root/lib_base.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. LJLIB_ASM
  2. LJLIB_ASM
  3. ffh_pairs
  4. LJLIB_PUSH
  5. LJLIB_ASM
  6. LJLIB_PUSH
  7. LJLIB_ASM_
  8. LJLIB_CF
  9. LJLIB_CF
  10. LJLIB_ASM
  11. LJLIB_CF
  12. LJLIB_CF
  13. LJLIB_CF
  14. LJLIB_CF
  15. LJLIB_CF
  16. LJLIB_ASM
  17. LJLIB_PUSH
  18. LJLIB_CF
  19. LJLIB_ASM
  20. LJLIB_ASM_
  21. LJLIB_CF
  22. reader_func
  23. LJLIB_CF
  24. LJLIB_CF
  25. LJLIB_CF
  26. LJLIB_CF
  27. LJLIB_CF
  28. LJLIB_PUSH
  29. LJLIB_PUSH
  30. LJLIB_PUSH
  31. LJLIB_CF
  32. LJLIB_CF
  33. LJLIB_ASM
  34. ffh_resume
  35. LJLIB_ASM
  36. LJLIB_ASM
  37. lj_ffh_coroutine_wrap_err
  38. LJLIB_CF
  39. setpc_wrap_aux
  40. newproxy_weaktable
  41. luaopen_base

   1 /*
   2 ** Base and coroutine library.
   3 ** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
   4 **
   5 ** Major portions taken verbatim or adapted from the Lua interpreter.
   6 ** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h
   7 */
   8 
   9 #include <stdio.h>
  10 
  11 #define lib_base_c
  12 #define LUA_LIB
  13 
  14 #include "lua.h"
  15 #include "lauxlib.h"
  16 #include "lualib.h"
  17 
  18 #include "lj_obj.h"
  19 #include "lj_gc.h"
  20 #include "lj_err.h"
  21 #include "lj_debug.h"
  22 #include "lj_str.h"
  23 #include "lj_tab.h"
  24 #include "lj_meta.h"
  25 #include "lj_state.h"
  26 #if LJ_HASFFI
  27 #include "lj_ctype.h"
  28 #include "lj_cconv.h"
  29 #endif
  30 #include "lj_bc.h"
  31 #include "lj_ff.h"
  32 #include "lj_dispatch.h"
  33 #include "lj_char.h"
  34 #include "lj_strscan.h"
  35 #include "lj_lib.h"
  36 
  37 /* -- Base library: checks ------------------------------------------------ */
  38 
  39 #define LJLIB_MODULE_base
  40 
  41 LJLIB_ASM(assert)               LJLIB_REC(.)
  42 {
  43   GCstr *s;
  44   lj_lib_checkany(L, 1);
  45   s = lj_lib_optstr(L, 2);
  46   if (s)
  47     lj_err_callermsg(L, strdata(s));
  48   else
  49     lj_err_caller(L, LJ_ERR_ASSERT);
  50   return FFH_UNREACHABLE;
  51 }
  52 
  53 /* ORDER LJ_T */
  54 LJLIB_PUSH("nil")
  55 LJLIB_PUSH("boolean")
  56 LJLIB_PUSH(top-1)  /* boolean */
  57 LJLIB_PUSH("userdata")
  58 LJLIB_PUSH("string")
  59 LJLIB_PUSH("upval")
  60 LJLIB_PUSH("thread")
  61 LJLIB_PUSH("proto")
  62 LJLIB_PUSH("function")
  63 LJLIB_PUSH("trace")
  64 LJLIB_PUSH("cdata")
  65 LJLIB_PUSH("table")
  66 LJLIB_PUSH(top-9)  /* userdata */
  67 LJLIB_PUSH("number")
  68 LJLIB_ASM_(type)                LJLIB_REC(.)
  69 /* Recycle the lj_lib_checkany(L, 1) from assert. */
  70 
  71 /* -- Base library: iterators --------------------------------------------- */
  72 
  73 /* This solves a circular dependency problem -- change FF_next_N as needed. */
  74 LJ_STATIC_ASSERT((int)FF_next == FF_next_N);
  75 
  76 LJLIB_ASM(next)
  77 {
  78   lj_lib_checktab(L, 1);
  79   return FFH_UNREACHABLE;
  80 }
  81 
  82 #if LJ_52 || LJ_HASFFI
  83 static int ffh_pairs(lua_State *L, MMS mm)
  84 {
  85   TValue *o = lj_lib_checkany(L, 1);
  86   cTValue *mo = lj_meta_lookup(L, o, mm);
  87   if ((LJ_52 || tviscdata(o)) && !tvisnil(mo)) {
  88     L->top = o+1;  /* Only keep one argument. */
  89     copyTV(L, L->base-1, mo);  /* Replace callable. */
  90     return FFH_TAILCALL;
  91   } else {
  92     if (!tvistab(o)) lj_err_argt(L, 1, LUA_TTABLE);
  93     setfuncV(L, o-1, funcV(lj_lib_upvalue(L, 1)));
  94     if (mm == MM_pairs) setnilV(o+1); else setintV(o+1, 0);
  95     return FFH_RES(3);
  96   }
  97 }
  98 #else
  99 #define ffh_pairs(L, mm)        (lj_lib_checktab(L, 1), FFH_UNREACHABLE)
 100 #endif
 101 
 102 LJLIB_PUSH(lastcl)
 103 LJLIB_ASM(pairs)
 104 {
 105   return ffh_pairs(L, MM_pairs);
 106 }
 107 
 108 LJLIB_NOREGUV LJLIB_ASM(ipairs_aux)     LJLIB_REC(.)
 109 {
 110   lj_lib_checktab(L, 1);
 111   lj_lib_checkint(L, 2);
 112   return FFH_UNREACHABLE;
 113 }
 114 
 115 LJLIB_PUSH(lastcl)
 116 LJLIB_ASM(ipairs)               LJLIB_REC(.)
 117 {
 118   return ffh_pairs(L, MM_ipairs);
 119 }
 120 
 121 /* -- Base library: getters and setters ----------------------------------- */
 122 
 123 LJLIB_ASM_(getmetatable)        LJLIB_REC(.)
 124 /* Recycle the lj_lib_checkany(L, 1) from assert. */
 125 
 126 LJLIB_ASM(setmetatable)         LJLIB_REC(.)
 127 {
 128   GCtab *t = lj_lib_checktab(L, 1);
 129   GCtab *mt = lj_lib_checktabornil(L, 2);
 130   if (!tvisnil(lj_meta_lookup(L, L->base, MM_metatable)))
 131     lj_err_caller(L, LJ_ERR_PROTMT);
 132   setgcref(t->metatable, obj2gco(mt));
 133   if (mt) { lj_gc_objbarriert(L, t, mt); }
 134   settabV(L, L->base-1, t);
 135   return FFH_RES(1);
 136 }
 137 
 138 LJLIB_CF(getfenv)
 139 {
 140   GCfunc *fn;
 141   cTValue *o = L->base;
 142   if (!(o < L->top && tvisfunc(o))) {
 143     int level = lj_lib_optint(L, 1, 1);
 144     o = lj_debug_frame(L, level, &level);
 145     if (o == NULL)
 146       lj_err_arg(L, 1, LJ_ERR_INVLVL);
 147   }
 148   fn = &gcval(o)->fn;
 149   settabV(L, L->top++, isluafunc(fn) ? tabref(fn->l.env) : tabref(L->env));
 150   return 1;
 151 }
 152 
 153 LJLIB_CF(setfenv)
 154 {
 155   GCfunc *fn;
 156   GCtab *t = lj_lib_checktab(L, 2);
 157   cTValue *o = L->base;
 158   if (!(o < L->top && tvisfunc(o))) {
 159     int level = lj_lib_checkint(L, 1);
 160     if (level == 0) {
 161       /* NOBARRIER: A thread (i.e. L) is never black. */
 162       setgcref(L->env, obj2gco(t));
 163       return 0;
 164     }
 165     o = lj_debug_frame(L, level, &level);
 166     if (o == NULL)
 167       lj_err_arg(L, 1, LJ_ERR_INVLVL);
 168   }
 169   fn = &gcval(o)->fn;
 170   if (!isluafunc(fn))
 171     lj_err_caller(L, LJ_ERR_SETFENV);
 172   setgcref(fn->l.env, obj2gco(t));
 173   lj_gc_objbarrier(L, obj2gco(fn), t);
 174   setfuncV(L, L->top++, fn);
 175   return 1;
 176 }
 177 
 178 LJLIB_ASM(rawget)               LJLIB_REC(.)
 179 {
 180   lj_lib_checktab(L, 1);
 181   lj_lib_checkany(L, 2);
 182   return FFH_UNREACHABLE;
 183 }
 184 
 185 LJLIB_CF(rawset)                LJLIB_REC(.)
 186 {
 187   lj_lib_checktab(L, 1);
 188   lj_lib_checkany(L, 2);
 189   L->top = 1+lj_lib_checkany(L, 3);
 190   lua_rawset(L, 1);
 191   return 1;
 192 }
 193 
 194 LJLIB_CF(rawequal)              LJLIB_REC(.)
 195 {
 196   cTValue *o1 = lj_lib_checkany(L, 1);
 197   cTValue *o2 = lj_lib_checkany(L, 2);
 198   setboolV(L->top-1, lj_obj_equal(o1, o2));
 199   return 1;
 200 }
 201 
 202 #if LJ_52
 203 LJLIB_CF(rawlen)                LJLIB_REC(.)
 204 {
 205   cTValue *o = L->base;
 206   int32_t len;
 207   if (L->top > o && tvisstr(o))
 208     len = (int32_t)strV(o)->len;
 209   else
 210     len = (int32_t)lj_tab_len(lj_lib_checktab(L, 1));
 211   setintV(L->top-1, len);
 212   return 1;
 213 }
 214 #endif
 215 
 216 LJLIB_CF(unpack)
 217 {
 218   GCtab *t = lj_lib_checktab(L, 1);
 219   int32_t n, i = lj_lib_optint(L, 2, 1);
 220   int32_t e = (L->base+3-1 < L->top && !tvisnil(L->base+3-1)) ?
 221               lj_lib_checkint(L, 3) : (int32_t)lj_tab_len(t);
 222   if (i > e) return 0;
 223   n = e - i + 1;
 224   if (n <= 0 || !lua_checkstack(L, n))
 225     lj_err_caller(L, LJ_ERR_UNPACK);
 226   do {
 227     cTValue *tv = lj_tab_getint(t, i);
 228     if (tv) {
 229       copyTV(L, L->top++, tv);
 230     } else {
 231       setnilV(L->top++);
 232     }
 233   } while (i++ < e);
 234   return n;
 235 }
 236 
 237 LJLIB_CF(select)                LJLIB_REC(.)
 238 {
 239   int32_t n = (int32_t)(L->top - L->base);
 240   if (n >= 1 && tvisstr(L->base) && *strVdata(L->base) == '#') {
 241     setintV(L->top-1, n-1);
 242     return 1;
 243   } else {
 244     int32_t i = lj_lib_checkint(L, 1);
 245     if (i < 0) i = n + i; else if (i > n) i = n;
 246     if (i < 1)
 247       lj_err_arg(L, 1, LJ_ERR_IDXRNG);
 248     return n - i;
 249   }
 250 }
 251 
 252 /* -- Base library: conversions ------------------------------------------- */
 253 
 254 LJLIB_ASM(tonumber)             LJLIB_REC(.)
 255 {
 256   int32_t base = lj_lib_optint(L, 2, 10);
 257   if (base == 10) {
 258     TValue *o = lj_lib_checkany(L, 1);
 259     if (lj_strscan_numberobj(o)) {
 260       copyTV(L, L->base-1, o);
 261       return FFH_RES(1);
 262     }
 263 #if LJ_HASFFI
 264     if (tviscdata(o)) {
 265       CTState *cts = ctype_cts(L);
 266       CType *ct = lj_ctype_rawref(cts, cdataV(o)->ctypeid);
 267       if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);
 268       if (ctype_isnum(ct->info) || ctype_iscomplex(ct->info)) {
 269         if (LJ_DUALNUM && ctype_isinteger_or_bool(ct->info) &&
 270             ct->size <= 4 && !(ct->size == 4 && (ct->info & CTF_UNSIGNED))) {
 271           int32_t i;
 272           lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, 0);
 273           setintV(L->base-1, i);
 274           return FFH_RES(1);
 275         }
 276         lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE),
 277                        (uint8_t *)&(L->base-1)->n, o, 0);
 278         return FFH_RES(1);
 279       }
 280     }
 281 #endif
 282   } else {
 283     const char *p = strdata(lj_lib_checkstr(L, 1));
 284     char *ep;
 285     unsigned long ul;
 286     if (base < 2 || base > 36)
 287       lj_err_arg(L, 2, LJ_ERR_BASERNG);
 288     ul = strtoul(p, &ep, base);
 289     if (p != ep) {
 290       while (lj_char_isspace((unsigned char)(*ep))) ep++;
 291       if (*ep == '\0') {
 292         if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u))
 293           setintV(L->base-1, (int32_t)ul);
 294         else
 295           setnumV(L->base-1, (lua_Number)ul);
 296         return FFH_RES(1);
 297       }
 298     }
 299   }
 300   setnilV(L->base-1);
 301   return FFH_RES(1);
 302 }
 303 
 304 LJLIB_PUSH("nil")
 305 LJLIB_PUSH("false")
 306 LJLIB_PUSH("true")
 307 LJLIB_ASM(tostring)             LJLIB_REC(.)
 308 {
 309   TValue *o = lj_lib_checkany(L, 1);
 310   cTValue *mo;
 311   L->top = o+1;  /* Only keep one argument. */
 312   if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
 313     copyTV(L, L->base-1, mo);  /* Replace callable. */
 314     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   }
 332 }
 333 
 334 /* -- Base library: throw and catch errors -------------------------------- */
 335 
 336 LJLIB_CF(error)
 337 {
 338   int32_t level = lj_lib_optint(L, 2, 1);
 339   lua_settop(L, 1);
 340   if (lua_isstring(L, 1) && level > 0) {
 341     luaL_where(L, level);
 342     lua_pushvalue(L, 1);
 343     lua_concat(L, 2);
 344   }
 345   return lua_error(L);
 346 }
 347 
 348 LJLIB_ASM(pcall)                LJLIB_REC(.)
 349 {
 350   lj_lib_checkany(L, 1);
 351   lj_lib_checkfunc(L, 2);  /* For xpcall only. */
 352   return FFH_UNREACHABLE;
 353 }
 354 LJLIB_ASM_(xpcall)              LJLIB_REC(.)
 355 
 356 /* -- Base library: load Lua code ----------------------------------------- */
 357 
 358 static int load_aux(lua_State *L, int status, int envarg)
 359 {
 360   if (status == 0) {
 361     if (tvistab(L->base+envarg-1)) {
 362       GCfunc *fn = funcV(L->top-1);
 363       GCtab *t = tabV(L->base+envarg-1);
 364       setgcref(fn->c.env, obj2gco(t));
 365       lj_gc_objbarrier(L, fn, t);
 366     }
 367     return 1;
 368   } else {
 369     setnilV(L->top-2);
 370     return 2;
 371   }
 372 }
 373 
 374 LJLIB_CF(loadfile)
 375 {
 376   GCstr *fname = lj_lib_optstr(L, 1);
 377   GCstr *mode = lj_lib_optstr(L, 2);
 378   int status;
 379   lua_settop(L, 3);  /* Ensure env arg exists. */
 380   status = luaL_loadfilex(L, fname ? strdata(fname) : NULL,
 381                           mode ? strdata(mode) : NULL);
 382   return load_aux(L, status, 3);
 383 }
 384 
 385 static const char *reader_func(lua_State *L, void *ud, size_t *size)
 386 {
 387   UNUSED(ud);
 388   luaL_checkstack(L, 2, "too many nested functions");
 389   copyTV(L, L->top++, L->base);
 390   lua_call(L, 0, 1);  /* Call user-supplied function. */
 391   L->top--;
 392   if (tvisnil(L->top)) {
 393     *size = 0;
 394     return NULL;
 395   } else if (tvisstr(L->top) || tvisnumber(L->top)) {
 396     copyTV(L, L->base+4, L->top);  /* Anchor string in reserved stack slot. */
 397     return lua_tolstring(L, 5, size);
 398   } else {
 399     lj_err_caller(L, LJ_ERR_RDRSTR);
 400     return NULL;
 401   }
 402 }
 403 
 404 LJLIB_CF(load)
 405 {
 406   GCstr *name = lj_lib_optstr(L, 2);
 407   GCstr *mode = lj_lib_optstr(L, 3);
 408   int status;
 409   if (L->base < L->top && (tvisstr(L->base) || tvisnumber(L->base))) {
 410     GCstr *s = lj_lib_checkstr(L, 1);
 411     lua_settop(L, 4);  /* Ensure env arg exists. */
 412     status = luaL_loadbufferx(L, strdata(s), s->len, strdata(name ? name : s),
 413                               mode ? strdata(mode) : NULL);
 414   } else {
 415     lj_lib_checkfunc(L, 1);
 416     lua_settop(L, 5);  /* Reserve a slot for the string from the reader. */
 417     status = lua_loadx(L, reader_func, NULL, name ? strdata(name) : "=(load)",
 418                        mode ? strdata(mode) : NULL);
 419   }
 420   return load_aux(L, status, 4);
 421 }
 422 
 423 LJLIB_CF(loadstring)
 424 {
 425   return lj_cf_load(L);
 426 }
 427 
 428 LJLIB_CF(dofile)
 429 {
 430   GCstr *fname = lj_lib_optstr(L, 1);
 431   setnilV(L->top);
 432   L->top = L->base+1;
 433   if (luaL_loadfile(L, fname ? strdata(fname) : NULL) != 0)
 434     lua_error(L);
 435   lua_call(L, 0, LUA_MULTRET);
 436   return (int)(L->top - L->base) - 1;
 437 }
 438 
 439 /* -- Base library: GC control -------------------------------------------- */
 440 
 441 LJLIB_CF(gcinfo)
 442 {
 443   setintV(L->top++, (G(L)->gc.total >> 10));
 444   return 1;
 445 }
 446 
 447 LJLIB_CF(collectgarbage)
 448 {
 449   int opt = lj_lib_checkopt(L, 1, LUA_GCCOLLECT,  /* ORDER LUA_GC* */
 450     "\4stop\7restart\7collect\5count\1\377\4step\10setpause\12setstepmul");
 451   int32_t data = lj_lib_optint(L, 2, 0);
 452   if (opt == LUA_GCCOUNT) {
 453     setnumV(L->top, (lua_Number)G(L)->gc.total/1024.0);
 454   } else {
 455     int res = lua_gc(L, opt, data);
 456     if (opt == LUA_GCSTEP)
 457       setboolV(L->top, res);
 458     else
 459       setintV(L->top, res);
 460   }
 461   L->top++;
 462   return 1;
 463 }
 464 
 465 /* -- Base library: miscellaneous functions ------------------------------- */
 466 
 467 LJLIB_PUSH(top-2)  /* Upvalue holds weak table. */
 468 LJLIB_CF(newproxy)
 469 {
 470   lua_settop(L, 1);
 471   lua_newuserdata(L, 0);
 472   if (lua_toboolean(L, 1) == 0) {  /* newproxy(): without metatable. */
 473     return 1;
 474   } else if (lua_isboolean(L, 1)) {  /* newproxy(true): with metatable. */
 475     lua_newtable(L);
 476     lua_pushvalue(L, -1);
 477     lua_pushboolean(L, 1);
 478     lua_rawset(L, lua_upvalueindex(1));  /* Remember mt in weak table. */
 479   } else {  /* newproxy(proxy): inherit metatable. */
 480     int validproxy = 0;
 481     if (lua_getmetatable(L, 1)) {
 482       lua_rawget(L, lua_upvalueindex(1));
 483       validproxy = lua_toboolean(L, -1);
 484       lua_pop(L, 1);
 485     }
 486     if (!validproxy)
 487       lj_err_arg(L, 1, LJ_ERR_NOPROXY);
 488     lua_getmetatable(L, 1);
 489   }
 490   lua_setmetatable(L, 2);
 491   return 1;
 492 }
 493 
 494 LJLIB_PUSH("tostring")
 495 LJLIB_CF(print)
 496 {
 497   ptrdiff_t i, nargs = L->top - L->base;
 498   cTValue *tv = lj_tab_getstr(tabref(L->env), strV(lj_lib_upvalue(L, 1)));
 499   int shortcut;
 500   if (tv && !tvisnil(tv)) {
 501     copyTV(L, L->top++, tv);
 502   } else {
 503     setstrV(L, L->top++, strV(lj_lib_upvalue(L, 1)));
 504     lua_gettable(L, LUA_GLOBALSINDEX);
 505     tv = L->top-1;
 506   }
 507   shortcut = (tvisfunc(tv) && funcV(tv)->c.ffid == FF_tostring);
 508   for (i = 0; i < nargs; i++) {
 509     const char *str;
 510     size_t size;
 511     cTValue *o = &L->base[i];
 512     if (shortcut && tvisstr(o)) {
 513       str = strVdata(o);
 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 {
 525       copyTV(L, L->top+1, o);
 526       copyTV(L, L->top, L->top-1);
 527       L->top += 2;
 528       lua_call(L, 1, 1);
 529       str = lua_tolstring(L, -1, &size);
 530       if (!str)
 531         lj_err_caller(L, LJ_ERR_PRTOSTR);
 532       L->top--;
 533     }
 534     if (i)
 535       putchar('\t');
 536     fwrite(str, 1, size, stdout);
 537   }
 538   putchar('\n');
 539   return 0;
 540 }
 541 
 542 LJLIB_PUSH(top-3)
 543 LJLIB_SET(_VERSION)
 544 
 545 #include "lj_libdef.h"
 546 
 547 /* -- Coroutine library --------------------------------------------------- */
 548 
 549 #define LJLIB_MODULE_coroutine
 550 
 551 LJLIB_CF(coroutine_status)
 552 {
 553   const char *s;
 554   lua_State *co;
 555   if (!(L->top > L->base && tvisthread(L->base)))
 556     lj_err_arg(L, 1, LJ_ERR_NOCORO);
 557   co = threadV(L->base);
 558   if (co == L) s = "running";
 559   else if (co->status == LUA_YIELD) s = "suspended";
 560   else if (co->status != 0) s = "dead";
 561   else if (co->base > tvref(co->stack)+1) s = "normal";
 562   else if (co->top == co->base) s = "dead";
 563   else s = "suspended";
 564   lua_pushstring(L, s);
 565   return 1;
 566 }
 567 
 568 LJLIB_CF(coroutine_running)
 569 {
 570 #if LJ_52
 571   int ismain = lua_pushthread(L);
 572   setboolV(L->top++, ismain);
 573   return 2;
 574 #else
 575   if (lua_pushthread(L))
 576     setnilV(L->top++);
 577   return 1;
 578 #endif
 579 }
 580 
 581 LJLIB_CF(coroutine_create)
 582 {
 583   lua_State *L1;
 584   if (!(L->base < L->top && tvisfunc(L->base)))
 585     lj_err_argt(L, 1, LUA_TFUNCTION);
 586   L1 = lua_newthread(L);
 587   setfuncV(L, L1->top++, funcV(L->base));
 588   return 1;
 589 }
 590 
 591 LJLIB_ASM(coroutine_yield)
 592 {
 593   lj_err_caller(L, LJ_ERR_CYIELD);
 594   return FFH_UNREACHABLE;
 595 }
 596 
 597 static int ffh_resume(lua_State *L, lua_State *co, int wrap)
 598 {
 599   if (co->cframe != NULL || co->status > LUA_YIELD ||
 600       (co->status == 0 && co->top == co->base)) {
 601     ErrMsg em = co->cframe ? LJ_ERR_CORUN : LJ_ERR_CODEAD;
 602     if (wrap) lj_err_caller(L, em);
 603     setboolV(L->base-1, 0);
 604     setstrV(L, L->base, lj_err_str(L, em));
 605     return FFH_RES(2);
 606   }
 607   lj_state_growstack(co, (MSize)(L->top - L->base));
 608   return FFH_RETRY;
 609 }
 610 
 611 LJLIB_ASM(coroutine_resume)
 612 {
 613   if (!(L->top > L->base && tvisthread(L->base)))
 614     lj_err_arg(L, 1, LJ_ERR_NOCORO);
 615   return ffh_resume(L, threadV(L->base), 0);
 616 }
 617 
 618 LJLIB_NOREG LJLIB_ASM(coroutine_wrap_aux)
 619 {
 620   return ffh_resume(L, threadV(lj_lib_upvalue(L, 1)), 1);
 621 }
 622 
 623 /* Inline declarations. */
 624 LJ_ASMF void lj_ff_coroutine_wrap_aux(void);
 625 #if !(LJ_TARGET_MIPS && defined(ljamalg_c))
 626 LJ_FUNCA_NORET void LJ_FASTCALL lj_ffh_coroutine_wrap_err(lua_State *L,
 627                                                           lua_State *co);
 628 #endif
 629 
 630 /* Error handler, called from assembler VM. */
 631 void LJ_FASTCALL lj_ffh_coroutine_wrap_err(lua_State *L, lua_State *co)
 632 {
 633   co->top--; copyTV(L, L->top, co->top); L->top++;
 634   if (tvisstr(L->top-1))
 635     lj_err_callermsg(L, strVdata(L->top-1));
 636   else
 637     lj_err_run(L);
 638 }
 639 
 640 /* Forward declaration. */
 641 static void setpc_wrap_aux(lua_State *L, GCfunc *fn);
 642 
 643 LJLIB_CF(coroutine_wrap)
 644 {
 645   lj_cf_coroutine_create(L);
 646   lj_lib_pushcc(L, lj_ffh_coroutine_wrap_aux, FF_coroutine_wrap_aux, 1);
 647   setpc_wrap_aux(L, funcV(L->top-1));
 648   return 1;
 649 }
 650 
 651 #include "lj_libdef.h"
 652 
 653 /* Fix the PC of wrap_aux. Really ugly workaround. */
 654 static void setpc_wrap_aux(lua_State *L, GCfunc *fn)
 655 {
 656   setmref(fn->c.pc, &L2GG(L)->bcff[lj_lib_init_coroutine[1]+2]);
 657 }
 658 
 659 /* ------------------------------------------------------------------------ */
 660 
 661 static void newproxy_weaktable(lua_State *L)
 662 {
 663   /* NOBARRIER: The table is new (marked white). */
 664   GCtab *t = lj_tab_new(L, 0, 1);
 665   settabV(L, L->top++, t);
 666   setgcref(t->metatable, obj2gco(t));
 667   setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "__mode")),
 668             lj_str_newlit(L, "kv"));
 669   t->nomm = (uint8_t)(~(1u<<MM_mode));
 670 }
 671 
 672 LUALIB_API int luaopen_base(lua_State *L)
 673 {
 674   /* NOBARRIER: Table and value are the same. */
 675   GCtab *env = tabref(L->env);
 676   settabV(L, lj_tab_setstr(L, env, lj_str_newlit(L, "_G")), env);
 677   lua_pushliteral(L, LUA_VERSION);  /* top-3. */
 678   newproxy_weaktable(L);  /* top-2. */
 679   LJ_LIB_REG(L, "_G", base);
 680   LJ_LIB_REG(L, LUA_COLIBNAME, coroutine);
 681   return 2;
 682 }
 683 

/* [<][>][^][v][top][bottom][index][help] */