aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2010-04-25 03:32:29 +0200
committerMike Pall <mike>2010-04-25 03:32:29 +0200
commit721b73fecbbeda5b5cb76628511c5b3fac41eb4d (patch)
treece72efaa313ab16eda652e4d277413c31a8d2af3 /src
parent3a32bbc7cb5c2287e8d4e24e362281c165f50976 (diff)
downloadluajit-721b73fecbbeda5b5cb76628511c5b3fac41eb4d.tar.gz
luajit-721b73fecbbeda5b5cb76628511c5b3fac41eb4d.tar.bz2
luajit-721b73fecbbeda5b5cb76628511c5b3fac41eb4d.zip
Turn traces into true GC objects (GCtrace).
Diffstat (limited to 'src')
-rw-r--r--src/buildvm_x64.h4
-rw-r--r--src/buildvm_x64win.h4
-rw-r--r--src/buildvm_x86.dasc6
-rw-r--r--src/buildvm_x86.h2
-rw-r--r--src/lib_base.c2
-rw-r--r--src/lib_jit.c19
-rw-r--r--src/lj_asm.c16
-rw-r--r--src/lj_asm.h4
-rw-r--r--src/lj_dispatch.c3
-rw-r--r--src/lj_func.c1
-rw-r--r--src/lj_gc.c68
-rw-r--r--src/lj_gc.h2
-rw-r--r--src/lj_gdbjit.c9
-rw-r--r--src/lj_gdbjit.h4
-rw-r--r--src/lj_ir.h2
-rw-r--r--src/lj_jit.h36
-rw-r--r--src/lj_obj.c2
-rw-r--r--src/lj_obj.h2
-rw-r--r--src/lj_record.c13
-rw-r--r--src/lj_snap.c8
-rw-r--r--src/lj_snap.h2
-rw-r--r--src/lj_trace.c167
-rw-r--r--src/lj_trace.h5
23 files changed, 186 insertions, 195 deletions
diff --git a/src/buildvm_x64.h b/src/buildvm_x64.h
index 6a15006b..b3466037 100644
--- a/src/buildvm_x64.h
+++ b/src/buildvm_x64.h
@@ -674,7 +674,7 @@ static const unsigned char build_actionlist[14075] = {
674 255,248,3,102,15,46,193,252,233,244,1,255,141,12,202,139,105,4,129,252,253, 674 255,248,3,102,15,46,193,252,233,244,1,255,141,12,202,139,105,4,129,252,253,
675 239,15,132,244,247,255,137,105,252,252,139,41,137,105,252,248,252,233,245, 675 239,15,132,244,247,255,137,105,252,252,139,41,137,105,252,248,252,233,245,
676 255,141,156,253,131,233,139,1,137,105,252,252,137,65,252,248,255,65,139,142, 676 255,141,156,253,131,233,139,1,137,105,252,252,137,65,252,248,255,65,139,142,
677 233,139,4,193,72,139,128,233,139,108,36,24,65,137,150,233,65,137,174,233, 677 233,139,4,129,72,139,128,233,139,108,36,24,65,137,150,233,65,137,174,233,
678 76,137,36,36,76,137,108,36,8,72,131,252,236,16,252,255,224,255,141,156,253, 678 76,137,36,36,76,137,108,36,8,72,131,252,236,16,252,255,224,255,141,156,253,
679 131,233,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252, 679 131,233,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,
680 238,255,137,221,209,252,237,129,229,239,102,65,131,172,253,46,233,1,15,132, 680 238,255,137,221,209,252,237,129,229,239,102,65,131,172,253,46,233,1,15,132,
@@ -1048,7 +1048,7 @@ static const char *const extnames[] = {
1048#define DtA(_V) (int)(ptrdiff_t)&(((GCupval *)0)_V) 1048#define DtA(_V) (int)(ptrdiff_t)&(((GCupval *)0)_V)
1049#define DtB(_V) (int)(ptrdiff_t)&(((Node *)0)_V) 1049#define DtB(_V) (int)(ptrdiff_t)&(((Node *)0)_V)
1050#define DtC(_V) (int)(ptrdiff_t)&(((int *)0)_V) 1050#define DtC(_V) (int)(ptrdiff_t)&(((int *)0)_V)
1051#define DtD(_V) (int)(ptrdiff_t)&(((Trace *)0)_V) 1051#define DtD(_V) (int)(ptrdiff_t)&(((GCtrace *)0)_V)
1052#define DtE(_V) (int)(ptrdiff_t)&(((ExitInfo *)0)_V) 1052#define DtE(_V) (int)(ptrdiff_t)&(((ExitInfo *)0)_V)
1053#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) 1053#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field))
1054#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) 1054#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field))
diff --git a/src/buildvm_x64win.h b/src/buildvm_x64win.h
index e1b243f4..69a8b27e 100644
--- a/src/buildvm_x64win.h
+++ b/src/buildvm_x64win.h
@@ -671,7 +671,7 @@ static const unsigned char build_actionlist[14023] = {
671 180,253,134,233,255,248,3,102,15,46,193,252,233,244,1,255,141,12,202,139, 671 180,253,134,233,255,248,3,102,15,46,193,252,233,244,1,255,141,12,202,139,
672 105,4,129,252,253,239,15,132,244,247,255,137,105,252,252,139,41,137,105,252, 672 105,4,129,252,253,239,15,132,244,247,255,137,105,252,252,139,41,137,105,252,
673 248,252,233,245,255,141,180,253,134,233,139,1,137,105,252,252,137,65,252, 673 248,252,233,245,255,141,180,253,134,233,139,1,137,105,252,252,137,65,252,
674 248,255,139,139,233,139,4,193,72,139,128,233,139,108,36,96,137,147,233,137, 674 248,255,139,139,233,139,4,129,72,139,128,233,139,108,36,96,137,147,233,137,
675 171,233,76,137,100,36,80,76,137,108,36,32,76,137,116,36,24,76,137,124,36, 675 171,233,76,137,100,36,80,76,137,108,36,32,76,137,116,36,24,76,137,124,36,
676 16,72,137,225,72,129,252,236,239,102,15,127,49,102,15,127,185,233,102,68, 676 16,72,137,225,72,129,252,236,239,102,15,127,49,102,15,127,185,233,102,68,
677 15,127,129,233,102,68,15,127,137,233,102,68,15,127,145,233,102,68,15,127, 677 15,127,129,233,102,68,15,127,137,233,102,68,15,127,145,233,102,68,15,127,
@@ -1048,7 +1048,7 @@ static const char *const extnames[] = {
1048#define DtA(_V) (int)(ptrdiff_t)&(((GCupval *)0)_V) 1048#define DtA(_V) (int)(ptrdiff_t)&(((GCupval *)0)_V)
1049#define DtB(_V) (int)(ptrdiff_t)&(((Node *)0)_V) 1049#define DtB(_V) (int)(ptrdiff_t)&(((Node *)0)_V)
1050#define DtC(_V) (int)(ptrdiff_t)&(((int *)0)_V) 1050#define DtC(_V) (int)(ptrdiff_t)&(((int *)0)_V)
1051#define DtD(_V) (int)(ptrdiff_t)&(((Trace *)0)_V) 1051#define DtD(_V) (int)(ptrdiff_t)&(((GCtrace *)0)_V)
1052#define DtE(_V) (int)(ptrdiff_t)&(((ExitInfo *)0)_V) 1052#define DtE(_V) (int)(ptrdiff_t)&(((ExitInfo *)0)_V)
1053#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) 1053#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field))
1054#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) 1054#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field))
diff --git a/src/buildvm_x86.dasc b/src/buildvm_x86.dasc
index 0fcfc1a9..942889ed 100644
--- a/src/buildvm_x86.dasc
+++ b/src/buildvm_x86.dasc
@@ -107,7 +107,7 @@
107|.type UPVAL, GCupval 107|.type UPVAL, GCupval
108|.type NODE, Node 108|.type NODE, Node
109|.type NARGS, int 109|.type NARGS, int
110|.type TRACE, Trace 110|.type TRACE, GCtrace
111|.type EXITINFO, ExitInfo 111|.type EXITINFO, ExitInfo
112| 112|
113|// Stack layout while in interpreter. Must match with lj_frame.h. 113|// Stack layout while in interpreter. Must match with lj_frame.h.
@@ -4746,11 +4746,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse)
4746#if LJ_HASJIT 4746#if LJ_HASJIT
4747 | ins_AD // RA = base (ignored), RD = traceno 4747 | ins_AD // RA = base (ignored), RD = traceno
4748 | mov RA, [DISPATCH+DISPATCH_J(trace)] 4748 | mov RA, [DISPATCH+DISPATCH_J(trace)]
4749 |.if X64
4750 | mov TRACE:RD, [RA+RD*8]
4751 |.else
4752 | mov TRACE:RD, [RA+RD*4] 4749 | mov TRACE:RD, [RA+RD*4]
4753 |.endif
4754 | mov RDa, TRACE:RD->mcode 4750 | mov RDa, TRACE:RD->mcode
4755 | mov L:RB, SAVE_L 4751 | mov L:RB, SAVE_L
4756 | mov [DISPATCH+DISPATCH_GL(jit_base)], BASE 4752 | mov [DISPATCH+DISPATCH_GL(jit_base)], BASE
diff --git a/src/buildvm_x86.h b/src/buildvm_x86.h
index d1a08ef8..84dd2802 100644
--- a/src/buildvm_x86.h
+++ b/src/buildvm_x86.h
@@ -1102,7 +1102,7 @@ static const char *const extnames[] = {
1102#define DtA(_V) (int)(ptrdiff_t)&(((GCupval *)0)_V) 1102#define DtA(_V) (int)(ptrdiff_t)&(((GCupval *)0)_V)
1103#define DtB(_V) (int)(ptrdiff_t)&(((Node *)0)_V) 1103#define DtB(_V) (int)(ptrdiff_t)&(((Node *)0)_V)
1104#define DtC(_V) (int)(ptrdiff_t)&(((int *)0)_V) 1104#define DtC(_V) (int)(ptrdiff_t)&(((int *)0)_V)
1105#define DtD(_V) (int)(ptrdiff_t)&(((Trace *)0)_V) 1105#define DtD(_V) (int)(ptrdiff_t)&(((GCtrace *)0)_V)
1106#define DtE(_V) (int)(ptrdiff_t)&(((ExitInfo *)0)_V) 1106#define DtE(_V) (int)(ptrdiff_t)&(((ExitInfo *)0)_V)
1107#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) 1107#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field))
1108#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) 1108#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field))
diff --git a/src/lib_base.c b/src/lib_base.c
index cbfd818a..1fa26d0a 100644
--- a/src/lib_base.c
+++ b/src/lib_base.c
@@ -54,7 +54,7 @@ LJLIB_PUSH("upval")
54LJLIB_PUSH("thread") 54LJLIB_PUSH("thread")
55LJLIB_PUSH("proto") 55LJLIB_PUSH("proto")
56LJLIB_PUSH("function") 56LJLIB_PUSH("function")
57LJLIB_PUSH("") /* Unused. */ 57LJLIB_PUSH("trace")
58LJLIB_PUSH("table") 58LJLIB_PUSH("table")
59LJLIB_PUSH(top-8) /* userdata */ 59LJLIB_PUSH(top-8) /* userdata */
60LJLIB_PUSH("number") 60LJLIB_PUSH("number")
diff --git a/src/lib_jit.c b/src/lib_jit.c
index e64ea9e4..5facf62e 100644
--- a/src/lib_jit.c
+++ b/src/lib_jit.c
@@ -72,9 +72,8 @@ LJLIB_CF(jit_flush)
72#if LJ_HASJIT 72#if LJ_HASJIT
73 if (L->base < L->top && (tvisnum(L->base) || tvisstr(L->base))) { 73 if (L->base < L->top && (tvisnum(L->base) || tvisstr(L->base))) {
74 int traceno = lj_lib_checkint(L, 1); 74 int traceno = lj_lib_checkint(L, 1);
75 setboolV(L->top-1, 75 luaJIT_setmode(L, traceno, LUAJIT_MODE_FLUSH|LUAJIT_MODE_TRACE);
76 luaJIT_setmode(L, traceno, LUAJIT_MODE_FLUSH|LUAJIT_MODE_TRACE)); 76 return 0;
77 return 1;
78 } 77 }
79#endif 78#endif
80 return setjitmode(L, LUAJIT_MODE_FLUSH); 79 return setjitmode(L, LUAJIT_MODE_FLUSH);
@@ -260,19 +259,19 @@ LJLIB_CF(jit_util_funcuvname)
260#if LJ_HASJIT 259#if LJ_HASJIT
261 260
262/* Check trace argument. Must not throw for non-existent trace numbers. */ 261/* Check trace argument. Must not throw for non-existent trace numbers. */
263static Trace *jit_checktrace(lua_State *L) 262static GCtrace *jit_checktrace(lua_State *L)
264{ 263{
265 TraceNo tr = (TraceNo)lj_lib_checkint(L, 1); 264 TraceNo tr = (TraceNo)lj_lib_checkint(L, 1);
266 jit_State *J = L2J(L); 265 jit_State *J = L2J(L);
267 if (tr > 0 && tr < J->sizetrace) 266 if (tr > 0 && tr < J->sizetrace)
268 return J->trace[tr]; 267 return traceref(J, tr);
269 return NULL; 268 return NULL;
270} 269}
271 270
272/* local info = jit.util.traceinfo(tr) */ 271/* local info = jit.util.traceinfo(tr) */
273LJLIB_CF(jit_util_traceinfo) 272LJLIB_CF(jit_util_traceinfo)
274{ 273{
275 Trace *T = jit_checktrace(L); 274 GCtrace *T = jit_checktrace(L);
276 if (T) { 275 if (T) {
277 GCtab *t; 276 GCtab *t;
278 lua_createtable(L, 0, 4); /* Increment hash size if fields are added. */ 277 lua_createtable(L, 0, 4); /* Increment hash size if fields are added. */
@@ -290,7 +289,7 @@ LJLIB_CF(jit_util_traceinfo)
290/* local m, ot, op1, op2, prev = jit.util.traceir(tr, idx) */ 289/* local m, ot, op1, op2, prev = jit.util.traceir(tr, idx) */
291LJLIB_CF(jit_util_traceir) 290LJLIB_CF(jit_util_traceir)
292{ 291{
293 Trace *T = jit_checktrace(L); 292 GCtrace *T = jit_checktrace(L);
294 IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS; 293 IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS;
295 if (T && ref >= REF_BIAS && ref < T->nins) { 294 if (T && ref >= REF_BIAS && ref < T->nins) {
296 IRIns *ir = &T->ir[ref]; 295 IRIns *ir = &T->ir[ref];
@@ -308,7 +307,7 @@ LJLIB_CF(jit_util_traceir)
308/* local k, t [, slot] = jit.util.tracek(tr, idx) */ 307/* local k, t [, slot] = jit.util.tracek(tr, idx) */
309LJLIB_CF(jit_util_tracek) 308LJLIB_CF(jit_util_tracek)
310{ 309{
311 Trace *T = jit_checktrace(L); 310 GCtrace *T = jit_checktrace(L);
312 IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS; 311 IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS;
313 if (T && ref >= T->nk && ref < REF_BIAS) { 312 if (T && ref >= T->nk && ref < REF_BIAS) {
314 IRIns *ir = &T->ir[ref]; 313 IRIns *ir = &T->ir[ref];
@@ -330,7 +329,7 @@ LJLIB_CF(jit_util_tracek)
330/* local snap = jit.util.tracesnap(tr, sn) */ 329/* local snap = jit.util.tracesnap(tr, sn) */
331LJLIB_CF(jit_util_tracesnap) 330LJLIB_CF(jit_util_tracesnap)
332{ 331{
333 Trace *T = jit_checktrace(L); 332 GCtrace *T = jit_checktrace(L);
334 SnapNo sn = (SnapNo)lj_lib_checkint(L, 2); 333 SnapNo sn = (SnapNo)lj_lib_checkint(L, 2);
335 if (T && sn < T->nsnap) { 334 if (T && sn < T->nsnap) {
336 SnapShot *snap = &T->snap[sn]; 335 SnapShot *snap = &T->snap[sn];
@@ -352,7 +351,7 @@ LJLIB_CF(jit_util_tracesnap)
352/* local mcode, addr, loop = jit.util.tracemc(tr) */ 351/* local mcode, addr, loop = jit.util.tracemc(tr) */
353LJLIB_CF(jit_util_tracemc) 352LJLIB_CF(jit_util_tracemc)
354{ 353{
355 Trace *T = jit_checktrace(L); 354 GCtrace *T = jit_checktrace(L);
356 if (T && T->mcode != NULL) { 355 if (T && T->mcode != NULL) {
357 setstrV(L, L->top-1, lj_str_new(L, (const char *)T->mcode, T->szmcode)); 356 setstrV(L, L->top-1, lj_str_new(L, (const char *)T->mcode, T->szmcode));
358 setnumV(L->top++, cast_num((intptr_t)T->mcode)); 357 setnumV(L->top++, cast_num((intptr_t)T->mcode));
diff --git a/src/lj_asm.c b/src/lj_asm.c
index b57cf118..5c564748 100644
--- a/src/lj_asm.c
+++ b/src/lj_asm.c
@@ -67,8 +67,8 @@ typedef struct ASMState {
67 BCReg topslot; /* Number of slots for stack check (unless 0). */ 67 BCReg topslot; /* Number of slots for stack check (unless 0). */
68 MSize gcsteps; /* Accumulated number of GC steps (per section). */ 68 MSize gcsteps; /* Accumulated number of GC steps (per section). */
69 69
70 Trace *T; /* Trace to assemble. */ 70 GCtrace *T; /* Trace to assemble. */
71 Trace *parent; /* Parent trace (or NULL). */ 71 GCtrace *parent; /* Parent trace (or NULL). */
72 72
73 MCode *mcbot; /* Bottom of reserved MCode. */ 73 MCode *mcbot; /* Bottom of reserved MCode. */
74 MCode *mctop; /* Top of generated MCode. */ 74 MCode *mctop; /* Top of generated MCode. */
@@ -3228,7 +3228,7 @@ static void asm_tail_link(ASMState *as)
3228 const BCIns *pc = snap_pc(as->T->snapmap[snap->mapofs + snap->nent]); 3228 const BCIns *pc = snap_pc(as->T->snapmap[snap->mapofs + snap->nent]);
3229 int32_t mres; 3229 int32_t mres;
3230 if (bc_op(*pc) == BC_JLOOP) { /* NYI: find a better way to do this. */ 3230 if (bc_op(*pc) == BC_JLOOP) { /* NYI: find a better way to do this. */
3231 BCIns *retpc = &as->J->trace[bc_d(*pc)]->startins; 3231 BCIns *retpc = &traceref(as->J, bc_d(*pc))->startins;
3232 if (bc_isret(bc_op(*retpc))) 3232 if (bc_isret(bc_op(*retpc)))
3233 pc = retpc; 3233 pc = retpc;
3234 } 3234 }
@@ -3294,7 +3294,7 @@ static void asm_tail_fixup(ASMState *as, TraceNo lnk)
3294 } 3294 }
3295 /* Patch exit branch. */ 3295 /* Patch exit branch. */
3296 target = lnk == TRACE_INTERP ? (MCode *)lj_vm_exit_interp : 3296 target = lnk == TRACE_INTERP ? (MCode *)lj_vm_exit_interp :
3297 as->J->trace[lnk]->mcode; 3297 traceref(as->J, lnk)->mcode;
3298 *(int32_t *)(p-4) = jmprel(p, target); 3298 *(int32_t *)(p-4) = jmprel(p, target);
3299 p[-5] = XI_JMP; 3299 p[-5] = XI_JMP;
3300 /* Drop unused mcode tail. Fill with NOPs to make the prefetcher happy. */ 3300 /* Drop unused mcode tail. Fill with NOPs to make the prefetcher happy. */
@@ -3437,7 +3437,7 @@ static void asm_trace(ASMState *as)
3437/* -- Trace setup --------------------------------------------------------- */ 3437/* -- Trace setup --------------------------------------------------------- */
3438 3438
3439/* Clear reg/sp for all instructions and add register hints. */ 3439/* Clear reg/sp for all instructions and add register hints. */
3440static void asm_setup_regsp(ASMState *as, Trace *T) 3440static void asm_setup_regsp(ASMState *as, GCtrace *T)
3441{ 3441{
3442 IRRef i, nins; 3442 IRRef i, nins;
3443 int inloop; 3443 int inloop;
@@ -3577,7 +3577,7 @@ static void asm_setup_regsp(ASMState *as, Trace *T)
3577#endif 3577#endif
3578 3578
3579/* Assemble a trace. */ 3579/* Assemble a trace. */
3580void lj_asm_trace(jit_State *J, Trace *T) 3580void lj_asm_trace(jit_State *J, GCtrace *T)
3581{ 3581{
3582 ASMState as_; 3582 ASMState as_;
3583 ASMState *as = &as_; 3583 ASMState *as = &as_;
@@ -3591,7 +3591,7 @@ void lj_asm_trace(jit_State *J, Trace *T)
3591 as->realign = NULL; 3591 as->realign = NULL;
3592 as->loopinv = 0; 3592 as->loopinv = 0;
3593 if (J->parent) { 3593 if (J->parent) {
3594 as->parent = J->trace[J->parent]; 3594 as->parent = traceref(J, J->parent);
3595 lj_snap_regspmap(as->parentmap, as->parent, J->exitno); 3595 lj_snap_regspmap(as->parentmap, as->parent, J->exitno);
3596 } else { 3596 } else {
3597 as->parent = NULL; 3597 as->parent = NULL;
@@ -3667,7 +3667,7 @@ void lj_asm_trace(jit_State *J, Trace *T)
3667} 3667}
3668 3668
3669/* Patch exit jumps of existing machine code to a new target. */ 3669/* Patch exit jumps of existing machine code to a new target. */
3670void lj_asm_patchexit(jit_State *J, Trace *T, ExitNo exitno, MCode *target) 3670void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
3671{ 3671{
3672 MCode *p = T->mcode; 3672 MCode *p = T->mcode;
3673 MCode *mcarea = lj_mcode_patch(J, p, 0); 3673 MCode *mcarea = lj_mcode_patch(J, p, 0);
diff --git a/src/lj_asm.h b/src/lj_asm.h
index 7502c49c..9df6dd5d 100644
--- a/src/lj_asm.h
+++ b/src/lj_asm.h
@@ -9,8 +9,8 @@
9#include "lj_jit.h" 9#include "lj_jit.h"
10 10
11#if LJ_HASJIT 11#if LJ_HASJIT
12LJ_FUNC void lj_asm_trace(jit_State *J, Trace *T); 12LJ_FUNC void lj_asm_trace(jit_State *J, GCtrace *T);
13LJ_FUNC void lj_asm_patchexit(jit_State *J, Trace *T, ExitNo exitno, 13LJ_FUNC void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno,
14 MCode *target); 14 MCode *target);
15#endif 15#endif
16 16
diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c
index 30137ab2..1a483b5a 100644
--- a/src/lj_dispatch.c
+++ b/src/lj_dispatch.c
@@ -239,7 +239,8 @@ int luaJIT_setmode(lua_State *L, int idx, int mode)
239 case LUAJIT_MODE_TRACE: 239 case LUAJIT_MODE_TRACE:
240 if (!(mode & LUAJIT_MODE_FLUSH)) 240 if (!(mode & LUAJIT_MODE_FLUSH))
241 return 0; /* Failed. */ 241 return 0; /* Failed. */
242 return lj_trace_flush(G2J(g), idx); 242 lj_trace_flush(G2J(g), idx);
243 break;
243#else 244#else
244 case LUAJIT_MODE_ENGINE: 245 case LUAJIT_MODE_ENGINE:
245 case LUAJIT_MODE_FUNC: 246 case LUAJIT_MODE_FUNC:
diff --git a/src/lj_func.c b/src/lj_func.c
index 3766b25e..1f5c3240 100644
--- a/src/lj_func.c
+++ b/src/lj_func.c
@@ -19,7 +19,6 @@
19 19
20void LJ_FASTCALL lj_func_freeproto(global_State *g, GCproto *pt) 20void LJ_FASTCALL lj_func_freeproto(global_State *g, GCproto *pt)
21{ 21{
22 lj_trace_freeproto(g, pt);
23 lj_mem_free(g, pt, pt->sizept); 22 lj_mem_free(g, pt, pt->sizept);
24} 23}
25 24
diff --git a/src/lj_gc.c b/src/lj_gc.c
index b457c424..7c224759 100644
--- a/src/lj_gc.c
+++ b/src/lj_gc.c
@@ -214,8 +214,21 @@ static void gc_traverse_func(global_State *g, GCfunc *fn)
214} 214}
215 215
216#if LJ_HASJIT 216#if LJ_HASJIT
217/* Mark a trace. */
218static void gc_marktrace(global_State *g, TraceNo traceno)
219{
220 if (traceno && traceno != G2J(g)->curtrace) {
221 GCobj *o = obj2gco(traceref(G2J(g), traceno));
222 if (iswhite(o)) {
223 white2gray(o);
224 setgcrefr(o->gch.gclist, g->gc.gray);
225 setgcref(g->gc.gray, o);
226 }
227 }
228}
229
217/* Traverse a trace. */ 230/* Traverse a trace. */
218static void gc_traverse_trace(global_State *g, Trace *T) 231static void gc_traverse_trace(global_State *g, GCtrace *T)
219{ 232{
220 IRRef ref; 233 IRRef ref;
221 for (ref = T->nk; ref < REF_TRUE; ref++) { 234 for (ref = T->nk; ref < REF_TRUE; ref++) {
@@ -223,31 +236,23 @@ static void gc_traverse_trace(global_State *g, Trace *T)
223 if (ir->o == IR_KGC) 236 if (ir->o == IR_KGC)
224 gc_markobj(g, ir_kgc(ir)); 237 gc_markobj(g, ir_kgc(ir));
225 } 238 }
239 gc_marktrace(g, T->link);
240 gc_marktrace(g, T->nextroot);
241 gc_marktrace(g, T->nextside);
242 gc_markobj(g, gcref(T->startpt));
226} 243}
227 244
228/* The current trace is a GC root while not anchored in the prototype (yet). */ 245/* The current trace is a GC root while not anchored in the prototype (yet). */
229#define gc_mark_curtrace(g) \ 246#define gc_traverse_curtrace(g) \
230 { if (G2J(g)->curtrace != 0) gc_traverse_trace(g, &G2J(g)->cur); } 247 { if (G2J(g)->curtrace != 0) gc_traverse_trace(g, &G2J(g)->cur); }
231#else 248#else
232#define gc_mark_curtrace(g) UNUSED(g) 249#define gc_traverse_curtrace(g) UNUSED(g)
233#endif 250#endif
234 251
235/* Traverse a prototype. */ 252/* Traverse a prototype. */
236static void gc_traverse_proto(global_State *g, GCproto *pt) 253static void gc_traverse_proto(global_State *g, GCproto *pt)
237{ 254{
238 ptrdiff_t i; 255 ptrdiff_t i;
239#if LJ_HASJIT
240 jit_State *J = G2J(g);
241 TraceNo root, side;
242 /* Mark all root traces and attached side traces. */
243 for (root = pt->trace; root != 0; root = J->trace[root]->nextroot) {
244 for (side = J->trace[root]->nextside; side != 0;
245 side = J->trace[side]->nextside)
246 gc_traverse_trace(g, J->trace[side]);
247 gc_traverse_trace(g, J->trace[root]);
248 }
249#endif
250 /* GC during prototype creation could cause NULL fields. */
251 gc_mark_str(proto_chunkname(pt)); 256 gc_mark_str(proto_chunkname(pt));
252 for (i = -(ptrdiff_t)pt->sizekgc; i < 0; i++) /* Mark collectable consts. */ 257 for (i = -(ptrdiff_t)pt->sizekgc; i < 0; i++) /* Mark collectable consts. */
253 gc_markobj(g, proto_kgc(pt, i)); 258 gc_markobj(g, proto_kgc(pt, i));
@@ -255,6 +260,9 @@ static void gc_traverse_proto(global_State *g, GCproto *pt)
255 gc_mark_str(proto_uvname(pt, i)); 260 gc_mark_str(proto_uvname(pt, i));
256 for (i = 0; i < (ptrdiff_t)pt->sizevarinfo; i++) /* Mark names of locals. */ 261 for (i = 0; i < (ptrdiff_t)pt->sizevarinfo; i++) /* Mark names of locals. */
257 gc_mark_str(gco2str(gcref(proto_varinfo(pt)[i].name))); 262 gc_mark_str(gco2str(gcref(proto_varinfo(pt)[i].name)));
263#if LJ_HASJIT
264 gc_marktrace(g, pt->trace);
265#endif
258} 266}
259 267
260/* Traverse the frame structure of a stack. */ 268/* Traverse the frame structure of a stack. */
@@ -311,13 +319,23 @@ static size_t propagatemark(global_State *g)
311 GCproto *pt = gco2pt(o); 319 GCproto *pt = gco2pt(o);
312 gc_traverse_proto(g, pt); 320 gc_traverse_proto(g, pt);
313 return pt->sizept; 321 return pt->sizept;
314 } else { 322 } else if (LJ_LIKELY(o->gch.gct == ~LJ_TTHREAD)) {
315 lua_State *th = gco2th(o); 323 lua_State *th = gco2th(o);
316 setgcrefr(th->gclist, g->gc.grayagain); 324 setgcrefr(th->gclist, g->gc.grayagain);
317 setgcref(g->gc.grayagain, o); 325 setgcref(g->gc.grayagain, o);
318 black2gray(o); /* Threads are never black. */ 326 black2gray(o); /* Threads are never black. */
319 gc_traverse_thread(g, th); 327 gc_traverse_thread(g, th);
320 return sizeof(lua_State) + sizeof(TValue) * th->stacksize; 328 return sizeof(lua_State) + sizeof(TValue) * th->stacksize;
329 } else {
330#if LJ_HASJIT
331 GCtrace *T = gco2trace(o);
332 gc_traverse_trace(g, T);
333 return ((sizeof(GCtrace)+7)&~7) + (T->nins-T->nk)*sizeof(IRIns) +
334 T->nsnap*sizeof(SnapShot) + T->nsnapmap*sizeof(SnapEntry);
335#else
336 lua_assert(0);
337 return 0;
338#endif
321 } 339 }
322} 340}
323 341
@@ -351,7 +369,11 @@ static const GCFreeFunc gc_freefunc[] = {
351 (GCFreeFunc)lj_state_free, 369 (GCFreeFunc)lj_state_free,
352 (GCFreeFunc)lj_func_freeproto, 370 (GCFreeFunc)lj_func_freeproto,
353 (GCFreeFunc)lj_func_free, 371 (GCFreeFunc)lj_func_free,
372#if LJ_HASJIT
373 (GCFreeFunc)lj_trace_free,
374#else
354 (GCFreeFunc)0, 375 (GCFreeFunc)0,
376#endif
355 (GCFreeFunc)lj_tab_free, 377 (GCFreeFunc)lj_tab_free,
356 (GCFreeFunc)lj_udata_free 378 (GCFreeFunc)lj_udata_free
357}; 379};
@@ -502,7 +524,7 @@ static void atomic(global_State *g, lua_State *L)
502 setgcrefnull(g->gc.weak); 524 setgcrefnull(g->gc.weak);
503 lua_assert(!iswhite(obj2gco(mainthread(g)))); 525 lua_assert(!iswhite(obj2gco(mainthread(g))));
504 gc_markobj(g, L); /* Mark running thread. */ 526 gc_markobj(g, L); /* Mark running thread. */
505 gc_mark_curtrace(g); /* Mark current trace. */ 527 gc_traverse_curtrace(g); /* Traverse current trace. */
506 gc_mark_gcroot(g); /* Mark GC roots (again). */ 528 gc_mark_gcroot(g); /* Mark GC roots (again). */
507 gc_propagate_gray(g); /* Propagate all of the above. */ 529 gc_propagate_gray(g); /* Propagate all of the above. */
508 530
@@ -681,7 +703,7 @@ void lj_gc_barrierf(global_State *g, GCobj *o, GCobj *v)
681 lua_assert(g->gc.state != GCSfinalize && g->gc.state != GCSpause); 703 lua_assert(g->gc.state != GCSfinalize && g->gc.state != GCSpause);
682 lua_assert(o->gch.gct != ~LJ_TTAB); 704 lua_assert(o->gch.gct != ~LJ_TTAB);
683 /* Preserve invariant during propagation. Otherwise it doesn't matter. */ 705 /* Preserve invariant during propagation. Otherwise it doesn't matter. */
684 if (g->gc.state == GCSpropagate) 706 if (g->gc.state == GCSpropagate || g->gc.state == GCSatomic)
685 gc_mark(g, v); /* Move frontier forward. */ 707 gc_mark(g, v); /* Move frontier forward. */
686 else 708 else
687 makewhite(g, o); /* Make it white to avoid the following barrier. */ 709 makewhite(g, o); /* Make it white to avoid the following barrier. */
@@ -692,7 +714,7 @@ void LJ_FASTCALL lj_gc_barrieruv(global_State *g, TValue *tv)
692{ 714{
693#define TV2MARKED(x) \ 715#define TV2MARKED(x) \
694 (*((uint8_t *)(x) - offsetof(GCupval, tv) + offsetof(GCupval, marked))) 716 (*((uint8_t *)(x) - offsetof(GCupval, tv) + offsetof(GCupval, marked)))
695 if (g->gc.state == GCSpropagate) 717 if (g->gc.state == GCSpropagate || g->gc.state == GCSatomic)
696 gc_mark(g, gcV(tv)); 718 gc_mark(g, gcV(tv));
697 else 719 else
698 TV2MARKED(tv) = (TV2MARKED(tv) & cast_byte(~LJ_GC_COLORS)) | curwhite(g); 720 TV2MARKED(tv) = (TV2MARKED(tv) & cast_byte(~LJ_GC_COLORS)) | curwhite(g);
@@ -710,7 +732,7 @@ void lj_gc_closeuv(global_State *g, GCupval *uv)
710 setgcrefr(o->gch.nextgc, g->gc.root); 732 setgcrefr(o->gch.nextgc, g->gc.root);
711 setgcref(g->gc.root, o); 733 setgcref(g->gc.root, o);
712 if (isgray(o)) { /* A closed upvalue is never gray, so fix this. */ 734 if (isgray(o)) { /* A closed upvalue is never gray, so fix this. */
713 if (g->gc.state == GCSpropagate) { 735 if (g->gc.state == GCSpropagate || g->gc.state == GCSatomic) {
714 gray2black(o); /* Make it black and preserve invariant. */ 736 gray2black(o); /* Make it black and preserve invariant. */
715 if (tviswhite(&uv->tv)) 737 if (tviswhite(&uv->tv))
716 lj_gc_barrierf(g, o, gcV(&uv->tv)); 738 lj_gc_barrierf(g, o, gcV(&uv->tv));
@@ -723,10 +745,10 @@ void lj_gc_closeuv(global_State *g, GCupval *uv)
723 745
724#if LJ_HASJIT 746#if LJ_HASJIT
725/* Mark a trace if it's saved during the propagation phase. */ 747/* Mark a trace if it's saved during the propagation phase. */
726void lj_gc_barriertrace(global_State *g, void *T) 748void lj_gc_barriertrace(global_State *g, uint32_t traceno)
727{ 749{
728 if (g->gc.state == GCSpropagate) 750 if (g->gc.state == GCSpropagate || g->gc.state == GCSatomic)
729 gc_traverse_trace(g, (Trace *)T); 751 gc_marktrace(g, traceno);
730} 752}
731#endif 753#endif
732 754
diff --git a/src/lj_gc.h b/src/lj_gc.h
index 3d213eb3..c3b91e07 100644
--- a/src/lj_gc.h
+++ b/src/lj_gc.h
@@ -65,7 +65,7 @@ LJ_FUNC void lj_gc_barrierf(global_State *g, GCobj *o, GCobj *v);
65LJ_FUNCA void LJ_FASTCALL lj_gc_barrieruv(global_State *g, TValue *tv); 65LJ_FUNCA void LJ_FASTCALL lj_gc_barrieruv(global_State *g, TValue *tv);
66LJ_FUNC void lj_gc_closeuv(global_State *g, GCupval *uv); 66LJ_FUNC void lj_gc_closeuv(global_State *g, GCupval *uv);
67#if LJ_HASJIT 67#if LJ_HASJIT
68LJ_FUNC void lj_gc_barriertrace(global_State *g, void *T); 68LJ_FUNC void lj_gc_barriertrace(global_State *g, uint32_t traceno);
69#endif 69#endif
70 70
71/* Barrier for stores to table objects. TValue and GCobj variant. */ 71/* Barrier for stores to table objects. TValue and GCobj variant. */
diff --git a/src/lj_gdbjit.c b/src/lj_gdbjit.c
index 951d52ec..d66ef455 100644
--- a/src/lj_gdbjit.c
+++ b/src/lj_gdbjit.c
@@ -378,7 +378,7 @@ static const ELFheader elfhdr_template = {
378typedef struct GDBJITctx { 378typedef struct GDBJITctx {
379 uint8_t *p; /* Pointer to next address in obj.space. */ 379 uint8_t *p; /* Pointer to next address in obj.space. */
380 uint8_t *startp; /* Pointer to start address in obj.space. */ 380 uint8_t *startp; /* Pointer to start address in obj.space. */
381 Trace *T; /* Generate symbols for this trace. */ 381 GCtrace *T; /* Generate symbols for this trace. */
382 uintptr_t mcaddr; /* Machine code address. */ 382 uintptr_t mcaddr; /* Machine code address. */
383 MSize szmcode; /* Size of machine code. */ 383 MSize szmcode; /* Size of machine code. */
384 MSize spadjp; /* Stack adjustment for parent trace or interpreter. */ 384 MSize spadjp; /* Stack adjustment for parent trace or interpreter. */
@@ -698,7 +698,7 @@ static void gdbjit_newentry(lua_State *L, GDBJITctx *ctx)
698} 698}
699 699
700/* Add debug info for newly compiled trace and notify GDB. */ 700/* Add debug info for newly compiled trace and notify GDB. */
701void lj_gdbjit_addtrace(jit_State *J, Trace *T, TraceNo traceno) 701void lj_gdbjit_addtrace(jit_State *J, GCtrace *T, TraceNo traceno)
702{ 702{
703 GDBJITctx ctx; 703 GDBJITctx ctx;
704 lua_State *L = J->L; 704 lua_State *L = J->L;
@@ -709,7 +709,8 @@ void lj_gdbjit_addtrace(jit_State *J, Trace *T, TraceNo traceno)
709 ctx.T = T; 709 ctx.T = T;
710 ctx.mcaddr = (uintptr_t)T->mcode; 710 ctx.mcaddr = (uintptr_t)T->mcode;
711 ctx.szmcode = T->szmcode; 711 ctx.szmcode = T->szmcode;
712 ctx.spadjp = CFRAME_SIZE_JIT + (MSize)(parent?J->trace[parent]->spadjust:0); 712 ctx.spadjp = CFRAME_SIZE_JIT +
713 (MSize)(parent ? traceref(J, parent)->spadjust : 0);
713 ctx.spadj = CFRAME_SIZE_JIT + T->spadjust; 714 ctx.spadj = CFRAME_SIZE_JIT + T->spadjust;
714 if (startpc >= proto_bc(pt) && startpc < proto_bc(pt) + pt->sizebc) 715 if (startpc >= proto_bc(pt) && startpc < proto_bc(pt) + pt->sizebc)
715 ctx.lineno = proto_line(pt, proto_bcpos(pt, startpc)); 716 ctx.lineno = proto_line(pt, proto_bcpos(pt, startpc));
@@ -727,7 +728,7 @@ void lj_gdbjit_addtrace(jit_State *J, Trace *T, TraceNo traceno)
727} 728}
728 729
729/* Delete debug info for trace and notify GDB. */ 730/* Delete debug info for trace and notify GDB. */
730void lj_gdbjit_deltrace(jit_State *J, Trace *T) 731void lj_gdbjit_deltrace(jit_State *J, GCtrace *T)
731{ 732{
732 GDBJITentryobj *eo = (GDBJITentryobj *)T->gdbjit_entry; 733 GDBJITentryobj *eo = (GDBJITentryobj *)T->gdbjit_entry;
733 if (eo) { 734 if (eo) {
diff --git a/src/lj_gdbjit.h b/src/lj_gdbjit.h
index b007260b..037d3344 100644
--- a/src/lj_gdbjit.h
+++ b/src/lj_gdbjit.h
@@ -11,8 +11,8 @@
11 11
12#if LJ_HASJIT && defined(LUAJIT_USE_GDBJIT) 12#if LJ_HASJIT && defined(LUAJIT_USE_GDBJIT)
13 13
14LJ_FUNC void lj_gdbjit_addtrace(jit_State *J, Trace *T, TraceNo traceno); 14LJ_FUNC void lj_gdbjit_addtrace(jit_State *J, GCtrace *T, TraceNo traceno);
15LJ_FUNC void lj_gdbjit_deltrace(jit_State *J, Trace *T); 15LJ_FUNC void lj_gdbjit_deltrace(jit_State *J, GCtrace *T);
16 16
17#else 17#else
18#define lj_gdbjit_addtrace(J, T, tn) UNUSED(T) 18#define lj_gdbjit_addtrace(J, T, tn) UNUSED(T)
diff --git a/src/lj_ir.h b/src/lj_ir.h
index 14f80ac5..60366049 100644
--- a/src/lj_ir.h
+++ b/src/lj_ir.h
@@ -317,7 +317,7 @@ typedef enum {
317 IRT_THREAD, 317 IRT_THREAD,
318 IRT_PROTO, 318 IRT_PROTO,
319 IRT_FUNC, 319 IRT_FUNC,
320 IRT_9, /* Never used in the IR. */ 320 IRT_9, /* Unused (map of LJ_TTRACE). */
321 IRT_TAB, 321 IRT_TAB,
322 IRT_UDATA, 322 IRT_UDATA,
323 /* ... until here. */ 323 /* ... until here. */
diff --git a/src/lj_jit.h b/src/lj_jit.h
index adb6f2d5..332596f0 100644
--- a/src/lj_jit.h
+++ b/src/lj_jit.h
@@ -152,34 +152,42 @@ typedef uint16_t TraceNo1; /* Stored trace number. */
152 152
153#define TRACE_INTERP 0 /* Fallback to interpreter. */ 153#define TRACE_INTERP 0 /* Fallback to interpreter. */
154 154
155/* Trace anchor. */ 155/* Trace object. */
156typedef struct Trace { 156typedef struct GCtrace {
157 IRIns *ir; /* IR instructions/constants. Biased with REF_BIAS. */ 157 GCHeader;
158 uint8_t topslot; /* Top stack slot already checked to be allocated. */
159 uint8_t unused1;
158 IRRef nins; /* Next IR instruction. Biased with REF_BIAS. */ 160 IRRef nins; /* Next IR instruction. Biased with REF_BIAS. */
161 GCRef gclist;
162 IRIns *ir; /* IR instructions/constants. Biased with REF_BIAS. */
159 IRRef nk; /* Lowest IR constant. Biased with REF_BIAS. */ 163 IRRef nk; /* Lowest IR constant. Biased with REF_BIAS. */
160 SnapShot *snap; /* Snapshot array. */
161 SnapEntry *snapmap; /* Snapshot map. */
162 uint16_t nsnap; /* Number of snapshots. */ 164 uint16_t nsnap; /* Number of snapshots. */
163 uint16_t nsnapmap; /* Number of snapshot map elements. */ 165 uint16_t nsnapmap; /* Number of snapshot map elements. */
166 SnapShot *snap; /* Snapshot array. */
167 SnapEntry *snapmap; /* Snapshot map. */
164 GCRef startpt; /* Starting prototype. */ 168 GCRef startpt; /* Starting prototype. */
165 BCIns startins; /* Original bytecode of starting instruction. */ 169 BCIns startins; /* Original bytecode of starting instruction. */
166 MCode *mcode; /* Start of machine code. */ 170 MCode *mcode; /* Start of machine code. */
167 MSize szmcode; /* Size of machine code. */ 171 MSize szmcode; /* Size of machine code. */
168 MSize mcloop; /* Offset of loop start in machine code. */ 172 MSize mcloop; /* Offset of loop start in machine code. */
173 uint16_t nchild; /* Number of child traces (root trace only). */
174 uint16_t spadjust; /* Stack pointer adjustment (offset in bytes). */
175 TraceNo1 traceno; /* Trace number. */
169 TraceNo1 link; /* Linked trace (or self for loops). */ 176 TraceNo1 link; /* Linked trace (or self for loops). */
170 TraceNo1 root; /* Root trace of side trace (or 0 for root traces). */ 177 TraceNo1 root; /* Root trace of side trace (or 0 for root traces). */
171 TraceNo1 nextroot; /* Next root trace for same prototype. */ 178 TraceNo1 nextroot; /* Next root trace for same prototype. */
172 TraceNo1 nextside; /* Next side trace of same root trace. */ 179 TraceNo1 nextside; /* Next side trace of same root trace. */
173 uint16_t nchild; /* Number of child traces (root trace only). */ 180 uint16_t unused2;
174 uint16_t spadjust; /* Stack pointer adjustment (offset in bytes). */
175 uint8_t topslot; /* Top stack slot already checked to be allocated. */
176 uint8_t unused1;
177 uint8_t unused2;
178 uint8_t unused3;
179#ifdef LUAJIT_USE_GDBJIT 181#ifdef LUAJIT_USE_GDBJIT
180 void *gdbjit_entry; /* GDB JIT entry. */ 182 void *gdbjit_entry; /* GDB JIT entry. */
181#endif 183#endif
182} Trace; 184} GCtrace;
185
186#define gco2trace(o) check_exp((o)->gch.gct == ~LJ_TTRACE, (GCtrace *)(o))
187#define traceref(J, n) \
188 check_exp((n)>0 && (MSize)(n)<J->sizetrace, (GCtrace *)gcref(J->trace[(n)]))
189
190LJ_STATIC_ASSERT(offsetof(GChead, gclist) == offsetof(GCtrace, gclist));
183 191
184/* Round-robin penalty cache for bytecodes leading to aborted traces. */ 192/* Round-robin penalty cache for bytecodes leading to aborted traces. */
185typedef struct HotPenalty { 193typedef struct HotPenalty {
@@ -233,7 +241,7 @@ typedef struct FoldState {
233 241
234/* JIT compiler state. */ 242/* JIT compiler state. */
235typedef struct jit_State { 243typedef struct jit_State {
236 Trace cur; /* Current trace. */ 244 GCtrace cur; /* Current trace. */
237 245
238 lua_State *L; /* Current Lua state. */ 246 lua_State *L; /* Current Lua state. */
239 const BCIns *pc; /* Current PC. */ 247 const BCIns *pc; /* Current PC. */
@@ -277,7 +285,7 @@ typedef struct jit_State {
277 MSize sizesnapmap; /* Size of temp. snapshot map buffer. */ 285 MSize sizesnapmap; /* Size of temp. snapshot map buffer. */
278 286
279 TraceNo curtrace; /* Current trace number (if not 0). Kept in J->cur. */ 287 TraceNo curtrace; /* Current trace number (if not 0). Kept in J->cur. */
280 Trace **trace; /* Array of traces. */ 288 GCRef *trace; /* Array of traces. */
281 TraceNo freetrace; /* Start of scan for next free trace. */ 289 TraceNo freetrace; /* Start of scan for next free trace. */
282 MSize sizetrace; /* Size of trace array. */ 290 MSize sizetrace; /* Size of trace array. */
283 291
diff --git a/src/lj_obj.c b/src/lj_obj.c
index 0df51bc4..3d7e9fcb 100644
--- a/src/lj_obj.c
+++ b/src/lj_obj.c
@@ -16,7 +16,7 @@ LJ_DATADEF const char *const lj_obj_typename[] = { /* ORDER LUA_T */
16 16
17LJ_DATADEF const char *const lj_obj_itypename[] = { /* ORDER LJ_T */ 17LJ_DATADEF const char *const lj_obj_itypename[] = { /* ORDER LJ_T */
18 "nil", "boolean", "boolean", "userdata", "string", "upval", "thread", 18 "nil", "boolean", "boolean", "userdata", "string", "upval", "thread",
19 "proto", "function", "" /* Unused */, "table", "userdata", "number" 19 "proto", "function", "trace", "table", "userdata", "number"
20}; 20};
21 21
22/* Compare two objects without calling metamethods. */ 22/* Compare two objects without calling metamethods. */
diff --git a/src/lj_obj.h b/src/lj_obj.h
index 71146dfc..b01bd97b 100644
--- a/src/lj_obj.h
+++ b/src/lj_obj.h
@@ -195,7 +195,7 @@ typedef const TValue cTValue;
195#define LJ_TTHREAD (-7) 195#define LJ_TTHREAD (-7)
196#define LJ_TPROTO (-8) 196#define LJ_TPROTO (-8)
197#define LJ_TFUNC (-9) 197#define LJ_TFUNC (-9)
198/* Unused (-10) */ 198#define LJ_TTRACE (-10)
199#define LJ_TTAB (-11) 199#define LJ_TTAB (-11)
200#define LJ_TUDATA (-12) 200#define LJ_TUDATA (-12)
201/* This is just the canonical number type used in some places. */ 201/* This is just the canonical number type used in some places. */
diff --git a/src/lj_record.c b/src/lj_record.c
index c13c67fd..a3f5b9c0 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -265,7 +265,7 @@ static TRef find_kinit(jit_State *J, const BCIns *endpc, BCReg slot, IRType t)
265 if (op == BC_KSHORT || op == BC_KNUM) { /* Found const. initializer. */ 265 if (op == BC_KSHORT || op == BC_KNUM) { /* Found const. initializer. */
266 /* Now try to verify there's no forward jump across it. */ 266 /* Now try to verify there's no forward jump across it. */
267 const BCIns *kpc = pc; 267 const BCIns *kpc = pc;
268 for ( ; pc > startpc; pc--) 268 for (; pc > startpc; pc--)
269 if (bc_op(*pc) == BC_JMP) { 269 if (bc_op(*pc) == BC_JMP) {
270 const BCIns *target = pc+bc_j(*pc)+1; 270 const BCIns *target = pc+bc_j(*pc)+1;
271 if (target > kpc && target <= endpc) 271 if (target > kpc && target <= endpc)
@@ -2237,10 +2237,10 @@ void lj_record_ins(jit_State *J)
2237 break; 2237 break;
2238 2238
2239 case BC_JFORL: 2239 case BC_JFORL:
2240 rec_loop_jit(J, rc, rec_for(J, pc+bc_j(J->trace[rc]->startins), 1)); 2240 rec_loop_jit(J, rc, rec_for(J, pc+bc_j(traceref(J, rc)->startins), 1));
2241 break; 2241 break;
2242 case BC_JITERL: 2242 case BC_JITERL:
2243 rec_loop_jit(J, rc, rec_iterl(J, J->trace[rc]->startins)); 2243 rec_loop_jit(J, rc, rec_iterl(J, traceref(J, rc)->startins));
2244 break; 2244 break;
2245 case BC_JLOOP: 2245 case BC_JLOOP:
2246 rec_loop_jit(J, rc, rec_loop(J, ra)); 2246 rec_loop_jit(J, rc, rec_loop(J, ra));
@@ -2412,7 +2412,7 @@ static const BCIns *rec_setup_root(jit_State *J)
2412} 2412}
2413 2413
2414/* Setup recording for a side trace. */ 2414/* Setup recording for a side trace. */
2415static void rec_setup_side(jit_State *J, Trace *T) 2415static void rec_setup_side(jit_State *J, GCtrace *T)
2416{ 2416{
2417 SnapShot *snap = &T->snap[J->exitno]; 2417 SnapShot *snap = &T->snap[J->exitno];
2418 SnapEntry *map = &T->snapmap[snap->mapofs]; 2418 SnapEntry *map = &T->snapmap[snap->mapofs];
@@ -2500,10 +2500,9 @@ void lj_record_setup(jit_State *J)
2500 } 2500 }
2501 J->cur.nk = REF_TRUE; 2501 J->cur.nk = REF_TRUE;
2502 2502
2503 setgcref(J->cur.startpt, obj2gco(J->pt));
2504 J->startpc = J->pc; 2503 J->startpc = J->pc;
2505 if (J->parent) { /* Side trace. */ 2504 if (J->parent) { /* Side trace. */
2506 Trace *T = J->trace[J->parent]; 2505 GCtrace *T = traceref(J, J->parent);
2507 TraceNo root = T->root ? T->root : J->parent; 2506 TraceNo root = T->root ? T->root : J->parent;
2508 J->cur.root = (uint16_t)root; 2507 J->cur.root = (uint16_t)root;
2509 J->cur.startins = BCINS_AD(BC_JMP, 0, 0); 2508 J->cur.startins = BCINS_AD(BC_JMP, 0, 0);
@@ -2521,7 +2520,7 @@ void lj_record_setup(jit_State *J)
2521 } 2520 }
2522 rec_setup_side(J, T); 2521 rec_setup_side(J, T);
2523 sidecheck: 2522 sidecheck:
2524 if (J->trace[J->cur.root]->nchild >= J->param[JIT_P_maxside] || 2523 if (traceref(J, J->cur.root)->nchild >= J->param[JIT_P_maxside] ||
2525 T->snap[J->exitno].count >= J->param[JIT_P_hotexit] + 2524 T->snap[J->exitno].count >= J->param[JIT_P_hotexit] +
2526 J->param[JIT_P_tryside]) 2525 J->param[JIT_P_tryside])
2527 rec_stop(J, TRACE_INTERP); 2526 rec_stop(J, TRACE_INTERP);
diff --git a/src/lj_snap.c b/src/lj_snap.c
index 33ac50f5..96badaaa 100644
--- a/src/lj_snap.c
+++ b/src/lj_snap.c
@@ -168,7 +168,7 @@ void lj_snap_shrink(jit_State *J)
168** There are very few renames (often none), so the filter has 168** There are very few renames (often none), so the filter has
169** very few bits set. This makes it suitable for negative filtering. 169** very few bits set. This makes it suitable for negative filtering.
170*/ 170*/
171static BloomFilter snap_renamefilter(Trace *T, SnapNo lim) 171static BloomFilter snap_renamefilter(GCtrace *T, SnapNo lim)
172{ 172{
173 BloomFilter rfilt = 0; 173 BloomFilter rfilt = 0;
174 IRIns *ir; 174 IRIns *ir;
@@ -179,7 +179,7 @@ static BloomFilter snap_renamefilter(Trace *T, SnapNo lim)
179} 179}
180 180
181/* Process matching renames to find the original RegSP. */ 181/* Process matching renames to find the original RegSP. */
182static RegSP snap_renameref(Trace *T, SnapNo lim, IRRef ref, RegSP rs) 182static RegSP snap_renameref(GCtrace *T, SnapNo lim, IRRef ref, RegSP rs)
183{ 183{
184 IRIns *ir; 184 IRIns *ir;
185 for (ir = &T->ir[T->nins-1]; ir->o == IR_RENAME; ir--) 185 for (ir = &T->ir[T->nins-1]; ir->o == IR_RENAME; ir--)
@@ -191,7 +191,7 @@ static RegSP snap_renameref(Trace *T, SnapNo lim, IRRef ref, RegSP rs)
191/* Convert a snapshot into a linear slot -> RegSP map. 191/* Convert a snapshot into a linear slot -> RegSP map.
192** Note: unused slots are not initialized! 192** Note: unused slots are not initialized!
193*/ 193*/
194void lj_snap_regspmap(uint16_t *rsmap, Trace *T, SnapNo snapno) 194void lj_snap_regspmap(uint16_t *rsmap, GCtrace *T, SnapNo snapno)
195{ 195{
196 SnapShot *snap = &T->snap[snapno]; 196 SnapShot *snap = &T->snap[snapno];
197 MSize n, nent = snap->nent; 197 MSize n, nent = snap->nent;
@@ -215,7 +215,7 @@ const BCIns *lj_snap_restore(jit_State *J, void *exptr)
215{ 215{
216 ExitState *ex = (ExitState *)exptr; 216 ExitState *ex = (ExitState *)exptr;
217 SnapNo snapno = J->exitno; /* For now, snapno == exitno. */ 217 SnapNo snapno = J->exitno; /* For now, snapno == exitno. */
218 Trace *T = J->trace[J->parent]; 218 GCtrace *T = traceref(J, J->parent);
219 SnapShot *snap = &T->snap[snapno]; 219 SnapShot *snap = &T->snap[snapno];
220 MSize n, nent = snap->nent; 220 MSize n, nent = snap->nent;
221 SnapEntry *map = &T->snapmap[snap->mapofs]; 221 SnapEntry *map = &T->snapmap[snap->mapofs];
diff --git a/src/lj_snap.h b/src/lj_snap.h
index 80be33b7..c5b8b2a1 100644
--- a/src/lj_snap.h
+++ b/src/lj_snap.h
@@ -12,7 +12,7 @@
12#if LJ_HASJIT 12#if LJ_HASJIT
13LJ_FUNC void lj_snap_add(jit_State *J); 13LJ_FUNC void lj_snap_add(jit_State *J);
14LJ_FUNC void lj_snap_shrink(jit_State *J); 14LJ_FUNC void lj_snap_shrink(jit_State *J);
15LJ_FUNC void lj_snap_regspmap(uint16_t *rsmap, Trace *T, SnapNo snapno); 15LJ_FUNC void lj_snap_regspmap(uint16_t *rsmap, GCtrace *T, SnapNo snapno);
16LJ_FUNC const BCIns *lj_snap_restore(jit_State *J, void *exptr); 16LJ_FUNC const BCIns *lj_snap_restore(jit_State *J, void *exptr);
17LJ_FUNC void lj_snap_grow_buf_(jit_State *J, MSize need); 17LJ_FUNC void lj_snap_grow_buf_(jit_State *J, MSize need);
18LJ_FUNC void lj_snap_grow_map_(jit_State *J, MSize need); 18LJ_FUNC void lj_snap_grow_map_(jit_State *J, MSize need);
diff --git a/src/lj_trace.c b/src/lj_trace.c
index 5571293e..4c9c4669 100644
--- a/src/lj_trace.c
+++ b/src/lj_trace.c
@@ -52,7 +52,7 @@ void lj_trace_err_info(jit_State *J, TraceError e)
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.). The trace is
54** kept in this state until a new trace needs to be created. Then the current 54** kept in this state until a new trace needs to be created. Then the current
55** trace and its data structures are copied to a new (compact) Trace object. 55** trace and its data structures are copied to a new (compact) GCtrace object.
56*/ 56*/
57 57
58/* Find a free trace number. */ 58/* Find a free trace number. */
@@ -62,7 +62,7 @@ static TraceNo trace_findfree(jit_State *J)
62 if (J->freetrace == 0) 62 if (J->freetrace == 0)
63 J->freetrace = 1; 63 J->freetrace = 1;
64 for (; J->freetrace < J->sizetrace; J->freetrace++) 64 for (; J->freetrace < J->sizetrace; J->freetrace++)
65 if (J->trace[J->freetrace] == NULL) 65 if (traceref(J, J->freetrace) == NULL)
66 return J->freetrace++; 66 return J->freetrace++;
67 /* Need to grow trace array. */ 67 /* Need to grow trace array. */
68 lim = (MSize)J->param[JIT_P_maxtrace] + 1; 68 lim = (MSize)J->param[JIT_P_maxtrace] + 1;
@@ -70,9 +70,9 @@ static TraceNo trace_findfree(jit_State *J)
70 osz = J->sizetrace; 70 osz = J->sizetrace;
71 if (osz >= lim) 71 if (osz >= lim)
72 return 0; /* Too many traces. */ 72 return 0; /* Too many traces. */
73 lj_mem_growvec(J->L, J->trace, J->sizetrace, lim, Trace *); 73 lj_mem_growvec(J->L, J->trace, J->sizetrace, lim, GCRef);
74 while (osz < J->sizetrace) 74 for (; osz < J->sizetrace; osz++)
75 J->trace[osz++] = NULL; 75 setgcrefnull(J->trace[osz]);
76 return J->freetrace; 76 return J->freetrace;
77} 77}
78 78
@@ -82,64 +82,40 @@ static TraceNo trace_findfree(jit_State *J)
82 p += T->szfield*sizeof(tp); 82 p += T->szfield*sizeof(tp);
83 83
84/* Save a trace by copying and compacting it. */ 84/* Save a trace by copying and compacting it. */
85static Trace *trace_save(jit_State *J, Trace *T) 85static GCtrace *trace_save(jit_State *J, GCtrace *T)
86{ 86{
87 size_t sztr = ((sizeof(Trace)+7)&~7); 87 size_t sztr = ((sizeof(GCtrace)+7)&~7);
88 size_t szins = (T->nins-T->nk)*sizeof(IRIns); 88 size_t szins = (T->nins-T->nk)*sizeof(IRIns);
89 size_t sz = sztr + szins + 89 size_t sz = sztr + szins +
90 T->nsnap*sizeof(SnapShot) + 90 T->nsnap*sizeof(SnapShot) +
91 T->nsnapmap*sizeof(SnapEntry); 91 T->nsnapmap*sizeof(SnapEntry);
92 Trace *T2 = lj_mem_newt(J->L, (MSize)sz, Trace); 92 GCtrace *T2 = lj_mem_newt(J->L, (MSize)sz, GCtrace);
93 char *p = (char *)T2 + sztr; 93 char *p = (char *)T2 + sztr;
94 memcpy(T2, T, sizeof(Trace)); 94 memcpy(T2, T, sizeof(GCtrace));
95 setgcrefr(T2->nextgc, J2G(J)->gc.root);
96 setgcrefp(J2G(J)->gc.root, T2);
97 newwhite(J2G(J), T2);
98 T2->gct = ~LJ_TTRACE;
95 T2->ir = (IRIns *)p - T->nk; 99 T2->ir = (IRIns *)p - T->nk;
96 memcpy(p, T->ir+T->nk, szins); 100 memcpy(p, T->ir+T->nk, szins);
97 p += szins; 101 p += szins;
98 TRACE_COPYELEM(snap, nsnap, SnapShot) 102 TRACE_COPYELEM(snap, nsnap, SnapShot)
99 TRACE_COPYELEM(snapmap, nsnapmap, SnapEntry) 103 TRACE_COPYELEM(snapmap, nsnapmap, SnapEntry)
100 lj_gc_barriertrace(J2G(J), T);
101 return T2; 104 return T2;
102} 105}
103 106
104/* Free a trace. */ 107void LJ_FASTCALL lj_trace_free(global_State *g, GCtrace *T)
105static void trace_free(jit_State *J, TraceNo traceno)
106{
107 lua_assert(traceno != 0);
108 if (traceno < J->freetrace)
109 J->freetrace = traceno;
110 lj_gdbjit_deltrace(J, J->trace[traceno]);
111 if (traceno == J->curtrace) {
112 lua_assert(J->trace[traceno] == &J->cur);
113 J->trace[traceno] = NULL;
114 J->curtrace = 0;
115 } else {
116 Trace *T = J->trace[traceno];
117 lua_assert(T != NULL && T != &J->cur);
118 J->trace[traceno] = NULL;
119 lj_mem_free(J2G(J), T,
120 ((sizeof(Trace)+7)&~7) + (T->nins-T->nk)*sizeof(IRIns) +
121 T->nsnap*sizeof(SnapShot) + T->nsnapmap*sizeof(SnapEntry));
122 }
123}
124
125/* Free all traces associated with a prototype. No unpatching needed. */
126void lj_trace_freeproto(global_State *g, GCproto *pt)
127{ 108{
128 jit_State *J = G2J(g); 109 jit_State *J = G2J(g);
129 TraceNo traceno; 110 if (T->traceno) {
130 /* Free all root traces. */ 111 lj_gdbjit_deltrace(J, T);
131 for (traceno = pt->trace; traceno != 0; ) { 112 if (T->traceno < J->freetrace)
132 TraceNo side, nextroot = J->trace[traceno]->nextroot; 113 J->freetrace = T->traceno;
133 /* Free all side traces. */ 114 setgcrefnull(J->trace[T->traceno]);
134 for (side = J->trace[traceno]->nextside; side != 0; ) {
135 TraceNo next = J->trace[side]->nextside;
136 trace_free(J, side);
137 side = next;
138 }
139 /* Now free the trace itself. */
140 trace_free(J, traceno);
141 traceno = nextroot;
142 } 115 }
116 lj_mem_free(g, T,
117 ((sizeof(GCtrace)+7)&~7) + (T->nins-T->nk)*sizeof(IRIns) +
118 T->nsnap*sizeof(SnapShot) + T->nsnapmap*sizeof(SnapEntry));
143} 119}
144 120
145/* Re-enable compiling a prototype by unpatching any modified bytecode. */ 121/* Re-enable compiling a prototype by unpatching any modified bytecode. */
@@ -160,7 +136,7 @@ void lj_trace_reenableproto(GCproto *pt)
160} 136}
161 137
162/* Unpatch the bytecode modified by a root trace. */ 138/* Unpatch the bytecode modified by a root trace. */
163static void trace_unpatch(jit_State *J, Trace *T) 139static void trace_unpatch(jit_State *J, GCtrace *T)
164{ 140{
165 BCOp op = bc_op(T->startins); 141 BCOp op = bc_op(T->startins);
166 MSize pcofs = T->snap[0].mapofs + T->snap[0].nent; 142 MSize pcofs = T->snap[0].mapofs + T->snap[0].nent;
@@ -171,21 +147,21 @@ static void trace_unpatch(jit_State *J, Trace *T)
171 lua_assert(bc_op(*pc) == BC_JFORI); 147 lua_assert(bc_op(*pc) == BC_JFORI);
172 setbc_op(pc, BC_FORI); /* Unpatch JFORI, too. */ 148 setbc_op(pc, BC_FORI); /* Unpatch JFORI, too. */
173 pc += bc_j(*pc); 149 pc += bc_j(*pc);
174 lua_assert(bc_op(*pc) == BC_JFORL && J->trace[bc_d(*pc)] == T); 150 lua_assert(bc_op(*pc) == BC_JFORL && traceref(J, bc_d(*pc)) == T);
175 *pc = T->startins; 151 *pc = T->startins;
176 break; 152 break;
177 case BC_LOOP: 153 case BC_LOOP:
178 lua_assert(bc_op(*pc) == BC_JLOOP && J->trace[bc_d(*pc)] == T); 154 lua_assert(bc_op(*pc) == BC_JLOOP && traceref(J, bc_d(*pc)) == T);
179 *pc = T->startins; 155 *pc = T->startins;
180 break; 156 break;
181 case BC_ITERL: 157 case BC_ITERL:
182 lua_assert(bc_op(*pc) == BC_JMP); 158 lua_assert(bc_op(*pc) == BC_JMP);
183 pc += bc_j(*pc)+2; 159 pc += bc_j(*pc)+2;
184 lua_assert(bc_op(*pc) == BC_JITERL && J->trace[bc_d(*pc)] == T); 160 lua_assert(bc_op(*pc) == BC_JITERL && traceref(J, bc_d(*pc)) == T);
185 *pc = T->startins; 161 *pc = T->startins;
186 break; 162 break;
187 case BC_FUNCF: 163 case BC_FUNCF:
188 lua_assert(bc_op(*pc) == BC_JFUNCF && J->trace[bc_d(*pc)] == T); 164 lua_assert(bc_op(*pc) == BC_JFUNCF && traceref(J, bc_d(*pc)) == T);
189 *pc = T->startins; 165 *pc = T->startins;
190 break; 166 break;
191 case BC_JMP: /* No need to unpatch branches in parent traces (yet). */ 167 case BC_JMP: /* No need to unpatch branches in parent traces (yet). */
@@ -195,58 +171,41 @@ static void trace_unpatch(jit_State *J, Trace *T)
195 } 171 }
196} 172}
197 173
198/* Free a root trace and any attached side traces. */ 174/* Flush a root trace. */
199static void trace_freeroot(jit_State *J, Trace *T, TraceNo traceno) 175static void trace_flushroot(jit_State *J, GCtrace *T)
200{ 176{
201 GCproto *pt = &gcref(T->startpt)->pt; 177 GCproto *pt = &gcref(T->startpt)->pt;
202 TraceNo side;
203 lua_assert(T->root == 0 && pt != NULL); 178 lua_assert(T->root == 0 && pt != NULL);
204 /* First unpatch any modified bytecode. */ 179 /* First unpatch any modified bytecode. */
205 trace_unpatch(J, T); 180 trace_unpatch(J, T);
206 /* Unlink root trace from chain anchored in prototype. */ 181 /* Unlink root trace from chain anchored in prototype. */
207 if (pt->trace == traceno) { /* Trace is first in chain. Easy. */ 182 if (pt->trace == T->traceno) { /* Trace is first in chain. Easy. */
208 pt->trace = T->nextroot; 183 pt->trace = T->nextroot;
209 } else { /* Otherwise search in chain of root traces. */ 184 } else { /* Otherwise search in chain of root traces. */
210 Trace *T2 = J->trace[pt->trace]; 185 GCtrace *T2 = traceref(J, pt->trace);
211 while (T2->nextroot != traceno) { 186 while (T2->nextroot != T->traceno) {
212 lua_assert(T2->nextroot != 0); 187 lua_assert(T2->nextroot != 0);
213 T2 = J->trace[T2->nextroot]; 188 T2 = traceref(J, T2->nextroot);
214 } 189 }
215 T2->nextroot = T->nextroot; /* Unlink from chain. */ 190 T2->nextroot = T->nextroot; /* Unlink from chain. */
216 } 191 }
217 /* Free all side traces. */
218 for (side = T->nextside; side != 0; ) {
219 TraceNo next = J->trace[side]->nextside;
220 trace_free(J, side);
221 side = next;
222 }
223 /* Now free the trace itself. */
224 trace_free(J, traceno);
225} 192}
226 193
227/* Flush a root trace + side traces, if there are no links to it. */ 194/* Flush a trace. Only root traces are considered. */
228int lj_trace_flush(jit_State *J, TraceNo traceno) 195void lj_trace_flush(jit_State *J, TraceNo traceno)
229{ 196{
230 if (traceno > 0 && traceno < J->sizetrace) { 197 if (traceno > 0 && traceno < J->sizetrace) {
231 Trace *T = J->trace[traceno]; 198 GCtrace *T = traceref(J, traceno);
232 if (T && T->root == 0) { 199 if (T && T->root == 0)
233 ptrdiff_t i; 200 trace_flushroot(J, T);
234 for (i = (ptrdiff_t)J->sizetrace-1; i > 0; i--)
235 if (i != (ptrdiff_t)traceno && J->trace[i] &&
236 J->trace[i]->root != traceno && J->trace[i]->link == traceno)
237 return 0; /* Failed: existing link to trace. */
238 trace_freeroot(J, T, traceno);
239 return 1; /* Ok. */
240 }
241 } 201 }
242 return 0; /* Failed. */
243} 202}
244 203
245/* Flush all traces associated with a prototype. */ 204/* Flush all traces associated with a prototype. */
246void lj_trace_flushproto(global_State *g, GCproto *pt) 205void lj_trace_flushproto(global_State *g, GCproto *pt)
247{ 206{
248 while (pt->trace != 0) 207 while (pt->trace != 0)
249 trace_freeroot(G2J(g), G2J(g)->trace[pt->trace], pt->trace); 208 trace_flushroot(G2J(g), traceref(G2J(g), pt->trace));
250} 209}
251 210
252/* Flush all traces. */ 211/* Flush all traces. */
@@ -257,14 +216,16 @@ int lj_trace_flushall(lua_State *L)
257 if ((J2G(J)->hookmask & HOOK_GC)) 216 if ((J2G(J)->hookmask & HOOK_GC))
258 return 1; 217 return 1;
259 for (i = (ptrdiff_t)J->sizetrace-1; i > 0; i--) { 218 for (i = (ptrdiff_t)J->sizetrace-1; i > 0; i--) {
260 Trace *T = J->trace[i]; 219 GCtrace *T = traceref(J, i);
261 if (T && T->root == 0) 220 if (T) {
262 trace_freeroot(J, T, (TraceNo)i); 221 if (T->root == 0)
222 trace_flushroot(J, T);
223 lj_gdbjit_deltrace(J, T);
224 T->traceno = 0;
225 setgcrefnull(J->trace[i]);
226 }
263 } 227 }
264#ifdef LUA_USE_ASSERT 228 J->curtrace = 0;
265 for (i = 0; i < (ptrdiff_t)J->sizetrace; i++)
266 lua_assert(J->trace[i] == NULL);
267#endif
268 J->freetrace = 0; 229 J->freetrace = 0;
269 /* Free the whole machine code and invalidate all exit stub groups. */ 230 /* Free the whole machine code and invalidate all exit stub groups. */
270 lj_mcode_free(J); 231 lj_mcode_free(J);
@@ -293,11 +254,13 @@ void lj_trace_initstate(global_State *g)
293void lj_trace_freestate(global_State *g) 254void lj_trace_freestate(global_State *g)
294{ 255{
295 jit_State *J = G2J(g); 256 jit_State *J = G2J(g);
257 if (J->curtrace)
258 lj_gdbjit_deltrace(J, &J->cur);
296#ifdef LUA_USE_ASSERT 259#ifdef LUA_USE_ASSERT
297 { /* This assumes all traces have already been freed. */ 260 { /* This assumes all traces have already been freed. */
298 ptrdiff_t i; 261 ptrdiff_t i;
299 for (i = 0; i < (ptrdiff_t)J->sizetrace; i++) 262 for (i = 1; i < (ptrdiff_t)J->sizetrace; i++)
300 lua_assert(J->trace[i] == NULL); 263 lua_assert(i == (ptrdiff_t)J->curtrace || traceref(J, i) == NULL);
301 } 264 }
302#endif 265#endif
303 lj_mcode_free(J); 266 lj_mcode_free(J);
@@ -305,7 +268,7 @@ void lj_trace_freestate(global_State *g)
305 lj_mem_freevec(g, J->snapmapbuf, J->sizesnapmap, SnapEntry); 268 lj_mem_freevec(g, J->snapmapbuf, J->sizesnapmap, SnapEntry);
306 lj_mem_freevec(g, J->snapbuf, J->sizesnap, SnapShot); 269 lj_mem_freevec(g, J->snapbuf, J->sizesnap, SnapShot);
307 lj_mem_freevec(g, J->irbuf + J->irbotlim, J->irtoplim - J->irbotlim, IRIns); 270 lj_mem_freevec(g, J->irbuf + J->irbotlim, J->irtoplim - J->irbotlim, IRIns);
308 lj_mem_freevec(g, J->trace, J->sizetrace, Trace *); 271 lj_mem_freevec(g, J->trace, J->sizetrace, GCRef);
309} 272}
310 273
311/* -- Penalties and blacklisting ------------------------------------------ */ 274/* -- Penalties and blacklisting ------------------------------------------ */
@@ -349,9 +312,11 @@ static void trace_start(jit_State *J)
349{ 312{
350 lua_State *L; 313 lua_State *L;
351 314
352 if (J->curtrace != 0 && J->trace[J->curtrace] == &J->cur) { 315 if (J->curtrace != 0 && traceref(J, J->curtrace) == &J->cur) {
353 J->trace[J->curtrace] = trace_save(J, &J->cur); /* Save current trace. */ 316 TraceNo tr = J->curtrace; /* Save current trace. */
317 setgcrefp(J->trace[tr], trace_save(J, &J->cur));
354 J->curtrace = 0; 318 J->curtrace = 0;
319 lj_gc_barriertrace(J2G(J), tr);
355 } 320 }
356 321
357 if ((J->pt->flags & PROTO_NO_JIT)) { /* JIT disabled for this proto? */ 322 if ((J->pt->flags & PROTO_NO_JIT)) { /* JIT disabled for this proto? */
@@ -374,10 +339,11 @@ static void trace_start(jit_State *J)
374 J->state = LJ_TRACE_IDLE; /* Silently ignored. */ 339 J->state = LJ_TRACE_IDLE; /* Silently ignored. */
375 return; 340 return;
376 } 341 }
377 J->trace[J->curtrace] = &J->cur; 342 setgcrefp(J->trace[J->curtrace], &J->cur);
378 343
379 /* Setup enough of the current trace to be able to send the vmevent. */ 344 /* Setup enough of the current trace to be able to send the vmevent. */
380 memset(&J->cur, 0, sizeof(Trace)); 345 memset(&J->cur, 0, sizeof(GCtrace));
346 J->cur.traceno = J->curtrace;
381 J->cur.nins = J->cur.nk = REF_BASE; 347 J->cur.nins = J->cur.nk = REF_BASE;
382 J->cur.ir = J->irbuf; 348 J->cur.ir = J->irbuf;
383 J->cur.snap = J->snapbuf; 349 J->cur.snap = J->snapbuf;
@@ -385,6 +351,7 @@ static void trace_start(jit_State *J)
385 J->mergesnap = 0; 351 J->mergesnap = 0;
386 J->needsnap = 0; 352 J->needsnap = 0;
387 J->guardemit.irt = 0; 353 J->guardemit.irt = 0;
354 setgcref(J->cur.startpt, obj2gco(J->pt));
388 355
389 L = J->L; 356 L = J->L;
390 lj_vmevent_send(L, TRACE, 357 lj_vmevent_send(L, TRACE,
@@ -431,12 +398,12 @@ static void trace_stop(jit_State *J)
431 case BC_JMP: 398 case BC_JMP:
432 /* Patch exit branch in parent to side trace entry. */ 399 /* Patch exit branch in parent to side trace entry. */
433 lua_assert(J->parent != 0 && J->cur.root != 0); 400 lua_assert(J->parent != 0 && J->cur.root != 0);
434 lj_asm_patchexit(J, J->trace[J->parent], J->exitno, J->cur.mcode); 401 lj_asm_patchexit(J, traceref(J, J->parent), J->exitno, J->cur.mcode);
435 /* Avoid compiling a side trace twice (stack resizing uses parent exit). */ 402 /* Avoid compiling a side trace twice (stack resizing uses parent exit). */
436 J->trace[J->parent]->snap[J->exitno].count = SNAPCOUNT_DONE; 403 traceref(J, J->parent)->snap[J->exitno].count = SNAPCOUNT_DONE;
437 /* Add to side trace chain in root trace. */ 404 /* Add to side trace chain in root trace. */
438 { 405 {
439 Trace *root = J->trace[J->cur.root]; 406 GCtrace *root = traceref(J, J->cur.root);
440 root->nchild++; 407 root->nchild++;
441 J->cur.nextside = root->nextside; 408 J->cur.nextside = root->nextside;
442 root->nextside = (TraceNo1)J->curtrace; 409 root->nextside = (TraceNo1)J->curtrace;
@@ -510,7 +477,7 @@ static int trace_abort(jit_State *J)
510 copyTV(L, L->top++, &J->errinfo); 477 copyTV(L, L->top++, &J->errinfo);
511 ); 478 );
512 /* Drop aborted trace after the vmevent (which may still access it). */ 479 /* Drop aborted trace after the vmevent (which may still access it). */
513 J->trace[J->curtrace] = NULL; 480 setgcrefnull(J->trace[J->curtrace]);
514 if (J->curtrace < J->freetrace) 481 if (J->curtrace < J->freetrace)
515 J->freetrace = J->curtrace; 482 J->freetrace = J->curtrace;
516 J->curtrace = 0; 483 J->curtrace = 0;
@@ -631,7 +598,7 @@ void LJ_FASTCALL lj_trace_hot(jit_State *J, const BCIns *pc)
631/* Check for a hot side exit. If yes, start recording a side trace. */ 598/* Check for a hot side exit. If yes, start recording a side trace. */
632static void trace_hotside(jit_State *J, const BCIns *pc) 599static void trace_hotside(jit_State *J, const BCIns *pc)
633{ 600{
634 SnapShot *snap = &J->trace[J->parent]->snap[J->exitno]; 601 SnapShot *snap = &traceref(J, J->parent)->snap[J->exitno];
635 if (!(J2G(J)->hookmask & (HOOK_GC|HOOK_VMEVENT)) && 602 if (!(J2G(J)->hookmask & (HOOK_GC|HOOK_VMEVENT)) &&
636 snap->count != SNAPCOUNT_DONE && 603 snap->count != SNAPCOUNT_DONE &&
637 ++snap->count >= J->param[JIT_P_hotexit]) { 604 ++snap->count >= J->param[JIT_P_hotexit]) {
@@ -699,7 +666,7 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
699 else 666 else
700 trace_hotside(J, pc); 667 trace_hotside(J, pc);
701 if (bc_op(*pc) == BC_JLOOP) { 668 if (bc_op(*pc) == BC_JLOOP) {
702 BCIns *retpc = &J->trace[bc_d(*pc)]->startins; 669 BCIns *retpc = &traceref(J, bc_d(*pc))->startins;
703 if (bc_isret(bc_op(*retpc))) { 670 if (bc_isret(bc_op(*retpc))) {
704 if (J->state == LJ_TRACE_RECORD) { 671 if (J->state == LJ_TRACE_RECORD) {
705 J->patchins = *pc; 672 J->patchins = *pc;
diff --git a/src/lj_trace.h b/src/lj_trace.h
index 4d19454f..7e101436 100644
--- a/src/lj_trace.h
+++ b/src/lj_trace.h
@@ -23,10 +23,10 @@ LJ_FUNC_NORET void lj_trace_err(jit_State *J, TraceError e);
23LJ_FUNC_NORET void lj_trace_err_info(jit_State *J, TraceError e); 23LJ_FUNC_NORET void lj_trace_err_info(jit_State *J, TraceError e);
24 24
25/* Trace management. */ 25/* Trace management. */
26LJ_FUNC void lj_trace_freeproto(global_State *g, GCproto *pt); 26LJ_FUNC void LJ_FASTCALL lj_trace_free(global_State *g, GCtrace *T);
27LJ_FUNC void lj_trace_reenableproto(GCproto *pt); 27LJ_FUNC void lj_trace_reenableproto(GCproto *pt);
28LJ_FUNC void lj_trace_flushproto(global_State *g, GCproto *pt); 28LJ_FUNC void lj_trace_flushproto(global_State *g, GCproto *pt);
29LJ_FUNC int lj_trace_flush(jit_State *J, TraceNo traceno); 29LJ_FUNC void lj_trace_flush(jit_State *J, TraceNo traceno);
30LJ_FUNC int lj_trace_flushall(lua_State *L); 30LJ_FUNC int lj_trace_flushall(lua_State *L);
31LJ_FUNC void lj_trace_initstate(global_State *g); 31LJ_FUNC void lj_trace_initstate(global_State *g);
32LJ_FUNC void lj_trace_freestate(global_State *g); 32LJ_FUNC void lj_trace_freestate(global_State *g);
@@ -45,7 +45,6 @@ LJ_FUNCA int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr);
45#define lj_trace_flushall(L) (UNUSED(L), 0) 45#define lj_trace_flushall(L) (UNUSED(L), 0)
46#define lj_trace_initstate(g) UNUSED(g) 46#define lj_trace_initstate(g) UNUSED(g)
47#define lj_trace_freestate(g) UNUSED(g) 47#define lj_trace_freestate(g) UNUSED(g)
48#define lj_trace_freeproto(g, pt) (UNUSED(g), UNUSED(pt), (void)0)
49#define lj_trace_abort(g) UNUSED(g) 48#define lj_trace_abort(g) UNUSED(g)
50#define lj_trace_end(J) UNUSED(J) 49#define lj_trace_end(J) UNUSED(J)
51 50