diff options
Diffstat (limited to 'src/lib_base.c')
| -rw-r--r-- | src/lib_base.c | 167 |
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 | ||
| 41 | LJLIB_ASM(assert) LJLIB_REC(.) | 44 | LJLIB_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. */ |
| 74 | LJ_STATIC_ASSERT((int)FF_next == FF_next_N); | 77 | LJ_STATIC_ASSERT((int)FF_next == FF_next_N); |
| 75 | 78 | ||
| 76 | LJLIB_ASM(next) | 79 | LJLIB_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 | ||
| 102 | LJLIB_PUSH(lastcl) | 107 | LJLIB_PUSH(lastcl) |
| 103 | LJLIB_ASM(pairs) | 108 | LJLIB_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 | ||
| 115 | LJLIB_PUSH(lastcl) | 120 | LJLIB_PUSH(lastcl) |
| 116 | LJLIB_ASM(ipairs) LJLIB_REC(.) | 121 | LJLIB_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 | ||
| 138 | LJLIB_CF(getfenv) | 143 | LJLIB_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 | ||
| 312 | LJLIB_PUSH("nil") | ||
| 313 | LJLIB_PUSH("false") | ||
| 314 | LJLIB_PUSH("true") | ||
| 315 | LJLIB_ASM(tostring) LJLIB_REC(.) | 328 | LJLIB_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 | ||
| 366 | static int load_aux(lua_State *L, int status, int envarg) | 366 | static 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 | ||
| 449 | LJLIB_CF(gcinfo) | 465 | LJLIB_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 | ||
| 455 | LJLIB_CF(collectgarbage) | 471 | LJLIB_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 | ||
| 597 | LJLIB_CF(coroutine_isyieldable) | ||
| 598 | { | ||
| 599 | setboolV(L->top++, cframe_canyield(L->cframe)); | ||
| 600 | return 1; | ||
| 601 | } | ||
| 602 | |||
| 590 | LJLIB_CF(coroutine_create) | 603 | LJLIB_CF(coroutine_create) |
| 591 | { | 604 | { |
| 592 | lua_State *L1; | 605 | lua_State *L1; |
| @@ -606,14 +619,17 @@ LJLIB_ASM(coroutine_yield) | |||
| 606 | static int ffh_resume(lua_State *L, lua_State *co, int wrap) | 619 | static 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 | ||
| 652 | LJLIB_CF(coroutine_wrap) | 668 | LJLIB_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 | ||
