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/host | |
| 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/host')
| -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 |
3 files changed, 122 insertions, 22 deletions
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] |
