From 697c2b0922a0d48e81cc5c7ef06497f9fff6fd70 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Mon, 17 Apr 2023 17:48:13 +0800 Subject: [PATCH] ... --- src/ceval.h | 326 ++++++++++++++++++++++++++-------------------------- 1 file changed, 164 insertions(+), 162 deletions(-) diff --git a/src/ceval.h b/src/ceval.h index 289a86a8..3ac2cfd7 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -11,6 +11,10 @@ inline PyObject* VM::_run_top_frame(){ const int base_id = frame.index; bool need_raise = false; + // shared registers + PyObject *_0, *_1, *_2; + StrName _name; + while(true){ #if DEBUG_EXTRA_CHECK if(frame.index < base_id) FATAL_ERROR(); @@ -21,8 +25,6 @@ inline PyObject* VM::_run_top_frame(){ /* NOTE: * Be aware of accidental gc! * DO NOT leave any strong reference of PyObject* in the C stack - * For example, POPX() returns a strong reference which may be dangerous - * `Args` containing strong references is safe if it is passed to `call` or `fast_call` */ { #define DISPATCH_OP_CALL() { frame = top_frame(); goto __NEXT_FRAME; } @@ -63,11 +65,10 @@ __NEXT_STEP:; TARGET(POP_TOP) POP(); DISPATCH(); TARGET(DUP_TOP) PUSH(TOP()); DISPATCH(); TARGET(ROT_TWO) std::swap(TOP(), SECOND()); DISPATCH(); - TARGET(PRINT_EXPR) { - PyObject* obj = TOP(); // use top() to avoid accidental gc - if(obj != None) *_stdout << CAST(Str&, asRepr(obj)) << '\n'; + TARGET(PRINT_EXPR) + if(TOP() != None) *_stdout << CAST(Str&, asRepr(TOP())) << '\n'; POP(); - } DISPATCH(); + DISPATCH(); /*****************************************/ TARGET(LOAD_CONST) heap._auto_collect(); @@ -93,134 +94,127 @@ __NEXT_STEP:; /*****************************************/ TARGET(LOAD_FAST) { heap._auto_collect(); - PyObject* val = frame->_locals[byte.arg]; - if(val == nullptr) vm->NameError(co->varnames[byte.arg]); - PUSH(val); + _0 = frame->_locals[byte.arg]; + if(_0 == nullptr) vm->NameError(co->varnames[byte.arg]); + PUSH(_0); } DISPATCH(); - TARGET(LOAD_NAME) { + TARGET(LOAD_NAME) heap._auto_collect(); - StrName name(byte.arg); - PyObject* val; - val = frame->_locals.try_get(name); - if(val != nullptr) { PUSH(val); DISPATCH(); } - val = frame->_closure.try_get(name); - if(val != nullptr) { PUSH(val); DISPATCH(); } - val = frame->f_globals().try_get(name); - if(val != nullptr) { PUSH(val); DISPATCH(); } - val = vm->builtins->attr().try_get(name); - if(val != nullptr) { PUSH(val); DISPATCH(); } - vm->NameError(name); - } DISPATCH(); + _name = StrName(byte.arg); + _0 = frame->_locals.try_get(_name); + if(_0 != nullptr) { PUSH(_0); DISPATCH(); } + _0 = frame->_closure.try_get(_name); + if(_0 != nullptr) { PUSH(_0); DISPATCH(); } + _0 = frame->f_globals().try_get(_name); + if(_0 != nullptr) { PUSH(_0); DISPATCH(); } + _0 = vm->builtins->attr().try_get(_name); + if(_0 != nullptr) { PUSH(_0); DISPATCH(); } + vm->NameError(_name); + DISPATCH(); TARGET(LOAD_NONLOCAL) { heap._auto_collect(); - StrName name(byte.arg); - PyObject* val; - val = frame->_closure.try_get(name); - if(val != nullptr) { PUSH(val); DISPATCH(); } - val = frame->f_globals().try_get(name); - if(val != nullptr) { PUSH(val); DISPATCH(); } - val = vm->builtins->attr().try_get(name); - if(val != nullptr) { PUSH(val); DISPATCH(); } - vm->NameError(name); + _name = StrName(byte.arg); + // _0 = frame->_locals.try_get(_name); + // if(_0 != nullptr) { PUSH(_0); DISPATCH(); } + _0 = frame->_closure.try_get(_name); + if(_0 != nullptr) { PUSH(_0); DISPATCH(); } + _0 = frame->f_globals().try_get(_name); + if(_0 != nullptr) { PUSH(_0); DISPATCH(); } + _0 = vm->builtins->attr().try_get(_name); + if(_0 != nullptr) { PUSH(_0); DISPATCH(); } + vm->NameError(_name); + DISPATCH(); } DISPATCH(); - TARGET(LOAD_GLOBAL) { + TARGET(LOAD_GLOBAL) heap._auto_collect(); - StrName name(byte.arg); - PyObject* val = frame->f_globals().try_get(name); - if(val != nullptr) { PUSH(val); DISPATCH(); } - val = vm->builtins->attr().try_get(name); - if(val != nullptr) { PUSH(val); DISPATCH(); } - vm->NameError(name); - } DISPATCH(); - TARGET(LOAD_ATTR) { - PyObject* a = TOP(); - StrName name(byte.arg); - TOP() = getattr(a, name); - } DISPATCH(); - TARGET(LOAD_METHOD) { - PyObject* a = TOP(); - StrName name(byte.arg); - PyObject* self; - TOP() = get_unbound_method(a, name, &self, true, true); - PUSH(self); - } DISPATCH(); - TARGET(LOAD_SUBSCR) { - PyObject* b = POPX(); - PyObject* a = TOP(); - TOP() = call_method(a, __getitem__, b); - } DISPATCH(); + _name = StrName(byte.arg); + _0 = frame->f_globals().try_get(_name); + if(_0 != nullptr) { PUSH(_0); DISPATCH(); } + _0 = vm->builtins->attr().try_get(_name); + if(_0 != nullptr) { PUSH(_0); DISPATCH(); } + vm->NameError(_name); + DISPATCH(); + TARGET(LOAD_ATTR) + TOP() = getattr(TOP(), StrName(byte.arg)); + DISPATCH(); + TARGET(LOAD_METHOD) + TOP() = get_unbound_method(TOP(), StrName(byte.arg), &_0, true, true); + PUSH(_0); + DISPATCH(); + TARGET(LOAD_SUBSCR) + _1 = POPX(); + _0 = TOP(); + TOP() = call_method(_0, __getitem__, _1); + DISPATCH(); TARGET(STORE_FAST) frame->_locals[byte.arg] = POPX(); DISPATCH(); - TARGET(STORE_NAME) { - StrName name(byte.arg); - PyObject* val = POPX(); + TARGET(STORE_NAME) + _name = StrName(byte.arg); + _0 = POPX(); if(frame->_locals.is_valid()){ - bool ok = frame->_locals.try_set(name, val); - if(!ok) vm->NameError(name); + bool ok = frame->_locals.try_set(_name, _0); + if(!ok) vm->NameError(_name); }else{ - frame->f_globals().set(name, val); + frame->f_globals().set(_name, _0); } - } DISPATCH(); - TARGET(STORE_GLOBAL) { - StrName name(byte.arg); - frame->f_globals().set(name, POPX()); - } DISPATCH(); + DISPATCH(); + TARGET(STORE_GLOBAL) + frame->f_globals().set(StrName(byte.arg), POPX()); + DISPATCH(); TARGET(STORE_ATTR) { - StrName name(byte.arg); - PyObject* a = TOP(); - PyObject* val = SECOND(); - setattr(a, name, val); + _0 = TOP(); // a + _1 = SECOND(); // val + setattr(_0, StrName(byte.arg), _1); STACK_SHRINK(2); } DISPATCH(); - TARGET(STORE_SUBSCR) { - // val a b - PyObject* b = POPX(); - PyObject* a = POPX(); - PyObject* val = POPX(); - call_method(a, __setitem__, b, val); - } DISPATCH(); - TARGET(DELETE_FAST) { - PyObject* val = frame->_locals[byte.arg]; - if(val == nullptr) vm->NameError(co->varnames[byte.arg]); + TARGET(STORE_SUBSCR) + _2 = POPX(); // b + _1 = POPX(); // a + _0 = POPX(); // val + call_method(_1, __setitem__, _2, _0); + DISPATCH(); + TARGET(DELETE_FAST) + _0 = frame->_locals[byte.arg]; + if(_0 == nullptr) vm->NameError(co->varnames[byte.arg]); frame->_locals[byte.arg] = nullptr; - } DISPATCH(); - TARGET(DELETE_NAME) { - StrName name(byte.arg); + DISPATCH(); + TARGET(DELETE_NAME) + _name = StrName(byte.arg); if(frame->_locals.is_valid()){ - if(!frame->_locals.contains(name)) vm->NameError(name); - frame->_locals.erase(name); + if(!frame->_locals.contains(_name)) vm->NameError(_name); + frame->_locals.erase(_name); }else{ - if(!frame->f_globals().contains(name)) vm->NameError(name); - frame->f_globals().erase(name); + if(!frame->f_globals().contains(_name)) vm->NameError(_name); + frame->f_globals().erase(_name); } - } DISPATCH(); - TARGET(DELETE_GLOBAL) { - StrName name(byte.arg); - if(frame->f_globals().contains(name)){ - frame->f_globals().erase(name); + DISPATCH(); + TARGET(DELETE_GLOBAL) + _name = StrName(byte.arg); + if(frame->f_globals().contains(_name)){ + frame->f_globals().erase(_name); }else{ - NameError(name); + NameError(_name); } - } DISPATCH(); - TARGET(DELETE_ATTR) { - PyObject* a = POPX(); - StrName name(byte.arg); - if(!a->is_attr_valid()) TypeError("cannot delete attribute"); - if(!a->attr().contains(name)) AttributeError(a, name); - a->attr().erase(name); - } DISPATCH(); - TARGET(DELETE_SUBSCR) { - PyObject* b = POPX(); - PyObject* a = POPX(); - call_method(a, __delitem__, b); - } DISPATCH(); + DISPATCH(); + TARGET(DELETE_ATTR) + _0 = POPX(); + _name = StrName(byte.arg); + if(!_0->is_attr_valid()) TypeError("cannot delete attribute"); + if(!_0->attr().contains(_name)) AttributeError(_0, _name); + _0->attr().erase(_name); + DISPATCH(); + TARGET(DELETE_SUBSCR) + _1 = POPX(); + _0 = POPX(); + call_method(_0, __delitem__, _1); + DISPATCH(); /*****************************************/ - TARGET(BUILD_LIST) { - PyObject* obj = VAR(STACK_VIEW(byte.arg).to_list()); + TARGET(BUILD_LIST) + _0 = VAR(STACK_VIEW(byte.arg).to_list()); STACK_SHRINK(byte.arg); - PUSH(obj); - } DISPATCH(); + PUSH(_0); + DISPATCH(); TARGET(BUILD_DICT) { PyObject* t = VAR(STACK_VIEW(byte.arg).to_tuple()); PyObject* obj = call_(builtins->attr(m_dict), t); @@ -234,20 +228,20 @@ __NEXT_STEP:; PUSH(obj); } DISPATCH(); TARGET(BUILD_SLICE) { - PyObject* step = POPX(); - PyObject* stop = POPX(); - PyObject* start = POPX(); + _2 = POPX(); + _1 = POPX(); + _0 = POPX(); Slice s; - if(start != None) s.start = CAST(int, start); - if(stop != None) s.stop = CAST(int, stop); - if(step != None) s.step = CAST(int, step); + if(_0 != None) s.start = CAST(int, _0); + if(_1 != None) s.stop = CAST(int, _1); + if(_2 != None) s.step = CAST(int, _2); PUSH(VAR(s)); } DISPATCH(); - TARGET(BUILD_TUPLE) { - PyObject* obj = VAR(STACK_VIEW(byte.arg).to_tuple()); + TARGET(BUILD_TUPLE) + _0 = VAR(STACK_VIEW(byte.arg).to_tuple()); STACK_SHRINK(byte.arg); - PUSH(obj); - } DISPATCH(); + PUSH(_0); + DISPATCH(); TARGET(BUILD_STRING) { std::stringstream ss; auto view = STACK_VIEW(byte.arg); @@ -256,11 +250,11 @@ __NEXT_STEP:; PUSH(VAR(ss.str())); } DISPATCH(); /*****************************************/ - TARGET(BINARY_OP) { - PyObject* b = POPX(); - PyObject* a = TOP(); - TOP() = call_method(a, BINARY_SPECIAL_METHODS[byte.arg], b); - } DISPATCH(); + TARGET(BINARY_OP) + _1 = POPX(); // b + _0 = TOP(); // a + TOP() = call_method(_0, BINARY_SPECIAL_METHODS[byte.arg], _1); + DISPATCH(); #define INT_BINARY_OP(op, func) \ if(is_both_int(TOP(), SECOND())){ \ @@ -269,9 +263,9 @@ __NEXT_STEP:; POP(); \ TOP() = VAR(a op b); \ }else{ \ - PyObject* b = POPX(); \ - PyObject* a = TOP(); \ - TOP() = call_method(a, func, b); \ + _1 = POPX(); \ + _0 = TOP(); \ + TOP() = call_method(_0, func, _1); \ } TARGET(BINARY_ADD) @@ -323,22 +317,29 @@ __NEXT_STEP:; INT_BINARY_OP(^, __xor__) DISPATCH() #undef INT_BINARY_OP - TARGET(IS_OP) { - PyObject* rhs = POPX(); - PyObject* lhs = TOP(); - bool ret_c = lhs == rhs; - if(byte.arg == 1) ret_c = !ret_c; - TOP() = VAR(ret_c); - } DISPATCH(); - TARGET(CONTAINS_OP) { + + TARGET(IS_OP) + _1 = POPX(); // rhs + _0 = TOP(); // lhs + if(byte.arg == 1){ + TOP() = VAR(_0 != _1); + }else{ + TOP() = VAR(_0 == _1); + } + DISPATCH(); + TARGET(CONTAINS_OP) // a in b -> b __contains__ a - PyObject* ret = call_method(TOP(), __contains__, SECOND()); - bool ret_c = CAST(bool, ret); - if(byte.arg == 1) ret_c = !ret_c; - TOP() = VAR(ret_c); - } DISPATCH(); + _0 = call_method(TOP(), __contains__, SECOND()); + if(byte.arg == 1){ + TOP() = VAR(!CAST(bool, _0)); + }else{ + TOP() = VAR(CAST(bool, _0)); + } + DISPATCH(); /*****************************************/ - TARGET(JUMP_ABSOLUTE) frame->jump_abs(byte.arg); DISPATCH(); + TARGET(JUMP_ABSOLUTE) + frame->jump_abs(byte.arg); + DISPATCH(); TARGET(POP_JUMP_IF_FALSE) if(!asBool(POPX())) frame->jump_abs(byte.arg); DISPATCH(); @@ -354,10 +355,11 @@ __NEXT_STEP:; int target = co_blocks[byte.block].start; frame->jump_abs(target); } DISPATCH(); - TARGET(LOOP_BREAK) { - int target = co_blocks[byte.block].end; - frame->jump_abs_break(target); - } DISPATCH(); + TARGET(LOOP_BREAK) + frame->jump_abs_break( + co_blocks[byte.block].end + ); + DISPATCH(); TARGET(GOTO) { StrName name(byte.arg); int index = co->labels->try_get(name); @@ -368,27 +370,27 @@ __NEXT_STEP:; TARGET(BEGIN_CALL) PUSH(_py_begin_call); DISPATCH(); - TARGET(CALL) { - int ARGC = byte.arg & 0xFFFF; - int KWARGC = (byte.arg >> 16) & 0xFFFF; - PyObject* ret = _vectorcall(ARGC, KWARGC, true); - if(ret == _py_op_call) { DISPATCH_OP_CALL(); } - PUSH(ret); + TARGET(CALL) + _0 = _vectorcall( + byte.arg & 0xFFFF, // ARGC + (byte.arg>>16) & 0xFFFF, // KWARGC + true + ); + if(_0 == _py_op_call) DISPATCH_OP_CALL(); + PUSH(_0); DISPATCH(); - } - TARGET(RETURN_VALUE) { - PyObject* __ret = POPX(); + TARGET(RETURN_VALUE) + _0 = POPX(); // cleanup the stack on return callstack.pop(); s_data.reset(frame->_sp_base); if(frame.index == base_id){ // [ frameBase<- ] - return __ret; + return _0; }else{ frame = top_frame(); - PUSH(__ret); + PUSH(_0); goto __NEXT_FRAME; } - } TARGET(YIELD_VALUE) return _py_op_yield; /*****************************************/ @@ -423,9 +425,9 @@ __NEXT_STEP:; DISPATCH(); TARGET(FOR_ITER) { BaseIter* it = PyIter_AS_C(TOP()); - PyObject* obj = it->next(); - if(obj != nullptr){ - PUSH(obj); + _0 = it->next(); + if(_0 != nullptr){ + PUSH(_0); }else{ int target = co_blocks[byte.block].end; frame->jump_abs_break(target);