Avoid duplicates in the SSC xrefs.
[mono.git] / mono / metadata / gc.c
index 90e5979b508bbbd4198e8ba2b60ffce28bf163eb..95fc99d61f6f0e5f414dd3e708ab2cb192bb674d 100644 (file)
@@ -1276,7 +1276,12 @@ mono_gc_parse_environment_string_extract_number (const char *str, glong *out)
        gboolean is_suffix = FALSE;
        char suffix;
 
-       switch (str [len - 1]) {
+       if (!len)
+               return FALSE;
+
+       suffix = str [len - 1];
+
+       switch (suffix) {
                case 'g':
                case 'G':
                        shift += 10;
@@ -1287,7 +1292,10 @@ mono_gc_parse_environment_string_extract_number (const char *str, glong *out)
                case 'K':
                        shift += 10;
                        is_suffix = TRUE;
-                       suffix = str [len - 1];
+                       break;
+               default:
+                       if (!isdigit (suffix))
+                               return FALSE;
                        break;
        }
 
@@ -1496,8 +1504,11 @@ mono_gc_reference_queue_free (MonoReferenceQueue *queue)
        queue->should_be_deleted = TRUE;
 }
 
-#define unaligned_bytes(ptr) (((size_t)ptr) & (sizeof (void*) - 1))
-#define aligned_end(ptr) ((void*)(((size_t)ptr) & ~(sizeof (void*) - 1)))
+#define ptr_mask ((sizeof (void*) - 1))
+#define _toi(ptr) ((size_t)ptr)
+#define unaligned_bytes(ptr) (_toi(ptr) & ptr_mask)
+#define align_down(ptr) ((void*)(_toi(ptr) & ~ptr_mask))
+#define align_up(ptr) ((void*) ((_toi(ptr) + ptr_mask) & ~ptr_mask))
 
 /**
  * Zero @size bytes starting at @dest.
@@ -1517,7 +1528,7 @@ mono_gc_bzero (void *dest, size_t size)
        while (p < align_end)
                *p++ = 0;
 
-       word_end = aligned_end (end);
+       word_end = align_down (end);
        while (p < word_end) {
                *((void**)p) = NULL;
                p += sizeof (void*);
@@ -1537,32 +1548,36 @@ mono_gc_bzero (void *dest, size_t size)
 void
 mono_gc_memmove (void *dest, const void *src, size_t size)
 {
-       void **p, * const *s;
-
-       p = dest;
-       s = src;
+       /*
+        * If dest and src are differently aligned with respect to
+        * pointer size then it makes no sense to do aligned copying.
+        * In fact, we would end up with unaligned loads which is
+        * incorrect on some architectures.
+        */
+       if ((char*)dest - (char*)align_down (dest) != (char*)src - (char*)align_down (src)) {
+               memmove (dest, src, size);
+               return;
+       }
 
        /*
         * A bit of explanation on why we align only dest before doing word copies.
         * Pointers to managed objects must always be stored in word aligned addresses, so
         * even if dest is misaligned, src will be by the same amount - this ensure proper atomicity of reads.
         */
-
-       /*potentially overlap, do a backward copy*/
-       if (dest > src) {
+       if (dest > src && ((size_t)((char*)dest - (char*)src) < size)) {
                char *p = (char*)dest + size;
                char *s = (char*)src + size;
                char *start = (char*)dest;
-               char *align_end = aligned_end (p);
+               char *align_end = MAX((char*)dest, (char*)align_down (p));
                char *word_start;
 
-               while (p >= align_end)
+               while (p > align_end)
                        *--p = *--s;
 
-               word_start = start + unaligned_bytes (start);
-               while (p >= word_start) {
+               word_start = align_up (start);
+               while (p > word_start) {
                        p -= sizeof (void*);
-                       s -= sizeof (void*);                    
+                       s -= sizeof (void*);
                        *((void**)p) = *((void**)s);
                }
 
@@ -1572,13 +1587,13 @@ mono_gc_memmove (void *dest, const void *src, size_t size)
                char *p = (char*)dest;
                char *s = (char*)src;
                char *end = p + size;
-               char *align_end = p + unaligned_bytes (p);
+               char *align_end = MIN ((char*)end, (char*)align_up (p));
                char *word_end;
 
                while (p < align_end)
                        *p++ = *s++;
 
-               word_end = aligned_end (end);
+               word_end = align_down (end);
                while (p < word_end) {
                        *((void**)p) = *((void**)s);
                        p += sizeof (void*);