diff options
| author | Mike Pall <mike> | 2025-03-09 23:04:23 +0100 |
|---|---|---|
| committer | Mike Pall <mike> | 2025-03-09 23:04:23 +0100 |
| commit | 85c3f2fb6f59276ebf07312859a69d6d5a897f62 (patch) | |
| tree | 9938c658dad87d390cb8cc35f9ae4b90e659c16e /src | |
| parent | d508715ab657261e8437a52c1b1966c20ab1631d (diff) | |
| download | luajit-85c3f2fb6f59276ebf07312859a69d6d5a897f62.tar.gz luajit-85c3f2fb6f59276ebf07312859a69d6d5a897f62.tar.bz2 luajit-85c3f2fb6f59276ebf07312859a69d6d5a897f62.zip | |
Avoid unpatching bytecode twice after a trace flush.
Reported by Sergey Kaplun. #1345
Diffstat (limited to 'src')
| -rw-r--r-- | src/lj_trace.c | 15 |
1 files changed, 4 insertions, 11 deletions
diff --git a/src/lj_trace.c b/src/lj_trace.c index ab4a9469..c7ac0bfa 100644 --- a/src/lj_trace.c +++ b/src/lj_trace.c | |||
| @@ -205,14 +205,6 @@ static void trace_unpatch(jit_State *J, GCtrace *T) | |||
| 205 | lua_assert(op == BC_ITERL || op == BC_LOOP || bc_isret(op)); | 205 | lua_assert(op == BC_ITERL || op == BC_LOOP || bc_isret(op)); |
| 206 | *pc = T->startins; | 206 | *pc = T->startins; |
| 207 | break; | 207 | break; |
| 208 | case BC_JMP: | ||
| 209 | lua_assert(op == BC_ITERL); | ||
| 210 | pc += bc_j(*pc)+2; | ||
| 211 | if (bc_op(*pc) == BC_JITERL) { | ||
| 212 | lua_assert(traceref(J, bc_d(*pc)) == T); | ||
| 213 | *pc = T->startins; | ||
| 214 | } | ||
| 215 | break; | ||
| 216 | case BC_JFUNCF: | 208 | case BC_JFUNCF: |
| 217 | lua_assert(op == BC_FUNCF); | 209 | lua_assert(op == BC_FUNCF); |
| 218 | *pc = T->startins; | 210 | *pc = T->startins; |
| @@ -227,18 +219,19 @@ static void trace_flushroot(jit_State *J, GCtrace *T) | |||
| 227 | { | 219 | { |
| 228 | GCproto *pt = &gcref(T->startpt)->pt; | 220 | GCproto *pt = &gcref(T->startpt)->pt; |
| 229 | lua_assert(T->root == 0 && pt != NULL); | 221 | lua_assert(T->root == 0 && pt != NULL); |
| 230 | /* First unpatch any modified bytecode. */ | ||
| 231 | trace_unpatch(J, T); | ||
| 232 | /* Unlink root trace from chain anchored in prototype. */ | 222 | /* Unlink root trace from chain anchored in prototype. */ |
| 233 | if (pt->trace == T->traceno) { /* Trace is first in chain. Easy. */ | 223 | if (pt->trace == T->traceno) { /* Trace is first in chain. Easy. */ |
| 234 | pt->trace = T->nextroot; | 224 | pt->trace = T->nextroot; |
| 225 | unpatch: | ||
| 226 | /* Unpatch modified bytecode only if the trace has not been flushed. */ | ||
| 227 | trace_unpatch(J, T); | ||
| 235 | } else if (pt->trace) { /* Otherwise search in chain of root traces. */ | 228 | } else if (pt->trace) { /* Otherwise search in chain of root traces. */ |
| 236 | GCtrace *T2 = traceref(J, pt->trace); | 229 | GCtrace *T2 = traceref(J, pt->trace); |
| 237 | if (T2) { | 230 | if (T2) { |
| 238 | for (; T2->nextroot; T2 = traceref(J, T2->nextroot)) | 231 | for (; T2->nextroot; T2 = traceref(J, T2->nextroot)) |
| 239 | if (T2->nextroot == T->traceno) { | 232 | if (T2->nextroot == T->traceno) { |
| 240 | T2->nextroot = T->nextroot; /* Unlink from chain. */ | 233 | T2->nextroot = T->nextroot; /* Unlink from chain. */ |
| 241 | break; | 234 | goto unpatch; |
| 242 | } | 235 | } |
| 243 | } | 236 | } |
| 244 | } | 237 | } |
