diff options
Diffstat (limited to 'src/lj_trace.c')
-rw-r--r-- | src/lj_trace.c | 37 |
1 files changed, 20 insertions, 17 deletions
diff --git a/src/lj_trace.c b/src/lj_trace.c index 03c8d1d0..e019a79f 100644 --- a/src/lj_trace.c +++ b/src/lj_trace.c | |||
@@ -431,6 +431,12 @@ static void trace_start(jit_State *J) | |||
431 | return; | 431 | return; |
432 | } | 432 | } |
433 | 433 | ||
434 | /* Ensuring forward progress for BC_ITERN can trigger hotcount again. */ | ||
435 | if (!J->parent && bc_op(*J->pc) == BC_JLOOP) { /* Already compiled. */ | ||
436 | J->state = LJ_TRACE_IDLE; /* Silently ignored. */ | ||
437 | return; | ||
438 | } | ||
439 | |||
434 | /* Get a new trace number. */ | 440 | /* Get a new trace number. */ |
435 | traceno = trace_findfree(J); | 441 | traceno = trace_findfree(J); |
436 | if (LJ_UNLIKELY(traceno == 0)) { /* No free trace? */ | 442 | if (LJ_UNLIKELY(traceno == 0)) { /* No free trace? */ |
@@ -867,7 +873,7 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) | |||
867 | ExitDataCP exd; | 873 | ExitDataCP exd; |
868 | int errcode, exitcode = J->exitcode; | 874 | int errcode, exitcode = J->exitcode; |
869 | TValue exiterr; | 875 | TValue exiterr; |
870 | const BCIns *pc; | 876 | const BCIns *pc, *retpc; |
871 | void *cf; | 877 | void *cf; |
872 | GCtrace *T; | 878 | GCtrace *T; |
873 | 879 | ||
@@ -919,22 +925,7 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) | |||
919 | } else { | 925 | } else { |
920 | trace_hotside(J, pc); | 926 | trace_hotside(J, pc); |
921 | } | 927 | } |
922 | if (bc_op(*pc) == BC_JLOOP) { | 928 | /* Return MULTRES or 0 or -17. */ |
923 | BCIns *retpc = &traceref(J, bc_d(*pc))->startins; | ||
924 | int isret = bc_isret(bc_op(*retpc)); | ||
925 | if (isret || bc_op(*retpc) == BC_ITERN) { | ||
926 | if (J->state == LJ_TRACE_RECORD) { | ||
927 | J->patchins = *pc; | ||
928 | J->patchpc = (BCIns *)pc; | ||
929 | *J->patchpc = *retpc; | ||
930 | J->bcskip = 1; | ||
931 | } else if (isret) { | ||
932 | pc = retpc; | ||
933 | setcframe_pc(cf, pc); | ||
934 | } | ||
935 | } | ||
936 | } | ||
937 | /* Return MULTRES or 0. */ | ||
938 | ERRNO_RESTORE | 929 | ERRNO_RESTORE |
939 | switch (bc_op(*pc)) { | 930 | switch (bc_op(*pc)) { |
940 | case BC_CALLM: case BC_CALLMT: | 931 | case BC_CALLM: case BC_CALLMT: |
@@ -943,6 +934,18 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) | |||
943 | return (int)((BCReg)(L->top - L->base) + 1 - bc_a(*pc) - bc_d(*pc)); | 934 | return (int)((BCReg)(L->top - L->base) + 1 - bc_a(*pc) - bc_d(*pc)); |
944 | case BC_TSETM: | 935 | case BC_TSETM: |
945 | return (int)((BCReg)(L->top - L->base) + 1 - bc_a(*pc)); | 936 | return (int)((BCReg)(L->top - L->base) + 1 - bc_a(*pc)); |
937 | case BC_JLOOP: | ||
938 | retpc = &traceref(J, bc_d(*pc))->startins; | ||
939 | if (bc_isret(bc_op(*retpc)) || bc_op(*retpc) == BC_ITERN) { | ||
940 | /* Dispatch to original ins to ensure forward progress. */ | ||
941 | if (J->state != LJ_TRACE_RECORD) return -17; | ||
942 | /* Unpatch bytecode when recording. */ | ||
943 | J->patchins = *pc; | ||
944 | J->patchpc = (BCIns *)pc; | ||
945 | *J->patchpc = *retpc; | ||
946 | J->bcskip = 1; | ||
947 | } | ||
948 | return 0; | ||
946 | default: | 949 | default: |
947 | if (bc_op(*pc) >= BC_FUNCF) | 950 | if (bc_op(*pc) >= BC_FUNCF) |
948 | return (int)((BCReg)(L->top - L->base) + 1); | 951 | return (int)((BCReg)(L->top - L->base) + 1); |