diff options
Diffstat (limited to 'src/lib_base.c')
-rw-r--r-- | src/lib_base.c | 134 |
1 files changed, 65 insertions, 69 deletions
diff --git a/src/lib_base.c b/src/lib_base.c index dae61fe1..54e9e2b0 100644 --- a/src/lib_base.c +++ b/src/lib_base.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include "lj_tab.h" | 23 | #include "lj_tab.h" |
24 | #include "lj_meta.h" | 24 | #include "lj_meta.h" |
25 | #include "lj_state.h" | 25 | #include "lj_state.h" |
26 | #include "lj_frame.h" | ||
26 | #if LJ_HASFFI | 27 | #if LJ_HASFFI |
27 | #include "lj_ctype.h" | 28 | #include "lj_ctype.h" |
28 | #include "lj_cconv.h" | 29 | #include "lj_cconv.h" |
@@ -32,6 +33,7 @@ | |||
32 | #include "lj_dispatch.h" | 33 | #include "lj_dispatch.h" |
33 | #include "lj_char.h" | 34 | #include "lj_char.h" |
34 | #include "lj_strscan.h" | 35 | #include "lj_strscan.h" |
36 | #include "lj_strfmt.h" | ||
35 | #include "lj_lib.h" | 37 | #include "lj_lib.h" |
36 | 38 | ||
37 | /* -- Base library: checks ------------------------------------------------ */ | 39 | /* -- Base library: checks ------------------------------------------------ */ |
@@ -40,13 +42,13 @@ | |||
40 | 42 | ||
41 | LJLIB_ASM(assert) LJLIB_REC(.) | 43 | LJLIB_ASM(assert) LJLIB_REC(.) |
42 | { | 44 | { |
43 | GCstr *s; | ||
44 | lj_lib_checkany(L, 1); | 45 | lj_lib_checkany(L, 1); |
45 | s = lj_lib_optstr(L, 2); | 46 | 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); | 47 | lj_err_caller(L, LJ_ERR_ASSERT); |
48 | else if (tvisstr(L->base+1) || tvisnumber(L->base+1)) | ||
49 | lj_err_callermsg(L, strdata(lj_lib_checkstr(L, 2))); | ||
50 | else | ||
51 | lj_err_run(L); | ||
50 | return FFH_UNREACHABLE; | 52 | return FFH_UNREACHABLE; |
51 | } | 53 | } |
52 | 54 | ||
@@ -86,10 +88,11 @@ static int ffh_pairs(lua_State *L, MMS mm) | |||
86 | cTValue *mo = lj_meta_lookup(L, o, mm); | 88 | cTValue *mo = lj_meta_lookup(L, o, mm); |
87 | if ((LJ_52 || tviscdata(o)) && !tvisnil(mo)) { | 89 | if ((LJ_52 || tviscdata(o)) && !tvisnil(mo)) { |
88 | L->top = o+1; /* Only keep one argument. */ | 90 | L->top = o+1; /* Only keep one argument. */ |
89 | copyTV(L, L->base-1, mo); /* Replace callable. */ | 91 | copyTV(L, L->base-1-LJ_FR2, mo); /* Replace callable. */ |
90 | return FFH_TAILCALL; | 92 | return FFH_TAILCALL; |
91 | } else { | 93 | } else { |
92 | if (!tvistab(o)) lj_err_argt(L, 1, LUA_TTABLE); | 94 | if (!tvistab(o)) lj_err_argt(L, 1, LUA_TTABLE); |
95 | if (LJ_FR2) { copyTV(L, o-1, o); o--; } | ||
93 | setfuncV(L, o-1, funcV(lj_lib_upvalue(L, 1))); | 96 | setfuncV(L, o-1, funcV(lj_lib_upvalue(L, 1))); |
94 | if (mm == MM_pairs) setnilV(o+1); else setintV(o+1, 0); | 97 | if (mm == MM_pairs) setnilV(o+1); else setintV(o+1, 0); |
95 | return FFH_RES(3); | 98 | return FFH_RES(3); |
@@ -100,7 +103,7 @@ static int ffh_pairs(lua_State *L, MMS mm) | |||
100 | #endif | 103 | #endif |
101 | 104 | ||
102 | LJLIB_PUSH(lastcl) | 105 | LJLIB_PUSH(lastcl) |
103 | LJLIB_ASM(pairs) | 106 | LJLIB_ASM(pairs) LJLIB_REC(xpairs 0) |
104 | { | 107 | { |
105 | return ffh_pairs(L, MM_pairs); | 108 | return ffh_pairs(L, MM_pairs); |
106 | } | 109 | } |
@@ -113,7 +116,7 @@ LJLIB_NOREGUV LJLIB_ASM(ipairs_aux) LJLIB_REC(.) | |||
113 | } | 116 | } |
114 | 117 | ||
115 | LJLIB_PUSH(lastcl) | 118 | LJLIB_PUSH(lastcl) |
116 | LJLIB_ASM(ipairs) LJLIB_REC(.) | 119 | LJLIB_ASM(ipairs) LJLIB_REC(xpairs 1) |
117 | { | 120 | { |
118 | return ffh_pairs(L, MM_ipairs); | 121 | return ffh_pairs(L, MM_ipairs); |
119 | } | 122 | } |
@@ -131,11 +134,11 @@ LJLIB_ASM(setmetatable) LJLIB_REC(.) | |||
131 | lj_err_caller(L, LJ_ERR_PROTMT); | 134 | lj_err_caller(L, LJ_ERR_PROTMT); |
132 | setgcref(t->metatable, obj2gco(mt)); | 135 | setgcref(t->metatable, obj2gco(mt)); |
133 | if (mt) { lj_gc_objbarriert(L, t, mt); } | 136 | if (mt) { lj_gc_objbarriert(L, t, mt); } |
134 | settabV(L, L->base-1, t); | 137 | settabV(L, L->base-1-LJ_FR2, t); |
135 | return FFH_RES(1); | 138 | return FFH_RES(1); |
136 | } | 139 | } |
137 | 140 | ||
138 | LJLIB_CF(getfenv) | 141 | LJLIB_CF(getfenv) LJLIB_REC(.) |
139 | { | 142 | { |
140 | GCfunc *fn; | 143 | GCfunc *fn; |
141 | cTValue *o = L->base; | 144 | cTValue *o = L->base; |
@@ -144,6 +147,7 @@ LJLIB_CF(getfenv) | |||
144 | o = lj_debug_frame(L, level, &level); | 147 | o = lj_debug_frame(L, level, &level); |
145 | if (o == NULL) | 148 | if (o == NULL) |
146 | lj_err_arg(L, 1, LJ_ERR_INVLVL); | 149 | lj_err_arg(L, 1, LJ_ERR_INVLVL); |
150 | if (LJ_FR2) o--; | ||
147 | } | 151 | } |
148 | fn = &gcval(o)->fn; | 152 | fn = &gcval(o)->fn; |
149 | settabV(L, L->top++, isluafunc(fn) ? tabref(fn->l.env) : tabref(L->env)); | 153 | settabV(L, L->top++, isluafunc(fn) ? tabref(fn->l.env) : tabref(L->env)); |
@@ -165,6 +169,7 @@ LJLIB_CF(setfenv) | |||
165 | o = lj_debug_frame(L, level, &level); | 169 | o = lj_debug_frame(L, level, &level); |
166 | if (o == NULL) | 170 | if (o == NULL) |
167 | lj_err_arg(L, 1, LJ_ERR_INVLVL); | 171 | lj_err_arg(L, 1, LJ_ERR_INVLVL); |
172 | if (LJ_FR2) o--; | ||
168 | } | 173 | } |
169 | fn = &gcval(o)->fn; | 174 | fn = &gcval(o)->fn; |
170 | if (!isluafunc(fn)) | 175 | if (!isluafunc(fn)) |
@@ -257,7 +262,7 @@ LJLIB_ASM(tonumber) LJLIB_REC(.) | |||
257 | if (base == 10) { | 262 | if (base == 10) { |
258 | TValue *o = lj_lib_checkany(L, 1); | 263 | TValue *o = lj_lib_checkany(L, 1); |
259 | if (lj_strscan_numberobj(o)) { | 264 | if (lj_strscan_numberobj(o)) { |
260 | copyTV(L, L->base-1, o); | 265 | copyTV(L, L->base-1-LJ_FR2, o); |
261 | return FFH_RES(1); | 266 | return FFH_RES(1); |
262 | } | 267 | } |
263 | #if LJ_HASFFI | 268 | #if LJ_HASFFI |
@@ -270,11 +275,11 @@ LJLIB_ASM(tonumber) LJLIB_REC(.) | |||
270 | ct->size <= 4 && !(ct->size == 4 && (ct->info & CTF_UNSIGNED))) { | 275 | ct->size <= 4 && !(ct->size == 4 && (ct->info & CTF_UNSIGNED))) { |
271 | int32_t i; | 276 | int32_t i; |
272 | lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, 0); | 277 | lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, 0); |
273 | setintV(L->base-1, i); | 278 | setintV(L->base-1-LJ_FR2, i); |
274 | return FFH_RES(1); | 279 | return FFH_RES(1); |
275 | } | 280 | } |
276 | lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE), | 281 | lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE), |
277 | (uint8_t *)&(L->base-1)->n, o, 0); | 282 | (uint8_t *)&(L->base-1-LJ_FR2)->n, o, 0); |
278 | return FFH_RES(1); | 283 | return FFH_RES(1); |
279 | } | 284 | } |
280 | } | 285 | } |
@@ -282,53 +287,46 @@ LJLIB_ASM(tonumber) LJLIB_REC(.) | |||
282 | } else { | 287 | } else { |
283 | const char *p = strdata(lj_lib_checkstr(L, 1)); | 288 | const char *p = strdata(lj_lib_checkstr(L, 1)); |
284 | char *ep; | 289 | char *ep; |
290 | unsigned int neg = 0; | ||
285 | unsigned long ul; | 291 | unsigned long ul; |
286 | if (base < 2 || base > 36) | 292 | if (base < 2 || base > 36) |
287 | lj_err_arg(L, 2, LJ_ERR_BASERNG); | 293 | lj_err_arg(L, 2, LJ_ERR_BASERNG); |
288 | ul = strtoul(p, &ep, base); | 294 | while (lj_char_isspace((unsigned char)(*p))) p++; |
289 | if (p != ep) { | 295 | if (*p == '-') { p++; neg = 1; } else if (*p == '+') { p++; } |
290 | while (lj_char_isspace((unsigned char)(*ep))) ep++; | 296 | if (lj_char_isalnum((unsigned char)(*p))) { |
291 | if (*ep == '\0') { | 297 | ul = strtoul(p, &ep, base); |
292 | if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u)) | 298 | if (p != ep) { |
293 | setintV(L->base-1, (int32_t)ul); | 299 | while (lj_char_isspace((unsigned char)(*ep))) ep++; |
294 | else | 300 | if (*ep == '\0') { |
295 | setnumV(L->base-1, (lua_Number)ul); | 301 | if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u+neg)) { |
296 | return FFH_RES(1); | 302 | if (neg) ul = -ul; |
303 | setintV(L->base-1-LJ_FR2, (int32_t)ul); | ||
304 | } else { | ||
305 | lua_Number n = (lua_Number)ul; | ||
306 | if (neg) n = -n; | ||
307 | setnumV(L->base-1-LJ_FR2, n); | ||
308 | } | ||
309 | return FFH_RES(1); | ||
310 | } | ||
297 | } | 311 | } |
298 | } | 312 | } |
299 | } | 313 | } |
300 | setnilV(L->base-1); | 314 | setnilV(L->base-1-LJ_FR2); |
301 | return FFH_RES(1); | 315 | return FFH_RES(1); |
302 | } | 316 | } |
303 | 317 | ||
304 | LJLIB_PUSH("nil") | ||
305 | LJLIB_PUSH("false") | ||
306 | LJLIB_PUSH("true") | ||
307 | LJLIB_ASM(tostring) LJLIB_REC(.) | 318 | LJLIB_ASM(tostring) LJLIB_REC(.) |
308 | { | 319 | { |
309 | TValue *o = lj_lib_checkany(L, 1); | 320 | TValue *o = lj_lib_checkany(L, 1); |
310 | cTValue *mo; | 321 | cTValue *mo; |
311 | L->top = o+1; /* Only keep one argument. */ | 322 | L->top = o+1; /* Only keep one argument. */ |
312 | if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) { | 323 | if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) { |
313 | copyTV(L, L->base-1, mo); /* Replace callable. */ | 324 | copyTV(L, L->base-1-LJ_FR2, mo); /* Replace callable. */ |
314 | return FFH_TAILCALL; | 325 | 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 | } | 326 | } |
327 | lj_gc_check(L); | ||
328 | setstrV(L, L->base-1-LJ_FR2, lj_strfmt_obj(L, L->base)); | ||
329 | return FFH_RES(1); | ||
332 | } | 330 | } |
333 | 331 | ||
334 | /* -- Base library: throw and catch errors -------------------------------- */ | 332 | /* -- Base library: throw and catch errors -------------------------------- */ |
@@ -357,7 +355,7 @@ LJLIB_ASM_(xpcall) LJLIB_REC(.) | |||
357 | 355 | ||
358 | static int load_aux(lua_State *L, int status, int envarg) | 356 | static int load_aux(lua_State *L, int status, int envarg) |
359 | { | 357 | { |
360 | if (status == 0) { | 358 | if (status == LUA_OK) { |
361 | if (tvistab(L->base+envarg-1)) { | 359 | if (tvistab(L->base+envarg-1)) { |
362 | GCfunc *fn = funcV(L->top-1); | 360 | GCfunc *fn = funcV(L->top-1); |
363 | GCtab *t = tabV(L->base+envarg-1); | 361 | GCtab *t = tabV(L->base+envarg-1); |
@@ -430,7 +428,7 @@ LJLIB_CF(dofile) | |||
430 | GCstr *fname = lj_lib_optstr(L, 1); | 428 | GCstr *fname = lj_lib_optstr(L, 1); |
431 | setnilV(L->top); | 429 | setnilV(L->top); |
432 | L->top = L->base+1; | 430 | L->top = L->base+1; |
433 | if (luaL_loadfile(L, fname ? strdata(fname) : NULL) != 0) | 431 | if (luaL_loadfile(L, fname ? strdata(fname) : NULL) != LUA_OK) |
434 | lua_error(L); | 432 | lua_error(L); |
435 | lua_call(L, 0, LUA_MULTRET); | 433 | lua_call(L, 0, LUA_MULTRET); |
436 | return (int)(L->top - L->base) - 1; | 434 | return (int)(L->top - L->base) - 1; |
@@ -440,20 +438,20 @@ LJLIB_CF(dofile) | |||
440 | 438 | ||
441 | LJLIB_CF(gcinfo) | 439 | LJLIB_CF(gcinfo) |
442 | { | 440 | { |
443 | setintV(L->top++, (G(L)->gc.total >> 10)); | 441 | setintV(L->top++, (int32_t)(G(L)->gc.total >> 10)); |
444 | return 1; | 442 | return 1; |
445 | } | 443 | } |
446 | 444 | ||
447 | LJLIB_CF(collectgarbage) | 445 | LJLIB_CF(collectgarbage) |
448 | { | 446 | { |
449 | int opt = lj_lib_checkopt(L, 1, LUA_GCCOLLECT, /* ORDER LUA_GC* */ | 447 | int opt = lj_lib_checkopt(L, 1, LUA_GCCOLLECT, /* ORDER LUA_GC* */ |
450 | "\4stop\7restart\7collect\5count\1\377\4step\10setpause\12setstepmul"); | 448 | "\4stop\7restart\7collect\5count\1\377\4step\10setpause\12setstepmul\1\377\11isrunning"); |
451 | int32_t data = lj_lib_optint(L, 2, 0); | 449 | int32_t data = lj_lib_optint(L, 2, 0); |
452 | if (opt == LUA_GCCOUNT) { | 450 | if (opt == LUA_GCCOUNT) { |
453 | setnumV(L->top, (lua_Number)G(L)->gc.total/1024.0); | 451 | setnumV(L->top, (lua_Number)G(L)->gc.total/1024.0); |
454 | } else { | 452 | } else { |
455 | int res = lua_gc(L, opt, data); | 453 | int res = lua_gc(L, opt, data); |
456 | if (opt == LUA_GCSTEP) | 454 | if (opt == LUA_GCSTEP || opt == LUA_GCISRUNNING) |
457 | setboolV(L->top, res); | 455 | setboolV(L->top, res); |
458 | else | 456 | else |
459 | setintV(L->top, res); | 457 | setintV(L->top, res); |
@@ -505,23 +503,14 @@ LJLIB_CF(print) | |||
505 | tv = L->top-1; | 503 | tv = L->top-1; |
506 | } | 504 | } |
507 | shortcut = (tvisfunc(tv) && funcV(tv)->c.ffid == FF_tostring) | 505 | shortcut = (tvisfunc(tv) && funcV(tv)->c.ffid == FF_tostring) |
508 | && !gcrefu(basemt_it(G(L), LJ_TNUMX)); | 506 | && !gcrefu(basemt_it(G(L), LJ_TNUMX)); |
509 | for (i = 0; i < nargs; i++) { | 507 | for (i = 0; i < nargs; i++) { |
508 | cTValue *o = &L->base[i]; | ||
510 | const char *str; | 509 | const char *str; |
511 | size_t size; | 510 | size_t size; |
512 | cTValue *o = &L->base[i]; | 511 | MSize len; |
513 | if (shortcut && tvisstr(o)) { | 512 | if (shortcut && (str = lj_strfmt_wstrnum(L, o, &len)) != NULL) { |
514 | str = strVdata(o); | 513 | size = len; |
515 | size = strV(o)->len; | ||
516 | } else if (shortcut && tvisint(o)) { | ||
517 | char buf[LJ_STR_INTBUF]; | ||
518 | char *p = lj_str_bufint(buf, intV(o)); | ||
519 | size = (size_t)(buf+LJ_STR_INTBUF-p); | ||
520 | str = p; | ||
521 | } else if (shortcut && tvisnum(o)) { | ||
522 | char buf[LJ_STR_NUMBUF]; | ||
523 | size = lj_str_bufnum(buf, o); | ||
524 | str = buf; | ||
525 | } else { | 514 | } else { |
526 | copyTV(L, L->top+1, o); | 515 | copyTV(L, L->top+1, o); |
527 | copyTV(L, L->top, L->top-1); | 516 | copyTV(L, L->top, L->top-1); |
@@ -558,8 +547,8 @@ LJLIB_CF(coroutine_status) | |||
558 | co = threadV(L->base); | 547 | co = threadV(L->base); |
559 | if (co == L) s = "running"; | 548 | if (co == L) s = "running"; |
560 | else if (co->status == LUA_YIELD) s = "suspended"; | 549 | else if (co->status == LUA_YIELD) s = "suspended"; |
561 | else if (co->status != 0) s = "dead"; | 550 | else if (co->status != LUA_OK) s = "dead"; |
562 | else if (co->base > tvref(co->stack)+1) s = "normal"; | 551 | else if (co->base > tvref(co->stack)+1+LJ_FR2) s = "normal"; |
563 | else if (co->top == co->base) s = "dead"; | 552 | else if (co->top == co->base) s = "dead"; |
564 | else s = "suspended"; | 553 | else s = "suspended"; |
565 | lua_pushstring(L, s); | 554 | lua_pushstring(L, s); |
@@ -579,6 +568,12 @@ LJLIB_CF(coroutine_running) | |||
579 | #endif | 568 | #endif |
580 | } | 569 | } |
581 | 570 | ||
571 | LJLIB_CF(coroutine_isyieldable) | ||
572 | { | ||
573 | setboolV(L->top++, cframe_canyield(L->cframe)); | ||
574 | return 1; | ||
575 | } | ||
576 | |||
582 | LJLIB_CF(coroutine_create) | 577 | LJLIB_CF(coroutine_create) |
583 | { | 578 | { |
584 | lua_State *L1; | 579 | lua_State *L1; |
@@ -598,11 +593,11 @@ LJLIB_ASM(coroutine_yield) | |||
598 | static int ffh_resume(lua_State *L, lua_State *co, int wrap) | 593 | static int ffh_resume(lua_State *L, lua_State *co, int wrap) |
599 | { | 594 | { |
600 | if (co->cframe != NULL || co->status > LUA_YIELD || | 595 | if (co->cframe != NULL || co->status > LUA_YIELD || |
601 | (co->status == 0 && co->top == co->base)) { | 596 | (co->status == LUA_OK && co->top == co->base)) { |
602 | ErrMsg em = co->cframe ? LJ_ERR_CORUN : LJ_ERR_CODEAD; | 597 | ErrMsg em = co->cframe ? LJ_ERR_CORUN : LJ_ERR_CODEAD; |
603 | if (wrap) lj_err_caller(L, em); | 598 | if (wrap) lj_err_caller(L, em); |
604 | setboolV(L->base-1, 0); | 599 | setboolV(L->base-1-LJ_FR2, 0); |
605 | setstrV(L, L->base, lj_err_str(L, em)); | 600 | setstrV(L, L->base-LJ_FR2, lj_err_str(L, em)); |
606 | return FFH_RES(2); | 601 | return FFH_RES(2); |
607 | } | 602 | } |
608 | lj_state_growstack(co, (MSize)(L->top - L->base)); | 603 | lj_state_growstack(co, (MSize)(L->top - L->base)); |
@@ -643,9 +638,10 @@ static void setpc_wrap_aux(lua_State *L, GCfunc *fn); | |||
643 | 638 | ||
644 | LJLIB_CF(coroutine_wrap) | 639 | LJLIB_CF(coroutine_wrap) |
645 | { | 640 | { |
641 | GCfunc *fn; | ||
646 | lj_cf_coroutine_create(L); | 642 | lj_cf_coroutine_create(L); |
647 | lj_lib_pushcc(L, lj_ffh_coroutine_wrap_aux, FF_coroutine_wrap_aux, 1); | 643 | fn = lj_lib_pushcc(L, lj_ffh_coroutine_wrap_aux, FF_coroutine_wrap_aux, 1); |
648 | setpc_wrap_aux(L, funcV(L->top-1)); | 644 | setpc_wrap_aux(L, fn); |
649 | return 1; | 645 | return 1; |
650 | } | 646 | } |
651 | 647 | ||