Add support for tailcalls from internal C functions.

PPC: Fix __call metamethod for tailcalls.
This commit is contained in:
Mike Pall
2011-04-12 19:12:29 +02:00
parent 23f847f4ed
commit fa5cd010e8
12 changed files with 4180 additions and 4103 deletions

View File

@@ -411,7 +411,7 @@ static void build_subroutines(BuildCtx *ctx)
|
|->vm_call_dispatch_f:
| ins_call
| // BASE = new base, RC = nargs*8
| // BASE = new base, CARG3 = func, RC = nargs*8, PC = caller PC
|
|->vm_cpcall: // Setup protected C frame, call C.
| // (lua_State *L, lua_CFunction func, void *ud, lua_CPFunction cp)
@@ -445,18 +445,26 @@ static void build_subroutines(BuildCtx *ctx)
|->cont_dispatch:
| // BASE = meta base, RA = resultptr, RC = (nresults+1)*8
| ldr LFUNC:CARG3, [RB, FRAME_FUNC]
| ldr CARG1, [BASE, #-16] // Get continuation.
| mov CARG4, BASE
| mov BASE, RB // Restore caller BASE.
| cmp CARG1, #0
| ldr PC, [CARG4, #-12] // Restore PC from [cont|PC].
| beq >1
| ldr CARG3, LFUNC:CARG3->field_pc
| mvn INS, #~LJ_TNIL
| add CARG2, RA, RC
| ldr CARG1, [CARG4, #-16] // Get continuation.
| str INS, [CARG2, #-4] // Ensure one valid arg.
| ldr KBASE, [CARG3, #PC2PROTO(k)]
| // BASE = base, RA = resultptr, CARG4 = meta base
| bx CARG1
|
|1: // Tail call from C function.
| ldr CARG3, [BASE, FRAME_FUNC]
| sub CARG4, CARG4, #16
| sub RC, CARG4, BASE
| b ->vm_call_tail
|
|->cont_cat: // RA = resultptr, CARG4 = meta base
| ldr INS, [PC, #-4]
| sub CARG2, CARG4, #16
@@ -714,7 +722,7 @@ static void build_subroutines(BuildCtx *ctx)
| str PC, SAVE_PC
| add CARG3, RA, NARGS8:RC
| bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top)
| ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here.
| ldr LFUNC:CARG3, [RA, FRAME_FUNC] // Guaranteed to be a function here.
| ldr PC, [BASE, FRAME_PC]
| add NARGS8:RC, NARGS8:RC, #8 // Got one more argument now.
| b ->BC_CALLT2_Z
@@ -1514,10 +1522,11 @@ static void build_subroutines(BuildCtx *ctx)
| ldr CARG1, L->top
| ldr LFUNC:CARG3, [BASE, FRAME_FUNC]
| sub NARGS8:RC, CARG1, BASE
| bne >2 // Returned -1?
| bne ->vm_call_tail // Returned -1?
| ins_callt // Returned 0: retry fast path.
|
|2: // Reconstruct previous base for vmeta_call during tailcall.
|// Reconstruct previous base for vmeta_call during tailcall.
|->vm_call_tail:
| ands CARG1, PC, #FRAME_TYPE
| bic CARG2, PC, #FRAME_TYPEP
| ldreq INS, [PC, #-4]