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 * 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` * `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); heap._auto_collect(this);
#endif #endif

View File

@ -33,11 +33,12 @@
// debug macros // debug macros
#define DEBUG_NO_BUILTIN_MODULES 0 #define DEBUG_NO_BUILTIN_MODULES 0
#define DEBUG_EXTRA_CHECK 0 #define DEBUG_EXTRA_CHECK 0
#define DEBUG_DIS_EXEC 0 #define DEBUG_DIS_EXEC 1
#define DEBUG_DIS_EXEC_MIN 1 #define DEBUG_DIS_EXEC_MIN 1
#define DEBUG_CEVAL_STEP 0 #define DEBUG_CEVAL_STEP 0
#define DEBUG_FULL_EXCEPTION 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__) #if (defined(__ANDROID__) && __ANDROID_API__ <= 22) || defined(__EMSCRIPTEN__)
#define PK_ENABLE_FILEIO 0 #define PK_ENABLE_FILEIO 0

View File

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

View File

@ -632,6 +632,8 @@ struct CallExpr: Expr{
void emit(CodeEmitContext* ctx) override { void emit(CodeEmitContext* ctx) override {
VM* vm = ctx->vm; 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); callable->emit(ctx);
// emit args // emit args
for(auto& item: args) item->emit(ctx); for(auto& item: args) item->emit(ctx);

View File

@ -5,45 +5,15 @@
#include "codeobject.h" #include "codeobject.h"
#include "namedict.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 { namespace pkpy {
struct ManagedHeap{ struct ManagedHeap{
std::vector<PyObject*> _no_gc; std::vector<PyObject*> _no_gc;
std::vector<PyObject*> gen; 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_threshold = kMinGCThreshold;
int gc_counter = 0; int gc_counter = 0;
@ -84,19 +54,20 @@ struct ManagedHeap{
~ManagedHeap(){ ~ManagedHeap(){
for(PyObject* obj: _no_gc) delete obj; for(PyObject* obj: _no_gc) delete obj;
// for(auto& [type, count]: deleted){ #if DEBUG_GC_STATS
// std::cout << "GC: " << type << "=" << count << std::endl; 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; std::vector<PyObject*> alive;
for(PyObject* obj: gen){ for(PyObject* obj: gen){
if(obj->gc.marked){ if(obj->gc.marked){
obj->gc.marked = false; obj->gc.marked = false;
alive.push_back(obj); alive.push_back(obj);
}else{ }else{
// _delete_hook(vm, obj);
deleted[obj->type] += 1; deleted[obj->type] += 1;
delete obj; delete obj;
} }
@ -112,25 +83,23 @@ struct ManagedHeap{
return freed; return freed;
} }
void _delete_hook(VM* vm, PyObject* obj); void _auto_collect(){
void _auto_collect(VM* vm){
if(_gc_lock_counter > 0) return; if(_gc_lock_counter > 0) return;
if(gc_counter < gc_threshold) return; if(gc_counter < gc_threshold) return;
gc_counter = 0; gc_counter = 0;
collect(vm); collect();
gc_threshold = gen.size() * 2; gc_threshold = gen.size() * 2;
if(gc_threshold < kMinGCThreshold) gc_threshold = kMinGCThreshold; if(gc_threshold < kMinGCThreshold) gc_threshold = kMinGCThreshold;
} }
int collect(VM* vm){ int collect(){
if(_gc_lock_counter > 0) UNREACHABLE(); if(_gc_lock_counter > 0) UNREACHABLE();
mark(vm); mark();
int freed = sweep(vm); int freed = sweep();
return freed; return freed;
} }
void mark(VM* vm); void mark();
}; };
inline void NameDict::_gc_mark() const{ 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_GET(T, obj) (((Py_<T>*)(obj))->_value)
#define OBJ_MARK(obj) if(!is_tagged(obj)) obj->_obj_gc_mark() #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 #if DEBUG_NO_BUILTIN_MODULES
#define OBJ_NAME(obj) Str("<?>") #define OBJ_NAME(obj) Str("<?>")
#else #else

View File

@ -756,7 +756,7 @@ inline void add_module_random(VM* vm){
inline void add_module_gc(VM* vm){ inline void add_module_gc(VM* vm){
PyObject* mod = vm->new_module("gc"); 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(){ inline void VM::post_init(){

View File

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