Ejemplo n.º 1
0
Archivo: opcode.c Proyecto: 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");
}
Ejemplo n.º 2
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");
  }
 }
}