让 LuaJIT 2.0 支持 Lua 5.2 中的 _ENV 特性
我们的项目是用 Lua 5.2 标准来写的, 最近想迁移到 LuaJIT 2.0 中。其中碰到的最大障碍是,LuaJIT 2.0 不支持 Lua 5.2 中的 _ENV
特性。而且,看起来将来也不会支持了。
在邮件列表中,LuaJIT 的作者 Mike 看起来很不喜欢这个新特性。
可是我真的需要它,所以只好自己阅读 luajit 的源代码,给它打了个 patch 支持这个特性。
patch (基于 luajit 2.0 的 beta 11) 如下:
diff --git a/src/lib_base.c b/src/lib_base.c index 568216e..b58a5a4 100644 --- a/src/lib_base.c +++ b/src/lib_base.c @@ -363,6 +363,10 @@ static int load_aux(lua_State *L, int status, int envarg) GCtab *t = tabV(L->base+envarg-1); setgcref(fn->c.env, obj2gco(t)); lj_gc_objbarrier(L, fn, t); + if (LJ_52) { + lua_pushvalue(L, envarg); + lua_setupvalue(L, -2, 1); + } } return 1; } else { diff --git a/src/lj_lex.c b/src/lj_lex.c index b54d2a2..59b2b84 100644 --- a/src/lj_lex.c +++ b/src/lj_lex.c @@ -381,6 +381,7 @@ int lj_lex_setup(lua_State *L, LexState *ls) ls->lookahead = TK_eof; /* No look-ahead token. */ ls->linenumber = 1; ls->lastline = 1; + ls->env = NULL; lj_str_resizebuf(ls->L, &ls->sb, LJ_MIN_SBUF); next(ls); /* Read-ahead first char. */ if (ls->current == 0xef && ls->n >= 2 && char2int(ls->p[0]) == 0xbb && diff --git a/src/lj_lex.h b/src/lj_lex.h index d16461a..37c15eb 100644 --- a/src/lj_lex.h +++ b/src/lj_lex.h @@ -73,6 +73,7 @@ typedef struct LexState { BCInsLine *bcstack; /* Stack for bytecode instructions/line numbers. */ MSize sizebcstack; /* Size of bytecode stack. */ uint32_t level; /* Syntactical nesting level. */ + GCstr *env; /* const _ENV */ } LexState; LJ_FUNC int lj_lex_setup(lua_State *L, LexState *ls); diff --git a/src/lj_load.c b/src/lj_load.c index e30421e..5a389af 100644 --- a/src/lj_load.c +++ b/src/lj_load.c @@ -40,6 +40,9 @@ static TValue *cpparser(lua_State *L, lua_CFunction dummy, void *ud) } pt = bc ? lj_bcread(ls) : lj_parse(ls); fn = lj_func_newL_empty(L, pt, tabref(L->env)); + if (LJ_52) { + settabV(L, uvval(&gcref(fn->l.uvptr[0])->uv), tabref(L->env)); /* Set env table to upvalue 1 */ + } /* Don't combine above/below into one statement. */ setfuncV(L, L->top++, fn); return NULL; diff --git a/src/lj_parse.c b/src/lj_parse.c index 29def7b..2f435a5 100644 --- a/src/lj_parse.c +++ b/src/lj_parse.c @@ -1112,6 +1112,12 @@ static MSize var_lookup_(FuncState *fs, GCstr *name, ExpDesc *e, int first) fscope_uvmark(fs, reg); /* Scope now has an upvalue. */ return (MSize)(e->u.s.aux = (uint32_t)fs->varmap[reg]); } else { + if (LJ_52 && name == fs->ls->env && fs->prev == NULL) { + fscope_uvmark(fs,0); + expr_init(e, VUPVAL, 0); + e->u.s.aux = 0; + return 0; + } MSize vidx = var_lookup_(fs->prev, name, e, 0); /* Var in outer func? */ if ((int32_t)vidx >= 0) { /* Yes, make it an upvalue here. */ e->u.s.info = (uint8_t)var_lookup_uv(fs, vidx, e); @@ -1128,7 +1134,9 @@ static MSize var_lookup_(FuncState *fs, GCstr *name, ExpDesc *e, int first) /* Lookup variable name. */ #define var_lookup(ls, e) \ - var_lookup_((ls)->fs, lex_str(ls), (e), 1) + var_lookup_((ls)->fs, lex_str(ls), (e), 1); if (LJ_52 && (e)->k == VGLOBAL) var_global_((ls), (e)) + +static void var_global_(LexState *ls, ExpDesc *e); /* -- Goto an label handling ---------------------------------------------- */ @@ -1687,6 +1695,18 @@ static void expr_index(FuncState *fs, ExpDesc *t, ExpDesc *e) t->u.s.aux = expr_toanyreg(fs, e); /* 0..255: register */ } +/* Convert global to _ENV index. */ +static void var_global_(LexState *ls, ExpDesc *e) +{ + FuncState *fs = ls->fs; + ExpDesc key; + expr_init(&key, VKSTR, 0); + key.u.sval = e->u.sval; + var_lookup_(fs, ls->env, e, 1); + expr_toanyreg(fs, e); + expr_index(fs, e, &key); +} + /* Parse index expression with named field. */ static void expr_field(LexState *ls, ExpDesc *v) { @@ -2732,6 +2752,16 @@ GCproto *lj_parse(LexState *ls) fs.bcbase = NULL; fs.bclim = 0; fs.flags |= PROTO_VARARG; /* Main chunk is always a vararg func. */ + + if (LJ_52) { + /* Create upvalue named _ENV */ + ls->env = lj_parse_keepstr(ls, "_ENV", 4); /* Anchor _ENV string, 4 is sizeof _ENV */ + var_new(ls, 0, ls->env); + fs.uvmap[0] = 0; + fs.uvtmp[0] = 0; + fs.nuv = 1; + } + fscope_begin(&fs, &bl, 0); bcemit_AD(&fs, BC_FUNCV, 0, 0); /* Placeholder. */ lj_lex_next(ls); /* Read-ahead first token. */
Comments
Posted by: Insert | (8) September 2, 2014 09:51 AM
Posted by: Cloud | (7) October 26, 2012 10:27 AM
Posted by: dwing | (6) October 26, 2012 09:49 AM
Posted by: Sil | (5) October 26, 2012 09:19 AM
Posted by: 愿得风,死无憾 | (4) October 26, 2012 12:36 AM
Posted by: guest | (3) October 25, 2012 08:41 PM
Posted by: bg | (2) October 25, 2012 08:16 PM
Posted by: CoolDesert | (1) October 25, 2012 07:23 PM