Browse Source

add some gc guard

blueloveTH 2 năm trước cách đây
mục cha
commit
c8b2387002
5 tập tin đã thay đổi với 28 bổ sung27 xóa
  1. 1 2
      src/frame.h
  2. 4 2
      src/pocketpy.h
  3. 2 5
      src/tuplelist.h
  4. 12 12
      src/vector.h
  5. 9 6
      src/vm.h

+ 1 - 2
src/frame.h

@@ -110,7 +110,7 @@ struct Frame {
 
     const CodeObject* co;
     PyObject* _module;
-    PyObject* _callable;
+    PyObject* _callable;    // weak ref
     FastLocals _locals;
 
     NameDict& f_globals() noexcept { return _module->attr(); }
@@ -189,7 +189,6 @@ struct Frame {
 
     void _gc_mark() const {
         OBJ_MARK(_module);
-        if(_callable != nullptr) OBJ_MARK(_callable);
         co->_gc_mark();
     }
 };

+ 4 - 2
src/pocketpy.h

@@ -453,9 +453,10 @@ inline void init_builtins(VM* _vm) {
     });
 
     _vm->bind_method<1>("str", "join", [](VM* vm, ArgsView args) {
+        auto _lock = vm->heap.gc_scope_lock();
         const Str& self = _CAST(Str&, args[0]);
         FastStrStream ss;
-        PyObject* it = vm->asIter(args[1]);
+        PyObject* it = vm->asIter(args[1]);     // strong ref
         PyObject* obj = vm->PyIterNext(it);
         while(obj != vm->StopIteration){
             if(!ss.empty()) ss << self;
@@ -477,8 +478,9 @@ inline void init_builtins(VM* _vm) {
     });
 
     _vm->bind_method<1>("list", "extend", [](VM* vm, ArgsView args) {
+        auto _lock = vm->heap.gc_scope_lock();
         List& self = _CAST(List&, args[0]);
-        PyObject* it = vm->asIter(args[1]);
+        PyObject* it = vm->asIter(args[1]);     // strong ref
         PyObject* obj = vm->PyIterNext(it);
         while(obj != vm->StopIteration){
             self.push_back(obj);

+ 2 - 5
src/tuplelist.h

@@ -38,12 +38,9 @@ public:
         for(PyObject* p : list) _args[i++] = p;
     }
 
-    // TODO: poor performance
-    // List is allocated by pool128 while tuple is by pool64
-    // ...
     Tuple(List&& other) noexcept : Tuple(other.size()){
-        for(int i=0; i<_size; i++) _args[i] = other[i];
-        other.clear();
+        _args = other._data;
+        other._data = nullptr;
     }
 
     PyObject*& operator[](int i){ return _args[i]; }

+ 12 - 12
src/vector.h

@@ -7,24 +7,24 @@ namespace pkpy{
 
 template<typename T>
 struct pod_vector{
-    static_assert(128 % sizeof(T) == 0);
+    static_assert(64 % sizeof(T) == 0);
     static_assert(std::is_pod_v<T>);
-    static constexpr int N = 128 / sizeof(T);
-    static_assert(N > 4);
+    static constexpr int N = 64 / sizeof(T);
+    static_assert(N >= 4);
     int _size;
     int _capacity;
     T* _data;
 
     pod_vector(): _size(0), _capacity(N) {
-        _data = (T*)pool128.alloc(_capacity * sizeof(T));
+        _data = (T*)pool64.alloc(_capacity * sizeof(T));
     }
 
     pod_vector(int size): _size(size), _capacity(std::max(N, size)) {
-        _data = (T*)pool128.alloc(_capacity * sizeof(T));
+        _data = (T*)pool64.alloc(_capacity * sizeof(T));
     }
 
     pod_vector(const pod_vector& other): _size(other._size), _capacity(other._capacity) {
-        _data = (T*)pool128.alloc(_capacity * sizeof(T));
+        _data = (T*)pool64.alloc(_capacity * sizeof(T));
         memcpy(_data, other._data, sizeof(T) * _size);
     }
 
@@ -36,7 +36,7 @@ struct pod_vector{
     }
 
     pod_vector& operator=(pod_vector&& other) noexcept {
-        if(_data!=nullptr) pool128.dealloc(_data);
+        if(_data!=nullptr) pool64.dealloc(_data);
         _size = other._size;
         _capacity = other._capacity;
         _data = other._data;
@@ -63,10 +63,10 @@ struct pod_vector{
         if(cap <= _capacity) return;
         _capacity = cap;
         T* old_data = _data;
-        _data = (T*)pool128.alloc(_capacity * sizeof(T));
+        _data = (T*)pool64.alloc(_capacity * sizeof(T));
         if(old_data!=nullptr){
             memcpy(_data, old_data, sizeof(T) * _size);
-            pool128.dealloc(old_data);
+            pool64.dealloc(old_data);
         }
     }
 
@@ -111,7 +111,7 @@ struct pod_vector{
     }
 
     ~pod_vector() {
-        if(_data!=nullptr) pool128.dealloc(_data);
+        if(_data!=nullptr) pool64.dealloc(_data);
     }
 };
 
@@ -137,6 +137,6 @@ public:
 	Container& data() { return vec; }
 };
 
-template <typename T>
-using pod_stack = stack<T, pod_vector<T>>;
+// template <typename T>
+// using pod_stack = stack<T, pod_vector<T>>;
 } // namespace pkpy

+ 9 - 6
src/vm.h

@@ -576,6 +576,7 @@ inline bool VM::asBool(PyObject* obj){
 }
 
 inline PyObject* VM::asList(PyObject* it){
+    auto _lock = heap.gc_scope_lock();
     it = asIter(it);
     List list;
     PyObject* obj = PyIterNext(it);
@@ -1051,9 +1052,9 @@ inline PyObject* VM::_py_call(PyObject** p0, PyObject* callable, ArgsView args,
     
     // handle *args
     if(fn.decl->starred_arg != -1){
-        List vargs;        // handle *args
-        while(i < args.size()) vargs.push_back(args[i++]);
-        buffer[fn.decl->starred_arg] = VAR(Tuple(std::move(vargs)));
+        ArgsView vargs(args.begin() + i, args.end());
+        buffer[fn.decl->starred_arg] = VAR(vargs.to_tuple());
+        i += vargs.size();
     }else{
         // kwdefaults override
         for(auto& kv: fn.decl->kwargs){
@@ -1070,8 +1071,9 @@ inline PyObject* VM::_py_call(PyObject** p0, PyObject* callable, ArgsView args,
         buffer[index] = kwargs[i+1];
     }
     
-    s_data.reset(p0);
+    
     if(co->is_generator){
+        s_data.reset(p0);
         PyObject* ret = PyIter(Generator(
             this,
             Frame(&s_data, nullptr, co, fn._module, callable),
@@ -1080,9 +1082,10 @@ inline PyObject* VM::_py_call(PyObject** p0, PyObject* callable, ArgsView args,
         return ret;
     }
 
-    // copy buffer to stack
+    // copy buffer back to stack
+    s_data.reset(args.begin());
     for(int i=0; i<co_nlocals; i++) PUSH(buffer[i]);
-    callstack.emplace(&s_data, p0, co, fn._module, callable);
+    callstack.emplace(&s_data, p0, co, fn._module, callable, FastLocals(co, args.begin()));
     return nullptr;
 }