You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2015/07/23 13:14:29 UTC
[32/43] trafficserver git commit: TS-3783 TS-3030 Add luajit v2.0.4
as a subtree
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1f27b840/lib/luajit/src/lib_base.c
----------------------------------------------------------------------
diff --git a/lib/luajit/src/lib_base.c b/lib/luajit/src/lib_base.c
new file mode 100644
index 0000000..17b9525
--- /dev/null
+++ b/lib/luajit/src/lib_base.c
@@ -0,0 +1,683 @@
+/*
+** Base and coroutine library.
+** Copyright (C) 2005-2015 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 <stdio.h>
+
+#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_strscan.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: 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;
+}
+
+#if LJ_52 || LJ_HASFFI
+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 ((LJ_52 || tviscdata(o)) && !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: 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;
+}
+
+#if LJ_52
+LJLIB_CF(rawlen) LJLIB_REC(.)
+{
+ cTValue *o = L->base;
+ int32_t len;
+ if (L->top > o && tvisstr(o))
+ len = (int32_t)strV(o)->len;
+ else
+ len = (int32_t)lj_tab_len(lj_lib_checktab(L, 1));
+ setintV(L->top-1, len);
+ return 1;
+}
+#endif
+
+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 (lj_strscan_numberobj(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)->ctypeid);
+ 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: builtin#%d", funcV(o)->c.ffid);
+ else
+ lua_pushfstring(L, "%s: %p", lj_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: 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, int envarg)
+{
+ if (status == 0) {
+ if (tvistab(L->base+envarg-1)) {
+ GCfunc *fn = funcV(L->top-1);
+ GCtab *t = tabV(L->base+envarg-1);
+ setgcref(fn->c.env, obj2gco(t));
+ lj_gc_objbarrier(L, fn, t);
+ }
+ return 1;
+ } else {
+ setnilV(L->top-2);
+ return 2;
+ }
+}
+
+LJLIB_CF(loadfile)
+{
+ GCstr *fname = lj_lib_optstr(L, 1);
+ GCstr *mode = lj_lib_optstr(L, 2);
+ int status;
+ lua_settop(L, 3); /* Ensure env arg exists. */
+ status = luaL_loadfilex(L, fname ? strdata(fname) : NULL,
+ mode ? strdata(mode) : NULL);
+ return load_aux(L, status, 3);
+}
+
+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+4, L->top); /* Anchor string in reserved stack slot. */
+ return lua_tolstring(L, 5, size);
+ } else {
+ lj_err_caller(L, LJ_ERR_RDRSTR);
+ return NULL;
+ }
+}
+
+LJLIB_CF(load)
+{
+ GCstr *name = lj_lib_optstr(L, 2);
+ GCstr *mode = lj_lib_optstr(L, 3);
+ int status;
+ if (L->base < L->top && (tvisstr(L->base) || tvisnumber(L->base))) {
+ GCstr *s = lj_lib_checkstr(L, 1);
+ lua_settop(L, 4); /* Ensure env arg exists. */
+ status = luaL_loadbufferx(L, strdata(s), s->len, strdata(name ? name : s),
+ mode ? strdata(mode) : NULL);
+ } else {
+ lj_lib_checkfunc(L, 1);
+ lua_settop(L, 5); /* Reserve a slot for the string from the reader. */
+ status = lua_loadx(L, reader_func, NULL, name ? strdata(name) : "=(load)",
+ mode ? strdata(mode) : NULL);
+ }
+ return load_aux(L, status, 4);
+}
+
+LJLIB_CF(loadstring)
+{
+ return lj_cf_load(L);
+}
+
+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)
+{
+#if LJ_52
+ 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;
+ if (!(L->base < L->top && tvisfunc(L->base)))
+ lj_err_argt(L, 1, LUA_TFUNCTION);
+ L1 = lua_newthread(L);
+ 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);
+#if !(LJ_TARGET_MIPS && defined(ljamalg_c))
+LJ_FUNCA_NORET void LJ_FASTCALL lj_ffh_coroutine_wrap_err(lua_State *L,
+ lua_State *co);
+#endif
+
+/* 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<<MM_mode));
+}
+
+LUALIB_API int luaopen_base(lua_State *L)
+{
+ /* NOBARRIER: Table and value are the same. */
+ GCtab *env = tabref(L->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;
+}
+
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1f27b840/lib/luajit/src/lib_bit.c
----------------------------------------------------------------------
diff --git a/lib/luajit/src/lib_bit.c b/lib/luajit/src/lib_bit.c
new file mode 100644
index 0000000..583e04b
--- /dev/null
+++ b/lib/luajit/src/lib_bit.c
@@ -0,0 +1,74 @@
+/*
+** Bit manipulation library.
+** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
+*/
+
+#define lib_bit_c
+#define LUA_LIB
+
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+
+#include "lj_obj.h"
+#include "lj_err.h"
+#include "lj_str.h"
+#include "lj_lib.h"
+
+/* ------------------------------------------------------------------------ */
+
+#define LJLIB_MODULE_bit
+
+LJLIB_ASM(bit_tobit) LJLIB_REC(bit_unary IR_TOBIT)
+{
+ lj_lib_checknumber(L, 1);
+ return FFH_RETRY;
+}
+LJLIB_ASM_(bit_bnot) LJLIB_REC(bit_unary IR_BNOT)
+LJLIB_ASM_(bit_bswap) LJLIB_REC(bit_unary IR_BSWAP)
+
+LJLIB_ASM(bit_lshift) LJLIB_REC(bit_shift IR_BSHL)
+{
+ lj_lib_checknumber(L, 1);
+ lj_lib_checkbit(L, 2);
+ return FFH_RETRY;
+}
+LJLIB_ASM_(bit_rshift) LJLIB_REC(bit_shift IR_BSHR)
+LJLIB_ASM_(bit_arshift) LJLIB_REC(bit_shift IR_BSAR)
+LJLIB_ASM_(bit_rol) LJLIB_REC(bit_shift IR_BROL)
+LJLIB_ASM_(bit_ror) LJLIB_REC(bit_shift IR_BROR)
+
+LJLIB_ASM(bit_band) LJLIB_REC(bit_nary IR_BAND)
+{
+ int i = 0;
+ do { lj_lib_checknumber(L, ++i); } while (L->base+i < L->top);
+ return FFH_RETRY;
+}
+LJLIB_ASM_(bit_bor) LJLIB_REC(bit_nary IR_BOR)
+LJLIB_ASM_(bit_bxor) LJLIB_REC(bit_nary IR_BXOR)
+
+/* ------------------------------------------------------------------------ */
+
+LJLIB_CF(bit_tohex)
+{
+ uint32_t b = (uint32_t)lj_lib_checkbit(L, 1);
+ int32_t i, n = L->base+1 >= L->top ? 8 : lj_lib_checkbit(L, 2);
+ const char *hexdigits = "0123456789abcdef";
+ char buf[8];
+ if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; }
+ if (n > 8) n = 8;
+ for (i = n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; }
+ lua_pushlstring(L, buf, (size_t)n);
+ return 1;
+}
+
+/* ------------------------------------------------------------------------ */
+
+#include "lj_libdef.h"
+
+LUALIB_API int luaopen_bit(lua_State *L)
+{
+ LJ_LIB_REG(L, LUA_BITLIBNAME, bit);
+ return 1;
+}
+
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1f27b840/lib/luajit/src/lib_debug.c
----------------------------------------------------------------------
diff --git a/lib/luajit/src/lib_debug.c b/lib/luajit/src/lib_debug.c
new file mode 100644
index 0000000..e87c35c
--- /dev/null
+++ b/lib/luajit/src/lib_debug.c
@@ -0,0 +1,405 @@
+/*
+** Debug library.
+** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
+**
+** Major portions taken verbatim or adapted from the Lua interpreter.
+** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
+*/
+
+#define lib_debug_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_lib.h"
+
+/* ------------------------------------------------------------------------ */
+
+#define LJLIB_MODULE_debug
+
+LJLIB_CF(debug_getregistry)
+{
+ copyTV(L, L->top++, registry(L));
+ return 1;
+}
+
+LJLIB_CF(debug_getmetatable)
+{
+ lj_lib_checkany(L, 1);
+ if (!lua_getmetatable(L, 1)) {
+ setnilV(L->top-1);
+ }
+ return 1;
+}
+
+LJLIB_CF(debug_setmetatable)
+{
+ lj_lib_checktabornil(L, 2);
+ L->top = L->base+2;
+ lua_setmetatable(L, 1);
+#if !LJ_52
+ setboolV(L->top-1, 1);
+#endif
+ return 1;
+}
+
+LJLIB_CF(debug_getfenv)
+{
+ lj_lib_checkany(L, 1);
+ lua_getfenv(L, 1);
+ return 1;
+}
+
+LJLIB_CF(debug_setfenv)
+{
+ lj_lib_checktab(L, 2);
+ L->top = L->base+2;
+ if (!lua_setfenv(L, 1))
+ lj_err_caller(L, LJ_ERR_SETFENV);
+ return 1;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void settabss(lua_State *L, const char *i, const char *v)
+{
+ lua_pushstring(L, v);
+ lua_setfield(L, -2, i);
+}
+
+static void settabsi(lua_State *L, const char *i, int v)
+{
+ lua_pushinteger(L, v);
+ lua_setfield(L, -2, i);
+}
+
+static void settabsb(lua_State *L, const char *i, int v)
+{
+ lua_pushboolean(L, v);
+ lua_setfield(L, -2, i);
+}
+
+static lua_State *getthread(lua_State *L, int *arg)
+{
+ if (L->base < L->top && tvisthread(L->base)) {
+ *arg = 1;
+ return threadV(L->base);
+ } else {
+ *arg = 0;
+ return L;
+ }
+}
+
+static void treatstackoption(lua_State *L, lua_State *L1, const char *fname)
+{
+ if (L == L1) {
+ lua_pushvalue(L, -2);
+ lua_remove(L, -3);
+ }
+ else
+ lua_xmove(L1, L, 1);
+ lua_setfield(L, -2, fname);
+}
+
+LJLIB_CF(debug_getinfo)
+{
+ lj_Debug ar;
+ int arg, opt_f = 0, opt_L = 0;
+ lua_State *L1 = getthread(L, &arg);
+ const char *options = luaL_optstring(L, arg+2, "flnSu");
+ if (lua_isnumber(L, arg+1)) {
+ if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), (lua_Debug *)&ar)) {
+ setnilV(L->top-1);
+ return 1;
+ }
+ } else if (L->base+arg < L->top && tvisfunc(L->base+arg)) {
+ options = lua_pushfstring(L, ">%s", options);
+ setfuncV(L1, L1->top++, funcV(L->base+arg));
+ } else {
+ lj_err_arg(L, arg+1, LJ_ERR_NOFUNCL);
+ }
+ if (!lj_debug_getinfo(L1, options, &ar, 1))
+ lj_err_arg(L, arg+2, LJ_ERR_INVOPT);
+ lua_createtable(L, 0, 16); /* Create result table. */
+ for (; *options; options++) {
+ switch (*options) {
+ case 'S':
+ settabss(L, "source", ar.source);
+ settabss(L, "short_src", ar.short_src);
+ settabsi(L, "linedefined", ar.linedefined);
+ settabsi(L, "lastlinedefined", ar.lastlinedefined);
+ settabss(L, "what", ar.what);
+ break;
+ case 'l':
+ settabsi(L, "currentline", ar.currentline);
+ break;
+ case 'u':
+ settabsi(L, "nups", ar.nups);
+ settabsi(L, "nparams", ar.nparams);
+ settabsb(L, "isvararg", ar.isvararg);
+ break;
+ case 'n':
+ settabss(L, "name", ar.name);
+ settabss(L, "namewhat", ar.namewhat);
+ break;
+ case 'f': opt_f = 1; break;
+ case 'L': opt_L = 1; break;
+ default: break;
+ }
+ }
+ if (opt_L) treatstackoption(L, L1, "activelines");
+ if (opt_f) treatstackoption(L, L1, "func");
+ return 1; /* Return result table. */
+}
+
+LJLIB_CF(debug_getlocal)
+{
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ lua_Debug ar;
+ const char *name;
+ int slot = lj_lib_checkint(L, arg+2);
+ if (tvisfunc(L->base+arg)) {
+ L->top = L->base+arg+1;
+ lua_pushstring(L, lua_getlocal(L, NULL, slot));
+ return 1;
+ }
+ if (!lua_getstack(L1, lj_lib_checkint(L, arg+1), &ar))
+ lj_err_arg(L, arg+1, LJ_ERR_LVLRNG);
+ name = lua_getlocal(L1, &ar, slot);
+ if (name) {
+ lua_xmove(L1, L, 1);
+ lua_pushstring(L, name);
+ lua_pushvalue(L, -2);
+ return 2;
+ } else {
+ setnilV(L->top-1);
+ return 1;
+ }
+}
+
+LJLIB_CF(debug_setlocal)
+{
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ lua_Debug ar;
+ TValue *tv;
+ if (!lua_getstack(L1, lj_lib_checkint(L, arg+1), &ar))
+ lj_err_arg(L, arg+1, LJ_ERR_LVLRNG);
+ tv = lj_lib_checkany(L, arg+3);
+ copyTV(L1, L1->top++, tv);
+ lua_pushstring(L, lua_setlocal(L1, &ar, lj_lib_checkint(L, arg+2)));
+ return 1;
+}
+
+static int debug_getupvalue(lua_State *L, int get)
+{
+ int32_t n = lj_lib_checkint(L, 2);
+ const char *name;
+ lj_lib_checkfunc(L, 1);
+ name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
+ if (name) {
+ lua_pushstring(L, name);
+ if (!get) return 1;
+ copyTV(L, L->top, L->top-2);
+ L->top++;
+ return 2;
+ }
+ return 0;
+}
+
+LJLIB_CF(debug_getupvalue)
+{
+ return debug_getupvalue(L, 1);
+}
+
+LJLIB_CF(debug_setupvalue)
+{
+ lj_lib_checkany(L, 3);
+ return debug_getupvalue(L, 0);
+}
+
+LJLIB_CF(debug_upvalueid)
+{
+ GCfunc *fn = lj_lib_checkfunc(L, 1);
+ int32_t n = lj_lib_checkint(L, 2) - 1;
+ if ((uint32_t)n >= fn->l.nupvalues)
+ lj_err_arg(L, 2, LJ_ERR_IDXRNG);
+ setlightudV(L->top-1, isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) :
+ (void *)&fn->c.upvalue[n]);
+ return 1;
+}
+
+LJLIB_CF(debug_upvaluejoin)
+{
+ GCfunc *fn[2];
+ GCRef *p[2];
+ int i;
+ for (i = 0; i < 2; i++) {
+ int32_t n;
+ fn[i] = lj_lib_checkfunc(L, 2*i+1);
+ if (!isluafunc(fn[i]))
+ lj_err_arg(L, 2*i+1, LJ_ERR_NOLFUNC);
+ n = lj_lib_checkint(L, 2*i+2) - 1;
+ if ((uint32_t)n >= fn[i]->l.nupvalues)
+ lj_err_arg(L, 2*i+2, LJ_ERR_IDXRNG);
+ p[i] = &fn[i]->l.uvptr[n];
+ }
+ setgcrefr(*p[0], *p[1]);
+ lj_gc_objbarrier(L, fn[0], gcref(*p[1]));
+ return 0;
+}
+
+#if LJ_52
+LJLIB_CF(debug_getuservalue)
+{
+ TValue *o = L->base;
+ if (o < L->top && tvisudata(o))
+ settabV(L, o, tabref(udataV(o)->env));
+ else
+ setnilV(o);
+ L->top = o+1;
+ return 1;
+}
+
+LJLIB_CF(debug_setuservalue)
+{
+ TValue *o = L->base;
+ if (!(o < L->top && tvisudata(o)))
+ lj_err_argt(L, 1, LUA_TUSERDATA);
+ if (!(o+1 < L->top && tvistab(o+1)))
+ lj_err_argt(L, 2, LUA_TTABLE);
+ L->top = o+2;
+ lua_setfenv(L, 1);
+ return 1;
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static const char KEY_HOOK = 'h';
+
+static void hookf(lua_State *L, lua_Debug *ar)
+{
+ static const char *const hooknames[] =
+ {"call", "return", "line", "count", "tail return"};
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ if (lua_isfunction(L, -1)) {
+ lua_pushstring(L, hooknames[(int)ar->event]);
+ if (ar->currentline >= 0)
+ lua_pushinteger(L, ar->currentline);
+ else lua_pushnil(L);
+ lua_call(L, 2, 0);
+ }
+}
+
+static int makemask(const char *smask, int count)
+{
+ int mask = 0;
+ if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
+ if (strchr(smask, 'r')) mask |= LUA_MASKRET;
+ if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
+ if (count > 0) mask |= LUA_MASKCOUNT;
+ return mask;
+}
+
+static char *unmakemask(int mask, char *smask)
+{
+ int i = 0;
+ if (mask & LUA_MASKCALL) smask[i++] = 'c';
+ if (mask & LUA_MASKRET) smask[i++] = 'r';
+ if (mask & LUA_MASKLINE) smask[i++] = 'l';
+ smask[i] = '\0';
+ return smask;
+}
+
+LJLIB_CF(debug_sethook)
+{
+ int arg, mask, count;
+ lua_Hook func;
+ (void)getthread(L, &arg);
+ if (lua_isnoneornil(L, arg+1)) {
+ lua_settop(L, arg+1);
+ func = NULL; mask = 0; count = 0; /* turn off hooks */
+ } else {
+ const char *smask = luaL_checkstring(L, arg+2);
+ luaL_checktype(L, arg+1, LUA_TFUNCTION);
+ count = luaL_optint(L, arg+3, 0);
+ func = hookf; mask = makemask(smask, count);
+ }
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_pushvalue(L, arg+1);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+ lua_sethook(L, func, mask, count);
+ return 0;
+}
+
+LJLIB_CF(debug_gethook)
+{
+ char buff[5];
+ int mask = lua_gethookmask(L);
+ lua_Hook hook = lua_gethook(L);
+ if (hook != NULL && hook != hookf) { /* external hook? */
+ lua_pushliteral(L, "external hook");
+ } else {
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */
+ }
+ lua_pushstring(L, unmakemask(mask, buff));
+ lua_pushinteger(L, lua_gethookcount(L));
+ return 3;
+}
+
+/* ------------------------------------------------------------------------ */
+
+LJLIB_CF(debug_debug)
+{
+ for (;;) {
+ char buffer[250];
+ fputs("lua_debug> ", stderr);
+ if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
+ strcmp(buffer, "cont\n") == 0)
+ return 0;
+ if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
+ lua_pcall(L, 0, 0, 0)) {
+ fputs(lua_tostring(L, -1), stderr);
+ fputs("\n", stderr);
+ }
+ lua_settop(L, 0); /* remove eventual returns */
+ }
+}
+
+/* ------------------------------------------------------------------------ */
+
+#define LEVELS1 12 /* size of the first part of the stack */
+#define LEVELS2 10 /* size of the second part of the stack */
+
+LJLIB_CF(debug_traceback)
+{
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ const char *msg = lua_tostring(L, arg+1);
+ if (msg == NULL && L->top > L->base+arg)
+ L->top = L->base+arg+1;
+ else
+ luaL_traceback(L, L1, msg, lj_lib_optint(L, arg+2, (L == L1)));
+ return 1;
+}
+
+/* ------------------------------------------------------------------------ */
+
+#include "lj_libdef.h"
+
+LUALIB_API int luaopen_debug(lua_State *L)
+{
+ LJ_LIB_REG(L, LUA_DBLIBNAME, debug);
+ return 1;
+}
+
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1f27b840/lib/luajit/src/lib_ffi.c
----------------------------------------------------------------------
diff --git a/lib/luajit/src/lib_ffi.c b/lib/luajit/src/lib_ffi.c
new file mode 100644
index 0000000..f6df39d
--- /dev/null
+++ b/lib/luajit/src/lib_ffi.c
@@ -0,0 +1,851 @@
+/*
+** FFI library.
+** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
+*/
+
+#define lib_ffi_c
+#define LUA_LIB
+
+#include <errno.h>
+
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+
+#include "lj_obj.h"
+
+#if LJ_HASFFI
+
+#include "lj_gc.h"
+#include "lj_err.h"
+#include "lj_str.h"
+#include "lj_tab.h"
+#include "lj_meta.h"
+#include "lj_ctype.h"
+#include "lj_cparse.h"
+#include "lj_cdata.h"
+#include "lj_cconv.h"
+#include "lj_carith.h"
+#include "lj_ccall.h"
+#include "lj_ccallback.h"
+#include "lj_clib.h"
+#include "lj_ff.h"
+#include "lj_lib.h"
+
+/* -- C type checks ------------------------------------------------------- */
+
+/* Check first argument for a C type and returns its ID. */
+static CTypeID ffi_checkctype(lua_State *L, CTState *cts, TValue *param)
+{
+ TValue *o = L->base;
+ if (!(o < L->top)) {
+ err_argtype:
+ lj_err_argtype(L, 1, "C type");
+ }
+ if (tvisstr(o)) { /* Parse an abstract C type declaration. */
+ GCstr *s = strV(o);
+ CPState cp;
+ int errcode;
+ cp.L = L;
+ cp.cts = cts;
+ cp.srcname = strdata(s);
+ cp.p = strdata(s);
+ cp.param = param;
+ cp.mode = CPARSE_MODE_ABSTRACT|CPARSE_MODE_NOIMPLICIT;
+ errcode = lj_cparse(&cp);
+ if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */
+ return cp.val.id;
+ } else {
+ GCcdata *cd;
+ if (!tviscdata(o)) goto err_argtype;
+ if (param && param < L->top) lj_err_arg(L, 1, LJ_ERR_FFI_NUMPARAM);
+ cd = cdataV(o);
+ return cd->ctypeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) : cd->ctypeid;
+ }
+}
+
+/* Check argument for C data and return it. */
+static GCcdata *ffi_checkcdata(lua_State *L, int narg)
+{
+ TValue *o = L->base + narg-1;
+ if (!(o < L->top && tviscdata(o)))
+ lj_err_argt(L, narg, LUA_TCDATA);
+ return cdataV(o);
+}
+
+/* Convert argument to C pointer. */
+static void *ffi_checkptr(lua_State *L, int narg, CTypeID id)
+{
+ CTState *cts = ctype_cts(L);
+ TValue *o = L->base + narg-1;
+ void *p;
+ if (o >= L->top)
+ lj_err_arg(L, narg, LJ_ERR_NOVAL);
+ lj_cconv_ct_tv(cts, ctype_get(cts, id), (uint8_t *)&p, o, CCF_ARG(narg));
+ return p;
+}
+
+/* Convert argument to int32_t. */
+static int32_t ffi_checkint(lua_State *L, int narg)
+{
+ CTState *cts = ctype_cts(L);
+ TValue *o = L->base + narg-1;
+ int32_t i;
+ if (o >= L->top)
+ lj_err_arg(L, narg, LJ_ERR_NOVAL);
+ lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o,
+ CCF_ARG(narg));
+ return i;
+}
+
+/* -- C type metamethods -------------------------------------------------- */
+
+#define LJLIB_MODULE_ffi_meta
+
+/* Handle ctype __index/__newindex metamethods. */
+static int ffi_index_meta(lua_State *L, CTState *cts, CType *ct, MMS mm)
+{
+ CTypeID id = ctype_typeid(cts, ct);
+ cTValue *tv = lj_ctype_meta(cts, id, mm);
+ TValue *base = L->base;
+ if (!tv) {
+ const char *s;
+ err_index:
+ s = strdata(lj_ctype_repr(L, id, NULL));
+ if (tvisstr(L->base+1)) {
+ lj_err_callerv(L, LJ_ERR_FFI_BADMEMBER, s, strVdata(L->base+1));
+ } else {
+ const char *key = tviscdata(L->base+1) ?
+ strdata(lj_ctype_repr(L, cdataV(L->base+1)->ctypeid, NULL)) :
+ lj_typename(L->base+1);
+ lj_err_callerv(L, LJ_ERR_FFI_BADIDXW, s, key);
+ }
+ }
+ if (!tvisfunc(tv)) {
+ if (mm == MM_index) {
+ cTValue *o = lj_meta_tget(L, tv, base+1);
+ if (o) {
+ if (tvisnil(o)) goto err_index;
+ copyTV(L, L->top-1, o);
+ return 1;
+ }
+ } else {
+ TValue *o = lj_meta_tset(L, tv, base+1);
+ if (o) {
+ copyTV(L, o, base+2);
+ return 0;
+ }
+ }
+ copyTV(L, base, L->top);
+ tv = L->top-1;
+ }
+ return lj_meta_tailcall(L, tv);
+}
+
+LJLIB_CF(ffi_meta___index) LJLIB_REC(cdata_index 0)
+{
+ CTState *cts = ctype_cts(L);
+ CTInfo qual = 0;
+ CType *ct;
+ uint8_t *p;
+ TValue *o = L->base;
+ if (!(o+1 < L->top && tviscdata(o))) /* Also checks for presence of key. */
+ lj_err_argt(L, 1, LUA_TCDATA);
+ ct = lj_cdata_index(cts, cdataV(o), o+1, &p, &qual);
+ if ((qual & 1))
+ return ffi_index_meta(L, cts, ct, MM_index);
+ if (lj_cdata_get(cts, ct, L->top-1, p))
+ lj_gc_check(L);
+ return 1;
+}
+
+LJLIB_CF(ffi_meta___newindex) LJLIB_REC(cdata_index 1)
+{
+ CTState *cts = ctype_cts(L);
+ CTInfo qual = 0;
+ CType *ct;
+ uint8_t *p;
+ TValue *o = L->base;
+ if (!(o+2 < L->top && tviscdata(o))) /* Also checks for key and value. */
+ lj_err_argt(L, 1, LUA_TCDATA);
+ ct = lj_cdata_index(cts, cdataV(o), o+1, &p, &qual);
+ if ((qual & 1)) {
+ if ((qual & CTF_CONST))
+ lj_err_caller(L, LJ_ERR_FFI_WRCONST);
+ return ffi_index_meta(L, cts, ct, MM_newindex);
+ }
+ lj_cdata_set(cts, ct, p, o+2, qual);
+ return 0;
+}
+
+/* Common handler for cdata arithmetic. */
+static int ffi_arith(lua_State *L)
+{
+ MMS mm = (MMS)(curr_func(L)->c.ffid - (int)FF_ffi_meta___eq + (int)MM_eq);
+ return lj_carith_op(L, mm);
+}
+
+/* The following functions must be in contiguous ORDER MM. */
+LJLIB_CF(ffi_meta___eq) LJLIB_REC(cdata_arith MM_eq)
+{
+ return ffi_arith(L);
+}
+
+LJLIB_CF(ffi_meta___len) LJLIB_REC(cdata_arith MM_len)
+{
+ return ffi_arith(L);
+}
+
+LJLIB_CF(ffi_meta___lt) LJLIB_REC(cdata_arith MM_lt)
+{
+ return ffi_arith(L);
+}
+
+LJLIB_CF(ffi_meta___le) LJLIB_REC(cdata_arith MM_le)
+{
+ return ffi_arith(L);
+}
+
+LJLIB_CF(ffi_meta___concat) LJLIB_REC(cdata_arith MM_concat)
+{
+ return ffi_arith(L);
+}
+
+/* Forward declaration. */
+static int lj_cf_ffi_new(lua_State *L);
+
+LJLIB_CF(ffi_meta___call) LJLIB_REC(cdata_call)
+{
+ CTState *cts = ctype_cts(L);
+ GCcdata *cd = ffi_checkcdata(L, 1);
+ CTypeID id = cd->ctypeid;
+ CType *ct;
+ cTValue *tv;
+ MMS mm = MM_call;
+ if (cd->ctypeid == CTID_CTYPEID) {
+ id = *(CTypeID *)cdataptr(cd);
+ mm = MM_new;
+ } else {
+ int ret = lj_ccall_func(L, cd);
+ if (ret >= 0)
+ return ret;
+ }
+ /* Handle ctype __call/__new metamethod. */
+ ct = ctype_raw(cts, id);
+ if (ctype_isptr(ct->info)) id = ctype_cid(ct->info);
+ tv = lj_ctype_meta(cts, id, mm);
+ if (tv)
+ return lj_meta_tailcall(L, tv);
+ else if (mm == MM_call)
+ lj_err_callerv(L, LJ_ERR_FFI_BADCALL, strdata(lj_ctype_repr(L, id, NULL)));
+ return lj_cf_ffi_new(L);
+}
+
+LJLIB_CF(ffi_meta___add) LJLIB_REC(cdata_arith MM_add)
+{
+ return ffi_arith(L);
+}
+
+LJLIB_CF(ffi_meta___sub) LJLIB_REC(cdata_arith MM_sub)
+{
+ return ffi_arith(L);
+}
+
+LJLIB_CF(ffi_meta___mul) LJLIB_REC(cdata_arith MM_mul)
+{
+ return ffi_arith(L);
+}
+
+LJLIB_CF(ffi_meta___div) LJLIB_REC(cdata_arith MM_div)
+{
+ return ffi_arith(L);
+}
+
+LJLIB_CF(ffi_meta___mod) LJLIB_REC(cdata_arith MM_mod)
+{
+ return ffi_arith(L);
+}
+
+LJLIB_CF(ffi_meta___pow) LJLIB_REC(cdata_arith MM_pow)
+{
+ return ffi_arith(L);
+}
+
+LJLIB_CF(ffi_meta___unm) LJLIB_REC(cdata_arith MM_unm)
+{
+ return ffi_arith(L);
+}
+/* End of contiguous ORDER MM. */
+
+LJLIB_CF(ffi_meta___tostring)
+{
+ GCcdata *cd = ffi_checkcdata(L, 1);
+ const char *msg = "cdata<%s>: %p";
+ CTypeID id = cd->ctypeid;
+ void *p = cdataptr(cd);
+ if (id == CTID_CTYPEID) {
+ msg = "ctype<%s>";
+ id = *(CTypeID *)p;
+ } else {
+ CTState *cts = ctype_cts(L);
+ CType *ct = ctype_raw(cts, id);
+ if (ctype_isref(ct->info)) {
+ p = *(void **)p;
+ ct = ctype_rawchild(cts, ct);
+ }
+ if (ctype_iscomplex(ct->info)) {
+ setstrV(L, L->top-1, lj_ctype_repr_complex(L, cdataptr(cd), ct->size));
+ goto checkgc;
+ } else if (ct->size == 8 && ctype_isinteger(ct->info)) {
+ setstrV(L, L->top-1, lj_ctype_repr_int64(L, *(uint64_t *)cdataptr(cd),
+ (ct->info & CTF_UNSIGNED)));
+ goto checkgc;
+ } else if (ctype_isfunc(ct->info)) {
+ p = *(void **)p;
+ } else if (ctype_isenum(ct->info)) {
+ msg = "cdata<%s>: %d";
+ p = (void *)(uintptr_t)*(uint32_t **)p;
+ } else {
+ if (ctype_isptr(ct->info)) {
+ p = cdata_getptr(p, ct->size);
+ ct = ctype_rawchild(cts, ct);
+ }
+ if (ctype_isstruct(ct->info) || ctype_isvector(ct->info)) {
+ /* Handle ctype __tostring metamethod. */
+ cTValue *tv = lj_ctype_meta(cts, ctype_typeid(cts, ct), MM_tostring);
+ if (tv)
+ return lj_meta_tailcall(L, tv);
+ }
+ }
+ }
+ lj_str_pushf(L, msg, strdata(lj_ctype_repr(L, id, NULL)), p);
+checkgc:
+ lj_gc_check(L);
+ return 1;
+}
+
+static int ffi_pairs(lua_State *L, MMS mm)
+{
+ CTState *cts = ctype_cts(L);
+ CTypeID id = ffi_checkcdata(L, 1)->ctypeid;
+ CType *ct = ctype_raw(cts, id);
+ cTValue *tv;
+ if (ctype_isptr(ct->info)) id = ctype_cid(ct->info);
+ tv = lj_ctype_meta(cts, id, mm);
+ if (!tv)
+ lj_err_callerv(L, LJ_ERR_FFI_BADMM, strdata(lj_ctype_repr(L, id, NULL)),
+ strdata(mmname_str(G(L), mm)));
+ return lj_meta_tailcall(L, tv);
+}
+
+LJLIB_CF(ffi_meta___pairs)
+{
+ return ffi_pairs(L, MM_pairs);
+}
+
+LJLIB_CF(ffi_meta___ipairs)
+{
+ return ffi_pairs(L, MM_ipairs);
+}
+
+LJLIB_PUSH("ffi") LJLIB_SET(__metatable)
+
+#include "lj_libdef.h"
+
+/* -- C library metamethods ----------------------------------------------- */
+
+#define LJLIB_MODULE_ffi_clib
+
+/* Index C library by a name. */
+static TValue *ffi_clib_index(lua_State *L)
+{
+ TValue *o = L->base;
+ CLibrary *cl;
+ if (!(o < L->top && tvisudata(o) && udataV(o)->udtype == UDTYPE_FFI_CLIB))
+ lj_err_argt(L, 1, LUA_TUSERDATA);
+ cl = (CLibrary *)uddata(udataV(o));
+ if (!(o+1 < L->top && tvisstr(o+1)))
+ lj_err_argt(L, 2, LUA_TSTRING);
+ return lj_clib_index(L, cl, strV(o+1));
+}
+
+LJLIB_CF(ffi_clib___index) LJLIB_REC(clib_index 1)
+{
+ TValue *tv = ffi_clib_index(L);
+ if (tviscdata(tv)) {
+ CTState *cts = ctype_cts(L);
+ GCcdata *cd = cdataV(tv);
+ CType *s = ctype_get(cts, cd->ctypeid);
+ if (ctype_isextern(s->info)) {
+ CTypeID sid = ctype_cid(s->info);
+ void *sp = *(void **)cdataptr(cd);
+ CType *ct = ctype_raw(cts, sid);
+ if (lj_cconv_tv_ct(cts, ct, sid, L->top-1, sp))
+ lj_gc_check(L);
+ return 1;
+ }
+ }
+ copyTV(L, L->top-1, tv);
+ return 1;
+}
+
+LJLIB_CF(ffi_clib___newindex) LJLIB_REC(clib_index 0)
+{
+ TValue *tv = ffi_clib_index(L);
+ TValue *o = L->base+2;
+ if (o < L->top && tviscdata(tv)) {
+ CTState *cts = ctype_cts(L);
+ GCcdata *cd = cdataV(tv);
+ CType *d = ctype_get(cts, cd->ctypeid);
+ if (ctype_isextern(d->info)) {
+ CTInfo qual = 0;
+ for (;;) { /* Skip attributes and collect qualifiers. */
+ d = ctype_child(cts, d);
+ if (!ctype_isattrib(d->info)) break;
+ if (ctype_attrib(d->info) == CTA_QUAL) qual |= d->size;
+ }
+ if (!((d->info|qual) & CTF_CONST)) {
+ lj_cconv_ct_tv(cts, d, *(void **)cdataptr(cd), o, 0);
+ return 0;
+ }
+ }
+ }
+ lj_err_caller(L, LJ_ERR_FFI_WRCONST);
+ return 0; /* unreachable */
+}
+
+LJLIB_CF(ffi_clib___gc)
+{
+ TValue *o = L->base;
+ if (o < L->top && tvisudata(o) && udataV(o)->udtype == UDTYPE_FFI_CLIB)
+ lj_clib_unload((CLibrary *)uddata(udataV(o)));
+ return 0;
+}
+
+#include "lj_libdef.h"
+
+/* -- Callback function metamethods --------------------------------------- */
+
+#define LJLIB_MODULE_ffi_callback
+
+static int ffi_callback_set(lua_State *L, GCfunc *fn)
+{
+ GCcdata *cd = ffi_checkcdata(L, 1);
+ CTState *cts = ctype_cts(L);
+ CType *ct = ctype_raw(cts, cd->ctypeid);
+ if (ctype_isptr(ct->info) && (LJ_32 || ct->size == 8)) {
+ MSize slot = lj_ccallback_ptr2slot(cts, *(void **)cdataptr(cd));
+ if (slot < cts->cb.sizeid && cts->cb.cbid[slot] != 0) {
+ GCtab *t = cts->miscmap;
+ TValue *tv = lj_tab_setint(L, t, (int32_t)slot);
+ if (fn) {
+ setfuncV(L, tv, fn);
+ lj_gc_anybarriert(L, t);
+ } else {
+ setnilV(tv);
+ cts->cb.cbid[slot] = 0;
+ cts->cb.topid = slot < cts->cb.topid ? slot : cts->cb.topid;
+ }
+ return 0;
+ }
+ }
+ lj_err_caller(L, LJ_ERR_FFI_BADCBACK);
+ return 0;
+}
+
+LJLIB_CF(ffi_callback_free)
+{
+ return ffi_callback_set(L, NULL);
+}
+
+LJLIB_CF(ffi_callback_set)
+{
+ GCfunc *fn = lj_lib_checkfunc(L, 2);
+ return ffi_callback_set(L, fn);
+}
+
+LJLIB_PUSH(top-1) LJLIB_SET(__index)
+
+#include "lj_libdef.h"
+
+/* -- FFI library functions ----------------------------------------------- */
+
+#define LJLIB_MODULE_ffi
+
+LJLIB_CF(ffi_cdef)
+{
+ GCstr *s = lj_lib_checkstr(L, 1);
+ CPState cp;
+ int errcode;
+ cp.L = L;
+ cp.cts = ctype_cts(L);
+ cp.srcname = strdata(s);
+ cp.p = strdata(s);
+ cp.param = L->base+1;
+ cp.mode = CPARSE_MODE_MULTI|CPARSE_MODE_DIRECT;
+ errcode = lj_cparse(&cp);
+ if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */
+ lj_gc_check(L);
+ return 0;
+}
+
+LJLIB_CF(ffi_new) LJLIB_REC(.)
+{
+ CTState *cts = ctype_cts(L);
+ CTypeID id = ffi_checkctype(L, cts, NULL);
+ CType *ct = ctype_raw(cts, id);
+ CTSize sz;
+ CTInfo info = lj_ctype_info(cts, id, &sz);
+ TValue *o = L->base+1;
+ GCcdata *cd;
+ if ((info & CTF_VLA)) {
+ o++;
+ sz = lj_ctype_vlsize(cts, ct, (CTSize)ffi_checkint(L, 2));
+ }
+ if (sz == CTSIZE_INVALID)
+ lj_err_arg(L, 1, LJ_ERR_FFI_INVSIZE);
+ if (!(info & CTF_VLA) && ctype_align(info) <= CT_MEMALIGN)
+ cd = lj_cdata_new(cts, id, sz);
+ else
+ cd = lj_cdata_newv(cts, id, sz, ctype_align(info));
+ setcdataV(L, o-1, cd); /* Anchor the uninitialized cdata. */
+ lj_cconv_ct_init(cts, ct, sz, cdataptr(cd),
+ o, (MSize)(L->top - o)); /* Initialize cdata. */
+ if (ctype_isstruct(ct->info)) {
+ /* Handle ctype __gc metamethod. Use the fast lookup here. */
+ cTValue *tv = lj_tab_getinth(cts->miscmap, -(int32_t)id);
+ if (tv && tvistab(tv) && (tv = lj_meta_fast(L, tabV(tv), MM_gc))) {
+ GCtab *t = cts->finalizer;
+ if (gcref(t->metatable)) {
+ /* Add to finalizer table, if still enabled. */
+ copyTV(L, lj_tab_set(L, t, o-1), tv);
+ lj_gc_anybarriert(L, t);
+ cd->marked |= LJ_GC_CDATA_FIN;
+ }
+ }
+ }
+ L->top = o; /* Only return the cdata itself. */
+ lj_gc_check(L);
+ return 1;
+}
+
+LJLIB_CF(ffi_cast) LJLIB_REC(ffi_new)
+{
+ CTState *cts = ctype_cts(L);
+ CTypeID id = ffi_checkctype(L, cts, NULL);
+ CType *d = ctype_raw(cts, id);
+ TValue *o = lj_lib_checkany(L, 2);
+ L->top = o+1; /* Make sure this is the last item on the stack. */
+ if (!(ctype_isnum(d->info) || ctype_isptr(d->info) || ctype_isenum(d->info)))
+ lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE);
+ if (!(tviscdata(o) && cdataV(o)->ctypeid == id)) {
+ GCcdata *cd = lj_cdata_new(cts, id, d->size);
+ lj_cconv_ct_tv(cts, d, cdataptr(cd), o, CCF_CAST);
+ setcdataV(L, o, cd);
+ lj_gc_check(L);
+ }
+ return 1;
+}
+
+LJLIB_CF(ffi_typeof) LJLIB_REC(.)
+{
+ CTState *cts = ctype_cts(L);
+ CTypeID id = ffi_checkctype(L, cts, L->base+1);
+ GCcdata *cd = lj_cdata_new(cts, CTID_CTYPEID, 4);
+ *(CTypeID *)cdataptr(cd) = id;
+ setcdataV(L, L->top-1, cd);
+ lj_gc_check(L);
+ return 1;
+}
+
+LJLIB_CF(ffi_istype) LJLIB_REC(.)
+{
+ CTState *cts = ctype_cts(L);
+ CTypeID id1 = ffi_checkctype(L, cts, NULL);
+ TValue *o = lj_lib_checkany(L, 2);
+ int b = 0;
+ if (tviscdata(o)) {
+ GCcdata *cd = cdataV(o);
+ CTypeID id2 = cd->ctypeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) :
+ cd->ctypeid;
+ CType *ct1 = lj_ctype_rawref(cts, id1);
+ CType *ct2 = lj_ctype_rawref(cts, id2);
+ if (ct1 == ct2) {
+ b = 1;
+ } else if (ctype_type(ct1->info) == ctype_type(ct2->info) &&
+ ct1->size == ct2->size) {
+ if (ctype_ispointer(ct1->info))
+ b = lj_cconv_compatptr(cts, ct1, ct2, CCF_IGNQUAL);
+ else if (ctype_isnum(ct1->info) || ctype_isvoid(ct1->info))
+ b = (((ct1->info ^ ct2->info) & ~(CTF_QUAL|CTF_LONG)) == 0);
+ } else if (ctype_isstruct(ct1->info) && ctype_isptr(ct2->info) &&
+ ct1 == ctype_rawchild(cts, ct2)) {
+ b = 1;
+ }
+ }
+ setboolV(L->top-1, b);
+ setboolV(&G(L)->tmptv2, b); /* Remember for trace recorder. */
+ return 1;
+}
+
+LJLIB_CF(ffi_sizeof) LJLIB_REC(ffi_xof FF_ffi_sizeof)
+{
+ CTState *cts = ctype_cts(L);
+ CTypeID id = ffi_checkctype(L, cts, NULL);
+ CTSize sz;
+ if (LJ_UNLIKELY(tviscdata(L->base) && cdataisv(cdataV(L->base)))) {
+ sz = cdatavlen(cdataV(L->base));
+ } else {
+ CType *ct = lj_ctype_rawref(cts, id);
+ if (ctype_isvltype(ct->info))
+ sz = lj_ctype_vlsize(cts, ct, (CTSize)ffi_checkint(L, 2));
+ else
+ sz = ctype_hassize(ct->info) ? ct->size : CTSIZE_INVALID;
+ if (LJ_UNLIKELY(sz == CTSIZE_INVALID)) {
+ setnilV(L->top-1);
+ return 1;
+ }
+ }
+ setintV(L->top-1, (int32_t)sz);
+ return 1;
+}
+
+LJLIB_CF(ffi_alignof) LJLIB_REC(ffi_xof FF_ffi_alignof)
+{
+ CTState *cts = ctype_cts(L);
+ CTypeID id = ffi_checkctype(L, cts, NULL);
+ CTSize sz = 0;
+ CTInfo info = lj_ctype_info(cts, id, &sz);
+ setintV(L->top-1, 1 << ctype_align(info));
+ return 1;
+}
+
+LJLIB_CF(ffi_offsetof) LJLIB_REC(ffi_xof FF_ffi_offsetof)
+{
+ CTState *cts = ctype_cts(L);
+ CTypeID id = ffi_checkctype(L, cts, NULL);
+ GCstr *name = lj_lib_checkstr(L, 2);
+ CType *ct = lj_ctype_rawref(cts, id);
+ CTSize ofs;
+ if (ctype_isstruct(ct->info) && ct->size != CTSIZE_INVALID) {
+ CType *fct = lj_ctype_getfield(cts, ct, name, &ofs);
+ if (fct) {
+ setintV(L->top-1, ofs);
+ if (ctype_isfield(fct->info)) {
+ return 1;
+ } else if (ctype_isbitfield(fct->info)) {
+ setintV(L->top++, ctype_bitpos(fct->info));
+ setintV(L->top++, ctype_bitbsz(fct->info));
+ return 3;
+ }
+ }
+ }
+ return 0;
+}
+
+LJLIB_CF(ffi_errno) LJLIB_REC(.)
+{
+ int err = errno;
+ if (L->top > L->base)
+ errno = ffi_checkint(L, 1);
+ setintV(L->top++, err);
+ return 1;
+}
+
+LJLIB_CF(ffi_string) LJLIB_REC(.)
+{
+ CTState *cts = ctype_cts(L);
+ TValue *o = lj_lib_checkany(L, 1);
+ const char *p;
+ size_t len;
+ if (o+1 < L->top && !tvisnil(o+1)) {
+ len = (size_t)ffi_checkint(L, 2);
+ lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CVOID), (uint8_t *)&p, o,
+ CCF_ARG(1));
+ } else {
+ lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CCHAR), (uint8_t *)&p, o,
+ CCF_ARG(1));
+ len = strlen(p);
+ }
+ L->top = o+1; /* Make sure this is the last item on the stack. */
+ setstrV(L, o, lj_str_new(L, p, len));
+ lj_gc_check(L);
+ return 1;
+}
+
+LJLIB_CF(ffi_copy) LJLIB_REC(.)
+{
+ void *dp = ffi_checkptr(L, 1, CTID_P_VOID);
+ void *sp = ffi_checkptr(L, 2, CTID_P_CVOID);
+ TValue *o = L->base+1;
+ CTSize len;
+ if (tvisstr(o) && o+1 >= L->top)
+ len = strV(o)->len+1; /* Copy Lua string including trailing '\0'. */
+ else
+ len = (CTSize)ffi_checkint(L, 3);
+ memcpy(dp, sp, len);
+ return 0;
+}
+
+LJLIB_CF(ffi_fill) LJLIB_REC(.)
+{
+ void *dp = ffi_checkptr(L, 1, CTID_P_VOID);
+ CTSize len = (CTSize)ffi_checkint(L, 2);
+ int32_t fill = 0;
+ if (L->base+2 < L->top && !tvisnil(L->base+2)) fill = ffi_checkint(L, 3);
+ memset(dp, fill, len);
+ return 0;
+}
+
+#define H_(le, be) LJ_ENDIAN_SELECT(0x##le, 0x##be)
+
+/* Test ABI string. */
+LJLIB_CF(ffi_abi) LJLIB_REC(.)
+{
+ GCstr *s = lj_lib_checkstr(L, 1);
+ int b = 0;
+ switch (s->hash) {
+#if LJ_64
+ case H_(849858eb,ad35fd06): b = 1; break; /* 64bit */
+#else
+ case H_(662d3c79,d0e22477): b = 1; break; /* 32bit */
+#endif
+#if LJ_ARCH_HASFPU
+ case H_(e33ee463,e33ee463): b = 1; break; /* fpu */
+#endif
+#if LJ_ABI_SOFTFP
+ case H_(61211a23,c2e8c81c): b = 1; break; /* softfp */
+#else
+ case H_(539417a8,8ce0812f): b = 1; break; /* hardfp */
+#endif
+#if LJ_ABI_EABI
+ case H_(2182df8f,f2ed1152): b = 1; break; /* eabi */
+#endif
+#if LJ_ABI_WIN
+ case H_(4ab624a8,4ab624a8): b = 1; break; /* win */
+#endif
+ case H_(3af93066,1f001464): b = 1; break; /* le/be */
+ default:
+ break;
+ }
+ setboolV(L->top-1, b);
+ setboolV(&G(L)->tmptv2, b); /* Remember for trace recorder. */
+ return 1;
+}
+
+#undef H_
+
+LJLIB_PUSH(top-8) LJLIB_SET(!) /* Store reference to miscmap table. */
+
+LJLIB_CF(ffi_metatype)
+{
+ CTState *cts = ctype_cts(L);
+ CTypeID id = ffi_checkctype(L, cts, NULL);
+ GCtab *mt = lj_lib_checktab(L, 2);
+ GCtab *t = cts->miscmap;
+ CType *ct = ctype_get(cts, id); /* Only allow raw types. */
+ TValue *tv;
+ GCcdata *cd;
+ if (!(ctype_isstruct(ct->info) || ctype_iscomplex(ct->info) ||
+ ctype_isvector(ct->info)))
+ lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE);
+ tv = lj_tab_setinth(L, t, -(int32_t)id);
+ if (!tvisnil(tv))
+ lj_err_caller(L, LJ_ERR_PROTMT);
+ settabV(L, tv, mt);
+ lj_gc_anybarriert(L, t);
+ cd = lj_cdata_new(cts, CTID_CTYPEID, 4);
+ *(CTypeID *)cdataptr(cd) = id;
+ setcdataV(L, L->top-1, cd);
+ lj_gc_check(L);
+ return 1;
+}
+
+LJLIB_PUSH(top-7) LJLIB_SET(!) /* Store reference to finalizer table. */
+
+LJLIB_CF(ffi_gc) LJLIB_REC(.)
+{
+ GCcdata *cd = ffi_checkcdata(L, 1);
+ TValue *fin = lj_lib_checkany(L, 2);
+ CTState *cts = ctype_cts(L);
+ GCtab *t = cts->finalizer;
+ CType *ct = ctype_raw(cts, cd->ctypeid);
+ if (!(ctype_isptr(ct->info) || ctype_isstruct(ct->info) ||
+ ctype_isrefarray(ct->info)))
+ lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE);
+ if (gcref(t->metatable)) { /* Update finalizer table, if still enabled. */
+ copyTV(L, lj_tab_set(L, t, L->base), fin);
+ lj_gc_anybarriert(L, t);
+ if (!tvisnil(fin))
+ cd->marked |= LJ_GC_CDATA_FIN;
+ else
+ cd->marked &= ~LJ_GC_CDATA_FIN;
+ }
+ L->top = L->base+1; /* Pass through the cdata object. */
+ return 1;
+}
+
+LJLIB_PUSH(top-5) LJLIB_SET(!) /* Store clib metatable in func environment. */
+
+LJLIB_CF(ffi_load)
+{
+ GCstr *name = lj_lib_checkstr(L, 1);
+ int global = (L->base+1 < L->top && tvistruecond(L->base+1));
+ lj_clib_load(L, tabref(curr_func(L)->c.env), name, global);
+ return 1;
+}
+
+LJLIB_PUSH(top-4) LJLIB_SET(C)
+LJLIB_PUSH(top-3) LJLIB_SET(os)
+LJLIB_PUSH(top-2) LJLIB_SET(arch)
+
+#include "lj_libdef.h"
+
+/* ------------------------------------------------------------------------ */
+
+/* Create special weak-keyed finalizer table. */
+static GCtab *ffi_finalizer(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, "K"));
+ t->nomm = (uint8_t)(~(1u<<MM_mode));
+ return t;
+}
+
+/* Register FFI module as loaded. */
+static void ffi_register_module(lua_State *L)
+{
+ cTValue *tmp = lj_tab_getstr(tabV(registry(L)), lj_str_newlit(L, "_LOADED"));
+ if (tmp && tvistab(tmp)) {
+ GCtab *t = tabV(tmp);
+ copyTV(L, lj_tab_setstr(L, t, lj_str_newlit(L, LUA_FFILIBNAME)), L->top-1);
+ lj_gc_anybarriert(L, t);
+ }
+}
+
+LUALIB_API int luaopen_ffi(lua_State *L)
+{
+ CTState *cts = lj_ctype_init(L);
+ settabV(L, L->top++, (cts->miscmap = lj_tab_new(L, 0, 1)));
+ cts->finalizer = ffi_finalizer(L);
+ LJ_LIB_REG(L, NULL, ffi_meta);
+ /* NOBARRIER: basemt is a GC root. */
+ setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1)));
+ LJ_LIB_REG(L, NULL, ffi_clib);
+ LJ_LIB_REG(L, NULL, ffi_callback);
+ /* NOBARRIER: the key is new and lj_tab_newkey() handles the barrier. */
+ settabV(L, lj_tab_setstr(L, cts->miscmap, &cts->g->strempty), tabV(L->top-1));
+ L->top--;
+ lj_clib_default(L, tabV(L->top-1)); /* Create ffi.C default namespace. */
+ lua_pushliteral(L, LJ_OS_NAME);
+ lua_pushliteral(L, LJ_ARCH_NAME);
+ LJ_LIB_REG(L, NULL, ffi); /* Note: no global "ffi" created! */
+ ffi_register_module(L);
+ return 1;
+}
+
+#endif
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1f27b840/lib/luajit/src/lib_init.c
----------------------------------------------------------------------
diff --git a/lib/luajit/src/lib_init.c b/lib/luajit/src/lib_init.c
new file mode 100644
index 0000000..85c194a
--- /dev/null
+++ b/lib/luajit/src/lib_init.c
@@ -0,0 +1,55 @@
+/*
+** Library initialization.
+** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
+**
+** Major parts taken verbatim from the Lua interpreter.
+** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
+*/
+
+#define lib_init_c
+#define LUA_LIB
+
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+
+#include "lj_arch.h"
+
+static const luaL_Reg lj_lib_load[] = {
+ { "", luaopen_base },
+ { LUA_LOADLIBNAME, luaopen_package },
+ { LUA_TABLIBNAME, luaopen_table },
+ { LUA_IOLIBNAME, luaopen_io },
+ { LUA_OSLIBNAME, luaopen_os },
+ { LUA_STRLIBNAME, luaopen_string },
+ { LUA_MATHLIBNAME, luaopen_math },
+ { LUA_DBLIBNAME, luaopen_debug },
+ { LUA_BITLIBNAME, luaopen_bit },
+ { LUA_JITLIBNAME, luaopen_jit },
+ { NULL, NULL }
+};
+
+static const luaL_Reg lj_lib_preload[] = {
+#if LJ_HASFFI
+ { LUA_FFILIBNAME, luaopen_ffi },
+#endif
+ { NULL, NULL }
+};
+
+LUALIB_API void luaL_openlibs(lua_State *L)
+{
+ const luaL_Reg *lib;
+ for (lib = lj_lib_load; lib->func; lib++) {
+ lua_pushcfunction(L, lib->func);
+ lua_pushstring(L, lib->name);
+ lua_call(L, 1, 0);
+ }
+ luaL_findtable(L, LUA_REGISTRYINDEX, "_PRELOAD",
+ sizeof(lj_lib_preload)/sizeof(lj_lib_preload[0])-1);
+ for (lib = lj_lib_preload; lib->func; lib++) {
+ lua_pushcfunction(L, lib->func);
+ lua_setfield(L, -2, lib->name);
+ }
+ lua_pop(L, 1);
+}
+
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1f27b840/lib/luajit/src/lib_io.c
----------------------------------------------------------------------
diff --git a/lib/luajit/src/lib_io.c b/lib/luajit/src/lib_io.c
new file mode 100644
index 0000000..037aa28
--- /dev/null
+++ b/lib/luajit/src/lib_io.c
@@ -0,0 +1,539 @@
+/*
+** I/O library.
+** Copyright (C) 2005-2015 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 <errno.h>
+#include <stdio.h>
+
+#define lib_io_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_str.h"
+#include "lj_state.h"
+#include "lj_ff.h"
+#include "lj_lib.h"
+
+/* Userdata payload for I/O file. */
+typedef struct IOFileUD {
+ FILE *fp; /* File handle. */
+ uint32_t type; /* File type. */
+} IOFileUD;
+
+#define IOFILE_TYPE_FILE 0 /* Regular file. */
+#define IOFILE_TYPE_PIPE 1 /* Pipe. */
+#define IOFILE_TYPE_STDF 2 /* Standard file handle. */
+#define IOFILE_TYPE_MASK 3
+
+#define IOFILE_FLAG_CLOSE 4 /* Close after io.lines() iterator. */
+
+#define IOSTDF_UD(L, id) (&gcref(G(L)->gcroot[(id)])->ud)
+#define IOSTDF_IOF(L, id) ((IOFileUD *)uddata(IOSTDF_UD(L, (id))))
+
+/* -- Open/close helpers -------------------------------------------------- */
+
+static IOFileUD *io_tofilep(lua_State *L)
+{
+ if (!(L->base < L->top && tvisudata(L->base) &&
+ udataV(L->base)->udtype == UDTYPE_IO_FILE))
+ lj_err_argtype(L, 1, "FILE*");
+ return (IOFileUD *)uddata(udataV(L->base));
+}
+
+static IOFileUD *io_tofile(lua_State *L)
+{
+ IOFileUD *iof = io_tofilep(L);
+ if (iof->fp == NULL)
+ lj_err_caller(L, LJ_ERR_IOCLFL);
+ return iof;
+}
+
+static FILE *io_stdfile(lua_State *L, ptrdiff_t id)
+{
+ IOFileUD *iof = IOSTDF_IOF(L, id);
+ if (iof->fp == NULL)
+ lj_err_caller(L, LJ_ERR_IOSTDCL);
+ return iof->fp;
+}
+
+static IOFileUD *io_file_new(lua_State *L)
+{
+ IOFileUD *iof = (IOFileUD *)lua_newuserdata(L, sizeof(IOFileUD));
+ GCudata *ud = udataV(L->top-1);
+ ud->udtype = UDTYPE_IO_FILE;
+ /* NOBARRIER: The GCudata is new (marked white). */
+ setgcrefr(ud->metatable, curr_func(L)->c.env);
+ iof->fp = NULL;
+ iof->type = IOFILE_TYPE_FILE;
+ return iof;
+}
+
+static IOFileUD *io_file_open(lua_State *L, const char *mode)
+{
+ const char *fname = strdata(lj_lib_checkstr(L, 1));
+ IOFileUD *iof = io_file_new(L);
+ iof->fp = fopen(fname, mode);
+ if (iof->fp == NULL)
+ luaL_argerror(L, 1, lj_str_pushf(L, "%s: %s", fname, strerror(errno)));
+ return iof;
+}
+
+static int io_file_close(lua_State *L, IOFileUD *iof)
+{
+ int ok;
+ if ((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_FILE) {
+ ok = (fclose(iof->fp) == 0);
+ } else if ((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_PIPE) {
+ int stat = -1;
+#if LJ_TARGET_POSIX
+ stat = pclose(iof->fp);
+#elif LJ_TARGET_WINDOWS
+ stat = _pclose(iof->fp);
+#else
+ lua_assert(0);
+ return 0;
+#endif
+#if LJ_52
+ iof->fp = NULL;
+ return luaL_execresult(L, stat);
+#else
+ ok = (stat != -1);
+#endif
+ } else {
+ lua_assert((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_STDF);
+ setnilV(L->top++);
+ lua_pushliteral(L, "cannot close standard file");
+ return 2;
+ }
+ iof->fp = NULL;
+ return luaL_fileresult(L, ok, NULL);
+}
+
+/* -- Read/write helpers -------------------------------------------------- */
+
+static int io_file_readnum(lua_State *L, FILE *fp)
+{
+ lua_Number d;
+ if (fscanf(fp, LUA_NUMBER_SCAN, &d) == 1) {
+ if (LJ_DUALNUM) {
+ int32_t i = lj_num2int(d);
+ if (d == (lua_Number)i && !tvismzero((cTValue *)&d)) {
+ setintV(L->top++, i);
+ return 1;
+ }
+ }
+ setnumV(L->top++, d);
+ return 1;
+ } else {
+ setnilV(L->top++);
+ return 0;
+ }
+}
+
+static int io_file_readline(lua_State *L, FILE *fp, MSize chop)
+{
+ MSize m = LUAL_BUFFERSIZE, n = 0, ok = 0;
+ char *buf;
+ for (;;) {
+ buf = lj_str_needbuf(L, &G(L)->tmpbuf, m);
+ if (fgets(buf+n, m-n, fp) == NULL) break;
+ n += (MSize)strlen(buf+n);
+ ok |= n;
+ if (n && buf[n-1] == '\n') { n -= chop; break; }
+ if (n >= m - 64) m += m;
+ }
+ setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
+ lj_gc_check(L);
+ return (int)ok;
+}
+
+static void io_file_readall(lua_State *L, FILE *fp)
+{
+ MSize m, n;
+ for (m = LUAL_BUFFERSIZE, n = 0; ; m += m) {
+ char *buf = lj_str_needbuf(L, &G(L)->tmpbuf, m);
+ n += (MSize)fread(buf+n, 1, m-n, fp);
+ if (n != m) {
+ setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
+ lj_gc_check(L);
+ return;
+ }
+ }
+}
+
+static int io_file_readlen(lua_State *L, FILE *fp, MSize m)
+{
+ if (m) {
+ char *buf = lj_str_needbuf(L, &G(L)->tmpbuf, m);
+ MSize n = (MSize)fread(buf, 1, m, fp);
+ setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
+ lj_gc_check(L);
+ return (n > 0 || m == 0);
+ } else {
+ int c = getc(fp);
+ ungetc(c, fp);
+ setstrV(L, L->top++, &G(L)->strempty);
+ return (c != EOF);
+ }
+}
+
+static int io_file_read(lua_State *L, FILE *fp, int start)
+{
+ int ok, n, nargs = (int)(L->top - L->base) - start;
+ clearerr(fp);
+ if (nargs == 0) {
+ ok = io_file_readline(L, fp, 1);
+ n = start+1; /* Return 1 result. */
+ } else {
+ /* The results plus the buffers go on top of the args. */
+ luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
+ ok = 1;
+ for (n = start; nargs-- && ok; n++) {
+ if (tvisstr(L->base+n)) {
+ const char *p = strVdata(L->base+n);
+ if (p[0] != '*')
+ lj_err_arg(L, n+1, LJ_ERR_INVOPT);
+ if (p[1] == 'n')
+ ok = io_file_readnum(L, fp);
+ else if ((p[1] & ~0x20) == 'L')
+ ok = io_file_readline(L, fp, (p[1] == 'l'));
+ else if (p[1] == 'a')
+ io_file_readall(L, fp);
+ else
+ lj_err_arg(L, n+1, LJ_ERR_INVFMT);
+ } else if (tvisnumber(L->base+n)) {
+ ok = io_file_readlen(L, fp, (MSize)lj_lib_checkint(L, n+1));
+ } else {
+ lj_err_arg(L, n+1, LJ_ERR_INVOPT);
+ }
+ }
+ }
+ if (ferror(fp))
+ return luaL_fileresult(L, 0, NULL);
+ if (!ok)
+ setnilV(L->top-1); /* Replace last result with nil. */
+ return n - start;
+}
+
+static int io_file_write(lua_State *L, FILE *fp, int start)
+{
+ cTValue *tv;
+ int status = 1;
+ for (tv = L->base+start; tv < L->top; tv++) {
+ if (tvisstr(tv)) {
+ MSize len = strV(tv)->len;
+ status = status && (fwrite(strVdata(tv), 1, len, fp) == len);
+ } else if (tvisint(tv)) {
+ char buf[LJ_STR_INTBUF];
+ char *p = lj_str_bufint(buf, intV(tv));
+ size_t len = (size_t)(buf+LJ_STR_INTBUF-p);
+ status = status && (fwrite(p, 1, len, fp) == len);
+ } else if (tvisnum(tv)) {
+ status = status && (fprintf(fp, LUA_NUMBER_FMT, numV(tv)) > 0);
+ } else {
+ lj_err_argt(L, (int)(tv - L->base) + 1, LUA_TSTRING);
+ }
+ }
+ if (LJ_52 && status) {
+ L->top = L->base+1;
+ if (start == 0)
+ setudataV(L, L->base, IOSTDF_UD(L, GCROOT_IO_OUTPUT));
+ return 1;
+ }
+ return luaL_fileresult(L, status, NULL);
+}
+
+static int io_file_iter(lua_State *L)
+{
+ GCfunc *fn = curr_func(L);
+ IOFileUD *iof = uddata(udataV(&fn->c.upvalue[0]));
+ int n = fn->c.nupvalues - 1;
+ if (iof->fp == NULL)
+ lj_err_caller(L, LJ_ERR_IOCLFL);
+ L->top = L->base;
+ if (n) { /* Copy upvalues with options to stack. */
+ if (n > LUAI_MAXCSTACK)
+ lj_err_caller(L, LJ_ERR_STKOV);
+ lj_state_checkstack(L, (MSize)n);
+ memcpy(L->top, &fn->c.upvalue[1], n*sizeof(TValue));
+ L->top += n;
+ }
+ n = io_file_read(L, iof->fp, 0);
+ if (ferror(iof->fp))
+ lj_err_callermsg(L, strVdata(L->top-2));
+ if (tvisnil(L->base) && (iof->type & IOFILE_FLAG_CLOSE)) {
+ io_file_close(L, iof); /* Return values are ignored. */
+ return 0;
+ }
+ return n;
+}
+
+/* -- I/O file methods ---------------------------------------------------- */
+
+#define LJLIB_MODULE_io_method
+
+LJLIB_CF(io_method_close)
+{
+ IOFileUD *iof = L->base < L->top ? io_tofile(L) :
+ IOSTDF_IOF(L, GCROOT_IO_OUTPUT);
+ return io_file_close(L, iof);
+}
+
+LJLIB_CF(io_method_read)
+{
+ return io_file_read(L, io_tofile(L)->fp, 1);
+}
+
+LJLIB_CF(io_method_write) LJLIB_REC(io_write 0)
+{
+ return io_file_write(L, io_tofile(L)->fp, 1);
+}
+
+LJLIB_CF(io_method_flush) LJLIB_REC(io_flush 0)
+{
+ return luaL_fileresult(L, fflush(io_tofile(L)->fp) == 0, NULL);
+}
+
+LJLIB_CF(io_method_seek)
+{
+ FILE *fp = io_tofile(L)->fp;
+ int opt = lj_lib_checkopt(L, 2, 1, "\3set\3cur\3end");
+ int64_t ofs = 0;
+ cTValue *o;
+ int res;
+ if (opt == 0) opt = SEEK_SET;
+ else if (opt == 1) opt = SEEK_CUR;
+ else if (opt == 2) opt = SEEK_END;
+ o = L->base+2;
+ if (o < L->top) {
+ if (tvisint(o))
+ ofs = (int64_t)intV(o);
+ else if (tvisnum(o))
+ ofs = (int64_t)numV(o);
+ else if (!tvisnil(o))
+ lj_err_argt(L, 3, LUA_TNUMBER);
+ }
+#if LJ_TARGET_POSIX
+ res = fseeko(fp, ofs, opt);
+#elif _MSC_VER >= 1400
+ res = _fseeki64(fp, ofs, opt);
+#elif defined(__MINGW32__)
+ res = fseeko64(fp, ofs, opt);
+#else
+ res = fseek(fp, (long)ofs, opt);
+#endif
+ if (res)
+ return luaL_fileresult(L, 0, NULL);
+#if LJ_TARGET_POSIX
+ ofs = ftello(fp);
+#elif _MSC_VER >= 1400
+ ofs = _ftelli64(fp);
+#elif defined(__MINGW32__)
+ ofs = ftello64(fp);
+#else
+ ofs = (int64_t)ftell(fp);
+#endif
+ setint64V(L->top-1, ofs);
+ return 1;
+}
+
+LJLIB_CF(io_method_setvbuf)
+{
+ FILE *fp = io_tofile(L)->fp;
+ int opt = lj_lib_checkopt(L, 2, -1, "\4full\4line\2no");
+ size_t sz = (size_t)lj_lib_optint(L, 3, LUAL_BUFFERSIZE);
+ if (opt == 0) opt = _IOFBF;
+ else if (opt == 1) opt = _IOLBF;
+ else if (opt == 2) opt = _IONBF;
+ return luaL_fileresult(L, setvbuf(fp, NULL, opt, sz) == 0, NULL);
+}
+
+LJLIB_CF(io_method_lines)
+{
+ io_tofile(L);
+ lua_pushcclosure(L, io_file_iter, (int)(L->top - L->base));
+ return 1;
+}
+
+LJLIB_CF(io_method___gc)
+{
+ IOFileUD *iof = io_tofilep(L);
+ if (iof->fp != NULL && (iof->type & IOFILE_TYPE_MASK) != IOFILE_TYPE_STDF)
+ io_file_close(L, iof);
+ return 0;
+}
+
+LJLIB_CF(io_method___tostring)
+{
+ IOFileUD *iof = io_tofilep(L);
+ if (iof->fp != NULL)
+ lua_pushfstring(L, "file (%p)", iof->fp);
+ else
+ lua_pushliteral(L, "file (closed)");
+ return 1;
+}
+
+LJLIB_PUSH(top-1) LJLIB_SET(__index)
+
+#include "lj_libdef.h"
+
+/* -- I/O library functions ----------------------------------------------- */
+
+#define LJLIB_MODULE_io
+
+LJLIB_PUSH(top-2) LJLIB_SET(!) /* Set environment. */
+
+LJLIB_CF(io_open)
+{
+ const char *fname = strdata(lj_lib_checkstr(L, 1));
+ GCstr *s = lj_lib_optstr(L, 2);
+ const char *mode = s ? strdata(s) : "r";
+ IOFileUD *iof = io_file_new(L);
+ iof->fp = fopen(fname, mode);
+ return iof->fp != NULL ? 1 : luaL_fileresult(L, 0, fname);
+}
+
+LJLIB_CF(io_popen)
+{
+#if LJ_TARGET_POSIX || LJ_TARGET_WINDOWS
+ const char *fname = strdata(lj_lib_checkstr(L, 1));
+ GCstr *s = lj_lib_optstr(L, 2);
+ const char *mode = s ? strdata(s) : "r";
+ IOFileUD *iof = io_file_new(L);
+ iof->type = IOFILE_TYPE_PIPE;
+#if LJ_TARGET_POSIX
+ fflush(NULL);
+ iof->fp = popen(fname, mode);
+#else
+ iof->fp = _popen(fname, mode);
+#endif
+ return iof->fp != NULL ? 1 : luaL_fileresult(L, 0, fname);
+#else
+ return luaL_error(L, LUA_QL("popen") " not supported");
+#endif
+}
+
+LJLIB_CF(io_tmpfile)
+{
+ IOFileUD *iof = io_file_new(L);
+#if LJ_TARGET_PS3 || LJ_TARGET_PS4 || LJ_TARGET_PSVITA
+ iof->fp = NULL; errno = ENOSYS;
+#else
+ iof->fp = tmpfile();
+#endif
+ return iof->fp != NULL ? 1 : luaL_fileresult(L, 0, NULL);
+}
+
+LJLIB_CF(io_close)
+{
+ return lj_cf_io_method_close(L);
+}
+
+LJLIB_CF(io_read)
+{
+ return io_file_read(L, io_stdfile(L, GCROOT_IO_INPUT), 0);
+}
+
+LJLIB_CF(io_write) LJLIB_REC(io_write GCROOT_IO_OUTPUT)
+{
+ return io_file_write(L, io_stdfile(L, GCROOT_IO_OUTPUT), 0);
+}
+
+LJLIB_CF(io_flush) LJLIB_REC(io_flush GCROOT_IO_OUTPUT)
+{
+ return luaL_fileresult(L, fflush(io_stdfile(L, GCROOT_IO_OUTPUT)) == 0, NULL);
+}
+
+static int io_std_getset(lua_State *L, ptrdiff_t id, const char *mode)
+{
+ if (L->base < L->top && !tvisnil(L->base)) {
+ if (tvisudata(L->base)) {
+ io_tofile(L);
+ L->top = L->base+1;
+ } else {
+ io_file_open(L, mode);
+ }
+ /* NOBARRIER: The standard I/O handles are GC roots. */
+ setgcref(G(L)->gcroot[id], gcV(L->top-1));
+ } else {
+ setudataV(L, L->top++, IOSTDF_UD(L, id));
+ }
+ return 1;
+}
+
+LJLIB_CF(io_input)
+{
+ return io_std_getset(L, GCROOT_IO_INPUT, "r");
+}
+
+LJLIB_CF(io_output)
+{
+ return io_std_getset(L, GCROOT_IO_OUTPUT, "w");
+}
+
+LJLIB_CF(io_lines)
+{
+ if (L->base == L->top) setnilV(L->top++);
+ if (!tvisnil(L->base)) { /* io.lines(fname) */
+ IOFileUD *iof = io_file_open(L, "r");
+ iof->type = IOFILE_TYPE_FILE|IOFILE_FLAG_CLOSE;
+ L->top--;
+ setudataV(L, L->base, udataV(L->top));
+ } else { /* io.lines() iterates over stdin. */
+ setudataV(L, L->base, IOSTDF_UD(L, GCROOT_IO_INPUT));
+ }
+ lua_pushcclosure(L, io_file_iter, (int)(L->top - L->base));
+ return 1;
+}
+
+LJLIB_CF(io_type)
+{
+ cTValue *o = lj_lib_checkany(L, 1);
+ if (!(tvisudata(o) && udataV(o)->udtype == UDTYPE_IO_FILE))
+ setnilV(L->top++);
+ else if (((IOFileUD *)uddata(udataV(o)))->fp != NULL)
+ lua_pushliteral(L, "file");
+ else
+ lua_pushliteral(L, "closed file");
+ return 1;
+}
+
+#include "lj_libdef.h"
+
+/* ------------------------------------------------------------------------ */
+
+static GCobj *io_std_new(lua_State *L, FILE *fp, const char *name)
+{
+ IOFileUD *iof = (IOFileUD *)lua_newuserdata(L, sizeof(IOFileUD));
+ GCudata *ud = udataV(L->top-1);
+ ud->udtype = UDTYPE_IO_FILE;
+ /* NOBARRIER: The GCudata is new (marked white). */
+ setgcref(ud->metatable, gcV(L->top-3));
+ iof->fp = fp;
+ iof->type = IOFILE_TYPE_STDF;
+ lua_setfield(L, -2, name);
+ return obj2gco(ud);
+}
+
+LUALIB_API int luaopen_io(lua_State *L)
+{
+ LJ_LIB_REG(L, NULL, io_method);
+ copyTV(L, L->top, L->top-1); L->top++;
+ lua_setfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
+ LJ_LIB_REG(L, LUA_IOLIBNAME, io);
+ setgcref(G(L)->gcroot[GCROOT_IO_INPUT], io_std_new(L, stdin, "stdin"));
+ setgcref(G(L)->gcroot[GCROOT_IO_OUTPUT], io_std_new(L, stdout, "stdout"));
+ io_std_new(L, stderr, "stderr");
+ return 1;
+}
+
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1f27b840/lib/luajit/src/lib_jit.c
----------------------------------------------------------------------
diff --git a/lib/luajit/src/lib_jit.c b/lib/luajit/src/lib_jit.c
new file mode 100644
index 0000000..96525fa
--- /dev/null
+++ b/lib/luajit/src/lib_jit.c
@@ -0,0 +1,663 @@
+/*
+** JIT library.
+** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
+*/
+
+#define lib_jit_c
+#define LUA_LIB
+
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+
+#include "lj_arch.h"
+#include "lj_obj.h"
+#include "lj_err.h"
+#include "lj_debug.h"
+#include "lj_str.h"
+#include "lj_tab.h"
+#include "lj_bc.h"
+#if LJ_HASJIT
+#include "lj_ir.h"
+#include "lj_jit.h"
+#include "lj_ircall.h"
+#include "lj_iropt.h"
+#include "lj_target.h"
+#endif
+#include "lj_dispatch.h"
+#include "lj_vm.h"
+#include "lj_vmevent.h"
+#include "lj_lib.h"
+
+#include "luajit.h"
+
+/* -- jit.* functions ----------------------------------------------------- */
+
+#define LJLIB_MODULE_jit
+
+static int setjitmode(lua_State *L, int mode)
+{
+ int idx = 0;
+ if (L->base == L->top || tvisnil(L->base)) { /* jit.on/off/flush([nil]) */
+ mode |= LUAJIT_MODE_ENGINE;
+ } else {
+ /* jit.on/off/flush(func|proto, nil|true|false) */
+ if (tvisfunc(L->base) || tvisproto(L->base))
+ idx = 1;
+ else if (!tvistrue(L->base)) /* jit.on/off/flush(true, nil|true|false) */
+ goto err;
+ if (L->base+1 < L->top && tvisbool(L->base+1))
+ mode |= boolV(L->base+1) ? LUAJIT_MODE_ALLFUNC : LUAJIT_MODE_ALLSUBFUNC;
+ else
+ mode |= LUAJIT_MODE_FUNC;
+ }
+ if (luaJIT_setmode(L, idx, mode) != 1) {
+ if ((mode & LUAJIT_MODE_MASK) == LUAJIT_MODE_ENGINE)
+ lj_err_caller(L, LJ_ERR_NOJIT);
+ err:
+ lj_err_argt(L, 1, LUA_TFUNCTION);
+ }
+ return 0;
+}
+
+LJLIB_CF(jit_on)
+{
+ return setjitmode(L, LUAJIT_MODE_ON);
+}
+
+LJLIB_CF(jit_off)
+{
+ return setjitmode(L, LUAJIT_MODE_OFF);
+}
+
+LJLIB_CF(jit_flush)
+{
+#if LJ_HASJIT
+ if (L->base < L->top && tvisnumber(L->base)) {
+ int traceno = lj_lib_checkint(L, 1);
+ luaJIT_setmode(L, traceno, LUAJIT_MODE_FLUSH|LUAJIT_MODE_TRACE);
+ return 0;
+ }
+#endif
+ return setjitmode(L, LUAJIT_MODE_FLUSH);
+}
+
+#if LJ_HASJIT
+/* Push a string for every flag bit that is set. */
+static void flagbits_to_strings(lua_State *L, uint32_t flags, uint32_t base,
+ const char *str)
+{
+ for (; *str; base <<= 1, str += 1+*str)
+ if (flags & base)
+ setstrV(L, L->top++, lj_str_new(L, str+1, *(uint8_t *)str));
+}
+#endif
+
+LJLIB_CF(jit_status)
+{
+#if LJ_HASJIT
+ jit_State *J = L2J(L);
+ L->top = L->base;
+ setboolV(L->top++, (J->flags & JIT_F_ON) ? 1 : 0);
+ flagbits_to_strings(L, J->flags, JIT_F_CPU_FIRST, JIT_F_CPUSTRING);
+ flagbits_to_strings(L, J->flags, JIT_F_OPT_FIRST, JIT_F_OPTSTRING);
+ return (int)(L->top - L->base);
+#else
+ setboolV(L->top++, 0);
+ return 1;
+#endif
+}
+
+LJLIB_CF(jit_attach)
+{
+#ifdef LUAJIT_DISABLE_VMEVENT
+ luaL_error(L, "vmevent API disabled");
+#else
+ GCfunc *fn = lj_lib_checkfunc(L, 1);
+ GCstr *s = lj_lib_optstr(L, 2);
+ luaL_findtable(L, LUA_REGISTRYINDEX, LJ_VMEVENTS_REGKEY, LJ_VMEVENTS_HSIZE);
+ if (s) { /* Attach to given event. */
+ const uint8_t *p = (const uint8_t *)strdata(s);
+ uint32_t h = s->len;
+ while (*p) h = h ^ (lj_rol(h, 6) + *p++);
+ lua_pushvalue(L, 1);
+ lua_rawseti(L, -2, VMEVENT_HASHIDX(h));
+ G(L)->vmevmask = VMEVENT_NOCACHE; /* Invalidate cache. */
+ } else { /* Detach if no event given. */
+ setnilV(L->top++);
+ while (lua_next(L, -2)) {
+ L->top--;
+ if (tvisfunc(L->top) && funcV(L->top) == fn) {
+ setnilV(lj_tab_set(L, tabV(L->top-2), L->top-1));
+ }
+ }
+ }
+#endif
+ return 0;
+}
+
+LJLIB_PUSH(top-5) LJLIB_SET(os)
+LJLIB_PUSH(top-4) LJLIB_SET(arch)
+LJLIB_PUSH(top-3) LJLIB_SET(version_num)
+LJLIB_PUSH(top-2) LJLIB_SET(version)
+
+#include "lj_libdef.h"
+
+/* -- jit.util.* functions ------------------------------------------------ */
+
+#define LJLIB_MODULE_jit_util
+
+/* -- Reflection API for Lua functions ------------------------------------ */
+
+/* Return prototype of first argument (Lua function or prototype object) */
+static GCproto *check_Lproto(lua_State *L, int nolua)
+{
+ TValue *o = L->base;
+ if (L->top > o) {
+ if (tvisproto(o)) {
+ return protoV(o);
+ } else if (tvisfunc(o)) {
+ if (isluafunc(funcV(o)))
+ return funcproto(funcV(o));
+ else if (nolua)
+ return NULL;
+ }
+ }
+ lj_err_argt(L, 1, LUA_TFUNCTION);
+ return NULL; /* unreachable */
+}
+
+static void setintfield(lua_State *L, GCtab *t, const char *name, int32_t val)
+{
+ setintV(lj_tab_setstr(L, t, lj_str_newz(L, name)), val);
+}
+
+/* local info = jit.util.funcinfo(func [,pc]) */
+LJLIB_CF(jit_util_funcinfo)
+{
+ GCproto *pt = check_Lproto(L, 1);
+ if (pt) {
+ BCPos pc = (BCPos)lj_lib_optint(L, 2, 0);
+ GCtab *t;
+ lua_createtable(L, 0, 16); /* Increment hash size if fields are added. */
+ t = tabV(L->top-1);
+ setintfield(L, t, "linedefined", pt->firstline);
+ setintfield(L, t, "lastlinedefined", pt->firstline + pt->numline);
+ setintfield(L, t, "stackslots", pt->framesize);
+ setintfield(L, t, "params", pt->numparams);
+ setintfield(L, t, "bytecodes", (int32_t)pt->sizebc);
+ setintfield(L, t, "gcconsts", (int32_t)pt->sizekgc);
+ setintfield(L, t, "nconsts", (int32_t)pt->sizekn);
+ setintfield(L, t, "upvalues", (int32_t)pt->sizeuv);
+ if (pc < pt->sizebc)
+ setintfield(L, t, "currentline", lj_debug_line(pt, pc));
+ lua_pushboolean(L, (pt->flags & PROTO_VARARG));
+ lua_setfield(L, -2, "isvararg");
+ lua_pushboolean(L, (pt->flags & PROTO_CHILD));
+ lua_setfield(L, -2, "children");
+ setstrV(L, L->top++, proto_chunkname(pt));
+ lua_setfield(L, -2, "source");
+ lj_debug_pushloc(L, pt, pc);
+ lua_setfield(L, -2, "loc");
+ } else {
+ GCfunc *fn = funcV(L->base);
+ GCtab *t;
+ lua_createtable(L, 0, 4); /* Increment hash size if fields are added. */
+ t = tabV(L->top-1);
+ if (!iscfunc(fn))
+ setintfield(L, t, "ffid", fn->c.ffid);
+ setintptrV(lj_tab_setstr(L, t, lj_str_newlit(L, "addr")),
+ (intptr_t)(void *)fn->c.f);
+ setintfield(L, t, "upvalues", fn->c.nupvalues);
+ }
+ return 1;
+}
+
+/* local ins, m = jit.util.funcbc(func, pc) */
+LJLIB_CF(jit_util_funcbc)
+{
+ GCproto *pt = check_Lproto(L, 0);
+ BCPos pc = (BCPos)lj_lib_checkint(L, 2);
+ if (pc < pt->sizebc) {
+ BCIns ins = proto_bc(pt)[pc];
+ BCOp op = bc_op(ins);
+ lua_assert(op < BC__MAX);
+ setintV(L->top, ins);
+ setintV(L->top+1, lj_bc_mode[op]);
+ L->top += 2;
+ return 2;
+ }
+ return 0;
+}
+
+/* local k = jit.util.funck(func, idx) */
+LJLIB_CF(jit_util_funck)
+{
+ GCproto *pt = check_Lproto(L, 0);
+ ptrdiff_t idx = (ptrdiff_t)lj_lib_checkint(L, 2);
+ if (idx >= 0) {
+ if (idx < (ptrdiff_t)pt->sizekn) {
+ copyTV(L, L->top-1, proto_knumtv(pt, idx));
+ return 1;
+ }
+ } else {
+ if (~idx < (ptrdiff_t)pt->sizekgc) {
+ GCobj *gc = proto_kgc(pt, idx);
+ setgcV(L, L->top-1, gc, ~gc->gch.gct);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* local name = jit.util.funcuvname(func, idx) */
+LJLIB_CF(jit_util_funcuvname)
+{
+ GCproto *pt = check_Lproto(L, 0);
+ uint32_t idx = (uint32_t)lj_lib_checkint(L, 2);
+ if (idx < pt->sizeuv) {
+ setstrV(L, L->top-1, lj_str_newz(L, lj_debug_uvname(pt, idx)));
+ return 1;
+ }
+ return 0;
+}
+
+/* -- Reflection API for traces ------------------------------------------- */
+
+#if LJ_HASJIT
+
+/* Check trace argument. Must not throw for non-existent trace numbers. */
+static GCtrace *jit_checktrace(lua_State *L)
+{
+ TraceNo tr = (TraceNo)lj_lib_checkint(L, 1);
+ jit_State *J = L2J(L);
+ if (tr > 0 && tr < J->sizetrace)
+ return traceref(J, tr);
+ return NULL;
+}
+
+/* Names of link types. ORDER LJ_TRLINK */
+static const char *const jit_trlinkname[] = {
+ "none", "root", "loop", "tail-recursion", "up-recursion", "down-recursion",
+ "interpreter", "return"
+};
+
+/* local info = jit.util.traceinfo(tr) */
+LJLIB_CF(jit_util_traceinfo)
+{
+ GCtrace *T = jit_checktrace(L);
+ if (T) {
+ GCtab *t;
+ lua_createtable(L, 0, 8); /* Increment hash size if fields are added. */
+ t = tabV(L->top-1);
+ setintfield(L, t, "nins", (int32_t)T->nins - REF_BIAS - 1);
+ setintfield(L, t, "nk", REF_BIAS - (int32_t)T->nk);
+ setintfield(L, t, "link", T->link);
+ setintfield(L, t, "nexit", T->nsnap);
+ setstrV(L, L->top++, lj_str_newz(L, jit_trlinkname[T->linktype]));
+ lua_setfield(L, -2, "linktype");
+ /* There are many more fields. Add them only when needed. */
+ return 1;
+ }
+ return 0;
+}
+
+/* local m, ot, op1, op2, prev = jit.util.traceir(tr, idx) */
+LJLIB_CF(jit_util_traceir)
+{
+ GCtrace *T = jit_checktrace(L);
+ IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS;
+ if (T && ref >= REF_BIAS && ref < T->nins) {
+ IRIns *ir = &T->ir[ref];
+ int32_t m = lj_ir_mode[ir->o];
+ setintV(L->top-2, m);
+ setintV(L->top-1, ir->ot);
+ setintV(L->top++, (int32_t)ir->op1 - (irm_op1(m)==IRMref ? REF_BIAS : 0));
+ setintV(L->top++, (int32_t)ir->op2 - (irm_op2(m)==IRMref ? REF_BIAS : 0));
+ setintV(L->top++, ir->prev);
+ return 5;
+ }
+ return 0;
+}
+
+/* local k, t [, slot] = jit.util.tracek(tr, idx) */
+LJLIB_CF(jit_util_tracek)
+{
+ GCtrace *T = jit_checktrace(L);
+ IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS;
+ if (T && ref >= T->nk && ref < REF_BIAS) {
+ IRIns *ir = &T->ir[ref];
+ int32_t slot = -1;
+ if (ir->o == IR_KSLOT) {
+ slot = ir->op2;
+ ir = &T->ir[ir->op1];
+ }
+ lj_ir_kvalue(L, L->top-2, ir);
+ setintV(L->top-1, (int32_t)irt_type(ir->t));
+ if (slot == -1)
+ return 2;
+ setintV(L->top++, slot);
+ return 3;
+ }
+ return 0;
+}
+
+/* local snap = jit.util.tracesnap(tr, sn) */
+LJLIB_CF(jit_util_tracesnap)
+{
+ GCtrace *T = jit_checktrace(L);
+ SnapNo sn = (SnapNo)lj_lib_checkint(L, 2);
+ if (T && sn < T->nsnap) {
+ SnapShot *snap = &T->snap[sn];
+ SnapEntry *map = &T->snapmap[snap->mapofs];
+ MSize n, nent = snap->nent;
+ GCtab *t;
+ lua_createtable(L, nent+2, 0);
+ t = tabV(L->top-1);
+ setintV(lj_tab_setint(L, t, 0), (int32_t)snap->ref - REF_BIAS);
+ setintV(lj_tab_setint(L, t, 1), (int32_t)snap->nslots);
+ for (n = 0; n < nent; n++)
+ setintV(lj_tab_setint(L, t, (int32_t)(n+2)), (int32_t)map[n]);
+ setintV(lj_tab_setint(L, t, (int32_t)(nent+2)), (int32_t)SNAP(255, 0, 0));
+ return 1;
+ }
+ return 0;
+}
+
+/* local mcode, addr, loop = jit.util.tracemc(tr) */
+LJLIB_CF(jit_util_tracemc)
+{
+ GCtrace *T = jit_checktrace(L);
+ if (T && T->mcode != NULL) {
+ setstrV(L, L->top-1, lj_str_new(L, (const char *)T->mcode, T->szmcode));
+ setintptrV(L->top++, (intptr_t)(void *)T->mcode);
+ setintV(L->top++, T->mcloop);
+ return 3;
+ }
+ return 0;
+}
+
+/* local addr = jit.util.traceexitstub([tr,] exitno) */
+LJLIB_CF(jit_util_traceexitstub)
+{
+#ifdef EXITSTUBS_PER_GROUP
+ ExitNo exitno = (ExitNo)lj_lib_checkint(L, 1);
+ jit_State *J = L2J(L);
+ if (exitno < EXITSTUBS_PER_GROUP*LJ_MAX_EXITSTUBGR) {
+ setintptrV(L->top-1, (intptr_t)(void *)exitstub_addr(J, exitno));
+ return 1;
+ }
+#else
+ if (L->top > L->base+1) { /* Don't throw for one-argument variant. */
+ GCtrace *T = jit_checktrace(L);
+ ExitNo exitno = (ExitNo)lj_lib_checkint(L, 2);
+ ExitNo maxexit = T->root ? T->nsnap+1 : T->nsnap;
+ if (T && T->mcode != NULL && exitno < maxexit) {
+ setintptrV(L->top-1, (intptr_t)(void *)exitstub_trace_addr(T, exitno));
+ return 1;
+ }
+ }
+#endif
+ return 0;
+}
+
+/* local addr = jit.util.ircalladdr(idx) */
+LJLIB_CF(jit_util_ircalladdr)
+{
+ uint32_t idx = (uint32_t)lj_lib_checkint(L, 1);
+ if (idx < IRCALL__MAX) {
+ setintptrV(L->top-1, (intptr_t)(void *)lj_ir_callinfo[idx].func);
+ return 1;
+ }
+ return 0;
+}
+
+#endif
+
+#include "lj_libdef.h"
+
+/* -- jit.opt module ------------------------------------------------------ */
+
+#if LJ_HASJIT
+
+#define LJLIB_MODULE_jit_opt
+
+/* Parse optimization level. */
+static int jitopt_level(jit_State *J, const char *str)
+{
+ if (str[0] >= '0' && str[0] <= '9' && str[1] == '\0') {
+ uint32_t flags;
+ if (str[0] == '0') flags = JIT_F_OPT_0;
+ else if (str[0] == '1') flags = JIT_F_OPT_1;
+ else if (str[0] == '2') flags = JIT_F_OPT_2;
+ else flags = JIT_F_OPT_3;
+ J->flags = (J->flags & ~JIT_F_OPT_MASK) | flags;
+ return 1; /* Ok. */
+ }
+ return 0; /* No match. */
+}
+
+/* Parse optimization flag. */
+static int jitopt_flag(jit_State *J, const char *str)
+{
+ const char *lst = JIT_F_OPTSTRING;
+ uint32_t opt;
+ int set = 1;
+ if (str[0] == '+') {
+ str++;
+ } else if (str[0] == '-') {
+ str++;
+ set = 0;
+ } else if (str[0] == 'n' && str[1] == 'o') {
+ str += str[2] == '-' ? 3 : 2;
+ set = 0;
+ }
+ for (opt = JIT_F_OPT_FIRST; ; opt <<= 1) {
+ size_t len = *(const uint8_t *)lst;
+ if (len == 0)
+ break;
+ if (strncmp(str, lst+1, len) == 0 && str[len] == '\0') {
+ if (set) J->flags |= opt; else J->flags &= ~opt;
+ return 1; /* Ok. */
+ }
+ lst += 1+len;
+ }
+ return 0; /* No match. */
+}
+
+/* Parse optimization parameter. */
+static int jitopt_param(jit_State *J, const char *str)
+{
+ const char *lst = JIT_P_STRING;
+ int i;
+ for (i = 0; i < JIT_P__MAX; i++) {
+ size_t len = *(const uint8_t *)lst;
+ lua_assert(len != 0);
+ if (strncmp(str, lst+1, len) == 0 && str[len] == '=') {
+ int32_t n = 0;
+ const char *p = &str[len+1];
+ while (*p >= '0' && *p <= '9')
+ n = n*10 + (*p++ - '0');
+ if (*p) return 0; /* Malformed number. */
+ J->param[i] = n;
+ if (i == JIT_P_hotloop)
+ lj_dispatch_init_hotcount(J2G(J));
+ return 1; /* Ok. */
+ }
+ lst += 1+len;
+ }
+ return 0; /* No match. */
+}
+
+/* jit.opt.start(flags...) */
+LJLIB_CF(jit_opt_start)
+{
+ jit_State *J = L2J(L);
+ int nargs = (int)(L->top - L->base);
+ if (nargs == 0) {
+ J->flags = (J->flags & ~JIT_F_OPT_MASK) | JIT_F_OPT_DEFAULT;
+ } else {
+ int i;
+ for (i = 1; i <= nargs; i++) {
+ const char *str = strdata(lj_lib_checkstr(L, i));
+ if (!jitopt_level(J, str) &&
+ !jitopt_flag(J, str) &&
+ !jitopt_param(J, str))
+ lj_err_callerv(L, LJ_ERR_JITOPT, str);
+ }
+ }
+ return 0;
+}
+
+#include "lj_libdef.h"
+
+#endif
+
+/* -- JIT compiler initialization ----------------------------------------- */
+
+#if LJ_HASJIT
+/* Default values for JIT parameters. */
+static const int32_t jit_param_default[JIT_P__MAX+1] = {
+#define JIT_PARAMINIT(len, name, value) (value),
+JIT_PARAMDEF(JIT_PARAMINIT)
+#undef JIT_PARAMINIT
+ 0
+};
+#endif
+
+#if LJ_TARGET_ARM && LJ_TARGET_LINUX
+#include <sys/utsname.h>
+#endif
+
+/* Arch-dependent CPU detection. */
+static uint32_t jit_cpudetect(lua_State *L)
+{
+ uint32_t flags = 0;
+#if LJ_TARGET_X86ORX64
+ uint32_t vendor[4];
+ uint32_t features[4];
+ if (lj_vm_cpuid(0, vendor) && lj_vm_cpuid(1, features)) {
+#if !LJ_HASJIT
+#define JIT_F_CMOV 1
+#define JIT_F_SSE2 2
+#endif
+ flags |= ((features[3] >> 15)&1) * JIT_F_CMOV;
+ flags |= ((features[3] >> 26)&1) * JIT_F_SSE2;
+#if LJ_HASJIT
+ flags |= ((features[2] >> 0)&1) * JIT_F_SSE3;
+ flags |= ((features[2] >> 19)&1) * JIT_F_SSE4_1;
+ if (vendor[2] == 0x6c65746e) { /* Intel. */
+ if ((features[0] & 0x0ff00f00) == 0x00000f00) /* P4. */
+ flags |= JIT_F_P4; /* Currently unused. */
+ else if ((features[0] & 0x0fff0ff0) == 0x000106c0) /* Atom. */
+ flags |= JIT_F_LEA_AGU;
+ } else if (vendor[2] == 0x444d4163) { /* AMD. */
+ uint32_t fam = (features[0] & 0x0ff00f00);
+ if (fam == 0x00000f00) /* K8. */
+ flags |= JIT_F_SPLIT_XMM;
+ if (fam >= 0x00000f00) /* K8, K10. */
+ flags |= JIT_F_PREFER_IMUL;
+ }
+#endif
+ }
+ /* Check for required instruction set support on x86 (unnecessary on x64). */
+#if LJ_TARGET_X86
+#if !defined(LUAJIT_CPU_NOCMOV)
+ if (!(flags & JIT_F_CMOV))
+ luaL_error(L, "CPU not supported");
+#endif
+#if defined(LUAJIT_CPU_SSE2)
+ if (!(flags & JIT_F_SSE2))
+ luaL_error(L, "CPU does not support SSE2 (recompile without -DLUAJIT_CPU_SSE2)");
+#endif
+#endif
+#elif LJ_TARGET_ARM
+#if LJ_HASJIT
+ int ver = LJ_ARCH_VERSION; /* Compile-time ARM CPU detection. */
+#if LJ_TARGET_LINUX
+ if (ver < 70) { /* Runtime ARM CPU detection. */
+ struct utsname ut;
+ uname(&ut);
+ if (strncmp(ut.machine, "armv", 4) == 0) {
+ if (ut.machine[4] >= '7')
+ ver = 70;
+ else if (ut.machine[4] == '6')
+ ver = 60;
+ }
+ }
+#endif
+ flags |= ver >= 70 ? JIT_F_ARMV7 :
+ ver >= 61 ? JIT_F_ARMV6T2_ :
+ ver >= 60 ? JIT_F_ARMV6_ : 0;
+ flags |= LJ_ARCH_HASFPU == 0 ? 0 : ver >= 70 ? JIT_F_VFPV3 : JIT_F_VFPV2;
+#endif
+#elif LJ_TARGET_PPC
+#if LJ_HASJIT
+#if LJ_ARCH_SQRT
+ flags |= JIT_F_SQRT;
+#endif
+#if LJ_ARCH_ROUND
+ flags |= JIT_F_ROUND;
+#endif
+#endif
+#elif LJ_TARGET_PPCSPE
+ /* Nothing to do. */
+#elif LJ_TARGET_MIPS
+#if LJ_HASJIT
+ /* Compile-time MIPS CPU detection. */
+#if LJ_ARCH_VERSION >= 20
+ flags |= JIT_F_MIPS32R2;
+#endif
+ /* Runtime MIPS CPU detection. */
+#if defined(__GNUC__)
+ if (!(flags & JIT_F_MIPS32R2)) {
+ int x;
+ /* On MIPS32R1 rotr is treated as srl. rotr r2,r2,1 -> srl r2,r2,1. */
+ __asm__("li $2, 1\n\t.long 0x00221042\n\tmove %0, $2" : "=r"(x) : : "$2");
+ if (x) flags |= JIT_F_MIPS32R2; /* Either 0x80000000 (R2) or 0 (R1). */
+ }
+#endif
+#endif
+#else
+#error "Missing CPU detection for this architecture"
+#endif
+ UNUSED(L);
+ return flags;
+}
+
+/* Initialize JIT compiler. */
+static void jit_init(lua_State *L)
+{
+ uint32_t flags = jit_cpudetect(L);
+#if LJ_HASJIT
+ jit_State *J = L2J(L);
+#if LJ_TARGET_X86
+ /* Silently turn off the JIT compiler on CPUs without SSE2. */
+ if ((flags & JIT_F_SSE2))
+#endif
+ J->flags = flags | JIT_F_ON | JIT_F_OPT_DEFAULT;
+ memcpy(J->param, jit_param_default, sizeof(J->param));
+ lj_dispatch_update(G(L));
+#else
+ UNUSED(flags);
+#endif
+}
+
+LUALIB_API int luaopen_jit(lua_State *L)
+{
+ lua_pushliteral(L, LJ_OS_NAME);
+ lua_pushliteral(L, LJ_ARCH_NAME);
+ lua_pushinteger(L, LUAJIT_VERSION_NUM);
+ lua_pushliteral(L, LUAJIT_VERSION);
+ LJ_LIB_REG(L, LUA_JITLIBNAME, jit);
+#ifndef LUAJIT_DISABLE_JITUTIL
+ LJ_LIB_REG(L, "jit.util", jit_util);
+#endif
+#if LJ_HASJIT
+ LJ_LIB_REG(L, "jit.opt", jit_opt);
+#endif
+ L->top -= 2;
+ jit_init(L);
+ return 1;
+}
+