diff --git a/src/ceval.h b/src/ceval.h index e8429a5b..871b4eb4 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -5,9 +5,21 @@ namespace pkpy{ -#define DISPATCH() goto __NEXT_STEP +inline PyObject* VM::_run_top_frame(){ + FrameId frame = top_frame(); + const int base_id = frame.index; + bool need_raise = false; + PyObject* __ret; -inline PyObject* VM::run_frame(FrameId frame){ + while(true){ +#if DEBUG_EXTRA_CHECK + if(frame->id < base_id) UNREACHABLE(); +#endif + try{ + if(need_raise){ need_raise = false; _raise(); } +/**********************************************************************/ +#define DISPATCH() goto __NEXT_STEP +{ __NEXT_STEP:; /* NOTE: * Be aware of accidental gc! @@ -284,7 +296,7 @@ __NEXT_STEP:; if(byte.op == OP_CALL_UNPACK) unpack_args(args); PyObject* callable = frame->popx(); PyObject* ret = call(callable, std::move(args), no_arg(), true); - if(ret == _py_op_call) return ret; + if(ret == _py_op_call) { __ret=ret; goto __PY_OP_CALL; } frame->push(std::move(ret)); } DISPATCH(); case OP_CALL_KWARGS: case OP_CALL_KWARGS_UNPACK: { @@ -300,10 +312,10 @@ __NEXT_STEP:; if(byte.op == OP_CALL_KWARGS_UNPACK) unpack_args(args); PyObject* callable = frame->popx(); PyObject* ret = call(callable, std::move(args), kwargs, true); - if(ret == _py_op_call) return ret; + if(ret == _py_op_call) { __ret=ret; goto __PY_OP_CALL; } frame->push(std::move(ret)); } DISPATCH(); - case OP_RETURN_VALUE: return frame->popx(); + case OP_RETURN_VALUE: { __ret=frame->popx(); goto __PY_SIMPLE_RETURN; } case OP_YIELD_VALUE: return _py_op_yield; /*****************************************/ case OP_LIST_APPEND: { @@ -456,7 +468,42 @@ __NEXT_STEP:; } UNREACHABLE(); } - #undef DISPATCH +/**********************************************************************/ +__PY_SIMPLE_RETURN: + if(frame.index == base_id){ // [ frameBase<- ] + callstack.pop(); + return __ret; + }else{ + callstack.pop(); + frame = top_frame(); + frame->push(__ret); + } + continue; +__PY_OP_CALL: + frame = top_frame(); // [ frameBase, newFrame<- ] + continue; + }catch(HandledException& e){ + continue; + }catch(UnhandledException& e){ + PyObject* obj = frame->popx(); + Exception& _e = CAST(Exception&, obj); + _e.st_push(frame->snapshot()); + callstack.pop(); + if(callstack.empty()){ +#if DEBUG_FULL_EXCEPTION + std::cerr << _e.summary() << std::endl; +#endif + throw _e; + } + frame = top_frame(); + frame->push(obj); + if(frame.index < base_id) throw ToBeRaisedException(); + need_raise = true; + }catch(ToBeRaisedException& e){ + need_raise = true; + } + } +} } // namespace pkpy \ No newline at end of file diff --git a/src/iter.h b/src/iter.h index 07d3faea..457cb010 100644 --- a/src/iter.h +++ b/src/iter.h @@ -64,7 +64,7 @@ public: inline PyObject* Generator::next(){ if(state == 2) return nullptr; vm->_push_new_frame(std::move(frame)); - PyObject* ret = vm->_exec(); + PyObject* ret = vm->_run_top_frame(); if(ret == vm->_py_op_yield){ frame = std::move(vm->callstack.top()); vm->callstack.pop(); diff --git a/src/vm.h b/src/vm.h index ff45625e..6acf383a 100644 --- a/src/vm.h +++ b/src/vm.h @@ -64,8 +64,6 @@ public: stack< Frame > callstack; std::vector _all_types; - PyObject* run_frame(FrameId frame); - NameDict _modules; // loaded modules std::map _lazy_modules; // lazy loaded modules @@ -206,7 +204,7 @@ public: template PyObject* _exec(Args&&... args){ _push_new_frame(std::forward(args)...); - return _exec(); + return _run_top_frame(); } PyObject* property(NativeFuncRaw fget){ @@ -349,7 +347,7 @@ public: template void bind_func(PyObject*, Str, NativeFuncRaw); void _error(Exception); - PyObject* _exec(); + PyObject* _run_top_frame(); void post_init(); }; @@ -747,7 +745,7 @@ inline PyObject* VM::call(PyObject* callable, Args args, const Args& kwargs, boo } _push_new_frame(fn.decl->code, _module, locals, fn._closure); if(opCall) return _py_op_call; - return _exec(); + return _run_top_frame(); } if(is_type(callable, tp_type)){ @@ -906,55 +904,6 @@ inline void VM::_error(Exception e){ _raise(); } -inline PyObject* VM::_exec(){ - FrameId frame = top_frame(); - const int base_id = frame.index; - bool need_raise = false; - PyObject* ret; - - while(true){ -#if DEBUG_EXTRA_CHECK - if(frame->id < base_id) UNREACHABLE(); -#endif - try{ - if(need_raise){ need_raise = false; _raise(); } - ret = run_frame(frame); - if(ret == _py_op_yield) return _py_op_yield; - if(ret != _py_op_call){ - if(frame.index == base_id){ // [ frameBase<- ] - callstack.pop(); - return ret; - }else{ - callstack.pop(); - frame = top_frame(); - frame->push(ret); - } - }else{ - frame = top_frame(); // [ frameBase, newFrame<- ] - } - }catch(HandledException& e){ - continue; - }catch(UnhandledException& e){ - PyObject* obj = frame->popx(); - Exception& _e = CAST(Exception&, obj); - _e.st_push(frame->snapshot()); - callstack.pop(); - if(callstack.empty()){ -#if DEBUG_FULL_EXCEPTION - std::cerr << _e.summary() << std::endl; -#endif - throw _e; - } - frame = top_frame(); - frame->push(obj); - if(frame.index < base_id) throw ToBeRaisedException(); - need_raise = true; - }catch(ToBeRaisedException& e){ - need_raise = true; - } - } -} - inline void ManagedHeap::mark() { for(PyObject* obj: _no_gc) OBJ_MARK(obj); for(auto& frame : vm->callstack.data()) frame._gc_mark();