diff options
| -rw-r--r-- | lapi.c | 11 | ||||
| -rw-r--r-- | lcode.c | 11 | ||||
| -rw-r--r-- | ldebug.c | 28 | ||||
| -rw-r--r-- | ldo.c | 28 | ||||
| -rw-r--r-- | lfunc.c | 100 | ||||
| -rw-r--r-- | lfunc.h | 11 | ||||
| -rw-r--r-- | lgc.c | 73 | ||||
| -rw-r--r-- | llimits.h | 7 | ||||
| -rw-r--r-- | lobject.h | 44 | ||||
| -rw-r--r-- | lopcodes.c | 8 | ||||
| -rw-r--r-- | lopcodes.h | 4 | ||||
| -rw-r--r-- | lparser.c | 147 | ||||
| -rw-r--r-- | lparser.h | 20 | ||||
| -rw-r--r-- | lstate.c | 6 | ||||
| -rw-r--r-- | lstate.h | 12 | ||||
| -rw-r--r-- | ltests.c | 6 | ||||
| -rw-r--r-- | lvm.c | 79 | ||||
| -rw-r--r-- | lvm.h | 4 |
18 files changed, 412 insertions, 187 deletions
| @@ -248,7 +248,7 @@ LUA_API size_t lua_strlen (lua_State *L, int index) { | |||
| 248 | 248 | ||
| 249 | LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index) { | 249 | LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index) { |
| 250 | StkId o = luaA_indexAcceptable(L, index); | 250 | StkId o = luaA_indexAcceptable(L, index); |
| 251 | return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->f.c; | 251 | return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->u.c.f; |
| 252 | } | 252 | } |
| 253 | 253 | ||
| 254 | 254 | ||
| @@ -310,9 +310,16 @@ LUA_API void lua_pushstring (lua_State *L, const l_char *s) { | |||
| 310 | 310 | ||
| 311 | 311 | ||
| 312 | LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { | 312 | LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { |
| 313 | Closure *cl; | ||
| 313 | lua_lock(L); | 314 | lua_lock(L); |
| 314 | api_checknelems(L, n); | 315 | api_checknelems(L, n); |
| 315 | luaV_Cclosure(L, fn, n); | 316 | cl = luaF_newCclosure(L, n); |
| 317 | cl->u.c.f = fn; | ||
| 318 | L->top -= n; | ||
| 319 | while (n--) | ||
| 320 | setobj(&cl->u.c.upvalue[n], L->top+n); | ||
| 321 | setclvalue(L->top, cl); | ||
| 322 | incr_top; | ||
| 316 | lua_unlock(L); | 323 | lua_unlock(L); |
| 317 | } | 324 | } |
| 318 | 325 | ||
| @@ -273,6 +273,11 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { | |||
| 273 | e->k = VNONRELOC; | 273 | e->k = VNONRELOC; |
| 274 | break; | 274 | break; |
| 275 | } | 275 | } |
| 276 | case VUPVAL: { | ||
| 277 | e->u.i.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.i.info, 0); | ||
| 278 | e->k = VRELOCABLE; | ||
| 279 | break; | ||
| 280 | } | ||
| 276 | case VGLOBAL: { | 281 | case VGLOBAL: { |
| 277 | e->u.i.info = luaK_codeABc(fs, OP_GETGLOBAL, 0, e->u.i.info); | 282 | e->u.i.info = luaK_codeABc(fs, OP_GETGLOBAL, 0, e->u.i.info); |
| 278 | e->k = VRELOCABLE; | 283 | e->k = VRELOCABLE; |
| @@ -437,6 +442,12 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) { | |||
| 437 | luaK_exp2reg(fs, exp, var->u.i.info); | 442 | luaK_exp2reg(fs, exp, var->u.i.info); |
| 438 | break; | 443 | break; |
| 439 | } | 444 | } |
| 445 | case VUPVAL: { | ||
| 446 | int e = luaK_exp2anyreg(fs, exp); | ||
| 447 | freereg(fs, e); | ||
| 448 | luaK_codeABC(fs, OP_SETUPVAL, e, var->u.i.info, 0); | ||
| 449 | break; | ||
| 450 | } | ||
| 440 | case VGLOBAL: { | 451 | case VGLOBAL: { |
| 441 | int e = luaK_exp2anyreg(fs, exp); | 452 | int e = luaK_exp2anyreg(fs, exp); |
| 442 | freereg(fs, e); | 453 | freereg(fs, e); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldebug.c,v 1.86 2001/06/28 19:58:57 roberto Exp roberto $ | 2 | ** $Id: ldebug.c,v 1.87 2001/07/03 17:01:34 roberto Exp $ |
| 3 | ** Debug Interface | 3 | ** Debug Interface |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -117,7 +117,7 @@ int luaG_getline (int *lineinfo, int pc, int refline, int *prefi) { | |||
| 117 | static int currentpc (CallInfo *ci) { | 117 | static int currentpc (CallInfo *ci) { |
| 118 | lua_assert(isLmark(ci)); | 118 | lua_assert(isLmark(ci)); |
| 119 | if (ci->pc) | 119 | if (ci->pc) |
| 120 | return (*ci->pc - ci_func(ci)->f.l->code) - 1; | 120 | return (*ci->pc - ci_func(ci)->u.l.p->code) - 1; |
| 121 | else | 121 | else |
| 122 | return -1; /* function is not active */ | 122 | return -1; /* function is not active */ |
| 123 | } | 123 | } |
| @@ -127,7 +127,7 @@ static int currentline (CallInfo *ci) { | |||
| 127 | if (!isLmark(ci)) | 127 | if (!isLmark(ci)) |
| 128 | return -1; /* only active lua functions have current-line information */ | 128 | return -1; /* only active lua functions have current-line information */ |
| 129 | else { | 129 | else { |
| 130 | int *lineinfo = ci_func(ci)->f.l->lineinfo; | 130 | int *lineinfo = ci_func(ci)->u.l.p->lineinfo; |
| 131 | return luaG_getline(lineinfo, currentpc(ci), 1, NULL); | 131 | return luaG_getline(lineinfo, currentpc(ci), 1, NULL); |
| 132 | } | 132 | } |
| 133 | } | 133 | } |
| @@ -135,7 +135,7 @@ static int currentline (CallInfo *ci) { | |||
| 135 | 135 | ||
| 136 | 136 | ||
| 137 | static Proto *getluaproto (CallInfo *ci) { | 137 | static Proto *getluaproto (CallInfo *ci) { |
| 138 | return (isLmark(ci) ? ci_func(ci)->f.l : NULL); | 138 | return (isLmark(ci) ? ci_func(ci)->u.l.p : NULL); |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | 141 | ||
| @@ -199,7 +199,7 @@ static void funcinfo (lua_State *L, lua_Debug *ar, StkId func) { | |||
| 199 | ar->what = l_s("C"); | 199 | ar->what = l_s("C"); |
| 200 | } | 200 | } |
| 201 | else | 201 | else |
| 202 | infoLproto(ar, cl->f.l); | 202 | infoLproto(ar, cl->u.l.p); |
| 203 | luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); | 203 | luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); |
| 204 | if (ar->linedefined == 0) | 204 | if (ar->linedefined == 0) |
| 205 | ar->what = l_s("main"); | 205 | ar->what = l_s("main"); |
| @@ -323,14 +323,15 @@ static int precheck (const Proto *pt) { | |||
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | 325 | ||
| 326 | static int checkopenop (Instruction i) { | 326 | static int checkopenop (const Proto *pt, int pc) { |
| 327 | OpCode op = GET_OPCODE(i); | 327 | Instruction i = pt->code[pc+1]; |
| 328 | switch (op) { | 328 | switch (GET_OPCODE(i)) { |
| 329 | case OP_CALL: | 329 | case OP_CALL: |
| 330 | case OP_RETURN: { | 330 | case OP_RETURN: { |
| 331 | check(GETARG_B(i) == NO_REG); | 331 | check(GETARG_B(i) == NO_REG); |
| 332 | return 1; | 332 | return 1; |
| 333 | } | 333 | } |
| 334 | case OP_CLOSE: return checkopenop(pt, pc+1); | ||
| 334 | case OP_SETLISTO: return 1; | 335 | case OP_SETLISTO: return 1; |
| 335 | default: return 0; /* invalid instruction after an open call */ | 336 | default: return 0; /* invalid instruction after an open call */ |
| 336 | } | 337 | } |
| @@ -382,7 +383,8 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { | |||
| 382 | last = pc; /* set registers from `a' to `b' */ | 383 | last = pc; /* set registers from `a' to `b' */ |
| 383 | break; | 384 | break; |
| 384 | } | 385 | } |
| 385 | case OP_LOADUPVAL: { | 386 | case OP_GETUPVAL: |
| 387 | case OP_SETUPVAL: { | ||
| 386 | check(b < pt->nupvalues); | 388 | check(b < pt->nupvalues); |
| 387 | break; | 389 | break; |
| 388 | } | 390 | } |
| @@ -419,7 +421,7 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { | |||
| 419 | checkreg(pt, a+b); | 421 | checkreg(pt, a+b); |
| 420 | } | 422 | } |
| 421 | if (c == NO_REG) { | 423 | if (c == NO_REG) { |
| 422 | check(checkopenop(pt->code[pc+1])); | 424 | check(checkopenop(pt, pc)); |
| 423 | } | 425 | } |
| 424 | else if (c != 0) | 426 | else if (c != 0) |
| 425 | checkreg(pt, a+c-1); | 427 | checkreg(pt, a+c-1); |
| @@ -452,7 +454,7 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { | |||
| 452 | } | 454 | } |
| 453 | case OP_CLOSURE: { | 455 | case OP_CLOSURE: { |
| 454 | check(b < pt->sizep); | 456 | check(b < pt->sizep); |
| 455 | checkreg(pt, a + pt->p[b]->nupvalues - 1); | 457 | check(pc + pt->p[b]->nupvalues < pt->sizecode); |
| 456 | break; | 458 | break; |
| 457 | } | 459 | } |
| 458 | default: break; | 460 | default: break; |
| @@ -472,7 +474,7 @@ int luaG_checkcode (const Proto *pt) { | |||
| 472 | static const l_char *getobjname (lua_State *L, StkId obj, const l_char **name) { | 474 | static const l_char *getobjname (lua_State *L, StkId obj, const l_char **name) { |
| 473 | CallInfo *ci = ci_stack(L, obj); | 475 | CallInfo *ci = ci_stack(L, obj); |
| 474 | if (isLmark(ci)) { /* an active Lua function? */ | 476 | if (isLmark(ci)) { /* an active Lua function? */ |
| 475 | Proto *p = ci_func(ci)->f.l; | 477 | Proto *p = ci_func(ci)->u.l.p; |
| 476 | int pc = currentpc(ci); | 478 | int pc = currentpc(ci); |
| 477 | int stackpos = obj - ci->base; | 479 | int stackpos = obj - ci->base; |
| 478 | Instruction i; | 480 | Instruction i; |
| @@ -516,7 +518,7 @@ static const l_char *getfuncname (lua_State *L, CallInfo *ci, | |||
| 516 | if (ci == &L->basefunc || !isLmark(ci)) | 518 | if (ci == &L->basefunc || !isLmark(ci)) |
| 517 | return NULL; /* not an active Lua function */ | 519 | return NULL; /* not an active Lua function */ |
| 518 | else { | 520 | else { |
| 519 | Proto *p = ci_func(ci)->f.l; | 521 | Proto *p = ci_func(ci)->u.l.p; |
| 520 | int pc = currentpc(ci); | 522 | int pc = currentpc(ci); |
| 521 | Instruction i; | 523 | Instruction i; |
| 522 | if (pc == -1) return NULL; /* function is not activated */ | 524 | if (pc == -1) return NULL; /* function is not activated */ |
| @@ -15,6 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | #include "ldebug.h" | 16 | #include "ldebug.h" |
| 17 | #include "ldo.h" | 17 | #include "ldo.h" |
| 18 | #include "lfunc.h" | ||
| 18 | #include "lgc.h" | 19 | #include "lgc.h" |
| 19 | #include "lmem.h" | 20 | #include "lmem.h" |
| 20 | #include "lobject.h" | 21 | #include "lobject.h" |
| @@ -122,9 +123,9 @@ static StkId callCclosure (lua_State *L, const struct Closure *cl) { | |||
| 122 | int n; | 123 | int n; |
| 123 | luaD_checkstack(L, nup+LUA_MINSTACK); /* ensure minimum stack size */ | 124 | luaD_checkstack(L, nup+LUA_MINSTACK); /* ensure minimum stack size */ |
| 124 | for (n=0; n<nup; n++) /* copy upvalues as extra arguments */ | 125 | for (n=0; n<nup; n++) /* copy upvalues as extra arguments */ |
| 125 | setobj(L->top++, &cl->upvalue[n]); | 126 | setobj(L->top++, &cl->u.c.upvalue[n]); |
| 126 | lua_unlock(L); | 127 | lua_unlock(L); |
| 127 | n = (*cl->f.c)(L); /* do the actual call */ | 128 | n = (*cl->u.c.f)(L); /* do the actual call */ |
| 128 | lua_lock(L); | 129 | lua_lock(L); |
| 129 | return L->top - n; /* return index of first result */ | 130 | return L->top - n; /* return index of first result */ |
| 130 | } | 131 | } |
| @@ -209,7 +210,12 @@ struct SParser { /* data to `f_parser' */ | |||
| 209 | static void f_parser (lua_State *L, void *ud) { | 210 | static void f_parser (lua_State *L, void *ud) { |
| 210 | struct SParser *p = cast(struct SParser *, ud); | 211 | struct SParser *p = cast(struct SParser *, ud); |
| 211 | Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z); | 212 | Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z); |
| 212 | luaV_Lclosure(L, tf, 0); | 213 | Closure *cl = luaF_newLclosure(L, 0); |
| 214 | cl->u.l.p = tf; | ||
| 215 | luaF_LConlist(L, cl); | ||
| 216 | setclvalue(L->top, cl); | ||
| 217 | incr_top; | ||
| 218 | |||
| 213 | } | 219 | } |
| 214 | 220 | ||
| 215 | 221 | ||
| @@ -286,6 +292,9 @@ struct lua_longjmp { | |||
| 286 | jmp_buf b; | 292 | jmp_buf b; |
| 287 | struct lua_longjmp *previous; | 293 | struct lua_longjmp *previous; |
| 288 | volatile int status; /* error code */ | 294 | volatile int status; /* error code */ |
| 295 | CallInfo *ci; /* call info of active function that set protection */ | ||
| 296 | StkId top; /* top stack when protection was set */ | ||
| 297 | int allowhooks; /* `allowhook' state when protection was set */ | ||
| 289 | }; | 298 | }; |
| 290 | 299 | ||
| 291 | 300 | ||
| @@ -325,19 +334,20 @@ void luaD_breakrun (lua_State *L, int errcode) { | |||
| 325 | 334 | ||
| 326 | 335 | ||
| 327 | int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { | 336 | int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { |
| 328 | CallInfo *oldci = L->ci; | ||
| 329 | StkId oldtop = L->top; | ||
| 330 | struct lua_longjmp lj; | 337 | struct lua_longjmp lj; |
| 331 | int allowhooks = L->allowhooks; | 338 | lj.ci = L->ci; |
| 339 | lj.top = L->top; | ||
| 340 | lj.allowhooks = L->allowhooks; | ||
| 332 | lj.status = 0; | 341 | lj.status = 0; |
| 333 | lj.previous = L->errorJmp; /* chain new error handler */ | 342 | lj.previous = L->errorJmp; /* chain new error handler */ |
| 334 | L->errorJmp = &lj; | 343 | L->errorJmp = &lj; |
| 335 | if (setjmp(lj.b) == 0) | 344 | if (setjmp(lj.b) == 0) |
| 336 | (*f)(L, ud); | 345 | (*f)(L, ud); |
| 337 | else { /* an error occurred: restore the state */ | 346 | else { /* an error occurred: restore the state */ |
| 338 | L->allowhooks = allowhooks; | 347 | luaF_close(L, lj.top); /* close eventual pending closures */ |
| 339 | L->ci = oldci; | 348 | L->ci = lj.ci; |
| 340 | L->top = oldtop; | 349 | L->top = lj.top; |
| 350 | L->allowhooks = lj.allowhooks; | ||
| 341 | restore_stack_limit(L); | 351 | restore_stack_limit(L); |
| 342 | } | 352 | } |
| 343 | L->errorJmp = lj.previous; /* restore old error handler */ | 353 | L->errorJmp = lj.previous; /* restore old error handler */ |
| @@ -12,15 +12,20 @@ | |||
| 12 | 12 | ||
| 13 | #include "lfunc.h" | 13 | #include "lfunc.h" |
| 14 | #include "lmem.h" | 14 | #include "lmem.h" |
| 15 | #include "lobject.h" | ||
| 15 | #include "lstate.h" | 16 | #include "lstate.h" |
| 16 | 17 | ||
| 17 | 18 | ||
| 18 | #define sizeclosure(n) (cast(int, sizeof(Closure)) + \ | 19 | #define sizeCclosure(n) (cast(int, sizeof(Closure)) + \ |
| 19 | cast(int, sizeof(TObject)*((n)-1))) | 20 | cast(int, sizeof(TObject)*((n)-1))) |
| 20 | 21 | ||
| 22 | #define sizeLclosure(n) (cast(int, sizeof(Closure)) + \ | ||
| 23 | cast(int, sizeof(TObject *)*((n)-1))) | ||
| 21 | 24 | ||
| 22 | Closure *luaF_newclosure (lua_State *L, int nelems) { | 25 | |
| 23 | Closure *c = cast(Closure *, luaM_malloc(L, sizeclosure(nelems))); | 26 | Closure *luaF_newCclosure (lua_State *L, int nelems) { |
| 27 | Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); | ||
| 28 | c->isC = 1; | ||
| 24 | c->next = G(L)->rootcl; | 29 | c->next = G(L)->rootcl; |
| 25 | G(L)->rootcl = c; | 30 | G(L)->rootcl = c; |
| 26 | c->mark = c; | 31 | c->mark = c; |
| @@ -29,6 +34,90 @@ Closure *luaF_newclosure (lua_State *L, int nelems) { | |||
| 29 | } | 34 | } |
| 30 | 35 | ||
| 31 | 36 | ||
| 37 | Closure *luaF_newLclosure (lua_State *L, int nelems) { | ||
| 38 | Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); | ||
| 39 | c->isC = 0; | ||
| 40 | c->mark = c; | ||
| 41 | c->u.l.isopen = 0; | ||
| 42 | c->nupvalues = nelems; | ||
| 43 | return c; | ||
| 44 | } | ||
| 45 | |||
| 46 | |||
| 47 | /* | ||
| 48 | ** returns the open pointer in a closure that points higher into the stack | ||
| 49 | */ | ||
| 50 | static StkId uppoint (Closure *cl) { | ||
| 51 | StkId lp = NULL; | ||
| 52 | int i; | ||
| 53 | lua_assert(cl->u.l.isopen); | ||
| 54 | for (i=0; i<cl->nupvalues; i++) { | ||
| 55 | if (!luaF_isclosed(cl, i)) | ||
| 56 | if (lp == NULL || cl->u.l.upvals[i] > lp) | ||
| 57 | lp = cl->u.l.upvals[i]; | ||
| 58 | } | ||
| 59 | lua_assert(lp != NULL); | ||
| 60 | return lp; | ||
| 61 | } | ||
| 62 | |||
| 63 | |||
| 64 | void luaF_LConlist (lua_State *L, Closure *cl) { | ||
| 65 | lua_assert(!cl->isC); | ||
| 66 | if (cl->u.l.isopen == 0) { /* no more open entries? */ | ||
| 67 | cl->next = G(L)->rootcl; /* insert in final list */ | ||
| 68 | G(L)->rootcl = cl; | ||
| 69 | } | ||
| 70 | else { /* insert in list of open closures, ordered by decreasing uppoints */ | ||
| 71 | StkId cli = uppoint(cl); | ||
| 72 | Closure **p = &L->opencl; | ||
| 73 | while (*p != NULL && uppoint(*p) > cli) p = &(*p)->next; | ||
| 74 | cl->next = *p; | ||
| 75 | *p = cl; | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | |||
| 80 | static int closeCl (lua_State *L, Closure *cl, StkId level) { | ||
| 81 | int got = 0; /* flag: 1 if some pointer in the closure was corrected */ | ||
| 82 | int i; | ||
| 83 | for (i=0; i<cl->nupvalues; i++) { | ||
| 84 | StkId var; | ||
| 85 | if (!luaF_isclosed(cl, i) && (var=cl->u.l.upvals[i]) >= level) { | ||
| 86 | if (ttype(var) != LUA_TUPVAL) { | ||
| 87 | UpVal *v = luaM_new(L, UpVal); | ||
| 88 | v->val = *var; | ||
| 89 | v->marked = 0; | ||
| 90 | v->next = G(L)->rootupval; | ||
| 91 | G(L)->rootupval = v; | ||
| 92 | setupvalue(var, v); | ||
| 93 | } | ||
| 94 | cl->u.l.upvals[i] = cast(TObject *, vvalue(var)); | ||
| 95 | luaF_closeentry(cl, i); | ||
| 96 | got = 1; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | return got; | ||
| 100 | } | ||
| 101 | |||
| 102 | |||
| 103 | void luaF_close (lua_State *L, StkId level) { | ||
| 104 | Closure *affected = NULL; /* closures with open pointers >= level */ | ||
| 105 | Closure *cl; | ||
| 106 | while ((cl=L->opencl) != NULL) { | ||
| 107 | if (!closeCl(L, cl, level)) break; | ||
| 108 | /* some pointer in `cl' changed; will re-insert it in original list */ | ||
| 109 | L->opencl = cl->next; /* remove from original list */ | ||
| 110 | cl->next = affected; | ||
| 111 | affected = cl; /* insert in affected list */ | ||
| 112 | } | ||
| 113 | /* re-insert all affected closures in original list */ | ||
| 114 | while ((cl=affected) != NULL) { | ||
| 115 | affected = cl->next; | ||
| 116 | luaF_LConlist(L, cl); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | |||
| 32 | Proto *luaF_newproto (lua_State *L) { | 121 | Proto *luaF_newproto (lua_State *L) { |
| 33 | Proto *f = luaM_new(L, Proto); | 122 | Proto *f = luaM_new(L, Proto); |
| 34 | f->k = NULL; | 123 | f->k = NULL; |
| @@ -60,12 +149,13 @@ void luaF_freeproto (lua_State *L, Proto *f) { | |||
| 60 | luaM_freearray(L, f->k, f->sizek, TObject); | 149 | luaM_freearray(L, f->k, f->sizek, TObject); |
| 61 | luaM_freearray(L, f->p, f->sizep, Proto *); | 150 | luaM_freearray(L, f->p, f->sizep, Proto *); |
| 62 | luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); | 151 | luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); |
| 63 | luaM_freelem(L, f, Proto); | 152 | luaM_freelem(L, f); |
| 64 | } | 153 | } |
| 65 | 154 | ||
| 66 | 155 | ||
| 67 | void luaF_freeclosure (lua_State *L, Closure *c) { | 156 | void luaF_freeclosure (lua_State *L, Closure *c) { |
| 68 | luaM_free(L, c, sizeclosure(c->nupvalues)); | 157 | int size = (c->isC) ? sizeCclosure(c->nupvalues) : sizeLclosure(c->nupvalues); |
| 158 | luaM_free(L, c, size); | ||
| 69 | } | 159 | } |
| 70 | 160 | ||
| 71 | 161 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lfunc.h,v 1.14 2000/12/28 12:55:41 roberto Exp roberto $ | 2 | ** $Id: lfunc.h,v 1.15 2001/02/23 17:17:25 roberto Exp $ |
| 3 | ** Auxiliary functions to manipulate prototypes and closures | 3 | ** Auxiliary functions to manipulate prototypes and closures |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -11,9 +11,16 @@ | |||
| 11 | #include "lobject.h" | 11 | #include "lobject.h" |
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | #define luaF_isclosed(c, i) (!((c)->u.l.isopen & (1 << (i)))) | ||
| 15 | #define luaF_openentry(c, i) ((c)->u.l.isopen |= (1 << (i))) | ||
| 16 | #define luaF_closeentry(c, i) ((c)->u.l.isopen &= ~(1 << (i))) | ||
| 17 | |||
| 14 | 18 | ||
| 15 | Proto *luaF_newproto (lua_State *L); | 19 | Proto *luaF_newproto (lua_State *L); |
| 16 | Closure *luaF_newclosure (lua_State *L, int nelems); | 20 | Closure *luaF_newCclosure (lua_State *L, int nelems); |
| 21 | Closure *luaF_newLclosure (lua_State *L, int nelems); | ||
| 22 | void luaF_LConlist (lua_State *L, Closure *cl); | ||
| 23 | void luaF_close (lua_State *L, StkId level); | ||
| 17 | void luaF_freeproto (lua_State *L, Proto *f); | 24 | void luaF_freeproto (lua_State *L, Proto *f); |
| 18 | void luaF_freeclosure (lua_State *L, Closure *c); | 25 | void luaF_freeclosure (lua_State *L, Closure *c); |
| 19 | 26 | ||
| @@ -7,6 +7,7 @@ | |||
| 7 | #define LUA_PRIVATE | 7 | #define LUA_PRIVATE |
| 8 | #include "lua.h" | 8 | #include "lua.h" |
| 9 | 9 | ||
| 10 | #include "ldebug.h" | ||
| 10 | #include "ldo.h" | 11 | #include "ldo.h" |
| 11 | #include "lfunc.h" | 12 | #include "lfunc.h" |
| 12 | #include "lgc.h" | 13 | #include "lgc.h" |
| @@ -45,15 +46,12 @@ static void protomark (Proto *f) { | |||
| 45 | for (i=0; i<f->sizelocvars; i++) /* mark local-variable names */ | 46 | for (i=0; i<f->sizelocvars; i++) /* mark local-variable names */ |
| 46 | strmark(f->locvars[i].varname); | 47 | strmark(f->locvars[i].varname); |
| 47 | } | 48 | } |
| 49 | lua_assert(luaG_checkcode(f)); | ||
| 48 | } | 50 | } |
| 49 | 51 | ||
| 50 | 52 | ||
| 51 | static void markclosure (GCState *st, Closure *cl) { | 53 | static void markclosure (GCState *st, Closure *cl) { |
| 52 | if (!ismarked(cl)) { | 54 | if (!ismarked(cl)) { |
| 53 | if (!cl->isC) { | ||
| 54 | lua_assert(cl->nupvalues == cl->f.l->nupvalues); | ||
| 55 | protomark(cl->f.l); | ||
| 56 | } | ||
| 57 | cl->mark = st->cmark; /* chain it for later traversal */ | 55 | cl->mark = st->cmark; /* chain it for later traversal */ |
| 58 | st->cmark = cl; | 56 | st->cmark = cl; |
| 59 | } | 57 | } |
| @@ -84,7 +82,10 @@ static void markobject (GCState *st, TObject *o) { | |||
| 84 | marktable(st, hvalue(o)); | 82 | marktable(st, hvalue(o)); |
| 85 | break; | 83 | break; |
| 86 | } | 84 | } |
| 87 | default: break; /* numbers, etc */ | 85 | default: { |
| 86 | lua_assert(0 <= ttype(o) && ttype(o) <= LUA_TUPVAL); | ||
| 87 | break; | ||
| 88 | } | ||
| 88 | } | 89 | } |
| 89 | } | 90 | } |
| 90 | 91 | ||
| @@ -119,10 +120,26 @@ static void marktagmethods (global_State *G, GCState *st) { | |||
| 119 | } | 120 | } |
| 120 | 121 | ||
| 121 | 122 | ||
| 122 | static void traverseclosure (GCState *st, Closure *f) { | 123 | static void traverseclosure (GCState *st, Closure *cl) { |
| 123 | int i; | 124 | if (cl->isC) { |
| 124 | for (i=0; i<f->nupvalues; i++) /* mark its upvalues */ | 125 | int i; |
| 125 | markobject(st, &f->upvalue[i]); | 126 | for (i=0; i<cl->nupvalues; i++) /* mark its upvalues */ |
| 127 | markobject(st, &cl->u.c.upvalue[i]); | ||
| 128 | } | ||
| 129 | else { | ||
| 130 | int i; | ||
| 131 | lua_assert(cl->nupvalues == cl->u.l.p->nupvalues); | ||
| 132 | protomark(cl->u.l.p); | ||
| 133 | for (i=0; i<cl->nupvalues; i++) { /* mark its upvalues */ | ||
| 134 | if (luaF_isclosed(cl, i)) { | ||
| 135 | UpVal *u = cast(UpVal *, cl->u.l.upvals[i]); | ||
| 136 | if (!u->marked) { | ||
| 137 | u->marked = 1; | ||
| 138 | markobject(st, &u->val); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | } | ||
| 142 | } | ||
| 126 | } | 143 | } |
| 127 | 144 | ||
| 128 | 145 | ||
| @@ -164,9 +181,9 @@ static void markall (lua_State *L) { | |||
| 164 | marktable(&st, G(L)->weakregistry); | 181 | marktable(&st, G(L)->weakregistry); |
| 165 | for (;;) { /* mark tables and closures */ | 182 | for (;;) { /* mark tables and closures */ |
| 166 | if (st.cmark) { | 183 | if (st.cmark) { |
| 167 | Closure *f = st.cmark; /* get first closure from list */ | 184 | Closure *cl = st.cmark; /* get first closure from list */ |
| 168 | st.cmark = f->mark; /* remove it from list */ | 185 | st.cmark = cl->mark; /* remove it from list */ |
| 169 | traverseclosure(&st, f); | 186 | traverseclosure(&st, cl); |
| 170 | } | 187 | } |
| 171 | else if (st.tmark) { | 188 | else if (st.tmark) { |
| 172 | Hash *h = st.tmark; /* get first table from list */ | 189 | Hash *h = st.tmark; /* get first table from list */ |
| @@ -232,8 +249,7 @@ static void collectproto (lua_State *L) { | |||
| 232 | } | 249 | } |
| 233 | 250 | ||
| 234 | 251 | ||
| 235 | static void collectclosure (lua_State *L) { | 252 | static void collectclosure (lua_State *L, Closure **p) { |
| 236 | Closure **p = &G(L)->rootcl; | ||
| 237 | Closure *curr; | 253 | Closure *curr; |
| 238 | while ((curr = *p) != NULL) { | 254 | while ((curr = *p) != NULL) { |
| 239 | if (ismarked(curr)) { | 255 | if (ismarked(curr)) { |
| @@ -248,6 +264,16 @@ static void collectclosure (lua_State *L) { | |||
| 248 | } | 264 | } |
| 249 | 265 | ||
| 250 | 266 | ||
| 267 | static void collectclosures (lua_State *L) { | ||
| 268 | lua_State *L1 = L; | ||
| 269 | do { /* for each thread */ | ||
| 270 | collectclosure(L1, &L1->opencl); | ||
| 271 | L1 = L1->next; | ||
| 272 | } while (L1 != L); | ||
| 273 | collectclosure(L, &G(L)->rootcl); | ||
| 274 | } | ||
| 275 | |||
| 276 | |||
| 251 | static void collecttable (lua_State *L) { | 277 | static void collecttable (lua_State *L) { |
| 252 | Hash **p = &G(L)->roottable; | 278 | Hash **p = &G(L)->roottable; |
| 253 | Hash *curr; | 279 | Hash *curr; |
| @@ -264,6 +290,22 @@ static void collecttable (lua_State *L) { | |||
| 264 | } | 290 | } |
| 265 | 291 | ||
| 266 | 292 | ||
| 293 | static void collectupval (lua_State *L) { | ||
| 294 | UpVal **v = &G(L)->rootupval; | ||
| 295 | UpVal *curr; | ||
| 296 | while ((curr = *v) != NULL) { | ||
| 297 | if (curr->marked) { | ||
| 298 | curr->marked = 0; | ||
| 299 | v = &curr->next; | ||
| 300 | } | ||
| 301 | else { | ||
| 302 | *v = curr->next; | ||
| 303 | luaM_freelem(L, curr); | ||
| 304 | } | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 308 | |||
| 267 | static void collectudata (lua_State *L, int keep) { | 309 | static void collectudata (lua_State *L, int keep) { |
| 268 | Udata **p = &G(L)->rootudata; | 310 | Udata **p = &G(L)->rootudata; |
| 269 | Udata *curr; | 311 | Udata *curr; |
| @@ -370,7 +412,8 @@ void luaC_collect (lua_State *L, int all) { | |||
| 370 | collectstrings(L, all); | 412 | collectstrings(L, all); |
| 371 | collecttable(L); | 413 | collecttable(L); |
| 372 | collectproto(L); | 414 | collectproto(L); |
| 373 | collectclosure(L); | 415 | collectupval(L); |
| 416 | collectclosures(L); | ||
| 374 | } | 417 | } |
| 375 | 418 | ||
| 376 | 419 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: llimits.h,v 1.30 2001/06/05 20:01:09 roberto Exp roberto $ | 2 | ** $Id: llimits.h,v 1.31 2001/08/27 15:16:28 roberto Exp $ |
| 3 | ** Limits, basic types, and some other `installation-dependent' definitions | 3 | ** Limits, basic types, and some other `installation-dependent' definitions |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -51,6 +51,9 @@ typedef unsigned long lu_mem; | |||
| 51 | /* an integer big enough to count the number of strings in use */ | 51 | /* an integer big enough to count the number of strings in use */ |
| 52 | typedef long ls_nstr; | 52 | typedef long ls_nstr; |
| 53 | 53 | ||
| 54 | /* a bitmap with one bit for each upvalue used by a function */ | ||
| 55 | typedef unsigned long ls_bitup; | ||
| 56 | |||
| 54 | 57 | ||
| 55 | /* chars used as small naturals (so that `char' is reserved for characteres) */ | 58 | /* chars used as small naturals (so that `char' is reserved for characteres) */ |
| 56 | typedef unsigned char lu_byte; | 59 | typedef unsigned char lu_byte; |
| @@ -108,7 +111,7 @@ typedef unsigned long Instruction; | |||
| 108 | 111 | ||
| 109 | /* maximum number of upvalues */ | 112 | /* maximum number of upvalues */ |
| 110 | #ifndef MAXUPVALUES | 113 | #ifndef MAXUPVALUES |
| 111 | #define MAXUPVALUES 32 /* arbitrary limit (<MAXSTACK) */ | 114 | #define MAXUPVALUES (sizeof(ls_bitup)*CHAR_BIT) |
| 112 | #endif | 115 | #endif |
| 113 | 116 | ||
| 114 | 117 | ||
| @@ -27,15 +27,20 @@ | |||
| 27 | #endif | 27 | #endif |
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | /* tags for values visible from Lua == first user-created tag */ | 30 | /* tags for values visible from Lua */ |
| 31 | #define NUM_TAGS 6 | 31 | #define NUM_TAGS 6 |
| 32 | 32 | ||
| 33 | 33 | ||
| 34 | /* extra tag: used locally when moving an upvalue from the stack to the heap */ | ||
| 35 | #define LUA_TUPVAL 6 | ||
| 36 | |||
| 37 | |||
| 34 | typedef union { | 38 | typedef union { |
| 35 | union TString *ts; | 39 | union TString *ts; |
| 36 | union Udata *u; | 40 | union Udata *u; |
| 37 | struct Closure *cl; | 41 | struct Closure *cl; |
| 38 | struct Hash *h; | 42 | struct Hash *h; |
| 43 | struct UpVal *v; | ||
| 39 | lua_Number n; /* LUA_TNUMBER */ | 44 | lua_Number n; /* LUA_TNUMBER */ |
| 40 | } Value; | 45 | } Value; |
| 41 | 46 | ||
| @@ -53,6 +58,7 @@ typedef struct lua_TObject { | |||
| 53 | #define uvalue(o) ((o)->value.u) | 58 | #define uvalue(o) ((o)->value.u) |
| 54 | #define clvalue(o) ((o)->value.cl) | 59 | #define clvalue(o) ((o)->value.cl) |
| 55 | #define hvalue(o) ((o)->value.h) | 60 | #define hvalue(o) ((o)->value.h) |
| 61 | #define vvalue(o) ((o)->value.v) | ||
| 56 | 62 | ||
| 57 | 63 | ||
| 58 | /* Macros to set values */ | 64 | /* Macros to set values */ |
| @@ -75,6 +81,9 @@ typedef struct lua_TObject { | |||
| 75 | 81 | ||
| 76 | #define setnilvalue(obj) ((obj)->tt=LUA_TNIL) | 82 | #define setnilvalue(obj) ((obj)->tt=LUA_TNIL) |
| 77 | 83 | ||
| 84 | #define setupvalue(obj,x) \ | ||
| 85 | { TObject *_o=(obj); _o->tt=LUA_TUPVAL; _o->value.v=(x); } | ||
| 86 | |||
| 78 | #define setobj(obj1,obj2) \ | 87 | #define setobj(obj1,obj2) \ |
| 79 | { TObject *o1=(obj1); const TObject *o2=(obj2); \ | 88 | { TObject *o1=(obj1); const TObject *o2=(obj2); \ |
| 80 | o1->tt=o2->tt; o1->value = o2->value; } | 89 | o1->tt=o2->tt; o1->value = o2->value; } |
| @@ -154,25 +163,48 @@ typedef struct LocVar { | |||
| 154 | } LocVar; | 163 | } LocVar; |
| 155 | 164 | ||
| 156 | 165 | ||
| 166 | |||
| 167 | /* | ||
| 168 | ** Upvalues in the heap | ||
| 169 | */ | ||
| 170 | typedef struct UpVal { | ||
| 171 | TObject val; | ||
| 172 | struct UpVal *next; | ||
| 173 | int marked; | ||
| 174 | } UpVal; | ||
| 175 | |||
| 176 | |||
| 157 | /* | 177 | /* |
| 158 | ** Closures | 178 | ** Closures |
| 159 | */ | 179 | */ |
| 160 | typedef struct Closure { | 180 | typedef struct Closure { |
| 161 | int isC; /* 0 for Lua functions, 1 for C functions */ | 181 | int isC; /* 0 for Lua functions, 1 for C functions */ |
| 162 | int nupvalues; | 182 | int nupvalues; |
| 163 | union { | ||
| 164 | lua_CFunction c; /* C functions */ | ||
| 165 | struct Proto *l; /* Lua functions */ | ||
| 166 | } f; | ||
| 167 | struct Closure *next; | 183 | struct Closure *next; |
| 168 | struct Closure *mark; /* marked closures (point to itself when not marked) */ | 184 | struct Closure *mark; /* marked closures (point to itself when not marked) */ |
| 169 | TObject upvalue[1]; | 185 | union { |
| 186 | struct { /* C functions */ | ||
| 187 | lua_CFunction f; | ||
| 188 | TObject upvalue[1]; | ||
| 189 | } c; | ||
| 190 | struct { /* Lua functions */ | ||
| 191 | struct Proto *p; | ||
| 192 | ls_bitup isopen; /* bitmap: bit==1 when upvals point to the stack */ | ||
| 193 | TObject *upvals[1]; /* may point to the stack or to an UpVal */ | ||
| 194 | } l; | ||
| 195 | } u; | ||
| 170 | } Closure; | 196 | } Closure; |
| 171 | 197 | ||
| 172 | 198 | ||
| 173 | #define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->isC) | 199 | #define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->isC) |
| 174 | 200 | ||
| 175 | 201 | ||
| 202 | |||
| 203 | |||
| 204 | /* | ||
| 205 | ** Hash Tables | ||
| 206 | */ | ||
| 207 | |||
| 176 | typedef struct Node { | 208 | typedef struct Node { |
| 177 | struct Node *next; /* for chaining */ | 209 | struct Node *next; /* for chaining */ |
| 178 | TObject key; | 210 | TObject key; |
| @@ -20,10 +20,11 @@ const l_char *const luaP_opnames[] = { | |||
| 20 | l_s("LOADK"), | 20 | l_s("LOADK"), |
| 21 | l_s("LOADINT"), | 21 | l_s("LOADINT"), |
| 22 | l_s("LOADNIL"), | 22 | l_s("LOADNIL"), |
| 23 | l_s("LOADUPVAL"), | 23 | l_s("GETUPVAL"), |
| 24 | l_s("GETGLOBAL"), | 24 | l_s("GETGLOBAL"), |
| 25 | l_s("GETTABLE"), | 25 | l_s("GETTABLE"), |
| 26 | l_s("SETGLOBAL"), | 26 | l_s("SETGLOBAL"), |
| 27 | l_s("SETUPVAL"), | ||
| 27 | l_s("SETTABLE"), | 28 | l_s("SETTABLE"), |
| 28 | l_s("NEWTABLE"), | 29 | l_s("NEWTABLE"), |
| 29 | l_s("SELF"), | 30 | l_s("SELF"), |
| @@ -54,6 +55,7 @@ const l_char *const luaP_opnames[] = { | |||
| 54 | l_s("TFORLOOP"), | 55 | l_s("TFORLOOP"), |
| 55 | l_s("SETLIST"), | 56 | l_s("SETLIST"), |
| 56 | l_s("SETLISTO"), | 57 | l_s("SETLISTO"), |
| 58 | l_s("CLOSE"), | ||
| 57 | l_s("CLOSURE") | 59 | l_s("CLOSURE") |
| 58 | }; | 60 | }; |
| 59 | 61 | ||
| @@ -69,10 +71,11 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
| 69 | ,opmode(0,0,0,0, 1,1,iABc) /* OP_LOADK */ | 71 | ,opmode(0,0,0,0, 1,1,iABc) /* OP_LOADK */ |
| 70 | ,opmode(0,0,0,0, 1,0,iAsBc) /* OP_LOADINT */ | 72 | ,opmode(0,0,0,0, 1,0,iAsBc) /* OP_LOADINT */ |
| 71 | ,opmode(0,0,1,0, 1,0,iABC) /* OP_LOADNIL */ | 73 | ,opmode(0,0,1,0, 1,0,iABC) /* OP_LOADNIL */ |
| 72 | ,opmode(0,0,0,0, 1,0,iABc) /* OP_LOADUPVAL */ | 74 | ,opmode(0,0,0,0, 1,0,iABC) /* OP_GETUPVAL */ |
| 73 | ,opmode(0,0,0,0, 1,1,iABc) /* OP_GETGLOBAL */ | 75 | ,opmode(0,0,0,0, 1,1,iABc) /* OP_GETGLOBAL */ |
| 74 | ,opmode(0,0,1,1, 1,0,iABC) /* OP_GETTABLE */ | 76 | ,opmode(0,0,1,1, 1,0,iABC) /* OP_GETTABLE */ |
| 75 | ,opmode(0,0,0,0, 0,1,iABc) /* OP_SETGLOBAL */ | 77 | ,opmode(0,0,0,0, 0,1,iABc) /* OP_SETGLOBAL */ |
| 78 | ,opmode(0,0,0,0, 0,0,iABC) /* OP_SETUPVAL */ | ||
| 76 | ,opmode(0,0,1,1, 0,0,iABC) /* OP_SETTABLE */ | 79 | ,opmode(0,0,1,1, 0,0,iABC) /* OP_SETTABLE */ |
| 77 | ,opmode(0,0,0,0, 1,0,iABc) /* OP_NEWTABLE */ | 80 | ,opmode(0,0,0,0, 1,0,iABc) /* OP_NEWTABLE */ |
| 78 | ,opmode(0,0,1,1, 1,0,iABC) /* OP_SELF */ | 81 | ,opmode(0,0,1,1, 1,0,iABC) /* OP_SELF */ |
| @@ -103,6 +106,7 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
| 103 | ,opmode(0,0,0,0, 0,0,iAsBc) /* OP_TFORLOOP */ | 106 | ,opmode(0,0,0,0, 0,0,iAsBc) /* OP_TFORLOOP */ |
| 104 | ,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLIST */ | 107 | ,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLIST */ |
| 105 | ,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLISTO */ | 108 | ,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLISTO */ |
| 109 | ,opmode(0,0,0,0, 0,0,iABC) /* OP_CLOSE */ | ||
| 106 | ,opmode(0,0,0,0, 1,0,iABc) /* OP_CLOSURE */ | 110 | ,opmode(0,0,0,0, 1,0,iABc) /* OP_CLOSURE */ |
| 107 | }; | 111 | }; |
| 108 | 112 | ||
| @@ -131,12 +131,13 @@ OP_MOVE,/* A B R(A) := R(B) */ | |||
| 131 | OP_LOADK,/* A Bc R(A) := Kst(Bc) */ | 131 | OP_LOADK,/* A Bc R(A) := Kst(Bc) */ |
| 132 | OP_LOADINT,/* A sBc R(A) := (Number)sBc */ | 132 | OP_LOADINT,/* A sBc R(A) := (Number)sBc */ |
| 133 | OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */ | 133 | OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */ |
| 134 | OP_LOADUPVAL,/* A Bc R(A) := UpValue[Bc] */ | 134 | OP_GETUPVAL,/* A B R(A) := UpValue[B] */ |
| 135 | 135 | ||
| 136 | OP_GETGLOBAL,/* A Bc R(A) := Gbl[Kst(Bc)] */ | 136 | OP_GETGLOBAL,/* A Bc R(A) := Gbl[Kst(Bc)] */ |
| 137 | OP_GETTABLE,/* A B C R(A) := R(B)[R/K(C)] */ | 137 | OP_GETTABLE,/* A B C R(A) := R(B)[R/K(C)] */ |
| 138 | 138 | ||
| 139 | OP_SETGLOBAL,/* A Bc Gbl[Kst(Bc)] := R(A) */ | 139 | OP_SETGLOBAL,/* A Bc Gbl[Kst(Bc)] := R(A) */ |
| 140 | OP_SETUPVAL,/* A B UpValue[B] := R(A) */ | ||
| 140 | OP_SETTABLE,/* A B C R(B)[R/K(C)] := R(A) */ | 141 | OP_SETTABLE,/* A B C R(B)[R/K(C)] := R(A) */ |
| 141 | 142 | ||
| 142 | OP_NEWTABLE,/* A Bc R(A) := {} (size = Bc) */ | 143 | OP_NEWTABLE,/* A Bc R(A) := {} (size = Bc) */ |
| @@ -180,6 +181,7 @@ OP_TFORLOOP,/* A sBc */ | |||
| 180 | OP_SETLIST,/* A Bc R(A)[Bc-Bc%FPF+i] := R(A+i), 1 <= i <= Bc%FPF+1 */ | 181 | OP_SETLIST,/* A Bc R(A)[Bc-Bc%FPF+i] := R(A+i), 1 <= i <= Bc%FPF+1 */ |
| 181 | OP_SETLISTO,/* A Bc */ | 182 | OP_SETLISTO,/* A Bc */ |
| 182 | 183 | ||
| 184 | OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/ | ||
| 183 | OP_CLOSURE /* A Bc R(A) := closure(KPROTO[Bc], R(A), ... ,R(A+n)) */ | 185 | OP_CLOSURE /* A Bc R(A) := closure(KPROTO[Bc], R(A), ... ,R(A+n)) */ |
| 184 | } OpCode; | 186 | } OpCode; |
| 185 | 187 | ||
| @@ -41,6 +41,7 @@ typedef struct Constdesc { | |||
| 41 | typedef struct Breaklabel { | 41 | typedef struct Breaklabel { |
| 42 | struct Breaklabel *previous; /* chain */ | 42 | struct Breaklabel *previous; /* chain */ |
| 43 | int breaklist; /* list of jumps out of this loop */ | 43 | int breaklist; /* list of jumps out of this loop */ |
| 44 | int nactloc; /* # of active local variables outside the breakable structure */ | ||
| 44 | } Breaklabel; | 45 | } Breaklabel; |
| 45 | 46 | ||
| 46 | 47 | ||
| @@ -163,13 +164,29 @@ static void new_localvar (LexState *ls, TString *name, int n) { | |||
| 163 | 164 | ||
| 164 | static void adjustlocalvars (LexState *ls, int nvars) { | 165 | static void adjustlocalvars (LexState *ls, int nvars) { |
| 165 | FuncState *fs = ls->fs; | 166 | FuncState *fs = ls->fs; |
| 166 | while (nvars--) | 167 | while (nvars--) { |
| 167 | fs->f->locvars[fs->actloc[fs->nactloc++]].startpc = fs->pc; | 168 | fs->f->locvars[fs->actloc[fs->nactloc]].startpc = fs->pc; |
| 169 | resetbit(fs->wasup, fs->nactloc); | ||
| 170 | fs->nactloc++; | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 174 | |||
| 175 | static void closelevel (LexState *ls, int level) { | ||
| 176 | FuncState *fs = ls->fs; | ||
| 177 | int i; | ||
| 178 | for (i=level; i<fs->nactloc; i++) | ||
| 179 | if (testbit(fs->wasup, i)) { | ||
| 180 | luaK_codeABC(fs, OP_CLOSE, level, 0, 0); | ||
| 181 | return; | ||
| 182 | } | ||
| 183 | return; /* nothing to close */ | ||
| 168 | } | 184 | } |
| 169 | 185 | ||
| 170 | 186 | ||
| 171 | static void removelocalvars (LexState *ls, int nvars) { | 187 | static void removelocalvars (LexState *ls, int nvars) { |
| 172 | FuncState *fs = ls->fs; | 188 | FuncState *fs = ls->fs; |
| 189 | closelevel(ls, fs->nactloc - nvars); | ||
| 173 | while (nvars--) | 190 | while (nvars--) |
| 174 | fs->f->locvars[fs->actloc[--fs->nactloc]].endpc = fs->pc; | 191 | fs->f->locvars[fs->actloc[--fs->nactloc]].endpc = fs->pc; |
| 175 | } | 192 | } |
| @@ -180,68 +197,47 @@ static void new_localvarstr (LexState *ls, const l_char *name, int n) { | |||
| 180 | } | 197 | } |
| 181 | 198 | ||
| 182 | 199 | ||
| 183 | static int search_local (LexState *ls, TString *n, expdesc *var) { | 200 | static int indexupvalue (FuncState *fs, expdesc *v) { |
| 184 | FuncState *fs; | ||
| 185 | int level = 0; | ||
| 186 | for (fs=ls->fs; fs; fs=fs->prev) { | ||
| 187 | int i; | ||
| 188 | for (i=fs->nactloc-1; i >= 0; i--) { | ||
| 189 | if (n == fs->f->locvars[fs->actloc[i]].varname) { | ||
| 190 | init_exp(var, VLOCAL, i); | ||
| 191 | return level; | ||
| 192 | } | ||
| 193 | } | ||
| 194 | level++; /* `var' not found; check outer level */ | ||
| 195 | } | ||
| 196 | init_exp(var, VGLOBAL, 0); /* not found in any level; must be global */ | ||
| 197 | return -1; | ||
| 198 | } | ||
| 199 | |||
| 200 | |||
| 201 | static void singlevar (LexState *ls, TString *n, expdesc *var) { | ||
| 202 | int level = search_local(ls, n, var); | ||
| 203 | if (level >= 1) /* neither local (0) nor global (-1)? */ | ||
| 204 | luaX_syntaxerror(ls, l_s("cannot access a variable in outer function"), | ||
| 205 | getstr(n)); | ||
| 206 | else if (level == -1) /* global? */ | ||
| 207 | var->u.i.info = luaK_stringk(ls->fs, n); | ||
| 208 | } | ||
| 209 | |||
| 210 | |||
| 211 | static int indexupvalue (LexState *ls, expdesc *v) { | ||
| 212 | FuncState *fs = ls->fs; | ||
| 213 | int i; | 201 | int i; |
| 214 | for (i=0; i<fs->f->nupvalues; i++) { | 202 | for (i=0; i<fs->f->nupvalues; i++) { |
| 215 | if (fs->upvalues[i].k == v->k && fs->upvalues[i].u.i.info == v->u.i.info) | 203 | if (fs->upvalues[i].k == v->k && fs->upvalues[i].u.i.info == v->u.i.info) |
| 216 | return i; | 204 | return i; |
| 217 | } | 205 | } |
| 218 | /* new one */ | 206 | /* new one */ |
| 219 | luaX_checklimit(ls, fs->f->nupvalues+1, MAXUPVALUES, l_s("upvalues")); | 207 | luaX_checklimit(fs->ls, fs->f->nupvalues+1, MAXUPVALUES, l_s("upvalues")); |
| 220 | fs->upvalues[fs->f->nupvalues] = *v; | 208 | fs->upvalues[fs->f->nupvalues] = *v; |
| 221 | return fs->f->nupvalues++; | 209 | return fs->f->nupvalues++; |
| 222 | } | 210 | } |
| 223 | 211 | ||
| 224 | 212 | ||
| 225 | static void codeupvalue (LexState *ls, expdesc *v, TString *n) { | 213 | static void singlevar (FuncState *fs, TString *n, expdesc *var, int baselevel) { |
| 226 | FuncState *fs = ls->fs; | 214 | if (fs == NULL) |
| 227 | int level; | 215 | init_exp(var, VGLOBAL, 0); /* not local in any level; global variable */ |
| 228 | level = search_local(ls, n, v); | 216 | else { /* look up at current level */ |
| 229 | if (level == -1) { /* global? */ | 217 | int i; |
| 230 | if (fs->prev == NULL) | 218 | for (i=fs->nactloc-1; i >= 0; i--) { |
| 231 | luaX_syntaxerror(ls, l_s("cannot access an upvalue at top level"), | 219 | if (n == fs->f->locvars[fs->actloc[i]].varname) { |
| 232 | getstr(n)); | 220 | if (!baselevel) |
| 233 | v->u.i.info = luaK_stringk(fs->prev, n); | 221 | setbit(fs->wasup, i); /* will be upvalue in some other level */ |
| 234 | } | 222 | init_exp(var, VLOCAL, i); |
| 235 | else if (level != 1) { | 223 | return; |
| 236 | luaX_syntaxerror(ls, | 224 | } |
| 237 | l_s("upvalue must be global or local to immediately outer function"), | 225 | } |
| 238 | getstr(n)); | 226 | /* not found at current level; try upper one */ |
| 227 | singlevar(fs->prev, n, var, 0); | ||
| 228 | if (var->k == VGLOBAL) { | ||
| 229 | if (baselevel) | ||
| 230 | var->u.i.info = luaK_stringk(fs, n); /* info points to global name */ | ||
| 231 | } | ||
| 232 | else { /* local variable in some upper level? */ | ||
| 233 | var->u.i.info = indexupvalue(fs, var); | ||
| 234 | var->k = VUPVAL; /* upvalue in this level */ | ||
| 235 | } | ||
| 239 | } | 236 | } |
| 240 | init_exp(v, VRELOCABLE, | ||
| 241 | luaK_codeABc(fs, OP_LOADUPVAL, 0, indexupvalue(ls, v))); | ||
| 242 | } | 237 | } |
| 243 | 238 | ||
| 244 | 239 | ||
| 240 | |||
| 245 | static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { | 241 | static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { |
| 246 | FuncState *fs = ls->fs; | 242 | FuncState *fs = ls->fs; |
| 247 | int extra = nvars - nexps; | 243 | int extra = nvars - nexps; |
| @@ -278,6 +274,7 @@ static void code_params (LexState *ls, int nparams, short dots) { | |||
| 278 | 274 | ||
| 279 | static void enterbreak (FuncState *fs, Breaklabel *bl) { | 275 | static void enterbreak (FuncState *fs, Breaklabel *bl) { |
| 280 | bl->breaklist = NO_JUMP; | 276 | bl->breaklist = NO_JUMP; |
| 277 | bl->nactloc = fs->nactloc; | ||
| 281 | bl->previous = fs->bl; | 278 | bl->previous = fs->bl; |
| 282 | fs->bl = bl; | 279 | fs->bl = bl; |
| 283 | } | 280 | } |
| @@ -286,6 +283,7 @@ static void enterbreak (FuncState *fs, Breaklabel *bl) { | |||
| 286 | static void leavebreak (FuncState *fs, Breaklabel *bl) { | 283 | static void leavebreak (FuncState *fs, Breaklabel *bl) { |
| 287 | fs->bl = bl->previous; | 284 | fs->bl = bl->previous; |
| 288 | luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs)); | 285 | luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs)); |
| 286 | lua_assert(bl->nactloc == fs->nactloc); | ||
| 289 | } | 287 | } |
| 290 | 288 | ||
| 291 | 289 | ||
| @@ -293,16 +291,14 @@ static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { | |||
| 293 | FuncState *fs = ls->fs; | 291 | FuncState *fs = ls->fs; |
| 294 | Proto *f = fs->f; | 292 | Proto *f = fs->f; |
| 295 | int i; | 293 | int i; |
| 296 | int reg = fs->freereg; | ||
| 297 | for (i=0; i<func->f->nupvalues; i++) | ||
| 298 | luaK_exp2nextreg(fs, &func->upvalues[i]); | ||
| 299 | luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, | 294 | luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, |
| 300 | MAXARG_Bc, l_s("constant table overflow")); | 295 | MAXARG_Bc, l_s("constant table overflow")); |
| 301 | f->p[fs->np++] = func->f; | 296 | f->p[fs->np++] = func->f; |
| 302 | fs->freereg = reg; /* CLOSURE will consume those values */ | 297 | init_exp(v, VRELOCABLE, luaK_codeABc(fs, OP_CLOSURE, 0, fs->np-1)); |
| 303 | init_exp(v, VNONRELOC, reg); | 298 | for (i=0; i<func->f->nupvalues; i++) { |
| 304 | luaK_reserveregs(fs, 1); | 299 | luaK_exp2nextreg(fs, &func->upvalues[i]); |
| 305 | luaK_codeABc(fs, OP_CLOSURE, v->u.i.info, fs->np-1); | 300 | fs->freereg--; /* CLOSURE will use these values */ |
| 301 | } | ||
| 306 | } | 302 | } |
| 307 | 303 | ||
| 308 | 304 | ||
| @@ -337,9 +333,9 @@ static void close_func (LexState *ls) { | |||
| 337 | lua_State *L = ls->L; | 333 | lua_State *L = ls->L; |
| 338 | FuncState *fs = ls->fs; | 334 | FuncState *fs = ls->fs; |
| 339 | Proto *f = fs->f; | 335 | Proto *f = fs->f; |
| 336 | removelocalvars(ls, fs->nactloc); | ||
| 340 | luaK_codeABC(fs, OP_RETURN, 0, 0, 0); /* final return */ | 337 | luaK_codeABC(fs, OP_RETURN, 0, 0, 0); /* final return */ |
| 341 | luaK_getlabel(fs); /* close eventual list of pending jumps */ | 338 | luaK_getlabel(fs); /* close eventual list of pending jumps */ |
| 342 | removelocalvars(ls, fs->nactloc); | ||
| 343 | lua_assert(G(L)->roottable == fs->h); | 339 | lua_assert(G(L)->roottable == fs->h); |
| 344 | G(L)->roottable = fs->h->next; | 340 | G(L)->roottable = fs->h->next; |
| 345 | luaH_free(L, fs->h); | 341 | luaH_free(L, fs->h); |
| @@ -644,16 +640,18 @@ static void primaryexp (LexState *ls, expdesc *v) { | |||
| 644 | return; | 640 | return; |
| 645 | } | 641 | } |
| 646 | case TK_NAME: { | 642 | case TK_NAME: { |
| 647 | singlevar(ls, str_checkname(ls), v); | 643 | singlevar(ls->fs, str_checkname(ls), v, 1); |
| 648 | next(ls); | 644 | next(ls); |
| 649 | return; | 645 | return; |
| 650 | } | 646 | } |
| 651 | case l_c('%'): { | 647 | case l_c('%'): { /* for compatibility only */ |
| 652 | next(ls); /* skip `%' */ | 648 | next(ls); /* skip `%' */ |
| 653 | codeupvalue(ls, v, str_checkname(ls)); | 649 | singlevar(ls->fs, str_checkname(ls), v, 1); |
| 650 | check_condition(ls, v->k == VUPVAL, l_s("global upvalues are deprecated")); | ||
| 654 | next(ls); | 651 | next(ls); |
| 655 | break; | 652 | return; |
| 656 | } | 653 | } |
| 654 | |||
| 657 | default: { | 655 | default: { |
| 658 | luaK_error(ls, l_s("unexpected symbol")); | 656 | luaK_error(ls, l_s("unexpected symbol")); |
| 659 | return; | 657 | return; |
| @@ -812,7 +810,7 @@ static void block (LexState *ls) { | |||
| 812 | */ | 810 | */ |
| 813 | struct LHS_assign { | 811 | struct LHS_assign { |
| 814 | struct LHS_assign *prev; | 812 | struct LHS_assign *prev; |
| 815 | expdesc v; /* variable (global, local, or indexed) */ | 813 | expdesc v; /* variable (global, local, upvalue, or indexed) */ |
| 816 | }; | 814 | }; |
| 817 | 815 | ||
| 818 | 816 | ||
| @@ -847,9 +845,8 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | |||
| 847 | 845 | ||
| 848 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { | 846 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { |
| 849 | expdesc e; | 847 | expdesc e; |
| 850 | check_condition(ls, lh->v.k == VLOCAL || lh->v.k == VGLOBAL || | 848 | check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, |
| 851 | lh->v.k == VINDEXED, | 849 | l_s("syntax error!!")); |
| 852 | l_s("syntax error")); | ||
| 853 | if (ls->t.token == l_c(',')) { /* assignment -> `,' simpleexp assignment */ | 850 | if (ls->t.token == l_c(',')) { /* assignment -> `,' simpleexp assignment */ |
| 854 | struct LHS_assign nv; | 851 | struct LHS_assign nv; |
| 855 | nv.prev = lh; | 852 | nv.prev = lh; |
| @@ -1054,7 +1051,7 @@ static void localstat (LexState *ls) { | |||
| 1054 | static int funcname (LexState *ls, expdesc *v) { | 1051 | static int funcname (LexState *ls, expdesc *v) { |
| 1055 | /* funcname -> NAME {field} [`:' NAME] */ | 1052 | /* funcname -> NAME {field} [`:' NAME] */ |
| 1056 | int needself = 0; | 1053 | int needself = 0; |
| 1057 | singlevar(ls, str_checkname(ls), v); | 1054 | singlevar(ls->fs, str_checkname(ls), v, 1); |
| 1058 | next(ls); /* skip var name */ | 1055 | next(ls); /* skip var name */ |
| 1059 | while (ls->t.token == l_c('.')) { | 1056 | while (ls->t.token == l_c('.')) { |
| 1060 | luaY_field(ls, v); | 1057 | luaY_field(ls, v); |
| @@ -1102,25 +1099,19 @@ static void retstat (LexState *ls) { | |||
| 1102 | if (block_follow(ls->t.token) || ls->t.token == l_c(';')) | 1099 | if (block_follow(ls->t.token) || ls->t.token == l_c(';')) |
| 1103 | first = nret = 0; /* return no values */ | 1100 | first = nret = 0; /* return no values */ |
| 1104 | else { | 1101 | else { |
| 1105 | int n = explist1(ls, &e); /* optional return values */ | 1102 | explist1(ls, &e); /* optional return values */ |
| 1106 | if (e.k == VCALL) { | 1103 | if (e.k == VCALL) { |
| 1107 | luaK_setcallreturns(fs, &e, LUA_MULTRET); | 1104 | luaK_setcallreturns(fs, &e, LUA_MULTRET); |
| 1108 | first = fs->nactloc; | 1105 | first = fs->nactloc; |
| 1109 | nret = NO_REG; /* return all values */ | 1106 | nret = NO_REG; /* return all values */ |
| 1110 | } | 1107 | } |
| 1111 | else { | 1108 | else { |
| 1112 | if (n == 1) { /* only one value? */ | 1109 | luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ |
| 1113 | luaK_exp2anyreg(fs, &e); | 1110 | first = fs->nactloc; |
| 1114 | first = e.u.i.info; | 1111 | nret = fs->freereg - first; /* return all `active' values */ |
| 1115 | nret = 1; /* return only this value */ | ||
| 1116 | } | ||
| 1117 | else { | ||
| 1118 | luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ | ||
| 1119 | first = fs->nactloc; | ||
| 1120 | nret = fs->freereg - first; /* return all `active' values */ | ||
| 1121 | } | ||
| 1122 | } | 1112 | } |
| 1123 | } | 1113 | } |
| 1114 | closelevel(ls, 0); | ||
| 1124 | luaK_codeABC(fs, OP_RETURN, first, nret, 0); | 1115 | luaK_codeABC(fs, OP_RETURN, first, nret, 0); |
| 1125 | fs->freereg = fs->nactloc; /* removes all temp values */ | 1116 | fs->freereg = fs->nactloc; /* removes all temp values */ |
| 1126 | } | 1117 | } |
| @@ -1133,8 +1124,8 @@ static void breakstat (LexState *ls) { | |||
| 1133 | if (!bl) | 1124 | if (!bl) |
| 1134 | luaK_error(ls, l_s("no loop to break")); | 1125 | luaK_error(ls, l_s("no loop to break")); |
| 1135 | next(ls); /* skip BREAK */ | 1126 | next(ls); /* skip BREAK */ |
| 1127 | closelevel(ls, bl->nactloc); | ||
| 1136 | luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); | 1128 | luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); |
| 1137 | /* correct stack for compiler and symbolic execution */ | ||
| 1138 | } | 1129 | } |
| 1139 | 1130 | ||
| 1140 | 1131 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.h,v 1.33 2001/08/10 20:53:03 roberto Exp roberto $ | 2 | ** $Id: lparser.h,v 1.34 2001/08/27 15:16:28 roberto Exp $ |
| 3 | ** Lua Parser | 3 | ** Lua Parser |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -7,11 +7,24 @@ | |||
| 7 | #ifndef lparser_h | 7 | #ifndef lparser_h |
| 8 | #define lparser_h | 8 | #define lparser_h |
| 9 | 9 | ||
| 10 | #include "llimits.h" | ||
| 10 | #include "lobject.h" | 11 | #include "lobject.h" |
| 11 | #include "ltable.h" | 12 | #include "ltable.h" |
| 12 | #include "lzio.h" | 13 | #include "lzio.h" |
| 13 | 14 | ||
| 14 | 15 | ||
| 16 | |||
| 17 | /* small implementation of bit arrays */ | ||
| 18 | |||
| 19 | #define BPW (CHAR_BIT*sizeof(unsigned int)) /* bits per word */ | ||
| 20 | |||
| 21 | #define words2bits(b) (((b)-1)/BPW + 1) | ||
| 22 | |||
| 23 | #define setbit(a, b) ((a)[(b)/BPW] |= (1 << (b)%BPW)) | ||
| 24 | #define resetbit(a, b) ((a)[(b)/BPW] &= ~((1 << (b)%BPW))) | ||
| 25 | #define testbit(a, b) ((a)[(b)/BPW] & (1 << (b)%BPW)) | ||
| 26 | |||
| 27 | |||
| 15 | /* | 28 | /* |
| 16 | ** Expression descriptor | 29 | ** Expression descriptor |
| 17 | */ | 30 | */ |
| @@ -21,8 +34,9 @@ typedef enum { | |||
| 21 | VNIL, | 34 | VNIL, |
| 22 | VNUMBER, /* n = value */ | 35 | VNUMBER, /* n = value */ |
| 23 | VK, /* info = index of constant in `k' */ | 36 | VK, /* info = index of constant in `k' */ |
| 24 | VGLOBAL, /* info = index of global name in `k' */ | ||
| 25 | VLOCAL, /* info = local register */ | 37 | VLOCAL, /* info = local register */ |
| 38 | VUPVAL, /* info = index of upvalue in `upvalues' */ | ||
| 39 | VGLOBAL, /* info = index of global name in `k' */ | ||
| 26 | VINDEXED, /* info = table register; aux = index register (or `k') */ | 40 | VINDEXED, /* info = table register; aux = index register (or `k') */ |
| 27 | VRELOCABLE, /* info = instruction pc */ | 41 | VRELOCABLE, /* info = instruction pc */ |
| 28 | VNONRELOC, /* info = result register */ | 42 | VNONRELOC, /* info = result register */ |
| @@ -63,6 +77,8 @@ typedef struct FuncState { | |||
| 63 | struct Breaklabel *bl; /* chain of breakable blocks */ | 77 | struct Breaklabel *bl; /* chain of breakable blocks */ |
| 64 | expdesc upvalues[MAXUPVALUES]; /* upvalues */ | 78 | expdesc upvalues[MAXUPVALUES]; /* upvalues */ |
| 65 | int actloc[MAXLOCALS]; /* local-variable stack (indices to locvars) */ | 79 | int actloc[MAXLOCALS]; /* local-variable stack (indices to locvars) */ |
| 80 | unsigned int wasup[words2bits(MAXLOCALS)]; /* bit array to mark whether a | ||
| 81 | local variable was used as upvalue at some level */ | ||
| 66 | } FuncState; | 82 | } FuncState; |
| 67 | 83 | ||
| 68 | 84 | ||
| @@ -58,6 +58,7 @@ static void f_luaopen (lua_State *L, void *ud) { | |||
| 58 | G(L)->rootcl = NULL; | 58 | G(L)->rootcl = NULL; |
| 59 | G(L)->roottable = NULL; | 59 | G(L)->roottable = NULL; |
| 60 | G(L)->rootudata = NULL; | 60 | G(L)->rootudata = NULL; |
| 61 | G(L)->rootupval = NULL; | ||
| 61 | G(L)->TMtable = NULL; | 62 | G(L)->TMtable = NULL; |
| 62 | G(L)->sizeTM = 0; | 63 | G(L)->sizeTM = 0; |
| 63 | G(L)->ntag = 0; | 64 | G(L)->ntag = 0; |
| @@ -91,6 +92,7 @@ LUA_API lua_State *lua_newthread (lua_State *OL, int stacksize) { | |||
| 91 | L->errorJmp = NULL; | 92 | L->errorJmp = NULL; |
| 92 | L->callhook = NULL; | 93 | L->callhook = NULL; |
| 93 | L->linehook = NULL; | 94 | L->linehook = NULL; |
| 95 | L->opencl = NULL; | ||
| 94 | L->allowhooks = 1; | 96 | L->allowhooks = 1; |
| 95 | L->next = L->previous = L; | 97 | L->next = L->previous = L; |
| 96 | so.stacksize = stacksize; | 98 | so.stacksize = stacksize; |
| @@ -122,10 +124,10 @@ static void close_state (lua_State *L, lua_State *OL) { | |||
| 122 | luaS_freeall(L); | 124 | luaS_freeall(L); |
| 123 | luaM_freearray(L, G(L)->TMtable, G(L)->sizeTM, struct TM); | 125 | luaM_freearray(L, G(L)->TMtable, G(L)->sizeTM, struct TM); |
| 124 | luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, l_char); | 126 | luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, l_char); |
| 125 | luaM_freelem(NULL, L->G, global_State); | 127 | luaM_freelem(NULL, L->G); |
| 126 | } | 128 | } |
| 127 | luaM_freearray(OL, L->stack, L->stacksize, TObject); | 129 | luaM_freearray(OL, L->stack, L->stacksize, TObject); |
| 128 | luaM_freelem(OL, L, lua_State); | 130 | luaM_freelem(OL, L); |
| 129 | } | 131 | } |
| 130 | 132 | ||
| 131 | LUA_API void lua_close (lua_State *L) { | 133 | LUA_API void lua_close (lua_State *L) { |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.h,v 1.57 2001/06/06 18:00:19 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 1.58 2001/06/15 19:16:41 roberto Exp $ |
| 3 | ** Global State | 3 | ** Global State |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -56,10 +56,6 @@ typedef struct stringtable { | |||
| 56 | typedef struct global_State { | 56 | typedef struct global_State { |
| 57 | void *Mbuffer; /* global buffer */ | 57 | void *Mbuffer; /* global buffer */ |
| 58 | size_t Mbuffsize; /* size of Mbuffer */ | 58 | size_t Mbuffsize; /* size of Mbuffer */ |
| 59 | Proto *rootproto; /* list of all prototypes */ | ||
| 60 | Closure *rootcl; /* list of all closures */ | ||
| 61 | Hash *roottable; /* list of all tables */ | ||
| 62 | Udata *rootudata; /* list of all userdata */ | ||
| 63 | stringtable strt; /* hash table for strings */ | 59 | stringtable strt; /* hash table for strings */ |
| 64 | Hash *type2tag; /* hash table from type names to tags */ | 60 | Hash *type2tag; /* hash table from type names to tags */ |
| 65 | Hash *registry; /* (strong) registry table */ | 61 | Hash *registry; /* (strong) registry table */ |
| @@ -69,6 +65,11 @@ typedef struct global_State { | |||
| 69 | int ntag; /* number of tags in TMtable */ | 65 | int ntag; /* number of tags in TMtable */ |
| 70 | lu_mem GCthreshold; | 66 | lu_mem GCthreshold; |
| 71 | lu_mem nblocks; /* number of `bytes' currently allocated */ | 67 | lu_mem nblocks; /* number of `bytes' currently allocated */ |
| 68 | Proto *rootproto; /* list of all prototypes */ | ||
| 69 | Closure *rootcl; /* list of all closed closures */ | ||
| 70 | Hash *roottable; /* list of all tables */ | ||
| 71 | Udata *rootudata; /* list of all userdata */ | ||
| 72 | UpVal *rootupval; /* list of all up values */ | ||
| 72 | } global_State; | 73 | } global_State; |
| 73 | 74 | ||
| 74 | 75 | ||
| @@ -88,6 +89,7 @@ struct lua_State { | |||
| 88 | lua_Hook linehook; | 89 | lua_Hook linehook; |
| 89 | int allowhooks; | 90 | int allowhooks; |
| 90 | struct lua_longjmp *errorJmp; /* current error recover point */ | 91 | struct lua_longjmp *errorJmp; /* current error recover point */ |
| 92 | Closure *opencl; /* list of closures still pointing to this stack */ | ||
| 91 | lua_State *next; /* circular double linked list of states */ | 93 | lua_State *next; /* circular double linked list of states */ |
| 92 | lua_State *previous; | 94 | lua_State *previous; |
| 93 | CallInfo basefunc; | 95 | CallInfo basefunc; |
| @@ -165,7 +165,7 @@ static int listcode (lua_State *L) { | |||
| 165 | Proto *p; | 165 | Proto *p; |
| 166 | luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), | 166 | luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), |
| 167 | 1, l_s("Lua function expected")); | 167 | 1, l_s("Lua function expected")); |
| 168 | p = clvalue(luaA_index(L, 1))->f.l; | 168 | p = clvalue(luaA_index(L, 1))->u.l.p; |
| 169 | lua_newtable(L); | 169 | lua_newtable(L); |
| 170 | setnameval(L, l_s("maxstack"), p->maxstacksize); | 170 | setnameval(L, l_s("maxstack"), p->maxstacksize); |
| 171 | setnameval(L, l_s("numparams"), p->numparams); | 171 | setnameval(L, l_s("numparams"), p->numparams); |
| @@ -184,7 +184,7 @@ static int listk (lua_State *L) { | |||
| 184 | int i; | 184 | int i; |
| 185 | luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), | 185 | luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), |
| 186 | 1, l_s("Lua function expected")); | 186 | 1, l_s("Lua function expected")); |
| 187 | p = clvalue(luaA_index(L, 1))->f.l; | 187 | p = clvalue(luaA_index(L, 1))->u.l.p; |
| 188 | lua_newtable(L); | 188 | lua_newtable(L); |
| 189 | for (i=0; i<p->sizek; i++) { | 189 | for (i=0; i<p->sizek; i++) { |
| 190 | lua_pushnumber(L, i+1); | 190 | lua_pushnumber(L, i+1); |
| @@ -202,7 +202,7 @@ static int listlocals (lua_State *L) { | |||
| 202 | const l_char *name; | 202 | const l_char *name; |
| 203 | luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), | 203 | luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), |
| 204 | 1, l_s("Lua function expected")); | 204 | 1, l_s("Lua function expected")); |
| 205 | p = clvalue(luaA_index(L, 1))->f.l; | 205 | p = clvalue(luaA_index(L, 1))->u.l.p; |
| 206 | while ((name = luaF_getlocalname(p, ++i, pc)) != NULL) | 206 | while ((name = luaF_getlocalname(p, ++i, pc)) != NULL) |
| 207 | lua_pushstring(L, name); | 207 | lua_pushstring(L, name); |
| 208 | return i-1; | 208 | return i-1; |
| @@ -64,8 +64,8 @@ int luaV_tostring (lua_State *L, TObject *obj) { | |||
| 64 | 64 | ||
| 65 | static void traceexec (lua_State *L, lua_Hook linehook) { | 65 | static void traceexec (lua_State *L, lua_Hook linehook) { |
| 66 | CallInfo *ci = L->ci; | 66 | CallInfo *ci = L->ci; |
| 67 | int *lineinfo = ci_func(ci)->f.l->lineinfo; | 67 | int *lineinfo = ci_func(ci)->u.l.p->lineinfo; |
| 68 | int pc = (*ci->pc - ci_func(ci)->f.l->code) - 1; | 68 | int pc = (*ci->pc - ci_func(ci)->u.l.p->code) - 1; |
| 69 | int newline; | 69 | int newline; |
| 70 | if (pc == 0) { /* may be first time? */ | 70 | if (pc == 0) { /* may be first time? */ |
| 71 | ci->line = 1; | 71 | ci->line = 1; |
| @@ -82,30 +82,6 @@ static void traceexec (lua_State *L, lua_Hook linehook) { | |||
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | 84 | ||
| 85 | static Closure *luaV_closure (lua_State *L, int nelems) { | ||
| 86 | Closure *c = luaF_newclosure(L, nelems); | ||
| 87 | L->top -= nelems; | ||
| 88 | while (nelems--) | ||
| 89 | setobj(&c->upvalue[nelems], L->top+nelems); | ||
| 90 | setclvalue(L->top, c); | ||
| 91 | incr_top; | ||
| 92 | return c; | ||
| 93 | } | ||
| 94 | |||
| 95 | |||
| 96 | void luaV_Cclosure (lua_State *L, lua_CFunction c, int nelems) { | ||
| 97 | Closure *cl = luaV_closure(L, nelems); | ||
| 98 | cl->f.c = c; | ||
| 99 | cl->isC = 1; | ||
| 100 | } | ||
| 101 | |||
| 102 | |||
| 103 | void luaV_Lclosure (lua_State *L, Proto *l, int nelems) { | ||
| 104 | Closure *cl = luaV_closure(L, nelems); | ||
| 105 | cl->f.l = l; | ||
| 106 | cl->isC = 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | 85 | ||
| 110 | /* maximum stack used by a call to a tag method (func + args) */ | 86 | /* maximum stack used by a call to a tag method (func + args) */ |
| 111 | #define MAXSTACK_TM 4 | 87 | #define MAXSTACK_TM 4 |
| @@ -376,7 +352,7 @@ static void adjust_varargs (lua_State *L, StkId base, int nfixargs) { | |||
| 376 | ** Returns n such that the the results are between [n,top). | 352 | ** Returns n such that the the results are between [n,top). |
| 377 | */ | 353 | */ |
| 378 | StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | 354 | StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { |
| 379 | const Proto *const tf = cl->f.l; | 355 | const Proto *const tf = cl->u.l.p; |
| 380 | const Instruction *pc; | 356 | const Instruction *pc; |
| 381 | lua_Hook linehook; | 357 | lua_Hook linehook; |
| 382 | if (tf->is_vararg) /* varargs? */ | 358 | if (tf->is_vararg) /* varargs? */ |
| @@ -406,10 +382,6 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
| 406 | setnvalue(ra, (lua_Number)GETARG_sBc(i)); | 382 | setnvalue(ra, (lua_Number)GETARG_sBc(i)); |
| 407 | break; | 383 | break; |
| 408 | } | 384 | } |
| 409 | case OP_LOADUPVAL: { | ||
| 410 | setobj(ra, cl->upvalue+GETARG_Bc(i)); | ||
| 411 | break; | ||
| 412 | } | ||
| 413 | case OP_LOADNIL: { | 385 | case OP_LOADNIL: { |
| 414 | TObject *rb = RB(i); | 386 | TObject *rb = RB(i); |
| 415 | do { | 387 | do { |
| @@ -417,6 +389,12 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
| 417 | } while (rb >= ra); | 389 | } while (rb >= ra); |
| 418 | break; | 390 | break; |
| 419 | } | 391 | } |
| 392 | case OP_GETUPVAL: { | ||
| 393 | int b = GETARG_B(i); | ||
| 394 | lua_assert(luaF_isclosed(cl, b) || cl->u.l.upvals[b] < base); | ||
| 395 | setobj(ra, cl->u.l.upvals[b]); | ||
| 396 | break; | ||
| 397 | } | ||
| 420 | case OP_GETGLOBAL: { | 398 | case OP_GETGLOBAL: { |
| 421 | lua_assert(ttype(KBc(i)) == LUA_TSTRING); | 399 | lua_assert(ttype(KBc(i)) == LUA_TSTRING); |
| 422 | luaV_getglobal(L, tsvalue(KBc(i)), ra); | 400 | luaV_getglobal(L, tsvalue(KBc(i)), ra); |
| @@ -431,6 +409,12 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
| 431 | luaV_setglobal(L, tsvalue(KBc(i)), ra); | 409 | luaV_setglobal(L, tsvalue(KBc(i)), ra); |
| 432 | break; | 410 | break; |
| 433 | } | 411 | } |
| 412 | case OP_SETUPVAL: { | ||
| 413 | int b = GETARG_B(i); | ||
| 414 | lua_assert(luaF_isclosed(cl, b) || cl->u.l.upvals[b] < base); | ||
| 415 | setobj(cl->u.l.upvals[b], ra); | ||
| 416 | break; | ||
| 417 | } | ||
| 434 | case OP_SETTABLE: { | 418 | case OP_SETTABLE: { |
| 435 | luaV_settable(L, RB(i), RKC(i), ra); | 419 | luaV_settable(L, RB(i), RKC(i), ra); |
| 436 | break; | 420 | break; |
| @@ -646,13 +630,34 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
| 646 | luaH_setnum(L, h, bc+n, ra+n); | 630 | luaH_setnum(L, h, bc+n, ra+n); |
| 647 | break; | 631 | break; |
| 648 | } | 632 | } |
| 633 | case OP_CLOSE: { | ||
| 634 | luaF_close(L, ra); | ||
| 635 | break; | ||
| 636 | } | ||
| 649 | case OP_CLOSURE: { | 637 | case OP_CLOSURE: { |
| 650 | Proto *p = tf->p[GETARG_Bc(i)]; | 638 | Proto *p; |
| 651 | int nup = p->nupvalues; | 639 | Closure *ncl; |
| 652 | luaV_checkGC(L, ra+nup); | 640 | int nup, j; |
| 653 | L->top = ra+nup; | 641 | luaV_checkGC(L, L->top); |
| 654 | luaV_Lclosure(L, p, nup); | 642 | p = tf->p[GETARG_Bc(i)]; |
| 655 | L->top = base + tf->maxstacksize; | 643 | nup = p->nupvalues; |
| 644 | ncl = luaF_newLclosure(L, nup); | ||
| 645 | ncl->u.l.p = p; | ||
| 646 | for (j=0; j<nup; j++, pc++) { | ||
| 647 | if (GET_OPCODE(*pc) == OP_GETUPVAL) { | ||
| 648 | int n = GETARG_B(*pc); | ||
| 649 | if (!luaF_isclosed(cl, n)) | ||
| 650 | luaF_openentry(ncl, j); | ||
| 651 | ncl->u.l.upvals[j] = cl->u.l.upvals[n]; | ||
| 652 | } | ||
| 653 | else { | ||
| 654 | lua_assert(GET_OPCODE(*pc) == OP_MOVE); | ||
| 655 | luaF_openentry(ncl, j); | ||
| 656 | ncl->u.l.upvals[j] = base + GETARG_B(*pc); | ||
| 657 | } | ||
| 658 | } | ||
| 659 | luaF_LConlist(L, ncl); | ||
| 660 | setclvalue(ra, ncl); | ||
| 656 | break; | 661 | break; |
| 657 | } | 662 | } |
| 658 | } | 663 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.h,v 1.29 2001/02/07 18:13:49 roberto Exp roberto $ | 2 | ** $Id: lvm.h,v 1.30 2001/06/05 18:17:01 roberto Exp $ |
| 3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -23,8 +23,6 @@ void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val); | |||
| 23 | void luaV_getglobal (lua_State *L, TString *s, StkId res); | 23 | void luaV_getglobal (lua_State *L, TString *s, StkId res); |
| 24 | void luaV_setglobal (lua_State *L, TString *s, StkId val); | 24 | void luaV_setglobal (lua_State *L, TString *s, StkId val); |
| 25 | StkId luaV_execute (lua_State *L, const Closure *cl, StkId base); | 25 | StkId luaV_execute (lua_State *L, const Closure *cl, StkId base); |
| 26 | void luaV_Cclosure (lua_State *L, lua_CFunction c, int nelems); | ||
| 27 | void luaV_Lclosure (lua_State *L, Proto *l, int nelems); | ||
| 28 | int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r); | 26 | int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r); |
| 29 | void luaV_strconc (lua_State *L, int total, StkId top); | 27 | void luaV_strconc (lua_State *L, int total, StkId top); |
| 30 | 28 | ||
