From 120773891aebcb9d82fc371c354d16ab48f9b75f Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Wed, 29 Mar 2023 19:32:46 +0800 Subject: [PATCH] update gc --- src/ceval.h | 18 +--------------- src/compiler.h | 56 +++++++++++++++++++++++++++++++------------------- src/gc.h | 45 ++++++++++++++++++++++++++++++++++++++-- src/opcodes.h | 3 --- src/vm.h | 1 + 5 files changed, 80 insertions(+), 43 deletions(-) diff --git a/src/ceval.h b/src/ceval.h index b4893812..531c3ea6 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -7,7 +7,7 @@ namespace pkpy{ inline PyObject* VM::run_frame(Frame* frame){ while(frame->has_next_bytecode()){ - heap._auto_collect(this); + // heap._auto_collect(this); const Bytecode& byte = frame->next_bytecode(); switch (byte.op) @@ -115,22 +115,6 @@ inline PyObject* VM::run_frame(Frame* frame){ args[0] = frame->top_value(this); frame->top() = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args)); } continue; - case OP_INPLACE_BINARY_OP: { - Args args(2); - args[1] = frame->pop(); - args[0] = frame->top_value(this); - PyObject* ret = fast_call(BINARY_SPECIAL_METHODS[byte.arg], std::move(args)); - PyRef_AS_C(frame->top())->set(this, frame, std::move(ret)); - frame->_pop(); - } continue; - case OP_INPLACE_BITWISE_OP: { - Args args(2); - args[1] = frame->pop_value(this); - args[0] = frame->top_value(this); - PyObject* ret = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args)); - PyRef_AS_C(frame->top())->set(this, frame, std::move(ret)); - frame->_pop(); - } continue; case OP_COMPARE_OP: { Args args(2); args[1] = frame->pop_value(this); diff --git a/src/compiler.h b/src/compiler.h index 942828d2..613fd970 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -1,6 +1,7 @@ #pragma once #include "codeobject.h" +#include "common.h" #include "parser.h" #include "error.h" #include "ceval.h" @@ -405,40 +406,51 @@ private: } void exprAssign() { - int lhs = co()->codes.empty() ? -1 : co()->codes.size() - 1; + if(co()->codes.empty()) UNREACHABLE(); + bool is_load_name_ref = co()->codes.back().op == OP_LOAD_NAME_REF; + int _name_arg = co()->codes.back().arg; + // if the last op is OP_LOAD_NAME_REF, remove it + // because we will emit OP_STORE_NAME or OP_STORE_CLASS_ATTR + if(is_load_name_ref) co()->codes.pop_back(); + co()->_rvalue += 1; TokenIndex op = parser->prev.type; if(op == TK("=")) { // a = (expr) EXPR_TUPLE(); - if(lhs!=-1 && co()->codes[lhs].op == OP_LOAD_NAME_REF){ - if(co()->_is_compiling_class){ - emit(OP_STORE_CLASS_ATTR, co()->codes[lhs].arg); - }else{ - emit(OP_STORE_NAME, co()->codes[lhs].arg); - } - co()->codes[lhs].op = OP_NO_OP; - co()->codes[lhs].arg = -1; + if(is_load_name_ref){ + auto op = co()->_is_compiling_class ? OP_STORE_CLASS_ATTR : OP_STORE_NAME; + emit(op, _name_arg); }else{ if(co()->_is_compiling_class) SyntaxError(); emit(OP_STORE_REF); } }else{ // a += (expr) -> a = a + (expr) if(co()->_is_compiling_class) SyntaxError(); + if(is_load_name_ref){ + emit(OP_LOAD_NAME, _name_arg); + }else{ + emit(OP_DUP_TOP_VALUE); + } EXPR(); switch (op) { - case TK("+="): emit(OP_INPLACE_BINARY_OP, 0); break; - case TK("-="): emit(OP_INPLACE_BINARY_OP, 1); break; - case TK("*="): emit(OP_INPLACE_BINARY_OP, 2); break; - case TK("/="): emit(OP_INPLACE_BINARY_OP, 3); break; - case TK("//="): emit(OP_INPLACE_BINARY_OP, 4); break; - case TK("%="): emit(OP_INPLACE_BINARY_OP, 5); break; - case TK("<<="): emit(OP_INPLACE_BITWISE_OP, 0); break; - case TK(">>="): emit(OP_INPLACE_BITWISE_OP, 1); break; - case TK("&="): emit(OP_INPLACE_BITWISE_OP, 2); break; - case TK("|="): emit(OP_INPLACE_BITWISE_OP, 3); break; - case TK("^="): emit(OP_INPLACE_BITWISE_OP, 4); break; + case TK("+="): emit(OP_BINARY_OP, 0); break; + case TK("-="): emit(OP_BINARY_OP, 1); break; + case TK("*="): emit(OP_BINARY_OP, 2); break; + case TK("/="): emit(OP_BINARY_OP, 3); break; + case TK("//="): emit(OP_BINARY_OP, 4); break; + case TK("%="): emit(OP_BINARY_OP, 5); break; + case TK("<<="): emit(OP_BITWISE_OP, 0); break; + case TK(">>="): emit(OP_BITWISE_OP, 1); break; + case TK("&="): emit(OP_BITWISE_OP, 2); break; + case TK("|="): emit(OP_BITWISE_OP, 3); break; + case TK("^="): emit(OP_BITWISE_OP, 4); break; default: UNREACHABLE(); } + if(is_load_name_ref){ + emit(OP_STORE_NAME, _name_arg); + }else{ + emit(OP_STORE_REF); + } } co()->_rvalue -= 1; } @@ -791,6 +803,9 @@ private: consume_end_stmt(); } + // a = 1 + 2 + // ['a', '1', '2', '+', '='] + // void parse_expression(Precedence precedence) { lex_token(); GrammarFn prefix = rules[parser->prev.type].prefix; @@ -1003,7 +1018,6 @@ private: // If last op is not an assignment, pop the result. uint8_t last_op = co()->codes.back().op; if( last_op!=OP_STORE_NAME && last_op!=OP_STORE_REF && - last_op!=OP_INPLACE_BINARY_OP && last_op!=OP_INPLACE_BITWISE_OP && last_op!=OP_STORE_ALL_NAMES && last_op!=OP_STORE_CLASS_ATTR){ for(int i=begin; icodes[i].op==OP_BUILD_TUPLE_REF) co()->codes[i].op = OP_BUILD_TUPLE; diff --git a/src/gc.h b/src/gc.h index b4e0643f..1e4d3f16 100644 --- a/src/gc.h +++ b/src/gc.h @@ -5,12 +5,46 @@ #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 _no_gc; std::vector gen; - int gc_threshold = 700; + static const int kMinGCThreshold = 700; + int gc_threshold = kMinGCThreshold; int gc_counter = 0; template @@ -29,8 +63,13 @@ struct ManagedHeap{ return obj; } + inline static std::map deleted; + ~ManagedHeap(){ for(PyObject* obj: _no_gc) delete obj; + for(auto& [type, count]: deleted){ + std::cout << "GC: " << type << "=" << count << std::endl; + } } int sweep(VM* vm){ @@ -41,6 +80,7 @@ struct ManagedHeap{ alive.push_back(obj); }else{ // _delete_hook(vm, obj); + deleted[obj->type] += 1; delete obj; } } @@ -49,6 +89,7 @@ struct ManagedHeap{ for(PyObject* obj: _no_gc) obj->gc.marked = false; int freed = gen.size() - alive.size(); + // std::cout << "GC: " << alive.size() << "/" << gen.size() << " (" << freed << " freed)" << std::endl; gen.clear(); gen.swap(alive); return freed; @@ -61,12 +102,12 @@ struct ManagedHeap{ gc_counter = 0; collect(vm); gc_threshold = gen.size() * 2; + if(gc_threshold < kMinGCThreshold) gc_threshold = kMinGCThreshold; } int collect(VM* vm){ mark(vm); int freed = sweep(vm); - // std::cout << "GC: " << freed << " objects freed" << std::endl; return freed; } diff --git a/src/opcodes.h b/src/opcodes.h index 1ad9dcad..693a579d 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -81,9 +81,6 @@ OPCODE(YIELD_VALUE) OPCODE(FAST_INDEX) // a[x] OPCODE(FAST_INDEX_REF) // a[x] -OPCODE(INPLACE_BINARY_OP) -OPCODE(INPLACE_BITWISE_OP) - OPCODE(SETUP_CLOSURE) OPCODE(SETUP_DECORATOR) OPCODE(STORE_ALL_NAMES) diff --git a/src/vm.h b/src/vm.h index bfb73a8f..749f321b 100644 --- a/src/vm.h +++ b/src/vm.h @@ -166,6 +166,7 @@ public: if(_module == nullptr) _module = _main; try { CodeObject_ code = compile(source, filename, mode); + if(_module == _main) std::cout << disassemble(code) << '\n'; return _exec(code, _module); }catch (const Exception& e){ *_stderr << e.summary() << '\n';