This commit is contained in:
blueloveTH 2024-05-19 15:55:51 +08:00
parent 5e0e2c9c51
commit 9a1a7f92b7
6 changed files with 139 additions and 116 deletions

View File

@ -11,9 +11,16 @@ struct NeedMoreLines {
bool is_compiling_class; bool is_compiling_class;
}; };
struct HandledException {}; enum class InternalExceptionType: int{
struct UnhandledException {}; Null, Handled, Unhandled, ToBeRaised
struct ToBeRaisedException {}; };
struct InternalException final{
InternalExceptionType type;
int arg;
InternalException(): type(InternalExceptionType::Null), arg(-1) {}
InternalException(InternalExceptionType type, int arg=-1): type(type), arg(arg) {}
};
enum CompileMode { enum CompileMode {
EXEC_MODE, EXEC_MODE,

View File

@ -70,7 +70,6 @@ struct ValueStack {
struct Frame { struct Frame {
int _ip; int _ip;
int _next_ip;
// This is for unwinding only, use `actual_sp_base()` for value stack access // This is for unwinding only, use `actual_sp_base()` for value stack access
PyVar* _sp_base; PyVar* _sp_base;
@ -84,28 +83,29 @@ struct Frame {
// function scope // function scope
Frame(PyVar* p0, const CodeObject* co, PyVar _module, PyVar _callable, PyVar* _locals_base) Frame(PyVar* p0, const CodeObject* co, PyVar _module, PyVar _callable, PyVar* _locals_base)
: _ip(-1), _next_ip(0), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(co, _locals_base) { } : _ip(-1), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(co, _locals_base) { }
// exec/eval // exec/eval
Frame(PyVar* p0, const CodeObject* co, PyVar _module, PyVar _callable, FastLocals _locals) Frame(PyVar* p0, const CodeObject* co, PyVar _module, PyVar _callable, FastLocals _locals)
: _ip(-1), _next_ip(0), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(_locals) { } : _ip(-1), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(_locals) { }
// global scope // global scope
Frame(PyVar* p0, const CodeObject_& co, PyVar _module) Frame(PyVar* p0, const CodeObject_& co, PyVar _module)
: _ip(-1), _next_ip(0), _sp_base(p0), co(co.get()), _module(_module), _callable(nullptr), _locals(co.get(), p0) {} : _ip(-1), _sp_base(p0), co(co.get()), _module(_module), _callable(nullptr), _locals(co.get(), p0) {}
PyVar* actual_sp_base() const { return _locals.a; } PyVar* actual_sp_base() const { return _locals.a; }
int stack_size(ValueStack* _s) const { return _s->_sp - actual_sp_base(); } int stack_size(ValueStack* _s) const { return _s->_sp - actual_sp_base(); }
ArgsView stack_view(ValueStack* _s) const { return ArgsView(actual_sp_base(), _s->_sp); } ArgsView stack_view(ValueStack* _s) const { return ArgsView(actual_sp_base(), _s->_sp); }
void jump_abs(int i){ _next_ip = i; } [[nodiscard]] int prepare_jump_exception_handler(ValueStack*);
bool jump_to_exception_handler(ValueStack*); void prepare_jump_break(ValueStack*, int);
int _exit_block(ValueStack*, int); int _exit_block(ValueStack*, int);
void jump_abs_break(ValueStack*, int);
void loop_break(ValueStack* s_data, const CodeObject*){ [[nodiscard]] int prepare_loop_break(ValueStack* s_data){
jump_abs_break(s_data, co->_get_block_codei(_ip).end); int target = co->_get_block_codei(_ip).end;
prepare_jump_break(s_data, target);
return target;
} }
int curr_lineno() const { return co->lines[_ip].lineno; } int curr_lineno() const { return co->lines[_ip].lineno; }

View File

@ -157,6 +157,7 @@ public:
std::map<std::string_view, CodeObject_> __cached_codes; std::map<std::string_view, CodeObject_> __cached_codes;
std::map<std::string_view, PyVar> __cached_op_funcs; std::map<std::string_view, PyVar> __cached_op_funcs;
FuncDecl_ __dynamic_func_decl; FuncDecl_ __dynamic_func_decl;
InternalException __internal_exception;
PyVar __vectorcall_buffer[PK_MAX_CO_VARNAMES]; PyVar __vectorcall_buffer[PK_MAX_CO_VARNAMES];
#if PK_ENABLE_PROFILER #if PK_ENABLE_PROFILER

View File

@ -81,22 +81,6 @@ bool VM::py_ge(PyVar _0, PyVar _1){
#undef BINARY_F_COMPARE #undef BINARY_F_COMPARE
PyVar VM::__run_top_frame(){
Frame* frame = &callstack.top();
const Frame* base_frame = frame;
bool need_raise = false;
while(true){
try{
if(need_raise){ need_raise = false; __raise_exc(); }
/**********************************************************************/
/* NOTE:
* Be aware of accidental gc!
* DO NOT leave any strong reference of PyVar in the C stack
*/
{
#if PK_ENABLE_PROFILER #if PK_ENABLE_PROFILER
#define CEVAL_STEP_CALLBACK() \ #define CEVAL_STEP_CALLBACK() \
if(_ceval_on_step) _ceval_on_step(this, frame, byte); \ if(_ceval_on_step) _ceval_on_step(this, frame, byte); \
@ -109,17 +93,38 @@ PyVar VM::__run_top_frame(){
} }
#endif #endif
#define DISPATCH() goto __NEXT_STEP; #define DISPATCH() { frame->_ip++; goto __NEXT_STEP; }
#define DISPATCH_JUMP(__target) { frame->_ip = __target; goto __NEXT_STEP; }
#define RETURN_OP_YIELD() { frame->_ip++; return PY_OP_YIELD; }
PyVar VM::__run_top_frame(){
Frame* frame = &callstack.top();
const Frame* base_frame = frame;
while(true){
try{
/**********************************************************************/
{
__NEXT_FRAME: __NEXT_FRAME:
const CodeObject* co = frame->co; if(__internal_exception.type == InternalExceptionType::Null){
// None
frame->_ip++;
}else if(__internal_exception.type == InternalExceptionType::Handled){
// HandledException + continue
frame->_ip = __internal_exception.arg;
__internal_exception = {};
}else{
// UnhandledException + continue (need_raise = true)
// ToBeRaisedException + continue (need_raise = true)
__internal_exception = {};
__raise_exc(); // no return
}
// TODO: when jit is enabled, co_codes may not be const // TODO: when jit is enabled, co_codes may not be const
const Bytecode* co_codes = co->codes.data(); const Bytecode* co_codes = frame->co->codes.data();
Bytecode byte; Bytecode byte;
__NEXT_STEP: __NEXT_STEP:
frame->_ip = frame->_next_ip;
frame->_next_ip++;
byte = co_codes[frame->_ip]; byte = co_codes[frame->_ip];
CEVAL_STEP_CALLBACK() CEVAL_STEP_CALLBACK()
@ -139,13 +144,13 @@ __NEXT_STEP:
SECOND() = THIRD(); SECOND() = THIRD();
THIRD() = _0; THIRD() = _0;
} DISPATCH() } DISPATCH()
case OP_PRINT_EXPR:{ case OP_PRINT_EXPR:
if(TOP() != None) stdout_write(py_repr(TOP()) + "\n"); if(TOP() != None) stdout_write(py_repr(TOP()) + "\n");
POP(); POP();
} DISPATCH() DISPATCH()
/*****************************************/ /*****************************************/
case OP_LOAD_CONST: case OP_LOAD_CONST:
PUSH(co->consts[byte.arg]); PUSH(frame->co->consts[byte.arg]);
DISPATCH() DISPATCH()
case OP_LOAD_NONE: PUSH(None); DISPATCH() case OP_LOAD_NONE: PUSH(None); DISPATCH()
case OP_LOAD_TRUE: PUSH(True); DISPATCH() case OP_LOAD_TRUE: PUSH(True); DISPATCH()
@ -155,7 +160,7 @@ __NEXT_STEP:
/*****************************************/ /*****************************************/
case OP_LOAD_ELLIPSIS: PUSH(Ellipsis); DISPATCH() case OP_LOAD_ELLIPSIS: PUSH(Ellipsis); DISPATCH()
case OP_LOAD_FUNCTION: { case OP_LOAD_FUNCTION: {
const FuncDecl_& decl = co->func_decls[byte.arg]; const FuncDecl_& decl = frame->co->func_decls[byte.arg];
PyVar obj; PyVar obj;
if(decl->nested){ if(decl->nested){
NameDict_ captured = frame->_locals.to_namedict(); NameDict_ captured = frame->_locals.to_namedict();
@ -170,7 +175,7 @@ __NEXT_STEP:
/*****************************************/ /*****************************************/
case OP_LOAD_FAST: { case OP_LOAD_FAST: {
PyVar _0 = frame->_locals[byte.arg]; PyVar _0 = frame->_locals[byte.arg];
if(_0 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]); if(_0 == PY_NULL) vm->UnboundLocalError(frame->co->varnames[byte.arg]);
PUSH(_0); PUSH(_0);
} DISPATCH() } DISPATCH()
case OP_LOAD_NAME: { case OP_LOAD_NAME: {
@ -239,7 +244,7 @@ __NEXT_STEP:
} DISPATCH() } DISPATCH()
case OP_LOAD_SUBSCR_FAST:{ case OP_LOAD_SUBSCR_FAST:{
PyVar _1 = frame->_locals[byte.arg]; PyVar _1 = frame->_locals[byte.arg];
if(_1 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]); if(_1 == PY_NULL) vm->UnboundLocalError(frame->co->varnames[byte.arg]);
PyVar _0 = TOP(); // a PyVar _0 = TOP(); // a
auto _ti = _tp_info(_0); auto _ti = _tp_info(_0);
if(_ti->m__getitem__){ if(_ti->m__getitem__){
@ -303,7 +308,7 @@ __NEXT_STEP:
}DISPATCH() }DISPATCH()
case OP_STORE_SUBSCR_FAST:{ case OP_STORE_SUBSCR_FAST:{
PyVar _2 = frame->_locals[byte.arg]; // b PyVar _2 = frame->_locals[byte.arg]; // b
if(_2 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]); if(_2 == PY_NULL) vm->UnboundLocalError(frame->co->varnames[byte.arg]);
PyVar _1 = POPX(); // a PyVar _1 = POPX(); // a
PyVar _0 = POPX(); // val PyVar _0 = POPX(); // val
auto _ti = _tp_info(_1); auto _ti = _tp_info(_1);
@ -315,7 +320,7 @@ __NEXT_STEP:
}DISPATCH() }DISPATCH()
case OP_DELETE_FAST:{ case OP_DELETE_FAST:{
PyVar _0 = frame->_locals[byte.arg]; PyVar _0 = frame->_locals[byte.arg];
if(_0 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]); if(_0 == PY_NULL) vm->UnboundLocalError(frame->co->varnames[byte.arg]);
frame->_locals[byte.arg] = PY_NULL; frame->_locals[byte.arg] = PY_NULL;
}DISPATCH() }DISPATCH()
case OP_DELETE_NAME:{ case OP_DELETE_NAME:{
@ -626,49 +631,45 @@ __NEXT_STEP:
} DISPATCH() } DISPATCH()
/*****************************************/ /*****************************************/
case OP_JUMP_ABSOLUTE: case OP_JUMP_ABSOLUTE:
frame->jump_abs(byte.arg); DISPATCH_JUMP(byte.arg)
DISPATCH()
case OP_JUMP_ABSOLUTE_TOP: case OP_JUMP_ABSOLUTE_TOP:
frame->jump_abs(_CAST(int, POPX())); DISPATCH_JUMP(_CAST(int, POPX()))
case OP_POP_JUMP_IF_FALSE:
if(!py_bool(POPX())) DISPATCH_JUMP(byte.arg)
DISPATCH() DISPATCH()
case OP_POP_JUMP_IF_FALSE:{ case OP_POP_JUMP_IF_TRUE:
if(!py_bool(TOP())) frame->jump_abs(byte.arg); if(py_bool(POPX())) DISPATCH_JUMP(byte.arg)
POP(); DISPATCH()
} DISPATCH() case OP_JUMP_IF_TRUE_OR_POP:
case OP_POP_JUMP_IF_TRUE:{ if(py_bool(POPX())) DISPATCH_JUMP(byte.arg)
if(py_bool(TOP())) frame->jump_abs(byte.arg); DISPATCH()
POP(); case OP_JUMP_IF_FALSE_OR_POP:
} DISPATCH() if(!py_bool(POPX())) DISPATCH_JUMP(byte.arg)
case OP_JUMP_IF_TRUE_OR_POP:{ DISPATCH()
if(py_bool(TOP())) frame->jump_abs(byte.arg); case OP_SHORTCUT_IF_FALSE_OR_POP:
else POP();
} DISPATCH()
case OP_JUMP_IF_FALSE_OR_POP:{
if(!py_bool(TOP())) frame->jump_abs(byte.arg);
else POP();
} DISPATCH()
case OP_SHORTCUT_IF_FALSE_OR_POP:{
if(!py_bool(TOP())){ // [b, False] if(!py_bool(TOP())){ // [b, False]
STACK_SHRINK(2); // [] STACK_SHRINK(2); // []
PUSH(vm->False); // [False] PUSH(vm->False); // [False]
frame->jump_abs(byte.arg); DISPATCH_JUMP(byte.arg)
} else POP(); // [b] } else{
} DISPATCH() POP(); // [b]
DISPATCH()
}
case OP_LOOP_CONTINUE: case OP_LOOP_CONTINUE:
frame->jump_abs(byte.arg); DISPATCH_JUMP(byte.arg)
DISPATCH()
case OP_LOOP_BREAK: case OP_LOOP_BREAK:
frame->jump_abs_break(&s_data, byte.arg); frame->prepare_jump_break(&s_data, byte.arg);
DISPATCH() DISPATCH_JUMP(byte.arg)
case OP_GOTO: { case OP_GOTO: {
StrName _name(byte.arg); StrName _name(byte.arg);
int index = co->labels.try_get_likely_found(_name); int target = frame->co->labels.try_get_likely_found(_name);
if(index < 0) RuntimeError(_S("label ", _name.escape(), " not found")); if(target < 0) RuntimeError(_S("label ", _name.escape(), " not found"));
frame->jump_abs_break(&s_data, index); frame->prepare_jump_break(&s_data, target);
} DISPATCH() DISPATCH_JUMP(target)
}
/*****************************************/ /*****************************************/
case OP_FSTRING_EVAL:{ case OP_FSTRING_EVAL:{
PyVar _0 = co->consts[byte.arg]; PyVar _0 = frame->co->consts[byte.arg];
std::string_view string = CAST(Str&, _0).sv(); std::string_view string = CAST(Str&, _0).sv();
auto it = __cached_codes.find(string); auto it = __cached_codes.find(string);
CodeObject_ code; CodeObject_ code;
@ -743,8 +744,7 @@ __NEXT_STEP:
goto __NEXT_FRAME; goto __NEXT_FRAME;
} }
} DISPATCH() } DISPATCH()
case OP_YIELD_VALUE: case OP_YIELD_VALUE: RETURN_OP_YIELD()
return PY_OP_YIELD;
/*****************************************/ /*****************************************/
case OP_LIST_APPEND:{ case OP_LIST_APPEND:{
PyVar _0 = POPX(); PyVar _0 = POPX();
@ -785,34 +785,44 @@ __NEXT_STEP:
DISPATCH() DISPATCH()
case OP_FOR_ITER:{ case OP_FOR_ITER:{
PyVar _0 = py_next(TOP()); PyVar _0 = py_next(TOP());
if(_0 == StopIteration) frame->loop_break(&s_data, co); if(_0 == StopIteration){
else PUSH(_0); int target = frame->prepare_loop_break(&s_data);
} DISPATCH() DISPATCH_JUMP(target)
} else{
PUSH(_0);
DISPATCH()
}
}
case OP_FOR_ITER_STORE_FAST:{ case OP_FOR_ITER_STORE_FAST:{
PyVar _0 = py_next(TOP()); PyVar _0 = py_next(TOP());
if(_0 == StopIteration){ if(_0 == StopIteration){
frame->loop_break(&s_data, co); int target = frame->prepare_loop_break(&s_data);
DISPATCH_JUMP(target)
}else{ }else{
frame->_locals[byte.arg] = _0; frame->_locals[byte.arg] = _0;
DISPATCH()
}
} }
} DISPATCH()
case OP_FOR_ITER_STORE_GLOBAL:{ case OP_FOR_ITER_STORE_GLOBAL:{
PyVar _0 = py_next(TOP()); PyVar _0 = py_next(TOP());
if(_0 == StopIteration){ if(_0 == StopIteration){
frame->loop_break(&s_data, co); int target = frame->prepare_loop_break(&s_data);
DISPATCH_JUMP(target)
}else{ }else{
frame->f_globals().set(StrName(byte.arg), _0); frame->f_globals().set(StrName(byte.arg), _0);
DISPATCH()
}
} }
} DISPATCH()
case OP_FOR_ITER_YIELD_VALUE:{ case OP_FOR_ITER_YIELD_VALUE:{
PyVar _0 = py_next(TOP()); PyVar _0 = py_next(TOP());
if(_0 == StopIteration){ if(_0 == StopIteration){
frame->loop_break(&s_data, co); int target = frame->prepare_loop_break(&s_data);
DISPATCH_JUMP(target)
}else{ }else{
PUSH(_0); PUSH(_0);
return PY_OP_YIELD; RETURN_OP_YIELD()
}
} }
} DISPATCH()
case OP_FOR_ITER_UNPACK:{ case OP_FOR_ITER_UNPACK:{
PyVar _0 = TOP(); PyVar _0 = TOP();
const PyTypeInfo* _ti = _tp_info(_0); const PyTypeInfo* _ti = _tp_info(_0);
@ -820,7 +830,8 @@ __NEXT_STEP:
unsigned n = _ti->m__next__(this, _0); unsigned n = _ti->m__next__(this, _0);
if(n == 0){ if(n == 0){
// StopIteration // StopIteration
frame->loop_break(&s_data, co); int target = frame->prepare_loop_break(&s_data);
DISPATCH_JUMP(target)
}else if(n == 1){ }else if(n == 1){
// UNPACK_SEQUENCE // UNPACK_SEQUENCE
__op_unpack_sequence(byte.arg); __op_unpack_sequence(byte.arg);
@ -837,13 +848,14 @@ __NEXT_STEP:
// UNPACK_SEQUENCE // UNPACK_SEQUENCE
__op_unpack_sequence(byte.arg); __op_unpack_sequence(byte.arg);
}else{ }else{
frame->loop_break(&s_data, co); int target = frame->prepare_loop_break(&s_data);
DISPATCH_JUMP(target)
} }
} }
} DISPATCH() } DISPATCH()
/*****************************************/ /*****************************************/
case OP_IMPORT_PATH:{ case OP_IMPORT_PATH:{
PyVar _0 = co->consts[byte.arg]; PyVar _0 = frame->co->consts[byte.arg];
PUSH(py_import(CAST(Str&, _0))); PUSH(py_import(CAST(Str&, _0)));
} DISPATCH() } DISPATCH()
case OP_POP_IMPORT_STAR: { case OP_POP_IMPORT_STAR: {
@ -970,18 +982,18 @@ __NEXT_STEP:
/*****************************************/ /*****************************************/
case OP_FORMAT_STRING: { case OP_FORMAT_STRING: {
PyVar _0 = POPX(); PyVar _0 = POPX();
const Str& spec = CAST(Str&, co->consts[byte.arg]); const Str& spec = CAST(Str&, frame->co->consts[byte.arg]);
PUSH(__format_object(_0, spec)); PUSH(__format_object(_0, spec));
} DISPATCH() } DISPATCH()
/*****************************************/ /*****************************************/
case OP_INC_FAST:{ case OP_INC_FAST:{
PyVar* p = &frame->_locals[byte.arg]; PyVar* p = &frame->_locals[byte.arg];
if(*p == PY_NULL) vm->NameError(co->varnames[byte.arg]); if(*p == PY_NULL) vm->NameError(frame->co->varnames[byte.arg]);
*p = VAR(CAST(i64, *p) + 1); *p = VAR(CAST(i64, *p) + 1);
} DISPATCH() } DISPATCH()
case OP_DEC_FAST:{ case OP_DEC_FAST:{
PyVar* p = &frame->_locals[byte.arg]; PyVar* p = &frame->_locals[byte.arg];
if(*p == PY_NULL) vm->NameError(co->varnames[byte.arg]); if(*p == PY_NULL) vm->NameError(frame->co->varnames[byte.arg]);
*p = VAR(CAST(i64, *p) - 1); *p = VAR(CAST(i64, *p) - 1);
} DISPATCH() } DISPATCH()
case OP_INC_GLOBAL:{ case OP_INC_GLOBAL:{
@ -1002,9 +1014,9 @@ __NEXT_STEP:
} }
/**********************************************************************/ /**********************************************************************/
PK_UNREACHABLE(); PK_UNREACHABLE();
}catch(HandledException){ }catch(InternalException internal){
continue; this->__internal_exception = internal;
}catch(UnhandledException){ if(internal.type == InternalExceptionType::Unhandled){
PyVar e_obj = POPX(); PyVar e_obj = POPX();
Exception& _e = PK_OBJ_GET(Exception, e_obj); Exception& _e = PK_OBJ_GET(Exception, e_obj);
bool is_base_frame_to_be_popped = frame == base_frame; bool is_base_frame_to_be_popped = frame == base_frame;
@ -1012,10 +1024,10 @@ __NEXT_STEP:
if(callstack.empty()) throw _e; // propagate to the top level if(callstack.empty()) throw _e; // propagate to the top level
frame = &callstack.top(); frame = &callstack.top();
PUSH(e_obj); PUSH(e_obj);
if(is_base_frame_to_be_popped) throw ToBeRaisedException(); if(is_base_frame_to_be_popped){
need_raise = true; throw InternalException(InternalExceptionType::ToBeRaised);
}catch(ToBeRaisedException){ }
need_raise = true; }
} }
} }
} }
@ -1030,6 +1042,8 @@ __NEXT_STEP:
#undef STACK_VIEW #undef STACK_VIEW
#undef DISPATCH #undef DISPATCH
#undef DISPATCH_JUMP
#undef RETURN_OP_YIELD
#undef CEVAL_STEP_CALLBACK #undef CEVAL_STEP_CALLBACK
} // namespace pkpy } // namespace pkpy

View File

@ -23,22 +23,21 @@ namespace pkpy{
return fn._closure->try_get(name); return fn._closure->try_get(name);
} }
bool Frame::jump_to_exception_handler(ValueStack* _s){ int Frame::prepare_jump_exception_handler(ValueStack* _s){
// try to find a parent try block // try to find a parent try block
int block = co->iblocks[_ip]; int block = co->iblocks[_ip];
while(block >= 0){ while(block >= 0){
if(co->blocks[block].type == CodeBlockType::TRY_EXCEPT) break; if(co->blocks[block].type == CodeBlockType::TRY_EXCEPT) break;
block = co->blocks[block].parent; block = co->blocks[block].parent;
} }
if(block < 0) return false; if(block < 0) return -1;
PyVar obj = _s->popx(); // pop exception object PyVar obj = _s->popx(); // pop exception object
// get the stack size of the try block // get the stack size of the try block
int _stack_size = co->blocks[block].base_stack_size; int _stack_size = co->blocks[block].base_stack_size;
if(stack_size(_s) < _stack_size) throw std::runtime_error(_S("invalid state: ", stack_size(_s), '<', _stack_size).str()); if(stack_size(_s) < _stack_size) throw std::runtime_error(_S("invalid state: ", stack_size(_s), '<', _stack_size).str());
_s->reset(actual_sp_base() + _locals.size() + _stack_size); // rollback the stack _s->reset(actual_sp_base() + _locals.size() + _stack_size); // rollback the stack
_s->push(obj); // push exception object _s->push(obj); // push exception object
_next_ip = co->blocks[block].end; return co->blocks[block].end;
return true;
} }
int Frame::_exit_block(ValueStack* _s, int i){ int Frame::_exit_block(ValueStack* _s, int i){
@ -47,10 +46,9 @@ namespace pkpy{
return co->blocks[i].parent; return co->blocks[i].parent;
} }
void Frame::jump_abs_break(ValueStack* _s, int target){ void Frame::prepare_jump_break(ValueStack* _s, int target){
int i = co->iblocks[_ip]; int i = co->iblocks[_ip];
_next_ip = target; if(target >= co->codes.size()){
if(_next_ip >= co->codes.size()){
while(i>=0) i = _exit_block(_s, i); while(i>=0) i = _exit_block(_s, i);
}else{ }else{
// BUG (solved) // BUG (solved)

View File

@ -425,7 +425,7 @@ bool VM::__py_bool_non_trivial(PyVar obj){
PyVar len_f = get_unbound_method(obj, __len__, &self, false); PyVar len_f = get_unbound_method(obj, __len__, &self, false);
if(self != PY_NULL){ if(self != PY_NULL){
PyVar ret = call_method(self, len_f); PyVar ret = call_method(self, len_f);
return CAST(i64, ret) > 0; return CAST(i64, ret) != 0;
} }
return true; return true;
} }
@ -1398,7 +1398,7 @@ void VM::__raise_exc(bool re_raise){
e._ip_on_error = frame->_ip; e._ip_on_error = frame->_ip;
e._code_on_error = (void*)frame->co; e._code_on_error = (void*)frame->co;
} }
bool ok = frame->jump_to_exception_handler(&s_data); int next_ip = frame->prepare_jump_exception_handler(&s_data);
int actual_ip = frame->_ip; int actual_ip = frame->_ip;
if(e._ip_on_error >= 0 && e._code_on_error == (void*)frame->co) actual_ip = e._ip_on_error; if(e._ip_on_error >= 0 && e._code_on_error == (void*)frame->co) actual_ip = e._ip_on_error;
@ -1407,8 +1407,11 @@ void VM::__raise_exc(bool re_raise){
if(frame->_callable == nullptr) current_f_name = ""; // not in a function if(frame->_callable == nullptr) current_f_name = ""; // not in a function
e.st_push(frame->co->src, current_line, nullptr, current_f_name); e.st_push(frame->co->src, current_line, nullptr, current_f_name);
if(ok) throw HandledException(); if(next_ip >= 0){
else throw UnhandledException(); throw InternalException(InternalExceptionType::Handled, next_ip);
}else{
throw InternalException(InternalExceptionType::Unhandled);
}
} }
void ManagedHeap::mark() { void ManagedHeap::mark() {