This commit is contained in:
blueloveTH 2023-04-06 15:52:04 +08:00
parent 6b9b5945a3
commit c694e1e67d
8 changed files with 33 additions and 64 deletions

View File

@ -15,7 +15,7 @@ __NEXT_STEP:;
* For example, frame->popx() returns a strong reference which may be dangerous
* `Args` containing strong references is safe if it is passed to `call` or `fast_call`
*/
#if !DEBUG_NO_GC
#if !DEBUG_NO_AUTO_GC
heap._auto_collect(this);
#endif

View File

@ -33,11 +33,12 @@
// debug macros
#define DEBUG_NO_BUILTIN_MODULES 0
#define DEBUG_EXTRA_CHECK 0
#define DEBUG_DIS_EXEC 0
#define DEBUG_DIS_EXEC 1
#define DEBUG_DIS_EXEC_MIN 1
#define DEBUG_CEVAL_STEP 0
#define DEBUG_FULL_EXCEPTION 0
#define DEBUG_NO_GC 0
#define DEBUG_NO_AUTO_GC 1
#define DEBUG_GC_STATS 0
#if (defined(__ANDROID__) && __ANDROID_API__ <= 22) || defined(__EMSCRIPTEN__)
#define PK_ENABLE_FILEIO 0

View File

@ -726,7 +726,6 @@ __SUBSCR_END:
/*************************************************/
case TK("assert"):
EXPR_TUPLE(false);
// TODO: change OP_ASSERT impl in ceval.h
ctx()->emit(OP_ASSERT, BC_NOARG, kw_line);
consume_end_stmt();
break;
@ -860,7 +859,6 @@ __SUBSCR_END:
}
void compile_function(const std::vector<Expr_>& decorators={}){
// TODO: bug, if there are multiple decorators, will cause error
FuncDecl_ decl = make_sp<FuncDecl>();
StrName obj_name;
consume(TK("@id"));

View File

@ -632,6 +632,8 @@ struct CallExpr: Expr{
void emit(CodeEmitContext* ctx) override {
VM* vm = ctx->vm;
// TODO: if callable is a AttrExpr, we should try to use `fast_call`
// instead of use `boundmethod` proxy
callable->emit(ctx);
// emit args
for(auto& item: args) item->emit(ctx);

View File

@ -5,45 +5,15 @@
#include "codeobject.h"
#include "namedict.h"
/*
0: object
1: type
2: int
3: float
4: bool
5: str
6: list
7: tuple
8: slice
9: range
10: module
11: _ref
12: _star_wrapper
13: function
14: native_function
15: iterator
16: bound_method
17: super
18: Exception
19: NoneType
20: ellipsis
21: _py_op_call
22: _py_op_yield
23: re.Match
24: random.Random
25: io.FileIO
26: property
27: staticmethod
28: dict
29: set
*/
namespace pkpy {
struct ManagedHeap{
std::vector<PyObject*> _no_gc;
std::vector<PyObject*> gen;
VM* vm;
ManagedHeap(VM* vm): vm(vm) {}
static const int kMinGCThreshold = 700;
static const int kMinGCThreshold = 4096;
int gc_threshold = kMinGCThreshold;
int gc_counter = 0;
@ -84,19 +54,20 @@ struct ManagedHeap{
~ManagedHeap(){
for(PyObject* obj: _no_gc) delete obj;
// for(auto& [type, count]: deleted){
// std::cout << "GC: " << type << "=" << count << std::endl;
// }
#if DEBUG_GC_STATS
for(auto& [type, count]: deleted){
std::cout << "GC: " << obj_type_name(vm, type) << "=" << count << std::endl;
}
#endif
}
int sweep(VM* vm){
int sweep(){
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);
deleted[obj->type] += 1;
delete obj;
}
@ -112,25 +83,23 @@ struct ManagedHeap{
return freed;
}
void _delete_hook(VM* vm, PyObject* obj);
void _auto_collect(VM* vm){
void _auto_collect(){
if(_gc_lock_counter > 0) return;
if(gc_counter < gc_threshold) return;
gc_counter = 0;
collect(vm);
collect();
gc_threshold = gen.size() * 2;
if(gc_threshold < kMinGCThreshold) gc_threshold = kMinGCThreshold;
}
int collect(VM* vm){
int collect(){
if(_gc_lock_counter > 0) UNREACHABLE();
mark(vm);
int freed = sweep(vm);
mark();
int freed = sweep();
return freed;
}
void mark(VM* vm);
void mark();
};
inline void NameDict::_gc_mark() const{

View File

@ -149,6 +149,8 @@ struct Py_ : PyObject {
#define OBJ_GET(T, obj) (((Py_<T>*)(obj))->_value)
#define OBJ_MARK(obj) if(!is_tagged(obj)) obj->_obj_gc_mark()
Str obj_type_name(VM* vm, Type type);
#if DEBUG_NO_BUILTIN_MODULES
#define OBJ_NAME(obj) Str("<?>")
#else

View File

@ -756,7 +756,7 @@ inline void add_module_random(VM* vm){
inline void add_module_gc(VM* vm){
PyObject* mod = vm->new_module("gc");
vm->bind_func<0>(mod, "collect", CPP_LAMBDA(VAR(vm->heap.collect(vm))));
vm->bind_func<0>(mod, "collect", CPP_LAMBDA(VAR(vm->heap.collect())));
}
inline void VM::post_init(){

View File

@ -4,6 +4,7 @@
#include "frame.h"
#include "error.h"
#include "gc.h"
#include "obj.h"
namespace pkpy{
@ -75,10 +76,10 @@ public:
Type tp_object, tp_type, tp_int, tp_float, tp_bool, tp_str;
Type tp_list, tp_tuple;
Type tp_function, tp_native_function, tp_iterator, tp_bound_method;
Type tp_slice, tp_range, tp_module, tp_ref;
Type tp_slice, tp_range, tp_module;
Type tp_super, tp_exception, tp_star_wrapper;
VM(bool use_stdio){
VM(bool use_stdio) : heap(this){
this->vm = this;
this->use_stdio = use_stdio;
if(use_stdio){
@ -317,7 +318,7 @@ public:
}
~VM() {
heap.collect(this);
heap.collect();
if(!use_stdio){
delete _stdout;
delete _stderr;
@ -344,8 +345,6 @@ public:
void bind_func(PyObject*, Str, NativeFuncRaw);
void _error(Exception);
PyObject* _exec();
template<typename P> PyObject* PyRef(P&&);
const BaseRef* PyRef_AS_C(PyObject* obj);
void post_init();
};
@ -652,7 +651,6 @@ inline void VM::init_builtin_types(){
tp_slice = _new_type_object("slice");
tp_range = _new_type_object("range");
tp_module = _new_type_object("module");
tp_ref = _new_type_object("_ref");
tp_star_wrapper = _new_type_object("_star_wrapper");
tp_function = _new_type_object("function");
tp_native_function = _new_type_object("native_function");
@ -690,7 +688,7 @@ inline void VM::init_builtin_types(){
for(auto [k, v]: _modules.items()) v->attr()._try_perfect_rehash();
}
// TODO: args here may be garbage collected accidentally
// TODO: callable/args here may be garbage collected accidentally
inline PyObject* VM::call(PyObject* callable, Args args, const Args& kwargs, bool opCall){
if(is_type(callable, tp_type)){
PyObject* new_f = callable->attr().try_get(__new__);
@ -907,14 +905,13 @@ inline PyObject* VM::_exec(){
}
}
inline void ManagedHeap::mark(VM *vm) {
inline void ManagedHeap::mark() {
for(PyObject* obj: _no_gc) OBJ_MARK(obj);
for(auto& frame : vm->callstack.data()) frame->_gc_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;
inline Str obj_type_name(VM *vm, Type type){
return vm->_all_types[type].name;
}
} // namespace pkpy