From b3d10cdf62ce07e5662a73ec654dc3ce5c117966 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Tue, 19 Apr 2011 16:09:07 +0200 Subject: [PATCH] ARM: Workaround for unaligned accesses. --- src/lj_str.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/lj_str.c b/src/lj_str.c index 9e9650a2..01bd68e2 100644 --- a/src/lj_str.c +++ b/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);