Kaynağa Gözat

object pool impl

blueloveTH 3 yıl önce
ebeveyn
işleme
e816ceee6c
9 değiştirilmiş dosya ile 191 ekleme ve 108 silme
  1. 17 2
      src/common.h
  2. 6 8
      src/iter.h
  3. 10 2
      src/memory.h
  4. 25 3
      src/obj.h
  5. 46 24
      src/pocketpy.h
  6. 8 7
      src/ref.h
  7. 12 4
      src/safestl.h
  8. 5 2
      src/str.h
  9. 62 56
      src/vm.h

+ 17 - 2
src/common.h

@@ -31,8 +31,23 @@
 #define UNREACHABLE() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " UNREACHABLE()!");
 #define UNREACHABLE() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " UNREACHABLE()!");
 #endif
 #endif
 
 
-#define PK_VERSION "0.8.3"
+#define PK_VERSION "0.8.4"
 
 
 typedef int64_t i64;
 typedef int64_t i64;
 typedef double f64;
 typedef double f64;
-#define DUMMY_VAL (i64)0
+#define DUMMY_VAL (char)1
+#define DUMMY_VAL_TP char
+
+template<typename T>
+void* tid() {
+	static volatile int8_t _x;
+	return (void*)(&_x);
+}
+
+// This does not ensure to be unique when the pointer of obj->type is deleted & reused.
+// But it is good enough for now.
+template<typename T>
+void* obj_tid(void* alt){
+    if constexpr(std::is_same_v<T, DUMMY_VAL_TP>) return alt;
+    return tid<T>();
+}

+ 6 - 8
src/iter.h

@@ -22,16 +22,14 @@ public:
     }
     }
 };
 };
 
 
