Example #1
0
File: opcode.c Project: cskau/VM
/*
** Call a C function. CLS_current.base will point to the top of the stack,
** and CLS_current.num is the number of parameters. Returns an index
** to the first result from C.
*/
static StkId callC (lua_CFunction func, StkId base)
{
  struct C_Lua_Stack oldCLS = CLS_current;
  StkId firstResult;
  CLS_current.num = (top-stack) - base;
  /* incorporate parameters on the stack */
  CLS_current.base = base+CLS_current.num;  /* == top-stack */
  if (lua_callhook)
    callHook(base, LUA_T_CMARK, 0);
  (*func)();
  if (lua_callhook)  /* func may have changed lua_callhook */
    callHook(base, LUA_T_CMARK, 1);
  firstResult = CLS_current.base;
  CLS_current = oldCLS;
  return firstResult;
}
Example #2
0
	void callEpilogue(Thread* t)
	{
		if(t->hooks & CrocThreadHook_Ret)
			callHook(t, CrocThreadHook_Ret);

		// Get results before popARTo takes them away
		auto destSlot = t->currentAR->returnSlot;
		auto expectedResults = t->currentAR->expectedResults;
		auto results = loadResults(t);

		// Pop the act record (which also closes upvals and removes EH frames)
		popARTo(t, t->arIndex - 1);

		// Copy and adjust results
		bool isMultRet = expectedResults == -1;
		auto actualResults = results.length;

		if(isMultRet)
			expectedResults = actualResults;

		auto stk = t->stack;
		auto slotAfterRets = destSlot + expectedResults;

		if(cast(uword)expectedResults <= actualResults)
			stk.slicea(destSlot, slotAfterRets, results.slice(0, expectedResults));
		else
		{
			stk.slicea(destSlot, destSlot + actualResults, results);
			stk.slice(destSlot + actualResults, slotAfterRets).fill(Value::nullValue);
		}

		t->numYields = actualResults;

		// Set stack index appropriately; last case happens in native -> native calls
		if(t->arIndex == 0 || isMultRet || t->currentAR->savedTop < slotAfterRets)
			t->stackIndex = slotAfterRets;
		else
			t->stackIndex = t->currentAR->savedTop;

		assert(t->stackIndex > 0);
	}
Example #3
0
	bool funcCallPrologue(Thread* t, Function* func, AbsStack returnSlot, word expectedResults, AbsStack paramSlot,
		uword numParams, bool isTailcall)
	{
		if(numParams > func->maxParams)
			croc_eh_throwStd(*t, "ParamError",
				"Function %s expected at most %" CROC_SIZE_T_FORMAT " parameters but was given %" CROC_SIZE_T_FORMAT,
				func->name->toCString(), func->maxParams - 1, numParams - 1);

		if(!func->isNative)
		{
			// Script function
			auto funcdef = func->scriptFunc;
			auto ar = isTailcall ? t->currentAR : pushAR(t);

			if(isTailcall)
			{
				assert(ar && ar->func && !ar->func->isNative);
				assert(paramSlot == returnSlot + 1);

				closeUpvals(t, ar->base);
				ar->numTailcalls++;
				memmove(&t->stack[ar->returnSlot], &t->stack[returnSlot], sizeof(Value) * (numParams + 1));
				returnSlot = ar->returnSlot;
				paramSlot = returnSlot + 1;
			}

			if(funcdef->isVararg && numParams > func->numParams)
			{
				// In this case, we move the formal parameters after the varargs and null out where the formal
				// params used to be.
				ar->base = paramSlot + numParams;
				ar->vargBase = paramSlot + func->numParams;
				checkStack(t, ar->base + funcdef->stackSize - 1);
				auto oldParams = t->stack.slice(paramSlot, paramSlot + func->numParams);
				t->stack.slicea(ar->base, ar->base + func->numParams, oldParams);
				oldParams.fill(Value::nullValue);

				// For nulling out the stack.
				numParams = func->numParams;
			}
			else
			{
				// In this case, everything is where it needs to be already.
				ar->base = paramSlot;
				ar->vargBase = paramSlot;
				checkStack(t, ar->base + funcdef->stackSize - 1);
				// If we have too few params, the extra param slots will be nulled out.
			}

			// Null out the stack frame after the parameters.
			t->stack.slice(ar->base + numParams, ar->base + funcdef->stackSize).fill(Value::nullValue);

			// Fill in the rest of the activation record.
			ar->returnSlot = returnSlot;
			ar->func = func;
			ar->pc = funcdef->code.ptr;
			ar->firstResult = 0;
			ar->numResults = 0;
			ar->savedTop = ar->base + funcdef->stackSize;
			ar->unwindCounter = 0;
			ar->unwindReturn = nullptr;

			if(!isTailcall)
			{
				ar->expectedResults = expectedResults;
				ar->numTailcalls = 0;
			}

			// Set the stack indices.
			t->stackBase = ar->base;
			t->stackIndex = ar->savedTop;

			// Call any hook.
			if(t->hooks & CrocThreadHook_Call)
				callHook(t, isTailcall ? CrocThreadHook_TailCall : CrocThreadHook_Call);

			return true;
		}
		else
		{
			// Native function
			t->stackIndex = paramSlot + numParams;
			checkStack(t, t->stackIndex);

			auto ar = pushAR(t);

			ar->base = paramSlot;
			ar->vargBase = paramSlot;
			ar->returnSlot = returnSlot;
			ar->func = func;
			ar->expectedResults = expectedResults;
			ar->firstResult = 0;
			ar->numResults = 0;
			ar->savedTop = t->stackIndex;
			ar->numTailcalls = 0;
			ar->unwindCounter = 0;
			ar->unwindReturn = nullptr;

			t->stackBase = ar->base;

			if(t->hooks & CrocThreadHook_Call)
				callHook(t, CrocThreadHook_Call);

			t->vm->curThread = t;
			t->nativeCallDepth++;
			auto savedState = t->state;
			t->state = CrocThreadState_Running;
			word actualResults = func->nativeFunc(*t);
			t->state = savedState;
			t->nativeCallDepth--;

			assert(actualResults >= 0); // for now, will change in the future

			if(cast(uword)actualResults > (t->stackIndex - (t->stackBase + 1)))
				croc_eh_throwStd(*t, "ApiError", "Native function '%s' returned an invalid number of results",
					func->name->toCString());

			saveResults(t, t, t->stackIndex - actualResults, actualResults);
			callEpilogue(t);
			return false;
		}
	}
