aboutsummaryrefslogtreecommitdiff
path: root/ldo.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>1999-12-01 17:50:08 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>1999-12-01 17:50:08 -0200
commitfe237ad8085f34e89fcd3610a9771215af63f03f (patch)
treef7ee5d8f7d1ffb74e94f049aa6f31eb03606cdf6 /ldo.c
parent3181dfefee40b9a424b80aa779c671f5f458904c (diff)
downloadlua-fe237ad8085f34e89fcd3610a9771215af63f03f.tar.gz
lua-fe237ad8085f34e89fcd3610a9771215af63f03f.tar.bz2
lua-fe237ad8085f34e89fcd3610a9771215af63f03f.zip
fixed stack; first version.
Diffstat (limited to 'ldo.c')
-rw-r--r--ldo.c171
1 files changed, 88 insertions, 83 deletions
diff --git a/ldo.c b/ldo.c
index cadfd650..25632e4b 100644
--- a/ldo.c
+++ b/ldo.c
@@ -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
46void luaD_init (lua_State *L) { 44void 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
53void luaD_checkstack (lua_State *L, int n) { 52void 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
72static 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*/
74void luaD_adjusttop (lua_State *L, StkId newtop) { 83void 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*/
89void luaD_openstack (lua_State *L, int nelems) { 98void 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
96void luaD_lineHook (lua_State *L, int line) { 104void 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
106void luaD_callHook (lua_State *L, StkId base, const TProtoFunc *tf, int isreturn) { 114void 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*/
128static StkId callC (lua_State *L, lua_CFunction f, StkId base) { 137static 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
147static StkId callCclosure (lua_State *L, const struct Closure *cl, 155static 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
162void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults) { 168void 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*/
176void luaD_call (lua_State *L, TObject *func, int nResults) { 183void 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) {
323void luaD_gcIM (lua_State *L, const TObject *o) { 328void 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 }