From 6523585c66c04cea54df50013df8886b589847d8 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Mon, 23 Jan 2012 23:36:30 +1000 Subject: Add luaproc and LuaJIT libraries. Two versions of LuaJIT, the stable release, and the dev version. Try the dev version first, until ih fails badly. --- libraries/luajit-2.0/src/lib_base.c | 650 ++++++++++++++++++++++++++++++++++++ 1 file changed, 650 insertions(+) create mode 100644 libraries/luajit-2.0/src/lib_base.c (limited to 'libraries/luajit-2.0/src/lib_base.c') diff --git a/libraries/luajit-2.0/src/lib_base.c b/libraries/luajit-2.0/src/lib_base.c new file mode 100644 index 0000000..f897598 --- /dev/null +++ b/libraries/luajit-2.0/src/lib_base.c @@ -0,0 +1,650 @@ +/* +** Base and coroutine library. +** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h +** +** Major portions taken verbatim or adapted from the Lua interpreter. +** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h +*/ + +#include + +#define lib_base_c +#define LUA_LIB + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" + +#include "lj_obj.h" +#include "lj_gc.h" +#include "lj_err.h" +#include "lj_debug.h" +#include "lj_str.h" +#include "lj_tab.h" +#include "lj_meta.h" +#include "lj_state.h" +#if LJ_HASFFI +#include "lj_ctype.h" +#include "lj_cconv.h" +#endif +#include "lj_bc.h" +#include "lj_ff.h" +#include "lj_dispatch.h" +#include "lj_char.h" +#include "lj_lib.h" + +/* -- Base library: checks ------------------------------------------------ */ + +#define LJLIB_MODULE_base + +LJLIB_ASM(assert) LJLIB_REC(.) +{ + GCstr *s; + lj_lib_checkany(L, 1); + s = lj_lib_optstr(L, 2); + if (s) + lj_err_callermsg(L, strdata(s)); + else + lj_err_caller(L, LJ_ERR_ASSERT); + return FFH_UNREACHABLE; +} + +/* ORDER LJ_T */ +LJLIB_PUSH("nil") +LJLIB_PUSH("boolean") +LJLIB_PUSH(top-1) /* boolean */ +LJLIB_PUSH("userdata") +LJLIB_PUSH("string") +LJLIB_PUSH("upval") +LJLIB_PUSH("thread") +LJLIB_PUSH("proto") +LJLIB_PUSH("function") +LJLIB_PUSH("trace") +LJLIB_PUSH("cdata") +LJLIB_PUSH("table") +LJLIB_PUSH(top-9) /* userdata */ +LJLIB_PUSH("number") +LJLIB_ASM_(type) LJLIB_REC(.) +/* Recycle the lj_lib_checkany(L, 1) from assert. */ + +/* -- Base library: getters and setters ----------------------------------- */ + +LJLIB_ASM_(getmetatable) LJLIB_REC(.) +/* Recycle the lj_lib_checkany(L, 1) from assert. */ + +LJLIB_ASM(setmetatable) LJLIB_REC(.) +{ + GCtab *t = lj_lib_checktab(L, 1); + GCtab *mt = lj_lib_checktabornil(L, 2); + if (!tvisnil(lj_meta_lookup(L, L->base, MM_metatable))) + lj_err_caller(L, LJ_ERR_PROTMT); + setgcref(t->metatable, obj2gco(mt)); + if (mt) { lj_gc_objbarriert(L, t, mt); } + settabV(L, L->base-1, t); + return FFH_RES(1); +} + +LJLIB_CF(getfenv) +{ + GCfunc *fn; + cTValue *o = L->base; + if (!(o < L->top && tvisfunc(o))) { + int level = lj_lib_optint(L, 1, 1); + o = lj_debug_frame(L, level, &level); + if (o == NULL) + lj_err_arg(L, 1, LJ_ERR_INVLVL); + } + fn = &gcval(o)->fn; + settabV(L, L->top++, isluafunc(fn) ? tabref(fn->l.env) : tabref(L->env)); + return 1; +} + +LJLIB_CF(setfenv) +{ + GCfunc *fn; + GCtab *t = lj_lib_checktab(L, 2); + cTValue *o = L->base; + if (!(o < L->top && tvisfunc(o))) { + int level = lj_lib_checkint(L, 1); + if (level == 0) { + /* NOBARRIER: A thread (i.e. L) is never black. */ + setgcref(L->env, obj2gco(t)); + return 0; + } + o = lj_debug_frame(L, level, &level); + if (o == NULL) + lj_err_arg(L, 1, LJ_ERR_INVLVL); + } + fn = &gcval(o)->fn; + if (!isluafunc(fn)) + lj_err_caller(L, LJ_ERR_SETFENV); + setgcref(fn->l.env, obj2gco(t)); + lj_gc_objbarrier(L, obj2gco(fn), t); + setfuncV(L, L->top++, fn); + return 1; +} + +LJLIB_ASM(rawget) LJLIB_REC(.) +{ + lj_lib_checktab(L, 1); + lj_lib_checkany(L, 2); + return FFH_UNREACHABLE; +} + +LJLIB_CF(rawset) LJLIB_REC(.) +{ + lj_lib_checktab(L, 1); + lj_lib_checkany(L, 2); + L->top = 1+lj_lib_checkany(L, 3); + lua_rawset(L, 1); + return 1; +} + +LJLIB_CF(rawequal) LJLIB_REC(.) +{ + cTValue *o1 = lj_lib_checkany(L, 1); + cTValue *o2 = lj_lib_checkany(L, 2); + setboolV(L->top-1, lj_obj_equal(o1, o2)); + return 1; +} + +LJLIB_CF(unpack) +{ + GCtab *t = lj_lib_checktab(L, 1); + int32_t n, i = lj_lib_optint(L, 2, 1); + int32_t e = (L->base+3-1 < L->top && !tvisnil(L->base+3-1)) ? + lj_lib_checkint(L, 3) : (int32_t)lj_tab_len(t); + if (i > e) return 0; + n = e - i + 1; + if (n <= 0 || !lua_checkstack(L, n)) + lj_err_caller(L, LJ_ERR_UNPACK); + do { + cTValue *tv = lj_tab_getint(t, i); + if (tv) { + copyTV(L, L->top++, tv); + } else { + setnilV(L->top++); + } + } while (i++ < e); + return n; +} + +LJLIB_CF(select) LJLIB_REC(.) +{ + int32_t n = (int32_t)(L->top - L->base); + if (n >= 1 && tvisstr(L->base) && *strVdata(L->base) == '#') { + setintV(L->top-1, n-1); + return 1; + } else { + int32_t i = lj_lib_checkint(L, 1); + if (i < 0) i = n + i; else if (i > n) i = n; + if (i < 1) + lj_err_arg(L, 1, LJ_ERR_IDXRNG); + return n - i; + } +} + +/* -- Base library: conversions ------------------------------------------- */ + +LJLIB_ASM(tonumber) LJLIB_REC(.) +{ + int32_t base = lj_lib_optint(L, 2, 10); + if (base == 10) { + TValue *o = lj_lib_checkany(L, 1); + if (tvisnumber(o) || (tvisstr(o) && lj_str_tonumber(strV(o), o))) { + copyTV(L, L->base-1, o); + return FFH_RES(1); + } +#if LJ_HASFFI + if (tviscdata(o)) { + CTState *cts = ctype_cts(L); + CType *ct = lj_ctype_rawref(cts, cdataV(o)->typeid); + if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct); + if (ctype_isnum(ct->info) || ctype_iscomplex(ct->info)) { + if (LJ_DUALNUM && ctype_isinteger_or_bool(ct->info) && + ct->size <= 4 && !(ct->size == 4 && (ct->info & CTF_UNSIGNED))) { + int32_t i; + lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, 0); + setintV(L->base-1, i); + return FFH_RES(1); + } + lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE), + (uint8_t *)&(L->base-1)->n, o, 0); + return FFH_RES(1); + } + } +#endif + } else { + const char *p = strdata(lj_lib_checkstr(L, 1)); + char *ep; + unsigned long ul; + if (base < 2 || base > 36) + lj_err_arg(L, 2, LJ_ERR_BASERNG); + ul = strtoul(p, &ep, base); + if (p != ep) { + while (lj_char_isspace((unsigned char)(*ep))) ep++; + if (*ep == '\0') { + if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u)) + setintV(L->base-1, (int32_t)ul); + else + setnumV(L->base-1, (lua_Number)ul); + return FFH_RES(1); + } + } + } + setnilV(L->base-1); + return FFH_RES(1); +} + +LJLIB_PUSH("nil") +LJLIB_PUSH("false") +LJLIB_PUSH("true") +LJLIB_ASM(tostring) LJLIB_REC(.) +{ + TValue *o = lj_lib_checkany(L, 1); + cTValue *mo; + L->top = o+1; /* Only keep one argument. */ + if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) { + copyTV(L, L->base-1, mo); /* Replace callable. */ + return FFH_TAILCALL; + } else { + GCstr *s; + if (tvisnumber(o)) { + s = lj_str_fromnumber(L, o); + } else if (tvispri(o)) { + s = strV(lj_lib_upvalue(L, -(int32_t)itype(o))); + } else { + if (tvisfunc(o) && isffunc(funcV(o))) + lua_pushfstring(L, "function: fast#%d", funcV(o)->c.ffid); + else + lua_pushfstring(L, "%s: %p", typename(o), lua_topointer(L, 1)); + /* Note: lua_pushfstring calls the GC which may invalidate o. */ + s = strV(L->top-1); + } + setstrV(L, L->base-1, s); + return FFH_RES(1); + } +} + +/* -- Base library: iterators --------------------------------------------- */ + +/* This solves a circular dependency problem -- change FF_next_N as needed. */ +LJ_STATIC_ASSERT((int)FF_next == FF_next_N); + +LJLIB_ASM(next) +{ + lj_lib_checktab(L, 1); + return FFH_UNREACHABLE; +} + +#ifdef LUAJIT_ENABLE_LUA52COMPAT +static int ffh_pairs(lua_State *L, MMS mm) +{ + TValue *o = lj_lib_checkany(L, 1); + cTValue *mo = lj_meta_lookup(L, o, mm); + if (!tvisnil(mo)) { + L->top = o+1; /* Only keep one argument. */ + copyTV(L, L->base-1, mo); /* Replace callable. */ + return FFH_TAILCALL; + } else { + if (!tvistab(o)) lj_err_argt(L, 1, LUA_TTABLE); + setfuncV(L, o-1, funcV(lj_lib_upvalue(L, 1))); + if (mm == MM_pairs) setnilV(o+1); else setintV(o+1, 0); + return FFH_RES(3); + } +} +#else +#define ffh_pairs(L, mm) (lj_lib_checktab(L, 1), FFH_UNREACHABLE) +#endif + +LJLIB_PUSH(lastcl) +LJLIB_ASM(pairs) +{ + return ffh_pairs(L, MM_pairs); +} + +LJLIB_NOREGUV LJLIB_ASM(ipairs_aux) LJLIB_REC(.) +{ + lj_lib_checktab(L, 1); + lj_lib_checkint(L, 2); + return FFH_UNREACHABLE; +} + +LJLIB_PUSH(lastcl) +LJLIB_ASM(ipairs) LJLIB_REC(.) +{ + return ffh_pairs(L, MM_ipairs); +} + +/* -- Base library: throw and catch errors -------------------------------- */ + +LJLIB_CF(error) +{ + int32_t level = lj_lib_optint(L, 2, 1); + lua_settop(L, 1); + if (lua_isstring(L, 1) && level > 0) { + luaL_where(L, level); + lua_pushvalue(L, 1); + lua_concat(L, 2); + } + return lua_error(L); +} + +LJLIB_ASM(pcall) LJLIB_REC(.) +{ + lj_lib_checkany(L, 1); + lj_lib_checkfunc(L, 2); /* For xpcall only. */ + return FFH_UNREACHABLE; +} +LJLIB_ASM_(xpcall) LJLIB_REC(.) + +/* -- Base library: load Lua code ----------------------------------------- */ + +static int load_aux(lua_State *L, int status) +{ + if (status == 0) + return 1; + copyTV(L, L->top, L->top-1); + setnilV(L->top-1); + L->top++; + return 2; +} + +LJLIB_CF(loadstring) +{ + GCstr *s = lj_lib_checkstr(L, 1); + GCstr *name = lj_lib_optstr(L, 2); + return load_aux(L, + luaL_loadbuffer(L, strdata(s), s->len, strdata(name ? name : s))); +} + +LJLIB_CF(loadfile) +{ + GCstr *fname = lj_lib_optstr(L, 1); + return load_aux(L, luaL_loadfile(L, fname ? strdata(fname) : NULL)); +} + +static const char *reader_func(lua_State *L, void *ud, size_t *size) +{ + UNUSED(ud); + luaL_checkstack(L, 2, "too many nested functions"); + copyTV(L, L->top++, L->base); + lua_call(L, 0, 1); /* Call user-supplied function. */ + L->top--; + if (tvisnil(L->top)) { + *size = 0; + return NULL; + } else if (tvisstr(L->top) || tvisnumber(L->top)) { + copyTV(L, L->base+2, L->top); /* Anchor string in reserved stack slot. */ + return lua_tolstring(L, 3, size); + } else { + lj_err_caller(L, LJ_ERR_RDRSTR); + return NULL; + } +} + +LJLIB_CF(load) +{ + GCstr *name; + if (L->base < L->top && (tvisstr(L->base) || tvisnumber(L->base))) + return lj_cf_loadstring(L); + lj_lib_checkfunc(L, 1); + name = lj_lib_optstr(L, 2); + lua_settop(L, 3); /* Reserve a slot for the string from the reader. */ + return load_aux(L, + lua_load(L, reader_func, NULL, name ? strdata(name) : "=(load)")); +} + +LJLIB_CF(dofile) +{ + GCstr *fname = lj_lib_optstr(L, 1); + setnilV(L->top); + L->top = L->base+1; + if (luaL_loadfile(L, fname ? strdata(fname) : NULL) != 0) + lua_error(L); + lua_call(L, 0, LUA_MULTRET); + return (int)(L->top - L->base) - 1; +} + +/* -- Base library: GC control -------------------------------------------- */ + +LJLIB_CF(gcinfo) +{ + setintV(L->top++, (G(L)->gc.total >> 10)); + return 1; +} + +LJLIB_CF(collectgarbage) +{ + int opt = lj_lib_checkopt(L, 1, LUA_GCCOLLECT, /* ORDER LUA_GC* */ + "\4stop\7restart\7collect\5count\1\377\4step\10setpause\12setstepmul"); + int32_t data = lj_lib_optint(L, 2, 0); + if (opt == LUA_GCCOUNT) { + setnumV(L->top, (lua_Number)G(L)->gc.total/1024.0); + } else { + int res = lua_gc(L, opt, data); + if (opt == LUA_GCSTEP) + setboolV(L->top, res); + else + setintV(L->top, res); + } + L->top++; + return 1; +} + +/* -- Base library: miscellaneous functions ------------------------------- */ + +LJLIB_PUSH(top-2) /* Upvalue holds weak table. */ +LJLIB_CF(newproxy) +{ + lua_settop(L, 1); + lua_newuserdata(L, 0); + if (lua_toboolean(L, 1) == 0) { /* newproxy(): without metatable. */ + return 1; + } else if (lua_isboolean(L, 1)) { /* newproxy(true): with metatable. */ + lua_newtable(L); + lua_pushvalue(L, -1); + lua_pushboolean(L, 1); + lua_rawset(L, lua_upvalueindex(1)); /* Remember mt in weak table. */ + } else { /* newproxy(proxy): inherit metatable. */ + int validproxy = 0; + if (lua_getmetatable(L, 1)) { + lua_rawget(L, lua_upvalueindex(1)); + validproxy = lua_toboolean(L, -1); + lua_pop(L, 1); + } + if (!validproxy) + lj_err_arg(L, 1, LJ_ERR_NOPROXY); + lua_getmetatable(L, 1); + } + lua_setmetatable(L, 2); + return 1; +} + +LJLIB_PUSH("tostring") +LJLIB_CF(print) +{ + ptrdiff_t i, nargs = L->top - L->base; + cTValue *tv = lj_tab_getstr(tabref(L->env), strV(lj_lib_upvalue(L, 1))); + int shortcut; + if (tv && !tvisnil(tv)) { + copyTV(L, L->top++, tv); + } else { + setstrV(L, L->top++, strV(lj_lib_upvalue(L, 1))); + lua_gettable(L, LUA_GLOBALSINDEX); + tv = L->top-1; + } + shortcut = (tvisfunc(tv) && funcV(tv)->c.ffid == FF_tostring); + for (i = 0; i < nargs; i++) { + const char *str; + size_t size; + cTValue *o = &L->base[i]; + if (shortcut && tvisstr(o)) { + str = strVdata(o); + size = strV(o)->len; + } else if (shortcut && tvisint(o)) { + char buf[LJ_STR_INTBUF]; + char *p = lj_str_bufint(buf, intV(o)); + size = (size_t)(buf+LJ_STR_INTBUF-p); + str = p; + } else if (shortcut && tvisnum(o)) { + char buf[LJ_STR_NUMBUF]; + size = lj_str_bufnum(buf, o); + str = buf; + } else { + copyTV(L, L->top+1, o); + copyTV(L, L->top, L->top-1); + L->top += 2; + lua_call(L, 1, 1); + str = lua_tolstring(L, -1, &size); + if (!str) + lj_err_caller(L, LJ_ERR_PRTOSTR); + L->top--; + } + if (i) + putchar('\t'); + fwrite(str, 1, size, stdout); + } + putchar('\n'); + return 0; +} + +LJLIB_PUSH(top-3) +LJLIB_SET(_VERSION) + +#include "lj_libdef.h" + +/* -- Coroutine library --------------------------------------------------- */ + +#define LJLIB_MODULE_coroutine + +LJLIB_CF(coroutine_status) +{ + const char *s; + lua_State *co; + if (!(L->top > L->base && tvisthread(L->base))) + lj_err_arg(L, 1, LJ_ERR_NOCORO); + co = threadV(L->base); + if (co == L) s = "running"; + else if (co->status == LUA_YIELD) s = "suspended"; + else if (co->status != 0) s = "dead"; + else if (co->base > tvref(co->stack)+1) s = "normal"; + else if (co->top == co->base) s = "dead"; + else s = "suspended"; + lua_pushstring(L, s); + return 1; +} + +LJLIB_CF(coroutine_running) +{ +#ifdef LUAJIT_ENABLE_LUA52COMPAT + int ismain = lua_pushthread(L); + setboolV(L->top++, ismain); + return 2; +#else + if (lua_pushthread(L)) + setnilV(L->top++); + return 1; +#endif +} + +LJLIB_CF(coroutine_create) +{ + lua_State *L1 = lua_newthread(L); + if (!(L->base < L->top && tvisfunc(L->base))) + lj_err_argt(L, 1, LUA_TFUNCTION); + setfuncV(L, L1->top++, funcV(L->base)); + return 1; +} + +LJLIB_ASM(coroutine_yield) +{ + lj_err_caller(L, LJ_ERR_CYIELD); + return FFH_UNREACHABLE; +} + +static int ffh_resume(lua_State *L, lua_State *co, int wrap) +{ + if (co->cframe != NULL || co->status > LUA_YIELD || + (co->status == 0 && co->top == co->base)) { + ErrMsg em = co->cframe ? LJ_ERR_CORUN : LJ_ERR_CODEAD; + if (wrap) lj_err_caller(L, em); + setboolV(L->base-1, 0); + setstrV(L, L->base, lj_err_str(L, em)); + return FFH_RES(2); + } + lj_state_growstack(co, (MSize)(L->top - L->base)); + return FFH_RETRY; +} + +LJLIB_ASM(coroutine_resume) +{ + if (!(L->top > L->base && tvisthread(L->base))) + lj_err_arg(L, 1, LJ_ERR_NOCORO); + return ffh_resume(L, threadV(L->base), 0); +} + +LJLIB_NOREG LJLIB_ASM(coroutine_wrap_aux) +{ + return ffh_resume(L, threadV(lj_lib_upvalue(L, 1)), 1); +} + +/* Inline declarations. */ +LJ_ASMF void lj_ff_coroutine_wrap_aux(void); +LJ_FUNCA_NORET void LJ_FASTCALL lj_ffh_coroutine_wrap_err(lua_State *L, + lua_State *co); + +/* Error handler, called from assembler VM. */ +void LJ_FASTCALL lj_ffh_coroutine_wrap_err(lua_State *L, lua_State *co) +{ + co->top--; copyTV(L, L->top, co->top); L->top++; + if (tvisstr(L->top-1)) + lj_err_callermsg(L, strVdata(L->top-1)); + else + lj_err_run(L); +} + +/* Forward declaration. */ +static void setpc_wrap_aux(lua_State *L, GCfunc *fn); + +LJLIB_CF(coroutine_wrap) +{ + lj_cf_coroutine_create(L); + lj_lib_pushcc(L, lj_ffh_coroutine_wrap_aux, FF_coroutine_wrap_aux, 1); + setpc_wrap_aux(L, funcV(L->top-1)); + return 1; +} + +#include "lj_libdef.h" + +/* Fix the PC of wrap_aux. Really ugly workaround. */ +static void setpc_wrap_aux(lua_State *L, GCfunc *fn) +{ + setmref(fn->c.pc, &L2GG(L)->bcff[lj_lib_init_coroutine[1]+2]); +} + +/* ------------------------------------------------------------------------ */ + +static void newproxy_weaktable(lua_State *L) +{ + /* NOBARRIER: The table is new (marked white). */ + GCtab *t = lj_tab_new(L, 0, 1); + settabV(L, L->top++, t); + setgcref(t->metatable, obj2gco(t)); + setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "__mode")), + lj_str_newlit(L, "kv")); + t->nomm = (uint8_t)(~(1u<env); + settabV(L, lj_tab_setstr(L, env, lj_str_newlit(L, "_G")), env); + lua_pushliteral(L, LUA_VERSION); /* top-3. */ + newproxy_weaktable(L); /* top-2. */ + LJ_LIB_REG(L, "_G", base); + LJ_LIB_REG(L, LUA_COLIBNAME, coroutine); + return 2; +} + -- cgit v1.1