Browse Source

ARM: Workaround for unaligned accesses.

Mike Pall 14 years ago
parent
commit
b3d10cdf62
1 changed files with 17 additions and 5 deletions
  1. 17 5
      src/lj_str.c

+ 17 - 5
src/lj_str.c

@@ -43,6 +43,18 @@ int32_t LJ_FASTCALL lj_str_cmp(GCstr *a, GCstr *b)
   return (int32_t)(a->len - b->len);
 }
 
+typedef union
+#ifdef __GNUC__
+__attribute__((packed))
+#endif
+Unaligned32 { uint32_t u; uint8_t b[4]; } Unaligned32;
+
+/* Unaligned read of uint32_t. */
+static uint32_t LJ_AINLINE str_getu32(const void *p)
+{
+  return ((const Unaligned32 *)p)->u;
+}
+
 /* Fast string data comparison. Caveat: unaligned access to 1st string! */
 static LJ_AINLINE int str_fastcmp(const char *a, const char *b, MSize len)
 {
@@ -50,7 +62,7 @@ static LJ_AINLINE int str_fastcmp(const char *a, const char *b, MSize len)
   lua_assert(len > 0);
   lua_assert((((uintptr_t)a + len) & (LJ_PAGESIZE-1)) <= LJ_PAGESIZE-4);
   do {  /* Note: innocuous access up to end of string + 3. */
-    uint32_t v = *(const uint32_t *)(a+i) ^ *(const uint32_t *)(b+i);
+    uint32_t v = str_getu32(a+i) ^ *(const uint32_t *)(b+i);
     if (v) {
       i -= len;
 #if LJ_LE
@@ -103,11 +115,11 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx)
   g = G(L);
   /* Compute string hash. Constants taken from lookup3 hash by Bob Jenkins. */
   if (len >= 4) {  /* Caveat: unaligned access! */
-    a = *(const uint32_t *)str;
-    h ^= *(const uint32_t *)(str+len-4);
-    b = *(const uint32_t *)(str+(len>>1)-2);
+    a = str_getu32(str);
+    h ^= str_getu32(str+len-4);
+    b = str_getu32(str+(len>>1)-2);
     h ^= b; h -= lj_rol(b, 14);
-    b += *(const uint32_t *)(str+(len>>2)-1);
+    b += str_getu32(str+(len>>2)-1);
   } else if (len > 0) {
     a = *(const uint8_t *)str;
     h ^= *(const uint8_t *)(str+len-1);