-class VectorIter : public BaseIter {
+template <typename T>
+class ArrayIter : public BaseIter {
     size_t index = 0;
     size_t index = 0;
-    const PyVarList* vec;
+    const T* p;
 public:
 public:
-    VectorIter(VM* vm, PyVar _ref) : BaseIter(vm, _ref) {
-        vec = &OBJ_GET(PyVarList, _ref);
-    }
-
-    bool hasNext(){ return index < vec->size(); }
-    PyVar next(){ return vec->operator[](index++); }
+    ArrayIter(VM* vm, PyVar _ref) : BaseIter(vm, _ref) { p = &OBJ_GET(T, _ref);}
+    bool hasNext(){ return index < p->size(); }
+    PyVar next(){ return p->operator[](index++); }
 };
 };
 
 
 class StringIter : public BaseIter {
 class StringIter : public BaseIter {

+ 10 - 2
src/memory.h

@@ -3,17 +3,25 @@
 #include "common.h"
 #include "common.h"
 
 
 namespace pkpy{
 namespace pkpy{
+    template<typename T>
+    struct sp_deleter {
+        inline static void call(int* counter){
+            ((T*)(counter + 1))->~T();
+            free(counter);
+        }
+    };
+
     template <typename T>
     template <typename T>
     class shared_ptr {
     class shared_ptr {
         int* counter = nullptr;
         int* counter = nullptr;
 
 
 #define _t() ((T*)(counter + 1))
 #define _t() ((T*)(counter + 1))
 #define _inc_counter() if(counter) ++(*counter)
 #define _inc_counter() if(counter) ++(*counter)
-#define _dec_counter() if(counter && --(*counter) == 0){ _t()->~T(); free(counter); }
+#define _dec_counter() if(counter && --(*counter) == 0){ pkpy::sp_deleter<T>::call(counter); }
 
 
     public:
     public:
         shared_ptr() {}
         shared_ptr() {}
-        shared_ptr(int* block) : counter(block) {}
+        shared_ptr(int* counter) : counter(counter) {}
         shared_ptr(const shared_ptr& other) : counter(other.counter) {
         shared_ptr(const shared_ptr& other) : counter(other.counter) {
             _inc_counter();
             _inc_counter();
         }
         }

+ 25 - 3
src/obj.h

@@ -78,7 +78,8 @@ struct PyObject {
     PyVarDict attribs;
     PyVarDict attribs;
 
 
     inline bool is_type(const PyVar& type) const noexcept{ return this->type == type; }
     inline bool is_type(const PyVar& type) const noexcept{ return this->type == type; }
-    inline virtual void* value() = 0;
+    virtual void* value() = 0;
+    virtual void* type_id() = 0;
 
 
     PyObject(const PyVar& type) : type(type) {}
     PyObject(const PyVar& type) : type(type) {}
     virtual ~PyObject() = default;
     virtual ~PyObject() = default;
@@ -89,7 +90,8 @@ struct Py_ : PyObject {
     T _value;
     T _value;
 
 
     Py_(const PyVar& type, T val) : PyObject(type), _value(val) {}
     Py_(const PyVar& type, T val) : PyObject(type), _value(val) {}
-    virtual void* value() override { return &_value; }
+    void* value() override { return &_value; }
+    void* type_id() override { return obj_tid<T>((void*)type.get()); }
 };
 };
 
 
 // Unsafe cast from PyObject to C++ type
 // Unsafe cast from PyObject to C++ type
@@ -102,4 +104,24 @@ struct Py_ : PyObject {
     inline static const char* _mod() { return #mod; } \
     inline static const char* _mod() { return #mod; } \
     inline static const char* _name() { return #name; }
     inline static const char* _name() { return #name; }
 
 
-#define PY_BUILTIN_CLASS(name) inline static PyVar _type(VM* vm) { return vm->_tp_##name; }
+#define PY_BUILTIN_CLASS(name) inline static PyVar _type(VM* vm) { return vm->_tp_##name; }
+
+
+// memory pool _tp -> [obj1, obj2, ...]
+static thread_local emhash8::HashMap<void*, std::vector<int*>> _obj_pool;
+
+namespace pkpy {
+    template<>
+    struct sp_deleter<PyObject> {
+        inline static void call(int* counter) {
+            PyObject* obj = (PyObject*)(counter + 1);
+            std::vector<int*>& pool = _obj_pool[obj->type_id()];
+            if(pool.size() > 100){
+                obj->~PyObject();
+                free(counter);
+            }else{
+                pool.push_back(counter);
+            }
+        }
+    };
+}

+ 46 - 24
src/pocketpy.h

@@ -370,20 +370,23 @@ void init_builtins(VM* _vm) {
     });
     });
 
 
     _vm->bind_method<1>("str", "join", [](VM* vm, const pkpy::Args& args) {
     _vm->bind_method<1>("str", "join", [](VM* vm, const pkpy::Args& args) {
-        const _Str& _self = vm->PyStr_AS_C(args[0]);
-        PyVarList* _list = nullptr;
+        const _Str& self = vm->PyStr_AS_C(args[0]);
+        _StrStream ss;
         if(args[1]->is_type(vm->_tp_list)){
         if(args[1]->is_type(vm->_tp_list)){
-            _list = &vm->PyList_AS_C(args[1]);
+            const PyVarList& a = vm->PyList_AS_C(args[1]);
+            for(int i = 0; i < a.size(); i++){
+                if(i > 0) ss << self;
+                ss << vm->PyStr_AS_C(vm->asStr(a[i]));
+            }
         }else if(args[1]->is_type(vm->_tp_tuple)){
         }else if(args[1]->is_type(vm->_tp_tuple)){
-            _list = &vm->PyTuple_AS_C(args[1]);
+            const _Tuple& a = vm->PyTuple_AS_C(args[1]);
+            for(int i = 0; i < a.size(); i++){
+                if(i > 0) ss << self;
+                ss << vm->PyStr_AS_C(vm->asStr(a[i]));
+            }
         }else{
         }else{
             vm->TypeError("can only join a list or tuple");
             vm->TypeError("can only join a list or tuple");
         }
         }
-        _StrStream ss;
-        for(int i = 0; i < _list->size(); i++){
-            if(i > 0) ss << _self;
-            ss << vm->PyStr_AS_C(vm->asStr(_list->operator[](i)));
-        }
         return vm->PyStr(ss.str());
         return vm->PyStr(ss.str());
     });
     });
 
 
@@ -426,25 +429,24 @@ void init_builtins(VM* _vm) {
         return vm->PyInt(_self.size());
         return vm->PyInt(_self.size());
     });
     });
 
 
-    _vm->_bind_methods<0>({"list", "tuple"}, "__iter__", [](VM* vm, const pkpy::Args& args) {
-        return vm->PyIter(pkpy::make_shared<BaseIter, VectorIter>(vm, args[0]));
+    _vm->bind_method<0>("list", "__iter__", [](VM* vm, const pkpy::Args& args) {
+        return vm->PyIter(pkpy::make_shared<BaseIter, ArrayIter<PyVarList>>(vm, args[0]));
     });
     });
 
 
-    _vm->_bind_methods<1>({"list", "tuple"}, "__getitem__", [](VM* vm, const pkpy::Args& args) {
-        bool list = args[0]->is_type(vm->_tp_list);
-        const PyVarList& _self = list ? vm->PyList_AS_C(args[0]) : vm->PyTuple_AS_C(args[0]);
+    _vm->bind_method<1>("list", "__getitem__", [](VM* vm, const pkpy::Args& args) {
+        const PyVarList& self = vm->PyList_AS_C(args[0]);
 
 
         if(args[1]->is_type(vm->_tp_slice)){
         if(args[1]->is_type(vm->_tp_slice)){
             _Slice s = vm->PySlice_AS_C(args[1]);
             _Slice s = vm->PySlice_AS_C(args[1]);
-            s.normalize(_self.size());
-            PyVarList _new_list;
-            for(size_t i = s.start; i < s.stop; i++) _new_list.push_back(_self[i]);
-            return list ? vm->PyList(_new_list) : vm->PyTuple(_new_list);
+            s.normalize(self.size());
+            PyVarList new_list;
+            for(size_t i = s.start; i < s.stop; i++) new_list.push_back(self[i]);
+            return vm->PyList(std::move(new_list));
         }
         }
 
 
-        int _index = (int)vm->PyInt_AS_C(args[1]);
-        _index = vm->normalized_index(_index, _self.size());
-        return _self[_index];
+        int index = (int)vm->PyInt_AS_C(args[1]);
+        index = vm->normalized_index(index, self.size());
+        return self[index];
     });
     });
 
 
     _vm->bind_method<2>("list", "__setitem__", [](VM* vm, const pkpy::Args& args) {
     _vm->bind_method<2>("list", "__setitem__", [](VM* vm, const pkpy::Args& args) {
@@ -466,12 +468,32 @@ void init_builtins(VM* _vm) {
     /************ PyTuple ************/
     /************ PyTuple ************/
     _vm->bind_static_method<1>("tuple", "__new__", [](VM* vm, const pkpy::Args& args) {
     _vm->bind_static_method<1>("tuple", "__new__", [](VM* vm, const pkpy::Args& args) {
         PyVarList _list = vm->PyList_AS_C(vm->call(vm->builtins->attribs["list"], args));
         PyVarList _list = vm->PyList_AS_C(vm->call(vm->builtins->attribs["list"], args));
-        return vm->PyTuple(_list);
+        return vm->PyTuple(std::move(_list));
+    });
+
+    _vm->bind_method<0>("tuple", "__iter__", [](VM* vm, const pkpy::Args& args) {
+        return vm->PyIter(pkpy::make_shared<BaseIter, ArrayIter<pkpy::Args>>(vm, args[0]));
+    });
+
+    _vm->bind_method<1>("tuple", "__getitem__", [](VM* vm, const pkpy::Args& args) {
+        const _Tuple& self = vm->PyTuple_AS_C(args[0]);
+
+        if(args[1]->is_type(vm->_tp_slice)){
+            _Slice s = vm->PySlice_AS_C(args[1]);
+            s.normalize(self.size());
+            PyVarList new_list;
+            for(size_t i = s.start; i < s.stop; i++) new_list.push_back(self[i]);
+            return vm->PyTuple(std::move(new_list));
+        }
+
+        int index = (int)vm->PyInt_AS_C(args[1]);
+        index = vm->normalized_index(index, self.size());
+        return self[index];
     });
     });
 
 
     _vm->bind_method<0>("tuple", "__len__", [](VM* vm, const pkpy::Args& args) {
     _vm->bind_method<0>("tuple", "__len__", [](VM* vm, const pkpy::Args& args) {
-        const PyVarList& _self = vm->PyTuple_AS_C(args[0]);
-        return vm->PyInt(_self.size());
+        const _Tuple& self = vm->PyTuple_AS_C(args[0]);
+        return vm->PyInt(self.size());
     });
     });
 
 
     /************ PyBool ************/
     /************ PyBool ************/

+ 8 - 7
src/ref.h

@@ -17,8 +17,10 @@ enum NameScope {
 };
 };
 
 
 struct NameRef : BaseRef {
 struct NameRef : BaseRef {
-    const std::pair<_Str, NameScope>* pair;
-    NameRef(const std::pair<_Str, NameScope>& pair) : pair(&pair) {}
+    std::pair<_Str, NameScope>* _pair;
+    inline const _Str& name() const { return _pair->first; }
+    inline NameScope scope() const { return _pair->second; }
+    NameRef(std::pair<_Str, NameScope>& pair) : _pair(&pair) {}
 
 
     PyVar get(VM* vm, Frame* frame) const;
     PyVar get(VM* vm, Frame* frame) const;
     void set(VM* vm, Frame* frame, PyVar val) const;
     void set(VM* vm, Frame* frame, PyVar val) const;
@@ -27,8 +29,8 @@ struct NameRef : BaseRef {
 
 
 struct AttrRef : BaseRef {
 struct AttrRef : BaseRef {
     mutable PyVar obj;
     mutable PyVar obj;
-    const NameRef attr;
-    AttrRef(PyVar obj, const NameRef attr) : obj(obj), attr(attr) {}
+    NameRef attr;
+    AttrRef(PyVar obj, NameRef attr) : obj(obj), attr(attr) {}
 
 
     PyVar get(VM* vm, Frame* frame) const;
     PyVar get(VM* vm, Frame* frame) const;
     void set(VM* vm, Frame* frame, PyVar val) const;
     void set(VM* vm, Frame* frame, PyVar val) const;
@@ -46,9 +48,8 @@ struct IndexRef : BaseRef {
 };
 };
 
 
 struct TupleRef : BaseRef {
 struct TupleRef : BaseRef {
-    PyVarList varRefs;
-    TupleRef(const PyVarList& varRefs) : varRefs(varRefs) {}
-    TupleRef(PyVarList&& varRefs) : varRefs(std::move(varRefs)) {}
+    _Tuple objs;
+    TupleRef(_Tuple&& objs) : objs(std::move(objs)) {}
 
 
     PyVar get(VM* vm, Frame* frame) const;
     PyVar get(VM* vm, Frame* frame) const;
     void set(VM* vm, Frame* frame, PyVar val) const;
     void set(VM* vm, Frame* frame, PyVar val) const;

+ 12 - 4
src/safestl.h

@@ -58,7 +58,7 @@ namespace pkpy {
             }
             }
         }
         }
 
 
-        void _release(){
+        void _free(){
             if(_size == 0 || _args == nullptr) return;
             if(_size == 0 || _args == nullptr) return;
             if(_size >= kMaxPoolSize || _args_pool[_size].size() > 32){
             if(_size >= kMaxPoolSize || _args_pool[_size].size() > 32){
                 delete[] _args;
                 delete[] _args;
@@ -76,6 +76,12 @@ namespace pkpy {
             for(int i=0; i<_size; i++) _args[i] = other._args[i];
             for(int i=0; i<_size; i++) _args[i] = other._args[i];
         }
         }
 
 
+        Args(std::initializer_list<PyVar> a){
+            _alloc(a.size());
+            int i = 0;
+            for(auto& v: a) _args[i++] = v;
+        }
+
         Args(Args&& other) noexcept {
         Args(Args&& other) noexcept {
             this->_args = other._args;
             this->_args = other._args;
             this->_size = other._size;
             this->_size = other._size;
@@ -93,7 +99,7 @@ namespace pkpy {
         const PyVar& operator[](int i) const { return _args[i]; }
         const PyVar& operator[](int i) const { return _args[i]; }
 
 
         Args& operator=(Args&& other) noexcept {
         Args& operator=(Args&& other) noexcept {
-            _release();
+            _free();
             this->_args = other._args;
             this->_args = other._args;
             this->_size = other._size;
             this->_size = other._size;
             other._args = nullptr;
             other._args = nullptr;
@@ -126,7 +132,7 @@ namespace pkpy {
             }
             }
         }
         }
 
 
-        ~Args(){ _release(); }
+        ~Args(){ _free(); }
     };
     };
 
 
     const Args& no_arg(){
     const Args& no_arg(){
@@ -148,4 +154,6 @@ namespace pkpy {
         ret[1] = std::forward<T2>(b);
         ret[1] = std::forward<T2>(b);
         return ret;
         return ret;
     }
     }
-}
+}
+
+typedef pkpy::Args _Tuple;

+ 5 - 2
src/str.h

@@ -117,8 +117,10 @@ public:
 
 
     _Str& operator=(const _Str& s){
     _Str& operator=(const _Str& s){
         this->std::string::operator=(s);
         this->std::string::operator=(s);
-        if(_u8_index != nullptr) delete _u8_index;
-        this->_u8_index = s._u8_index;
+        if(_u8_index != nullptr){
+            delete _u8_index;
+            _u8_index = new std::vector<uint16_t>(*s._u8_index);
+        }
         this->hash_initialized = s.hash_initialized;
         this->hash_initialized = s.hash_initialized;
         this->_hash = s._hash;
         this->_hash = s._hash;
         return *this;
         return *this;
@@ -128,6 +130,7 @@ public:
         this->std::string::operator=(std::move(s));
         this->std::string::operator=(std::move(s));
         if(_u8_index != nullptr) delete _u8_index;
         if(_u8_index != nullptr) delete _u8_index;
         this->_u8_index = s._u8_index;
         this->_u8_index = s._u8_index;
+        s._u8_index = nullptr;
         this->hash_initialized = s.hash_initialized;
         this->hash_initialized = s.hash_initialized;
         this->_hash = s._hash;
         this->_hash = s._hash;
         return *this;
         return *this;

+ 62 - 56
src/vm.h

@@ -20,14 +20,14 @@
 
 
 
 
 class VM {
 class VM {
-    std::vector<PyVar> _small_integers;             // [-5, 256]
+    // std::vector<PyVar> _small_integers;             // [-5, 256]
     std::stack< std::unique_ptr<Frame> > callstack;
     std::stack< std::unique_ptr<Frame> > callstack;
     PyVar _py_op_call;
     PyVar _py_op_call;
-    
+
     PyVar run_frame(Frame* frame){
     PyVar run_frame(Frame* frame){
         while(frame->has_next_bytecode()){
         while(frame->has_next_bytecode()){
             const Bytecode& byte = frame->next_bytecode();
             const Bytecode& byte = frame->next_bytecode();
-            // if(frame->_module != builtins){
+            // if(true || frame->_module != builtins){
             //     printf("%d: %s (%d) %s\n", frame->_ip, OP_NAMES[byte.op], byte.arg, frame->stack_info().c_str());
             //     printf("%d: %s (%d) %s\n", frame->_ip, OP_NAMES[byte.op], byte.arg, frame->stack_info().c_str());
             // }
             // }
             switch (byte.op)
             switch (byte.op)
@@ -46,11 +46,11 @@ class VM {
                 frame->push(NameRef(frame->co->names[byte.arg]).get(this, frame));
                 frame->push(NameRef(frame->co->names[byte.arg]).get(this, frame));
             } break;
             } break;
             case OP_STORE_NAME: {
             case OP_STORE_NAME: {
-                const auto& p = frame->co->names[byte.arg];
+                auto& p = frame->co->names[byte.arg];
                 NameRef(p).set(this, frame, frame->pop_value(this));
                 NameRef(p).set(this, frame, frame->pop_value(this));
             } break;
             } break;
             case OP_BUILD_ATTR_REF: {
             case OP_BUILD_ATTR_REF: {
-                const auto& attr = frame->co->names[byte.arg];
+                auto& attr = frame->co->names[byte.arg];
                 PyVar obj = frame->pop_value(this);
                 PyVar obj = frame->pop_value(this);
                 frame->push(PyRef(AttrRef(obj, NameRef(attr))));
                 frame->push(PyRef(AttrRef(obj, NameRef(attr))));
             } break;
             } break;
@@ -75,14 +75,13 @@ class VM {
                 for(int i=0; i<items.size(); i++){
                 for(int i=0; i<items.size(); i++){
                     if(!items[i]->is_type(_tp_ref)) {
                     if(!items[i]->is_type(_tp_ref)) {
                         done = true;
                         done = true;
-                        PyVarList values = items.to_list();
-                        for(int j=i; j<values.size(); j++) frame->try_deref(this, values[j]);
-                        frame->push(PyTuple(values));
+                        for(int j=i; j<items.size(); j++) frame->try_deref(this, items[j]);
+                        frame->push(PyTuple(std::move(items)));
                         break;
                         break;
                     }
                     }
                 }
                 }
                 if(done) break;
                 if(done) break;
-                frame->push(PyRef(TupleRef(items.to_list())));
+                frame->push(PyRef(TupleRef(std::move(items))));
             } break;
             } break;
             case OP_BUILD_STRING:
             case OP_BUILD_STRING:
             {
             {
@@ -364,10 +363,9 @@ public:
             this->_stdout = new _StrStream();
             this->_stdout = new _StrStream();
             this->_stderr = new _StrStream();
             this->_stderr = new _StrStream();
         }
         }
-        initializeBuiltinClasses();
 
 
-        _small_integers.reserve(270);
-        for(i64 i=-5; i<=256; i++) _small_integers.push_back(new_object(_tp_int, i));
+        init_builtin_types();
+        // for(i64 i=-5; i<=256; i++) _small_integers.push_back(new_object(_tp_int, i));
     }
     }
 
 
     PyVar asStr(const PyVar& obj){
     PyVar asStr(const PyVar& obj){
@@ -473,8 +471,7 @@ public:
 
 
             std::vector<_Str> positional_overrided_keys;
             std::vector<_Str> positional_overrided_keys;
             if(!fn->starredArg.empty()){
             if(!fn->starredArg.empty()){
-                // handle *args
-                PyVarList vargs;
+                PyVarList vargs;        // handle *args
                 while(i < args.size()) vargs.push_back(args[i++]);
                 while(i < args.size()) vargs.push_back(args[i++]);
                 locals.emplace(fn->starredArg, PyTuple(std::move(vargs)));
                 locals.emplace(fn->starredArg, PyTuple(std::move(vargs)));
             }else{
             }else{
@@ -608,7 +605,14 @@ public:
     template<typename T>
     template<typename T>
     inline PyVar new_object(PyVar type, T _value) {
     inline PyVar new_object(PyVar type, T _value) {
         if(!type->is_type(_tp_type)) UNREACHABLE();
         if(!type->is_type(_tp_type)) UNREACHABLE();
-        return pkpy::make_shared<PyObject, Py_<T>>(type, _value);
+        std::vector<int*>& pool = _obj_pool[obj_tid<T>((void*)type.get())];
+        if(pool.empty()) return pkpy::make_shared<PyObject, Py_<T>>(type, _value);
+        int* counter = pool.back(); pool.pop_back();
+        *counter = 1;
+        Py_<T>* obj = (Py_<T>*)(counter + 1);
+        obj->_value = std::move(_value);
+        obj->attribs.clear();
+        return PyVar(counter);
     }
     }
 
 
     template<typename T, typename... Args>
     template<typename T, typename... Args>
@@ -810,16 +814,11 @@ public:
         return (const BaseRef*)(obj->value());
         return (const BaseRef*)(obj->value());
     }
     }
 
 
-    __DEF_PY_AS_C(Int, i64, _tp_int)
-    inline PyVar PyInt(i64 value) { 
-        if(value >= -5 && value <= 256) return _small_integers[value + 5];
-        return new_object(_tp_int, value);
-    }
-
+    DEF_NATIVE(Int, i64, _tp_int)
     DEF_NATIVE(Float, f64, _tp_float)
     DEF_NATIVE(Float, f64, _tp_float)
     DEF_NATIVE(Str, _Str, _tp_str)
     DEF_NATIVE(Str, _Str, _tp_str)
     DEF_NATIVE(List, PyVarList, _tp_list)
     DEF_NATIVE(List, PyVarList, _tp_list)
-    DEF_NATIVE(Tuple, PyVarList, _tp_tuple)
+    DEF_NATIVE(Tuple, _Tuple, _tp_tuple)
     DEF_NATIVE(Function, _Func, _tp_function)
     DEF_NATIVE(Function, _Func, _tp_function)
     DEF_NATIVE(NativeFunction, _CppFunc, _tp_native_function)
     DEF_NATIVE(NativeFunction, _CppFunc, _tp_native_function)
     DEF_NATIVE(Iter, pkpy::shared_ptr<BaseIter>, _tp_native_iterator)
     DEF_NATIVE(Iter, pkpy::shared_ptr<BaseIter>, _tp_native_iterator)
@@ -832,7 +831,7 @@ public:
     inline bool PyBool_AS_C(const PyVar& obj){return obj == True;}
     inline bool PyBool_AS_C(const PyVar& obj){return obj == True;}
     inline const PyVar& PyBool(bool value){return value ? True : False;}
     inline const PyVar& PyBool(bool value){return value ? True : False;}
 
 
-    void initializeBuiltinClasses(){
+    void init_builtin_types(){
         _tp_object = pkpy::make_shared<PyObject, Py_<i64>>(nullptr, DUMMY_VAL);
         _tp_object = pkpy::make_shared<PyObject, Py_<i64>>(nullptr, DUMMY_VAL);
         _tp_type = pkpy::make_shared<PyObject, Py_<i64>>(nullptr, DUMMY_VAL);
         _tp_type = pkpy::make_shared<PyObject, Py_<i64>>(nullptr, DUMMY_VAL);
         _types["object"] = _tp_object;
         _types["object"] = _tp_object;
@@ -890,8 +889,9 @@ public:
         if (obj->is_type(_tp_type)) return (i64)obj.get();
         if (obj->is_type(_tp_type)) return (i64)obj.get();
         if (obj->is_type(_tp_tuple)) {
         if (obj->is_type(_tp_tuple)) {
             i64 x = 1000003;
             i64 x = 1000003;
-            for (const auto& item : PyTuple_AS_C(obj)) {
-                i64 y = hash(item);
+            const _Tuple& items = PyTuple_AS_C(obj);
+            for (int i=0; i<items.size(); i++) {
+                i64 y = hash(items[i]);
                 x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2)); // recommended by Github Copilot
                 x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2)); // recommended by Github Copilot
             }
             }
             return x;
             return x;
@@ -964,26 +964,26 @@ public:
 /***** Pointers' Impl *****/
 /***** Pointers' Impl *****/
 PyVar NameRef::get(VM* vm, Frame* frame) const{
 PyVar NameRef::get(VM* vm, Frame* frame) const{
     PyVar* val;
     PyVar* val;
-    val = frame->f_locals().try_get(pair->first);
+    val = frame->f_locals().try_get(name());
     if(val) return *val;
     if(val) return *val;
-    val = frame->f_globals().try_get(pair->first);
+    val = frame->f_globals().try_get(name());
     if(val) return *val;
     if(val) return *val;
-    val = vm->builtins->attribs.try_get(pair->first);
+    val = vm->builtins->attribs.try_get(name());
     if(val) return *val;
     if(val) return *val;
-    vm->NameError(pair->first);
+    vm->NameError(name());
     return nullptr;
     return nullptr;
 }
 }
 
 
 void NameRef::set(VM* vm, Frame* frame, PyVar val) const{
 void NameRef::set(VM* vm, Frame* frame, PyVar val) const{
-    switch(pair->second) {
-        case NAME_LOCAL: frame->f_locals()[pair->first] = std::move(val); break;
+    switch(scope()) {
+        case NAME_LOCAL: frame->f_locals()[name()] = std::move(val); break;
         case NAME_GLOBAL:
         case NAME_GLOBAL:
         {
         {
-            PyVar* existing = frame->f_locals().try_get(pair->first);
+            PyVar* existing = frame->f_locals().try_get(name());
             if(existing != nullptr){
             if(existing != nullptr){
                 *existing = std::move(val);
                 *existing = std::move(val);
             }else{
             }else{
-                frame->f_globals()[pair->first] = std::move(val);
+                frame->f_globals()[name()] = std::move(val);
             }
             }
         } break;
         } break;
         default: UNREACHABLE();
         default: UNREACHABLE();
@@ -991,23 +991,23 @@ void NameRef::set(VM* vm, Frame* frame, PyVar val) const{
 }
 }
 
 
 void NameRef::del(VM* vm, Frame* frame) const{
 void NameRef::del(VM* vm, Frame* frame) const{
-    switch(pair->second) {
+    switch(scope()) {
         case NAME_LOCAL: {
         case NAME_LOCAL: {
-            if(frame->f_locals().contains(pair->first)){
-                frame->f_locals().erase(pair->first);
+            if(frame->f_locals().contains(name())){
+                frame->f_locals().erase(name());
             }else{
             }else{
-                vm->NameError(pair->first);
+                vm->NameError(name());
             }
             }
         } break;
         } break;
         case NAME_GLOBAL:
         case NAME_GLOBAL:
         {
         {
-            if(frame->f_locals().contains(pair->first)){
-                frame->f_locals().erase(pair->first);
+            if(frame->f_locals().contains(name())){
+                frame->f_locals().erase(name());
             }else{
             }else{
-                if(frame->f_globals().contains(pair->first)){
-                    frame->f_globals().erase(pair->first);
+                if(frame->f_globals().contains(name())){
+                    frame->f_globals().erase(name());
                 }else{
                 }else{
-                    vm->NameError(pair->first);
+                    vm->NameError(name());
                 }
                 }
             }
             }
         } break;
         } break;
@@ -1016,11 +1016,11 @@ void NameRef::del(VM* vm, Frame* frame) const{
 }
 }
 
 
 PyVar AttrRef::get(VM* vm, Frame* frame) const{
 PyVar AttrRef::get(VM* vm, Frame* frame) const{
-    return vm->getattr(obj, attr.pair->first);
+    return vm->getattr(obj, attr.name());
 }
 }
 
 
 void AttrRef::set(VM* vm, Frame* frame, PyVar val) const{
 void AttrRef::set(VM* vm, Frame* frame, PyVar val) const{
-    vm->setattr(obj, attr.pair->first, val);
+    vm->setattr(obj, attr.name(), val);
 }
 }
 
 
 void AttrRef::del(VM* vm, Frame* frame) const{
 void AttrRef::del(VM* vm, Frame* frame) const{
@@ -1040,27 +1040,33 @@ void IndexRef::del(VM* vm, Frame* frame) const{
 }
 }
 
 
 PyVar TupleRef::get(VM* vm, Frame* frame) const{
 PyVar TupleRef::get(VM* vm, Frame* frame) const{
-    PyVarList args(varRefs.size());
-    for (int i = 0; i < varRefs.size(); i++) {
-        args[i] = vm->PyRef_AS_C(varRefs[i])->get(vm, frame);
+    _Tuple args(objs.size());
+    for (int i = 0; i < objs.size(); i++) {
+        args[i] = vm->PyRef_AS_C(objs[i])->get(vm, frame);
     }
     }
-    return vm->PyTuple(args);
+    return vm->PyTuple(std::move(args));
 }
 }
 
 
 void TupleRef::set(VM* vm, Frame* frame, PyVar val) const{
 void TupleRef::set(VM* vm, Frame* frame, PyVar val) const{
-    if(!val->is_type(vm->_tp_tuple) && !val->is_type(vm->_tp_list)){
+#define TUPLE_REF_SET() \
+    if(args.size() > objs.size()) vm->ValueError("too many values to unpack");       \
+    if(args.size() < objs.size()) vm->ValueError("not enough values to unpack");     \
+    for (int i = 0; i < objs.size(); i++) vm->PyRef_AS_C(objs[i])->set(vm, frame, args[i]);
+
+    if(val->is_type(vm->_tp_tuple)){
+        const _Tuple& args = OBJ_GET(_Tuple, val);
+        TUPLE_REF_SET()
+    }else if(val->is_type(vm->_tp_list)){
+        const PyVarList& args = OBJ_GET(PyVarList, val);
+        TUPLE_REF_SET()
+    }else{
         vm->TypeError("only tuple or list can be unpacked");
         vm->TypeError("only tuple or list can be unpacked");
     }
     }
-    const PyVarList& args = OBJ_GET(PyVarList, val);
-    if(args.size() > varRefs.size()) vm->ValueError("too many values to unpack");
-    if(args.size() < varRefs.size()) vm->ValueError("not enough values to unpack");
-    for (int i = 0; i < varRefs.size(); i++) {
-        vm->PyRef_AS_C(varRefs[i])->set(vm, frame, args[i]);
-    }
+#undef TUPLE_REF_SET
 }
 }
 
 
 void TupleRef::del(VM* vm, Frame* frame) const{
 void TupleRef::del(VM* vm, Frame* frame) const{
-    for (auto& r : varRefs) vm->PyRef_AS_C(r)->del(vm, frame);
+    for(int i=0; i<objs.size(); i++) vm->PyRef_AS_C(objs[i])->del(vm, frame);
 }
 }
 
 
 /***** Frame's Impl *****/
 /***** Frame's Impl *****/