aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/api.html13
-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
24 files changed, 193 insertions, 201 deletions
diff --git a/doc/api.html b/doc/api.html
index 79924f4f..1494d490 100644
--- a/doc/api.html
+++ b/doc/api.html
@@ -138,11 +138,11 @@ of a module to turn off JIT compilation for the whole module for
138debugging purposes. 138debugging purposes.
139</p> 139</p>
140 140
141<h3 id="jit_flush_tr"><tt>status = jit.flush(tr)</tt></h3> 141<h3 id="jit_flush_tr"><tt>jit.flush(tr)</tt></h3>
142<p> 142<p>
143Tries to flush the code for the specified trace and all of its 143Flushes the specified root trace and all of its side traces from the cache.
144side traces from the cache. Returns <tt>true</tt> on success. 144The code for the trace will be retained as long as there are any other
145Returns <tt>false</tt> if there are still links to this trace. 145traces which link to it.
146</p> 146</p>
147 147
148<h3 id="jit_status"><tt>status, ... = jit.status()</tt></h3> 148<h3 id="jit_status"><tt>status, ... = jit.status()</tt></h3>
@@ -262,8 +262,9 @@ applies recursively to all sub-functions of the function with
262<h3 id="mode_engine"><tt>luaJIT_setmode(L, trace,<br> 262<h3 id="mode_engine"><tt>luaJIT_setmode(L, trace,<br>
263&nbsp;&nbsp;LUAJIT_MODE_TRACE|LUAJIT_MODE_FLUSH)</tt></h3> 263&nbsp;&nbsp;LUAJIT_MODE_TRACE|LUAJIT_MODE_FLUSH)</tt></h3>
264<p> 264<p>
265Tries to flush the code for the specified trace and all of its 265Flushes the specified root trace and all of its side traces from the cache.
266side traces from the cache. 266The code for the trace will be retained as long as there are any other
267traces which link to it.
267</p> 268</p>
268 269
269<h3 id="mode_engine"><tt>luaJIT_setmode(L, idx, LUAJIT_MODE_WRAPCFUNC|flag)</tt></h3> 270<h3 id="mode_engine"><tt>luaJIT_setmode(L, idx, LUAJIT_MODE_WRAPCFUNC|flag)</tt></h3>
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