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;
case 'K':
shift += 10;
is_suffix = TRUE;
- suffix = str [len - 1];
+ break;
+ default:
+ if (!isdigit (suffix))
+ return FALSE;
break;
}
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.
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*);
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);
}
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*);