blueloveTH 2 лет назад
Родитель
Сommit
1d36ab0235
5 измененных файлов с 28 добавлено и 30 удалено
  1. 4 4
      src/ceval.h
  2. 7 0
      src/common.h
  3. 1 1
      src/iter.h
  4. 2 0
      src/obj.h
  5. 14 25
      src/vm.h

+ 4 - 4
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();

+ 7 - 0
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> Expr_;
 

+ 1 - 1
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();

+ 2 - 0
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;
 }

+ 14 - 25
src/vm.h

@@ -83,10 +83,6 @@ public:
     NameDict _modules;                                  // 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* 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<typename... Args>
     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<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->_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, <self>, 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){