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 | ||