aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2010-02-23 18:27:39 +0100
committerMike Pall <mike>2010-02-23 19:41:32 +0100
commit8ae2f9feaaed874e01a87df6646242b80acceabb (patch)
tree0c0e030b007a4ef5b663476f4142f1f860ee3675 /src
parentd5c8fe4b90c54cbd03924d3eaf04d83dcf2f3cb8 (diff)
downloadluajit-8ae2f9feaaed874e01a87df6646242b80acceabb.tar.gz
luajit-8ae2f9feaaed874e01a87df6646242b80acceabb.tar.bz2
luajit-8ae2f9feaaed874e01a87df6646242b80acceabb.zip
Randomize penalties for aborts and add blacklisting.
Diffstat (limited to 'src')
-rw-r--r--src/lj_dispatch.h2
-rw-r--r--src/lj_jit.h13
-rw-r--r--src/lj_record.c6
-rw-r--r--src/lj_trace.c42
-rw-r--r--src/lj_traceerr.h2
5 files changed, 45 insertions, 20 deletions
diff --git a/src/lj_dispatch.h b/src/lj_dispatch.h
index 1aa7dae0..5ef9dcd4 100644
--- a/src/lj_dispatch.h
+++ b/src/lj_dispatch.h
@@ -19,8 +19,6 @@ typedef uint16_t HotCount;
19/* Number of hot counter hash table entries (must be a power of two). */ 19/* Number of hot counter hash table entries (must be a power of two). */
20#define HOTCOUNT_SIZE 64 20#define HOTCOUNT_SIZE 64
21#define HOTCOUNT_PCMASK ((HOTCOUNT_SIZE-1)*sizeof(HotCount)) 21#define HOTCOUNT_PCMASK ((HOTCOUNT_SIZE-1)*sizeof(HotCount))
22#define HOTCOUNT_MIN_PENALTY 103
23#define HOTCOUNT_MAX_PENALTY 60000
24 22
25/* This solves a circular dependency problem -- bump as needed. Sigh. */ 23/* This solves a circular dependency problem -- bump as needed. Sigh. */
26#define GG_NUM_ASMFF 62 24#define GG_NUM_ASMFF 62
diff --git a/src/lj_jit.h b/src/lj_jit.h
index 18069ac9..23adf30d 100644
--- a/src/lj_jit.h
+++ b/src/lj_jit.h
@@ -69,14 +69,14 @@
69 _(\007, maxside, 100) /* Max. # of side traces of a root trace. */ \ 69 _(\007, maxside, 100) /* Max. # of side traces of a root trace. */ \
70 _(\007, maxsnap, 100) /* Max. # of snapshots for a trace. */ \ 70 _(\007, maxsnap, 100) /* Max. # of snapshots for a trace. */ \
71 \ 71 \
72 _(\007, hotloop, 57) /* # of iterations to detect a hot loop. */ \ 72 _(\007, hotloop, 56) /* # of iter. to detect a hot loop/call. */ \
73 _(\007, hotexit, 10) /* # of taken exits to start a side trace. */ \ 73 _(\007, hotexit, 10) /* # of taken exits to start a side trace. */ \
74 _(\007, tryside, 4) /* # of attempts to compile a side trace. */ \ 74 _(\007, tryside, 4) /* # of attempts to compile a side trace. */ \
75 \ 75 \
76 _(\012, instunroll, 4) /* Max. unroll for instable loops. */ \ 76 _(\012, instunroll, 4) /* Max. unroll for instable loops. */ \
77 _(\012, loopunroll, 7) /* Max. unroll for loop ops in side traces. */ \ 77 _(\012, loopunroll, 7) /* Max. unroll for loop ops in side traces. */ \
78 _(\012, callunroll, 3) /* Max. unroll for recursive calls. */ \ 78 _(\012, callunroll, 3) /* Max. unroll for recursive calls. */ \
79 _(\011, recunroll, 2) /* Max. unroll for true recursion. */ \ 79 _(\011, recunroll, 2) /* Min. unroll for true recursion. */ \
80 \ 80 \
81 /* Size of each machine code area (in KBytes). */ \ 81 /* Size of each machine code area (in KBytes). */ \
82 _(\011, sizemcode, JIT_P_sizemcode_DEFAULT) \ 82 _(\011, sizemcode, JIT_P_sizemcode_DEFAULT) \
@@ -181,13 +181,15 @@ typedef struct Trace {
181 181
182/* Round-robin penalty cache for bytecodes leading to aborted traces. */ 182/* Round-robin penalty cache for bytecodes leading to aborted traces. */
183typedef struct HotPenalty { 183typedef struct HotPenalty {
184 const BCIns *pc; /* Starting bytecode PC. */ 184 MRef pc; /* Starting bytecode PC. */
185 uint16_t val; /* Penalty value, i.e. hotcount start. */ 185 uint16_t val; /* Penalty value, i.e. hotcount start. */
186 uint16_t reason; /* Abort reason (really TraceErr). */ 186 uint16_t reason; /* Abort reason (really TraceErr). */
187} HotPenalty; 187} HotPenalty;
188 188
189/* Number of slots for the penalty cache. Must be a power of 2. */ 189#define PENALTY_SLOTS 64 /* Penalty cache slot. Must be a power of 2. */
190#define PENALTY_SLOTS 16 190#define PENALTY_MIN 36 /* Minimum penalty value. */
191#define PENALTY_MAX 60000 /* Maximum penalty value. */
192#define PENALTY_RNDBITS 4 /* # of random bits to add to penalty value. */
191 193
192/* Round-robin backpropagation cache for narrowing conversions. */ 194/* Round-robin backpropagation cache for narrowing conversions. */
193typedef struct BPropEntry { 195typedef struct BPropEntry {
@@ -264,6 +266,7 @@ typedef struct jit_State {
264 266
265 HotPenalty penalty[PENALTY_SLOTS]; /* Penalty slots. */ 267 HotPenalty penalty[PENALTY_SLOTS]; /* Penalty slots. */
266 uint32_t penaltyslot; /* Round-robin index into penalty slots. */ 268 uint32_t penaltyslot; /* Round-robin index into penalty slots. */
269 uint32_t prngstate; /* PRNG state for penalty randomization. */
267 270
268 BPropEntry bpropcache[BPROP_SLOTS]; /* Backpropagation cache slots. */ 271 BPropEntry bpropcache[BPROP_SLOTS]; /* Backpropagation cache slots. */
269 uint32_t bpropslot; /* Round-robin index into bpropcache slots. */ 272 uint32_t bpropslot; /* Round-robin index into bpropcache slots. */
diff --git a/src/lj_record.c b/src/lj_record.c
index 2b63b87d..1ef01386 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -419,9 +419,9 @@ static int innerloopleft(jit_State *J, const BCIns *pc)
419{ 419{
420 ptrdiff_t i; 420 ptrdiff_t i;
421 for (i = 0; i < PENALTY_SLOTS; i++) 421 for (i = 0; i < PENALTY_SLOTS; i++)
422 if (J->penalty[i].pc == pc) { 422 if (mref(J->penalty[i].pc, const BCIns) == pc) {
423 if (J->penalty[i].reason == LJ_TRERR_LLEAVE && 423 if (J->penalty[i].reason == LJ_TRERR_LLEAVE &&
424 J->penalty[i].val >= 2*HOTCOUNT_MIN_PENALTY) 424 J->penalty[i].val >= 2*PENALTY_MIN)
425 return 1; 425 return 1;
426 break; 426 break;
427 } 427 }
@@ -2149,7 +2149,7 @@ void lj_record_ins(jit_State *J)
2149 case BC_ILOOP: 2149 case BC_ILOOP:
2150 case BC_IFUNCF: 2150 case BC_IFUNCF:
2151 case BC_IFUNCV: 2151 case BC_IFUNCV:
2152 lj_trace_err(J, LJ_TRERR_LBLACKL); 2152 lj_trace_err(J, LJ_TRERR_BLACKL);
2153 break; 2153 break;
2154 2154
2155 case BC_JMP: 2155 case BC_JMP:
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,
diff --git a/src/lj_traceerr.h b/src/lj_traceerr.h
index abc53024..db7668fe 100644
--- a/src/lj_traceerr.h
+++ b/src/lj_traceerr.h
@@ -10,13 +10,13 @@ TREDEF(RECERR, "error thrown or hook called during recording")
10TREDEF(TRACEOV, "trace too long") 10TREDEF(TRACEOV, "trace too long")
11TREDEF(STACKOV, "trace too deep") 11TREDEF(STACKOV, "trace too deep")
12TREDEF(SNAPOV, "too many snapshots") 12TREDEF(SNAPOV, "too many snapshots")
13TREDEF(BLACKL, "blacklisted")
13TREDEF(NYIBC, "NYI: bytecode %d") 14TREDEF(NYIBC, "NYI: bytecode %d")
14 15
15/* Recording loop ops. */ 16/* Recording loop ops. */
16TREDEF(LLEAVE, "leaving loop in root trace") 17TREDEF(LLEAVE, "leaving loop in root trace")
17TREDEF(LINNER, "inner loop in root trace") 18TREDEF(LINNER, "inner loop in root trace")
18TREDEF(LUNROLL, "loop unroll limit reached") 19TREDEF(LUNROLL, "loop unroll limit reached")
19TREDEF(LBLACKL, "blacklisted loop")
20 20
21/* Recording calls/returns. */ 21/* Recording calls/returns. */
22TREDEF(BADTYPE, "bad argument type") 22TREDEF(BADTYPE, "bad argument type")