aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lj_dispatch.c11
-rw-r--r--src/lj_record.c891
2 files changed, 455 insertions, 447 deletions
diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c
index 29b06438..4629fb7e 100644
--- a/src/lj_dispatch.c
+++ b/src/lj_dispatch.c
@@ -71,7 +71,8 @@ void lj_dispatch_update(global_State *g)
71 uint8_t mode = 0; 71 uint8_t mode = 0;
72#if LJ_HASJIT 72#if LJ_HASJIT
73 mode |= (G2J(g)->flags & JIT_F_ON) ? DISPMODE_JIT : 0; 73 mode |= (G2J(g)->flags & JIT_F_ON) ? DISPMODE_JIT : 0;
74 mode |= G2J(g)->state != LJ_TRACE_IDLE ? (DISPMODE_REC|DISPMODE_INS) : 0; 74 mode |= G2J(g)->state != LJ_TRACE_IDLE ?
75 (DISPMODE_REC|DISPMODE_INS|DISPMODE_CALL) : 0;
75#endif 76#endif
76 mode |= (g->hookmask & (LUA_MASKLINE|LUA_MASKCOUNT)) ? DISPMODE_INS : 0; 77 mode |= (g->hookmask & (LUA_MASKLINE|LUA_MASKCOUNT)) ? DISPMODE_INS : 0;
77 mode |= (g->hookmask & LUA_MASKCALL) ? DISPMODE_CALL : 0; 78 mode |= (g->hookmask & LUA_MASKCALL) ? DISPMODE_CALL : 0;
@@ -398,7 +399,7 @@ static void call_init(lua_State *L, GCfunc *fn)
398 } 399 }
399} 400}
400 401
401/* Call dispatch. Used by call hooks and hot calls. */ 402/* Call dispatch. Used by call hooks, hot calls or when recording. */
402ASMFunction LJ_FASTCALL lj_dispatch_call(lua_State *L, const BCIns *pc) 403ASMFunction LJ_FASTCALL lj_dispatch_call(lua_State *L, const BCIns *pc)
403{ 404{
404 GCfunc *fn = curr_func(L); 405 GCfunc *fn = curr_func(L);
@@ -409,10 +410,14 @@ ASMFunction LJ_FASTCALL lj_dispatch_call(lua_State *L, const BCIns *pc)
409#endif 410#endif
410 call_init(L, fn); 411 call_init(L, fn);
411#if LJ_HASJIT 412#if LJ_HASJIT
413 J->L = L;
412 if ((uintptr_t)pc & 1) { /* Marker for hot call. */ 414 if ((uintptr_t)pc & 1) { /* Marker for hot call. */
413 J->L = L;
414 lj_trace_hot(J, (const BCIns *)((uintptr_t)pc & ~(uintptr_t)1)); 415 lj_trace_hot(J, (const BCIns *)((uintptr_t)pc & ~(uintptr_t)1));
415 goto out; 416 goto out;
417 } else if (J->state != LJ_TRACE_IDLE &&
418 !(g->hookmask & (HOOK_GC|HOOK_VMEVENT))) {
419 /* Record the FUNC* bytecodes, too. */
420 lj_trace_ins(J, pc-1); /* The interpreter bytecode PC is offset by 1. */
416 } 421 }
417#endif 422#endif
418 if ((g->hookmask & LUA_MASKCALL)) 423 if ((g->hookmask & LUA_MASKCALL))
diff --git a/src/lj_record.c b/src/lj_record.c
index ed882f1e..5d99f3a4 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -53,18 +53,9 @@ typedef struct RecordIndex {
53 int idxchain; /* Index indirections left or 0 for raw lookup. */ 53 int idxchain; /* Index indirections left or 0 for raw lookup. */
54} RecordIndex; 54} RecordIndex;
55 55
56/* Requested results from rec_call(). */
57enum {
58 /* Non-negative numbers are number of requested results. */
59 CALLRES_MULTI = -1, /* Return multiple results. */
60 CALLRES_TAILCALL = -2, /* Tail call. */
61 CALLRES_PENDING = -3, /* Call is pending, no results yet. */
62 CALLRES_CONT = -4 /* Continuation call. */
63};
64
65/* Forward declarations. */ 56/* Forward declarations. */
57static int rec_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm);
66static TRef rec_idx(jit_State *J, RecordIndex *ix); 58static TRef rec_idx(jit_State *J, RecordIndex *ix);
67static int rec_call(jit_State *J, BCReg func, ptrdiff_t cres, ptrdiff_t nargs);
68 59
69/* -- Sanity checks ------------------------------------------------------- */ 60/* -- Sanity checks ------------------------------------------------------- */
70 61
@@ -474,6 +465,126 @@ static void rec_loop_jit(jit_State *J, TraceNo lnk, LoopEvent ev)
474 } /* Side trace continues across a loop that's left or not entered. */ 465 } /* Side trace continues across a loop that's left or not entered. */
475} 466}
476 467
468/* -- Record calls and returns -------------------------------------------- */
469
470/* Record call. */
471static void rec_call(jit_State *J, BCReg func, ptrdiff_t nargs)
472{
473 RecordIndex ix;
474 TValue *functv = &J->L->base[func];
475 TRef trfunc, *fbase = &J->base[func];
476
477 if (!tref_isfunc(fbase[0])) { /* Resolve __call metamethod. */
478 ptrdiff_t i;
479 ix.tab = fbase[0];
480 copyTV(J->L, &ix.tabv, functv);
481 if (!rec_mm_lookup(J, &ix, MM_call) || !tref_isfunc(ix.mobj))
482 lj_trace_err(J, LJ_TRERR_NOMM);
483 for (i = ++nargs; i > 0; i--) /* Shift arguments up. */
484 fbase[i] = fbase[i-1];
485 fbase[0] = ix.mobj; /* Replace function. */
486 functv = &ix.mobjv;
487 }
488
489 /* Specialize to the runtime value of the called function. */
490 trfunc = lj_ir_kfunc(J, funcV(functv));
491 emitir(IRTG(IR_EQ, IRT_FUNC), fbase[0], trfunc);
492 fbase[0] = trfunc | TREF_FRAME;
493
494 /* Bump frame. */
495 J->frame[J->framedepth++] = SNAP_MKPC(J->pc+1);
496 if (J->framedepth > LJ_MAX_JFRAME)
497 lj_trace_err(J, LJ_TRERR_STACKOV);
498 J->base += func+1;
499 J->baseslot += func+1;
500 J->maxslot = nargs;
501}
502
503/* Record tail call. */
504static void rec_tailcall(jit_State *J, BCReg func, ptrdiff_t nargs)
505{
506 rec_call(J, func, nargs);
507 /* Move func + args down. */
508 J->framedepth--;
509 J->base -= func+1;
510 J->baseslot -= func+1;
511 memmove(&J->base[-1], &J->base[func], sizeof(TRef)*(J->maxslot+1));
512 /* Note: the new TREF_FRAME is now at J->base[-1] (even for slot #0). */
513}
514
515/* Record return. */
516static void rec_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
517{
518 TValue *frame = J->L->base - 1;
519 ptrdiff_t i;
520 for (i = 0; i < gotresults; i++)
521 getslot(J, rbase+i); /* Ensure all results have a reference. */
522 while (frame_ispcall(frame)) { /* Immediately resolve pcall() returns. */
523 BCReg cbase = (BCReg)frame_delta(frame);
524 if (--J->framedepth < 0)
525 lj_trace_err(J, LJ_TRERR_NYIRETL);
526 lua_assert(J->baseslot > 1);
527 J->base[--rbase] = TREF_TRUE; /* Prepend true to results. */
528 gotresults++;
529 rbase += cbase;
530 J->baseslot -= (BCReg)cbase;
531 J->base -= cbase;
532 frame = frame_prevd(frame);
533 }
534 if (frame_islua(frame)) { /* Return to Lua frame. */
535 BCIns callins = *(frame_pc(frame)-1);
536 ptrdiff_t nresults = bc_b(callins) ? (ptrdiff_t)bc_b(callins)-1 :gotresults;
537 BCReg cbase = bc_a(callins);
538 for (i = 0; i < nresults; i++) /* Adjust results. */
539 J->base[i-1] = i < gotresults ? J->base[rbase+i] : TREF_NIL;
540 J->maxslot = cbase+(BCReg)nresults;
541 if (J->framedepth > 0) { /* Return to a frame that is part of the trace. */
542 J->framedepth--;
543 lua_assert(J->baseslot > cbase+1);
544 J->baseslot -= cbase+1;
545 J->base -= cbase+1;
546 } else if (J->parent == 0) {
547 /* Return to lower frame would leave the loop in a root trace. */
548 lj_trace_err(J, LJ_TRERR_LLEAVE);
549 } else { /* Return to lower frame. Guard for the target we return to. */
550 GCproto *pt = funcproto(frame_func(frame - (cbase+1)));
551 TRef trpt = lj_ir_kgc(J, obj2gco(pt), IRT_PROTO);
552 TRef trpc = lj_ir_kptr(J, (void *)frame_pc(frame));
553 emitir(IRTG(IR_RETF, IRT_PTR), trpt, trpc);
554 J->retdepth++;
555 J->needsnap = 1;
556 lua_assert(J->baseslot == 1);
557 /* Shift result slots up and clear the slots of the new frame below. */
558 memmove(J->base + cbase, J->base-1, sizeof(TRef)*nresults);
559 memset(J->base-1, 0, sizeof(TRef)*(cbase+1));
560 }
561 } else if (frame_iscont(frame)) { /* Return to continuation frame. */
562 ASMFunction cont = frame_contf(frame);
563 BCReg cbase = (BCReg)frame_delta(frame);
564 if ((J->framedepth -= 2) < 0)
565 lj_trace_err(J, LJ_TRERR_NYIRETL);
566 J->baseslot -= (BCReg)cbase;
567 J->base -= cbase;
568 J->maxslot = cbase-2;
569 if (cont == lj_cont_ra) {
570 /* Copy result to destination slot. */
571 BCReg dst = bc_a(*(frame_contpc(frame)-1));
572 J->base[dst] = gotresults ? J->base[cbase+rbase] : TREF_NIL;
573 if (dst > J->maxslot) J->maxslot = dst+1;
574 } else if (cont == lj_cont_nop) {
575 /* Nothing to do here. */
576 } else if (cont == lj_cont_cat) {
577 lua_assert(0);
578 } else {
579 /* Result type already specialized. */
580 lua_assert(cont == lj_cont_condf || cont == lj_cont_condt);
581 }
582 } else {
583 lj_trace_err(J, LJ_TRERR_NYIRETL); /* NYI: handle return to C frame. */
584 }
585 lua_assert(J->baseslot >= 1);
586}
587
477/* -- Metamethod handling ------------------------------------------------- */ 588/* -- Metamethod handling ------------------------------------------------- */
478 589
479/* Prepare to record call to metamethod. */ 590/* Prepare to record call to metamethod. */
@@ -556,7 +667,9 @@ static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm)
556ok: 667ok:
557 base[0] = ix->mobj; 668 base[0] = ix->mobj;
558 copyTV(J->L, basev+0, &ix->mobjv); 669 copyTV(J->L, basev+0, &ix->mobjv);
559 return rec_call(J, func, CALLRES_CONT, 2) ? J->base[func] : 0; 670 rec_call(J, func, 2);
671 J->frame[J->framedepth++] = SNAP_MKFTSZ((func+1)*sizeof(TValue)+FRAME_CONT);
672 return 0; /* No result yet. */
560} 673}
561 674
562/* Call a comparison metamethod. */ 675/* Call a comparison metamethod. */
@@ -569,11 +682,8 @@ static void rec_mm_callcomp(jit_State *J, RecordIndex *ix, int op)
569 copyTV(J->L, tv+0, &ix->mobjv); 682 copyTV(J->L, tv+0, &ix->mobjv);
570 copyTV(J->L, tv+1, &ix->valv); 683 copyTV(J->L, tv+1, &ix->valv);
571 copyTV(J->L, tv+2, &ix->keyv); 684 copyTV(J->L, tv+2, &ix->keyv);
572 rec_call(J, func, CALLRES_CONT, 2); 685 rec_call(J, func, 2);
573 /* It doesn't matter whether this is immediately resolved or not. 686 J->frame[J->framedepth++] = SNAP_MKFTSZ((func+1)*sizeof(TValue)+FRAME_CONT);
574 ** Type specialization of the return type suffices to specialize
575 ** the control flow.
576 */
577} 687}
578 688
579/* Record call to equality comparison metamethod (for tab and udata only). */ 689/* Record call to equality comparison metamethod (for tab and udata only). */
@@ -752,11 +862,13 @@ static TRef rec_idx(jit_State *J, RecordIndex *ix)
752 if (ix->val) { 862 if (ix->val) {
753 base[3] = ix->val; 863 base[3] = ix->val;
754 copyTV(J->L, tv+3, &ix->valv); 864 copyTV(J->L, tv+3, &ix->valv);
755 rec_call(J, func, CALLRES_CONT, 3); /* mobj(tab, key, val) */ 865 rec_call(J, func, 3); /* mobj(tab, key, val) */
866 J->frame[J->framedepth++] = SNAP_MKFTSZ((func+1)*sizeof(TValue)+FRAME_CONT);
756 return 0; 867 return 0;
757 } else { 868 } else {
758 /* res = mobj(tab, key) */ 869 rec_call(J, func, 2); /* res = mobj(tab, key) */
759 return rec_call(J, func, CALLRES_CONT, 2) ? J->base[func] : 0; 870 J->frame[J->framedepth++] = SNAP_MKFTSZ((func+1)*sizeof(TValue)+FRAME_CONT);
871 return 0; /* No result yet. */
760 } 872 }
761 } 873 }
762 /* Otherwise retry lookup with metaobject. */ 874 /* Otherwise retry lookup with metaobject. */
@@ -915,19 +1027,12 @@ static TRef rec_upvalue(jit_State *J, uint32_t uv, TRef val)
915/* Data used by handlers to record a fast function. */ 1027/* Data used by handlers to record a fast function. */
916typedef struct RecordFFData { 1028typedef struct RecordFFData {
917 TValue *argv; /* Runtime argument values. */ 1029 TValue *argv; /* Runtime argument values. */
918 GCfunc *fn; /* The currently recorded function. */
919 ptrdiff_t nargs; /* Number of passed arguments. */
920 ptrdiff_t nres; /* Number of returned results (defaults to 1). */ 1030 ptrdiff_t nres; /* Number of returned results (defaults to 1). */
921 ptrdiff_t cres; /* Wanted number of call results. */
922 uint32_t data; /* Per-ffid auxiliary data (opcode, literal etc.). */ 1031 uint32_t data; /* Per-ffid auxiliary data (opcode, literal etc.). */
923 int metacall; /* True if function was resolved via __call. */
924} RecordFFData; 1032} RecordFFData;
925 1033
926/* Type of handler to record a fast function. */ 1034/* Type of handler to record a fast function. */
927typedef void (*RecordFunc)(jit_State *J, TRef *res, RecordFFData *rd); 1035typedef void (LJ_FASTCALL *RecordFunc)(jit_State *J, RecordFFData *rd);
928
929/* Avoid carrying two pointers around. */
930#define arg (res+1)
931 1036
932/* Get runtime value of int argument. */ 1037/* Get runtime value of int argument. */
933static int32_t argv2int(jit_State *J, TValue *o) 1038static int32_t argv2int(jit_State *J, TValue *o)
@@ -951,65 +1056,73 @@ static GCstr *argv2str(jit_State *J, TValue *o)
951 } 1056 }
952} 1057}
953 1058
954/* Fallback handler for all fast functions that are not recorded (yet). */ 1059/* Return number of results wanted by caller. */
955static void recff_nyi(jit_State *J, TRef *res, RecordFFData *rd) 1060static ptrdiff_t results_wanted(jit_State *J)
956{ 1061{
957 UNUSED(res); 1062 TValue *frame = J->L->base-1;
958 setfuncV(J->L, &J->errinfo, rd->fn); 1063 if (frame_islua(frame))
959 lj_trace_err_info(J, LJ_TRERR_NYIFF); 1064 return (ptrdiff_t)bc_b(frame_pc(frame)[-1]) - 1;
1065 else
1066 return -1;
960} 1067}
961 1068
962LJ_NORET static void recff_err_nyi(jit_State *J, RecordFFData *rd) 1069/* Throw error for unsupported variant of fast function. */
1070LJ_NORET static void recff_nyiu(jit_State *J)
963{ 1071{
964 setfuncV(J->L, &J->errinfo, rd->fn); 1072 setfuncV(J->L, &J->errinfo, J->fn);
965 lj_trace_err_info(J, LJ_TRERR_NYIFFU); 1073 lj_trace_err_info(J, LJ_TRERR_NYIFFU);
966} 1074}
967 1075
1076/* Fallback handler for all fast functions that are not recorded (yet). */
1077static void LJ_FASTCALL recff_nyi(jit_State *J, RecordFFData *rd)
1078{
1079 setfuncV(J->L, &J->errinfo, J->fn);
1080 lj_trace_err_info(J, LJ_TRERR_NYIFF);
1081 UNUSED(rd);
1082}
1083
968/* C functions can have arbitrary side-effects and are not recorded (yet). */ 1084/* C functions can have arbitrary side-effects and are not recorded (yet). */
969static void recff_c(jit_State *J, TRef *res, RecordFFData *rd) 1085static void LJ_FASTCALL recff_c(jit_State *J, RecordFFData *rd)
970{ 1086{
971 UNUSED(res); 1087 setfuncV(J->L, &J->errinfo, J->fn);
972 setlightudV(&J->errinfo, (void *)rd->fn->c.f);
973 lj_trace_err_info(J, LJ_TRERR_NYICF); 1088 lj_trace_err_info(J, LJ_TRERR_NYICF);
1089 UNUSED(rd);
974} 1090}
975 1091
976/* -- Base library fast functions ----------------------------------------- */ 1092/* -- Base library fast functions ----------------------------------------- */
977 1093
978static void recff_assert(jit_State *J, TRef *res, RecordFFData *rd) 1094static void LJ_FASTCALL recff_assert(jit_State *J, RecordFFData *rd)
979{ 1095{
980 /* Arguments already specialized. The interpreter throws for nil/false. */ 1096 /* Arguments already specialized. The interpreter throws for nil/false. */
981 ptrdiff_t i; 1097 rd->nres = J->maxslot; /* Pass through all arguments. */
982 for (i = 0; arg[i]; i++) /* Need to pass through all arguments. */
983 res[i] = arg[i];
984 rd->nres = i;
985 UNUSED(J);
986} 1098}
987 1099
988static void recff_type(jit_State *J, TRef *res, RecordFFData *rd) 1100static void LJ_FASTCALL recff_type(jit_State *J, RecordFFData *rd)
989{ 1101{
990 /* Arguments already specialized. Result is a constant string. Neat, huh? */ 1102 /* Arguments already specialized. Result is a constant string. Neat, huh? */
991 IRType t = tref_isinteger(arg[0]) ? IRT_NUM : tref_type(arg[0]); 1103 IRType t = tref_isinteger(J->base[0]) ? IRT_NUM : tref_type(J->base[0]);
992 res[0] = lj_ir_kstr(J, strV(&rd->fn->c.upvalue[t])); 1104 J->base[0] = lj_ir_kstr(J, strV(&J->fn->c.upvalue[t]));
1105 UNUSED(rd);
993} 1106}
994 1107
995static void recff_getmetatable(jit_State *J, TRef *res, RecordFFData *rd) 1108static void LJ_FASTCALL recff_getmetatable(jit_State *J, RecordFFData *rd)
996{ 1109{
997 TRef tr = arg[0]; 1110 TRef tr = J->base[0];
998 if (tref_istab(tr)) { 1111 if (tref_istab(tr)) {
999 RecordIndex ix; 1112 RecordIndex ix;
1000 ix.tab = tr; 1113 ix.tab = tr;
1001 copyTV(J->L, &ix.tabv, &rd->argv[0]); 1114 copyTV(J->L, &ix.tabv, &rd->argv[0]);
1002 if (rec_mm_lookup(J, &ix, MM_metatable)) 1115 if (rec_mm_lookup(J, &ix, MM_metatable))
1003 res[0] = ix.mobj; 1116 J->base[0] = ix.mobj;
1004 else 1117 else
1005 res[0] = ix.mt; 1118 J->base[0] = ix.mt;
1006 } /* else: Interpreter will throw. */ 1119 } /* else: Interpreter will throw. */
1007} 1120}
1008 1121
1009static void recff_setmetatable(jit_State *J, TRef *res, RecordFFData *rd) 1122static void LJ_FASTCALL recff_setmetatable(jit_State *J, RecordFFData *rd)
1010{ 1123{
1011 TRef tr = arg[0]; 1124 TRef tr = J->base[0];
1012 TRef mt = arg[1]; 1125 TRef mt = J->base[1];
1013 if (tref_istab(tr) && (tref_istab(mt) || (mt && tref_isnil(mt)))) { 1126 if (tref_istab(tr) && (tref_istab(mt) || (mt && tref_isnil(mt)))) {
1014 TRef fref, mtref; 1127 TRef fref, mtref;
1015 RecordIndex ix; 1128 RecordIndex ix;
@@ -1021,227 +1134,213 @@ static void recff_setmetatable(jit_State *J, TRef *res, RecordFFData *rd)
1021 emitir(IRT(IR_FSTORE, IRT_TAB), fref, mtref); 1134 emitir(IRT(IR_FSTORE, IRT_TAB), fref, mtref);
1022 if (!tref_isnil(mt)) 1135 if (!tref_isnil(mt))
1023 emitir(IRT(IR_TBAR, IRT_TAB), tr, 0); 1136 emitir(IRT(IR_TBAR, IRT_TAB), tr, 0);
1024 res[0] = tr; 1137 J->base[0] = tr;
1025 J->needsnap = 1; 1138 J->needsnap = 1;
1026 } /* else: Interpreter will throw. */ 1139 } /* else: Interpreter will throw. */
1027} 1140}
1028 1141
1029static void recff_rawget(jit_State *J, TRef *res, RecordFFData *rd) 1142static void LJ_FASTCALL recff_rawget(jit_State *J, RecordFFData *rd)
1030{ 1143{
1031 if (tref_istab(arg[0]) && arg[1]) { 1144 RecordIndex ix;
1032 RecordIndex ix; 1145 ix.tab = J->base[0]; ix.key = J->base[1];
1033 ix.tab = arg[0]; ix.key = arg[1]; ix.val = 0; ix.idxchain = 0; 1146 if (tref_istab(ix.tab) && ix.key) {
1147 ix.val = 0; ix.idxchain = 0;
1034 settabV(J->L, &ix.tabv, tabV(&rd->argv[0])); 1148 settabV(J->L, &ix.tabv, tabV(&rd->argv[0]));
1035 copyTV(J->L, &ix.keyv, &rd->argv[1]); 1149 copyTV(J->L, &ix.keyv, &rd->argv[1]);
1036 res[0] = rec_idx(J, &ix); 1150 J->base[0] = rec_idx(J, &ix);
1037 } /* else: Interpreter will throw. */ 1151 } /* else: Interpreter will throw. */
1038} 1152}
1039 1153
1040static void recff_rawset(jit_State *J, TRef *res, RecordFFData *rd) 1154static void LJ_FASTCALL recff_rawset(jit_State *J, RecordFFData *rd)
1041{ 1155{
1042 if (tref_istab(arg[0]) && arg[1] && arg[2]) { 1156 RecordIndex ix;
1043 RecordIndex ix; 1157 ix.tab = J->base[0]; ix.key = J->base[1]; ix.val = J->base[2];
1044 ix.tab = arg[0]; ix.key = arg[1]; ix.val = arg[2]; ix.idxchain = 0; 1158 if (tref_istab(ix.tab) && ix.key && ix.val) {
1159 ix.idxchain = 0;
1045 settabV(J->L, &ix.tabv, tabV(&rd->argv[0])); 1160 settabV(J->L, &ix.tabv, tabV(&rd->argv[0]));
1046 copyTV(J->L, &ix.keyv, &rd->argv[1]); 1161 copyTV(J->L, &ix.keyv, &rd->argv[1]);
1047 copyTV(J->L, &ix.valv, &rd->argv[2]); 1162 copyTV(J->L, &ix.valv, &rd->argv[2]);
1048 rec_idx(J, &ix); 1163 rec_idx(J, &ix);
1049 res[0] = arg[0]; /* Returns table. */ 1164 /* Pass through table at J->base[0] as result. */
1050 } /* else: Interpreter will throw. */ 1165 } /* else: Interpreter will throw. */
1051} 1166}
1052 1167
1053static void recff_rawequal(jit_State *J, TRef *res, RecordFFData *rd) 1168static void LJ_FASTCALL recff_rawequal(jit_State *J, RecordFFData *rd)
1054{ 1169{
1055 if (arg[0] && arg[1]) { 1170 TRef tra = J->base[0];
1056 int diff = rec_objcmp(J, arg[0], arg[1], &rd->argv[0], &rd->argv[1]); 1171 TRef trb = J->base[1];
1057 res[0] = diff ? TREF_FALSE : TREF_TRUE; 1172 if (tra && trb) {
1173 int diff = rec_objcmp(J, tra, trb, &rd->argv[0], &rd->argv[1]);
1174 J->base[0] = diff ? TREF_FALSE : TREF_TRUE;
1058 } /* else: Interpreter will throw. */ 1175 } /* else: Interpreter will throw. */
1059} 1176}
1060 1177
1061static void recff_tonumber(jit_State *J, TRef *res, RecordFFData *rd) 1178static void LJ_FASTCALL recff_tonumber(jit_State *J, RecordFFData *rd)
1062{ 1179{
1063 TRef tr = arg[0]; 1180 TRef tr = J->base[0];
1064 if (tref_isnumber_str(tr)) { 1181 if (tref_isnumber_str(tr)) {
1065 if (arg[1]) { 1182 TRef base = J->base[1];
1066 TRef base = lj_ir_toint(J, arg[1]); 1183 if (base) {
1184 base = lj_ir_toint(J, base);
1067 if (!tref_isk(base) || IR(tref_ref(base))->i != 10) 1185 if (!tref_isk(base) || IR(tref_ref(base))->i != 10)
1068 recff_err_nyi(J, rd); 1186 recff_nyiu(J);
1069 } 1187 }
1070 if (tref_isstr(tr)) 1188 if (tref_isstr(tr))
1071 tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0); 1189 tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0);
1072 } else { 1190 } else {
1073 tr = TREF_NIL; 1191 tr = TREF_NIL;
1074 } 1192 }
1075 res[0] = tr; 1193 J->base[0] = tr;
1076 UNUSED(rd); 1194 UNUSED(rd);
1077} 1195}
1078 1196
1079static void recff_tostring(jit_State *J, TRef *res, RecordFFData *rd) 1197static TValue *recff_tostring_cp(lua_State *L, lua_CFunction dummy, void *ud)
1198{
1199 jit_State *J = (jit_State *)ud;
1200 rec_tailcall(J, 0, 1);
1201 UNUSED(L); UNUSED(dummy);
1202 return NULL;
1203}
1204
1205static void LJ_FASTCALL recff_tostring(jit_State *J, RecordFFData *rd)
1080{ 1206{
1081 TRef tr = arg[0]; 1207 TRef tr = J->base[0];
1082 if (tref_isstr(tr)) { 1208 if (tref_isstr(tr)) {
1083 /* Ignore __tostring in the string base metatable. */ 1209 /* Ignore __tostring in the string base metatable. */
1084 res[0] = tr; 1210 /* Pass on result in J->base[0]. */
1085 } else { 1211 } else {
1086 RecordIndex ix; 1212 RecordIndex ix;
1087 ix.tab = tr; 1213 ix.tab = tr;
1088 copyTV(J->L, &ix.tabv, &rd->argv[0]); 1214 copyTV(J->L, &ix.tabv, &rd->argv[0]);
1089 if (rec_mm_lookup(J, &ix, MM_tostring)) { /* Has __tostring metamethod? */ 1215 if (rec_mm_lookup(J, &ix, MM_tostring)) { /* Has __tostring metamethod? */
1090 if (rd->metacall) /* Must not use kludge. */ 1216 int errcode;
1091 recff_err_nyi(J, rd); 1217 /* Temporarily insert metamethod below object. */
1092 res[0] = ix.mobj; 1218 J->base[1] = tr;
1093 copyTV(J->L, rd->argv - 1, &ix.mobjv); /* Kludge. */ 1219 J->base[0] = ix.mobj;
1094 J->framedepth--; 1220 copyTV(J->L, &rd->argv[1], &rd->argv[0]);
1095 if (rec_call(J, (BCReg)(res - J->base), 1, 1)) 1221 copyTV(J->L, &rd->argv[0], &ix.mobjv);
1096 J->framedepth++; 1222 /* Need to protect rec_tailcall because it may throw. */
1097 else 1223 errcode = lj_vm_cpcall(J->L, NULL, J, recff_tostring_cp);
1098 rd->cres = CALLRES_PENDING; 1224 /* Always undo Lua stack changes to avoid confusing the interpreter. */
1099 /* Otherwise res[0] already contains the result. */ 1225 copyTV(J->L, &rd->argv[0], &rd->argv[1]);
1226 if (errcode)
1227 lj_err_throw(J->L, errcode); /* Propagate errors. */
1228 rd->nres = -1; /* Pending call. */
1100 } else if (tref_isnumber(tr)) { 1229 } else if (tref_isnumber(tr)) {
1101 res[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0); 1230 J->base[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0);
1102 } else if (tref_ispri(tr)) { 1231 } else if (tref_ispri(tr)) {
1103 res[0] = lj_ir_kstr(J, strV(&rd->fn->c.upvalue[tref_type(tr)])); 1232 J->base[0] = lj_ir_kstr(J, strV(&J->fn->c.upvalue[tref_type(tr)]));
1104 } else { 1233 } else {
1105 recff_err_nyi(J, rd); 1234 recff_nyiu(J);
1106 } 1235 }
1107 } 1236 }
1108} 1237}
1109 1238
1110static void recff_ipairs_aux(jit_State *J, TRef *res, RecordFFData *rd) 1239static void LJ_FASTCALL recff_ipairs_aux(jit_State *J, RecordFFData *rd)
1111{ 1240{
1112 RecordIndex ix; 1241 RecordIndex ix;
1113 ix.tab = arg[0]; 1242 ix.tab = J->base[0];
1114 if (tref_istab(ix.tab)) { 1243 if (tref_istab(ix.tab)) {
1115 if (!tvisnum(&rd->argv[1])) /* No support for string coercion. */ 1244 if (!tvisnum(&rd->argv[1])) /* No support for string coercion. */
1116 lj_trace_err(J, LJ_TRERR_BADTYPE); 1245 lj_trace_err(J, LJ_TRERR_BADTYPE);
1117 setnumV(&ix.keyv, numV(&rd->argv[1])+(lua_Number)1); 1246 setnumV(&ix.keyv, numV(&rd->argv[1])+(lua_Number)1);
1118 settabV(J->L, &ix.tabv, tabV(&rd->argv[0])); 1247 settabV(J->L, &ix.tabv, tabV(&rd->argv[0]));
1119 ix.val = 0; ix.idxchain = 0; 1248 ix.val = 0; ix.idxchain = 0;
1120 ix.key = lj_ir_toint(J, arg[1]); 1249 ix.key = lj_ir_toint(J, J->base[1]);
1121 res[0] = ix.key = emitir(IRTI(IR_ADD), ix.key, lj_ir_kint(J, 1)); 1250 J->base[0] = ix.key = emitir(IRTI(IR_ADD), ix.key, lj_ir_kint(J, 1));
1122 res[1] = rec_idx(J, &ix); 1251 J->base[1] = rec_idx(J, &ix);
1123 rd->nres = tref_isnil(res[1]) ? 0 : 2; 1252 rd->nres = tref_isnil(J->base[1]) ? 0 : 2;
1124 } /* else: Interpreter will throw. */ 1253 } /* else: Interpreter will throw. */
1125} 1254}
1126 1255
1127static void recff_ipairs(jit_State *J, TRef *res, RecordFFData *rd) 1256static void LJ_FASTCALL recff_ipairs(jit_State *J, RecordFFData *rd)
1128{ 1257{
1129 TRef tab = arg[0]; 1258 TRef tab = J->base[0];
1130 if (tref_istab(tab)) { 1259 if (tref_istab(tab)) {
1131 res[0] = lj_ir_kfunc(J, funcV(&rd->fn->c.upvalue[0])); 1260 J->base[0] = lj_ir_kfunc(J, funcV(&J->fn->c.upvalue[0]));
1132 res[1] = tab; 1261 J->base[1] = tab;
1133 res[2] = lj_ir_kint(J, 0); 1262 J->base[2] = lj_ir_kint(J, 0);
1134 rd->nres = 3; 1263 rd->nres = 3;
1135 } /* else: Interpreter will throw. */ 1264 } /* else: Interpreter will throw. */
1136} 1265}
1137 1266
1138static void recff_pcall(jit_State *J, TRef *res, RecordFFData *rd) 1267static void LJ_FASTCALL recff_pcall(jit_State *J, RecordFFData *rd)
1139{ 1268{
1140 if (rd->nargs >= 1) { 1269 if (J->maxslot >= 1) {
1141 BCReg parg = (BCReg)(arg - J->base);
1142 J->pc = (const BCIns *)(sizeof(TValue) - 4 + 1270 J->pc = (const BCIns *)(sizeof(TValue) - 4 +
1143 (hook_active(J2G(J)) ? FRAME_PCALLH : FRAME_PCALL)); 1271 (hook_active(J2G(J)) ? FRAME_PCALLH : FRAME_PCALL));
1144 if (rec_call(J, parg, CALLRES_MULTI, rd->nargs - 1)) { /* Resolved call. */ 1272 rec_call(J, 0, J->maxslot - 1);
1145 res[0] = TREF_TRUE; /* Prepend true result. No need to move results. */ 1273 rd->nres = -1; /* Pending call. */
1146 rd->nres = (ptrdiff_t)J->maxslot - (ptrdiff_t)parg + 1;
1147 } else { /* Propagate pending call. */
1148 rd->cres = CALLRES_PENDING;
1149 }
1150 } /* else: Interpreter will throw. */ 1274 } /* else: Interpreter will throw. */
1151} 1275}
1152 1276
1153/* Struct to pass context across lj_vm_cpcall. */
1154typedef struct RecordXpcall {
1155 ptrdiff_t nargs;
1156 BCReg parg;
1157 int resolved;
1158} RecordXpcall;
1159
1160static TValue *recff_xpcall_cp(lua_State *L, lua_CFunction dummy, void *ud) 1277static TValue *recff_xpcall_cp(lua_State *L, lua_CFunction dummy, void *ud)
1161{ 1278{
1162 jit_State *J = L2J(L); 1279 jit_State *J = (jit_State *)ud;
1163 RecordXpcall *rx = (RecordXpcall *)ud; 1280 rec_call(J, 1, J->maxslot - 2);
1164 UNUSED(dummy); 1281 UNUSED(L); UNUSED(dummy);
1165 rx->resolved = rec_call(J, rx->parg, CALLRES_MULTI, rx->nargs);
1166 return NULL; 1282 return NULL;
1167} 1283}
1168 1284
1169static void recff_xpcall(jit_State *J, TRef *res, RecordFFData *rd) 1285static void LJ_FASTCALL recff_xpcall(jit_State *J, RecordFFData *rd)
1170{ 1286{
1171 if (rd->nargs >= 2) { 1287 if (J->maxslot >= 2) {
1172 RecordXpcall rx;
1173 BCReg parg = (BCReg)(arg - J->base) + 1;
1174 TRef tmp;
1175 TValue argv0, argv1; 1288 TValue argv0, argv1;
1176 ptrdiff_t oargv; 1289 TRef tmp;
1177 int errcode; 1290 int errcode;
1178 /* Swap function and traceback. */ 1291 /* Swap function and traceback. */
1179 tmp = arg[0]; arg[0] = arg[1]; arg[1] = tmp; 1292 tmp = J->base[0]; J->base[0] = J->base[1]; J->base[1] = tmp;
1180 copyTV(J->L, &argv0, &rd->argv[0]); 1293 copyTV(J->L, &argv0, &rd->argv[0]);
1181 copyTV(J->L, &argv1, &rd->argv[1]); 1294 copyTV(J->L, &argv1, &rd->argv[1]);
1182 copyTV(J->L, &rd->argv[0], &argv1); 1295 copyTV(J->L, &rd->argv[0], &argv1);
1183 copyTV(J->L, &rd->argv[1], &argv0); 1296 copyTV(J->L, &rd->argv[1], &argv0);
1184 oargv = savestack(J->L, rd->argv);
1185 J->pc = (const BCIns *)(2*sizeof(TValue) - 4 + 1297 J->pc = (const BCIns *)(2*sizeof(TValue) - 4 +
1186 (hook_active(J2G(J)) ? FRAME_PCALLH : FRAME_PCALL)); 1298 (hook_active(J2G(J)) ? FRAME_PCALLH : FRAME_PCALL));
1187 /* Need to protect rec_call because the recorder may throw. */ 1299 /* Need to protect rec_call because it may throw. */
1188 rx.parg = parg; 1300 errcode = lj_vm_cpcall(J->L, NULL, J, recff_xpcall_cp);
1189 rx.nargs = rd->nargs - 2;
1190 errcode = lj_vm_cpcall(J->L, NULL, &rx, recff_xpcall_cp);
1191 /* Always undo Lua stack swap to avoid confusing the interpreter. */ 1301 /* Always undo Lua stack swap to avoid confusing the interpreter. */
1192 rd->argv = restorestack(J->L, oargv); /* Stack may have been resized. */
1193 copyTV(J->L, &rd->argv[0], &argv0); 1302 copyTV(J->L, &rd->argv[0], &argv0);
1194 copyTV(J->L, &rd->argv[1], &argv1); 1303 copyTV(J->L, &rd->argv[1], &argv1);
1195 if (errcode) 1304 if (errcode)
1196 lj_err_throw(J->L, errcode); /* Propagate errors. */ 1305 lj_err_throw(J->L, errcode); /* Propagate errors. */
1197 if (rx.resolved) { /* Resolved call. */ 1306 rd->nres = -1; /* Pending call. */
1198 ptrdiff_t i, nres = (ptrdiff_t)J->maxslot - (ptrdiff_t)parg;
1199 rd->nres = nres + 1;
1200 res[0] = TREF_TRUE; /* Prepend true result. */
1201 for (i = 1; i <= nres; i++) /* Move results down. */
1202 res[i] = res[i+1];
1203 } else { /* Propagate pending call. */
1204 rd->cres = CALLRES_PENDING;
1205 }
1206 } /* else: Interpreter will throw. */ 1307 } /* else: Interpreter will throw. */
1207} 1308}
1208 1309
1209/* -- Math library fast functions ----------------------------------------- */ 1310/* -- Math library fast functions ----------------------------------------- */
1210 1311
1211static void recff_math_abs(jit_State *J, TRef *res, RecordFFData *rd) 1312static void LJ_FASTCALL recff_math_abs(jit_State *J, RecordFFData *rd)
1212{ 1313{
1213 TRef tr = lj_ir_tonum(J, arg[0]); 1314 TRef tr = lj_ir_tonum(J, J->base[0]);
1214 res[0] = emitir(IRTN(IR_ABS), tr, lj_ir_knum_abs(J)); 1315 J->base[0] = emitir(IRTN(IR_ABS), tr, lj_ir_knum_abs(J));
1215 UNUSED(rd); 1316 UNUSED(rd);
1216} 1317}
1217 1318
1218/* Record rounding functions math.floor and math.ceil. */ 1319/* Record rounding functions math.floor and math.ceil. */
1219static void recff_math_round(jit_State *J, TRef *res, RecordFFData *rd) 1320static void LJ_FASTCALL recff_math_round(jit_State *J, RecordFFData *rd)
1220{ 1321{
1221 if (tref_isinteger(arg[0])) 1322 if (!tref_isinteger(J->base[0])) /* Pass through integers unmodified. */
1222 res[0] = arg[0]; 1323 J->base[0] = emitir(IRTN(IR_FPMATH), lj_ir_tonum(J, J->base[0]), rd->data);
1223 else
1224 res[0] = emitir(IRTN(IR_FPMATH), lj_ir_tonum(J, arg[0]), rd->data);
1225 /* Note: result is integral (or NaN/Inf), but may not fit into an integer. */ 1324 /* Note: result is integral (or NaN/Inf), but may not fit into an integer. */
1226} 1325}
1227 1326
1228/* Record unary math.* functions, mapped to IR_FPMATH opcode. */ 1327/* Record unary math.* functions, mapped to IR_FPMATH opcode. */
1229static void recff_math_unary(jit_State *J, TRef *res, RecordFFData *rd) 1328static void LJ_FASTCALL recff_math_unary(jit_State *J, RecordFFData *rd)
1230{ 1329{
1231 res[0] = emitir(IRTN(IR_FPMATH), lj_ir_tonum(J, arg[0]), rd->data); 1330 J->base[0] = emitir(IRTN(IR_FPMATH), lj_ir_tonum(J, J->base[0]), rd->data);
1232} 1331}
1233 1332
1234/* Record binary math.* functions math.atan2 and math.ldexp. */ 1333/* Record binary math.* functions math.atan2 and math.ldexp. */
1235static void recff_math_binary(jit_State *J, TRef *res, RecordFFData *rd) 1334static void LJ_FASTCALL recff_math_binary(jit_State *J, RecordFFData *rd)
1236{ 1335{
1237 TRef tr = lj_ir_tonum(J, arg[0]); 1336 TRef tr = lj_ir_tonum(J, J->base[0]);
1238 res[0] = emitir(IRTN(rd->data), tr, lj_ir_tonum(J, arg[1])); 1337 J->base[0] = emitir(IRTN(rd->data), tr, lj_ir_tonum(J, J->base[1]));
1239} 1338}
1240 1339
1241/* Record math.asin, math.acos, math.atan. */ 1340/* Record math.asin, math.acos, math.atan. */
1242static void recff_math_atrig(jit_State *J, TRef *res, RecordFFData *rd) 1341static void LJ_FASTCALL recff_math_atrig(jit_State *J, RecordFFData *rd)
1243{ 1342{
1244 TRef y = lj_ir_tonum(J, arg[0]); 1343 TRef y = lj_ir_tonum(J, J->base[0]);
1245 TRef x = lj_ir_knum_one(J); 1344 TRef x = lj_ir_knum_one(J);
1246 uint32_t ffid = rd->data; 1345 uint32_t ffid = rd->data;
1247 if (ffid != FF_math_atan) { 1346 if (ffid != FF_math_atan) {
@@ -1250,66 +1349,70 @@ static void recff_math_atrig(jit_State *J, TRef *res, RecordFFData *rd)
1250 tmp = emitir(IRTN(IR_FPMATH), tmp, IRFPM_SQRT); 1349 tmp = emitir(IRTN(IR_FPMATH), tmp, IRFPM_SQRT);
1251 if (ffid == FF_math_asin) { x = tmp; } else { x = y; y = tmp; } 1350 if (ffid == FF_math_asin) { x = tmp; } else { x = y; y = tmp; }
1252 } 1351 }
1253 res[0] = emitir(IRTN(IR_ATAN2), y, x); 1352 J->base[0] = emitir(IRTN(IR_ATAN2), y, x);
1254} 1353}
1255 1354
1256static void recff_math_htrig(jit_State *J, TRef *res, RecordFFData *rd) 1355static void LJ_FASTCALL recff_math_htrig(jit_State *J, RecordFFData *rd)
1257{ 1356{
1258 TRef tr = lj_ir_tonum(J, arg[0]); 1357 TRef tr = lj_ir_tonum(J, J->base[0]);
1259 res[0] = lj_ir_call(J, rd->data, tr); 1358 J->base[0] = lj_ir_call(J, rd->data, tr);
1260} 1359}
1261 1360
1262static void recff_math_modf(jit_State *J, TRef *res, RecordFFData *rd) 1361static void LJ_FASTCALL recff_math_modf(jit_State *J, RecordFFData *rd)
1263{ 1362{
1264 TRef tr = arg[0]; 1363 TRef tr = J->base[0];
1265 if (tref_isinteger(tr)) { 1364 if (tref_isinteger(tr)) {
1266 res[0] = tr; 1365 J->base[0] = tr;
1267 res[1] = lj_ir_kint(J, 0); 1366 J->base[1] = lj_ir_kint(J, 0);
1268 } else { 1367 } else {
1368 TRef trt;
1269 tr = lj_ir_tonum(J, tr); 1369 tr = lj_ir_tonum(J, tr);
1270 res[0] = emitir(IRTN(IR_FPMATH), tr, IRFPM_TRUNC); 1370 trt = emitir(IRTN(IR_FPMATH), tr, IRFPM_TRUNC);
1271 res[1] = emitir(IRTN(IR_SUB), tr, res[0]); 1371 J->base[0] = trt;
1372 J->base[1] = emitir(IRTN(IR_SUB), tr, trt);
1272 } 1373 }
1273 rd->nres = 2; 1374 rd->nres = 2;
1274} 1375}
1275 1376
1276static void recff_math_degrad(jit_State *J, TRef *res, RecordFFData *rd) 1377static void LJ_FASTCALL recff_math_degrad(jit_State *J, RecordFFData *rd)
1277{ 1378{
1278 TRef tr = lj_ir_tonum(J, arg[0]); 1379 TRef tr = lj_ir_tonum(J, J->base[0]);
1279 res[0] = emitir(IRTN(IR_MUL), tr, lj_ir_knum(J, numV(&rd->fn->c.upvalue[0]))); 1380 TRef trm = lj_ir_knum(J, numV(&J->fn->c.upvalue[0]));
1381 J->base[0] = emitir(IRTN(IR_MUL), tr, trm);
1382 UNUSED(rd);
1280} 1383}
1281 1384
1282static void recff_math_pow(jit_State *J, TRef *res, RecordFFData *rd) 1385static void LJ_FASTCALL recff_math_pow(jit_State *J, RecordFFData *rd)
1283{ 1386{
1284 TRef tr = lj_ir_tonum(J, arg[0]); 1387 TRef tr = lj_ir_tonum(J, J->base[0]);
1285 if (!tref_isnumber_str(arg[1])) 1388 if (!tref_isnumber_str(J->base[1]))
1286 lj_trace_err(J, LJ_TRERR_BADTYPE); 1389 lj_trace_err(J, LJ_TRERR_BADTYPE);
1287 res[0] = lj_opt_narrow_pow(J, tr, arg[1], &rd->argv[1]); 1390 J->base[0] = lj_opt_narrow_pow(J, tr, J->base[1], &rd->argv[1]);
1288 UNUSED(rd); 1391 UNUSED(rd);
1289} 1392}
1290 1393
1291static void recff_math_minmax(jit_State *J, TRef *res, RecordFFData *rd) 1394static void LJ_FASTCALL recff_math_minmax(jit_State *J, RecordFFData *rd)
1292{ 1395{
1293 TRef tr = lj_ir_tonum(J, arg[0]); 1396 TRef tr = lj_ir_tonum(J, J->base[0]);
1294 uint32_t op = rd->data; 1397 uint32_t op = rd->data;
1295 BCReg i; 1398 BCReg i;
1296 for (i = 1; arg[i]; i++) 1399 for (i = 1; J->base[i] != 0; i++)
1297 tr = emitir(IRTN(op), tr, lj_ir_tonum(J, arg[i])); 1400 tr = emitir(IRTN(op), tr, lj_ir_tonum(J, J->base[i]));
1298 res[0] = tr; 1401 J->base[0] = tr;
1299} 1402}
1300 1403
1301static void recff_math_random(jit_State *J, TRef *res, RecordFFData *rd) 1404static void LJ_FASTCALL recff_math_random(jit_State *J, RecordFFData *rd)
1302{ 1405{
1303 GCudata *ud = udataV(&rd->fn->c.upvalue[0]); 1406 GCudata *ud = udataV(&J->fn->c.upvalue[0]);
1304 TRef tr, one; 1407 TRef tr, one;
1305 lj_ir_kgc(J, obj2gco(ud), IRT_UDATA); /* Prevent collection. */ 1408 lj_ir_kgc(J, obj2gco(ud), IRT_UDATA); /* Prevent collection. */
1306 tr = lj_ir_call(J, IRCALL_lj_math_random_step, lj_ir_kptr(J, uddata(ud))); 1409 tr = lj_ir_call(J, IRCALL_lj_math_random_step, lj_ir_kptr(J, uddata(ud)));
1307 one = lj_ir_knum_one(J); 1410 one = lj_ir_knum_one(J);
1308 tr = emitir(IRTN(IR_SUB), tr, one); 1411 tr = emitir(IRTN(IR_SUB), tr, one);
1309 if (arg[0]) { 1412 if (J->base[0]) {
1310 TRef tr1 = lj_ir_tonum(J, arg[0]); 1413 TRef tr1 = lj_ir_tonum(J, J->base[0]);
1311 if (arg[1]) { /* d = floor(d*(r2-r1+1.0)) + r1 */ 1414 if (J->base[1]) { /* d = floor(d*(r2-r1+1.0)) + r1 */
1312 TRef tr2 = lj_ir_tonum(J, arg[1]); 1415 TRef tr2 = lj_ir_tonum(J, J->base[1]);
1313 tr2 = emitir(IRTN(IR_SUB), tr2, tr1); 1416 tr2 = emitir(IRTN(IR_SUB), tr2, tr1);
1314 tr2 = emitir(IRTN(IR_ADD), tr2, one); 1417 tr2 = emitir(IRTN(IR_ADD), tr2, one);
1315 tr = emitir(IRTN(IR_MUL), tr, tr2); 1418 tr = emitir(IRTN(IR_MUL), tr, tr2);
@@ -1321,69 +1424,82 @@ static void recff_math_random(jit_State *J, TRef *res, RecordFFData *rd)
1321 tr = emitir(IRTN(IR_ADD), tr, one); 1424 tr = emitir(IRTN(IR_ADD), tr, one);
1322 } 1425 }
1323 } 1426 }
1324 res[0] = tr; 1427 J->base[0] = tr;
1428 UNUSED(rd);
1325} 1429}
1326 1430
1327/* -- Bit library fast functions ------------------------------------------ */ 1431/* -- Bit library fast functions ------------------------------------------ */
1328 1432
1329/* Record unary bit.tobit, bit.bnot, bit.bswap. */ 1433/* Record unary bit.tobit, bit.bnot, bit.bswap. */
1330static void recff_bit_unary(jit_State *J, TRef *res, RecordFFData *rd) 1434static void LJ_FASTCALL recff_bit_unary(jit_State *J, RecordFFData *rd)
1331{ 1435{
1332 TRef tr = lj_ir_tobit(J, arg[0]); 1436 TRef tr = lj_ir_tobit(J, J->base[0]);
1333 res[0] = (rd->data == IR_TOBIT) ? tr : emitir(IRTI(rd->data), tr, 0); 1437 J->base[0] = (rd->data == IR_TOBIT) ? tr : emitir(IRTI(rd->data), tr, 0);
1334} 1438}
1335 1439
1336/* Record N-ary bit.band, bit.bor, bit.bxor. */ 1440/* Record N-ary bit.band, bit.bor, bit.bxor. */
1337static void recff_bit_nary(jit_State *J, TRef *res, RecordFFData *rd) 1441static void LJ_FASTCALL recff_bit_nary(jit_State *J, RecordFFData *rd)
1338{ 1442{
1339 TRef tr = lj_ir_tobit(J, arg[0]); 1443 TRef tr = lj_ir_tobit(J, J->base[0]);
1340 uint32_t op = rd->data; 1444 uint32_t op = rd->data;
1341 BCReg i; 1445 BCReg i;
1342 for (i = 1; arg[i]; i++) 1446 for (i = 1; J->base[i] != 0; i++)
1343 tr = emitir(IRTI(op), tr, lj_ir_tobit(J, arg[i])); 1447 tr = emitir(IRTI(op), tr, lj_ir_tobit(J, J->base[i]));
1344 res[0] = tr; 1448 J->base[0] = tr;
1345} 1449}
1346 1450
1347/* Record bit shifts. */ 1451/* Record bit shifts. */
1348static void recff_bit_shift(jit_State *J, TRef *res, RecordFFData *rd) 1452static void LJ_FASTCALL recff_bit_shift(jit_State *J, RecordFFData *rd)
1349{ 1453{
1350 TRef tr = lj_ir_tobit(J, arg[0]); 1454 TRef tr = lj_ir_tobit(J, J->base[0]);
1351 TRef tsh = lj_ir_tobit(J, arg[1]); 1455 TRef tsh = lj_ir_tobit(J, J->base[1]);
1352#if !LJ_TARGET_MASKEDSHIFT 1456#if !LJ_TARGET_MASKEDSHIFT
1353 if (!tref_isk(tsh)) 1457 if (!tref_isk(tsh))
1354 tsh = emitir(IRTI(IR_BAND), tsh, lj_ir_kint(J, 31)); 1458 tsh = emitir(IRTI(IR_BAND), tsh, lj_ir_kint(J, 31));
1355#endif 1459#endif
1356 res[0] = emitir(IRTI(rd->data), tr, tsh); 1460 J->base[0] = emitir(IRTI(rd->data), tr, tsh);
1357} 1461}
1358 1462
1359/* -- String library fast functions --------------------------------------- */ 1463/* -- String library fast functions --------------------------------------- */
1360 1464
1361static void recff_string_len(jit_State *J, TRef *res, RecordFFData *rd) 1465static void LJ_FASTCALL recff_string_len(jit_State *J, RecordFFData *rd)
1362{ 1466{
1363 res[0] = emitir(IRTI(IR_FLOAD), lj_ir_tostr(J, arg[0]), IRFL_STR_LEN); 1467 J->base[0] = emitir(IRTI(IR_FLOAD), lj_ir_tostr(J, J->base[0]), IRFL_STR_LEN);
1364 UNUSED(rd); 1468 UNUSED(rd);
1365} 1469}
1366 1470
1367/* Handle string.byte (rd->data = 0) and string.sub (rd->data = 1). */ 1471/* Handle string.byte (rd->data = 0) and string.sub (rd->data = 1). */
1368static void recff_string_range(jit_State *J, TRef *res, RecordFFData *rd) 1472static void LJ_FASTCALL recff_string_range(jit_State *J, RecordFFData *rd)
1369{ 1473{
1370 TRef trstr = lj_ir_tostr(J, arg[0]); 1474 TRef trstr = lj_ir_tostr(J, J->base[0]);
1371 TRef trlen = emitir(IRTI(IR_FLOAD), trstr, IRFL_STR_LEN); 1475 TRef trlen = emitir(IRTI(IR_FLOAD), trstr, IRFL_STR_LEN);
1372 TRef tr0 = lj_ir_kint(J, 0); 1476 TRef tr0 = lj_ir_kint(J, 0);
1373 TRef trstart, trend; 1477 TRef trstart, trend;
1374 GCstr *str = argv2str(J, &rd->argv[0]); 1478 GCstr *str = argv2str(J, &rd->argv[0]);
1375 int32_t start, end; 1479 int32_t start, end;
1376 if (rd->data) { /* string.sub(str, start [,end]) */ 1480 if (rd->data) { /* string.sub(str, start [,end]) */
1377 trstart = lj_ir_toint(J, arg[1]);
1378 trend = tref_isnil(arg[2]) ? lj_ir_kint(J, -1) : lj_ir_toint(J, arg[2]);
1379 start = argv2int(J, &rd->argv[1]); 1481 start = argv2int(J, &rd->argv[1]);
1380 end = tref_isnil(arg[2]) ? -1 : argv2int(J, &rd->argv[2]); 1482 trstart = lj_ir_toint(J, J->base[1]);
1483 trend = J->base[2];
1484 if (tref_isnil(trend)) {
1485 trend = lj_ir_kint(J, -1);
1486 end = -1;
1487 } else {
1488 trend = lj_ir_toint(J, trend);
1489 end = argv2int(J, &rd->argv[2]);
1490 }
1381 } else { /* string.byte(str, [,start [,end]]) */ 1491 } else { /* string.byte(str, [,start [,end]]) */
1382 if (arg[1]) { 1492 if (J->base[1]) {
1383 trstart = lj_ir_toint(J, arg[1]);
1384 trend = tref_isnil(arg[2]) ? trstart : lj_ir_toint(J, arg[2]);
1385 start = argv2int(J, &rd->argv[1]); 1493 start = argv2int(J, &rd->argv[1]);
1386 end = tref_isnil(arg[2]) ? start : argv2int(J, &rd->argv[2]); 1494 trstart = lj_ir_toint(J, J->base[1]);
1495 trend = J->base[2];
1496 if (tref_isnil(trend)) {
1497 trend = trstart;
1498 end = start;
1499 } else {
1500 trend = lj_ir_toint(J, trend);
1501 end = argv2int(J, &rd->argv[2]);
1502 }
1387 } else { 1503 } else {
1388 trend = trstart = lj_ir_kint(J, 1); 1504 trend = trstart = lj_ir_kint(J, 1);
1389 end = start = 1; 1505 end = start = 1;
@@ -1426,23 +1542,23 @@ static void recff_string_range(jit_State *J, TRef *res, RecordFFData *rd)
1426 TRef trptr, trslen = emitir(IRTI(IR_SUB), trend, trstart); 1542 TRef trptr, trslen = emitir(IRTI(IR_SUB), trend, trstart);
1427 emitir(IRTGI(IR_GE), trslen, tr0); 1543 emitir(IRTGI(IR_GE), trslen, tr0);
1428 trptr = emitir(IRT(IR_STRREF, IRT_PTR), trstr, trstart); 1544 trptr = emitir(IRT(IR_STRREF, IRT_PTR), trstr, trstart);
1429 res[0] = emitir(IRT(IR_SNEW, IRT_STR), trptr, trslen); 1545 J->base[0] = emitir(IRT(IR_SNEW, IRT_STR), trptr, trslen);
1430 } else { /* Range underflow: return empty string. */ 1546 } else { /* Range underflow: return empty string. */
1431 emitir(IRTGI(IR_LT), trend, trstart); 1547 emitir(IRTGI(IR_LT), trend, trstart);
1432 res[0] = lj_ir_kstr(J, lj_str_new(J->L, strdata(str), 0)); 1548 J->base[0] = lj_ir_kstr(J, lj_str_new(J->L, strdata(str), 0));
1433 } 1549 }
1434 } else { /* Return string.byte result(s). */ 1550 } else { /* Return string.byte result(s). */
1435 ptrdiff_t i, len = end - start; 1551 ptrdiff_t i, len = end - start;
1436 if (len > 0) { 1552 if (len > 0) {
1437 TRef trslen = emitir(IRTI(IR_SUB), trend, trstart); 1553 TRef trslen = emitir(IRTI(IR_SUB), trend, trstart);
1438 emitir(IRTGI(IR_EQ), trslen, lj_ir_kint(J, len)); 1554 emitir(IRTGI(IR_EQ), trslen, lj_ir_kint(J, len));
1439 if (res + len > J->slot + LJ_MAX_JSLOTS) 1555 if (J->baseslot + len > LJ_MAX_JSLOTS)
1440 lj_trace_err(J, LJ_TRERR_STACKOV); 1556 lj_trace_err_info(J, LJ_TRERR_STACKOV);
1441 rd->nres = len; 1557 rd->nres = len;
1442 for (i = 0; i < len; i++) { 1558 for (i = 0; i < len; i++) {
1443 TRef tmp = emitir(IRTI(IR_ADD), trstart, lj_ir_kint(J, i)); 1559 TRef tmp = emitir(IRTI(IR_ADD), trstart, lj_ir_kint(J, i));
1444 tmp = emitir(IRT(IR_STRREF, IRT_PTR), trstr, tmp); 1560 tmp = emitir(IRT(IR_STRREF, IRT_PTR), trstr, tmp);
1445 res[i] = emitir(IRT(IR_XLOAD, IRT_U8), tmp, IRXLOAD_READONLY); 1561 J->base[i] = emitir(IRT(IR_XLOAD, IRT_U8), tmp, IRXLOAD_READONLY);
1446 } 1562 }
1447 } else { /* Empty range or range underflow: return no results. */ 1563 } else { /* Empty range or range underflow: return no results. */
1448 emitir(IRTGI(IR_LE), trend, trstart); 1564 emitir(IRTGI(IR_LE), trend, trstart);
@@ -1453,62 +1569,63 @@ static void recff_string_range(jit_State *J, TRef *res, RecordFFData *rd)
1453 1569
1454/* -- Table library fast functions ---------------------------------------- */ 1570/* -- Table library fast functions ---------------------------------------- */
1455 1571
1456static void recff_table_getn(jit_State *J, TRef *res, RecordFFData *rd) 1572static void LJ_FASTCALL recff_table_getn(jit_State *J, RecordFFData *rd)
1457{ 1573{
1458 if (tref_istab(arg[0])) { 1574 if (tref_istab(J->base[0]))
1459 res[0] = lj_ir_call(J, IRCALL_lj_tab_len, arg[0]); 1575 J->base[0] = lj_ir_call(J, IRCALL_lj_tab_len, J->base[0]);
1460 } /* else: Interpreter will throw. */ 1576 /* else: Interpreter will throw. */
1461 UNUSED(rd); 1577 UNUSED(rd);
1462} 1578}
1463 1579
1464static void recff_table_remove(jit_State *J, TRef *res, RecordFFData *rd) 1580static void LJ_FASTCALL recff_table_remove(jit_State *J, RecordFFData *rd)
1465{ 1581{
1466 if (tref_istab(arg[0])) { 1582 TRef tab = J->base[0];
1467 if (!arg[1] || tref_isnil(arg[1])) { /* Simple pop: t[#t] = nil */ 1583 rd->nres = 0;
1468 TRef trlen = lj_ir_call(J, IRCALL_lj_tab_len, arg[0]); 1584 if (tref_istab(tab)) {
1585 if (!J->base[1] || tref_isnil(J->base[1])) { /* Simple pop: t[#t] = nil */
1586 TRef trlen = lj_ir_call(J, IRCALL_lj_tab_len, tab);
1469 GCtab *t = tabV(&rd->argv[0]); 1587 GCtab *t = tabV(&rd->argv[0]);
1470 MSize len = lj_tab_len(t); 1588 MSize len = lj_tab_len(t);
1471 emitir(IRTGI(len ? IR_NE : IR_EQ), trlen, lj_ir_kint(J, 0)); 1589 emitir(IRTGI(len ? IR_NE : IR_EQ), trlen, lj_ir_kint(J, 0));
1472 if (len) { 1590 if (len) {
1473 RecordIndex ix; 1591 RecordIndex ix;
1474 ix.tab = arg[0]; 1592 ix.tab = tab;
1475 ix.key = trlen; 1593 ix.key = trlen;
1476 settabV(J->L, &ix.tabv, t); 1594 settabV(J->L, &ix.tabv, t);
1477 setintV(&ix.keyv, len); 1595 setintV(&ix.keyv, len);
1478 ix.idxchain = 0; 1596 ix.idxchain = 0;
1479 if (rd->cres != 0) { /* Specialize load only if result needed. */ 1597 if (results_wanted(J) != 0) { /* Specialize load only if needed. */
1480 ix.val = 0; 1598 ix.val = 0;
1481 res[0] = rec_idx(J, &ix); /* Load previous value. */ 1599 J->base[0] = rec_idx(J, &ix); /* Load previous value. */
1600 rd->nres = 1;
1482 /* Assumes ix.key/ix.tab is not modified for raw rec_idx(). */ 1601 /* Assumes ix.key/ix.tab is not modified for raw rec_idx(). */
1483 } 1602 }
1484 ix.val = TREF_NIL; 1603 ix.val = TREF_NIL;
1485 rec_idx(J, &ix); /* Remove value. */ 1604 rec_idx(J, &ix); /* Remove value. */
1486 } else {
1487 rd->nres = 0;
1488 } 1605 }
1489 } else { /* Complex case: remove in the middle. */ 1606 } else { /* Complex case: remove in the middle. */
1490 recff_err_nyi(J, rd); 1607 recff_nyiu(J);
1491 } 1608 }
1492 } /* else: Interpreter will throw. */ 1609 } /* else: Interpreter will throw. */
1493} 1610}
1494 1611
1495static void recff_table_insert(jit_State *J, TRef *res, RecordFFData *rd) 1612static void LJ_FASTCALL recff_table_insert(jit_State *J, RecordFFData *rd)
1496{ 1613{
1614 RecordIndex ix;
1615 ix.tab = J->base[0];
1616 ix.val = J->base[1];
1497 rd->nres = 0; 1617 rd->nres = 0;
1498 if (tref_istab(arg[0]) && arg[1]) { 1618 if (tref_istab(ix.tab) && ix.val) {
1499 if (!arg[2]) { /* Simple push: t[#t+1] = v */ 1619 if (!J->base[2]) { /* Simple push: t[#t+1] = v */
1500 TRef trlen = lj_ir_call(J, IRCALL_lj_tab_len, arg[0]); 1620 TRef trlen = lj_ir_call(J, IRCALL_lj_tab_len, ix.tab);
1501 GCtab *t = tabV(&rd->argv[0]); 1621 GCtab *t = tabV(&rd->argv[0]);
1502 RecordIndex ix;
1503 ix.tab = arg[0];
1504 ix.val = arg[1];
1505 ix.key = emitir(IRTI(IR_ADD), trlen, lj_ir_kint(J, 1)); 1622 ix.key = emitir(IRTI(IR_ADD), trlen, lj_ir_kint(J, 1));
1506 settabV(J->L, &ix.tabv, t); 1623 settabV(J->L, &ix.tabv, t);
1507 setintV(&ix.keyv, lj_tab_len(t) + 1); 1624 setintV(&ix.keyv, lj_tab_len(t) + 1);
1508 ix.idxchain = 0; 1625 ix.idxchain = 0;
1509 rec_idx(J, &ix); /* Set new value. */ 1626 rec_idx(J, &ix); /* Set new value. */
1510 } else { /* Complex case: insert in the middle. */ 1627 } else { /* Complex case: insert in the middle. */
1511 recff_err_nyi(J, rd); 1628 recff_nyiu(J);
1512 } 1629 }
1513 } /* else: Interpreter will throw. */ 1630 } /* else: Interpreter will throw. */
1514} 1631}
@@ -1518,14 +1635,14 @@ static void recff_table_insert(jit_State *J, TRef *res, RecordFFData *rd)
1518/* Get FILE* for I/O function. Any I/O error aborts recording, so there's 1635/* Get FILE* for I/O function. Any I/O error aborts recording, so there's
1519** no need to encode the alternate cases for any of the guards. 1636** no need to encode the alternate cases for any of the guards.
1520*/ 1637*/
1521static TRef recff_io_fp(jit_State *J, TRef *res, uint32_t id) 1638static TRef recff_io_fp(jit_State *J, uint32_t id)
1522{ 1639{
1523 TRef tr, ud, fp; 1640 TRef tr, ud, fp;
1524 if (id) { /* io.func() */ 1641 if (id) { /* io.func() */
1525 tr = lj_ir_kptr(J, &J2G(J)->gcroot[id]); 1642 tr = lj_ir_kptr(J, &J2G(J)->gcroot[id]);
1526 ud = emitir(IRT(IR_XLOAD, IRT_UDATA), tr, 0); 1643 ud = emitir(IRT(IR_XLOAD, IRT_UDATA), tr, 0);
1527 } else { /* fp:method() */ 1644 } else { /* fp:method() */
1528 ud = arg[0]; 1645 ud = J->base[0];
1529 if (!tref_isudata(ud)) 1646 if (!tref_isudata(ud))
1530 lj_trace_err(J, LJ_TRERR_BADTYPE); 1647 lj_trace_err(J, LJ_TRERR_BADTYPE);
1531 tr = emitir(IRT(IR_FLOAD, IRT_U8), ud, IRFL_UDATA_UDTYPE); 1648 tr = emitir(IRT(IR_FLOAD, IRT_U8), ud, IRFL_UDATA_UDTYPE);
@@ -1536,130 +1653,75 @@ static TRef recff_io_fp(jit_State *J, TRef *res, uint32_t id)
1536 return fp; 1653 return fp;
1537} 1654}
1538 1655
1539static void recff_io_write(jit_State *J, TRef *res, RecordFFData *rd) 1656static void LJ_FASTCALL recff_io_write(jit_State *J, RecordFFData *rd)
1540{ 1657{
1541 TRef fp = recff_io_fp(J, res, rd->data); 1658 TRef fp = recff_io_fp(J, rd->data);
1542 TRef zero = lj_ir_kint(J, 0); 1659 TRef zero = lj_ir_kint(J, 0);
1543 TRef one = lj_ir_kint(J, 1); 1660 TRef one = lj_ir_kint(J, 1);
1544 ptrdiff_t i = rd->data == 0 ? 1 : 0; 1661 ptrdiff_t i = rd->data == 0 ? 1 : 0;
1545 for (; arg[i]; i++) { 1662 for (; J->base[i]; i++) {
1546 TRef str = lj_ir_tostr(J, arg[i]); 1663 TRef str = lj_ir_tostr(J, J->base[i]);
1547 TRef buf = emitir(IRT(IR_STRREF, IRT_PTR), str, zero); 1664 TRef buf = emitir(IRT(IR_STRREF, IRT_PTR), str, zero);
1548 TRef len = emitir(IRTI(IR_FLOAD), str, IRFL_STR_LEN); 1665 TRef len = emitir(IRTI(IR_FLOAD), str, IRFL_STR_LEN);
1549 if (tref_isk(len) && IR(tref_ref(len))->i == 1) { 1666 if (tref_isk(len) && IR(tref_ref(len))->i == 1) {
1550 TRef tr = emitir(IRT(IR_XLOAD, IRT_U8), buf, IRXLOAD_READONLY); 1667 TRef tr = emitir(IRT(IR_XLOAD, IRT_U8), buf, IRXLOAD_READONLY);
1551 tr = lj_ir_call(J, IRCALL_fputc, tr, fp); 1668 tr = lj_ir_call(J, IRCALL_fputc, tr, fp);
1552 if (rd->cres != 0) /* Check result only if requested. */ 1669 if (results_wanted(J) != 0) /* Check result only if not ignored. */
1553 emitir(IRTGI(IR_NE), tr, lj_ir_kint(J, -1)); 1670 emitir(IRTGI(IR_NE), tr, lj_ir_kint(J, -1));
1554 } else { 1671 } else {
1555 TRef tr = lj_ir_call(J, IRCALL_fwrite, buf, one, len, fp); 1672 TRef tr = lj_ir_call(J, IRCALL_fwrite, buf, one, len, fp);
1556 if (rd->cres != 0) /* Check result only if requested. */ 1673 if (results_wanted(J) != 0) /* Check result only if not ignored. */
1557 emitir(IRTGI(IR_EQ), tr, len); 1674 emitir(IRTGI(IR_EQ), tr, len);
1558 } 1675 }
1559 } 1676 }
1560 res[0] = TREF_TRUE; 1677 J->base[0] = TREF_TRUE;
1561} 1678}
1562 1679
1563static void recff_io_flush(jit_State *J, TRef *res, RecordFFData *rd) 1680static void LJ_FASTCALL recff_io_flush(jit_State *J, RecordFFData *rd)
1564{ 1681{
1565 TRef fp = recff_io_fp(J, res, rd->data); 1682 TRef fp = recff_io_fp(J, rd->data);
1566 TRef tr = lj_ir_call(J, IRCALL_fflush, fp); 1683 TRef tr = lj_ir_call(J, IRCALL_fflush, fp);
1567 if (rd->cres != 0) /* Check result only if requested. */ 1684 if (results_wanted(J) != 0) /* Check result only if not ignored. */
1568 emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, 0)); 1685 emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, 0));
1569 res[0] = TREF_TRUE; 1686 J->base[0] = TREF_TRUE;
1570} 1687}
1571 1688
1572/* -- Record calls and returns -------------------------------------------- */
1573
1574#undef arg
1575
1576#include "lj_recdef.h" 1689#include "lj_recdef.h"
1577 1690
1578/* Record return. */ 1691static uint32_t recdef_lookup(GCfunc *fn)
1579static void rec_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
1580{ 1692{
1581 TValue *frame = J->L->base - 1; 1693 if (fn->c.ffid < sizeof(recff_idmap)/sizeof(recff_idmap[0]))
1582 ptrdiff_t i; 1694 return recff_idmap[fn->c.ffid];
1583 for (i = 0; i < gotresults; i++) 1695 else
1584 getslot(J, rbase+i); /* Ensure all results have a reference. */ 1696 return 0;
1585 J->tailcalled = 0; 1697}
1586 while (frame_ispcall(frame)) { /* Immediately resolve pcall() returns. */ 1698
1587 BCReg cbase = (BCReg)frame_delta(frame); 1699/* Record call to fast function or C function. */
1588 if (J->framedepth-- <= 0) 1700static void rec_func_ff(jit_State *J)
1589 lj_trace_err(J, LJ_TRERR_NYIRETL); 1701{
1590 lua_assert(J->baseslot > 1); 1702 RecordFFData rd;
1591 J->base[--rbase] = TREF_TRUE; /* Prepend true to results. */ 1703 uint32_t m = recdef_lookup(J->fn);
1592 gotresults++; 1704 rd.data = m & 0xff;
1593 rbase += cbase; 1705 rd.nres = 1; /* Default is one result. */
1594 J->baseslot -= (BCReg)cbase; 1706 rd.argv = J->L->base;
1595 J->base -= cbase; 1707 J->base[J->maxslot] = 0; /* Mark end of arguments. */
1596 frame = frame_prevd(frame); 1708 (recff_func[m >> 8])(J, &rd); /* Call recff_* handler. */
1597 } 1709 if (rd.nres >= 0)
1598 if (frame_islua(frame)) { /* Return to Lua frame. */ 1710 rec_ret(J, 0, rd.nres);
1599 BCIns callins = *(frame_pc(frame)-1);
1600 ptrdiff_t nresults = bc_b(callins) ? (ptrdiff_t)bc_b(callins)-1 :gotresults;
1601 BCReg cbase = bc_a(callins);
1602 for (i = 0; i < nresults; i++) /* Adjust results. */
1603 J->base[i-1] = i < gotresults ? J->base[rbase+i] : TREF_NIL;
1604 J->maxslot = cbase+(BCReg)nresults;
1605 if (J->framedepth > 0) { /* Return to a frame that is part of the trace. */
1606 J->framedepth--;
1607 lua_assert(J->baseslot > cbase+1);
1608 J->baseslot -= cbase+1;
1609 J->base -= cbase+1;
1610 } else if (J->parent == 0) {
1611 /* Return to lower frame would leave the loop in a root trace. */
1612 lj_trace_err(J, LJ_TRERR_LLEAVE);
1613 } else { /* Return to lower frame. Guard for the target we return to. */
1614 GCproto *pt = funcproto(frame_func(frame - (cbase+1)));
1615 TRef trpt = lj_ir_kgc(J, obj2gco(pt), IRT_PROTO);
1616 TRef trpc = lj_ir_kptr(J, (void *)frame_pc(frame));
1617 emitir(IRTG(IR_RETF, IRT_PTR), trpt, trpc);
1618 J->retdepth++;
1619 J->needsnap = 1;
1620 lua_assert(J->baseslot == 1);
1621 /* Shift result slots up and clear the slots of the new frame below. */
1622 memmove(J->base + cbase, J->base-1, sizeof(TRef)*nresults);
1623 memset(J->base-1, 0, sizeof(TRef)*(cbase+1));
1624 }
1625 } else if (frame_iscont(frame)) { /* Return to continuation frame. */
1626 ASMFunction cont = frame_contf(frame);
1627 BCReg cbase = (BCReg)frame_delta(frame);
1628 if ((J->framedepth -= 2) <= 0)
1629 lj_trace_err(J, LJ_TRERR_NYIRETL);
1630 J->baseslot -= (BCReg)cbase;
1631 J->base -= cbase;
1632 J->maxslot = cbase-2;
1633 if (cont == lj_cont_ra) {
1634 /* Copy result to destination slot. */
1635 BCReg dst = bc_a(*(frame_contpc(frame)-1));
1636 J->base[dst] = gotresults ? J->base[cbase+rbase] : TREF_NIL;
1637 if (dst > J->maxslot) J->maxslot = dst+1;
1638 } else if (cont == lj_cont_nop) {
1639 /* Nothing to do here. */
1640 } else if (cont == lj_cont_cat) {
1641 lua_assert(0);
1642 } else {
1643 /* Result type already specialized. */
1644 lua_assert(cont == lj_cont_condf || cont == lj_cont_condt);
1645 }
1646 } else {
1647 lj_trace_err(J, LJ_TRERR_NYIRETL); /* NYI: handle return to C frame. */
1648 }
1649 lua_assert(J->baseslot >= 1);
1650} 1711}
1651 1712
1713/* -- Record calls to Lua functions --------------------------------------- */
1714
1652/* Check unroll limits for calls. */ 1715/* Check unroll limits for calls. */
1653static void check_call_unroll(jit_State *J, GCfunc *fn) 1716static void check_call_unroll(jit_State *J)
1654{ 1717{
1655 IRRef fref = tref_ref(J->base[-1]); 1718 IRRef fref = tref_ref(J->base[-1]);
1656 int32_t count = 0; 1719 int32_t count = 0;
1657 ptrdiff_t s; 1720 BCReg s;
1658 for (s = (ptrdiff_t)J->baseslot - 1; s > 0; s--) 1721 for (s = J->baseslot - 1; s > 0; s--)
1659 if ((J->slot[s] & TREF_FRAME) && tref_ref(J->slot[s]) == fref) 1722 if ((J->slot[s] & TREF_FRAME) && tref_ref(J->slot[s]) == fref)
1660 count++; 1723 count++;
1661 if (bc_op(J->cur.startins) == BC_CALL && 1724 if (J->pc == J->startpc) {
1662 funcproto(fn) == &gcref(J->cur.startpt)->pt) {
1663 if (count + J->tailcalled > J->param[JIT_P_recunroll]) 1725 if (count + J->tailcalled > J->param[JIT_P_recunroll])
1664 lj_trace_err(J, LJ_TRERR_NYIRECU); 1726 lj_trace_err(J, LJ_TRERR_NYIRECU);
1665 } else { 1727 } else {
@@ -1668,110 +1730,20 @@ static void check_call_unroll(jit_State *J, GCfunc *fn)
1668 } 1730 }
1669} 1731}
1670 1732
1671/* Record call. Returns 0 for pending calls and 1 for resolved calls. */ 1733static void rec_func_lua(jit_State *J)
1672static int rec_call(jit_State *J, BCReg func, ptrdiff_t cres, ptrdiff_t nargs)
1673{ 1734{
1674 RecordFFData rd; 1735 GCproto *pt = J->pt;
1675 TRef trfunc, *res = &J->base[func]; 1736 if ((pt->flags & PROTO_NO_JIT))
1676 TValue *tv = &J->L->base[func]; 1737 lj_trace_err(J, LJ_TRERR_CJITOFF);
1677 1738 lua_assert(!(pt->flags & PROTO_IS_VARARG));
1678 if (tref_isfunc(res[0])) { /* Regular function call. */ 1739 if (J->baseslot + pt->framesize >= LJ_MAX_JSLOTS)
1679 rd.fn = funcV(tv);
1680 rd.argv = tv+1;
1681 rd.metacall = 0;
1682 } else { /* Otherwise resolve __call metamethod for called object. */
1683 RecordIndex ix;
1684 ptrdiff_t i;
1685 ix.tab = res[0];
1686 copyTV(J->L, &ix.tabv, tv);
1687 if (!rec_mm_lookup(J, &ix, MM_call) || !tref_isfunc(ix.mobj))
1688 lj_trace_err(J, LJ_TRERR_NOMM);
1689 /* Update the recorder state, but not the Lua stack. */
1690 for (i = ++nargs; i > 0; i--)
1691 res[i] = res[i-1];
1692 res[0] = ix.mobj;
1693 rd.fn = funcV(&ix.mobjv);
1694 rd.argv = tv; /* The called object is the 1st arg. */
1695 rd.metacall = 1;
1696 }
1697
1698 /* Specialize to the runtime value of the called function. */
1699 trfunc = lj_ir_kfunc(J, rd.fn);
1700 emitir(IRTG(IR_EQ, IRT_FUNC), res[0], trfunc);
1701 res[0] = trfunc | TREF_FRAME;
1702
1703 /* Add frame links. */
1704 J->frame[J->framedepth++] = SNAP_MKPC(J->pc+1);
1705 if (cres == CALLRES_CONT) /* Continuations need an extra frame stack slot. */
1706 J->frame[J->framedepth++] = SNAP_MKFTSZ((func+1)*sizeof(TValue)+FRAME_CONT);
1707 /* NYI: func is wrong if any fast function ever sets up a continuation. */
1708 if (J->framedepth > LJ_MAX_JFRAME)
1709 lj_trace_err(J, LJ_TRERR_STACKOV); 1740 lj_trace_err(J, LJ_TRERR_STACKOV);
1710 1741 /* Fill up missing args with nil. */
1711 if (isluafunc(rd.fn)) { /* Record call to Lua function. */ 1742 while (J->maxslot < pt->numparams)
1712 GCproto *pt = funcproto(rd.fn); 1743 J->base[J->maxslot++] = TREF_NIL;
1713 if ((pt->flags & PROTO_NO_JIT)) 1744 /* The remaining slots should never be read before they are written. */
1714 lj_trace_err(J, LJ_TRERR_CJITOFF); 1745 J->maxslot = pt->numparams;
1715 if ((pt->flags & PROTO_IS_VARARG)) 1746 check_call_unroll(J);
1716 lj_trace_err(J, LJ_TRERR_NYIVF);
1717 if (cres == CALLRES_TAILCALL) {
1718 ptrdiff_t i;
1719 /* Tailcalls can form a loop, so count towards the loop unroll limit. */
1720 if (++J->tailcalled > J->loopunroll)
1721 lj_trace_err(J, LJ_TRERR_LUNROLL);
1722 for (i = 0; i <= nargs; i++) /* Move func + args down. */
1723 J->base[i-1] = res[i];
1724 J->framedepth--;
1725 /* Note: the new FRAME is now at J->base[-1] (even for slot #0). */
1726 } else { /* Regular call. */
1727 J->base += func+1;
1728 J->baseslot += func+1;
1729 }
1730 if (J->baseslot + pt->framesize >= LJ_MAX_JSLOTS)
1731 lj_trace_err(J, LJ_TRERR_STACKOV);
1732 /* Fill up missing args with nil. */
1733 while (nargs < pt->numparams)
1734 J->base[nargs++] = TREF_NIL;
1735 /* The remaining slots should never be read before they are written. */
1736 J->maxslot = pt->numparams;
1737 check_call_unroll(J, rd.fn);
1738 return 0; /* No result yet. */
1739 } else { /* Record call to C function or fast function. */
1740 uint32_t m = 0;
1741 BCReg oldmaxslot = J->maxslot;
1742 res[1+nargs] = 0;
1743 rd.nargs = nargs;
1744 if (rd.fn->c.ffid < sizeof(recff_idmap)/sizeof(recff_idmap[0]))
1745 m = recff_idmap[rd.fn->c.ffid];
1746 rd.data = m & 0xff;
1747 rd.cres = cres;
1748 rd.nres = 1; /* Default is one result. */
1749 (recff_func[m >> 8])(J, res, &rd); /* Call recff_* handler. */
1750 J->framedepth--;
1751 cres = rd.cres;
1752 if (cres >= 0) {
1753 /* Caller takes fixed number of results: local a,b = f() */
1754 J->maxslot = func + (BCReg)cres;
1755 while (rd.nres < cres) /* Fill up missing results with nil. */
1756 res[rd.nres++] = TREF_NIL;
1757 } else if (cres == CALLRES_MULTI) {
1758 /* Caller takes any number of results: return 1,f() */
1759 J->maxslot = func + (BCReg)rd.nres;
1760 } else if (cres == CALLRES_TAILCALL) {
1761 /* Tail call: return f() */
1762 rec_ret(J, func, rd.nres);
1763 } else if (cres == CALLRES_CONT) {
1764 /* Note: immediately resolved continuations must not change J->maxslot. */
1765 J->maxslot = oldmaxslot;
1766 J->framedepth--;
1767 res[rd.nres] = TREF_NIL; /* Turn 0 results into nil result. */
1768 } else {
1769 lua_assert(cres == CALLRES_PENDING);
1770 J->framedepth++;
1771 return 0; /* Pending call, no result yet. */
1772 }
1773 return 1; /* Result resolved immediately. */
1774 }
1775} 1747}
1776 1748
1777/* -- Record allocations -------------------------------------------------- */ 1749/* -- Record allocations -------------------------------------------------- */
@@ -2068,22 +2040,25 @@ void lj_record_ins(jit_State *J)
2068 copyTV(J->L, b+1, b-2); 2040 copyTV(J->L, b+1, b-2);
2069 copyTV(J->L, b+2, b-1); 2041 copyTV(J->L, b+2, b-1);
2070 } 2042 }
2071 goto callop; 2043 rec_call(J, ra, (ptrdiff_t)rc-1);
2044 break;
2072 2045
2073 case BC_CALLMT: 2046 /* L->top is set to L->base+ra+rc+NARGS-1+1. See lj_dispatch_ins(). */
2074 rb = (TRef)(CALLRES_TAILCALL+1);
2075 /* fallthrough */
2076 case BC_CALLM: 2047 case BC_CALLM:
2077 /* L->top is set to L->base+ra+rc+NRESULTS-1+1, see lj_dispatch_ins(). */
2078 rc = (BCReg)(J->L->top - J->L->base) - ra; 2048 rc = (BCReg)(J->L->top - J->L->base) - ra;
2079 goto callop;
2080
2081 case BC_CALLT:
2082 rb = (TRef)(CALLRES_TAILCALL+1);
2083 /* fallthrough */ 2049 /* fallthrough */
2084 case BC_CALL: 2050 case BC_CALL:
2085 callop: 2051 rec_call(J, ra, (ptrdiff_t)rc-1);
2086 rec_call(J, ra, (ptrdiff_t)rb-1, (ptrdiff_t)rc-1); 2052 break;
2053
2054 case BC_CALLMT:
2055 rc = (BCReg)(J->L->top - J->L->base) - ra;
2056 /* fallthrough */
2057 case BC_CALLT:
2058 rec_tailcall(J, ra, (ptrdiff_t)rc-1);
2059 /* Tailcalls can form a loop, so count towards the loop unroll limit. */
2060 if (++J->tailcalled > J->loopunroll)
2061 lj_trace_err(J, LJ_TRERR_LUNROLL);
2087 break; 2062 break;
2088 2063
2089 /* -- Returns ----------------------------------------------------------- */ 2064 /* -- Returns ----------------------------------------------------------- */
@@ -2094,6 +2069,7 @@ void lj_record_ins(jit_State *J)
2094 /* fallthrough */ 2069 /* fallthrough */
2095 case BC_RET: case BC_RET0: case BC_RET1: 2070 case BC_RET: case BC_RET0: case BC_RET1:
2096 rec_ret(J, ra, (ptrdiff_t)rc-1); 2071 rec_ret(J, ra, (ptrdiff_t)rc-1);
2072 J->tailcalled = 0; /* NYI: logic is broken, need a better check. */
2097 break; 2073 break;
2098 2074
2099 /* -- Loops and branches ------------------------------------------------ */ 2075 /* -- Loops and branches ------------------------------------------------ */
@@ -2132,6 +2108,8 @@ void lj_record_ins(jit_State *J)
2132 case BC_IFORL: 2108 case BC_IFORL:
2133 case BC_IITERL: 2109 case BC_IITERL:
2134 case BC_ILOOP: 2110 case BC_ILOOP:
2111 case BC_IFUNCF:
2112 case BC_IFUNCV:
2135 lj_trace_err(J, LJ_TRERR_LBLACKL); 2113 lj_trace_err(J, LJ_TRERR_LBLACKL);
2136 break; 2114 break;
2137 2115
@@ -2140,12 +2118,37 @@ void lj_record_ins(jit_State *J)
2140 J->maxslot = ra; /* Shrink used slots. */ 2118 J->maxslot = ra; /* Shrink used slots. */
2141 break; 2119 break;
2142 2120
2121 /* -- Function headers -------------------------------------------------- */
2122
2123 case BC_FUNCF:
2124 rec_func_lua(J);
2125 break;
2126
2127 case BC_JFUNCF:
2128 lj_trace_err(J, LJ_TRERR_NYILNKF);
2129 break;
2130
2131 case BC_FUNCV:
2132 case BC_JFUNCV:
2133 lj_trace_err(J, LJ_TRERR_NYIVF);
2134 break;
2135
2136 case BC_FUNCC:
2137 case BC_FUNCCW:
2138 rec_func_ff(J);
2139 break;
2140
2141 default:
2142 if (op >= BC__MAX) {
2143 rec_func_ff(J);
2144 break;
2145 }
2146 /* fallthrough */
2143 case BC_CAT: 2147 case BC_CAT:
2144 case BC_UCLO: 2148 case BC_UCLO:
2145 case BC_FNEW: 2149 case BC_FNEW:
2146 case BC_TSETM: 2150 case BC_TSETM:
2147 case BC_VARG: 2151 case BC_VARG:
2148 default:
2149 setintV(&J->errinfo, (int32_t)op); 2152 setintV(&J->errinfo, (int32_t)op);
2150 lj_trace_err_info(J, LJ_TRERR_NYIBC); 2153 lj_trace_err_info(J, LJ_TRERR_NYIBC);
2151 break; 2154 break;