ARM: Workaround for unaligned accesses.

This commit is contained in:
Mike Pall 2011-04-19 16:09:07 +02:00
parent 4fbacaf887
commit b3d10cdf62

View File

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