diff options
author | Mike Pall <mike> | 2013-02-23 02:09:19 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2013-02-23 02:09:19 +0100 |
commit | 73ef845fcaf65937ad63e9cf6b681cb3e61f4504 (patch) | |
tree | 078cfae62c78ae9b9c0cfe5afe6000643ffc805d | |
parent | b359ce804bb52585815fc52d7846202db4341acb (diff) | |
download | luajit-73ef845fcaf65937ad63e9cf6b681cb3e61f4504.tar.gz luajit-73ef845fcaf65937ad63e9cf6b681cb3e61f4504.tar.bz2 luajit-73ef845fcaf65937ad63e9cf6b681cb3e61f4504.zip |
Add special bytecodes for builtins.
BC_ISTYPE, BC_ISNUM: fast type checks/coercions.
BC_TGETR, BC_TSETR: fast rawgeti/rawseti, no type checks for table/key.
-rw-r--r-- | src/Makefile.dep | 18 | ||||
-rw-r--r-- | src/host/buildvm_lib.c | 32 | ||||
-rw-r--r-- | src/host/buildvm_libbc.h | 4 | ||||
-rw-r--r-- | src/host/genlibbc.lua | 108 | ||||
-rw-r--r-- | src/lj_arch.h | 1 | ||||
-rw-r--r-- | src/lj_bc.h | 4 | ||||
-rw-r--r-- | src/lj_bcdump.h | 2 | ||||
-rw-r--r-- | src/lj_dispatch.h | 10 | ||||
-rw-r--r-- | src/lj_meta.c | 13 | ||||
-rw-r--r-- | src/lj_meta.h | 1 | ||||
-rw-r--r-- | src/lj_record.c | 16 | ||||
-rw-r--r-- | src/lj_tab.h | 2 | ||||
-rw-r--r-- | src/vm_arm.dasc | 93 | ||||
-rw-r--r-- | src/vm_mips.dasc | 108 | ||||
-rw-r--r-- | src/vm_ppc.dasc | 109 | ||||
-rw-r--r-- | src/vm_x86.dasc | 131 |
16 files changed, 614 insertions, 38 deletions
diff --git a/src/Makefile.dep b/src/Makefile.dep index 54004f7c..10118c5e 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep | |||
@@ -134,7 +134,7 @@ lj_mcode.o: lj_mcode.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | |||
134 | lj_traceerr.h lj_vm.h | 134 | lj_traceerr.h lj_vm.h |
135 | lj_meta.o: lj_meta.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 135 | lj_meta.o: lj_meta.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
136 | lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \ | 136 | lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \ |
137 | lj_vm.h lj_strscan.h | 137 | lj_vm.h lj_strscan.h lj_lib.h |
138 | lj_obj.o: lj_obj.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h | 138 | lj_obj.o: lj_obj.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h |
139 | lj_opt_dce.o: lj_opt_dce.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 139 | lj_opt_dce.o: lj_opt_dce.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
140 | lj_ir.h lj_jit.h lj_iropt.h | 140 | lj_ir.h lj_jit.h lj_iropt.h |
@@ -195,13 +195,13 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_gc.c lj_obj.h lj_def.h \ | |||
195 | lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_err.c \ | 195 | lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_err.c \ |
196 | lj_debug.h lj_ff.h lj_ffdef.h lj_char.c lj_char.h lj_bc.c lj_bcdef.h \ | 196 | lj_debug.h lj_ff.h lj_ffdef.h lj_char.c lj_char.h lj_bc.c lj_bcdef.h \ |
197 | lj_obj.c lj_str.c lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h \ | 197 | lj_obj.c lj_str.c lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h \ |
198 | lj_debug.c lj_state.c lj_lex.h lj_alloc.h lj_dispatch.c lj_ccallback.h \ | 198 | lj_lib.h lj_debug.c lj_state.c lj_lex.h lj_alloc.h lj_dispatch.c \ |
199 | luajit.h lj_vmevent.c lj_vmevent.h lj_vmmath.c lj_strscan.c lj_api.c \ | 199 | lj_ccallback.h luajit.h lj_vmevent.c lj_vmevent.h lj_vmmath.c \ |
200 | lj_lex.c lualib.h lj_parse.h lj_parse.c lj_bcread.c lj_bcdump.h \ | 200 | lj_strscan.c lj_api.c lj_lex.c lualib.h lj_parse.h lj_parse.c \ |
201 | lj_bcwrite.c lj_load.c lj_ctype.c lj_cdata.c lj_cconv.h lj_cconv.c \ | 201 | lj_bcread.c lj_bcdump.h lj_bcwrite.c lj_load.c lj_ctype.c lj_cdata.c \ |
202 | lj_ccall.c lj_ccall.h lj_ccallback.c lj_target.h lj_target_*.h \ | 202 | lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h lj_ccallback.c lj_target.h \ |
203 | lj_mcode.h lj_carith.c lj_carith.h lj_clib.c lj_clib.h lj_cparse.c \ | 203 | lj_target_*.h lj_mcode.h lj_carith.c lj_carith.h lj_clib.c lj_clib.h \ |
204 | lj_cparse.h lj_lib.c lj_lib.h lj_ir.c lj_ircall.h lj_iropt.h \ | 204 | lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c lj_ircall.h lj_iropt.h \ |
205 | lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \ | 205 | lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \ |
206 | lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c lj_mcode.c \ | 206 | lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c lj_mcode.c \ |
207 | lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \ | 207 | lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \ |
@@ -221,7 +221,7 @@ host/buildvm_asm.o: host/buildvm_asm.c host/buildvm.h lj_def.h lua.h luaconf.h \ | |||
221 | host/buildvm_fold.o: host/buildvm_fold.c host/buildvm.h lj_def.h lua.h \ | 221 | host/buildvm_fold.o: host/buildvm_fold.c host/buildvm.h lj_def.h lua.h \ |
222 | luaconf.h lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_ir.h lj_obj.h | 222 | luaconf.h lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_ir.h lj_obj.h |
223 | host/buildvm_lib.o: host/buildvm_lib.c host/buildvm.h lj_def.h lua.h luaconf.h \ | 223 | host/buildvm_lib.o: host/buildvm_lib.c host/buildvm.h lj_def.h lua.h luaconf.h \ |
224 | lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_lib.h lj_obj.h \ | 224 | lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_bc.h lj_lib.h lj_obj.h \ |
225 | host/buildvm_libbc.h | 225 | host/buildvm_libbc.h |
226 | host/buildvm_peobj.o: host/buildvm_peobj.c host/buildvm.h lj_def.h lua.h \ | 226 | host/buildvm_peobj.o: host/buildvm_peobj.c host/buildvm.h lj_def.h lua.h \ |
227 | luaconf.h lj_arch.h lj_bc.h lj_def.h lj_arch.h | 227 | luaconf.h lj_arch.h lj_bc.h lj_def.h lj_arch.h |
diff --git a/src/host/buildvm_lib.c b/src/host/buildvm_lib.c index 182ab90f..dcd3ca41 100644 --- a/src/host/buildvm_lib.c +++ b/src/host/buildvm_lib.c | |||
@@ -5,6 +5,7 @@ | |||
5 | 5 | ||
6 | #include "buildvm.h" | 6 | #include "buildvm.h" |
7 | #include "lj_obj.h" | 7 | #include "lj_obj.h" |
8 | #include "lj_bc.h" | ||
8 | #include "lj_lib.h" | 9 | #include "lj_lib.h" |
9 | #include "buildvm_libbc.h" | 10 | #include "buildvm_libbc.h" |
10 | 11 | ||
@@ -152,28 +153,36 @@ static void libdef_func(BuildCtx *ctx, char *p, int arg) | |||
152 | regfunc = REGFUNC_OK; | 153 | regfunc = REGFUNC_OK; |
153 | } | 154 | } |
154 | 155 | ||
155 | static uint32_t libdef_uleb128(uint8_t **pp) | 156 | static uint8_t *libdef_uleb128(uint8_t *p, uint32_t *vv) |
156 | { | 157 | { |
157 | uint8_t *p = *pp; | ||
158 | uint32_t v = *p++; | 158 | uint32_t v = *p++; |
159 | if (v >= 0x80) { | 159 | if (v >= 0x80) { |
160 | int sh = 0; v &= 0x7f; | 160 | int sh = 0; v &= 0x7f; |
161 | do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80); | 161 | do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80); |
162 | } | 162 | } |
163 | *pp = p; | 163 | *vv = v; |
164 | return v; | 164 | return p; |
165 | } | 165 | } |
166 | 166 | ||
167 | static void libdef_swapbc(uint8_t *p) | 167 | static void libdef_fixupbc(uint8_t *p) |
168 | { | 168 | { |
169 | uint32_t i, sizebc; | 169 | uint32_t i, sizebc; |
170 | p += 4; | 170 | p += 4; |
171 | libdef_uleb128(&p); | 171 | p = libdef_uleb128(p, &sizebc); |
172 | libdef_uleb128(&p); | 172 | p = libdef_uleb128(p, &sizebc); |
173 | sizebc = libdef_uleb128(&p); | 173 | p = libdef_uleb128(p, &sizebc); |
174 | for (i = 0; i < sizebc; i++, p += 4) { | 174 | for (i = 0; i < sizebc; i++, p += 4) { |
175 | uint8_t t = p[0]; p[0] = p[3]; p[3] = t; | 175 | uint8_t op = p[libbc_endian ? 3 : 0]; |
176 | t = p[1]; p[1] = p[2]; p[2] = t; | 176 | uint8_t ra = p[libbc_endian ? 2 : 1]; |
177 | uint8_t rc = p[libbc_endian ? 1 : 2]; | ||
178 | uint8_t rb = p[libbc_endian ? 0 : 3]; | ||
179 | if (!LJ_DUALNUM && op == BC_ISTYPE && rc == ~LJ_TNUMX+1) { | ||
180 | op = BC_ISNUM; rc++; | ||
181 | } | ||
182 | p[LJ_ENDIAN_SELECT(0, 3)] = op; | ||
183 | p[LJ_ENDIAN_SELECT(1, 2)] = ra; | ||
184 | p[LJ_ENDIAN_SELECT(2, 1)] = rc; | ||
185 | p[LJ_ENDIAN_SELECT(3, 0)] = rb; | ||
177 | } | 186 | } |
178 | } | 187 | } |
179 | 188 | ||
@@ -190,8 +199,7 @@ static void libdef_lua(BuildCtx *ctx, char *p, int arg) | |||
190 | *optr++ = LIBINIT_LUA; | 199 | *optr++ = LIBINIT_LUA; |
191 | libdef_name(p, 0); | 200 | libdef_name(p, 0); |
192 | memcpy(optr, libbc_code + ofs, len); | 201 | memcpy(optr, libbc_code + ofs, len); |
193 | if (libbc_endian != LJ_BE) | 202 | libdef_fixupbc(optr); |
194 | libdef_swapbc(optr); | ||
195 | optr += len; | 203 | optr += len; |
196 | return; | 204 | return; |
197 | } | 205 | } |
diff --git a/src/host/buildvm_libbc.h b/src/host/buildvm_libbc.h index ee97836a..6b0e1d03 100644 --- a/src/host/buildvm_libbc.h +++ b/src/host/buildvm_libbc.h | |||
@@ -3,8 +3,8 @@ | |||
3 | static const int libbc_endian = 0; | 3 | static const int libbc_endian = 0; |
4 | 4 | ||
5 | static const uint8_t libbc_code[] = { | 5 | static const uint8_t libbc_code[] = { |
6 | 0,1,2,0,0,1,2,22,1,0,0,72,1,2,0,241,135,158,166,3,220,203,178,130,4,0,1,2,0, | 6 | 0,1,2,0,0,1,2,24,1,0,0,76,1,2,0,241,135,158,166,3,220,203,178,130,4,0,1,2,0, |
7 | 0,1,2,22,1,0,0,72,1,2,0,243,244,148,165,20,198,190,199,252,3,0 | 7 | 0,1,2,24,1,0,0,76,1,2,0,243,244,148,165,20,198,190,199,252,3,0 |
8 | }; | 8 | }; |
9 | 9 | ||
10 | static const struct { const char *name; int ofs; } libbc_map[] = { | 10 | static const struct { const char *name; int ofs; } libbc_map[] = { |
diff --git a/src/host/genlibbc.lua b/src/host/genlibbc.lua index bdcfb588..72c55d73 100644 --- a/src/host/genlibbc.lua +++ b/src/host/genlibbc.lua | |||
@@ -6,6 +6,15 @@ | |||
6 | -- Released under the MIT license. See Copyright Notice in luajit.h | 6 | -- Released under the MIT license. See Copyright Notice in luajit.h |
7 | ---------------------------------------------------------------------------- | 7 | ---------------------------------------------------------------------------- |
8 | 8 | ||
9 | local ffi = require("ffi") | ||
10 | local bit = require("bit") | ||
11 | local vmdef = require("jit.vmdef") | ||
12 | local bcnames = vmdef.bcnames | ||
13 | |||
14 | local format = string.format | ||
15 | |||
16 | local isbe = (string.byte(string.dump(function() end), 5) % 2 == 1) | ||
17 | |||
9 | local function usage(arg) | 18 | local function usage(arg) |
10 | io.stderr:write("Usage: ", arg and arg[0] or "genlibbc", | 19 | io.stderr:write("Usage: ", arg and arg[0] or "genlibbc", |
11 | " [-o buildvm_libbc.h] lib_*.c\n") | 20 | " [-o buildvm_libbc.h] lib_*.c\n") |
@@ -36,15 +45,100 @@ local function read_files(names) | |||
36 | return src | 45 | return src |
37 | end | 46 | end |
38 | 47 | ||
48 | local function transform_lua(code) | ||
49 | local fixup = {} | ||
50 | local n = -30000 | ||
51 | code = string.gsub(code, "CHECK_(%w*)%((.-)%)", function(tp, var) | ||
52 | n = n + 1 | ||
53 | fixup[n] = { "CHECK", tp } | ||
54 | return format("%s=%d", var, n) | ||
55 | end) | ||
56 | code = string.gsub(code, "PAIRS%((.-)%)", function(var) | ||
57 | fixup.PAIRS = true | ||
58 | return format("nil, %s, 0", var) | ||
59 | end) | ||
60 | return "return "..code, fixup | ||
61 | end | ||
62 | |||
63 | local function read_uleb128(p) | ||
64 | local v = p[0]; p = p + 1 | ||
65 | if v >= 128 then | ||
66 | local sh = 7; v = v - 128 | ||
67 | repeat | ||
68 | local r = p[0] | ||
69 | v = v + bit.lshift(bit.band(r, 128), sh) | ||
70 | sh = sh + 7 | ||
71 | p = p + 1 | ||
72 | until r < 128 | ||
73 | end | ||
74 | return p, v | ||
75 | end | ||
76 | |||
77 | -- ORDER LJ_T | ||
78 | local name2itype = { | ||
79 | str = 5, func = 9, tab = 12, int = 14, num = 15 | ||
80 | } | ||
81 | |||
82 | local BC = {} | ||
83 | for i=0,#bcnames/6-1 do | ||
84 | BC[string.gsub(string.sub(bcnames, i*6+1, i*6+6), " ", "")] = i | ||
85 | end | ||
86 | local xop, xra = isbe and 3 or 0, isbe and 2 or 1 | ||
87 | local xrc, xrb = isbe and 1 or 2, isbe and 0 or 3 | ||
88 | |||
89 | local function fixup_dump(dump, fixup) | ||
90 | local buf = ffi.new("uint8_t[?]", #dump+1, dump) | ||
91 | local p = buf+5 | ||
92 | local n, sizebc | ||
93 | p, n = read_uleb128(p) | ||
94 | local start = p | ||
95 | p = p + 4 | ||
96 | p = read_uleb128(p) | ||
97 | p = read_uleb128(p) | ||
98 | p, sizebc = read_uleb128(p) | ||
99 | local rawtab = {} | ||
100 | for i=0,sizebc-1 do | ||
101 | local op = p[xop] | ||
102 | if op == BC.KSHORT then | ||
103 | local rd = p[xrc] + 256*p[xrb] | ||
104 | rd = bit.arshift(bit.lshift(rd, 16), 16) | ||
105 | local f = fixup[rd] | ||
106 | if f then | ||
107 | if f[1] == "CHECK" then | ||
108 | local tp = f[2] | ||
109 | if tp == "tab" then rawtab[p[xra]] = true end | ||
110 | p[xop] = tp == "num" and BC.ISNUM or BC.ISTYPE | ||
111 | p[xrb] = 0 | ||
112 | p[xrc] = name2itype[tp] | ||
113 | else | ||
114 | error("unhandled fixup type: "..f[1]) | ||
115 | end | ||
116 | end | ||
117 | elseif op == BC.TGETV then | ||
118 | if rawtab[p[xrb]] then | ||
119 | p[xop] = BC.TGETR | ||
120 | end | ||
121 | elseif op == BC.TSETV then | ||
122 | if rawtab[p[xrb]] then | ||
123 | p[xop] = BC.TSETR | ||
124 | end | ||
125 | elseif op == BC.ITERC then | ||
126 | if fixup.PAIRS then | ||
127 | p[xop] = BC.ITERN | ||
128 | end | ||
129 | end | ||
130 | p = p + 4 | ||
131 | end | ||
132 | return ffi.string(start, n) | ||
133 | end | ||
134 | |||
39 | local function find_defs(src) | 135 | local function find_defs(src) |
40 | local defs = {} | 136 | local defs = {} |
41 | for name, code in string.gmatch(src, "LJLIB_LUA%(([^)]*)%)%s*/%*(.-)%*/") do | 137 | for name, code in string.gmatch(src, "LJLIB_LUA%(([^)]*)%)%s*/%*(.-)%*/") do |
42 | local env = {} | 138 | local env = {} |
43 | local func = assert(load("return "..code, "", nil, env))() | 139 | local tcode, fixup = transform_lua(code) |
44 | local d = string.dump(func, true) | 140 | local func = assert(load(tcode, "", nil, env))() |
45 | local ofs = 6 | 141 | defs[name] = fixup_dump(string.dump(func, true), fixup) |
46 | while string.byte(d, ofs) > 127 do ofs = ofs + 1 end | ||
47 | defs[name] = string.sub(d, ofs+1, -2) | ||
48 | defs[#defs+1] = name | 142 | defs[#defs+1] = name |
49 | end | 143 | end |
50 | return defs | 144 | return defs |
@@ -54,9 +148,7 @@ local function gen_header(defs) | |||
54 | local t = {} | 148 | local t = {} |
55 | local function w(x) t[#t+1] = x end | 149 | local function w(x) t[#t+1] = x end |
56 | w("/* This is a generated file. DO NOT EDIT! */\n\n") | 150 | w("/* This is a generated file. DO NOT EDIT! */\n\n") |
57 | w("static const int libbc_endian = ") | 151 | w("static const int libbc_endian = ") w(isbe and 1 or 0) w(";\n\n") |
58 | w(string.byte(string.dump(function() end), 5) % 2) | ||
59 | w(";\n\n") | ||
60 | local s = "" | 152 | local s = "" |
61 | for _,name in ipairs(defs) do | 153 | for _,name in ipairs(defs) do |
62 | s = s .. defs[name] | 154 | s = s .. defs[name] |
diff --git a/src/lj_arch.h b/src/lj_arch.h index 9ea10d0f..c5f2fb3d 100644 --- a/src/lj_arch.h +++ b/src/lj_arch.h | |||
@@ -227,6 +227,7 @@ | |||
227 | 227 | ||
228 | #elif LUAJIT_TARGET == LUAJIT_ARCH_PPCSPE | 228 | #elif LUAJIT_TARGET == LUAJIT_ARCH_PPCSPE |
229 | 229 | ||
230 | #error "The PPC/e500 port is broken and will be abandoned with LuaJIT 2.1" | ||
230 | #define LJ_ARCH_NAME "ppcspe" | 231 | #define LJ_ARCH_NAME "ppcspe" |
231 | #define LJ_ARCH_BITS 32 | 232 | #define LJ_ARCH_BITS 32 |
232 | #define LJ_ARCH_ENDIAN LUAJIT_BE | 233 | #define LJ_ARCH_ENDIAN LUAJIT_BE |
diff --git a/src/lj_bc.h b/src/lj_bc.h index 56e71dd9..ac9cc5e1 100644 --- a/src/lj_bc.h +++ b/src/lj_bc.h | |||
@@ -89,6 +89,8 @@ | |||
89 | _(ISFC, dst, ___, var, ___) \ | 89 | _(ISFC, dst, ___, var, ___) \ |
90 | _(IST, ___, ___, var, ___) \ | 90 | _(IST, ___, ___, var, ___) \ |
91 | _(ISF, ___, ___, var, ___) \ | 91 | _(ISF, ___, ___, var, ___) \ |
92 | _(ISTYPE, var, ___, lit, ___) \ | ||
93 | _(ISNUM, var, ___, lit, ___) \ | ||
92 | \ | 94 | \ |
93 | /* Unary ops. */ \ | 95 | /* Unary ops. */ \ |
94 | _(MOV, dst, ___, var, ___) \ | 96 | _(MOV, dst, ___, var, ___) \ |
@@ -143,10 +145,12 @@ | |||
143 | _(TGETV, dst, var, var, index) \ | 145 | _(TGETV, dst, var, var, index) \ |
144 | _(TGETS, dst, var, str, index) \ | 146 | _(TGETS, dst, var, str, index) \ |
145 | _(TGETB, dst, var, lit, index) \ | 147 | _(TGETB, dst, var, lit, index) \ |
148 | _(TGETR, dst, var, var, index) \ | ||
146 | _(TSETV, var, var, var, newindex) \ | 149 | _(TSETV, var, var, var, newindex) \ |
147 | _(TSETS, var, var, str, newindex) \ | 150 | _(TSETS, var, var, str, newindex) \ |
148 | _(TSETB, var, var, lit, newindex) \ | 151 | _(TSETB, var, var, lit, newindex) \ |
149 | _(TSETM, base, ___, num, newindex) \ | 152 | _(TSETM, base, ___, num, newindex) \ |
153 | _(TSETR, var, var, var, newindex) \ | ||
150 | \ | 154 | \ |
151 | /* Calls and vararg handling. T = tail call. */ \ | 155 | /* Calls and vararg handling. T = tail call. */ \ |
152 | _(CALLM, base, lit, lit, call) \ | 156 | _(CALLM, base, lit, lit, call) \ |
diff --git a/src/lj_bcdump.h b/src/lj_bcdump.h index c1ed54e7..22a8b823 100644 --- a/src/lj_bcdump.h +++ b/src/lj_bcdump.h | |||
@@ -36,7 +36,7 @@ | |||
36 | /* If you perform *any* kind of private modifications to the bytecode itself | 36 | /* If you perform *any* kind of private modifications to the bytecode itself |
37 | ** or to the dump format, you *must* set BCDUMP_VERSION to 0x80 or higher. | 37 | ** or to the dump format, you *must* set BCDUMP_VERSION to 0x80 or higher. |
38 | */ | 38 | */ |
39 | #define BCDUMP_VERSION 1 | 39 | #define BCDUMP_VERSION 2 |
40 | 40 | ||
41 | /* Compatibility flags. */ | 41 | /* Compatibility flags. */ |
42 | #define BCDUMP_F_BE 0x01 | 42 | #define BCDUMP_F_BE 0x01 |
diff --git a/src/lj_dispatch.h b/src/lj_dispatch.h index 57614d99..a662439b 100644 --- a/src/lj_dispatch.h +++ b/src/lj_dispatch.h | |||
@@ -33,11 +33,11 @@ | |||
33 | _(lj_ffh_coroutine_wrap_err) _(lj_func_closeuv) _(lj_func_newL_gc) \ | 33 | _(lj_ffh_coroutine_wrap_err) _(lj_func_closeuv) _(lj_func_newL_gc) \ |
34 | _(lj_gc_barrieruv) _(lj_gc_step) _(lj_gc_step_fixtop) _(lj_meta_arith) \ | 34 | _(lj_gc_barrieruv) _(lj_gc_step) _(lj_gc_step_fixtop) _(lj_meta_arith) \ |
35 | _(lj_meta_call) _(lj_meta_cat) _(lj_meta_comp) _(lj_meta_equal) \ | 35 | _(lj_meta_call) _(lj_meta_cat) _(lj_meta_comp) _(lj_meta_equal) \ |
36 | _(lj_meta_for) _(lj_meta_len) _(lj_meta_tget) _(lj_meta_tset) \ | 36 | _(lj_meta_for) _(lj_meta_istype) _(lj_meta_len) _(lj_meta_tget) \ |
37 | _(lj_state_growstack) _(lj_str_fromnum) _(lj_str_fromnumber) _(lj_str_new) \ | 37 | _(lj_meta_tset) _(lj_state_growstack) _(lj_str_fromnum) _(lj_str_fromnumber) \ |
38 | _(lj_tab_dup) _(lj_tab_get) _(lj_tab_getinth) _(lj_tab_len) _(lj_tab_new) \ | 38 | _(lj_str_new) _(lj_tab_dup) _(lj_tab_get) _(lj_tab_getinth) _(lj_tab_len) \ |
39 | _(lj_tab_newkey) _(lj_tab_next) _(lj_tab_reasize) \ | 39 | _(lj_tab_new) _(lj_tab_newkey) _(lj_tab_next) _(lj_tab_reasize) \ |
40 | JITGOTDEF(_) FFIGOTDEF(_) | 40 | _(lj_tab_setinth) JITGOTDEF(_) FFIGOTDEF(_) |
41 | 41 | ||
42 | enum { | 42 | enum { |
43 | #define GOTENUM(name) LJ_GOT_##name, | 43 | #define GOTENUM(name) LJ_GOT_##name, |
diff --git a/src/lj_meta.c b/src/lj_meta.c index 441d571a..e11f1b75 100644 --- a/src/lj_meta.c +++ b/src/lj_meta.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include "lj_bc.h" | 19 | #include "lj_bc.h" |
20 | #include "lj_vm.h" | 20 | #include "lj_vm.h" |
21 | #include "lj_strscan.h" | 21 | #include "lj_strscan.h" |
22 | #include "lj_lib.h" | ||
22 | 23 | ||
23 | /* -- Metamethod handling ------------------------------------------------- */ | 24 | /* -- Metamethod handling ------------------------------------------------- */ |
24 | 25 | ||
@@ -423,6 +424,18 @@ TValue *lj_meta_comp(lua_State *L, cTValue *o1, cTValue *o2, int op) | |||
423 | } | 424 | } |
424 | } | 425 | } |
425 | 426 | ||
427 | /* Helper for ISTYPE and ISNUM. Implicit coercion or error. */ | ||
428 | void lj_meta_istype(lua_State *L, BCReg ra, BCReg tp) | ||
429 | { | ||
430 | L->top = curr_topL(L); | ||
431 | ra++; tp--; | ||
432 | lua_assert(LJ_DUALNUM || tp != ~LJ_TNUMX); /* ISTYPE -> ISNUM broken. */ | ||
433 | if (LJ_DUALNUM && tp == ~LJ_TNUMX) lj_lib_checkint(L, ra); | ||
434 | else if (tp == ~LJ_TNUMX+1) lj_lib_checknum(L, ra); | ||
435 | else if (tp == ~LJ_TSTR) lj_lib_checkstr(L, ra); | ||
436 | else lj_err_argtype(L, ra, lj_obj_itypename[tp]); | ||
437 | } | ||
438 | |||
426 | /* Helper for calls. __call metamethod. */ | 439 | /* Helper for calls. __call metamethod. */ |
427 | void lj_meta_call(lua_State *L, TValue *func, TValue *top) | 440 | void lj_meta_call(lua_State *L, TValue *func, TValue *top) |
428 | { | 441 | { |
diff --git a/src/lj_meta.h b/src/lj_meta.h index 6af5e514..970398ec 100644 --- a/src/lj_meta.h +++ b/src/lj_meta.h | |||
@@ -31,6 +31,7 @@ LJ_FUNCA TValue * LJ_FASTCALL lj_meta_len(lua_State *L, cTValue *o); | |||
31 | LJ_FUNCA TValue *lj_meta_equal(lua_State *L, GCobj *o1, GCobj *o2, int ne); | 31 | LJ_FUNCA TValue *lj_meta_equal(lua_State *L, GCobj *o1, GCobj *o2, int ne); |
32 | LJ_FUNCA TValue * LJ_FASTCALL lj_meta_equal_cd(lua_State *L, BCIns ins); | 32 | LJ_FUNCA TValue * LJ_FASTCALL lj_meta_equal_cd(lua_State *L, BCIns ins); |
33 | LJ_FUNCA TValue *lj_meta_comp(lua_State *L, cTValue *o1, cTValue *o2, int op); | 33 | LJ_FUNCA TValue *lj_meta_comp(lua_State *L, cTValue *o1, cTValue *o2, int op); |
34 | LJ_FUNCA void lj_meta_istype(lua_State *L, BCReg ra, BCReg tp); | ||
34 | LJ_FUNCA void lj_meta_call(lua_State *L, TValue *func, TValue *top); | 35 | LJ_FUNCA void lj_meta_call(lua_State *L, TValue *func, TValue *top); |
35 | LJ_FUNCA void LJ_FASTCALL lj_meta_for(lua_State *L, TValue *o); | 36 | LJ_FUNCA void LJ_FASTCALL lj_meta_for(lua_State *L, TValue *o); |
36 | 37 | ||
diff --git a/src/lj_record.c b/src/lj_record.c index 7336e0ac..003910a9 100644 --- a/src/lj_record.c +++ b/src/lj_record.c | |||
@@ -1826,6 +1826,18 @@ void lj_record_ins(jit_State *J) | |||
1826 | J->maxslot = bc_a(pc[1]); /* Shrink used slots. */ | 1826 | J->maxslot = bc_a(pc[1]); /* Shrink used slots. */ |
1827 | break; | 1827 | break; |
1828 | 1828 | ||
1829 | case BC_ISTYPE: case BC_ISNUM: | ||
1830 | /* These coercions need to correspond with lj_meta_istype(). */ | ||
1831 | if (LJ_DUALNUM && rc == ~LJ_TNUMX+1) | ||
1832 | ra = lj_opt_narrow_toint(J, ra); | ||
1833 | else if (rc == ~LJ_TNUMX+2) | ||
1834 | ra = lj_ir_tonum(J, ra); | ||
1835 | else if (rc == ~LJ_TSTR+1) | ||
1836 | ra = lj_ir_tostr(J, ra); | ||
1837 | /* else: type specialization suffices. */ | ||
1838 | J->base[bc_a(ins)] = ra; | ||
1839 | break; | ||
1840 | |||
1829 | /* -- Unary ops --------------------------------------------------------- */ | 1841 | /* -- Unary ops --------------------------------------------------------- */ |
1830 | 1842 | ||
1831 | case BC_NOT: | 1843 | case BC_NOT: |
@@ -1937,6 +1949,10 @@ void lj_record_ins(jit_State *J) | |||
1937 | ix.idxchain = LJ_MAX_IDXCHAIN; | 1949 | ix.idxchain = LJ_MAX_IDXCHAIN; |
1938 | rc = lj_record_idx(J, &ix); | 1950 | rc = lj_record_idx(J, &ix); |
1939 | break; | 1951 | break; |
1952 | case BC_TGETR: case BC_TSETR: | ||
1953 | ix.idxchain = 0; | ||
1954 | rc = lj_record_idx(J, &ix); | ||
1955 | break; | ||
1940 | 1956 | ||
1941 | case BC_TNEW: | 1957 | case BC_TNEW: |
1942 | rc = rec_tnew(J, rc); | 1958 | rc = rec_tnew(J, rc); |
diff --git a/src/lj_tab.h b/src/lj_tab.h index 2787caa0..d361137c 100644 --- a/src/lj_tab.h +++ b/src/lj_tab.h | |||
@@ -50,7 +50,7 @@ LJ_FUNCA cTValue *lj_tab_get(lua_State *L, GCtab *t, cTValue *key); | |||
50 | /* Caveat: all setters require a write barrier for the stored value. */ | 50 | /* Caveat: all setters require a write barrier for the stored value. */ |
51 | 51 | ||
52 | LJ_FUNCA TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key); | 52 | LJ_FUNCA TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key); |
53 | LJ_FUNC TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key); | 53 | LJ_FUNCA TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key); |
54 | LJ_FUNC TValue *lj_tab_setstr(lua_State *L, GCtab *t, GCstr *key); | 54 | LJ_FUNC TValue *lj_tab_setstr(lua_State *L, GCtab *t, GCstr *key); |
55 | LJ_FUNC TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key); | 55 | LJ_FUNC TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key); |
56 | 56 | ||
diff --git a/src/vm_arm.dasc b/src/vm_arm.dasc index c46d9243..d999d5ff 100644 --- a/src/vm_arm.dasc +++ b/src/vm_arm.dasc | |||
@@ -615,6 +615,16 @@ static void build_subroutines(BuildCtx *ctx) | |||
615 | | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here. | 615 | | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here. |
616 | | b ->vm_call_dispatch_f | 616 | | b ->vm_call_dispatch_f |
617 | | | 617 | | |
618 | |->vmeta_tgetr: | ||
619 | | .IOS mov RC, BASE | ||
620 | | bl extern lj_tab_getinth // (GCtab *t, int32_t key) | ||
621 | | // Returns cTValue * or NULL. | ||
622 | | .IOS mov BASE, RC | ||
623 | | cmp CRET1, #0 | ||
624 | | ldrdne CARG12, [CRET1] | ||
625 | | mvneq CARG2, #~LJ_TNIL | ||
626 | | b ->BC_TGETR_Z | ||
627 | | | ||
618 | |//----------------------------------------------------------------------- | 628 | |//----------------------------------------------------------------------- |
619 | | | 629 | | |
620 | |->vmeta_tsets1: | 630 | |->vmeta_tsets1: |
@@ -672,6 +682,15 @@ static void build_subroutines(BuildCtx *ctx) | |||
672 | | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here. | 682 | | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here. |
673 | | b ->vm_call_dispatch_f | 683 | | b ->vm_call_dispatch_f |
674 | | | 684 | | |
685 | |->vmeta_tsetr: | ||
686 | | str BASE, L->base | ||
687 | | .IOS mov RC, BASE | ||
688 | | str PC, SAVE_PC | ||
689 | | bl extern lj_tab_setinth // (lua_State *L, GCtab *t, int32_t key) | ||
690 | | // Returns TValue *. | ||
691 | | .IOS mov BASE, RC | ||
692 | | b ->BC_TSETR_Z | ||
693 | | | ||
675 | |//-- Comparison metamethods --------------------------------------------- | 694 | |//-- Comparison metamethods --------------------------------------------- |
676 | | | 695 | | |
677 | |->vmeta_comp: | 696 | |->vmeta_comp: |
@@ -736,6 +755,17 @@ static void build_subroutines(BuildCtx *ctx) | |||
736 | | b <3 | 755 | | b <3 |
737 | |.endif | 756 | |.endif |
738 | | | 757 | | |
758 | |->vmeta_istype: | ||
759 | | sub PC, PC, #4 | ||
760 | | str BASE, L->base | ||
761 | | mov CARG1, L | ||
762 | | lsr CARG2, RA, #3 | ||
763 | | mov CARG3, RC | ||
764 | | str PC, SAVE_PC | ||
765 | | bl extern lj_meta_istype // (lua_State *L, BCReg ra, BCReg tp) | ||
766 | | .IOS ldr BASE, L->base | ||
767 | | b ->cont_nop | ||
768 | | | ||
739 | |//-- Arithmetic metamethods --------------------------------------------- | 769 | |//-- Arithmetic metamethods --------------------------------------------- |
740 | | | 770 | | |
741 | |->vmeta_arith_vn: | 771 | |->vmeta_arith_vn: |
@@ -2821,6 +2851,25 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
2821 | | ins_next | 2851 | | ins_next |
2822 | break; | 2852 | break; |
2823 | 2853 | ||
2854 | case BC_ISTYPE: | ||
2855 | | // RA = src*8, RC = -type | ||
2856 | | ldrd CARG12, [BASE, RA] | ||
2857 | | ins_next1 | ||
2858 | | cmn CARG2, RC | ||
2859 | | ins_next2 | ||
2860 | | bne ->vmeta_istype | ||
2861 | | ins_next3 | ||
2862 | break; | ||
2863 | case BC_ISNUM: | ||
2864 | | // RA = src*8, RC = -(TISNUM-1) | ||
2865 | | ldrd CARG12, [BASE, RA] | ||
2866 | | ins_next1 | ||
2867 | | checktp CARG2, LJ_TISNUM | ||
2868 | | ins_next2 | ||
2869 | | bhs ->vmeta_istype | ||
2870 | | ins_next3 | ||
2871 | break; | ||
2872 | |||
2824 | /* -- Unary ops --------------------------------------------------------- */ | 2873 | /* -- Unary ops --------------------------------------------------------- */ |
2825 | 2874 | ||
2826 | case BC_MOV: | 2875 | case BC_MOV: |
@@ -3491,6 +3540,24 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
3491 | | bne <1 // 'no __index' flag set: done. | 3540 | | bne <1 // 'no __index' flag set: done. |
3492 | | b ->vmeta_tgetb | 3541 | | b ->vmeta_tgetb |
3493 | break; | 3542 | break; |
3543 | case BC_TGETR: | ||
3544 | | decode_RB8 RB, INS | ||
3545 | | decode_RC8 RC, INS | ||
3546 | | // RA = dst*8, RB = table*8, RC = key*8 | ||
3547 | | ldr TAB:CARG1, [BASE, RB] | ||
3548 | | ldr CARG2, [BASE, RC] | ||
3549 | | ldr CARG4, TAB:CARG1->array | ||
3550 | | ldr CARG3, TAB:CARG1->asize | ||
3551 | | add CARG4, CARG4, CARG2, lsl #3 | ||
3552 | | cmp CARG2, CARG3 // In array part? | ||
3553 | | bhs ->vmeta_tgetr | ||
3554 | | ldrd CARG12, [CARG4] | ||
3555 | |->BC_TGETR_Z: | ||
3556 | | ins_next1 | ||
3557 | | ins_next2 | ||
3558 | | strd CARG12, [BASE, RA] | ||
3559 | | ins_next3 | ||
3560 | break; | ||
3494 | 3561 | ||
3495 | case BC_TSETV: | 3562 | case BC_TSETV: |
3496 | | decode_RB8 RB, INS | 3563 | | decode_RB8 RB, INS |
@@ -3661,6 +3728,32 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
3661 | | barrierback TAB:CARG1, INS, CARG3 | 3728 | | barrierback TAB:CARG1, INS, CARG3 |
3662 | | b <2 | 3729 | | b <2 |
3663 | break; | 3730 | break; |
3731 | case BC_TSETR: | ||
3732 | | decode_RB8 RB, INS | ||
3733 | | decode_RC8 RC, INS | ||
3734 | | // RA = dst*8, RB = table*8, RC = key*8 | ||
3735 | | ldr TAB:CARG2, [BASE, RB] | ||
3736 | | ldr CARG3, [BASE, RC] | ||
3737 | | ldrb INS, TAB:CARG2->marked | ||
3738 | | ldr CARG1, TAB:CARG2->array | ||
3739 | | ldr CARG4, TAB:CARG2->asize | ||
3740 | | tst INS, #LJ_GC_BLACK // isblack(table) | ||
3741 | | add CARG1, CARG1, CARG3, lsl #3 | ||
3742 | | bne >7 | ||
3743 | |2: | ||
3744 | | cmp CARG3, CARG4 // In array part? | ||
3745 | | bhs ->vmeta_tsetr | ||
3746 | |->BC_TSETR_Z: | ||
3747 | | ldrd CARG34, [BASE, RA] | ||
3748 | | ins_next1 | ||
3749 | | ins_next2 | ||
3750 | | strd CARG34, [CARG1] | ||
3751 | | ins_next3 | ||
3752 | | | ||
3753 | |7: // Possible table write barrier for the value. Skip valiswhite check. | ||
3754 | | barrierback TAB:CARG2, INS, RB | ||
3755 | | b <2 | ||
3756 | break; | ||
3664 | 3757 | ||
3665 | case BC_TSETM: | 3758 | case BC_TSETM: |
3666 | | // RA = base*8 (table at base-1), RC = num_const (start index) | 3759 | | // RA = base*8 (table at base-1), RC = num_const (start index) |
diff --git a/src/vm_mips.dasc b/src/vm_mips.dasc index f37cd931..6db5801f 100644 --- a/src/vm_mips.dasc +++ b/src/vm_mips.dasc | |||
@@ -688,6 +688,16 @@ static void build_subroutines(BuildCtx *ctx) | |||
688 | | b ->vm_call_dispatch_f | 688 | | b ->vm_call_dispatch_f |
689 | |. li NARGS8:RC, 16 // 2 args for func(t, k). | 689 | |. li NARGS8:RC, 16 // 2 args for func(t, k). |
690 | | | 690 | | |
691 | |->vmeta_tgetr: | ||
692 | | load_got lj_tab_getinth | ||
693 | | call_intern lj_tab_getinth // (GCtab *t, int32_t key) | ||
694 | |. nop | ||
695 | | // Returns cTValue * or NULL. | ||
696 | | beqz CRET1, >1 | ||
697 | |. nop | ||
698 | | b ->BC_TGETR_Z | ||
699 | |. ldc1 f0, 0(CRET1) | ||
700 | | | ||
691 | |//----------------------------------------------------------------------- | 701 | |//----------------------------------------------------------------------- |
692 | | | 702 | | |
693 | |->vmeta_tsets1: | 703 | |->vmeta_tsets1: |
@@ -740,6 +750,16 @@ static void build_subroutines(BuildCtx *ctx) | |||
740 | | b ->vm_call_dispatch_f | 750 | | b ->vm_call_dispatch_f |
741 | |. li NARGS8:RC, 24 // 3 args for func(t, k, v) | 751 | |. li NARGS8:RC, 24 // 3 args for func(t, k, v) |
742 | | | 752 | | |
753 | |->vmeta_tsetr: | ||
754 | | load_got lj_tab_setinth | ||
755 | | sw BASE, L->base | ||
756 | | sw PC, SAVE_PC | ||
757 | | call_intern lj_tab_setinth // (lua_State *L, GCtab *t, int32_t key) | ||
758 | |. move CARG1, L | ||
759 | | // Returns TValue *. | ||
760 | | b ->BC_TSETR_Z | ||
761 | |. nop | ||
762 | | | ||
743 | |//-- Comparison metamethods --------------------------------------------- | 763 | |//-- Comparison metamethods --------------------------------------------- |
744 | | | 764 | | |
745 | |->vmeta_comp: | 765 | |->vmeta_comp: |
@@ -813,6 +833,18 @@ static void build_subroutines(BuildCtx *ctx) | |||
813 | |. nop | 833 | |. nop |
814 | |.endif | 834 | |.endif |
815 | | | 835 | | |
836 | |->vmeta_istype: | ||
837 | | load_got lj_meta_istype | ||
838 | | addiu PC, PC, -4 | ||
839 | | sw BASE, L->base | ||
840 | | srl CARG2, RA, 3 | ||
841 | | srl CARG3, RD, 3 | ||
842 | | sw PC, SAVE_PC | ||
843 | | call_intern lj_meta_istype // (lua_State *L, BCReg ra, BCReg tp) | ||
844 | |. move CARG1, L | ||
845 | | b ->cont_nop | ||
846 | |. nop | ||
847 | | | ||
816 | |//-- Arithmetic metamethods --------------------------------------------- | 848 | |//-- Arithmetic metamethods --------------------------------------------- |
817 | | | 849 | | |
818 | |->vmeta_unm: | 850 | |->vmeta_unm: |
@@ -2566,6 +2598,26 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
2566 | | ins_next | 2598 | | ins_next |
2567 | break; | 2599 | break; |
2568 | 2600 | ||
2601 | case BC_ISTYPE: | ||
2602 | | // RA = src*8, RD = -type*8 | ||
2603 | | addu TMP2, BASE, RA | ||
2604 | | srl TMP1, RD, 3 | ||
2605 | | lw TMP0, HI(TMP2) | ||
2606 | | ins_next1 | ||
2607 | | addu AT, TMP0, TMP1 | ||
2608 | | bnez AT, ->vmeta_istype | ||
2609 | |. ins_next2 | ||
2610 | break; | ||
2611 | case BC_ISNUM: | ||
2612 | | // RA = src*8, RD = -(TISNUM-1)*8 | ||
2613 | | addu TMP2, BASE, RA | ||
2614 | | lw TMP0, HI(TMP2) | ||
2615 | | ins_next1 | ||
2616 | | sltiu AT, TMP0, LJ_TISNUM | ||
2617 | | beqz AT, ->vmeta_istype | ||
2618 | |. ins_next2 | ||
2619 | break; | ||
2620 | |||
2569 | /* -- Unary ops --------------------------------------------------------- */ | 2621 | /* -- Unary ops --------------------------------------------------------- */ |
2570 | 2622 | ||
2571 | case BC_MOV: | 2623 | case BC_MOV: |
@@ -3204,6 +3256,30 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
3204 | | b ->vmeta_tgetb // Caveat: preserve TMP0! | 3256 | | b ->vmeta_tgetb // Caveat: preserve TMP0! |
3205 | |. nop | 3257 | |. nop |
3206 | break; | 3258 | break; |
3259 | case BC_TGETR: | ||
3260 | | // RA = dst*8, RB = table*8, RC = key*8 | ||
3261 | | decode_RB8a RB, INS | ||
3262 | | decode_RB8b RB | ||
3263 | | decode_RDtoRC8 RC, RD | ||
3264 | | addu CARG2, BASE, RB | ||
3265 | | addu CARG3, BASE, RC | ||
3266 | | lw TAB:CARG1, LO(CARG2) | ||
3267 | | ldc1 f0, 0(CARG3) | ||
3268 | | trunc.w.d f2, f0 | ||
3269 | | lw TMP0, TAB:CARG1->asize | ||
3270 | | mfc1 CARG2, f2 | ||
3271 | | lw TMP1, TAB:CARG1->array | ||
3272 | | sltu AT, CARG2, TMP0 | ||
3273 | | sll TMP2, CARG2, 3 | ||
3274 | | beqz AT, ->vmeta_tgetr // In array part? | ||
3275 | |. addu TMP2, TMP1, TMP2 | ||
3276 | | ldc1 f0, 0(TMP2) | ||
3277 | |->BC_TGETR_Z: | ||
3278 | | addu RA, BASE, RA | ||
3279 | | ins_next1 | ||
3280 | | sdc1 f0, 0(RA) | ||
3281 | | ins_next2 | ||
3282 | break; | ||
3207 | 3283 | ||
3208 | case BC_TSETV: | 3284 | case BC_TSETV: |
3209 | | // RA = src*8, RB = table*8, RC = key*8 | 3285 | | // RA = src*8, RB = table*8, RC = key*8 |
@@ -3392,6 +3468,38 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
3392 | |7: // Possible table write barrier for the value. Skip valiswhite check. | 3468 | |7: // Possible table write barrier for the value. Skip valiswhite check. |
3393 | | barrierback TAB:RB, TMP3, TMP0, <2 | 3469 | | barrierback TAB:RB, TMP3, TMP0, <2 |
3394 | break; | 3470 | break; |
3471 | case BC_TSETR: | ||
3472 | | // RA = dst*8, RB = table*8, RC = key*8 | ||
3473 | | decode_RB8a RB, INS | ||
3474 | | decode_RB8b RB | ||
3475 | | decode_RDtoRC8 RC, RD | ||
3476 | | addu CARG1, BASE, RB | ||
3477 | | addu CARG3, BASE, RC | ||
3478 | | lw TAB:CARG2, LO(CARG1) | ||
3479 | | ldc1 f0, 0(CARG3) | ||
3480 | | trunc.w.d f2, f0 | ||
3481 | | lbu TMP3, TAB:CARG2->marked | ||
3482 | | lw TMP0, TAB:CARG2->asize | ||
3483 | | mfc1 CARG3, f2 | ||
3484 | | lw TMP1, TAB:CARG2->array | ||
3485 | | andi AT, TMP3, LJ_GC_BLACK // isblack(table) | ||
3486 | | bnez AT, >7 | ||
3487 | |. addu RA, BASE, RA | ||
3488 | |2: | ||
3489 | | sltu AT, CARG3, TMP0 | ||
3490 | | sll TMP2, CARG3, 3 | ||
3491 | | beqz AT, ->vmeta_tsetr // In array part? | ||
3492 | |. ldc1 f20, 0(RA) | ||
3493 | | addu CRET1, TMP1, TMP2 | ||
3494 | |->BC_TSETR_Z: | ||
3495 | | ins_next1 | ||
3496 | | sdc1 f20, 0(CRET1) | ||
3497 | | ins_next2 | ||
3498 | | | ||
3499 | |7: // Possible table write barrier for the value. Skip valiswhite check. | ||
3500 | | barrierback TAB:RB, TMP3, TMP0, <2 | ||
3501 | break; | ||
3502 | |||
3395 | 3503 | ||
3396 | case BC_TSETM: | 3504 | case BC_TSETM: |
3397 | | // RA = base*8 (table at base-1), RD = num_const*8 (start index) | 3505 | | // RA = base*8 (table at base-1), RD = num_const*8 (start index) |
diff --git a/src/vm_ppc.dasc b/src/vm_ppc.dasc index e6fd977b..d76e3a7b 100644 --- a/src/vm_ppc.dasc +++ b/src/vm_ppc.dasc | |||
@@ -895,6 +895,17 @@ static void build_subroutines(BuildCtx *ctx) | |||
895 | | li NARGS8:RC, 16 // 2 args for func(t, k). | 895 | | li NARGS8:RC, 16 // 2 args for func(t, k). |
896 | | b ->vm_call_dispatch_f | 896 | | b ->vm_call_dispatch_f |
897 | | | 897 | | |
898 | |->vmeta_tgetr: | ||
899 | | bl extern lj_tab_getinth // (GCtab *t, int32_t key) | ||
900 | | // Returns cTValue * or NULL. | ||
901 | | cmplwi CRET1, 0 | ||
902 | | beq >1 | ||
903 | | lfd f14, 0(CRET1) | ||
904 | | b ->BC_TGETR_Z | ||
905 | |1: | ||
906 | | stwx TISNIL, BASE, RA | ||
907 | | b ->cont_nop | ||
908 | | | ||
898 | |//----------------------------------------------------------------------- | 909 | |//----------------------------------------------------------------------- |
899 | | | 910 | | |
900 | |->vmeta_tsets1: | 911 | |->vmeta_tsets1: |
@@ -962,6 +973,14 @@ static void build_subroutines(BuildCtx *ctx) | |||
962 | | stfd f0, 16(BASE) // Copy value to third argument. | 973 | | stfd f0, 16(BASE) // Copy value to third argument. |
963 | | b ->vm_call_dispatch_f | 974 | | b ->vm_call_dispatch_f |
964 | | | 975 | | |
976 | |->vmeta_tsetr: | ||
977 | | stp BASE, L->base | ||
978 | | stw PC, SAVE_PC | ||
979 | | bl extern lj_tab_setinth // (lua_State *L, GCtab *t, int32_t key) | ||
980 | | // Returns TValue *. | ||
981 | | stfd f14, 0(CRET1) | ||
982 | | b ->cont_nop | ||
983 | | | ||
965 | |//-- Comparison metamethods --------------------------------------------- | 984 | |//-- Comparison metamethods --------------------------------------------- |
966 | | | 985 | | |
967 | |->vmeta_comp: | 986 | |->vmeta_comp: |
@@ -1040,6 +1059,16 @@ static void build_subroutines(BuildCtx *ctx) | |||
1040 | | b <3 | 1059 | | b <3 |
1041 | |.endif | 1060 | |.endif |
1042 | | | 1061 | | |
1062 | |->vmeta_istype: | ||
1063 | | subi PC, PC, 4 | ||
1064 | | stp BASE, L->base | ||
1065 | | srwi CARG2, RA, 3 | ||
1066 | | mr CARG1, L | ||
1067 | | srwi CARG3, RD, 3 | ||
1068 | | stw PC, SAVE_PC | ||
1069 | | bl extern lj_meta_istype // (lua_State *L, BCReg ra, BCReg tp) | ||
1070 | | b ->cont_nop | ||
1071 | | | ||
1043 | |//-- Arithmetic metamethods --------------------------------------------- | 1072 | |//-- Arithmetic metamethods --------------------------------------------- |
1044 | | | 1073 | | |
1045 | |->vmeta_arith_nv: | 1074 | |->vmeta_arith_nv: |
@@ -3259,6 +3288,29 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
3259 | | ins_next | 3288 | | ins_next |
3260 | break; | 3289 | break; |
3261 | 3290 | ||
3291 | case BC_ISTYPE: | ||
3292 | | // RA = src*8, RD = -type*8 | ||
3293 | | lwzx TMP0, BASE, RA | ||
3294 | | srwi TMP1, RD, 3 | ||
3295 | | ins_next1 | ||
3296 | |.if not PPE and not GPR64 | ||
3297 | | add. TMP0, TMP0, TMP1 | ||
3298 | |.else | ||
3299 | | neg TMP1 | ||
3300 | | cmpw TMP0, TMP1 | ||
3301 | |.endif | ||
3302 | | bne ->vmeta_istype | ||
3303 | | ins_next2 | ||
3304 | break; | ||
3305 | case BC_ISNUM: | ||
3306 | | // RA = src*8, RD = -(TISNUM-1)*8 | ||
3307 | | lwzx TMP0, BASE, RA | ||
3308 | | ins_next1 | ||
3309 | | checknum TMP0 | ||
3310 | | bge ->vmeta_istype | ||
3311 | | ins_next2 | ||
3312 | break; | ||
3313 | |||
3262 | /* -- Unary ops --------------------------------------------------------- */ | 3314 | /* -- Unary ops --------------------------------------------------------- */ |
3263 | 3315 | ||
3264 | case BC_MOV: | 3316 | case BC_MOV: |
@@ -4010,6 +4062,30 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
4010 | | bne <1 // 'no __index' flag set: done. | 4062 | | bne <1 // 'no __index' flag set: done. |
4011 | | b ->vmeta_tgetb // Caveat: preserve TMP0! | 4063 | | b ->vmeta_tgetb // Caveat: preserve TMP0! |
4012 | break; | 4064 | break; |
4065 | case BC_TGETR: | ||
4066 | | // RA = dst*8, RB = table*8, RC = key*8 | ||
4067 | | add RB, BASE, RB | ||
4068 | | lwz TAB:CARG1, 4(RB) | ||
4069 | |.if DUALNUM | ||
4070 | | add RC, BASE, RC | ||
4071 | | lwz TMP0, TAB:CARG1->asize | ||
4072 | | lwz CARG2, 4(RC) | ||
4073 | | lwz TMP1, TAB:CARG1->array | ||
4074 | |.else | ||
4075 | | lfdx f0, BASE, RC | ||
4076 | | lwz TMP0, TAB:CARG1->asize | ||
4077 | | toint CARG2, f0 | ||
4078 | | lwz TMP1, TAB:CARG1->array | ||
4079 | |.endif | ||
4080 | | cmplw TMP0, CARG2 | ||
4081 | | slwi TMP2, CARG2, 3 | ||
4082 | | ble ->vmeta_tgetr // In array part? | ||
4083 | | lfdx f14, TMP1, TMP2 | ||
4084 | |->BC_TGETR_Z: | ||
4085 | | ins_next1 | ||
4086 | | stfdx f14, BASE, RA | ||
4087 | | ins_next2 | ||
4088 | break; | ||
4013 | 4089 | ||
4014 | case BC_TSETV: | 4090 | case BC_TSETV: |
4015 | | // RA = src*8, RB = table*8, RC = key*8 | 4091 | | // RA = src*8, RB = table*8, RC = key*8 |
@@ -4189,6 +4265,39 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
4189 | | barrierback TAB:RB, TMP3, TMP0 | 4265 | | barrierback TAB:RB, TMP3, TMP0 |
4190 | | b <2 | 4266 | | b <2 |
4191 | break; | 4267 | break; |
4268 | case BC_TSETR: | ||
4269 | | // RA = dst*8, RB = table*8, RC = key*8 | ||
4270 | | add RB, BASE, RB | ||
4271 | | lwz TAB:CARG2, 4(RB) | ||
4272 | |.if DUALNUM | ||
4273 | | add RC, BASE, RC | ||
4274 | | lbz TMP3, TAB:RB->marked | ||
4275 | | lwz TMP0, TAB:CARG2->asize | ||
4276 | | lwz CARG3, 4(RC) | ||
4277 | | lwz TMP1, TAB:CARG2->array | ||
4278 | |.else | ||
4279 | | lfdx f0, BASE, RC | ||
4280 | | lbz TMP3, TAB:RB->marked | ||
4281 | | lwz TMP0, TAB:CARG2->asize | ||
4282 | | toint CARG3, f0 | ||
4283 | | lwz TMP1, TAB:CARG2->array | ||
4284 | |.endif | ||
4285 | | andix. TMP2, TMP3, LJ_GC_BLACK // isblack(table) | ||
4286 | | bne >7 | ||
4287 | |2: | ||
4288 | | cmplw TMP0, CARG3 | ||
4289 | | slwi TMP2, CARG3, 3 | ||
4290 | | lfdx f14, BASE, RA | ||
4291 | | ble ->vmeta_tsetr // In array part? | ||
4292 | | ins_next1 | ||
4293 | | stfdx f14, TMP1, TMP2 | ||
4294 | | ins_next2 | ||
4295 | | | ||
4296 | |7: // Possible table write barrier for the value. Skip valiswhite check. | ||
4297 | | barrierback TAB:CARG2, TMP3, TMP2 | ||
4298 | | b <2 | ||
4299 | break; | ||
4300 | |||
4192 | 4301 | ||
4193 | case BC_TSETM: | 4302 | case BC_TSETM: |
4194 | | // RA = base*8 (table at base-1), RD = num_const*8 (start index) | 4303 | | // RA = base*8 (table at base-1), RD = num_const*8 (start index) |
diff --git a/src/vm_x86.dasc b/src/vm_x86.dasc index c8095db2..0c4b0ce6 100644 --- a/src/vm_x86.dasc +++ b/src/vm_x86.dasc | |||
@@ -911,6 +911,19 @@ static void build_subroutines(BuildCtx *ctx) | |||
911 | | mov NARGS:RD, 2+1 // 2 args for func(t, k). | 911 | | mov NARGS:RD, 2+1 // 2 args for func(t, k). |
912 | | jmp ->vm_call_dispatch_f | 912 | | jmp ->vm_call_dispatch_f |
913 | | | 913 | | |
914 | |->vmeta_tgetr: | ||
915 | | mov FCARG1, TAB:RB | ||
916 | | mov RB, BASE // Save BASE. | ||
917 | | mov FCARG2, RC // Caveat: FCARG2 == BASE | ||
918 | | call extern lj_tab_getinth@8 // (GCtab *t, int32_t key) | ||
919 | | // cTValue * or NULL returned in eax (RC). | ||
920 | | movzx RA, PC_RA | ||
921 | | mov BASE, RB // Restore BASE. | ||
922 | | test RC, RC | ||
923 | | jnz ->BC_TGETR_Z | ||
924 | | mov dword [BASE+RA*8+4], LJ_TNIL | ||
925 | | jmp ->BC_TGETR2_Z | ||
926 | | | ||
914 | |//----------------------------------------------------------------------- | 927 | |//----------------------------------------------------------------------- |
915 | | | 928 | | |
916 | |->vmeta_tsets: | 929 | |->vmeta_tsets: |
@@ -998,6 +1011,33 @@ static void build_subroutines(BuildCtx *ctx) | |||
998 | | mov NARGS:RD, 3+1 // 3 args for func(t, k, v). | 1011 | | mov NARGS:RD, 3+1 // 3 args for func(t, k, v). |
999 | | jmp ->vm_call_dispatch_f | 1012 | | jmp ->vm_call_dispatch_f |
1000 | | | 1013 | | |
1014 | |->vmeta_tsetr: | ||
1015 | |.if X64WIN | ||
1016 | | mov L:CARG1d, SAVE_L | ||
1017 | | mov CARG3d, RC | ||
1018 | | mov L:CARG1d->base, BASE | ||
1019 | | xchg CARG2d, TAB:RB // Caveat: CARG2d == BASE. | ||
1020 | |.elif X64 | ||
1021 | | mov L:CARG1d, SAVE_L | ||
1022 | | mov CARG2d, TAB:RB | ||
1023 | | mov L:CARG1d->base, BASE | ||
1024 | | mov RB, BASE // Save BASE. | ||
1025 | | mov CARG3d, RC // Caveat: CARG3d == BASE. | ||
1026 | |.else | ||
1027 | | mov L:RA, SAVE_L | ||
1028 | | mov ARG2, TAB:RB | ||
1029 | | mov RB, BASE // Save BASE. | ||
1030 | | mov ARG3, RC | ||
1031 | | mov ARG1, L:RA | ||
1032 | | mov L:RA->base, BASE | ||
1033 | |.endif | ||
1034 | | mov SAVE_PC, PC | ||
1035 | | call extern lj_tab_setinth // (lua_State *L, GCtab *t, int32_t key) | ||
1036 | | // TValue * returned in eax (RC). | ||
1037 | | movzx RA, PC_RA | ||
1038 | | mov BASE, RB // Restore BASE. | ||
1039 | | jmp ->BC_TSETR_Z | ||
1040 | | | ||
1001 | |//-- Comparison metamethods --------------------------------------------- | 1041 | |//-- Comparison metamethods --------------------------------------------- |
1002 | | | 1042 | | |
1003 | |->vmeta_comp: | 1043 | |->vmeta_comp: |
@@ -1092,6 +1132,26 @@ static void build_subroutines(BuildCtx *ctx) | |||
1092 | | jmp <3 | 1132 | | jmp <3 |
1093 | |.endif | 1133 | |.endif |
1094 | | | 1134 | | |
1135 | |->vmeta_istype: | ||
1136 | |.if X64 | ||
1137 | | mov L:CARG1d, SAVE_L | ||
1138 | | mov L:CARG1d->base, BASE // Caveat: CARG2d/CARG3d may be BASE. | ||
1139 | | mov CARG2d, RA | ||
1140 | | movzx CARG3d, PC_RD | ||
1141 | | mov L:RB, L:CARG1d | ||
1142 | |.else | ||
1143 | | movzx RD, PC_RD | ||
1144 | | mov ARG2, RA | ||
1145 | | mov L:RB, SAVE_L | ||
1146 | | mov ARG3, RD | ||
1147 | | mov ARG1, L:RB | ||
1148 | | mov L:RB->base, BASE | ||
1149 | |.endif | ||
1150 | | mov SAVE_PC, PC | ||
1151 | | call extern lj_meta_istype // (lua_State *L, BCReg ra, BCReg tp) | ||
1152 | | mov BASE, L:RB->base | ||
1153 | | jmp <6 | ||
1154 | | | ||
1095 | |//-- Arithmetic metamethods --------------------------------------------- | 1155 | |//-- Arithmetic metamethods --------------------------------------------- |
1096 | | | 1156 | | |
1097 | |->vmeta_arith_vno: | 1157 | |->vmeta_arith_vno: |
@@ -3827,6 +3887,18 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
3827 | | ins_next | 3887 | | ins_next |
3828 | break; | 3888 | break; |
3829 | 3889 | ||
3890 | case BC_ISTYPE: | ||
3891 | | ins_AD // RA = src, RD = -type | ||
3892 | | add RD, [BASE+RA*8+4] | ||
3893 | | jne ->vmeta_istype | ||
3894 | | ins_next | ||
3895 | break; | ||
3896 | case BC_ISNUM: | ||
3897 | | ins_AD // RA = src, RD = -(TISNUM-1) | ||
3898 | | checknum RA, ->vmeta_istype | ||
3899 | | ins_next | ||
3900 | break; | ||
3901 | |||
3830 | /* -- Unary ops --------------------------------------------------------- */ | 3902 | /* -- Unary ops --------------------------------------------------------- */ |
3831 | 3903 | ||
3832 | case BC_MOV: | 3904 | case BC_MOV: |
@@ -4502,6 +4574,32 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
4502 | | mov dword [BASE+RA*8+4], LJ_TNIL | 4574 | | mov dword [BASE+RA*8+4], LJ_TNIL |
4503 | | jmp <1 | 4575 | | jmp <1 |
4504 | break; | 4576 | break; |
4577 | case BC_TGETR: | ||
4578 | | ins_ABC // RA = dst, RB = table, RC = key | ||
4579 | | mov TAB:RB, [BASE+RB*8] | ||
4580 | |.if DUALNUM | ||
4581 | | mov RC, dword [BASE+RC*8] | ||
4582 | |.else | ||
4583 | | cvttsd2si RC, qword [BASE+RC*8] | ||
4584 | |.endif | ||
4585 | | cmp RC, TAB:RB->asize | ||
4586 | | jae ->vmeta_tgetr // Not in array part? Use fallback. | ||
4587 | | shl RC, 3 | ||
4588 | | add RC, TAB:RB->array | ||
4589 | | // Get array slot. | ||
4590 | |->BC_TGETR_Z: | ||
4591 | |.if X64 | ||
4592 | | mov RBa, [RC] | ||
4593 | | mov [BASE+RA*8], RBa | ||
4594 | |.else | ||
4595 | | mov RB, [RC] | ||
4596 | | mov RC, [RC+4] | ||
4597 | | mov [BASE+RA*8], RB | ||
4598 | | mov [BASE+RA*8+4], RC | ||
4599 | |.endif | ||
4600 | |->BC_TGETR2_Z: | ||
4601 | | ins_next | ||
4602 | break; | ||
4505 | 4603 | ||
4506 | case BC_TSETV: | 4604 | case BC_TSETV: |
4507 | | ins_ABC // RA = src, RB = table, RC = key | 4605 | | ins_ABC // RA = src, RB = table, RC = key |
@@ -4688,6 +4786,39 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
4688 | | movzx RA, PC_RA // Restore RA. | 4786 | | movzx RA, PC_RA // Restore RA. |
4689 | | jmp <2 | 4787 | | jmp <2 |
4690 | break; | 4788 | break; |
4789 | case BC_TSETR: | ||
4790 | | ins_ABC // RA = src, RB = table, RC = key | ||
4791 | | mov TAB:RB, [BASE+RB*8] | ||
4792 | |.if DUALNUM | ||
4793 | | mov RC, dword [BASE+RC*8] | ||
4794 | |.else | ||
4795 | | cvttsd2si RC, qword [BASE+RC*8] | ||
4796 | |.endif | ||
4797 | | test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table) | ||
4798 | | jnz >7 | ||
4799 | |2: | ||
4800 | | cmp RC, TAB:RB->asize | ||
4801 | | jae ->vmeta_tsetr | ||
4802 | | shl RC, 3 | ||
4803 | | add RC, TAB:RB->array | ||
4804 | | // Set array slot. | ||
4805 | |->BC_TSETR_Z: | ||
4806 | |.if X64 | ||
4807 | | mov RBa, [BASE+RA*8] | ||
4808 | | mov [RC], RBa | ||
4809 | |.else | ||
4810 | | mov RB, [BASE+RA*8+4] | ||
4811 | | mov RA, [BASE+RA*8] | ||
4812 | | mov [RC+4], RB | ||
4813 | | mov [RC], RA | ||
4814 | |.endif | ||
4815 | | ins_next | ||
4816 | | | ||
4817 | |7: // Possible table write barrier for the value. Skip valiswhite check. | ||
4818 | | barrierback TAB:RB, RA | ||
4819 | | movzx RA, PC_RA // Restore RA. | ||
4820 | | jmp <2 | ||
4821 | break; | ||
4691 | 4822 | ||
4692 | case BC_TSETM: | 4823 | case BC_TSETM: |
4693 | | ins_AD // RA = base (table at base-1), RD = num const (start index) | 4824 | | ins_AD // RA = base (table at base-1), RD = num const (start index) |