This commit is contained in:
blueloveTH 2023-04-18 18:55:54 +08:00
parent d828fcfecc
commit 1d36ab0235
5 changed files with 28 additions and 30 deletions

View File

@ -92,7 +92,7 @@ __NEXT_STEP:;
} }
PUSH(obj); PUSH(obj);
} DISPATCH(); } DISPATCH();
TARGET(LOAD_NULL) PUSH(_py_null); DISPATCH(); TARGET(LOAD_NULL) PUSH(PY_NULL); DISPATCH();
/*****************************************/ /*****************************************/
TARGET(LOAD_FAST) { TARGET(LOAD_FAST) {
heap._auto_collect(); heap._auto_collect();
@ -369,7 +369,7 @@ __NEXT_STEP:;
} DISPATCH(); } DISPATCH();
/*****************************************/ /*****************************************/
TARGET(BEGIN_CALL) TARGET(BEGIN_CALL)
PUSH(_py_begin_call); PUSH(PY_BEGIN_CALL);
DISPATCH(); DISPATCH();
TARGET(CALL) TARGET(CALL)
_0 = vectorcall( _0 = vectorcall(
@ -377,7 +377,7 @@ __NEXT_STEP:;
(byte.arg>>16) & 0xFFFF, // KWARGC (byte.arg>>16) & 0xFFFF, // KWARGC
true true
); );
if(_0 == _py_op_call) DISPATCH_OP_CALL(); if(_0 == PY_OP_CALL) DISPATCH_OP_CALL();
PUSH(_0); PUSH(_0);
DISPATCH(); DISPATCH();
TARGET(RETURN_VALUE) TARGET(RETURN_VALUE)
@ -391,7 +391,7 @@ __NEXT_STEP:;
goto __NEXT_FRAME; goto __NEXT_FRAME;
} }
TARGET(YIELD_VALUE) TARGET(YIELD_VALUE)
return _py_op_yield; return PY_OP_YIELD;
/*****************************************/ /*****************************************/
TARGET(LIST_APPEND) { TARGET(LIST_APPEND) {
PyObject* obj = POPX(); PyObject* obj = POPX();

View File

@ -120,6 +120,7 @@ struct PyObject;
inline bool is_tagged(PyObject* p) noexcept { return (BITS(p) & 0b11) != 0b00; } 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_int(PyObject* p) noexcept { return (BITS(p) & 0b11) == 0b01; }
inline bool is_float(PyObject* p) noexcept { return (BITS(p) & 0b11) == 0b10; } 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 { inline bool is_both_int_or_float(PyObject* a, PyObject* b) noexcept {
return is_tagged(a) && is_tagged(b); 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); 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; struct Expr;
typedef std::unique_ptr<Expr> Expr_; typedef std::unique_ptr<Expr> Expr_;

View File

@ -75,7 +75,7 @@ inline PyObject* Generator::next(){
s_backup.clear(); s_backup.clear();
vm->callstack.push(std::move(frame)); vm->callstack.push(std::move(frame));
PyObject* ret = vm->_run_top_frame(); PyObject* ret = vm->_run_top_frame();
if(ret == vm->_py_op_yield){ if(ret == PY_OP_YIELD){
// backup the context // backup the context
frame = std::move(vm->callstack.top()); frame = std::move(vm->callstack.top());
PyObject* ret = frame._s->popx(); PyObject* ret = frame._s->popx();

View File

@ -161,6 +161,7 @@ const int kTpFloatIndex = 3;
inline bool is_type(PyObject* obj, Type type) { inline bool is_type(PyObject* obj, Type type) {
#if DEBUG_EXTRA_CHECK #if DEBUG_EXTRA_CHECK
if(obj == nullptr) throw std::runtime_error("is_type() called with nullptr"); 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 #endif
switch(type.index){ switch(type.index){
case kTpIntIndex: return is_int(obj); 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) { inline bool is_non_tagged_type(PyObject* obj, Type type) {
#if DEBUG_EXTRA_CHECK #if DEBUG_EXTRA_CHECK
if(obj == nullptr) throw std::runtime_error("is_non_tagged_type() called with nullptr"); 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 #endif
return !is_tagged(obj) && obj->type == type; return !is_tagged(obj) && obj->type == type;
} }

View File

@ -83,10 +83,6 @@ public:
NameDict _modules; // loaded modules NameDict _modules; // loaded modules
std::map<StrName, Str> _lazy_modules; // lazy loaded modules std::map<StrName, Str> _lazy_modules; // lazy loaded modules
PyObject* _py_null;
PyObject* _py_begin_call;
PyObject* _py_op_call;
PyObject* _py_op_yield;
PyObject* None; PyObject* None;
PyObject* True; PyObject* True;
PyObject* False; PyObject* False;
@ -130,7 +126,7 @@ public:
PyObject* asStr(PyObject* obj){ PyObject* asStr(PyObject* obj){
PyObject* self; PyObject* self;
PyObject* f = get_unbound_method(obj, __str__, &self, false); 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); return asRepr(obj);
} }
@ -138,7 +134,7 @@ public:
if(is_type(obj, tp_iterator)) return obj; if(is_type(obj, tp_iterator)) return obj;
PyObject* self; PyObject* self;
PyObject* iter_f = get_unbound_method(obj, __iter__, &self, false); 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"); TypeError(OBJ_NAME(_t(obj)).escape() + " object is not iterable");
return nullptr; return nullptr;
} }
@ -216,7 +212,7 @@ public:
template<typename... Args> template<typename... Args>
PyObject* call(PyObject* callable, Args&&... args){ PyObject* call(PyObject* callable, Args&&... args){
PUSH(callable); PUSH(callable);
PUSH(_py_null); PUSH(PY_NULL);
_push_varargs(args...); _push_varargs(args...);
return vectorcall(sizeof...(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; if(is_float(obj)) return CAST(f64, obj) != 0.0;
PyObject* self; PyObject* self;
PyObject* len_f = get_unbound_method(obj, __len__, &self, false); 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); PyObject* ret = call_method(self, len_f);
return CAST(i64, ret) > 0; return CAST(i64, ret) > 0;
} }
@ -684,8 +680,8 @@ inline void VM::_log_s_data(const char* title) {
if(sp_bases[p] > 0) ss << " "; if(sp_bases[p] > 0) ss << " ";
PyObject* obj = *p; PyObject* obj = *p;
if(obj == nullptr) ss << "(nil)"; if(obj == nullptr) ss << "(nil)";
else if(obj == _py_begin_call) ss << "BEGIN_CALL"; else if(obj == PY_BEGIN_CALL) ss << "BEGIN_CALL";
else if(obj == _py_null) ss << "NULL"; else if(obj == PY_NULL) ss << "NULL";
else if(is_int(obj)) ss << CAST(i64, obj); else if(is_int(obj)) ss << CAST(i64, obj);
else if(is_float(obj)) ss << CAST(f64, obj); else if(is_float(obj)) ss << CAST(f64, obj);
else if(is_type(obj, tp_str)) ss << CAST(Str, obj).escape(); 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<Dummy>(tp_bool, {}); this->True = heap._new<Dummy>(tp_bool, {});
this->False = heap._new<Dummy>(tp_bool, {}); this->False = heap._new<Dummy>(tp_bool, {});
Type _internal_type = _new_type_object("_internal");
this->_py_null = heap._new<Dummy>(_internal_type, {});
this->_py_begin_call = heap._new<Dummy>(_internal_type, {});
this->_py_op_call = heap._new<Dummy>(_internal_type, {});
this->_py_op_yield = heap._new<Dummy>(_internal_type, {});
this->builtins = new_module("builtins"); this->builtins = new_module("builtins");
this->_main = new_module("__main__"); 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; PyObject** p1 = s_data._sp - KWARGC*2;
if(is_varargs){ if(is_varargs){
p0 = p1 - 1; p0 = p1 - 1;
while(*p0 != _py_begin_call) p0--; while(*p0 != PY_BEGIN_CALL) p0--;
// [BEGIN_CALL, callable, <self>, args..., kwargs...] // [BEGIN_CALL, callable, <self>, args..., kwargs...]
// ^p0 ^p1 ^_sp // ^p0 ^p1 ^_sp
ARGC = p1 - (p0 + 3); ARGC = p1 - (p0 + 3);
@ -787,7 +777,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
// ^p0 ^p1 ^_sp // ^p0 ^p1 ^_sp
} }
PyObject* callable = p1[-(ARGC + 2)]; 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 // 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); PyObject* ret = _py_call(p0, callable, args, kwargs);
// stack resetting is handled by _py_call // stack resetting is handled by _py_call
if(ret != nullptr) return ret; if(ret != nullptr) return ret;
if(op_call) return _py_op_call; if(op_call) return PY_OP_CALL;
return _run_top_frame(); return _run_top_frame();
} }
@ -831,7 +821,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
PyObject* obj; PyObject* obj;
if(new_f != nullptr){ if(new_f != nullptr){
PUSH(new_f); PUSH(new_f);
PUSH(_py_null); PUSH(PY_NULL);
for(PyObject* obj: args) PUSH(obj); for(PyObject* obj: args) PUSH(obj);
for(PyObject* obj: kwargs) PUSH(obj); for(PyObject* obj: kwargs) PUSH(obj);
obj = vectorcall(ARGC, KWARGC); obj = vectorcall(ARGC, KWARGC);
@ -841,7 +831,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
} }
PyObject* self; PyObject* self;
callable = get_unbound_method(obj, __init__, &self, false); callable = get_unbound_method(obj, __init__, &self, false);
if (self != _py_null) { if (self != PY_NULL) {
// replace `NULL` with `self` // replace `NULL` with `self`
p1[-(ARGC + 2)] = callable; p1[-(ARGC + 2)] = callable;
p1[-(ARGC + 1)] = self; p1[-(ARGC + 1)] = self;
@ -859,7 +849,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
// handle `__call__` overload // handle `__call__` overload
PyObject* self; PyObject* self;
PyObject* call_f = get_unbound_method(callable, __call__, &self, false); 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 + 2)] = call_f;
p1[-(ARGC + 1)] = self; p1[-(ARGC + 1)] = self;
// [call_f, self, args..., kwargs...] // [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 // used by OP_LOAD_METHOD
// try to load a unbound method (fallback to `getattr` if not found) // 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){ 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); PyObject* objtype = _t(obj);
// handle super() proxy // handle super() proxy
if(is_non_tagged_type(obj, tp_super)){ if(is_non_tagged_type(obj, tp_super)){
@ -1067,8 +1057,7 @@ inline void VM::_error(Exception e){
inline void ManagedHeap::mark() { inline void ManagedHeap::mark() {
for(PyObject* obj: _no_gc) OBJ_MARK(obj); for(PyObject* obj: _no_gc) OBJ_MARK(obj);
for(auto& frame : vm->callstack.data()) frame._gc_mark(); 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){ inline Str obj_type_name(VM *vm, Type type){