update gc

This commit is contained in:
blueloveTH 2023-03-29 15:34:50 +08:00
parent 78b73998da
commit 6a9d220433
9 changed files with 66 additions and 36 deletions

View File

@ -1,8 +1,12 @@
class dict:
def __init__(self, capacity=13):
self._capacity = capacity
def __init__(self, mapping=None):
self._capacity = 16
self._a = [None] * self._capacity
self._len = 0
if mapping is not None:
for k,v in mapping:
self[k] = v
def __len__(self):
return self._len

View File

@ -186,11 +186,14 @@ inline PyObject* VM::run_frame(Frame* frame){
frame->push(VAR(frame->pop_n_values_reversed(this, byte.arg).to_list()));
continue;
case OP_BUILD_MAP: {
Args items = frame->pop_n_values_reversed(this, byte.arg*2);
PyObject* obj = call(builtins->attr("dict"), no_arg());
for(int i=0; i<items.size(); i+=2){
call(obj, __setitem__, Args{items[i], items[i+1]});
List list(byte.arg);
for(int i=0; i<byte.arg; i++){
PyObject* value = frame->pop_value(this);
PyObject* key = frame->pop_value(this);
list[i] = VAR(Tuple({key, value}));
}
PyObject* d_arg = VAR(std::move(list));
PyObject* obj = call(builtins->attr("dict"), Args{d_arg});
frame->push(obj);
} continue;
case OP_BUILD_SET: {

View File

@ -1,59 +1,78 @@
#pragma once
#include "common.h"
#include "obj.h"
#include "codeobject.h"
#include "namedict.h"
namespace pkpy {
struct ManagedHeap{
std::vector<PyObject*> _no_gc;
std::vector<PyObject*> gen;
int counter = 0;
int gc_threshold = 700;
int gc_counter = 0;
template<typename T>
PyObject* gcnew(Type type, T&& val){
PyObject* obj = new Py_<std::decay_t<T>>(type, std::forward<T>(val));
gen.push_back(obj);
counter++;
gc_counter++;
return obj;
}
template<typename T>
PyObject* _new(Type type, T&& val){
return gcnew<T>(type, std::forward<T>(val));
PyObject* obj = new Py_<std::decay_t<T>>(type, std::forward<T>(val));
obj->gc.enabled = false;
_no_gc.push_back(obj);
return obj;
}
int sweep(){
~ManagedHeap(){
for(PyObject* obj: _no_gc) delete obj;
}
int sweep(VM* vm){
std::vector<PyObject*> alive;
for(PyObject* obj: gen){
if(obj->gc.marked){
obj->gc.marked = false;
alive.push_back(obj);
}else{
// _delete_hook(vm, obj);
delete obj;
}
}
// clear _no_gc marked flag
for(PyObject* obj: _no_gc) obj->gc.marked = false;
int freed = gen.size() - alive.size();
gen.clear();
gen.swap(alive);
return freed;
}
void _delete_hook(VM* vm, PyObject* obj);
void _auto_collect(VM* vm){
if(counter > 1000){
counter = 0;
collect(vm);
}
if(gc_counter < gc_threshold) return;
gc_counter = 0;
collect(vm);
gc_threshold = gen.size() * 2;
}
int collect(VM* vm){
mark(vm);
return sweep();
int freed = sweep(vm);
// std::cout << "GC: " << freed << " objects freed" << std::endl;
return freed;
}
void mark(VM* vm);
};
inline void NameDict::_mark(){
for(uint16_t i=0; i<_capacity; i++){
if(_items[i].first.empty()) continue;

View File

@ -72,7 +72,7 @@ inline void BaseIter::_mark() {
inline void Generator::_mark(){
BaseIter::_mark();
frame->_mark();
if(frame!=nullptr) frame->_mark();
}
template<typename T>

View File

@ -91,8 +91,9 @@ public:
};
struct GCHeader {
bool enabled; // whether this object is managed by GC
bool marked; // whether this object is marked
GCHeader() : marked(false) {}
GCHeader() : enabled(true), marked(false) {}
};
struct PyObject {
@ -135,7 +136,6 @@ struct Py_ : PyObject {
void _mark() override {
if(gc.marked) return;
// std::cout << "marking " << type << std::endl;
gc.marked = true;
if(_attr != nullptr) _attr->_mark();
pkpy::_mark<T>(_value); // handle PyObject* inside _value `T`

View File

@ -88,8 +88,7 @@ inline void init_builtins(VM* _vm) {
i64 lhs = CAST(i64, args[0]);
i64 rhs = CAST(i64, args[1]);
if(rhs == 0) vm->ZeroDivisionError();
Tuple t = Tuple{VAR(lhs/rhs), VAR(lhs%rhs)};
return VAR(std::move(t));
return VAR(Tuple({VAR(lhs/rhs), VAR(lhs%rhs)}));
});
_vm->bind_builtin_func<1>("eval", [](VM* vm, Args& args) {
@ -146,7 +145,7 @@ inline void init_builtins(VM* _vm) {
});
_vm->bind_builtin_func<1>("hex", [](VM* vm, Args& args) {
std::stringstream ss;
StrStream ss;
ss << std::hex << CAST(i64, args[0]);
return VAR("0x" + ss.str());
});
@ -649,8 +648,7 @@ struct ReMatch {
vm->bind_method<0>(type, "span", [](VM* vm, Args& args) {
auto& self = CAST(ReMatch&, args[0]);
Tuple t = Tuple{VAR(self.start), VAR(self.end)};
return VAR(std::move(t));
return VAR(Tuple({VAR(self.start), VAR(self.end)}));
});
vm->bind_method<1>(type, "group", [](VM* vm, Args& args) {

View File

@ -881,15 +881,14 @@ inline void VM::_error(Exception e){
inline PyObject* VM::_exec(){
Frame* frame = top_frame();
i64 base_id = frame->id;
PyObject* ret = nullptr;
const i64 base_id = frame->id;
bool need_raise = false;
while(true){
if(frame->id < base_id) UNREACHABLE();
try{
if(need_raise){ need_raise = false; _raise(); }
ret = run_frame(frame);
PyObject* ret = run_frame(frame);
if(ret == _py_op_yield) return _py_op_yield;
if(ret != _py_op_call){
if(frame->id == base_id){ // [ frameBase<- ]
@ -922,11 +921,15 @@ inline PyObject* VM::_exec(){
}
inline void ManagedHeap::mark(VM *vm) {
vm->_modules._mark();
for(auto& t: vm->_all_types) t.obj->_mark();
for(PyObject* obj: _no_gc) OBJ_MARK(obj);
for(auto& frame : vm->callstack.data()){
frame->_mark();
}
}
inline void ManagedHeap::_delete_hook(VM *vm, PyObject *obj){
Type t = OBJ_GET(Type, vm->_t(obj));
std::cout << "delete " << vm->_all_types[t].name << " at " << obj << std::endl;
}
} // namespace pkpy

View File

@ -42,4 +42,7 @@ d1 = {1:2, 3:4}
d2 = {3:4, 1:2}
d3 = {1:2, 3:4, 5:6}
assert d1 == d2
assert d1 != d3
assert d1 != d3
a = dict([(1, 2), (3, 4)])
assert a == {1: 2, 3: 4}

View File

@ -3,12 +3,12 @@ a = {
'b': 2,
'c': None,
'd': [1, 2, 3],
# 'e': {
# 'a': 1,
# 'b': 2,
# 'c': None,
# 'd': [1, 2, 3],
# },
'e': {
'a': 1,
'b': 2,
'c': None,
'd': [1, 2, 3],
},
"f": 'This is a string',
'g': [True, False, None],
'h': False