├── CodeConvention.txt ├── lapi.c ├── lcode.c ├── ldebug.c ├── ldo.c ├── ldump.c ├── lfunc.c ├── lgc.c ├── lgc.h ├── lmem.c ├── lobject.h ├── lopcodes.h ├── lparser.c ├── ltable.c ├── ltm.c ├── lua.h └── lvm.c /CodeConvention.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | LuaX Lexical 4 | LuaY Parser 5 | LuaK Code emission 6 | 7 | LuaD Execution 8 | 9 | LuaC Garbage collection 10 | LuaO Object-related API 11 | 12 | LuaF Function-related API (prototype/closure) 13 | LuaH Table-related API 14 | 15 | LuaS String-related API 16 | LuaT Meta-table-related API 17 | 18 | LuaL Util 19 | LuaG Debug 20 | LuaM Memory 21 | -------------------------------------------------------------------------------- /lapi.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | lua_settop(lua_State *L, int idx) 4 | 5 | 6 | 7 | lua_pcallk 8 | ===================================== 9 | lua_pcallk(L, ..., errfunc, ...) 10 | [CallS c] 11 | index2addr(L, errfunc) 12 | savestack(L, o) 13 | luaD_pcall(L, f_call, &c, ...) 14 | luaD_rawrunprotected(L, f_call, &c) 15 | _setjmp(...) 16 | f_call(L, &c) 17 | luaD_call(L, c->func, c->nresult, 0) 18 | luaD_precall(L, c->func, c->nresult) // Note 1 19 | luaV_execute(...) // 20 | adjustresults(...) 21 | 22 | 23 | 24 | 25 | Note 1: A normal call purely in byte-code invoke "luaD_precall()" and 26 | re-enter the exec-loop by a "goto". 27 | 28 | 29 | 30 | lua_pcallk (with continuation) 31 | ===================================== 32 | lua_pcallk(L, ..., errfunc, ctx, k) 33 | [CallS c] 34 | index2addr(L, errfunc) 35 | savestack(L, o) 36 | 37 | 38 | 39 | luaD_precall (lua_State *L, StkId func, int nresults) 40 | ===================================== 41 | (C Closure) (return 1 for C-closure) 42 | ------------------------- 43 | luaD_precall(L, func, nresult) 44 | savestack(L, func) // ==> funcr 45 | clCvalue(func) 46 | next_ci(L) 47 | restorestack(L, funcr) // ==> ci->func, same to "func ==> ci->func" 48 | luaC_checkGC(L) 49 | (*f)(...) // ==> n 50 | luaD_poscall(L, L->top - n) 51 | L->ci->func ==> res 52 | [Loop from "L->top - n" to "L->top"] 53 | setobjs2s(L, ...) 54 | [Loop] 55 | setnilvalue(...) -------------------------------------------------------------------------------- /lcode.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | General 4 | ------------------------------------------------------- 5 | - luaK_code... returns the "pc" of the instruction just being generated. 6 | - if a "luaK_..." function accepts an "expdesc" as parameter, it usually does not put 7 | instruction into Proto::code, at least not putting the last instruction. 8 | 9 | - A "test-mode" instruction means one of the following three: 10 | - OP_EQ, 11 | - OP_LT, 12 | - OP_LE, 13 | - OP_TEST, 14 | - OP_TESTSET. 15 | - A "test-mode" instruction is followed by a JMP instruction. 16 | - The first three, OP_EQ, OP_LT, OP_LE, is used for generating a comp-instruction, 17 | luaK_posfix() ==> codecomp() generates it as "jmp-if-true" (the same as "go-if-false"). 18 | That means the "true-block"/"then-block" is located last. 19 | - In "goiftrue()", the "test-bit" shall be inverted to invert the "jmp-if-true" behavior 20 | in order to have the "then-block" located first (so if-then, if-else-then must use goifture()). 21 | 22 | 23 | 24 | Global Tables 25 | ------------------------------------------------------- 26 | OpCode: Enum type which is the index of the following two arraies. 27 | luaP_opnames: All OP names in "char*". 28 | luaP_opmodes: OP mode of each instruction, indexed as the same order to "luaP_opnames". 29 | 30 | 31 | 32 | 33 | void luaK_setoneret (FuncState *fs, expdesc *e) 34 | ========================================================================== 35 | Set the expression of a "VVARARG" or "VCALL". 36 | 1. For VVARARG, set its "B" as 2, meaning adjusting to 1 value. 37 | 2. For VCALL, set "e->k" to "NONRELOC" and "e->u.info" to the original "A". 38 | 39 | 40 | 41 | static int addk (FuncState *fs, TValue *key, TValue *v) 42 | ========================================================================== 43 | Add "v" to field "k" of the "struct Proto". 44 | Before really creating an entry in "k", it check and reuse an eixsting one whenever possible. 45 | It check by search in "fs->h", which is a compile-time hash-index of "k". 46 | 47 | fs->f->k grows by double if there is no enough room, and all new items are set as "nil". 48 | The number of actually used slots is stored in fs->nk. 49 | 50 | Returns the location in "f->k" of the newly-added constant. 51 | 52 | 53 | 54 | static int luaK_code (FuncState *fs, Instruction i) 55 | ========================================================================== 56 | Put Instruction "i" into "fs->f->code". 57 | Put the line number into "fs->f->lineinfo". 58 | Increase fs->pc. Note "pc" is not part of fs->f (Proto) but of f (FuncState). 59 | 60 | 61 | 62 | 63 | void luaK_exp2val (FuncState *fs, expdesc *e) 64 | ========================================================================== 65 | luaK_exp2val (fs, e) 66 | hasjumps(e) 67 | [true] 68 | luaK_exp2anyreg(fs, e) 69 | [false] 70 | luaK_dischargevars(fs, e) 71 | 72 | 73 | 74 | static int jumponcond (FuncState *fs, expdesc *e, int cond) 75 | ========================================================================== 76 | 77 | If "e" is a RELOC "NOT" 78 | -------------------------------------- 79 | TEST RB(ie), !cond 80 | JMP 0, "jpc" 81 | 82 | Otherwise 83 | -------------------------------------- 84 | TESTSET -1, "Rdischarge(e)", cond 85 | JMP 0, "jpc" 86 | 87 | 88 | 89 | static int condjump (FuncState *fs, OpCode op, int A, int B, int C) 90 | ========================================================================== 91 | "op" A, B, C 92 | JMP 0, "jpc" 93 | 94 | 95 | 96 | void luaK_goiftrue (FuncState *fs, expdesc *e) 97 | ========================================================================== 98 | For "VJMP" 99 | ------------------------------------------------------- 100 | e->t: JMP 0, "jpc" // pre-generated, not by this function 101 | 102 | 103 | 104 | 105 | 106 | 107 | int luaK_jump (FuncState *fs) 108 | ========================================================================== 109 | Generate an "OP_JMP" instruction. 110 | Put the current "fs->jpc" to the target of the instruction. 111 | Clean "fs->jpc". 112 | Return the instruction's "pc". 113 | 114 | 115 | 116 | 117 | static void luaK_concat (FuncState *fs, int *l1, int l2) 118 | ========================================================================== 119 | Add instruction at index "l2" to a chain of jump instructions, which is called a patch-list. 120 | ------------------------------------------------------- 121 | l1: header to a patch-list (i.e. a sequence of unpatched JMP instructions, more strictly speaking, 122 | the "pc" indices of those instructions). NO_JUMP means the list is empty. 123 | l2: a "pc" index. 124 | ------------------------------------------------------- 125 | 1. Noop, when l2 == NO_JUMP. 126 | 2. *l1 = l2, when l1 == NO_JUMP. Mean to initialize the list. 127 | 3. if "*l1" has a non-"NO_JUMP" value, trace to the end of the patch-list and set "l2" as the target of 128 | the tail instruction, meaning add l2 to the end of the patch-list. 129 | 130 | 131 | 132 | void luaK_patchtohere (FuncState *fs, int list) 133 | ========================================================================== 134 | The function is used to patch a list of JMPs (i.e. a patch-list) to the location of the next instruction. 135 | 136 | It stores the "list" to fs->jpc. When Lua compiler generate the next instruction, the fs->jpc will be 137 | cleared to NO_JUMP, and the "list" will be: 138 | 1. Patched to the location of next instruction if it is not a JMP, or 139 | 2. Be augmented with the newly-generated JMP instruction, and the list will be usually put back to 140 | fs->jpc later on, or be handled differently in some cases. 141 | 142 | Effectively the same to: 143 | luaK_concat(fs, &fs->jpc, list) 144 | 145 | With a minor side-effect that modifying "fs->lasttarget". 146 | 147 | 148 | 149 | void luaK_dischargevars (FuncState *fs, expdesc *e) 150 | ========================================================================== 151 | Gaurantee there is one value avaialbe for "e". 152 | 1. If the value already exists in a register (VCALL, VLOCAL), then no new instruction 153 | spat out, no instruction patched. The pre-determined reg is put into "e->u.info". 154 | 2. If the value is not allocated with a register (VUPVAL, VINDEXED, VVARARG), this function 155 | 1) Spit out a "GET..." instruction for VUPVAL/VINDEXED, left the target reg pent. 156 | 2) Patch the VVARARG instruct to assign only one value (e.g. Bx=2), left the target reg pent. 157 | ---------------------------------------------------- 158 | 1. VNONRELOC: in "e->u.info" register. 159 | 2. VRELOCABLE: "e->u.info" point to an instruction, whose "A" parameter is pending. 160 | 3. Other. 161 | 162 | 163 | 164 | void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) 165 | ========================================================================== 166 | Adjust a multi-value. 167 | 1. For VCALL, patch Cx as "nresults+1". 168 | 2. For VVARARG, patch Bx as "nresults+1", patch Ax (destination reg) to a free reg slot. 169 | 170 | 171 | 172 | static void exp2reg (FuncState *fs, expdesc *e, int reg) 173 | ========================================================================== 174 | 175 | For e->k == VJMP and NOT following a "TESTSET" 176 | ---------------------------------------------------------- 177 | JMP 0, "e->t" 178 | e->f: LOAD_BOOL "reg", 0, 1 179 | e->t: LOAD_BOOL "reg", 1, 0 180 | 181 | For anything else, just delegate to discharge2reg(). 182 | 183 | For e->k == VJMP 184 | ---------------------------------------------------------- 185 | exp2reg (fs, e, reg) 186 | 187 | 188 | 189 | 190 | int luaK_exp2RK (FuncState *fs, expdesc *e) 191 | ========================================================================== 192 | Make result of "e" in a register or in a constant entry (prepared for instruction accepting 193 | RK parameters). 194 | 195 | 196 | 197 | static void discharge2reg (FuncState *fs, expdesc *e, int reg) 198 | ========================================================================== 199 | Make the result of "e" into register "reg". 200 | Except for "VVOID" and "VJMP". 201 | 202 | 203 | 204 | static void dischargejpc (FuncState *fs) 205 | ========================================================================== 206 | Travserse the "fs->jpc" list. Modify all "TESTSET" instructions involved in the list to 207 | "TEST" instructions. Patch all insructions' sBx to "fs->pc". 208 | ------------------------------------------------------- 209 | patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc) 210 | 211 | 212 | 213 | 214 | static int code_label (FuncState *fs, int A, int b, int jump) 215 | ========================================================================== 216 | Emit the last two instructions for a logical expression, one for the case the yielded 217 | value is TRUE, the other for FALSE. 218 | 219 | All sub-expressions in the same logical expression, which yield non-bollean values, 220 | jumps to the instruction following the last instruction generated by this function. 221 | The location of that instruction (the one following the last) is called "vtarget". 222 | 223 | 224 | 225 | static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, int dtarget) 226 | ========================================================================== 227 | Traverse the patch-list pointed by "list". 228 | 1. For all instructions which do NOT follow a "TESTSET", set their sBx to "dtarget". 229 | 2. For all which follow "TESTSET"s, set the "TESTSET"'s' "register A" to "reg" and their 230 | sBx to "vtarget". 231 | 232 | Note: 233 | 1. If "reg" is NO_REG, then "vtarget" should be the same to "dtarget". 234 | 2. "vtarget" means "value" target. It is used by a relation-expr whose value is not 235 | necessarily boolean, but could be any type. When the expr code jumps to "vtarget", 236 | "register A" is the value of the expr which is set by the "TESTSET" instruction. 237 | 3. Param "vtarget" and "reg" are used only in exp2reg(). 238 | 239 | 240 | 241 | 242 | 243 | static int patchtestreg (FuncState *fs, int node, int reg) 244 | ========================================================================== 245 | Patch the "register A" (i.e. the destination register) of a "TESTSET" instruction. 246 | The "TESTSET" would be either the one prior to "node", or the "node". 247 | 1. Do nothing and returns 0 if the "node"-1 or "node" instruction is not "TESTSET". 248 | 2. If "reg" is neither "NO_REG" nor equal to "register B" of the instruction, set 249 | it as "register A" of the instruction. 250 | 3. Otherwise, change the instruction to a "TEST" instruction, set the old 251 | "register B" as "register A". (For a TEST, "register B" is ignored.) 252 | 253 | 254 | 255 | static int need_value (FuncState *fs, int list) 256 | ========================================================================== 257 | The name of the function means the patch-list specified by "list" does not set a value 258 | in a register by its own. Therefore it *needs* a value from somewhere else. 259 | 260 | Not setting a value means not all instructions are TESTSET in "list". 261 | 262 | This function is used by exp2reg() only. When an expr with JMP needs a value, exp2reg() 263 | will generate two LOADBOOL instructions to generate the final boolean value. 264 | 265 | 266 | 267 | static int getjump (FuncState *fs, int pc) 268 | ========================================================================== 269 | The instruction at index "pc" must be of sBx form. 270 | Return the target absolute index of the jump, or "NO_JUMP" when the offset is "NO_JUMP". 271 | The absolute index of the jump is computed according to the relative jump offset obtained 272 | from the instrcution, and the "pc" of the instruction. 273 | 274 | 275 | 276 | 277 | static Instruction *getjumpcontrol (FuncState *fs, int pc) 278 | ========================================================================== 279 | Test if the instruction proceeding "pc" is a "test instruction" (see "testTMode(m)" for details). 280 | If so, return the "test instruction", otherwise return the instruction at index "pc". 281 | 282 | 283 | 284 | 285 | static void fixjump (FuncState *fs, int pc, int dest) 286 | ========================================================================== 287 | Write the sBx part of the instruction at index "pc" to have it jump to "dest". 288 | 289 | 290 | 291 | testTMode(m) 292 | ========================================================================== 293 | If the OP_ "m" is a "test"-mode instruction. 294 | A "test"-mode instruction followed by a jump instruction. 295 | Test mode includes: 296 | - OP_EQ 297 | - OP_LT 298 | - OP_LE 299 | - OP_TEST 300 | - OP_TESTSET 301 | 302 | 303 | 304 | 305 | assignment 306 | 307 | 308 | -------------------------------------------------------------------------------- /ldebug.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | l_noret luaG_runerror (lua_State *L, const char *fmt, ...) 5 | ========================================================================== 6 | luaG_runerror(L, fmt, ...) 7 | [va_list argp] 8 | va_start(argp, fmt) 9 | luaO_pushvfstring(L, fmt, argp) 10 | strchr(fmt, '%') 11 | luaD_checkstack(L, 2) -------------------------------------------------------------------------------- /ldo.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | static void correctstack (lua_State *L, TValue *oldstack) 5 | ========================================================================== 6 | Set all "abstract" address in the "oldstack" to having the same relative address 7 | to the current "L->stack". 8 | 9 | -------------------------------------------------------------------------------- /ldump.c: -------------------------------------------------------------------------------- 1 | 2 | static void DumpFunction(const Proto* f, DumpState* D) 3 | ------------------------------------------------------------------------------------------ 4 | Nested function are dumped in DumpConstants(). 5 | 6 | 7 | 8 | 9 | static void DumpConstants(const Proto* f, DumpState* D) 10 | ------------------------------------------------------------------------------------------ 11 | Dumping format: 12 | -------------------------------- 13 | | f->sizek | 14 | -------------------------------- 15 | | (constants) | 16 | | ... | 17 | -------------------------------- 18 | | f->sizep (nested funcs) | 19 | -------------------------------- 20 | | f->p[0] | 21 | | f->p[1] | 22 | | ... | 23 | -------------------------------- -------------------------------------------------------------------------------- /lfunc.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | void luaF_close (lua_State *L, StkId level) 4 | ========================================================================== 5 | Close all open upvals when a block is out of execution flow. 6 | - All upvals of all closures are linked into "L->openupval". 7 | - Upvals belonging to the about-to-exit block has the "v" field higher than "level". 8 | - "level" is the base of a function call, or the nactvar of a block. 9 | ("nactvar" is the number of active locals outside a block.) 10 | 11 | This function is invoked in two places: 12 | - Returning from a function. (OP_RETURN) 13 | - Exit a block in which some local variables are used as UpVals. Whether there being any 14 | variables in a block are used UpVals is determined by BlockCnt::upval and BlockCnt::prev. (OP_JMP) 15 | BockCnt::prev is used to determine if it is the topmost level in a chunck (i.e. loaded source code). 16 | -------------------------------------------------------------------------------- /lgc.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | General Process 5 | -------------------------------------------------------------------------------- 6 | 1. All objects are created white. 7 | 2. A reachable object is marked as black, and added to the gray list because its 8 | refered objects might still remain white (or gray if they in turn have refered 9 | objects). 10 | 3. If all directly and indirectly referred object of a black object is marked black, 11 | the black object is removed out of the gray list. 12 | 4. A black object is not necessarily a reachable object, because it might be 13 | obsoleted after it is marked. 14 | 5. A current-white object is not necessarily unreachable unless GC is in "atomic" 15 | step. 16 | 6. A current-white object MUST be unreachable at "atomic" step because at that 17 | point all reachable and some just-becoming-unreachable objects have all been marked. 18 | 7. At "atomic" step, all current-white objects are added to the sweep lists, and 19 | then they become other-white because the while flag is flipped. After "atomic" step, 20 | all "other-white" objects are guranteed to be unreachable until the next "pause" 21 | step. 22 | 23 | 24 | 25 | 26 | 27 | Barriers 28 | -------------------------------------------------------------------------------- 29 | A barriers is set when a object is added to another object as the latter's refered 30 | object. 31 | 32 | If the "refering" object is a table, then a backward barrier is usually set, making 33 | the table back to the gray-list. 34 | 35 | Otherwise, a forward barrier is set, mark the refered object as "black" (but possibly 36 | in the gray-list) in order to avoid putting the refering object into gray-list (but 37 | it might be already there). 38 | 39 | 40 | 41 | 42 | 43 | 44 | Global List 45 | ================================================================================ 46 | finobj Objects marked by a meta-table with "__gc" method. 47 | tobefnz Objects moved from finobj in the "atomic" step, all unreachable. 48 | They will be: 49 | 1. Remarked at "pause" step; and/or 50 | 2. Be inovked "__gc" upon, and then put to "allgc" list. 51 | allgc Objects except for those in "finobj" and "tobefnz". 52 | 53 | 54 | 55 | 56 | 57 | Object Status 58 | ================================================================================ 59 | Current-white Unreached yet. 60 | Black Currently used. Not neccessarily reachable. 61 | Other-white Unreachable (never used). __gc has been invoked on it. 62 | 63 | 64 | 65 | GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) 66 | ================================================================================ 67 | This function is simplified from what it was in 5.2. In 5.2, there was a "list" parameter which was 68 | used for only UpVal (which then was a GCObject). UpVal in 5.2, although was GCObject, were not linked 69 | to g->allgc, but instead g->uvhead. 70 | 71 | 72 | 73 | bitmask(b) 74 | ================================================================================ 75 | Create a mask in which the "b"th bit is "1". 76 | 77 | 78 | resetbits(x,m) 79 | ================================================================================ 80 | Set to zero all bits in "x" which are masked by "m". 81 | 82 | 83 | resetbit(x,b) 84 | ================================================================================ 85 | Set to zero the "b"th bit of "x". 86 | 87 | 88 | isdeadm(ow,m) 89 | ================================================================================ 90 | Ture if "m" has "other_than_current_white" marked. 91 | 92 | 93 | linkgclist(o,p) 94 | ================================================================================ 95 | Link object "o" on to list "p". The *next* pointer is h->gclist. 96 | This was named linktable in 5.2. 97 | 98 | 99 | static GCObject *udata2finalize (global_State *g) 100 | ================================================================================ 101 | Move the head of "g->tobefnz" to "g->allgc". 102 | Clear its "FINALIZEDBIT" bit. Then return that object (previous head of g->tobefnz). 103 | 104 | Immediately after this function, the "__gc" of the returned object must be invoked 105 | by invoking GCTM(). 106 | 107 | Before this function called, markbeingfnz() is called to mark all objects as black 108 | or gray (and added to the gray-list). Then this function adding them to g->allgc 109 | makes the object subject to normal GC rules (normally reclaimed, but could be 110 | resurrected within "__gc"). 111 | 112 | 113 | static void separatetobefnz (global_State *g, int all) 114 | ================================================================================ 115 | Move un-reached ("all" is 0) or all ("all" is 1) objects in g->finobj to g->tobefnz. 116 | "all" is set to 1 only at the time that a lua_State is closed. 117 | 118 | 119 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) 120 | ================================================================================ 121 | Reclaim the dead object in "*p". Mark still alive objects as "current-white". 122 | 123 | If "*p" is allgc, then the alive objects wait for the next marking phase. 124 | If "*p" is finobj, they will be moved to tobefnz by separatetobefnz() later. 125 | If "*p" is tobefnz, they will be moved to allgc after "__gc" called by udata2finalize(). 126 | 127 | 128 | 129 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) 130 | ================================================================================ 131 | sweeplist (L, p, count) 132 | otherwhite(L->l_G) // ==> ow 133 | luaC_white(L->l_G) // ==> white 134 | [iterate over lisp "p"] 135 | isdeadm(ow, (*p)->marked) 136 | [true] 137 | freeobj(L, curr) 138 | 139 | 140 | 141 | 142 | 143 | static void reallymarkobject (global_State *g, GCObject *o) 144 | ================================================================================ 145 | 1. Objects which do not refer to other colletable objects (userdata, string) 146 | are marked black. 147 | 2. Objects which refer to other collectable objects (table, closure, thread, 148 | prototype/func) are linked to a gray list, waiting for "propagation" of 149 | the marks. 150 | 3. Upval is marked black and its real value is marked according to the above 151 | rules. 152 | 153 | Userdata 154 | ----------------------------------------- 155 | reallymarkobject(g, o) 156 | white2gray(o) // clear all white bits 157 | markobject(g, mt) 158 | markobject(g, o->env) 159 | gray2black(o) 160 | 161 | Table 162 | ----------------------------------------- 163 | reallymarkobject(g, o) 164 | white2gray(o) // clear all white bits 165 | linktable(gco2t(o), &g->gray); 166 | gray2black(o) 167 | 168 | 169 | 170 | static void separatetobefnz (global_State *g, int all) 171 | ================================================================================ 172 | separatetobefnz(g, 0) 173 | findlast(&g->tobefnz) // ==> lastnext 174 | [loop over g->finobj: curr] 175 | iswhite(curr) 176 | [move curr from g->finobj to the tail of g->tobefnz] 177 | 178 | 179 | static void callallpendingfinalizers (lua_State *L, int propagateerrors) 180 | ================================================================================ 181 | callallpendingfinalizers(L, 1) 182 | [loop on "L->l_G->tobefnz"] 183 | GCTM(L, 1) 184 | udata2finalize(L->l_G) 185 | resetbit(gch(o)->marked, FINALIZEDBIT) 186 | issweepphase(L->L_G) 187 | [makewhite(L->l_G, o)] 188 | setgcovalue(L, &v, L->l_G->allgc) 189 | luaT_gettmbyobj(L, &v, TM_GC) // ==> tm 190 | [L->l_G->gcrunning = 0] 191 | luaD_pcall(L, dothecall, NULL, ...); 192 | luaD_rawrunprotected(L, dothecall, NULL) 193 | dothecall(L, NULL) 194 | luaD_call(L, L->top - 2, 0, 0) 195 | luaD_precall(L, L->top - 2, 0) 196 | [luaV_execute(L)] // only for Lua-function 197 | 198 | 199 | 200 | 201 | void luaC_fullgc (lua_State *L, int isemergency) 202 | ================================================================================ 203 | luaC_fullgc(L, isemergency) 204 | keepinvariant(L->l_G) 205 | [entersweep(L)] 206 | sweeptolive(L, &L->l_G->allgc, &n) 207 | [loop on L->l_G->allgc] 208 | sweeplist(L, &L->l_G->allgc, &n) 209 | luaC_runtilstate(L, bitmask(GCSpause)) 210 | 211 | 212 | 213 | 214 | 215 | markvalue(g,o) 216 | ================================================================================ 217 | markvalue(g,o) 218 | checkconsistency(o) 219 | iscollectable(o) 220 | rttype(o) 221 | righttt(o) 222 | valiswhite(o) 223 | iscollectable(o) 224 | iswhite(gcvalue(o)) 225 | 226 | 227 | traversethread(global_State *g, lua_State *th) 228 | ================================================================================ 229 | traversethread(g, th) 230 | [loop from th->stack to th->top: o] 231 | markobject(o) 232 | [in atomic step] 233 | [loop from th->top+1 to th->stack+th->stacksize] 234 | setnilvalue(o) 235 | 236 | 237 | Steps 238 | ================================================================================ 239 | 240 | Pause 241 | ----------------------------------------- 242 | singlestep(L) // L->l_G ==> g 243 | restartcollection(g) 244 | [clean "gray", "grayagain"] 245 | [clean "weak", "allweak", "ephemeron"] 246 | markobject(g, g->mainthread) // mainthread ==> gray list 247 | markvalue(g, &g->l_registry) 248 | markmt(g) 249 | [for each in "g->mt"] 250 | markobject(g, [each]) 251 | markbeingfnz(g) 252 | [for each in "g->tobefnz"] 253 | makewhite(g, [each]) 254 | reallymarkobject(g, [each]) 255 | 256 | Propregate with gray 257 | ----------------------------------------- 258 | singlestep(L) // L->l_G ==> g 259 | propagatemark(g) 260 | 261 | 262 | Proporgate with no gray 263 | ----------------------------------------- 264 | singlestep(L) // L->l_G ==> g 265 | atomic(L) 266 | markobject(g, L) 267 | markvalue(g, &g->l_registry) 268 | markmt(g) 269 | remarkupvals(g) 270 | propagateall(g) // assure no gray any more 271 | retraversegrays(g) 272 | propagateall(g) // seems no use? 273 | propagatelist(g, grayagain) 274 | propagatelist(g, weak) 275 | propagatelist(g, ephemeron) 276 | convergeephemerons(g) 277 | clearkeys(g, g->ephemeron, NULL) 278 | clearkeys(g, g->allweak, NULL) 279 | clearvalues(g, g->weak, NULL) 280 | clearvalues(g, g->allweak, origall) 281 | entersweep(L) 282 | 283 | 284 | 285 | 286 | 287 | -------------------------------------------------------------------------------- /lgc.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | GCObject::marked 4 | =========================================================================================================== 5 | 6 | FINALIZEDBIT In 5.2, it means the object is in "tobefnz" list. 7 | In 5.3 beta, it means the object is in either "finobj" or in "tobefnz" list. 8 | In 5.3 beta, after an object's "__gc" called and the object is moved back to "allgc" list, 9 | there will be no flag indicating the object was "finalized". In 5.2, such an object still 10 | has "FINALIZEDBIT" in its mark but that state is not used. 11 | 12 | SEPARATED In 5.2, it means the objct is in either "finobj" or in "tobefnz" list. 13 | In 5.3 beta, its meaning is replaced by FINALIZEDBIT, and this flag is removed. 14 | There is no longer a flag indicating an object is in "tobefnz" (which was FINALIZEDBIT 15 | in 5.1). 16 | -------------------------------------------------------------------------------- /lmem.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) 5 | -------------------------------------------------------------------------------------------- 6 | Augment L->l_G->frealloc with GC. 7 | It increases L->l_G->GCdebt by (nsize - osize). 8 | 9 | 10 | 11 | luaM_reallocv(L, b, on, n, e) 12 | -------------------------------------------------------------------------------------------- 13 | on: old number of elements. 14 | n: new number of elements. 15 | e: size of a single element. "n * e" pass to luaM_realloc_(...) as "nsize". 16 | 17 | 18 | 19 | 20 | luaM_reallocvector(L, v, oldn, n, t) 21 | -------------------------------------------------------------------------------------------- 22 | Cast result to type "t" and use type "t" for element size. 23 | 24 | 25 | 26 | 27 | void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, 28 | int limit, const char *what) 29 | -------------------------------------------------------------------------------------------- 30 | Try to double the size of block, or to "limit" if the doubled-size is larger than limit. 31 | size - numbr of elements 32 | size_elems - size in bytes of a single element 33 | 34 | 35 | 36 | luaM_growvector(L, v, nelems, size, t, limit, e) 37 | -------------------------------------------------------------------------------------------- 38 | Try to double the size of v if nelems + 1 > size. 39 | size - original and new size 40 | t - type of elements 41 | e - error message will be "too many [e] (limit is [limit])" 42 | 43 | 44 | luaM_growvector(L, 45 | funcstate.f->upvalues, 46 | funcstat.nups, 47 | f->sizeupvalues, 48 | Upvaldesc, MAXUPVAL, "upvalues"); -------------------------------------------------------------------------------- /lobject.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Value vs. GCObject vs. GCUnion 5 | --------------------- 6 | Values (or TValue, more strictly speaking) are what is associated with Lua variables. 7 | TValues reside in stack. Values represent UpVals. TValues act as table fields. 8 | 9 | GCObjects reside only in the heap. They are referred by Values. 10 | GCUnion represents all subclasses of GCObject. 11 | 12 | 13 | 14 | StkId --> TValue --> lua_TValue --> (contains) TValuefields 15 | 16 | 17 | TValuefields 18 | ----------------- 19 | Value is untagged (having no type information). TValue means "tagged" value, value augmented 20 | with type tag (tt_). 21 | ----------------- 22 | value (Value) ---> (union) gc (GCObject) 23 | tt_ (int) p (void) 24 | b (int) 25 | f (lua_CFunction) 26 | n (ua_Number) 27 | 28 | 29 | 30 | setnilvalue(obj) 31 | ================== 32 | Assign *tt_* field as LUA_TNIL 33 | 34 | 35 | 36 | 37 | 38 | GCUnion 39 | ----------------- 40 | "gclist" is the next node of the gray list if the object resides in one such list. 41 | 42 | ------------------------------------------------- 43 | GCObject* next | 44 | lu_byte tt | Common header 45 | lu_byte marked | 46 | ------------------------------------------------- 47 | lu_byte nupvalues | Closure header 48 | GCObject* gclist | 49 | ------------------------------------------------- 50 | 51 | 52 | TString 53 | ------------------------------------------------- 54 | GCObject* next | 55 | lu_byte tt | Common header 56 | lu_byte marked | 57 | ------------------------------------------------- 58 | lu_byte extra | 59 | unsigned int hash | 60 | size_t len | 61 | TString* next | 62 | ------------------------------------------------- 63 | 64 | 65 | 66 | 67 | 68 | 69 | UpVal 70 | ----------------- 71 | UpVal is no longer a GCObject like it was in 5.2. 72 | UpVal is no longer linked to g->uvhead, but only linked to L->openupval. 73 | ------------------------------------------------------------------------------------- 74 | TValue* v | linked to either in-stack value or to "value" 75 | lu_mem refcount | 76 | ------------------------------------------------------------------------------------- 77 | TValue value | UpVal* next | linked to "L->openupval". In 5.2 it was to g->uvhead 78 | | int touched | 79 | ------------------------------------------------------------------------------------- 80 | 81 | 82 | 83 | 84 | Table 85 | ----------------- 86 | 87 | ------------------------------------------------- 88 | GCObject* next | 89 | lu_byte tt | Common header 90 | lu_byte marked | 91 | ------------------------------------------------- 92 | lu_byte flags | Presence of meta-method. "1" means absent. All "1" at initialized. 93 | lu_byte lsizenode | Log(sizenode), so there is no "sizenode" field 94 | ... | 95 | Node* node | Hashed key-value 96 | ... | 97 | 98 | 99 | 100 | UData 101 | ----------------- 102 | 103 | ------------------------------------------------- 104 | GCObject* next | 105 | lu_byte tt | Common header 106 | lu_byte marked | 107 | ------------------------------------------------- 108 | lu_byte ttuv_ | New in 5.3 109 | Table* metatable | 110 | size_t len | 111 | Value user_ | New in 5.3. Holding any Lua type. In 5.2, it was "env" which holds table type only. 112 | | Note: "env" in 5.2 does not really mean env. Just an ordinary table. 113 | ------------------------------------------------- 114 | ... (real data) 115 | ------------------------------------------------- 116 | 117 | 118 | 119 | Proto 120 | ----------------- 121 | 122 | ------------------------------------------------- 123 | GCObject* next | 124 | lu_byte tt | Common header 125 | lu_byte marked | 126 | ------------------------------------------------- 127 | ... | 128 | -------------------------------------------------------------------------------------------------- 129 | LocVar* locvars | TString* varname | debug and parsing information for local-var, 130 | | int startpc | used for var-seach in parsing. indexed by 131 | | int endpc | "Dyndata::actvar.arr". 132 | -------------------------------------------------------------------------------------------------- 133 | ... | 134 | int sizecode | size of "code" 135 | int sizelineinfo | size of "lineinfo" 136 | ... | 137 | lu_byte is_vararg | it has mere two possible values now, 0 or 1. 138 | lu_byte upvalues | for the _description_ of upvalues. For example, if an upval shall be 139 | | on the stack (locals of enclosing function). 140 | 141 | 142 | 143 | Closure 144 | ----------------- 145 | upvals: Reference to real upvals. Its initialization is made according to 146 | Proto.upvalues specification. 147 | 148 | 149 | 150 | 151 | 152 | setgcovalue(L,obj,x) 153 | ================== 154 | Set TValue "obj" pointing to collectable object "x", including make "obj" and "x" 155 | marked as the same type ("tt_" field of the former and "tt" field of the latter). 156 | 157 | -------------------------------------------------------------------------------- /lopcodes.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | OP_SELF 4 | ------------------------ 5 | OP_SELF is a OP_GETTABLE with loading the table into the next register. -------------------------------------------------------------------------------- /lparser.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | General Rules 4 | -------------------------------------------------------------- 5 | Arraies are usually stored in continuous memory block. The block is pre-allocated 6 | and grow on-the-fly by doubling its size. 7 | - The actually used item number is of name "n...". For Proto::code, the actually 8 | generated code instruction number is FuncState::pc. 9 | - the allocated memory size is of name "size...", 10 | - both in terms of the number of items (not in bytes). 11 | 12 | 13 | 14 | LClosure 15 | ----------------------------- ----------------- ---------------- 16 | | GCObject* next | 17 | | lu_byte tt | CommonHeader 18 | | lu_byte marked | 19 | ----------------------------- ------- ClosureHeader 20 | | lu_byte nupvalues | 21 | | GCObject* gclist | 22 | ----------------------------- ----------------- ----------------- 23 | | Proto* p | 24 | ----------------------------- 25 | | UpVal* upvalue | 26 | | ... | 27 | | ... | 28 | ----------------------------- 29 | 30 | 31 | 32 | 33 | 34 | FuncState 35 | ----------------------------- 36 | | Proto* f | 37 | | Table* h | hash-table of "f->k", for resuing const whenever possible 38 | | FuncState* prev | 39 | | LexState* ls | 40 | | BlockCnt* bl | chain of nesting blocks 41 | | int pc | count of "f->code" and "f->lineinfo". 42 | | int lasttarget | 43 | | int jpc | list of JMP instructions pending to the next "pc" 44 | | ... | 45 | | int nk | number of already-used slot in "f->k". 46 | | ... | 47 | | int firstlocal | first local index in "dyd". 48 | | short nlocvars | number of all local vars within the current function, used items in "f->locvars". 49 | ---------------------------------------------------------- 50 | | lu_byte nactvar | number of currently active local vars, "nactvar <= nlocalvars" because some blocks 51 | | | already exited. its maximal value is the number of regs allocated to the current 52 | | | function with a name. note some statments allocate temp "var" without name 53 | ---------------------------------------------------------- 54 | | lu_byte nups | number of currently parsed up-values 55 | | ... | 56 | ----------------------------- 57 | 58 | 59 | 60 | Dyndata 61 | ----------------------------- 62 | | Vardesc* arr | array of (short index)s, indices to Proto::locvars 63 | | | this array itself is indexed by "reg" number. note that items in Proto::locvars might 64 | | | reuse the same "reg" numbers as this array grows and shrinks 65 | | int n | 66 | | int size | 67 | ----------------------------- 68 | | Labellist* gt | 69 | | Labellist* label | 70 | ----------------------------- 71 | 72 | 73 | 74 | expdesc 75 | ----------------------------- 76 | | expkind k | 77 | | int u.info | 78 | | int t | 79 | | int f | 80 | ----------------------------- 81 | 82 | 83 | static int explist (LexState *ls, expdesc *v) 84 | ========================================================================== 85 | Generate code as follows: 86 | Put comma-separated expression into adajcent "reg"s, except for the last one. 87 | 88 | Note: The general rule is functions other than "lua_K..." does not generate 89 | code into Proto::code. This method handles more than one expressions but 90 | accepts and resues single "v", so it generates actual code to Proto::code 91 | and only leaves the code for the last expression in the list "open". 92 | 93 | 94 | 95 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) 96 | ========================================================================== 97 | An invocation to "assignment()" handles a suffixing portion of an "assignment-stat", 98 | which is a type of "exprstat" (although this is not a type defined in syntax). 99 | 100 | For example: 101 | a, b, c, d, e = f, g, h, i 102 | 103 | Then an assignment could be one of the follows: 104 | - , b, c, d, e = f, g, h, i 105 | - , c, d, e = f, g, h, i 106 | - , d, e = f, g, h, i 107 | - , e = f, g, h, i 108 | - = f, g, h, i 109 | 110 | But not the follows: 111 | - a, b, c, d, e = f, g, h, i // this is a whole "exprstat" 112 | - f, g, h, i // this is the tailing "explist", must contain the "=" 113 | 114 | For a multi-assignment, "assignment()" recursively invokes as many level as the 115 | number of left-hand vars. 116 | 117 | 118 | 119 | static void singlevar (LexState *ls, expdesc *var) 120 | ========================================================================== 121 | Initialize "var" for a single NAME. The resulted "var" content is: 122 | 1. VLOCAL. 123 | 2. VUPVAL, or 124 | 3. VINDEXED, for a global var. 125 | 126 | 127 | 128 | 129 | static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) 130 | ========================================================================== 131 | base: indicating if this is the local-level (as 1) or upper-level (as 0). 132 | if a var is found at an upper-level, mark BlockCnt.upval. 133 | BlockCnt.upval makes leaveblock() inserts a JMP to close upvals. 134 | 135 | along the path from a FuncState where an upvalue is found (call level n) 136 | to the current "fs", call level 0, a new item is added to FunState::f->upvalues 137 | from level n-1 to 0. 138 | 139 | return: VVOID if the name "n" is not found. A global var. 140 | VLOCAL if found at the current level. Only meaningful when "base" is 0. 141 | When "base" is greater than 0, the found var is marked as "used-as- 142 | upval", and the return value is ignored by the lower level (inner- 143 | nested) searching. 144 | VUPVAL if found at the upper level. 145 | 146 | 147 | 148 | static int searchupvalue (FuncState *fs, TString *name) 149 | ========================================================================== 150 | Return the index of "fs->upvalues" of the upvalue, which has the given name "name". 151 | Return -1 if no upvalue of the name found. 152 | 153 | 154 | 155 | static int searchvar (FuncState *fs, TString *n) 156 | ========================================================================== 157 | Search a local var with the given name "n" within the given function-level 158 | "fs". Return the "reg" index the local var residing. 159 | 160 | 161 | 162 | static LocVar *getlocvar (FuncState *fs, int i) 163 | ========================================================================== 164 | return information of the var: name, start/end pc of valid region 165 | 166 | i: "reg" number of the local var 167 | fs: represent the current function level 168 | 169 | 170 | 171 | static int newupvalue (FuncState *fs, TString *name, expdesc *v) 172 | ========================================================================== 173 | Add a new slot into "fs->upvalues". 174 | Note: "v->k" should be either 175 | 1. VLOCAL, meaning an upvalue at the immediate outter block, or 176 | 2. VUPVAL, meaning an upvalue at the indirectly outter block, for 177 | which a slot is added to "fs->upvalues" for each "fs" along the 178 | nesting-path. 179 | Note: used only in two places: 180 | 1. when create a chunk, creating the "_ENV". 181 | 2. in singlevaraux(). 182 | 183 | 184 | 185 | static void codestring (LexState *ls, expdesc *e, TString *s) 186 | ========================================================================== 187 | Add a string constant "s" to "ls->fs->f->k". 188 | Set the index to "e->u.info", the value to "e->k". 189 | 190 | e: out parameter, set as a constant with content of "s". 191 | s: the content of the new string constant. 192 | 193 | 194 | 195 | 196 | static TString *str_checkname (LexState *ls) 197 | ========================================================================== 198 | Assure the current token is a NAME. Return the string of the NAME and advance 199 | the Lexer state, for one token. 200 | 201 | 202 | 203 | 204 | lua_load (lua_State *L, lua_Reader reader, void *data, 205 | const char *chunkname, const char *mode) 206 | ========================================================================== 207 | lua_load (L, reader, data, chunkname, mode) 208 | luaZ_init(L, &z, reader, data) 209 | luaD_protectedparser(L, &z, chunkname, mode) 210 | [SParser p] 211 | luaZ_initbuffer(L, &p.buff) 212 | luaD_pcall(L, f_parser, &p, ...) 213 | luaD_rawrunprotected(L, f_parser, &p) 214 | _setjmp(...) 215 | f_parser(L, &p) 216 | luaY_parser(L, p->z, &p->buff, &p->dyd, chunkname, ...) 217 | [LexState lexstate] 218 | [FuncState funcstate] 219 | luaF_newLclosure(L, 1) // ==> cl 220 | luaC_newobj(L, LUA_TLCL, ...) 221 | setclLvalue(L, L->top, cl) 222 | luaF_newproto(L) // ==> cl.l.p 223 | luaS_new(L, chunkname) // ==> cl.l.p.source 224 | luaX_setinput(L, &lexstate, p->z, funcstate.f->source, ...) 225 | luaS_new(L, LUA_ENV) // ==> lexstate.envn 226 | luaS_fix(lexstate->envn) 227 | luaZ_resizebuffer(L, &p->buff, LUA_MINBUFFER) 228 | mainfunc(&lexstate, &funcstate) 229 | [BlockCnt bl] 230 | [expdesc v] 231 | open_func(&lexstate, &funcstate, &bl) 232 | luaH_new(L) // ==> funcstate.h 233 | enterblock(&funcstate, bl, 0); 234 | init_exp(&v, VLOCAL, 0) 235 | newupvalue(&funcstate, lexstate.envn, &v) 236 | checklimit(&funcstate, funcstate.nups + 1, MAXUPVAL, "upvalues") 237 | luaM_growvector(L, funcstate.f->upvalues, funcstat.nups, f->sizeupvalues, 238 | Upvaldesc, MAXUPVAL, "upvalues"); 239 | luaC_objbarrier(L, funcstate.f, chunkname) 240 | luaX_next(&lexstate) 241 | statlist(&lexstate) 242 | close_func(&lexstate) 243 | 244 | 245 | 246 | 247 | static void statlist (LexState *ls) 248 | ========================================================================== 249 | statlist(ls) 250 | block_follow(ls, 1) 251 | 252 | 253 | 254 | 255 | static void ifstat (LexState *ls, int line) 256 | ========================================================================== 257 | GOTO state 258 | ------------------------------------------ 259 | ifstat(ls, line) 260 | [escapelist] 261 | test_then_block(ls, &escapelist) 262 | [expdesc v] 263 | expr(ls, &v) 264 | checknext(ls, TK_THEN) 265 | luaK_goiffalse(ls->fs, &v) 266 | luaK_dischargevars(ls->fs, &v) 267 | freereg(fs, u.ind.idx) 268 | 269 | 270 | 271 | 272 | Expressions Apperaing In (Only): 273 | ------------------------------------------ 274 | 1. Rvalue of assignment statement. 275 | 2. Rvalue of local statement. 276 | 3. Cond of "if", "while", "repeat". 277 | 278 | 279 | 280 | Expression Type 281 | ------------------------------------------ 282 | VNIL | Instuction has not been emitted. 283 | VTRUE | 284 | VFALSE | 285 | VK | 286 | VKFLT | 287 | VKINT | 288 | VJMP: The expression is a comparison expression (i.e. EQ, LT, LE, NE, GE, GT). 289 | VRELOCABLE: The target register (usually R(A)) is not yet determined (set as 0). 290 | The instruction is already put into Proto. 291 | e->u.info stores the location of the instruction. 292 | VNONRELOC: The instruction has been emitted to FuncState::f->code. 293 | e->u.info stores the register storing the result value. The instruction is 294 | complete and must not be modified (hence the type NONRELOC). 295 | VVARARG: The target reg could be ether determined or not: 296 | 1. If determined, it is a multi-value which is NOT adjusted. 297 | 2. If undetermined, it will be either: 298 | 2.a) assigned to a free reg for a multi-assignement. 299 | 2.b) adjust to one value and the target reg left pent, type changed 300 | to VRELOCABLE. 301 | VCALL: The reg location of the returned value is already determined by OP_CALL, 302 | and will be transfer into "VNONRELOC" with no further post-fixing. 303 | VINDEXED: The instruction of evaluate the table and the key have already been in Proto. 304 | The instruction of evaluate the value is NOT in Proto. 305 | 306 | 307 | 308 | Methods Modifying "e->k" 309 | ========================================================================== 310 | 1. The "..exp2.." functions make sure an expression is set in a register, with VNONRELOC as result. 311 | 2. The "..discharge.." functions process only some types of expression, leaving others handled by 312 | other "..discharge.." or "..exp2.." functions. 313 | 4. No "..dischare.." function processes VJMP expressions. It's left to "..exp2.." functions. 314 | 5. The functions with prefix "luaK_" are interfacing with the parser. 315 | 6. The functions with prefix "luaK_" do not specify which reg the value should be put. They use 316 | "2anyreg" or "2nextreg", or "2value" (meaing either to reg, or have a constant result). 317 | 7. The functions with "2reg" do not have "luaK_" prefix because the register allocation is done 318 | completely inside the code-generator. 319 | ========================================================================== 320 | 321 | void luaK_exp2nextreg (FuncState *fs, expdesc *e) 322 | --------------------------------------------------- 323 | Set "e" to the next free register, even when "e" is VNONRELOC (in such case generating 324 | an "OP_MOV"). 325 | 326 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) 327 | --------------------------------------------------- 328 | Assure "e" to be in a register. If "e" is VNONRELOC, doing nothing (??). 329 | 330 | void exp2reg (FuncState *fs, expdesc *e, int reg) 331 | --------------------------------------------------- 332 | The cover function which gurantees the "e" to be VNONRELOC. Its main purpose 333 | is handling "VJMP". All other types are delegated to "discharge2reg()". 334 | --------------------------------------------------- 335 | * VJMP => VNONRELOC 336 | * (discharge2reg) 337 | 338 | static void discharge2reg (FuncState *fs, expdesc *e, int reg) 339 | --------------------------------------------------- 340 | With a specified "reg", this function makes most of "e" to "VNONRELOC". 341 | "VJMP" and "VVOID" are left unchanged. "VJMP" will be handled by "exp2reg()". 342 | --------------------------------------------------- 343 | * VNIL => VNONRELOC 344 | * VFALSE => VNONRELOC 345 | * VTRUE => VNONRELOC 346 | * VK => VNONRELOC 347 | * VKFLT => VNONRELOC 348 | * VKINT => VNONRELOC 349 | * VRELOCABLE => VNONRELOC 350 | * VNONRELOC => VNONRELOC | insert an "OP_MOVE". 351 | * (luaK_dischargevars) 352 | 353 | void luaK_dischargevars (FuncState *fs, expdesc *e) 354 | --------------------------------------------------- 355 | * VLOCAL => VNONRELOC 356 | * VUPVAL => VRELOCABLE 357 | * VINDEXED => VRELOCABLE 358 | * VCALL => VNONRELOC | (luaK_setoneret), pre-determined reg location 359 | * VVARARG => VRELOCABLE | (luaK_setoneret), only adjust-to-one VVARARG could be relocable. 360 | 361 | void luaK_setoneret (FuncState *fs, expdesc *e) 362 | --------------------------------------------------- 363 | * VCALL => VNONRELOC | e->u.info is the reg A of the OP_CALL. 364 | * VVARARG => VRELOCABLE | set reg B to 2 (meaning copying one value through OP_VARARG) 365 | 366 | int luaK_exp2RK (FuncState *fs, expdesc *e) 367 | --------------------------------------------------- 368 | * VTRUE => VK | 369 | * VFALSE => VK | 370 | * VNIL => VK | => (luaK_dischargevars) 371 | * VKNUM => VK | 372 | * VK => VK | 373 | 374 | void luaK_self (FuncState *fs, expdesc *e, expdesc *key) 375 | --------------------------------------------------- 376 | * => VNONRELOC 377 | 378 | 379 | Expression Evaluation Dependencies 380 | ========================================================================== 381 | 382 | luaK_exp2RK => luaK_exp2val (luaK_exp2anyreg)? 383 | 384 | luaK_exp2val => luaK_exp2anyreg | 385 | luaK_dischargevars 386 | 387 | luaK_exp2anyreg => luaK_dischargevars (exp2reg | luaK_exp2nextreg)? 388 | 389 | luaK_exp2nextreg => luaK_dischargevars exp2reg 390 | 391 | luaK_dischargevars => luaK_setoneret 392 | 393 | exp2reg => discharge2reg 394 | 395 | discharge2reg => luaK_dischargevars 396 | 397 | 398 | static void freeexp (FuncState *fs, expdesc *e) 399 | ========================================================================== 400 | "e" should be a non-relocatable expression whose register is the last allocated 401 | one. 402 | 403 | 404 | 405 | static void freereg (FuncState *fs, int reg) 406 | ========================================================================== 407 | Register "reg" should be a constant, or a register outside the current block 408 | (less than fs->nactvar), or the last allocated register. 409 | 410 | For the first two cases, the function is no-op. For the second, it will release 411 | the register slot (by fs->freereg--). 412 | 413 | 414 | 415 | void luaK_dischargevars (FuncState *fs, expdesc *e) 416 | ========================================================================== 417 | Change the "e" to either VNONRELOC or VRELOCABLE. (Exception, not handle VJMP.) 418 | 419 | 420 | 421 | void luaK_setoneret (FuncState *fs, expdesc *e) 422 | ========================================================================== 423 | Invoked when the result of "e" is adjusted to only one value. 424 | "e" is a list, either the return value of a function (VCALL) or a VVARARG. 425 | 1. It calls getcode() to retrive the instruction. 426 | - For e->k being VCALL, it should be a OP_CALL. 427 | - For e->k being VVARARG, it should be a OP_VARARG. 428 | 2. For VCALL, set e->u.info as the reg A of the OP_CALL, and change type 429 | to VNONRELOC. 430 | For VVARARG, set reg B of OP_VARARG as 2 (meaing copying one value), 431 | leave reg A zero and set the type VRELOCABLE. 432 | 433 | 434 | 435 | static void discharge2reg (FuncState *fs, expdesc *e, int reg) 436 | ========================================================================== 437 | Make sure the result of "e" get into register "reg". (Excpetion, not handle VJMP) 438 | 439 | If there is already some code generated in Proto::code (see the above section "Expression Type"), 440 | the "luaK_dischargevars()" will make sure the code is patched that only register "A" is left. 441 | 442 | Then this function handle one of the following cases: 443 | 1. If "e" is constant, the function emit constant-loading instruction: 444 | OP_LOADNIL, OP_LOADBOOL, OP_LOADK/OP_LOADKX, 445 | or add new item into Proto::k. 446 | 2. If "e" is VRELOCABLE, patch the reg "A" in the instruction as "reg". 447 | 3. If "e" is VNONRELOC, emit OP_MOVE to copy the value to reg "reg". 448 | 449 | ------------------------------------------------------------------------------------------------ 450 | VUPVAL | OP_GETUPVAL reg, e->u.info, 0 | R(reg) := UpValue[e->u.info] 451 | ------------------------------------------------------------------------------------------------ 452 | VINDEXED | OP_GETTABUP 0, e->u.ind.t, e->u.ind.ind | 453 | ------------------------------------------------------------------------------------------------ 454 | VNIL | OP_LOADNIL reg, 1 | R(reg) := nil 455 | VFALSE | OP_LOADBOOL reg, 0 | R(reg) := FALSE 456 | VTRUE | OP_LOADBOOL reg, 1 | R(reg) := TRUE 457 | VK (normal) | OP_LOADK reg, e->u.info | R(reg) := e->u.info 458 | ------------------------------------------------------------------------------------------------ 459 | VK (ex_large) | OP_LOADKX reg, 0 | R(reg) := e->u.info 460 | | OP_EXTRAARG, e->u.info | 461 | ------------------------------------------------------------------------------------------------ 462 | VRELOCABLE | (no new instruction) | 463 | 464 | 465 | discharge2reg(fs, e, reg) // e->k == VUPVAL 466 | luaK_dischargevars(fs, e) 467 | luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0) 468 | e->k <== VRELOCABLE 469 | getcode(fs, e) // ==> pc 470 | SETARG_A(*pc, reg) 471 | 472 | discharge2reg(fs, e, reg) // e->k == VINDEXED 473 | luaK_dischargevars(fs, e) 474 | freereg(fs, e->u.ind.idx) 475 | 476 | 477 | discharge2reg(fs, e, reg) // e->k == VRELOCABLE 478 | getcode(fs, e) // ==> pc 479 | SETARG_A(*pc, reg) 480 | 481 | 482 | 483 | Methods Creating "expdesc" 484 | ========================================================================== 485 | 486 | static void singlevar (LexState *ls, expdesc *var) 487 | --------------------------------------------------- 488 | Only as a "string" constant for indexing "_ENV". 489 | 490 | static void fieldsel (LexState *ls, expdesc *v) 491 | --------------------------------------------------- 492 | Only as a "string" constant for a table. 493 | 494 | static void recfield (LexState *ls, struct ConsControl *cc) 495 | --------------------------------------------------- 496 | key: as "string" constant 497 | val: value expression to assign to a table field "key" 498 | 499 | static void funcargs (LexState *ls, expdesc *f, int line) 500 | --------------------------------------------------- 501 | As the argument list expression. 502 | Should be either "VCALL" or "VVARARG". 503 | 504 | static void suffixedexp (LexState *ls, expdesc *v) 505 | --------------------------------------------------- 506 | If following a ":", treated as a "string" constant. 507 | If encompassed by a "[]", treated as a normal expression. 508 | 509 | static BinOpr subexpr (LexState *ls, expdesc *v, int limit) 510 | --------------------------------------------------- 511 | For the inner recursively-invoked "subexpr()". 512 | 513 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) 514 | --------------------------------------------------- 515 | For the "rvalue" exprlist. 516 | 517 | static int cond (LexState *ls) 518 | --------------------------------------------------- 519 | 520 | static int exp1 (LexState *ls) 521 | static void forlist (LexState *ls, TString *indexname) 522 | static void test_then_block (LexState *ls, int *escapelist) 523 | static void localfunc (LexState *ls) 524 | static void localstat (LexState *ls) 525 | static void funcstat (LexState *ls, int line) 526 | static void retstat (LexState *ls) 527 | static void mainfunc (LexState *ls, FuncState *fs) 528 | 529 | static void constructor (LexState *ls, expdesc *t) // through ConsControl 530 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) // through LHS_assign 531 | static void exprstat (LexState *ls) // through LHS_assign 532 | 533 | 534 | mainfunc => statlist 535 | 536 | 537 | statlist => (statement)* 538 | 539 | 540 | statement => ";" | 541 | ifstat | 542 | whilestat | 543 | "do" block "end" | 544 | forstat | 545 | repeatstat | 546 | funcstat | 547 | "local" (localfunc | localstat) | 548 | "::" labelstat | 549 | "return" retstat | 550 | "goto" gotostat | 551 | exprstat 552 | 553 | 554 | ifstat => (test_then_block)+ ["else" block] "end" 555 | 556 | 557 | test_then_block => ("if" | "elseif") expr "then" 558 | (gotostat | statlist) 559 | 560 | 561 | whilestat => "while" expr "do" block "end" 562 | 563 | 564 | forstat => "for" NAME (fornum | forlist) "end" 565 | 566 | 567 | fornum => "=" expr "," expr ("," expr)? forbody 568 | 569 | 570 | forlist => ("," NAME)+ "in" explist forbody 571 | 572 | 573 | forbody => "do" block 574 | 575 | 576 | gotostat => "goto" label | "break" 577 | 578 | 579 | funcstat => funcname body 580 | 581 | 582 | block => statlist 583 | 584 | Note: "block"s are "statlist"s which must be surrounded by "begin"/"end" pair. 585 | "block"'s sematic is repsonsible for storing block-level of the internal 586 | parser state. 587 | 588 | 589 | exprstat => suffixedexp (assignment)? 590 | 591 | 592 | assignment => "," suffixedexp assignment | 593 | "=" explist 594 | 595 | Note: "assignment" by its own is not a completed statement. it should always be a 596 | part of a "exprstat". An "exprstat" becomes an "assignment-stat" when its sufixing 597 | part is "assignment". 598 | 599 | Note: "suffixedexp" involved in "assignment", including the one in the precending 600 | "exprstat" must all be "NAME". This is checked in "assignment()" when a "=" 601 | is encountered. 602 | 603 | 604 | explist => expr ("," expr)* 605 | 606 | 607 | expr => subexpr 608 | 609 | 610 | subexpr => (UNOP subexpr | simpleexp) (BIOP subexpr)* 611 | 612 | 613 | simpleexp => NUMBER | STRING | NIL | TRUE | FASLE | DOTS | 614 | constructor | 615 | "function" body | 616 | suffixedexp 617 | 618 | 619 | suffixedexp => primaryexp (fieldsel | yindex | (":" NAME funcargs) | funcargs)? 620 | 621 | Note: A "suffixed" expr consists of a "primaryexp" and optionally its suffixed part. 622 | 623 | Note: Function invocations are always "suffixedexp". The call instruction is generated 624 | from within "funcargs" according to the "expdesc" filled by the "primaryexp" (and 625 | "suffixedexp" if it is an object-oriented method). 626 | 627 | 628 | primaryexp => "(" expr ")" | NAME 629 | 630 | 631 | 632 | 633 | UNOP: "#", "-", "not" 634 | 635 | 636 | 637 | 638 | 639 | 640 | -------------------------------------------------------------------------------- /ltable.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | hashpow2(t,n) 5 | ========================================================================== 6 | n: hash code, int 7 | t: table 8 | Return the hashed slot corresponding to "n" in table "t". 9 | 10 | 11 | 12 | 13 | hashmod(t,n) 14 | ========================================================================== 15 | This method differs from "hashpow2()" in that the underlying algorithm of 16 | moduling is the ordinary "C" moduling rather than a bit-manipulating one optimized 17 | for 2-base-powered size of "t". 18 | 19 | "n" is actually moduled by size of t minues 1, rather than size of t. 20 | 21 | 22 | 23 | 24 | 25 | const TValue *luaH_getstr (Table *t, TString *key) 26 | ========================================================================== 27 | Get value if "key" is a short-string. 28 | 29 | 30 | 31 | 32 | static Node *mainposition (const Table *t, const TValue *key) 33 | ========================================================================== 34 | Get the main hash-ed position for "key". 35 | 36 | 37 | 38 | 39 | static Node *hashnum (const Table *t, lua_Number n) 40 | ========================================================================== 41 | Return the main hash-ed position for "n". 42 | 43 | 44 | 45 | 46 | luai_hashnum(i,n) 47 | ========================================================================== 48 | Compute the hashcode of "n" and put it to "i". 49 | 50 | 51 | -------------------------------------------------------------------------------- /ltm.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | const TValue *luaT_gettm (Table *events, TMS event, TString *ename) 5 | ====================================================================== -------------------------------------------------------------------------------- /lua.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | Basic Types 4 | ----------------------------------------------------------- 5 | The enum of "basic types" is: LUA_T... 6 | A "basic type" enum occupies only the right-most forth bits. 7 | The fifth right-most bit represent the "sub-type": 8 | - short/long string 9 | - c/Lua closure 10 | ... 11 | The seventh right-most bit represent if the type is collectable. 12 | 13 | 14 | /* 15 | ** tags for Tagged Values have the following use of bits: 16 | ** bits 0-3: actual tag (a LUA_T* value) 17 | ** bits 4-5: variant bits 18 | ** bit 6: whether value is collectable 19 | */ 20 | 21 | -------------------------------------------------------------------------------- /lvm.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | lua_State 4 | --------------------------------- ----------------- ---------------- 5 | | GCObject* next | 6 | | lu_byte tt | CommonHeader 7 | | lu_byte marked | 8 | --------------------------------- ----------------- ---------------- 9 | | lu_byte status | Store the status of a stack-shrunk event, e.g. LUA_YIELD, and/or error code 10 | | | of an "unprotected" call (i.e. errorJmp == NULL). 11 | --------------------------------- ----------------- ---------------- 12 | | StkId top | 13 | | global_State* l_G | 14 | | CallInfo* ci | 15 | | Instruction* oldpc | (debug info) for trace 16 | | StkId stack_last | the first slot of EXTRA_STACK (room beyond maximally-allowed "top" but under "stacksize") 17 | | StkId stack | 18 | | int stacksize | 19 | | unsigned short nny | 20 | | unsigned short nCcalls | with dual-meaning: 1. Nested C call, 2. Nested syntac structure. 21 | | ... | 22 | | lua_longjmp* errorJmp | store the location and error-code of longjmp, except coroutine yeild. 23 | | CallInfo base_ci | first level CallInfo 24 | --------------------------------- 25 | 26 | 27 | 28 | global_State 29 | --------------------------------- ----------------- ---------------- 30 | | lua_Alloc freealloc | memory allocator with its 31 | | void* ud | user-data 32 | --------------------------------- ----------------- ---------------- ---------------- ---------------- 33 | | lu_mem totalbytes | invariant: totalbytes + GCdebt = sizeof(LG) + "allocated" | 34 | | l_mem GCdebt | just-allocated bytes | Seems not real purpose except 35 | | lu_mem GCmemtrav | | guranteeing some invariants. 36 | | lu_mem GCestimate | used as the "debt" of the next step | 37 | --------------------------------- ----------------- ---------------- ---------------- ---------------- 38 | | GCObject** hash | 39 | | lu_int32 nuse | stringtable strt 40 | | int size | 41 | --------------------------------- ----------------- ---------------- 42 | | TValue l_registry | 43 | | unsigned int seed | 44 | --------------------------------- ----------------- ---------------- 45 | | lu_byte currentwhite| 46 | | lu_byte gcstate | GC incremental steps 47 | | lu_byte gckind | 48 | | lu_byte gcrunning | 49 | | int sweepstrgc | 50 | | ... | 51 | 52 | 53 | 54 | 55 | 56 | ------------------- 57 | | | 58 | | Local | 59 | | | 60 | ------------------- 61 | | | 62 | | Copied Fixed | ci->p->numparams 63 | | | 64 | ------------------- <---- ci->u.l.base Current 65 | | | Stake Frame (Callee) 66 | | | 67 | | | 68 | | Var Args | 69 | | | 70 | | | 71 | ------------------- ------------------------------ 72 | | | 73 | | Fixed Params | ci->p->numparams 74 | | | Previous 75 | ------------------- Stack Frame (Caller) 76 | | Function | 77 | ------------------- <---- ci->func 78 | | | 79 | | | 80 | 81 | 82 | ci->u.l.base is the "top" of the previous function call frame. In Lua, instructions specify var-length register 83 | parameters by a number to indicate registers indexed from that number to the "stack top". 84 | 85 | OP_VARARGS re-set the "stack top" if it accept "all" var-args so a following var-args function-call will get 86 | right number of parameters from the "func" register to the "stack top". --------------------------------------------------------------------------------