diff options
| author | Mike Pall <mike> | 2010-02-23 18:27:39 +0100 |
|---|---|---|
| committer | Mike Pall <mike> | 2010-02-23 19:41:32 +0100 |
| commit | 8ae2f9feaaed874e01a87df6646242b80acceabb (patch) | |
| tree | 0c0e030b007a4ef5b663476f4142f1f860ee3675 | |
| parent | d5c8fe4b90c54cbd03924d3eaf04d83dcf2f3cb8 (diff) | |
| download | luajit-8ae2f9feaaed874e01a87df6646242b80acceabb.tar.gz luajit-8ae2f9feaaed874e01a87df6646242b80acceabb.tar.bz2 luajit-8ae2f9feaaed874e01a87df6646242b80acceabb.zip | |
Randomize penalties for aborts and add blacklisting.
| -rw-r--r-- | doc/running.html | 8 | ||||
| -rw-r--r-- | src/lj_dispatch.h | 2 | ||||
| -rw-r--r-- | src/lj_jit.h | 13 | ||||
| -rw-r--r-- | src/lj_record.c | 6 | ||||
| -rw-r--r-- | src/lj_trace.c | 42 | ||||
| -rw-r--r-- | src/lj_traceerr.h | 2 |
6 files changed, 50 insertions, 23 deletions
diff --git a/doc/running.html b/doc/running.html index 247457d6..bc09d9e5 100644 --- a/doc/running.html +++ b/doc/running.html | |||
| @@ -203,7 +203,7 @@ Here are the parameters and their default settings: | |||
| 203 | <tr class="odd"> | 203 | <tr class="odd"> |
| 204 | <td class="param_name">maxsnap</td><td class="param_default">100</td><td class="param_desc">Max. number of snapshots for a trace</td></tr> | 204 | <td class="param_name">maxsnap</td><td class="param_default">100</td><td class="param_desc">Max. number of snapshots for a trace</td></tr> |
| 205 | <tr class="even separate"> | 205 | <tr class="even separate"> |
| 206 | <td class="param_name">hotloop</td><td class="param_default">57</td><td class="param_desc">Number of iterations to detect a hot loop</td></tr> | 206 | <td class="param_name">hotloop</td><td class="param_default">56</td><td class="param_desc">Number of iterations to detect a hot loop or hot call</td></tr> |
| 207 | <tr class="odd"> | 207 | <tr class="odd"> |
| 208 | <td class="param_name">hotexit</td><td class="param_default">10</td><td class="param_desc">Number of taken exits to start a side trace</td></tr> | 208 | <td class="param_name">hotexit</td><td class="param_default">10</td><td class="param_desc">Number of taken exits to start a side trace</td></tr> |
| 209 | <tr class="even"> | 209 | <tr class="even"> |
| @@ -214,9 +214,11 @@ Here are the parameters and their default settings: | |||
| 214 | <td class="param_name">loopunroll</td><td class="param_default">7</td><td class="param_desc">Max. unroll factor for loop ops in side traces</td></tr> | 214 | <td class="param_name">loopunroll</td><td class="param_default">7</td><td class="param_desc">Max. unroll factor for loop ops in side traces</td></tr> |
| 215 | <tr class="odd"> | 215 | <tr class="odd"> |
| 216 | <td class="param_name">callunroll</td><td class="param_default">3</td><td class="param_desc">Max. unroll factor for pseudo-recursive calls</td></tr> | 216 | <td class="param_name">callunroll</td><td class="param_default">3</td><td class="param_desc">Max. unroll factor for pseudo-recursive calls</td></tr> |
| 217 | <tr class="even separate"> | 217 | <tr class="even"> |
| 218 | <td class="param_name">recunroll</td><td class="param_default">2</td><td class="param_desc">Min. unroll factor for true recursion</td></tr> | ||
| 219 | <tr class="odd separate"> | ||
| 218 | <td class="param_name">sizemcode</td><td class="param_default">32</td><td class="param_desc">Size of each machine code area in KBytes (Windows: 64K)</td></tr> | 220 | <td class="param_name">sizemcode</td><td class="param_default">32</td><td class="param_desc">Size of each machine code area in KBytes (Windows: 64K)</td></tr> |
| 219 | <tr class="odd"> | 221 | <tr class="even"> |
| 220 | <td class="param_name">maxmcode</td><td class="param_default">512</td><td class="param_desc">Max. total size of all machine code areas in KBytes</td></tr> | 222 | <td class="param_name">maxmcode</td><td class="param_default">512</td><td class="param_desc">Max. total size of all machine code areas in KBytes</td></tr> |
| 221 | </table> | 223 | </table> |
| 222 | <br class="flush"> | 224 | <br class="flush"> |
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. */ |
| 183 | typedef struct HotPenalty { | 183 | typedef 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. */ |
| 193 | typedef struct BPropEntry { | 195 | typedef 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. */ | ||
| 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, |
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") | |||
| 10 | TREDEF(TRACEOV, "trace too long") | 10 | TREDEF(TRACEOV, "trace too long") |
| 11 | TREDEF(STACKOV, "trace too deep") | 11 | TREDEF(STACKOV, "trace too deep") |
| 12 | TREDEF(SNAPOV, "too many snapshots") | 12 | TREDEF(SNAPOV, "too many snapshots") |
| 13 | TREDEF(BLACKL, "blacklisted") | ||
| 13 | TREDEF(NYIBC, "NYI: bytecode %d") | 14 | TREDEF(NYIBC, "NYI: bytecode %d") |
| 14 | 15 | ||
| 15 | /* Recording loop ops. */ | 16 | /* Recording loop ops. */ |
| 16 | TREDEF(LLEAVE, "leaving loop in root trace") | 17 | TREDEF(LLEAVE, "leaving loop in root trace") |
| 17 | TREDEF(LINNER, "inner loop in root trace") | 18 | TREDEF(LINNER, "inner loop in root trace") |
| 18 | TREDEF(LUNROLL, "loop unroll limit reached") | 19 | TREDEF(LUNROLL, "loop unroll limit reached") |
| 19 | TREDEF(LBLACKL, "blacklisted loop") | ||
| 20 | 20 | ||
| 21 | /* Recording calls/returns. */ | 21 | /* Recording calls/returns. */ |
| 22 | TREDEF(BADTYPE, "bad argument type") | 22 | TREDEF(BADTYPE, "bad argument type") |
