mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 12:00:18 +00:00
up
This commit is contained in:
parent
6b9b5945a3
commit
c694e1e67d
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"));
|
||||
|
@ -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);
|
||||
|
63
src/gc.h
63
src/gc.h
@ -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;
|
||||
|
||||
static const int kMinGCThreshold = 700;
|
||||
ManagedHeap(VM* vm): vm(vm) {}
|
||||
|
||||
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{
|
||||
|
@ -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
|
||||
|
@ -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(){
|
||||
|
19
src/vm.h
19
src/vm.h
@ -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
|
Loading…
x
Reference in New Issue
Block a user