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 /src | |
| 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.
Diffstat (limited to 'src')
| -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) |
