summaryrefslogtreecommitdiff
path: root/opcode.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>1995-10-09 10:10:20 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>1995-10-09 10:10:20 -0300
commit7e0134865866951e522ad95034daf0e044fbedd2 (patch)
treec16dcca7bdf5c54c803134c9e530c06e1ebc90e2 /opcode.c
parent28b3017baff1778bd31c3e4d45b8ac676035d1a9 (diff)
downloadlua-7e0134865866951e522ad95034daf0e044fbedd2.tar.gz
lua-7e0134865866951e522ad95034daf0e044fbedd2.tar.bz2
lua-7e0134865866951e522ad95034daf0e044fbedd2.zip
"docall" now assumes that called function is always on the stack, just
below "base". That gives more regularity for the stack shape, and prevents fallbacks of being garbage collected if they are redefined during execution.
Diffstat (limited to 'opcode.c')
-rw-r--r--opcode.c176
1 files changed, 101 insertions, 75 deletions
diff --git a/opcode.c b/opcode.c
index 78fabf25..1fb831c7 100644
--- a/opcode.c
+++ b/opcode.c
@@ -3,7 +3,7 @@
3** TecCGraf - PUC-Rio 3** TecCGraf - PUC-Rio
4*/ 4*/
5 5
6char *rcs_opcode="$Id: opcode.c,v 3.38 1995/05/16 17:23:58 roberto Exp $"; 6char *rcs_opcode="$Id: opcode.c,v 3.40 1995/10/04 14:20:26 roberto Exp roberto $";
7 7
8#include <setjmp.h> 8#include <setjmp.h>
9#include <stdlib.h> 9#include <stdlib.h>
@@ -54,7 +54,7 @@ static jmp_buf *errorJmp = NULL; /* current error recover point */
54 54
55 55
56static StkId lua_execute (Byte *pc, StkId base); 56static StkId lua_execute (Byte *pc, StkId base);
57static void do_call (Object *func, StkId base, int nResults, StkId whereRes); 57static void do_call (StkId base, int nResults);
58 58
59 59
60 60
@@ -64,32 +64,6 @@ Object *luaI_Address (lua_Object o)
64} 64}
65 65
66 66
67/*
68** Error messages
69*/
70
71
72static void lua_message (char *s)
73{
74 luaI_reportbug(s, 1);
75 do_call(&luaI_fallBacks[FB_ERROR].function, (top-stack)-1, 0, (top-stack)-1);
76}
77
78/*
79** Reports an error, and jumps up to the available recover label
80*/
81void lua_error (char *s)
82{
83 if (s) lua_message(s);
84 if (errorJmp)
85 longjmp(*errorJmp, 1);
86 else
87 {
88 fprintf (stderr, "lua: exit(1). Unable to recover\n");
89 exit(1);
90 }
91}
92
93 67
94/* 68/*
95** Init stack 69** Init stack
@@ -211,6 +185,17 @@ static void adjustC (int nParams)
211 adjust_top(CBase+nParams); 185 adjust_top(CBase+nParams);
212} 186}
213 187
188/*
189** Open a hole below "nelems" from the top.
190*/
191static void open_stack (int nelems)
192{
193 int i;
194 for (i=0; i<nelems; i++)
195 *(top-i) = *(top-i-1);
196 incr_top;
197}
198
214 199
215/* 200/*
216** Call a C function. CBase will point to the top of the stack, 201** Call a C function. CBase will point to the top of the stack,
@@ -233,49 +218,58 @@ static StkId callC (lua_CFunction func, StkId base)
233} 218}
234 219
235/* 220/*
221** Call the specified fallback, putting it on the stack below its arguments
222*/
223static void callFB (int fb)
224{
225 int nParams = luaI_fallBacks[fb].nParams;
226 open_stack(nParams);
227 *(top-nParams-1) = luaI_fallBacks[fb].function;
228 do_call((top-stack)-nParams, luaI_fallBacks[fb].nResults);
229}
230
231/*
236** Call the fallback for invalid functions (see do_call) 232** Call the fallback for invalid functions (see do_call)
237*/ 233*/
238static void call_funcFB (Object *func, StkId base, int nResults, StkId whereRes) 234static void call_funcFB (StkId base, int nResults)
239{ 235{
240 StkId i; 236 open_stack((top-stack)-(base-1));
241 /* open space for first parameter (func) */ 237 stack[base-1] = luaI_fallBacks[FB_FUNCTION].function;
242 for (i=top-stack; i>base; i--) 238 do_call(base, nResults);
243 stack[i] = stack[i-1];
244 incr_top;
245 stack[base] = *func;
246 do_call(&luaI_fallBacks[FB_FUNCTION].function, base, nResults, whereRes);
247} 239}
248 240
249 241
250/* 242/*
251** Call a function (C or Lua). The parameters must be on the stack, 243** Call a function (C or Lua). The parameters must be on the stack,
252** between [stack+base,top). When returns, the results are on the stack, 244** between [stack+base,top). The function to be called is at stack+base-1.
253** between [stack+whereRes,top). The number of results is nResults, unless 245** When returns, the results are on the stack, between [stack+base-1,top).
254** nResults=MULT_RET. 246** The number of results is nResults, unless nResults=MULT_RET.
255*/ 247*/
256static void do_call (Object *func, StkId base, int nResults, StkId whereRes) 248static void do_call (StkId base, int nResults)
257{ 249{
258 StkId firstResult; 250 StkId firstResult;
251 Object *func = stack+base-1;
259 if (tag(func) == LUA_T_CFUNCTION) 252 if (tag(func) == LUA_T_CFUNCTION)
260 firstResult = callC(fvalue(func), base); 253 firstResult = callC(fvalue(func), base);
261 else if (tag(func) == LUA_T_FUNCTION) 254 else if (tag(func) == LUA_T_FUNCTION)
262 firstResult = lua_execute(func->value.tf->code, base); 255 firstResult = lua_execute(func->value.tf->code, base);
263 else 256 else
264 { /* func is not a function */ 257 { /* func is not a function */
265 call_funcFB(func, base, nResults, whereRes); 258 call_funcFB(base, nResults);
266 return; 259 return;
267 } 260 }
268 /* adjust the number of results */ 261 /* adjust the number of results */
269 if (nResults != MULT_RET && top - (stack+firstResult) != nResults) 262 if (nResults != MULT_RET && top - (stack+firstResult) != nResults)
270 adjust_top(firstResult+nResults); 263 adjust_top(firstResult+nResults);
271 /* move results to the given position */ 264 /* move results to base-1 (to erase parameters and function) */
272 if (firstResult != whereRes) 265 base--;
266 if (firstResult != base)
273 { 267 {
274 int i; 268 int i;
275 nResults = top - (stack+firstResult); /* actual number of results */ 269 nResults = top - (stack+firstResult); /* actual number of results */
276 for (i=0; i<nResults; i++) 270 for (i=0; i<nResults; i++)
277 *(stack+whereRes+i) = *(stack+firstResult+i); 271 *(stack+base+i) = *(stack+firstResult+i);
278 top -= firstResult-whereRes; 272 top -= firstResult-base;
279 } 273 }
280} 274}
281 275
@@ -287,12 +281,12 @@ static void do_call (Object *func, StkId base, int nResults, StkId whereRes)
287static void pushsubscript (void) 281static void pushsubscript (void)
288{ 282{
289 if (tag(top-2) != LUA_T_ARRAY) 283 if (tag(top-2) != LUA_T_ARRAY)
290 do_call(&luaI_fallBacks[FB_GETTABLE].function, (top-stack)-2, 1, (top-stack)-2); 284 callFB(FB_GETTABLE);
291 else 285 else
292 { 286 {
293 Object *h = lua_hashget(avalue(top-2), top-1); 287 Object *h = lua_hashget(avalue(top-2), top-1);
294 if (h == NULL || tag(h) == LUA_T_NIL) 288 if (h == NULL || tag(h) == LUA_T_NIL)
295 do_call(&luaI_fallBacks[FB_INDEX].function, (top-stack)-2, 1, (top-stack)-2); 289 callFB(FB_INDEX);
296 else 290 else
297 { 291 {
298 --top; 292 --top;
@@ -308,7 +302,7 @@ static void pushsubscript (void)
308static void storesubscript (void) 302static void storesubscript (void)
309{ 303{
310 if (tag(top-3) != LUA_T_ARRAY) 304 if (tag(top-3) != LUA_T_ARRAY)
311 do_call(&luaI_fallBacks[FB_SETTABLE].function, (top-stack)-3, 0, (top-stack)-3); 305 callFB(FB_SETTABLE);
312 else 306 else
313 { 307 {
314 Object *h = lua_hashdefine (avalue(top-3), top-2); 308 Object *h = lua_hashdefine (avalue(top-3), top-2);
@@ -330,10 +324,36 @@ void lua_travstack (void (*fn)(Object *))
330 324
331 325
332/* 326/*
333** Execute a protected call. If function is null compiles the pre-set input. 327** Error messages
334** Leave nResults on the stack. 328*/
329
330static void lua_message (char *s)
331{
332 luaI_reportbug(s, 1);
333 callFB(FB_ERROR);
334}
335
336/*
337** Reports an error, and jumps up to the available recover label
338*/
339void lua_error (char *s)
340{
341 if (s) lua_message(s);
342 if (errorJmp)
343 longjmp(*errorJmp, 1);
344 else
345 {
346 fprintf (stderr, "lua: exit(1). Unable to recover\n");
347 exit(1);
348 }
349}
350
351
352/*
353** Execute a protected call. Assumes that function is at CBase and
354** parameters are on top of it. Leave nResults on the stack.
335*/ 355*/
336static int do_protectedrun (Object *function, int nResults) 356static int do_protectedrun (int nResults)
337{ 357{
338 jmp_buf myErrorJmp; 358 jmp_buf myErrorJmp;
339 int status; 359 int status;
@@ -342,13 +362,13 @@ static int do_protectedrun (Object *function, int nResults)
342 errorJmp = &myErrorJmp; 362 errorJmp = &myErrorJmp;
343 if (setjmp(myErrorJmp) == 0) 363 if (setjmp(myErrorJmp) == 0)
344 { 364 {
345 do_call(function, CBase, nResults, CBase); 365 do_call(CBase+1, nResults);
346 CnResults = (top-stack) - CBase; /* number of results */ 366 CnResults = (top-stack) - CBase; /* number of results */
347 CBase += CnResults; /* incorporate results on the stack */ 367 CBase += CnResults; /* incorporate results on the stack */
348 status = 0; 368 status = 0;
349 } 369 }
350 else 370 else
351 { 371 { /* an error occurred: restore CBase and top */
352 CBase = oldCBase; 372 CBase = oldCBase;
353 top = stack+CBase; 373 top = stack+CBase;
354 status = 1; 374 status = 1;
@@ -362,27 +382,26 @@ static int do_protectedmain (void)
362{ 382{
363 TFunc tf; 383 TFunc tf;
364 int status; 384 int status;
365 StkId oldCBase = CBase;
366 jmp_buf myErrorJmp; 385 jmp_buf myErrorJmp;
367 jmp_buf *oldErr = errorJmp; 386 jmp_buf *oldErr = errorJmp;
368 errorJmp = &myErrorJmp; 387 errorJmp = &myErrorJmp;
388 adjustC(1); /* one slot for the pseudo-function */
389 stack[CBase].tag = LUA_T_FUNCTION;
390 stack[CBase].value.tf = &tf;
369 tf.code = NULL; 391 tf.code = NULL;
370 if (setjmp(myErrorJmp) == 0) 392 if (setjmp(myErrorJmp) == 0)
371 { 393 {
372 Object f;
373 f.tag = LUA_T_FUNCTION;
374 f.value.tf = &tf;
375 lua_parse(&tf); 394 lua_parse(&tf);
376 do_call(&f, CBase, 0, CBase); 395 status = do_protectedrun(0);
377 status = 0;
378 } 396 }
379 else 397 else
398 {
380 status = 1; 399 status = 1;
400 adjustC(0); /* erase extra slot */
401 }
402 errorJmp = oldErr;
381 if (tf.code) 403 if (tf.code)
382 luaI_free(tf.code); 404 luaI_free(tf.code);
383 errorJmp = oldErr;
384 CBase = oldCBase;
385 top = stack+CBase;
386 return status; 405 return status;
387} 406}
388 407
@@ -395,14 +414,20 @@ int lua_callfunction (lua_Object function)
395 if (function == LUA_NOOBJECT) 414 if (function == LUA_NOOBJECT)
396 return 1; 415 return 1;
397 else 416 else
398 return do_protectedrun (Address(function), MULT_RET); 417 {
418 open_stack((top-stack)-CBase);
419 stack[CBase] = *Address(function);
420 return do_protectedrun (MULT_RET);
421 }
399} 422}
400 423
401 424
402int lua_call (char *funcname) 425int lua_call (char *funcname)
403{ 426{
404 Word n = luaI_findsymbolbyname(funcname); 427 Word n = luaI_findsymbolbyname(funcname);
405 return do_protectedrun(&s_object(n), MULT_RET); 428 open_stack((top-stack)-CBase);
429 stack[CBase] = s_object(n);
430 return do_protectedrun(MULT_RET);
406} 431}
407 432
408 433
@@ -448,11 +473,12 @@ int lua_dostring (char *string)
448*/ 473*/
449lua_Object lua_setfallback (char *name, lua_CFunction fallback) 474lua_Object lua_setfallback (char *name, lua_CFunction fallback)
450{ 475{
451 static Object func = {LUA_T_CFUNCTION, {luaI_setfallback}}; 476 adjustC(1); /* one slot for the pseudo-function */
452 adjustC(0); 477 stack[CBase].tag = LUA_T_CFUNCTION;
478 stack[CBase].value.f = luaI_setfallback;
453 lua_pushstring(name); 479 lua_pushstring(name);
454 lua_pushcfunction(fallback); 480 lua_pushcfunction(fallback);
455 do_protectedrun(&func, 1); 481 do_protectedrun(1);
456 return (Ref(top-1)); 482 return (Ref(top-1));
457} 483}
458 484
@@ -597,8 +623,9 @@ int lua_lock (void)
597} 623}
598 624
599 625
626
600/* 627/*
601** Get a global object. Return the object handle or NULL on error. 628** Get a global object.
602*/ 629*/
603lua_Object lua_getglobal (char *name) 630lua_Object lua_getglobal (char *name)
604{ 631{
@@ -708,14 +735,14 @@ void luaI_gcFB (Object *o)
708{ 735{
709 *top = *o; 736 *top = *o;
710 incr_top; 737 incr_top;
711 do_call(&luaI_fallBacks[FB_GC].function, (top-stack)-1, 0, (top-stack)-1); 738 callFB(FB_GC);
712} 739}
713 740
714 741
715static void call_arith (char *op) 742static void call_arith (char *op)
716{ 743{
717 lua_pushstring(op); 744 lua_pushstring(op);
718 do_call(&luaI_fallBacks[FB_ARITH].function, (top-stack)-3, 1, (top-stack)-3); 745 callFB(FB_ARITH);
719} 746}
720 747
721static void comparison (lua_Type tag_less, lua_Type tag_equal, 748static void comparison (lua_Type tag_less, lua_Type tag_equal,
@@ -729,7 +756,7 @@ static void comparison (lua_Type tag_less, lua_Type tag_equal,
729 else if (tostring(l) || tostring(r)) 756 else if (tostring(l) || tostring(r))
730 { 757 {
731 lua_pushstring(op); 758 lua_pushstring(op);
732 do_call(&luaI_fallBacks[FB_ORDER].function, (top-stack)-3, 1, (top-stack)-3); 759 callFB(FB_ORDER);
733 return; 760 return;
734 } 761 }
735 else 762 else
@@ -867,7 +894,7 @@ static StkId lua_execute (Byte *pc, StkId base)
867 *(top) = *(top-2-n); 894 *(top) = *(top-2-n);
868 *(top-1) = *(top-3-n); 895 *(top-1) = *(top-3-n);
869 top += 2; 896 top += 2;
870 do_call(&luaI_fallBacks[FB_SETTABLE].function, (top-stack)-3, 0, (top-stack)-3); 897 callFB(FB_SETTABLE);
871 } 898 }
872 else 899 else
873 { 900 {
@@ -1021,7 +1048,7 @@ static StkId lua_execute (Byte *pc, StkId base)
1021 Object *l = top-2; 1048 Object *l = top-2;
1022 Object *r = top-1; 1049 Object *r = top-1;
1023 if (tostring(r) || tostring(l)) 1050 if (tostring(r) || tostring(l))
1024 do_call(&luaI_fallBacks[FB_CONCAT].function, (top-stack)-2, 1, (top-stack)-2); 1051 callFB(FB_CONCAT);
1025 else 1052 else
1026 { 1053 {
1027 tsvalue(l) = lua_createstring (lua_strconc(svalue(l),svalue(r))); 1054 tsvalue(l) = lua_createstring (lua_strconc(svalue(l),svalue(r)));
@@ -1102,9 +1129,8 @@ static StkId lua_execute (Byte *pc, StkId base)
1102 { 1129 {
1103 int nParams = *(pc++); 1130 int nParams = *(pc++);
1104 int nResults = *(pc++); 1131 int nResults = *(pc++);
1105 Object *func = top-1-nParams; /* function is below parameters */
1106 StkId newBase = (top-stack)-nParams; 1132 StkId newBase = (top-stack)-nParams;
1107 do_call(func, newBase, nResults, newBase-1); 1133 do_call(newBase, nResults);
1108 } 1134 }
1109 break; 1135 break;
1110 1136