Partially implement ipairs.

Still need to handle ipairs_aux.
This commit is contained in:
Michael Munday 2016-12-29 17:37:11 -05:00
parent 12602d2a1f
commit 21f2fdfab2

View File

@ -431,12 +431,23 @@ static void build_subroutines(BuildCtx *ctx)
| stg r0, 0(r0)
|
|->vm_unwind_ff: // Unwind C stack, return from ff pcall.
| stg r0, 0(r0)
| stg r0, 0(r0)
|
| // (void *cframe)
| nill CARG1, CFRAME_RAWMASK // Assumes high 48-bits set in CFRAME_RAWMASK.
| lgr sp, CARG1
|->vm_unwind_ff_eh: // Landing pad for external unwinder.
| stg r0, 0(r0)
| stg r0, 0(r0)
| lg L:RB, SAVE_L
| lghi RD, 1+1 // Really 1+2 results, incr. later.
| lg BASE, L:RB->base
| lg DISPATCH, L:RB->glref // Setup pointer to dispatch table.
| lay DISPATCH, GG_G2DISP(DISPATCH)
| lg PC, -8(BASE) // Fetch PC of previous frame.
| load_false RA
| lg RB, 0(BASE)
| stg RA, -16(BASE) // Prepend false to error message.
| stg RB, -8(BASE)
| lghi RA, -16 // Results start at BASE+RA = BASE-16.
| set_vmstate INTERP
| j ->vm_returnc // Increments RD/MULTRES and returns.
|
|//-----------------------------------------------------------------------
|//-- Grow stack for calls -----------------------------------------------
@ -1086,19 +1097,60 @@ static void build_subroutines(BuildCtx *ctx)
|//-- Base library: iterators -------------------------------------------
|
|.ffunc_1 next
| stg r0, 0(r0)
| stg r0, 0(r0)
|
|.ffunc_1 pairs
| stg r0, 0(r0)
| stg r0, 0(r0)
|
|.ffunc_2 ipairs_aux
| stg r0, 0(r0)
| stg r0, 0(r0)
|->fff_res0:
| stg r0, 0(r0)
| stg r0, 0(r0)
|
|.ffunc_1 ipairs
| lg TAB:RB, 0(BASE)
| lgr TMPR1, TAB:RB
| checktab TAB:RB, ->fff_fallback
#if LJ_52
| lghi TMPR2, 0
| cg TMPR2, TAB:RB->metatable; jne ->fff_fallback
#endif
| lg CFUNC:RD, -16(BASE)
| cleartp CFUNC:RD
| lg CFUNC:RD, CFUNC:RD->upvalue[0]
| settp CFUNC:RD, LJ_TFUNC
| lg PC, -8(BASE)
| stg CFUNC:RD, -16(BASE)
| stg TMPR1, -8(BASE)
| llihh RD, ((int)LJ_TISNUM)>>1 // mov64 RD, ((int64_t)LJ_TISNUM<<47) // TODO: write mov64-macro, use all of TISNUM (currently this is very fragile).
| stg RD, 0(BASE)
| lghi RD, 1+3
| j ->fff_res
|
|//-- Base library: catch errors ----------------------------------------
|
|.ffunc_1 pcall
| stg r0, 0(r0)
| stg r0, 0(r0)
| la RA, 16(BASE)
| aghi NARGS:RD, -1
| lghi PC, 16+FRAME_PCALL
|1:
| llgc RB, (DISPATCH_GL(hookmask))(DISPATCH)
| srlg RB, RB, HOOK_ACTIVE_SHIFT(r0)
| nill RB, 1 // High bits already zero (from load).
| agr PC, RB // Remember active hook before pcall.
| // Note: this does a (harmless) copy of the function to the PC slot, too.
| lgr KBASE, RD
|2:
| sllg TMPR1, KBASE, 3(r0)
| lg RB, -24(TMPR1, RA)
| stg RB, -16(TMPR1, RA)
| aghi KBASE, -1
| jh <2
| j ->vm_call_dispatch
|
|.ffunc_2 xpcall
| stg r0, 0(r0)
@ -2846,9 +2898,21 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
break;
case BC_ITERC:
| stg r0, 0(r0)
| stg r0, 0(r0)
| ins_A // RA = base, (RB = nresults+1,) RC = nargs+1 (2+1)
| sllg RA, RA, 3(r0)
| la RA, 16(RA, BASE) // fb = base+2
| lg RB, -32(RA) // Copy state. fb[0] = fb[-4].
| lg RC, -24(RA) // Copy control var. fb[1] = fb[-3].
| stg RB, 0(RA)
| stg RC, 8(RA)
| lg LFUNC:RB, -40(RA) // Copy callable. fb[-2] = fb[-5]
| stg LFUNC:RB, -16(RA)
| lghi NARGS:RD, 2+1 // Handle like a regular 2-arg call.
| checkfunc LFUNC:RB, ->vmeta_call
| lgr BASE, RA
| ins_call
break;
case BC_ITERN:
| stg r0, 0(r0)
| stg r0, 0(r0)
@ -3156,16 +3220,31 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
break;
case BC_ITERL:
| stg r0, 0(r0)
| stg r0, 0(r0)
|.if JIT
| hotloop RB
|.endif
| // Fall through. Assumes BC_IITERL follows and ins_AJ is a no-op.
break;
case BC_JITERL:
| stg r0, 0(r0)
| stg r0, 0(r0)
#if !LJ_HASJIT
break;
#endif
case BC_IITERL:
| stg r0, 0(r0)
| stg r0, 0(r0)
| ins_AJ // RA = base, RD = target
| sllg RA, RA, 3(r0)
| la RA, 0(RA, BASE)
| lg RB, 0(RA)
| cghi RB, LJ_TNIL; je >1 // Stop if iterator returned nil.
if (op == BC_JITERL) {
| stg RB, -8(RA)
| j =>BC_JLOOP
} else {
| branchPC RD // Otherwise save control var + branch.
| stg RB, -8(RA)
}
|1:
| ins_next
break;
case BC_LOOP: