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.c156
1 files changed, 83 insertions, 73 deletions
diff --git a/src/lib_base.c b/src/lib_base.c
index 6c96e8d5..98ec67c7 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;
@@ -144,6 +149,7 @@ LJLIB_CF(getfenv)
144 o = lj_debug_frame(L, level, &level); 149 o = lj_debug_frame(L, level, &level);
145 if (o == NULL) 150 if (o == NULL)
146 lj_err_arg(L, 1, LJ_ERR_INVLVL); 151 lj_err_arg(L, 1, LJ_ERR_INVLVL);
152 if (LJ_FR2) o--;
147 } 153 }
148 fn = &gcval(o)->fn; 154 fn = &gcval(o)->fn;
149 settabV(L, L->top++, isluafunc(fn) ? tabref(fn->l.env) : tabref(L->env)); 155 settabV(L, L->top++, isluafunc(fn) ? tabref(fn->l.env) : tabref(L->env));
@@ -165,6 +171,7 @@ LJLIB_CF(setfenv)
165 o = lj_debug_frame(L, level, &level); 171 o = lj_debug_frame(L, level, &level);
166 if (o == NULL) 172 if (o == NULL)
167 lj_err_arg(L, 1, LJ_ERR_INVLVL); 173 lj_err_arg(L, 1, LJ_ERR_INVLVL);
174 if (LJ_FR2) o--;
168 } 175 }
169 fn = &gcval(o)->fn; 176 fn = &gcval(o)->fn;
170 if (!isluafunc(fn)) 177 if (!isluafunc(fn))
@@ -259,7 +266,7 @@ LJLIB_ASM(tonumber) LJLIB_REC(.)
259 if (base == 10) { 266 if (base == 10) {
260 TValue *o = lj_lib_checkany(L, 1); 267 TValue *o = lj_lib_checkany(L, 1);
261 if (lj_strscan_numberobj(o)) { 268 if (lj_strscan_numberobj(o)) {
262 copyTV(L, L->base-1, o); 269 copyTV(L, L->base-1-LJ_FR2, o);
263 return FFH_RES(1); 270 return FFH_RES(1);
264 } 271 }
265#if LJ_HASFFI 272#if LJ_HASFFI
@@ -272,11 +279,11 @@ LJLIB_ASM(tonumber) LJLIB_REC(.)
272 ct->size <= 4 && !(ct->size == 4 && (ct->info & CTF_UNSIGNED))) { 279 ct->size <= 4 && !(ct->size == 4 && (ct->info & CTF_UNSIGNED))) {
273 int32_t i; 280 int32_t i;
274 lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, 0); 281 lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, 0);
275 setintV(L->base-1, i); 282 setintV(L->base-1-LJ_FR2, i);
276 return FFH_RES(1); 283 return FFH_RES(1);
277 } 284 }
278 lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE), 285 lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE),
279 (uint8_t *)&(L->base-1)->n, o, 0); 286 (uint8_t *)&(L->base-1-LJ_FR2)->n, o, 0);
280 return FFH_RES(1); 287 return FFH_RES(1);
281 } 288 }
282 } 289 }
@@ -284,53 +291,46 @@ LJLIB_ASM(tonumber) LJLIB_REC(.)
284 } else { 291 } else {
285 const char *p = strdata(lj_lib_checkstr(L, 1)); 292 const char *p = strdata(lj_lib_checkstr(L, 1));
286 char *ep; 293 char *ep;
294 unsigned int neg = 0;
287 unsigned long ul; 295 unsigned long ul;
288 if (base < 2 || base > 36) 296 if (base < 2 || base > 36)
289 lj_err_arg(L, 2, LJ_ERR_BASERNG); 297 lj_err_arg(L, 2, LJ_ERR_BASERNG);
290 ul = strtoul(p, &ep, base); 298 while (lj_char_isspace((unsigned char)(*p))) p++;
291 if (p != ep) { 299 if (*p == '-') { p++; neg = 1; } else if (*p == '+') { p++; }
292 while (lj_char_isspace((unsigned char)(*ep))) ep++; 300 if (lj_char_isalnum((unsigned char)(*p))) {
293 if (*ep == '\0') { 301 ul = strtoul(p, &ep, base);
294 if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u)) 302 if (p != ep) {
295 setintV(L->base-1, (int32_t)ul); 303 while (lj_char_isspace((unsigned char)(*ep))) ep++;
296 else 304 if (*ep == '\0') {
297 setnumV(L->base-1, (lua_Number)ul); 305 if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u+neg)) {
298 return FFH_RES(1); 306 if (neg) ul = (unsigned long)-(long)ul;
307 setintV(L->base-1-LJ_FR2, (int32_t)ul);
308 } else {
309 lua_Number n = (lua_Number)ul;
310 if (neg) n = -n;
311 setnumV(L->base-1-LJ_FR2, n);
312 }
313 return FFH_RES(1);
314 }
299 } 315 }
300 } 316 }
301 } 317 }
302 setnilV(L->base-1); 318 setnilV(L->base-1-LJ_FR2);
303 return FFH_RES(1); 319 return FFH_RES(1);
304} 320}
305 321
306LJLIB_PUSH("nil")
307LJLIB_PUSH("false")
308LJLIB_PUSH("true")
309LJLIB_ASM(tostring) LJLIB_REC(.) 322LJLIB_ASM(tostring) LJLIB_REC(.)
310{ 323{
311 TValue *o = lj_lib_checkany(L, 1); 324 TValue *o = lj_lib_checkany(L, 1);
312 cTValue *mo; 325 cTValue *mo;
313 L->top = o+1; /* Only keep one argument. */ 326 L->top = o+1; /* Only keep one argument. */
314 if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) { 327 if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
315 copyTV(L, L->base-1, mo); /* Replace callable. */ 328 copyTV(L, L->base-1-LJ_FR2, mo); /* Replace callable. */
316 return FFH_TAILCALL; 329 return FFH_TAILCALL;
317 } else {
318 GCstr *s;
319 if (tvisnumber(o)) {
320 s = lj_str_fromnumber(L, o);
321 } else if (tvispri(o)) {
322 s = strV(lj_lib_upvalue(L, -(int32_t)itype(o)));
323 } else {
324 if (tvisfunc(o) && isffunc(funcV(o)))
325 lua_pushfstring(L, "function: builtin#%d", funcV(o)->c.ffid);
326 else
327 lua_pushfstring(L, "%s: %p", lj_typename(o), lua_topointer(L, 1));
328 /* Note: lua_pushfstring calls the GC which may invalidate o. */
329 s = strV(L->top-1);
330 }
331 setstrV(L, L->base-1, s);
332 return FFH_RES(1);
333 } 330 }
331 lj_gc_check(L);
332 setstrV(L, L->base-1-LJ_FR2, lj_strfmt_obj(L, L->base));
333 return FFH_RES(1);
334} 334}
335 335
336/* -- Base library: throw and catch errors -------------------------------- */ 336/* -- Base library: throw and catch errors -------------------------------- */
@@ -359,7 +359,7 @@ LJLIB_ASM_(xpcall) LJLIB_REC(.)
359 359
360static int load_aux(lua_State *L, int status, int envarg) 360static int load_aux(lua_State *L, int status, int envarg)
361{ 361{
362 if (status == 0) { 362 if (status == LUA_OK) {
363 if (tvistab(L->base+envarg-1)) { 363 if (tvistab(L->base+envarg-1)) {
364 GCfunc *fn = funcV(L->top-1); 364 GCfunc *fn = funcV(L->top-1);
365 GCtab *t = tabV(L->base+envarg-1); 365 GCtab *t = tabV(L->base+envarg-1);
@@ -408,10 +408,22 @@ LJLIB_CF(load)
408 GCstr *name = lj_lib_optstr(L, 2); 408 GCstr *name = lj_lib_optstr(L, 2);
409 GCstr *mode = lj_lib_optstr(L, 3); 409 GCstr *mode = lj_lib_optstr(L, 3);
410 int status; 410 int status;
411 if (L->base < L->top && (tvisstr(L->base) || tvisnumber(L->base))) { 411 if (L->base < L->top &&
412 GCstr *s = lj_lib_checkstr(L, 1); 412 (tvisstr(L->base) || tvisnumber(L->base) || tvisbuf(L->base))) {
413 const char *s;
414 MSize len;
415 if (tvisbuf(L->base)) {
416 SBufExt *sbx = bufV(L->base);
417 s = sbx->r;
418 len = sbufxlen(sbx);
419 if (!name) name = &G(L)->strempty; /* Buffers are not NUL-terminated. */
420 } else {
421 GCstr *str = lj_lib_checkstr(L, 1);
422 s = strdata(str);
423 len = str->len;
424 }
413 lua_settop(L, 4); /* Ensure env arg exists. */ 425 lua_settop(L, 4); /* Ensure env arg exists. */
414 status = luaL_loadbufferx(L, strdata(s), s->len, strdata(name ? name : s), 426 status = luaL_loadbufferx(L, s, len, name ? strdata(name) : s,
415 mode ? strdata(mode) : NULL); 427 mode ? strdata(mode) : NULL);
416 } else { 428 } else {
417 lj_lib_checkfunc(L, 1); 429 lj_lib_checkfunc(L, 1);
@@ -432,7 +444,7 @@ LJLIB_CF(dofile)
432 GCstr *fname = lj_lib_optstr(L, 1); 444 GCstr *fname = lj_lib_optstr(L, 1);
433 setnilV(L->top); 445 setnilV(L->top);
434 L->top = L->base+1; 446 L->top = L->base+1;
435 if (luaL_loadfile(L, fname ? strdata(fname) : NULL) != 0) 447 if (luaL_loadfile(L, fname ? strdata(fname) : NULL) != LUA_OK)
436 lua_error(L); 448 lua_error(L);
437 lua_call(L, 0, LUA_MULTRET); 449 lua_call(L, 0, LUA_MULTRET);
438 return (int)(L->top - L->base) - 1; 450 return (int)(L->top - L->base) - 1;
@@ -442,20 +454,20 @@ LJLIB_CF(dofile)
442 454
443LJLIB_CF(gcinfo) 455LJLIB_CF(gcinfo)
444{ 456{
445 setintV(L->top++, (G(L)->gc.total >> 10)); 457 setintV(L->top++, (int32_t)(G(L)->gc.total >> 10));
446 return 1; 458 return 1;
447} 459}
448 460
449LJLIB_CF(collectgarbage) 461LJLIB_CF(collectgarbage)
450{ 462{
451 int opt = lj_lib_checkopt(L, 1, LUA_GCCOLLECT, /* ORDER LUA_GC* */ 463 int opt = lj_lib_checkopt(L, 1, LUA_GCCOLLECT, /* ORDER LUA_GC* */
452 "\4stop\7restart\7collect\5count\1\377\4step\10setpause\12setstepmul"); 464 "\4stop\7restart\7collect\5count\1\377\4step\10setpause\12setstepmul\1\377\11isrunning");
453 int32_t data = lj_lib_optint(L, 2, 0); 465 int32_t data = lj_lib_optint(L, 2, 0);
454 if (opt == LUA_GCCOUNT) { 466 if (opt == LUA_GCCOUNT) {
455 setnumV(L->top, (lua_Number)G(L)->gc.total/1024.0); 467 setnumV(L->top, (lua_Number)G(L)->gc.total/1024.0);
456 } else { 468 } else {
457 int res = lua_gc(L, opt, data); 469 int res = lua_gc(L, opt, data);
458 if (opt == LUA_GCSTEP) 470 if (opt == LUA_GCSTEP || opt == LUA_GCISRUNNING)
459 setboolV(L->top, res); 471 setboolV(L->top, res);
460 else 472 else
461 setintV(L->top, res); 473 setintV(L->top, res);
@@ -507,23 +519,14 @@ LJLIB_CF(print)
507 tv = L->top-1; 519 tv = L->top-1;
508 } 520 }
509 shortcut = (tvisfunc(tv) && funcV(tv)->c.ffid == FF_tostring) && 521 shortcut = (tvisfunc(tv) && funcV(tv)->c.ffid == FF_tostring) &&
510 !gcrefu(basemt_it(G(L), LJ_TNUMX)); 522 !gcrefu(basemt_it(G(L), LJ_TNUMX));
511 for (i = 0; i < nargs; i++) { 523 for (i = 0; i < nargs; i++) {
524 cTValue *o = &L->base[i];
512 const char *str; 525 const char *str;
513 size_t size; 526 size_t size;
514 cTValue *o = &L->base[i]; 527 MSize len;
515 if (shortcut && tvisstr(o)) { 528 if (shortcut && (str = lj_strfmt_wstrnum(L, o, &len)) != NULL) {
516 str = strVdata(o); 529 size = len;
517 size = strV(o)->len;
518 } else if (shortcut && tvisint(o)) {
519 char buf[LJ_STR_INTBUF];
520 char *p = lj_str_bufint(buf, intV(o));
521 size = (size_t)(buf+LJ_STR_INTBUF-p);
522 str = p;
523 } else if (shortcut && tvisnum(o)) {
524 char buf[LJ_STR_NUMBUF];
525 size = lj_str_bufnum(buf, o);
526 str = buf;
527 } else { 530 } else {
528 copyTV(L, L->top+1, o); 531 copyTV(L, L->top+1, o);
529 copyTV(L, L->top, L->top-1); 532 copyTV(L, L->top, L->top-1);
@@ -560,8 +563,8 @@ LJLIB_CF(coroutine_status)
560 co = threadV(L->base); 563 co = threadV(L->base);
561 if (co == L) s = "running"; 564 if (co == L) s = "running";
562 else if (co->status == LUA_YIELD) s = "suspended"; 565 else if (co->status == LUA_YIELD) s = "suspended";
563 else if (co->status != 0) s = "dead"; 566 else if (co->status != LUA_OK) s = "dead";
564 else if (co->base > tvref(co->stack)+1) s = "normal"; 567 else if (co->base > tvref(co->stack)+1+LJ_FR2) s = "normal";
565 else if (co->top == co->base) s = "dead"; 568 else if (co->top == co->base) s = "dead";
566 else s = "suspended"; 569 else s = "suspended";
567 lua_pushstring(L, s); 570 lua_pushstring(L, s);
@@ -581,6 +584,12 @@ LJLIB_CF(coroutine_running)
581#endif 584#endif
582} 585}
583 586
587LJLIB_CF(coroutine_isyieldable)
588{
589 setboolV(L->top++, cframe_canyield(L->cframe));
590 return 1;
591}
592
584LJLIB_CF(coroutine_create) 593LJLIB_CF(coroutine_create)
585{ 594{
586 lua_State *L1; 595 lua_State *L1;
@@ -600,11 +609,11 @@ LJLIB_ASM(coroutine_yield)
600static int ffh_resume(lua_State *L, lua_State *co, int wrap) 609static int ffh_resume(lua_State *L, lua_State *co, int wrap)
601{ 610{
602 if (co->cframe != NULL || co->status > LUA_YIELD || 611 if (co->cframe != NULL || co->status > LUA_YIELD ||
603 (co->status == 0 && co->top == co->base)) { 612 (co->status == LUA_OK && co->top == co->base)) {
604 ErrMsg em = co->cframe ? LJ_ERR_CORUN : LJ_ERR_CODEAD; 613 ErrMsg em = co->cframe ? LJ_ERR_CORUN : LJ_ERR_CODEAD;
605 if (wrap) lj_err_caller(L, em); 614 if (wrap) lj_err_caller(L, em);
606 setboolV(L->base-1, 0); 615 setboolV(L->base-1-LJ_FR2, 0);
607 setstrV(L, L->base, lj_err_str(L, em)); 616 setstrV(L, L->base-LJ_FR2, lj_err_str(L, em));
608 return FFH_RES(2); 617 return FFH_RES(2);
609 } 618 }
610 lj_state_growstack(co, (MSize)(L->top - L->base)); 619 lj_state_growstack(co, (MSize)(L->top - L->base));
@@ -645,9 +654,10 @@ static void setpc_wrap_aux(lua_State *L, GCfunc *fn);
645 654
646LJLIB_CF(coroutine_wrap) 655LJLIB_CF(coroutine_wrap)
647{ 656{
657 GCfunc *fn;
648 lj_cf_coroutine_create(L); 658 lj_cf_coroutine_create(L);
649 lj_lib_pushcc(L, lj_ffh_coroutine_wrap_aux, FF_coroutine_wrap_aux, 1); 659 fn = lj_lib_pushcc(L, lj_ffh_coroutine_wrap_aux, FF_coroutine_wrap_aux, 1);
650 setpc_wrap_aux(L, funcV(L->top-1)); 660 setpc_wrap_aux(L, fn);
651 return 1; 661 return 1;
652} 662}
653 663