From 1d36ab0235a19b8afef831319f62528b59280d6b Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Tue, 18 Apr 2023 18:55:54 +0800 Subject: [PATCH] ... --- src/ceval.h | 8 ++++---- src/common.h | 7 +++++++ src/iter.h | 2 +- src/obj.h | 2 ++ src/vm.h | 39 ++++++++++++++------------------------- 5 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/ceval.h b/src/ceval.h index 4b1238b2..81ab9c57 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -92,7 +92,7 @@ __NEXT_STEP:; } PUSH(obj); } DISPATCH(); - TARGET(LOAD_NULL) PUSH(_py_null); DISPATCH(); + TARGET(LOAD_NULL) PUSH(PY_NULL); DISPATCH(); /*****************************************/ TARGET(LOAD_FAST) { heap._auto_collect(); @@ -369,7 +369,7 @@ __NEXT_STEP:; } DISPATCH(); /*****************************************/ TARGET(BEGIN_CALL) - PUSH(_py_begin_call); + PUSH(PY_BEGIN_CALL); DISPATCH(); TARGET(CALL) _0 = vectorcall( @@ -377,7 +377,7 @@ __NEXT_STEP:; (byte.arg>>16) & 0xFFFF, // KWARGC true ); - if(_0 == _py_op_call) DISPATCH_OP_CALL(); + if(_0 == PY_OP_CALL) DISPATCH_OP_CALL(); PUSH(_0); DISPATCH(); TARGET(RETURN_VALUE) @@ -391,7 +391,7 @@ __NEXT_STEP:; goto __NEXT_FRAME; } TARGET(YIELD_VALUE) - return _py_op_yield; + return PY_OP_YIELD; /*****************************************/ TARGET(LIST_APPEND) { PyObject* obj = POPX(); diff --git a/src/common.h b/src/common.h index 203cd463..7b0101c0 100644 --- a/src/common.h +++ b/src/common.h @@ -120,6 +120,7 @@ struct PyObject; inline bool is_tagged(PyObject* p) noexcept { return (BITS(p) & 0b11) != 0b00; } inline bool is_int(PyObject* p) noexcept { return (BITS(p) & 0b11) == 0b01; } inline bool is_float(PyObject* p) noexcept { return (BITS(p) & 0b11) == 0b10; } +inline bool is_special(PyObject* p) noexcept { return (BITS(p) & 0b11) == 0b11; } inline bool is_both_int_or_float(PyObject* a, PyObject* b) noexcept { return is_tagged(a) && is_tagged(b); @@ -129,6 +130,12 @@ inline bool is_both_int(PyObject* a, PyObject* b) noexcept { return is_int(a) && is_int(b); } +// special singals, is_tagged() for them is true +inline PyObject* const PY_NULL = (PyObject*)0b000011; +inline PyObject* const PY_BEGIN_CALL = (PyObject*)0b010011; +inline PyObject* const PY_OP_CALL = (PyObject*)0b100011; +inline PyObject* const PY_OP_YIELD = (PyObject*)0b110011; + struct Expr; typedef std::unique_ptr Expr_; diff --git a/src/iter.h b/src/iter.h index eb2c9f5d..f06047ec 100644 --- a/src/iter.h +++ b/src/iter.h @@ -75,7 +75,7 @@ inline PyObject* Generator::next(){ s_backup.clear(); vm->callstack.push(std::move(frame)); PyObject* ret = vm->_run_top_frame(); - if(ret == vm->_py_op_yield){ + if(ret == PY_OP_YIELD){ // backup the context frame = std::move(vm->callstack.top()); PyObject* ret = frame._s->popx(); diff --git a/src/obj.h b/src/obj.h index 74d609f8..800f4a9e 100644 --- a/src/obj.h +++ b/src/obj.h @@ -161,6 +161,7 @@ const int kTpFloatIndex = 3; inline bool is_type(PyObject* obj, Type type) { #if DEBUG_EXTRA_CHECK if(obj == nullptr) throw std::runtime_error("is_type() called with nullptr"); + if(is_special(obj)) throw std::runtime_error("is_type() called with special object"); #endif switch(type.index){ case kTpIntIndex: return is_int(obj); @@ -172,6 +173,7 @@ inline bool is_type(PyObject* obj, Type type) { inline bool is_non_tagged_type(PyObject* obj, Type type) { #if DEBUG_EXTRA_CHECK if(obj == nullptr) throw std::runtime_error("is_non_tagged_type() called with nullptr"); + if(is_special(obj)) throw std::runtime_error("is_non_tagged_type() called with special object"); #endif return !is_tagged(obj) && obj->type == type; } diff --git a/src/vm.h b/src/vm.h index 74dc82fc..1130590e 100644 --- a/src/vm.h +++ b/src/vm.h @@ -83,10 +83,6 @@ public: NameDict _modules; // loaded modules std::map _lazy_modules; // lazy loaded modules - PyObject* _py_null; - PyObject* _py_begin_call; - PyObject* _py_op_call; - PyObject* _py_op_yield; PyObject* None; PyObject* True; PyObject* False; @@ -130,7 +126,7 @@ public: PyObject* asStr(PyObject* obj){ PyObject* self; PyObject* f = get_unbound_method(obj, __str__, &self, false); - if(self != _py_null) return call_method(self, f); + if(self != PY_NULL) return call_method(self, f); return asRepr(obj); } @@ -138,7 +134,7 @@ public: if(is_type(obj, tp_iterator)) return obj; PyObject* self; PyObject* iter_f = get_unbound_method(obj, __iter__, &self, false); - if(self != _py_null) return call_method(self, iter_f); + if(self != PY_NULL) return call_method(self, iter_f); TypeError(OBJ_NAME(_t(obj)).escape() + " object is not iterable"); return nullptr; } @@ -216,7 +212,7 @@ public: template PyObject* call(PyObject* callable, Args&&... args){ PUSH(callable); - PUSH(_py_null); + PUSH(PY_NULL); _push_varargs(args...); return vectorcall(sizeof...(args)); } @@ -549,7 +545,7 @@ inline bool VM::asBool(PyObject* obj){ if(is_float(obj)) return CAST(f64, obj) != 0.0; PyObject* self; PyObject* len_f = get_unbound_method(obj, __len__, &self, false); - if(self != _py_null){ + if(self != PY_NULL){ PyObject* ret = call_method(self, len_f); return CAST(i64, ret) > 0; } @@ -684,8 +680,8 @@ inline void VM::_log_s_data(const char* title) { if(sp_bases[p] > 0) ss << " "; PyObject* obj = *p; if(obj == nullptr) ss << "(nil)"; - else if(obj == _py_begin_call) ss << "BEGIN_CALL"; - else if(obj == _py_null) ss << "NULL"; + else if(obj == PY_BEGIN_CALL) ss << "BEGIN_CALL"; + else if(obj == PY_NULL) ss << "NULL"; else if(is_int(obj)) ss << CAST(i64, obj); else if(is_float(obj)) ss << CAST(f64, obj); else if(is_type(obj, tp_str)) ss << CAST(Str, obj).escape(); @@ -744,12 +740,6 @@ inline void VM::init_builtin_types(){ this->True = heap._new(tp_bool, {}); this->False = heap._new(tp_bool, {}); - Type _internal_type = _new_type_object("_internal"); - this->_py_null = heap._new(_internal_type, {}); - this->_py_begin_call = heap._new(_internal_type, {}); - this->_py_op_call = heap._new(_internal_type, {}); - this->_py_op_yield = heap._new(_internal_type, {}); - this->builtins = new_module("builtins"); this->_main = new_module("__main__"); @@ -777,7 +767,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){ PyObject** p1 = s_data._sp - KWARGC*2; if(is_varargs){ p0 = p1 - 1; - while(*p0 != _py_begin_call) p0--; + while(*p0 != PY_BEGIN_CALL) p0--; // [BEGIN_CALL, callable, , args..., kwargs...] // ^p0 ^p1 ^_sp ARGC = p1 - (p0 + 3); @@ -787,7 +777,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){ // ^p0 ^p1 ^_sp } PyObject* callable = p1[-(ARGC + 2)]; - bool method_call = p1[-(ARGC + 1)] != _py_null; + bool method_call = p1[-(ARGC + 1)] != PY_NULL; // handle boundmethod, do a patch @@ -818,7 +808,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){ PyObject* ret = _py_call(p0, callable, args, kwargs); // stack resetting is handled by _py_call if(ret != nullptr) return ret; - if(op_call) return _py_op_call; + if(op_call) return PY_OP_CALL; return _run_top_frame(); } @@ -831,7 +821,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){ PyObject* obj; if(new_f != nullptr){ PUSH(new_f); - PUSH(_py_null); + PUSH(PY_NULL); for(PyObject* obj: args) PUSH(obj); for(PyObject* obj: kwargs) PUSH(obj); obj = vectorcall(ARGC, KWARGC); @@ -841,7 +831,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){ } PyObject* self; callable = get_unbound_method(obj, __init__, &self, false); - if (self != _py_null) { + if (self != PY_NULL) { // replace `NULL` with `self` p1[-(ARGC + 2)] = callable; p1[-(ARGC + 1)] = self; @@ -859,7 +849,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){ // handle `__call__` overload PyObject* self; PyObject* call_f = get_unbound_method(callable, __call__, &self, false); - if(self != _py_null){ + if(self != PY_NULL){ p1[-(ARGC + 2)] = call_f; p1[-(ARGC + 1)] = self; // [call_f, self, args..., kwargs...] @@ -984,7 +974,7 @@ inline PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err){ // used by OP_LOAD_METHOD // try to load a unbound method (fallback to `getattr` if not found) inline PyObject* VM::get_unbound_method(PyObject* obj, StrName name, PyObject** self, bool throw_err, bool fallback){ - *self = _py_null; + *self = PY_NULL; PyObject* objtype = _t(obj); // handle super() proxy if(is_non_tagged_type(obj, tp_super)){ @@ -1067,8 +1057,7 @@ inline void VM::_error(Exception e){ inline void ManagedHeap::mark() { for(PyObject* obj: _no_gc) OBJ_MARK(obj); for(auto& frame : vm->callstack.data()) frame._gc_mark(); - // TODO: avoid use nullptr? - for(PyObject* obj: vm->s_data) if(obj != nullptr) OBJ_MARK(obj); + for(PyObject* obj: vm->s_data) if(obj!=nullptr) OBJ_MARK(obj); } inline Str obj_type_name(VM *vm, Type type){