aboutsummaryrefslogtreecommitdiff
path: root/src/lib_base.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib_base.c')
-rw-r--r--src/lib_base.c167
1 files changed, 92 insertions, 75 deletions
diff --git a/src/lib_base.c b/src/lib_base.c
index 046518c7..bf98f284 100644
--- a/src/lib_base.c
+++ b/src/lib_base.c
@@ -19,10 +19,12 @@
19#include "lj_gc.h" 19#include "lj_gc.h"
20#include "lj_err.h" 20#include "lj_err.h"
21#include "lj_debug.h" 21#include "lj_debug.h"
22#include "lj_buf.h"
22#include "lj_str.h" 23#include "lj_str.h"
23#include "lj_tab.h" 24#include "lj_tab.h"
24#include "lj_meta.h" 25#include "lj_meta.h"
25#include "lj_state.h" 26#include "lj_state.h"
27#include "lj_frame.h"
26#if LJ_HASFFI 28#if LJ_HASFFI
27#include "lj_ctype.h" 29#include "lj_ctype.h"
28#include "lj_cconv.h" 30#include "lj_cconv.h"
@@ -32,6 +34,7 @@
32#include "lj_dispatch.h" 34#include "lj_dispatch.h"
33#include "lj_char.h" 35#include "lj_char.h"
34#include "lj_strscan.h" 36#include "lj_strscan.h"
37#include "lj_strfmt.h"
35#include "lj_lib.h" 38#include "lj_lib.h"
36 39
37/* -- Base library: checks ------------------------------------------------ */ 40/* -- Base library: checks ------------------------------------------------ */
@@ -40,13 +43,13 @@
40 43
41LJLIB_ASM(assert) LJLIB_REC(.) 44LJLIB_ASM(assert) LJLIB_REC(.)
42{ 45{
43 GCstr *s;
44 lj_lib_checkany(L, 1); 46 lj_lib_checkany(L, 1);
45 s = lj_lib_optstr(L, 2); 47 if (L->top == L->base+1)
46 if (s)
47 lj_err_callermsg(L, strdata(s));
48 else
49 lj_err_caller(L, LJ_ERR_ASSERT); 48 lj_err_caller(L, LJ_ERR_ASSERT);
49 else if (tvisstr(L->base+1) || tvisnumber(L->base+1))
50 lj_err_callermsg(L, strdata(lj_lib_checkstr(L, 2)));
51 else
52 lj_err_run(L);
50 return FFH_UNREACHABLE; 53 return FFH_UNREACHABLE;
51} 54}
52 55
@@ -73,9 +76,10 @@ LJLIB_ASM_(type) LJLIB_REC(.)
73/* This solves a circular dependency problem -- change FF_next_N as needed. */ 76/* This solves a circular dependency problem -- change FF_next_N as needed. */
74LJ_STATIC_ASSERT((int)FF_next == FF_next_N); 77LJ_STATIC_ASSERT((int)FF_next == FF_next_N);
75 78
76LJLIB_ASM(next) 79LJLIB_ASM(next) LJLIB_REC(.)
77{ 80{
78 lj_lib_checktab(L, 1); 81 lj_lib_checktab(L, 1);
82 lj_err_msg(L, LJ_ERR_NEXTIDX);
79 return FFH_UNREACHABLE; 83 return FFH_UNREACHABLE;
80} 84}
81 85
@@ -86,10 +90,11 @@ static int ffh_pairs(lua_State *L, MMS mm)
86 cTValue *mo = lj_meta_lookup(L, o, mm); 90 cTValue *mo = lj_meta_lookup(L, o, mm);
87 if ((LJ_52 || tviscdata(o)) && !tvisnil(mo)) { 91 if ((LJ_52 || tviscdata(o)) && !tvisnil(mo)) {
88 L->top = o+1; /* Only keep one argument. */ 92 L->top = o+1; /* Only keep one argument. */
89 copyTV(L, L->base-1, mo); /* Replace callable. */ 93 copyTV(L, L->base-1-LJ_FR2, mo); /* Replace callable. */
90 return FFH_TAILCALL; 94 return FFH_TAILCALL;
91 } else { 95 } else {
92 if (!tvistab(o)) lj_err_argt(L, 1, LUA_TTABLE); 96 if (!tvistab(o)) lj_err_argt(L, 1, LUA_TTABLE);
97 if (LJ_FR2) { copyTV(L, o-1, o); o--; }
93 setfuncV(L, o-1, funcV(lj_lib_upvalue(L, 1))); 98 setfuncV(L, o-1, funcV(lj_lib_upvalue(L, 1)));
94 if (mm == MM_pairs) setnilV(o+1); else setintV(o+1, 0); 99 if (mm == MM_pairs) setnilV(o+1); else setintV(o+1, 0);
95 return FFH_RES(3); 100 return FFH_RES(3);
@@ -100,7 +105,7 @@ static int ffh_pairs(lua_State *L, MMS mm)
100#endif 105#endif
101 106
102LJLIB_PUSH(lastcl) 107LJLIB_PUSH(lastcl)
103LJLIB_ASM(pairs) 108LJLIB_ASM(pairs) LJLIB_REC(xpairs 0)
104{ 109{
105 return ffh_pairs(L, MM_pairs); 110 return ffh_pairs(L, MM_pairs);
106} 111}
@@ -113,7 +118,7 @@ LJLIB_NOREGUV LJLIB_ASM(ipairs_aux) LJLIB_REC(.)
113} 118}
114 119
115LJLIB_PUSH(lastcl) 120LJLIB_PUSH(lastcl)
116LJLIB_ASM(ipairs) LJLIB_REC(.) 121LJLIB_ASM(ipairs) LJLIB_REC(xpairs 1)
117{ 122{
118 return ffh_pairs(L, MM_ipairs); 123 return ffh_pairs(L, MM_ipairs);
119} 124}
@@ -131,11 +136,11 @@ LJLIB_ASM(setmetatable) LJLIB_REC(.)
131 lj_err_caller(L, LJ_ERR_PROTMT); 136 lj_err_caller(L, LJ_ERR_PROTMT);
132 setgcref(t->metatable, obj2gco(mt)); 137 setgcref(t->metatable, obj2gco(mt));
133 if (mt) { lj_gc_objbarriert(L, t, mt); } 138 if (mt) { lj_gc_objbarriert(L, t, mt); }
134 settabV(L, L->base-1, t); 139 settabV(L, L->base-1-LJ_FR2, t);
135 return FFH_RES(1); 140 return FFH_RES(1);
136} 141}
137 142
138LJLIB_CF(getfenv) 143LJLIB_CF(getfenv) LJLIB_REC(.)
139{ 144{
140 GCfunc *fn; 145 GCfunc *fn;
141 cTValue *o = L->base; 146 cTValue *o = L->base;
@@ -146,6 +151,7 @@ LJLIB_CF(getfenv)
146 o = lj_debug_frame(L, level, &level); 151 o = lj_debug_frame(L, level, &level);
147 if (o == NULL) 152 if (o == NULL)
148 lj_err_arg(L, 1, LJ_ERR_INVLVL); 153 lj_err_arg(L, 1, LJ_ERR_INVLVL);
154 if (LJ_FR2) o--;
149 } 155 }
150 fn = &gcval(o)->fn; 156 fn = &gcval(o)->fn;
151 settabV(L, L->top++, isluafunc(fn) ? tabref(fn->l.env) : tabref(L->env)); 157 settabV(L, L->top++, isluafunc(fn) ? tabref(fn->l.env) : tabref(L->env));
@@ -169,6 +175,7 @@ LJLIB_CF(setfenv)
169 o = lj_debug_frame(L, level, &level); 175 o = lj_debug_frame(L, level, &level);
170 if (o == NULL) 176 if (o == NULL)
171 lj_err_arg(L, 1, LJ_ERR_INVLVL); 177 lj_err_arg(L, 1, LJ_ERR_INVLVL);
178 if (LJ_FR2) o--;
172 } 179 }
173 fn = &gcval(o)->fn; 180 fn = &gcval(o)->fn;
174 if (!isluafunc(fn)) 181 if (!isluafunc(fn))
@@ -265,7 +272,7 @@ LJLIB_ASM(tonumber) LJLIB_REC(.)
265 if (base == 10) { 272 if (base == 10) {
266 TValue *o = lj_lib_checkany(L, 1); 273 TValue *o = lj_lib_checkany(L, 1);
267 if (lj_strscan_numberobj(o)) { 274 if (lj_strscan_numberobj(o)) {
268 copyTV(L, L->base-1, o); 275 copyTV(L, L->base-1-LJ_FR2, o);
269 return FFH_RES(1); 276 return FFH_RES(1);
270 } 277 }
271#if LJ_HASFFI 278#if LJ_HASFFI
@@ -278,11 +285,11 @@ LJLIB_ASM(tonumber) LJLIB_REC(.)
278 ct->size <= 4 && !(ct->size == 4 && (ct->info & CTF_UNSIGNED))) { 285 ct->size <= 4 && !(ct->size == 4 && (ct->info & CTF_UNSIGNED))) {
279 int32_t i; 286 int32_t i;
280 lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, 0); 287 lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, 0);
281 setintV(L->base-1, i); 288 setintV(L->base-1-LJ_FR2, i);
282 return FFH_RES(1); 289 return FFH_RES(1);
283 } 290 }
284 lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE), 291 lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE),
285 (uint8_t *)&(L->base-1)->n, o, 0); 292 (uint8_t *)&(L->base-1-LJ_FR2)->n, o, 0);
286 return FFH_RES(1); 293 return FFH_RES(1);
287 } 294 }
288 } 295 }
@@ -290,53 +297,46 @@ LJLIB_ASM(tonumber) LJLIB_REC(.)
290 } else { 297 } else {
291 const char *p = strdata(lj_lib_checkstr(L, 1)); 298 const char *p = strdata(lj_lib_checkstr(L, 1));
292 char *ep; 299 char *ep;
300 unsigned int neg = 0;
293 unsigned long ul; 301 unsigned long ul;
294 if (base < 2 || base > 36) 302 if (base < 2 || base > 36)
295 lj_err_arg(L, 2, LJ_ERR_BASERNG); 303 lj_err_arg(L, 2, LJ_ERR_BASERNG);
296 ul = strtoul(p, &ep, base); 304 while (lj_char_isspace((unsigned char)(*p))) p++;
297 if (p != ep) { 305 if (*p == '-') { p++; neg = 1; } else if (*p == '+') { p++; }
298 while (lj_char_isspace((unsigned char)(*ep))) ep++; 306 if (lj_char_isalnum((unsigned char)(*p))) {
299 if (*ep == '\0') { 307 ul = strtoul(p, &ep, base);
300 if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u)) 308 if (p != ep) {
301 setintV(L->base-1, (int32_t)ul); 309 while (lj_char_isspace((unsigned char)(*ep))) ep++;
302 else 310 if (*ep == '\0') {
303 setnumV(L->base-1, (lua_Number)ul); 311 if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u+neg)) {
304 return FFH_RES(1); 312 if (neg) ul = ~ul+1u;
313 setintV(L->base-1-LJ_FR2, (int32_t)ul);
314 } else {
315 lua_Number n = (lua_Number)ul;
316 if (neg) n = -n;
317 setnumV(L->base-1-LJ_FR2, n);
318 }
319 return FFH_RES(1);
320 }
305 } 321 }
306 } 322 }
307 } 323 }
308 setnilV(L->base-1); 324 setnilV(L->base-1-LJ_FR2);
309 return FFH_RES(1); 325 return FFH_RES(1);
310} 326}
311 327
312LJLIB_PUSH("nil")
313LJLIB_PUSH("false")
314LJLIB_PUSH("true")
315LJLIB_ASM(tostring) LJLIB_REC(.) 328LJLIB_ASM(tostring) LJLIB_REC(.)
316{ 329{
317 TValue *o = lj_lib_checkany(L, 1); 330 TValue *o = lj_lib_checkany(L, 1);
318 cTValue *mo; 331 cTValue *mo;
319 L->top = o+1; /* Only keep one argument. */ 332 L->top = o+1; /* Only keep one argument. */
320 if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) { 333 if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
321 copyTV(L, L->base-1, mo); /* Replace callable. */ 334 copyTV(L, L->base-1-LJ_FR2, mo); /* Replace callable. */
322 return FFH_TAILCALL; 335 return FFH_TAILCALL;
323 } else {
324 GCstr *s;
325 if (tvisnumber(o)) {
326 s = lj_str_fromnumber(L, o);
327 } else if (tvispri(o)) {
328 s = strV(lj_lib_upvalue(L, -(int32_t)itype(o)));
329 } else {
330 if (tvisfunc(o) && isffunc(funcV(o)))
331 lua_pushfstring(L, "function: builtin#%d", funcV(o)->c.ffid);
332 else
333 lua_pushfstring(L, "%s: %p", lj_typename(o), lua_topointer(L, 1));
334 /* Note: lua_pushfstring calls the GC which may invalidate o. */
335 s = strV(L->top-1);
336 }
337 setstrV(L, L->base-1, s);
338 return FFH_RES(1);
339 } 336 }
337 lj_gc_check(L);
338 setstrV(L, L->base-1-LJ_FR2, lj_strfmt_obj(L, L->base));
339 return FFH_RES(1);
340} 340}
341 341
342/* -- Base library: throw and catch errors -------------------------------- */ 342/* -- Base library: throw and catch errors -------------------------------- */
@@ -365,8 +365,12 @@ LJLIB_ASM_(xpcall) LJLIB_REC(.)
365 365
366static int load_aux(lua_State *L, int status, int envarg) 366static int load_aux(lua_State *L, int status, int envarg)
367{ 367{
368 if (status == 0) { 368 if (status == LUA_OK) {
369 if (tvistab(L->base+envarg-1)) { 369 /*
370 ** Set environment table for top-level function.
371 ** Don't do this for non-native bytecode, which returns a prototype.
372 */
373 if (tvistab(L->base+envarg-1) && tvisfunc(L->top-1)) {
370 GCfunc *fn = funcV(L->top-1); 374 GCfunc *fn = funcV(L->top-1);
371 GCtab *t = tabV(L->base+envarg-1); 375 GCtab *t = tabV(L->base+envarg-1);
372 setgcref(fn->c.env, obj2gco(t)); 376 setgcref(fn->c.env, obj2gco(t));
@@ -414,10 +418,22 @@ LJLIB_CF(load)
414 GCstr *name = lj_lib_optstr(L, 2); 418 GCstr *name = lj_lib_optstr(L, 2);
415 GCstr *mode = lj_lib_optstr(L, 3); 419 GCstr *mode = lj_lib_optstr(L, 3);
416 int status; 420 int status;
417 if (L->base < L->top && (tvisstr(L->base) || tvisnumber(L->base))) { 421 if (L->base < L->top &&
418 GCstr *s = lj_lib_checkstr(L, 1); 422 (tvisstr(L->base) || tvisnumber(L->base) || tvisbuf(L->base))) {
423 const char *s;
424 MSize len;
425 if (tvisbuf(L->base)) {
426 SBufExt *sbx = bufV(L->base);
427 s = sbx->r;
428 len = sbufxlen(sbx);
429 if (!name) name = &G(L)->strempty; /* Buffers are not NUL-terminated. */
430 } else {
431 GCstr *str = lj_lib_checkstr(L, 1);
432 s = strdata(str);
433 len = str->len;
434 }
419 lua_settop(L, 4); /* Ensure env arg exists. */ 435 lua_settop(L, 4); /* Ensure env arg exists. */
420 status = luaL_loadbufferx(L, strdata(s), s->len, strdata(name ? name : s), 436 status = luaL_loadbufferx(L, s, len, name ? strdata(name) : s,
421 mode ? strdata(mode) : NULL); 437 mode ? strdata(mode) : NULL);
422 } else { 438 } else {
423 lj_lib_checkfunc(L, 1); 439 lj_lib_checkfunc(L, 1);
@@ -438,7 +454,7 @@ LJLIB_CF(dofile)
438 GCstr *fname = lj_lib_optstr(L, 1); 454 GCstr *fname = lj_lib_optstr(L, 1);
439 setnilV(L->top); 455 setnilV(L->top);
440 L->top = L->base+1; 456 L->top = L->base+1;
441 if (luaL_loadfile(L, fname ? strdata(fname) : NULL) != 0) 457 if (luaL_loadfile(L, fname ? strdata(fname) : NULL) != LUA_OK)
442 lua_error(L); 458 lua_error(L);
443 lua_call(L, 0, LUA_MULTRET); 459 lua_call(L, 0, LUA_MULTRET);
444 return (int)(L->top - L->base) - 1; 460 return (int)(L->top - L->base) - 1;
@@ -448,20 +464,20 @@ LJLIB_CF(dofile)
448 464
449LJLIB_CF(gcinfo) 465LJLIB_CF(gcinfo)
450{ 466{
451 setintV(L->top++, (G(L)->gc.total >> 10)); 467 setintV(L->top++, (int32_t)(G(L)->gc.total >> 10));
452 return 1; 468 return 1;
453} 469}
454 470
455LJLIB_CF(collectgarbage) 471LJLIB_CF(collectgarbage)
456{ 472{
457 int opt = lj_lib_checkopt(L, 1, LUA_GCCOLLECT, /* ORDER LUA_GC* */ 473 int opt = lj_lib_checkopt(L, 1, LUA_GCCOLLECT, /* ORDER LUA_GC* */
458 "\4stop\7restart\7collect\5count\1\377\4step\10setpause\12setstepmul"); 474 "\4stop\7restart\7collect\5count\1\377\4step\10setpause\12setstepmul\1\377\11isrunning");
459 int32_t data = lj_lib_optint(L, 2, 0); 475 int32_t data = lj_lib_optint(L, 2, 0);
460 if (opt == LUA_GCCOUNT) { 476 if (opt == LUA_GCCOUNT) {
461 setnumV(L->top, (lua_Number)G(L)->gc.total/1024.0); 477 setnumV(L->top, (lua_Number)G(L)->gc.total/1024.0);
462 } else { 478 } else {
463 int res = lua_gc(L, opt, data); 479 int res = lua_gc(L, opt, data);
464 if (opt == LUA_GCSTEP) 480 if (opt == LUA_GCSTEP || opt == LUA_GCISRUNNING)
465 setboolV(L->top, res); 481 setboolV(L->top, res);
466 else 482 else
467 setintV(L->top, res); 483 setintV(L->top, res);
@@ -513,23 +529,14 @@ LJLIB_CF(print)
513 tv = L->top-1; 529 tv = L->top-1;
514 } 530 }
515 shortcut = (tvisfunc(tv) && funcV(tv)->c.ffid == FF_tostring) && 531 shortcut = (tvisfunc(tv) && funcV(tv)->c.ffid == FF_tostring) &&
516 !gcrefu(basemt_it(G(L), LJ_TNUMX)); 532 !gcrefu(basemt_it(G(L), LJ_TNUMX));
517 for (i = 0; i < nargs; i++) { 533 for (i = 0; i < nargs; i++) {
534 cTValue *o = &L->base[i];
518 const char *str; 535 const char *str;
519 size_t size; 536 size_t size;
520 cTValue *o = &L->base[i]; 537 MSize len;
521 if (shortcut && tvisstr(o)) { 538 if (shortcut && (str = lj_strfmt_wstrnum(L, o, &len)) != NULL) {
522 str = strVdata(o); 539 size = len;
523 size = strV(o)->len;
524 } else if (shortcut && tvisint(o)) {
525 char buf[LJ_STR_INTBUF];
526 char *p = lj_str_bufint(buf, intV(o));
527 size = (size_t)(buf+LJ_STR_INTBUF-p);
528 str = p;
529 } else if (shortcut && tvisnum(o)) {
530 char buf[LJ_STR_NUMBUF];
531 size = lj_str_bufnum(buf, o);
532 str = buf;
533 } else { 540 } else {
534 copyTV(L, L->top+1, o); 541 copyTV(L, L->top+1, o);
535 copyTV(L, L->top, L->top-1); 542 copyTV(L, L->top, L->top-1);
@@ -566,8 +573,8 @@ LJLIB_CF(coroutine_status)
566 co = threadV(L->base); 573 co = threadV(L->base);
567 if (co == L) s = "running"; 574 if (co == L) s = "running";
568 else if (co->status == LUA_YIELD) s = "suspended"; 575 else if (co->status == LUA_YIELD) s = "suspended";
569 else if (co->status != 0) s = "dead"; 576 else if (co->status != LUA_OK) s = "dead";
570 else if (co->base > tvref(co->stack)+1) s = "normal"; 577 else if (co->base > tvref(co->stack)+1+LJ_FR2) s = "normal";
571 else if (co->top == co->base) s = "dead"; 578 else if (co->top == co->base) s = "dead";
572 else s = "suspended"; 579 else s = "suspended";
573 lua_pushstring(L, s); 580 lua_pushstring(L, s);
@@ -587,6 +594,12 @@ LJLIB_CF(coroutine_running)
587#endif 594#endif
588} 595}
589 596
597LJLIB_CF(coroutine_isyieldable)
598{
599 setboolV(L->top++, cframe_canyield(L->cframe));
600 return 1;
601}
602
590LJLIB_CF(coroutine_create) 603LJLIB_CF(coroutine_create)
591{ 604{
592 lua_State *L1; 605 lua_State *L1;
@@ -606,14 +619,17 @@ LJLIB_ASM(coroutine_yield)
606static int ffh_resume(lua_State *L, lua_State *co, int wrap) 619static int ffh_resume(lua_State *L, lua_State *co, int wrap)
607{ 620{
608 if (co->cframe != NULL || co->status > LUA_YIELD || 621 if (co->cframe != NULL || co->status > LUA_YIELD ||
609 (co->status == 0 && co->top == co->base)) { 622 (co->status == LUA_OK && co->top == co->base)) {
610 ErrMsg em = co->cframe ? LJ_ERR_CORUN : LJ_ERR_CODEAD; 623 ErrMsg em = co->cframe ? LJ_ERR_CORUN : LJ_ERR_CODEAD;
611 if (wrap) lj_err_caller(L, em); 624 if (wrap) lj_err_caller(L, em);
612 setboolV(L->base-1, 0); 625 setboolV(L->base-1-LJ_FR2, 0);
613 setstrV(L, L->base, lj_err_str(L, em)); 626 setstrV(L, L->base-LJ_FR2, lj_err_str(L, em));
614 return FFH_RES(2); 627 return FFH_RES(2);
615 } 628 }
616 lj_state_growstack(co, (MSize)(L->top - L->base)); 629 if (lj_state_cpgrowstack(co, (MSize)(L->top - L->base)) != LUA_OK) {
630 cTValue *msg = --co->top;
631 lj_err_callermsg(L, strVdata(msg));
632 }
617 return FFH_RETRY; 633 return FFH_RETRY;
618} 634}
619 635
@@ -651,9 +667,10 @@ static void setpc_wrap_aux(lua_State *L, GCfunc *fn);
651 667
652LJLIB_CF(coroutine_wrap) 668LJLIB_CF(coroutine_wrap)
653{ 669{
670 GCfunc *fn;
654 lj_cf_coroutine_create(L); 671 lj_cf_coroutine_create(L);
655 lj_lib_pushcc(L, lj_ffh_coroutine_wrap_aux, FF_coroutine_wrap_aux, 1); 672 fn = lj_lib_pushcc(L, lj_ffh_coroutine_wrap_aux, FF_coroutine_wrap_aux, 1);
656 setpc_wrap_aux(L, funcV(L->top-1)); 673 setpc_wrap_aux(L, fn);
657 return 1; 674 return 1;
658} 675}
659 676