diff options
author | Mike Pall <mike> | 2010-02-08 05:26:52 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2010-02-08 05:26:52 +0100 |
commit | 60b5af44222fff87a7184365a7f49654032d4cbf (patch) | |
tree | 9c108bc330f16ef8914c3bea84b5170000788932 /src | |
parent | 1307f49137f328b0880c736644755428d84be0ba (diff) | |
download | luajit-60b5af44222fff87a7184365a7f49654032d4cbf.tar.gz luajit-60b5af44222fff87a7184365a7f49654032d4cbf.tar.bz2 luajit-60b5af44222fff87a7184365a7f49654032d4cbf.zip |
Redesign of prototype generation, part 1: varinfo and uvname.
Use a growable, per-chunk variable stack.
Collect varinfo/uvname for prototype at the end.
Diffstat (limited to 'src')
-rw-r--r-- | src/lj_api.c | 6 | ||||
-rw-r--r-- | src/lj_errmsg.h | 1 | ||||
-rw-r--r-- | src/lj_gc.c | 6 | ||||
-rw-r--r-- | src/lj_lex.c | 14 | ||||
-rw-r--r-- | src/lj_lex.h | 6 | ||||
-rw-r--r-- | src/lj_parse.c | 172 |
6 files changed, 109 insertions, 96 deletions
diff --git a/src/lj_api.c b/src/lj_api.c index 8216c395..48bd605d 100644 --- a/src/lj_api.c +++ b/src/lj_api.c | |||
@@ -1102,7 +1102,7 @@ static TValue *cpparser(lua_State *L, lua_CFunction dummy, void *ud) | |||
1102 | GCfunc *fn; | 1102 | GCfunc *fn; |
1103 | UNUSED(dummy); | 1103 | UNUSED(dummy); |
1104 | cframe_errfunc(L->cframe) = -1; /* Inherit error function. */ | 1104 | cframe_errfunc(L->cframe) = -1; /* Inherit error function. */ |
1105 | lj_lex_start(L, ls); | 1105 | lj_lex_setup(L, ls); |
1106 | fn = lj_func_newL(L, lj_parse(ls), tabref(L->env)); | 1106 | fn = lj_func_newL(L, lj_parse(ls), tabref(L->env)); |
1107 | /* Parser may realloc stack. Don't combine above/below into one statement. */ | 1107 | /* Parser may realloc stack. Don't combine above/below into one statement. */ |
1108 | setfuncV(L, L->top++, fn); | 1108 | setfuncV(L, L->top++, fn); |
@@ -1114,14 +1114,12 @@ LUA_API int lua_load(lua_State *L, lua_Reader reader, void *data, | |||
1114 | { | 1114 | { |
1115 | LexState ls; | 1115 | LexState ls; |
1116 | int status; | 1116 | int status; |
1117 | global_State *g; | ||
1118 | ls.rfunc = reader; | 1117 | ls.rfunc = reader; |
1119 | ls.rdata = data; | 1118 | ls.rdata = data; |
1120 | ls.chunkarg = chunkname ? chunkname : "?"; | 1119 | ls.chunkarg = chunkname ? chunkname : "?"; |
1121 | lj_str_initbuf(L, &ls.sb); | 1120 | lj_str_initbuf(L, &ls.sb); |
1122 | status = lj_vm_cpcall(L, NULL, &ls, cpparser); | 1121 | status = lj_vm_cpcall(L, NULL, &ls, cpparser); |
1123 | g = G(L); | 1122 | lj_lex_cleanup(L, &ls); |
1124 | lj_str_freebuf(g, &ls.sb); | ||
1125 | lj_gc_check(L); | 1123 | lj_gc_check(L); |
1126 | return status; | 1124 | return status; |
1127 | } | 1125 | } |
diff --git a/src/lj_errmsg.h b/src/lj_errmsg.h index 826366a6..0a2d9dd7 100644 --- a/src/lj_errmsg.h +++ b/src/lj_errmsg.h | |||
@@ -118,6 +118,7 @@ ERRDEF(XBCLOAD, "cannot load Lua bytecode") | |||
118 | ERRDEF(XTOKEN, LUA_QS " expected") | 118 | ERRDEF(XTOKEN, LUA_QS " expected") |
119 | ERRDEF(XJUMP, "control structure too long") | 119 | ERRDEF(XJUMP, "control structure too long") |
120 | ERRDEF(XSLOTS, "function or expression too complex") | 120 | ERRDEF(XSLOTS, "function or expression too complex") |
121 | ERRDEF(XLIMC, "chunk has more than %d local variables") | ||
121 | ERRDEF(XLIMM, "main function has more than %d %s") | 122 | ERRDEF(XLIMM, "main function has more than %d %s") |
122 | ERRDEF(XLIMF, "function at line %d has more than %d %s") | 123 | ERRDEF(XLIMF, "function at line %d has more than %d %s") |
123 | ERRDEF(XMATCH, LUA_QS " expected (to close " LUA_QS " at line %d)") | 124 | ERRDEF(XMATCH, LUA_QS " expected (to close " LUA_QS " at line %d)") |
diff --git a/src/lj_gc.c b/src/lj_gc.c index c1ade95a..5750d0ef 100644 --- a/src/lj_gc.c +++ b/src/lj_gc.c | |||
@@ -256,11 +256,9 @@ static void gc_traverse_proto(global_State *g, GCproto *pt) | |||
256 | for (i = -(ptrdiff_t)pt->sizekgc; i < 0; i++) /* Mark collectable consts. */ | 256 | for (i = -(ptrdiff_t)pt->sizekgc; i < 0; i++) /* Mark collectable consts. */ |
257 | gc_markobj(g, proto_kgc(pt, i)); | 257 | gc_markobj(g, proto_kgc(pt, i)); |
258 | for (i = 0; i < (ptrdiff_t)pt->sizeuvname; i++) /* Mark upvalue names. */ | 258 | for (i = 0; i < (ptrdiff_t)pt->sizeuvname; i++) /* Mark upvalue names. */ |
259 | if (proto_uvname(pt, i)) | 259 | gc_mark_str(gco2str(proto_uvname(pt, i))); |
260 | gc_mark_str(gco2str(proto_uvname(pt, i))); | ||
261 | for (i = 0; i < (ptrdiff_t)pt->sizevarinfo; i++) /* Mark names of locals. */ | 260 | for (i = 0; i < (ptrdiff_t)pt->sizevarinfo; i++) /* Mark names of locals. */ |
262 | if (gcref(proto_varinfo(pt)[i].name)) | 261 | gc_mark_str(gco2str(gcref(proto_varinfo(pt)[i].name))); |
263 | gc_mark_str(gco2str(gcref(proto_varinfo(pt)[i].name))); | ||
264 | } | 262 | } |
265 | 263 | ||
266 | /* Traverse the frame structure of a stack. */ | 264 | /* Traverse the frame structure of a stack. */ |
diff --git a/src/lj_lex.c b/src/lj_lex.c index d1df138e..28aad901 100644 --- a/src/lj_lex.c +++ b/src/lj_lex.c | |||
@@ -301,12 +301,16 @@ static int llex(LexState *ls, TValue *tv) | |||
301 | 301 | ||
302 | /* -- Lexer API ----------------------------------------------------------- */ | 302 | /* -- Lexer API ----------------------------------------------------------- */ |
303 | 303 | ||
304 | void lj_lex_start(lua_State *L, LexState *ls) | 304 | /* Setup lexer state. */ |
305 | void lj_lex_setup(lua_State *L, LexState *ls) | ||
305 | { | 306 | { |
306 | ls->L = L; | 307 | ls->L = L; |
307 | ls->fs = NULL; | 308 | ls->fs = NULL; |
308 | ls->n = 0; | 309 | ls->n = 0; |
309 | ls->p = NULL; | 310 | ls->p = NULL; |
311 | ls->vstack = NULL; | ||
312 | ls->sizevstack = 0; | ||
313 | ls->vtop = 0; | ||
310 | ls->lookahead = TK_eof; /* No look-ahead token. */ | 314 | ls->lookahead = TK_eof; /* No look-ahead token. */ |
311 | ls->linenumber = 1; | 315 | ls->linenumber = 1; |
312 | ls->lastline = 1; | 316 | ls->lastline = 1; |
@@ -335,6 +339,14 @@ void lj_lex_start(lua_State *L, LexState *ls) | |||
335 | ls->chunkname = lj_str_newz(L, ls->chunkarg); | 339 | ls->chunkname = lj_str_newz(L, ls->chunkarg); |
336 | } | 340 | } |
337 | 341 | ||
342 | /* Cleanup lexer state. */ | ||
343 | void lj_lex_cleanup(lua_State *L, LexState *ls) | ||
344 | { | ||
345 | global_State *g = G(L); | ||
346 | lj_mem_freevec(g, ls->vstack, ls->sizevstack, VarInfo); | ||
347 | lj_str_freebuf(g, &ls->sb); | ||
348 | } | ||
349 | |||
338 | void lj_lex_next(LexState *ls) | 350 | void lj_lex_next(LexState *ls) |
339 | { | 351 | { |
340 | ls->lastline = ls->linenumber; | 352 | ls->lastline = ls->linenumber; |
diff --git a/src/lj_lex.h b/src/lj_lex.h index cc5d5a9f..ee183b40 100644 --- a/src/lj_lex.h +++ b/src/lj_lex.h | |||
@@ -50,10 +50,14 @@ typedef struct LexState { | |||
50 | BCLine lastline; /* Line of last token. */ | 50 | BCLine lastline; /* Line of last token. */ |
51 | GCstr *chunkname; /* Current chunk name (interned string). */ | 51 | GCstr *chunkname; /* Current chunk name (interned string). */ |
52 | const char *chunkarg; /* Chunk name argument. */ | 52 | const char *chunkarg; /* Chunk name argument. */ |
53 | VarInfo *vstack; /* Stack for names and extents of local variables. */ | ||
54 | MSize sizevstack; /* Size of variable stack. */ | ||
55 | MSize vtop; /* Top of variable stack. */ | ||
53 | uint32_t level; /* Syntactical nesting level. */ | 56 | uint32_t level; /* Syntactical nesting level. */ |
54 | } LexState; | 57 | } LexState; |
55 | 58 | ||
56 | LJ_FUNC void lj_lex_start(lua_State *L, LexState *ls); | 59 | LJ_FUNC void lj_lex_setup(lua_State *L, LexState *ls); |
60 | LJ_FUNC void lj_lex_cleanup(lua_State *L, LexState *ls); | ||
57 | LJ_FUNC void lj_lex_next(LexState *ls); | 61 | LJ_FUNC void lj_lex_next(LexState *ls); |
58 | LJ_FUNC LexToken lj_lex_lookahead(LexState *ls); | 62 | LJ_FUNC LexToken lj_lex_lookahead(LexState *ls); |
59 | LJ_FUNC const char *lj_lex_token2str(LexState *ls, LexToken token); | 63 | LJ_FUNC const char *lj_lex_token2str(LexState *ls, LexToken token); |
diff --git a/src/lj_parse.c b/src/lj_parse.c index 96136280..d949698f 100644 --- a/src/lj_parse.c +++ b/src/lj_parse.c | |||
@@ -88,11 +88,15 @@ typedef struct FuncScope { | |||
88 | uint8_t isbreakable; /* Scope is a loop and allows a break. */ | 88 | uint8_t isbreakable; /* Scope is a loop and allows a break. */ |
89 | } FuncScope; | 89 | } FuncScope; |
90 | 90 | ||
91 | /* Upvalue type and location. */ | 91 | /* Index into variable stack. */ |
92 | typedef struct UVLoc { | 92 | typedef uint16_t VarIndex; |
93 | uint8_t k; /* Upvalue type (ExpKind). */ | 93 | #define LJ_MAX_VSTACK 65536 |
94 | uint8_t info; /* Upvalue location (BCReg or uvidx). */ | 94 | |
95 | } UVLoc; | 95 | /* Upvalue map. */ |
96 | typedef struct UVMap { | ||
97 | VarIndex vidx; /* Varinfo index. */ | ||
98 | uint16_t slot; /* Slot or parent upvalue index. */ | ||
99 | } UVMap; | ||
96 | 100 | ||
97 | /* Per-function state. */ | 101 | /* Per-function state. */ |
98 | typedef struct FuncState { | 102 | typedef struct FuncState { |
@@ -108,13 +112,13 @@ typedef struct FuncState { | |||
108 | BCReg freereg; /* First free register. */ | 112 | BCReg freereg; /* First free register. */ |
109 | BCReg nkn, nkgc; /* Number of lua_Number/GCobj constants */ | 113 | BCReg nkn, nkgc; /* Number of lua_Number/GCobj constants */ |
110 | BCLine linedefined; /* First line of the function definition. */ | 114 | BCLine linedefined; /* First line of the function definition. */ |
111 | MSize nvarinfo; /* Number of entries in varinfo. */ | 115 | MSize vbase; /* Base of variable stack for this function. */ |
112 | uint8_t nactvar; /* Number of active local variables. */ | 116 | uint8_t nactvar; /* Number of active local variables. */ |
113 | uint8_t flags; /* Prototype flags. */ | 117 | uint8_t flags; /* Prototype flags. */ |
114 | uint8_t framesize; /* Fixed frame size. */ | 118 | uint8_t framesize; /* Fixed frame size. */ |
115 | uint8_t nuv; /* Number of upvalues */ | 119 | uint8_t nuv; /* Number of upvalues */ |
116 | uint16_t varmap[LJ_MAX_LOCVAR]; /* Map from register to varinfo index. */ | 120 | VarIndex varmap[LJ_MAX_LOCVAR]; /* Map from register to variable idx. */ |
117 | UVLoc uvloc[LJ_MAX_UPVAL]; /* Upvalue type and location. */ | 121 | UVMap uvloc[LJ_MAX_UPVAL]; /* Map from upvalue to variable idx and slot. */ |
118 | } FuncState; | 122 | } FuncState; |
119 | 123 | ||
120 | /* Binary and unary operators. ORDER OPR */ | 124 | /* Binary and unary operators. ORDER OPR */ |
@@ -924,28 +928,27 @@ static GCstr *lex_str(LexState *ls) | |||
924 | 928 | ||
925 | /* -- Variable handling --------------------------------------------------- */ | 929 | /* -- Variable handling --------------------------------------------------- */ |
926 | 930 | ||
927 | #define var_get(fs, i) (proto_varinfo((fs)->pt)[(fs)->varmap[(i)]]) | 931 | #define var_get(ls, fs, i) ((ls)->vstack[(fs)->varmap[(i)]]) |
928 | 932 | ||
929 | /* Define a new local variable. */ | 933 | /* Define a new local variable. */ |
930 | static void var_new(LexState *ls, BCReg n, GCstr *name) | 934 | static void var_new(LexState *ls, BCReg n, GCstr *name) |
931 | { | 935 | { |
932 | FuncState *fs = ls->fs; | 936 | FuncState *fs = ls->fs; |
933 | GCproto *pt = fs->pt; | 937 | MSize vtop = ls->vtop; |
934 | VarInfo *varinfo = proto_varinfo(pt); | ||
935 | checklimit(fs, fs->nactvar+n, LJ_MAX_LOCVAR, "local variables"); | 938 | checklimit(fs, fs->nactvar+n, LJ_MAX_LOCVAR, "local variables"); |
936 | if (LJ_UNLIKELY(fs->nvarinfo >= pt->sizevarinfo)) { | 939 | if (LJ_UNLIKELY(vtop >= ls->sizevstack)) { |
937 | MSize oldsize = pt->sizevarinfo; | 940 | if (ls->sizevstack >= LJ_MAX_VSTACK) |
938 | checklimit(fs, fs->nvarinfo, 32767, "local variables"); | 941 | lj_lex_error(ls, 0, LJ_ERR_XLIMC, LJ_MAX_VSTACK); |
939 | lj_mem_growvec(fs->L, varinfo, pt->sizevarinfo, 32767, VarInfo); | 942 | lj_mem_growvec(ls->L, ls->vstack, ls->sizevstack, LJ_MAX_VSTACK, VarInfo); |
940 | setmref(pt->varinfo, varinfo); | ||
941 | while (oldsize < pt->sizevarinfo) setgcrefnull(varinfo[oldsize++].name); | ||
942 | } | 943 | } |
943 | setgcref(varinfo[fs->nvarinfo].name, obj2gco(name)); | 944 | lua_assert(lj_tab_getstr(fs->kt, name) != NULL); |
944 | lj_gc_objbarrier(ls->L, pt, name); | 945 | /* NOBARRIER: name is anchored in fs->kt and ls->vstack is not a GCobj. */ |
945 | fs->varmap[fs->nactvar+n] = (uint16_t)(fs->nvarinfo++); | 946 | setgcref(ls->vstack[vtop].name, obj2gco(name)); |
947 | fs->varmap[fs->nactvar+n] = (uint16_t)vtop; | ||
948 | ls->vtop = vtop+1; | ||
946 | } | 949 | } |
947 | 950 | ||
948 | #define var_new_lit(ls, v, n) \ | 951 | #define var_new_lit(ls, n, v) \ |
949 | var_new(ls, (n), lj_parse_keepstr(ls, "" v, sizeof(v)-1)) | 952 | var_new(ls, (n), lj_parse_keepstr(ls, "" v, sizeof(v)-1)) |
950 | 953 | ||
951 | /* Add local variables. */ | 954 | /* Add local variables. */ |
@@ -954,7 +957,7 @@ static void var_add(LexState *ls, BCReg nvars) | |||
954 | FuncState *fs = ls->fs; | 957 | FuncState *fs = ls->fs; |
955 | fs->nactvar = cast_byte(fs->nactvar + nvars); | 958 | fs->nactvar = cast_byte(fs->nactvar + nvars); |
956 | for (; nvars; nvars--) | 959 | for (; nvars; nvars--) |
957 | var_get(fs, fs->nactvar - nvars).startpc = fs->pc; | 960 | var_get(ls, fs, fs->nactvar - nvars).startpc = fs->pc; |
958 | } | 961 | } |
959 | 962 | ||
960 | /* Remove local variables. */ | 963 | /* Remove local variables. */ |
@@ -962,7 +965,7 @@ static void var_remove(LexState *ls, BCReg tolevel) | |||
962 | { | 965 | { |
963 | FuncState *fs = ls->fs; | 966 | FuncState *fs = ls->fs; |
964 | while (fs->nactvar > tolevel) | 967 | while (fs->nactvar > tolevel) |
965 | var_get(fs, --fs->nactvar).endpc = fs->pc; | 968 | var_get(ls, fs, --fs->nactvar).endpc = fs->pc; |
966 | } | 969 | } |
967 | 970 | ||
968 | /* Lookup local variable name. */ | 971 | /* Lookup local variable name. */ |
@@ -970,46 +973,33 @@ static BCReg var_lookup_local(FuncState *fs, GCstr *n) | |||
970 | { | 973 | { |
971 | int i; | 974 | int i; |
972 | for (i = fs->nactvar-1; i >= 0; i--) { | 975 | for (i = fs->nactvar-1; i >= 0; i--) { |
973 | if (n == gco2str(gcref(var_get(fs, i).name))) | 976 | if (n == gco2str(gcref(var_get(fs->ls, fs, i).name))) |
974 | return (BCReg)i; | 977 | return (BCReg)i; |
975 | } | 978 | } |
976 | return (BCReg)-1; /* Not found. */ | 979 | return (BCReg)-1; /* Not found. */ |
977 | } | 980 | } |
978 | 981 | ||
979 | /* Lookup upvalue name. */ | 982 | /* Lookup or add upvalue index. */ |
980 | static uint32_t var_lookup_uv(FuncState *fs, GCstr *name, ExpDesc *v) | 983 | static MSize var_lookup_uv(FuncState *fs, MSize vidx, ExpDesc *e) |
981 | { | 984 | { |
982 | uint32_t i; | 985 | MSize i, n = fs->nuv; |
983 | GCproto *pt = fs->pt; | 986 | for (i = 0; i < n; i++) |
984 | GCRef *uvname; | 987 | if (fs->uvloc[i].vidx == vidx) |
985 | for (i = 0; i < fs->nuv; i++) { | 988 | return i; /* Already exists. */ |
986 | if (fs->uvloc[i].info == v->u.s.info && fs->uvloc[i].k == v->k) { | 989 | /* Otherwise create a new one. */ |
987 | lua_assert(gco2str(proto_uvname(pt, i)) == name); | 990 | checklimit(fs, fs->nuv, LJ_MAX_UPVAL, "upvalues"); |
988 | return i; | 991 | lua_assert(e->k == VLOCAL || e->k == VUPVAL); |
989 | } | 992 | fs->uvloc[n].vidx = (uint16_t)vidx; |
990 | } | 993 | fs->uvloc[n].slot = (uint16_t)(e->u.s.info | (e->k == VLOCAL ? 0x8000 : 0)); |
991 | /* Not found, create a new upvalue for this name. */ | 994 | fs->nuv = n+1; |
992 | uvname = mref(pt->uvname, GCRef); | 995 | return n; |
993 | if (LJ_UNLIKELY(fs->nuv >= pt->sizeuvname)) { | ||
994 | MSize oldsize = pt->sizeuvname; | ||
995 | checklimit(fs, fs->nuv, LJ_MAX_UPVAL, "upvalues"); | ||
996 | lj_mem_growvec(fs->L, uvname, pt->sizeuvname, LJ_MAX_UPVAL, GCRef); | ||
997 | setmref(pt->uvname, uvname); | ||
998 | while (oldsize < pt->sizeuvname) setgcrefnull(uvname[oldsize++]); | ||
999 | } | ||
1000 | setgcref(uvname[fs->nuv], obj2gco(name)); | ||
1001 | lj_gc_objbarrier(fs->L, pt, name); | ||
1002 | lua_assert(v->k == VLOCAL || v->k == VUPVAL); | ||
1003 | fs->uvloc[fs->nuv].k = cast_byte(v->k); | ||
1004 | fs->uvloc[fs->nuv].info = cast_byte(v->u.s.info); | ||
1005 | return fs->nuv++; | ||
1006 | } | 996 | } |
1007 | 997 | ||
1008 | /* Forward declaration. */ | 998 | /* Forward declaration. */ |
1009 | static void scope_uvmark(FuncState *fs, BCReg level); | 999 | static void scope_uvmark(FuncState *fs, BCReg level); |
1010 | 1000 | ||
1011 | /* Recursively lookup variables in enclosing functions. */ | 1001 | /* Recursively lookup variables in enclosing functions. */ |
1012 | static int var_lookup_(FuncState *fs, GCstr *name, ExpDesc *e, int first) | 1002 | static MSize var_lookup_(FuncState *fs, GCstr *name, ExpDesc *e, int first) |
1013 | { | 1003 | { |
1014 | if (fs) { | 1004 | if (fs) { |
1015 | BCReg reg = var_lookup_local(fs, name); | 1005 | BCReg reg = var_lookup_local(fs, name); |
@@ -1017,17 +1007,20 @@ static int var_lookup_(FuncState *fs, GCstr *name, ExpDesc *e, int first) | |||
1017 | expr_init(e, VLOCAL, reg); | 1007 | expr_init(e, VLOCAL, reg); |
1018 | if (!first) | 1008 | if (!first) |
1019 | scope_uvmark(fs, reg); /* Scope now has an upvalue. */ | 1009 | scope_uvmark(fs, reg); /* Scope now has an upvalue. */ |
1020 | return 1; | 1010 | return (MSize)fs->varmap[reg]; |
1021 | } else if (var_lookup_(fs->prev, name, e, 0)) { /* In outer function? */ | 1011 | } else { |
1022 | e->u.s.info = var_lookup_uv(fs, name, e); /* Make it an upvalue here. */ | 1012 | MSize vidx = var_lookup_(fs->prev, name, e, 0); /* Var in outer func? */ |
1023 | e->k = VUPVAL; | 1013 | if ((int32_t)vidx >= 0) { /* Yes, make it an upvalue here. */ |
1024 | return 1; | 1014 | e->u.s.info = (uint8_t)var_lookup_uv(fs, vidx, e); |
1015 | e->k = VUPVAL; | ||
1016 | return vidx; | ||
1017 | } | ||
1025 | } | 1018 | } |
1026 | } else { /* Not found in any function, must be a global. */ | 1019 | } else { /* Not found in any function, must be a global. */ |
1027 | expr_init(e, VGLOBAL, 0); | 1020 | expr_init(e, VGLOBAL, 0); |
1028 | e->u.sval = name; | 1021 | e->u.sval = name; |
1029 | } | 1022 | } |
1030 | return 0; /* Global. */ | 1023 | return (MSize)-1; /* Global. */ |
1031 | } | 1024 | } |
1032 | 1025 | ||
1033 | /* Lookup variable name. */ | 1026 | /* Lookup variable name. */ |
@@ -1080,15 +1073,12 @@ static void fs_fixup_k(FuncState *fs, GCproto *pt) | |||
1080 | /* Fixup upvalues for prototype. */ | 1073 | /* Fixup upvalues for prototype. */ |
1081 | static void fs_fixup_uv(FuncState *fs, GCproto *pt) | 1074 | static void fs_fixup_uv(FuncState *fs, GCproto *pt) |
1082 | { | 1075 | { |
1083 | uint32_t i; | 1076 | MSize i, n = fs->nuv; |
1084 | uint16_t *uv = lj_mem_newvec(fs->L, fs->nuv, uint16_t); | 1077 | uint16_t *uv = lj_mem_newvec(fs->L, n, uint16_t); |
1085 | setmref(pt->uv, uv); | 1078 | setmref(pt->uv, uv); |
1086 | pt->sizeuv = fs->nuv; | 1079 | pt->sizeuv = n; |
1087 | for (i = 0; i < pt->sizeuv; i++) { | 1080 | for (i = 0; i < n; i++) |
1088 | uint32_t v = fs->uvloc[i].info; | 1081 | uv[i] = fs->uvloc[i].slot; |
1089 | if (fs->uvloc[i].k == VLOCAL) v |= 0x8000; | ||
1090 | uv[i] = (uint16_t)v; | ||
1091 | } | ||
1092 | } | 1082 | } |
1093 | 1083 | ||
1094 | /* Check if bytecode op returns. */ | 1084 | /* Check if bytecode op returns. */ |
@@ -1143,9 +1133,7 @@ static GCproto *fs_finish(LexState *ls, BCLine line) | |||
1143 | FuncState *fs = ls->fs; | 1133 | FuncState *fs = ls->fs; |
1144 | GCproto *pt = fs->pt; | 1134 | GCproto *pt = fs->pt; |
1145 | BCIns *bc; | 1135 | BCIns *bc; |
1146 | GCRef *uvname; | ||
1147 | BCLine *lineinfo; | 1136 | BCLine *lineinfo; |
1148 | VarInfo *varinfo; | ||
1149 | 1137 | ||
1150 | /* Apply final fixups. */ | 1138 | /* Apply final fixups. */ |
1151 | var_remove(ls, 0); | 1139 | var_remove(ls, 0); |
@@ -1156,21 +1144,31 @@ static GCproto *fs_finish(LexState *ls, BCLine line) | |||
1156 | lj_mem_reallocvec(L, bc, pt->sizebc, fs->pc, BCIns); | 1144 | lj_mem_reallocvec(L, bc, pt->sizebc, fs->pc, BCIns); |
1157 | setmref(pt->bc, bc); | 1145 | setmref(pt->bc, bc); |
1158 | pt->sizebc = fs->pc; | 1146 | pt->sizebc = fs->pc; |
1147 | |||
1159 | fs_fixup_k(fs, pt); | 1148 | fs_fixup_k(fs, pt); |
1160 | fs_fixup_uv(fs, pt); | 1149 | fs_fixup_uv(fs, pt); |
1150 | |||
1161 | lineinfo = proto_lineinfo(pt); | 1151 | lineinfo = proto_lineinfo(pt); |
1162 | lj_mem_reallocvec(L, lineinfo, pt->sizelineinfo, fs->pc, BCLine); | 1152 | lj_mem_reallocvec(L, lineinfo, pt->sizelineinfo, fs->pc, BCLine); |
1163 | setmref(pt->lineinfo, lineinfo); | 1153 | setmref(pt->lineinfo, lineinfo); |
1164 | pt->sizelineinfo = fs->pc; | 1154 | pt->sizelineinfo = fs->pc; |
1165 | varinfo = proto_varinfo(pt); | 1155 | |
1166 | lj_mem_reallocvec(L, varinfo, pt->sizevarinfo, fs->nvarinfo, VarInfo); | 1156 | { |
1167 | setmref(pt->varinfo, varinfo); | 1157 | MSize n = ls->vtop - fs->vbase; |
1168 | pt->sizevarinfo = fs->nvarinfo; | 1158 | VarInfo *vi = lj_mem_newvec(L, n, VarInfo); |
1169 | uvname = mref(pt->uvname, GCRef); | 1159 | memcpy(vi, &ls->vstack[fs->vbase], n*sizeof(VarInfo)); |
1170 | lj_mem_reallocvec(L, uvname, pt->sizeuvname, fs->nuv, GCRef); | 1160 | setmref(pt->varinfo, vi); |
1171 | setmref(pt->uvname, uvname); | 1161 | pt->sizevarinfo = n; |
1172 | pt->sizeuvname = fs->nuv; | 1162 | } |
1173 | lua_assert(fs->bl == NULL); | 1163 | |
1164 | { | ||
1165 | MSize i, n = fs->nuv; | ||
1166 | GCRef *uvname = lj_mem_newvec(L, n, GCRef); | ||
1167 | for (i = 0; i < n; i++) | ||
1168 | setgcref(uvname[i], gcref(ls->vstack[fs->uvloc[i].vidx].name)); | ||
1169 | setmref(pt->uvname, uvname); | ||
1170 | pt->sizeuvname = n; | ||
1171 | } | ||
1174 | 1172 | ||
1175 | /* Initialize prototype fields. */ | 1173 | /* Initialize prototype fields. */ |
1176 | pt->flags = fs->flags; | 1174 | pt->flags = fs->flags; |
@@ -1182,7 +1180,9 @@ static GCproto *fs_finish(LexState *ls, BCLine line) | |||
1182 | setprotoV(L, L->top++, pt); | 1180 | setprotoV(L, L->top++, pt); |
1183 | ); | 1181 | ); |
1184 | 1182 | ||
1185 | /* Remove FuncState from list. Pop const table and prototype. */ | 1183 | /* Remove VarInfo and FuncState. Pop const table and prototype. */ |
1184 | lua_assert(fs->bl == NULL); | ||
1185 | ls->vtop = fs->vbase; | ||
1186 | ls->fs = fs->prev; | 1186 | ls->fs = fs->prev; |
1187 | L->top -= 2; | 1187 | L->top -= 2; |
1188 | lua_assert(ls->fs != NULL || ls->token == TK_eof); | 1188 | lua_assert(ls->fs != NULL || ls->token == TK_eof); |
@@ -1202,6 +1202,7 @@ static void fs_init(LexState *ls, FuncState *fs, BCLine line) | |||
1202 | fs->pt = pt; | 1202 | fs->pt = pt; |
1203 | fs->prev = ls->fs; ls->fs = fs; /* Append to list. */ | 1203 | fs->prev = ls->fs; ls->fs = fs; /* Append to list. */ |
1204 | fs->ls = ls; | 1204 | fs->ls = ls; |
1205 | fs->vbase = ls->vtop; | ||
1205 | fs->L = L; | 1206 | fs->L = L; |
1206 | fs->pc = 0; | 1207 | fs->pc = 0; |
1207 | fs->lasttarget = 0; | 1208 | fs->lasttarget = 0; |
@@ -1209,7 +1210,6 @@ static void fs_init(LexState *ls, FuncState *fs, BCLine line) | |||
1209 | fs->freereg = 0; | 1210 | fs->freereg = 0; |
1210 | fs->nkgc = 0; | 1211 | fs->nkgc = 0; |
1211 | fs->nkn = 0; | 1212 | fs->nkn = 0; |
1212 | fs->nvarinfo = 0; | ||
1213 | fs->nactvar = 0; | 1213 | fs->nactvar = 0; |
1214 | fs->nuv = 0; | 1214 | fs->nuv = 0; |
1215 | fs->bl = NULL; | 1215 | fs->bl = NULL; |
@@ -1382,7 +1382,7 @@ static void parse_params(LexState *ls, int needself) | |||
1382 | BCReg nparams = 0; | 1382 | BCReg nparams = 0; |
1383 | lex_check(ls, '('); | 1383 | lex_check(ls, '('); |
1384 | if (needself) { | 1384 | if (needself) { |
1385 | var_new_lit(ls, "self", 0); | 1385 | var_new_lit(ls, 0, "self"); |
1386 | var_add(ls, 1); | 1386 | var_add(ls, 1); |
1387 | } | 1387 | } |
1388 | if (ls->token != ')') { | 1388 | if (ls->token != ')') { |
@@ -1921,7 +1921,7 @@ static void parse_local(LexState *ls) | |||
1921 | parse_body(ls, &b, 0, ls->linenumber); | 1921 | parse_body(ls, &b, 0, ls->linenumber); |
1922 | bcemit_store(fs, &v, &b); | 1922 | bcemit_store(fs, &v, &b); |
1923 | /* The upvalue is in scope, but the local is only valid after the store. */ | 1923 | /* The upvalue is in scope, but the local is only valid after the store. */ |
1924 | var_get(fs, fs->nactvar - 1).startpc = fs->pc; | 1924 | var_get(ls, fs, fs->nactvar - 1).startpc = fs->pc; |
1925 | } else { /* Local variable declaration. */ | 1925 | } else { /* Local variable declaration. */ |
1926 | ExpDesc e; | 1926 | ExpDesc e; |
1927 | BCReg nexps, nvars = 0; | 1927 | BCReg nexps, nvars = 0; |
@@ -2045,9 +2045,9 @@ static void parse_for_num(LexState *ls, GCstr *varname, BCLine line) | |||
2045 | FuncState *fs = ls->fs; | 2045 | FuncState *fs = ls->fs; |
2046 | BCReg base = fs->freereg; | 2046 | BCReg base = fs->freereg; |
2047 | /* Hidden control variables. */ | 2047 | /* Hidden control variables. */ |
2048 | var_new_lit(ls, "(for index)", FORL_IDX); | 2048 | var_new_lit(ls, FORL_IDX, "(for index)"); |
2049 | var_new_lit(ls, "(for limit)", FORL_STOP); | 2049 | var_new_lit(ls, FORL_STOP, "(for limit)"); |
2050 | var_new_lit(ls, "(for step)", FORL_STEP); | 2050 | var_new_lit(ls, FORL_STEP, "(for step)"); |
2051 | /* Visible copy of index variable. */ | 2051 | /* Visible copy of index variable. */ |
2052 | var_new(ls, FORL_EXT, varname); | 2052 | var_new(ls, FORL_EXT, varname); |
2053 | lex_check(ls, '='); | 2053 | lex_check(ls, '='); |
@@ -2072,9 +2072,9 @@ static void parse_for_iter(LexState *ls, GCstr *indexname) | |||
2072 | BCLine line; | 2072 | BCLine line; |
2073 | BCReg base = fs->freereg; | 2073 | BCReg base = fs->freereg; |
2074 | /* Hidden control variables. */ | 2074 | /* Hidden control variables. */ |
2075 | var_new_lit(ls, "(for generator)", nvars++); | 2075 | var_new_lit(ls, nvars++, "(for generator)"); |
2076 | var_new_lit(ls, "(for state)", nvars++); | 2076 | var_new_lit(ls, nvars++, "(for state)"); |
2077 | var_new_lit(ls, "(for control)", nvars++); | 2077 | var_new_lit(ls, nvars++, "(for control)"); |
2078 | /* Visible variables returned from iterator. */ | 2078 | /* Visible variables returned from iterator. */ |
2079 | var_new(ls, nvars++, indexname); | 2079 | var_new(ls, nvars++, indexname); |
2080 | while (lex_opt(ls, ',')) | 2080 | while (lex_opt(ls, ',')) |