aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/host/buildvm_libbc.h15
-rw-r--r--src/lib_base.c29
-rw-r--r--src/lib_bit.c4
-rw-r--r--src/lib_ffi.c2
-rw-r--r--src/lib_math.c2
-rw-r--r--src/lib_string.c4
-rw-r--r--src/lj_api.c97
-rw-r--r--src/lj_arch.h5
-rw-r--r--src/lj_asm.c2
-rw-r--r--src/lj_asm_arm.h2
-rw-r--r--src/lj_asm_mips.h2
-rw-r--r--src/lj_asm_ppc.h2
-rw-r--r--src/lj_asm_x86.h2
-rw-r--r--src/lj_bcdump.h3
-rw-r--r--src/lj_bcread.c1
-rw-r--r--src/lj_bcwrite.c5
-rw-r--r--src/lj_ccallback.c28
-rw-r--r--src/lj_crecord.c2
-rw-r--r--src/lj_debug.c12
-rw-r--r--src/lj_dispatch.c2
-rw-r--r--src/lj_err.c14
-rw-r--r--src/lj_ffrecord.c2
-rw-r--r--src/lj_frame.h57
-rw-r--r--src/lj_gc.c17
-rw-r--r--src/lj_lib.h5
-rw-r--r--src/lj_meta.c50
-rw-r--r--src/lj_obj.h18
-rw-r--r--src/lj_parse.c14
-rw-r--r--src/lj_record.c25
-rw-r--r--src/lj_snap.c5
-rw-r--r--src/lj_state.c8
-rw-r--r--src/lj_trace.c2
-rw-r--r--src/lj_vmevent.c1
33 files changed, 300 insertions, 139 deletions
diff --git a/src/host/buildvm_libbc.h b/src/host/buildvm_libbc.h
index e96c8a53..45f8f8cb 100644
--- a/src/host/buildvm_libbc.h
+++ b/src/host/buildvm_libbc.h
@@ -3,6 +3,20 @@
3static const int libbc_endian = 0; 3static const int libbc_endian = 0;
4 4
5static const uint8_t libbc_code[] = { 5static const uint8_t libbc_code[] = {
6#if LJ_FR2
70,1,2,0,0,1,2,24,1,0,0,76,1,2,0,241,135,158,166,3,220,203,178,130,4,0,1,2,0,
80,1,2,24,1,0,0,76,1,2,0,243,244,148,165,20,198,190,199,252,3,0,1,2,0,0,0,3,
916,0,5,0,21,1,0,0,76,1,2,0,0,2,10,0,0,0,15,16,0,12,0,16,1,9,0,41,2,1,0,21,3,
100,0,41,4,1,0,77,2,8,128,18,6,1,0,18,8,5,0,59,9,5,0,66,6,3,2,10,6,0,0,88,7,1,
11128,76,6,2,0,79,2,248,127,75,0,1,0,0,2,11,0,0,0,16,16,0,12,0,16,1,9,0,43,2,
120,0,18,3,0,0,41,4,0,0,88,5,7,128,18,7,1,0,18,9,5,0,18,10,6,0,66,7,3,2,10,7,
130,0,88,8,1,128,76,7,2,0,70,5,3,3,82,5,247,127,75,0,1,0,0,1,2,0,0,0,3,16,0,12,
140,21,1,0,0,76,1,2,0,0,2,10,0,0,2,30,16,0,12,0,21,2,0,0,11,1,0,0,88,3,7,128,
158,2,0,0,88,3,23,128,59,3,2,0,43,4,0,0,64,4,2,0,76,3,2,0,88,3,18,128,16,1,14,
160,41,3,1,0,3,3,1,0,88,3,14,128,3,1,2,0,88,3,12,128,59,3,1,0,22,4,1,1,18,5,2,
170,41,6,1,0,77,4,4,128,23,8,1,7,59,9,7,0,64,9,8,0,79,4,252,127,43,4,0,0,64,4,
182,0,76,3,2,0,75,0,1,0,0,2,0
19#else
60,1,2,0,0,1,2,24,1,0,0,76,1,2,0,241,135,158,166,3,220,203,178,130,4,0,1,2,0, 200,1,2,0,0,1,2,24,1,0,0,76,1,2,0,241,135,158,166,3,220,203,178,130,4,0,1,2,0,
70,1,2,24,1,0,0,76,1,2,0,243,244,148,165,20,198,190,199,252,3,0,1,2,0,0,0,3, 210,1,2,24,1,0,0,76,1,2,0,243,244,148,165,20,198,190,199,252,3,0,1,2,0,0,0,3,
816,0,5,0,21,1,0,0,76,1,2,0,0,2,9,0,0,0,15,16,0,12,0,16,1,9,0,41,2,1,0,21,3, 2216,0,5,0,21,1,0,0,76,1,2,0,0,2,9,0,0,0,15,16,0,12,0,16,1,9,0,41,2,1,0,21,3,
@@ -15,6 +29,7 @@ static const uint8_t libbc_code[] = {
150,41,3,1,0,3,3,1,0,88,3,14,128,3,1,2,0,88,3,12,128,59,3,1,0,22,4,1,1,18,5,2, 290,41,3,1,0,3,3,1,0,88,3,14,128,3,1,2,0,88,3,12,128,59,3,1,0,22,4,1,1,18,5,2,
160,41,6,1,0,77,4,4,128,23,8,1,7,59,9,7,0,64,9,8,0,79,4,252,127,43,4,0,0,64,4, 300,41,6,1,0,77,4,4,128,23,8,1,7,59,9,7,0,64,9,8,0,79,4,252,127,43,4,0,0,64,4,
172,0,76,3,2,0,75,0,1,0,0,2,0 312,0,76,3,2,0,75,0,1,0,0,2,0
32#endif
18}; 33};
19 34
20static const struct { const char *name; int ofs; } libbc_map[] = { 35static const struct { const char *name; int ofs; } libbc_map[] = {
diff --git a/src/lib_base.c b/src/lib_base.c
index 713bdae5..6bb71d54 100644
--- a/src/lib_base.c
+++ b/src/lib_base.c
@@ -87,10 +87,11 @@ static int ffh_pairs(lua_State *L, MMS mm)
87 cTValue *mo = lj_meta_lookup(L, o, mm); 87 cTValue *mo = lj_meta_lookup(L, o, mm);
88 if ((LJ_52 || tviscdata(o)) && !tvisnil(mo)) { 88 if ((LJ_52 || tviscdata(o)) && !tvisnil(mo)) {
89 L->top = o+1; /* Only keep one argument. */ 89 L->top = o+1; /* Only keep one argument. */
90 copyTV(L, L->base-1, mo); /* Replace callable. */ 90 copyTV(L, L->base-1-LJ_FR2, mo); /* Replace callable. */
91 return FFH_TAILCALL; 91 return FFH_TAILCALL;
92 } else { 92 } else {
93 if (!tvistab(o)) lj_err_argt(L, 1, LUA_TTABLE); 93 if (!tvistab(o)) lj_err_argt(L, 1, LUA_TTABLE);
94 if (LJ_FR2) { copyTV(L, o-1, o); o--; }
94 setfuncV(L, o-1, funcV(lj_lib_upvalue(L, 1))); 95 setfuncV(L, o-1, funcV(lj_lib_upvalue(L, 1)));
95 if (mm == MM_pairs) setnilV(o+1); else setintV(o+1, 0); 96 if (mm == MM_pairs) setnilV(o+1); else setintV(o+1, 0);
96 return FFH_RES(3); 97 return FFH_RES(3);
@@ -132,7 +133,7 @@ LJLIB_ASM(setmetatable) LJLIB_REC(.)
132 lj_err_caller(L, LJ_ERR_PROTMT); 133 lj_err_caller(L, LJ_ERR_PROTMT);
133 setgcref(t->metatable, obj2gco(mt)); 134 setgcref(t->metatable, obj2gco(mt));
134 if (mt) { lj_gc_objbarriert(L, t, mt); } 135 if (mt) { lj_gc_objbarriert(L, t, mt); }
135 settabV(L, L->base-1, t); 136 settabV(L, L->base-1-LJ_FR2, t);
136 return FFH_RES(1); 137 return FFH_RES(1);
137} 138}
138 139
@@ -145,6 +146,7 @@ LJLIB_CF(getfenv) LJLIB_REC(.)
145 o = lj_debug_frame(L, level, &level); 146 o = lj_debug_frame(L, level, &level);
146 if (o == NULL) 147 if (o == NULL)
147 lj_err_arg(L, 1, LJ_ERR_INVLVL); 148 lj_err_arg(L, 1, LJ_ERR_INVLVL);
149 if (LJ_FR2) o--;
148 } 150 }
149 fn = &gcval(o)->fn; 151 fn = &gcval(o)->fn;
150 settabV(L, L->top++, isluafunc(fn) ? tabref(fn->l.env) : tabref(L->env)); 152 settabV(L, L->top++, isluafunc(fn) ? tabref(fn->l.env) : tabref(L->env));
@@ -166,6 +168,7 @@ LJLIB_CF(setfenv)
166 o = lj_debug_frame(L, level, &level); 168 o = lj_debug_frame(L, level, &level);
167 if (o == NULL) 169 if (o == NULL)
168 lj_err_arg(L, 1, LJ_ERR_INVLVL); 170 lj_err_arg(L, 1, LJ_ERR_INVLVL);
171 if (LJ_FR2) o--;
169 } 172 }
170 fn = &gcval(o)->fn; 173 fn = &gcval(o)->fn;
171 if (!isluafunc(fn)) 174 if (!isluafunc(fn))
@@ -258,7 +261,7 @@ LJLIB_ASM(tonumber) LJLIB_REC(.)
258 if (base == 10) { 261 if (base == 10) {
259 TValue *o = lj_lib_checkany(L, 1); 262 TValue *o = lj_lib_checkany(L, 1);
260 if (lj_strscan_numberobj(o)) { 263 if (lj_strscan_numberobj(o)) {
261 copyTV(L, L->base-1, o); 264 copyTV(L, L->base-1-LJ_FR2, o);
262 return FFH_RES(1); 265 return FFH_RES(1);
263 } 266 }
264#if LJ_HASFFI 267#if LJ_HASFFI
@@ -271,11 +274,11 @@ LJLIB_ASM(tonumber) LJLIB_REC(.)
271 ct->size <= 4 && !(ct->size == 4 && (ct->info & CTF_UNSIGNED))) { 274 ct->size <= 4 && !(ct->size == 4 && (ct->info & CTF_UNSIGNED))) {
272 int32_t i; 275 int32_t i;
273 lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, 0); 276 lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, 0);
274 setintV(L->base-1, i); 277 setintV(L->base-1-LJ_FR2, i);
275 return FFH_RES(1); 278 return FFH_RES(1);
276 } 279 }
277 lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE), 280 lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE),
278 (uint8_t *)&(L->base-1)->n, o, 0); 281 (uint8_t *)&(L->base-1-LJ_FR2)->n, o, 0);
279 return FFH_RES(1); 282 return FFH_RES(1);
280 } 283 }
281 } 284 }
@@ -291,14 +294,14 @@ LJLIB_ASM(tonumber) LJLIB_REC(.)
291 while (lj_char_isspace((unsigned char)(*ep))) ep++; 294 while (lj_char_isspace((unsigned char)(*ep))) ep++;
292 if (*ep == '\0') { 295 if (*ep == '\0') {
293 if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u)) 296 if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u))
294 setintV(L->base-1, (int32_t)ul); 297 setintV(L->base-1-LJ_FR2, (int32_t)ul);
295 else 298 else
296 setnumV(L->base-1, (lua_Number)ul); 299 setnumV(L->base-1-LJ_FR2, (lua_Number)ul);
297 return FFH_RES(1); 300 return FFH_RES(1);
298 } 301 }
299 } 302 }
300 } 303 }
301 setnilV(L->base-1); 304 setnilV(L->base-1-LJ_FR2);
302 return FFH_RES(1); 305 return FFH_RES(1);
303} 306}
304 307
@@ -308,11 +311,11 @@ LJLIB_ASM(tostring) LJLIB_REC(.)
308 cTValue *mo; 311 cTValue *mo;
309 L->top = o+1; /* Only keep one argument. */ 312 L->top = o+1; /* Only keep one argument. */
310 if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) { 313 if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
311 copyTV(L, L->base-1, mo); /* Replace callable. */ 314 copyTV(L, L->base-1-LJ_FR2, mo); /* Replace callable. */
312 return FFH_TAILCALL; 315 return FFH_TAILCALL;
313 } 316 }
314 lj_gc_check(L); 317 lj_gc_check(L);
315 setstrV(L, L->base-1, lj_strfmt_obj(L, L->base)); 318 setstrV(L, L->base-1-LJ_FR2, lj_strfmt_obj(L, L->base));
316 return FFH_RES(1); 319 return FFH_RES(1);
317} 320}
318 321
@@ -535,7 +538,7 @@ LJLIB_CF(coroutine_status)
535 if (co == L) s = "running"; 538 if (co == L) s = "running";
536 else if (co->status == LUA_YIELD) s = "suspended"; 539 else if (co->status == LUA_YIELD) s = "suspended";
537 else if (co->status != 0) s = "dead"; 540 else if (co->status != 0) s = "dead";
538 else if (co->base > tvref(co->stack)+1) s = "normal"; 541 else if (co->base > tvref(co->stack)+1+LJ_FR2) s = "normal";
539 else if (co->top == co->base) s = "dead"; 542 else if (co->top == co->base) s = "dead";
540 else s = "suspended"; 543 else s = "suspended";
541 lua_pushstring(L, s); 544 lua_pushstring(L, s);
@@ -577,8 +580,8 @@ static int ffh_resume(lua_State *L, lua_State *co, int wrap)
577 (co->status == 0 && co->top == co->base)) { 580 (co->status == 0 && co->top == co->base)) {
578 ErrMsg em = co->cframe ? LJ_ERR_CORUN : LJ_ERR_CODEAD; 581 ErrMsg em = co->cframe ? LJ_ERR_CORUN : LJ_ERR_CODEAD;
579 if (wrap) lj_err_caller(L, em); 582 if (wrap) lj_err_caller(L, em);
580 setboolV(L->base-1, 0); 583 setboolV(L->base-1-LJ_FR2, 0);
581 setstrV(L, L->base, lj_err_str(L, em)); 584 setstrV(L, L->base-LJ_FR2, lj_err_str(L, em));
582 return FFH_RES(2); 585 return FFH_RES(2);
583 } 586 }
584 lj_state_growstack(co, (MSize)(L->top - L->base)); 587 lj_state_growstack(co, (MSize)(L->top - L->base));
diff --git a/src/lib_bit.c b/src/lib_bit.c
index ffdc29c1..25731900 100644
--- a/src/lib_bit.c
+++ b/src/lib_bit.c
@@ -33,7 +33,7 @@ static int bit_result64(lua_State *L, CTypeID id, uint64_t x)
33{ 33{
34 GCcdata *cd = lj_cdata_new_(L, id, 8); 34 GCcdata *cd = lj_cdata_new_(L, id, 8);
35 *(uint64_t *)cdataptr(cd) = x; 35 *(uint64_t *)cdataptr(cd) = x;
36 setcdataV(L, L->base-1, cd); 36 setcdataV(L, L->base-1-LJ_FR2, cd);
37 return FFH_RES(1); 37 return FFH_RES(1);
38} 38}
39#else 39#else
@@ -56,7 +56,7 @@ LJLIB_ASM(bit_tobit) LJLIB_REC(bit_tobit)
56{ 56{
57#if LJ_HASFFI 57#if LJ_HASFFI
58 CTypeID id = 0; 58 CTypeID id = 0;
59 setintV(L->base-1, (int32_t)lj_carith_check64(L, 1, &id)); 59 setintV(L->base-1-LJ_FR2, (int32_t)lj_carith_check64(L, 1, &id));
60 return FFH_RES(1); 60 return FFH_RES(1);
61#else 61#else
62 lj_lib_checknumber(L, 1); 62 lj_lib_checknumber(L, 1);
diff --git a/src/lib_ffi.c b/src/lib_ffi.c
index bc2339ce..d64f2167 100644
--- a/src/lib_ffi.c
+++ b/src/lib_ffi.c
@@ -138,7 +138,7 @@ static int ffi_index_meta(lua_State *L, CTState *cts, CType *ct, MMS mm)
138 } 138 }
139 } 139 }
140 copyTV(L, base, L->top); 140 copyTV(L, base, L->top);
141 tv = L->top-1; 141 tv = L->top-1-LJ_FR2;
142 } 142 }
143 return lj_meta_tailcall(L, tv); 143 return lj_meta_tailcall(L, tv);
144} 144}
diff --git a/src/lib_math.c b/src/lib_math.c
index 87ec2883..225630d0 100644
--- a/src/lib_math.c
+++ b/src/lib_math.c
@@ -57,7 +57,7 @@ LJLIB_ASM(math_log) LJLIB_REC(math_log)
57#else 57#else
58 x = lj_vm_log2(x); y = 1.0 / lj_vm_log2(y); 58 x = lj_vm_log2(x); y = 1.0 / lj_vm_log2(y);
59#endif 59#endif
60 setnumV(L->base-1, x*y); /* Do NOT join the expression to x / y. */ 60 setnumV(L->base-1-LJ_FR2, x*y); /* Do NOT join the expression to x / y. */
61 return FFH_RES(1); 61 return FFH_RES(1);
62 } 62 }
63 return FFH_RETRY; 63 return FFH_RETRY;
diff --git a/src/lib_string.c b/src/lib_string.c
index 6ca7a76b..6cab0a19 100644
--- a/src/lib_string.c
+++ b/src/lib_string.c
@@ -58,7 +58,7 @@ LJLIB_ASM(string_byte) LJLIB_REC(string_range 0)
58 lj_state_checkstack(L, (MSize)n); 58 lj_state_checkstack(L, (MSize)n);
59 p = (const unsigned char *)strdata(s) + start; 59 p = (const unsigned char *)strdata(s) + start;
60 for (i = 0; i < n; i++) 60 for (i = 0; i < n; i++)
61 setintV(L->base + i-1, p[i]); 61 setintV(L->base + i-1-LJ_FR2, p[i]);
62 return FFH_RES(n); 62 return FFH_RES(n);
63} 63}
64 64
@@ -72,7 +72,7 @@ LJLIB_ASM(string_char) LJLIB_REC(.)
72 lj_err_arg(L, i, LJ_ERR_BADVAL); 72 lj_err_arg(L, i, LJ_ERR_BADVAL);
73 buf[i-1] = (char)k; 73 buf[i-1] = (char)k;
74 } 74 }
75 setstrV(L, L->base-1, lj_str_new(L, buf, (size_t)nargs)); 75 setstrV(L, L->base-1-LJ_FR2, lj_str_new(L, buf, (size_t)nargs));
76 return FFH_RES(1); 76 return FFH_RES(1);
77} 77}
78 78
diff --git a/src/lj_api.c b/src/lj_api.c
index 4a7809bc..6ad09b9d 100644
--- a/src/lj_api.c
+++ b/src/lj_api.c
@@ -284,8 +284,8 @@ LUA_API int lua_equal(lua_State *L, int idx1, int idx2)
284 } else { 284 } else {
285 L->top = base+2; 285 L->top = base+2;
286 lj_vm_call(L, base, 1+1); 286 lj_vm_call(L, base, 1+1);
287 L->top -= 2; 287 L->top -= 2+LJ_FR2;
288 return tvistruecond(L->top+1); 288 return tvistruecond(L->top+1+LJ_FR2);
289 } 289 }
290 } 290 }
291} 291}
@@ -307,8 +307,8 @@ LUA_API int lua_lessthan(lua_State *L, int idx1, int idx2)
307 } else { 307 } else {
308 L->top = base+2; 308 L->top = base+2;
309 lj_vm_call(L, base, 1+1); 309 lj_vm_call(L, base, 1+1);
310 L->top -= 2; 310 L->top -= 2+LJ_FR2;
311 return tvistruecond(L->top+1); 311 return tvistruecond(L->top+1+LJ_FR2);
312 } 312 }
313 } 313 }
314} 314}
@@ -704,8 +704,8 @@ LUA_API void lua_concat(lua_State *L, int n)
704 n -= (int)(L->top - top); 704 n -= (int)(L->top - top);
705 L->top = top+2; 705 L->top = top+2;
706 lj_vm_call(L, top, 1+1); 706 lj_vm_call(L, top, 1+1);
707 L->top--; 707 L->top -= 1+LJ_FR2;
708 copyTV(L, L->top-1, L->top); 708 copyTV(L, L->top-1, L->top+LJ_FR2);
709 } while (--n > 0); 709 } while (--n > 0);
710 } else if (n == 0) { /* Push empty string. */ 710 } else if (n == 0) { /* Push empty string. */
711 setstrV(L, L->top, &G(L)->strempty); 711 setstrV(L, L->top, &G(L)->strempty);
@@ -724,8 +724,8 @@ LUA_API void lua_gettable(lua_State *L, int idx)
724 if (v == NULL) { 724 if (v == NULL) {
725 L->top += 2; 725 L->top += 2;
726 lj_vm_call(L, L->top-2, 1+1); 726 lj_vm_call(L, L->top-2, 1+1);
727 L->top -= 2; 727 L->top -= 2+LJ_FR2;
728 v = L->top+1; 728 v = L->top+1+LJ_FR2;
729 } 729 }
730 copyTV(L, L->top-1, v); 730 copyTV(L, L->top-1, v);
731} 731}
@@ -740,8 +740,8 @@ LUA_API void lua_getfield(lua_State *L, int idx, const char *k)
740 if (v == NULL) { 740 if (v == NULL) {
741 L->top += 2; 741 L->top += 2;
742 lj_vm_call(L, L->top-2, 1+1); 742 lj_vm_call(L, L->top-2, 1+1);
743 L->top -= 2; 743 L->top -= 2+LJ_FR2;
744 v = L->top+1; 744 v = L->top+1+LJ_FR2;
745 } 745 }
746 copyTV(L, L->top, v); 746 copyTV(L, L->top, v);
747 incr_top(L); 747 incr_top(L);
@@ -882,13 +882,14 @@ LUA_API void lua_settable(lua_State *L, int idx)
882 o = lj_meta_tset(L, t, L->top-2); 882 o = lj_meta_tset(L, t, L->top-2);
883 if (o) { 883 if (o) {
884 /* NOBARRIER: lj_meta_tset ensures the table is not black. */ 884 /* NOBARRIER: lj_meta_tset ensures the table is not black. */
885 copyTV(L, o, L->top-1);
886 L->top -= 2; 885 L->top -= 2;
886 copyTV(L, o, L->top+1);
887 } else { 887 } else {
888 L->top += 3; 888 TValue *base = L->top;
889 copyTV(L, L->top-1, L->top-6); 889 copyTV(L, base+2, base-3-LJ_FR2);
890 lj_vm_call(L, L->top-3, 0+1); 890 L->top = base+3;
891 L->top -= 3; 891 lj_vm_call(L, base, 0+1);
892 L->top -= 3+LJ_FR2;
892 } 893 }
893} 894}
894 895
@@ -902,14 +903,14 @@ LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
902 setstrV(L, &key, lj_str_newz(L, k)); 903 setstrV(L, &key, lj_str_newz(L, k));
903 o = lj_meta_tset(L, t, &key); 904 o = lj_meta_tset(L, t, &key);
904 if (o) { 905 if (o) {
905 L->top--;
906 /* NOBARRIER: lj_meta_tset ensures the table is not black. */ 906 /* NOBARRIER: lj_meta_tset ensures the table is not black. */
907 copyTV(L, o, L->top); 907 copyTV(L, o, --L->top);
908 } else { 908 } else {
909 L->top += 3; 909 TValue *base = L->top;
910 copyTV(L, L->top-1, L->top-6); 910 copyTV(L, base+2, base-3-LJ_FR2);
911 lj_vm_call(L, L->top-3, 0+1); 911 L->top = base+3;
912 L->top -= 2; 912 lj_vm_call(L, base, 0+1);
913 L->top -= 2+LJ_FR2;
913 } 914 }
914} 915}
915 916
@@ -1016,11 +1017,24 @@ LUA_API const char *lua_setupvalue(lua_State *L, int idx, int n)
1016 1017
1017/* -- Calls --------------------------------------------------------------- */ 1018/* -- Calls --------------------------------------------------------------- */
1018 1019
1020#if LJ_FR2
1021static TValue *api_call_base(lua_State *L, int nargs)
1022{
1023 TValue *o = L->top, *base = o - nargs;
1024 L->top = o+1;
1025 for (; o > base; o--) copyTV(L, o, o-1);
1026 setnilV(o);
1027 return o+1;
1028}
1029#else
1030#define api_call_base(L, nargs) (L->top - (nargs))
1031#endif
1032
1019LUA_API void lua_call(lua_State *L, int nargs, int nresults) 1033LUA_API void lua_call(lua_State *L, int nargs, int nresults)
1020{ 1034{
1021 api_check(L, L->status == 0 || L->status == LUA_ERRERR); 1035 api_check(L, L->status == 0 || L->status == LUA_ERRERR);
1022 api_checknelems(L, nargs+1); 1036 api_checknelems(L, nargs+1);
1023 lj_vm_call(L, L->top - nargs, nresults+1); 1037 lj_vm_call(L, api_call_base(L, nargs), nresults+1);
1024} 1038}
1025 1039
1026LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc) 1040LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc)
@@ -1038,7 +1052,7 @@ LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc)
1038 api_checkvalidindex(L, o); 1052 api_checkvalidindex(L, o);
1039 ef = savestack(L, o); 1053 ef = savestack(L, o);
1040 } 1054 }
1041 status = lj_vm_pcall(L, L->top - nargs, nresults+1, ef); 1055 status = lj_vm_pcall(L, api_call_base(L, nargs), nresults+1, ef);
1042 if (status) hook_restore(g, oldh); 1056 if (status) hook_restore(g, oldh);
1043 return status; 1057 return status;
1044} 1058}
@@ -1046,12 +1060,14 @@ LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc)
1046static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud) 1060static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud)
1047{ 1061{
1048 GCfunc *fn = lj_func_newC(L, 0, getcurrenv(L)); 1062 GCfunc *fn = lj_func_newC(L, 0, getcurrenv(L));
1063 TValue *top = L->top;
1049 fn->c.f = func; 1064 fn->c.f = func;
1050 setfuncV(L, L->top, fn); 1065 setfuncV(L, top++, fn);
1051 setlightudV(L->top+1, checklightudptr(L, ud)); 1066 if (LJ_FR2) setnilV(top++);
1067 setlightudV(top++, checklightudptr(L, ud));
1052 cframe_nres(L->cframe) = 1+0; /* Zero results. */ 1068 cframe_nres(L->cframe) = 1+0; /* Zero results. */
1053 L->top += 2; 1069 L->top = top;
1054 return L->top-1; /* Now call the newly allocated C function. */ 1070 return top-1; /* Now call the newly allocated C function. */
1055} 1071}
1056 1072
1057LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud) 1073LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud)
@@ -1068,10 +1084,11 @@ LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud)
1068LUALIB_API int luaL_callmeta(lua_State *L, int idx, const char *field) 1084LUALIB_API int luaL_callmeta(lua_State *L, int idx, const char *field)
1069{ 1085{
1070 if (luaL_getmetafield(L, idx, field)) { 1086 if (luaL_getmetafield(L, idx, field)) {
1071 TValue *base = L->top--; 1087 TValue *top = L->top--;
1072 copyTV(L, base, index2adr(L, idx)); 1088 if (LJ_FR2) setnilV(top++);
1073 L->top = base+1; 1089 copyTV(L, top++, index2adr(L, idx));
1074 lj_vm_call(L, base, 1+1); 1090 L->top = top;
1091 lj_vm_call(L, top-1, 1+1);
1075 return 1; 1092 return 1;
1076 } 1093 }
1077 return 0; 1094 return 0;
@@ -1098,12 +1115,14 @@ LUA_API int lua_yield(lua_State *L, int nresults)
1098 } else { /* Yield from hook: add a pseudo-frame. */ 1115 } else { /* Yield from hook: add a pseudo-frame. */
1099 TValue *top = L->top; 1116 TValue *top = L->top;
1100 hook_leave(g); 1117 hook_leave(g);
1101 top->u64 = cframe_multres(cf); 1118 (top++)->u64 = cframe_multres(cf);
1102 setcont(top+1, lj_cont_hook); 1119 setcont(top, lj_cont_hook);
1103 setframe_pc(top+1, cframe_pc(cf)-1); 1120 if (LJ_FR2) top++;
1104 setframe_gc(top+2, obj2gco(L), LJ_TTHREAD); 1121 setframe_pc(top, cframe_pc(cf)-1);
1105 setframe_ftsz(top+2, ((char *)(top+3)-(char *)L->base)+FRAME_CONT); 1122 if (LJ_FR2) top++;
1106 L->top = L->base = top+3; 1123 setframe_gc(top, obj2gco(L), LJ_TTHREAD);
1124 setframe_ftsz(top, ((char *)(top+1)-(char *)L->base)+FRAME_CONT);
1125 L->top = L->base = top+1;
1107#if LJ_TARGET_X64 1126#if LJ_TARGET_X64
1108 lj_err_throw(L, LUA_YIELD); 1127 lj_err_throw(L, LUA_YIELD);
1109#else 1128#else
@@ -1120,7 +1139,9 @@ LUA_API int lua_yield(lua_State *L, int nresults)
1120LUA_API int lua_resume(lua_State *L, int nargs) 1139LUA_API int lua_resume(lua_State *L, int nargs)
1121{ 1140{
1122 if (L->cframe == NULL && L->status <= LUA_YIELD) 1141 if (L->cframe == NULL && L->status <= LUA_YIELD)
1123 return lj_vm_resume(L, L->top - nargs, 0, 0); 1142 return lj_vm_resume(L,
1143 L->status == 0 ? api_call_base(L, nargs) : L->top - nargs,
1144 0, 0);
1124 L->top = L->base; 1145 L->top = L->base;
1125 setstrV(L, L->top, lj_err_str(L, LJ_ERR_COSUSP)); 1146 setstrV(L, L->top, lj_err_str(L, LJ_ERR_COSUSP));
1126 incr_top(L); 1147 incr_top(L);
diff --git a/src/lj_arch.h b/src/lj_arch.h
index 36b38886..8f3796fc 100644
--- a/src/lj_arch.h
+++ b/src/lj_arch.h
@@ -365,8 +365,11 @@
365#endif 365#endif
366#endif 366#endif
367 367
368/* 2-slot frame info. */
369#define LJ_FR2 0
370
368/* Disable or enable the JIT compiler. */ 371/* Disable or enable the JIT compiler. */
369#if defined(LUAJIT_DISABLE_JIT) || defined(LJ_ARCH_NOJIT) || defined(LJ_OS_NOJIT) 372#if defined(LUAJIT_DISABLE_JIT) || defined(LJ_ARCH_NOJIT) || defined(LJ_OS_NOJIT) || LJ_FR2
370#define LJ_HASJIT 0 373#define LJ_HASJIT 0
371#else 374#else
372#define LJ_HASJIT 1 375#define LJ_HASJIT 1
diff --git a/src/lj_asm.c b/src/lj_asm.c
index e740e8a8..6002392c 100644
--- a/src/lj_asm.c
+++ b/src/lj_asm.c
@@ -1913,7 +1913,7 @@ static void asm_tail_link(ASMState *as)
1913 mres = (int32_t)(snap->nslots - baseslot); 1913 mres = (int32_t)(snap->nslots - baseslot);
1914 switch (bc_op(*pc)) { 1914 switch (bc_op(*pc)) {
1915 case BC_CALLM: case BC_CALLMT: 1915 case BC_CALLM: case BC_CALLMT:
1916 mres -= (int32_t)(1 + bc_a(*pc) + bc_c(*pc)); break; 1916 mres -= (int32_t)(1 + LJ_FR2 + bc_a(*pc) + bc_c(*pc)); break;
1917 case BC_RETM: mres -= (int32_t)(bc_a(*pc) + bc_d(*pc)); break; 1917 case BC_RETM: mres -= (int32_t)(bc_a(*pc) + bc_d(*pc)); break;
1918 case BC_TSETM: mres -= (int32_t)bc_a(*pc); break; 1918 case BC_TSETM: mres -= (int32_t)bc_a(*pc); break;
1919 default: if (bc_op(*pc) < BC_FUNCF) mres = 0; break; 1919 default: if (bc_op(*pc) < BC_FUNCF) mres = 0; break;
diff --git a/src/lj_asm_arm.h b/src/lj_asm_arm.h
index 8339367b..f8915cfb 100644
--- a/src/lj_asm_arm.h
+++ b/src/lj_asm_arm.h
@@ -481,7 +481,7 @@ static void asm_retf(ASMState *as, IRIns *ir)
481{ 481{
482 Reg base = ra_alloc1(as, REF_BASE, RSET_GPR); 482 Reg base = ra_alloc1(as, REF_BASE, RSET_GPR);
483 void *pc = ir_kptr(IR(ir->op2)); 483 void *pc = ir_kptr(IR(ir->op2));
484 int32_t delta = 1+bc_a(*((const BCIns *)pc - 1)); 484 int32_t delta = 1+LJ_FR2+bc_a(*((const BCIns *)pc - 1));
485 as->topslot -= (BCReg)delta; 485 as->topslot -= (BCReg)delta;
486 if ((int32_t)as->topslot < 0) as->topslot = 0; 486 if ((int32_t)as->topslot < 0) as->topslot = 0;
487 irt_setmark(IR(REF_BASE)->t); /* Children must not coalesce with BASE reg. */ 487 irt_setmark(IR(REF_BASE)->t); /* Children must not coalesce with BASE reg. */
diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h
index bc521596..346e0254 100644
--- a/src/lj_asm_mips.h
+++ b/src/lj_asm_mips.h
@@ -372,7 +372,7 @@ static void asm_retf(ASMState *as, IRIns *ir)
372{ 372{
373 Reg base = ra_alloc1(as, REF_BASE, RSET_GPR); 373 Reg base = ra_alloc1(as, REF_BASE, RSET_GPR);
374 void *pc = ir_kptr(IR(ir->op2)); 374 void *pc = ir_kptr(IR(ir->op2));
375 int32_t delta = 1+bc_a(*((const BCIns *)pc - 1)); 375 int32_t delta = 1+LJ_FR2+bc_a(*((const BCIns *)pc - 1));
376 as->topslot -= (BCReg)delta; 376 as->topslot -= (BCReg)delta;
377 if ((int32_t)as->topslot < 0) as->topslot = 0; 377 if ((int32_t)as->topslot < 0) as->topslot = 0;
378 irt_setmark(IR(REF_BASE)->t); /* Children must not coalesce with BASE reg. */ 378 irt_setmark(IR(REF_BASE)->t); /* Children must not coalesce with BASE reg. */
diff --git a/src/lj_asm_ppc.h b/src/lj_asm_ppc.h
index 815d9058..6fc8dfb7 100644
--- a/src/lj_asm_ppc.h
+++ b/src/lj_asm_ppc.h
@@ -361,7 +361,7 @@ static void asm_retf(ASMState *as, IRIns *ir)
361{ 361{
362 Reg base = ra_alloc1(as, REF_BASE, RSET_GPR); 362 Reg base = ra_alloc1(as, REF_BASE, RSET_GPR);
363 void *pc = ir_kptr(IR(ir->op2)); 363 void *pc = ir_kptr(IR(ir->op2));
364 int32_t delta = 1+bc_a(*((const BCIns *)pc - 1)); 364 int32_t delta = 1+LJ_FR2+bc_a(*((const BCIns *)pc - 1));
365 as->topslot -= (BCReg)delta; 365 as->topslot -= (BCReg)delta;
366 if ((int32_t)as->topslot < 0) as->topslot = 0; 366 if ((int32_t)as->topslot < 0) as->topslot = 0;
367 irt_setmark(IR(REF_BASE)->t); /* Children must not coalesce with BASE reg. */ 367 irt_setmark(IR(REF_BASE)->t); /* Children must not coalesce with BASE reg. */
diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h
index bd97764f..c4c7300d 100644
--- a/src/lj_asm_x86.h
+++ b/src/lj_asm_x86.h
@@ -643,7 +643,7 @@ static void asm_retf(ASMState *as, IRIns *ir)
643{ 643{
644 Reg base = ra_alloc1(as, REF_BASE, RSET_GPR); 644 Reg base = ra_alloc1(as, REF_BASE, RSET_GPR);
645 void *pc = ir_kptr(IR(ir->op2)); 645 void *pc = ir_kptr(IR(ir->op2));
646 int32_t delta = 1+bc_a(*((const BCIns *)pc - 1)); 646 int32_t delta = 1+LJ_FR2+bc_a(*((const BCIns *)pc - 1));
647 as->topslot -= (BCReg)delta; 647 as->topslot -= (BCReg)delta;
648 if ((int32_t)as->topslot < 0) as->topslot = 0; 648 if ((int32_t)as->topslot < 0) as->topslot = 0;
649 irt_setmark(IR(REF_BASE)->t); /* Children must not coalesce with BASE reg. */ 649 irt_setmark(IR(REF_BASE)->t); /* Children must not coalesce with BASE reg. */
diff --git a/src/lj_bcdump.h b/src/lj_bcdump.h
index 940ed147..ba6edfcc 100644
--- a/src/lj_bcdump.h
+++ b/src/lj_bcdump.h
@@ -42,8 +42,9 @@
42#define BCDUMP_F_BE 0x01 42#define BCDUMP_F_BE 0x01
43#define BCDUMP_F_STRIP 0x02 43#define BCDUMP_F_STRIP 0x02
44#define BCDUMP_F_FFI 0x04 44#define BCDUMP_F_FFI 0x04
45#define BCDUMP_F_FR2 0x08
45 46
46#define BCDUMP_F_KNOWN (BCDUMP_F_FFI*2-1) 47#define BCDUMP_F_KNOWN (BCDUMP_F_FR2*2-1)
47 48
48/* Type codes for the GC constants of a prototype. Plus length for strings. */ 49/* Type codes for the GC constants of a prototype. Plus length for strings. */
49enum { 50enum {
diff --git a/src/lj_bcread.c b/src/lj_bcread.c
index cea20e90..898f029c 100644
--- a/src/lj_bcread.c
+++ b/src/lj_bcread.c
@@ -394,6 +394,7 @@ static int bcread_header(LexState *ls)
394 bcread_byte(ls) != BCDUMP_VERSION) return 0; 394 bcread_byte(ls) != BCDUMP_VERSION) return 0;
395 bcread_flags(ls) = flags = bcread_uleb128(ls); 395 bcread_flags(ls) = flags = bcread_uleb128(ls);
396 if ((flags & ~(BCDUMP_F_KNOWN)) != 0) return 0; 396 if ((flags & ~(BCDUMP_F_KNOWN)) != 0) return 0;
397 if ((flags & BCDUMP_F_FR2) != LJ_FR2*BCDUMP_F_FR2) return 0;
397 if ((flags & BCDUMP_F_FFI)) { 398 if ((flags & BCDUMP_F_FFI)) {
398#if LJ_HASFFI 399#if LJ_HASFFI
399 lua_State *L = ls->L; 400 lua_State *L = ls->L;
diff --git a/src/lj_bcwrite.c b/src/lj_bcwrite.c
index a70735ca..cc51d0b2 100644
--- a/src/lj_bcwrite.c
+++ b/src/lj_bcwrite.c
@@ -309,8 +309,9 @@ static void bcwrite_header(BCWriteCtx *ctx)
309 *p++ = BCDUMP_HEAD3; 309 *p++ = BCDUMP_HEAD3;
310 *p++ = BCDUMP_VERSION; 310 *p++ = BCDUMP_VERSION;
311 *p++ = (ctx->strip ? BCDUMP_F_STRIP : 0) + 311 *p++ = (ctx->strip ? BCDUMP_F_STRIP : 0) +
312 (LJ_BE ? BCDUMP_F_BE : 0) + 312 LJ_BE*BCDUMP_F_BE +
313 ((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0); 313 ((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0) +
314 LJ_FR2*BCDUMP_F_FR2;
314 if (!ctx->strip) { 315 if (!ctx->strip) {
315 p = lj_strfmt_wuleb128(p, len); 316 p = lj_strfmt_wuleb128(p, len);
316 p = lj_buf_wmem(p, name, len); 317 p = lj_buf_wmem(p, name, len);
diff --git a/src/lj_ccallback.c b/src/lj_ccallback.c
index 5fe63a76..60735ade 100644
--- a/src/lj_ccallback.c
+++ b/src/lj_ccallback.c
@@ -422,7 +422,7 @@ static void callback_conv_args(CTState *cts, lua_State *L)
422 422
423 if (slot < cts->cb.sizeid && (id = cts->cb.cbid[slot]) != 0) { 423 if (slot < cts->cb.sizeid && (id = cts->cb.cbid[slot]) != 0) {
424 ct = ctype_get(cts, id); 424 ct = ctype_get(cts, id);
425 rid = ctype_cid(ct->info); 425 rid = ctype_cid(ct->info); /* Return type. x86: +(spadj<<16). */
426 fn = funcV(lj_tab_getint(cts->miscmap, (int32_t)slot)); 426 fn = funcV(lj_tab_getint(cts->miscmap, (int32_t)slot));
427 fntp = LJ_TFUNC; 427 fntp = LJ_TFUNC;
428 } else { /* Must set up frame first, before throwing the error. */ 428 } else { /* Must set up frame first, before throwing the error. */
@@ -431,9 +431,16 @@ static void callback_conv_args(CTState *cts, lua_State *L)
431 fn = (GCfunc *)L; 431 fn = (GCfunc *)L;
432 fntp = LJ_TTHREAD; 432 fntp = LJ_TTHREAD;
433 } 433 }
434 o->u32.lo = LJ_CONT_FFI_CALLBACK; /* Continuation returns from callback. */ 434 /* Continuation returns from callback. */
435 o->u32.hi = rid; /* Return type. x86: +(spadj<<16). */ 435 if (LJ_FR2) {
436 o++; 436 (o++)->u64 = LJ_CONT_FFI_CALLBACK;
437 (o++)->u64 = rid;
438 o++;
439 } else {
440 o->u32.lo = LJ_CONT_FFI_CALLBACK;
441 o->u32.hi = rid;
442 o++;
443 }
437 setframe_gc(o, obj2gco(fn), fntp); 444 setframe_gc(o, obj2gco(fn), fntp);
438 setframe_ftsz(o, ((char *)(o+1) - (char *)L->base) + FRAME_CONT); 445 setframe_ftsz(o, ((char *)(o+1) - (char *)L->base) + FRAME_CONT);
439 L->top = L->base = ++o; 446 L->top = L->base = ++o;
@@ -486,9 +493,14 @@ static void callback_conv_args(CTState *cts, lua_State *L)
486 L->top = o; 493 L->top = o;
487#if LJ_TARGET_X86 494#if LJ_TARGET_X86
488 /* Store stack adjustment for returns from non-cdecl callbacks. */ 495 /* Store stack adjustment for returns from non-cdecl callbacks. */
489 if (ctype_cconv(ct->info) != CTCC_CDECL) 496 if (ctype_cconv(ct->info) != CTCC_CDECL) {
497#if LJ_FR2
498 (L->base-3)->u64 |= (nsp << (16+2));
499#else
490 (L->base-2)->u32.hi |= (nsp << (16+2)); 500 (L->base-2)->u32.hi |= (nsp << (16+2));
491#endif 501#endif
502 }
503#endif
492 while (gcsteps-- > 0) 504 while (gcsteps-- > 0)
493 lj_gc_check(L); 505 lj_gc_check(L);
494} 506}
@@ -496,7 +508,11 @@ static void callback_conv_args(CTState *cts, lua_State *L)
496/* Convert Lua object to callback result. */ 508/* Convert Lua object to callback result. */
497static void callback_conv_result(CTState *cts, lua_State *L, TValue *o) 509static void callback_conv_result(CTState *cts, lua_State *L, TValue *o)
498{ 510{
511#if LJ_FR2
512 CType *ctr = ctype_raw(cts, (uint16_t)(L->base-3)->u64);
513#else
499 CType *ctr = ctype_raw(cts, (uint16_t)(L->base-2)->u32.hi); 514 CType *ctr = ctype_raw(cts, (uint16_t)(L->base-2)->u32.hi);
515#endif
500#if LJ_TARGET_X86 516#if LJ_TARGET_X86
501 cts->cb.gpr[2] = 0; 517 cts->cb.gpr[2] = 0;
502#endif 518#endif
@@ -565,7 +581,7 @@ void LJ_FASTCALL lj_ccallback_leave(CTState *cts, TValue *o)
565 } 581 }
566 callback_conv_result(cts, L, o); 582 callback_conv_result(cts, L, o);
567 /* Finally drop C frame and continuation frame. */ 583 /* Finally drop C frame and continuation frame. */
568 L->top -= 2; 584 L->top -= 2+2*LJ_FR2;
569 L->base = obase; 585 L->base = obase;
570 L->cframe = cframe_prev(L->cframe); 586 L->cframe = cframe_prev(L->cframe);
571 cts->cb.slot = 0; /* Blacklist C function that called the callback. */ 587 cts->cb.slot = 0; /* Blacklist C function that called the callback. */
diff --git a/src/lj_crecord.c b/src/lj_crecord.c
index eb37597a..10334cec 100644
--- a/src/lj_crecord.c
+++ b/src/lj_crecord.c
@@ -1123,7 +1123,7 @@ static void crec_snap_caller(jit_State *J)
1123 ptrdiff_t delta; 1123 ptrdiff_t delta;
1124 if (!frame_islua(base-1) || J->framedepth <= 0) 1124 if (!frame_islua(base-1) || J->framedepth <= 0)
1125 lj_trace_err(J, LJ_TRERR_NYICALL); 1125 lj_trace_err(J, LJ_TRERR_NYICALL);
1126 J->pc = frame_pc(base-1); delta = 1+bc_a(J->pc[-1]); 1126 J->pc = frame_pc(base-1); delta = 1+LJ_FR2+bc_a(J->pc[-1]);
1127 L->top = base; L->base = base - delta; 1127 L->top = base; L->base = base - delta;
1128 J->base[-1] = TREF_FALSE; 1128 J->base[-1] = TREF_FALSE;
1129 J->base -= delta; J->baseslot -= (BCReg)delta; 1129 J->base -= delta; J->baseslot -= (BCReg)delta;
diff --git a/src/lj_debug.c b/src/lj_debug.c
index 1b794753..e9117b31 100644
--- a/src/lj_debug.c
+++ b/src/lj_debug.c
@@ -24,7 +24,7 @@
24/* Get frame corresponding to a level. */ 24/* Get frame corresponding to a level. */
25cTValue *lj_debug_frame(lua_State *L, int level, int *size) 25cTValue *lj_debug_frame(lua_State *L, int level, int *size)
26{ 26{
27 cTValue *frame, *nextframe, *bot = tvref(L->stack); 27 cTValue *frame, *nextframe, *bot = tvref(L->stack)+LJ_FR2;
28 /* Traverse frames backwards. */ 28 /* Traverse frames backwards. */
29 for (nextframe = frame = L->base-1; frame > bot; ) { 29 for (nextframe = frame = L->base-1; frame > bot; ) {
30 if (frame_gc(frame) == obj2gco(L)) 30 if (frame_gc(frame) == obj2gco(L))
@@ -184,7 +184,7 @@ static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
184 TValue *nextframe = size ? frame + size : NULL; 184 TValue *nextframe = size ? frame + size : NULL;
185 GCfunc *fn = frame_func(frame); 185 GCfunc *fn = frame_func(frame);
186 BCPos pc = debug_framepc(L, fn, nextframe); 186 BCPos pc = debug_framepc(L, fn, nextframe);
187 if (!nextframe) nextframe = L->top; 187 if (!nextframe) nextframe = L->top+LJ_FR2;
188 if ((int)slot1 < 0) { /* Negative slot number is for varargs. */ 188 if ((int)slot1 < 0) { /* Negative slot number is for varargs. */
189 if (pc != NO_BCPOS) { 189 if (pc != NO_BCPOS) {
190 GCproto *pt = funcproto(fn); 190 GCproto *pt = funcproto(fn);
@@ -194,7 +194,7 @@ static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
194 nextframe = frame; 194 nextframe = frame;
195 frame = frame_prevd(frame); 195 frame = frame_prevd(frame);
196 } 196 }
197 if (frame + slot1 < nextframe) { 197 if (frame + slot1+LJ_FR2 < nextframe) {
198 *name = "(*vararg)"; 198 *name = "(*vararg)";
199 return frame+slot1; 199 return frame+slot1;
200 } 200 }
@@ -205,7 +205,7 @@ static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
205 if (pc != NO_BCPOS && 205 if (pc != NO_BCPOS &&
206 (*name = debug_varname(funcproto(fn), pc, slot1-1)) != NULL) 206 (*name = debug_varname(funcproto(fn), pc, slot1-1)) != NULL)
207 ; 207 ;
208 else if (slot1 > 0 && frame + slot1 < nextframe) 208 else if (slot1 > 0 && frame + slot1+LJ_FR2 < nextframe)
209 *name = "(*temporary)"; 209 *name = "(*temporary)";
210 return frame+slot1; 210 return frame+slot1;
211} 211}
@@ -268,7 +268,7 @@ restart:
268 *name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_c(ins)))); 268 *name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_c(ins))));
269 if (ip > proto_bc(pt)) { 269 if (ip > proto_bc(pt)) {
270 BCIns insp = ip[-1]; 270 BCIns insp = ip[-1];
271 if (bc_op(insp) == BC_MOV && bc_a(insp) == ra+1 && 271 if (bc_op(insp) == BC_MOV && bc_a(insp) == ra+1+LJ_FR2 &&
272 bc_d(insp) == bc_b(ins)) 272 bc_d(insp) == bc_b(ins))
273 return "method"; 273 return "method";
274 } 274 }
@@ -290,7 +290,7 @@ const char *lj_debug_funcname(lua_State *L, cTValue *frame, const char **name)
290 cTValue *pframe; 290 cTValue *pframe;
291 GCfunc *fn; 291 GCfunc *fn;
292 BCPos pc; 292 BCPos pc;
293 if (frame <= tvref(L->stack)) 293 if (frame <= tvref(L->stack)+LJ_FR2)
294 return NULL; 294 return NULL;
295 if (frame_isvarg(frame)) 295 if (frame_isvarg(frame))
296 frame = frame_prevd(frame); 296 frame = frame_prevd(frame);
diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c
index ea196ef2..8ce587a3 100644
--- a/src/lj_dispatch.c
+++ b/src/lj_dispatch.c
@@ -393,7 +393,7 @@ static BCReg cur_topslot(GCproto *pt, const BCIns *pc, uint32_t nres)
393 if (bc_op(ins) == BC_UCLO) 393 if (bc_op(ins) == BC_UCLO)
394 ins = pc[bc_j(ins)]; 394 ins = pc[bc_j(ins)];
395 switch (bc_op(ins)) { 395 switch (bc_op(ins)) {
396 case BC_CALLM: case BC_CALLMT: return bc_a(ins) + bc_c(ins) + nres-1+1; 396 case BC_CALLM: case BC_CALLMT: return bc_a(ins) + bc_c(ins) + nres-1+1+LJ_FR2;
397 case BC_RETM: return bc_a(ins) + bc_d(ins) + nres-1; 397 case BC_RETM: return bc_a(ins) + bc_d(ins) + nres-1;
398 case BC_TSETM: return bc_a(ins) + nres-1; 398 case BC_TSETM: return bc_a(ins) + nres-1;
399 default: return pt->framesize; 399 default: return pt->framesize;
diff --git a/src/lj_err.c b/src/lj_err.c
index a824ee66..5be938e4 100644
--- a/src/lj_err.c
+++ b/src/lj_err.c
@@ -106,7 +106,7 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode)
106 return cf; 106 return cf;
107 } 107 }
108 } 108 }
109 if (frame <= tvref(L->stack)) 109 if (frame <= tvref(L->stack)+LJ_FR2)
110 break; 110 break;
111 switch (frame_typep(frame)) { 111 switch (frame_typep(frame)) {
112 case FRAME_LUA: /* Lua frame. */ 112 case FRAME_LUA: /* Lua frame. */
@@ -171,7 +171,7 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode)
171 } 171 }
172 /* No C frame. */ 172 /* No C frame. */
173 if (errcode) { 173 if (errcode) {
174 L->base = tvref(L->stack)+1; 174 L->base = tvref(L->stack)+1+LJ_FR2;
175 L->cframe = NULL; 175 L->cframe = NULL;
176 unwindstack(L, L->base); 176 unwindstack(L, L->base);
177 if (G(L)->panic) 177 if (G(L)->panic)
@@ -494,7 +494,7 @@ LJ_NOINLINE void lj_err_mem(lua_State *L)
494/* Find error function for runtime errors. Requires an extra stack traversal. */ 494/* Find error function for runtime errors. Requires an extra stack traversal. */
495static ptrdiff_t finderrfunc(lua_State *L) 495static ptrdiff_t finderrfunc(lua_State *L)
496{ 496{
497 cTValue *frame = L->base-1, *bot = tvref(L->stack); 497 cTValue *frame = L->base-1, *bot = tvref(L->stack)+LJ_FR2;
498 void *cf = L->cframe; 498 void *cf = L->cframe;
499 while (frame > bot && cf) { 499 while (frame > bot && cf) {
500 while (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */ 500 while (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */
@@ -530,8 +530,8 @@ static ptrdiff_t finderrfunc(lua_State *L)
530 break; 530 break;
531 case FRAME_PCALL: 531 case FRAME_PCALL:
532 case FRAME_PCALLH: 532 case FRAME_PCALLH:
533 if (frame_ftsz(frame) >= (ptrdiff_t)(2*sizeof(TValue))) /* xpcall? */ 533 if (frame_func(frame_prevd(frame))->c.ffid == FF_xpcall)
534 return savestack(L, frame-1); /* Point to xpcall's errorfunc. */ 534 return savestack(L, frame_prevd(frame)+1); /* xpcall's errorfunc. */
535 return 0; 535 return 0;
536 default: 536 default:
537 lua_assert(0); 537 lua_assert(0);
@@ -554,8 +554,9 @@ LJ_NOINLINE void lj_err_run(lua_State *L)
554 lj_err_throw(L, LUA_ERRERR); 554 lj_err_throw(L, LUA_ERRERR);
555 } 555 }
556 L->status = LUA_ERRERR; 556 L->status = LUA_ERRERR;
557 copyTV(L, top, top-1); 557 copyTV(L, top+LJ_FR2, top-1);
558 copyTV(L, top-1, errfunc); 558 copyTV(L, top-1, errfunc);
559 if (LJ_FR2) setnilV(top++);
559 L->top = top+1; 560 L->top = top+1;
560 lj_vm_call(L, top, 1+1); /* Stack: |errfunc|msg| -> |msg| */ 561 lj_vm_call(L, top, 1+1); /* Stack: |errfunc|msg| -> |msg| */
561 } 562 }
@@ -630,6 +631,7 @@ LJ_NOINLINE void lj_err_optype_call(lua_State *L, TValue *o)
630 const BCIns *pc = cframe_Lpc(L); 631 const BCIns *pc = cframe_Lpc(L);
631 if (((ptrdiff_t)pc & FRAME_TYPE) != FRAME_LUA) { 632 if (((ptrdiff_t)pc & FRAME_TYPE) != FRAME_LUA) {
632 const char *tname = lj_typename(o); 633 const char *tname = lj_typename(o);
634 if (LJ_FR2) o++;
633 setframe_pc(o, pc); 635 setframe_pc(o, pc);
634 setframe_gc(o, obj2gco(L), LJ_TTHREAD); 636 setframe_gc(o, obj2gco(L), LJ_TTHREAD);
635 L->top = L->base = o+1; 637 L->top = L->base = o+1;
diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c
index b65759a5..55cdc63e 100644
--- a/src/lj_ffrecord.c
+++ b/src/lj_ffrecord.c
@@ -107,6 +107,7 @@ static void recff_stitch(jit_State *J)
107 TValue *pframe = frame_prevl(base-1); 107 TValue *pframe = frame_prevl(base-1);
108 TRef trcont; 108 TRef trcont;
109 109
110 lua_assert(!LJ_FR2); /* TODO_FR2: handle frame shift. */
110 /* Move func + args up in Lua stack and insert continuation. */ 111 /* Move func + args up in Lua stack and insert continuation. */
111 memmove(&base[1], &base[-1], sizeof(TValue)*(J->maxslot+1)); 112 memmove(&base[1], &base[-1], sizeof(TValue)*(J->maxslot+1));
112 setframe_ftsz(base+1, ((char *)(base+1) - (char *)pframe) + FRAME_CONT); 113 setframe_ftsz(base+1, ((char *)(base+1) - (char *)pframe) + FRAME_CONT);
@@ -466,6 +467,7 @@ static void LJ_FASTCALL recff_xpcall(jit_State *J, RecordFFData *rd)
466 TValue argv0, argv1; 467 TValue argv0, argv1;
467 TRef tmp; 468 TRef tmp;
468 int errcode; 469 int errcode;
470 lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */
469 /* Swap function and traceback. */ 471 /* Swap function and traceback. */
470 tmp = J->base[0]; J->base[0] = J->base[1]; J->base[1] = tmp; 472 tmp = J->base[0]; J->base[0] = J->base[1]; J->base[1] = tmp;
471 copyTV(J->L, &argv0, &rd->argv[0]); 473 copyTV(J->L, &argv0, &rd->argv[0]);
diff --git a/src/lj_frame.h b/src/lj_frame.h
index 061b396c..226d74f1 100644
--- a/src/lj_frame.h
+++ b/src/lj_frame.h
@@ -11,7 +11,16 @@
11 11
12/* -- Lua stack frame ----------------------------------------------------- */ 12/* -- Lua stack frame ----------------------------------------------------- */
13 13
14/* Frame type markers in callee function slot (callee base-1). */ 14/* Frame type markers in LSB of PC (4-byte aligned) or delta (8-byte aligned:
15**
16** PC 00 Lua frame
17** delta 001 C frame
18** delta 010 Continuation frame
19** delta 011 Lua vararg frame
20** delta 101 cpcall() frame
21** delta 110 ff pcall() frame
22** delta 111 ff pcall() frame with active hook
23*/
15enum { 24enum {
16 FRAME_LUA, FRAME_C, FRAME_CONT, FRAME_VARG, 25 FRAME_LUA, FRAME_C, FRAME_CONT, FRAME_VARG,
17 FRAME_LUAP, FRAME_CP, FRAME_PCALL, FRAME_PCALLH 26 FRAME_LUAP, FRAME_CP, FRAME_PCALL, FRAME_PCALLH
@@ -21,12 +30,47 @@ enum {
21#define FRAME_TYPEP (FRAME_TYPE|FRAME_P) 30#define FRAME_TYPEP (FRAME_TYPE|FRAME_P)
22 31
23/* Macros to access and modify Lua frames. */ 32/* Macros to access and modify Lua frames. */
33#if LJ_FR2
34/* Two-slot frame info, required for 64 bit PC/GCRef:
35**
36** base-2 base-1 | base base+1 ...
37** [func PC/delta/ft] | [slots ...]
38** ^-- frame | ^-- base ^-- top
39**
40** Continuation frames:
41**
42** base-4 base-3 base-2 base-1 | base base+1 ...
43** [cont PC ] [func PC/delta/ft] | [slots ...]
44** ^-- frame | ^-- base ^-- top
45*/
46#define frame_gc(f) (gcval((f)-1))
47#define frame_ftsz(f) ((ptrdiff_t)(f)->ftsz)
48#define frame_pc(f) ((const BCIns *)frame_ftsz(f))
49#define setframe_gc(f, p, tp) (setgcVraw((f)-1, (p), (tp)))
50#define setframe_ftsz(f, sz) ((f)->ftsz = (sz))
51#define setframe_pc(f, pc) ((f)->ftsz = (int64_t)(intptr_t)(pc))
52#else
53/* One-slot frame info, sufficient for 32 bit PC/GCRef:
54**
55** base-1 | base base+1 ...
56** lo hi |
57** [func | PC/delta/ft] | [slots ...]
58** ^-- frame | ^-- base ^-- top
59**
60** Continuation frames:
61**
62** base-2 base-1 | base base+1 ...
63** lo hi lo hi |
64** [cont | PC] [func | PC/delta/ft] | [slots ...]
65** ^-- frame | ^-- base ^-- top
66*/
24#define frame_gc(f) (gcref((f)->fr.func)) 67#define frame_gc(f) (gcref((f)->fr.func))
25#define frame_ftsz(f) ((ptrdiff_t)(f)->fr.tp.ftsz) 68#define frame_ftsz(f) ((ptrdiff_t)(f)->fr.tp.ftsz)
26#define frame_pc(f) (mref((f)->fr.tp.pcr, const BCIns)) 69#define frame_pc(f) (mref((f)->fr.tp.pcr, const BCIns))
27#define setframe_gc(f, p, tp) (setgcref((f)->fr.func, (p)), UNUSED(tp)) 70#define setframe_gc(f, p, tp) (setgcref((f)->fr.func, (p)), UNUSED(tp))
28#define setframe_ftsz(f, sz) ((f)->fr.tp.ftsz = (int32_t)(sz)) 71#define setframe_ftsz(f, sz) ((f)->fr.tp.ftsz = (int32_t)(sz))
29#define setframe_pc(f, pc) (setmref((f)->fr.tp.pcr, (pc))) 72#define setframe_pc(f, pc) (setmref((f)->fr.tp.pcr, (pc)))
73#endif
30 74
31#define frame_type(f) (frame_ftsz(f) & FRAME_TYPE) 75#define frame_type(f) (frame_ftsz(f) & FRAME_TYPE)
32#define frame_typep(f) (frame_ftsz(f) & FRAME_TYPEP) 76#define frame_typep(f) (frame_ftsz(f) & FRAME_TYPEP)
@@ -42,9 +86,16 @@ enum {
42 86
43enum { LJ_CONT_TAILCALL, LJ_CONT_FFI_CALLBACK }; /* Special continuations. */ 87enum { LJ_CONT_TAILCALL, LJ_CONT_FFI_CALLBACK }; /* Special continuations. */
44 88
89#if LJ_FR2
90#define frame_contpc(f) (frame_pc((f)-2))
91#define frame_contv(f) (((f)-3)->u64)
92#else
45#define frame_contpc(f) (frame_pc((f)-1)) 93#define frame_contpc(f) (frame_pc((f)-1))
46#define frame_contv(f) (((f)-1)->u32.lo) 94#define frame_contv(f) (((f)-1)->u32.lo)
47#if LJ_64 95#endif
96#if LJ_FR2
97#define frame_contf(f) ((ASMFunction)(uintptr_t)((f)-3)->u64)
98#elif LJ_64
48#define frame_contf(f) \ 99#define frame_contf(f) \
49 ((ASMFunction)(void *)((intptr_t)lj_vm_asm_begin + \ 100 ((ASMFunction)(void *)((intptr_t)lj_vm_asm_begin + \
50 (intptr_t)(int32_t)((f)-1)->u32.lo)) 101 (intptr_t)(int32_t)((f)-1)->u32.lo))
@@ -54,7 +105,7 @@ enum { LJ_CONT_TAILCALL, LJ_CONT_FFI_CALLBACK }; /* Special continuations. */
54#define frame_iscont_fficb(f) \ 105#define frame_iscont_fficb(f) \
55 (LJ_HASFFI && frame_contv(f) == LJ_CONT_FFI_CALLBACK) 106 (LJ_HASFFI && frame_contv(f) == LJ_CONT_FFI_CALLBACK)
56 107
57#define frame_prevl(f) ((f) - (1+bc_a(frame_pc(f)[-1]))) 108#define frame_prevl(f) ((f) - (1+LJ_FR2+bc_a(frame_pc(f)[-1])))
58#define frame_prevd(f) ((TValue *)((char *)(f) - frame_sized(f))) 109#define frame_prevd(f) ((TValue *)((char *)(f) - frame_sized(f)))
59#define frame_prev(f) (frame_islua(f)?frame_prevl(f):frame_prevd(f)) 110#define frame_prev(f) (frame_islua(f)?frame_prevl(f):frame_prevd(f))
60/* Note: this macro does not skip over FRAME_VARG. */ 111/* Note: this macro does not skip over FRAME_VARG. */
diff --git a/src/lj_gc.c b/src/lj_gc.c
index 5a7127c2..d6dfde93 100644
--- a/src/lj_gc.c
+++ b/src/lj_gc.c
@@ -268,12 +268,12 @@ static MSize gc_traverse_frames(global_State *g, lua_State *th)
268{ 268{
269 TValue *frame, *top = th->top-1, *bot = tvref(th->stack); 269 TValue *frame, *top = th->top-1, *bot = tvref(th->stack);
270 /* Note: extra vararg frame not skipped, marks function twice (harmless). */ 270 /* Note: extra vararg frame not skipped, marks function twice (harmless). */
271 for (frame = th->base-1; frame > bot; frame = frame_prev(frame)) { 271 for (frame = th->base-1; frame > bot+LJ_FR2; frame = frame_prev(frame)) {
272 GCfunc *fn = frame_func(frame); 272 GCfunc *fn = frame_func(frame);
273 TValue *ftop = frame; 273 TValue *ftop = frame;
274 if (isluafunc(fn)) ftop += funcproto(fn)->framesize; 274 if (isluafunc(fn)) ftop += funcproto(fn)->framesize;
275 if (ftop > top) top = ftop; 275 if (ftop > top) top = ftop;
276 gc_markobj(g, fn); /* Need to mark hidden function (or L). */ 276 if (!LJ_FR2) gc_markobj(g, fn); /* Need to mark hidden function (or L). */
277 } 277 }
278 top++; /* Correct bias of -1 (frame == base-1). */ 278 top++; /* Correct bias of -1 (frame == base-1). */
279 if (top > tvref(th->maxstack)) top = tvref(th->maxstack); 279 if (top > tvref(th->maxstack)) top = tvref(th->maxstack);
@@ -284,7 +284,7 @@ static MSize gc_traverse_frames(global_State *g, lua_State *th)
284static void gc_traverse_thread(global_State *g, lua_State *th) 284static void gc_traverse_thread(global_State *g, lua_State *th)
285{ 285{
286 TValue *o, *top = th->top; 286 TValue *o, *top = th->top;
287 for (o = tvref(th->stack)+1; o < top; o++) 287 for (o = tvref(th->stack)+1+LJ_FR2; o < top; o++)
288 gc_marktv(g, o); 288 gc_marktv(g, o);
289 if (g->gc.state == GCSatomic) { 289 if (g->gc.state == GCSatomic) {
290 top = tvref(th->stack) + th->stacksize; 290 top = tvref(th->stack) + th->stacksize;
@@ -456,13 +456,14 @@ static void gc_call_finalizer(global_State *g, lua_State *L,
456 int errcode; 456 int errcode;
457 TValue *top; 457 TValue *top;
458 lj_trace_abort(g); 458 lj_trace_abort(g);
459 top = L->top;
460 L->top = top+2;
461 hook_entergc(g); /* Disable hooks and new traces during __gc. */ 459 hook_entergc(g); /* Disable hooks and new traces during __gc. */
462 g->gc.threshold = LJ_MAX_MEM; /* Prevent GC steps. */ 460 g->gc.threshold = LJ_MAX_MEM; /* Prevent GC steps. */
463 copyTV(L, top, mo); 461 top = L->top;
464 setgcV(L, top+1, o, ~o->gch.gct); 462 copyTV(L, top++, mo);
465 errcode = lj_vm_pcall(L, top+1, 1+0, -1); /* Stack: |mo|o| -> | */ 463 if (LJ_FR2) setnilV(top++);
464 setgcV(L, top, o, ~o->gch.gct);
465 L->top = top+1;
466 errcode = lj_vm_pcall(L, top, 1+0, -1); /* Stack: |mo|o| -> | */
466 hook_restore(g, oldh); 467 hook_restore(g, oldh);
467 g->gc.threshold = oldt; /* Restore GC threshold. */ 468 g->gc.threshold = oldt; /* Restore GC threshold. */
468 if (errcode) 469 if (errcode)
diff --git a/src/lj_lib.h b/src/lj_lib.h
index 5bfd8d7c..dff99c09 100644
--- a/src/lj_lib.h
+++ b/src/lj_lib.h
@@ -47,8 +47,13 @@ LJ_FUNC GCtab *lj_lib_checktabornil(lua_State *L, int narg);
47LJ_FUNC int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst); 47LJ_FUNC int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst);
48 48
49/* Avoid including lj_frame.h. */ 49/* Avoid including lj_frame.h. */
50#if LJ_FR2
51#define lj_lib_upvalue(L, n) \
52 (&gcref((L->base-2)->gcr)->fn.c.upvalue[(n)-1])
53#else
50#define lj_lib_upvalue(L, n) \ 54#define lj_lib_upvalue(L, n) \
51 (&gcref((L->base-1)->fr.func)->fn.c.upvalue[(n)-1]) 55 (&gcref((L->base-1)->fr.func)->fn.c.upvalue[(n)-1])
56#endif
52 57
53#if LJ_TARGET_WINDOWS 58#if LJ_TARGET_WINDOWS
54#define lj_lib_checkfpu(L) \ 59#define lj_lib_checkfpu(L) \
diff --git a/src/lj_meta.c b/src/lj_meta.c
index 520c3763..d26ed220 100644
--- a/src/lj_meta.c
+++ b/src/lj_meta.c
@@ -80,12 +80,16 @@ int lj_meta_tailcall(lua_State *L, cTValue *tv)
80 TValue *base = L->base; 80 TValue *base = L->base;
81 TValue *top = L->top; 81 TValue *top = L->top;
82 const BCIns *pc = frame_pc(base-1); /* Preserve old PC from frame. */ 82 const BCIns *pc = frame_pc(base-1); /* Preserve old PC from frame. */
83 copyTV(L, base-1, tv); /* Replace frame with new object. */ 83 copyTV(L, base-1-LJ_FR2, tv); /* Replace frame with new object. */
84 top->u32.lo = LJ_CONT_TAILCALL; 84 if (LJ_FR2)
85 setframe_pc(top, pc); 85 (top++)->u64 = LJ_CONT_TAILCALL;
86 setframe_gc(top+1, obj2gco(L), LJ_TTHREAD); /* Dummy frame object. */ 86 else
87 setframe_ftsz(top+1, ((char *)(top+2) - (char *)base) + FRAME_CONT); 87 top->u32.lo = LJ_CONT_TAILCALL;
88 L->base = L->top = top+2; 88 setframe_pc(top++, pc);
89 if (LJ_FR2) top++;
90 setframe_gc(top, obj2gco(L), LJ_TTHREAD); /* Dummy frame object. */
91 setframe_ftsz(top, ((char *)(top+1) - (char *)base) + FRAME_CONT);
92 L->base = L->top = top+1;
89 /* 93 /*
90 ** before: [old_mo|PC] [... ...] 94 ** before: [old_mo|PC] [... ...]
91 ** ^base ^top 95 ** ^base ^top
@@ -116,11 +120,13 @@ static TValue *mmcall(lua_State *L, ASMFunction cont, cTValue *mo,
116 */ 120 */
117 TValue *top = L->top; 121 TValue *top = L->top;
118 if (curr_funcisL(L)) top = curr_topL(L); 122 if (curr_funcisL(L)) top = curr_topL(L);
119 setcont(top, cont); /* Assembler VM stores PC in upper word. */ 123 setcont(top++, cont); /* Assembler VM stores PC in upper word or FR2. */
120 copyTV(L, top+1, mo); /* Store metamethod and two arguments. */ 124 if (LJ_FR2) setnilV(top++);
121 copyTV(L, top+2, a); 125 copyTV(L, top++, mo); /* Store metamethod and two arguments. */
122 copyTV(L, top+3, b); 126 if (LJ_FR2) setnilV(top++);
123 return top+2; /* Return new base. */ 127 copyTV(L, top, a);
128 copyTV(L, top+1, b);
129 return top; /* Return new base. */
124} 130}
125 131
126/* -- C helpers for some instructions, called from assembler VM ----------- */ 132/* -- C helpers for some instructions, called from assembler VM ----------- */
@@ -256,10 +262,11 @@ TValue *lj_meta_cat(lua_State *L, TValue *top, int left)
256 ** after mm: [...][CAT stack ...] <--push-- [result] 262 ** after mm: [...][CAT stack ...] <--push-- [result]
257 ** next step: [...][CAT stack .............] 263 ** next step: [...][CAT stack .............]
258 */ 264 */
259 copyTV(L, top+2, top); /* Careful with the order of stack copies! */ 265 copyTV(L, top+2*LJ_FR2+2, top); /* Carefully ordered stack copies! */
260 copyTV(L, top+1, top-1); 266 copyTV(L, top+2*LJ_FR2+1, top-1);
261 copyTV(L, top, mo); 267 copyTV(L, top+LJ_FR2, mo);
262 setcont(top-1, lj_cont_cat); 268 setcont(top-1, lj_cont_cat);
269 if (LJ_FR2) { setnilV(top); setnilV(top+2); top += 2; }
263 return top+1; /* Trigger metamethod call. */ 270 return top+1; /* Trigger metamethod call. */
264 } else { 271 } else {
265 /* Pick as many strings as possible from the top and concatenate them: 272 /* Pick as many strings as possible from the top and concatenate them:
@@ -327,12 +334,14 @@ TValue *lj_meta_equal(lua_State *L, GCobj *o1, GCobj *o2, int ne)
327 return (TValue *)(intptr_t)ne; 334 return (TValue *)(intptr_t)ne;
328 } 335 }
329 top = curr_top(L); 336 top = curr_top(L);
330 setcont(top, ne ? lj_cont_condf : lj_cont_condt); 337 setcont(top++, ne ? lj_cont_condf : lj_cont_condt);
331 copyTV(L, top+1, mo); 338 if (LJ_FR2) setnilV(top++);
339 copyTV(L, top++, mo);
340 if (LJ_FR2) setnilV(top++);
332 it = ~(uint32_t)o1->gch.gct; 341 it = ~(uint32_t)o1->gch.gct;
333 setgcV(L, top+2, o1, it); 342 setgcV(L, top, o1, it);
334 setgcV(L, top+3, o2, it); 343 setgcV(L, top+1, o2, it);
335 return top+2; /* Trigger metamethod call. */ 344 return top; /* Trigger metamethod call. */
336 } 345 }
337 return (TValue *)(intptr_t)ne; 346 return (TValue *)(intptr_t)ne;
338} 347}
@@ -431,7 +440,8 @@ void lj_meta_call(lua_State *L, TValue *func, TValue *top)
431 TValue *p; 440 TValue *p;
432 if (!tvisfunc(mo)) 441 if (!tvisfunc(mo))
433 lj_err_optype_call(L, func); 442 lj_err_optype_call(L, func);
434 for (p = top; p > func; p--) copyTV(L, p, p-1); 443 for (p = top; p > func+2*LJ_FR2; p--) copyTV(L, p, p-1);
444 if (LJ_FR2) copyTV(L, func+2, func);
435 copyTV(L, func, mo); 445 copyTV(L, func, mo);
436} 446}
437 447
diff --git a/src/lj_obj.h b/src/lj_obj.h
index e5724859..438c83d4 100644
--- a/src/lj_obj.h
+++ b/src/lj_obj.h
@@ -131,7 +131,7 @@ typedef struct SBuf {
131/* Frame link. */ 131/* Frame link. */
132typedef union { 132typedef union {
133 int32_t ftsz; /* Frame type and size of previous frame. */ 133 int32_t ftsz; /* Frame type and size of previous frame. */
134 MRef pcr; /* Overlaps PC for Lua frames. */ 134 MRef pcr; /* Or PC for Lua frames. */
135} FrameLink; 135} FrameLink;
136 136
137/* Tagged value. */ 137/* Tagged value. */
@@ -147,12 +147,16 @@ typedef LJ_ALIGN(8) union TValue {
147 , uint32_t it; /* Internal object tag. Must overlap MSW of number. */ 147 , uint32_t it; /* Internal object tag. Must overlap MSW of number. */
148 ) 148 )
149 }; 149 };
150#if LJ_FR2
151 int64_t ftsz; /* Frame type and size of previous frame, or PC. */
152#else
150 struct { 153 struct {
151 LJ_ENDIAN_LOHI( 154 LJ_ENDIAN_LOHI(
152 GCRef func; /* Function for next frame (or dummy L). */ 155 GCRef func; /* Function for next frame (or dummy L). */
153 , FrameLink tp; /* Link to previous frame. */ 156 , FrameLink tp; /* Link to previous frame. */
154 ) 157 )
155 } fr; 158 } fr;
159#endif
156 struct { 160 struct {
157 LJ_ENDIAN_LOHI( 161 LJ_ENDIAN_LOHI(
158 uint32_t lo; /* Lower 32 bits of number. */ 162 uint32_t lo; /* Lower 32 bits of number. */
@@ -584,7 +588,11 @@ struct lua_State {
584#define registry(L) (&G(L)->registrytv) 588#define registry(L) (&G(L)->registrytv)
585 589
586/* Macros to access the currently executing (Lua) function. */ 590/* Macros to access the currently executing (Lua) function. */
591#if LJ_FR2
592#define curr_func(L) (&gcref((L->base-2)->gcr)->fn)
593#else
587#define curr_func(L) (&gcref((L->base-1)->fr.func)->fn) 594#define curr_func(L) (&gcref((L->base-1)->fr.func)->fn)
595#endif
588#define curr_funcisL(L) (isluafunc(curr_func(L))) 596#define curr_funcisL(L) (isluafunc(curr_func(L)))
589#define curr_proto(L) (funcproto(curr_func(L))) 597#define curr_proto(L) (funcproto(curr_func(L)))
590#define curr_topL(L) (L->base + curr_proto(L)->framesize) 598#define curr_topL(L) (L->base + curr_proto(L)->framesize)
@@ -732,10 +740,16 @@ static LJ_AINLINE void setlightudV(TValue *o, void *p)
732#if LJ_64 740#if LJ_64
733#define checklightudptr(L, p) \ 741#define checklightudptr(L, p) \
734 (((uint64_t)(p) >> 47) ? (lj_err_msg(L, LJ_ERR_BADLU), NULL) : (p)) 742 (((uint64_t)(p) >> 47) ? (lj_err_msg(L, LJ_ERR_BADLU), NULL) : (p))
743#else
744#define checklightudptr(L, p) (p)
745#endif
746
747#if LJ_FR2
748#define setcont(o, f) ((o)->u64 = (uint64_t)(uintptr_t)(void *)(f))
749#elif LJ_64
735#define setcont(o, f) \ 750#define setcont(o, f) \
736 ((o)->u64 = (uint64_t)(void *)(f) - (uint64_t)lj_vm_asm_begin) 751 ((o)->u64 = (uint64_t)(void *)(f) - (uint64_t)lj_vm_asm_begin)
737#else 752#else
738#define checklightudptr(L, p) (p)
739#define setcont(o, f) setlightudV((o), (void *)(f)) 753#define setcont(o, f) setlightudV((o), (void *)(f))
740#endif 754#endif
741 755
diff --git a/src/lj_parse.c b/src/lj_parse.c
index 198ddfc9..91282768 100644
--- a/src/lj_parse.c
+++ b/src/lj_parse.c
@@ -662,14 +662,14 @@ static void bcemit_method(FuncState *fs, ExpDesc *e, ExpDesc *key)
662 BCReg idx, func, obj = expr_toanyreg(fs, e); 662 BCReg idx, func, obj = expr_toanyreg(fs, e);
663 expr_free(fs, e); 663 expr_free(fs, e);
664 func = fs->freereg; 664 func = fs->freereg;
665 bcemit_AD(fs, BC_MOV, func+1, obj); /* Copy object to first argument. */ 665 bcemit_AD(fs, BC_MOV, func+1+LJ_FR2, obj); /* Copy object to 1st argument. */
666 lua_assert(expr_isstrk(key)); 666 lua_assert(expr_isstrk(key));
667 idx = const_str(fs, key); 667 idx = const_str(fs, key);
668 if (idx <= BCMAX_C) { 668 if (idx <= BCMAX_C) {
669 bcreg_reserve(fs, 2); 669 bcreg_reserve(fs, 2+LJ_FR2);
670 bcemit_ABC(fs, BC_TGETS, func, obj, idx); 670 bcemit_ABC(fs, BC_TGETS, func, obj, idx);
671 } else { 671 } else {
672 bcreg_reserve(fs, 3); 672 bcreg_reserve(fs, 3+LJ_FR2);
673 bcemit_AD(fs, BC_KSTR, func+2, idx); 673 bcemit_AD(fs, BC_KSTR, func+2, idx);
674 bcemit_ABC(fs, BC_TGETV, func, obj, func+2); 674 bcemit_ABC(fs, BC_TGETV, func, obj, func+2);
675 fs->freereg--; 675 fs->freereg--;
@@ -1913,11 +1913,11 @@ static void parse_args(LexState *ls, ExpDesc *e)
1913 lua_assert(e->k == VNONRELOC); 1913 lua_assert(e->k == VNONRELOC);
1914 base = e->u.s.info; /* Base register for call. */ 1914 base = e->u.s.info; /* Base register for call. */
1915 if (args.k == VCALL) { 1915 if (args.k == VCALL) {
1916 ins = BCINS_ABC(BC_CALLM, base, 2, args.u.s.aux - base - 1); 1916 ins = BCINS_ABC(BC_CALLM, base, 2, args.u.s.aux - base - 1 - LJ_FR2);
1917 } else { 1917 } else {
1918 if (args.k != VVOID) 1918 if (args.k != VVOID)
1919 expr_tonextreg(fs, &args); 1919 expr_tonextreg(fs, &args);
1920 ins = BCINS_ABC(BC_CALL, base, 2, fs->freereg - base); 1920 ins = BCINS_ABC(BC_CALL, base, 2, fs->freereg - base - LJ_FR2);
1921 } 1921 }
1922 expr_init(e, VCALL, bcemit_INS(fs, ins)); 1922 expr_init(e, VCALL, bcemit_INS(fs, ins));
1923 e->u.s.aux = base; 1923 e->u.s.aux = base;
@@ -1957,6 +1957,7 @@ static void expr_primary(LexState *ls, ExpDesc *v)
1957 parse_args(ls, v); 1957 parse_args(ls, v);
1958 } else if (ls->tok == '(' || ls->tok == TK_string || ls->tok == '{') { 1958 } else if (ls->tok == '(' || ls->tok == TK_string || ls->tok == '{') {
1959 expr_tonextreg(fs, v); 1959 expr_tonextreg(fs, v);
1960 if (LJ_FR2) bcreg_reserve(fs, 1);
1960 parse_args(ls, v); 1961 parse_args(ls, v);
1961 } else { 1962 } else {
1962 break; 1963 break;
@@ -2537,7 +2538,8 @@ static void parse_for_iter(LexState *ls, GCstr *indexname)
2537 lex_check(ls, TK_in); 2538 lex_check(ls, TK_in);
2538 line = ls->linenumber; 2539 line = ls->linenumber;
2539 assign_adjust(ls, 3, expr_list(ls, &e), &e); 2540 assign_adjust(ls, 3, expr_list(ls, &e), &e);
2540 bcreg_bump(fs, 3); /* The iterator needs another 3 slots (func + 2 args). */ 2541 /* The iterator needs another 3 [4] slots (func [pc] | state ctl). */
2542 bcreg_bump(fs, 3+LJ_FR2);
2541 isnext = (nvars <= 5 && predict_next(ls, fs, exprpc)); 2543 isnext = (nvars <= 5 && predict_next(ls, fs, exprpc));
2542 var_add(ls, 3); /* Hidden control variables. */ 2544 var_add(ls, 3); /* Hidden control variables. */
2543 lex_check(ls, TK_do); 2545 lex_check(ls, TK_do);
diff --git a/src/lj_record.c b/src/lj_record.c
index 01c09c58..539fd197 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -502,6 +502,7 @@ static LoopEvent rec_for(jit_State *J, const BCIns *fori, int isforl)
502static LoopEvent rec_iterl(jit_State *J, const BCIns iterins) 502static LoopEvent rec_iterl(jit_State *J, const BCIns iterins)
503{ 503{
504 BCReg ra = bc_a(iterins); 504 BCReg ra = bc_a(iterins);
505 lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */
505 if (!tref_isnil(getslot(J, ra))) { /* Looping back? */ 506 if (!tref_isnil(getslot(J, ra))) { /* Looping back? */
506 J->base[ra-1] = J->base[ra]; /* Copy result of ITERC to control var. */ 507 J->base[ra-1] = J->base[ra]; /* Copy result of ITERC to control var. */
507 J->maxslot = ra-1+bc_b(J->pc[-1]); 508 J->maxslot = ra-1+bc_b(J->pc[-1]);
@@ -672,6 +673,7 @@ static void rec_call_setup(jit_State *J, BCReg func, ptrdiff_t nargs)
672 TValue *functv = &J->L->base[func]; 673 TValue *functv = &J->L->base[func];
673 TRef *fbase = &J->base[func]; 674 TRef *fbase = &J->base[func];
674 ptrdiff_t i; 675 ptrdiff_t i;
676 lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */
675 for (i = 0; i <= nargs; i++) 677 for (i = 0; i <= nargs; i++)
676 (void)getslot(J, func+i); /* Ensure func and all args have a reference. */ 678 (void)getslot(J, func+i); /* Ensure func and all args have a reference. */
677 if (!tref_isfunc(fbase[0])) { /* Resolve __call metamethod. */ 679 if (!tref_isfunc(fbase[0])) { /* Resolve __call metamethod. */
@@ -788,7 +790,8 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
788 BCIns callins = *(frame_pc(frame)-1); 790 BCIns callins = *(frame_pc(frame)-1);
789 ptrdiff_t nresults = bc_b(callins) ? (ptrdiff_t)bc_b(callins)-1 :gotresults; 791 ptrdiff_t nresults = bc_b(callins) ? (ptrdiff_t)bc_b(callins)-1 :gotresults;
790 BCReg cbase = bc_a(callins); 792 BCReg cbase = bc_a(callins);
791 GCproto *pt = funcproto(frame_func(frame - (cbase+1))); 793 GCproto *pt = funcproto(frame_func(frame - (cbase+1-LJ_FR2)));
794 lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame teardown. */
792 if ((pt->flags & PROTO_NOJIT)) 795 if ((pt->flags & PROTO_NOJIT))
793 lj_trace_err(J, LJ_TRERR_CJITOFF); 796 lj_trace_err(J, LJ_TRERR_CJITOFF);
794 if (J->framedepth == 0 && J->pt && frame == J->L->base - 1) { 797 if (J->framedepth == 0 && J->pt && frame == J->L->base - 1) {
@@ -973,6 +976,7 @@ static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm)
973 lj_trace_err(J, LJ_TRERR_NOMM); 976 lj_trace_err(J, LJ_TRERR_NOMM);
974 } 977 }
975ok: 978ok:
979 lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */
976 base[0] = ix->mobj; 980 base[0] = ix->mobj;
977 copyTV(J->L, basev+0, &ix->mobjv); 981 copyTV(J->L, basev+0, &ix->mobjv);
978 lj_record_call(J, func, 2); 982 lj_record_call(J, func, 2);
@@ -989,6 +993,7 @@ static TRef rec_mm_len(jit_State *J, TRef tr, TValue *tv)
989 BCReg func = rec_mm_prep(J, lj_cont_ra); 993 BCReg func = rec_mm_prep(J, lj_cont_ra);
990 TRef *base = J->base + func; 994 TRef *base = J->base + func;
991 TValue *basev = J->L->base + func; 995 TValue *basev = J->L->base + func;
996 lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */
992 base[0] = ix.mobj; copyTV(J->L, basev+0, &ix.mobjv); 997 base[0] = ix.mobj; copyTV(J->L, basev+0, &ix.mobjv);
993 base[1] = tr; copyTV(J->L, basev+1, tv); 998 base[1] = tr; copyTV(J->L, basev+1, tv);
994#if LJ_52 999#if LJ_52
@@ -1011,6 +1016,7 @@ static void rec_mm_callcomp(jit_State *J, RecordIndex *ix, int op)
1011 BCReg func = rec_mm_prep(J, (op&1) ? lj_cont_condf : lj_cont_condt); 1016 BCReg func = rec_mm_prep(J, (op&1) ? lj_cont_condf : lj_cont_condt);
1012 TRef *base = J->base + func; 1017 TRef *base = J->base + func;
1013 TValue *tv = J->L->base + func; 1018 TValue *tv = J->L->base + func;
1019 lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */
1014 base[0] = ix->mobj; base[1] = ix->val; base[2] = ix->key; 1020 base[0] = ix->mobj; base[1] = ix->val; base[2] = ix->key;
1015 copyTV(J->L, tv+0, &ix->mobjv); 1021 copyTV(J->L, tv+0, &ix->mobjv);
1016 copyTV(J->L, tv+1, &ix->valv); 1022 copyTV(J->L, tv+1, &ix->valv);
@@ -1261,6 +1267,7 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix)
1261 BCReg func = rec_mm_prep(J, ix->val ? lj_cont_nop : lj_cont_ra); 1267 BCReg func = rec_mm_prep(J, ix->val ? lj_cont_nop : lj_cont_ra);
1262 TRef *base = J->base + func; 1268 TRef *base = J->base + func;
1263 TValue *tv = J->L->base + func; 1269 TValue *tv = J->L->base + func;
1270 lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */
1264 base[0] = ix->mobj; base[1] = ix->tab; base[2] = ix->key; 1271 base[0] = ix->mobj; base[1] = ix->tab; base[2] = ix->key;
1265 setfuncV(J->L, tv+0, funcV(&ix->mobjv)); 1272 setfuncV(J->L, tv+0, funcV(&ix->mobjv));
1266 copyTV(J->L, tv+1, &ix->tabv); 1273 copyTV(J->L, tv+1, &ix->tabv);
@@ -2135,28 +2142,28 @@ void lj_record_ins(jit_State *J)
2135 /* -- Calls and vararg handling ----------------------------------------- */ 2142 /* -- Calls and vararg handling ----------------------------------------- */
2136 2143
2137 case BC_ITERC: 2144 case BC_ITERC:
2138 J->base[ra] = getslot(J, ra-3); 2145 J->base[ra] = getslot(J, ra-3-LJ_FR2);
2139 J->base[ra+1] = getslot(J, ra-2); 2146 J->base[ra+1] = getslot(J, ra-2-LJ_FR2);
2140 J->base[ra+2] = getslot(J, ra-1); 2147 J->base[ra+2] = getslot(J, ra-1-LJ_FR2);
2141 { /* Do the actual copy now because lj_record_call needs the values. */ 2148 { /* Do the actual copy now because lj_record_call needs the values. */
2142 TValue *b = &J->L->base[ra]; 2149 TValue *b = &J->L->base[ra];
2143 copyTV(J->L, b, b-3); 2150 copyTV(J->L, b, b-3-LJ_FR2);
2144 copyTV(J->L, b+1, b-2); 2151 copyTV(J->L, b+1, b-2-LJ_FR2);
2145 copyTV(J->L, b+2, b-1); 2152 copyTV(J->L, b+2, b-1-LJ_FR2);
2146 } 2153 }
2147 lj_record_call(J, ra, (ptrdiff_t)rc-1); 2154 lj_record_call(J, ra, (ptrdiff_t)rc-1);
2148 break; 2155 break;
2149 2156
2150 /* L->top is set to L->base+ra+rc+NARGS-1+1. See lj_dispatch_ins(). */ 2157 /* L->top is set to L->base+ra+rc+NARGS-1+1. See lj_dispatch_ins(). */
2151 case BC_CALLM: 2158 case BC_CALLM:
2152 rc = (BCReg)(J->L->top - J->L->base) - ra; 2159 rc = (BCReg)(J->L->top - J->L->base) - ra - LJ_FR2;
2153 /* fallthrough */ 2160 /* fallthrough */
2154 case BC_CALL: 2161 case BC_CALL:
2155 lj_record_call(J, ra, (ptrdiff_t)rc-1); 2162 lj_record_call(J, ra, (ptrdiff_t)rc-1);
2156 break; 2163 break;
2157 2164
2158 case BC_CALLMT: 2165 case BC_CALLMT:
2159 rc = (BCReg)(J->L->top - J->L->base) - ra; 2166 rc = (BCReg)(J->L->top - J->L->base) - ra - LJ_FR2;
2160 /* fallthrough */ 2167 /* fallthrough */
2161 case BC_CALLT: 2168 case BC_CALLT:
2162 lj_record_tailcall(J, ra, (ptrdiff_t)rc-1); 2169 lj_record_tailcall(J, ra, (ptrdiff_t)rc-1);
diff --git a/src/lj_snap.c b/src/lj_snap.c
index 2917424f..4bac2d28 100644
--- a/src/lj_snap.c
+++ b/src/lj_snap.c
@@ -100,6 +100,7 @@ static BCReg snapshot_framelinks(jit_State *J, SnapEntry *map)
100 GCfunc *fn = frame_func(frame); 100 GCfunc *fn = frame_func(frame);
101 cTValue *ftop = isluafunc(fn) ? (frame+funcproto(fn)->framesize) : J->L->top; 101 cTValue *ftop = isluafunc(fn) ? (frame+funcproto(fn)->framesize) : J->L->top;
102 MSize f = 0; 102 MSize f = 0;
103 lua_assert(!LJ_FR2); /* TODO_FR2: store 64 bit PCs. */
103 map[f++] = SNAP_MKPC(J->pc); /* The current PC is always the first entry. */ 104 map[f++] = SNAP_MKPC(J->pc); /* The current PC is always the first entry. */
104 while (frame > lim) { /* Backwards traversal of all frames above base. */ 105 while (frame > lim) { /* Backwards traversal of all frames above base. */
105 if (frame_islua(frame)) { 106 if (frame_islua(frame)) {
@@ -241,7 +242,8 @@ static BCReg snap_usedef(jit_State *J, uint8_t *udf,
241 case BCMbase: 242 case BCMbase:
242 if (op >= BC_CALLM && op <= BC_VARG) { 243 if (op >= BC_CALLM && op <= BC_VARG) {
243 BCReg top = (op == BC_CALLM || op == BC_CALLMT || bc_c(ins) == 0) ? 244 BCReg top = (op == BC_CALLM || op == BC_CALLMT || bc_c(ins) == 0) ?
244 maxslot : (bc_a(ins) + bc_c(ins)); 245 maxslot : (bc_a(ins) + bc_c(ins)+LJ_FR2);
246 if (LJ_FR2) DEF_SLOT(bc_a(ins)+1);
245 s = bc_a(ins) - ((op == BC_ITERC || op == BC_ITERN) ? 3 : 0); 247 s = bc_a(ins) - ((op == BC_ITERC || op == BC_ITERN) ? 3 : 0);
246 for (; s < top; s++) USE_SLOT(s); 248 for (; s < top; s++) USE_SLOT(s);
247 for (; s < maxslot; s++) DEF_SLOT(s); 249 for (; s < maxslot; s++) DEF_SLOT(s);
@@ -836,6 +838,7 @@ const BCIns *lj_snap_restore(jit_State *J, void *exptr)
836 snap_restoreval(J, T, ex, snapno, rfilt, ref+1, &tmp); 838 snap_restoreval(J, T, ex, snapno, rfilt, ref+1, &tmp);
837 o->u32.hi = tmp.u32.lo; 839 o->u32.hi = tmp.u32.lo;
838 } else if ((sn & (SNAP_CONT|SNAP_FRAME))) { 840 } else if ((sn & (SNAP_CONT|SNAP_FRAME))) {
841 lua_assert(!LJ_FR2); /* TODO_FR2: store 64 bit PCs. */
839 /* Overwrite tag with frame link. */ 842 /* Overwrite tag with frame link. */
840 setframe_ftsz(o, snap_slot(sn) != 0 ? (int32_t)*flinks-- : ftsz0); 843 setframe_ftsz(o, snap_slot(sn) != 0 ? (int32_t)*flinks-- : ftsz0);
841 L->base = o+1; 844 L->base = o+1;
diff --git a/src/lj_state.c b/src/lj_state.c
index 344f8fe1..f7cdb8f3 100644
--- a/src/lj_state.c
+++ b/src/lj_state.c
@@ -49,6 +49,7 @@
49** one extra slot if mobj is not a function. Only lj_meta_tset needs 5 49** one extra slot if mobj is not a function. Only lj_meta_tset needs 5
50** slots above top, but then mobj is always a function. So we can get by 50** slots above top, but then mobj is always a function. So we can get by
51** with 5 extra slots. 51** with 5 extra slots.
52** LJ_FR2: We need 2 more slots for the frame PC and the continuation PC.
52*/ 53*/
53 54
54/* Resize stack slots and adjust pointers in state. */ 55/* Resize stack slots and adjust pointers in state. */
@@ -128,8 +129,9 @@ static void stack_init(lua_State *L1, lua_State *L)
128 L1->stacksize = LJ_STACK_START + LJ_STACK_EXTRA; 129 L1->stacksize = LJ_STACK_START + LJ_STACK_EXTRA;
129 stend = st + L1->stacksize; 130 stend = st + L1->stacksize;
130 setmref(L1->maxstack, stend - LJ_STACK_EXTRA - 1); 131 setmref(L1->maxstack, stend - LJ_STACK_EXTRA - 1);
131 L1->base = L1->top = st+1; 132 setthreadV(L1, st++, L1); /* Needed for curr_funcisL() on empty stack. */
132 setthreadV(L1, st, L1); /* Needed for curr_funcisL() on empty stack. */ 133 if (LJ_FR2) setnilV(st++);
134 L1->base = L1->top = st;
133 while (st < stend) /* Clear new slots. */ 135 while (st < stend) /* Clear new slots. */
134 setnilV(st++); 136 setnilV(st++);
135} 137}
@@ -253,7 +255,7 @@ LUA_API void lua_close(lua_State *L)
253 for (i = 0;;) { 255 for (i = 0;;) {
254 hook_enter(g); 256 hook_enter(g);
255 L->status = 0; 257 L->status = 0;
256 L->base = L->top = tvref(L->stack) + 1; 258 L->base = L->top = tvref(L->stack) + 1 + LJ_FR2;
257 L->cframe = NULL; 259 L->cframe = NULL;
258 if (lj_vm_cpcall(L, NULL, NULL, cpfinalize) == 0) { 260 if (lj_vm_cpcall(L, NULL, NULL, cpfinalize) == 0) {
259 if (++i >= 10) break; 261 if (++i >= 10) break;
diff --git a/src/lj_trace.c b/src/lj_trace.c
index f386b95e..7d2ce8f2 100644
--- a/src/lj_trace.c
+++ b/src/lj_trace.c
@@ -830,7 +830,7 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
830 ERRNO_RESTORE 830 ERRNO_RESTORE
831 switch (bc_op(*pc)) { 831 switch (bc_op(*pc)) {
832 case BC_CALLM: case BC_CALLMT: 832 case BC_CALLM: case BC_CALLMT:
833 return (int)((BCReg)(L->top - L->base) - bc_a(*pc) - bc_c(*pc)); 833 return (int)((BCReg)(L->top - L->base) - bc_a(*pc) - bc_c(*pc) + LJ_FR2);
834 case BC_RETM: 834 case BC_RETM:
835 return (int)((BCReg)(L->top - L->base) + 1 - bc_a(*pc) - bc_d(*pc)); 835 return (int)((BCReg)(L->top - L->base) + 1 - bc_a(*pc) - bc_d(*pc));
836 case BC_TSETM: 836 case BC_TSETM:
diff --git a/src/lj_vmevent.c b/src/lj_vmevent.c
index e14ad5b6..8e10a627 100644
--- a/src/lj_vmevent.c
+++ b/src/lj_vmevent.c
@@ -27,6 +27,7 @@ ptrdiff_t lj_vmevent_prepare(lua_State *L, VMEvent ev)
27 if (tv && tvisfunc(tv)) { 27 if (tv && tvisfunc(tv)) {
28 lj_state_checkstack(L, LUA_MINSTACK); 28 lj_state_checkstack(L, LUA_MINSTACK);
29 setfuncV(L, L->top++, funcV(tv)); 29 setfuncV(L, L->top++, funcV(tv));
30 if (LJ_FR2) setnilV(L->top++);
30 return savestack(L, L->top); 31 return savestack(L, L->top);
31 } 32 }
32 } 33 }