diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lj_asm.c | 28 | ||||
-rw-r--r-- | src/lj_jit.h | 6 |
2 files changed, 26 insertions, 8 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c index aed12043..8d852ac0 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
@@ -2840,19 +2840,24 @@ static void asm_head_root(ASMState *as) | |||
2840 | spadj = sps_adjust(as->evenspill); | 2840 | spadj = sps_adjust(as->evenspill); |
2841 | as->T->spadjust = (uint16_t)spadj; | 2841 | as->T->spadjust = (uint16_t)spadj; |
2842 | emit_addptr(as, RID_ESP, -spadj); | 2842 | emit_addptr(as, RID_ESP, -spadj); |
2843 | /* Root traces assume a checked stack for the starting proto. */ | ||
2844 | as->T->topslot = gcref(as->T->startpt)->pt.framesize; | ||
2843 | } | 2845 | } |
2844 | 2846 | ||
2845 | /* Check Lua stack size for overflow at the start of a side trace. | 2847 | /* Check Lua stack size for overflow at the start of a side trace. |
2846 | ** Stack overflow is rare, so let the regular exit handling fix this up. | 2848 | ** Stack overflow is rare, so let the regular exit handling fix this up. |
2847 | ** This is done in the context of the *parent* trace and parent exitno! | 2849 | ** This is done in the context of the *parent* trace and parent exitno! |
2848 | */ | 2850 | */ |
2849 | static void asm_checkstack(ASMState *as, BCReg topslot, Reg pbase, RegSet allow) | 2851 | static void asm_checkstack(ASMState *as, BCReg topslot, |
2852 | Reg pbase, RegSet allow, ExitNo exitno) | ||
2850 | { | 2853 | { |
2851 | /* Try to get an unused temp. register, otherwise spill/restore eax. */ | 2854 | /* Try to get an unused temp. register, otherwise spill/restore eax. */ |
2852 | Reg r = allow ? rset_pickbot(allow) : RID_EAX; | 2855 | Reg r = allow ? rset_pickbot(allow) : RID_EAX; |
2853 | emit_jcc(as, CC_B, exitstub_addr(as->J, as->J->exitno)); | 2856 | emit_jcc(as, CC_B, exitstub_addr(as->J, exitno)); |
2854 | if (allow == RSET_EMPTY) /* Restore temp. register. */ | 2857 | if (allow == RSET_EMPTY) /* Restore temp. register. */ |
2855 | emit_rmro(as, XO_MOV, r, RID_ESP, sps_scale(SPS_TEMP1)); | 2858 | emit_rmro(as, XO_MOV, r, RID_ESP, sps_scale(SPS_TEMP1)); |
2859 | else | ||
2860 | ra_modified(as, r); | ||
2856 | emit_gri(as, XG_ARITHi(XOg_CMP), r, (int32_t)(8*topslot)); | 2861 | emit_gri(as, XG_ARITHi(XOg_CMP), r, (int32_t)(8*topslot)); |
2857 | if (ra_hasreg(pbase) && pbase != r) | 2862 | if (ra_hasreg(pbase) && pbase != r) |
2858 | emit_rr(as, XO_ARITH(XOg_SUB), r, pbase); | 2863 | emit_rr(as, XO_ARITH(XOg_SUB), r, pbase); |
@@ -3029,9 +3034,13 @@ static void asm_head_side(ASMState *as) | |||
3029 | /* Continue with coalescing to fix up the broken cycle(s). */ | 3034 | /* Continue with coalescing to fix up the broken cycle(s). */ |
3030 | } | 3035 | } |
3031 | 3036 | ||
3032 | /* Check Lua stack size if frames have been added. */ | 3037 | /* Inherit top stack slot already checked by parent trace. */ |
3033 | if (as->topslot) | 3038 | as->T->topslot = as->parent->topslot; |
3034 | asm_checkstack(as, as->topslot, pbase, allow & RSET_GPR); | 3039 | if (as->topslot > as->T->topslot) { /* Need to check for higher slot? */ |
3040 | as->T->topslot = (uint8_t)as->topslot; /* Remember for child traces. */ | ||
3041 | /* Reuse the parent exit in the context of the parent trace. */ | ||
3042 | asm_checkstack(as, as->topslot, pbase, allow & RSET_GPR, as->J->exitno); | ||
3043 | } | ||
3035 | } | 3044 | } |
3036 | 3045 | ||
3037 | /* -- Tail of trace ------------------------------------------------------- */ | 3046 | /* -- Tail of trace ------------------------------------------------------- */ |
@@ -3041,7 +3050,8 @@ static void asm_head_side(ASMState *as) | |||
3041 | */ | 3050 | */ |
3042 | static void asm_tail_sync(ASMState *as) | 3051 | static void asm_tail_sync(ASMState *as) |
3043 | { | 3052 | { |
3044 | SnapShot *snap = &as->T->snap[as->T->nsnap-1]; /* Last snapshot. */ | 3053 | SnapNo snapno = as->T->nsnap-1; /* Last snapshot. */ |
3054 | SnapShot *snap = &as->T->snap[snapno]; | ||
3045 | MSize n, nent = snap->nent; | 3055 | MSize n, nent = snap->nent; |
3046 | SnapEntry *map = &as->T->snapmap[snap->mapofs]; | 3056 | SnapEntry *map = &as->T->snapmap[snap->mapofs]; |
3047 | SnapEntry *flinks = map + nent + snap->depth; | 3057 | SnapEntry *flinks = map + nent + snap->depth; |
@@ -3107,6 +3117,10 @@ static void asm_tail_sync(ASMState *as) | |||
3107 | checkmclim(as); | 3117 | checkmclim(as); |
3108 | } | 3118 | } |
3109 | lua_assert(map + nent == flinks); | 3119 | lua_assert(map + nent == flinks); |
3120 | |||
3121 | /* Root traces that grow the stack need to check the stack at the end. */ | ||
3122 | if (!as->parent && topslot) | ||
3123 | asm_checkstack(as, topslot, RID_BASE, as->freeset & RSET_GPR, snapno); | ||
3110 | } | 3124 | } |
3111 | 3125 | ||
3112 | /* Fixup the tail code. */ | 3126 | /* Fixup the tail code. */ |
@@ -3479,7 +3493,7 @@ void lj_asm_trace(jit_State *J, Trace *T) | |||
3479 | if (as->gcsteps) | 3493 | if (as->gcsteps) |
3480 | asm_gc_check(as, &as->T->snap[0]); | 3494 | asm_gc_check(as, &as->T->snap[0]); |
3481 | asm_const_remat(as); | 3495 | asm_const_remat(as); |
3482 | if (J->parent) | 3496 | if (as->parent) |
3483 | asm_head_side(as); | 3497 | asm_head_side(as); |
3484 | else | 3498 | else |
3485 | asm_head_root(as); | 3499 | asm_head_root(as); |
diff --git a/src/lj_jit.h b/src/lj_jit.h index a43611de..41a3fe9a 100644 --- a/src/lj_jit.h +++ b/src/lj_jit.h | |||
@@ -169,6 +169,10 @@ typedef struct Trace { | |||
169 | TraceNo1 nextside; /* Next side trace of same root trace. */ | 169 | TraceNo1 nextside; /* Next side trace of same root trace. */ |
170 | uint16_t nchild; /* Number of child traces (root trace only). */ | 170 | uint16_t nchild; /* Number of child traces (root trace only). */ |
171 | uint16_t spadjust; /* Stack pointer adjustment (offset in bytes). */ | 171 | uint16_t spadjust; /* Stack pointer adjustment (offset in bytes). */ |
172 | uint8_t topslot; /* Top stack slot already checked to be allocated. */ | ||
173 | uint8_t unused1; | ||
174 | uint8_t unused2; | ||
175 | uint8_t unused3; | ||
172 | #ifdef LUAJIT_USE_GDBJIT | 176 | #ifdef LUAJIT_USE_GDBJIT |
173 | void *gdbjit_entry; /* GDB JIT entry. */ | 177 | void *gdbjit_entry; /* GDB JIT entry. */ |
174 | #endif | 178 | #endif |
@@ -227,9 +231,9 @@ typedef struct jit_State { | |||
227 | 231 | ||
228 | TraceState state; /* Trace compiler state. */ | 232 | TraceState state; /* Trace compiler state. */ |
229 | 233 | ||
234 | uint64_t tailcalled; /* History of the number of successive tailcalls. */ | ||
230 | int32_t instunroll; /* Unroll counter for instable loops. */ | 235 | int32_t instunroll; /* Unroll counter for instable loops. */ |
231 | int32_t loopunroll; /* Unroll counter for loop ops in side traces. */ | 236 | int32_t loopunroll; /* Unroll counter for loop ops in side traces. */ |
232 | uint64_t tailcalled; /* History of the number of successive tailcalls. */ | ||
233 | int32_t framedepth; /* Current frame depth. */ | 237 | int32_t framedepth; /* Current frame depth. */ |
234 | int32_t retdepth; /* Return frame depth (count of RETF). */ | 238 | int32_t retdepth; /* Return frame depth (count of RETF). */ |
235 | 239 | ||