diff options
| author | Mike Pall <mike> | 2013-02-22 01:40:41 +0100 |
|---|---|---|
| committer | Mike Pall <mike> | 2013-02-22 01:40:41 +0100 |
| commit | e20157c6e68472e7c4d82d9ed4c0bb5be029c388 (patch) | |
| tree | b26bfadc10b7301d73b84293630c44e7d1fb37f9 | |
| parent | c3219b7d177f6722b9de808cfd3d3dbfc6808e6f (diff) | |
| download | luajit-e20157c6e68472e7c4d82d9ed4c0bb5be029c388.tar.gz luajit-e20157c6e68472e7c4d82d9ed4c0bb5be029c388.tar.bz2 luajit-e20157c6e68472e7c4d82d9ed4c0bb5be029c388.zip | |
Add support for embedding LuaJIT bytecode for builtins.
| -rw-r--r-- | src/Makefile | 6 | ||||
| -rw-r--r-- | src/Makefile.dep | 6 | ||||
| -rw-r--r-- | src/host/buildvm_lib.c | 51 | ||||
| -rw-r--r-- | src/host/buildvm_libbc.h | 12 | ||||
| -rw-r--r-- | src/host/genlibbc.lua | 68 | ||||
| -rw-r--r-- | src/lj_bcdump.h | 1 | ||||
| -rw-r--r-- | src/lj_bcread.c | 34 | ||||
| -rw-r--r-- | src/lj_debug.c | 17 | ||||
| -rw-r--r-- | src/lj_debug.h | 2 | ||||
| -rw-r--r-- | src/lj_err.c | 2 | ||||
| -rw-r--r-- | src/lj_lib.c | 27 | ||||
| -rw-r--r-- | src/lj_lib.h | 4 |
12 files changed, 199 insertions, 31 deletions
diff --git a/src/Makefile b/src/Makefile index 4ea8c85e..f3631a0d 100644 --- a/src/Makefile +++ b/src/Makefile | |||
| @@ -558,6 +558,10 @@ amalg: | |||
| 558 | clean: | 558 | clean: |
| 559 | $(HOST_RM) $(ALL_RM) | 559 | $(HOST_RM) $(ALL_RM) |
| 560 | 560 | ||
| 561 | libbc: | ||
| 562 | ./$(LUAJIT_T) host/genlibbc.lua $(LJLIB_C) >host/buildvm_libbc.h | ||
| 563 | $(MAKE) all | ||
| 564 | |||
| 561 | depend: | 565 | depend: |
| 562 | @for file in $(ALL_HDRGEN); do \ | 566 | @for file in $(ALL_HDRGEN); do \ |
| 563 | test -f $$file || touch $$file; \ | 567 | test -f $$file || touch $$file; \ |
| @@ -572,7 +576,7 @@ depend: | |||
| 572 | test -s $$file || $(HOST_RM) $$file; \ | 576 | test -s $$file || $(HOST_RM) $$file; \ |
| 573 | done | 577 | done |
| 574 | 578 | ||
| 575 | .PHONY: default all amalg clean depend | 579 | .PHONY: default all amalg clean libbc depend |
| 576 | 580 | ||
| 577 | ############################################################################## | 581 | ############################################################################## |
| 578 | # Rules for generated files. | 582 | # Rules for generated files. |
diff --git a/src/Makefile.dep b/src/Makefile.dep index 5d91723a..54004f7c 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep | |||
| @@ -124,7 +124,8 @@ lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | |||
| 124 | lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h | 124 | lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h |
| 125 | lj_lib.o: lj_lib.c lauxlib.h lua.h luaconf.h lj_obj.h lj_def.h lj_arch.h \ | 125 | lj_lib.o: lj_lib.c lauxlib.h lua.h luaconf.h lj_obj.h lj_def.h lj_arch.h \ |
| 126 | lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_bc.h \ | 126 | lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_bc.h \ |
| 127 | lj_dispatch.h lj_jit.h lj_ir.h lj_vm.h lj_strscan.h lj_lib.h | 127 | lj_dispatch.h lj_jit.h lj_ir.h lj_vm.h lj_strscan.h lj_lex.h lj_bcdump.h \ |
| 128 | lj_lib.h | ||
| 128 | lj_load.o: lj_load.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ | 129 | lj_load.o: lj_load.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ |
| 129 | lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_func.h lj_frame.h \ | 130 | lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_func.h lj_frame.h \ |
| 130 | lj_bc.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h | 131 | lj_bc.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h |
| @@ -220,7 +221,8 @@ host/buildvm_asm.o: host/buildvm_asm.c host/buildvm.h lj_def.h lua.h luaconf.h \ | |||
| 220 | 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 \ |
| 221 | 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 |
| 222 | 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 \ |
| 223 | 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_lib.h lj_obj.h \ |
| 225 | host/buildvm_libbc.h | ||
| 224 | 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 \ |
| 225 | 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 |
| 226 | host/minilua.o: host/minilua.c | 228 | host/minilua.o: host/minilua.c |
diff --git a/src/host/buildvm_lib.c b/src/host/buildvm_lib.c index 40141dfb..182ab90f 100644 --- a/src/host/buildvm_lib.c +++ b/src/host/buildvm_lib.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include "buildvm.h" | 6 | #include "buildvm.h" |
| 7 | #include "lj_obj.h" | 7 | #include "lj_obj.h" |
| 8 | #include "lj_lib.h" | 8 | #include "lj_lib.h" |
| 9 | #include "buildvm_libbc.h" | ||
| 9 | 10 | ||
| 10 | /* Context for library definitions. */ | 11 | /* Context for library definitions. */ |
| 11 | static uint8_t obuf[8192]; | 12 | static uint8_t obuf[8192]; |
| @@ -151,6 +152,55 @@ static void libdef_func(BuildCtx *ctx, char *p, int arg) | |||
| 151 | regfunc = REGFUNC_OK; | 152 | regfunc = REGFUNC_OK; |
| 152 | } | 153 | } |
| 153 | 154 | ||
| 155 | static uint32_t libdef_uleb128(uint8_t **pp) | ||
| 156 | { | ||
| 157 | uint8_t *p = *pp; | ||
| 158 | uint32_t v = *p++; | ||
| 159 | if (v >= 0x80) { | ||
| 160 | int sh = 0; v &= 0x7f; | ||
| 161 | do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80); | ||
| 162 | } | ||
| 163 | *pp = p; | ||
| 164 | return v; | ||
| 165 | } | ||
| 166 | |||
| 167 | static void libdef_swapbc(uint8_t *p) | ||
| 168 | { | ||
| 169 | uint32_t i, sizebc; | ||
| 170 | p += 4; | ||
| 171 | libdef_uleb128(&p); | ||
| 172 | libdef_uleb128(&p); | ||
| 173 | sizebc = libdef_uleb128(&p); | ||
| 174 | for (i = 0; i < sizebc; i++, p += 4) { | ||
| 175 | uint8_t t = p[0]; p[0] = p[3]; p[3] = t; | ||
| 176 | t = p[1]; p[1] = p[2]; p[2] = t; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | static void libdef_lua(BuildCtx *ctx, char *p, int arg) | ||
| 181 | { | ||
| 182 | UNUSED(arg); | ||
| 183 | if (ctx->mode == BUILD_libdef) { | ||
| 184 | int i; | ||
| 185 | for (i = 0; libbc_map[i].name != NULL; i++) { | ||
| 186 | if (!strcmp(libbc_map[i].name, p)) { | ||
| 187 | int ofs = libbc_map[i].ofs; | ||
| 188 | int len = libbc_map[i+1].ofs - ofs; | ||
| 189 | obuf[2]++; /* Bump hash table size. */ | ||
| 190 | *optr++ = LIBINIT_LUA; | ||
| 191 | libdef_name(p, 0); | ||
| 192 | memcpy(optr, libbc_code + ofs, len); | ||
| 193 | if (libbc_endian != LJ_BE) | ||
| 194 | libdef_swapbc(optr); | ||
| 195 | optr += len; | ||
| 196 | return; | ||
| 197 | } | ||
| 198 | } | ||
| 199 | fprintf(stderr, "Error: missing libbc definition for %s\n", p); | ||
| 200 | exit(1); | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 154 | static uint32_t find_rec(char *name) | 204 | static uint32_t find_rec(char *name) |
| 155 | { | 205 | { |
| 156 | char *p = (char *)obuf; | 206 | char *p = (char *)obuf; |
| @@ -277,6 +327,7 @@ static const LibDefHandler libdef_handlers[] = { | |||
| 277 | { "CF(", ")", libdef_func, LIBINIT_CF }, | 327 | { "CF(", ")", libdef_func, LIBINIT_CF }, |
| 278 | { "ASM(", ")", libdef_func, LIBINIT_ASM }, | 328 | { "ASM(", ")", libdef_func, LIBINIT_ASM }, |
| 279 | { "ASM_(", ")", libdef_func, LIBINIT_ASM_ }, | 329 | { "ASM_(", ")", libdef_func, LIBINIT_ASM_ }, |
| 330 | { "LUA(", ")", libdef_lua, 0 }, | ||
| 280 | { "REC(", ")", libdef_rec, 0 }, | 331 | { "REC(", ")", libdef_rec, 0 }, |
| 281 | { "PUSH(", ")", libdef_push, 0 }, | 332 | { "PUSH(", ")", libdef_push, 0 }, |
| 282 | { "SET(", ")", libdef_set, 0 }, | 333 | { "SET(", ")", libdef_set, 0 }, |
diff --git a/src/host/buildvm_libbc.h b/src/host/buildvm_libbc.h new file mode 100644 index 00000000..d2d83ea6 --- /dev/null +++ b/src/host/buildvm_libbc.h | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | /* This is a generated file. DO NOT EDIT! */ | ||
| 2 | |||
| 3 | static const int libbc_endian = 0; | ||
| 4 | |||
| 5 | static const uint8_t libbc_code[] = { | ||
| 6 | 0 | ||
| 7 | }; | ||
| 8 | |||
| 9 | static const struct { const char *name; int ofs; } libbc_map[] = { | ||
| 10 | {NULL,0} | ||
| 11 | }; | ||
| 12 | |||
diff --git a/src/host/genlibbc.lua b/src/host/genlibbc.lua new file mode 100644 index 00000000..b0dbf17a --- /dev/null +++ b/src/host/genlibbc.lua | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | ---------------------------------------------------------------------------- | ||
| 2 | -- Lua script to dump the bytecode of the library functions written in Lua. | ||
| 3 | -- The resulting 'buildvm_libbc.h' is used for the build process of LuaJIT. | ||
| 4 | ---------------------------------------------------------------------------- | ||
| 5 | -- Copyright (C) 2005-2013 Mike Pall. All rights reserved. | ||
| 6 | -- Released under the MIT license. See Copyright Notice in luajit.h | ||
| 7 | ---------------------------------------------------------------------------- | ||
| 8 | |||
| 9 | local function usage() | ||
| 10 | io.stderr:write("Usage: ", arg and arg[0] or "genlibbc", " lib_*.c\n") | ||
| 11 | os.exit(1) | ||
| 12 | end | ||
| 13 | |||
| 14 | local function read_source() | ||
| 15 | if not (arg and arg[1]) then usage() end | ||
| 16 | local src = "" | ||
| 17 | for _,name in ipairs(arg) do | ||
| 18 | local fp = assert(io.open(name)) | ||
| 19 | src = src .. fp:read("*a") | ||
| 20 | fp:close() | ||
| 21 | end | ||
| 22 | return src | ||
| 23 | end | ||
| 24 | |||
| 25 | local function find_defs(src) | ||
| 26 | local defs = {} | ||
| 27 | for name, code in string.gmatch(src, "LJLIB_LUA%(([^)]*)%)%s*/%*(.-)%*/") do | ||
| 28 | local env = {} | ||
| 29 | local func = assert(load("return "..code, "", nil, env))() | ||
| 30 | local d = string.dump(func, true) | ||
| 31 | local ofs = 6 | ||
| 32 | while string.byte(d, ofs) > 127 do ofs = ofs + 1 end | ||
| 33 | defs[name] = string.sub(d, ofs+1, -2) | ||
| 34 | defs[#defs+1] = name | ||
| 35 | end | ||
| 36 | return defs | ||
| 37 | end | ||
| 38 | |||
| 39 | local function write_defs(fp, defs) | ||
| 40 | fp:write("/* This is a generated file. DO NOT EDIT! */\n\n") | ||
| 41 | fp:write("static const int libbc_endian = ", | ||
| 42 | string.byte(string.dump(function() end), 5) % 2, ";\n\n") | ||
| 43 | local s = "" | ||
| 44 | for _,name in ipairs(defs) do | ||
| 45 | s = s .. defs[name] | ||
| 46 | end | ||
| 47 | fp:write("static const uint8_t libbc_code[] = {\n") | ||
| 48 | local n = 0 | ||
| 49 | for i=1,#s do | ||
| 50 | local x = string.byte(s, i) | ||
| 51 | fp:write(x, ",") | ||
| 52 | n = n + (x < 10 and 2 or (x < 100 and 3 or 4)) | ||
| 53 | if n >= 75 then n = 0; fp:write("\n") end | ||
| 54 | end | ||
| 55 | fp:write("0\n};\n\n") | ||
| 56 | fp:write("static const struct { const char *name; int ofs; } libbc_map[] = {\n") | ||
| 57 | local m = 0 | ||
| 58 | for _,name in ipairs(defs) do | ||
| 59 | fp:write('{"', name, '",', m, '},\n') | ||
| 60 | m = m + #defs[name] | ||
| 61 | end | ||
| 62 | fp:write("{NULL,", m, "}\n};\n\n") | ||
| 63 | fp:flush() | ||
| 64 | end | ||
| 65 | |||
| 66 | local src = read_source() | ||
| 67 | local defs = find_defs(src) | ||
| 68 | write_defs(io.stdout, defs) | ||
diff --git a/src/lj_bcdump.h b/src/lj_bcdump.h index e660156d..c1ed54e7 100644 --- a/src/lj_bcdump.h +++ b/src/lj_bcdump.h | |||
| @@ -61,6 +61,7 @@ enum { | |||
| 61 | 61 | ||
| 62 | LJ_FUNC int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, | 62 | LJ_FUNC int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, |
| 63 | void *data, int strip); | 63 | void *data, int strip); |
| 64 | LJ_FUNC GCproto *lj_bcread_proto(LexState *ls); | ||
| 64 | LJ_FUNC GCproto *lj_bcread(LexState *ls); | 65 | LJ_FUNC GCproto *lj_bcread(LexState *ls); |
| 65 | 66 | ||
| 66 | #endif | 67 | #endif |
diff --git a/src/lj_bcread.c b/src/lj_bcread.c index 2b5ba855..7a8c08f5 100644 --- a/src/lj_bcread.c +++ b/src/lj_bcread.c | |||
| @@ -326,25 +326,13 @@ static void bcread_uv(LexState *ls, GCproto *pt, MSize sizeuv) | |||
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | /* Read a prototype. */ | 328 | /* Read a prototype. */ |
| 329 | static GCproto *bcread_proto(LexState *ls) | 329 | GCproto *lj_bcread_proto(LexState *ls) |
| 330 | { | 330 | { |
| 331 | GCproto *pt; | 331 | GCproto *pt; |
| 332 | MSize framesize, numparams, flags, sizeuv, sizekgc, sizekn, sizebc, sizept; | 332 | MSize framesize, numparams, flags, sizeuv, sizekgc, sizekn, sizebc, sizept; |
| 333 | MSize ofsk, ofsuv, ofsdbg; | 333 | MSize ofsk, ofsuv, ofsdbg; |
| 334 | MSize sizedbg = 0; | 334 | MSize sizedbg = 0; |
| 335 | BCLine firstline = 0, numline = 0; | 335 | BCLine firstline = 0, numline = 0; |
| 336 | MSize len, startn; | ||
| 337 | |||
| 338 | /* Read length. */ | ||
| 339 | if (ls->n > 0 && ls->p[0] == 0) { /* Shortcut EOF. */ | ||
| 340 | ls->n--; ls->p++; | ||
| 341 | return NULL; | ||
| 342 | } | ||
| 343 | bcread_want(ls, 5); | ||
| 344 | len = bcread_uleb128(ls); | ||
| 345 | if (!len) return NULL; /* EOF */ | ||
| 346 | bcread_need(ls, len); | ||
| 347 | startn = ls->n; | ||
| 348 | 336 | ||
| 349 | /* Read prototype header. */ | 337 | /* Read prototype header. */ |
| 350 | flags = bcread_byte(ls); | 338 | flags = bcread_byte(ls); |
| @@ -413,9 +401,6 @@ static GCproto *bcread_proto(LexState *ls) | |||
| 413 | setmref(pt->uvinfo, NULL); | 401 | setmref(pt->uvinfo, NULL); |
| 414 | setmref(pt->varinfo, NULL); | 402 | setmref(pt->varinfo, NULL); |
| 415 | } | 403 | } |
| 416 | |||
| 417 | if (len != startn - ls->n) | ||
| 418 | bcread_error(ls, LJ_ERR_BCBAD); | ||
| 419 | return pt; | 404 | return pt; |
| 420 | } | 405 | } |
| 421 | 406 | ||
| @@ -462,8 +447,21 @@ GCproto *lj_bcread(LexState *ls) | |||
| 462 | if (!bcread_header(ls)) | 447 | if (!bcread_header(ls)) |
| 463 | bcread_error(ls, LJ_ERR_BCFMT); | 448 | bcread_error(ls, LJ_ERR_BCFMT); |
| 464 | for (;;) { /* Process all prototypes in the bytecode dump. */ | 449 | for (;;) { /* Process all prototypes in the bytecode dump. */ |
| 465 | GCproto *pt = bcread_proto(ls); | 450 | GCproto *pt; |
| 466 | if (!pt) break; | 451 | MSize len, startn; |
| 452 | /* Read length. */ | ||
| 453 | if (ls->n > 0 && ls->p[0] == 0) { /* Shortcut EOF. */ | ||
| 454 | ls->n--; ls->p++; | ||
| 455 | break; | ||
| 456 | } | ||
| 457 | bcread_want(ls, 5); | ||
| 458 | len = bcread_uleb128(ls); | ||
| 459 | if (!len) break; /* EOF */ | ||
| 460 | bcread_need(ls, len); | ||
| 461 | startn = ls->n; | ||
| 462 | pt = lj_bcread_proto(ls); | ||
| 463 | if (len != startn - ls->n) | ||
| 464 | bcread_error(ls, LJ_ERR_BCBAD); | ||
| 467 | setprotoV(L, L->top, pt); | 465 | setprotoV(L, L->top, pt); |
| 468 | incr_top(L); | 466 | incr_top(L); |
| 469 | } | 467 | } |
diff --git a/src/lj_debug.c b/src/lj_debug.c index be7fb2b1..ec56b7d2 100644 --- a/src/lj_debug.c +++ b/src/lj_debug.c | |||
| @@ -321,7 +321,7 @@ const char *lj_debug_funcname(lua_State *L, TValue *frame, const char **name) | |||
| 321 | /* -- Source code locations ----------------------------------------------- */ | 321 | /* -- Source code locations ----------------------------------------------- */ |
| 322 | 322 | ||
| 323 | /* Generate shortened source name. */ | 323 | /* Generate shortened source name. */ |
| 324 | void lj_debug_shortname(char *out, GCstr *str) | 324 | void lj_debug_shortname(char *out, GCstr *str, BCLine line) |
| 325 | { | 325 | { |
| 326 | const char *src = strdata(str); | 326 | const char *src = strdata(str); |
| 327 | if (*src == '=') { | 327 | if (*src == '=') { |
| @@ -335,11 +335,11 @@ void lj_debug_shortname(char *out, GCstr *str) | |||
| 335 | *out++ = '.'; *out++ = '.'; *out++ = '.'; | 335 | *out++ = '.'; *out++ = '.'; *out++ = '.'; |
| 336 | } | 336 | } |
| 337 | strcpy(out, src); | 337 | strcpy(out, src); |
| 338 | } else { /* Output [string "string"]. */ | 338 | } else { /* Output [string "string"] or [builtin:name]. */ |
| 339 | size_t len; /* Length, up to first control char. */ | 339 | size_t len; /* Length, up to first control char. */ |
| 340 | for (len = 0; len < LUA_IDSIZE-12; len++) | 340 | for (len = 0; len < LUA_IDSIZE-12; len++) |
| 341 | if (((const unsigned char *)src)[len] < ' ') break; | 341 | if (((const unsigned char *)src)[len] < ' ') break; |
| 342 | strcpy(out, "[string \""); out += 9; | 342 | strcpy(out, line == ~(BCLine)0 ? "[builtin:" : "[string \""); out += 9; |
| 343 | if (src[len] != '\0') { /* Must truncate? */ | 343 | if (src[len] != '\0') { /* Must truncate? */ |
| 344 | if (len > LUA_IDSIZE-15) len = LUA_IDSIZE-15; | 344 | if (len > LUA_IDSIZE-15) len = LUA_IDSIZE-15; |
| 345 | strncpy(out, src, len); out += len; | 345 | strncpy(out, src, len); out += len; |
| @@ -347,7 +347,7 @@ void lj_debug_shortname(char *out, GCstr *str) | |||
| 347 | } else { | 347 | } else { |
| 348 | strcpy(out, src); out += len; | 348 | strcpy(out, src); out += len; |
| 349 | } | 349 | } |
| 350 | strcpy(out, "\"]"); | 350 | strcpy(out, line == ~(BCLine)0 ? "]" : "\"]"); |
| 351 | } | 351 | } |
| 352 | } | 352 | } |
| 353 | 353 | ||
| @@ -360,8 +360,9 @@ void lj_debug_addloc(lua_State *L, const char *msg, | |||
| 360 | if (isluafunc(fn)) { | 360 | if (isluafunc(fn)) { |
| 361 | BCLine line = debug_frameline(L, fn, nextframe); | 361 | BCLine line = debug_frameline(L, fn, nextframe); |
| 362 | if (line >= 0) { | 362 | if (line >= 0) { |
| 363 | GCproto *pt = funcproto(fn); | ||
| 363 | char buf[LUA_IDSIZE]; | 364 | char buf[LUA_IDSIZE]; |
| 364 | lj_debug_shortname(buf, proto_chunkname(funcproto(fn))); | 365 | lj_debug_shortname(buf, proto_chunkname(pt), pt->firstline); |
| 365 | lj_str_pushf(L, "%s:%d: %s", buf, line, msg); | 366 | lj_str_pushf(L, "%s:%d: %s", buf, line, msg); |
| 366 | return; | 367 | return; |
| 367 | } | 368 | } |
| @@ -377,7 +378,9 @@ void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc) | |||
| 377 | const char *s = strdata(name); | 378 | const char *s = strdata(name); |
| 378 | MSize i, len = name->len; | 379 | MSize i, len = name->len; |
| 379 | BCLine line = lj_debug_line(pt, pc); | 380 | BCLine line = lj_debug_line(pt, pc); |
| 380 | if (*s == '@') { | 381 | if (pt->firstline == ~(BCLine)0) { |
| 382 | lj_str_pushf(L, "builtin:%s", s); | ||
| 383 | } else if (*s == '@') { | ||
| 381 | s++; len--; | 384 | s++; len--; |
| 382 | for (i = len; i > 0; i--) | 385 | for (i = len; i > 0; i--) |
| 383 | if (s[i] == '/' || s[i] == '\\') { | 386 | if (s[i] == '/' || s[i] == '\\') { |
| @@ -453,7 +456,7 @@ int lj_debug_getinfo(lua_State *L, const char *what, lj_Debug *ar, int ext) | |||
| 453 | BCLine firstline = pt->firstline; | 456 | BCLine firstline = pt->firstline; |
| 454 | GCstr *name = proto_chunkname(pt); | 457 | GCstr *name = proto_chunkname(pt); |
| 455 | ar->source = strdata(name); | 458 | ar->source = strdata(name); |
| 456 | lj_debug_shortname(ar->short_src, name); | 459 | lj_debug_shortname(ar->short_src, name, pt->firstline); |
| 457 | ar->linedefined = (int)firstline; | 460 | ar->linedefined = (int)firstline; |
| 458 | ar->lastlinedefined = (int)(firstline + pt->numline); | 461 | ar->lastlinedefined = (int)(firstline + pt->numline); |
| 459 | ar->what = firstline ? "Lua" : "main"; | 462 | ar->what = firstline ? "Lua" : "main"; |
diff --git a/src/lj_debug.h b/src/lj_debug.h index 7cf57de7..4144b47e 100644 --- a/src/lj_debug.h +++ b/src/lj_debug.h | |||
| @@ -34,7 +34,7 @@ LJ_FUNC const char *lj_debug_slotname(GCproto *pt, const BCIns *pc, | |||
| 34 | BCReg slot, const char **name); | 34 | BCReg slot, const char **name); |
| 35 | LJ_FUNC const char *lj_debug_funcname(lua_State *L, TValue *frame, | 35 | LJ_FUNC const char *lj_debug_funcname(lua_State *L, TValue *frame, |
| 36 | const char **name); | 36 | const char **name); |
| 37 | LJ_FUNC void lj_debug_shortname(char *out, GCstr *str); | 37 | LJ_FUNC void lj_debug_shortname(char *out, GCstr *str, BCLine line); |
| 38 | LJ_FUNC void lj_debug_addloc(lua_State *L, const char *msg, | 38 | LJ_FUNC void lj_debug_addloc(lua_State *L, const char *msg, |
| 39 | cTValue *frame, cTValue *nextframe); | 39 | cTValue *frame, cTValue *nextframe); |
| 40 | LJ_FUNC void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc); | 40 | LJ_FUNC void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc); |
diff --git a/src/lj_err.c b/src/lj_err.c index 4a33a233..e0fb7167 100644 --- a/src/lj_err.c +++ b/src/lj_err.c | |||
| @@ -587,7 +587,7 @@ LJ_NOINLINE void lj_err_lex(lua_State *L, GCstr *src, const char *tok, | |||
| 587 | { | 587 | { |
| 588 | char buff[LUA_IDSIZE]; | 588 | char buff[LUA_IDSIZE]; |
| 589 | const char *msg; | 589 | const char *msg; |
| 590 | lj_debug_shortname(buff, src); | 590 | lj_debug_shortname(buff, src, line); |
| 591 | msg = lj_str_pushvf(L, err2msg(em), argp); | 591 | msg = lj_str_pushvf(L, err2msg(em), argp); |
| 592 | msg = lj_str_pushf(L, "%s:%d: %s", buff, line, msg); | 592 | msg = lj_str_pushf(L, "%s:%d: %s", buff, line, msg); |
| 593 | if (tok) | 593 | if (tok) |
diff --git a/src/lj_lib.c b/src/lj_lib.c index 331eaa6a..be3ee004 100644 --- a/src/lj_lib.c +++ b/src/lj_lib.c | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | #include "lj_dispatch.h" | 18 | #include "lj_dispatch.h" |
| 19 | #include "lj_vm.h" | 19 | #include "lj_vm.h" |
| 20 | #include "lj_strscan.h" | 20 | #include "lj_strscan.h" |
| 21 | #include "lj_lex.h" | ||
| 22 | #include "lj_bcdump.h" | ||
| 21 | #include "lj_lib.h" | 23 | #include "lj_lib.h" |
| 22 | 24 | ||
| 23 | /* -- Library initialization ---------------------------------------------- */ | 25 | /* -- Library initialization ---------------------------------------------- */ |
| @@ -43,6 +45,28 @@ static GCtab *lib_create_table(lua_State *L, const char *libname, int hsize) | |||
| 43 | return tabV(L->top-1); | 45 | return tabV(L->top-1); |
| 44 | } | 46 | } |
| 45 | 47 | ||
| 48 | static const uint8_t *lib_read_lfunc(lua_State *L, const uint8_t *p, GCtab *tab) | ||
| 49 | { | ||
| 50 | int len = *p++; | ||
| 51 | GCstr *name = lj_str_new(L, (const char *)p, len); | ||
| 52 | LexState ls; | ||
| 53 | GCproto *pt; | ||
| 54 | GCfunc *fn; | ||
| 55 | memset(&ls, 0, sizeof(ls)); | ||
| 56 | ls.L = L; | ||
| 57 | ls.p = (const char *)(p+len); | ||
| 58 | ls.n = ~(MSize)0; | ||
| 59 | ls.current = -1; | ||
| 60 | ls.level = (BCDUMP_F_STRIP|(LJ_BE*BCDUMP_F_BE)); | ||
| 61 | ls.chunkname = name; | ||
| 62 | pt = lj_bcread_proto(&ls); | ||
| 63 | pt->firstline = ~(BCLine)0; | ||
| 64 | fn = lj_func_newL_empty(L, pt, tabref(L->env)); | ||
| 65 | /* NOBARRIER: See below for common barrier. */ | ||
| 66 | setfuncV(L, lj_tab_setstr(L, tab, name), fn); | ||
| 67 | return (const uint8_t *)ls.p; | ||
| 68 | } | ||
| 69 | |||
| 46 | void lj_lib_register(lua_State *L, const char *libname, | 70 | void lj_lib_register(lua_State *L, const char *libname, |
| 47 | const uint8_t *p, const lua_CFunction *cf) | 71 | const uint8_t *p, const lua_CFunction *cf) |
| 48 | { | 72 | { |
| @@ -87,6 +111,9 @@ void lj_lib_register(lua_State *L, const char *libname, | |||
| 87 | ofn = fn; | 111 | ofn = fn; |
| 88 | } else { | 112 | } else { |
| 89 | switch (tag | len) { | 113 | switch (tag | len) { |
| 114 | case LIBINIT_LUA: | ||
| 115 | p = lib_read_lfunc(L, p, tab); | ||
| 116 | break; | ||
| 90 | case LIBINIT_SET: | 117 | case LIBINIT_SET: |
| 91 | L->top -= 2; | 118 | L->top -= 2; |
| 92 | if (tvisstr(L->top+1) && strV(L->top+1)->len == 0) | 119 | if (tvisstr(L->top+1) && strV(L->top+1)->len == 0) |
diff --git a/src/lj_lib.h b/src/lj_lib.h index 2fe6d2a8..05f90de5 100644 --- a/src/lj_lib.h +++ b/src/lj_lib.h | |||
| @@ -77,6 +77,7 @@ static LJ_AINLINE void lj_lib_pushcc(lua_State *L, lua_CFunction f, | |||
| 77 | #define LJLIB_CF(name) static int lj_cf_##name(lua_State *L) | 77 | #define LJLIB_CF(name) static int lj_cf_##name(lua_State *L) |
| 78 | #define LJLIB_ASM(name) static int lj_ffh_##name(lua_State *L) | 78 | #define LJLIB_ASM(name) static int lj_ffh_##name(lua_State *L) |
| 79 | #define LJLIB_ASM_(name) | 79 | #define LJLIB_ASM_(name) |
| 80 | #define LJLIB_LUA(name) | ||
| 80 | #define LJLIB_SET(name) | 81 | #define LJLIB_SET(name) |
| 81 | #define LJLIB_PUSH(arg) | 82 | #define LJLIB_PUSH(arg) |
| 82 | #define LJLIB_REC(handler) | 83 | #define LJLIB_REC(handler) |
| @@ -96,7 +97,8 @@ LJ_FUNC void lj_lib_register(lua_State *L, const char *libname, | |||
| 96 | #define LIBINIT_ASM 0x40 | 97 | #define LIBINIT_ASM 0x40 |
| 97 | #define LIBINIT_ASM_ 0x80 | 98 | #define LIBINIT_ASM_ 0x80 |
| 98 | #define LIBINIT_STRING 0xc0 | 99 | #define LIBINIT_STRING 0xc0 |
| 99 | #define LIBINIT_MAXSTR 0x39 | 100 | #define LIBINIT_MAXSTR 0x38 |
| 101 | #define LIBINIT_LUA 0xf9 | ||
| 100 | #define LIBINIT_SET 0xfa | 102 | #define LIBINIT_SET 0xfa |
| 101 | #define LIBINIT_NUMBER 0xfb | 103 | #define LIBINIT_NUMBER 0xfb |
| 102 | #define LIBINIT_COPY 0xfc | 104 | #define LIBINIT_COPY 0xfc |
