summaryrefslogtreecommitdiff
path: root/src/lj_trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_trace.c')
-rw-r--r--src/lj_trace.c82
1 files changed, 48 insertions, 34 deletions
diff --git a/src/lj_trace.c b/src/lj_trace.c
index 6ceb5633..a0748b40 100644
--- a/src/lj_trace.c
+++ b/src/lj_trace.c
@@ -191,47 +191,58 @@ static void trace_unpatch(jit_State *J, Trace *T)
191 } 191 }
192} 192}
193 193
194/* Flush a root trace and any attached side traces. */ 194/* Free a root trace and any attached side traces. */
195void lj_trace_flush(jit_State *J, TraceNo traceno) 195static void trace_freeroot(jit_State *J, Trace *T, TraceNo traceno)
196{ 196{
197 Trace *T = NULL; 197 GCproto *pt = &gcref(T->startpt)->pt;
198 GCproto *pt; 198 TraceNo side;
199 if (traceno > 0 && traceno <= J->sizetrace) 199 lua_assert(T->root == 0 && pt != NULL);
200 T = J->trace[traceno]; 200 /* First unpatch any modified bytecode. */
201 if (T == NULL) 201 trace_unpatch(J, T);
202 return; 202 /* Unlink root trace from chain anchored in prototype. */
203 pt = &gcref(T->startpt)->pt; 203 if (pt->trace == traceno) { /* Trace is first in chain. Easy. */
204 if (T->root == 0 && pt != NULL) { 204 pt->trace = T->nextroot;
205 TraceNo side; 205 } else { /* Otherwise search in chain of root traces. */
206 /* First unpatch any modified bytecode. */ 206 Trace *T2 = J->trace[pt->trace];
207 trace_unpatch(J, T); 207 while (T2->nextroot != traceno) {
208 /* Unlink root trace from chain anchored in prototype. */ 208 lua_assert(T2->nextroot != 0);
209 if (pt->trace == traceno) { /* Trace is first in chain. Easy. */ 209 T2 = J->trace[T2->nextroot];
210 pt->trace = T->nextroot;
211 } else { /* Otherwise search in chain of root traces. */
212 Trace *T2 = J->trace[pt->trace];
213 while (T2->nextroot != traceno) {
214 lua_assert(T2->nextroot != 0);
215 T2 = J->trace[T2->nextroot];
216 }
217 T2->nextroot = T->nextroot; /* Unlink from chain. */
218 } 210 }
219 /* Free all side traces. */ 211 T2->nextroot = T->nextroot; /* Unlink from chain. */
220 for (side = T->nextside; side != 0; ) { 212 }
221 TraceNo next = J->trace[side]->nextside; 213 /* Free all side traces. */
222 trace_free(J, side); 214 for (side = T->nextside; side != 0; ) {
223 side = next; 215 TraceNo next = J->trace[side]->nextside;
216 trace_free(J, side);
217 side = next;
218 }
219 /* Now free the trace itself. */
220 trace_free(J, traceno);
221}
222
223/* Flush a root trace + side traces, if there are no links to it. */
224int lj_trace_flush(jit_State *J, TraceNo traceno)
225{
226 if (traceno > 0 && traceno < J->sizetrace) {
227 Trace *T = J->trace[traceno];
228 if (T && T->root == 0) {
229 ptrdiff_t i;
230 for (i = (ptrdiff_t)J->sizetrace-1; i > 0; i--)
231 if (i != (ptrdiff_t)traceno && J->trace[i] &&
232 J->trace[i]->root != traceno && J->trace[i]->link == traceno)
233 return 0; /* Failed: existing link to trace. */
234 trace_freeroot(J, T, traceno);
235 return 1; /* Ok. */
224 } 236 }
225 /* Now free the trace itself. */ 237 }
226 trace_free(J, traceno); 238 return 0; /* Failed. */
227 } /* Flush for non-root traces is currently ignored. */
228} 239}
229 240
230/* Flush all traces associated with a prototype. */ 241/* Flush all traces associated with a prototype. */
231void lj_trace_flushproto(global_State *g, GCproto *pt) 242void lj_trace_flushproto(global_State *g, GCproto *pt)
232{ 243{
233 while (pt->trace != 0) 244 while (pt->trace != 0)
234 lj_trace_flush(G2J(g), pt->trace); 245 trace_freeroot(G2J(g), G2J(g)->trace[pt->trace], pt->trace);
235} 246}
236 247
237/* Flush all traces. */ 248/* Flush all traces. */
@@ -241,8 +252,11 @@ int lj_trace_flushall(lua_State *L)
241 ptrdiff_t i; 252 ptrdiff_t i;
242 if ((J2G(J)->hookmask & HOOK_GC)) 253 if ((J2G(J)->hookmask & HOOK_GC))
243 return 1; 254 return 1;
244 for (i = (ptrdiff_t)J->sizetrace-1; i > 0; i--) 255 for (i = (ptrdiff_t)J->sizetrace-1; i > 0; i--) {
245 lj_trace_flush(J, (TraceNo)i); 256 Trace *T = J->trace[i];
257 if (T && T->root == 0)
258 trace_freeroot(J, T, (TraceNo)i);
259 }
246#ifdef LUA_USE_ASSERT 260#ifdef LUA_USE_ASSERT
247 for (i = 0; i < (ptrdiff_t)J->sizetrace; i++) 261 for (i = 0; i < (ptrdiff_t)J->sizetrace; i++)
248 lua_assert(J->trace[i] == NULL); 262 lua_assert(J->trace[i] == NULL);