diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-12-01 17:50:08 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-12-01 17:50:08 -0200 |
commit | fe237ad8085f34e89fcd3610a9771215af63f03f (patch) | |
tree | f7ee5d8f7d1ffb74e94f049aa6f31eb03606cdf6 /ldo.c | |
parent | 3181dfefee40b9a424b80aa779c671f5f458904c (diff) | |
download | lua-fe237ad8085f34e89fcd3610a9771215af63f03f.tar.gz lua-fe237ad8085f34e89fcd3610a9771215af63f03f.tar.bz2 lua-fe237ad8085f34e89fcd3610a9771215af63f03f.zip |
fixed stack; first version.
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 171 |
1 files changed, 88 insertions, 83 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 1.52 1999/11/22 13:12:07 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.53 1999/11/25 18:58:51 roberto Exp roberto $ |
3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -28,39 +28,40 @@ | |||
28 | 28 | ||
29 | 29 | ||
30 | 30 | ||
31 | #ifndef STACK_LIMIT | 31 | #ifndef DEFAULT_STACK_SIZE |
32 | #define STACK_LIMIT 6000 /* arbitrary limit */ | 32 | #define DEFAULT_STACK_SIZE 1024 |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | #define EXTRA_STACK 32 /* space to handle stack overflow errors */ | ||
35 | 36 | ||
36 | 37 | /* | |
37 | #define STACK_UNIT 128 | 38 | ** typical numer of recursive calls that fit in the stack |
38 | 39 | ** (only for error messages) | |
39 | 40 | */ | |
40 | #ifdef DEBUG | 41 | #define REC_DEEP (DEFAULT_STACK_SIZE/20) |
41 | #undef STACK_UNIT | ||
42 | #define STACK_UNIT 2 | ||
43 | #endif | ||
44 | 42 | ||
45 | 43 | ||
46 | void luaD_init (lua_State *L) { | 44 | void luaD_init (lua_State *L) { |
47 | L->stack.stack = luaM_newvector(L, STACK_UNIT, TObject); | 45 | L->stack = luaM_newvector(L, DEFAULT_STACK_SIZE+EXTRA_STACK, TObject); |
48 | L->stack.top = L->stack.stack; | 46 | L->stack_last = L->stack+(DEFAULT_STACK_SIZE-1); |
49 | L->stack.last = L->stack.stack+(STACK_UNIT-1); | 47 | L->Cstack.base = L->Cstack.lua2C = L->top = L->stack; |
48 | L->Cstack.num = 0; | ||
50 | } | 49 | } |
51 | 50 | ||
52 | 51 | ||
53 | void luaD_checkstack (lua_State *L, int n) { | 52 | void luaD_checkstack (lua_State *L, int n) { |
54 | struct Stack *S = &L->stack; | 53 | if (L->stack_last-L->top <= n) { /* stack overflow? */ |
55 | if (S->last-S->top <= n) { | 54 | if (L->stack_last-L->stack > (DEFAULT_STACK_SIZE-1)) { |
56 | StkId top = S->top-S->stack; | 55 | /* overflow while handling overflow: do what?? */ |
57 | int stacksize = (S->last-S->stack)+STACK_UNIT+n; | 56 | L->top -= EXTRA_STACK; |
58 | luaM_reallocvector(L, S->stack, stacksize, TObject); | 57 | lua_error(L, "BAD STACK OVERFLOW! DATA CORRUPTED!!"); |
59 | S->last = S->stack+(stacksize-1); | 58 | } |
60 | S->top = S->stack + top; | 59 | else { |
61 | if (stacksize >= STACK_LIMIT) { /* stack overflow? */ | 60 | L->stack_last += EXTRA_STACK; /* to be used by error message */ |
62 | if (lua_stackedfunction(L, 100) == LUA_NOOBJECT) /* 100 funcs on stack? */ | 61 | if (lua_stackedfunction(L, REC_DEEP) == LUA_NOOBJECT) { |
63 | lua_error(L, "Lua2C - C2Lua overflow"); /* doesn't look like a rec. loop */ | 62 | /* less than REC_DEEP funcs on stack: doesn't look like a rec. loop */ |
63 | lua_error(L, "Lua2C - C2Lua overflow"); | ||
64 | } | ||
64 | else | 65 | else |
65 | lua_error(L, "stack size overflow"); | 66 | lua_error(L, "stack size overflow"); |
66 | } | 67 | } |
@@ -68,54 +69,62 @@ void luaD_checkstack (lua_State *L, int n) { | |||
68 | } | 69 | } |
69 | 70 | ||
70 | 71 | ||
72 | static void restore_stack_limit (lua_State *L) { | ||
73 | if (L->top-L->stack < DEFAULT_STACK_SIZE-1) | ||
74 | L->stack_last = L->stack+(DEFAULT_STACK_SIZE-1); | ||
75 | } | ||
76 | |||
77 | |||
71 | /* | 78 | /* |
72 | ** Adjust stack. Set top to the given value, pushing NILs if needed. | 79 | ** Adjust stack. Set top to base+extra, pushing NILs if needed. |
80 | ** (we cannot add base+extra unless we are sure it fits in the stack; | ||
81 | ** otherwise the result of such operation on pointers is undefined) | ||
73 | */ | 82 | */ |
74 | void luaD_adjusttop (lua_State *L, StkId newtop) { | 83 | void luaD_adjusttop (lua_State *L, StkId base, int extra) { |
75 | int diff = newtop-(L->stack.top-L->stack.stack); | 84 | int diff = extra-(L->top-base); |
76 | if (diff <= 0) | 85 | if (diff <= 0) |
77 | L->stack.top += diff; | 86 | L->top = base+extra; |
78 | else { | 87 | else { |
79 | luaD_checkstack(L, diff); | 88 | luaD_checkstack(L, diff); |
80 | while (diff--) | 89 | while (diff--) |
81 | ttype(L->stack.top++) = LUA_T_NIL; | 90 | ttype(L->top++) = LUA_T_NIL; |
82 | } | 91 | } |
83 | } | 92 | } |
84 | 93 | ||
85 | 94 | ||
86 | /* | 95 | /* |
87 | ** Open a hole below "nelems" from the L->stack.top. | 96 | ** Open a hole inside the stack at `pos' |
88 | */ | 97 | */ |
89 | void luaD_openstack (lua_State *L, int nelems) { | 98 | void luaD_openstack (lua_State *L, StkId pos) { |
90 | luaO_memup(L->stack.top-nelems+1, L->stack.top-nelems, | 99 | luaO_memup(pos+1, pos, (L->top-pos)*sizeof(TObject)); |
91 | nelems*sizeof(TObject)); | ||
92 | incr_top; | 100 | incr_top; |
93 | } | 101 | } |
94 | 102 | ||
95 | 103 | ||
96 | void luaD_lineHook (lua_State *L, int line) { | 104 | void luaD_lineHook (lua_State *L, int line) { |
97 | struct C_Lua_Stack oldCLS = L->Cstack; | 105 | struct C_Lua_Stack oldCLS = L->Cstack; |
98 | StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->stack.top-L->stack.stack; | 106 | StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->top; |
99 | L->Cstack.num = 0; | 107 | L->Cstack.num = 0; |
100 | (*L->linehook)(L, line); | 108 | (*L->linehook)(L, line); |
101 | L->stack.top = L->stack.stack+old_top; | 109 | L->top = old_top; |
102 | L->Cstack = oldCLS; | 110 | L->Cstack = oldCLS; |
103 | } | 111 | } |
104 | 112 | ||
105 | 113 | ||
106 | void luaD_callHook (lua_State *L, StkId base, const TProtoFunc *tf, int isreturn) { | 114 | void luaD_callHook (lua_State *L, StkId base, const TProtoFunc *tf, |
115 | int isreturn) { | ||
107 | struct C_Lua_Stack oldCLS = L->Cstack; | 116 | struct C_Lua_Stack oldCLS = L->Cstack; |
108 | StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->stack.top-L->stack.stack; | 117 | StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->top; |
109 | L->Cstack.num = 0; | 118 | L->Cstack.num = 0; |
110 | if (isreturn) | 119 | if (isreturn) |
111 | (*L->callhook)(L, LUA_NOOBJECT, "(return)", 0); | 120 | (*L->callhook)(L, LUA_NOOBJECT, "(return)", 0); |
112 | else { | 121 | else { |
113 | TObject *f = L->stack.stack+base-1; | 122 | TObject *f = base-1; |
114 | if (tf) | 123 | if (tf) |
115 | (*L->callhook)(L, Ref(L, f), tf->source->str, tf->lineDefined); | 124 | (*L->callhook)(L, Ref(L, f), tf->source->str, tf->lineDefined); |
116 | else (*L->callhook)(L, Ref(L, f), "(C)", -1); | 125 | else (*L->callhook)(L, Ref(L, f), "(C)", -1); |
117 | } | 126 | } |
118 | L->stack.top = L->stack.stack+old_top; | 127 | L->top = old_top; |
119 | L->Cstack = oldCLS; | 128 | L->Cstack = oldCLS; |
120 | } | 129 | } |
121 | 130 | ||
@@ -126,43 +135,41 @@ void luaD_callHook (lua_State *L, StkId base, const TProtoFunc *tf, int isreturn | |||
126 | ** first argument. Returns an index to the first result from C. | 135 | ** first argument. Returns an index to the first result from C. |
127 | */ | 136 | */ |
128 | static StkId callC (lua_State *L, lua_CFunction f, StkId base) { | 137 | static StkId callC (lua_State *L, lua_CFunction f, StkId base) { |
129 | struct C_Lua_Stack *cls = &L->Cstack; | 138 | struct C_Lua_Stack oldCLS = L->Cstack; |
130 | struct C_Lua_Stack oldCLS = *cls; | ||
131 | StkId firstResult; | 139 | StkId firstResult; |
132 | int numarg = (L->stack.top-L->stack.stack) - base; | 140 | int numarg = L->top - base; |
133 | cls->num = numarg; | 141 | L->Cstack.num = numarg; |
134 | cls->lua2C = base; | 142 | L->Cstack.lua2C = base; |
135 | cls->base = base+numarg; /* == top-stack */ | 143 | L->Cstack.base = L->top; |
136 | if (L->callhook) | 144 | if (L->callhook) |
137 | luaD_callHook(L, base, NULL, 0); | 145 | luaD_callHook(L, base, NULL, 0); |
138 | (*f)(L); /* do the actual call */ | 146 | (*f)(L); /* do the actual call */ |
139 | if (L->callhook) /* func may have changed callhook */ | 147 | if (L->callhook) /* test again: `func' may have changed callhook */ |
140 | luaD_callHook(L, base, NULL, 1); | 148 | luaD_callHook(L, base, NULL, 1); |
141 | firstResult = cls->base; | 149 | firstResult = L->Cstack.base; |
142 | *cls = oldCLS; | 150 | L->Cstack = oldCLS; |
143 | return firstResult; | 151 | return firstResult; |
144 | } | 152 | } |
145 | 153 | ||
146 | 154 | ||
147 | static StkId callCclosure (lua_State *L, const struct Closure *cl, | 155 | static StkId callCclosure (lua_State *L, const struct Closure *cl, |
148 | lua_CFunction f, StkId base) { | 156 | lua_CFunction f, StkId base) { |
149 | TObject *pbase; | ||
150 | int nup = cl->nelems; /* number of upvalues */ | 157 | int nup = cl->nelems; /* number of upvalues */ |
151 | luaD_checkstack(L, nup); | 158 | luaD_checkstack(L, nup); |
152 | pbase = L->stack.stack+base; /* care: previous call may change this */ | ||
153 | /* open space for upvalues as extra arguments */ | 159 | /* open space for upvalues as extra arguments */ |
154 | luaO_memup(pbase+nup, pbase, (L->stack.top-pbase)*sizeof(TObject)); | 160 | luaO_memup(base+nup, base, (L->top-base)*sizeof(TObject)); |
155 | /* copy upvalues into stack */ | 161 | /* copy upvalues into stack */ |
156 | memcpy(pbase, cl->consts+1, nup*sizeof(TObject)); | 162 | memcpy(base, cl->consts+1, nup*sizeof(TObject)); |
157 | L->stack.top += nup; | 163 | L->top += nup; |
158 | return callC(L, f, base); | 164 | return callC(L, f, base); |
159 | } | 165 | } |
160 | 166 | ||
161 | 167 | ||
162 | void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults) { | 168 | void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults) { |
163 | luaD_openstack(L, nParams); | 169 | StkId base = L->top - nParams; |
164 | *(L->stack.top-nParams-1) = *f; | 170 | luaD_openstack(L, base); |
165 | luaD_call(L, L->stack.top-nParams-1, nResults); | 171 | *base = *f; |
172 | luaD_call(L, base, nResults); | ||
166 | } | 173 | } |
167 | 174 | ||
168 | 175 | ||
@@ -173,26 +180,24 @@ void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults) { | |||
173 | ** function position. | 180 | ** function position. |
174 | ** The number of results is nResults, unless nResults=MULT_RET. | 181 | ** The number of results is nResults, unless nResults=MULT_RET. |
175 | */ | 182 | */ |
176 | void luaD_call (lua_State *L, TObject *func, int nResults) { | 183 | void luaD_call (lua_State *L, StkId func, int nResults) { |
177 | struct Stack *S = &L->stack; /* to optimize */ | ||
178 | StkId base = func - S->stack + 1; /* where is first argument */ | ||
179 | StkId firstResult; | 184 | StkId firstResult; |
180 | switch (ttype(func)) { | 185 | switch (ttype(func)) { |
181 | case LUA_T_CPROTO: | 186 | case LUA_T_CPROTO: |
182 | ttype(func) = LUA_T_CMARK; | 187 | ttype(func) = LUA_T_CMARK; |
183 | firstResult = callC(L, fvalue(func), base); | 188 | firstResult = callC(L, fvalue(func), func+1); |
184 | break; | 189 | break; |
185 | case LUA_T_PROTO: | 190 | case LUA_T_PROTO: |
186 | ttype(func) = LUA_T_PMARK; | 191 | ttype(func) = LUA_T_PMARK; |
187 | firstResult = luaV_execute(L, NULL, tfvalue(func), base); | 192 | firstResult = luaV_execute(L, NULL, tfvalue(func), func+1); |
188 | break; | 193 | break; |
189 | case LUA_T_CLOSURE: { | 194 | case LUA_T_CLOSURE: { |
190 | Closure *c = clvalue(func); | 195 | Closure *c = clvalue(func); |
191 | TObject *proto = c->consts; | 196 | TObject *proto = c->consts; |
192 | ttype(func) = LUA_T_CLMARK; | 197 | ttype(func) = LUA_T_CLMARK; |
193 | firstResult = (ttype(proto) == LUA_T_CPROTO) ? | 198 | firstResult = (ttype(proto) == LUA_T_CPROTO) ? |
194 | callCclosure(L, c, fvalue(proto), base) : | 199 | callCclosure(L, c, fvalue(proto), func+1) : |
195 | luaV_execute(L, c, tfvalue(proto), base); | 200 | luaV_execute(L, c, tfvalue(proto), func+1); |
196 | break; | 201 | break; |
197 | } | 202 | } |
198 | default: { /* func is not a function */ | 203 | default: { /* func is not a function */ |
@@ -200,19 +205,18 @@ void luaD_call (lua_State *L, TObject *func, int nResults) { | |||
200 | const TObject *im = luaT_getimbyObj(L, func, IM_FUNCTION); | 205 | const TObject *im = luaT_getimbyObj(L, func, IM_FUNCTION); |
201 | if (ttype(im) == LUA_T_NIL) | 206 | if (ttype(im) == LUA_T_NIL) |
202 | lua_error(L, "call expression not a function"); | 207 | lua_error(L, "call expression not a function"); |
203 | luaD_callTM(L, im, (S->top-S->stack)-(base-1), nResults); | 208 | luaD_callTM(L, im, L->top-func, nResults); |
204 | return; | 209 | return; |
205 | } | 210 | } |
206 | } | 211 | } |
207 | /* adjust the number of results */ | 212 | /* adjust the number of results */ |
208 | if (nResults == MULT_RET) | 213 | if (nResults == MULT_RET) |
209 | nResults = (S->top-S->stack)-firstResult; | 214 | nResults = L->top - firstResult; |
210 | else | 215 | else |
211 | luaD_adjusttop(L, firstResult+nResults); | 216 | luaD_adjusttop(L, firstResult, nResults); |
212 | /* move results to base-1 (to erase parameters and function) */ | 217 | /* move results to func (to erase parameters and function) */ |
213 | base--; | 218 | luaO_memdown(func, firstResult, nResults*sizeof(TObject)); |
214 | luaO_memdown(S->stack+base, S->stack+firstResult, nResults*sizeof(TObject)); | 219 | L->top = func+nResults; |
215 | S->top -= firstResult-base; | ||
216 | } | 220 | } |
217 | 221 | ||
218 | 222 | ||
@@ -220,10 +224,10 @@ static void message (lua_State *L, const char *s) { | |||
220 | const TObject *em = &(luaS_assertglobalbyname(L, "_ERRORMESSAGE")->value); | 224 | const TObject *em = &(luaS_assertglobalbyname(L, "_ERRORMESSAGE")->value); |
221 | if (ttype(em) == LUA_T_PROTO || ttype(em) == LUA_T_CPROTO || | 225 | if (ttype(em) == LUA_T_PROTO || ttype(em) == LUA_T_CPROTO || |
222 | ttype(em) == LUA_T_CLOSURE) { | 226 | ttype(em) == LUA_T_CLOSURE) { |
223 | *L->stack.top = *em; | 227 | *L->top = *em; |
224 | incr_top; | 228 | incr_top; |
225 | lua_pushstring(L, s); | 229 | lua_pushstring(L, s); |
226 | luaD_call(L, L->stack.top-2, 0); | 230 | luaD_call(L, L->top-2, 0); |
227 | } | 231 | } |
228 | } | 232 | } |
229 | 233 | ||
@@ -253,15 +257,16 @@ int luaD_protectedrun (lua_State *L) { | |||
253 | L->errorJmp = &myErrorJmp; | 257 | L->errorJmp = &myErrorJmp; |
254 | if (setjmp(myErrorJmp.b) == 0) { | 258 | if (setjmp(myErrorJmp.b) == 0) { |
255 | StkId base = L->Cstack.base; | 259 | StkId base = L->Cstack.base; |
256 | luaD_call(L, L->stack.stack+base, MULT_RET); | 260 | luaD_call(L, base, MULT_RET); |
257 | L->Cstack.lua2C = base; /* position of the new results */ | 261 | L->Cstack.lua2C = base; /* position of the new results */ |
258 | L->Cstack.num = (L->stack.top-L->stack.stack) - base; | 262 | L->Cstack.num = L->top - base; |
259 | L->Cstack.base = base + L->Cstack.num; /* incorporate results on stack */ | 263 | L->Cstack.base = base + L->Cstack.num; /* incorporate results on stack */ |
260 | status = 0; | 264 | status = 0; |
261 | } | 265 | } |
262 | else { /* an error occurred: restore L->Cstack and L->stack.top */ | 266 | else { /* an error occurred: restore the stack */ |
263 | L->Cstack = oldCLS; | 267 | L->Cstack = oldCLS; |
264 | L->stack.top = L->stack.stack+L->Cstack.base; | 268 | L->top = L->Cstack.base; |
269 | restore_stack_limit(L); | ||
265 | status = 1; | 270 | status = 1; |
266 | } | 271 | } |
267 | L->errorJmp = oldErr; | 272 | L->errorJmp = oldErr; |
@@ -283,18 +288,18 @@ static int protectedparser (lua_State *L, ZIO *z, int bin) { | |||
283 | tf = bin ? luaU_undump1(L, z) : luaY_parser(L, z); | 288 | tf = bin ? luaU_undump1(L, z) : luaY_parser(L, z); |
284 | status = 0; | 289 | status = 0; |
285 | } | 290 | } |
286 | else { /* an error occurred: restore L->Cstack and L->stack.top */ | 291 | else { /* an error occurred: restore L->Cstack and L->top */ |
287 | L->Cstack = oldCLS; | 292 | L->Cstack = oldCLS; |
288 | L->stack.top = L->stack.stack+L->Cstack.base; | 293 | L->top = L->Cstack.base; |
289 | tf = NULL; | 294 | tf = NULL; |
290 | status = 1; | 295 | status = 1; |
291 | } | 296 | } |
292 | L->errorJmp = oldErr; | 297 | L->errorJmp = oldErr; |
293 | if (status) return 1; /* error code */ | 298 | if (status) return 1; /* error code */ |
294 | if (tf == NULL) return 2; /* 'natural' end */ | 299 | if (tf == NULL) return 2; /* `natural' end */ |
295 | luaD_adjusttop(L, L->Cstack.base+1); /* one slot for the pseudo-function */ | 300 | luaD_adjusttop(L, L->Cstack.base, 1); /* one slot for the pseudo-function */ |
296 | L->stack.stack[L->Cstack.base].ttype = LUA_T_PROTO; | 301 | L->Cstack.base->ttype = LUA_T_PROTO; |
297 | L->stack.stack[L->Cstack.base].value.tf = tf; | 302 | L->Cstack.base->value.tf = tf; |
298 | luaV_closure(L, 0); | 303 | luaV_closure(L, 0); |
299 | return 0; | 304 | return 0; |
300 | } | 305 | } |
@@ -323,7 +328,7 @@ static int do_main (lua_State *L, ZIO *z, int bin) { | |||
323 | void luaD_gcIM (lua_State *L, const TObject *o) { | 328 | void luaD_gcIM (lua_State *L, const TObject *o) { |
324 | const TObject *im = luaT_getimbyObj(L, o, IM_GC); | 329 | const TObject *im = luaT_getimbyObj(L, o, IM_GC); |
325 | if (ttype(im) != LUA_T_NIL) { | 330 | if (ttype(im) != LUA_T_NIL) { |
326 | *L->stack.top = *o; | 331 | *L->top = *o; |
327 | incr_top; | 332 | incr_top; |
328 | luaD_callTM(L, im, 1, 0); | 333 | luaD_callTM(L, im, 1, 0); |
329 | } | 334 | } |