diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1995-10-09 10:10:20 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1995-10-09 10:10:20 -0300 |
commit | 7e0134865866951e522ad95034daf0e044fbedd2 (patch) | |
tree | c16dcca7bdf5c54c803134c9e530c06e1ebc90e2 /opcode.c | |
parent | 28b3017baff1778bd31c3e4d45b8ac676035d1a9 (diff) | |
download | lua-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.c | 176 |
1 files changed, 101 insertions, 75 deletions
@@ -3,7 +3,7 @@ | |||
3 | ** TecCGraf - PUC-Rio | 3 | ** TecCGraf - PUC-Rio |
4 | */ | 4 | */ |
5 | 5 | ||
6 | char *rcs_opcode="$Id: opcode.c,v 3.38 1995/05/16 17:23:58 roberto Exp $"; | 6 | char *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 | ||
56 | static StkId lua_execute (Byte *pc, StkId base); | 56 | static StkId lua_execute (Byte *pc, StkId base); |
57 | static void do_call (Object *func, StkId base, int nResults, StkId whereRes); | 57 | static 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 | |||
72 | static 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 | */ | ||
81 | void 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 | */ | ||
191 | static 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 | */ | ||
223 | static 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 | */ |
238 | static void call_funcFB (Object *func, StkId base, int nResults, StkId whereRes) | 234 | static 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 | */ |
256 | static void do_call (Object *func, StkId base, int nResults, StkId whereRes) | 248 | static 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) | |||
287 | static void pushsubscript (void) | 281 | static 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) | |||
308 | static void storesubscript (void) | 302 | static 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 | |||
330 | static 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 | */ | ||
339 | void 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 | */ |
336 | static int do_protectedrun (Object *function, int nResults) | 356 | static 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 | ||
402 | int lua_call (char *funcname) | 425 | int 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 | */ |
449 | lua_Object lua_setfallback (char *name, lua_CFunction fallback) | 474 | lua_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 | */ |
603 | lua_Object lua_getglobal (char *name) | 630 | lua_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 | ||
715 | static void call_arith (char *op) | 742 | static 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 | ||
721 | static void comparison (lua_Type tag_less, lua_Type tag_equal, | 748 | static 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 | ||