add some gc guard

This commit is contained in:
blueloveTH 2023-05-10 14:24:54 +08:00
parent 345215e17a
commit c8b2387002
5 changed files with 28 additions and 27 deletions

View File

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

View File

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

View File

@ -38,12 +38,9 @@ public:
for(PyObject* p : list) _args[i++] = p; 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()){ Tuple(List&& other) noexcept : Tuple(other.size()){
for(int i=0; i<_size; i++) _args[i] = other[i]; _args = other._data;
other.clear(); other._data = nullptr;
} }
PyObject*& operator[](int i){ return _args[i]; } PyObject*& operator[](int i){ return _args[i]; }

View File

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

View File

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