diff options
Diffstat (limited to 'src/lj_ir.c')
-rw-r--r-- | src/lj_ir.c | 94 |
1 files changed, 52 insertions, 42 deletions
diff --git a/src/lj_ir.c b/src/lj_ir.c index 529c333b..d39a345f 100644 --- a/src/lj_ir.c +++ b/src/lj_ir.c | |||
@@ -167,88 +167,95 @@ found: | |||
167 | return TREF(ref, IRT_INT); | 167 | return TREF(ref, IRT_INT); |
168 | } | 168 | } |
169 | 169 | ||
170 | /* The MRef inside the KNUM IR instruction holds the address of the constant | 170 | /* The MRef inside the KNUM/KINT64 IR instructions holds the address of the |
171 | ** (an aligned double or a special 64 bit pattern). The KNUM constants | 171 | ** 64 bit constant. The constants themselves are stored in a chained array |
172 | ** themselves are stored in a chained array and shared across traces. | 172 | ** and shared across traces. |
173 | ** | 173 | ** |
174 | ** Rationale for choosing this data structure: | 174 | ** Rationale for choosing this data structure: |
175 | ** - The address of the constants is embedded in the generated machine code | 175 | ** - The address of the constants is embedded in the generated machine code |
176 | ** and must never move. A resizable array or hash table wouldn't work. | 176 | ** and must never move. A resizable array or hash table wouldn't work. |
177 | ** - Most apps need very few non-integer constants (less than a dozen). | 177 | ** - Most apps need very few non-32 bit integer constants (less than a dozen). |
178 | ** - Linear search is hard to beat in terms of speed and low complexity. | 178 | ** - Linear search is hard to beat in terms of speed and low complexity. |
179 | */ | 179 | */ |
180 | typedef struct KNumArray { | 180 | typedef struct K64Array { |
181 | MRef next; /* Pointer to next list. */ | 181 | MRef next; /* Pointer to next list. */ |
182 | MSize numk; /* Number of used elements in this array. */ | 182 | MSize numk; /* Number of used elements in this array. */ |
183 | TValue k[LJ_MIN_KNUMSZ]; /* Array of constants. */ | 183 | TValue k[LJ_MIN_K64SZ]; /* Array of constants. */ |
184 | } KNumArray; | 184 | } K64Array; |
185 | 185 | ||
186 | /* Free all chained arrays. */ | 186 | /* Free all chained arrays. */ |
187 | void lj_ir_knum_freeall(jit_State *J) | 187 | void lj_ir_k64_freeall(jit_State *J) |
188 | { | 188 | { |
189 | KNumArray *kn; | 189 | K64Array *k; |
190 | for (kn = mref(J->knum, KNumArray); kn; ) { | 190 | for (k = mref(J->k64, K64Array); k; ) { |
191 | KNumArray *next = mref(kn->next, KNumArray); | 191 | K64Array *next = mref(k->next, K64Array); |
192 | lj_mem_free(J2G(J), kn, sizeof(KNumArray)); | 192 | lj_mem_free(J2G(J), k, sizeof(K64Array)); |
193 | kn = next; | 193 | k = next; |
194 | } | 194 | } |
195 | } | 195 | } |
196 | 196 | ||
197 | /* Find KNUM constant in chained array or add it. */ | 197 | /* Find 64 bit constant in chained array or add it. */ |
198 | static cTValue *ir_knum_find(jit_State *J, uint64_t nn) | 198 | static cTValue *ir_k64_find(jit_State *J, uint64_t u64) |
199 | { | 199 | { |
200 | KNumArray *kn, *knp = NULL; | 200 | K64Array *k, *kp = NULL; |
201 | TValue *ntv; | 201 | TValue *ntv; |
202 | MSize idx; | 202 | MSize idx; |
203 | /* Search for the constant in the whole chain of arrays. */ | 203 | /* Search for the constant in the whole chain of arrays. */ |
204 | for (kn = mref(J->knum, KNumArray); kn; kn = mref(kn->next, KNumArray)) { | 204 | for (k = mref(J->k64, K64Array); k; k = mref(k->next, K64Array)) { |
205 | knp = kn; /* Remember previous element in list. */ | 205 | kp = k; /* Remember previous element in list. */ |
206 | for (idx = 0; idx < kn->numk; idx++) { /* Search one array. */ | 206 | for (idx = 0; idx < k->numk; idx++) { /* Search one array. */ |
207 | TValue *tv = &kn->k[idx]; | 207 | TValue *tv = &k->k[idx]; |
208 | if (tv->u64 == nn) /* Needed for +-0/NaN/absmask. */ | 208 | if (tv->u64 == u64) /* Needed for +-0/NaN/absmask. */ |
209 | return tv; | 209 | return tv; |
210 | } | 210 | } |
211 | } | 211 | } |
212 | /* Constant was not found, need to add it. */ | 212 | /* Constant was not found, need to add it. */ |
213 | if (!(knp && knp->numk < LJ_MIN_KNUMSZ)) { /* Allocate a new array. */ | 213 | if (!(kp && kp->numk < LJ_MIN_K64SZ)) { /* Allocate a new array. */ |
214 | KNumArray *nkn = lj_mem_newt(J->L, sizeof(KNumArray), KNumArray); | 214 | K64Array *kn = lj_mem_newt(J->L, sizeof(K64Array), K64Array); |
215 | setmref(nkn->next, NULL); | 215 | setmref(kn->next, NULL); |
216 | nkn->numk = 0; | 216 | kn->numk = 0; |
217 | if (knp) | 217 | if (kp) |
218 | setmref(knp->next, nkn); /* Chain to the end of the list. */ | 218 | setmref(kp->next, kn); /* Chain to the end of the list. */ |
219 | else | 219 | else |
220 | setmref(J->knum, nkn); /* Link first array. */ | 220 | setmref(J->k64, kn); /* Link first array. */ |
221 | knp = nkn; | 221 | kp = kn; |
222 | } | 222 | } |
223 | ntv = &knp->k[knp->numk++]; /* Add to current array. */ | 223 | ntv = &kp->k[kp->numk++]; /* Add to current array. */ |
224 | ntv->u64 = nn; | 224 | ntv->u64 = u64; |
225 | return ntv; | 225 | return ntv; |
226 | } | 226 | } |
227 | 227 | ||
228 | /* Intern FP constant, given by its address. */ | 228 | /* Intern 64 bit constant, given by its address. */ |
229 | TRef lj_ir_knum_addr(jit_State *J, cTValue *tv) | 229 | TRef lj_ir_k64(jit_State *J, IROp op, cTValue *tv) |
230 | { | 230 | { |
231 | IRIns *ir, *cir = J->cur.ir; | 231 | IRIns *ir, *cir = J->cur.ir; |
232 | IRRef ref; | 232 | IRRef ref; |
233 | for (ref = J->chain[IR_KNUM]; ref; ref = cir[ref].prev) | 233 | IRType t = op == IR_KNUM ? IRT_NUM : IRT_I64; |
234 | if (ir_knum(&cir[ref]) == tv) | 234 | for (ref = J->chain[op]; ref; ref = cir[ref].prev) |
235 | if (ir_k64(&cir[ref]) == tv) | ||
235 | goto found; | 236 | goto found; |
236 | ref = ir_nextk(J); | 237 | ref = ir_nextk(J); |
237 | ir = IR(ref); | 238 | ir = IR(ref); |
238 | lua_assert(checkptr32(tv)); | 239 | lua_assert(checkptr32(tv)); |
239 | setmref(ir->ptr, tv); | 240 | setmref(ir->ptr, tv); |
240 | ir->t.irt = IRT_NUM; | 241 | ir->t.irt = t; |
241 | ir->o = IR_KNUM; | 242 | ir->o = op; |
242 | ir->prev = J->chain[IR_KNUM]; | 243 | ir->prev = J->chain[op]; |
243 | J->chain[IR_KNUM] = (IRRef1)ref; | 244 | J->chain[op] = (IRRef1)ref; |
244 | found: | 245 | found: |
245 | return TREF(ref, IRT_NUM); | 246 | return TREF(ref, t); |
246 | } | 247 | } |
247 | 248 | ||
248 | /* Intern FP constant, given by its 64 bit pattern. */ | 249 | /* Intern FP constant, given by its 64 bit pattern. */ |
249 | TRef lj_ir_knum_nn(jit_State *J, uint64_t nn) | 250 | TRef lj_ir_knum_u64(jit_State *J, uint64_t u64) |
251 | { | ||
252 | return lj_ir_k64(J, IR_KNUM, ir_k64_find(J, u64)); | ||
253 | } | ||
254 | |||
255 | /* Intern 64 bit integer constant. */ | ||
256 | TRef lj_ir_kint64(jit_State *J, uint64_t u64) | ||
250 | { | 257 | { |
251 | return lj_ir_knum_addr(J, ir_knum_find(J, nn)); | 258 | return lj_ir_k64(J, IR_KINT64, ir_k64_find(J, u64)); |
252 | } | 259 | } |
253 | 260 | ||
254 | /* Check whether a number is int and return it. -0 is NOT considered an int. */ | 261 | /* Check whether a number is int and return it. -0 is NOT considered an int. */ |
@@ -373,6 +380,9 @@ void lj_ir_kvalue(lua_State *L, TValue *tv, const IRIns *ir) | |||
373 | } else if (irt_isnum(ir->t)) { | 380 | } else if (irt_isnum(ir->t)) { |
374 | lua_assert(ir->o == IR_KNUM); | 381 | lua_assert(ir->o == IR_KNUM); |
375 | setnumV(tv, ir_knum(ir)->n); | 382 | setnumV(tv, ir_knum(ir)->n); |
383 | } else if (irt_is64(ir->t)) { | ||
384 | lua_assert(ir->o == IR_KINT64); | ||
385 | setnumV(tv, (int64_t)ir_kint64(ir)->u64); /* NYI: use FFI int64_t. */ | ||
376 | } else if (irt_ispri(ir->t)) { | 386 | } else if (irt_ispri(ir->t)) { |
377 | lua_assert(ir->o == IR_KPRI); | 387 | lua_assert(ir->o == IR_KPRI); |
378 | setitype(tv, irt_toitype(ir->t)); | 388 | setitype(tv, irt_toitype(ir->t)); |