diff options
Diffstat (limited to 'src/lj_trace.c')
-rw-r--r-- | src/lj_trace.c | 167 |
1 files changed, 67 insertions, 100 deletions
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; |