Lua Jit |
|
|
== Comments == Below are some random user-contributed notes. Note: To keep options open, by posting to the Bytecode and SSA sections below, you hereby permit the content to also be used in any way designated by the LuaJIT maintainer (e.g. licensed under the same terms as LuaJIT). == Bytecode Instructions (2.0beta, 2011-01, 6bce6b118eeb2bb7f36157de158e5cccf0ea68e5) == The following are notes on the bytecode instructions. Warning: this list is incomplete and likely has inaccuracies. See lj_bc.h and buildvm_*.dasc for details. From lj_bc.h:
Comparison ops. ISLT, var, ___, var, lt Branch if less than. If A < D, branches to D of following (JMP) instruction; otherwise, skips next instruction. ISGE, var, ___, var, lt Branch if greater than or equal. ISLE, var, ___, var, le Branch if less than or equal. ISGT, var, ___, var, le Branch if greater than. Why are ISGE and ISGT used when they could be written in terms of ISLT and ISLE? ISEQV, var, ___, var, eq ISNEV, var, ___, var, eq ISEQS, var, ___, str, eq ISNES, var, ___, str, eq ISEQN, var, ___, num, eq ISNEN, var, ___, num, eq ISEQP, var, ___, pri, eq ISNEP, var, ___, pri, eq Unary test and copy ops. ISTC, dst, ___, var, ___ Is true then copy and branch. ISFC, dst, ___, var, ___ If false then copy and branch. ISTC and ISFC are just like IST and ISF respectively but have an addition argument. On branch, then D is copied to A. IST, ___, ___, var, ___ Is true then branch. If D is considered true (i.e. neither false nor nil), branches to D of following (JMP) instruction; otherwise, skips next instruction.ISF, ___, ___, var, ___ Is false then branch. If D is considered false (i.e. false or nil), branches to D of following (JMP) instruction; otherwise, skips next instruction.Unary ops. MOV, dst, ___, var, ___ Copy value from D to A. NOT, dst, ___, var, ___ Sets A to not D. "not D" is true if D is nil or false; otherwise, it is false.UNM, dst, ___, var, unm Unary minus (-). Sets A = - D. LEN, dst, ___, var, len Object length. Sets A = # D. Binary ops. ADDVV, dst, var, var, add Sets A to B + C. ADDVN, dst, var, num, add Sets A to B + C, where C is a numeric constant. ADDNV, dst, var, num, add Sets A to C + B, where B is a numeric constant. SUBVV, dst, var, var, sub SUBVN, dst, var, num, sub SUBNV, dst, var, num, sub MULVV, dst, var, var, mul MULVN, dst, var, num, mul MULNV, dst, var, num, mul DIVVV, dst, var, var, div DIVVN, dst, var, num, div DIVNV, dst, var, num, div MODVV, dst, var, var, mod MODVN, dst, var, num, mod MODNV, dst, var, num, mod POW, dst, var, var, pow CAT, dst, rbase, rbase, concat Concatenates ("..") values in slots B to D inclusive and stores in A. Constant ops. KSTR, dst, ___, str, ___ Lua string constant. R(A) = destination. K(D) = string constant (D is negative index in function prototype's constant table, i.e. GCproto.k). KCDATA, dst, ___, cdata, ___ cdata (FFI C structure) constant. R(A) = destination. K(D) = C data constant (D is negative index in function prototype's constant table) KSHORT, dst, ___, lits, ___ 32-bit signed integer constant. R(A) = destination. D = signed 16-bit integer literal
KNUM, dst, ___, num, ___ Lua Number constant. R(A) = destination. K(D) = Number constant (D is positive index in function prototype's constant table) KPRI, dst, ___, pri, ___ R(A) = destination. D = bitwise NOT of value of primitive type (see "Internal object tags" in lj_obj.h). Note: "KPRI 0 0" means nil, "KPRI 0 1" means false, "KRI 0 2" means true, ... can any others occur?
KNIL, base, ___, base, ___ R(A)..R(D) inclusive are filled with nil.Note: a single nil value may alternately be set via KPRI ? 0.
Upvalue and function ops. UGET, dst, ___, uv, ___ USETV, uv, ___, var, ___ USETS, uv, ___, str, ___ USETN, uv, ___, num, ___ USETP, uv, ___, pri, ___ UCLO, rbase, ___, jump, ___ FNEW, dst, ___, func, gc Table ops. TNEW, dst, ___, lit, gc Creates new table. R(A) = destination. D = lower 11 bits "asize" represent array size (allocates slots 0..size-1, not including this value); upper bits "hbits" represent hash size (2^hsize for hsize > 0; 0 for hsize = 0). See lj_tab_new comments for details.TDUP, dst, ___, tab, gc GGET, dst, ___, str, index Get global. Copies environment variable named by string const K(D) into R(A). R(A) = env[K(D)] GSET, var, ___, str, newindex Set global. Copies R(A) into environment variable named by string K(D). env[K(D)] = R(A) TGETV, dst, var, var, index Gets table value with any type of key. R(A) = R(B)[R(C)]. TGETS, dst, var, str, index Gets table value with string key. R(A) = R(B).K(C) Note: C is negative index into function prototypes constant table. TGETB, dst, var, lit, index Gets table, using literal byte key (integer 0..255). R(A) = R(B)[C] TSETV, var, var, var, newindex Sets table, using arbitrary variable key. R(B)[R(C)] = R(A) TSETS, var, var, str, newindex Sets table, using string constant key. R(B)[K(C)] = R(A) TSETB, var, var, lit, newindex Sets table, using literal byte key (integer 0..255). R(B)[C] = R(A) TSETM, base, ___, num, newindex Fills table with variable length (multi-return) values--e.g. {a,b, ...} R(A-1) is table to fill. Subsequent registers are values to fill with. K(D) is starting index in table (e.g. 3 in above example). D is encoded as a index+2^52 (see bc.lua), as lj_parse.c says, "Biased integer to avoid denormals" (explain?). Calls and vararg handling. T = tail call. CALL, base, lit, lit, call Function call. R(A) is register holding function to call. B is 1 + number of return values. 0 indicates variable number of returns, such as when the function call is at end of expression list-- return f(), g(1, 2, f()), or {1, 2, f()} C is 1 + number of arguments. Arguments and return values are assumed to be in consecutive registers starting at R(A+1). CALLM, base, lit, lit, call This is like CALL but with variable number of arguments (i.e. last argument is a "multireturn" expression). C is number of fixed arguments (not including last argument that may inject a variable number of values). CALLT, base, ___, lit, call This is like CALL but for tail calls. R(A) has the same meaning as in CALL. D has the same meaning as C in CALL. CALLMT, base, ___, lit, call Function call that both has a variable number of arguments and is a tail call (i.e. CALLM and CALLT combined). R(A) has the same meaning as in CALL. D has the same meaning as C in CALLM. ITERC, base, lit, lit, call Handles iterator call in for iterator.(Does this stand for "iterator control"? or "iterator call"?) R(A-3) = iterator function (f) R(A-2) = state (s) R(A-1) = control variable (var) B = 1 + number of results for iterator function C = 1 + number of arguments for iterator function (always C = 1 + 2) Invokes f(s, var), placing return values in registers R(A)..R(A+B-2) inclusive. This opcode therefore is somewhat similar to CALL but does not pop values. Typically this is followed by a ITERL.
ITERN, base, lit, lit, call This is a specialization of ITERC when the iterator function is next (which is also returned by pairs). Typically ITERN is preceded by an ISNEXT to test if next is the iterator function.R(A-3) = iterator function (f) (should always be next)R(A-2) = state (s) R(A-1) = control variable (var) B = 1 + number of results for iterator function (typically B = 1 + 2 or 1 + 1). In practice, B is always ignored, and two results are always returned. C = 1 + number of arguments for iterator function (always C = 1 + 2) Note: see also ITERL.
ISNEXT, base, ___, jump, ___ Conditionally despecializes ITERN bytecode to ITERC if not an next based iteration.R(A-3), R(A-2), R(A-1) are the f, s, var variables [1] in a iterator for loop respectively.J(D) is the jump target. (assumed ITERN bytecode). Unless f is the next function, s is a table, and var is nil (as is true of the pairs return values), then the bytecodes are "despecialized": the current bytecode and the jump target are translated to JMP and ITERC bytecodes respectively and that JMP is executed. Otherwise, the lower four (otherwise unused) bytes of the internal representation of the nil value in var are set to 0 (explain further? note: ITERN uses this four byte integer as the control variable for the array part) and the jump occurs.The parser has a heuristic ( lj_parse.c:predict_next) that determines whether the ISNEXT bytecode is generated. Basically, if the variable name is next or pairs and the number of loop values is 1 or 2, then ISNEXT is used.
VARG, base, lit, lit, ___ Copies vararg (...) values into registers. R(A)..R(A+B-2) inclusive are registers where first B-1 number of varargs are to be stored. C is the number of fixed paramters in the function. For example, function(a,b,...) has C=2.Returns. RET, rbase, ___, lit, ___ Return with fixed number of values > 1. Return values are R(A)..R(A+D-2) inclusive. D-1 is the number of return values. RET0, rbase, ___, lit, ___ Return with zero return values. A = 0 (always) D-1 is the number of return values (D is always 1). RET1, rbase, ___, lit, ___ Return with exactly one value. R(A) holds return value. D-1 is the number of return values (D is always 2). RETM, base, ___, lit, ___ Return with variable number of return values (multi-return). For example, return 5,6, ... and return 5, 6, f() have two fixed return values plus an additional variable number of return values.R(A)..R(A+D-1) hold fixed return values, and subsequent registers hold variable number of return values. D is the number of fixed return values. Loops and branches. I/J = interp/JIT, I/C/L = init/call/loop. FORI, base, ___, jump, ___ Start (initialize) numeric for loop.R(A), R(A+1), R(A+2) are the var, limit, step [1] respectively.J(D) is the jump target to the end of the for loopTODO: redescribe more? Note: numeric for loops look like this:
JFORI, base, ___, jump, ___ FORI may be rewritten as this on JIT tracing (see lj_trace.c:trace_stop).FORL, base, ___, jump, ___ End of numeric for loop.R(A), R(A+1), R(A+2) are the var, limit, step [1] respectively.J(D) is the jump target to the start of the for loopTODO: redescribe more? implementation is somewhat tricky (e.g. fallthrough to IFORL) IFORL, base, ___, jump, ___ Interpreted FORL. This is like FORL but does not do JIT hot counting. This is used indirectly by FORL's implementation. FORL's may be rewritten as this on blacklisting (see lj_trace.c:blacklist_pc and lj_trace_reenableproto).JFORL, base, ___, lit, ___ FORL may be rewritten as this on JIT tracing (see lj_trace.c:trace_stop).ITERL, base, ___, jump, ___ Handles bottom of iterator for loop.R(A-1) contains the var variable [1] in an iterator for loop.R(A) contains the var_1 variable.J(D) is the jump target to the start of the for loopIf var_1 is nil, it advances to the next opcode; otherwise, it sets var to {{var_1} and jumps to the jump target.Typically this follows an ITERC (or sometimes ITERN). Note: iterator for loops look like this:
IITERL, base, ___, jump, ___ This is like ITERL but does not do JIT hot counting. ITERL may be rewritten as this on blacklisting (see lj_trace.c:blacklist_pc and lj_trace_reenableproto).JITERL, base, ___, lit, ___ ITERL may be rewritten as this on JIT tracing (see lj_trace.c:trace_stop).LOOP, rbase, ___, jump, ___ Note: while loops look like this:
and repeat loops look like this:
ILOOP, rbase, ___, jump, ___ This is like LOOP but does not do JIT hot counting. LOOP may be rewritten as this on blacklisting (see lj_trace.c:blacklist_pc and lj_trace_reenableproto).JLOOP, rbase, ___, lit, ___ LOOP may be rewritten as this on JIT tracing (see lj_trace.c:trace_stop).JMP, rbase, ___, jump, ___ Function headers. I/J = interp/JIT, F/V/C = fixarg/vararg/C func. FUNCF, rbase, ___, ___, ___ IFUNCF, rbase, ___, ___, ___ This is like FUNCF but does not do JIT hot counting. JFUNCF, rbase, ___, lit, ___ FUNCF may be rewritten as this on JIT tracing (see lj_trace.c:trace_stop).FUNCV, rbase, ___, ___, ___ IFUNCV, rbase, ___, ___, ___ This is like FUNCV but does not do JIT hot counting. (NYI?) JFUNCV, rbase, ___, lit, ___ FUNCC, rbase, ___, ___, ___ FUNCCW, rbase, ___, ___, ___ == SSA Instructions (2.0beta, 2011-01, aca1e5b3e69d8e7ed155de3d2db959bc49597bf1) == The following are notes on the SSA instructions. Warning: this list is incomplete and likely has inaccuracies. See lj_ir.h, lj_asm.c, lj_opt_fold.c, and dump.lua for details. Basic example:
The above prints the bytecode of the trace, the IR generated from that bytecode, and the machine code generated from the IR. The columns of the IR are as follows:
See also SSA dump format comments: LuaList:2008-06/msg00225.html (older version). See formatk in dump.lua. Each snaphot (SNAP) lists the modified stack slots and their values. The i-th value in the snapshot list represents the index of the IR that writes a value in slot number #i. '---' indicates that the slot is not written. Frames are separated by '|'. For further comments on snapshots, see LuaList:2009-11/msg00089.html. IR types (see irtype_text in dump.lua or IRTDEF in lj_ir.h):
"Mode bits" (used in below opcode definitions): Commutative (C), {Normal/Ref (N), Alloc (A), Load (L), Store (S)}, Non-weak guard (W). Guarded assertions. The trace is exited if these checks fail. LT, N , ref, ref less than. Exits unless op1 < op2. GE, N , ref, ref greater than or equal. Exits unless op1 >= op2. LE, N , ref, ref. Exits unless op1 <= op2. less than or equal GT, N , ref, ref. Exits unless op1 > op2. greater than Unordered comparisons. (This concerns floating point comparisons where one value may be NaN. NaN is not ordered. For background see [2].) When int's rather than float's are used, this appears to do unsigned comparison. ULT, N , ref, ref unordered less than UGE, N , ref, ref unordered greater than or equal ULE, N , ref, ref unordered less than or equal UGT, N , ref, ref unordered greater than EQ, C , ref, ref equal NE, C , ref, ref not equal ABC, N , ref, ref ABCelim: Array Bounds Check Elimination? RETF, S , ref, ref (?) Return to lower frame? NOP, N , ___, ___ no operation (NOP). BASE, N , lit, lit (?) LOOP, S , ___, ___ Loop. PHI, S , ref, ref The SSA phi thing. Should be explained further... RENAME, S , ref, lit (?) Constants KPRI, N , ___, ___ (?) KINT, N , cst, ___ KGC, N , cst, ___ KPTR, N , cst, ___ Const pointer to possibly non-const data. KKPTR, N , cst, ___ Const pointer to definitely const data. Notes from commit: "Only content known by the VM to be const qualifies. Content tagged as const by users (e.g. const char *) doesn't." [commit] KNULL, N , cst, ___ KNUM, N , cst, ___ KINT64, N , cst, ___ KSLOT, N , ref, lit (?) == Bit ops == BNOT, N , ref, ___ Bitwise not. See bit.bnot. BSWAP, N , ref, ___ See bit.bswap. BAND, C , ref, ref See bit.band. BOR, C , ref, ref See bit.bor. BXOR, C , ref, ref See bit.bxor. BSHL, N , ref, ref See bit.lshift. BSHR, N , ref, ref See bit.rshift. BSAR, N , ref, ref See bit.arshift. BROL, N , ref, ref See bit.rol. BROR, N , ref, ref See bit.ror. Arithmetic ops ADD, C , ref, ref x + y op1: x, op2: y SUB, N , ref, ref x - y MUL, C , ref, ref x * y DIV, N , ref, ref x / y FPMATH, N , ref, lit Floating point math operation.
POWI, N , ref, ref Raise to power (with integer exponent). NEG, N , ref, ref Negation (-x). ABS, N , ref, ref Absolute value. see math.abs. ATAN2, N , ref, ref atan2. see math.atan2. LDEXP, N , ref, ref see math.ldexp. MIN, C , ref, ref see math.min. MAX, C , ref, ref see math.max. Overflow-checking arithmetic ops ADDOV, C , ref, ref SUBOV, N , ref, ref Memory ops. A = array, H = hash, U = upvalue, F = field, S = stack. Memory references. AREF, R , ref, ref Array reference HREFK, R , ref, ref Hash reference (with constant key?) op1: index to IR for table hash part (tab.node)? op2: key? HREF, L , ref, ref Hash reference. op1: index to IR for table op2: index to IR for key NEWREF, S , ref, ref This is something related to creating a new table key (lj_tab_newkey). op1: index to IR for table op2: index to IR for key UREFO, LW, ref, lit Upvalue reference, open? op1 is the index to the IR for the function value. op2 - bits 0..7 are some type of hash value for the upvalue (see rec_upvalue). Bits above that represent the upvalue index (0-based integer) in the function. UREFC, LW, ref, lit upvalue reference, closed? op1 and op2 are the same as in UREFO. FREF, R , ref, lit Field reference op1: op2: field identifier - see op2 values in FLOAD. STRREF, N , ref, ref String reference Loads and Stores ALOAD, L , ref, ___ Array load HLOAD, L , ref, ___ Hash table load ULOAD, L , ref, ___ Upvalue load op1: index of IR for upvalue reference (e.g. UREFC/UREFO). FLOAD, L , ref, lit Field load. This accesses the field identified by (lit) in a C struct located at the address referred to in (ref). The fields are at known constant offsets from the structure base address.
XLOAD, L , ref, lit Load from pointer? Note: can occur with FFI cdata. op1: index of IR for pointer to load from op2: bitwise OR of SLOAD, L , lit, lit Stack load
VLOAD, L , ref, ___ Vararg load ASTORE, S , ref, ref Array store HSTORE, S , ref, ref Hash table store op1: index of IR for reference to value in hash table. op2: key USTORE, S , ref, ref Upvalue store FSTORE, S , ref, ref Field store XSTORE, S , ref, ref Store to pointer? Note: can occur with FFI cdata. op1: index of IR for pointer to store to op2: index of of IR for value to store Allocations. SNEW, N , ref, ref Create new string. (lj_str_new) op1: const char *str; op2: size_t len. TNEW, AW, lit, lit Create new table. TDUP, AW, ref, ___ Duplicate a table. (lj_tab_dup) op1: table to copy CNEW, AW, ref, ref FFI cdata new. CNEWP, NW, ref, ref FFI cdata pointer new. Write barriers. TBAR, S , ref, ___ (?) OBAR, S , ref, ref Specialized barrier for closed upvalue? Type conversions CONV, N , ref, lit Various int and float number conversions. op1: lref op2: type conversion.
TOBIT, N , ref, ref (see bit.tobit) op1: dest op1: source TOSTR, N , ref, ___ Convert to string. STRTO, N , ref, ___ Convert string to number. Calls. CALLN, N , ref, lit Call Normal/Ref (N)? CALLL, L , ref, lit Call Load (L)? CALLS, S , ref, lit Call Store (S)? CARG, N , ref, ref (?) something related to function call arguments |
|
LuaJIT also has its own wiki: http://wiki.luajit.org/ . |
LuaJIT also has its own wiki: http://wiki.luajit.org/ .