aboutsummaryrefslogtreecommitdiff
path: root/src/lj_ffrecord.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_ffrecord.c')
-rw-r--r--src/lj_ffrecord.c130
1 files changed, 96 insertions, 34 deletions
diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c
index 42aae8b5..6a156c7c 100644
--- a/src/lj_ffrecord.c
+++ b/src/lj_ffrecord.c
@@ -96,28 +96,81 @@ static ptrdiff_t results_wanted(jit_State *J)
96 return -1; 96 return -1;
97} 97}
98 98
99/* Throw error for unsupported variant of fast function. */ 99/* Trace stitching: add continuation below frame to start a new trace. */
100LJ_NORET static void recff_nyiu(jit_State *J) 100static void recff_stitch(jit_State *J)
101{ 101{
102 setfuncV(J->L, &J->errinfo, J->fn); 102 ASMFunction cont = lj_cont_stitch;
103 lj_trace_err_info(J, LJ_TRERR_NYIFFU); 103 TraceNo traceno = J->cur.traceno;
104 lua_State *L = J->L;
105 TValue *base = L->base;
106 const BCIns *pc = frame_pc(base-1);
107 TValue *pframe = frame_prevl(base-1);
108 TRef trcont;
109
110 /* Move func + args up in Lua stack and insert continuation. */
111 memmove(&base[1], &base[-1], sizeof(TValue)*(J->maxslot+1));
112 setframe_ftsz(base+1, (int)((char *)(base+1) - (char *)pframe) + FRAME_CONT);
113 setcont(base, cont);
114 setframe_pc(base, pc);
115 if (LJ_DUALNUM) setintV(base-1, traceno); else base[-1].u64 = traceno;
116 L->base += 2;
117 L->top += 2;
118
119 /* Ditto for the IR. */
120 memmove(&J->base[1], &J->base[-1], sizeof(TRef)*(J->maxslot+1));
121#if LJ_64
122 trcont = lj_ir_kptr(J, (void *)((int64_t)cont-(int64_t)lj_vm_asm_begin));
123#else
124 trcont = lj_ir_kptr(J, (void *)cont);
125#endif
126 J->base[0] = trcont | TREF_CONT;
127 J->base[-1] = LJ_DUALNUM ? lj_ir_kint(J,traceno) : lj_ir_knum_u64(J,traceno);
128 J->maxslot += 2;
129 J->framedepth++;
130
131 lj_record_stop(J, LJ_TRLINK_STITCH, 0);
132
133 /* Undo Lua stack changes. */
134 memmove(&base[-1], &base[1], sizeof(TValue)*(J->maxslot+1));
135 setframe_pc(base-1, pc);
136 L->base -= 2;
137 L->top -= 2;
104} 138}
105 139
106/* Fallback handler for all fast functions that are not recorded (yet). */ 140/* Fallback handler for fast functions that are not recorded (yet). */
107static void LJ_FASTCALL recff_nyi(jit_State *J, RecordFFData *rd) 141static void LJ_FASTCALL recff_nyi(jit_State *J, RecordFFData *rd)
108{ 142{
109 setfuncV(J->L, &J->errinfo, J->fn); 143 if (J->cur.nins < (IRRef)J->param[JIT_P_minstitch] + REF_BASE) {
110 lj_trace_err_info(J, LJ_TRERR_NYIFF); 144 lj_trace_err_info(J, LJ_TRERR_TRACEUV);
111 UNUSED(rd); 145 } else {
146 /* Can only stitch from Lua call. */
147 if (J->framedepth && frame_islua(J->L->base-1)) {
148 BCOp op = bc_op(*frame_pc(J->L->base-1));
149 /* Stitched trace cannot start with *M op with variable # of args. */
150 if (!(op == BC_CALLM || op == BC_RETM || op == BC_TSETM)) {
151 switch (J->fn->c.ffid) {
152 case FF_error:
153 case FF_debug_sethook:
154 case FF_jit_flush:
155 break; /* Don't stitch across special builtins. */
156 default:
157 recff_stitch(J); /* Use trace stitching. */
158 rd->nres = -1;
159 return;
160 }
161 }
162 }
163 /* Otherwise stop trace and return to interpreter. */
164 lj_record_stop(J, LJ_TRLINK_RETURN, 0);
165 rd->nres = -1;
166 }
112} 167}
113 168
114/* C functions can have arbitrary side-effects and are not recorded (yet). */ 169/* Fallback handler for unsupported variants of fast functions. */
115static void LJ_FASTCALL recff_c(jit_State *J, RecordFFData *rd) 170#define recff_nyiu recff_nyi
116{ 171
117 setfuncV(J->L, &J->errinfo, J->fn); 172/* Must stop the trace for classic C functions with arbitrary side-effects. */
118 lj_trace_err_info(J, LJ_TRERR_NYICF); 173#define recff_c recff_nyi
119 UNUSED(rd);
120}
121 174
122/* Emit BUFHDR for the global temporary buffer. */ 175/* Emit BUFHDR for the global temporary buffer. */
123static TRef recff_bufhdr(jit_State *J) 176static TRef recff_bufhdr(jit_State *J)
@@ -268,7 +321,8 @@ static void LJ_FASTCALL recff_select(jit_State *J, RecordFFData *rd)
268 J->base[i] = J->base[start+i]; 321 J->base[i] = J->base[start+i];
269 } /* else: Interpreter will throw. */ 322 } /* else: Interpreter will throw. */
270 } else { 323 } else {
271 recff_nyiu(J); 324 recff_nyiu(J, rd);
325 return;
272 } 326 }
273 } /* else: Interpreter will throw. */ 327 } /* else: Interpreter will throw. */
274} 328}
@@ -279,14 +333,18 @@ static void LJ_FASTCALL recff_tonumber(jit_State *J, RecordFFData *rd)
279 TRef base = J->base[1]; 333 TRef base = J->base[1];
280 if (tr && !tref_isnil(base)) { 334 if (tr && !tref_isnil(base)) {
281 base = lj_opt_narrow_toint(J, base); 335 base = lj_opt_narrow_toint(J, base);
282 if (!tref_isk(base) || IR(tref_ref(base))->i != 10) 336 if (!tref_isk(base) || IR(tref_ref(base))->i != 10) {
283 recff_nyiu(J); 337 recff_nyiu(J, rd);
338 return;
339 }
284 } 340 }
285 if (tref_isnumber_str(tr)) { 341 if (tref_isnumber_str(tr)) {
286 if (tref_isstr(tr)) { 342 if (tref_isstr(tr)) {
287 TValue tmp; 343 TValue tmp;
288 if (!lj_strscan_num(strV(&rd->argv[0]), &tmp)) 344 if (!lj_strscan_num(strV(&rd->argv[0]), &tmp)) {
289 recff_nyiu(J); /* Would need an inverted STRTO for this case. */ 345 recff_nyiu(J, rd); /* Would need an inverted STRTO for this case. */
346 return;
347 }
290 tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0); 348 tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0);
291 } 349 }
292#if LJ_HASFFI 350#if LJ_HASFFI
@@ -348,7 +406,8 @@ static void LJ_FASTCALL recff_tostring(jit_State *J, RecordFFData *rd)
348 } else if (tref_ispri(tr)) { 406 } else if (tref_ispri(tr)) {
349 J->base[0] = lj_ir_kstr(J, lj_strfmt_obj(J->L, &rd->argv[0])); 407 J->base[0] = lj_ir_kstr(J, lj_strfmt_obj(J->L, &rd->argv[0]));
350 } else { 408 } else {
351 recff_nyiu(J); 409 recff_nyiu(J, rd);
410 return;
352 } 411 }
353 } 412 }
354} 413}
@@ -370,14 +429,14 @@ static void LJ_FASTCALL recff_ipairs_aux(jit_State *J, RecordFFData *rd)
370 } /* else: Interpreter will throw. */ 429 } /* else: Interpreter will throw. */
371} 430}
372 431
373static void LJ_FASTCALL recff_ipairs(jit_State *J, RecordFFData *rd) 432static void LJ_FASTCALL recff_xpairs(jit_State *J, RecordFFData *rd)
374{ 433{
375 if (!(LJ_52 && recff_metacall(J, rd, MM_ipairs))) { 434 if (!(LJ_52 && recff_metacall(J, rd, MM_ipairs))) {
376 TRef tab = J->base[0]; 435 TRef tab = J->base[0];
377 if (tref_istab(tab)) { 436 if (tref_istab(tab)) {
378 J->base[0] = lj_ir_kfunc(J, funcV(&J->fn->c.upvalue[0])); 437 J->base[0] = lj_ir_kfunc(J, funcV(&J->fn->c.upvalue[0]));
379 J->base[1] = tab; 438 J->base[1] = tab;
380 J->base[2] = lj_ir_kint(J, 0); 439 J->base[2] = rd->data ? lj_ir_kint(J, 0) : TREF_NIL;
381 rd->nres = 3; 440 rd->nres = 3;
382 } /* else: Interpreter will throw. */ 441 } /* else: Interpreter will throw. */
383 } 442 }
@@ -431,8 +490,7 @@ static void LJ_FASTCALL recff_getfenv(jit_State *J, RecordFFData *rd)
431 J->base[0] = emitir(IRT(IR_FLOAD, IRT_TAB), trl, IRFL_THREAD_ENV); 490 J->base[0] = emitir(IRT(IR_FLOAD, IRT_TAB), trl, IRFL_THREAD_ENV);
432 return; 491 return;
433 } 492 }
434 recff_nyiu(J); 493 recff_nyiu(J, rd);
435 UNUSED(rd);
436} 494}
437 495
438/* -- Math library fast functions ----------------------------------------- */ 496/* -- Math library fast functions ----------------------------------------- */
@@ -672,8 +730,7 @@ static void LJ_FASTCALL recff_bit_tohex(jit_State *J, RecordFFData *rd)
672 TRef tr = recff_bit64_tohex(J, rd, hdr); 730 TRef tr = recff_bit64_tohex(J, rd, hdr);
673 J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr); 731 J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr);
674#else 732#else
675 UNUSED(rd); 733 recff_nyiu(J, rd); /* Don't bother working around this NYI. */
676 recff_nyiu(J); /* Don't bother working around this NYI. */
677#endif 734#endif
678} 735}
679 736
@@ -891,7 +948,8 @@ static void LJ_FASTCALL recff_string_find(jit_State *J, RecordFFData *rd)
891 J->base[0] = TREF_NIL; 948 J->base[0] = TREF_NIL;
892 } 949 }
893 } else { /* Search for pattern. */ 950 } else { /* Search for pattern. */
894 recff_nyiu(J); 951 recff_nyiu(J, rd);
952 return;
895 } 953 }
896} 954}
897 955
@@ -931,7 +989,8 @@ static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd)
931 tr = lj_ir_call(J, IRCALL_lj_strfmt_putfxint, tr, trsf, tra); 989 tr = lj_ir_call(J, IRCALL_lj_strfmt_putfxint, tr, trsf, tra);
932 lj_needsplit(J); 990 lj_needsplit(J);
933#else 991#else
934 recff_nyiu(J); /* Don't bother working around this NYI. */ 992 recff_nyiu(J, rd); /* Don't bother working around this NYI. */
993 return;
935#endif 994#endif
936 } 995 }
937 break; 996 break;
@@ -946,8 +1005,10 @@ static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd)
946 if (LJ_SOFTFP) lj_needsplit(J); 1005 if (LJ_SOFTFP) lj_needsplit(J);
947 break; 1006 break;
948 case STRFMT_STR: 1007 case STRFMT_STR:
949 if (!tref_isstr(tra)) 1008 if (!tref_isstr(tra)) {
950 recff_nyiu(J); /* NYI: __tostring and non-string types for %s. */ 1009 recff_nyiu(J, rd); /* NYI: __tostring and non-string types for %s. */
1010 return;
1011 }
951 if (sf == STRFMT_STR) /* Shortcut for plain %s. */ 1012 if (sf == STRFMT_STR) /* Shortcut for plain %s. */
952 tr = emitir(IRT(IR_BUFPUT, IRT_P32), tr, tra); 1013 tr = emitir(IRT(IR_BUFPUT, IRT_P32), tr, tra);
953 else if ((sf & STRFMT_T_QUOTED)) 1014 else if ((sf & STRFMT_T_QUOTED))
@@ -966,8 +1027,8 @@ static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd)
966 case STRFMT_PTR: /* NYI */ 1027 case STRFMT_PTR: /* NYI */
967 case STRFMT_ERR: 1028 case STRFMT_ERR:
968 default: 1029 default:
969 recff_nyiu(J); 1030 recff_nyiu(J, rd);
970 break; 1031 return;
971 } 1032 }
972 } 1033 }
973 J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr); 1034 J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr);
@@ -991,7 +1052,8 @@ static void LJ_FASTCALL recff_table_insert(jit_State *J, RecordFFData *rd)
991 ix.idxchain = 0; 1052 ix.idxchain = 0;
992 lj_record_idx(J, &ix); /* Set new value. */ 1053 lj_record_idx(J, &ix); /* Set new value. */
993 } else { /* Complex case: insert in the middle. */ 1054 } else { /* Complex case: insert in the middle. */
994 recff_nyiu(J); 1055 recff_nyiu(J, rd);
1056 return;
995 } 1057 }
996 } /* else: Interpreter will throw. */ 1058 } /* else: Interpreter will throw. */
997} 1059}