Explicitly indicate tailcall from fast function fallback.

This commit is contained in:
Mike Pall 2010-09-02 17:16:56 +02:00
parent 44fb3ebc64
commit f708d31bcc
6 changed files with 967 additions and 965 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2393,37 +2393,38 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
|.endif |.endif
| call aword CFUNC:RD->f // (lua_State *L) | call aword CFUNC:RD->f // (lua_State *L)
| mov BASE, L:RB->base | mov BASE, L:RB->base
| // Either throws an error or recovers and returns 0 or MULTRES (+1). | // Either throws an error, or recovers and returns -1, 0 or nresults+1.
| test RD, RD; jnz ->fff_res // Returned MULTRES (already in RD). | test RD, RD; jg ->fff_res // Returned nresults+1?
|1: // Returned 0: retry fast path. |1:
| mov RD, L:RB->top | mov RA, L:RB->top
| sub RD, BASE | sub RA, BASE
| shr RD, 3 | shr RA, 3
| add NARGS:RD, 1 | test RD, RD
| lea NARGS:RD, [RA+1]
| mov LFUNC:RB, [BASE-8] | mov LFUNC:RB, [BASE-8]
| cmp dword [BASE-4], PC | jne >2 // Returned -1?
| jne >2 // Tailcalled? | ins_callt // Returned 0: retry fast path.
| ins_callt // Retry the call.
| |
|2: // Reconstruct previous base for vmeta_call. |2: // Reconstruct previous base for vmeta_call during tailcall.
| mov RA, BASE | mov RA, BASE
| test PC, FRAME_TYPE | test PC, FRAME_TYPE
| jnz >3 | jnz >3
| movzx RB, PC_RA | movzx RB, PC_RA
| not RBa // Note: ~RB = -(RB+1) | not RBa // Note: ~RB = -(RB+1)
| lea BASE, [BASE+RB*8] // base = base - (RB+1)*8 | lea BASE, [BASE+RB*8] // base = base - (RB+1)*8
| jmp ->vm_call_dispatch // Resolve again. | jmp ->vm_call_dispatch // Resolve again for tailcall.
|3: |3:
| mov RB, PC | mov RB, PC
| and RB, -8 | and RB, -8
| sub BASE, RB | sub BASE, RB
| jmp ->vm_call_dispatch // Resolve again. | jmp ->vm_call_dispatch // Resolve again for tailcall.
| |
|5: // Grow stack for fallback handler. |5: // Grow stack for fallback handler.
| mov FCARG2, LUA_MINSTACK | mov FCARG2, LUA_MINSTACK
| mov FCARG1, L:RB | mov FCARG1, L:RB
| call extern lj_state_growstack@8 // (lua_State *L, int n) | call extern lj_state_growstack@8 // (lua_State *L, int n)
| mov BASE, L:RB->base | mov BASE, L:RB->base
| xor RD, RD // Simulate a return 0.
| jmp <1 // Dumb retry (goes through ff first). | jmp <1 // Dumb retry (goes through ff first).
| |
|->fff_gcstep: // Call GC step function. |->fff_gcstep: // Call GC step function.
@ -4366,7 +4367,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse)
case BC_CALLMT: case BC_CALLMT:
| ins_AD // RA = base, RD = extra_nargs | ins_AD // RA = base, RD = extra_nargs
| add NARGS:RD, MULTRES | add NARGS:RD, MULTRES
| // Fall through. Assumes BC_CALLMT follows and ins_AD is a no-op. | // Fall through. Assumes BC_CALLT follows and ins_AD is a no-op.
break; break;
case BC_CALLT: case BC_CALLT:
| ins_AD // RA = base, RD = nargs+1 | ins_AD // RA = base, RD = nargs+1

File diff suppressed because it is too large Load Diff

View File

@ -218,7 +218,7 @@ LJLIB_ASM(tostring) LJLIB_REC(.)
L->top = o+1; /* Only keep one argument. */ L->top = o+1; /* Only keep one argument. */
if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) { if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
copyTV(L, L->base-1, mo); /* Replace callable. */ copyTV(L, L->base-1, mo); /* Replace callable. */
return FFH_RETRY; return FFH_TAILCALL;
} else { } else {
GCstr *s; GCstr *s;
if (tvisnum(o)) { if (tvisnum(o)) {

View File

@ -28,6 +28,7 @@
#define FFH_RETRY 0 #define FFH_RETRY 0
#define FFH_UNREACHABLE FFH_RETRY #define FFH_UNREACHABLE FFH_RETRY
#define FFH_RES(n) ((n)+1) #define FFH_RES(n) ((n)+1)
#define FFH_TAILCALL (-1)
LJ_FUNC TValue *lj_lib_checkany(lua_State *L, int narg); LJ_FUNC TValue *lj_lib_checkany(lua_State *L, int narg);
LJ_FUNC GCstr *lj_lib_checkstr(lua_State *L, int narg); LJ_FUNC GCstr *lj_lib_checkstr(lua_State *L, int narg);