diff options
Diffstat (limited to 'src/opcode.c')
-rw-r--r-- | src/opcode.c | 396 |
1 files changed, 226 insertions, 170 deletions
diff --git a/src/opcode.c b/src/opcode.c index 7ce5b2a6..e4089f01 100644 --- a/src/opcode.c +++ b/src/opcode.c @@ -3,14 +3,14 @@ ** TecCGraf - PUC-Rio */ -char *rcs_opcode="$Id: opcode.c,v 3.34 1995/02/06 19:35:09 roberto Exp $"; +char *rcs_opcode="$Id: opcode.c,v 3.50 1995/11/16 20:46:24 roberto Exp $"; #include <setjmp.h> #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <math.h> +#include "luadebug.h" #include "mem.h" #include "opcode.h" #include "hash.h" @@ -23,13 +23,15 @@ char *rcs_opcode="$Id: opcode.c,v 3.34 1995/02/06 19:35:09 roberto Exp $"; #define tostring(o) ((tag(o) != LUA_T_STRING) && (lua_tostring(o) != 0)) -#define STACK_BUFFER (STACKGAP+128) +#define STACK_SIZE 128 typedef int StkId; /* index to stack elements */ -static Long maxstack = 0L; -static Object *stack = NULL; -static Object *top = NULL; +static Object initial_stack; + +static Object *stackLimit = &initial_stack+1; +static Object *stack = &initial_stack; +static Object *top = &initial_stack; /* macros to convert from lua_Object to (Object *) and back */ @@ -38,6 +40,11 @@ static Object *top = NULL; #define Ref(st) ((st)-stack+1) +/* macro to increment stack top. There must be always an empty slot in +* the stack +*/ +#define incr_top if (++top >= stackLimit) growstack() + static StkId CBase = 0; /* when Lua calls C or C calls Lua, points to */ /* the first slot after the last parameter. */ static int CnResults = 0; /* when Lua calls C, has the number of parameters; */ @@ -47,7 +54,7 @@ static jmp_buf *errorJmp = NULL; /* current error recover point */ static StkId lua_execute (Byte *pc, StkId base); -static void do_call (Object *func, StkId base, int nResults, StkId whereRes); +static void do_call (StkId base, int nResults); @@ -57,61 +64,40 @@ Object *luaI_Address (lua_Object o) } -/* -** Error messages -*/ - -static void lua_message (char *s) -{ - lua_pushstring(s); - do_call(&luaI_fallBacks[FB_ERROR].function, (top-stack)-1, 0, (top-stack)-1); -} - -/* -** Reports an error, and jumps up to the available recover label -*/ -void lua_error (char *s) -{ - if (s) lua_message(s); - if (errorJmp) - longjmp(*errorJmp, 1); - else - { - fprintf (stderr, "lua: exit(1). Unable to recover\n"); - exit(1); - } -} - /* ** Init stack */ static void lua_initstack (void) { - maxstack = STACK_BUFFER; + Long maxstack = STACK_SIZE; stack = newvector(maxstack, Object); + stackLimit = stack+maxstack; top = stack; + *(top++) = initial_stack; } /* ** Check stack overflow and, if necessary, realloc vector */ -#define lua_checkstack(n) if ((Long)(n) > maxstack) checkstack(n) +#define lua_checkstack(nt) if ((nt) >= stackLimit) growstack() -static void checkstack (StkId n) +static void growstack (void) { - StkId t; - if (stack == NULL) + if (stack == &initial_stack) lua_initstack(); - if (maxstack >= MAX_INT) - lua_error("stack size overflow"); - t = top-stack; - maxstack *= 2; - if (maxstack >= MAX_INT) - maxstack = MAX_INT; - stack = growvector(stack, maxstack, Object); - top = stack + t; + else + { + StkId t = top-stack; + Long maxstack = stackLimit - stack; + maxstack *= 2; + stack = growvector(stack, maxstack, Object); + stackLimit = stack+maxstack; + top = stack + t; + if (maxstack >= MAX_WORD/2) + lua_error("stack size overflow"); + } } @@ -184,15 +170,25 @@ static int lua_tostring (Object *obj) */ static void adjust_top (StkId newtop) { - Object *nt = stack+newtop; + Object *nt; + lua_checkstack(stack+newtop); + nt = stack+newtop; /* warning: previous call may change stack */ while (top < nt) tag(top++) = LUA_T_NIL; top = nt; /* top could be bigger than newtop */ } +#define adjustC(nParams) adjust_top(CBase+nParams) + -static void adjustC (int nParams) +/* +** Open a hole below "nelems" from the top. +*/ +static void open_stack (int nelems) { - adjust_top(CBase+nParams); + int i; + for (i=0; i<nelems; i++) + *(top-i) = *(top-i-1); + incr_top; } @@ -217,50 +213,55 @@ static StkId callC (lua_CFunction func, StkId base) } /* -** Call the fallback for invalid functions (see do_call) +** Call the specified fallback, putting it on the stack below its arguments */ -static void call_funcFB (Object *func, StkId base, int nResults, StkId whereRes) +static void callFB (int fb) { - StkId i; - /* open space for first parameter (func) */ - for (i=top-stack; i>base; i--) - stack[i] = stack[i-1]; - top++; - stack[base] = *func; - do_call(&luaI_fallBacks[FB_FUNCTION].function, base, nResults, whereRes); + int nParams = luaI_fallBacks[fb].nParams; + open_stack(nParams); + *(top-nParams-1) = luaI_fallBacks[fb].function; + do_call((top-stack)-nParams, luaI_fallBacks[fb].nResults); } /* ** Call a function (C or Lua). The parameters must be on the stack, -** between [stack+base,top). When returns, the results are on the stack, -** between [stack+whereRes,top). The number of results is nResults, unless -** nResults=MULT_RET. +** between [stack+base,top). The function to be called is at stack+base-1. +** When returns, the results are on the stack, between [stack+base-1,top). +** The number of results is nResults, unless nResults=MULT_RET. */ -static void do_call (Object *func, StkId base, int nResults, StkId whereRes) +static void do_call (StkId base, int nResults) { StkId firstResult; + Object *func = stack+base-1; + int i; if (tag(func) == LUA_T_CFUNCTION) + { + tag(func) = LUA_T_CMARK; firstResult = callC(fvalue(func), base); + } else if (tag(func) == LUA_T_FUNCTION) - firstResult = lua_execute(bvalue(func), base); + { + tag(func) = LUA_T_MARK; + firstResult = lua_execute(func->value.tf->code, base); + } else { /* func is not a function */ - call_funcFB(func, base, nResults, whereRes); + /* Call the fallback for invalid functions */ + open_stack((top-stack)-(base-1)); + stack[base-1] = luaI_fallBacks[FB_FUNCTION].function; + do_call(base, nResults); return; } /* adjust the number of results */ if (nResults != MULT_RET && top - (stack+firstResult) != nResults) adjust_top(firstResult+nResults); - /* move results to the given position */ - if (firstResult != whereRes) - { - int i; - nResults = top - (stack+firstResult); /* actual number of results */ - for (i=0; i<nResults; i++) - *(stack+whereRes+i) = *(stack+firstResult+i); - top -= firstResult-whereRes; - } + /* move results to base-1 (to erase parameters and function) */ + base--; + nResults = top - (stack+firstResult); /* actual number of results */ + for (i=0; i<nResults; i++) + *(stack+base+i) = *(stack+firstResult+i); + top -= firstResult-base; } @@ -271,12 +272,12 @@ static void do_call (Object *func, StkId base, int nResults, StkId whereRes) static void pushsubscript (void) { if (tag(top-2) != LUA_T_ARRAY) - do_call(&luaI_fallBacks[FB_GETTABLE].function, (top-stack)-2, 1, (top-stack)-2); + callFB(FB_GETTABLE); else { Object *h = lua_hashget(avalue(top-2), top-1); if (h == NULL || tag(h) == LUA_T_NIL) - do_call(&luaI_fallBacks[FB_INDEX].function, (top-stack)-2, 1, (top-stack)-2); + callFB(FB_INDEX); else { --top; @@ -292,7 +293,7 @@ static void pushsubscript (void) static void storesubscript (void) { if (tag(top-3) != LUA_T_ARRAY) - do_call(&luaI_fallBacks[FB_SETTABLE].function, (top-stack)-3, 0, (top-stack)-3); + callFB(FB_SETTABLE); else { Object *h = lua_hashdefine (avalue(top-3), top-2); @@ -305,19 +306,63 @@ static void storesubscript (void) /* ** Traverse all objects on stack */ -void lua_travstack (void (*fn)(Object *)) +void lua_travstack (int (*fn)(Object *)) { Object *o; for (o = top-1; o >= stack; o--) - fn (o); + fn (o); } /* -** Execute a protected call. If function is null compiles the pre-set input. -** Leave nResults on the stack. +** Error messages and debug functions +*/ + +static void lua_message (char *s) +{ + lua_pushstring(s); + callFB(FB_ERROR); +} + +/* +** Reports an error, and jumps up to the available recover label */ -static int do_protectedrun (Object *function, int nResults) +void lua_error (char *s) +{ + if (s) lua_message(s); + if (errorJmp) + longjmp(*errorJmp, 1); + else + { + fprintf (stderr, "lua: exit(1). Unable to recover\n"); + exit(1); + } +} + + +lua_Object lua_stackedfunction (int level) +{ + Object *p = top; + while (--p >= stack) + if (p->tag == LUA_T_MARK || p->tag == LUA_T_CMARK) + if (level-- == 0) + return Ref(p); + return LUA_NOOBJECT; +} + + +int lua_currentline (lua_Object func) +{ + Object *f = Address(func); + return (f+1 < top && (f+1)->tag == LUA_T_LINE) ? (f+1)->value.i : -1; +} + + +/* +** Execute a protected call. Assumes that function is at CBase and +** parameters are on top of it. Leave nResults on the stack. +*/ +static int do_protectedrun (int nResults) { jmp_buf myErrorJmp; int status; @@ -326,13 +371,13 @@ static int do_protectedrun (Object *function, int nResults) errorJmp = &myErrorJmp; if (setjmp(myErrorJmp) == 0) { - do_call(function, CBase, nResults, CBase); + do_call(CBase+1, nResults); CnResults = (top-stack) - CBase; /* number of results */ CBase += CnResults; /* incorporate results on the stack */ status = 0; } else - { + { /* an error occurred: restore CBase and top */ CBase = oldCBase; top = stack+CBase; status = 1; @@ -344,27 +389,30 @@ static int do_protectedrun (Object *function, int nResults) static int do_protectedmain (void) { - Byte *code = NULL; + TFunc tf; int status; - StkId oldCBase = CBase; jmp_buf myErrorJmp; jmp_buf *oldErr = errorJmp; errorJmp = &myErrorJmp; + adjustC(1); /* one slot for the pseudo-function */ + stack[CBase].tag = LUA_T_FUNCTION; + stack[CBase].value.tf = &tf; + tf.lineDefined = 0; + tf.fileName = lua_parsedfile; + tf.code = NULL; if (setjmp(myErrorJmp) == 0) { - Object f; - lua_parse(&code); - tag(&f) = LUA_T_FUNCTION; bvalue(&f) = code; - do_call(&f, CBase, 0, CBase); - status = 0; + lua_parse(&tf); + status = do_protectedrun(0); } else + { status = 1; - if (code) - luaI_free(code); + adjustC(0); /* erase extra slot */ + } errorJmp = oldErr; - CBase = oldCBase; - top = stack+CBase; + if (tf.code) + luaI_free(tf.code); return status; } @@ -377,14 +425,20 @@ int lua_callfunction (lua_Object function) if (function == LUA_NOOBJECT) return 1; else - return do_protectedrun (Address(function), MULT_RET); + { + open_stack((top-stack)-CBase); + stack[CBase] = *Address(function); + return do_protectedrun (MULT_RET); + } } int lua_call (char *funcname) { Word n = luaI_findsymbolbyname(funcname); - return do_protectedrun(&s_object(n), MULT_RET); + open_stack((top-stack)-CBase); + stack[CBase] = s_object(n); + return do_protectedrun(MULT_RET); } @@ -413,12 +467,7 @@ int lua_dofile (char *filename) int lua_dostring (char *string) { int status; - char *message = lua_openstring(string); - if (message) - { - lua_message(message); - return 1; - } + lua_openstring(string); status = do_protectedmain(); lua_closestring(); return status; @@ -430,12 +479,15 @@ int lua_dostring (char *string) */ lua_Object lua_setfallback (char *name, lua_CFunction fallback) { - static Object func = {LUA_T_CFUNCTION, luaI_setfallback}; - adjustC(0); + adjustC(1); /* one slot for the pseudo-function */ + stack[CBase].tag = LUA_T_CFUNCTION; + stack[CBase].value.f = luaI_setfallback; lua_pushstring(name); lua_pushcfunction(fallback); - do_protectedrun(&func, 1); - return (Ref(top-1)); + if (do_protectedrun(1) == 0) + return (Ref(top-1)); + else + return LUA_NOOBJECT; } @@ -497,7 +549,7 @@ lua_Object lua_createtable (void) adjustC(0); avalue(top) = lua_createarray(0); tag(top) = LUA_T_ARRAY; - top++; + incr_top; CBase++; /* incorporate object in the stack */ return Ref(top-1); } @@ -519,9 +571,9 @@ lua_Object lua_getparam (int number) */ real lua_getnumber (lua_Object object) { - if (object == LUA_NOOBJECT || tag(Address(object)) == LUA_T_NIL) return 0.0; + if (object == LUA_NOOBJECT) return 0.0; if (tonumber (Address(object))) return 0.0; - else return (nvalue(Address(object))); + else return (nvalue(Address(object))); } /* @@ -529,7 +581,7 @@ real lua_getnumber (lua_Object object) */ char *lua_getstring (lua_Object object) { - if (object == LUA_NOOBJECT || tag(Address(object)) == LUA_T_NIL) return NULL; + if (object == LUA_NOOBJECT) return NULL; if (tostring (Address(object))) return NULL; else return (svalue(Address(object))); } @@ -559,7 +611,7 @@ lua_Object lua_getlocked (int ref) { adjustC(0); *top = *luaI_getlocked(ref); - top++; + incr_top; CBase++; /* incorporate object in the stack */ return Ref(top-1); } @@ -567,9 +619,8 @@ lua_Object lua_getlocked (int ref) void lua_pushlocked (int ref) { - lua_checkstack(top-stack+1); *top = *luaI_getlocked(ref); - top++; + incr_top; } @@ -580,15 +631,16 @@ int lua_lock (void) } + /* -** Get a global object. Return the object handle or NULL on error. +** Get a global object. */ lua_Object lua_getglobal (char *name) { Word n = luaI_findsymbolbyname(name); adjustC(0); *top = s_object(n); - top++; + incr_top; CBase++; /* incorporate object in the stack */ return Ref(top-1); } @@ -608,8 +660,8 @@ void lua_storeglobal (char *name) */ void lua_pushnil (void) { - lua_checkstack(top-stack+1); - tag(top++) = LUA_T_NIL; + tag(top) = LUA_T_NIL; + incr_top; } /* @@ -617,8 +669,8 @@ void lua_pushnil (void) */ void lua_pushnumber (real n) { - lua_checkstack(top-stack+1); - tag(top) = LUA_T_NUMBER; nvalue(top++) = n; + tag(top) = LUA_T_NUMBER; nvalue(top) = n; + incr_top; } /* @@ -626,10 +678,9 @@ void lua_pushnumber (real n) */ void lua_pushstring (char *s) { - lua_checkstack(top-stack+1); tsvalue(top) = lua_createstring(s); tag(top) = LUA_T_STRING; - top++; + incr_top; } /* @@ -637,10 +688,9 @@ void lua_pushstring (char *s) */ void lua_pushliteral (char *s) { - lua_checkstack(top-stack+1); - tsvalue(top) = lua_constant[luaI_findconstant(lua_constcreate(s))]; + tsvalue(top) = lua_constant[luaI_findconstantbyname(s)]; tag(top) = LUA_T_STRING; - top++; + incr_top; } /* @@ -648,8 +698,8 @@ void lua_pushliteral (char *s) */ void lua_pushcfunction (lua_CFunction fn) { - lua_checkstack(top-stack+1); - tag(top) = LUA_T_CFUNCTION; fvalue(top++) = fn; + tag(top) = LUA_T_CFUNCTION; fvalue(top) = fn; + incr_top; } /* @@ -658,8 +708,8 @@ void lua_pushcfunction (lua_CFunction fn) void lua_pushusertag (void *u, int tag) { if (tag < LUA_T_USERDATA) return; - lua_checkstack(top-stack+1); - tag(top) = tag; uvalue(top++) = u; + tag(top) = tag; uvalue(top) = u; + incr_top; } /* @@ -667,8 +717,8 @@ void lua_pushusertag (void *u, int tag) */ void lua_pushobject (lua_Object o) { - lua_checkstack(top-stack+1); - *top++ = *Address(o); + *top = *Address(o); + incr_top; } /* @@ -676,8 +726,8 @@ void lua_pushobject (lua_Object o) */ void luaI_pushobject (Object *o) { - lua_checkstack(top-stack+1); - *top++ = *o; + *top = *o; + incr_top; } int lua_type (lua_Object o) @@ -691,15 +741,16 @@ int lua_type (lua_Object o) void luaI_gcFB (Object *o) { - *(top++) = *o; - do_call(&luaI_fallBacks[FB_GC].function, (top-stack)-1, 0, (top-stack)-1); + *top = *o; + incr_top; + callFB(FB_GC); } static void call_arith (char *op) { lua_pushstring(op); - do_call(&luaI_fallBacks[FB_ARITH].function, (top-stack)-3, 1, (top-stack)-3); + callFB(FB_ARITH); } static void comparison (lua_Type tag_less, lua_Type tag_equal, @@ -713,7 +764,7 @@ static void comparison (lua_Type tag_less, lua_Type tag_equal, else if (tostring(l) || tostring(r)) { lua_pushstring(op); - do_call(&luaI_fallBacks[FB_ORDER].function, (top-stack)-3, 1, (top-stack)-3); + callFB(FB_ORDER); return; } else @@ -732,26 +783,28 @@ static void comparison (lua_Type tag_less, lua_Type tag_equal, */ static StkId lua_execute (Byte *pc, StkId base) { - lua_checkstack(STACKGAP+MAX_TEMPS+base); while (1) { OpCode opcode; switch (opcode = (OpCode)*pc++) { - case PUSHNIL: tag(top++) = LUA_T_NIL; break; + case PUSHNIL: tag(top) = LUA_T_NIL; incr_top; break; case PUSH0: case PUSH1: case PUSH2: tag(top) = LUA_T_NUMBER; - nvalue(top++) = opcode-PUSH0; + nvalue(top) = opcode-PUSH0; + incr_top; break; - case PUSHBYTE: tag(top) = LUA_T_NUMBER; nvalue(top++) = *pc++; break; + case PUSHBYTE: + tag(top) = LUA_T_NUMBER; nvalue(top) = *pc++; incr_top; break; case PUSHWORD: { CodeWord code; get_word(code,pc); - tag(top) = LUA_T_NUMBER; nvalue(top++) = code.w; + tag(top) = LUA_T_NUMBER; nvalue(top) = code.w; + incr_top; } break; @@ -759,7 +812,8 @@ static StkId lua_execute (Byte *pc, StkId base) { CodeFloat code; get_float(code,pc); - tag(top) = LUA_T_NUMBER; nvalue(top++) = code.f; + tag(top) = LUA_T_NUMBER; nvalue(top) = code.f; + incr_top; } break; @@ -767,7 +821,8 @@ static StkId lua_execute (Byte *pc, StkId base) { CodeWord code; get_word(code,pc); - tag(top) = LUA_T_STRING; tsvalue(top++) = lua_constant[code.w]; + tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[code.w]; + incr_top; } break; @@ -775,22 +830,27 @@ static StkId lua_execute (Byte *pc, StkId base) { CodeCode code; get_code(code,pc); - tag(top) = LUA_T_FUNCTION; bvalue(top++) = code.b; + luaI_insertfunction(code.tf); /* may take part in GC */ + top->tag = LUA_T_FUNCTION; + top->value.tf = code.tf; + incr_top; } break; case PUSHLOCAL0: case PUSHLOCAL1: case PUSHLOCAL2: case PUSHLOCAL3: case PUSHLOCAL4: case PUSHLOCAL5: case PUSHLOCAL6: case PUSHLOCAL7: case PUSHLOCAL8: - case PUSHLOCAL9: *top++ = *((stack+base) + (int)(opcode-PUSHLOCAL0)); break; + case PUSHLOCAL9: + *top = *((stack+base) + (int)(opcode-PUSHLOCAL0)); incr_top; break; - case PUSHLOCAL: *top++ = *((stack+base) + (*pc++)); break; + case PUSHLOCAL: *top = *((stack+base) + (*pc++)); incr_top; break; case PUSHGLOBAL: { CodeWord code; get_word(code,pc); - *top++ = s_object(code.w); + *top = s_object(code.w); + incr_top; } break; @@ -803,9 +863,11 @@ static StkId lua_execute (Byte *pc, StkId base) Object receiver = *(top-1); CodeWord code; get_word(code,pc); - tag(top) = LUA_T_STRING; tsvalue(top++) = lua_constant[code.w]; + tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[code.w]; + incr_top; pushsubscript(); - *(top++) = receiver; + *top = receiver; + incr_top; break; } @@ -835,11 +897,12 @@ static StkId lua_execute (Byte *pc, StkId base) int n = *pc++; if (tag(top-3-n) != LUA_T_ARRAY) { + lua_checkstack(top+2); *(top+1) = *(top-1); *(top) = *(top-2-n); *(top-1) = *(top-3-n); top += 2; - do_call(&luaI_fallBacks[FB_SETTABLE].function, (top-stack)-3, 0, (top-stack)-3); + callFB(FB_SETTABLE); } else { @@ -899,7 +962,7 @@ static StkId lua_execute (Byte *pc, StkId base) get_word(size,pc); avalue(top) = lua_createarray(size.w); tag(top) = LUA_T_ARRAY; - top++; + incr_top; } break; @@ -993,7 +1056,7 @@ static StkId lua_execute (Byte *pc, StkId base) Object *l = top-2; Object *r = top-1; if (tostring(r) || tostring(l)) - do_call(&luaI_fallBacks[FB_CONCAT].function, (top-stack)-2, 1, (top-stack)-2); + callFB(FB_CONCAT); else { tsvalue(l) = lua_createstring (lua_strconc(svalue(l),svalue(r))); @@ -1005,7 +1068,8 @@ static StkId lua_execute (Byte *pc, StkId base) case MINUSOP: if (tonumber(top-1)) { - tag(top++) = LUA_T_NIL; + tag(top) = LUA_T_NIL; + incr_top; call_arith("unm"); } else @@ -1073,9 +1137,8 @@ static StkId lua_execute (Byte *pc, StkId base) { int nParams = *(pc++); int nResults = *(pc++); - Object *func = top-1-nParams; /* function is below parameters */ StkId newBase = (top-stack)-nParams; - do_call(func, newBase, nResults, newBase-1); + do_call(newBase, nResults); } break; @@ -1085,27 +1148,20 @@ static StkId lua_execute (Byte *pc, StkId base) case RETCODE: return base+*pc; - case SETFUNCTION: - { - CodeCode file; - CodeWord func; - get_code(file,pc); - get_word(func,pc); - lua_pushfunction ((char *)file.b, func.w); - } - break; - case SETLINE: { CodeWord code; get_word(code,pc); - lua_debugline = code.w; + if ((stack+base-1)->tag != LUA_T_LINE) + { + /* open space for LINE value */ + open_stack((top-stack)-base); + base++; + (stack+base-1)->tag = LUA_T_LINE; + } + (stack+base-1)->value.i = code.w; + break; } - break; - - case RESET: - lua_popfunction (); - break; default: lua_error ("internal error - opcode doesn't match"); |