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 |