diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/host/genlibbc.lua | 91 | ||||
-rw-r--r-- | src/jit/bcsave.lua | 31 | ||||
-rw-r--r-- | src/lib_base.c | 6 | ||||
-rw-r--r-- | src/lib_jit.c | 26 | ||||
-rw-r--r-- | src/lib_string.c | 22 | ||||
-rw-r--r-- | src/lj_bcdump.h | 4 | ||||
-rw-r--r-- | src/lj_bcread.c | 9 | ||||
-rw-r--r-- | src/lj_bcwrite.c | 109 | ||||
-rw-r--r-- | src/lj_lex.c | 1 | ||||
-rw-r--r-- | src/lj_lex.h | 1 | ||||
-rw-r--r-- | src/lj_lib.c | 18 | ||||
-rw-r--r-- | src/lj_lib.h | 1 | ||||
-rw-r--r-- | src/lj_load.c | 29 | ||||
-rw-r--r-- | src/lj_parse.c | 28 |
14 files changed, 260 insertions, 116 deletions
diff --git a/src/host/genlibbc.lua b/src/host/genlibbc.lua index 3621c3f5..e697fceb 100644 --- a/src/host/genlibbc.lua +++ b/src/host/genlibbc.lua | |||
@@ -138,65 +138,73 @@ local function fixup_dump(dump, fixup) | |||
138 | return { dump = ndump, startbc = startbc, sizebc = sizebc } | 138 | return { dump = ndump, startbc = startbc, sizebc = sizebc } |
139 | end | 139 | end |
140 | 140 | ||
141 | local function find_defs(src) | 141 | local function find_defs(src, mode) |
142 | local defs = {} | 142 | local defs = {} |
143 | for name, code in string.gmatch(src, "LJLIB_LUA%(([^)]*)%)%s*/%*(.-)%*/") do | 143 | for name, code in string.gmatch(src, "LJLIB_LUA%(([^)]*)%)%s*/%*(.-)%*/") do |
144 | local env = {} | ||
145 | local tcode, fixup = transform_lua(code) | 144 | local tcode, fixup = transform_lua(code) |
146 | local func = assert(load(tcode, "", nil, env))() | 145 | local func = assert(load(tcode, "", mode)) |
147 | defs[name] = fixup_dump(string.dump(func, true), fixup) | 146 | defs[name] = fixup_dump(string.dump(func, mode), fixup) |
148 | defs[#defs+1] = name | 147 | defs[#defs+1] = name |
149 | end | 148 | end |
150 | return defs | 149 | return defs |
151 | end | 150 | end |
152 | 151 | ||
153 | local function gen_header(defs) | 152 | local function gen_header(defs32, defs64) |
154 | local t = {} | 153 | local t = {} |
155 | local function w(x) t[#t+1] = x end | 154 | local function w(x) t[#t+1] = x end |
156 | w("/* This is a generated file. DO NOT EDIT! */\n\n") | 155 | w("/* This is a generated file. DO NOT EDIT! */\n\n") |
157 | w("static const int libbc_endian = ") w(isbe and 1 or 0) w(";\n\n") | 156 | w("static const int libbc_endian = ") w(isbe and 1 or 0) w(";\n\n") |
158 | local s, sb = "", "" | 157 | for j,defs in ipairs{defs64, defs32} do |
159 | for i,name in ipairs(defs) do | 158 | local s, sb = "", "" |
160 | local d = defs[name] | 159 | for i,name in ipairs(defs) do |
161 | s = s .. d.dump | 160 | local d = defs[name] |
162 | sb = sb .. string.char(i) .. ("\0"):rep(d.startbc - 1) | 161 | s = s .. d.dump |
163 | .. (isbe and "\0\0\0\255" or "\255\0\0\0"):rep(d.sizebc) | 162 | sb = sb .. string.char(i) .. ("\0"):rep(d.startbc - 1) |
164 | .. ("\0"):rep(#d.dump - d.startbc - d.sizebc*4) | 163 | .. (isbe and "\0\0\0\255" or "\255\0\0\0"):rep(d.sizebc) |
165 | end | 164 | .. ("\0"):rep(#d.dump - d.startbc - d.sizebc*4) |
166 | w("static const uint8_t libbc_code[] = {\n") | 165 | end |
167 | local n = 0 | 166 | if j == 1 then |
168 | for i=1,#s do | 167 | w("static const uint8_t libbc_code[] = {\n#if LJ_FR2\n") |
169 | local x = string.byte(s, i) | ||
170 | local xb = string.byte(sb, i) | ||
171 | if xb == 255 then | ||
172 | local name = BCN[x] | ||
173 | local m = #name + 4 | ||
174 | if n + m > 78 then n = 0; w("\n") end | ||
175 | n = n + m | ||
176 | w("BC_"); w(name) | ||
177 | else | 168 | else |
178 | local m = x < 10 and 2 or (x < 100 and 3 or 4) | 169 | w("\n#else\n") |
179 | if xb == 0 then | 170 | end |
171 | local n = 0 | ||
172 | for i=1,#s do | ||
173 | local x = string.byte(s, i) | ||
174 | local xb = string.byte(sb, i) | ||
175 | if xb == 255 then | ||
176 | local name = BCN[x] | ||
177 | local m = #name + 4 | ||
180 | if n + m > 78 then n = 0; w("\n") end | 178 | if n + m > 78 then n = 0; w("\n") end |
179 | n = n + m | ||
180 | w("BC_"); w(name) | ||
181 | else | 181 | else |
182 | local name = defs[xb]:gsub("_", ".") | 182 | local m = x < 10 and 2 or (x < 100 and 3 or 4) |
183 | if n ~= 0 then w("\n") end | 183 | if xb == 0 then |
184 | w("/* "); w(name); w(" */ ") | 184 | if n + m > 78 then n = 0; w("\n") end |
185 | n = #name + 7 | 185 | else |
186 | local name = defs[xb]:gsub("_", ".") | ||
187 | if n ~= 0 then w("\n") end | ||
188 | w("/* "); w(name); w(" */ ") | ||
189 | n = #name + 7 | ||
190 | end | ||
191 | n = n + m | ||
192 | w(x) | ||
186 | end | 193 | end |
187 | n = n + m | 194 | w(",") |
188 | w(x) | ||
189 | end | 195 | end |
190 | w(",") | ||
191 | end | 196 | end |
192 | w("\n0\n};\n\n") | 197 | w("\n#endif\n0\n};\n\n") |
193 | w("static const struct { const char *name; int ofs; } libbc_map[] = {\n") | 198 | w("static const struct { const char *name; int ofs; } libbc_map[] = {\n") |
194 | local m = 0 | 199 | local m32, m64 = 0, 0 |
195 | for _,name in ipairs(defs) do | 200 | for i,name in ipairs(defs32) do |
196 | w('{"'); w(name); w('",'); w(m) w('},\n') | 201 | assert(name == defs64[i]) |
197 | m = m + #defs[name].dump | 202 | w('{"'); w(name); w('",'); w(m32) w('},\n') |
203 | m32 = m32 + #defs32[name].dump | ||
204 | m64 = m64 + #defs64[name].dump | ||
205 | assert(m32 == m64) | ||
198 | end | 206 | end |
199 | w("{NULL,"); w(m); w("}\n};\n\n") | 207 | w("{NULL,"); w(m32); w("}\n};\n\n") |
200 | return table.concat(t) | 208 | return table.concat(t) |
201 | end | 209 | end |
202 | 210 | ||
@@ -219,7 +227,8 @@ end | |||
219 | 227 | ||
220 | local outfile = parse_arg(arg) | 228 | local outfile = parse_arg(arg) |
221 | local src = read_files(arg) | 229 | local src = read_files(arg) |
222 | local defs = find_defs(src) | 230 | local defs32 = find_defs(src, "Wdts") |
223 | local hdr = gen_header(defs) | 231 | local defs64 = find_defs(src, "Xdts") |
232 | local hdr = gen_header(defs32, defs64) | ||
224 | write_file(outfile, hdr) | 233 | write_file(outfile, hdr) |
225 | 234 | ||
diff --git a/src/jit/bcsave.lua b/src/jit/bcsave.lua index 390d297c..131bf39b 100644 --- a/src/jit/bcsave.lua +++ b/src/jit/bcsave.lua | |||
@@ -29,6 +29,9 @@ Save LuaJIT bytecode: luajit -b[options] input output | |||
29 | -l Only list bytecode. | 29 | -l Only list bytecode. |
30 | -s Strip debug info (default). | 30 | -s Strip debug info (default). |
31 | -g Keep debug info. | 31 | -g Keep debug info. |
32 | -W Generate 32 bit (non-GC64) bytecode. | ||
33 | -X Generate 64 bit (GC64) bytecode. | ||
34 | -d Generate bytecode in deterministic manner. | ||
32 | -n name Set module name (default: auto-detect from input name). | 35 | -n name Set module name (default: auto-detect from input name). |
33 | -t type Set output file type (default: auto-detect from output name). | 36 | -t type Set output file type (default: auto-detect from output name). |
34 | -a arch Override architecture for object files (default: native). | 37 | -a arch Override architecture for object files (default: native). |
@@ -51,8 +54,9 @@ local function check(ok, ...) | |||
51 | end | 54 | end |
52 | 55 | ||
53 | local function readfile(ctx, input) | 56 | local function readfile(ctx, input) |
54 | if type(input) == "function" then return input end | 57 | if ctx.string then |
55 | if ctx.filename then | 58 | return check(loadstring(input, nil, ctx.mode)) |
59 | elseif ctx.filename then | ||
56 | local data | 60 | local data |
57 | if input == "-" then | 61 | if input == "-" then |
58 | data = io.stdin:read("*a") | 62 | data = io.stdin:read("*a") |
@@ -61,10 +65,10 @@ local function readfile(ctx, input) | |||
61 | data = assert(fp:read("*a")) | 65 | data = assert(fp:read("*a")) |
62 | assert(fp:close()) | 66 | assert(fp:close()) |
63 | end | 67 | end |
64 | return check(load(data, ctx.filename)) | 68 | return check(load(data, ctx.filename, ctx.mode)) |
65 | else | 69 | else |
66 | if input == "-" then input = nil end | 70 | if input == "-" then input = nil end |
67 | return check(loadfile(input)) | 71 | return check(loadfile(input, ctx.mode)) |
68 | end | 72 | end |
69 | end | 73 | end |
70 | 74 | ||
@@ -624,7 +628,7 @@ end | |||
624 | 628 | ||
625 | local function bcsave(ctx, input, output) | 629 | local function bcsave(ctx, input, output) |
626 | local f = readfile(ctx, input) | 630 | local f = readfile(ctx, input) |
627 | local s = string.dump(f, ctx.strip) | 631 | local s = string.dump(f, ctx.mode) |
628 | local t = ctx.type | 632 | local t = ctx.type |
629 | if not t then | 633 | if not t then |
630 | t = detecttype(output) | 634 | t = detecttype(output) |
@@ -647,9 +651,11 @@ local function docmd(...) | |||
647 | local n = 1 | 651 | local n = 1 |
648 | local list = false | 652 | local list = false |
649 | local ctx = { | 653 | local ctx = { |
650 | strip = true, arch = jit.arch, os = jit.os:lower(), | 654 | mode = "bt", arch = jit.arch, os = jit.os:lower(), |
651 | type = false, modname = false, | 655 | type = false, modname = false, string = false, |
652 | } | 656 | } |
657 | local strip = "s" | ||
658 | local gc64 = "" | ||
653 | while n <= #arg do | 659 | while n <= #arg do |
654 | local a = arg[n] | 660 | local a = arg[n] |
655 | if type(a) == "string" and a:sub(1, 1) == "-" and a ~= "-" then | 661 | if type(a) == "string" and a:sub(1, 1) == "-" and a ~= "-" then |
@@ -660,14 +666,18 @@ local function docmd(...) | |||
660 | if opt == "l" then | 666 | if opt == "l" then |
661 | list = true | 667 | list = true |
662 | elseif opt == "s" then | 668 | elseif opt == "s" then |
663 | ctx.strip = true | 669 | strip = "s" |
664 | elseif opt == "g" then | 670 | elseif opt == "g" then |
665 | ctx.strip = false | 671 | strip = "" |
672 | elseif opt == "W" or opt == "X" then | ||
673 | gc64 = opt | ||
674 | elseif opt == "d" then | ||
675 | ctx.mode = ctx.mode .. opt | ||
666 | else | 676 | else |
667 | if arg[n] == nil or m ~= #a then usage() end | 677 | if arg[n] == nil or m ~= #a then usage() end |
668 | if opt == "e" then | 678 | if opt == "e" then |
669 | if n ~= 1 then usage() end | 679 | if n ~= 1 then usage() end |
670 | arg[1] = check(loadstring(arg[1])) | 680 | ctx.string = true |
671 | elseif opt == "n" then | 681 | elseif opt == "n" then |
672 | ctx.modname = checkmodname(tremove(arg, n)) | 682 | ctx.modname = checkmodname(tremove(arg, n)) |
673 | elseif opt == "t" then | 683 | elseif opt == "t" then |
@@ -687,6 +697,7 @@ local function docmd(...) | |||
687 | n = n + 1 | 697 | n = n + 1 |
688 | end | 698 | end |
689 | end | 699 | end |
700 | ctx.mode = ctx.mode .. strip .. gc64 | ||
690 | if list then | 701 | if list then |
691 | if #arg == 0 or #arg > 2 then usage() end | 702 | if #arg == 0 or #arg > 2 then usage() end |
692 | bclist(ctx, arg[1], arg[2] or "-") | 703 | bclist(ctx, arg[1], arg[2] or "-") |
diff --git a/src/lib_base.c b/src/lib_base.c index 4e6f8a30..d644b4f2 100644 --- a/src/lib_base.c +++ b/src/lib_base.c | |||
@@ -360,7 +360,11 @@ LJLIB_ASM_(xpcall) LJLIB_REC(.) | |||
360 | static int load_aux(lua_State *L, int status, int envarg) | 360 | static int load_aux(lua_State *L, int status, int envarg) |
361 | { | 361 | { |
362 | if (status == LUA_OK) { | 362 | if (status == LUA_OK) { |
363 | if (tvistab(L->base+envarg-1)) { | 363 | /* |
364 | ** Set environment table for top-level function. | ||
365 | ** Don't do this for non-native bytecode, which returns a prototype. | ||
366 | */ | ||
367 | if (tvistab(L->base+envarg-1) && tvisfunc(L->top-1)) { | ||
364 | GCfunc *fn = funcV(L->top-1); | 368 | GCfunc *fn = funcV(L->top-1); |
365 | GCtab *t = tabV(L->base+envarg-1); | 369 | GCtab *t = tabV(L->base+envarg-1); |
366 | setgcref(fn->c.env, obj2gco(t)); | 370 | setgcref(fn->c.env, obj2gco(t)); |
diff --git a/src/lib_jit.c b/src/lib_jit.c index c0294927..b83c865a 100644 --- a/src/lib_jit.c +++ b/src/lib_jit.c | |||
@@ -161,24 +161,6 @@ LJLIB_PUSH(top-2) LJLIB_SET(version) | |||
161 | 161 | ||
162 | /* -- Reflection API for Lua functions ------------------------------------ */ | 162 | /* -- Reflection API for Lua functions ------------------------------------ */ |
163 | 163 | ||
164 | /* Return prototype of first argument (Lua function or prototype object) */ | ||
165 | static GCproto *check_Lproto(lua_State *L, int nolua) | ||
166 | { | ||
167 | TValue *o = L->base; | ||
168 | if (L->top > o) { | ||
169 | if (tvisproto(o)) { | ||
170 | return protoV(o); | ||
171 | } else if (tvisfunc(o)) { | ||
172 | if (isluafunc(funcV(o))) | ||
173 | return funcproto(funcV(o)); | ||
174 | else if (nolua) | ||
175 | return NULL; | ||
176 | } | ||
177 | } | ||
178 | lj_err_argt(L, 1, LUA_TFUNCTION); | ||
179 | return NULL; /* unreachable */ | ||
180 | } | ||
181 | |||
182 | static void setintfield(lua_State *L, GCtab *t, const char *name, int32_t val) | 164 | static void setintfield(lua_State *L, GCtab *t, const char *name, int32_t val) |
183 | { | 165 | { |
184 | setintV(lj_tab_setstr(L, t, lj_str_newz(L, name)), val); | 166 | setintV(lj_tab_setstr(L, t, lj_str_newz(L, name)), val); |
@@ -187,7 +169,7 @@ static void setintfield(lua_State *L, GCtab *t, const char *name, int32_t val) | |||
187 | /* local info = jit.util.funcinfo(func [,pc]) */ | 169 | /* local info = jit.util.funcinfo(func [,pc]) */ |
188 | LJLIB_CF(jit_util_funcinfo) | 170 | LJLIB_CF(jit_util_funcinfo) |
189 | { | 171 | { |
190 | GCproto *pt = check_Lproto(L, 1); | 172 | GCproto *pt = lj_lib_checkLproto(L, 1, 1); |
191 | if (pt) { | 173 | if (pt) { |
192 | BCPos pc = (BCPos)lj_lib_optint(L, 2, 0); | 174 | BCPos pc = (BCPos)lj_lib_optint(L, 2, 0); |
193 | GCtab *t; | 175 | GCtab *t; |
@@ -229,7 +211,7 @@ LJLIB_CF(jit_util_funcinfo) | |||
229 | /* local ins, m = jit.util.funcbc(func, pc) */ | 211 | /* local ins, m = jit.util.funcbc(func, pc) */ |
230 | LJLIB_CF(jit_util_funcbc) | 212 | LJLIB_CF(jit_util_funcbc) |
231 | { | 213 | { |
232 | GCproto *pt = check_Lproto(L, 0); | 214 | GCproto *pt = lj_lib_checkLproto(L, 1, 0); |
233 | BCPos pc = (BCPos)lj_lib_checkint(L, 2); | 215 | BCPos pc = (BCPos)lj_lib_checkint(L, 2); |
234 | if (pc < pt->sizebc) { | 216 | if (pc < pt->sizebc) { |
235 | BCIns ins = proto_bc(pt)[pc]; | 217 | BCIns ins = proto_bc(pt)[pc]; |
@@ -246,7 +228,7 @@ LJLIB_CF(jit_util_funcbc) | |||
246 | /* local k = jit.util.funck(func, idx) */ | 228 | /* local k = jit.util.funck(func, idx) */ |
247 | LJLIB_CF(jit_util_funck) | 229 | LJLIB_CF(jit_util_funck) |
248 | { | 230 | { |
249 | GCproto *pt = check_Lproto(L, 0); | 231 | GCproto *pt = lj_lib_checkLproto(L, 1, 0); |
250 | ptrdiff_t idx = (ptrdiff_t)lj_lib_checkint(L, 2); | 232 | ptrdiff_t idx = (ptrdiff_t)lj_lib_checkint(L, 2); |
251 | if (idx >= 0) { | 233 | if (idx >= 0) { |
252 | if (idx < (ptrdiff_t)pt->sizekn) { | 234 | if (idx < (ptrdiff_t)pt->sizekn) { |
@@ -266,7 +248,7 @@ LJLIB_CF(jit_util_funck) | |||
266 | /* local name = jit.util.funcuvname(func, idx) */ | 248 | /* local name = jit.util.funcuvname(func, idx) */ |
267 | LJLIB_CF(jit_util_funcuvname) | 249 | LJLIB_CF(jit_util_funcuvname) |
268 | { | 250 | { |
269 | GCproto *pt = check_Lproto(L, 0); | 251 | GCproto *pt = lj_lib_checkLproto(L, 1, 0); |
270 | uint32_t idx = (uint32_t)lj_lib_checkint(L, 2); | 252 | uint32_t idx = (uint32_t)lj_lib_checkint(L, 2); |
271 | if (idx < pt->sizeuv) { | 253 | if (idx < pt->sizeuv) { |
272 | setstrV(L, L->top-1, lj_str_newz(L, lj_debug_uvname(pt, idx))); | 254 | setstrV(L, L->top-1, lj_str_newz(L, lj_debug_uvname(pt, idx))); |
diff --git a/src/lib_string.c b/src/lib_string.c index 29bcb8fe..255689ce 100644 --- a/src/lib_string.c +++ b/src/lib_string.c | |||
@@ -122,11 +122,25 @@ static int writer_buf(lua_State *L, const void *p, size_t size, void *sb) | |||
122 | 122 | ||
123 | LJLIB_CF(string_dump) | 123 | LJLIB_CF(string_dump) |
124 | { | 124 | { |
125 | GCfunc *fn = lj_lib_checkfunc(L, 1); | 125 | GCproto *pt = lj_lib_checkLproto(L, 1, 1); |
126 | int strip = L->base+1 < L->top && tvistruecond(L->base+1); | 126 | uint32_t flags = 0; |
127 | SBuf *sb = lj_buf_tmp_(L); /* Assumes lj_bcwrite() doesn't use tmpbuf. */ | 127 | SBuf *sb; |
128 | TValue *o = L->base+1; | ||
129 | if (o < L->top) { | ||
130 | if (tvisstr(o)) { | ||
131 | const char *mode = strVdata(o); | ||
132 | char c; | ||
133 | while ((c = *mode++)) { | ||
134 | if (c == 's') flags |= BCDUMP_F_STRIP; | ||
135 | if (c == 'd') flags |= BCDUMP_F_DETERMINISTIC; | ||
136 | } | ||
137 | } else if (tvistruecond(o)) { | ||
138 | flags |= BCDUMP_F_STRIP; | ||
139 | } | ||
140 | } | ||
141 | sb = lj_buf_tmp_(L); /* Assumes lj_bcwrite() doesn't use tmpbuf. */ | ||
128 | L->top = L->base+1; | 142 | L->top = L->base+1; |
129 | if (!isluafunc(fn) || lj_bcwrite(L, funcproto(fn), writer_buf, sb, strip)) | 143 | if (!pt || lj_bcwrite(L, pt, writer_buf, sb, flags)) |
130 | lj_err_caller(L, LJ_ERR_STRDUMP); | 144 | lj_err_caller(L, LJ_ERR_STRDUMP); |
131 | setstrV(L, L->top-1, lj_buf_str(L, sb)); | 145 | setstrV(L, L->top-1, lj_buf_str(L, sb)); |
132 | lj_gc_check(L); | 146 | lj_gc_check(L); |
diff --git a/src/lj_bcdump.h b/src/lj_bcdump.h index 6ba71e25..3e56e39c 100644 --- a/src/lj_bcdump.h +++ b/src/lj_bcdump.h | |||
@@ -46,6 +46,8 @@ | |||
46 | 46 | ||
47 | #define BCDUMP_F_KNOWN (BCDUMP_F_FR2*2-1) | 47 | #define BCDUMP_F_KNOWN (BCDUMP_F_FR2*2-1) |
48 | 48 | ||
49 | #define BCDUMP_F_DETERMINISTIC 0x80000000 | ||
50 | |||
49 | /* Type codes for the GC constants of a prototype. Plus length for strings. */ | 51 | /* Type codes for the GC constants of a prototype. Plus length for strings. */ |
50 | enum { | 52 | enum { |
51 | BCDUMP_KGC_CHILD, BCDUMP_KGC_TAB, BCDUMP_KGC_I64, BCDUMP_KGC_U64, | 53 | BCDUMP_KGC_CHILD, BCDUMP_KGC_TAB, BCDUMP_KGC_I64, BCDUMP_KGC_U64, |
@@ -61,7 +63,7 @@ enum { | |||
61 | /* -- Bytecode reader/writer ---------------------------------------------- */ | 63 | /* -- Bytecode reader/writer ---------------------------------------------- */ |
62 | 64 | ||
63 | LJ_FUNC int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, | 65 | LJ_FUNC int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, |
64 | void *data, int strip); | 66 | void *data, uint32_t flags); |
65 | LJ_FUNC GCproto *lj_bcread_proto(LexState *ls); | 67 | LJ_FUNC GCproto *lj_bcread_proto(LexState *ls); |
66 | LJ_FUNC GCproto *lj_bcread(LexState *ls); | 68 | LJ_FUNC GCproto *lj_bcread(LexState *ls); |
67 | 69 | ||
diff --git a/src/lj_bcread.c b/src/lj_bcread.c index c98c0d42..637ef067 100644 --- a/src/lj_bcread.c +++ b/src/lj_bcread.c | |||
@@ -281,8 +281,11 @@ static void bcread_knum(LexState *ls, GCproto *pt, MSize sizekn) | |||
281 | static void bcread_bytecode(LexState *ls, GCproto *pt, MSize sizebc) | 281 | static void bcread_bytecode(LexState *ls, GCproto *pt, MSize sizebc) |
282 | { | 282 | { |
283 | BCIns *bc = proto_bc(pt); | 283 | BCIns *bc = proto_bc(pt); |
284 | bc[0] = BCINS_AD((pt->flags & PROTO_VARARG) ? BC_FUNCV : BC_FUNCF, | 284 | BCIns op; |
285 | pt->framesize, 0); | 285 | if (ls->fr2 != LJ_FR2) op = BC_NOT; /* Mark non-native prototype. */ |
286 | else if ((pt->flags & PROTO_VARARG)) op = BC_FUNCV; | ||
287 | else op = BC_FUNCF; | ||
288 | bc[0] = BCINS_AD(op, pt->framesize, 0); | ||
286 | bcread_block(ls, bc+1, (sizebc-1)*(MSize)sizeof(BCIns)); | 289 | bcread_block(ls, bc+1, (sizebc-1)*(MSize)sizeof(BCIns)); |
287 | /* Swap bytecode instructions if the endianess differs. */ | 290 | /* Swap bytecode instructions if the endianess differs. */ |
288 | if (bcread_swap(ls)) { | 291 | if (bcread_swap(ls)) { |
@@ -395,7 +398,7 @@ static int bcread_header(LexState *ls) | |||
395 | bcread_byte(ls) != BCDUMP_VERSION) return 0; | 398 | bcread_byte(ls) != BCDUMP_VERSION) return 0; |
396 | bcread_flags(ls) = flags = bcread_uleb128(ls); | 399 | bcread_flags(ls) = flags = bcread_uleb128(ls); |
397 | if ((flags & ~(BCDUMP_F_KNOWN)) != 0) return 0; | 400 | if ((flags & ~(BCDUMP_F_KNOWN)) != 0) return 0; |
398 | if ((flags & BCDUMP_F_FR2) != LJ_FR2*BCDUMP_F_FR2) return 0; | 401 | if ((flags & BCDUMP_F_FR2) != (uint32_t)ls->fr2*BCDUMP_F_FR2) return 0; |
399 | if ((flags & BCDUMP_F_FFI)) { | 402 | if ((flags & BCDUMP_F_FFI)) { |
400 | #if LJ_HASFFI | 403 | #if LJ_HASFFI |
401 | lua_State *L = ls->L; | 404 | lua_State *L = ls->L; |
diff --git a/src/lj_bcwrite.c b/src/lj_bcwrite.c index dd969413..c062dc49 100644 --- a/src/lj_bcwrite.c +++ b/src/lj_bcwrite.c | |||
@@ -27,7 +27,9 @@ typedef struct BCWriteCtx { | |||
27 | GCproto *pt; /* Root prototype. */ | 27 | GCproto *pt; /* Root prototype. */ |
28 | lua_Writer wfunc; /* Writer callback. */ | 28 | lua_Writer wfunc; /* Writer callback. */ |
29 | void *wdata; /* Writer callback data. */ | 29 | void *wdata; /* Writer callback data. */ |
30 | int strip; /* Strip debug info. */ | 30 | TValue **heap; /* Heap used for deterministic sorting. */ |
31 | uint32_t heapsz; /* Size of heap. */ | ||
32 | uint32_t flags; /* BCDUMP_F_* flags. */ | ||
31 | int status; /* Status from writer callback. */ | 33 | int status; /* Status from writer callback. */ |
32 | #ifdef LUA_USE_ASSERT | 34 | #ifdef LUA_USE_ASSERT |
33 | global_State *g; | 35 | global_State *g; |
@@ -76,6 +78,75 @@ static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow) | |||
76 | ctx->sb.w = p; | 78 | ctx->sb.w = p; |
77 | } | 79 | } |
78 | 80 | ||
81 | /* Compare two template table keys. */ | ||
82 | static LJ_AINLINE int bcwrite_ktabk_lt(TValue *a, TValue *b) | ||
83 | { | ||
84 | uint32_t at = itype(a), bt = itype(b); | ||
85 | if (at != bt) { /* This also handles false and true keys. */ | ||
86 | return at < bt; | ||
87 | } else if (at == LJ_TSTR) { | ||
88 | return lj_str_cmp(strV(a), strV(b)) < 0; | ||
89 | } else { | ||
90 | return a->u64 < b->u64; /* This works for numbers and integers. */ | ||
91 | } | ||
92 | } | ||
93 | |||
94 | /* Insert key into a sorted heap. */ | ||
95 | static void bcwrite_ktabk_heap_insert(TValue **heap, MSize idx, MSize end, | ||
96 | TValue *key) | ||
97 | { | ||
98 | MSize child; | ||
99 | while ((child = idx * 2 + 1) < end) { | ||
100 | /* Find lower of the two children. */ | ||
101 | TValue *c0 = heap[child]; | ||
102 | if (child + 1 < end) { | ||
103 | TValue *c1 = heap[child + 1]; | ||
104 | if (bcwrite_ktabk_lt(c1, c0)) { | ||
105 | c0 = c1; | ||
106 | child++; | ||
107 | } | ||
108 | } | ||
109 | if (bcwrite_ktabk_lt(key, c0)) break; /* Key lower? Found our position. */ | ||
110 | heap[idx] = c0; /* Move lower child up. */ | ||
111 | idx = child; /* Descend. */ | ||
112 | } | ||
113 | heap[idx] = key; /* Insert key here. */ | ||
114 | } | ||
115 | |||
116 | /* Resize heap, dropping content. */ | ||
117 | static void bcwrite_heap_resize(BCWriteCtx *ctx, uint32_t nsz) | ||
118 | { | ||
119 | lua_State *L = sbufL(&ctx->sb); | ||
120 | if (ctx->heapsz) { | ||
121 | lj_mem_freevec(G(L), ctx->heap, ctx->heapsz, TValue *); | ||
122 | ctx->heapsz = 0; | ||
123 | } | ||
124 | if (nsz) { | ||
125 | ctx->heap = lj_mem_newvec(L, nsz, TValue *); | ||
126 | ctx->heapsz = nsz; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | /* Write hash part of template table in sorted order. */ | ||
131 | static void bcwrite_ktab_sorted_hash(BCWriteCtx *ctx, Node *node, MSize nhash) | ||
132 | { | ||
133 | TValue **heap = ctx->heap; | ||
134 | MSize i = nhash; | ||
135 | for (;; node--) { /* Build heap. */ | ||
136 | if (!tvisnil(&node->val)) { | ||
137 | bcwrite_ktabk_heap_insert(heap, --i, nhash, &node->key); | ||
138 | if (i == 0) break; | ||
139 | } | ||
140 | } | ||
141 | do { /* Drain heap. */ | ||
142 | TValue *key = heap[0]; /* Output lowest key from top. */ | ||
143 | bcwrite_ktabk(ctx, key, 0); | ||
144 | bcwrite_ktabk(ctx, (TValue *)((char *)key - offsetof(Node, key)), 1); | ||
145 | key = heap[--nhash]; /* Remove last key. */ | ||
146 | bcwrite_ktabk_heap_insert(heap, 0, nhash, key); /* Re-insert. */ | ||
147 | } while (nhash); | ||
148 | } | ||
149 | |||
79 | /* Write a template table. */ | 150 | /* Write a template table. */ |
80 | static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t) | 151 | static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t) |
81 | { | 152 | { |
@@ -105,14 +176,20 @@ static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t) | |||
105 | bcwrite_ktabk(ctx, o, 1); | 176 | bcwrite_ktabk(ctx, o, 1); |
106 | } | 177 | } |
107 | if (nhash) { /* Write hash entries. */ | 178 | if (nhash) { /* Write hash entries. */ |
108 | MSize i = nhash; | ||
109 | Node *node = noderef(t->node) + t->hmask; | 179 | Node *node = noderef(t->node) + t->hmask; |
110 | for (;; node--) | 180 | if ((ctx->flags & BCDUMP_F_DETERMINISTIC) && nhash > 1) { |
111 | if (!tvisnil(&node->val)) { | 181 | if (ctx->heapsz < nhash) |
112 | bcwrite_ktabk(ctx, &node->key, 0); | 182 | bcwrite_heap_resize(ctx, t->hmask + 1); |
113 | bcwrite_ktabk(ctx, &node->val, 1); | 183 | bcwrite_ktab_sorted_hash(ctx, node, nhash); |
114 | if (--i == 0) break; | 184 | } else { |
115 | } | 185 | MSize i = nhash; |
186 | for (;; node--) | ||
187 | if (!tvisnil(&node->val)) { | ||
188 | bcwrite_ktabk(ctx, &node->key, 0); | ||
189 | bcwrite_ktabk(ctx, &node->val, 1); | ||
190 | if (--i == 0) break; | ||
191 | } | ||
192 | } | ||
116 | } | 193 | } |
117 | } | 194 | } |
118 | 195 | ||
@@ -269,7 +346,7 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) | |||
269 | p = lj_strfmt_wuleb128(p, pt->sizekgc); | 346 | p = lj_strfmt_wuleb128(p, pt->sizekgc); |
270 | p = lj_strfmt_wuleb128(p, pt->sizekn); | 347 | p = lj_strfmt_wuleb128(p, pt->sizekn); |
271 | p = lj_strfmt_wuleb128(p, pt->sizebc-1); | 348 | p = lj_strfmt_wuleb128(p, pt->sizebc-1); |
272 | if (!ctx->strip) { | 349 | if (!(ctx->flags & BCDUMP_F_STRIP)) { |
273 | if (proto_lineinfo(pt)) | 350 | if (proto_lineinfo(pt)) |
274 | sizedbg = pt->sizept - (MSize)((char *)proto_lineinfo(pt) - (char *)pt); | 351 | sizedbg = pt->sizept - (MSize)((char *)proto_lineinfo(pt) - (char *)pt); |
275 | p = lj_strfmt_wuleb128(p, sizedbg); | 352 | p = lj_strfmt_wuleb128(p, sizedbg); |
@@ -317,11 +394,10 @@ static void bcwrite_header(BCWriteCtx *ctx) | |||
317 | *p++ = BCDUMP_HEAD2; | 394 | *p++ = BCDUMP_HEAD2; |
318 | *p++ = BCDUMP_HEAD3; | 395 | *p++ = BCDUMP_HEAD3; |
319 | *p++ = BCDUMP_VERSION; | 396 | *p++ = BCDUMP_VERSION; |
320 | *p++ = (ctx->strip ? BCDUMP_F_STRIP : 0) + | 397 | *p++ = (ctx->flags & (BCDUMP_F_STRIP | BCDUMP_F_FR2)) + |
321 | LJ_BE*BCDUMP_F_BE + | 398 | LJ_BE*BCDUMP_F_BE + |
322 | ((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0) + | 399 | ((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0); |
323 | LJ_FR2*BCDUMP_F_FR2; | 400 | if (!(ctx->flags & BCDUMP_F_STRIP)) { |
324 | if (!ctx->strip) { | ||
325 | p = lj_strfmt_wuleb128(p, len); | 401 | p = lj_strfmt_wuleb128(p, len); |
326 | p = lj_buf_wmem(p, name, len); | 402 | p = lj_buf_wmem(p, name, len); |
327 | } | 403 | } |
@@ -352,14 +428,16 @@ static TValue *cpwriter(lua_State *L, lua_CFunction dummy, void *ud) | |||
352 | 428 | ||
353 | /* Write bytecode for a prototype. */ | 429 | /* Write bytecode for a prototype. */ |
354 | int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, void *data, | 430 | int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, void *data, |
355 | int strip) | 431 | uint32_t flags) |
356 | { | 432 | { |
357 | BCWriteCtx ctx; | 433 | BCWriteCtx ctx; |
358 | int status; | 434 | int status; |
359 | ctx.pt = pt; | 435 | ctx.pt = pt; |
360 | ctx.wfunc = writer; | 436 | ctx.wfunc = writer; |
361 | ctx.wdata = data; | 437 | ctx.wdata = data; |
362 | ctx.strip = strip; | 438 | ctx.heapsz = 0; |
439 | if ((bc_op(proto_bc(pt)[0]) != BC_NOT) == LJ_FR2) flags |= BCDUMP_F_FR2; | ||
440 | ctx.flags = flags; | ||
363 | ctx.status = 0; | 441 | ctx.status = 0; |
364 | #ifdef LUA_USE_ASSERT | 442 | #ifdef LUA_USE_ASSERT |
365 | ctx.g = G(L); | 443 | ctx.g = G(L); |
@@ -368,6 +446,7 @@ int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, void *data, | |||
368 | status = lj_vm_cpcall(L, NULL, &ctx, cpwriter); | 446 | status = lj_vm_cpcall(L, NULL, &ctx, cpwriter); |
369 | if (status == 0) status = ctx.status; | 447 | if (status == 0) status = ctx.status; |
370 | lj_buf_free(G(sbufL(&ctx.sb)), &ctx.sb); | 448 | lj_buf_free(G(sbufL(&ctx.sb)), &ctx.sb); |
449 | bcwrite_heap_resize(&ctx, 0); | ||
371 | return status; | 450 | return status; |
372 | } | 451 | } |
373 | 452 | ||
diff --git a/src/lj_lex.c b/src/lj_lex.c index 61b04c4b..bd81dc40 100644 --- a/src/lj_lex.c +++ b/src/lj_lex.c | |||
@@ -411,6 +411,7 @@ int lj_lex_setup(lua_State *L, LexState *ls) | |||
411 | ls->linenumber = 1; | 411 | ls->linenumber = 1; |
412 | ls->lastline = 1; | 412 | ls->lastline = 1; |
413 | ls->endmark = 0; | 413 | ls->endmark = 0; |
414 | ls->fr2 = LJ_FR2; /* Generate native bytecode by default. */ | ||
414 | lex_next(ls); /* Read-ahead first char. */ | 415 | lex_next(ls); /* Read-ahead first char. */ |
415 | if (ls->c == 0xef && ls->p + 2 <= ls->pe && (uint8_t)ls->p[0] == 0xbb && | 416 | if (ls->c == 0xef && ls->p + 2 <= ls->pe && (uint8_t)ls->p[0] == 0xbb && |
416 | (uint8_t)ls->p[1] == 0xbf) { /* Skip UTF-8 BOM (if buffered). */ | 417 | (uint8_t)ls->p[1] == 0xbf) { /* Skip UTF-8 BOM (if buffered). */ |
diff --git a/src/lj_lex.h b/src/lj_lex.h index e46fbd89..2ef7fc77 100644 --- a/src/lj_lex.h +++ b/src/lj_lex.h | |||
@@ -74,6 +74,7 @@ typedef struct LexState { | |||
74 | MSize sizebcstack; /* Size of bytecode stack. */ | 74 | MSize sizebcstack; /* Size of bytecode stack. */ |
75 | uint32_t level; /* Syntactical nesting level. */ | 75 | uint32_t level; /* Syntactical nesting level. */ |
76 | int endmark; /* Trust bytecode end marker, even if not at EOF. */ | 76 | int endmark; /* Trust bytecode end marker, even if not at EOF. */ |
77 | int fr2; /* Generate bytecode for LJ_FR2 mode. */ | ||
77 | } LexState; | 78 | } LexState; |
78 | 79 | ||
79 | LJ_FUNC int lj_lex_setup(lua_State *L, LexState *ls); | 80 | LJ_FUNC int lj_lex_setup(lua_State *L, LexState *ls); |
diff --git a/src/lj_lib.c b/src/lj_lib.c index ebe0dc78..06ae4fcf 100644 --- a/src/lj_lib.c +++ b/src/lj_lib.c | |||
@@ -62,6 +62,7 @@ static const uint8_t *lib_read_lfunc(lua_State *L, const uint8_t *p, GCtab *tab) | |||
62 | ls.pe = (const char *)~(uintptr_t)0; | 62 | ls.pe = (const char *)~(uintptr_t)0; |
63 | ls.c = -1; | 63 | ls.c = -1; |
64 | ls.level = (BCDUMP_F_STRIP|(LJ_BE*BCDUMP_F_BE)); | 64 | ls.level = (BCDUMP_F_STRIP|(LJ_BE*BCDUMP_F_BE)); |
65 | ls.fr2 = LJ_FR2; | ||
65 | ls.chunkname = name; | 66 | ls.chunkname = name; |
66 | pt = lj_bcread_proto(&ls); | 67 | pt = lj_bcread_proto(&ls); |
67 | pt->firstline = ~(BCLine)0; | 68 | pt->firstline = ~(BCLine)0; |
@@ -266,6 +267,23 @@ GCfunc *lj_lib_checkfunc(lua_State *L, int narg) | |||
266 | return funcV(o); | 267 | return funcV(o); |
267 | } | 268 | } |
268 | 269 | ||
270 | GCproto *lj_lib_checkLproto(lua_State *L, int narg, int nolua) | ||
271 | { | ||
272 | TValue *o = L->base + narg-1; | ||
273 | if (L->top > o) { | ||
274 | if (tvisproto(o)) { | ||
275 | return protoV(o); | ||
276 | } else if (tvisfunc(o)) { | ||
277 | if (isluafunc(funcV(o))) | ||
278 | return funcproto(funcV(o)); | ||
279 | else if (nolua) | ||
280 | return NULL; | ||
281 | } | ||
282 | } | ||
283 | lj_err_argt(L, narg, LUA_TFUNCTION); | ||
284 | return NULL; /* unreachable */ | ||
285 | } | ||
286 | |||
269 | GCtab *lj_lib_checktab(lua_State *L, int narg) | 287 | GCtab *lj_lib_checktab(lua_State *L, int narg) |
270 | { | 288 | { |
271 | TValue *o = L->base + narg-1; | 289 | TValue *o = L->base + narg-1; |
diff --git a/src/lj_lib.h b/src/lj_lib.h index 6c3a1c83..a48e3c98 100644 --- a/src/lj_lib.h +++ b/src/lj_lib.h | |||
@@ -42,6 +42,7 @@ LJ_FUNC lua_Number lj_lib_checknum(lua_State *L, int narg); | |||
42 | LJ_FUNC int32_t lj_lib_checkint(lua_State *L, int narg); | 42 | LJ_FUNC int32_t lj_lib_checkint(lua_State *L, int narg); |
43 | LJ_FUNC int32_t lj_lib_optint(lua_State *L, int narg, int32_t def); | 43 | LJ_FUNC int32_t lj_lib_optint(lua_State *L, int narg, int32_t def); |
44 | LJ_FUNC GCfunc *lj_lib_checkfunc(lua_State *L, int narg); | 44 | LJ_FUNC GCfunc *lj_lib_checkfunc(lua_State *L, int narg); |
45 | LJ_FUNC GCproto *lj_lib_checkLproto(lua_State *L, int narg, int nolua); | ||
45 | LJ_FUNC GCtab *lj_lib_checktab(lua_State *L, int narg); | 46 | LJ_FUNC GCtab *lj_lib_checktab(lua_State *L, int narg); |
46 | LJ_FUNC GCtab *lj_lib_checktabornil(lua_State *L, int narg); | 47 | LJ_FUNC GCtab *lj_lib_checktabornil(lua_State *L, int narg); |
47 | LJ_FUNC int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst); | 48 | LJ_FUNC int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst); |
diff --git a/src/lj_load.c b/src/lj_load.c index 07304487..152ef6da 100644 --- a/src/lj_load.c +++ b/src/lj_load.c | |||
@@ -34,14 +34,28 @@ static TValue *cpparser(lua_State *L, lua_CFunction dummy, void *ud) | |||
34 | UNUSED(dummy); | 34 | UNUSED(dummy); |
35 | cframe_errfunc(L->cframe) = -1; /* Inherit error function. */ | 35 | cframe_errfunc(L->cframe) = -1; /* Inherit error function. */ |
36 | bc = lj_lex_setup(L, ls); | 36 | bc = lj_lex_setup(L, ls); |
37 | if (ls->mode && !strchr(ls->mode, bc ? 'b' : 't')) { | 37 | if (ls->mode) { |
38 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_XMODE)); | 38 | int xmode = 1; |
39 | lj_err_throw(L, LUA_ERRSYNTAX); | 39 | const char *mode = ls->mode; |
40 | char c; | ||
41 | while ((c = *mode++)) { | ||
42 | if (c == (bc ? 'b' : 't')) xmode = 0; | ||
43 | if (c == (LJ_FR2 ? 'W' : 'X')) ls->fr2 = !LJ_FR2; | ||
44 | } | ||
45 | if (xmode) { | ||
46 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_XMODE)); | ||
47 | lj_err_throw(L, LUA_ERRSYNTAX); | ||
48 | } | ||
40 | } | 49 | } |
41 | pt = bc ? lj_bcread(ls) : lj_parse(ls); | 50 | pt = bc ? lj_bcread(ls) : lj_parse(ls); |
42 | fn = lj_func_newL_empty(L, pt, tabref(L->env)); | 51 | if (ls->fr2 == LJ_FR2) { |
43 | /* Don't combine above/below into one statement. */ | 52 | fn = lj_func_newL_empty(L, pt, tabref(L->env)); |
44 | setfuncV(L, L->top++, fn); | 53 | /* Don't combine above/below into one statement. */ |
54 | setfuncV(L, L->top++, fn); | ||
55 | } else { | ||
56 | /* Non-native generation returns a dumpable, but non-runnable prototype. */ | ||
57 | setprotoV(L, L->top++, pt); | ||
58 | } | ||
45 | return NULL; | 59 | return NULL; |
46 | } | 60 | } |
47 | 61 | ||
@@ -159,9 +173,10 @@ LUALIB_API int luaL_loadstring(lua_State *L, const char *s) | |||
159 | LUA_API int lua_dump(lua_State *L, lua_Writer writer, void *data) | 173 | LUA_API int lua_dump(lua_State *L, lua_Writer writer, void *data) |
160 | { | 174 | { |
161 | cTValue *o = L->top-1; | 175 | cTValue *o = L->top-1; |
176 | uint32_t flags = LJ_FR2*BCDUMP_F_FR2; /* Default mode for legacy C API. */ | ||
162 | lj_checkapi(L->top > L->base, "top slot empty"); | 177 | lj_checkapi(L->top > L->base, "top slot empty"); |
163 | if (tvisfunc(o) && isluafunc(funcV(o))) | 178 | if (tvisfunc(o) && isluafunc(funcV(o))) |
164 | return lj_bcwrite(L, funcproto(funcV(o)), writer, data, 0); | 179 | return lj_bcwrite(L, funcproto(funcV(o)), writer, data, flags); |
165 | else | 180 | else |
166 | return 1; | 181 | return 1; |
167 | } | 182 | } |
diff --git a/src/lj_parse.c b/src/lj_parse.c index a30921af..5a44f8db 100644 --- a/src/lj_parse.c +++ b/src/lj_parse.c | |||
@@ -667,19 +667,20 @@ static void bcemit_store(FuncState *fs, ExpDesc *var, ExpDesc *e) | |||
667 | /* Emit method lookup expression. */ | 667 | /* Emit method lookup expression. */ |
668 | static void bcemit_method(FuncState *fs, ExpDesc *e, ExpDesc *key) | 668 | static void bcemit_method(FuncState *fs, ExpDesc *e, ExpDesc *key) |
669 | { | 669 | { |
670 | BCReg idx, func, obj = expr_toanyreg(fs, e); | 670 | BCReg idx, func, fr2, obj = expr_toanyreg(fs, e); |
671 | expr_free(fs, e); | 671 | expr_free(fs, e); |
672 | func = fs->freereg; | 672 | func = fs->freereg; |
673 | bcemit_AD(fs, BC_MOV, func+1+LJ_FR2, obj); /* Copy object to 1st argument. */ | 673 | fr2 = fs->ls->fr2; |
674 | bcemit_AD(fs, BC_MOV, func+1+fr2, obj); /* Copy object to 1st argument. */ | ||
674 | lj_assertFS(expr_isstrk(key), "bad usage"); | 675 | lj_assertFS(expr_isstrk(key), "bad usage"); |
675 | idx = const_str(fs, key); | 676 | idx = const_str(fs, key); |
676 | if (idx <= BCMAX_C) { | 677 | if (idx <= BCMAX_C) { |
677 | bcreg_reserve(fs, 2+LJ_FR2); | 678 | bcreg_reserve(fs, 2+fr2); |
678 | bcemit_ABC(fs, BC_TGETS, func, obj, idx); | 679 | bcemit_ABC(fs, BC_TGETS, func, obj, idx); |
679 | } else { | 680 | } else { |
680 | bcreg_reserve(fs, 3+LJ_FR2); | 681 | bcreg_reserve(fs, 3+fr2); |
681 | bcemit_AD(fs, BC_KSTR, func+2+LJ_FR2, idx); | 682 | bcemit_AD(fs, BC_KSTR, func+2+fr2, idx); |
682 | bcemit_ABC(fs, BC_TGETV, func, obj, func+2+LJ_FR2); | 683 | bcemit_ABC(fs, BC_TGETV, func, obj, func+2+fr2); |
683 | fs->freereg--; | 684 | fs->freereg--; |
684 | } | 685 | } |
685 | e->u.s.info = func; | 686 | e->u.s.info = func; |
@@ -1326,9 +1327,12 @@ static void fs_fixup_bc(FuncState *fs, GCproto *pt, BCIns *bc, MSize n) | |||
1326 | { | 1327 | { |
1327 | BCInsLine *base = fs->bcbase; | 1328 | BCInsLine *base = fs->bcbase; |
1328 | MSize i; | 1329 | MSize i; |
1330 | BCIns op; | ||
1329 | pt->sizebc = n; | 1331 | pt->sizebc = n; |
1330 | bc[0] = BCINS_AD((fs->flags & PROTO_VARARG) ? BC_FUNCV : BC_FUNCF, | 1332 | if (fs->ls->fr2 != LJ_FR2) op = BC_NOT; /* Mark non-native prototype. */ |
1331 | fs->framesize, 0); | 1333 | else if ((fs->flags & PROTO_VARARG)) op = BC_FUNCV; |
1334 | else op = BC_FUNCF; | ||
1335 | bc[0] = BCINS_AD(op, fs->framesize, 0); | ||
1332 | for (i = 1; i < n; i++) | 1336 | for (i = 1; i < n; i++) |
1333 | bc[i] = base[i].ins; | 1337 | bc[i] = base[i].ins; |
1334 | } | 1338 | } |
@@ -1936,11 +1940,11 @@ static void parse_args(LexState *ls, ExpDesc *e) | |||
1936 | lj_assertFS(e->k == VNONRELOC, "bad expr type %d", e->k); | 1940 | lj_assertFS(e->k == VNONRELOC, "bad expr type %d", e->k); |
1937 | base = e->u.s.info; /* Base register for call. */ | 1941 | base = e->u.s.info; /* Base register for call. */ |
1938 | if (args.k == VCALL) { | 1942 | if (args.k == VCALL) { |
1939 | ins = BCINS_ABC(BC_CALLM, base, 2, args.u.s.aux - base - 1 - LJ_FR2); | 1943 | ins = BCINS_ABC(BC_CALLM, base, 2, args.u.s.aux - base - 1 - ls->fr2); |
1940 | } else { | 1944 | } else { |
1941 | if (args.k != VVOID) | 1945 | if (args.k != VVOID) |
1942 | expr_tonextreg(fs, &args); | 1946 | expr_tonextreg(fs, &args); |
1943 | ins = BCINS_ABC(BC_CALL, base, 2, fs->freereg - base - LJ_FR2); | 1947 | ins = BCINS_ABC(BC_CALL, base, 2, fs->freereg - base - ls->fr2); |
1944 | } | 1948 | } |
1945 | expr_init(e, VCALL, bcemit_INS(fs, ins)); | 1949 | expr_init(e, VCALL, bcemit_INS(fs, ins)); |
1946 | e->u.s.aux = base; | 1950 | e->u.s.aux = base; |
@@ -1980,7 +1984,7 @@ static void expr_primary(LexState *ls, ExpDesc *v) | |||
1980 | parse_args(ls, v); | 1984 | parse_args(ls, v); |
1981 | } else if (ls->tok == '(' || ls->tok == TK_string || ls->tok == '{') { | 1985 | } else if (ls->tok == '(' || ls->tok == TK_string || ls->tok == '{') { |
1982 | expr_tonextreg(fs, v); | 1986 | expr_tonextreg(fs, v); |
1983 | if (LJ_FR2) bcreg_reserve(fs, 1); | 1987 | if (ls->fr2) bcreg_reserve(fs, 1); |
1984 | parse_args(ls, v); | 1988 | parse_args(ls, v); |
1985 | } else { | 1989 | } else { |
1986 | break; | 1990 | break; |
@@ -2565,7 +2569,7 @@ static void parse_for_iter(LexState *ls, GCstr *indexname) | |||
2565 | line = ls->linenumber; | 2569 | line = ls->linenumber; |
2566 | assign_adjust(ls, 3, expr_list(ls, &e), &e); | 2570 | assign_adjust(ls, 3, expr_list(ls, &e), &e); |
2567 | /* The iterator needs another 3 [4] slots (func [pc] | state ctl). */ | 2571 | /* The iterator needs another 3 [4] slots (func [pc] | state ctl). */ |
2568 | bcreg_bump(fs, 3+LJ_FR2); | 2572 | bcreg_bump(fs, 3+ls->fr2); |
2569 | isnext = (nvars <= 5 && predict_next(ls, fs, exprpc)); | 2573 | isnext = (nvars <= 5 && predict_next(ls, fs, exprpc)); |
2570 | var_add(ls, 3); /* Hidden control variables. */ | 2574 | var_add(ls, 3); /* Hidden control variables. */ |
2571 | lex_check(ls, TK_do); | 2575 | lex_check(ls, TK_do); |