diff options
author | Mike Pall <mike> | 2011-04-19 16:09:07 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2011-04-19 16:09:07 +0200 |
commit | b3d10cdf62ce07e5662a73ec654dc3ce5c117966 (patch) | |
tree | cd804cc5ec888d7c9a65de20b0c569a65146e0b8 /src | |
parent | 4fbacaf887d9b891f385eea835d2a18fdb752ac2 (diff) | |
download | luajit-b3d10cdf62ce07e5662a73ec654dc3ce5c117966.tar.gz luajit-b3d10cdf62ce07e5662a73ec654dc3ce5c117966.tar.bz2 luajit-b3d10cdf62ce07e5662a73ec654dc3ce5c117966.zip |
ARM: Workaround for unaligned accesses.
Diffstat (limited to 'src')
-rw-r--r-- | src/lj_str.c | 22 |
1 files 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) | |||
43 | return (int32_t)(a->len - b->len); | 43 | return (int32_t)(a->len - b->len); |
44 | } | 44 | } |
45 | 45 | ||
46 | typedef union | ||
47 | #ifdef __GNUC__ | ||
48 | __attribute__((packed)) | ||
49 | #endif | ||
50 | Unaligned32 { uint32_t u; uint8_t b[4]; } Unaligned32; | ||
51 | |||
52 | /* Unaligned read of uint32_t. */ | ||
53 | static uint32_t LJ_AINLINE str_getu32(const void *p) | ||
54 | { | ||
55 | return ((const Unaligned32 *)p)->u; | ||
56 | } | ||
57 | |||
46 | /* Fast string data comparison. Caveat: unaligned access to 1st string! */ | 58 | /* Fast string data comparison. Caveat: unaligned access to 1st string! */ |
47 | static LJ_AINLINE int str_fastcmp(const char *a, const char *b, MSize len) | 59 | static LJ_AINLINE int str_fastcmp(const char *a, const char *b, MSize len) |
48 | { | 60 | { |
@@ -50,7 +62,7 @@ static LJ_AINLINE int str_fastcmp(const char *a, const char *b, MSize len) | |||
50 | lua_assert(len > 0); | 62 | lua_assert(len > 0); |
51 | lua_assert((((uintptr_t)a + len) & (LJ_PAGESIZE-1)) <= LJ_PAGESIZE-4); | 63 | lua_assert((((uintptr_t)a + len) & (LJ_PAGESIZE-1)) <= LJ_PAGESIZE-4); |
52 | do { /* Note: innocuous access up to end of string + 3. */ | 64 | do { /* Note: innocuous access up to end of string + 3. */ |
53 | uint32_t v = *(const uint32_t *)(a+i) ^ *(const uint32_t *)(b+i); | 65 | uint32_t v = str_getu32(a+i) ^ *(const uint32_t *)(b+i); |
54 | if (v) { | 66 | if (v) { |
55 | i -= len; | 67 | i -= len; |
56 | #if LJ_LE | 68 | #if LJ_LE |
@@ -103,11 +115,11 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx) | |||
103 | g = G(L); | 115 | g = G(L); |
104 | /* Compute string hash. Constants taken from lookup3 hash by Bob Jenkins. */ | 116 | /* Compute string hash. Constants taken from lookup3 hash by Bob Jenkins. */ |
105 | if (len >= 4) { /* Caveat: unaligned access! */ | 117 | if (len >= 4) { /* Caveat: unaligned access! */ |
106 | a = *(const uint32_t *)str; | 118 | a = str_getu32(str); |
107 | h ^= *(const uint32_t *)(str+len-4); | 119 | h ^= str_getu32(str+len-4); |
108 | b = *(const uint32_t *)(str+(len>>1)-2); | 120 | b = str_getu32(str+(len>>1)-2); |
109 | h ^= b; h -= lj_rol(b, 14); | 121 | h ^= b; h -= lj_rol(b, 14); |
110 | b += *(const uint32_t *)(str+(len>>2)-1); | 122 | b += str_getu32(str+(len>>2)-1); |
111 | } else if (len > 0) { | 123 | } else if (len > 0) { |
112 | a = *(const uint8_t *)str; | 124 | a = *(const uint8_t *)str; |
113 | h ^= *(const uint8_t *)(str+len-1); | 125 | h ^= *(const uint8_t *)(str+len-1); |