📄 vm_interpret.cpp
字号:
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 + -