aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2013-02-22 01:40:41 +0100
committerMike Pall <mike>2013-02-22 01:40:41 +0100
commite20157c6e68472e7c4d82d9ed4c0bb5be029c388 (patch)
treeb26bfadc10b7301d73b84293630c44e7d1fb37f9
parentc3219b7d177f6722b9de808cfd3d3dbfc6808e6f (diff)
downloadluajit-e20157c6e68472e7c4d82d9ed4c0bb5be029c388.tar.gz
luajit-e20157c6e68472e7c4d82d9ed4c0bb5be029c388.tar.bz2
luajit-e20157c6e68472e7c4d82d9ed4c0bb5be029c388.zip
Add support for embedding LuaJIT bytecode for builtins.
-rw-r--r--src/Makefile6
-rw-r--r--src/Makefile.dep6
-rw-r--r--src/host/buildvm_lib.c51
-rw-r--r--src/host/buildvm_libbc.h12
-rw-r--r--src/host/genlibbc.lua68
-rw-r--r--src/lj_bcdump.h1
-rw-r--r--src/lj_bcread.c34
-rw-r--r--src/lj_debug.c17
-rw-r--r--src/lj_debug.h2
-rw-r--r--src/lj_err.c2
-rw-r--r--src/lj_lib.c27
-rw-r--r--src/lj_lib.h4
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:
558clean: 558clean:
559 $(HOST_RM) $(ALL_RM) 559 $(HOST_RM) $(ALL_RM)
560 560
561libbc:
562 ./$(LUAJIT_T) host/genlibbc.lua $(LJLIB_C) >host/buildvm_libbc.h
563 $(MAKE) all
564
561depend: 565depend:
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
125lj_lib.o: lj_lib.c lauxlib.h lua.h luaconf.h lj_obj.h lj_def.h lj_arch.h \ 125lj_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
128lj_load.o: lj_load.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ 129lj_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 \
220host/buildvm_fold.o: host/buildvm_fold.c host/buildvm.h lj_def.h lua.h \ 221host/buildvm_fold.o: host/buildvm_fold.c host/buildvm.h lj_def.h lua.h \
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
222host/buildvm_lib.o: host/buildvm_lib.c host/buildvm.h lj_def.h lua.h luaconf.h \ 223host/buildvm_lib.o: host/buildvm_lib.c host/buildvm.h lj_def.h lua.h luaconf.h \
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
224host/buildvm_peobj.o: host/buildvm_peobj.c host/buildvm.h lj_def.h lua.h \ 226host/buildvm_peobj.o: host/buildvm_peobj.c host/buildvm.h lj_def.h lua.h \
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
226host/minilua.o: host/minilua.c 228host/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. */
11static uint8_t obuf[8192]; 12static 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
155static 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
167static 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
180static 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
154static uint32_t find_rec(char *name) 204static 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
3static const int libbc_endian = 0;
4
5static const uint8_t libbc_code[] = {
60
7};
8
9static 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
9local function usage()
10 io.stderr:write("Usage: ", arg and arg[0] or "genlibbc", " lib_*.c\n")
11 os.exit(1)
12end
13
14local 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
23end
24
25local 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
37end
38
39local 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()
64end
65
66local src = read_source()
67local defs = find_defs(src)
68write_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
62LJ_FUNC int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, 62LJ_FUNC int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer,
63 void *data, int strip); 63 void *data, int strip);
64LJ_FUNC GCproto *lj_bcread_proto(LexState *ls);
64LJ_FUNC GCproto *lj_bcread(LexState *ls); 65LJ_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. */
329static GCproto *bcread_proto(LexState *ls) 329GCproto *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. */
324void lj_debug_shortname(char *out, GCstr *str) 324void 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);
35LJ_FUNC const char *lj_debug_funcname(lua_State *L, TValue *frame, 35LJ_FUNC const char *lj_debug_funcname(lua_State *L, TValue *frame,
36 const char **name); 36 const char **name);
37LJ_FUNC void lj_debug_shortname(char *out, GCstr *str); 37LJ_FUNC void lj_debug_shortname(char *out, GCstr *str, BCLine line);
38LJ_FUNC void lj_debug_addloc(lua_State *L, const char *msg, 38LJ_FUNC void lj_debug_addloc(lua_State *L, const char *msg,
39 cTValue *frame, cTValue *nextframe); 39 cTValue *frame, cTValue *nextframe);
40LJ_FUNC void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc); 40LJ_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
48static 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
46void lj_lib_register(lua_State *L, const char *libname, 70void 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