aboutsummaryrefslogtreecommitdiff
path: root/src/lj_trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_trace.c')
-rw-r--r--src/lj_trace.c257
1 files changed, 205 insertions, 52 deletions
diff --git a/src/lj_trace.c b/src/lj_trace.c
index 89c3c5ed..c2329394 100644
--- a/src/lj_trace.c
+++ b/src/lj_trace.c
@@ -30,6 +30,7 @@
30#include "lj_vm.h" 30#include "lj_vm.h"
31#include "lj_vmevent.h" 31#include "lj_vmevent.h"
32#include "lj_target.h" 32#include "lj_target.h"
33#include "lj_prng.h"
33 34
34/* -- Error handling ------------------------------------------------------ */ 35/* -- Error handling ------------------------------------------------------ */
35 36
@@ -104,7 +105,8 @@ static void perftools_addtrace(GCtrace *T)
104 name++; 105 name++;
105 else 106 else
106 name = "(string)"; 107 name = "(string)";
107 lua_assert(startpc >= proto_bc(pt) && startpc < proto_bc(pt) + pt->sizebc); 108 lj_assertX(startpc >= proto_bc(pt) && startpc < proto_bc(pt) + pt->sizebc,
109 "trace PC out of range");
108 lineno = lj_debug_line(pt, proto_bcpos(pt, startpc)); 110 lineno = lj_debug_line(pt, proto_bcpos(pt, startpc));
109 if (!fp) { 111 if (!fp) {
110 char fname[40]; 112 char fname[40];
@@ -117,15 +119,26 @@ static void perftools_addtrace(GCtrace *T)
117} 119}
118#endif 120#endif
119 121
120/* Allocate space for copy of trace. */ 122/* Allocate space for copy of T. */
121static GCtrace *trace_save_alloc(jit_State *J) 123GCtrace * LJ_FASTCALL lj_trace_alloc(lua_State *L, GCtrace *T)
122{ 124{
123 size_t sztr = ((sizeof(GCtrace)+7)&~7); 125 size_t sztr = ((sizeof(GCtrace)+7)&~7);
124 size_t szins = (J->cur.nins-J->cur.nk)*sizeof(IRIns); 126 size_t szins = (T->nins-T->nk)*sizeof(IRIns);
125 size_t sz = sztr + szins + 127 size_t sz = sztr + szins +
126 J->cur.nsnap*sizeof(SnapShot) + 128 T->nsnap*sizeof(SnapShot) +
127 J->cur.nsnapmap*sizeof(SnapEntry); 129 T->nsnapmap*sizeof(SnapEntry);
128 return lj_mem_newt(J->L, (MSize)sz, GCtrace); 130 GCtrace *T2 = lj_mem_newt(L, (MSize)sz, GCtrace);
131 char *p = (char *)T2 + sztr;
132 T2->gct = ~LJ_TTRACE;
133 T2->marked = 0;
134 T2->traceno = 0;
135 T2->ir = (IRIns *)p - T->nk;
136 T2->nins = T->nins;
137 T2->nk = T->nk;
138 T2->nsnap = T->nsnap;
139 T2->nsnapmap = T->nsnapmap;
140 memcpy(p, T->ir + T->nk, szins);
141 return T2;
129} 142}
130 143
131/* Save current trace by copying and compacting it. */ 144/* Save current trace by copying and compacting it. */
@@ -139,12 +152,12 @@ static void trace_save(jit_State *J, GCtrace *T)
139 setgcrefp(J2G(J)->gc.root, T); 152 setgcrefp(J2G(J)->gc.root, T);
140 newwhite(J2G(J), T); 153 newwhite(J2G(J), T);
141 T->gct = ~LJ_TTRACE; 154 T->gct = ~LJ_TTRACE;
142 T->ir = (IRIns *)p - J->cur.nk; 155 T->ir = (IRIns *)p - J->cur.nk; /* The IR has already been copied above. */
143 memcpy(p, J->cur.ir+J->cur.nk, szins);
144 p += szins; 156 p += szins;
145 TRACE_APPENDVEC(snap, nsnap, SnapShot) 157 TRACE_APPENDVEC(snap, nsnap, SnapShot)
146 TRACE_APPENDVEC(snapmap, nsnapmap, SnapEntry) 158 TRACE_APPENDVEC(snapmap, nsnapmap, SnapEntry)
147 J->cur.traceno = 0; 159 J->cur.traceno = 0;
160 J->curfinal = NULL;
148 setgcrefp(J->trace[T->traceno], T); 161 setgcrefp(J->trace[T->traceno], T);
149 lj_gc_barriertrace(J2G(J), T->traceno); 162 lj_gc_barriertrace(J2G(J), T->traceno);
150 lj_gdbjit_addtrace(J, T); 163 lj_gdbjit_addtrace(J, T);
@@ -172,7 +185,7 @@ void lj_trace_reenableproto(GCproto *pt)
172{ 185{
173 if ((pt->flags & PROTO_ILOOP)) { 186 if ((pt->flags & PROTO_ILOOP)) {
174 BCIns *bc = proto_bc(pt); 187 BCIns *bc = proto_bc(pt);
175 BCPos i, sizebc = pt->sizebc;; 188 BCPos i, sizebc = pt->sizebc;
176 pt->flags &= ~PROTO_ILOOP; 189 pt->flags &= ~PROTO_ILOOP;
177 if (bc_op(bc[0]) == BC_IFUNCF) 190 if (bc_op(bc[0]) == BC_IFUNCF)
178 setbc_op(&bc[0], BC_FUNCF); 191 setbc_op(&bc[0], BC_FUNCF);
@@ -194,27 +207,28 @@ static void trace_unpatch(jit_State *J, GCtrace *T)
194 return; /* No need to unpatch branches in parent traces (yet). */ 207 return; /* No need to unpatch branches in parent traces (yet). */
195 switch (bc_op(*pc)) { 208 switch (bc_op(*pc)) {
196 case BC_JFORL: 209 case BC_JFORL:
197 lua_assert(traceref(J, bc_d(*pc)) == T); 210 lj_assertJ(traceref(J, bc_d(*pc)) == T, "JFORL references other trace");
198 *pc = T->startins; 211 *pc = T->startins;
199 pc += bc_j(T->startins); 212 pc += bc_j(T->startins);
200 lua_assert(bc_op(*pc) == BC_JFORI); 213 lj_assertJ(bc_op(*pc) == BC_JFORI, "FORL does not point to JFORI");
201 setbc_op(pc, BC_FORI); 214 setbc_op(pc, BC_FORI);
202 break; 215 break;
203 case BC_JITERL: 216 case BC_JITERL:
204 case BC_JLOOP: 217 case BC_JLOOP:
205 lua_assert(op == BC_ITERL || op == BC_LOOP || bc_isret(op)); 218 lj_assertJ(op == BC_ITERL || op == BC_ITERN || op == BC_LOOP ||
219 bc_isret(op), "bad original bytecode %d", op);
206 *pc = T->startins; 220 *pc = T->startins;
207 break; 221 break;
208 case BC_JMP: 222 case BC_JMP:
209 lua_assert(op == BC_ITERL); 223 lj_assertJ(op == BC_ITERL, "bad original bytecode %d", op);
210 pc += bc_j(*pc)+2; 224 pc += bc_j(*pc)+2;
211 if (bc_op(*pc) == BC_JITERL) { 225 if (bc_op(*pc) == BC_JITERL) {
212 lua_assert(traceref(J, bc_d(*pc)) == T); 226 lj_assertJ(traceref(J, bc_d(*pc)) == T, "JITERL references other trace");
213 *pc = T->startins; 227 *pc = T->startins;
214 } 228 }
215 break; 229 break;
216 case BC_JFUNCF: 230 case BC_JFUNCF:
217 lua_assert(op == BC_FUNCF); 231 lj_assertJ(op == BC_FUNCF, "bad original bytecode %d", op);
218 *pc = T->startins; 232 *pc = T->startins;
219 break; 233 break;
220 default: /* Already unpatched. */ 234 default: /* Already unpatched. */
@@ -226,7 +240,8 @@ static void trace_unpatch(jit_State *J, GCtrace *T)
226static void trace_flushroot(jit_State *J, GCtrace *T) 240static void trace_flushroot(jit_State *J, GCtrace *T)
227{ 241{
228 GCproto *pt = &gcref(T->startpt)->pt; 242 GCproto *pt = &gcref(T->startpt)->pt;
229 lua_assert(T->root == 0 && pt != NULL); 243 lj_assertJ(T->root == 0, "not a root trace");
244 lj_assertJ(pt != NULL, "trace has no prototype");
230 /* First unpatch any modified bytecode. */ 245 /* First unpatch any modified bytecode. */
231 trace_unpatch(J, T); 246 trace_unpatch(J, T);
232 /* Unlink root trace from chain anchored in prototype. */ 247 /* Unlink root trace from chain anchored in prototype. */
@@ -274,7 +289,7 @@ int lj_trace_flushall(lua_State *L)
274 if (T->root == 0) 289 if (T->root == 0)
275 trace_flushroot(J, T); 290 trace_flushroot(J, T);
276 lj_gdbjit_deltrace(J, T); 291 lj_gdbjit_deltrace(J, T);
277 T->traceno = 0; 292 T->traceno = T->link = 0; /* Blacklist the link for cont_stitch. */
278 setgcrefnull(J->trace[i]); 293 setgcrefnull(J->trace[i]);
279 } 294 }
280 } 295 }
@@ -296,13 +311,42 @@ void lj_trace_initstate(global_State *g)
296{ 311{
297 jit_State *J = G2J(g); 312 jit_State *J = G2J(g);
298 TValue *tv; 313 TValue *tv;
299 /* Initialize SIMD constants. */ 314
315 /* Initialize aligned SIMD constants. */
300 tv = LJ_KSIMD(J, LJ_KSIMD_ABS); 316 tv = LJ_KSIMD(J, LJ_KSIMD_ABS);
301 tv[0].u64 = U64x(7fffffff,ffffffff); 317 tv[0].u64 = U64x(7fffffff,ffffffff);
302 tv[1].u64 = U64x(7fffffff,ffffffff); 318 tv[1].u64 = U64x(7fffffff,ffffffff);
303 tv = LJ_KSIMD(J, LJ_KSIMD_NEG); 319 tv = LJ_KSIMD(J, LJ_KSIMD_NEG);
304 tv[0].u64 = U64x(80000000,00000000); 320 tv[0].u64 = U64x(80000000,00000000);
305 tv[1].u64 = U64x(80000000,00000000); 321 tv[1].u64 = U64x(80000000,00000000);
322
323 /* Initialize 32/64 bit constants. */
324#if LJ_TARGET_X86ORX64
325 J->k64[LJ_K64_TOBIT].u64 = U64x(43380000,00000000);
326#if LJ_32
327 J->k64[LJ_K64_M2P64_31].u64 = U64x(c1e00000,00000000);
328#endif
329 J->k64[LJ_K64_2P64].u64 = U64x(43f00000,00000000);
330 J->k32[LJ_K32_M2P64_31] = LJ_64 ? 0xdf800000 : 0xcf000000;
331#endif
332#if LJ_TARGET_X86ORX64 || LJ_TARGET_MIPS64
333 J->k64[LJ_K64_M2P64].u64 = U64x(c3f00000,00000000);
334#endif
335#if LJ_TARGET_PPC
336 J->k32[LJ_K32_2P52_2P31] = 0x59800004;
337 J->k32[LJ_K32_2P52] = 0x59800000;
338#endif
339#if LJ_TARGET_PPC || LJ_TARGET_MIPS
340 J->k32[LJ_K32_2P31] = 0x4f000000;
341#endif
342#if LJ_TARGET_MIPS
343 J->k64[LJ_K64_2P31].u64 = U64x(41e00000,00000000);
344#if LJ_64
345 J->k64[LJ_K64_2P63].u64 = U64x(43e00000,00000000);
346 J->k32[LJ_K32_2P63] = 0x5f000000;
347 J->k32[LJ_K32_M2P64] = 0xdf800000;
348#endif
349#endif
306} 350}
307 351
308/* Free everything associated with the JIT compiler state. */ 352/* Free everything associated with the JIT compiler state. */
@@ -313,11 +357,11 @@ void lj_trace_freestate(global_State *g)
313 { /* This assumes all traces have already been freed. */ 357 { /* This assumes all traces have already been freed. */
314 ptrdiff_t i; 358 ptrdiff_t i;
315 for (i = 1; i < (ptrdiff_t)J->sizetrace; i++) 359 for (i = 1; i < (ptrdiff_t)J->sizetrace; i++)
316 lua_assert(i == (ptrdiff_t)J->cur.traceno || traceref(J, i) == NULL); 360 lj_assertG(i == (ptrdiff_t)J->cur.traceno || traceref(J, i) == NULL,
361 "trace still allocated");
317 } 362 }
318#endif 363#endif
319 lj_mcode_free(J); 364 lj_mcode_free(J);
320 lj_ir_k64_freeall(J);
321 lj_mem_freevec(g, J->snapmapbuf, J->sizesnapmap, SnapEntry); 365 lj_mem_freevec(g, J->snapmapbuf, J->sizesnapmap, SnapEntry);
322 lj_mem_freevec(g, J->snapbuf, J->sizesnap, SnapShot); 366 lj_mem_freevec(g, J->snapbuf, J->sizesnap, SnapShot);
323 lj_mem_freevec(g, J->irbuf + J->irbotlim, J->irtoplim - J->irbotlim, IRIns); 367 lj_mem_freevec(g, J->irbuf + J->irbotlim, J->irtoplim - J->irbotlim, IRIns);
@@ -329,8 +373,13 @@ void lj_trace_freestate(global_State *g)
329/* Blacklist a bytecode instruction. */ 373/* Blacklist a bytecode instruction. */
330static void blacklist_pc(GCproto *pt, BCIns *pc) 374static void blacklist_pc(GCproto *pt, BCIns *pc)
331{ 375{
332 setbc_op(pc, (int)bc_op(*pc)+(int)BC_ILOOP-(int)BC_LOOP); 376 if (bc_op(*pc) == BC_ITERN) {
333 pt->flags |= PROTO_ILOOP; 377 setbc_op(pc, BC_ITERC);
378 setbc_op(pc+1+bc_j(pc[1]), BC_JMP);
379 } else {
380 setbc_op(pc, (int)bc_op(*pc)+(int)BC_ILOOP-(int)BC_LOOP);
381 pt->flags |= PROTO_ILOOP;
382 }
334} 383}
335 384
336/* Penalize a bytecode instruction. */ 385/* Penalize a bytecode instruction. */
@@ -341,7 +390,7 @@ static void penalty_pc(jit_State *J, GCproto *pt, BCIns *pc, TraceError e)
341 if (mref(J->penalty[i].pc, const BCIns) == pc) { /* Cache slot found? */ 390 if (mref(J->penalty[i].pc, const BCIns) == pc) { /* Cache slot found? */
342 /* First try to bump its hotcount several times. */ 391 /* First try to bump its hotcount several times. */
343 val = ((uint32_t)J->penalty[i].val << 1) + 392 val = ((uint32_t)J->penalty[i].val << 1) +
344 LJ_PRNG_BITS(J, PENALTY_RNDBITS); 393 (lj_prng_u64(&J2G(J)->prng) & ((1u<<PENALTY_RNDBITS)-1));
345 if (val > PENALTY_MAX) { 394 if (val > PENALTY_MAX) {
346 blacklist_pc(pt, pc); /* Blacklist it, if that didn't help. */ 395 blacklist_pc(pt, pc); /* Blacklist it, if that didn't help. */
347 return; 396 return;
@@ -367,10 +416,11 @@ static void trace_start(jit_State *J)
367 TraceNo traceno; 416 TraceNo traceno;
368 417
369 if ((J->pt->flags & PROTO_NOJIT)) { /* JIT disabled for this proto? */ 418 if ((J->pt->flags & PROTO_NOJIT)) { /* JIT disabled for this proto? */
370 if (J->parent == 0) { 419 if (J->parent == 0 && J->exitno == 0 && bc_op(*J->pc) != BC_ITERN) {
371 /* Lazy bytecode patching to disable hotcount events. */ 420 /* Lazy bytecode patching to disable hotcount events. */
372 lua_assert(bc_op(*J->pc) == BC_FORL || bc_op(*J->pc) == BC_ITERL || 421 lj_assertJ(bc_op(*J->pc) == BC_FORL || bc_op(*J->pc) == BC_ITERL ||
373 bc_op(*J->pc) == BC_LOOP || bc_op(*J->pc) == BC_FUNCF); 422 bc_op(*J->pc) == BC_LOOP || bc_op(*J->pc) == BC_FUNCF,
423 "bad hot bytecode %d", bc_op(*J->pc));
374 setbc_op(J->pc, (int)bc_op(*J->pc)+(int)BC_ILOOP-(int)BC_LOOP); 424 setbc_op(J->pc, (int)bc_op(*J->pc)+(int)BC_ILOOP-(int)BC_LOOP);
375 J->pt->flags |= PROTO_ILOOP; 425 J->pt->flags |= PROTO_ILOOP;
376 } 426 }
@@ -381,7 +431,8 @@ static void trace_start(jit_State *J)
381 /* Get a new trace number. */ 431 /* Get a new trace number. */
382 traceno = trace_findfree(J); 432 traceno = trace_findfree(J);
383 if (LJ_UNLIKELY(traceno == 0)) { /* No free trace? */ 433 if (LJ_UNLIKELY(traceno == 0)) { /* No free trace? */
384 lua_assert((J2G(J)->hookmask & HOOK_GC) == 0); 434 lj_assertJ((J2G(J)->hookmask & HOOK_GC) == 0,
435 "recorder called from GC hook");
385 lj_trace_flushall(J->L); 436 lj_trace_flushall(J->L);
386 J->state = LJ_TRACE_IDLE; /* Silently ignored. */ 437 J->state = LJ_TRACE_IDLE; /* Silently ignored. */
387 return; 438 return;
@@ -401,6 +452,8 @@ static void trace_start(jit_State *J)
401 J->guardemit.irt = 0; 452 J->guardemit.irt = 0;
402 J->postproc = LJ_POST_NONE; 453 J->postproc = LJ_POST_NONE;
403 lj_resetsplit(J); 454 lj_resetsplit(J);
455 J->retryrec = 0;
456 J->ktrace = 0;
404 setgcref(J->cur.startpt, obj2gco(J->pt)); 457 setgcref(J->cur.startpt, obj2gco(J->pt));
405 458
406 L = J->L; 459 L = J->L;
@@ -412,6 +465,12 @@ static void trace_start(jit_State *J)
412 if (J->parent) { 465 if (J->parent) {
413 setintV(L->top++, J->parent); 466 setintV(L->top++, J->parent);
414 setintV(L->top++, J->exitno); 467 setintV(L->top++, J->exitno);
468 } else {
469 BCOp op = bc_op(*J->pc);
470 if (op == BC_CALLM || op == BC_CALL || op == BC_ITERC) {
471 setintV(L->top++, J->exitno); /* Parent of stitched trace. */
472 setintV(L->top++, -1);
473 }
415 } 474 }
416 ); 475 );
417 lj_record_setup(J); 476 lj_record_setup(J);
@@ -424,7 +483,7 @@ static void trace_stop(jit_State *J)
424 BCOp op = bc_op(J->cur.startins); 483 BCOp op = bc_op(J->cur.startins);
425 GCproto *pt = &gcref(J->cur.startpt)->pt; 484 GCproto *pt = &gcref(J->cur.startpt)->pt;
426 TraceNo traceno = J->cur.traceno; 485 TraceNo traceno = J->cur.traceno;
427 GCtrace *T = trace_save_alloc(J); /* Do this first. May throw OOM. */ 486 GCtrace *T = J->curfinal;
428 lua_State *L; 487 lua_State *L;
429 488
430 switch (op) { 489 switch (op) {
@@ -442,6 +501,7 @@ static void trace_stop(jit_State *J)
442 J->cur.nextroot = pt->trace; 501 J->cur.nextroot = pt->trace;
443 pt->trace = (TraceNo1)traceno; 502 pt->trace = (TraceNo1)traceno;
444 break; 503 break;
504 case BC_ITERN:
445 case BC_RET: 505 case BC_RET:
446 case BC_RET0: 506 case BC_RET0:
447 case BC_RET1: 507 case BC_RET1:
@@ -449,7 +509,7 @@ static void trace_stop(jit_State *J)
449 goto addroot; 509 goto addroot;
450 case BC_JMP: 510 case BC_JMP:
451 /* Patch exit branch in parent to side trace entry. */ 511 /* Patch exit branch in parent to side trace entry. */
452 lua_assert(J->parent != 0 && J->cur.root != 0); 512 lj_assertJ(J->parent != 0 && J->cur.root != 0, "not a side trace");
453 lj_asm_patchexit(J, traceref(J, J->parent), J->exitno, J->cur.mcode); 513 lj_asm_patchexit(J, traceref(J, J->parent), J->exitno, J->cur.mcode);
454 /* Avoid compiling a side trace twice (stack resizing uses parent exit). */ 514 /* Avoid compiling a side trace twice (stack resizing uses parent exit). */
455 { 515 {
@@ -465,8 +525,14 @@ static void trace_stop(jit_State *J)
465 root->nextside = (TraceNo1)traceno; 525 root->nextside = (TraceNo1)traceno;
466 } 526 }
467 break; 527 break;
528 case BC_CALLM:
529 case BC_CALL:
530 case BC_ITERC:
531 /* Trace stitching: patch link of previous trace. */
532 traceref(J, J->exitno)->link = traceno;
533 break;
468 default: 534 default:
469 lua_assert(0); 535 lj_assertJ(0, "bad stop bytecode %d", op);
470 break; 536 break;
471 } 537 }
472 538
@@ -479,6 +545,7 @@ static void trace_stop(jit_State *J)
479 lj_vmevent_send(L, TRACE, 545 lj_vmevent_send(L, TRACE,
480 setstrV(L, L->top++, lj_str_newlit(L, "stop")); 546 setstrV(L, L->top++, lj_str_newlit(L, "stop"));
481 setintV(L->top++, traceno); 547 setintV(L->top++, traceno);
548 setfuncV(L, L->top++, J->fn);
482 ); 549 );
483} 550}
484 551
@@ -486,8 +553,8 @@ static void trace_stop(jit_State *J)
486static int trace_downrec(jit_State *J) 553static int trace_downrec(jit_State *J)
487{ 554{
488 /* Restart recording at the return instruction. */ 555 /* Restart recording at the return instruction. */
489 lua_assert(J->pt != NULL); 556 lj_assertJ(J->pt != NULL, "no active prototype");
490 lua_assert(bc_isret(bc_op(*J->pc))); 557 lj_assertJ(bc_isret(bc_op(*J->pc)), "not at a return bytecode");
491 if (bc_op(*J->pc) == BC_RETM) 558 if (bc_op(*J->pc) == BC_RETM)
492 return 0; /* NYI: down-recursion with RETM. */ 559 return 0; /* NYI: down-recursion with RETM. */
493 J->parent = 0; 560 J->parent = 0;
@@ -506,6 +573,10 @@ static int trace_abort(jit_State *J)
506 573
507 J->postproc = LJ_POST_NONE; 574 J->postproc = LJ_POST_NONE;
508 lj_mcode_abort(J); 575 lj_mcode_abort(J);
576 if (J->curfinal) {
577 lj_trace_free(J2G(J), J->curfinal);
578 J->curfinal = NULL;
579 }
509 if (tvisnumber(L->top-1)) 580 if (tvisnumber(L->top-1))
510 e = (TraceError)numberVint(L->top-1); 581 e = (TraceError)numberVint(L->top-1);
511 if (e == LJ_TRERR_MCODELM) { 582 if (e == LJ_TRERR_MCODELM) {
@@ -514,8 +585,17 @@ static int trace_abort(jit_State *J)
514 return 1; /* Retry ASM with new MCode area. */ 585 return 1; /* Retry ASM with new MCode area. */
515 } 586 }
516 /* Penalize or blacklist starting bytecode instruction. */ 587 /* Penalize or blacklist starting bytecode instruction. */
517 if (J->parent == 0 && !bc_isret(bc_op(J->cur.startins))) 588 if (J->parent == 0 && !bc_isret(bc_op(J->cur.startins))) {
518 penalty_pc(J, &gcref(J->cur.startpt)->pt, mref(J->cur.startpc, BCIns), e); 589 if (J->exitno == 0) {
590 BCIns *startpc = mref(J->cur.startpc, BCIns);
591 if (e == LJ_TRERR_RETRY)
592 hotcount_set(J2GG(J), startpc+1, 1); /* Immediate retry. */
593 else
594 penalty_pc(J, &gcref(J->cur.startpt)->pt, startpc, e);
595 } else {
596 traceref(J, J->exitno)->link = J->exitno; /* Self-link is blacklisted. */
597 }
598 }
519 599
520 /* Is there anything to abort? */ 600 /* Is there anything to abort? */
521 traceno = J->cur.traceno; 601 traceno = J->cur.traceno;
@@ -581,8 +661,13 @@ static TValue *trace_state(lua_State *L, lua_CFunction dummy, void *ud)
581 J->state = LJ_TRACE_RECORD; /* trace_start() may change state. */ 661 J->state = LJ_TRACE_RECORD; /* trace_start() may change state. */
582 trace_start(J); 662 trace_start(J);
583 lj_dispatch_update(J2G(J)); 663 lj_dispatch_update(J2G(J));
584 break; 664 if (J->state != LJ_TRACE_RECORD_1ST)
665 break;
666 /* fallthrough */
585 667
668 case LJ_TRACE_RECORD_1ST:
669 J->state = LJ_TRACE_RECORD;
670 /* fallthrough */
586 case LJ_TRACE_RECORD: 671 case LJ_TRACE_RECORD:
587 trace_pendpatch(J, 0); 672 trace_pendpatch(J, 0);
588 setvmstate(J2G(J), RECORD); 673 setvmstate(J2G(J), RECORD);
@@ -688,15 +773,30 @@ static void trace_hotside(jit_State *J, const BCIns *pc)
688{ 773{
689 SnapShot *snap = &traceref(J, J->parent)->snap[J->exitno]; 774 SnapShot *snap = &traceref(J, J->parent)->snap[J->exitno];
690 if (!(J2G(J)->hookmask & (HOOK_GC|HOOK_VMEVENT)) && 775 if (!(J2G(J)->hookmask & (HOOK_GC|HOOK_VMEVENT)) &&
776 isluafunc(curr_func(J->L)) &&
691 snap->count != SNAPCOUNT_DONE && 777 snap->count != SNAPCOUNT_DONE &&
692 ++snap->count >= J->param[JIT_P_hotexit]) { 778 ++snap->count >= J->param[JIT_P_hotexit]) {
693 lua_assert(J->state == LJ_TRACE_IDLE); 779 lj_assertJ(J->state == LJ_TRACE_IDLE, "hot side exit while recording");
694 /* J->parent is non-zero for a side trace. */ 780 /* J->parent is non-zero for a side trace. */
695 J->state = LJ_TRACE_START; 781 J->state = LJ_TRACE_START;
696 lj_trace_ins(J, pc); 782 lj_trace_ins(J, pc);
697 } 783 }
698} 784}
699 785
786/* Stitch a new trace to the previous trace. */
787void LJ_FASTCALL lj_trace_stitch(jit_State *J, const BCIns *pc)
788{
789 /* Only start a new trace if not recording or inside __gc call or vmevent. */
790 if (J->state == LJ_TRACE_IDLE &&
791 !(J2G(J)->hookmask & (HOOK_GC|HOOK_VMEVENT))) {
792 J->parent = 0; /* Have to treat it like a root trace. */
793 /* J->exitno is set to the invoking trace. */
794 J->state = LJ_TRACE_START;
795 lj_trace_ins(J, pc);
796 }
797}
798
799
700/* Tiny struct to pass data to protected call. */ 800/* Tiny struct to pass data to protected call. */
701typedef struct ExitDataCP { 801typedef struct ExitDataCP {
702 jit_State *J; 802 jit_State *J;
@@ -740,7 +840,7 @@ static void trace_exit_regs(lua_State *L, ExitState *ex)
740} 840}
741#endif 841#endif
742 842
743#ifdef EXITSTATE_PCREG 843#if defined(EXITSTATE_PCREG) || (LJ_UNWIND_JIT && !EXITTRACE_VMSTATE)
744/* Determine trace number from pc of exit instruction. */ 844/* Determine trace number from pc of exit instruction. */
745static TraceNo trace_exit_find(jit_State *J, MCode *pc) 845static TraceNo trace_exit_find(jit_State *J, MCode *pc)
746{ 846{
@@ -750,7 +850,7 @@ static TraceNo trace_exit_find(jit_State *J, MCode *pc)
750 if (T && pc >= T->mcode && pc < (MCode *)((char *)T->mcode + T->szmcode)) 850 if (T && pc >= T->mcode && pc < (MCode *)((char *)T->mcode + T->szmcode))
751 return traceno; 851 return traceno;
752 } 852 }
753 lua_assert(0); 853 lj_assertJ(0, "bad exit pc");
754 return 0; 854 return 0;
755} 855}
756#endif 856#endif
@@ -762,40 +862,55 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
762 lua_State *L = J->L; 862 lua_State *L = J->L;
763 ExitState *ex = (ExitState *)exptr; 863 ExitState *ex = (ExitState *)exptr;
764 ExitDataCP exd; 864 ExitDataCP exd;
765 int errcode; 865 int errcode, exitcode = J->exitcode;
866 TValue exiterr;
766 const BCIns *pc; 867 const BCIns *pc;
767 void *cf; 868 void *cf;
768 GCtrace *T; 869 GCtrace *T;
870
871 setnilV(&exiterr);
872 if (exitcode) { /* Trace unwound with error code. */
873 J->exitcode = 0;
874 copyTV(L, &exiterr, L->top-1);
875 }
876
769#ifdef EXITSTATE_PCREG 877#ifdef EXITSTATE_PCREG
770 J->parent = trace_exit_find(J, (MCode *)(intptr_t)ex->gpr[EXITSTATE_PCREG]); 878 J->parent = trace_exit_find(J, (MCode *)(intptr_t)ex->gpr[EXITSTATE_PCREG]);
771#endif 879#endif
772 T = traceref(J, J->parent); UNUSED(T); 880 T = traceref(J, J->parent); UNUSED(T);
773#ifdef EXITSTATE_CHECKEXIT 881#ifdef EXITSTATE_CHECKEXIT
774 if (J->exitno == T->nsnap) { /* Treat stack check like a parent exit. */ 882 if (J->exitno == T->nsnap) { /* Treat stack check like a parent exit. */
775 lua_assert(T->root != 0); 883 lj_assertJ(T->root != 0, "stack check in root trace");
776 J->exitno = T->ir[REF_BASE].op2; 884 J->exitno = T->ir[REF_BASE].op2;
777 J->parent = T->ir[REF_BASE].op1; 885 J->parent = T->ir[REF_BASE].op1;
778 T = traceref(J, J->parent); 886 T = traceref(J, J->parent);
779 } 887 }
780#endif 888#endif
781 lua_assert(T != NULL && J->exitno < T->nsnap); 889 lj_assertJ(T != NULL && J->exitno < T->nsnap, "bad trace or exit number");
782 exd.J = J; 890 exd.J = J;
783 exd.exptr = exptr; 891 exd.exptr = exptr;
784 errcode = lj_vm_cpcall(L, NULL, &exd, trace_exit_cp); 892 errcode = lj_vm_cpcall(L, NULL, &exd, trace_exit_cp);
785 if (errcode) 893 if (errcode)
786 return -errcode; /* Return negated error code. */ 894 return -errcode; /* Return negated error code. */
787 895
788 lj_vmevent_send(L, TEXIT, 896 if (exitcode) copyTV(L, L->top++, &exiterr); /* Anchor the error object. */
789 lj_state_checkstack(L, 4+RID_NUM_GPR+RID_NUM_FPR+LUA_MINSTACK); 897
790 setintV(L->top++, J->parent); 898 if (!(LJ_HASPROFILE && (G(L)->hookmask & HOOK_PROFILE)))
791 setintV(L->top++, J->exitno); 899 lj_vmevent_send(L, TEXIT,
792 trace_exit_regs(L, ex); 900 lj_state_checkstack(L, 4+RID_NUM_GPR+RID_NUM_FPR+LUA_MINSTACK);
793 ); 901 setintV(L->top++, J->parent);
902 setintV(L->top++, J->exitno);
903 trace_exit_regs(L, ex);
904 );
794 905
795 pc = exd.pc; 906 pc = exd.pc;
796 cf = cframe_raw(L->cframe); 907 cf = cframe_raw(L->cframe);
797 setcframe_pc(cf, pc); 908 setcframe_pc(cf, pc);
798 if (G(L)->gc.state == GCSatomic || G(L)->gc.state == GCSfinalize) { 909 if (exitcode) {
910 return -exitcode;
911 } else if (LJ_HASPROFILE && (G(L)->hookmask & HOOK_PROFILE)) {
912 /* Just exit to interpreter. */
913 } else if (G(L)->gc.state == GCSatomic || G(L)->gc.state == GCSfinalize) {
799 if (!(G(L)->hookmask & HOOK_GC)) 914 if (!(G(L)->hookmask & HOOK_GC))
800 lj_gc_step(L); /* Exited because of GC: drive GC forward. */ 915 lj_gc_step(L); /* Exited because of GC: drive GC forward. */
801 } else { 916 } else {
@@ -803,13 +918,14 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
803 } 918 }
804 if (bc_op(*pc) == BC_JLOOP) { 919 if (bc_op(*pc) == BC_JLOOP) {
805 BCIns *retpc = &traceref(J, bc_d(*pc))->startins; 920 BCIns *retpc = &traceref(J, bc_d(*pc))->startins;
806 if (bc_isret(bc_op(*retpc))) { 921 int isret = bc_isret(bc_op(*retpc));
922 if (isret || bc_op(*retpc) == BC_ITERN) {
807 if (J->state == LJ_TRACE_RECORD) { 923 if (J->state == LJ_TRACE_RECORD) {
808 J->patchins = *pc; 924 J->patchins = *pc;
809 J->patchpc = (BCIns *)pc; 925 J->patchpc = (BCIns *)pc;
810 *J->patchpc = *retpc; 926 *J->patchpc = *retpc;
811 J->bcskip = 1; 927 J->bcskip = 1;
812 } else { 928 } else if (isret) {
813 pc = retpc; 929 pc = retpc;
814 setcframe_pc(cf, pc); 930 setcframe_pc(cf, pc);
815 } 931 }
@@ -819,7 +935,7 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
819 ERRNO_RESTORE 935 ERRNO_RESTORE
820 switch (bc_op(*pc)) { 936 switch (bc_op(*pc)) {
821 case BC_CALLM: case BC_CALLMT: 937 case BC_CALLM: case BC_CALLMT:
822 return (int)((BCReg)(L->top - L->base) - bc_a(*pc) - bc_c(*pc)); 938 return (int)((BCReg)(L->top - L->base) - bc_a(*pc) - bc_c(*pc) - LJ_FR2);
823 case BC_RETM: 939 case BC_RETM:
824 return (int)((BCReg)(L->top - L->base) + 1 - bc_a(*pc) - bc_d(*pc)); 940 return (int)((BCReg)(L->top - L->base) + 1 - bc_a(*pc) - bc_d(*pc));
825 case BC_TSETM: 941 case BC_TSETM:
@@ -831,4 +947,41 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
831 } 947 }
832} 948}
833 949
950#if LJ_UNWIND_JIT
951/* Given an mcode address determine trace exit address for unwinding. */
952uintptr_t LJ_FASTCALL lj_trace_unwind(jit_State *J, uintptr_t addr, ExitNo *ep)
953{
954#if EXITTRACE_VMSTATE
955 TraceNo traceno = J2G(J)->vmstate;
956#else
957 TraceNo traceno = trace_exit_find(J, (MCode *)addr);
958#endif
959 GCtrace *T = traceref(J, traceno);
960 if (T
961#if EXITTRACE_VMSTATE
962 && addr >= (uintptr_t)T->mcode && addr < (uintptr_t)T->mcode + T->szmcode
963#endif
964 ) {
965 SnapShot *snap = T->snap;
966 SnapNo lo = 0, exitno = T->nsnap;
967 uintptr_t ofs = (uintptr_t)((MCode *)addr - T->mcode); /* MCode units! */
968 /* Rightmost binary search for mcode offset to determine exit number. */
969 do {
970 SnapNo mid = (lo+exitno) >> 1;
971 if (ofs < snap[mid].mcofs) exitno = mid; else lo = mid + 1;
972 } while (lo < exitno);
973 exitno--;
974 *ep = exitno;
975#ifdef EXITSTUBS_PER_GROUP
976 return (uintptr_t)exitstub_addr(J, exitno);
977#else
978 return (uintptr_t)exitstub_trace_addr(T, exitno);
979#endif
980 }
981 /* Cannot correlate addr with trace/exit. This will be fatal. */
982 lj_assertJ(0, "bad exit pc");
983 return 0;
984}
985#endif
986
834#endif 987#endif