diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib_base.c | 84 |
1 files changed, 32 insertions, 52 deletions
diff --git a/src/lib_base.c b/src/lib_base.c index 1564725e..6107bde0 100644 --- a/src/lib_base.c +++ b/src/lib_base.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "lj_dispatch.h" | 32 | #include "lj_dispatch.h" |
33 | #include "lj_char.h" | 33 | #include "lj_char.h" |
34 | #include "lj_strscan.h" | 34 | #include "lj_strscan.h" |
35 | #include "lj_strfmt.h" | ||
35 | #include "lj_lib.h" | 36 | #include "lj_lib.h" |
36 | 37 | ||
37 | /* -- Base library: checks ------------------------------------------------ */ | 38 | /* -- Base library: checks ------------------------------------------------ */ |
@@ -86,10 +87,11 @@ static int ffh_pairs(lua_State *L, MMS mm) | |||
86 | cTValue *mo = lj_meta_lookup(L, o, mm); | 87 | cTValue *mo = lj_meta_lookup(L, o, mm); |
87 | if ((LJ_52 || tviscdata(o)) && !tvisnil(mo)) { | 88 | if ((LJ_52 || tviscdata(o)) && !tvisnil(mo)) { |
88 | L->top = o+1; /* Only keep one argument. */ | 89 | L->top = o+1; /* Only keep one argument. */ |
89 | copyTV(L, L->base-1, mo); /* Replace callable. */ | 90 | copyTV(L, L->base-1-LJ_FR2, mo); /* Replace callable. */ |
90 | return FFH_TAILCALL; | 91 | return FFH_TAILCALL; |
91 | } else { | 92 | } else { |
92 | 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--; } | ||
93 | setfuncV(L, o-1, funcV(lj_lib_upvalue(L, 1))); | 95 | setfuncV(L, o-1, funcV(lj_lib_upvalue(L, 1))); |
94 | 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); |
95 | return FFH_RES(3); | 97 | return FFH_RES(3); |
@@ -100,7 +102,7 @@ static int ffh_pairs(lua_State *L, MMS mm) | |||
100 | #endif | 102 | #endif |
101 | 103 | ||
102 | LJLIB_PUSH(lastcl) | 104 | LJLIB_PUSH(lastcl) |
103 | LJLIB_ASM(pairs) | 105 | LJLIB_ASM(pairs) LJLIB_REC(xpairs 0) |
104 | { | 106 | { |
105 | return ffh_pairs(L, MM_pairs); | 107 | return ffh_pairs(L, MM_pairs); |
106 | } | 108 | } |
@@ -113,7 +115,7 @@ LJLIB_NOREGUV LJLIB_ASM(ipairs_aux) LJLIB_REC(.) | |||
113 | } | 115 | } |
114 | 116 | ||
115 | LJLIB_PUSH(lastcl) | 117 | LJLIB_PUSH(lastcl) |
116 | LJLIB_ASM(ipairs) LJLIB_REC(.) | 118 | LJLIB_ASM(ipairs) LJLIB_REC(xpairs 1) |
117 | { | 119 | { |
118 | return ffh_pairs(L, MM_ipairs); | 120 | return ffh_pairs(L, MM_ipairs); |
119 | } | 121 | } |
@@ -131,11 +133,11 @@ LJLIB_ASM(setmetatable) LJLIB_REC(.) | |||
131 | lj_err_caller(L, LJ_ERR_PROTMT); | 133 | lj_err_caller(L, LJ_ERR_PROTMT); |
132 | setgcref(t->metatable, obj2gco(mt)); | 134 | setgcref(t->metatable, obj2gco(mt)); |
133 | if (mt) { lj_gc_objbarriert(L, t, mt); } | 135 | if (mt) { lj_gc_objbarriert(L, t, mt); } |
134 | settabV(L, L->base-1, t); | 136 | settabV(L, L->base-1-LJ_FR2, t); |
135 | return FFH_RES(1); | 137 | return FFH_RES(1); |
136 | } | 138 | } |
137 | 139 | ||
138 | LJLIB_CF(getfenv) | 140 | LJLIB_CF(getfenv) LJLIB_REC(.) |
139 | { | 141 | { |
140 | GCfunc *fn; | 142 | GCfunc *fn; |
141 | cTValue *o = L->base; | 143 | cTValue *o = L->base; |
@@ -144,6 +146,7 @@ LJLIB_CF(getfenv) | |||
144 | o = lj_debug_frame(L, level, &level); | 146 | o = lj_debug_frame(L, level, &level); |
145 | if (o == NULL) | 147 | if (o == NULL) |
146 | lj_err_arg(L, 1, LJ_ERR_INVLVL); | 148 | lj_err_arg(L, 1, LJ_ERR_INVLVL); |
149 | if (LJ_FR2) o--; | ||
147 | } | 150 | } |
148 | fn = &gcval(o)->fn; | 151 | fn = &gcval(o)->fn; |
149 | 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)); |
@@ -165,6 +168,7 @@ LJLIB_CF(setfenv) | |||
165 | o = lj_debug_frame(L, level, &level); | 168 | o = lj_debug_frame(L, level, &level); |
166 | if (o == NULL) | 169 | if (o == NULL) |
167 | lj_err_arg(L, 1, LJ_ERR_INVLVL); | 170 | lj_err_arg(L, 1, LJ_ERR_INVLVL); |
171 | if (LJ_FR2) o--; | ||
168 | } | 172 | } |
169 | fn = &gcval(o)->fn; | 173 | fn = &gcval(o)->fn; |
170 | if (!isluafunc(fn)) | 174 | if (!isluafunc(fn)) |
@@ -257,7 +261,7 @@ LJLIB_ASM(tonumber) LJLIB_REC(.) | |||
257 | if (base == 10) { | 261 | if (base == 10) { |
258 | TValue *o = lj_lib_checkany(L, 1); | 262 | TValue *o = lj_lib_checkany(L, 1); |
259 | if (lj_strscan_numberobj(o)) { | 263 | if (lj_strscan_numberobj(o)) { |
260 | copyTV(L, L->base-1, o); | 264 | copyTV(L, L->base-1-LJ_FR2, o); |
261 | return FFH_RES(1); | 265 | return FFH_RES(1); |
262 | } | 266 | } |
263 | #if LJ_HASFFI | 267 | #if LJ_HASFFI |
@@ -270,11 +274,11 @@ LJLIB_ASM(tonumber) LJLIB_REC(.) | |||
270 | ct->size <= 4 && !(ct->size == 4 && (ct->info & CTF_UNSIGNED))) { | 274 | ct->size <= 4 && !(ct->size == 4 && (ct->info & CTF_UNSIGNED))) { |
271 | int32_t i; | 275 | int32_t i; |
272 | 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); |
273 | setintV(L->base-1, i); | 277 | setintV(L->base-1-LJ_FR2, i); |
274 | return FFH_RES(1); | 278 | return FFH_RES(1); |
275 | } | 279 | } |
276 | lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE), | 280 | lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE), |
277 | (uint8_t *)&(L->base-1)->n, o, 0); | 281 | (uint8_t *)&(L->base-1-LJ_FR2)->n, o, 0); |
278 | return FFH_RES(1); | 282 | return FFH_RES(1); |
279 | } | 283 | } |
280 | } | 284 | } |
@@ -290,45 +294,29 @@ LJLIB_ASM(tonumber) LJLIB_REC(.) | |||
290 | while (lj_char_isspace((unsigned char)(*ep))) ep++; | 294 | while (lj_char_isspace((unsigned char)(*ep))) ep++; |
291 | if (*ep == '\0') { | 295 | if (*ep == '\0') { |
292 | if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u)) | 296 | if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u)) |
293 | setintV(L->base-1, (int32_t)ul); | 297 | setintV(L->base-1-LJ_FR2, (int32_t)ul); |
294 | else | 298 | else |
295 | setnumV(L->base-1, (lua_Number)ul); | 299 | setnumV(L->base-1-LJ_FR2, (lua_Number)ul); |
296 | return FFH_RES(1); | 300 | return FFH_RES(1); |
297 | } | 301 | } |
298 | } | 302 | } |
299 | } | 303 | } |
300 | setnilV(L->base-1); | 304 | setnilV(L->base-1-LJ_FR2); |
301 | return FFH_RES(1); | 305 | return FFH_RES(1); |
302 | } | 306 | } |
303 | 307 | ||
304 | LJLIB_PUSH("nil") | ||
305 | LJLIB_PUSH("false") | ||
306 | LJLIB_PUSH("true") | ||
307 | LJLIB_ASM(tostring) LJLIB_REC(.) | 308 | LJLIB_ASM(tostring) LJLIB_REC(.) |
308 | { | 309 | { |
309 | TValue *o = lj_lib_checkany(L, 1); | 310 | TValue *o = lj_lib_checkany(L, 1); |
310 | cTValue *mo; | 311 | cTValue *mo; |
311 | L->top = o+1; /* Only keep one argument. */ | 312 | L->top = o+1; /* Only keep one argument. */ |
312 | if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) { | 313 | if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) { |
313 | copyTV(L, L->base-1, mo); /* Replace callable. */ | 314 | copyTV(L, L->base-1-LJ_FR2, mo); /* Replace callable. */ |
314 | return FFH_TAILCALL; | 315 | return FFH_TAILCALL; |
315 | } else { | ||
316 | GCstr *s; | ||
317 | if (tvisnumber(o)) { | ||
318 | s = lj_str_fromnumber(L, o); | ||
319 | } else if (tvispri(o)) { | ||
320 | s = strV(lj_lib_upvalue(L, -(int32_t)itype(o))); | ||
321 | } else { | ||
322 | if (tvisfunc(o) && isffunc(funcV(o))) | ||
323 | lua_pushfstring(L, "function: builtin#%d", funcV(o)->c.ffid); | ||
324 | else | ||
325 | lua_pushfstring(L, "%s: %p", lj_typename(o), lua_topointer(L, 1)); | ||
326 | /* Note: lua_pushfstring calls the GC which may invalidate o. */ | ||
327 | s = strV(L->top-1); | ||
328 | } | ||
329 | setstrV(L, L->base-1, s); | ||
330 | return FFH_RES(1); | ||
331 | } | 316 | } |
317 | lj_gc_check(L); | ||
318 | setstrV(L, L->base-1-LJ_FR2, lj_strfmt_obj(L, L->base)); | ||
319 | return FFH_RES(1); | ||
332 | } | 320 | } |
333 | 321 | ||
334 | /* -- Base library: throw and catch errors -------------------------------- */ | 322 | /* -- Base library: throw and catch errors -------------------------------- */ |
@@ -440,20 +428,20 @@ LJLIB_CF(dofile) | |||
440 | 428 | ||
441 | LJLIB_CF(gcinfo) | 429 | LJLIB_CF(gcinfo) |
442 | { | 430 | { |
443 | setintV(L->top++, (G(L)->gc.total >> 10)); | 431 | setintV(L->top++, (int32_t)(G(L)->gc.total >> 10)); |
444 | return 1; | 432 | return 1; |
445 | } | 433 | } |
446 | 434 | ||
447 | LJLIB_CF(collectgarbage) | 435 | LJLIB_CF(collectgarbage) |
448 | { | 436 | { |
449 | int opt = lj_lib_checkopt(L, 1, LUA_GCCOLLECT, /* ORDER LUA_GC* */ | 437 | int opt = lj_lib_checkopt(L, 1, LUA_GCCOLLECT, /* ORDER LUA_GC* */ |
450 | "\4stop\7restart\7collect\5count\1\377\4step\10setpause\12setstepmul"); | 438 | "\4stop\7restart\7collect\5count\1\377\4step\10setpause\12setstepmul\1\377\11isrunning"); |
451 | int32_t data = lj_lib_optint(L, 2, 0); | 439 | int32_t data = lj_lib_optint(L, 2, 0); |
452 | if (opt == LUA_GCCOUNT) { | 440 | if (opt == LUA_GCCOUNT) { |
453 | setnumV(L->top, (lua_Number)G(L)->gc.total/1024.0); | 441 | setnumV(L->top, (lua_Number)G(L)->gc.total/1024.0); |
454 | } else { | 442 | } else { |
455 | int res = lua_gc(L, opt, data); | 443 | int res = lua_gc(L, opt, data); |
456 | if (opt == LUA_GCSTEP) | 444 | if (opt == LUA_GCSTEP || opt == LUA_GCISRUNNING) |
457 | setboolV(L->top, res); | 445 | setboolV(L->top, res); |
458 | else | 446 | else |
459 | setintV(L->top, res); | 447 | setintV(L->top, res); |
@@ -506,21 +494,12 @@ LJLIB_CF(print) | |||
506 | } | 494 | } |
507 | shortcut = (tvisfunc(tv) && funcV(tv)->c.ffid == FF_tostring); | 495 | shortcut = (tvisfunc(tv) && funcV(tv)->c.ffid == FF_tostring); |
508 | for (i = 0; i < nargs; i++) { | 496 | for (i = 0; i < nargs; i++) { |
497 | cTValue *o = &L->base[i]; | ||
509 | const char *str; | 498 | const char *str; |
510 | size_t size; | 499 | size_t size; |
511 | cTValue *o = &L->base[i]; | 500 | MSize len; |
512 | if (shortcut && tvisstr(o)) { | 501 | if (shortcut && (str = lj_strfmt_wstrnum(L, o, &len)) != NULL) { |
513 | str = strVdata(o); | 502 | size = len; |
514 | size = strV(o)->len; | ||
515 | } else if (shortcut && tvisint(o)) { | ||
516 | char buf[LJ_STR_INTBUF]; | ||
517 | char *p = lj_str_bufint(buf, intV(o)); | ||
518 | size = (size_t)(buf+LJ_STR_INTBUF-p); | ||
519 | str = p; | ||
520 | } else if (shortcut && tvisnum(o)) { | ||
521 | char buf[LJ_STR_NUMBUF]; | ||
522 | size = lj_str_bufnum(buf, o); | ||
523 | str = buf; | ||
524 | } else { | 503 | } else { |
525 | copyTV(L, L->top+1, o); | 504 | copyTV(L, L->top+1, o); |
526 | copyTV(L, L->top, L->top-1); | 505 | copyTV(L, L->top, L->top-1); |
@@ -558,7 +537,7 @@ LJLIB_CF(coroutine_status) | |||
558 | if (co == L) s = "running"; | 537 | if (co == L) s = "running"; |
559 | else if (co->status == LUA_YIELD) s = "suspended"; | 538 | else if (co->status == LUA_YIELD) s = "suspended"; |
560 | else if (co->status != 0) s = "dead"; | 539 | else if (co->status != 0) s = "dead"; |
561 | else if (co->base > tvref(co->stack)+1) s = "normal"; | 540 | else if (co->base > tvref(co->stack)+1+LJ_FR2) s = "normal"; |
562 | else if (co->top == co->base) s = "dead"; | 541 | else if (co->top == co->base) s = "dead"; |
563 | else s = "suspended"; | 542 | else s = "suspended"; |
564 | lua_pushstring(L, s); | 543 | lua_pushstring(L, s); |
@@ -600,8 +579,8 @@ static int ffh_resume(lua_State *L, lua_State *co, int wrap) | |||
600 | (co->status == 0 && co->top == co->base)) { | 579 | (co->status == 0 && co->top == co->base)) { |
601 | ErrMsg em = co->cframe ? LJ_ERR_CORUN : LJ_ERR_CODEAD; | 580 | ErrMsg em = co->cframe ? LJ_ERR_CORUN : LJ_ERR_CODEAD; |
602 | if (wrap) lj_err_caller(L, em); | 581 | if (wrap) lj_err_caller(L, em); |
603 | setboolV(L->base-1, 0); | 582 | setboolV(L->base-1-LJ_FR2, 0); |
604 | setstrV(L, L->base, lj_err_str(L, em)); | 583 | setstrV(L, L->base-LJ_FR2, lj_err_str(L, em)); |
605 | return FFH_RES(2); | 584 | return FFH_RES(2); |
606 | } | 585 | } |
607 | lj_state_growstack(co, (MSize)(L->top - L->base)); | 586 | lj_state_growstack(co, (MSize)(L->top - L->base)); |
@@ -642,9 +621,10 @@ static void setpc_wrap_aux(lua_State *L, GCfunc *fn); | |||
642 | 621 | ||
643 | LJLIB_CF(coroutine_wrap) | 622 | LJLIB_CF(coroutine_wrap) |
644 | { | 623 | { |
624 | GCfunc *fn; | ||
645 | lj_cf_coroutine_create(L); | 625 | lj_cf_coroutine_create(L); |
646 | lj_lib_pushcc(L, lj_ffh_coroutine_wrap_aux, FF_coroutine_wrap_aux, 1); | 626 | fn = lj_lib_pushcc(L, lj_ffh_coroutine_wrap_aux, FF_coroutine_wrap_aux, 1); |
647 | setpc_wrap_aux(L, funcV(L->top-1)); | 627 | setpc_wrap_aux(L, fn); |
648 | return 1; | 628 | return 1; |
649 | } | 629 | } |
650 | 630 | ||