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.c42
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. */
300static 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. */
308static 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. */
300static void hotpenalty(jit_State *J, const BCIns *pc, TraceError e) 315static 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);
312setpenalty: 333setpenalty:
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. */
319static void trace_start(jit_State *J) 342static 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,