aboutsummaryrefslogtreecommitdiff
path: root/src/lj_ir.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_ir.c')
-rw-r--r--src/lj_ir.c94
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*/
180typedef struct KNumArray { 180typedef 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. */
187void lj_ir_knum_freeall(jit_State *J) 187void 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. */
198static cTValue *ir_knum_find(jit_State *J, uint64_t nn) 198static 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. */
229TRef lj_ir_knum_addr(jit_State *J, cTValue *tv) 229TRef 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;
244found: 245found:
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. */
249TRef lj_ir_knum_nn(jit_State *J, uint64_t nn) 250TRef 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. */
256TRef 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));