Mercurial
comparison third_party/luajit/src/lj_record.c @ 178:94705b5986b3
[ThirdParty] Added WRK and luajit for load testing.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Thu, 22 Jan 2026 20:10:30 -0800 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 177:24fe8ff94056 | 178:94705b5986b3 |
|---|---|
| 1 /* | |
| 2 ** Trace recorder (bytecode -> SSA IR). | |
| 3 ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h | |
| 4 */ | |
| 5 | |
| 6 #define lj_record_c | |
| 7 #define LUA_CORE | |
| 8 | |
| 9 #include "lj_obj.h" | |
| 10 | |
| 11 #if LJ_HASJIT | |
| 12 | |
| 13 #include "lj_err.h" | |
| 14 #include "lj_str.h" | |
| 15 #include "lj_tab.h" | |
| 16 #include "lj_meta.h" | |
| 17 #include "lj_frame.h" | |
| 18 #if LJ_HASFFI | |
| 19 #include "lj_ctype.h" | |
| 20 #endif | |
| 21 #include "lj_bc.h" | |
| 22 #include "lj_ff.h" | |
| 23 #if LJ_HASPROFILE | |
| 24 #include "lj_debug.h" | |
| 25 #endif | |
| 26 #include "lj_ir.h" | |
| 27 #include "lj_jit.h" | |
| 28 #include "lj_ircall.h" | |
| 29 #include "lj_iropt.h" | |
| 30 #include "lj_trace.h" | |
| 31 #include "lj_record.h" | |
| 32 #include "lj_ffrecord.h" | |
| 33 #include "lj_snap.h" | |
| 34 #include "lj_dispatch.h" | |
| 35 #include "lj_vm.h" | |
| 36 #include "lj_prng.h" | |
| 37 | |
| 38 /* Some local macros to save typing. Undef'd at the end. */ | |
| 39 #define IR(ref) (&J->cur.ir[(ref)]) | |
| 40 | |
| 41 /* Pass IR on to next optimization in chain (FOLD). */ | |
| 42 #define emitir(ot, a, b) (lj_ir_set(J, (ot), (a), (b)), lj_opt_fold(J)) | |
| 43 | |
| 44 /* Emit raw IR without passing through optimizations. */ | |
| 45 #define emitir_raw(ot, a, b) (lj_ir_set(J, (ot), (a), (b)), lj_ir_emit(J)) | |
| 46 | |
| 47 /* -- Sanity checks ------------------------------------------------------- */ | |
| 48 | |
| 49 #ifdef LUA_USE_ASSERT | |
| 50 /* Sanity check the whole IR -- sloooow. */ | |
| 51 static void rec_check_ir(jit_State *J) | |
| 52 { | |
| 53 IRRef i, nins = J->cur.nins, nk = J->cur.nk; | |
| 54 lj_assertJ(nk <= REF_BIAS && nins >= REF_BIAS && nins < 65536, | |
| 55 "inconsistent IR layout"); | |
| 56 for (i = nk; i < nins; i++) { | |
| 57 IRIns *ir = IR(i); | |
| 58 uint32_t mode = lj_ir_mode[ir->o]; | |
| 59 IRRef op1 = ir->op1; | |
| 60 IRRef op2 = ir->op2; | |
| 61 const char *err = NULL; | |
| 62 switch (irm_op1(mode)) { | |
| 63 case IRMnone: | |
| 64 if (op1 != 0) err = "IRMnone op1 used"; | |
| 65 break; | |
| 66 case IRMref: | |
| 67 if (op1 < nk || (i >= REF_BIAS ? op1 >= i : op1 <= i)) | |
| 68 err = "IRMref op1 out of range"; | |
| 69 break; | |
| 70 case IRMlit: break; | |
| 71 case IRMcst: | |
| 72 if (i >= REF_BIAS) { err = "constant in IR range"; break; } | |
| 73 if (irt_is64(ir->t) && ir->o != IR_KNULL) | |
| 74 i++; | |
| 75 continue; | |
| 76 } | |
| 77 switch (irm_op2(mode)) { | |
| 78 case IRMnone: | |
| 79 if (op2) err = "IRMnone op2 used"; | |
| 80 break; | |
| 81 case IRMref: | |
| 82 if (op2 < nk || (i >= REF_BIAS ? op2 >= i : op2 <= i)) | |
| 83 err = "IRMref op2 out of range"; | |
| 84 break; | |
| 85 case IRMlit: break; | |
| 86 case IRMcst: err = "IRMcst op2"; break; | |
| 87 } | |
| 88 if (!err && ir->prev) { | |
| 89 if (ir->prev < nk || (i >= REF_BIAS ? ir->prev >= i : ir->prev <= i)) | |
| 90 err = "chain out of range"; | |
| 91 else if (ir->o != IR_NOP && IR(ir->prev)->o != ir->o) | |
| 92 err = "chain to different op"; | |
| 93 } | |
| 94 lj_assertJ(!err, "bad IR %04d op %d(%04d,%04d): %s", | |
| 95 i-REF_BIAS, | |
| 96 ir->o, | |
| 97 irm_op1(mode) == IRMref ? op1-REF_BIAS : op1, | |
| 98 irm_op2(mode) == IRMref ? op2-REF_BIAS : op2, | |
| 99 err); | |
| 100 } | |
| 101 } | |
| 102 | |
| 103 /* Compare stack slots and frames of the recorder and the VM. */ | |
| 104 static void rec_check_slots(jit_State *J) | |
| 105 { | |
| 106 BCReg s, nslots = J->baseslot + J->maxslot; | |
| 107 int32_t depth = 0; | |
| 108 cTValue *base = J->L->base - J->baseslot; | |
| 109 lj_assertJ(J->baseslot >= 1+LJ_FR2, "bad baseslot"); | |
| 110 lj_assertJ(J->baseslot == 1+LJ_FR2 || (J->slot[J->baseslot-1] & TREF_FRAME), | |
| 111 "baseslot does not point to frame"); | |
| 112 lj_assertJ(nslots <= LJ_MAX_JSLOTS, "slot overflow"); | |
| 113 for (s = 0; s < nslots; s++) { | |
| 114 TRef tr = J->slot[s]; | |
| 115 if (tr) { | |
| 116 cTValue *tv = &base[s]; | |
| 117 IRRef ref = tref_ref(tr); | |
| 118 IRIns *ir = NULL; /* Silence compiler. */ | |
| 119 lj_assertJ(tv < J->L->top, "slot %d above top of Lua stack", s); | |
| 120 if (!LJ_FR2 || ref || !(tr & (TREF_FRAME | TREF_CONT))) { | |
| 121 lj_assertJ(ref >= J->cur.nk && ref < J->cur.nins, | |
| 122 "slot %d ref %04d out of range", s, ref - REF_BIAS); | |
| 123 ir = IR(ref); | |
| 124 lj_assertJ(irt_t(ir->t) == tref_t(tr), "slot %d IR type mismatch", s); | |
| 125 } | |
| 126 if (s == 0) { | |
| 127 lj_assertJ(tref_isfunc(tr), "frame slot 0 is not a function"); | |
| 128 #if LJ_FR2 | |
| 129 } else if (s == 1) { | |
| 130 lj_assertJ((tr & ~TREF_FRAME) == 0, "bad frame slot 1"); | |
| 131 #endif | |
| 132 } else if ((tr & TREF_FRAME)) { | |
| 133 GCfunc *fn = gco2func(frame_gc(tv)); | |
| 134 BCReg delta = (BCReg)(tv - frame_prev(tv)); | |
| 135 #if LJ_FR2 | |
| 136 lj_assertJ(!ref || ir_knum(ir)->u64 == tv->u64, | |
| 137 "frame slot %d PC mismatch", s); | |
| 138 tr = J->slot[s-1]; | |
| 139 ir = IR(tref_ref(tr)); | |
| 140 #endif | |
| 141 lj_assertJ(tref_isfunc(tr), | |
| 142 "frame slot %d is not a function", s-LJ_FR2); | |
| 143 lj_assertJ(!tref_isk(tr) || fn == ir_kfunc(ir), | |
| 144 "frame slot %d function mismatch", s-LJ_FR2); | |
| 145 lj_assertJ(s > delta + LJ_FR2 ? (J->slot[s-delta] & TREF_FRAME) | |
| 146 : (s == delta + LJ_FR2), | |
| 147 "frame slot %d broken chain", s-LJ_FR2); | |
| 148 depth++; | |
| 149 } else if ((tr & TREF_CONT)) { | |
| 150 #if LJ_FR2 | |
| 151 lj_assertJ(!ref || ir_knum(ir)->u64 == tv->u64, | |
| 152 "cont slot %d continuation mismatch", s); | |
| 153 #else | |
| 154 lj_assertJ(ir_kptr(ir) == gcrefp(tv->gcr, void), | |
| 155 "cont slot %d continuation mismatch", s); | |
| 156 #endif | |
| 157 lj_assertJ((J->slot[s+1+LJ_FR2] & TREF_FRAME), | |
| 158 "cont slot %d not followed by frame", s); | |
| 159 depth++; | |
| 160 } else if ((tr & TREF_KEYINDEX)) { | |
| 161 lj_assertJ(tref_isint(tr), "keyindex slot %d bad type %d", | |
| 162 s, tref_type(tr)); | |
| 163 } else { | |
| 164 /* Number repr. may differ, but other types must be the same. */ | |
| 165 lj_assertJ(tvisnumber(tv) ? tref_isnumber(tr) : | |
| 166 itype2irt(tv) == tref_type(tr), | |
| 167 "slot %d type mismatch: stack type %d vs IR type %d", | |
| 168 s, itypemap(tv), tref_type(tr)); | |
| 169 if (tref_isk(tr)) { /* Compare constants. */ | |
| 170 TValue tvk; | |
| 171 lj_ir_kvalue(J->L, &tvk, ir); | |
| 172 lj_assertJ((tvisnum(&tvk) && tvisnan(&tvk)) ? | |
| 173 (tvisnum(tv) && tvisnan(tv)) : | |
| 174 lj_obj_equal(tv, &tvk), | |
| 175 "slot %d const mismatch: stack %016llx vs IR %016llx", | |
| 176 s, tv->u64, tvk.u64); | |
| 177 } | |
| 178 } | |
| 179 } | |
| 180 } | |
| 181 lj_assertJ(J->framedepth == depth, | |
| 182 "frame depth mismatch %d vs %d", J->framedepth, depth); | |
| 183 } | |
| 184 #endif | |
| 185 | |
| 186 /* -- Type handling and specialization ------------------------------------ */ | |
| 187 | |
| 188 /* Note: these functions return tagged references (TRef). */ | |
| 189 | |
| 190 /* Specialize a slot to a specific type. Note: slot can be negative! */ | |
| 191 static TRef sloadt(jit_State *J, int32_t slot, IRType t, int mode) | |
| 192 { | |
| 193 /* Caller may set IRT_GUARD in t. */ | |
| 194 TRef ref = emitir_raw(IRT(IR_SLOAD, t), (int32_t)J->baseslot+slot, mode); | |
| 195 J->base[slot] = ref; | |
| 196 return ref; | |
| 197 } | |
| 198 | |
| 199 /* Specialize a slot to the runtime type. Note: slot can be negative! */ | |
| 200 static TRef sload(jit_State *J, int32_t slot) | |
| 201 { | |
| 202 IRType t = itype2irt(&J->L->base[slot]); | |
| 203 TRef ref = emitir_raw(IRTG(IR_SLOAD, t), (int32_t)J->baseslot+slot, | |
| 204 IRSLOAD_TYPECHECK); | |
| 205 if (irtype_ispri(t)) ref = TREF_PRI(t); /* Canonicalize primitive refs. */ | |
| 206 J->base[slot] = ref; | |
| 207 return ref; | |
| 208 } | |
| 209 | |
| 210 /* Get TRef from slot. Load slot and specialize if not done already. */ | |
| 211 #define getslot(J, s) (J->base[(s)] ? J->base[(s)] : sload(J, (int32_t)(s))) | |
| 212 | |
| 213 /* Get TRef for current function. */ | |
| 214 static TRef getcurrf(jit_State *J) | |
| 215 { | |
| 216 if (J->base[-1-LJ_FR2]) | |
| 217 return J->base[-1-LJ_FR2]; | |
| 218 /* Non-base frame functions ought to be loaded already. */ | |
| 219 lj_assertJ(J->baseslot == 1+LJ_FR2, "bad baseslot"); | |
| 220 return sloadt(J, -1-LJ_FR2, IRT_FUNC, IRSLOAD_READONLY); | |
| 221 } | |
| 222 | |
| 223 /* Compare for raw object equality. | |
| 224 ** Returns 0 if the objects are the same. | |
| 225 ** Returns 1 if they are different, but the same type. | |
| 226 ** Returns 2 for two different types. | |
| 227 ** Comparisons between primitives always return 1 -- no caller cares about it. | |
| 228 */ | |
| 229 int lj_record_objcmp(jit_State *J, TRef a, TRef b, cTValue *av, cTValue *bv) | |
| 230 { | |
| 231 int diff = !lj_obj_equal(av, bv); | |
| 232 if (!tref_isk2(a, b)) { /* Shortcut, also handles primitives. */ | |
| 233 IRType ta = tref_isinteger(a) ? IRT_INT : tref_type(a); | |
| 234 IRType tb = tref_isinteger(b) ? IRT_INT : tref_type(b); | |
| 235 if (ta != tb) { | |
| 236 /* Widen mixed number/int comparisons to number/number comparison. */ | |
| 237 if (ta == IRT_INT && tb == IRT_NUM) { | |
| 238 a = emitir(IRTN(IR_CONV), a, IRCONV_NUM_INT); | |
| 239 ta = IRT_NUM; | |
| 240 } else if (ta == IRT_NUM && tb == IRT_INT) { | |
| 241 b = emitir(IRTN(IR_CONV), b, IRCONV_NUM_INT); | |
| 242 } else { | |
| 243 return 2; /* Two different types are never equal. */ | |
| 244 } | |
| 245 } | |
| 246 emitir(IRTG(diff ? IR_NE : IR_EQ, ta), a, b); | |
| 247 } | |
| 248 return diff; | |
| 249 } | |
| 250 | |
| 251 /* Constify a value. Returns 0 for non-representable object types. */ | |
| 252 TRef lj_record_constify(jit_State *J, cTValue *o) | |
| 253 { | |
| 254 if (tvisgcv(o)) | |
| 255 return lj_ir_kgc(J, gcV(o), itype2irt(o)); | |
| 256 else if (tvisint(o)) | |
| 257 return lj_ir_kint(J, intV(o)); | |
| 258 else if (tvisnum(o)) | |
| 259 return lj_ir_knumint(J, numV(o)); | |
| 260 else if (tvisbool(o)) | |
| 261 return TREF_PRI(itype2irt(o)); | |
| 262 else | |
| 263 return 0; /* Can't represent lightuserdata (pointless). */ | |
| 264 } | |
| 265 | |
| 266 /* Emit a VLOAD with the correct type. */ | |
| 267 TRef lj_record_vload(jit_State *J, TRef ref, MSize idx, IRType t) | |
| 268 { | |
| 269 TRef tr = emitir(IRTG(IR_VLOAD, t), ref, idx); | |
| 270 if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */ | |
| 271 return tr; | |
| 272 } | |
| 273 | |
| 274 /* -- Record loop ops ----------------------------------------------------- */ | |
| 275 | |
| 276 /* Loop event. */ | |
| 277 typedef enum { | |
| 278 LOOPEV_LEAVE, /* Loop is left or not entered. */ | |
| 279 LOOPEV_ENTERLO, /* Loop is entered with a low iteration count left. */ | |
| 280 LOOPEV_ENTER /* Loop is entered. */ | |
| 281 } LoopEvent; | |
| 282 | |
| 283 /* Canonicalize slots: convert integers to numbers. */ | |
| 284 static void canonicalize_slots(jit_State *J) | |
| 285 { | |
| 286 BCReg s; | |
| 287 if (LJ_DUALNUM) return; | |
| 288 for (s = J->baseslot+J->maxslot-1; s >= 1; s--) { | |
| 289 TRef tr = J->slot[s]; | |
| 290 if (tref_isinteger(tr) && !(tr & TREF_KEYINDEX)) { | |
| 291 IRIns *ir = IR(tref_ref(tr)); | |
| 292 if (!(ir->o == IR_SLOAD && (ir->op2 & (IRSLOAD_READONLY)))) | |
| 293 J->slot[s] = emitir(IRTN(IR_CONV), tr, IRCONV_NUM_INT); | |
| 294 } | |
| 295 } | |
| 296 } | |
| 297 | |
| 298 /* Stop recording. */ | |
| 299 void lj_record_stop(jit_State *J, TraceLink linktype, TraceNo lnk) | |
| 300 { | |
| 301 #ifdef LUAJIT_ENABLE_TABLE_BUMP | |
| 302 if (J->retryrec) | |
| 303 lj_trace_err(J, LJ_TRERR_RETRY); | |
| 304 #endif | |
| 305 lj_trace_end(J); | |
| 306 J->cur.linktype = (uint8_t)linktype; | |
| 307 J->cur.link = (uint16_t)lnk; | |
| 308 /* Looping back at the same stack level? */ | |
| 309 if (lnk == J->cur.traceno && J->framedepth + J->retdepth == 0) { | |
| 310 if ((J->flags & JIT_F_OPT_LOOP)) /* Shall we try to create a loop? */ | |
| 311 goto nocanon; /* Do not canonicalize or we lose the narrowing. */ | |
| 312 if (J->cur.root) /* Otherwise ensure we always link to the root trace. */ | |
| 313 J->cur.link = J->cur.root; | |
| 314 } | |
| 315 canonicalize_slots(J); | |
| 316 nocanon: | |
| 317 /* Note: all loop ops must set J->pc to the following instruction! */ | |
| 318 lj_snap_add(J); /* Add loop snapshot. */ | |
| 319 J->needsnap = 0; | |
| 320 J->mergesnap = 1; /* In case recording continues. */ | |
| 321 } | |
| 322 | |
| 323 /* Search bytecode backwards for a int/num constant slot initializer. */ | |
| 324 static TRef find_kinit(jit_State *J, const BCIns *endpc, BCReg slot, IRType t) | |
| 325 { | |
| 326 /* This algorithm is rather simplistic and assumes quite a bit about | |
| 327 ** how the bytecode is generated. It works fine for FORI initializers, | |
| 328 ** but it won't necessarily work in other cases (e.g. iterator arguments). | |
| 329 ** It doesn't do anything fancy, either (like backpropagating MOVs). | |
| 330 */ | |
| 331 const BCIns *pc, *startpc = proto_bc(J->pt); | |
| 332 for (pc = endpc-1; pc > startpc; pc--) { | |
| 333 BCIns ins = *pc; | |
| 334 BCOp op = bc_op(ins); | |
| 335 /* First try to find the last instruction that stores to this slot. */ | |
| 336 if (bcmode_a(op) == BCMbase && bc_a(ins) <= slot) { | |
| 337 return 0; /* Multiple results, e.g. from a CALL or KNIL. */ | |
| 338 } else if (bcmode_a(op) == BCMdst && bc_a(ins) == slot) { | |
| 339 if (op == BC_KSHORT || op == BC_KNUM) { /* Found const. initializer. */ | |
| 340 /* Now try to verify there's no forward jump across it. */ | |
| 341 const BCIns *kpc = pc; | |
| 342 for (; pc > startpc; pc--) | |
| 343 if (bc_op(*pc) == BC_JMP) { | |
| 344 const BCIns *target = pc+bc_j(*pc)+1; | |
| 345 if (target > kpc && target <= endpc) | |
| 346 return 0; /* Conditional assignment. */ | |
| 347 } | |
| 348 if (op == BC_KSHORT) { | |
| 349 int32_t k = (int32_t)(int16_t)bc_d(ins); | |
| 350 return t == IRT_INT ? lj_ir_kint(J, k) : lj_ir_knum(J, (lua_Number)k); | |
| 351 } else { | |
| 352 cTValue *tv = proto_knumtv(J->pt, bc_d(ins)); | |
| 353 if (t == IRT_INT) { | |
| 354 int32_t k = numberVint(tv); | |
| 355 if (tvisint(tv) || numV(tv) == (lua_Number)k) /* -0 is ok here. */ | |
| 356 return lj_ir_kint(J, k); | |
| 357 return 0; /* Type mismatch. */ | |
| 358 } else { | |
| 359 return lj_ir_knum(J, numberVnum(tv)); | |
| 360 } | |
| 361 } | |
| 362 } | |
| 363 return 0; /* Non-constant initializer. */ | |
| 364 } | |
| 365 } | |
| 366 return 0; /* No assignment to this slot found? */ | |
| 367 } | |
| 368 | |
| 369 /* Load and optionally convert a FORI argument from a slot. */ | |
| 370 static TRef fori_load(jit_State *J, BCReg slot, IRType t, int mode) | |
| 371 { | |
| 372 int conv = (tvisint(&J->L->base[slot]) != (t==IRT_INT)) ? IRSLOAD_CONVERT : 0; | |
| 373 return sloadt(J, (int32_t)slot, | |
| 374 t + (((mode & IRSLOAD_TYPECHECK) || | |
| 375 (conv && t == IRT_INT && !(mode >> 16))) ? | |
| 376 IRT_GUARD : 0), | |
| 377 mode + conv); | |
| 378 } | |
| 379 | |
| 380 /* Peek before FORI to find a const initializer. Otherwise load from slot. */ | |
| 381 static TRef fori_arg(jit_State *J, const BCIns *fori, BCReg slot, | |
| 382 IRType t, int mode) | |
| 383 { | |
| 384 TRef tr = J->base[slot]; | |
| 385 if (!tr) { | |
| 386 tr = find_kinit(J, fori, slot, t); | |
| 387 if (!tr) | |
| 388 tr = fori_load(J, slot, t, mode); | |
| 389 } | |
| 390 return tr; | |
| 391 } | |
| 392 | |
| 393 /* Return the direction of the FOR loop iterator. | |
| 394 ** It's important to exactly reproduce the semantics of the interpreter. | |
| 395 */ | |
| 396 static int rec_for_direction(cTValue *o) | |
| 397 { | |
| 398 return (tvisint(o) ? intV(o) : (int32_t)o->u32.hi) >= 0; | |
| 399 } | |
| 400 | |
| 401 /* Simulate the runtime behavior of the FOR loop iterator. */ | |
| 402 static LoopEvent rec_for_iter(IROp *op, cTValue *o, int isforl) | |
| 403 { | |
| 404 lua_Number stopv = numberVnum(&o[FORL_STOP]); | |
| 405 lua_Number idxv = numberVnum(&o[FORL_IDX]); | |
| 406 lua_Number stepv = numberVnum(&o[FORL_STEP]); | |
| 407 if (isforl) | |
| 408 idxv += stepv; | |
| 409 if (rec_for_direction(&o[FORL_STEP])) { | |
| 410 if (idxv <= stopv) { | |
| 411 *op = IR_LE; | |
| 412 return idxv + 2*stepv > stopv ? LOOPEV_ENTERLO : LOOPEV_ENTER; | |
| 413 } | |
| 414 *op = IR_GT; return LOOPEV_LEAVE; | |
| 415 } else { | |
| 416 if (stopv <= idxv) { | |
| 417 *op = IR_GE; | |
| 418 return idxv + 2*stepv < stopv ? LOOPEV_ENTERLO : LOOPEV_ENTER; | |
| 419 } | |
| 420 *op = IR_LT; return LOOPEV_LEAVE; | |
| 421 } | |
| 422 } | |
| 423 | |
| 424 /* Record checks for FOR loop overflow and step direction. */ | |
| 425 static void rec_for_check(jit_State *J, IRType t, int dir, | |
| 426 TRef stop, TRef step, int init) | |
| 427 { | |
| 428 if (!tref_isk(step)) { | |
| 429 /* Non-constant step: need a guard for the direction. */ | |
| 430 TRef zero = (t == IRT_INT) ? lj_ir_kint(J, 0) : lj_ir_knum_zero(J); | |
| 431 emitir(IRTG(dir ? IR_GE : IR_LT, t), step, zero); | |
| 432 /* Add hoistable overflow checks for a narrowed FORL index. */ | |
| 433 if (init && t == IRT_INT) { | |
| 434 if (tref_isk(stop)) { | |
| 435 /* Constant stop: optimize check away or to a range check for step. */ | |
| 436 int32_t k = IR(tref_ref(stop))->i; | |
| 437 if (dir) { | |
| 438 if (k > 0) | |
| 439 emitir(IRTGI(IR_LE), step, lj_ir_kint(J, (int32_t)0x7fffffff-k)); | |
| 440 } else { | |
| 441 if (k < 0) | |
| 442 emitir(IRTGI(IR_GE), step, lj_ir_kint(J, (int32_t)0x80000000-k)); | |
| 443 } | |
| 444 } else { | |
| 445 /* Stop+step variable: need full overflow check. */ | |
| 446 TRef tr = emitir(IRTGI(IR_ADDOV), step, stop); | |
| 447 emitir(IRTI(IR_USE), tr, 0); /* ADDOV is weak. Avoid dead result. */ | |
| 448 } | |
| 449 } | |
| 450 } else if (init && t == IRT_INT && !tref_isk(stop)) { | |
| 451 /* Constant step: optimize overflow check to a range check for stop. */ | |
| 452 int32_t k = IR(tref_ref(step))->i; | |
| 453 k = (int32_t)(dir ? 0x7fffffff : 0x80000000) - k; | |
| 454 emitir(IRTGI(dir ? IR_LE : IR_GE), stop, lj_ir_kint(J, k)); | |
| 455 } | |
| 456 } | |
| 457 | |
| 458 /* Record a FORL instruction. */ | |
| 459 static void rec_for_loop(jit_State *J, const BCIns *fori, ScEvEntry *scev, | |
| 460 int init) | |
| 461 { | |
| 462 BCReg ra = bc_a(*fori); | |
| 463 cTValue *tv = &J->L->base[ra]; | |
| 464 TRef idx = J->base[ra+FORL_IDX]; | |
| 465 IRType t = idx ? tref_type(idx) : | |
| 466 (init || LJ_DUALNUM) ? lj_opt_narrow_forl(J, tv) : IRT_NUM; | |
| 467 int mode = IRSLOAD_INHERIT + | |
| 468 ((!LJ_DUALNUM || tvisint(tv) == (t == IRT_INT)) ? IRSLOAD_READONLY : 0); | |
| 469 TRef stop = fori_arg(J, fori, ra+FORL_STOP, t, mode); | |
| 470 TRef step = fori_arg(J, fori, ra+FORL_STEP, t, mode); | |
| 471 int tc, dir = rec_for_direction(&tv[FORL_STEP]); | |
| 472 lj_assertJ(bc_op(*fori) == BC_FORI || bc_op(*fori) == BC_JFORI, | |
| 473 "bad bytecode %d instead of FORI/JFORI", bc_op(*fori)); | |
| 474 scev->t.irt = t; | |
| 475 scev->dir = dir; | |
| 476 scev->stop = tref_ref(stop); | |
| 477 scev->step = tref_ref(step); | |
| 478 rec_for_check(J, t, dir, stop, step, init); | |
| 479 scev->start = tref_ref(find_kinit(J, fori, ra+FORL_IDX, IRT_INT)); | |
| 480 tc = (LJ_DUALNUM && | |
| 481 !(scev->start && irref_isk(scev->stop) && irref_isk(scev->step) && | |
| 482 tvisint(&tv[FORL_IDX]) == (t == IRT_INT))) ? | |
| 483 IRSLOAD_TYPECHECK : 0; | |
| 484 if (tc) { | |
| 485 J->base[ra+FORL_STOP] = stop; | |
| 486 J->base[ra+FORL_STEP] = step; | |
| 487 } | |
| 488 if (!idx) | |
| 489 idx = fori_load(J, ra+FORL_IDX, t, | |
| 490 IRSLOAD_INHERIT + tc + (J->scev.start << 16)); | |
| 491 if (!init) | |
| 492 J->base[ra+FORL_IDX] = idx = emitir(IRT(IR_ADD, t), idx, step); | |
| 493 J->base[ra+FORL_EXT] = idx; | |
| 494 scev->idx = tref_ref(idx); | |
| 495 setmref(scev->pc, fori); | |
| 496 J->maxslot = ra+FORL_EXT+1; | |
| 497 } | |
| 498 | |
| 499 /* Record FORL/JFORL or FORI/JFORI. */ | |
| 500 static LoopEvent rec_for(jit_State *J, const BCIns *fori, int isforl) | |
| 501 { | |
| 502 BCReg ra = bc_a(*fori); | |
| 503 TValue *tv = &J->L->base[ra]; | |
| 504 TRef *tr = &J->base[ra]; | |
| 505 IROp op; | |
| 506 LoopEvent ev; | |
| 507 TRef stop; | |
| 508 IRType t; | |
| 509 if (isforl) { /* Handle FORL/JFORL opcodes. */ | |
| 510 TRef idx = tr[FORL_IDX]; | |
| 511 if (mref(J->scev.pc, const BCIns) == fori && tref_ref(idx) == J->scev.idx) { | |
| 512 t = J->scev.t.irt; | |
| 513 stop = J->scev.stop; | |
| 514 idx = emitir(IRT(IR_ADD, t), idx, J->scev.step); | |
| 515 tr[FORL_EXT] = tr[FORL_IDX] = idx; | |
| 516 } else { | |
| 517 ScEvEntry scev; | |
| 518 rec_for_loop(J, fori, &scev, 0); | |
| 519 t = scev.t.irt; | |
| 520 stop = scev.stop; | |
| 521 } | |
| 522 } else { /* Handle FORI/JFORI opcodes. */ | |
| 523 BCReg i; | |
| 524 lj_meta_for(J->L, tv); | |
| 525 t = (LJ_DUALNUM || tref_isint(tr[FORL_IDX])) ? lj_opt_narrow_forl(J, tv) : | |
| 526 IRT_NUM; | |
| 527 for (i = FORL_IDX; i <= FORL_STEP; i++) { | |
| 528 if (!tr[i]) sload(J, ra+i); | |
| 529 lj_assertJ(tref_isnumber_str(tr[i]), "bad FORI argument type"); | |
| 530 if (tref_isstr(tr[i])) | |
| 531 tr[i] = emitir(IRTG(IR_STRTO, IRT_NUM), tr[i], 0); | |
| 532 if (t == IRT_INT) { | |
| 533 if (!tref_isinteger(tr[i])) | |
| 534 tr[i] = emitir(IRTGI(IR_CONV), tr[i], IRCONV_INT_NUM|IRCONV_CHECK); | |
| 535 } else { | |
| 536 if (!tref_isnum(tr[i])) | |
| 537 tr[i] = emitir(IRTN(IR_CONV), tr[i], IRCONV_NUM_INT); | |
| 538 } | |
| 539 } | |
| 540 tr[FORL_EXT] = tr[FORL_IDX]; | |
| 541 stop = tr[FORL_STOP]; | |
| 542 rec_for_check(J, t, rec_for_direction(&tv[FORL_STEP]), | |
| 543 stop, tr[FORL_STEP], 1); | |
| 544 } | |
| 545 | |
| 546 ev = rec_for_iter(&op, tv, isforl); | |
| 547 if (ev == LOOPEV_LEAVE) { | |
| 548 J->maxslot = ra+FORL_EXT+1; | |
| 549 J->pc = fori+1; | |
| 550 } else { | |
| 551 J->maxslot = ra; | |
| 552 J->pc = fori+bc_j(*fori)+1; | |
| 553 } | |
| 554 lj_snap_add(J); | |
| 555 | |
| 556 emitir(IRTG(op, t), tr[FORL_IDX], stop); | |
| 557 | |
| 558 if (ev == LOOPEV_LEAVE) { | |
| 559 J->maxslot = ra; | |
| 560 J->pc = fori+bc_j(*fori)+1; | |
| 561 } else { | |
| 562 J->maxslot = ra+FORL_EXT+1; | |
| 563 J->pc = fori+1; | |
| 564 } | |
| 565 J->needsnap = 1; | |
| 566 return ev; | |
| 567 } | |
| 568 | |
| 569 /* Record ITERL/JITERL. */ | |
| 570 static LoopEvent rec_iterl(jit_State *J, const BCIns iterins) | |
| 571 { | |
| 572 BCReg ra = bc_a(iterins); | |
| 573 if (!tref_isnil(getslot(J, ra))) { /* Looping back? */ | |
| 574 J->base[ra-1] = J->base[ra]; /* Copy result of ITERC to control var. */ | |
| 575 J->maxslot = ra-1+bc_b(J->pc[-1]); | |
| 576 J->pc += bc_j(iterins)+1; | |
| 577 return LOOPEV_ENTER; | |
| 578 } else { | |
| 579 J->maxslot = ra-3; | |
| 580 J->pc++; | |
| 581 return LOOPEV_LEAVE; | |
| 582 } | |
| 583 } | |
| 584 | |
| 585 /* Record LOOP/JLOOP. Now, that was easy. */ | |
| 586 static LoopEvent rec_loop(jit_State *J, BCReg ra, int skip) | |
| 587 { | |
| 588 if (ra < J->maxslot) J->maxslot = ra; | |
| 589 J->pc += skip; | |
| 590 return LOOPEV_ENTER; | |
| 591 } | |
| 592 | |
| 593 /* Check if a loop repeatedly failed to trace because it didn't loop back. */ | |
| 594 static int innerloopleft(jit_State *J, const BCIns *pc) | |
| 595 { | |
| 596 ptrdiff_t i; | |
| 597 for (i = 0; i < PENALTY_SLOTS; i++) | |
| 598 if (mref(J->penalty[i].pc, const BCIns) == pc) { | |
| 599 if ((J->penalty[i].reason == LJ_TRERR_LLEAVE || | |
| 600 J->penalty[i].reason == LJ_TRERR_LINNER) && | |
| 601 J->penalty[i].val >= 2*PENALTY_MIN) | |
| 602 return 1; | |
| 603 break; | |
| 604 } | |
| 605 return 0; | |
| 606 } | |
| 607 | |
| 608 /* Handle the case when an interpreted loop op is hit. */ | |
| 609 static void rec_loop_interp(jit_State *J, const BCIns *pc, LoopEvent ev) | |
| 610 { | |
| 611 if (J->parent == 0 && J->exitno == 0) { | |
| 612 if (pc == J->startpc && J->framedepth + J->retdepth == 0) { | |
| 613 if (bc_op(J->cur.startins) == BC_ITERN) return; /* See rec_itern(). */ | |
| 614 /* Same loop? */ | |
| 615 if (ev == LOOPEV_LEAVE) /* Must loop back to form a root trace. */ | |
| 616 lj_trace_err(J, LJ_TRERR_LLEAVE); | |
| 617 lj_record_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Looping trace. */ | |
| 618 } else if (ev != LOOPEV_LEAVE) { /* Entering inner loop? */ | |
| 619 /* It's usually better to abort here and wait until the inner loop | |
| 620 ** is traced. But if the inner loop repeatedly didn't loop back, | |
| 621 ** this indicates a low trip count. In this case try unrolling | |
| 622 ** an inner loop even in a root trace. But it's better to be a bit | |
| 623 ** more conservative here and only do it for very short loops. | |
| 624 */ | |
| 625 if (bc_j(*pc) != -1 && !innerloopleft(J, pc)) | |
| 626 lj_trace_err(J, LJ_TRERR_LINNER); /* Root trace hit an inner loop. */ | |
| 627 if ((ev != LOOPEV_ENTERLO && | |
| 628 J->loopref && J->cur.nins - J->loopref > 24) || --J->loopunroll < 0) | |
| 629 lj_trace_err(J, LJ_TRERR_LUNROLL); /* Limit loop unrolling. */ | |
| 630 J->loopref = J->cur.nins; | |
| 631 } | |
| 632 } else if (ev != LOOPEV_LEAVE) { /* Side trace enters an inner loop. */ | |
| 633 J->loopref = J->cur.nins; | |
| 634 if (--J->loopunroll < 0) | |
| 635 lj_trace_err(J, LJ_TRERR_LUNROLL); /* Limit loop unrolling. */ | |
| 636 } /* Side trace continues across a loop that's left or not entered. */ | |
| 637 } | |
| 638 | |
| 639 /* Handle the case when an already compiled loop op is hit. */ | |
| 640 static void rec_loop_jit(jit_State *J, TraceNo lnk, LoopEvent ev) | |
| 641 { | |
| 642 if (J->parent == 0 && J->exitno == 0) { /* Root trace hit an inner loop. */ | |
| 643 /* Better let the inner loop spawn a side trace back here. */ | |
| 644 lj_trace_err(J, LJ_TRERR_LINNER); | |
| 645 } else if (ev != LOOPEV_LEAVE) { /* Side trace enters a compiled loop. */ | |
| 646 J->instunroll = 0; /* Cannot continue across a compiled loop op. */ | |
| 647 if (J->pc == J->startpc && J->framedepth + J->retdepth == 0) | |
| 648 lj_record_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Form extra loop. */ | |
| 649 else | |
| 650 lj_record_stop(J, LJ_TRLINK_ROOT, lnk); /* Link to the loop. */ | |
| 651 } /* Side trace continues across a loop that's left or not entered. */ | |
| 652 } | |
| 653 | |
| 654 /* Record ITERN. */ | |
| 655 static LoopEvent rec_itern(jit_State *J, BCReg ra, BCReg rb) | |
| 656 { | |
| 657 #if LJ_BE | |
| 658 /* YAGNI: Disabled on big-endian due to issues with lj_vm_next, | |
| 659 ** IR_HIOP, RID_RETLO/RID_RETHI and ra_destpair. | |
| 660 */ | |
| 661 UNUSED(ra); UNUSED(rb); | |
| 662 setintV(&J->errinfo, (int32_t)BC_ITERN); | |
| 663 lj_trace_err_info(J, LJ_TRERR_NYIBC); | |
| 664 #else | |
| 665 RecordIndex ix; | |
| 666 /* Since ITERN is recorded at the start, we need our own loop detection. */ | |
| 667 if (J->pc == J->startpc && | |
| 668 J->framedepth + J->retdepth == 0 && J->parent == 0 && J->exitno == 0) { | |
| 669 IRRef ref = REF_FIRST + LJ_HASPROFILE; | |
| 670 #ifdef LUAJIT_ENABLE_CHECKHOOK | |
| 671 ref += 3; | |
| 672 #endif | |
| 673 if (J->cur.nins > ref || | |
| 674 (LJ_HASPROFILE && J->cur.nins == ref && J->cur.ir[ref-1].o != IR_PROF)) { | |
| 675 J->instunroll = 0; /* Cannot continue unrolling across an ITERN. */ | |
| 676 lj_record_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Looping trace. */ | |
| 677 return LOOPEV_ENTER; | |
| 678 } | |
| 679 } | |
| 680 J->maxslot = ra; | |
| 681 lj_snap_add(J); /* Required to make JLOOP the first ins in a side-trace. */ | |
| 682 ix.tab = getslot(J, ra-2); | |
| 683 ix.key = J->base[ra-1] ? J->base[ra-1] : | |
| 684 sloadt(J, (int32_t)(ra-1), IRT_GUARD|IRT_INT, | |
| 685 IRSLOAD_TYPECHECK|IRSLOAD_KEYINDEX); | |
| 686 copyTV(J->L, &ix.tabv, &J->L->base[ra-2]); | |
| 687 copyTV(J->L, &ix.keyv, &J->L->base[ra-1]); | |
| 688 ix.idxchain = (rb < 3); /* Omit value type check, if unused. */ | |
| 689 ix.mobj = 1; /* We need the next index, too. */ | |
| 690 J->maxslot = ra + lj_record_next(J, &ix); | |
| 691 J->needsnap = 1; | |
| 692 if (!tref_isnil(ix.key)) { /* Looping back? */ | |
| 693 J->base[ra-1] = ix.mobj | TREF_KEYINDEX; /* Control var has next index. */ | |
| 694 J->base[ra] = ix.key; | |
| 695 J->base[ra+1] = ix.val; | |
| 696 J->pc += bc_j(J->pc[1])+2; | |
| 697 return LOOPEV_ENTER; | |
| 698 } else { | |
| 699 J->maxslot = ra-3; | |
| 700 J->pc += 2; | |
| 701 return LOOPEV_LEAVE; | |
| 702 } | |
| 703 #endif | |
| 704 } | |
| 705 | |
| 706 /* Record ISNEXT. */ | |
| 707 static void rec_isnext(jit_State *J, BCReg ra) | |
| 708 { | |
| 709 cTValue *b = &J->L->base[ra-3]; | |
| 710 if (tvisfunc(b) && funcV(b)->c.ffid == FF_next && | |
| 711 tvistab(b+1) && tvisnil(b+2)) { | |
| 712 /* These checks are folded away for a compiled pairs(). */ | |
| 713 TRef func = getslot(J, ra-3); | |
| 714 TRef trid = emitir(IRT(IR_FLOAD, IRT_U8), func, IRFL_FUNC_FFID); | |
| 715 emitir(IRTGI(IR_EQ), trid, lj_ir_kint(J, FF_next)); | |
| 716 (void)getslot(J, ra-2); /* Type check for table. */ | |
| 717 (void)getslot(J, ra-1); /* Type check for nil key. */ | |
| 718 J->base[ra-1] = lj_ir_kint(J, 0) | TREF_KEYINDEX; | |
| 719 J->maxslot = ra; | |
| 720 } else { /* Abort trace. Interpreter will despecialize bytecode. */ | |
| 721 lj_trace_err(J, LJ_TRERR_RECERR); | |
| 722 } | |
| 723 } | |
| 724 | |
| 725 /* -- Record profiler hook checks ----------------------------------------- */ | |
| 726 | |
| 727 #if LJ_HASPROFILE | |
| 728 | |
| 729 /* Need to insert profiler hook check? */ | |
| 730 static int rec_profile_need(jit_State *J, GCproto *pt, const BCIns *pc) | |
| 731 { | |
| 732 GCproto *ppt; | |
| 733 lj_assertJ(J->prof_mode == 'f' || J->prof_mode == 'l', | |
| 734 "bad profiler mode %c", J->prof_mode); | |
| 735 if (!pt) | |
| 736 return 0; | |
| 737 ppt = J->prev_pt; | |
| 738 J->prev_pt = pt; | |
| 739 if (pt != ppt && ppt) { | |
| 740 J->prev_line = -1; | |
| 741 return 1; | |
| 742 } | |
| 743 if (J->prof_mode == 'l') { | |
| 744 BCLine line = lj_debug_line(pt, proto_bcpos(pt, pc)); | |
| 745 BCLine pline = J->prev_line; | |
| 746 J->prev_line = line; | |
| 747 if (pline != line) | |
| 748 return 1; | |
| 749 } | |
| 750 return 0; | |
| 751 } | |
| 752 | |
| 753 static void rec_profile_ins(jit_State *J, const BCIns *pc) | |
| 754 { | |
| 755 if (J->prof_mode && rec_profile_need(J, J->pt, pc)) { | |
| 756 emitir(IRTG(IR_PROF, IRT_NIL), 0, 0); | |
| 757 lj_snap_add(J); | |
| 758 } | |
| 759 } | |
| 760 | |
| 761 static void rec_profile_ret(jit_State *J) | |
| 762 { | |
| 763 if (J->prof_mode == 'f') { | |
| 764 emitir(IRTG(IR_PROF, IRT_NIL), 0, 0); | |
| 765 J->prev_pt = NULL; | |
| 766 lj_snap_add(J); | |
| 767 } | |
| 768 } | |
| 769 | |
| 770 #endif | |
| 771 | |
| 772 /* -- Record calls and returns -------------------------------------------- */ | |
| 773 | |
| 774 /* Specialize to the runtime value of the called function or its prototype. */ | |
| 775 static TRef rec_call_specialize(jit_State *J, GCfunc *fn, TRef tr) | |
| 776 { | |
| 777 TRef kfunc; | |
| 778 if (isluafunc(fn)) { | |
| 779 GCproto *pt = funcproto(fn); | |
| 780 /* Too many closures created? Probably not a monomorphic function. */ | |
| 781 if (pt->flags >= PROTO_CLC_POLY) { /* Specialize to prototype instead. */ | |
| 782 TRef trpt = emitir(IRT(IR_FLOAD, IRT_PGC), tr, IRFL_FUNC_PC); | |
| 783 emitir(IRTG(IR_EQ, IRT_PGC), trpt, lj_ir_kptr(J, proto_bc(pt))); | |
| 784 (void)lj_ir_kgc(J, obj2gco(pt), IRT_PROTO); /* Prevent GC of proto. */ | |
| 785 return tr; | |
| 786 } | |
| 787 } else { | |
| 788 /* Don't specialize to non-monomorphic builtins. */ | |
| 789 switch (fn->c.ffid) { | |
| 790 case FF_coroutine_wrap_aux: | |
| 791 case FF_string_gmatch_aux: | |
| 792 /* NYI: io_file_iter doesn't have an ffid, yet. */ | |
| 793 { /* Specialize to the ffid. */ | |
| 794 TRef trid = emitir(IRT(IR_FLOAD, IRT_U8), tr, IRFL_FUNC_FFID); | |
| 795 emitir(IRTGI(IR_EQ), trid, lj_ir_kint(J, fn->c.ffid)); | |
| 796 } | |
| 797 return tr; | |
| 798 default: | |
| 799 /* NYI: don't specialize to non-monomorphic C functions. */ | |
| 800 break; | |
| 801 } | |
| 802 } | |
| 803 /* Otherwise specialize to the function (closure) value itself. */ | |
| 804 kfunc = lj_ir_kfunc(J, fn); | |
| 805 emitir(IRTG(IR_EQ, IRT_FUNC), tr, kfunc); | |
| 806 return kfunc; | |
| 807 } | |
| 808 | |
| 809 /* Record call setup. */ | |
| 810 static void rec_call_setup(jit_State *J, BCReg func, ptrdiff_t nargs) | |
| 811 { | |
| 812 RecordIndex ix; | |
| 813 TValue *functv = &J->L->base[func]; | |
| 814 TRef kfunc, *fbase = &J->base[func]; | |
| 815 ptrdiff_t i; | |
| 816 (void)getslot(J, func); /* Ensure func has a reference. */ | |
| 817 for (i = 1; i <= nargs; i++) | |
| 818 (void)getslot(J, func+LJ_FR2+i); /* Ensure all args have a reference. */ | |
| 819 if (!tref_isfunc(fbase[0])) { /* Resolve __call metamethod. */ | |
| 820 ix.tab = fbase[0]; | |
| 821 copyTV(J->L, &ix.tabv, functv); | |
| 822 if (!lj_record_mm_lookup(J, &ix, MM_call) || !tref_isfunc(ix.mobj)) | |
| 823 lj_trace_err(J, LJ_TRERR_NOMM); | |
| 824 for (i = ++nargs; i > LJ_FR2; i--) /* Shift arguments up. */ | |
| 825 fbase[i+LJ_FR2] = fbase[i+LJ_FR2-1]; | |
| 826 #if LJ_FR2 | |
| 827 fbase[2] = fbase[0]; | |
| 828 #endif | |
| 829 fbase[0] = ix.mobj; /* Replace function. */ | |
| 830 functv = &ix.mobjv; | |
| 831 } | |
| 832 kfunc = rec_call_specialize(J, funcV(functv), fbase[0]); | |
| 833 #if LJ_FR2 | |
| 834 fbase[0] = kfunc; | |
| 835 fbase[1] = TREF_FRAME; | |
| 836 #else | |
| 837 fbase[0] = kfunc | TREF_FRAME; | |
| 838 #endif | |
| 839 J->maxslot = (BCReg)nargs; | |
| 840 } | |
| 841 | |
| 842 /* Record call. */ | |
| 843 void lj_record_call(jit_State *J, BCReg func, ptrdiff_t nargs) | |
| 844 { | |
| 845 rec_call_setup(J, func, nargs); | |
| 846 /* Bump frame. */ | |
| 847 J->framedepth++; | |
| 848 J->base += func+1+LJ_FR2; | |
| 849 J->baseslot += func+1+LJ_FR2; | |
| 850 if (J->baseslot + J->maxslot >= LJ_MAX_JSLOTS) | |
| 851 lj_trace_err(J, LJ_TRERR_STACKOV); | |
| 852 } | |
| 853 | |
| 854 /* Record tail call. */ | |
| 855 void lj_record_tailcall(jit_State *J, BCReg func, ptrdiff_t nargs) | |
| 856 { | |
| 857 rec_call_setup(J, func, nargs); | |
| 858 if (frame_isvarg(J->L->base - 1)) { | |
| 859 BCReg cbase = (BCReg)frame_delta(J->L->base - 1); | |
| 860 if (--J->framedepth < 0) | |
| 861 lj_trace_err(J, LJ_TRERR_NYIRETL); | |
| 862 J->baseslot -= (BCReg)cbase; | |
| 863 J->base -= cbase; | |
| 864 func += cbase; | |
| 865 } | |
| 866 /* Move func + args down. */ | |
| 867 if (LJ_FR2 && J->baseslot == 2) | |
| 868 J->base[func+1] = TREF_FRAME; | |
| 869 memmove(&J->base[-1-LJ_FR2], &J->base[func], sizeof(TRef)*(J->maxslot+1+LJ_FR2)); | |
| 870 /* Note: the new TREF_FRAME is now at J->base[-1] (even for slot #0). */ | |
| 871 /* Tailcalls can form a loop, so count towards the loop unroll limit. */ | |
| 872 if (++J->tailcalled > J->loopunroll) | |
| 873 lj_trace_err(J, LJ_TRERR_LUNROLL); | |
| 874 } | |
| 875 | |
| 876 /* Check unroll limits for down-recursion. */ | |
| 877 static int check_downrec_unroll(jit_State *J, GCproto *pt) | |
| 878 { | |
| 879 IRRef ptref; | |
| 880 for (ptref = J->chain[IR_KGC]; ptref; ptref = IR(ptref)->prev) | |
| 881 if (ir_kgc(IR(ptref)) == obj2gco(pt)) { | |
| 882 int count = 0; | |
| 883 IRRef ref; | |
| 884 for (ref = J->chain[IR_RETF]; ref; ref = IR(ref)->prev) | |
| 885 if (IR(ref)->op1 == ptref) | |
| 886 count++; | |
| 887 if (count) { | |
| 888 if (J->pc == J->startpc) { | |
| 889 if (count + J->tailcalled > J->param[JIT_P_recunroll]) | |
| 890 return 1; | |
| 891 } else { | |
| 892 lj_trace_err(J, LJ_TRERR_DOWNREC); | |
| 893 } | |
| 894 } | |
| 895 } | |
| 896 return 0; | |
| 897 } | |
| 898 | |
| 899 static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot); | |
| 900 | |
| 901 /* Record return. */ | |
| 902 void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |
| 903 { | |
| 904 TValue *frame = J->L->base - 1; | |
| 905 ptrdiff_t i; | |
| 906 for (i = 0; i < gotresults; i++) | |
| 907 (void)getslot(J, rbase+i); /* Ensure all results have a reference. */ | |
| 908 while (frame_ispcall(frame)) { /* Immediately resolve pcall() returns. */ | |
| 909 BCReg cbase = (BCReg)frame_delta(frame); | |
| 910 if (--J->framedepth <= 0) | |
| 911 lj_trace_err(J, LJ_TRERR_NYIRETL); | |
| 912 lj_assertJ(J->baseslot > 1+LJ_FR2, "bad baseslot for return"); | |
| 913 gotresults++; | |
| 914 rbase += cbase; | |
| 915 J->baseslot -= (BCReg)cbase; | |
| 916 J->base -= cbase; | |
| 917 J->base[--rbase] = TREF_TRUE; /* Prepend true to results. */ | |
| 918 frame = frame_prevd(frame); | |
| 919 J->needsnap = 1; /* Stop catching on-trace errors. */ | |
| 920 } | |
| 921 /* Return to lower frame via interpreter for unhandled cases. */ | |
| 922 if (J->framedepth == 0 && J->pt && bc_isret(bc_op(*J->pc)) && | |
| 923 (!frame_islua(frame) || | |
| 924 (J->parent == 0 && J->exitno == 0 && | |
| 925 !bc_isret(bc_op(J->cur.startins))))) { | |
| 926 /* NYI: specialize to frame type and return directly, not via RET*. */ | |
| 927 for (i = 0; i < (ptrdiff_t)rbase; i++) | |
| 928 J->base[i] = 0; /* Purge dead slots. */ | |
| 929 J->maxslot = rbase + (BCReg)gotresults; | |
| 930 lj_record_stop(J, LJ_TRLINK_RETURN, 0); /* Return to interpreter. */ | |
| 931 return; | |
| 932 } | |
| 933 if (frame_isvarg(frame)) { | |
| 934 BCReg cbase = (BCReg)frame_delta(frame); | |
| 935 if (--J->framedepth < 0) /* NYI: return of vararg func to lower frame. */ | |
| 936 lj_trace_err(J, LJ_TRERR_NYIRETL); | |
| 937 lj_assertJ(J->baseslot > 1+LJ_FR2, "bad baseslot for return"); | |
| 938 rbase += cbase; | |
| 939 J->baseslot -= (BCReg)cbase; | |
| 940 J->base -= cbase; | |
| 941 frame = frame_prevd(frame); | |
| 942 } | |
| 943 if (frame_islua(frame)) { /* Return to Lua frame. */ | |
| 944 BCIns callins = *(frame_pc(frame)-1); | |
| 945 ptrdiff_t nresults = bc_b(callins) ? (ptrdiff_t)bc_b(callins)-1 :gotresults; | |
| 946 BCReg cbase = bc_a(callins); | |
| 947 GCproto *pt = funcproto(frame_func(frame - (cbase+1+LJ_FR2))); | |
| 948 if ((pt->flags & PROTO_NOJIT)) | |
| 949 lj_trace_err(J, LJ_TRERR_CJITOFF); | |
| 950 if (J->framedepth == 0 && J->pt && frame == J->L->base - 1) { | |
| 951 if (check_downrec_unroll(J, pt)) { | |
| 952 J->maxslot = (BCReg)(rbase + gotresults); | |
| 953 lj_snap_purge(J); | |
| 954 lj_record_stop(J, LJ_TRLINK_DOWNREC, J->cur.traceno); /* Down-rec. */ | |
| 955 return; | |
| 956 } | |
| 957 lj_snap_add(J); | |
| 958 } | |
| 959 for (i = 0; i < nresults; i++) /* Adjust results. */ | |
| 960 J->base[i-1-LJ_FR2] = i < gotresults ? J->base[rbase+i] : TREF_NIL; | |
| 961 J->maxslot = cbase+(BCReg)nresults; | |
| 962 if (J->framedepth > 0) { /* Return to a frame that is part of the trace. */ | |
| 963 J->framedepth--; | |
| 964 lj_assertJ(J->baseslot > cbase+1+LJ_FR2, "bad baseslot for return"); | |
| 965 J->baseslot -= cbase+1+LJ_FR2; | |
| 966 J->base -= cbase+1+LJ_FR2; | |
| 967 } else if (J->parent == 0 && J->exitno == 0 && | |
| 968 !bc_isret(bc_op(J->cur.startins))) { | |
| 969 /* Return to lower frame would leave the loop in a root trace. */ | |
| 970 lj_trace_err(J, LJ_TRERR_LLEAVE); | |
| 971 } else if (J->needsnap) { /* Tailcalled to ff with side-effects. */ | |
| 972 lj_trace_err(J, LJ_TRERR_NYIRETL); /* No way to insert snapshot here. */ | |
| 973 } else { /* Return to lower frame. Guard for the target we return to. */ | |
| 974 TRef trpt = lj_ir_kgc(J, obj2gco(pt), IRT_PROTO); | |
| 975 TRef trpc = lj_ir_kptr(J, (void *)frame_pc(frame)); | |
| 976 emitir(IRTG(IR_RETF, IRT_PGC), trpt, trpc); | |
| 977 J->retdepth++; | |
| 978 J->needsnap = 1; | |
| 979 lj_assertJ(J->baseslot == 1+LJ_FR2, "bad baseslot for return"); | |
| 980 /* Shift result slots up and clear the slots of the new frame below. */ | |
| 981 memmove(J->base + cbase, J->base-1-LJ_FR2, sizeof(TRef)*nresults); | |
| 982 memset(J->base-1-LJ_FR2, 0, sizeof(TRef)*(cbase+1+LJ_FR2)); | |
| 983 } | |
| 984 } else if (frame_iscont(frame)) { /* Return to continuation frame. */ | |
| 985 ASMFunction cont = frame_contf(frame); | |
| 986 BCReg cbase = (BCReg)frame_delta(frame); | |
| 987 if ((J->framedepth -= 2) < 0) | |
| 988 lj_trace_err(J, LJ_TRERR_NYIRETL); | |
| 989 J->baseslot -= (BCReg)cbase; | |
| 990 J->base -= cbase; | |
| 991 J->maxslot = cbase-(2<<LJ_FR2); | |
| 992 if (cont == lj_cont_ra) { | |
| 993 /* Copy result to destination slot. */ | |
| 994 BCReg dst = bc_a(*(frame_contpc(frame)-1)); | |
| 995 J->base[dst] = gotresults ? J->base[cbase+rbase] : TREF_NIL; | |
| 996 if (dst >= J->maxslot) { | |
| 997 J->maxslot = dst+1; | |
| 998 } | |
| 999 } else if (cont == lj_cont_nop) { | |
| 1000 /* Nothing to do here. */ | |
| 1001 } else if (cont == lj_cont_cat) { | |
| 1002 BCReg bslot = bc_b(*(frame_contpc(frame)-1)); | |
| 1003 TRef tr = gotresults ? J->base[cbase+rbase] : TREF_NIL; | |
| 1004 if (bslot != J->maxslot) { /* Concatenate the remainder. */ | |
| 1005 TValue *b = J->L->base, save; /* Simulate lower frame and result. */ | |
| 1006 /* Can't handle MM_concat + CALLT + fast func side-effects. */ | |
| 1007 if (J->postproc != LJ_POST_NONE) | |
| 1008 lj_trace_err(J, LJ_TRERR_NYIRETL); | |
| 1009 J->base[J->maxslot] = tr; | |
| 1010 copyTV(J->L, &save, b-(2<<LJ_FR2)); | |
| 1011 if (gotresults) | |
| 1012 copyTV(J->L, b-(2<<LJ_FR2), b+rbase); | |
| 1013 else | |
| 1014 setnilV(b-(2<<LJ_FR2)); | |
| 1015 J->L->base = b - cbase; | |
| 1016 tr = rec_cat(J, bslot, cbase-(2<<LJ_FR2)); | |
| 1017 b = J->L->base + cbase; /* Undo. */ | |
| 1018 J->L->base = b; | |
| 1019 copyTV(J->L, b-(2<<LJ_FR2), &save); | |
| 1020 } | |
| 1021 if (tr) { /* Store final result. */ | |
| 1022 BCReg dst = bc_a(*(frame_contpc(frame)-1)); | |
| 1023 J->base[dst] = tr; | |
| 1024 if (dst >= J->maxslot) { | |
| 1025 J->maxslot = dst+1; | |
| 1026 } | |
| 1027 } /* Otherwise continue with another __concat call. */ | |
| 1028 } else { | |
| 1029 /* Result type already specialized. */ | |
| 1030 lj_assertJ(cont == lj_cont_condf || cont == lj_cont_condt, | |
| 1031 "bad continuation type"); | |
| 1032 } | |
| 1033 } else { | |
| 1034 lj_trace_err(J, LJ_TRERR_NYIRETL); /* NYI: handle return to C frame. */ | |
| 1035 } | |
| 1036 lj_assertJ(J->baseslot >= 1+LJ_FR2, "bad baseslot for return"); | |
| 1037 } | |
| 1038 | |
| 1039 /* -- Metamethod handling ------------------------------------------------- */ | |
| 1040 | |
| 1041 /* Prepare to record call to metamethod. */ | |
| 1042 static BCReg rec_mm_prep(jit_State *J, ASMFunction cont) | |
| 1043 { | |
| 1044 BCReg s, top = cont == lj_cont_cat ? J->maxslot : curr_proto(J->L)->framesize; | |
| 1045 #if LJ_FR2 | |
| 1046 J->base[top] = lj_ir_k64(J, IR_KNUM, u64ptr(contptr(cont))); | |
| 1047 J->base[top+1] = TREF_CONT; | |
| 1048 #else | |
| 1049 J->base[top] = lj_ir_kptr(J, contptr(cont)) | TREF_CONT; | |
| 1050 #endif | |
| 1051 J->framedepth++; | |
| 1052 for (s = J->maxslot; s < top; s++) | |
| 1053 J->base[s] = 0; /* Clear frame gap to avoid resurrecting previous refs. */ | |
| 1054 return top+1+LJ_FR2; | |
| 1055 } | |
| 1056 | |
| 1057 /* Record metamethod lookup. */ | |
| 1058 int lj_record_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm) | |
| 1059 { | |
| 1060 RecordIndex mix; | |
| 1061 GCtab *mt; | |
| 1062 if (tref_istab(ix->tab)) { | |
| 1063 mt = tabref(tabV(&ix->tabv)->metatable); | |
| 1064 mix.tab = emitir(IRT(IR_FLOAD, IRT_TAB), ix->tab, IRFL_TAB_META); | |
| 1065 } else if (tref_isudata(ix->tab)) { | |
| 1066 int udtype = udataV(&ix->tabv)->udtype; | |
| 1067 mt = tabref(udataV(&ix->tabv)->metatable); | |
| 1068 /* The metatables of special userdata objects are treated as immutable. */ | |
| 1069 if (udtype != UDTYPE_USERDATA) { | |
| 1070 cTValue *mo; | |
| 1071 if (LJ_HASFFI && udtype == UDTYPE_FFI_CLIB) { | |
| 1072 /* Specialize to the C library namespace object. */ | |
| 1073 emitir(IRTG(IR_EQ, IRT_PGC), ix->tab, lj_ir_kptr(J, udataV(&ix->tabv))); | |
| 1074 } else { | |
| 1075 /* Specialize to the type of userdata. */ | |
| 1076 TRef tr = emitir(IRT(IR_FLOAD, IRT_U8), ix->tab, IRFL_UDATA_UDTYPE); | |
| 1077 emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, udtype)); | |
| 1078 } | |
| 1079 immutable_mt: | |
| 1080 mo = lj_tab_getstr(mt, mmname_str(J2G(J), mm)); | |
| 1081 if (!mo || tvisnil(mo)) | |
| 1082 return 0; /* No metamethod. */ | |
| 1083 /* Treat metamethod or index table as immutable, too. */ | |
| 1084 if (!(tvisfunc(mo) || tvistab(mo))) | |
| 1085 lj_trace_err(J, LJ_TRERR_BADTYPE); | |
| 1086 copyTV(J->L, &ix->mobjv, mo); | |
| 1087 ix->mobj = lj_ir_kgc(J, gcV(mo), tvisfunc(mo) ? IRT_FUNC : IRT_TAB); | |
| 1088 ix->mtv = mt; | |
| 1089 ix->mt = TREF_NIL; /* Dummy value for comparison semantics. */ | |
| 1090 return 1; /* Got metamethod or index table. */ | |
| 1091 } | |
| 1092 mix.tab = emitir(IRT(IR_FLOAD, IRT_TAB), ix->tab, IRFL_UDATA_META); | |
| 1093 } else { | |
| 1094 /* Specialize to base metatable. Must flush mcode in lua_setmetatable(). */ | |
| 1095 mt = tabref(basemt_obj(J2G(J), &ix->tabv)); | |
| 1096 if (mt == NULL) { | |
| 1097 ix->mt = TREF_NIL; | |
| 1098 return 0; /* No metamethod. */ | |
| 1099 } | |
| 1100 /* The cdata metatable is treated as immutable. */ | |
| 1101 if (LJ_HASFFI && tref_iscdata(ix->tab)) goto immutable_mt; | |
| 1102 ix->mt = mix.tab = lj_ir_ggfload(J, IRT_TAB, | |
| 1103 GG_OFS(g.gcroot[GCROOT_BASEMT+itypemap(&ix->tabv)])); | |
| 1104 goto nocheck; | |
| 1105 } | |
| 1106 ix->mt = mt ? mix.tab : TREF_NIL; | |
| 1107 emitir(IRTG(mt ? IR_NE : IR_EQ, IRT_TAB), mix.tab, lj_ir_knull(J, IRT_TAB)); | |
| 1108 nocheck: | |
| 1109 if (mt) { | |
| 1110 GCstr *mmstr = mmname_str(J2G(J), mm); | |
| 1111 cTValue *mo = lj_tab_getstr(mt, mmstr); | |
| 1112 if (mo && !tvisnil(mo)) | |
| 1113 copyTV(J->L, &ix->mobjv, mo); | |
| 1114 ix->mtv = mt; | |
| 1115 settabV(J->L, &mix.tabv, mt); | |
| 1116 setstrV(J->L, &mix.keyv, mmstr); | |
| 1117 mix.key = lj_ir_kstr(J, mmstr); | |
| 1118 mix.val = 0; | |
| 1119 mix.idxchain = 0; | |
| 1120 ix->mobj = lj_record_idx(J, &mix); | |
| 1121 return !tref_isnil(ix->mobj); /* 1 if metamethod found, 0 if not. */ | |
| 1122 } | |
| 1123 return 0; /* No metamethod. */ | |
| 1124 } | |
| 1125 | |
| 1126 /* Record call to arithmetic metamethod. */ | |
| 1127 static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm) | |
| 1128 { | |
| 1129 /* Set up metamethod call first to save ix->tab and ix->tabv. */ | |
| 1130 BCReg func = rec_mm_prep(J, mm == MM_concat ? lj_cont_cat : lj_cont_ra); | |
| 1131 TRef *base = J->base + func; | |
| 1132 TValue *basev = J->L->base + func; | |
| 1133 base[1+LJ_FR2] = ix->tab; base[2+LJ_FR2] = ix->key; | |
| 1134 copyTV(J->L, basev+1+LJ_FR2, &ix->tabv); | |
| 1135 copyTV(J->L, basev+2+LJ_FR2, &ix->keyv); | |
| 1136 if (!lj_record_mm_lookup(J, ix, mm)) { /* Lookup mm on 1st operand. */ | |
| 1137 if (mm != MM_unm) { | |
| 1138 ix->tab = ix->key; | |
| 1139 copyTV(J->L, &ix->tabv, &ix->keyv); | |
| 1140 if (lj_record_mm_lookup(J, ix, mm)) /* Lookup mm on 2nd operand. */ | |
| 1141 goto ok; | |
| 1142 } | |
| 1143 lj_trace_err(J, LJ_TRERR_NOMM); | |
| 1144 } | |
| 1145 ok: | |
| 1146 base[0] = ix->mobj; | |
| 1147 #if LJ_FR2 | |
| 1148 base[1] = 0; | |
| 1149 #endif | |
| 1150 copyTV(J->L, basev+0, &ix->mobjv); | |
| 1151 lj_record_call(J, func, 2); | |
| 1152 return 0; /* No result yet. */ | |
| 1153 } | |
| 1154 | |
| 1155 /* Record call to __len metamethod. */ | |
| 1156 static TRef rec_mm_len(jit_State *J, TRef tr, TValue *tv) | |
| 1157 { | |
| 1158 RecordIndex ix; | |
| 1159 ix.tab = tr; | |
| 1160 copyTV(J->L, &ix.tabv, tv); | |
| 1161 if (lj_record_mm_lookup(J, &ix, MM_len)) { | |
| 1162 BCReg func = rec_mm_prep(J, lj_cont_ra); | |
| 1163 TRef *base = J->base + func; | |
| 1164 TValue *basev = J->L->base + func; | |
| 1165 base[0] = ix.mobj; copyTV(J->L, basev+0, &ix.mobjv); | |
| 1166 base += LJ_FR2; | |
| 1167 basev += LJ_FR2; | |
| 1168 base[1] = tr; copyTV(J->L, basev+1, tv); | |
| 1169 #if LJ_52 | |
| 1170 base[2] = tr; copyTV(J->L, basev+2, tv); | |
| 1171 #else | |
| 1172 base[2] = TREF_NIL; setnilV(basev+2); | |
| 1173 #endif | |
| 1174 lj_record_call(J, func, 2); | |
| 1175 } else { | |
| 1176 if (LJ_52 && tref_istab(tr)) | |
| 1177 return emitir(IRTI(IR_ALEN), tr, TREF_NIL); | |
| 1178 lj_trace_err(J, LJ_TRERR_NOMM); | |
| 1179 } | |
| 1180 return 0; /* No result yet. */ | |
| 1181 } | |
| 1182 | |
| 1183 /* Call a comparison metamethod. */ | |
| 1184 static void rec_mm_callcomp(jit_State *J, RecordIndex *ix, int op) | |
| 1185 { | |
| 1186 BCReg func = rec_mm_prep(J, (op&1) ? lj_cont_condf : lj_cont_condt); | |
| 1187 TRef *base = J->base + func + LJ_FR2; | |
| 1188 TValue *tv = J->L->base + func + LJ_FR2; | |
| 1189 base[-LJ_FR2] = ix->mobj; base[1] = ix->val; base[2] = ix->key; | |
| 1190 copyTV(J->L, tv-LJ_FR2, &ix->mobjv); | |
| 1191 copyTV(J->L, tv+1, &ix->valv); | |
| 1192 copyTV(J->L, tv+2, &ix->keyv); | |
| 1193 lj_record_call(J, func, 2); | |
| 1194 } | |
| 1195 | |
| 1196 /* Record call to equality comparison metamethod (for tab and udata only). */ | |
| 1197 static void rec_mm_equal(jit_State *J, RecordIndex *ix, int op) | |
| 1198 { | |
| 1199 ix->tab = ix->val; | |
| 1200 copyTV(J->L, &ix->tabv, &ix->valv); | |
| 1201 if (lj_record_mm_lookup(J, ix, MM_eq)) { /* Lookup mm on 1st operand. */ | |
| 1202 cTValue *bv; | |
| 1203 TRef mo1 = ix->mobj; | |
| 1204 TValue mo1v; | |
| 1205 copyTV(J->L, &mo1v, &ix->mobjv); | |
| 1206 /* Avoid the 2nd lookup and the objcmp if the metatables are equal. */ | |
| 1207 bv = &ix->keyv; | |
| 1208 if (tvistab(bv) && tabref(tabV(bv)->metatable) == ix->mtv) { | |
| 1209 TRef mt2 = emitir(IRT(IR_FLOAD, IRT_TAB), ix->key, IRFL_TAB_META); | |
| 1210 emitir(IRTG(IR_EQ, IRT_TAB), mt2, ix->mt); | |
| 1211 } else if (tvisudata(bv) && tabref(udataV(bv)->metatable) == ix->mtv) { | |
| 1212 TRef mt2 = emitir(IRT(IR_FLOAD, IRT_TAB), ix->key, IRFL_UDATA_META); | |
| 1213 emitir(IRTG(IR_EQ, IRT_TAB), mt2, ix->mt); | |
| 1214 } else { /* Lookup metamethod on 2nd operand and compare both. */ | |
| 1215 ix->tab = ix->key; | |
| 1216 copyTV(J->L, &ix->tabv, bv); | |
| 1217 if (!lj_record_mm_lookup(J, ix, MM_eq) || | |
| 1218 lj_record_objcmp(J, mo1, ix->mobj, &mo1v, &ix->mobjv)) | |
| 1219 return; | |
| 1220 } | |
| 1221 rec_mm_callcomp(J, ix, op); | |
| 1222 } | |
| 1223 } | |
| 1224 | |
| 1225 /* Record call to ordered comparison metamethods (for arbitrary objects). */ | |
| 1226 static void rec_mm_comp(jit_State *J, RecordIndex *ix, int op) | |
| 1227 { | |
| 1228 ix->tab = ix->val; | |
| 1229 copyTV(J->L, &ix->tabv, &ix->valv); | |
| 1230 while (1) { | |
| 1231 MMS mm = (op & 2) ? MM_le : MM_lt; /* Try __le + __lt or only __lt. */ | |
| 1232 #if LJ_52 | |
| 1233 if (!lj_record_mm_lookup(J, ix, mm)) { /* Lookup mm on 1st operand. */ | |
| 1234 ix->tab = ix->key; | |
| 1235 copyTV(J->L, &ix->tabv, &ix->keyv); | |
| 1236 if (!lj_record_mm_lookup(J, ix, mm)) /* Lookup mm on 2nd operand. */ | |
| 1237 goto nomatch; | |
| 1238 } | |
| 1239 rec_mm_callcomp(J, ix, op); | |
| 1240 return; | |
| 1241 #else | |
| 1242 if (lj_record_mm_lookup(J, ix, mm)) { /* Lookup mm on 1st operand. */ | |
| 1243 cTValue *bv; | |
| 1244 TRef mo1 = ix->mobj; | |
| 1245 TValue mo1v; | |
| 1246 copyTV(J->L, &mo1v, &ix->mobjv); | |
| 1247 /* Avoid the 2nd lookup and the objcmp if the metatables are equal. */ | |
| 1248 bv = &ix->keyv; | |
| 1249 if (tvistab(bv) && tabref(tabV(bv)->metatable) == ix->mtv) { | |
| 1250 TRef mt2 = emitir(IRT(IR_FLOAD, IRT_TAB), ix->key, IRFL_TAB_META); | |
| 1251 emitir(IRTG(IR_EQ, IRT_TAB), mt2, ix->mt); | |
| 1252 } else if (tvisudata(bv) && tabref(udataV(bv)->metatable) == ix->mtv) { | |
| 1253 TRef mt2 = emitir(IRT(IR_FLOAD, IRT_TAB), ix->key, IRFL_UDATA_META); | |
| 1254 emitir(IRTG(IR_EQ, IRT_TAB), mt2, ix->mt); | |
| 1255 } else { /* Lookup metamethod on 2nd operand and compare both. */ | |
| 1256 ix->tab = ix->key; | |
| 1257 copyTV(J->L, &ix->tabv, bv); | |
| 1258 if (!lj_record_mm_lookup(J, ix, mm) || | |
| 1259 lj_record_objcmp(J, mo1, ix->mobj, &mo1v, &ix->mobjv)) | |
| 1260 goto nomatch; | |
| 1261 } | |
| 1262 rec_mm_callcomp(J, ix, op); | |
| 1263 return; | |
| 1264 } | |
| 1265 #endif | |
| 1266 nomatch: | |
| 1267 /* Lookup failed. Retry with __lt and swapped operands. */ | |
| 1268 if (!(op & 2)) break; /* Already at __lt. Interpreter will throw. */ | |
| 1269 ix->tab = ix->key; ix->key = ix->val; ix->val = ix->tab; | |
| 1270 copyTV(J->L, &ix->tabv, &ix->keyv); | |
| 1271 copyTV(J->L, &ix->keyv, &ix->valv); | |
| 1272 copyTV(J->L, &ix->valv, &ix->tabv); | |
| 1273 op ^= 3; | |
| 1274 } | |
| 1275 } | |
| 1276 | |
| 1277 #if LJ_HASFFI | |
| 1278 /* Setup call to cdata comparison metamethod. */ | |
| 1279 static void rec_mm_comp_cdata(jit_State *J, RecordIndex *ix, int op, MMS mm) | |
| 1280 { | |
| 1281 lj_snap_add(J); | |
| 1282 if (tref_iscdata(ix->val)) { | |
| 1283 ix->tab = ix->val; | |
| 1284 copyTV(J->L, &ix->tabv, &ix->valv); | |
| 1285 } else { | |
| 1286 lj_assertJ(tref_iscdata(ix->key), "cdata expected"); | |
| 1287 ix->tab = ix->key; | |
| 1288 copyTV(J->L, &ix->tabv, &ix->keyv); | |
| 1289 } | |
| 1290 lj_record_mm_lookup(J, ix, mm); | |
| 1291 rec_mm_callcomp(J, ix, op); | |
| 1292 } | |
| 1293 #endif | |
| 1294 | |
| 1295 /* -- Indexed access ------------------------------------------------------ */ | |
| 1296 | |
| 1297 #ifdef LUAJIT_ENABLE_TABLE_BUMP | |
| 1298 /* Bump table allocations in bytecode when they grow during recording. */ | |
| 1299 static void rec_idx_bump(jit_State *J, RecordIndex *ix) | |
| 1300 { | |
| 1301 RBCHashEntry *rbc = &J->rbchash[(ix->tab & (RBCHASH_SLOTS-1))]; | |
| 1302 if (tref_ref(ix->tab) == rbc->ref) { | |
| 1303 const BCIns *pc = mref(rbc->pc, const BCIns); | |
| 1304 GCtab *tb = tabV(&ix->tabv); | |
| 1305 uint32_t nhbits; | |
| 1306 IRIns *ir; | |
| 1307 if (!tvisnil(&ix->keyv)) | |
| 1308 (void)lj_tab_set(J->L, tb, &ix->keyv); /* Grow table right now. */ | |
| 1309 nhbits = tb->hmask > 0 ? lj_fls(tb->hmask)+1 : 0; | |
| 1310 ir = IR(tref_ref(ix->tab)); | |
| 1311 if (ir->o == IR_TNEW) { | |
| 1312 uint32_t ah = bc_d(*pc); | |
| 1313 uint32_t asize = ah & 0x7ff, hbits = ah >> 11; | |
| 1314 if (nhbits > hbits) hbits = nhbits; | |
| 1315 if (tb->asize > asize) { | |
| 1316 asize = tb->asize <= 0x7ff ? tb->asize : 0x7ff; | |
| 1317 } | |
| 1318 if ((asize | (hbits<<11)) != ah) { /* Has the size changed? */ | |
| 1319 /* Patch bytecode, but continue recording (for more patching). */ | |
| 1320 setbc_d(pc, (asize | (hbits<<11))); | |
| 1321 /* Patching TNEW operands is only safe if the trace is aborted. */ | |
| 1322 ir->op1 = asize; ir->op2 = hbits; | |
| 1323 J->retryrec = 1; /* Abort the trace at the end of recording. */ | |
| 1324 } | |
| 1325 } else if (ir->o == IR_TDUP) { | |
| 1326 GCtab *tpl = gco2tab(proto_kgc(&gcref(rbc->pt)->pt, ~(ptrdiff_t)bc_d(*pc))); | |
| 1327 /* Grow template table, but preserve keys with nil values. */ | |
| 1328 if ((tb->asize > tpl->asize && (1u << nhbits)-1 == tpl->hmask) || | |
| 1329 (tb->asize == tpl->asize && (1u << nhbits)-1 > tpl->hmask)) { | |
| 1330 Node *node = noderef(tpl->node); | |
| 1331 uint32_t i, hmask = tpl->hmask, asize; | |
| 1332 TValue *array; | |
| 1333 for (i = 0; i <= hmask; i++) { | |
| 1334 if (!tvisnil(&node[i].key) && tvisnil(&node[i].val)) | |
| 1335 settabV(J->L, &node[i].val, tpl); | |
| 1336 } | |
| 1337 if (!tvisnil(&ix->keyv) && tref_isk(ix->key)) { | |
| 1338 TValue *o = lj_tab_set(J->L, tpl, &ix->keyv); | |
| 1339 if (tvisnil(o)) settabV(J->L, o, tpl); | |
| 1340 } | |
| 1341 lj_tab_resize(J->L, tpl, tb->asize, nhbits); | |
| 1342 node = noderef(tpl->node); | |
| 1343 hmask = tpl->hmask; | |
| 1344 for (i = 0; i <= hmask; i++) { | |
| 1345 /* This is safe, since template tables only hold immutable values. */ | |
| 1346 if (tvistab(&node[i].val)) | |
| 1347 setnilV(&node[i].val); | |
| 1348 } | |
| 1349 /* The shape of the table may have changed. Clean up array part, too. */ | |
| 1350 asize = tpl->asize; | |
| 1351 array = tvref(tpl->array); | |
| 1352 for (i = 0; i < asize; i++) { | |
| 1353 if (tvistab(&array[i])) | |
| 1354 setnilV(&array[i]); | |
| 1355 } | |
| 1356 J->retryrec = 1; /* Abort the trace at the end of recording. */ | |
| 1357 } | |
| 1358 } | |
| 1359 } | |
| 1360 } | |
| 1361 #endif | |
| 1362 | |
| 1363 /* Record bounds-check. */ | |
| 1364 static void rec_idx_abc(jit_State *J, TRef asizeref, TRef ikey, uint32_t asize) | |
| 1365 { | |
| 1366 /* Try to emit invariant bounds checks. */ | |
| 1367 if ((J->flags & (JIT_F_OPT_LOOP|JIT_F_OPT_ABC)) == | |
| 1368 (JIT_F_OPT_LOOP|JIT_F_OPT_ABC)) { | |
| 1369 IRRef ref = tref_ref(ikey); | |
| 1370 IRIns *ir = IR(ref); | |
| 1371 int32_t ofs = 0; | |
| 1372 IRRef ofsref = 0; | |
| 1373 /* Handle constant offsets. */ | |
| 1374 if (ir->o == IR_ADD && irref_isk(ir->op2)) { | |
| 1375 ofsref = ir->op2; | |
| 1376 ofs = IR(ofsref)->i; | |
| 1377 ref = ir->op1; | |
| 1378 ir = IR(ref); | |
| 1379 } | |
| 1380 /* Got scalar evolution analysis results for this reference? */ | |
| 1381 if (ref == J->scev.idx) { | |
| 1382 int32_t stop; | |
| 1383 lj_assertJ(irt_isint(J->scev.t) && ir->o == IR_SLOAD, | |
| 1384 "only int SCEV supported"); | |
| 1385 stop = numberVint(&(J->L->base - J->baseslot)[ir->op1 + FORL_STOP]); | |
| 1386 /* Runtime value for stop of loop is within bounds? */ | |
| 1387 if ((uint64_t)stop + ofs < (uint64_t)asize) { | |
| 1388 /* Emit invariant bounds check for stop. */ | |
| 1389 emitir(IRTG(IR_ABC, IRT_P32), asizeref, ofs == 0 ? J->scev.stop : | |
| 1390 emitir(IRTI(IR_ADD), J->scev.stop, ofsref)); | |
| 1391 /* Emit invariant bounds check for start, if not const or negative. */ | |
| 1392 if (!(J->scev.dir && J->scev.start && | |
| 1393 (int64_t)IR(J->scev.start)->i + ofs >= 0)) | |
| 1394 emitir(IRTG(IR_ABC, IRT_P32), asizeref, ikey); | |
| 1395 return; | |
| 1396 } | |
| 1397 } | |
| 1398 } | |
| 1399 emitir(IRTGI(IR_ABC), asizeref, ikey); /* Emit regular bounds check. */ | |
| 1400 } | |
| 1401 | |
| 1402 /* Record indexed key lookup. */ | |
| 1403 static TRef rec_idx_key(jit_State *J, RecordIndex *ix, IRRef *rbref, | |
| 1404 IRType1 *rbguard) | |
| 1405 { | |
| 1406 TRef key; | |
| 1407 GCtab *t = tabV(&ix->tabv); | |
| 1408 ix->oldv = lj_tab_get(J->L, t, &ix->keyv); /* Lookup previous value. */ | |
| 1409 *rbref = 0; | |
| 1410 rbguard->irt = 0; | |
| 1411 | |
| 1412 /* Integer keys are looked up in the array part first. */ | |
| 1413 key = ix->key; | |
| 1414 if (tref_isnumber(key)) { | |
| 1415 int32_t k = numberVint(&ix->keyv); | |
| 1416 if (!tvisint(&ix->keyv) && numV(&ix->keyv) != (lua_Number)k) | |
| 1417 k = LJ_MAX_ASIZE; | |
| 1418 if ((MSize)k < LJ_MAX_ASIZE) { /* Potential array key? */ | |
| 1419 TRef ikey = lj_opt_narrow_index(J, key); | |
| 1420 TRef asizeref = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_ASIZE); | |
| 1421 if ((MSize)k < t->asize) { /* Currently an array key? */ | |
| 1422 TRef arrayref; | |
| 1423 rec_idx_abc(J, asizeref, ikey, t->asize); | |
| 1424 arrayref = emitir(IRT(IR_FLOAD, IRT_PGC), ix->tab, IRFL_TAB_ARRAY); | |
| 1425 return emitir(IRT(IR_AREF, IRT_PGC), arrayref, ikey); | |
| 1426 } else { /* Currently not in array (may be an array extension)? */ | |
| 1427 emitir(IRTGI(IR_ULE), asizeref, ikey); /* Inv. bounds check. */ | |
| 1428 if (k == 0 && tref_isk(key)) | |
| 1429 key = lj_ir_knum_zero(J); /* Canonicalize 0 or +-0.0 to +0.0. */ | |
| 1430 /* And continue with the hash lookup. */ | |
| 1431 } | |
| 1432 } else if (!tref_isk(key)) { | |
| 1433 /* We can rule out const numbers which failed the integerness test | |
| 1434 ** above. But all other numbers are potential array keys. | |
| 1435 */ | |
| 1436 if (t->asize == 0) { /* True sparse tables have an empty array part. */ | |
| 1437 /* Guard that the array part stays empty. */ | |
| 1438 TRef tmp = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_ASIZE); | |
| 1439 emitir(IRTGI(IR_EQ), tmp, lj_ir_kint(J, 0)); | |
| 1440 } else { | |
| 1441 lj_trace_err(J, LJ_TRERR_NYITMIX); | |
| 1442 } | |
| 1443 } | |
| 1444 } | |
| 1445 | |
| 1446 /* Otherwise the key is located in the hash part. */ | |
| 1447 if (t->hmask == 0) { /* Shortcut for empty hash part. */ | |
| 1448 /* Guard that the hash part stays empty. */ | |
| 1449 TRef tmp = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_HMASK); | |
| 1450 emitir(IRTGI(IR_EQ), tmp, lj_ir_kint(J, 0)); | |
| 1451 return lj_ir_kkptr(J, niltvg(J2G(J))); | |
| 1452 } | |
| 1453 if (tref_isinteger(key)) /* Hash keys are based on numbers, not ints. */ | |
| 1454 key = emitir(IRTN(IR_CONV), key, IRCONV_NUM_INT); | |
| 1455 if (tref_isk(key)) { | |
| 1456 /* Optimize lookup of constant hash keys. */ | |
| 1457 GCSize hslot = (GCSize)((char *)ix->oldv-(char *)&noderef(t->node)[0].val); | |
| 1458 if (hslot <= t->hmask*(GCSize)sizeof(Node) && | |
| 1459 hslot <= 65535*(GCSize)sizeof(Node)) { | |
| 1460 TRef node, kslot, hm; | |
| 1461 *rbref = J->cur.nins; /* Mark possible rollback point. */ | |
| 1462 *rbguard = J->guardemit; | |
| 1463 hm = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_HMASK); | |
| 1464 emitir(IRTGI(IR_EQ), hm, lj_ir_kint(J, (int32_t)t->hmask)); | |
| 1465 node = emitir(IRT(IR_FLOAD, IRT_PGC), ix->tab, IRFL_TAB_NODE); | |
| 1466 kslot = lj_ir_kslot(J, key, (IRRef)(hslot / sizeof(Node))); | |
| 1467 return emitir(IRTG(IR_HREFK, IRT_PGC), node, kslot); | |
| 1468 } | |
| 1469 } | |
| 1470 /* Fall back to a regular hash lookup. */ | |
| 1471 return emitir(IRT(IR_HREF, IRT_PGC), ix->tab, key); | |
| 1472 } | |
| 1473 | |
| 1474 /* Determine whether a key is NOT one of the fast metamethod names. */ | |
| 1475 static int nommstr(jit_State *J, TRef key) | |
| 1476 { | |
| 1477 if (tref_isstr(key)) { | |
| 1478 if (tref_isk(key)) { | |
| 1479 GCstr *str = ir_kstr(IR(tref_ref(key))); | |
| 1480 uint32_t mm; | |
| 1481 for (mm = 0; mm <= MM_FAST; mm++) | |
| 1482 if (mmname_str(J2G(J), mm) == str) | |
| 1483 return 0; /* MUST be one the fast metamethod names. */ | |
| 1484 } else { | |
| 1485 return 0; /* Variable string key MAY be a metamethod name. */ | |
| 1486 } | |
| 1487 } | |
| 1488 return 1; /* CANNOT be a metamethod name. */ | |
| 1489 } | |
| 1490 | |
| 1491 /* Record indexed load/store. */ | |
| 1492 TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |
| 1493 { | |
| 1494 TRef xref; | |
| 1495 IROp xrefop, loadop; | |
| 1496 IRRef rbref; | |
| 1497 IRType1 rbguard; | |
| 1498 cTValue *oldv; | |
| 1499 | |
| 1500 while (!tref_istab(ix->tab)) { /* Handle non-table lookup. */ | |
| 1501 /* Never call raw lj_record_idx() on non-table. */ | |
| 1502 lj_assertJ(ix->idxchain != 0, "bad usage"); | |
| 1503 if (!lj_record_mm_lookup(J, ix, ix->val ? MM_newindex : MM_index)) | |
| 1504 lj_trace_err(J, LJ_TRERR_NOMM); | |
| 1505 handlemm: | |
| 1506 if (tref_isfunc(ix->mobj)) { /* Handle metamethod call. */ | |
| 1507 BCReg func = rec_mm_prep(J, ix->val ? lj_cont_nop : lj_cont_ra); | |
| 1508 TRef *base = J->base + func + LJ_FR2; | |
| 1509 TValue *tv = J->L->base + func + LJ_FR2; | |
| 1510 base[-LJ_FR2] = ix->mobj; base[1] = ix->tab; base[2] = ix->key; | |
| 1511 setfuncV(J->L, tv-LJ_FR2, funcV(&ix->mobjv)); | |
| 1512 copyTV(J->L, tv+1, &ix->tabv); | |
| 1513 copyTV(J->L, tv+2, &ix->keyv); | |
| 1514 if (ix->val) { | |
| 1515 base[3] = ix->val; | |
| 1516 copyTV(J->L, tv+3, &ix->valv); | |
| 1517 lj_record_call(J, func, 3); /* mobj(tab, key, val) */ | |
| 1518 return 0; | |
| 1519 } else { | |
| 1520 lj_record_call(J, func, 2); /* res = mobj(tab, key) */ | |
| 1521 return 0; /* No result yet. */ | |
| 1522 } | |
| 1523 } | |
| 1524 #if LJ_HASBUFFER | |
| 1525 /* The index table of buffer objects is treated as immutable. */ | |
| 1526 if (ix->mt == TREF_NIL && !ix->val && | |
| 1527 tref_isudata(ix->tab) && udataV(&ix->tabv)->udtype == UDTYPE_BUFFER && | |
| 1528 tref_istab(ix->mobj) && tref_isstr(ix->key) && tref_isk(ix->key)) { | |
| 1529 cTValue *val = lj_tab_getstr(tabV(&ix->mobjv), strV(&ix->keyv)); | |
| 1530 TRef tr = lj_record_constify(J, val); | |
| 1531 if (tr) return tr; /* Specialize to the value, i.e. a method. */ | |
| 1532 } | |
| 1533 #endif | |
| 1534 /* Otherwise retry lookup with metaobject. */ | |
| 1535 ix->tab = ix->mobj; | |
| 1536 copyTV(J->L, &ix->tabv, &ix->mobjv); | |
| 1537 if (--ix->idxchain == 0) | |
| 1538 lj_trace_err(J, LJ_TRERR_IDXLOOP); | |
| 1539 } | |
| 1540 | |
| 1541 /* First catch nil and NaN keys for tables. */ | |
| 1542 if (tvisnil(&ix->keyv) || (tvisnum(&ix->keyv) && tvisnan(&ix->keyv))) { | |
| 1543 if (ix->val) /* Better fail early. */ | |
| 1544 lj_trace_err(J, LJ_TRERR_STORENN); | |
| 1545 if (tref_isk(ix->key)) { | |
| 1546 if (ix->idxchain && lj_record_mm_lookup(J, ix, MM_index)) | |
| 1547 goto handlemm; | |
| 1548 return TREF_NIL; | |
| 1549 } | |
| 1550 } | |
| 1551 | |
| 1552 /* Record the key lookup. */ | |
| 1553 xref = rec_idx_key(J, ix, &rbref, &rbguard); | |
| 1554 xrefop = IR(tref_ref(xref))->o; | |
| 1555 loadop = xrefop == IR_AREF ? IR_ALOAD : IR_HLOAD; | |
| 1556 /* The lj_meta_tset() inconsistency is gone, but better play safe. */ | |
| 1557 oldv = xrefop == IR_KKPTR ? (cTValue *)ir_kptr(IR(tref_ref(xref))) : ix->oldv; | |
| 1558 | |
| 1559 if (ix->val == 0) { /* Indexed load */ | |
| 1560 IRType t = itype2irt(oldv); | |
| 1561 TRef res; | |
| 1562 if (oldv == niltvg(J2G(J))) { | |
| 1563 emitir(IRTG(IR_EQ, IRT_PGC), xref, lj_ir_kkptr(J, niltvg(J2G(J)))); | |
| 1564 res = TREF_NIL; | |
| 1565 } else { | |
| 1566 res = emitir(IRTG(loadop, t), xref, 0); | |
| 1567 } | |
| 1568 if (tref_ref(res) < rbref) { /* HREFK + load forwarded? */ | |
| 1569 lj_ir_rollback(J, rbref); /* Rollback to eliminate hmask guard. */ | |
| 1570 J->guardemit = rbguard; | |
| 1571 } | |
| 1572 if (t == IRT_NIL && ix->idxchain && lj_record_mm_lookup(J, ix, MM_index)) | |
| 1573 goto handlemm; | |
| 1574 if (irtype_ispri(t)) res = TREF_PRI(t); /* Canonicalize primitives. */ | |
| 1575 return res; | |
| 1576 } else { /* Indexed store. */ | |
| 1577 GCtab *mt = tabref(tabV(&ix->tabv)->metatable); | |
| 1578 int keybarrier = tref_isgcv(ix->key) && !tref_isnil(ix->val); | |
| 1579 if (tref_ref(xref) < rbref) { /* HREFK forwarded? */ | |
| 1580 lj_ir_rollback(J, rbref); /* Rollback to eliminate hmask guard. */ | |
| 1581 J->guardemit = rbguard; | |
| 1582 } | |
| 1583 if (tvisnil(oldv)) { /* Previous value was nil? */ | |
| 1584 /* Need to duplicate the hasmm check for the early guards. */ | |
| 1585 int hasmm = 0; | |
| 1586 if (ix->idxchain && mt) { | |
| 1587 cTValue *mo = lj_tab_getstr(mt, mmname_str(J2G(J), MM_newindex)); | |
| 1588 hasmm = mo && !tvisnil(mo); | |
| 1589 } | |
| 1590 if (hasmm) | |
| 1591 emitir(IRTG(loadop, IRT_NIL), xref, 0); /* Guard for nil value. */ | |
| 1592 else if (xrefop == IR_HREF) | |
| 1593 emitir(IRTG(oldv == niltvg(J2G(J)) ? IR_EQ : IR_NE, IRT_PGC), | |
| 1594 xref, lj_ir_kkptr(J, niltvg(J2G(J)))); | |
| 1595 if (ix->idxchain && lj_record_mm_lookup(J, ix, MM_newindex)) { | |
| 1596 lj_assertJ(hasmm, "inconsistent metamethod handling"); | |
| 1597 goto handlemm; | |
| 1598 } | |
| 1599 lj_assertJ(!hasmm, "inconsistent metamethod handling"); | |
| 1600 if (oldv == niltvg(J2G(J))) { /* Need to insert a new key. */ | |
| 1601 TRef key = ix->key; | |
| 1602 if (tref_isinteger(key)) /* NEWREF needs a TValue as a key. */ | |
| 1603 key = emitir(IRTN(IR_CONV), key, IRCONV_NUM_INT); | |
| 1604 else if (tref_isnumber(key) && tref_isk(key) && tvismzero(&ix->keyv)) | |
| 1605 key = lj_ir_knum_zero(J); /* Canonicalize -0.0 to +0.0. */ | |
| 1606 xref = emitir(IRT(IR_NEWREF, IRT_PGC), ix->tab, key); | |
| 1607 keybarrier = 0; /* NEWREF already takes care of the key barrier. */ | |
| 1608 #ifdef LUAJIT_ENABLE_TABLE_BUMP | |
| 1609 if ((J->flags & JIT_F_OPT_SINK)) /* Avoid a separate flag. */ | |
| 1610 rec_idx_bump(J, ix); | |
| 1611 #endif | |
| 1612 } | |
| 1613 } else if (!lj_opt_fwd_wasnonnil(J, loadop, tref_ref(xref))) { | |
| 1614 /* Cannot derive that the previous value was non-nil, must do checks. */ | |
| 1615 if (xrefop == IR_HREF) /* Guard against store to niltv. */ | |
| 1616 emitir(IRTG(IR_NE, IRT_PGC), xref, lj_ir_kkptr(J, niltvg(J2G(J)))); | |
| 1617 if (ix->idxchain) { /* Metamethod lookup required? */ | |
| 1618 /* A check for NULL metatable is cheaper (hoistable) than a load. */ | |
| 1619 if (!mt) { | |
| 1620 TRef mtref = emitir(IRT(IR_FLOAD, IRT_TAB), ix->tab, IRFL_TAB_META); | |
| 1621 emitir(IRTG(IR_EQ, IRT_TAB), mtref, lj_ir_knull(J, IRT_TAB)); | |
| 1622 } else { | |
| 1623 IRType t = itype2irt(oldv); | |
| 1624 emitir(IRTG(loadop, t), xref, 0); /* Guard for non-nil value. */ | |
| 1625 } | |
| 1626 } | |
| 1627 } else { | |
| 1628 keybarrier = 0; /* Previous non-nil value kept the key alive. */ | |
| 1629 } | |
| 1630 /* Convert int to number before storing. */ | |
| 1631 if (!LJ_DUALNUM && tref_isinteger(ix->val)) | |
| 1632 ix->val = emitir(IRTN(IR_CONV), ix->val, IRCONV_NUM_INT); | |
| 1633 emitir(IRT(loadop+IRDELTA_L2S, tref_type(ix->val)), xref, ix->val); | |
| 1634 if (keybarrier || tref_isgcv(ix->val)) | |
| 1635 emitir(IRT(IR_TBAR, IRT_NIL), ix->tab, 0); | |
| 1636 /* Invalidate neg. metamethod cache for stores with certain string keys. */ | |
| 1637 if (!nommstr(J, ix->key)) { | |
| 1638 TRef fref = emitir(IRT(IR_FREF, IRT_PGC), ix->tab, IRFL_TAB_NOMM); | |
| 1639 emitir(IRT(IR_FSTORE, IRT_U8), fref, lj_ir_kint(J, 0)); | |
| 1640 } | |
| 1641 J->needsnap = 1; | |
| 1642 return 0; | |
| 1643 } | |
| 1644 } | |
| 1645 | |
| 1646 /* Determine result type of table traversal. */ | |
| 1647 static IRType rec_next_types(GCtab *t, uint32_t idx) | |
| 1648 { | |
| 1649 for (; idx < t->asize; idx++) { | |
| 1650 cTValue *a = arrayslot(t, idx); | |
| 1651 if (LJ_LIKELY(!tvisnil(a))) | |
| 1652 return (LJ_DUALNUM ? IRT_INT : IRT_NUM) + (itype2irt(a) << 8); | |
| 1653 } | |
| 1654 idx -= t->asize; | |
| 1655 for (; idx <= t->hmask; idx++) { | |
| 1656 Node *n = &noderef(t->node)[idx]; | |
| 1657 if (!tvisnil(&n->val)) | |
| 1658 return itype2irt(&n->key) + (itype2irt(&n->val) << 8); | |
| 1659 } | |
| 1660 return IRT_NIL + (IRT_NIL << 8); | |
| 1661 } | |
| 1662 | |
| 1663 /* Record a table traversal step aka next(). */ | |
| 1664 int lj_record_next(jit_State *J, RecordIndex *ix) | |
| 1665 { | |
| 1666 IRType t, tkey, tval; | |
| 1667 TRef trvk; | |
| 1668 t = rec_next_types(tabV(&ix->tabv), ix->keyv.u32.lo); | |
| 1669 tkey = (t & 0xff); tval = (t >> 8); | |
| 1670 trvk = lj_ir_call(J, IRCALL_lj_vm_next, ix->tab, ix->key); | |
| 1671 if (ix->mobj || tkey == IRT_NIL) { | |
| 1672 TRef idx = emitir(IRTI(IR_HIOP), trvk, trvk); | |
| 1673 /* Always check for invalid key from next() for nil result. */ | |
| 1674 if (!ix->mobj) emitir(IRTGI(IR_NE), idx, lj_ir_kint(J, -1)); | |
| 1675 ix->mobj = idx; | |
| 1676 } | |
| 1677 ix->key = lj_record_vload(J, trvk, 1, tkey); | |
| 1678 if (tkey == IRT_NIL || ix->idxchain) { /* Omit value type check. */ | |
| 1679 ix->val = TREF_NIL; | |
| 1680 return 1; | |
| 1681 } else { /* Need value. */ | |
| 1682 ix->val = lj_record_vload(J, trvk, 0, tval); | |
| 1683 return 2; | |
| 1684 } | |
| 1685 } | |
| 1686 | |
| 1687 static void rec_tsetm(jit_State *J, BCReg ra, BCReg rn, int32_t i) | |
| 1688 { | |
| 1689 RecordIndex ix; | |
| 1690 cTValue *basev = J->L->base; | |
| 1691 GCtab *t = tabV(&basev[ra-1]); | |
| 1692 settabV(J->L, &ix.tabv, t); | |
| 1693 ix.tab = getslot(J, ra-1); | |
| 1694 ix.idxchain = 0; | |
| 1695 #ifdef LUAJIT_ENABLE_TABLE_BUMP | |
| 1696 if ((J->flags & JIT_F_OPT_SINK)) { | |
| 1697 if (t->asize < i+rn-ra) | |
| 1698 lj_tab_reasize(J->L, t, i+rn-ra); | |
| 1699 setnilV(&ix.keyv); | |
| 1700 rec_idx_bump(J, &ix); | |
| 1701 } | |
| 1702 #endif | |
| 1703 for (; ra < rn; i++, ra++) { | |
| 1704 setintV(&ix.keyv, i); | |
| 1705 ix.key = lj_ir_kint(J, i); | |
| 1706 copyTV(J->L, &ix.valv, &basev[ra]); | |
| 1707 ix.val = getslot(J, ra); | |
| 1708 lj_record_idx(J, &ix); | |
| 1709 } | |
| 1710 } | |
| 1711 | |
| 1712 /* -- Upvalue access ------------------------------------------------------ */ | |
| 1713 | |
| 1714 /* Check whether upvalue is immutable and ok to constify. */ | |
| 1715 static int rec_upvalue_constify(jit_State *J, GCupval *uvp) | |
| 1716 { | |
| 1717 if (uvp->immutable) { | |
| 1718 cTValue *o = uvval(uvp); | |
| 1719 /* Don't constify objects that may retain large amounts of memory. */ | |
| 1720 #if LJ_HASFFI | |
| 1721 if (tviscdata(o)) { | |
| 1722 GCcdata *cd = cdataV(o); | |
| 1723 if (!cdataisv(cd) && !(cd->marked & LJ_GC_CDATA_FIN)) { | |
| 1724 CType *ct = ctype_raw(ctype_ctsG(J2G(J)), cd->ctypeid); | |
| 1725 if (!ctype_hassize(ct->info) || ct->size <= 16) | |
| 1726 return 1; | |
| 1727 } | |
| 1728 return 0; | |
| 1729 } | |
| 1730 #else | |
| 1731 UNUSED(J); | |
| 1732 #endif | |
| 1733 if (!(tvistab(o) || tvisudata(o) || tvisthread(o))) | |
| 1734 return 1; | |
| 1735 } | |
| 1736 return 0; | |
| 1737 } | |
| 1738 | |
| 1739 /* Record upvalue load/store. */ | |
| 1740 static TRef rec_upvalue(jit_State *J, uint32_t uv, TRef val) | |
| 1741 { | |
| 1742 GCupval *uvp = &gcref(J->fn->l.uvptr[uv])->uv; | |
| 1743 TRef fn = getcurrf(J); | |
| 1744 IRRef uref; | |
| 1745 int needbarrier = 0; | |
| 1746 if (rec_upvalue_constify(J, uvp)) { /* Try to constify immutable upvalue. */ | |
| 1747 TRef tr, kfunc; | |
| 1748 lj_assertJ(val == 0, "bad usage"); | |
| 1749 if (!tref_isk(fn)) { /* Late specialization of current function. */ | |
| 1750 if (J->pt->flags >= PROTO_CLC_POLY) | |
| 1751 goto noconstify; | |
| 1752 kfunc = lj_ir_kfunc(J, J->fn); | |
| 1753 emitir(IRTG(IR_EQ, IRT_FUNC), fn, kfunc); | |
| 1754 #if LJ_FR2 | |
| 1755 J->base[-2] = kfunc; | |
| 1756 #else | |
| 1757 J->base[-1] = kfunc | TREF_FRAME; | |
| 1758 #endif | |
| 1759 fn = kfunc; | |
| 1760 } | |
| 1761 tr = lj_record_constify(J, uvval(uvp)); | |
| 1762 if (tr) | |
| 1763 return tr; | |
| 1764 } | |
| 1765 noconstify: | |
| 1766 /* Note: this effectively limits LJ_MAX_UPVAL to 127. */ | |
| 1767 uv = (uv << 8) | (hashrot(uvp->dhash, uvp->dhash + HASH_BIAS) & 0xff); | |
| 1768 if (!uvp->closed) { | |
| 1769 uref = tref_ref(emitir(IRTG(IR_UREFO, IRT_PGC), fn, uv)); | |
| 1770 /* In current stack? */ | |
| 1771 if (uvval(uvp) >= tvref(J->L->stack) && | |
| 1772 uvval(uvp) < tvref(J->L->maxstack)) { | |
| 1773 int32_t slot = (int32_t)(uvval(uvp) - (J->L->base - J->baseslot)); | |
| 1774 if (slot >= 0) { /* Aliases an SSA slot? */ | |
| 1775 emitir(IRTG(IR_EQ, IRT_PGC), | |
| 1776 REF_BASE, | |
| 1777 emitir(IRT(IR_ADD, IRT_PGC), uref, | |
| 1778 lj_ir_kint(J, (slot - 1 - LJ_FR2) * -8))); | |
| 1779 slot -= (int32_t)J->baseslot; /* Note: slot number may be negative! */ | |
| 1780 if (val == 0) { | |
| 1781 return getslot(J, slot); | |
| 1782 } else { | |
| 1783 J->base[slot] = val; | |
| 1784 if (slot >= (int32_t)J->maxslot) J->maxslot = (BCReg)(slot+1); | |
| 1785 return 0; | |
| 1786 } | |
| 1787 } | |
| 1788 } | |
| 1789 emitir(IRTG(IR_UGT, IRT_PGC), | |
| 1790 emitir(IRT(IR_SUB, IRT_PGC), uref, REF_BASE), | |
| 1791 lj_ir_kint(J, (J->baseslot + J->maxslot) * 8)); | |
| 1792 } else { | |
| 1793 needbarrier = 1; | |
| 1794 uref = tref_ref(emitir(IRTG(IR_UREFC, IRT_PGC), fn, uv)); | |
| 1795 } | |
| 1796 if (val == 0) { /* Upvalue load */ | |
| 1797 IRType t = itype2irt(uvval(uvp)); | |
| 1798 TRef res = emitir(IRTG(IR_ULOAD, t), uref, 0); | |
| 1799 if (irtype_ispri(t)) res = TREF_PRI(t); /* Canonicalize primitive refs. */ | |
| 1800 return res; | |
| 1801 } else { /* Upvalue store. */ | |
| 1802 /* Convert int to number before storing. */ | |
| 1803 if (!LJ_DUALNUM && tref_isinteger(val)) | |
| 1804 val = emitir(IRTN(IR_CONV), val, IRCONV_NUM_INT); | |
| 1805 emitir(IRT(IR_USTORE, tref_type(val)), uref, val); | |
| 1806 if (needbarrier && tref_isgcv(val)) | |
| 1807 emitir(IRT(IR_OBAR, IRT_NIL), uref, val); | |
| 1808 J->needsnap = 1; | |
| 1809 return 0; | |
| 1810 } | |
| 1811 } | |
| 1812 | |
| 1813 /* -- Record calls to Lua functions --------------------------------------- */ | |
| 1814 | |
| 1815 /* Check unroll limits for calls. */ | |
| 1816 static void check_call_unroll(jit_State *J, TraceNo lnk) | |
| 1817 { | |
| 1818 cTValue *frame = J->L->base - 1; | |
| 1819 void *pc = mref(frame_func(frame)->l.pc, void); | |
| 1820 int32_t depth = J->framedepth; | |
| 1821 int32_t count = 0; | |
| 1822 if ((J->pt->flags & PROTO_VARARG)) depth--; /* Vararg frame still missing. */ | |
| 1823 for (; depth > 0; depth--) { /* Count frames with same prototype. */ | |
| 1824 if (frame_iscont(frame)) depth--; | |
| 1825 frame = frame_prev(frame); | |
| 1826 if (mref(frame_func(frame)->l.pc, void) == pc) | |
| 1827 count++; | |
| 1828 } | |
| 1829 if (J->pc == J->startpc) { | |
| 1830 if (count + J->tailcalled > J->param[JIT_P_recunroll]) { | |
| 1831 J->pc++; | |
| 1832 if (J->framedepth + J->retdepth == 0) | |
| 1833 lj_record_stop(J, LJ_TRLINK_TAILREC, J->cur.traceno); /* Tail-rec. */ | |
| 1834 else | |
| 1835 lj_record_stop(J, LJ_TRLINK_UPREC, J->cur.traceno); /* Up-recursion. */ | |
| 1836 } | |
| 1837 } else { | |
| 1838 if (count > J->param[JIT_P_callunroll]) { | |
| 1839 if (lnk) { /* Possible tail- or up-recursion. */ | |
| 1840 lj_trace_flush(J, lnk); /* Flush trace that only returns. */ | |
| 1841 /* Set a small, pseudo-random hotcount for a quick retry of JFUNC*. */ | |
| 1842 hotcount_set(J2GG(J), J->pc+1, lj_prng_u64(&J2G(J)->prng) & 15u); | |
| 1843 } | |
| 1844 lj_trace_err(J, LJ_TRERR_CUNROLL); | |
| 1845 } | |
| 1846 } | |
| 1847 } | |
| 1848 | |
| 1849 /* Record Lua function setup. */ | |
| 1850 static void rec_func_setup(jit_State *J) | |
| 1851 { | |
| 1852 GCproto *pt = J->pt; | |
| 1853 BCReg s, numparams = pt->numparams; | |
| 1854 if ((pt->flags & PROTO_NOJIT)) | |
| 1855 lj_trace_err(J, LJ_TRERR_CJITOFF); | |
| 1856 if (J->baseslot + pt->framesize >= LJ_MAX_JSLOTS) | |
| 1857 lj_trace_err(J, LJ_TRERR_STACKOV); | |
| 1858 /* Fill up missing parameters with nil. */ | |
| 1859 for (s = J->maxslot; s < numparams; s++) | |
| 1860 J->base[s] = TREF_NIL; | |
| 1861 /* The remaining slots should never be read before they are written. */ | |
| 1862 J->maxslot = numparams; | |
| 1863 } | |
| 1864 | |
| 1865 /* Record Lua vararg function setup. */ | |
| 1866 static void rec_func_vararg(jit_State *J) | |
| 1867 { | |
| 1868 GCproto *pt = J->pt; | |
| 1869 BCReg s, fixargs, vframe = J->maxslot+1+LJ_FR2; | |
| 1870 lj_assertJ((pt->flags & PROTO_VARARG), "FUNCV in non-vararg function"); | |
| 1871 if (J->baseslot + vframe + pt->framesize >= LJ_MAX_JSLOTS) | |
| 1872 lj_trace_err(J, LJ_TRERR_STACKOV); | |
| 1873 J->base[vframe-1-LJ_FR2] = J->base[-1-LJ_FR2]; /* Copy function up. */ | |
| 1874 #if LJ_FR2 | |
| 1875 J->base[vframe-1] = TREF_FRAME; | |
| 1876 #endif | |
| 1877 /* Copy fixarg slots up and set their original slots to nil. */ | |
| 1878 fixargs = pt->numparams < J->maxslot ? pt->numparams : J->maxslot; | |
| 1879 for (s = 0; s < fixargs; s++) { | |
| 1880 J->base[vframe+s] = J->base[s]; | |
| 1881 J->base[s] = TREF_NIL; | |
| 1882 } | |
| 1883 J->maxslot = fixargs; | |
| 1884 J->framedepth++; | |
| 1885 J->base += vframe; | |
| 1886 J->baseslot += vframe; | |
| 1887 } | |
| 1888 | |
| 1889 /* Record entry to a Lua function. */ | |
| 1890 static void rec_func_lua(jit_State *J) | |
| 1891 { | |
| 1892 rec_func_setup(J); | |
| 1893 check_call_unroll(J, 0); | |
| 1894 } | |
| 1895 | |
| 1896 /* Record entry to an already compiled function. */ | |
| 1897 static void rec_func_jit(jit_State *J, TraceNo lnk) | |
| 1898 { | |
| 1899 GCtrace *T; | |
| 1900 rec_func_setup(J); | |
| 1901 T = traceref(J, lnk); | |
| 1902 if (T->linktype == LJ_TRLINK_RETURN) { /* Trace returns to interpreter? */ | |
| 1903 check_call_unroll(J, lnk); | |
| 1904 /* Temporarily unpatch JFUNC* to continue recording across function. */ | |
| 1905 J->patchins = *J->pc; | |
| 1906 J->patchpc = (BCIns *)J->pc; | |
| 1907 *J->patchpc = T->startins; | |
| 1908 return; | |
| 1909 } | |
| 1910 J->instunroll = 0; /* Cannot continue across a compiled function. */ | |
| 1911 if (J->pc == J->startpc && J->framedepth + J->retdepth == 0) | |
| 1912 lj_record_stop(J, LJ_TRLINK_TAILREC, J->cur.traceno); /* Extra tail-rec. */ | |
| 1913 else | |
| 1914 lj_record_stop(J, LJ_TRLINK_ROOT, lnk); /* Link to the function. */ | |
| 1915 } | |
| 1916 | |
| 1917 /* -- Vararg handling ----------------------------------------------------- */ | |
| 1918 | |
| 1919 /* Detect y = select(x, ...) idiom. */ | |
| 1920 static int select_detect(jit_State *J) | |
| 1921 { | |
| 1922 BCIns ins = J->pc[1]; | |
| 1923 if (bc_op(ins) == BC_CALLM && bc_b(ins) == 2 && bc_c(ins) == 1) { | |
| 1924 cTValue *func = &J->L->base[bc_a(ins)]; | |
| 1925 if (tvisfunc(func) && funcV(func)->c.ffid == FF_select) { | |
| 1926 TRef kfunc = lj_ir_kfunc(J, funcV(func)); | |
| 1927 emitir(IRTG(IR_EQ, IRT_FUNC), getslot(J, bc_a(ins)), kfunc); | |
| 1928 return 1; | |
| 1929 } | |
| 1930 } | |
| 1931 return 0; | |
| 1932 } | |
| 1933 | |
| 1934 /* Record vararg instruction. */ | |
| 1935 static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults) | |
| 1936 { | |
| 1937 int32_t numparams = J->pt->numparams; | |
| 1938 ptrdiff_t nvararg = frame_delta(J->L->base-1) - numparams - 1 - LJ_FR2; | |
| 1939 lj_assertJ(frame_isvarg(J->L->base-1), "VARG in non-vararg frame"); | |
| 1940 if (LJ_FR2 && dst > J->maxslot) | |
| 1941 J->base[dst-1] = 0; /* Prevent resurrection of unrelated slot. */ | |
| 1942 if (J->framedepth > 0) { /* Simple case: varargs defined on-trace. */ | |
| 1943 ptrdiff_t i; | |
| 1944 if (nvararg < 0) nvararg = 0; | |
| 1945 if (nresults != 1) { | |
| 1946 if (nresults == -1) nresults = nvararg; | |
| 1947 J->maxslot = dst + (BCReg)nresults; | |
| 1948 } else if (dst >= J->maxslot) { | |
| 1949 J->maxslot = dst + 1; | |
| 1950 } | |
| 1951 if (J->baseslot + J->maxslot >= LJ_MAX_JSLOTS) | |
| 1952 lj_trace_err(J, LJ_TRERR_STACKOV); | |
| 1953 for (i = 0; i < nresults; i++) | |
| 1954 J->base[dst+i] = i < nvararg ? getslot(J, i - nvararg - 1 - LJ_FR2) : TREF_NIL; | |
| 1955 } else { /* Unknown number of varargs passed to trace. */ | |
| 1956 TRef fr = emitir(IRTI(IR_SLOAD), LJ_FR2, IRSLOAD_READONLY|IRSLOAD_FRAME); | |
| 1957 int32_t frofs = 8*(1+LJ_FR2+numparams)+FRAME_VARG; | |
| 1958 if (nresults >= 0) { /* Known fixed number of results. */ | |
| 1959 ptrdiff_t i; | |
| 1960 if (nvararg > 0) { | |
| 1961 ptrdiff_t nload = nvararg >= nresults ? nresults : nvararg; | |
| 1962 TRef vbase; | |
| 1963 if (nvararg >= nresults) | |
| 1964 emitir(IRTGI(IR_GE), fr, lj_ir_kint(J, frofs+8*(int32_t)nresults)); | |
| 1965 else | |
| 1966 emitir(IRTGI(IR_EQ), fr, | |
| 1967 lj_ir_kint(J, (int32_t)frame_ftsz(J->L->base-1))); | |
| 1968 vbase = emitir(IRT(IR_SUB, IRT_IGC), REF_BASE, fr); | |
| 1969 vbase = emitir(IRT(IR_ADD, IRT_PGC), vbase, lj_ir_kint(J, frofs-8*(1+LJ_FR2))); | |
| 1970 for (i = 0; i < nload; i++) { | |
| 1971 IRType t = itype2irt(&J->L->base[i-1-LJ_FR2-nvararg]); | |
| 1972 J->base[dst+i] = lj_record_vload(J, vbase, (MSize)i, t); | |
| 1973 } | |
| 1974 } else { | |
| 1975 emitir(IRTGI(IR_LE), fr, lj_ir_kint(J, frofs)); | |
| 1976 nvararg = 0; | |
| 1977 } | |
| 1978 for (i = nvararg; i < nresults; i++) | |
| 1979 J->base[dst+i] = TREF_NIL; | |
| 1980 if (nresults != 1 || dst >= J->maxslot) { | |
| 1981 J->maxslot = dst + (BCReg)nresults; | |
| 1982 } | |
| 1983 } else if (select_detect(J)) { /* y = select(x, ...) */ | |
| 1984 TRef tridx = J->base[dst-1]; | |
| 1985 TRef tr = TREF_NIL; | |
| 1986 ptrdiff_t idx = lj_ffrecord_select_mode(J, tridx, &J->L->base[dst-1]); | |
| 1987 if (idx < 0) goto nyivarg; | |
| 1988 if (idx != 0 && !tref_isinteger(tridx)) | |
| 1989 tridx = emitir(IRTGI(IR_CONV), tridx, IRCONV_INT_NUM|IRCONV_INDEX); | |
| 1990 if (idx != 0 && tref_isk(tridx)) { | |
| 1991 emitir(IRTGI(idx <= nvararg ? IR_GE : IR_LT), | |
| 1992 fr, lj_ir_kint(J, frofs+8*(int32_t)idx)); | |
| 1993 frofs -= 8; /* Bias for 1-based index. */ | |
| 1994 } else if (idx <= nvararg) { /* Compute size. */ | |
| 1995 TRef tmp = emitir(IRTI(IR_ADD), fr, lj_ir_kint(J, -frofs)); | |
| 1996 if (numparams) | |
| 1997 emitir(IRTGI(IR_GE), tmp, lj_ir_kint(J, 0)); | |
| 1998 tr = emitir(IRTI(IR_BSHR), tmp, lj_ir_kint(J, 3)); | |
| 1999 if (idx != 0) { | |
| 2000 tridx = emitir(IRTI(IR_ADD), tridx, lj_ir_kint(J, -1)); | |
| 2001 rec_idx_abc(J, tr, tridx, (uint32_t)nvararg); | |
| 2002 } | |
| 2003 } else { | |
| 2004 TRef tmp = lj_ir_kint(J, frofs); | |
| 2005 if (idx != 0) { | |
| 2006 TRef tmp2 = emitir(IRTI(IR_BSHL), tridx, lj_ir_kint(J, 3)); | |
| 2007 tmp = emitir(IRTI(IR_ADD), tmp2, tmp); | |
| 2008 } else { | |
| 2009 tr = lj_ir_kint(J, 0); | |
| 2010 } | |
| 2011 emitir(IRTGI(IR_LT), fr, tmp); | |
| 2012 } | |
| 2013 if (idx != 0 && idx <= nvararg) { | |
| 2014 IRType t; | |
| 2015 TRef aref, vbase = emitir(IRT(IR_SUB, IRT_IGC), REF_BASE, fr); | |
| 2016 vbase = emitir(IRT(IR_ADD, IRT_PGC), vbase, | |
| 2017 lj_ir_kint(J, frofs-(8<<LJ_FR2))); | |
| 2018 t = itype2irt(&J->L->base[idx-2-LJ_FR2-nvararg]); | |
| 2019 aref = emitir(IRT(IR_AREF, IRT_PGC), vbase, tridx); | |
| 2020 tr = lj_record_vload(J, aref, 0, t); | |
| 2021 } | |
| 2022 J->base[dst-2-LJ_FR2] = tr; | |
| 2023 J->maxslot = dst-1-LJ_FR2; | |
| 2024 J->bcskip = 2; /* Skip CALLM + select. */ | |
| 2025 } else { | |
| 2026 nyivarg: | |
| 2027 setintV(&J->errinfo, BC_VARG); | |
| 2028 lj_trace_err_info(J, LJ_TRERR_NYIBC); | |
| 2029 } | |
| 2030 } | |
| 2031 } | |
| 2032 | |
| 2033 /* -- Record allocations -------------------------------------------------- */ | |
| 2034 | |
| 2035 static TRef rec_tnew(jit_State *J, uint32_t ah) | |
| 2036 { | |
| 2037 uint32_t asize = ah & 0x7ff; | |
| 2038 uint32_t hbits = ah >> 11; | |
| 2039 TRef tr; | |
| 2040 if (asize == 0x7ff) asize = 0x801; | |
| 2041 tr = emitir(IRTG(IR_TNEW, IRT_TAB), asize, hbits); | |
| 2042 #ifdef LUAJIT_ENABLE_TABLE_BUMP | |
| 2043 J->rbchash[(tr & (RBCHASH_SLOTS-1))].ref = tref_ref(tr); | |
| 2044 setmref(J->rbchash[(tr & (RBCHASH_SLOTS-1))].pc, J->pc); | |
| 2045 setgcref(J->rbchash[(tr & (RBCHASH_SLOTS-1))].pt, obj2gco(J->pt)); | |
| 2046 #endif | |
| 2047 return tr; | |
| 2048 } | |
| 2049 | |
| 2050 /* -- Concatenation ------------------------------------------------------- */ | |
| 2051 | |
| 2052 static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) | |
| 2053 { | |
| 2054 TRef *top = &J->base[topslot]; | |
| 2055 TValue savetv[5+LJ_FR2]; | |
| 2056 BCReg s; | |
| 2057 RecordIndex ix; | |
| 2058 lj_assertJ(baseslot < topslot, "bad CAT arg"); | |
| 2059 for (s = baseslot; s <= topslot; s++) | |
| 2060 (void)getslot(J, s); /* Ensure all arguments have a reference. */ | |
| 2061 if (tref_isnumber_str(top[0]) && tref_isnumber_str(top[-1])) { | |
| 2062 TRef tr, hdr, *trp, *xbase, *base = &J->base[baseslot]; | |
| 2063 /* First convert numbers to strings. */ | |
| 2064 for (trp = top; trp >= base; trp--) { | |
| 2065 if (tref_isnumber(*trp)) | |
| 2066 *trp = emitir(IRT(IR_TOSTR, IRT_STR), *trp, | |
| 2067 tref_isnum(*trp) ? IRTOSTR_NUM : IRTOSTR_INT); | |
| 2068 else if (!tref_isstr(*trp)) | |
| 2069 break; | |
| 2070 } | |
| 2071 xbase = ++trp; | |
| 2072 tr = hdr = emitir(IRT(IR_BUFHDR, IRT_PGC), | |
| 2073 lj_ir_kptr(J, &J2G(J)->tmpbuf), IRBUFHDR_RESET); | |
| 2074 do { | |
| 2075 tr = emitir(IRTG(IR_BUFPUT, IRT_PGC), tr, *trp++); | |
| 2076 } while (trp <= top); | |
| 2077 tr = emitir(IRTG(IR_BUFSTR, IRT_STR), tr, hdr); | |
| 2078 J->maxslot = (BCReg)(xbase - J->base); | |
| 2079 if (xbase == base) return tr; /* Return simple concatenation result. */ | |
| 2080 /* Pass partial result. */ | |
| 2081 topslot = J->maxslot--; | |
| 2082 *xbase = tr; | |
| 2083 top = xbase; | |
| 2084 setstrV(J->L, &ix.keyv, &J2G(J)->strempty); /* Simulate string result. */ | |
| 2085 } else { | |
| 2086 J->maxslot = topslot-1; | |
| 2087 copyTV(J->L, &ix.keyv, &J->L->base[topslot]); | |
| 2088 } | |
| 2089 copyTV(J->L, &ix.tabv, &J->L->base[topslot-1]); | |
| 2090 ix.tab = top[-1]; | |
| 2091 ix.key = top[0]; | |
| 2092 memcpy(savetv, &J->L->base[topslot-1], sizeof(savetv)); /* Save slots. */ | |
| 2093 rec_mm_arith(J, &ix, MM_concat); /* Call __concat metamethod. */ | |
| 2094 memcpy(&J->L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */ | |
| 2095 return 0; /* No result yet. */ | |
| 2096 } | |
| 2097 | |
| 2098 /* -- Record bytecode ops ------------------------------------------------- */ | |
| 2099 | |
| 2100 /* Prepare for comparison. */ | |
| 2101 static void rec_comp_prep(jit_State *J) | |
| 2102 { | |
| 2103 /* Prevent merging with snapshot #0 (GC exit) since we fixup the PC. */ | |
| 2104 if (J->cur.nsnap == 1 && J->cur.snap[0].ref == J->cur.nins) | |
| 2105 emitir_raw(IRT(IR_NOP, IRT_NIL), 0, 0); | |
| 2106 lj_snap_add(J); | |
| 2107 } | |
| 2108 | |
| 2109 /* Fixup comparison. */ | |
| 2110 static void rec_comp_fixup(jit_State *J, const BCIns *pc, int cond) | |
| 2111 { | |
| 2112 BCIns jmpins = pc[1]; | |
| 2113 const BCIns *npc = pc + 2 + (cond ? bc_j(jmpins) : 0); | |
| 2114 SnapShot *snap = &J->cur.snap[J->cur.nsnap-1]; | |
| 2115 /* Set PC to opposite target to avoid re-recording the comp. in side trace. */ | |
| 2116 #if LJ_FR2 | |
| 2117 SnapEntry *flink = &J->cur.snapmap[snap->mapofs + snap->nent]; | |
| 2118 uint64_t pcbase; | |
| 2119 memcpy(&pcbase, flink, sizeof(uint64_t)); | |
| 2120 pcbase = (pcbase & 0xff) | (u64ptr(npc) << 8); | |
| 2121 memcpy(flink, &pcbase, sizeof(uint64_t)); | |
| 2122 #else | |
| 2123 J->cur.snapmap[snap->mapofs + snap->nent] = SNAP_MKPC(npc); | |
| 2124 #endif | |
| 2125 J->needsnap = 1; | |
| 2126 if (bc_a(jmpins) < J->maxslot) J->maxslot = bc_a(jmpins); | |
| 2127 lj_snap_shrink(J); /* Shrink last snapshot if possible. */ | |
| 2128 } | |
| 2129 | |
| 2130 /* Record the next bytecode instruction (_before_ it's executed). */ | |
| 2131 void lj_record_ins(jit_State *J) | |
| 2132 { | |
| 2133 cTValue *lbase; | |
| 2134 RecordIndex ix; | |
| 2135 const BCIns *pc; | |
| 2136 BCIns ins; | |
| 2137 BCOp op; | |
| 2138 TRef ra, rb, rc; | |
| 2139 | |
| 2140 /* Perform post-processing action before recording the next instruction. */ | |
| 2141 if (LJ_UNLIKELY(J->postproc != LJ_POST_NONE)) { | |
| 2142 switch (J->postproc) { | |
| 2143 case LJ_POST_FIXCOMP: /* Fixup comparison. */ | |
| 2144 pc = (const BCIns *)(uintptr_t)J2G(J)->tmptv.u64; | |
| 2145 rec_comp_fixup(J, pc, (!tvistruecond(&J2G(J)->tmptv2) ^ (bc_op(*pc)&1))); | |
| 2146 /* fallthrough */ | |
| 2147 case LJ_POST_FIXGUARD: /* Fixup and emit pending guard. */ | |
| 2148 case LJ_POST_FIXGUARDSNAP: /* Fixup and emit pending guard and snapshot. */ | |
| 2149 if (!tvistruecond(&J2G(J)->tmptv2)) { | |
| 2150 J->fold.ins.o ^= 1; /* Flip guard to opposite. */ | |
| 2151 if (J->postproc == LJ_POST_FIXGUARDSNAP) { | |
| 2152 SnapShot *snap = &J->cur.snap[J->cur.nsnap-1]; | |
| 2153 J->cur.snapmap[snap->mapofs+snap->nent-1]--; /* False -> true. */ | |
| 2154 } | |
| 2155 } | |
| 2156 lj_opt_fold(J); /* Emit pending guard. */ | |
| 2157 /* fallthrough */ | |
| 2158 case LJ_POST_FIXBOOL: | |
| 2159 if (!tvistruecond(&J2G(J)->tmptv2)) { | |
| 2160 BCReg s; | |
| 2161 TValue *tv = J->L->base; | |
| 2162 for (s = 0; s < J->maxslot; s++) /* Fixup stack slot (if any). */ | |
| 2163 if (J->base[s] == TREF_TRUE && tvisfalse(&tv[s])) { | |
| 2164 J->base[s] = TREF_FALSE; | |
| 2165 break; | |
| 2166 } | |
| 2167 } | |
| 2168 break; | |
| 2169 case LJ_POST_FIXCONST: | |
| 2170 { | |
| 2171 BCReg s; | |
| 2172 TValue *tv = J->L->base; | |
| 2173 for (s = 0; s < J->maxslot; s++) /* Constify stack slots (if any). */ | |
| 2174 if (J->base[s] == TREF_NIL && !tvisnil(&tv[s])) | |
| 2175 J->base[s] = lj_record_constify(J, &tv[s]); | |
| 2176 } | |
| 2177 break; | |
| 2178 case LJ_POST_FFRETRY: /* Suppress recording of retried fast function. */ | |
| 2179 if (bc_op(*J->pc) >= BC__MAX) | |
| 2180 return; | |
| 2181 break; | |
| 2182 default: lj_assertJ(0, "bad post-processing mode"); break; | |
| 2183 } | |
| 2184 J->postproc = LJ_POST_NONE; | |
| 2185 } | |
| 2186 | |
| 2187 /* Need snapshot before recording next bytecode (e.g. after a store). */ | |
| 2188 if (J->needsnap) { | |
| 2189 J->needsnap = 0; | |
| 2190 if (J->pt) lj_snap_purge(J); | |
| 2191 lj_snap_add(J); | |
| 2192 J->mergesnap = 1; | |
| 2193 } | |
| 2194 | |
| 2195 /* Skip some bytecodes. */ | |
| 2196 if (LJ_UNLIKELY(J->bcskip > 0)) { | |
| 2197 J->bcskip--; | |
| 2198 return; | |
| 2199 } | |
| 2200 | |
| 2201 /* Record only closed loops for root traces. */ | |
| 2202 pc = J->pc; | |
| 2203 if (J->framedepth == 0 && | |
| 2204 (MSize)((char *)pc - (char *)J->bc_min) >= J->bc_extent) | |
| 2205 lj_trace_err(J, LJ_TRERR_LLEAVE); | |
| 2206 | |
| 2207 #ifdef LUA_USE_ASSERT | |
| 2208 rec_check_slots(J); | |
| 2209 rec_check_ir(J); | |
| 2210 #endif | |
| 2211 | |
| 2212 #if LJ_HASPROFILE | |
| 2213 rec_profile_ins(J, pc); | |
| 2214 #endif | |
| 2215 | |
| 2216 /* Keep a copy of the runtime values of var/num/str operands. */ | |
| 2217 #define rav (&ix.valv) | |
| 2218 #define rbv (&ix.tabv) | |
| 2219 #define rcv (&ix.keyv) | |
| 2220 | |
| 2221 lbase = J->L->base; | |
| 2222 ins = *pc; | |
| 2223 op = bc_op(ins); | |
| 2224 ra = bc_a(ins); | |
| 2225 ix.val = 0; | |
| 2226 switch (bcmode_a(op)) { | |
| 2227 case BCMvar: | |
| 2228 copyTV(J->L, rav, &lbase[ra]); ix.val = ra = getslot(J, ra); break; | |
| 2229 default: break; /* Handled later. */ | |
| 2230 } | |
| 2231 rb = bc_b(ins); | |
| 2232 rc = bc_c(ins); | |
| 2233 switch (bcmode_b(op)) { | |
| 2234 case BCMnone: rb = 0; rc = bc_d(ins); break; /* Upgrade rc to 'rd'. */ | |
| 2235 case BCMvar: | |
| 2236 copyTV(J->L, rbv, &lbase[rb]); ix.tab = rb = getslot(J, rb); break; | |
| 2237 default: break; /* Handled later. */ | |
| 2238 } | |
| 2239 switch (bcmode_c(op)) { | |
| 2240 case BCMvar: | |
| 2241 copyTV(J->L, rcv, &lbase[rc]); ix.key = rc = getslot(J, rc); break; | |
| 2242 case BCMpri: setpriV(rcv, ~rc); ix.key = rc = TREF_PRI(IRT_NIL+rc); break; | |
| 2243 case BCMnum: { cTValue *tv = proto_knumtv(J->pt, rc); | |
| 2244 copyTV(J->L, rcv, tv); ix.key = rc = tvisint(tv) ? lj_ir_kint(J, intV(tv)) : | |
| 2245 tv->u32.hi == LJ_KEYINDEX ? (lj_ir_kint(J, 0) | TREF_KEYINDEX) : | |
| 2246 lj_ir_knumint(J, numV(tv)); } break; | |
| 2247 case BCMstr: { GCstr *s = gco2str(proto_kgc(J->pt, ~(ptrdiff_t)rc)); | |
| 2248 setstrV(J->L, rcv, s); ix.key = rc = lj_ir_kstr(J, s); } break; | |
| 2249 default: break; /* Handled later. */ | |
| 2250 } | |
| 2251 | |
| 2252 switch (op) { | |
| 2253 | |
| 2254 /* -- Comparison ops ---------------------------------------------------- */ | |
| 2255 | |
| 2256 case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: | |
| 2257 #if LJ_HASFFI | |
| 2258 if (tref_iscdata(ra) || tref_iscdata(rc)) { | |
| 2259 rec_mm_comp_cdata(J, &ix, op, ((int)op & 2) ? MM_le : MM_lt); | |
| 2260 break; | |
| 2261 } | |
| 2262 #endif | |
| 2263 /* Emit nothing for two numeric or string consts. */ | |
| 2264 if (!(tref_isk2(ra,rc) && tref_isnumber_str(ra) && tref_isnumber_str(rc))) { | |
| 2265 IRType ta = tref_isinteger(ra) ? IRT_INT : tref_type(ra); | |
| 2266 IRType tc = tref_isinteger(rc) ? IRT_INT : tref_type(rc); | |
| 2267 int irop; | |
| 2268 if (ta != tc) { | |
| 2269 /* Widen mixed number/int comparisons to number/number comparison. */ | |
| 2270 if (ta == IRT_INT && tc == IRT_NUM) { | |
| 2271 ra = emitir(IRTN(IR_CONV), ra, IRCONV_NUM_INT); | |
| 2272 ta = IRT_NUM; | |
| 2273 } else if (ta == IRT_NUM && tc == IRT_INT) { | |
| 2274 rc = emitir(IRTN(IR_CONV), rc, IRCONV_NUM_INT); | |
| 2275 } else if (LJ_52) { | |
| 2276 ta = IRT_NIL; /* Force metamethod for different types. */ | |
| 2277 } else if (!((ta == IRT_FALSE || ta == IRT_TRUE) && | |
| 2278 (tc == IRT_FALSE || tc == IRT_TRUE))) { | |
| 2279 break; /* Interpreter will throw for two different types. */ | |
| 2280 } | |
| 2281 } | |
| 2282 rec_comp_prep(J); | |
| 2283 irop = (int)op - (int)BC_ISLT + (int)IR_LT; | |
| 2284 if (ta == IRT_NUM) { | |
| 2285 if ((irop & 1)) irop ^= 4; /* ISGE/ISGT are unordered. */ | |
| 2286 if (!lj_ir_numcmp(numberVnum(rav), numberVnum(rcv), (IROp)irop)) | |
| 2287 irop ^= 5; | |
| 2288 } else if (ta == IRT_INT) { | |
| 2289 if (!lj_ir_numcmp(numberVnum(rav), numberVnum(rcv), (IROp)irop)) | |
| 2290 irop ^= 1; | |
| 2291 } else if (ta == IRT_STR) { | |
| 2292 if (!lj_ir_strcmp(strV(rav), strV(rcv), (IROp)irop)) irop ^= 1; | |
| 2293 ra = lj_ir_call(J, IRCALL_lj_str_cmp, ra, rc); | |
| 2294 rc = lj_ir_kint(J, 0); | |
| 2295 ta = IRT_INT; | |
| 2296 } else { | |
| 2297 rec_mm_comp(J, &ix, (int)op); | |
| 2298 break; | |
| 2299 } | |
| 2300 emitir(IRTG(irop, ta), ra, rc); | |
| 2301 rec_comp_fixup(J, J->pc, ((int)op ^ irop) & 1); | |
| 2302 } | |
| 2303 break; | |
| 2304 | |
| 2305 case BC_ISEQV: case BC_ISNEV: | |
| 2306 case BC_ISEQS: case BC_ISNES: | |
| 2307 case BC_ISEQN: case BC_ISNEN: | |
| 2308 case BC_ISEQP: case BC_ISNEP: | |
| 2309 #if LJ_HASFFI | |
| 2310 if (tref_iscdata(ra) || tref_iscdata(rc)) { | |
| 2311 rec_mm_comp_cdata(J, &ix, op, MM_eq); | |
| 2312 break; | |
| 2313 } | |
| 2314 #endif | |
| 2315 /* Emit nothing for two non-table, non-udata consts. */ | |
| 2316 if (!(tref_isk2(ra, rc) && !(tref_istab(ra) || tref_isudata(ra)))) { | |
| 2317 int diff; | |
| 2318 rec_comp_prep(J); | |
| 2319 diff = lj_record_objcmp(J, ra, rc, rav, rcv); | |
| 2320 if (diff == 2 || !(tref_istab(ra) || tref_isudata(ra))) | |
| 2321 rec_comp_fixup(J, J->pc, ((int)op & 1) == !diff); | |
| 2322 else if (diff == 1) /* Only check __eq if different, but same type. */ | |
| 2323 rec_mm_equal(J, &ix, (int)op); | |
| 2324 } | |
| 2325 break; | |
| 2326 | |
| 2327 /* -- Unary test and copy ops ------------------------------------------- */ | |
| 2328 | |
| 2329 case BC_ISTC: case BC_ISFC: | |
| 2330 if ((op & 1) == tref_istruecond(rc)) | |
| 2331 rc = 0; /* Don't store if condition is not true. */ | |
| 2332 /* fallthrough */ | |
| 2333 case BC_IST: case BC_ISF: /* Type specialization suffices. */ | |
| 2334 if (bc_a(pc[1]) < J->maxslot) | |
| 2335 J->maxslot = bc_a(pc[1]); /* Shrink used slots. */ | |
| 2336 break; | |
| 2337 | |
| 2338 case BC_ISTYPE: case BC_ISNUM: | |
| 2339 /* These coercions need to correspond with lj_meta_istype(). */ | |
| 2340 if (LJ_DUALNUM && rc == ~LJ_TNUMX+1) | |
| 2341 ra = lj_opt_narrow_toint(J, ra); | |
| 2342 else if (rc == ~LJ_TNUMX+2) | |
| 2343 ra = lj_ir_tonum(J, ra); | |
| 2344 else if (rc == ~LJ_TSTR+1) | |
| 2345 ra = lj_ir_tostr(J, ra); | |
| 2346 /* else: type specialization suffices. */ | |
| 2347 J->base[bc_a(ins)] = ra; | |
| 2348 break; | |
| 2349 | |
| 2350 /* -- Unary ops --------------------------------------------------------- */ | |
| 2351 | |
| 2352 case BC_NOT: | |
| 2353 /* Type specialization already forces const result. */ | |
| 2354 rc = tref_istruecond(rc) ? TREF_FALSE : TREF_TRUE; | |
| 2355 break; | |
| 2356 | |
| 2357 case BC_LEN: | |
| 2358 if (tref_isstr(rc)) | |
| 2359 rc = emitir(IRTI(IR_FLOAD), rc, IRFL_STR_LEN); | |
| 2360 else if (!LJ_52 && tref_istab(rc)) | |
| 2361 rc = emitir(IRTI(IR_ALEN), rc, TREF_NIL); | |
| 2362 else | |
| 2363 rc = rec_mm_len(J, rc, rcv); | |
| 2364 break; | |
| 2365 | |
| 2366 /* -- Arithmetic ops ---------------------------------------------------- */ | |
| 2367 | |
| 2368 case BC_UNM: | |
| 2369 if (tref_isnumber_str(rc)) { | |
| 2370 rc = lj_opt_narrow_unm(J, rc, rcv); | |
| 2371 } else { | |
| 2372 ix.tab = rc; | |
| 2373 copyTV(J->L, &ix.tabv, rcv); | |
| 2374 rc = rec_mm_arith(J, &ix, MM_unm); | |
| 2375 } | |
| 2376 break; | |
| 2377 | |
| 2378 case BC_ADDNV: case BC_SUBNV: case BC_MULNV: case BC_DIVNV: case BC_MODNV: | |
| 2379 /* Swap rb/rc and rbv/rcv. rav is temp. */ | |
| 2380 ix.tab = rc; ix.key = rc = rb; rb = ix.tab; | |
| 2381 copyTV(J->L, rav, rbv); | |
| 2382 copyTV(J->L, rbv, rcv); | |
| 2383 copyTV(J->L, rcv, rav); | |
| 2384 if (op == BC_MODNV) | |
| 2385 goto recmod; | |
| 2386 /* fallthrough */ | |
| 2387 case BC_ADDVN: case BC_SUBVN: case BC_MULVN: case BC_DIVVN: | |
| 2388 case BC_ADDVV: case BC_SUBVV: case BC_MULVV: case BC_DIVVV: { | |
| 2389 MMS mm = bcmode_mm(op); | |
| 2390 if (tref_isnumber_str(rb) && tref_isnumber_str(rc)) | |
| 2391 rc = lj_opt_narrow_arith(J, rb, rc, rbv, rcv, | |
| 2392 (int)mm - (int)MM_add + (int)IR_ADD); | |
| 2393 else | |
| 2394 rc = rec_mm_arith(J, &ix, mm); | |
| 2395 break; | |
| 2396 } | |
| 2397 | |
| 2398 case BC_MODVN: case BC_MODVV: | |
| 2399 recmod: | |
| 2400 if (tref_isnumber_str(rb) && tref_isnumber_str(rc)) | |
| 2401 rc = lj_opt_narrow_mod(J, rb, rc, rbv, rcv); | |
| 2402 else | |
| 2403 rc = rec_mm_arith(J, &ix, MM_mod); | |
| 2404 break; | |
| 2405 | |
| 2406 case BC_POW: | |
| 2407 if (tref_isnumber_str(rb) && tref_isnumber_str(rc)) | |
| 2408 rc = lj_opt_narrow_arith(J, rb, rc, rbv, rcv, IR_POW); | |
| 2409 else | |
| 2410 rc = rec_mm_arith(J, &ix, MM_pow); | |
| 2411 break; | |
| 2412 | |
| 2413 /* -- Miscellaneous ops ------------------------------------------------- */ | |
| 2414 | |
| 2415 case BC_CAT: | |
| 2416 rc = rec_cat(J, rb, rc); | |
| 2417 break; | |
| 2418 | |
| 2419 /* -- Constant and move ops --------------------------------------------- */ | |
| 2420 | |
| 2421 case BC_MOV: | |
| 2422 /* Clear gap of method call to avoid resurrecting previous refs. */ | |
| 2423 if (ra > J->maxslot) { | |
| 2424 #if LJ_FR2 | |
| 2425 memset(J->base + J->maxslot, 0, (ra - J->maxslot) * sizeof(TRef)); | |
| 2426 #else | |
| 2427 J->base[ra-1] = 0; | |
| 2428 #endif | |
| 2429 } | |
| 2430 break; | |
| 2431 case BC_KSTR: case BC_KNUM: case BC_KPRI: | |
| 2432 break; | |
| 2433 case BC_KSHORT: | |
| 2434 rc = lj_ir_kint(J, (int32_t)(int16_t)rc); | |
| 2435 break; | |
| 2436 case BC_KNIL: | |
| 2437 if (LJ_FR2 && ra > J->maxslot) | |
| 2438 J->base[ra-1] = 0; | |
| 2439 while (ra <= rc) | |
| 2440 J->base[ra++] = TREF_NIL; | |
| 2441 if (rc >= J->maxslot) J->maxslot = rc+1; | |
| 2442 break; | |
| 2443 #if LJ_HASFFI | |
| 2444 case BC_KCDATA: | |
| 2445 rc = lj_ir_kgc(J, proto_kgc(J->pt, ~(ptrdiff_t)rc), IRT_CDATA); | |
| 2446 break; | |
| 2447 #endif | |
| 2448 | |
| 2449 /* -- Upvalue and function ops ------------------------------------------ */ | |
| 2450 | |
| 2451 case BC_UGET: | |
| 2452 rc = rec_upvalue(J, rc, 0); | |
| 2453 break; | |
| 2454 case BC_USETV: case BC_USETS: case BC_USETN: case BC_USETP: | |
| 2455 rec_upvalue(J, ra, rc); | |
| 2456 break; | |
| 2457 | |
| 2458 /* -- Table ops --------------------------------------------------------- */ | |
| 2459 | |
| 2460 case BC_GGET: case BC_GSET: | |
| 2461 settabV(J->L, &ix.tabv, tabref(J->fn->l.env)); | |
| 2462 ix.tab = emitir(IRT(IR_FLOAD, IRT_TAB), getcurrf(J), IRFL_FUNC_ENV); | |
| 2463 ix.idxchain = LJ_MAX_IDXCHAIN; | |
| 2464 rc = lj_record_idx(J, &ix); | |
| 2465 break; | |
| 2466 | |
| 2467 case BC_TGETB: case BC_TSETB: | |
| 2468 setintV(&ix.keyv, (int32_t)rc); | |
| 2469 ix.key = lj_ir_kint(J, (int32_t)rc); | |
| 2470 /* fallthrough */ | |
| 2471 case BC_TGETV: case BC_TGETS: case BC_TSETV: case BC_TSETS: | |
| 2472 ix.idxchain = LJ_MAX_IDXCHAIN; | |
| 2473 rc = lj_record_idx(J, &ix); | |
| 2474 break; | |
| 2475 case BC_TGETR: case BC_TSETR: | |
| 2476 ix.idxchain = 0; | |
| 2477 rc = lj_record_idx(J, &ix); | |
| 2478 break; | |
| 2479 | |
| 2480 case BC_TSETM: | |
| 2481 rec_tsetm(J, ra, (BCReg)(J->L->top - J->L->base), (int32_t)rcv->u32.lo); | |
| 2482 J->maxslot = ra; /* The table slot at ra-1 is the highest used slot. */ | |
| 2483 break; | |
| 2484 | |
| 2485 case BC_TNEW: | |
| 2486 rc = rec_tnew(J, rc); | |
| 2487 break; | |
| 2488 case BC_TDUP: | |
| 2489 rc = emitir(IRTG(IR_TDUP, IRT_TAB), | |
| 2490 lj_ir_ktab(J, gco2tab(proto_kgc(J->pt, ~(ptrdiff_t)rc))), 0); | |
| 2491 #ifdef LUAJIT_ENABLE_TABLE_BUMP | |
| 2492 J->rbchash[(rc & (RBCHASH_SLOTS-1))].ref = tref_ref(rc); | |
| 2493 setmref(J->rbchash[(rc & (RBCHASH_SLOTS-1))].pc, pc); | |
| 2494 setgcref(J->rbchash[(rc & (RBCHASH_SLOTS-1))].pt, obj2gco(J->pt)); | |
| 2495 #endif | |
| 2496 break; | |
| 2497 | |
| 2498 /* -- Calls and vararg handling ----------------------------------------- */ | |
| 2499 | |
| 2500 case BC_ITERC: | |
| 2501 J->base[ra] = getslot(J, ra-3); | |
| 2502 J->base[ra+1+LJ_FR2] = getslot(J, ra-2); | |
| 2503 J->base[ra+2+LJ_FR2] = getslot(J, ra-1); | |
| 2504 { /* Do the actual copy now because lj_record_call needs the values. */ | |
| 2505 TValue *b = &J->L->base[ra]; | |
| 2506 copyTV(J->L, b, b-3); | |
| 2507 copyTV(J->L, b+1+LJ_FR2, b-2); | |
| 2508 copyTV(J->L, b+2+LJ_FR2, b-1); | |
| 2509 } | |
| 2510 lj_record_call(J, ra, (ptrdiff_t)rc-1); | |
| 2511 break; | |
| 2512 | |
| 2513 /* L->top is set to L->base+ra+rc+NARGS-1+1. See lj_dispatch_ins(). */ | |
| 2514 case BC_CALLM: | |
| 2515 rc = (BCReg)(J->L->top - J->L->base) - ra - LJ_FR2; | |
| 2516 /* fallthrough */ | |
| 2517 case BC_CALL: | |
| 2518 lj_record_call(J, ra, (ptrdiff_t)rc-1); | |
| 2519 break; | |
| 2520 | |
| 2521 case BC_CALLMT: | |
| 2522 rc = (BCReg)(J->L->top - J->L->base) - ra - LJ_FR2; | |
| 2523 /* fallthrough */ | |
| 2524 case BC_CALLT: | |
| 2525 lj_record_tailcall(J, ra, (ptrdiff_t)rc-1); | |
| 2526 break; | |
| 2527 | |
| 2528 case BC_VARG: | |
| 2529 rec_varg(J, ra, (ptrdiff_t)rb-1); | |
| 2530 break; | |
| 2531 | |
| 2532 /* -- Returns ----------------------------------------------------------- */ | |
| 2533 | |
| 2534 case BC_RETM: | |
| 2535 /* L->top is set to L->base+ra+rc+NRESULTS-1, see lj_dispatch_ins(). */ | |
| 2536 rc = (BCReg)(J->L->top - J->L->base) - ra + 1; | |
| 2537 /* fallthrough */ | |
| 2538 case BC_RET: case BC_RET0: case BC_RET1: | |
| 2539 #if LJ_HASPROFILE | |
| 2540 rec_profile_ret(J); | |
| 2541 #endif | |
| 2542 lj_record_ret(J, ra, (ptrdiff_t)rc-1); | |
| 2543 break; | |
| 2544 | |
| 2545 /* -- Loops and branches ------------------------------------------------ */ | |
| 2546 | |
| 2547 case BC_FORI: | |
| 2548 if (rec_for(J, pc, 0) != LOOPEV_LEAVE) | |
| 2549 J->loopref = J->cur.nins; | |
| 2550 break; | |
| 2551 case BC_JFORI: | |
| 2552 lj_assertJ(bc_op(pc[(ptrdiff_t)rc-BCBIAS_J]) == BC_JFORL, | |
| 2553 "JFORI does not point to JFORL"); | |
| 2554 if (rec_for(J, pc, 0) != LOOPEV_LEAVE) /* Link to existing loop. */ | |
| 2555 lj_record_stop(J, LJ_TRLINK_ROOT, bc_d(pc[(ptrdiff_t)rc-BCBIAS_J])); | |
| 2556 /* Continue tracing if the loop is not entered. */ | |
| 2557 break; | |
| 2558 | |
| 2559 case BC_FORL: | |
| 2560 rec_loop_interp(J, pc, rec_for(J, pc+((ptrdiff_t)rc-BCBIAS_J), 1)); | |
| 2561 break; | |
| 2562 case BC_ITERL: | |
| 2563 rec_loop_interp(J, pc, rec_iterl(J, *pc)); | |
| 2564 break; | |
| 2565 case BC_ITERN: | |
| 2566 rec_loop_interp(J, pc, rec_itern(J, ra, rb)); | |
| 2567 break; | |
| 2568 case BC_LOOP: | |
| 2569 rec_loop_interp(J, pc, rec_loop(J, ra, 1)); | |
| 2570 break; | |
| 2571 | |
| 2572 case BC_JFORL: | |
| 2573 rec_loop_jit(J, rc, rec_for(J, pc+bc_j(traceref(J, rc)->startins), 1)); | |
| 2574 break; | |
| 2575 case BC_JITERL: | |
| 2576 rec_loop_jit(J, rc, rec_iterl(J, traceref(J, rc)->startins)); | |
| 2577 break; | |
| 2578 case BC_JLOOP: | |
| 2579 rec_loop_jit(J, rc, rec_loop(J, ra, | |
| 2580 !bc_isret(bc_op(traceref(J, rc)->startins)) && | |
| 2581 bc_op(traceref(J, rc)->startins) != BC_ITERN)); | |
| 2582 break; | |
| 2583 | |
| 2584 case BC_IFORL: | |
| 2585 case BC_IITERL: | |
| 2586 case BC_ILOOP: | |
| 2587 case BC_IFUNCF: | |
| 2588 case BC_IFUNCV: | |
| 2589 lj_trace_err(J, LJ_TRERR_BLACKL); | |
| 2590 break; | |
| 2591 | |
| 2592 case BC_JMP: | |
| 2593 if (ra < J->maxslot) | |
| 2594 J->maxslot = ra; /* Shrink used slots. */ | |
| 2595 break; | |
| 2596 | |
| 2597 case BC_ISNEXT: | |
| 2598 rec_isnext(J, ra); | |
| 2599 break; | |
| 2600 | |
| 2601 /* -- Function headers -------------------------------------------------- */ | |
| 2602 | |
| 2603 case BC_FUNCF: | |
| 2604 rec_func_lua(J); | |
| 2605 break; | |
| 2606 case BC_JFUNCF: | |
| 2607 rec_func_jit(J, rc); | |
| 2608 break; | |
| 2609 | |
| 2610 case BC_FUNCV: | |
| 2611 rec_func_vararg(J); | |
| 2612 rec_func_lua(J); | |
| 2613 break; | |
| 2614 case BC_JFUNCV: | |
| 2615 /* Cannot happen. No hotcall counting for varag funcs. */ | |
| 2616 lj_assertJ(0, "unsupported vararg hotcall"); | |
| 2617 break; | |
| 2618 | |
| 2619 case BC_FUNCC: | |
| 2620 case BC_FUNCCW: | |
| 2621 lj_ffrecord_func(J); | |
| 2622 break; | |
| 2623 | |
| 2624 default: | |
| 2625 if (op >= BC__MAX) { | |
| 2626 lj_ffrecord_func(J); | |
| 2627 break; | |
| 2628 } | |
| 2629 /* fallthrough */ | |
| 2630 case BC_UCLO: | |
| 2631 case BC_FNEW: | |
| 2632 setintV(&J->errinfo, (int32_t)op); | |
| 2633 lj_trace_err_info(J, LJ_TRERR_NYIBC); | |
| 2634 break; | |
| 2635 } | |
| 2636 | |
| 2637 /* rc == 0 if we have no result yet, e.g. pending __index metamethod call. */ | |
| 2638 if (bcmode_a(op) == BCMdst && rc) { | |
| 2639 J->base[ra] = rc; | |
| 2640 if (ra >= J->maxslot) { | |
| 2641 #if LJ_FR2 | |
| 2642 if (ra > J->maxslot) J->base[ra-1] = 0; | |
| 2643 #endif | |
| 2644 J->maxslot = ra+1; | |
| 2645 } | |
| 2646 } | |
| 2647 | |
| 2648 #undef rav | |
| 2649 #undef rbv | |
| 2650 #undef rcv | |
| 2651 | |
| 2652 /* Limit the number of recorded IR instructions and constants. */ | |
| 2653 if (J->cur.nins > REF_FIRST+(IRRef)J->param[JIT_P_maxrecord] || | |
| 2654 J->cur.nk < REF_BIAS-(IRRef)J->param[JIT_P_maxirconst]) | |
| 2655 lj_trace_err(J, LJ_TRERR_TRACEOV); | |
| 2656 } | |
| 2657 | |
| 2658 /* -- Recording setup ----------------------------------------------------- */ | |
| 2659 | |
| 2660 /* Setup recording for a root trace started by a hot loop. */ | |
| 2661 static const BCIns *rec_setup_root(jit_State *J) | |
| 2662 { | |
| 2663 /* Determine the next PC and the bytecode range for the loop. */ | |
| 2664 const BCIns *pcj, *pc = J->pc; | |
| 2665 BCIns ins = *pc; | |
| 2666 BCReg ra = bc_a(ins); | |
| 2667 switch (bc_op(ins)) { | |
| 2668 case BC_FORL: | |
| 2669 J->bc_extent = (MSize)(-bc_j(ins))*sizeof(BCIns); | |
| 2670 pc += 1+bc_j(ins); | |
| 2671 J->bc_min = pc; | |
| 2672 break; | |
| 2673 case BC_ITERL: | |
| 2674 if (bc_op(pc[-1]) == BC_JLOOP) | |
| 2675 lj_trace_err(J, LJ_TRERR_LINNER); | |
| 2676 lj_assertJ(bc_op(pc[-1]) == BC_ITERC, "no ITERC before ITERL"); | |
| 2677 J->maxslot = ra + bc_b(pc[-1]) - 1; | |
| 2678 J->bc_extent = (MSize)(-bc_j(ins))*sizeof(BCIns); | |
| 2679 pc += 1+bc_j(ins); | |
| 2680 lj_assertJ(bc_op(pc[-1]) == BC_JMP, "ITERL does not point to JMP+1"); | |
| 2681 J->bc_min = pc; | |
| 2682 break; | |
| 2683 case BC_ITERN: | |
| 2684 lj_assertJ(bc_op(pc[1]) == BC_ITERL, "no ITERL after ITERN"); | |
| 2685 J->maxslot = ra; | |
| 2686 J->bc_extent = (MSize)(-bc_j(pc[1]))*sizeof(BCIns); | |
| 2687 J->bc_min = pc+2 + bc_j(pc[1]); | |
| 2688 J->state = LJ_TRACE_RECORD_1ST; /* Record the first ITERN, too. */ | |
| 2689 break; | |
| 2690 case BC_LOOP: | |
| 2691 /* Only check BC range for real loops, but not for "repeat until true". */ | |
| 2692 pcj = pc + bc_j(ins); | |
| 2693 ins = *pcj; | |
| 2694 if (bc_op(ins) == BC_JMP && bc_j(ins) < 0) { | |
| 2695 J->bc_min = pcj+1 + bc_j(ins); | |
| 2696 J->bc_extent = (MSize)(-bc_j(ins))*sizeof(BCIns); | |
| 2697 } | |
| 2698 J->maxslot = ra; | |
| 2699 pc++; | |
| 2700 break; | |
| 2701 case BC_RET: | |
| 2702 case BC_RET0: | |
| 2703 case BC_RET1: | |
| 2704 /* No bytecode range check for down-recursive root traces. */ | |
| 2705 J->maxslot = ra + bc_d(ins) - 1; | |
| 2706 break; | |
| 2707 case BC_FUNCF: | |
| 2708 /* No bytecode range check for root traces started by a hot call. */ | |
| 2709 J->maxslot = J->pt->numparams; | |
| 2710 pc++; | |
| 2711 break; | |
| 2712 case BC_CALLM: | |
| 2713 case BC_CALL: | |
| 2714 case BC_ITERC: | |
| 2715 /* No bytecode range check for stitched traces. */ | |
| 2716 pc++; | |
| 2717 break; | |
| 2718 default: | |
| 2719 lj_assertJ(0, "bad root trace start bytecode %d", bc_op(ins)); | |
| 2720 break; | |
| 2721 } | |
| 2722 return pc; | |
| 2723 } | |
| 2724 | |
| 2725 /* Setup for recording a new trace. */ | |
| 2726 void lj_record_setup(jit_State *J) | |
| 2727 { | |
| 2728 uint32_t i; | |
| 2729 | |
| 2730 /* Initialize state related to current trace. */ | |
| 2731 memset(J->slot, 0, sizeof(J->slot)); | |
| 2732 memset(J->chain, 0, sizeof(J->chain)); | |
| 2733 #ifdef LUAJIT_ENABLE_TABLE_BUMP | |
| 2734 memset(J->rbchash, 0, sizeof(J->rbchash)); | |
| 2735 #endif | |
| 2736 memset(J->bpropcache, 0, sizeof(J->bpropcache)); | |
| 2737 J->scev.idx = REF_NIL; | |
| 2738 setmref(J->scev.pc, NULL); | |
| 2739 | |
| 2740 J->baseslot = 1+LJ_FR2; /* Invoking function is at base[-1-LJ_FR2]. */ | |
| 2741 J->base = J->slot + J->baseslot; | |
| 2742 J->maxslot = 0; | |
| 2743 J->framedepth = 0; | |
| 2744 J->retdepth = 0; | |
| 2745 | |
| 2746 J->instunroll = J->param[JIT_P_instunroll]; | |
| 2747 J->loopunroll = J->param[JIT_P_loopunroll]; | |
| 2748 J->tailcalled = 0; | |
| 2749 J->loopref = 0; | |
| 2750 | |
| 2751 J->bc_min = NULL; /* Means no limit. */ | |
| 2752 J->bc_extent = ~(MSize)0; | |
| 2753 | |
| 2754 /* Emit instructions for fixed references. Also triggers initial IR alloc. */ | |
| 2755 emitir_raw(IRT(IR_BASE, IRT_PGC), J->parent, J->exitno); | |
| 2756 for (i = 0; i <= 2; i++) { | |
| 2757 IRIns *ir = IR(REF_NIL-i); | |
| 2758 ir->i = 0; | |
| 2759 ir->t.irt = (uint8_t)(IRT_NIL+i); | |
| 2760 ir->o = IR_KPRI; | |
| 2761 ir->prev = 0; | |
| 2762 } | |
| 2763 J->cur.nk = REF_TRUE; | |
| 2764 | |
| 2765 J->startpc = J->pc; | |
| 2766 setmref(J->cur.startpc, J->pc); | |
| 2767 if (J->parent) { /* Side trace. */ | |
| 2768 GCtrace *T = traceref(J, J->parent); | |
| 2769 TraceNo root = T->root ? T->root : J->parent; | |
| 2770 J->cur.root = (uint16_t)root; | |
| 2771 J->cur.startins = BCINS_AD(BC_JMP, 0, 0); | |
| 2772 /* Check whether we could at least potentially form an extra loop. */ | |
| 2773 if (J->exitno == 0 && T->snap[0].nent == 0) { | |
| 2774 /* We can narrow a FORL for some side traces, too. */ | |
| 2775 if (J->pc > proto_bc(J->pt) && bc_op(J->pc[-1]) == BC_JFORI && | |
| 2776 bc_d(J->pc[bc_j(J->pc[-1])-1]) == root) { | |
| 2777 lj_snap_add(J); | |
| 2778 rec_for_loop(J, J->pc-1, &J->scev, 1); | |
| 2779 goto sidecheck; | |
| 2780 } | |
| 2781 } else { | |
| 2782 J->startpc = NULL; /* Prevent forming an extra loop. */ | |
| 2783 } | |
| 2784 lj_snap_replay(J, T); | |
| 2785 sidecheck: | |
| 2786 if ((traceref(J, J->cur.root)->nchild >= J->param[JIT_P_maxside] || | |
| 2787 T->snap[J->exitno].count >= J->param[JIT_P_hotexit] + | |
| 2788 J->param[JIT_P_tryside])) { | |
| 2789 if (bc_op(*J->pc) == BC_JLOOP) { | |
| 2790 BCIns startins = traceref(J, bc_d(*J->pc))->startins; | |
| 2791 if (bc_op(startins) == BC_ITERN) | |
| 2792 rec_itern(J, bc_a(startins), bc_b(startins)); | |
| 2793 } | |
| 2794 lj_record_stop(J, LJ_TRLINK_INTERP, 0); | |
| 2795 } | |
| 2796 } else { /* Root trace. */ | |
| 2797 J->cur.root = 0; | |
| 2798 J->cur.startins = *J->pc; | |
| 2799 J->pc = rec_setup_root(J); | |
| 2800 /* Note: the loop instruction itself is recorded at the end and not | |
| 2801 ** at the start! So snapshot #0 needs to point to the *next* instruction. | |
| 2802 ** The one exception is BC_ITERN, which sets LJ_TRACE_RECORD_1ST. | |
| 2803 */ | |
| 2804 lj_snap_add(J); | |
| 2805 if (bc_op(J->cur.startins) == BC_FORL) | |
| 2806 rec_for_loop(J, J->pc-1, &J->scev, 1); | |
| 2807 else if (bc_op(J->cur.startins) == BC_ITERC) | |
| 2808 J->startpc = NULL; | |
| 2809 if (1 + J->pt->framesize >= LJ_MAX_JSLOTS) | |
| 2810 lj_trace_err(J, LJ_TRERR_STACKOV); | |
| 2811 } | |
| 2812 #if LJ_HASPROFILE | |
| 2813 J->prev_pt = NULL; | |
| 2814 J->prev_line = -1; | |
| 2815 #endif | |
| 2816 #ifdef LUAJIT_ENABLE_CHECKHOOK | |
| 2817 /* Regularly check for instruction/line hooks from compiled code and | |
| 2818 ** exit to the interpreter if the hooks are set. | |
| 2819 ** | |
| 2820 ** This is a compile-time option and disabled by default, since the | |
| 2821 ** hook checks may be quite expensive in tight loops. | |
| 2822 ** | |
| 2823 ** Note this is only useful if hooks are *not* set most of the time. | |
| 2824 ** Use this only if you want to *asynchronously* interrupt the execution. | |
| 2825 ** | |
| 2826 ** You can set the instruction hook via lua_sethook() with a count of 1 | |
| 2827 ** from a signal handler or another native thread. Please have a look | |
| 2828 ** at the first few functions in luajit.c for an example (Ctrl-C handler). | |
| 2829 */ | |
| 2830 { | |
| 2831 TRef tr = emitir(IRT(IR_XLOAD, IRT_U8), | |
| 2832 lj_ir_kptr(J, &J2G(J)->hookmask), IRXLOAD_VOLATILE); | |
| 2833 tr = emitir(IRTI(IR_BAND), tr, lj_ir_kint(J, (LUA_MASKLINE|LUA_MASKCOUNT))); | |
| 2834 emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, 0)); | |
| 2835 } | |
| 2836 #endif | |
| 2837 } | |
| 2838 | |
| 2839 #undef IR | |
| 2840 #undef emitir_raw | |
| 2841 #undef emitir | |
| 2842 | |
| 2843 #endif |