aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.dep18
-rw-r--r--src/host/buildvm_lib.c32
-rw-r--r--src/host/buildvm_libbc.h4
-rw-r--r--src/host/genlibbc.lua108
-rw-r--r--src/lj_arch.h1
-rw-r--r--src/lj_bc.h4
-rw-r--r--src/lj_bcdump.h2
-rw-r--r--src/lj_dispatch.h10
-rw-r--r--src/lj_meta.c13
-rw-r--r--src/lj_meta.h1
-rw-r--r--src/lj_record.c16
-rw-r--r--src/lj_tab.h2
-rw-r--r--src/vm_arm.dasc93
-rw-r--r--src/vm_mips.dasc108
-rw-r--r--src/vm_ppc.dasc109
-rw-r--r--src/vm_x86.dasc131
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
135lj_meta.o: lj_meta.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 135lj_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
138lj_obj.o: lj_obj.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h 138lj_obj.o: lj_obj.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h
139lj_opt_dce.o: lj_opt_dce.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 139lj_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 \
221host/buildvm_fold.o: host/buildvm_fold.c host/buildvm.h lj_def.h lua.h \ 221host/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
223host/buildvm_lib.o: host/buildvm_lib.c host/buildvm.h lj_def.h lua.h luaconf.h \ 223host/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
226host/buildvm_peobj.o: host/buildvm_peobj.c host/buildvm.h lj_def.h lua.h \ 226host/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
155static uint32_t libdef_uleb128(uint8_t **pp) 156static 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
167static void libdef_swapbc(uint8_t *p) 167static 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 @@
3static const int libbc_endian = 0; 3static const int libbc_endian = 0;
4 4
5static const uint8_t libbc_code[] = { 5static const uint8_t libbc_code[] = {
60,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, 60,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,
70,1,2,22,1,0,0,72,1,2,0,243,244,148,165,20,198,190,199,252,3,0 70,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
10static const struct { const char *name; int ofs; } libbc_map[] = { 10static 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
9local ffi = require("ffi")
10local bit = require("bit")
11local vmdef = require("jit.vmdef")
12local bcnames = vmdef.bcnames
13
14local format = string.format
15
16local isbe = (string.byte(string.dump(function() end), 5) % 2 == 1)
17
9local function usage(arg) 18local 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
37end 46end
38 47
48local 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
61end
62
63local 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
75end
76
77-- ORDER LJ_T
78local name2itype = {
79 str = 5, func = 9, tab = 12, int = 14, num = 15
80}
81
82local BC = {}
83for i=0,#bcnames/6-1 do
84 BC[string.gsub(string.sub(bcnames, i*6+1, i*6+6), " ", "")] = i
85end
86local xop, xra = isbe and 3 or 0, isbe and 2 or 1
87local xrc, xrb = isbe and 1 or 2, isbe and 0 or 3
88
89local 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)
133end
134
39local function find_defs(src) 135local 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
42enum { 42enum {
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. */
428void 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. */
427void lj_meta_call(lua_State *L, TValue *func, TValue *top) 440void 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);
31LJ_FUNCA TValue *lj_meta_equal(lua_State *L, GCobj *o1, GCobj *o2, int ne); 31LJ_FUNCA TValue *lj_meta_equal(lua_State *L, GCobj *o1, GCobj *o2, int ne);
32LJ_FUNCA TValue * LJ_FASTCALL lj_meta_equal_cd(lua_State *L, BCIns ins); 32LJ_FUNCA TValue * LJ_FASTCALL lj_meta_equal_cd(lua_State *L, BCIns ins);
33LJ_FUNCA TValue *lj_meta_comp(lua_State *L, cTValue *o1, cTValue *o2, int op); 33LJ_FUNCA TValue *lj_meta_comp(lua_State *L, cTValue *o1, cTValue *o2, int op);
34LJ_FUNCA void lj_meta_istype(lua_State *L, BCReg ra, BCReg tp);
34LJ_FUNCA void lj_meta_call(lua_State *L, TValue *func, TValue *top); 35LJ_FUNCA void lj_meta_call(lua_State *L, TValue *func, TValue *top);
35LJ_FUNCA void LJ_FASTCALL lj_meta_for(lua_State *L, TValue *o); 36LJ_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
52LJ_FUNCA TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key); 52LJ_FUNCA TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key);
53LJ_FUNC TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key); 53LJ_FUNCA TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key);
54LJ_FUNC TValue *lj_tab_setstr(lua_State *L, GCtab *t, GCstr *key); 54LJ_FUNC TValue *lj_tab_setstr(lua_State *L, GCtab *t, GCstr *key);
55LJ_FUNC TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key); 55LJ_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)