blueloveTH 2 lat temu
rodzic
commit
c694e1e67d
8 zmienionych plików z 33 dodań i 64 usunięć
  1. 1 1
      src/ceval.h
  2. 3 2
      src/common.h
  3. 0 2
      src/compiler.h
  4. 2 0
      src/expr.h
  5. 16 47
      src/gc.h
  6. 2 0
      src/obj.h
  7. 1 1
      src/pocketpy.h
  8. 8 11
      src/vm.h

+ 1 - 1
src/ceval.h

@@ -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
 

+ 3 - 2
src/common.h

@@ -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

+ 0 - 2
src/compiler.h

@@ -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"));

+ 2 - 0
src/expr.h

@@ -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);

+ 16 - 47
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;
+
+    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{

+ 2 - 0
src/obj.h

@@ -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

+ 1 - 1
src/pocketpy.h

@@ -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(){

+ 8 - 11
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