diff options
author | Mike Pall <mike> | 2010-04-25 03:32:29 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2010-04-25 03:32:29 +0200 |
commit | 721b73fecbbeda5b5cb76628511c5b3fac41eb4d (patch) | |
tree | ce72efaa313ab16eda652e4d277413c31a8d2af3 /src | |
parent | 3a32bbc7cb5c2287e8d4e24e362281c165f50976 (diff) | |
download | luajit-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.h | 4 | ||||
-rw-r--r-- | src/buildvm_x64win.h | 4 | ||||
-rw-r--r-- | src/buildvm_x86.dasc | 6 | ||||
-rw-r--r-- | src/buildvm_x86.h | 2 | ||||
-rw-r--r-- | src/lib_base.c | 2 | ||||
-rw-r--r-- | src/lib_jit.c | 19 | ||||
-rw-r--r-- | src/lj_asm.c | 16 | ||||
-rw-r--r-- | src/lj_asm.h | 4 | ||||
-rw-r--r-- | src/lj_dispatch.c | 3 | ||||
-rw-r--r-- | src/lj_func.c | 1 | ||||
-rw-r--r-- | src/lj_gc.c | 68 | ||||
-rw-r--r-- | src/lj_gc.h | 2 | ||||
-rw-r--r-- | src/lj_gdbjit.c | 9 | ||||
-rw-r--r-- | src/lj_gdbjit.h | 4 | ||||
-rw-r--r-- | src/lj_ir.h | 2 | ||||
-rw-r--r-- | src/lj_jit.h | 36 | ||||
-rw-r--r-- | src/lj_obj.c | 2 | ||||
-rw-r--r-- | src/lj_obj.h | 2 | ||||
-rw-r--r-- | src/lj_record.c | 13 | ||||
-rw-r--r-- | src/lj_snap.c | 8 | ||||
-rw-r--r-- | src/lj_snap.h | 2 | ||||
-rw-r--r-- | src/lj_trace.c | 167 | ||||
-rw-r--r-- | src/lj_trace.h | 5 |
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") | |||
54 | LJLIB_PUSH("thread") | 54 | LJLIB_PUSH("thread") |
55 | LJLIB_PUSH("proto") | 55 | LJLIB_PUSH("proto") |
56 | LJLIB_PUSH("function") | 56 | LJLIB_PUSH("function") |
57 | LJLIB_PUSH("") /* Unused. */ | 57 | LJLIB_PUSH("trace") |
58 | LJLIB_PUSH("table") | 58 | LJLIB_PUSH("table") |
59 | LJLIB_PUSH(top-8) /* userdata */ | 59 | LJLIB_PUSH(top-8) /* userdata */ |
60 | LJLIB_PUSH("number") | 60 | LJLIB_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. */ |
263 | static Trace *jit_checktrace(lua_State *L) | 262 | static 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) */ |
273 | LJLIB_CF(jit_util_traceinfo) | 272 | LJLIB_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) */ |
291 | LJLIB_CF(jit_util_traceir) | 290 | LJLIB_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) */ |
309 | LJLIB_CF(jit_util_tracek) | 308 | LJLIB_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) */ |
331 | LJLIB_CF(jit_util_tracesnap) | 330 | LJLIB_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) */ |
353 | LJLIB_CF(jit_util_tracemc) | 352 | LJLIB_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. */ |
3440 | static void asm_setup_regsp(ASMState *as, Trace *T) | 3440 | static 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. */ |
3580 | void lj_asm_trace(jit_State *J, Trace *T) | 3580 | void 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. */ |
3670 | void lj_asm_patchexit(jit_State *J, Trace *T, ExitNo exitno, MCode *target) | 3670 | void 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 |
12 | LJ_FUNC void lj_asm_trace(jit_State *J, Trace *T); | 12 | LJ_FUNC void lj_asm_trace(jit_State *J, GCtrace *T); |
13 | LJ_FUNC void lj_asm_patchexit(jit_State *J, Trace *T, ExitNo exitno, | 13 | LJ_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 | ||
20 | void LJ_FASTCALL lj_func_freeproto(global_State *g, GCproto *pt) | 20 | void 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. */ | ||
218 | static 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. */ |
218 | static void gc_traverse_trace(global_State *g, Trace *T) | 231 | static 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. */ |
236 | static void gc_traverse_proto(global_State *g, GCproto *pt) | 253 | static 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. */ |
726 | void lj_gc_barriertrace(global_State *g, void *T) | 748 | void 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); | |||
65 | LJ_FUNCA void LJ_FASTCALL lj_gc_barrieruv(global_State *g, TValue *tv); | 65 | LJ_FUNCA void LJ_FASTCALL lj_gc_barrieruv(global_State *g, TValue *tv); |
66 | LJ_FUNC void lj_gc_closeuv(global_State *g, GCupval *uv); | 66 | LJ_FUNC void lj_gc_closeuv(global_State *g, GCupval *uv); |
67 | #if LJ_HASJIT | 67 | #if LJ_HASJIT |
68 | LJ_FUNC void lj_gc_barriertrace(global_State *g, void *T); | 68 | LJ_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 = { | |||
378 | typedef struct GDBJITctx { | 378 | typedef 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. */ |
701 | void lj_gdbjit_addtrace(jit_State *J, Trace *T, TraceNo traceno) | 701 | void 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. */ |
730 | void lj_gdbjit_deltrace(jit_State *J, Trace *T) | 731 | void 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 | ||
14 | LJ_FUNC void lj_gdbjit_addtrace(jit_State *J, Trace *T, TraceNo traceno); | 14 | LJ_FUNC void lj_gdbjit_addtrace(jit_State *J, GCtrace *T, TraceNo traceno); |
15 | LJ_FUNC void lj_gdbjit_deltrace(jit_State *J, Trace *T); | 15 | LJ_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. */ |
156 | typedef struct Trace { | 156 | typedef 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 | |||
190 | LJ_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. */ |
185 | typedef struct HotPenalty { | 193 | typedef struct HotPenalty { |
@@ -233,7 +241,7 @@ typedef struct FoldState { | |||
233 | 241 | ||
234 | /* JIT compiler state. */ | 242 | /* JIT compiler state. */ |
235 | typedef struct jit_State { | 243 | typedef 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 | ||
17 | LJ_DATADEF const char *const lj_obj_itypename[] = { /* ORDER LJ_T */ | 17 | LJ_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. */ |
2415 | static void rec_setup_side(jit_State *J, Trace *T) | 2415 | static 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 | */ |
171 | static BloomFilter snap_renamefilter(Trace *T, SnapNo lim) | 171 | static 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. */ |
182 | static RegSP snap_renameref(Trace *T, SnapNo lim, IRRef ref, RegSP rs) | 182 | static 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 | */ |
194 | void lj_snap_regspmap(uint16_t *rsmap, Trace *T, SnapNo snapno) | 194 | void 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 |
13 | LJ_FUNC void lj_snap_add(jit_State *J); | 13 | LJ_FUNC void lj_snap_add(jit_State *J); |
14 | LJ_FUNC void lj_snap_shrink(jit_State *J); | 14 | LJ_FUNC void lj_snap_shrink(jit_State *J); |
15 | LJ_FUNC void lj_snap_regspmap(uint16_t *rsmap, Trace *T, SnapNo snapno); | 15 | LJ_FUNC void lj_snap_regspmap(uint16_t *rsmap, GCtrace *T, SnapNo snapno); |
16 | LJ_FUNC const BCIns *lj_snap_restore(jit_State *J, void *exptr); | 16 | LJ_FUNC const BCIns *lj_snap_restore(jit_State *J, void *exptr); |
17 | LJ_FUNC void lj_snap_grow_buf_(jit_State *J, MSize need); | 17 | LJ_FUNC void lj_snap_grow_buf_(jit_State *J, MSize need); |
18 | LJ_FUNC void lj_snap_grow_map_(jit_State *J, MSize need); | 18 | LJ_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. */ |
85 | static Trace *trace_save(jit_State *J, Trace *T) | 85 | static 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. */ | 107 | void LJ_FASTCALL lj_trace_free(global_State *g, GCtrace *T) |
105 | static 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. */ | ||
126 | void 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. */ |
163 | static void trace_unpatch(jit_State *J, Trace *T) | 139 | static 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. */ |
199 | static void trace_freeroot(jit_State *J, Trace *T, TraceNo traceno) | 175 | static 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. */ |
228 | int lj_trace_flush(jit_State *J, TraceNo traceno) | 195 | void 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. */ |
246 | void lj_trace_flushproto(global_State *g, GCproto *pt) | 205 | void 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) | |||
293 | void lj_trace_freestate(global_State *g) | 254 | void 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. */ |
632 | static void trace_hotside(jit_State *J, const BCIns *pc) | 599 | static 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); | |||
23 | LJ_FUNC_NORET void lj_trace_err_info(jit_State *J, TraceError e); | 23 | LJ_FUNC_NORET void lj_trace_err_info(jit_State *J, TraceError e); |
24 | 24 | ||
25 | /* Trace management. */ | 25 | /* Trace management. */ |
26 | LJ_FUNC void lj_trace_freeproto(global_State *g, GCproto *pt); | 26 | LJ_FUNC void LJ_FASTCALL lj_trace_free(global_State *g, GCtrace *T); |
27 | LJ_FUNC void lj_trace_reenableproto(GCproto *pt); | 27 | LJ_FUNC void lj_trace_reenableproto(GCproto *pt); |
28 | LJ_FUNC void lj_trace_flushproto(global_State *g, GCproto *pt); | 28 | LJ_FUNC void lj_trace_flushproto(global_State *g, GCproto *pt); |
29 | LJ_FUNC int lj_trace_flush(jit_State *J, TraceNo traceno); | 29 | LJ_FUNC void lj_trace_flush(jit_State *J, TraceNo traceno); |
30 | LJ_FUNC int lj_trace_flushall(lua_State *L); | 30 | LJ_FUNC int lj_trace_flushall(lua_State *L); |
31 | LJ_FUNC void lj_trace_initstate(global_State *g); | 31 | LJ_FUNC void lj_trace_initstate(global_State *g); |
32 | LJ_FUNC void lj_trace_freestate(global_State *g); | 32 | LJ_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 | ||