diff options
Diffstat (limited to 'src/lj_trace.c')
-rw-r--r-- | src/lj_trace.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/src/lj_trace.c b/src/lj_trace.c index 43104be6..6f63c945 100644 --- a/src/lj_trace.c +++ b/src/lj_trace.c | |||
@@ -294,27 +294,50 @@ void lj_trace_freestate(global_State *g) | |||
294 | lj_mem_freevec(g, J->trace, J->sizetrace, Trace *); | 294 | lj_mem_freevec(g, J->trace, J->sizetrace, Trace *); |
295 | } | 295 | } |
296 | 296 | ||
297 | /* -- Trace compiler state machine ---------------------------------------- */ | 297 | /* -- Penalties and blacklisting ------------------------------------------ */ |
298 | |||
299 | /* Trivial PRNG for randomization of penalties. */ | ||
300 | static uint32_t penalty_prng(jit_State *J, int bits) | ||
301 | { | ||
302 | /* Yes, this LCG is very weak, but that doesn't matter for our use case. */ | ||
303 | J->prngstate = J->prngstate * 1103515245 + 12345; | ||
304 | return J->prngstate >> (32-bits); | ||
305 | } | ||
306 | |||
307 | /* Blacklist a bytecode instruction. */ | ||
308 | static void blacklist_pc(GCproto *pt, BCIns *pc) | ||
309 | { | ||
310 | setbc_op(pc, (int)bc_op(*pc)+(int)BC_ILOOP-(int)BC_LOOP); | ||
311 | pt->flags |= PROTO_HAS_ILOOP; | ||
312 | } | ||
298 | 313 | ||
299 | /* Penalize a bytecode instruction by bumping its hot counter. */ | 314 | /* Penalize a bytecode instruction. */ |
300 | static void hotpenalty(jit_State *J, const BCIns *pc, TraceError e) | 315 | static void penalty_pc(jit_State *J, GCproto *pt, BCIns *pc, TraceError e) |
301 | { | 316 | { |
302 | uint32_t i, val = HOTCOUNT_MIN_PENALTY; | 317 | uint32_t i, val = PENALTY_MIN; |
303 | for (i = 0; i < PENALTY_SLOTS; i++) | 318 | for (i = 0; i < PENALTY_SLOTS; i++) |
304 | if (J->penalty[i].pc == pc) { | 319 | if (mref(J->penalty[i].pc, const BCIns) == pc) { /* Cache slot found? */ |
305 | val = ((uint32_t)J->penalty[i].val << 1) + 1; | 320 | /* First try to bump its hotcount several times. */ |
306 | if (val > HOTCOUNT_MAX_PENALTY) val = HOTCOUNT_MAX_PENALTY; | 321 | val = ((uint32_t)J->penalty[i].val << 1) + |
322 | penalty_prng(J, PENALTY_RNDBITS); | ||
323 | if (val > PENALTY_MAX) { | ||
324 | blacklist_pc(pt, pc); /* Blacklist it, if that didn't help. */ | ||
325 | return; | ||
326 | } | ||
307 | goto setpenalty; | 327 | goto setpenalty; |
308 | } | 328 | } |
329 | /* Assign a new penalty cache slot. */ | ||
309 | i = J->penaltyslot; | 330 | i = J->penaltyslot; |
310 | J->penaltyslot = (J->penaltyslot + 1) & (PENALTY_SLOTS-1); | 331 | J->penaltyslot = (J->penaltyslot + 1) & (PENALTY_SLOTS-1); |
311 | J->penalty[i].pc = pc; | 332 | setmref(J->penalty[i].pc, pc); |
312 | setpenalty: | 333 | setpenalty: |
313 | J->penalty[i].val = (uint16_t)val; | 334 | J->penalty[i].val = (uint16_t)val; |
314 | J->penalty[i].reason = e; | 335 | J->penalty[i].reason = e; |
315 | hotcount_set(J2GG(J), pc+1, val); | 336 | hotcount_set(J2GG(J), pc+1, val); |
316 | } | 337 | } |
317 | 338 | ||
339 | /* -- Trace compiler state machine ---------------------------------------- */ | ||
340 | |||
318 | /* Start tracing. */ | 341 | /* Start tracing. */ |
319 | static void trace_start(jit_State *J) | 342 | static void trace_start(jit_State *J) |
320 | { | 343 | { |
@@ -433,8 +456,9 @@ static int trace_abort(jit_State *J) | |||
433 | J->state = LJ_TRACE_ASM; | 456 | J->state = LJ_TRACE_ASM; |
434 | return 1; /* Retry ASM with new MCode area. */ | 457 | return 1; /* Retry ASM with new MCode area. */ |
435 | } | 458 | } |
459 | /* Penalize or blacklist starting bytecode instruction. */ | ||
436 | if (J->parent == 0) | 460 | if (J->parent == 0) |
437 | hotpenalty(J, J->startpc, e); /* Penalize starting instruction. */ | 461 | penalty_pc(J, &gcref(J->cur.startpt)->pt, (BCIns *)J->startpc, e); |
438 | if (J->curtrace) { /* Is there anything to abort? */ | 462 | if (J->curtrace) { /* Is there anything to abort? */ |
439 | ptrdiff_t errobj = savestack(L, L->top-1); /* Stack may be resized. */ | 463 | ptrdiff_t errobj = savestack(L, L->top-1); /* Stack may be resized. */ |
440 | lj_vmevent_send(L, TRACE, | 464 | lj_vmevent_send(L, TRACE, |