diff --git a/README.md b/README.md index fe8e2a7c76..2b335839d5 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,13 @@ Making performance predictable for application developers brings new requirement The development process has to support moving quickly in these directions: - Quality assurance based on repeatable standard benchmarks executed by CI. -- Streamlined codebase: x86-64 architecture, 64-bit heap (GC64), "no `#ifdef`." -- Distributed development ("Linux-style") with many maintainers, forks, and merges. +- Streamlined codebase: x86-64 architecture, Linux kernel, 64-bit heap (GC64), "no `#ifdef`." +- Distributed development with many maintainers, forks, and merges. Once these requirements have been thoroughly satisfied then new -requirements can be introduced. For example, ARM64 and other platforms -can be supported as the project matures. +requirements can be introduced. For example, new architectures like +ARM64 and operating systems like MacOS can be supported as the project +matures. ### Performance diff --git a/doc/changes.html b/doc/changes.html index 426b18f783..44e03293c3 100644 --- a/doc/changes.html +++ b/doc/changes.html @@ -44,8 +44,6 @@

LuaJIT Change History

jit.* Library
  • Lua/C API -
  • -Profiler
  • Status diff --git a/doc/contact.html b/doc/contact.html index fe4751c0ea..5e07bded58 100644 --- a/doc/contact.html +++ b/doc/contact.html @@ -41,8 +41,6 @@

    Contact

    jit.* Library
  • Lua/C API -
  • -Profiler
  • Status diff --git a/doc/ext_c_api.html b/doc/ext_c_api.html index ad462c63e5..041a722009 100644 --- a/doc/ext_c_api.html +++ b/doc/ext_c_api.html @@ -41,8 +41,6 @@

    Lua/C API Extensions

    jit.* Library
  • Lua/C API -
  • -Profiler
  • Status diff --git a/doc/ext_ffi.html b/doc/ext_ffi.html index 5e1daaf54b..d48d77fae3 100644 --- a/doc/ext_ffi.html +++ b/doc/ext_ffi.html @@ -41,8 +41,6 @@

    FFI Library

    jit.* Library
  • Lua/C API -
  • -Profiler
  • Status diff --git a/doc/ext_ffi_api.html b/doc/ext_ffi_api.html index 91af2e1d43..5cedcf0e7e 100644 --- a/doc/ext_ffi_api.html +++ b/doc/ext_ffi_api.html @@ -46,8 +46,6 @@

    ffi.* API Functions

    jit.* Library
  • Lua/C API -
  • -Profiler
  • Status diff --git a/doc/ext_ffi_semantics.html b/doc/ext_ffi_semantics.html index 268ac104f5..f7480be0dd 100644 --- a/doc/ext_ffi_semantics.html +++ b/doc/ext_ffi_semantics.html @@ -46,8 +46,6 @@

    FFI Semantics

    jit.* Library
  • Lua/C API -
  • -Profiler
  • Status @@ -1215,8 +1213,7 @@

    Current Status

    The JIT compiler already handles a large subset of all FFI operations. It automatically falls back to the interpreter for unimplemented -operations (you can check for this with the --jv command line option). +operations. The following operations are currently not compiled and may exhibit suboptimal performance, especially when used in inner loops:

    diff --git a/doc/ext_ffi_tutorial.html b/doc/ext_ffi_tutorial.html index 3650066440..29cf549e2c 100644 --- a/doc/ext_ffi_tutorial.html +++ b/doc/ext_ffi_tutorial.html @@ -48,8 +48,6 @@

    FFI Tutorial

    jit.* Library
  • Lua/C API -
  • -Profiler
  • Status diff --git a/doc/ext_jit.html b/doc/ext_jit.html index e4088bcbd2..0b0924a896 100644 --- a/doc/ext_jit.html +++ b/doc/ext_jit.html @@ -41,8 +41,6 @@

    jit.* Library

    jit.* Library
  • Lua/C API -
  • -Profiler
  • Status @@ -176,17 +174,6 @@

    jit.opt.* — JIT compiler optimization control -

    jit.util.* — JIT compiler introspection

    -

    -This sub-module holds functions to introspect the bytecode, generated -traces, the IR and the generated machine code. The functionality -provided by this module is still in flux and therefore undocumented. -

    -

    -The debug modules -jbc, -jv and -jdump make -extensive use of these functions. Please check out their source code, -if you want to know more. -


  • Lua/C API -
  • -Profiler
  • Status @@ -151,11 +149,6 @@

    C API extensions

    extra functions to the Lua/C API.

    -

    Profiler

    -

    -LuaJIT has an integrated profiler. -

    -

    Enhanced Standard Library Functions

    xpcall(f, err [,args...]) passes arguments

    diff --git a/doc/faq.html b/doc/faq.html index 2c930743dd..afeff940c4 100644 --- a/doc/faq.html +++ b/doc/faq.html @@ -44,8 +44,6 @@

    Frequently Asked Questions (FAQ)

    jit.* Library
  • Lua/C API -
  • -Profiler
  • Status diff --git a/doc/install.html b/doc/install.html index 851f910afa..97c5f27925 100644 --- a/doc/install.html +++ b/doc/install.html @@ -69,8 +69,6 @@

    Installation

    jit.* Library
  • Lua/C API -
  • -Profiler
  • Status diff --git a/doc/luajit.html b/doc/luajit.html index ef5b824c1b..7202f73f2b 100644 --- a/doc/luajit.html +++ b/doc/luajit.html @@ -126,8 +126,6 @@

    LuaJIT

    jit.* Library
  • Lua/C API -
  • -Profiler
  • Status diff --git a/doc/running.html b/doc/running.html index 64f0491647..eb43075a4d 100644 --- a/doc/running.html +++ b/doc/running.html @@ -63,8 +63,6 @@

    Running LuaJIT

    jit.* Library
  • Lua/C API -
  • -Profiler
  • Status @@ -162,14 +160,10 @@

    -b[options] input output

    # Link test.obj with your application and load it with require("test") -

    -j cmd[=arg[,arg...]]

    +

    -j cmd

    -This option performs a LuaJIT control command or activates one of the -loadable extension modules. The command is first looked up in the -jit.* library. If no matching function is found, a module -named jit.<cmd> is loaded and the start() -function of the module is called with the specified arguments (if -any). The space between -j and cmd is optional. +This option performs a LuaJIT control command from the jit.* +library.

    Here are the available LuaJIT control commands: @@ -178,20 +172,7 @@

    -j cmd[=arg[,arg...]]

  • -jon — Turns the JIT compiler on (default).
  • -joff — Turns the JIT compiler off (only use the interpreter).
  • -jflush — Flushes the whole cache of compiled code.
  • -
  • -jv — Shows verbose information about the progress of the JIT compiler.
  • -
  • -jdump — Dumps the code and structures used in various compiler stages.
  • -
  • -jp — Start the integrated profiler.
  • -

    -The -jv and -jdump commands are extension modules -written in Lua. They are mainly used for debugging the JIT compiler -itself. For a description of their options and output format, please -read the comment block at the start of their source. -They can be found in the lib directory of the source -distribution or installed under the jit directory. By default -this is /usr/local/share/luajit-2.0.4/jit on POSIX -systems. -

    -O[level]
    -O[+]flag   -O-flag
    diff --git a/doc/status.html b/doc/status.html index cad6ca6546..6619ebb7db 100644 --- a/doc/status.html +++ b/doc/status.html @@ -44,8 +44,6 @@

    Status

    jit.* Library
  • Lua/C API -
  • -Profiler
  • Status diff --git a/etc/luajit.1 b/etc/luajit.1 index 0d263db79f..09e57e78cf 100644 --- a/etc/luajit.1 +++ b/etc/luajit.1 @@ -68,10 +68,6 @@ luajit \-e "local x=0; for i=1,1e9 do x=x+i end; print(x)" Calculates the sum of the numbers from 1 to 1000000000. .br And finishes in a reasonable amount of time, too. -.TP -luajit \-jv \-e "for i=1,10 do for j=1,10 do for k=1,100 do end end end" - -Runs some nested loops and shows the resulting traces. .SH COPYRIGHT .PP \fBLuaJIT\fR is Copyright \(co 2005-2017 Mike Pall. diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000000..f654fd33d3 --- /dev/null +++ b/shell.nix @@ -0,0 +1,2 @@ +(import ./default.nix {}).raptorjit + diff --git a/src/lj_bcread.c b/src/lj_bcread.c index 74edf55348..9398d33f54 100644 --- a/src/lj_bcread.c +++ b/src/lj_bcread.c @@ -153,7 +153,7 @@ static uint32_t bcread_uleb128_33(LexState *ls) static void bcread_dbg(LexState *ls, GCproto *pt, MSize sizedbg) { uint32_t *lineinfo = (uint32_t*)proto_lineinfo(pt); - bcread_block(ls, lineinfo, sizedbg); + bcread_block(ls, (void*)proto_declname(pt), sizedbg); /* Swap lineinfo if the endianess differs. */ if (bcread_swap(ls)) { int i; @@ -303,7 +303,7 @@ GCproto *lj_bcread_proto(LexState *ls) MSize framesize, numparams, flags, sizeuv, sizekgc, sizekn, sizebc, sizept; MSize ofsk, ofsuv, ofsdbg; MSize sizedbg = 0; - BCLine firstline = 0, numline = 0; + BCLine firstline = 0, numline = 0, ndeclname = 0; /* Read prototype header. */ flags = bcread_byte(ls); @@ -316,6 +316,7 @@ GCproto *lj_bcread_proto(LexState *ls) if (!(bcread_flags(ls) & BCDUMP_F_STRIP)) { sizedbg = bcread_uleb128(ls); if (sizedbg) { + ndeclname = bcread_uleb128(ls); firstline = bcread_uleb128(ls); numline = bcread_uleb128(ls); } @@ -363,11 +364,14 @@ GCproto *lj_bcread_proto(LexState *ls) pt->numline = numline; if (sizedbg) { MSize sizeli = (sizebc-1) * sizeof(BCLine); - setmref(pt->lineinfo, (char *)pt + ofsdbg); - setmref(pt->uvinfo, (char *)pt + ofsdbg + sizeli); + setmref(pt->declname, (char *)pt + ofsdbg); + setmref(pt->lineinfo, (char *)pt + ofsdbg + ndeclname); + setmref(pt->uvinfo, (char *)pt + ofsdbg + ndeclname + sizeli); bcread_dbg(ls, pt, sizedbg); setmref(pt->varinfo, bcread_varinfo(pt)); + lua_assert(strlen(pt->declname)+1 == ndeclname); } else { + setmref(pt->declname, NULL); setmref(pt->lineinfo, NULL); setmref(pt->uvinfo, NULL); setmref(pt->varinfo, NULL); diff --git a/src/lj_bcwrite.c b/src/lj_bcwrite.c index 69bb430f91..5167c731d3 100644 --- a/src/lj_bcwrite.c +++ b/src/lj_bcwrite.c @@ -212,6 +212,7 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) { MSize sizedbg = 0; char *p; + const char *declname = pt->declname ? proto_declname(pt) : ""; /* Recursively write children of prototype. */ if ((pt->flags & PROTO_CHILD)) { @@ -239,9 +240,10 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) p = lj_strfmt_wuleb128(p, pt->sizebc-1); if (!ctx->strip) { if (proto_lineinfo(pt)) - sizedbg = pt->sizept - (MSize)((char *)proto_lineinfo(pt) - (char *)pt); + sizedbg = pt->sizept - (MSize)((char *)proto_declname(pt) - (char *)pt); p = lj_strfmt_wuleb128(p, sizedbg); if (sizedbg) { + p = lj_strfmt_wuleb128(p, strlen(declname)+1); p = lj_strfmt_wuleb128(p, pt->firstline); p = lj_strfmt_wuleb128(p, pt->numline); } @@ -259,7 +261,7 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) /* Write debug info, if not stripped. */ if (sizedbg) { p = lj_buf_more(&ctx->sb, sizedbg); - p = lj_buf_wmem(p, proto_lineinfo(pt), sizedbg); + p = lj_buf_wmem(p, declname, sizedbg); setsbufP(&ctx->sb, p); } diff --git a/src/lj_lex.c b/src/lj_lex.c index f29d3cebf4..ca618435d6 100644 --- a/src/lj_lex.c +++ b/src/lj_lex.c @@ -56,7 +56,9 @@ static LJ_NOINLINE LexChar lex_more(LexState *ls) /* Get next character. */ static LJ_AINLINE LexChar lex_next(LexState *ls) { - return (ls->c = ls->p < ls->pe ? (LexChar)(uint8_t)*ls->p++ : lex_more(ls)); + LexChar c = (ls->c = ls->p < ls->pe ? (LexChar)(uint8_t)*ls->p++ : lex_more(ls)); + if (ls->log && ls->log < ls->logend) *ls->log++ = c; + return c; } /* Save character. */ @@ -401,6 +403,8 @@ int lj_lex_setup(lua_State *L, LexState *ls) ls->lookahead = TK_eof; /* No look-ahead token. */ ls->linenumber = 1; ls->lastline = 1; + ls->log = NULL; + ls->logend = NULL; lex_next(ls); /* Read-ahead first char. */ if (ls->c == 0xef && ls->p + 2 <= ls->pe && (uint8_t)ls->p[0] == 0xbb && (uint8_t)ls->p[1] == 0xbf) { /* Skip UTF-8 BOM (if buffered). */ @@ -491,6 +495,20 @@ void lj_lex_error(LexState *ls, LexToken tok, ErrMsg em, ...) va_end(argp); } +/* Log the next input characters to a bounded buffer. */ +void lj_lex_log(LexState *ls, char *log, int size) +{ + ls->log = log; + ls->logend = log + size-1; +} + +/* Stop logging input characters. */ +void lj_lex_endlog(LexState *ls) +{ + ls->log = NULL; + ls->logend = NULL; +} + /* Initialize strings for reserved words. */ void lj_lex_init(lua_State *L) { diff --git a/src/lj_lex.h b/src/lj_lex.h index 33fa865726..5d6e7d9eb7 100644 --- a/src/lj_lex.h +++ b/src/lj_lex.h @@ -73,6 +73,8 @@ typedef struct LexState { BCInsLine *bcstack; /* Stack for bytecode instructions/line numbers. */ MSize sizebcstack; /* Size of bytecode stack. */ uint32_t level; /* Syntactical nesting level. */ + char *log; /* Current position where input should be logged. */ + char *logend; /* Last position where input can be logged. */ } LexState; LJ_FUNC int lj_lex_setup(lua_State *L, LexState *ls); @@ -80,6 +82,8 @@ LJ_FUNC void lj_lex_cleanup(lua_State *L, LexState *ls); LJ_FUNC void lj_lex_next(LexState *ls); LJ_FUNC LexToken lj_lex_lookahead(LexState *ls); LJ_FUNC const char *lj_lex_token2str(LexState *ls, LexToken tok); +LJ_FUNC void lj_lex_log(LexState *ls, char *log, int size); +LJ_FUNC void lj_lex_endlog(LexState *ls); LJ_FUNC_NORET void lj_lex_error(LexState *ls, LexToken tok, ErrMsg em, ...); LJ_FUNC void lj_lex_init(lua_State *L); diff --git a/src/lj_obj.h b/src/lj_obj.h index 7586aa55bf..9d9349ef86 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h @@ -311,6 +311,7 @@ typedef struct GCproto { GCRef chunkname; /* Name of the chunk this function was defined in. */ BCLine firstline; /* First line of the function definition. */ BCLine numline; /* Number of lines for the function definition. */ + MRef declname; /* Declared name of function (null-terminated). */ MRef lineinfo; /* Map from bytecode ins. to source line. */ MRef uvinfo; /* Upvalue names. */ MRef varinfo; /* Names and compressed extents of local variables. */ @@ -344,6 +345,7 @@ typedef struct GCproto { #define proto_chunkname(pt) (strref((pt)->chunkname)) #define proto_chunknamestr(pt) (strdata(proto_chunkname((pt)))) +#define proto_declname(pt) (mref((pt)->declname, const char)) #define proto_lineinfo(pt) (mref((pt)->lineinfo, const uint32_t)) #define proto_uvinfo(pt) (mref((pt)->uvinfo, const uint8_t)) #define proto_varinfo(pt) (mref((pt)->varinfo, const uint8_t)) diff --git a/src/lj_parse.c b/src/lj_parse.c index 755ad6a8de..0ed405394d 100644 --- a/src/lj_parse.c +++ b/src/lj_parse.c @@ -1367,12 +1367,20 @@ static void fs_fixup_line(FuncState *fs, GCproto *pt, } /* Prepare variable info for prototype. */ -static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar) +static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar, const char *declname) { VarInfo *vs =ls->vstack, *ve; MSize i, n; BCPos lastpc; lj_buf_reset(&ls->sb); /* Copy to temp. string buffer. */ + /* Store function declaration name. */ + { + char *p; + int len = strlen(declname) + 1; + p = lj_buf_more(&ls->sb, len); + p = lj_buf_wmem(p, declname, len); + setsbufP(&ls->sb, p); + } /* Store upvalue names. */ for (i = 0, n = fs->nuv; i < n; i++) { GCstr *s = strref(vs[fs->uvmap[i]].name); @@ -1411,7 +1419,9 @@ static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar) /* Fixup variable info for prototype. */ static void fs_fixup_var(LexState *ls, GCproto *pt, uint8_t *p, size_t ofsvar) { - setmref(pt->uvinfo, p); + int ndeclname = strlen((char*)p)+1; + setmref(pt->declname, p); + setmref(pt->uvinfo, p + ndeclname); setmref(pt->varinfo, (char *)p + ofsvar); memcpy(p, sbufB(&ls->sb), sbuflen(&ls->sb)); /* Copy from temp. buffer. */ } @@ -1467,7 +1477,7 @@ static void fs_fixup_ret(FuncState *fs) } /* Finish a FuncState and return the new prototype. */ -static GCproto *fs_finish(LexState *ls, BCLine line) +static GCproto *fs_finish(LexState *ls, BCLine line, char *declname) { lua_State *L = ls->L; FuncState *fs = ls->fs; @@ -1484,7 +1494,7 @@ static GCproto *fs_finish(LexState *ls, BCLine line) ofsk = sizept; sizept += fs->nkn*sizeof(TValue); ofsuv = sizept; sizept += ((fs->nuv+1)&~1)*2; ofsli = sizept; sizept += fs_prep_line(fs, numline); - ofsdbg = sizept; sizept += fs_prep_var(ls, fs, &ofsvar); + ofsdbg = sizept; sizept += fs_prep_var(ls, fs, &ofsvar, declname); /* Allocate prototype and initialize its fields. */ pt = (GCproto *)lj_mem_newgco(L, (MSize)sizept); @@ -1744,7 +1754,8 @@ static BCReg parse_params(LexState *ls, int needself) static void parse_chunk(LexState *ls); /* Parse body of a function. */ -static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line) +static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line, + char *declname) { FuncState fs, *pfs = ls->fs; FuncScope bl; @@ -1759,7 +1770,7 @@ static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line) bcemit_AD(&fs, BC_FUNCF, 0, 0); /* Placeholder. */ parse_chunk(ls); if (ls->tok != TK_end) lex_match(ls, TK_end, TK_function, line); - pt = fs_finish(ls, (ls->lastline = ls->linenumber)); + pt = fs_finish(ls, (ls->lastline = ls->linenumber), declname); pfs->bcbase = ls->bcstack + oldbase; /* May have been reallocated. */ pfs->bclim = (BCPos)(ls->sizebcstack - oldbase); /* Store new prototype in the constant array of the parent. */ @@ -1910,7 +1921,7 @@ static void expr_simple(LexState *ls, ExpDesc *v) return; case TK_function: lj_lex_next(ls); - parse_body(ls, v, 0, ls->linenumber); + parse_body(ls, v, 0, ls->linenumber, ""); return; default: expr_primary(ls, v); @@ -2139,9 +2150,24 @@ static void parse_call_assign(LexState *ls) } } +/* Convert the logged input into a canonical function declaration name. */ +static char *log_declname(char *log) +{ + char *end = log + strlen(log) - 1; + /* Strip off trailing chars e.g. change "myfunc (X" to "myfunc". */ + while (end > log && *end != '(') end--; /* Rewind to '('. */ + if (*end != '(') return log; else end--; /* Skip '(' if present. */ + while (end > log && *end == ' ') end--; /* Rewind over spaces. */ + *(end+1) = '\0'; /* Truncate. */ + return log; +} + /* Parse 'local' statement. */ static void parse_local(LexState *ls) { + char log[128]; + memset(&log[0], 0, sizeof(log)); + lj_lex_log(ls, &log[0], sizeof(log)-1); if (lex_opt(ls, TK_function)) { /* Local function declaration. */ ExpDesc v, b; FuncState *fs = ls->fs; @@ -2150,7 +2176,8 @@ static void parse_local(LexState *ls) v.u.s.aux = fs->varmap[fs->freereg]; bcreg_reserve(fs, 1); var_add(ls, 1); - parse_body(ls, &b, 0, ls->linenumber); + lj_lex_endlog(ls); /* Captured declared function name. */ + parse_body(ls, &b, 0, ls->linenumber, log_declname(log)); /* bcemit_store(fs, &v, &b) without setting VSTACK_VAR_RW. */ expr_free(fs, &b); expr_toreg(fs, &b, v.u.s.info); @@ -2159,6 +2186,7 @@ static void parse_local(LexState *ls) } else { /* Local variable declaration. */ ExpDesc e; BCReg nexps, nvars = 0; + lj_lex_endlog(ls); /* Not used for variables. */ do { /* Collect LHS. */ var_new(ls, nvars++, lex_str(ls)); } while (lex_opt(ls, ',')); @@ -2179,6 +2207,10 @@ static void parse_func(LexState *ls, BCLine line) FuncState *fs; ExpDesc v, b; int needself = 0; + char log[128]; + log[0] = 'c'; + memset(log, 0, sizeof(log)); + lj_lex_log(ls, log, sizeof(log)-1); lj_lex_next(ls); /* Skip 'function'. */ /* Parse function name. */ var_lookup(ls, &v); @@ -2188,7 +2220,8 @@ static void parse_func(LexState *ls, BCLine line) needself = 1; expr_field(ls, &v); } - parse_body(ls, &b, needself, line); + lj_lex_endlog(ls); + parse_body(ls, &b, needself, line, log_declname(log)); fs = ls->fs; bcemit_store(fs, &v, &b); fs->bcbase[fs->pc - 1].line = line; /* Set line for the store. */ @@ -2618,7 +2651,7 @@ GCproto *lj_parse(LexState *ls) parse_chunk(ls); if (ls->tok != TK_eof) err_token(ls, TK_eof); - pt = fs_finish(ls, ls->linenumber); + pt = fs_finish(ls, ls->linenumber, ""); L->top--; /* Drop chunkname. */ lua_assert(fs.prev == NULL); lua_assert(ls->fs == NULL);