Example #4
0
File: opcode.c Project: cskau/VM
/*
** Execute the given opcode, until a RET. Parameters are between
** [stack+base,top). Returns n such that the the results are between
** [stack+n,top).
*/
static StkId lua_execute (Byte *pc, StkId base)
{
  void* table[] = {
    &&pushnil,
    &&push0,
    &&push1,
    &&push2,
    &&pushbyte,
    &&pushword,
    &&pushfloat,
    &&pushstring,
    &&pushfunction,
    &&pushlocal0,
    &&pushlocal1,
    &&pushlocal2,
    &&pushlocal3,
    &&pushlocal4,
    &&pushlocal5,
    &&pushlocal6,
    &&pushlocal7,
    &&pushlocal8,
    &&pushlocal9,
    &&pushlocal,
    &&pushglobal,
    &&pushindexed,
    &&pushself,
    &&storelocal0,
    &&storelocal1,
    &&storelocal2,
    &&storelocal3,
    &&storelocal4,
    &&storelocal5,
    &&storelocal6,
    &&storelocal7,
    &&storelocal8,
    &&storelocal9,
    &&storelocal,
    &&storeglobal,
    &&storeindexed0,
    &&storeindexed,
    &&storelist0,
    &&storelist,
    &&storerecord,
    &&adjust0,
    &&adjust,
    &&createarray,
    &&eqop,
    &&ltop,
    &&leop,
    &&gtop,
    &&geop,
    &&addop,
    &&subop,
    &&multop,
    &&divop,
    &&powop,
    &&concop,
    &&minusop,
    &&notop,
    &&ontjmp,
    &&onfjmp,
    &&jmp,
    &&upjmp,
    &&iffjmp,
    &&iffupjmp,
    &&pop,
    &&callfunc,
    &&retcode0,
    &&retcode,
    &&setline,
    &&varargs
  };

  if (lua_callhook)
    callHook (base, LUA_T_MARK, 0);

  goto *table[*pc++];

   pushnil: tag(top) = LUA_T_NIL; incr_top; goto *table[*pc++];

   push0: push1: push2:
     tag(top) = LUA_T_NUMBER;
     nvalue(top) = ((OpCode)*(pc-1))-PUSH0;
     incr_top;
     goto *table[*pc++];

   pushbyte: 
     tag(top) = LUA_T_NUMBER; nvalue(top) = *pc++; incr_top; goto *table[*pc++];

   pushword:
   {
    Word w;
    get_word(w,pc);
    tag(top) = LUA_T_NUMBER; nvalue(top) = w;
    incr_top;
   }
   goto *table[*pc++];

   pushfloat:
   {
    real num;
    get_float(num,pc);
    tag(top) = LUA_T_NUMBER; nvalue(top) = num;
    incr_top;
   }
   goto *table[*pc++];

   pushstring:
   {
    Word w;
    get_word(w,pc);
    tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[w];
    incr_top;
   }
   goto *table[*pc++];

   pushfunction:
   {
    TFunc *f;
    get_code(f,pc);
    luaI_insertfunction(f);  /* may take part in GC */
    top->tag = LUA_T_FUNCTION;
    top->value.tf = f;
    incr_top;
   }
   goto *table[*pc++];

   pushlocal0: pushlocal1: pushlocal2:
   pushlocal3: pushlocal4: pushlocal5:
   pushlocal6: pushlocal7: pushlocal8:
   pushlocal9: 
     *top = *((stack+base) + (int)(((OpCode)*(pc-1))-PUSHLOCAL0)); incr_top; goto *table[*pc++];

   pushlocal: *top = *((stack+base) + (*pc++)); incr_top; goto *table[*pc++];

   pushglobal:
   {
    Word w;
    get_word(w,pc);
    getglobal(w);
   }
   goto *table[*pc++];

   pushindexed:
    pushsubscript();
    goto *table[*pc++];

   pushself:
   {
     Object receiver = *(top-1);
     Word w;
     get_word(w,pc);
     tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[w];
     incr_top;
     pushsubscript();
     *top = receiver;
     incr_top;
     goto *table[*pc++];
   }

   storelocal0: storelocal1: storelocal2:
   storelocal3: storelocal4: storelocal5:
   storelocal6: storelocal7: storelocal8:
   storelocal9:
     *((stack+base) + (int)(((OpCode)*(pc-1))-STORELOCAL0)) = *(--top);
     goto *table[*pc++];

   storelocal: *((stack+base) + (*pc++)) = *(--top); goto *table[*pc++];

   storeglobal:
   {
    Word w;
    get_word(w,pc);
    s_object(w) = *(--top);
   }
   goto *table[*pc++];

   storeindexed0:
    storesubscript();
    goto *table[*pc++];

   storeindexed:
   {
    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;
      callFB(FB_SETTABLE);
    }
    else
    {
     Object *h = lua_hashdefine (avalue(top-3-n), top-2-n);
     *h = *(top-1);
     top--;
    }
   }
   goto *table[*pc++];

   storelist0:
   storelist:
   {
    int m, n;
    Object *arr;
    if (((OpCode)*(pc-1)) == STORELIST0) m = 0;
    else m = *(pc++) * FIELDS_PER_FLUSH;
    n = *(pc++);
    arr = top-n-1;
    while (n)
    {
     tag(top) = LUA_T_NUMBER; nvalue(top) = n+m;
     *(lua_hashdefine (avalue(arr), top)) = *(top-1);
     top--;
     n--;
    }
   }
   goto *table[*pc++];

   storerecord:
   {
    int n = *(pc++);
    Object *arr = top-n-1;
    while (n)
    {
     Word w;
     get_word(w,pc);
     tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[w];
     *(lua_hashdefine (avalue(arr), top)) = *(top-1);
     top--;
     n--;
    }
   }
   goto *table[*pc++];

   adjust0:
     adjust_top(base);
     goto *table[*pc++];

   adjust:
     adjust_top(base + *(pc++));
     goto *table[*pc++];

   varargs:
     adjust_varargs(base + *(pc++));
     goto *table[*pc++];

   createarray:
   {
    Word size;
    get_word(size,pc);
    avalue(top) = lua_createarray(size);
    tag(top) = LUA_T_ARRAY;
    incr_top;
   }
   goto *table[*pc++];

   eqop:
   {
    int res = lua_equalObj(top-2, top-1);
    --top;
    tag(top-1) = res ? LUA_T_NUMBER : LUA_T_NIL;
    nvalue(top-1) = 1;
   }
   goto *table[*pc++];

    ltop:
      comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, "lt");
      goto *table[*pc++];

   leop:
      comparison(LUA_T_NUMBER, LUA_T_NUMBER, LUA_T_NIL, "le");
      goto *table[*pc++];

   gtop:
      comparison(LUA_T_NIL, LUA_T_NIL, LUA_T_NUMBER, "gt");
      goto *table[*pc++];

   geop:
      comparison(LUA_T_NIL, LUA_T_NUMBER, LUA_T_NUMBER, "ge");
      goto *table[*pc++];

   addop:
   {
    Object *l = top-2;
    Object *r = top-1;
    if (tonumber(r) || tonumber(l))
      call_arith("add");
    else
    {
      nvalue(l) += nvalue(r);
      --top;
    }
   }
   goto *table[*pc++];

   subop:
   {
    Object *l = top-2;
    Object *r = top-1;
    if (tonumber(r) || tonumber(l))
      call_arith("sub");
    else
    {
      nvalue(l) -= nvalue(r);
      --top;
    }
   }
   goto *table[*pc++];

   multop:
   {
    Object *l = top-2;
    Object *r = top-1;
    if (tonumber(r) || tonumber(l))
      call_arith("mul");
    else
    {
      nvalue(l) *= nvalue(r);
      --top;
    }
   }
   goto *table[*pc++];

   divop:
   {
    Object *l = top-2;
    Object *r = top-1;
    if (tonumber(r) || tonumber(l))
      call_arith("div");
    else
    {
      nvalue(l) /= nvalue(r);
      --top;
    }
   }
   goto *table[*pc++];

   powop:
    call_arith("pow");
    goto *table[*pc++];

   concop:
   {
    Object *l = top-2;
    Object *r = top-1;
    if (tostring(r) || tostring(l))
      callFB(FB_CONCAT);
    else
    {
      tsvalue(l) = lua_createstring (lua_strconc(svalue(l),svalue(r)));
      --top;
    }
   }
   goto *table[*pc++];

   minusop:
    if (tonumber(top-1))
    {
      tag(top) = LUA_T_NIL;
      incr_top;
      call_arith("unm");
    }
    else
      nvalue(top-1) = - nvalue(top-1);
   goto *table[*pc++];

   notop:
    tag(top-1) = (tag(top-1) == LUA_T_NIL) ? LUA_T_NUMBER : LUA_T_NIL;
    nvalue(top-1) = 1;
   goto *table[*pc++];

   ontjmp:
   {
    Word w;
    get_word(w,pc);
    if (tag(top-1) != LUA_T_NIL) pc += w;
   }
   goto *table[*pc++];

   onfjmp:
   {
    Word w;
    get_word(w,pc);
    if (tag(top-1) == LUA_T_NIL) pc += w;
   }
   goto *table[*pc++];

   jmp:
   {
    Word w;
    get_word(w,pc);
    pc += w;
   }
   goto *table[*pc++];

   upjmp:
   {
    Word w;
    get_word(w,pc);
    pc -= w;
   }
   goto *table[*pc++];

   iffjmp:
   {
    Word w;
    get_word(w,pc);
    top--;
    if (tag(top) == LUA_T_NIL) pc += w;
   }
   goto *table[*pc++];

   iffupjmp:
   {
    Word w;
    get_word(w,pc);
    top--;
    if (tag(top) == LUA_T_NIL) pc -= w;
   }
   goto *table[*pc++];

   pop: --top; goto *table[*pc++];

   callfunc:
   {
     int nParams = *(pc++);
     int nResults = *(pc++);
     StkId newBase = (top-stack)-nParams;
     do_call(newBase, nResults);
   }
   goto *table[*pc++];

   retcode0:
   retcode:
     if (lua_callhook)
       callHook (base, LUA_T_MARK, 1);
     return (base + ((((OpCode)*(pc-1))==RETCODE0) ? 0 : *pc));

   setline:
   {
    Word line;
    get_word(line,pc);
    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 = line;
    if (lua_linehook)
      lineHook (line);
    goto *table[*pc++];
   }


  lua_error ("internal error - opcode doesn't match");
}
Example #5
0
/*
** Execute the given opcode, until a RET. Parameters are between
** [stack+base,top). Returns n such that the the results are between
** [stack+n,top).
*/
static StkId lua_execute (Byte *pc, StkId base)
{
  if (lua_callhook)
    callHook (base, LUA_T_MARK, 0);
 while (1)
 {
  OpCode opcode;
  switch (opcode = (OpCode)*pc++)
  {
   case PUSHNIL: ttype(top) = LUA_T_NIL; incr_top; break;

   case PUSH0: case PUSH1: case PUSH2:
     ttype(top) = LUA_T_NUMBER;
     nvalue(top) = opcode-PUSH0;
     incr_top;
     break;

   case PUSHBYTE: 
     ttype(top) = LUA_T_NUMBER; nvalue(top) = *pc++; incr_top; break;

   case PUSHWORD:
   {
    Word w;
    get_word(w,pc);
    ttype(top) = LUA_T_NUMBER; nvalue(top) = w;
    incr_top;
   }
   break;

   case PUSHFLOAT:
   {
    real num;
    get_float(num,pc);
    ttype(top) = LUA_T_NUMBER; nvalue(top) = num;
    incr_top;
   }
   break;

   case PUSHSTRING:
   {
    Word w;
    get_word(w,pc);
    ttype(top) = LUA_T_STRING; tsvalue(top) = lua_constant[w];
    incr_top;
   }
   break;

   case PUSHFUNCTION:
   {
    TFunc *f;
    get_code(f,pc);
    luaI_insertfunction(f);  /* may take part in GC */
    top->ttype = LUA_T_FUNCTION;
    top->value.tf = f;
    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)); incr_top; break;

   case PUSHLOCAL: *top = *((stack+base) + (*pc++)); incr_top; break;

   case PUSHGLOBAL:
   {
    Word w;
    get_word(w,pc);
    getglobal(w);
   }
   break;

   case PUSHINDEXED:
    pushsubscript();
    break;

   case PUSHSELF:
   {
     TObject receiver = *(top-1);
     Word w;
     get_word(w,pc);
     ttype(top) = LUA_T_STRING; tsvalue(top) = lua_constant[w];
     incr_top;
     pushsubscript();
     *top = receiver;
     incr_top;
     break;
   }

   case STORELOCAL0: case STORELOCAL1: case STORELOCAL2:
   case STORELOCAL3: case STORELOCAL4: case STORELOCAL5:
   case STORELOCAL6: case STORELOCAL7: case STORELOCAL8:
   case STORELOCAL9:
     *((stack+base) + (int)(opcode-STORELOCAL0)) = *(--top);
     break;

   case STORELOCAL: *((stack+base) + (*pc++)) = *(--top); break;

   case STOREGLOBAL:
   {
    Word w;
    get_word(w,pc);
    setglobal(w);
   }
   break;

   case STOREINDEXED0:
    storesubscript(top-3, 1);
    break;

   case STOREINDEXED: {
     int n = *pc++;
     storesubscript(top-3-n, 2);
     break;
   }

   case STORELIST0:
   case STORELIST:
   {
    int m, n;
    TObject *arr;
    if (opcode == STORELIST0) m = 0;
    else m = *(pc++) * FIELDS_PER_FLUSH;
    n = *(pc++);
    arr = top-n-1;
    while (n)
    {
     ttype(top) = LUA_T_NUMBER; nvalue(top) = n+m;
     *(lua_hashdefine (avalue(arr), top)) = *(top-1);
     top--;
     n--;
    }
   }
   break;

   case STORERECORD:  /* opcode obsolete: supersed by STOREMAP */
   {
    int n = *(pc++);
    TObject *arr = top-n-1;
    while (n)
    {
     Word w;
     get_word(w,pc);
     ttype(top) = LUA_T_STRING; tsvalue(top) = lua_constant[w];
     *(lua_hashdefine (avalue(arr), top)) = *(top-1);
     top--;
     n--;
    }
   }
   break;

   case STOREMAP: {
     int n = *(pc++);
     TObject *arr = top-(2*n)-1;
     while (n--) {
       *(lua_hashdefine (avalue(arr), top-2)) = *(top-1);
       top-=2;
     }
   }
   break;

   case ADJUST0:
     adjust_top(base);
     break;

   case ADJUST: {
     StkId newtop = base + *(pc++);
     adjust_top(newtop);
     break;
   }

   case VARARGS:
     adjust_varargs(base + *(pc++));
     break;

   case CREATEARRAY:
   {
    Word size;
    get_word(size,pc);
    avalue(top) = lua_createarray(size);
    ttype(top) = LUA_T_ARRAY;
    incr_top;
   }
   break;

   case EQOP:
   {
    int res = lua_equalObj(top-2, top-1);
    --top;
    ttype(top-1) = res ? LUA_T_NUMBER : LUA_T_NIL;
    nvalue(top-1) = 1;
   }
   break;

    case LTOP:
      comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, IM_LT);
      break;

   case LEOP:
      comparison(LUA_T_NUMBER, LUA_T_NUMBER, LUA_T_NIL, IM_LE);
      break;

   case GTOP:
      comparison(LUA_T_NIL, LUA_T_NIL, LUA_T_NUMBER, IM_GT);
      break;

   case GEOP:
      comparison(LUA_T_NIL, LUA_T_NUMBER, LUA_T_NUMBER, IM_GE);
      break;

   case ADDOP:
   {
    TObject *l = top-2;
    TObject *r = top-1;
    if (tonumber(r) || tonumber(l))
      call_arith(IM_ADD);
    else
    {
      nvalue(l) += nvalue(r);
      --top;
    }
   }
   break;

   case SUBOP:
   {
    TObject *l = top-2;
    TObject *r = top-1;
    if (tonumber(r) || tonumber(l))
      call_arith(IM_SUB);
    else
    {
      nvalue(l) -= nvalue(r);
      --top;
    }
   }
   break;

   case MULTOP:
   {
    TObject *l = top-2;
    TObject *r = top-1;
    if (tonumber(r) || tonumber(l))
      call_arith(IM_MUL);
    else
    {
      nvalue(l) *= nvalue(r);
      --top;
    }
   }
   break;

   case DIVOP:
   {
    TObject *l = top-2;
    TObject *r = top-1;
    if (tonumber(r) || tonumber(l))
      call_arith(IM_DIV);
    else
    {
      nvalue(l) /= nvalue(r);
      --top;
    }
   }
   break;

   case POWOP:
    call_arith(IM_POW);
    break;

   case CONCOP: {
     TObject *l = top-2;
     TObject *r = top-1;
     if (tostring(l) || tostring(r))
       call_binTM(IM_CONCAT, "unexpected type for concatenation");
     else {
       tsvalue(l) = lua_createstring(lua_strconc(svalue(l),svalue(r)));
       --top;
     }
   }
   break;

   case MINUSOP:
    if (tonumber(top-1))
    {
      ttype(top) = LUA_T_NIL;
      incr_top;
      call_arith(IM_UNM);
    }
    else
      nvalue(top-1) = - nvalue(top-1);
   break;

   case NOTOP:
    ttype(top-1) = (ttype(top-1) == LUA_T_NIL) ? LUA_T_NUMBER : LUA_T_NIL;
    nvalue(top-1) = 1;
   break;

   case ONTJMP:
   {
    Word w;
    get_word(w,pc);
    if (ttype(top-1) != LUA_T_NIL) pc += w;
   }
   break;

   case ONFJMP:
   {
    Word w;
    get_word(w,pc);
    if (ttype(top-1) == LUA_T_NIL) pc += w;
   }
   break;

   case JMP:
   {
    Word w;
    get_word(w,pc);
    pc += w;
   }
   break;

   case UPJMP:
   {
    Word w;
    get_word(w,pc);
    pc -= w;
   }
   break;

   case IFFJMP:
   {
    Word w;
    get_word(w,pc);
    top--;
    if (ttype(top) == LUA_T_NIL) pc += w;
   }
   break;

   case IFFUPJMP:
   {
    Word w;
    get_word(w,pc);
    top--;
    if (ttype(top) == LUA_T_NIL) pc -= w;
   }
   break;

   case POP: --top; break;

   case CALLFUNC:
   {
     int nParams = *(pc++);
     int nResults = *(pc++);
     StkId newBase = (top-stack)-nParams;
     do_call(newBase, nResults);
   }
   break;

   case RETCODE0:
   case RETCODE:
     if (lua_callhook)
       callHook (base, LUA_T_MARK, 1);
     return (base + ((opcode==RETCODE0) ? 0 : *pc));

   case SETLINE:
   {
    Word line;
    get_word(line,pc);
    if ((stack+base-1)->ttype != LUA_T_LINE)
    {
      /* open space for LINE value */
      open_stack((top-stack)-base);
      base++;
      (stack+base-1)->ttype = LUA_T_LINE;
    }
    (stack+base-1)->value.i = line;
    if (lua_linehook)
      lineHook (line);
    break;
   }

   default:
    lua_error ("internal error - opcode doesn't match");
  }
 }
}