diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-01-25 20:14:54 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-01-25 20:14:54 -0200 |
commit | 50e29525936be4891f9db090f293432913b5f7c0 (patch) | |
tree | 8e487b87f82761e15cd096ac345354f57f38fedc /lvm.c | |
parent | b217ae644e3a83def93be2fe742e2cd0970e1a5f (diff) | |
download | lua-50e29525936be4891f9db090f293432913b5f7c0.tar.gz lua-50e29525936be4891f9db090f293432913b5f7c0.tar.bz2 lua-50e29525936be4891f9db090f293432913b5f7c0.zip |
first version of dynamic stack
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 83 |
1 files changed, 42 insertions, 41 deletions
@@ -29,10 +29,9 @@ | |||
29 | 29 | ||
30 | static void luaV_checkGC (lua_State *L, StkId top) { | 30 | static void luaV_checkGC (lua_State *L, StkId top) { |
31 | if (G(L)->nblocks >= G(L)->GCthreshold) { | 31 | if (G(L)->nblocks >= G(L)->GCthreshold) { |
32 | StkId temp = L->top; | 32 | L->top = top; /* limit for active registers */ |
33 | L->top = top; | ||
34 | luaC_collectgarbage(L); | 33 | luaC_collectgarbage(L); |
35 | L->top = temp; /* restore old top position */ | 34 | L->top = L->ci->top; /* restore old top position */ |
36 | } | 35 | } |
37 | } | 36 | } |
38 | 37 | ||
@@ -83,32 +82,37 @@ static void traceexec (lua_State *L, lua_Hook linehook) { | |||
83 | if (newline != ci->line || pc <= ci->lastpc) { | 82 | if (newline != ci->line || pc <= ci->lastpc) { |
84 | ci->line = newline; | 83 | ci->line = newline; |
85 | luaD_lineHook(L, newline, linehook); | 84 | luaD_lineHook(L, newline, linehook); |
85 | ci = L->ci; /* previous call may realocate `ci' */ | ||
86 | } | 86 | } |
87 | ci->lastpc = pc; | 87 | ci->lastpc = pc; |
88 | } | 88 | } |
89 | 89 | ||
90 | 90 | ||
91 | static void callTMres (lua_State *L, const TObject *f, | ||
92 | const TObject *p1, const TObject *p2, TObject *result ) { | ||
93 | StkId stack = L->stack; | ||
94 | setobj(L->top, f); /* push function */ | ||
95 | setobj(L->top+1, p1); /* 1st argument */ | ||
96 | setobj(L->top+2, p2); /* 2nd argument */ | ||
97 | luaD_checkstack(L, 3); /* cannot check before (could invalidate p1, p2) */ | ||
98 | L->top += 3; | ||
99 | luaD_call(L, L->top - 3, 1); | ||
100 | if (stack != L->stack) /* stack changed? */ | ||
101 | result = (result - stack) + L->stack; /* correct pointer */ | ||
102 | setobj(result, --L->top); /* get result */ | ||
103 | } | ||
104 | |||
91 | 105 | ||
92 | /* maximum stack used by a call to a tag method (func + args) */ | ||
93 | #define MAXSTACK_TM 4 | ||
94 | 106 | ||
95 | static void callTM (lua_State *L, const TObject *f, | 107 | static void callTM (lua_State *L, const TObject *f, |
96 | const TObject *p1, const TObject *p2, const TObject *p3, TObject *result ) { | 108 | const TObject *p1, const TObject *p2, const TObject *p3) { |
97 | StkId base = L->top; | 109 | setobj(L->top, f); /* push function */ |
98 | luaD_checkstack(L, MAXSTACK_TM); | 110 | setobj(L->top+1, p1); /* 1st argument */ |
99 | setobj(base, f); /* push function */ | 111 | setobj(L->top+2, p2); /* 2nd argument */ |
100 | setobj(base+1, p1); /* 1st argument */ | 112 | setobj(L->top+3, p3); /* 3th argument */ |
101 | setobj(base+2, p2); /* 2nd argument */ | 113 | luaD_checkstack(L, 4); /* cannot check before (could invalidate p1...p3) */ |
102 | L->top += 3; | 114 | L->top += 4; |
103 | if (p3) { | 115 | luaD_call(L, L->top - 4, 0); |
104 | setobj(base+3, p3); /* 3th argument */ | ||
105 | L->top++; | ||
106 | } | ||
107 | luaD_call(L, base, 1); | ||
108 | if (result) { /* need a result? */ | ||
109 | setobj(result, base); /* get it */ | ||
110 | } | ||
111 | L->top = base; /* restore top */ | ||
112 | } | 116 | } |
113 | 117 | ||
114 | 118 | ||
@@ -139,7 +143,7 @@ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) { | |||
139 | } | 143 | } |
140 | } | 144 | } |
141 | if (ttype(tm) == LUA_TFUNCTION) | 145 | if (ttype(tm) == LUA_TFUNCTION) |
142 | callTM(L, tm, t, key, NULL, res); | 146 | callTMres(L, tm, t, key, res); |
143 | else { | 147 | else { |
144 | t = (StkId)tm; /* ?? */ | 148 | t = (StkId)tm; /* ?? */ |
145 | goto init; /* return luaV_gettable(L, tm, key, res); */ | 149 | goto init; /* return luaV_gettable(L, tm, key, res); */ |
@@ -167,7 +171,7 @@ void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val) { | |||
167 | } | 171 | } |
168 | } | 172 | } |
169 | if (ttype(tm) == LUA_TFUNCTION) | 173 | if (ttype(tm) == LUA_TFUNCTION) |
170 | callTM(L, tm, t, key, val, NULL); | 174 | callTM(L, tm, t, key, val); |
171 | else { | 175 | else { |
172 | t = (StkId)tm; /* ?? */ | 176 | t = (StkId)tm; /* ?? */ |
173 | goto init; /* luaV_settable(L, tm, key, val); */ | 177 | goto init; /* luaV_settable(L, tm, key, val); */ |
@@ -181,7 +185,7 @@ static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2, | |||
181 | if (ttype(tm) == LUA_TNIL) | 185 | if (ttype(tm) == LUA_TNIL) |
182 | tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ | 186 | tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ |
183 | if (ttype(tm) != LUA_TFUNCTION) return 0; | 187 | if (ttype(tm) != LUA_TFUNCTION) return 0; |
184 | callTM(L, tm, p1, p2, NULL, res); | 188 | callTMres(L, tm, p1, p2, res); |
185 | return 1; | 189 | return 1; |
186 | } | 190 | } |
187 | 191 | ||
@@ -229,7 +233,6 @@ int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) { | |||
229 | 233 | ||
230 | 234 | ||
231 | void luaV_strconc (lua_State *L, int total, int last) { | 235 | void luaV_strconc (lua_State *L, int total, int last) { |
232 | luaV_checkGC(L, L->ci->base + last + 1); | ||
233 | do { | 236 | do { |
234 | StkId top = L->ci->base + last + 1; | 237 | StkId top = L->ci->base + last + 1; |
235 | int n = 2; /* number of elements handled in this pass (at least 2) */ | 238 | int n = 2; /* number of elements handled in this pass (at least 2) */ |
@@ -273,7 +276,7 @@ static void powOp (lua_State *L, StkId ra, StkId rb, StkId rc) { | |||
273 | luaV_gettable(L, gt(L), &o, &f); | 276 | luaV_gettable(L, gt(L), &o, &f); |
274 | if (ttype(&f) != LUA_TFUNCTION) | 277 | if (ttype(&f) != LUA_TFUNCTION) |
275 | luaD_error(L, "`pow' (for `^' operator) is not a function"); | 278 | luaD_error(L, "`pow' (for `^' operator) is not a function"); |
276 | callTM(L, &f, b, c, NULL, ra); | 279 | callTMres(L, &f, b, c, ra); |
277 | } | 280 | } |
278 | else | 281 | else |
279 | call_arith(L, rb, rc, ra, TM_POW); | 282 | call_arith(L, rb, rc, ra, TM_POW); |
@@ -324,17 +327,18 @@ StkId luaV_execute (lua_State *L) { | |||
324 | k = cl->p->k; | 327 | k = cl->p->k; |
325 | linehook = L->linehook; | 328 | linehook = L->linehook; |
326 | L->ci->pc = &pc; | 329 | L->ci->pc = &pc; |
330 | L->ci->pb = &base; | ||
327 | pc = L->ci->savedpc; | 331 | pc = L->ci->savedpc; |
328 | L->ci->savedpc = NULL; | ||
329 | /* main loop of interpreter */ | 332 | /* main loop of interpreter */ |
330 | for (;;) { | 333 | for (;;) { |
331 | const Instruction i = *pc++; | 334 | const Instruction i = *pc++; |
332 | const StkId ra = RA(i); | 335 | StkId ra; |
333 | if (linehook) | 336 | if (linehook) |
334 | traceexec(L, linehook); | 337 | traceexec(L, linehook); |
338 | ra = RA(i); | ||
339 | lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base); | ||
335 | lua_assert(L->top == L->ci->top || GET_OPCODE(i) == OP_CALL || | 340 | lua_assert(L->top == L->ci->top || GET_OPCODE(i) == OP_CALL || |
336 | GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO); | 341 | GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO); |
337 | lua_assert(L->ci->savedpc == NULL); | ||
338 | switch (GET_OPCODE(i)) { | 342 | switch (GET_OPCODE(i)) { |
339 | case OP_MOVE: { | 343 | case OP_MOVE: { |
340 | setobj(ra, RB(i)); | 344 | setobj(ra, RB(i)); |
@@ -344,10 +348,6 @@ StkId luaV_execute (lua_State *L) { | |||
344 | setobj(ra, KBc(i)); | 348 | setobj(ra, KBc(i)); |
345 | break; | 349 | break; |
346 | } | 350 | } |
347 | case OP_LOADINT: { | ||
348 | setnvalue(ra, (lua_Number)GETARG_sBc(i)); | ||
349 | break; | ||
350 | } | ||
351 | case OP_LOADBOOL: { | 351 | case OP_LOADBOOL: { |
352 | setbvalue(ra, GETARG_B(i)); | 352 | setbvalue(ra, GETARG_B(i)); |
353 | if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ | 353 | if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ |
@@ -441,8 +441,9 @@ StkId luaV_execute (lua_State *L) { | |||
441 | case OP_CONCAT: { | 441 | case OP_CONCAT: { |
442 | int b = GETARG_B(i); | 442 | int b = GETARG_B(i); |
443 | int c = GETARG_C(i); | 443 | int c = GETARG_C(i); |
444 | luaV_strconc(L, c-b+1, c); | 444 | luaV_strconc(L, c-b+1, c); /* this call may change `base' (and `ra') */ |
445 | setobj(ra, base+b); | 445 | setobj(base+GETARG_A(i), base+b); |
446 | luaV_checkGC(L, base+c+1); | ||
446 | break; | 447 | break; |
447 | } | 448 | } |
448 | case OP_JMP: { | 449 | case OP_JMP: { |
@@ -493,7 +494,7 @@ StkId luaV_execute (lua_State *L) { | |||
493 | nresults = GETARG_C(i) - 1; | 494 | nresults = GETARG_C(i) - 1; |
494 | firstResult = luaD_precall(L, ra); | 495 | firstResult = luaD_precall(L, ra); |
495 | if (firstResult) { | 496 | if (firstResult) { |
496 | if (firstResult == base) { /* yield?? */ | 497 | if (firstResult > L->top) { /* yield? */ |
497 | (L->ci-1)->savedpc = pc; | 498 | (L->ci-1)->savedpc = pc; |
498 | return NULL; | 499 | return NULL; |
499 | } | 500 | } |
@@ -514,16 +515,16 @@ StkId luaV_execute (lua_State *L) { | |||
514 | b = GETARG_B(i); | 515 | b = GETARG_B(i); |
515 | if (b != 0) L->top = ra+b-1; | 516 | if (b != 0) L->top = ra+b-1; |
516 | ci = L->ci - 1; | 517 | ci = L->ci - 1; |
517 | if (ci->savedpc == NULL) | 518 | lua_assert((ci+1)->pc == &pc); |
518 | return ra; | 519 | if (ci->pc != &pc) /* previous function was running `here'? */ |
519 | else { /* previous function is Lua: continue its execution */ | 520 | return ra; /* no: return */ |
521 | else { /* yes: continue its execution */ | ||
520 | int nresults; | 522 | int nresults; |
521 | lua_assert(ttype(ci->base-1) == LUA_TFUNCTION); | 523 | lua_assert(ttype(ci->base-1) == LUA_TFUNCTION); |
522 | base = ci->base; /* restore previous values */ | 524 | base = ci->base; /* restore previous values */ |
523 | cl = &clvalue(base - 1)->l; | 525 | cl = &clvalue(base - 1)->l; |
524 | k = cl->p->k; | 526 | k = cl->p->k; |
525 | pc = ci->savedpc; | 527 | pc = ci->savedpc; |
526 | ci->savedpc = NULL; | ||
527 | lua_assert(GET_OPCODE(*(pc-1)) == OP_CALL); | 528 | lua_assert(GET_OPCODE(*(pc-1)) == OP_CALL); |
528 | nresults = GETARG_C(*(pc-1)) - 1; | 529 | nresults = GETARG_C(*(pc-1)) - 1; |
529 | luaD_poscall(L, nresults, ra); | 530 | luaD_poscall(L, nresults, ra); |
@@ -607,7 +608,6 @@ StkId luaV_execute (lua_State *L) { | |||
607 | Proto *p; | 608 | Proto *p; |
608 | Closure *ncl; | 609 | Closure *ncl; |
609 | int nup, j; | 610 | int nup, j; |
610 | luaV_checkGC(L, L->top); | ||
611 | p = cl->p->p[GETARG_Bc(i)]; | 611 | p = cl->p->p[GETARG_Bc(i)]; |
612 | nup = p->nupvalues; | 612 | nup = p->nupvalues; |
613 | ncl = luaF_newLclosure(L, nup); | 613 | ncl = luaF_newLclosure(L, nup); |
@@ -621,6 +621,7 @@ StkId luaV_execute (lua_State *L) { | |||
621 | } | 621 | } |
622 | } | 622 | } |
623 | setclvalue(ra, ncl); | 623 | setclvalue(ra, ncl); |
624 | luaV_checkGC(L, L->top); | ||
624 | break; | 625 | break; |
625 | } | 626 | } |
626 | } | 627 | } |