⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vm_interpret.cpp

📁 c-smile 一个语法类似与JS 又有点像C++的 编译器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        case OP_PUSH:
          CHECKSTACK ( 1 );
          PUSH ( undefined );
          break;

        case OP_NOT:
          SP ( 0 ) = ! ( istrue ( SP ( 0 ) ) );
          break;

        case OP_NEG:
          CHECKTYPE ( 0, DT_INTEGER );
          SP ( 0 ) .v.v_integer = - SP ( 0 ) .v.v_integer;
          break;

        case OP_ADD:
          SP ( 1 ) = op_add ( this, SP ( 1 ), SP ( 0 ) );
          POP;
          break;

        case OP_SUB:
          SP ( 1 ) = op_sub ( this, SP ( 1 ), SP ( 0 ) );
          POP;
          break;

        case OP_MUL:
          SP ( 1 ) = op_mul ( this, SP ( 1 ), SP ( 0 ) );
          POP;
          break;

        case OP_DIV:
          SP ( 1 ) = op_div ( this, SP ( 1 ), SP ( 0 ) );
          POP;
          break;

        case OP_REM:
          SP ( 1 ) = op_rem ( this, SP ( 1 ), SP ( 0 ) );
          POP;
          break;

        case OP_MAKEREF:
          CHECKTYPE ( 0, DT_CODE );
          if ( !SP ( 1 ) .is_thing () ) 
          {
            VM::error ( "expecting object" );
          }
          //TODO: test code!!!!
          SP ( 1 ) .set_method ( SP ( 1 ) .v.v_thing, SP ( 0 ) .v.v_code );
          POP;
          break;

        case OP_INC:
          op_inc ( this, SP ( 0 ) );
          break;

        case OP_DEC:
          op_dec ( this, SP ( 0 ) );
          break;

        case OP_BAND:
          SP ( 1 ) = op_band ( this, SP ( 1 ), SP ( 0 ) );
          POP;
          break;

        case OP_BOR:
          SP ( 1 ) = op_bor ( this, SP ( 1 ), SP ( 0 ) );
          POP;
          break;

        case OP_XOR:
          SP ( 1 ) = op_bxor ( this, SP ( 1 ), SP ( 0 ) );
          POP;
          break;

        case OP_BNOT:
          SP ( 0 ) = op_bnot ( this, SP ( 0 ) );
          break;

        case OP_SHL:
          CHECKTYPE ( 0, DT_INTEGER );
          CHECKTYPE ( 1, DT_INTEGER );
          SP ( 1 ).v.v_integer <<= sp->v.v_integer;
          POP;
          break;

        case OP_SHR:
          CHECKTYPE ( 0, DT_INTEGER );
          CHECKTYPE ( 1, DT_INTEGER );
          SP ( 1 ).v.v_integer >>= sp->v.v_integer;
          POP;
          break;

        case OP_LT:
          SP ( 1 ) = op_lt ( this, SP ( 1 ), SP ( 0 ) );
          POP;
          break;

        case OP_LE:
          SP ( 1 ) = op_le ( this, SP ( 1 ), SP ( 0 ) );
          POP;
          break;

        case OP_EQ:
          SP ( 1 ) = ( SP ( 1 ) == SP ( 0 ) );
          POP;
          break;

        case OP_NE:
          SP ( 1 ) = op_neq ( this, SP ( 1 ), SP ( 0 ) );
          POP;
          break;

        case OP_GE:
          SP ( 1 ) = op_le ( this, SP ( 0 ), SP ( 1 ) );
          POP;
          break;

        case OP_GT:
          SP ( 1 ) = op_lt ( this, SP ( 0 ), SP ( 1 ) );
          POP;
          break;

        case OP_LIT:
          woperand = getwoperand ();
          SP ( 0 ) = ( *package->literals ) [ woperand ];
          break;

        case OP_POP:
          POP;
          break;

        case OP_COPY:
          SP ( 0 ) = SP ( 1 );
          break;

        case OP_DUP2:
          CHECKSTACK ( 2 );
          PUSHN ( 2 );
          SP ( 0 ) = SP ( 2 );
          SP ( 1 ) = SP ( 3 );
          break;

        case OP_DUP:
          PUSH ( undefined );
          SP ( 0 ) = SP ( 1 );
          break;

        case OP_NEW:
          opNEW ();
          break;

        case OP_LINE:
          line_num = getwoperand ();
          break;

        case OP_EH_PUSH:
          n = getwoperand ();
          assert ( eh_pos < ( eh_size-1 ) ); // critical error
          ++eh_pos;
          {
            error_handler *ep = &eh [ eh_pos ];
            ep->catch_pc = n;
            ep->m_stack_pos = m_stack_pos;
            ep->code = code;
            ep->fp = fp;
            ep->sp = sp;
            ep->thrown = undefined;
          }
          break;

        case OP_EH_POP:
          assert ( eh_pos >= 0 ); // otherwise something wrong
          pc = cbase + getwoperand ();
          --eh_pos;
          break;

        case OP_THROW:
          if ( eh_pos >= 0 ) 
          {
            eh [ eh_pos ] .thrown = SP ( 0 );
            throw VM_RTE ( this, SP ( 0 ) );
          }
          else
          {
            //TODO
            throw VM_RTE ( this, "TODO: ALARM! " );
          }
          break;

        case OP_ENTER:
          {
            if ( SP ( 0 ) .v_type != DT_EXT ||
              SP ( 0 ) .v.v_thing->get_class () != MUTEX::INSTANCE::klass ) 
            {
              error ( "not a mutex" );
            }

            if ( m_stack_pos >= m_stack_size - 1 ) 
            {
              error ( "too many synchronized blocks" );
            }

            MUTEX::INSTANCE *pmi = ( MUTEX::INSTANCE * ) SP ( 0 ) .v.v_thing;
            m_stack [ ++m_stack_pos ] = pmi;

            //POP; !!!!

            pmi->_m.enter ();
          }
          break;

        case OP_LEAVE:
          assert ( m_stack_pos >= 0 ); // otherwise something wrong
          m_stack [ m_stack_pos-- ] ->_m.leave ();
          break;

        case OP_INSTANCEOF:
          if ( !SP ( 1 ).is_thing () ) 
          {
            error ( "instanceof - left side is not an object" );
          }
          if ( !SP ( 0 ) .is_class () ) 
          {
            error ( "instanceof - right side is not a class" );
          }
          SP ( 1 ) = SP ( 1 ) .v.v_thing -> instance_of ( SP ( 0 ) .v.v_class );
          POP;
          break;

        case OP_UNDEFINED:
          SP ( 0 ) = undefined;
          break;

        case OP_ARGUMENT:
          CHECKTYPE ( 0, DT_INTEGER );
          // skip 'this'
          SP ( 0 ) = ARG ( int ( SP ( 0 ) )  + 1 );
          break;

        case OP_ARGUMENTS:
          // without 'this'
          SP ( 0 ) = int ( FP ( FRAME_ARGC ) )  - 1;
          break;

        case OP_TSTORE:
          t_register = SP ( 0 );
          break;

        case OP_TRESTORE:
          SP ( 0 ) = t_register; t_register.init ();
          break;

        default:
          error ( "Bad opcode %02x", pc [ -1 ] );
          break;
        }
      }
      // for
    }
    catch ( VM_RTE& rte ) 
    {
      if ( eh_pos < 0 ) 
      {
        ready_for_gc = true;
        running = false;
        throw rte;
      }
      // uncaught exception

      error_handler *ep = &eh [ eh_pos ];
      n = ep->catch_pc;
      code = ep->code;
      package = code->klass () ->get_package ();
      fp = ep->fp;
      sp = ep->sp;
      int mspos = ep->m_stack_pos;

      if ( ep->thrown.is_null () ) 
      {
        //TODO: create instance of ERROR class
        if ( rte.err_value.is_null () ) 
          SP ( 0 ) = new STRING ( rte.report () );
        else
          SP ( 0 ) = rte.err_value;
      }
      else
      {
        SP ( 0 ) = ep->thrown;
      }
      cbase = ( unsigned char * ) code->bytecode ();
      pc = cbase + n;
      --eh_pos;

      // free synchro locks originated in the function - source of error
      for ( int i = m_stack_pos; i > mspos; i-- ) 
      {
        m_stack [ i ] ->_m.leave ();
      }
      m_stack_pos = mspos;

      goto start;
    }

  STOP:
    ready_for_gc = true;
    running = false;

  }


  //| 0
  //|
  //|
  //|
  //|
  //| fp : pcoff  - old programm counter offset
  //|      fpoff  - old frame pointer
  //|      argc   - arg counter
  //|      argn
  //|      argn-1
  //|      ...
  //|      arg0
  //|      bytecode
  //|
  //|
  //|
  //| stktop

  // opRETURN - RETURN opcode handler
  bool
    VM::opRETURN () 
  {
    int pcoff, n;
    VALUE val = SP ( 0 );
    sp = fp;
    pcoff = FP ( FRAME_PCOFF ) .v.v_integer;
    n = FP ( FRAME_ARGC ) .v.v_integer;
    int ehpos = FP ( FRAME_EHPOS ) .v.v_integer;
    int mspos = FP ( FRAME_MSPOS ) .v.v_integer;
    fp = stkbase + FP ( FRAME_FPOFF ) .v.v_integer;

    // free synchro locks originated in this function
    for ( int i = m_stack_pos; i > mspos; i-- ) m_stack [ i ] ->_m.leave ();
      m_stack_pos = mspos;
    eh_pos = ehpos;

    if ( fp == stkbase ) return false;

    int  coff = FP ( FRAME_ARGC ) .v.v_integer + FRAME_SIZE;
    code = FP ( coff ) .v.v_code;
    package = code->klass () ->get_package ();
    cbase = ( unsigned char * ) code->bytecode ();
    pc = cbase + pcoff;
    POPN ( n + FRAME_SIZE );
    SP ( 0 ) = val;

    return true;
  }

  // opCALL - CALL opcode handler
  void
    VM::opCALL () 
  {
    int     argc = getwoperand ();	/* get argument count */
    VALUE * argv = &SP ( argc-1 );

    VALUE   _ref = SP ( argc );
    VALUE&  _this = SP ( argc-1 );

    switch ( SP ( argc ) .v_type ) 
    {
    case DT_CODE:
      {
        if ( SP ( argc ) .v.v_code->is_native () ) 
        {
          // argc - 1 : without this; argv+1 : skip this
          VALUE v = invoke_native ( SP ( argc ) .v.v_code,  argc - 1, argv + 1 );
          POPN ( argc );
          SP ( 0 ) = v;
        }
        else
        {
          CHECKSTACK ( FRAME_SIZE );
          code = SP ( argc ) .v.v_code;
          package = code->klass () ->get_package ();
          PUSH ( argc );		/* argument count */
          PUSH ( eh_pos );
          PUSH ( m_stack_pos );
          PUSH ( int ( fp - stkbase ) );	/* old fp */
          PUSH ( int ( pc - cbase ) );	/* old pc */
          cbase = pc = ( unsigned char* ) code->bytecode ();
          fp = sp;
        }
      }
      return;
    case DT_CLASS:
      {
        CLASS * cls = _ref.v.v_class;
        if ( cls->cast_function ) 
        {
          _this = cls;
          _ref = cls->cast_function;
          goto gotit;
        }
        VM::error ( "static function %s::cast not found", (const char *) cls->full_name () );
      }
    case DT_OBJECT_METHOD:
      {

        _this = VALUE ( *_ref.v.v_om.thing );
        _ref = _ref.v.v_om.code;
      gotit:
        if ( _ref.v.v_code->is_native () ) 
        {
          VALUE v = invoke_native ( _ref.v.v_code,  argc - 1, argv + 1 );
          POPN ( argc );
          SP ( 0 ) = v;
        }
        else
        {
          CHECKSTACK ( FRAME_SIZE );
          code = _ref.v.v_code;
          package = code->klass () ->get_package ();
          //TODO check it SP ( argc ) 
          SP ( argc ) = code;
          PUSH ( argc );		/* argument count */
          PUSH ( eh_pos );
          PUSH ( m_stack_pos );
          PUSH ( int ( fp - stkbase ) );	/* old fp */
          PUSH ( int ( pc - cbase ) );	/* old pc */
          cbase = pc = ( unsigned char * ) code->bytecode ();
          fp = sp;
        }
        return;
      }

    default:
      error ( "Call to non-procedure,  Type %s", nameoftype ( SP ( argc ) .v_type ) );
      break;
    }
  }


  // opNEW - OP_NEW opcode handler
  void
    VM::opNEW () 
  {
    register int n;

    n = *pc++;

    assert ( SP ( n ) .v_type == DT_CLASS );
    CLASS *klass = SP ( n ) .v.v_class;

    SP ( n-1 ) = SP ( n );

    CODE * ctor = klass->ctor_function;
    if ( !ctor ) 
      error ( "No constructor defined for the class '%s'", (const char *) klass->full_name () );

    int     argc = n;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -