mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 20:10:17 +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
|
* 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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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"));
|
||||||
|
@ -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);
|
||||||
|
63
src/gc.h
63
src/gc.h
@ -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{
|
||||||
|
@ -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
|
||||||
|
@ -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(){
|
||||||
|
19
src/vm.h
19
src/vm.h
@ -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
|
Loading…
x
Reference in New Issue
Block a user