diff options
Diffstat (limited to 'src/lj_trace.c')
-rw-r--r-- | src/lj_trace.c | 111 |
1 files changed, 57 insertions, 54 deletions
diff --git a/src/lj_trace.c b/src/lj_trace.c index 4c9c4669..8419c9bb 100644 --- a/src/lj_trace.c +++ b/src/lj_trace.c | |||
@@ -50,9 +50,9 @@ void lj_trace_err_info(jit_State *J, TraceError e) | |||
50 | /* -- Trace management ---------------------------------------------------- */ | 50 | /* -- Trace management ---------------------------------------------------- */ |
51 | 51 | ||
52 | /* The current trace is first assembled in J->cur. The variable length | 52 | /* The current trace is first assembled in J->cur. The variable length |
53 | ** arrays point to shared, growable buffers (J->irbuf etc.). The trace is | 53 | ** arrays point to shared, growable buffers (J->irbuf etc.). When trace |
54 | ** kept in this state until a new trace needs to be created. Then the current | 54 | ** recording ends successfully, the current trace and its data structures |
55 | ** trace and its data structures are copied to a new (compact) GCtrace object. | 55 | ** are copied to a new (compact) GCtrace object. |
56 | */ | 56 | */ |
57 | 57 | ||
58 | /* Find a free trace number. */ | 58 | /* Find a free trace number. */ |
@@ -76,32 +76,35 @@ static TraceNo trace_findfree(jit_State *J) | |||
76 | return J->freetrace; | 76 | return J->freetrace; |
77 | } | 77 | } |
78 | 78 | ||
79 | #define TRACE_COPYELEM(field, szfield, tp) \ | 79 | #define TRACE_APPENDVEC(field, szfield, tp) \ |
80 | T2->field = (tp *)p; \ | 80 | T->field = (tp *)p; \ |
81 | memcpy(p, T->field, T->szfield*sizeof(tp)); \ | 81 | memcpy(p, J->cur.field, J->cur.szfield*sizeof(tp)); \ |
82 | p += T->szfield*sizeof(tp); | 82 | p += J->cur.szfield*sizeof(tp); |
83 | 83 | ||
84 | /* Save a trace by copying and compacting it. */ | 84 | /* Save current trace by copying and compacting it. */ |
85 | static GCtrace *trace_save(jit_State *J, GCtrace *T) | 85 | static void trace_save(jit_State *J) |
86 | { | 86 | { |
87 | size_t sztr = ((sizeof(GCtrace)+7)&~7); | 87 | size_t sztr = ((sizeof(GCtrace)+7)&~7); |
88 | size_t szins = (T->nins-T->nk)*sizeof(IRIns); | 88 | size_t szins = (J->cur.nins-J->cur.nk)*sizeof(IRIns); |
89 | size_t sz = sztr + szins + | 89 | size_t sz = sztr + szins + |
90 | T->nsnap*sizeof(SnapShot) + | 90 | J->cur.nsnap*sizeof(SnapShot) + |
91 | T->nsnapmap*sizeof(SnapEntry); | 91 | J->cur.nsnapmap*sizeof(SnapEntry); |
92 | GCtrace *T2 = lj_mem_newt(J->L, (MSize)sz, GCtrace); | 92 | GCtrace *T = lj_mem_newt(J->L, (MSize)sz, GCtrace); |
93 | char *p = (char *)T2 + sztr; | 93 | char *p = (char *)T + sztr; |
94 | memcpy(T2, T, sizeof(GCtrace)); | 94 | memcpy(T, &J->cur, sizeof(GCtrace)); |
95 | setgcrefr(T2->nextgc, J2G(J)->gc.root); | 95 | setgcrefr(T->nextgc, J2G(J)->gc.root); |
96 | setgcrefp(J2G(J)->gc.root, T2); | 96 | setgcrefp(J2G(J)->gc.root, T); |
97 | newwhite(J2G(J), T2); | 97 | newwhite(J2G(J), T); |
98 | T2->gct = ~LJ_TTRACE; | 98 | T->gct = ~LJ_TTRACE; |
99 | T2->ir = (IRIns *)p - T->nk; | 99 | T->ir = (IRIns *)p - J->cur.nk; |
100 | memcpy(p, T->ir+T->nk, szins); | 100 | memcpy(p, J->cur.ir+J->cur.nk, szins); |
101 | p += szins; | 101 | p += szins; |
102 | TRACE_COPYELEM(snap, nsnap, SnapShot) | 102 | TRACE_APPENDVEC(snap, nsnap, SnapShot) |
103 | TRACE_COPYELEM(snapmap, nsnapmap, SnapEntry) | 103 | TRACE_APPENDVEC(snapmap, nsnapmap, SnapEntry) |
104 | return T2; | 104 | J->cur.traceno = 0; |
105 | setgcrefp(J->trace[T->traceno], T); | ||
106 | lj_gc_barriertrace(J2G(J), T->traceno); | ||
107 | lj_gdbjit_addtrace(J, T); | ||
105 | } | 108 | } |
106 | 109 | ||
107 | void LJ_FASTCALL lj_trace_free(global_State *g, GCtrace *T) | 110 | void LJ_FASTCALL lj_trace_free(global_State *g, GCtrace *T) |
@@ -225,7 +228,7 @@ int lj_trace_flushall(lua_State *L) | |||
225 | setgcrefnull(J->trace[i]); | 228 | setgcrefnull(J->trace[i]); |
226 | } | 229 | } |
227 | } | 230 | } |
228 | J->curtrace = 0; | 231 | J->cur.traceno = 0; |
229 | J->freetrace = 0; | 232 | J->freetrace = 0; |
230 | /* Free the whole machine code and invalidate all exit stub groups. */ | 233 | /* Free the whole machine code and invalidate all exit stub groups. */ |
231 | lj_mcode_free(J); | 234 | lj_mcode_free(J); |
@@ -254,13 +257,11 @@ void lj_trace_initstate(global_State *g) | |||
254 | void lj_trace_freestate(global_State *g) | 257 | void lj_trace_freestate(global_State *g) |
255 | { | 258 | { |
256 | jit_State *J = G2J(g); | 259 | jit_State *J = G2J(g); |
257 | if (J->curtrace) | ||
258 | lj_gdbjit_deltrace(J, &J->cur); | ||
259 | #ifdef LUA_USE_ASSERT | 260 | #ifdef LUA_USE_ASSERT |
260 | { /* This assumes all traces have already been freed. */ | 261 | { /* This assumes all traces have already been freed. */ |
261 | ptrdiff_t i; | 262 | ptrdiff_t i; |
262 | for (i = 1; i < (ptrdiff_t)J->sizetrace; i++) | 263 | for (i = 1; i < (ptrdiff_t)J->sizetrace; i++) |
263 | lua_assert(i == (ptrdiff_t)J->curtrace || traceref(J, i) == NULL); | 264 | lua_assert(i == (ptrdiff_t)J->cur.traceno || traceref(J, i) == NULL); |
264 | } | 265 | } |
265 | #endif | 266 | #endif |
266 | lj_mcode_free(J); | 267 | lj_mcode_free(J); |
@@ -311,13 +312,7 @@ setpenalty: | |||
311 | static void trace_start(jit_State *J) | 312 | static void trace_start(jit_State *J) |
312 | { | 313 | { |
313 | lua_State *L; | 314 | lua_State *L; |
314 | 315 | TraceNo traceno; | |
315 | if (J->curtrace != 0 && traceref(J, J->curtrace) == &J->cur) { | ||
316 | TraceNo tr = J->curtrace; /* Save current trace. */ | ||
317 | setgcrefp(J->trace[tr], trace_save(J, &J->cur)); | ||
318 | J->curtrace = 0; | ||
319 | lj_gc_barriertrace(J2G(J), tr); | ||
320 | } | ||
321 | 316 | ||
322 | if ((J->pt->flags & PROTO_NO_JIT)) { /* JIT disabled for this proto? */ | 317 | if ((J->pt->flags & PROTO_NO_JIT)) { /* JIT disabled for this proto? */ |
323 | if (J->parent == 0) { | 318 | if (J->parent == 0) { |
@@ -332,18 +327,18 @@ static void trace_start(jit_State *J) | |||
332 | } | 327 | } |
333 | 328 | ||
334 | /* Get a new trace number. */ | 329 | /* Get a new trace number. */ |
335 | J->curtrace = trace_findfree(J); | 330 | traceno = trace_findfree(J); |
336 | if (LJ_UNLIKELY(J->curtrace == 0)) { /* No free trace? */ | 331 | if (LJ_UNLIKELY(traceno == 0)) { /* No free trace? */ |
337 | lua_assert((J2G(J)->hookmask & HOOK_GC) == 0); | 332 | lua_assert((J2G(J)->hookmask & HOOK_GC) == 0); |
338 | lj_trace_flushall(J->L); | 333 | lj_trace_flushall(J->L); |
339 | J->state = LJ_TRACE_IDLE; /* Silently ignored. */ | 334 | J->state = LJ_TRACE_IDLE; /* Silently ignored. */ |
340 | return; | 335 | return; |
341 | } | 336 | } |
342 | setgcrefp(J->trace[J->curtrace], &J->cur); | 337 | setgcrefp(J->trace[traceno], &J->cur); |
343 | 338 | ||
344 | /* Setup enough of the current trace to be able to send the vmevent. */ | 339 | /* Setup enough of the current trace to be able to send the vmevent. */ |
345 | memset(&J->cur, 0, sizeof(GCtrace)); | 340 | memset(&J->cur, 0, sizeof(GCtrace)); |
346 | J->cur.traceno = J->curtrace; | 341 | J->cur.traceno = traceno; |
347 | J->cur.nins = J->cur.nk = REF_BASE; | 342 | J->cur.nins = J->cur.nk = REF_BASE; |
348 | J->cur.ir = J->irbuf; | 343 | J->cur.ir = J->irbuf; |
349 | J->cur.snap = J->snapbuf; | 344 | J->cur.snap = J->snapbuf; |
@@ -356,7 +351,7 @@ static void trace_start(jit_State *J) | |||
356 | L = J->L; | 351 | L = J->L; |
357 | lj_vmevent_send(L, TRACE, | 352 | lj_vmevent_send(L, TRACE, |
358 | setstrV(L, L->top++, lj_str_newlit(L, "start")); | 353 | setstrV(L, L->top++, lj_str_newlit(L, "start")); |
359 | setintV(L->top++, J->curtrace); | 354 | setintV(L->top++, traceno); |
360 | setfuncV(L, L->top++, J->fn); | 355 | setfuncV(L, L->top++, J->fn); |
361 | setintV(L->top++, proto_bcpos(J->pt, J->pc)); | 356 | setintV(L->top++, proto_bcpos(J->pt, J->pc)); |
362 | if (J->parent) { | 357 | if (J->parent) { |
@@ -373,6 +368,7 @@ static void trace_stop(jit_State *J) | |||
373 | BCIns *pc = (BCIns *)J->startpc; /* Not const here. */ | 368 | BCIns *pc = (BCIns *)J->startpc; /* Not const here. */ |
374 | BCOp op = bc_op(J->cur.startins); | 369 | BCOp op = bc_op(J->cur.startins); |
375 | GCproto *pt = &gcref(J->cur.startpt)->pt; | 370 | GCproto *pt = &gcref(J->cur.startpt)->pt; |
371 | TraceNo traceno = J->cur.traceno; | ||
376 | lua_State *L; | 372 | lua_State *L; |
377 | 373 | ||
378 | switch (op) { | 374 | switch (op) { |
@@ -384,16 +380,16 @@ static void trace_stop(jit_State *J) | |||
384 | case BC_FUNCF: | 380 | case BC_FUNCF: |
385 | /* Patch bytecode of starting instruction in root trace. */ | 381 | /* Patch bytecode of starting instruction in root trace. */ |
386 | setbc_op(pc, (int)op+(int)BC_JLOOP-(int)BC_LOOP); | 382 | setbc_op(pc, (int)op+(int)BC_JLOOP-(int)BC_LOOP); |
387 | setbc_d(pc, J->curtrace); | 383 | setbc_d(pc, traceno); |
388 | addroot: | 384 | addroot: |
389 | /* Add to root trace chain in prototype. */ | 385 | /* Add to root trace chain in prototype. */ |
390 | J->cur.nextroot = pt->trace; | 386 | J->cur.nextroot = pt->trace; |
391 | pt->trace = (TraceNo1)J->curtrace; | 387 | pt->trace = (TraceNo1)traceno; |
392 | break; | 388 | break; |
393 | case BC_RET: | 389 | case BC_RET: |
394 | case BC_RET0: | 390 | case BC_RET0: |
395 | case BC_RET1: | 391 | case BC_RET1: |
396 | *pc = BCINS_AD(BC_JLOOP, J->cur.snap[0].nslots, J->curtrace); | 392 | *pc = BCINS_AD(BC_JLOOP, J->cur.snap[0].nslots, traceno); |
397 | goto addroot; | 393 | goto addroot; |
398 | case BC_JMP: | 394 | case BC_JMP: |
399 | /* Patch exit branch in parent to side trace entry. */ | 395 | /* Patch exit branch in parent to side trace entry. */ |
@@ -406,7 +402,7 @@ static void trace_stop(jit_State *J) | |||
406 | GCtrace *root = traceref(J, J->cur.root); | 402 | GCtrace *root = traceref(J, J->cur.root); |
407 | root->nchild++; | 403 | root->nchild++; |
408 | J->cur.nextside = root->nextside; | 404 | J->cur.nextside = root->nextside; |
409 | root->nextside = (TraceNo1)J->curtrace; | 405 | root->nextside = (TraceNo1)traceno; |
410 | } | 406 | } |
411 | break; | 407 | break; |
412 | default: | 408 | default: |
@@ -416,12 +412,12 @@ static void trace_stop(jit_State *J) | |||
416 | 412 | ||
417 | /* Commit new mcode only after all patching is done. */ | 413 | /* Commit new mcode only after all patching is done. */ |
418 | lj_mcode_commit(J, J->cur.mcode); | 414 | lj_mcode_commit(J, J->cur.mcode); |
419 | lj_gdbjit_addtrace(J, &J->cur, J->curtrace); | 415 | trace_save(J); |
420 | 416 | ||
421 | L = J->L; | 417 | L = J->L; |
422 | lj_vmevent_send(L, TRACE, | 418 | lj_vmevent_send(L, TRACE, |
423 | setstrV(L, L->top++, lj_str_newlit(L, "stop")); | 419 | setstrV(L, L->top++, lj_str_newlit(L, "stop")); |
424 | setintV(L->top++, J->curtrace); | 420 | setintV(L->top++, traceno); |
425 | ); | 421 | ); |
426 | } | 422 | } |
427 | 423 | ||
@@ -445,6 +441,8 @@ static int trace_abort(jit_State *J) | |||
445 | { | 441 | { |
446 | lua_State *L = J->L; | 442 | lua_State *L = J->L; |
447 | TraceError e = LJ_TRERR_RECERR; | 443 | TraceError e = LJ_TRERR_RECERR; |
444 | TraceNo traceno; | ||
445 | |||
448 | lj_mcode_abort(J); | 446 | lj_mcode_abort(J); |
449 | if (tvisnum(L->top-1)) | 447 | if (tvisnum(L->top-1)) |
450 | e = (TraceError)lj_num2int(numV(L->top-1)); | 448 | e = (TraceError)lj_num2int(numV(L->top-1)); |
@@ -455,14 +453,18 @@ static int trace_abort(jit_State *J) | |||
455 | /* Penalize or blacklist starting bytecode instruction. */ | 453 | /* Penalize or blacklist starting bytecode instruction. */ |
456 | if (J->parent == 0 && !bc_isret(bc_op(J->cur.startins))) | 454 | if (J->parent == 0 && !bc_isret(bc_op(J->cur.startins))) |
457 | penalty_pc(J, &gcref(J->cur.startpt)->pt, (BCIns *)J->startpc, e); | 455 | penalty_pc(J, &gcref(J->cur.startpt)->pt, (BCIns *)J->startpc, e); |
458 | if (J->curtrace) { /* Is there anything to abort? */ | 456 | |
457 | /* Is there anything to abort? */ | ||
458 | traceno = J->cur.traceno; | ||
459 | if (traceno) { | ||
459 | ptrdiff_t errobj = savestack(L, L->top-1); /* Stack may be resized. */ | 460 | ptrdiff_t errobj = savestack(L, L->top-1); /* Stack may be resized. */ |
461 | J->cur.link = 0; | ||
460 | lj_vmevent_send(L, TRACE, | 462 | lj_vmevent_send(L, TRACE, |
461 | TValue *frame; | 463 | TValue *frame; |
462 | const BCIns *pc; | 464 | const BCIns *pc; |
463 | GCfunc *fn; | 465 | GCfunc *fn; |
464 | setstrV(L, L->top++, lj_str_newlit(L, "abort")); | 466 | setstrV(L, L->top++, lj_str_newlit(L, "abort")); |
465 | setintV(L->top++, J->curtrace); | 467 | setintV(L->top++, traceno); |
466 | /* Find original Lua function call to generate a better error message. */ | 468 | /* Find original Lua function call to generate a better error message. */ |
467 | frame = J->L->base-1; | 469 | frame = J->L->base-1; |
468 | pc = J->pc; | 470 | pc = J->pc; |
@@ -477,10 +479,10 @@ static int trace_abort(jit_State *J) | |||
477 | copyTV(L, L->top++, &J->errinfo); | 479 | copyTV(L, L->top++, &J->errinfo); |
478 | ); | 480 | ); |
479 | /* Drop aborted trace after the vmevent (which may still access it). */ | 481 | /* Drop aborted trace after the vmevent (which may still access it). */ |
480 | setgcrefnull(J->trace[J->curtrace]); | 482 | setgcrefnull(J->trace[traceno]); |
481 | if (J->curtrace < J->freetrace) | 483 | if (traceno < J->freetrace) |
482 | J->freetrace = J->curtrace; | 484 | J->freetrace = traceno; |
483 | J->curtrace = 0; | 485 | J->cur.traceno = 0; |
484 | } | 486 | } |
485 | L->top--; /* Remove error object */ | 487 | L->top--; /* Remove error object */ |
486 | if (e == LJ_TRERR_DOWNREC) | 488 | if (e == LJ_TRERR_DOWNREC) |
@@ -517,7 +519,7 @@ static TValue *trace_state(lua_State *L, lua_CFunction dummy, void *ud) | |||
517 | trace_pendpatch(J, 0); | 519 | trace_pendpatch(J, 0); |
518 | setvmstate(J2G(J), RECORD); | 520 | setvmstate(J2G(J), RECORD); |
519 | lj_vmevent_send(L, RECORD, | 521 | lj_vmevent_send(L, RECORD, |
520 | setintV(L->top++, J->curtrace); | 522 | setintV(L->top++, J->cur.traceno); |
521 | setfuncV(L, L->top++, J->fn); | 523 | setfuncV(L, L->top++, J->fn); |
522 | setintV(L->top++, J->pt ? (int32_t)proto_bcpos(J->pt, J->pc) : -1); | 524 | setintV(L->top++, J->pt ? (int32_t)proto_bcpos(J->pt, J->pc) : -1); |
523 | setintV(L->top++, J->framedepth); | 525 | setintV(L->top++, J->framedepth); |
@@ -529,10 +531,11 @@ static TValue *trace_state(lua_State *L, lua_CFunction dummy, void *ud) | |||
529 | trace_pendpatch(J, 1); | 531 | trace_pendpatch(J, 1); |
530 | J->loopref = 0; | 532 | J->loopref = 0; |
531 | if ((J->flags & JIT_F_OPT_LOOP) && | 533 | if ((J->flags & JIT_F_OPT_LOOP) && |
532 | J->cur.link == J->curtrace && J->framedepth + J->retdepth == 0) { | 534 | J->cur.link == J->cur.traceno && J->framedepth + J->retdepth == 0) { |
533 | setvmstate(J2G(J), OPT); | 535 | setvmstate(J2G(J), OPT); |
534 | lj_opt_dce(J); | 536 | lj_opt_dce(J); |
535 | if (lj_opt_loop(J)) { /* Loop optimization failed? */ | 537 | if (lj_opt_loop(J)) { /* Loop optimization failed? */ |
538 | J->cur.link = 0; | ||
536 | J->loopref = J->cur.nins; | 539 | J->loopref = J->cur.nins; |
537 | J->state = LJ_TRACE_RECORD; /* Try to continue recording. */ | 540 | J->state = LJ_TRACE_RECORD; /* Try to continue recording. */ |
538 | break; | 541 | break; |