blueloveTH 2 лет назад
Родитель
Сommit
8764a23302
5 измененных файлов с 28 добавлено и 26 удалено
  1. 15 9
      src/memory.h
  2. 3 4
      src/namedict.h
  3. 4 7
      src/obj.h
  4. 4 4
      src/pocketpy.h
  5. 2 2
      src/tuplelist.h

+ 15 - 9
src/memory.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include "common.h"
+#include <type_traits>
 
 namespace pkpy{
 
@@ -68,25 +69,30 @@ shared_ptr<T> make_sp(Args&&... args) {
     return shared_ptr<T>(p);
 }
 
-template<typename T, int __Bucket, int __BucketSize=32, bool __ZeroCheck=true>
+template<typename T, int __Bucket, bool __ZeroInit>
 struct FreeListA {
     std::vector<T*> buckets[__Bucket+1];
 
     T* alloc(int n){
-        if constexpr(__ZeroCheck) if(n == 0) return nullptr;
+        static_assert(std::is_standard_layout_v<T>);
+        T* p;
         if(n > __Bucket || buckets[n].empty()){
-            return new T[n];
+            p = (T*)malloc(sizeof(T) * n);
         }else{
-            T* p = buckets[n].back();
+            p = buckets[n].back();
             buckets[n].pop_back();
-            return p;
         }
+        if constexpr(__ZeroInit){
+            // the constructor of T should be equivalent to zero initialization
+            memset((void*)p, 0, sizeof(T) * n);
+        }
+        return p;
     }
 
     void dealloc(T* p, int n){
-        if constexpr(__ZeroCheck) if(n == 0) return;
-        if(n > __Bucket || buckets[n].size() >= __BucketSize){
-            delete[] p;
+        if(p == nullptr) return;
+        if(n > __Bucket || buckets[n].size() >= 80){
+            free(p);
         }else{
             buckets[n].push_back(p);
         }
@@ -94,7 +100,7 @@ struct FreeListA {
 
     ~FreeListA(){
         for(int i=0; i<=__Bucket; i++){
-            for(T* p : buckets[i]) delete[] p;
+            for(T* p : buckets[i]) free(p);
         }
     }
 };

+ 3 - 4
src/namedict.h

@@ -34,7 +34,7 @@ inline static uint16_t find_perfect_hash_seed(uint16_t capacity, const std::vect
 
 struct NameDict {
     using Item = std::pair<StrName, PyObject*>;
-    inline static FreeListA<Item, 32, 32, false> _pool;
+    inline static THREAD_LOCAL FreeListA<Item, 32, true> _pool;
 
     uint16_t _capacity;
     uint16_t _size;
@@ -88,8 +88,7 @@ while(!_items[i].first.empty()) {       \
         return _items[i].second;
     }
 
-    template<typename T>
-    void set(StrName key, T&& val){
+    void set(StrName key, PyObject* val){
         bool ok; uint16_t i;
         HASH_PROBE(key, ok, i);
         if(!ok) {
@@ -100,7 +99,7 @@ while(!_items[i].first.empty()) {       \
             }
             _items[i].first = key;
         }
-        _items[i].second = std::forward<T>(val);
+        _items[i].second = val;
     }
 
     void _rehash(bool resize){

+ 4 - 7
src/obj.h

@@ -105,12 +105,7 @@ struct PyObject {
     NameDict& attr() noexcept { return *_attr; }
     PyObject* attr(StrName name) const noexcept { return (*_attr)[name]; }
     virtual void* value() = 0;
-
-    virtual void mark() {
-        if(!gc.enabled || gc.marked) return;
-        gc.marked = true;
-        if(is_attr_valid()) attr().apply_v([](PyObject* v){ v->mark(); });
-    }
+    virtual void mark() = 0;
 
     PyObject(Type type) : type(type) {}
     virtual ~PyObject() { delete _attr; }
@@ -137,7 +132,9 @@ struct Py_ : PyObject {
     void* value() override { return &_value; }
 
     void mark() override {
-        PyObject::mark();
+        if(!gc.enabled || gc.marked) return;
+        gc.marked = true;
+        if(is_attr_valid()) attr().apply_v([](PyObject* v){ v->mark(); });
         if constexpr (is_container_gc<T>::value) _value._mark();
     }
 };

+ 4 - 4
src/pocketpy.h

@@ -68,7 +68,7 @@ inline void init_builtins(VM* _vm) {
         if(!vm->isinstance(args[1], type)){
             vm->TypeError("super(type, obj): obj must be an instance or subtype of type");
         }
-        Type base = vm->_all_types[type.index].base;
+        Type base = vm->_all_types[type].base;
         return vm->gcnew(vm->tp_super, Super(args[1], base));
     });
 
@@ -788,11 +788,11 @@ inline void VM::post_init(){
     // property is defined in builtins.py so we need to add it after builtins is loaded
     _t(tp_object)->attr().set(__class__, property(CPP_LAMBDA(vm->_t(args[0]))));
     _t(tp_type)->attr().set(__base__, property([](VM* vm, Args& args){
-        const PyTypeInfo& info = vm->_all_types[OBJ_GET(Type, args[0]).index];
-        return info.base.index == -1 ? vm->None : vm->_all_types[info.base.index].obj;
+        const PyTypeInfo& info = vm->_all_types[OBJ_GET(Type, args[0])];
+        return info.base.index == -1 ? vm->None : vm->_all_types[info.base].obj;
     }));
     _t(tp_type)->attr().set(__name__, property([](VM* vm, Args& args){
-        const PyTypeInfo& info = vm->_all_types[OBJ_GET(Type, args[0]).index];
+        const PyTypeInfo& info = vm->_all_types[OBJ_GET(Type, args[0])];
         return VAR(info.name);
     }));
 }

+ 2 - 2
src/tuplelist.h

@@ -9,13 +9,13 @@ namespace pkpy {
 using List = std::vector<PyObject*>;
 
 class Args {
-    inline static THREAD_LOCAL FreeListA<PyObject*, 10> _pool;
+    inline static THREAD_LOCAL FreeListA<PyObject*, 10, false> _pool;
 
     PyObject** _args;
     int _size;
 
     void _alloc(int n){
-        this->_args = _pool.alloc(n);
+        this->_args = (n==0) ? nullptr : _pool.alloc(n);
         this->_size = n;
     }