update gc

This commit is contained in:
blueloveTH 2023-03-29 19:32:46 +08:00
parent 87e52df142
commit 120773891a
5 changed files with 80 additions and 43 deletions

View File

@ -7,7 +7,7 @@ namespace pkpy{
inline PyObject* VM::run_frame(Frame* frame){ inline PyObject* VM::run_frame(Frame* frame){
while(frame->has_next_bytecode()){ while(frame->has_next_bytecode()){
heap._auto_collect(this); // heap._auto_collect(this);
const Bytecode& byte = frame->next_bytecode(); const Bytecode& byte = frame->next_bytecode();
switch (byte.op) switch (byte.op)
@ -115,22 +115,6 @@ inline PyObject* VM::run_frame(Frame* frame){
args[0] = frame->top_value(this); args[0] = frame->top_value(this);
frame->top() = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args)); frame->top() = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args));
} continue; } 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: { case OP_COMPARE_OP: {
Args args(2); Args args(2);
args[1] = frame->pop_value(this); args[1] = frame->pop_value(this);

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "codeobject.h" #include "codeobject.h"
#include "common.h"
#include "parser.h" #include "parser.h"
#include "error.h" #include "error.h"
#include "ceval.h" #include "ceval.h"
@ -405,40 +406,51 @@ private:
} }
void exprAssign() { 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; co()->_rvalue += 1;
TokenIndex op = parser->prev.type; TokenIndex op = parser->prev.type;
if(op == TK("=")) { // a = (expr) if(op == TK("=")) { // a = (expr)
EXPR_TUPLE(); EXPR_TUPLE();
if(lhs!=-1 && co()->codes[lhs].op == OP_LOAD_NAME_REF){ if(is_load_name_ref){
if(co()->_is_compiling_class){ auto op = co()->_is_compiling_class ? OP_STORE_CLASS_ATTR : OP_STORE_NAME;
emit(OP_STORE_CLASS_ATTR, co()->codes[lhs].arg); emit(op, _name_arg);
}else{
emit(OP_STORE_NAME, co()->codes[lhs].arg);
}
co()->codes[lhs].op = OP_NO_OP;
co()->codes[lhs].arg = -1;
}else{ }else{
if(co()->_is_compiling_class) SyntaxError(); if(co()->_is_compiling_class) SyntaxError();
emit(OP_STORE_REF); emit(OP_STORE_REF);
} }
}else{ // a += (expr) -> a = a + (expr) }else{ // a += (expr) -> a = a + (expr)
if(co()->_is_compiling_class) SyntaxError(); if(co()->_is_compiling_class) SyntaxError();
if(is_load_name_ref){
emit(OP_LOAD_NAME, _name_arg);
}else{
emit(OP_DUP_TOP_VALUE);
}
EXPR(); EXPR();
switch (op) { switch (op) {
case TK("+="): emit(OP_INPLACE_BINARY_OP, 0); break; case TK("+="): emit(OP_BINARY_OP, 0); break;
case TK("-="): emit(OP_INPLACE_BINARY_OP, 1); break; case TK("-="): emit(OP_BINARY_OP, 1); break;
case TK("*="): emit(OP_INPLACE_BINARY_OP, 2); break; case TK("*="): emit(OP_BINARY_OP, 2); break;
case TK("/="): emit(OP_INPLACE_BINARY_OP, 3); break; case TK("/="): emit(OP_BINARY_OP, 3); break;
case TK("//="): emit(OP_INPLACE_BINARY_OP, 4); break; case TK("//="): emit(OP_BINARY_OP, 4); break;
case TK("%="): emit(OP_INPLACE_BINARY_OP, 5); break; case TK("%="): emit(OP_BINARY_OP, 5); break;
case TK("<<="): emit(OP_INPLACE_BITWISE_OP, 0); break; case TK("<<="): emit(OP_BITWISE_OP, 0); break;
case TK(">>="): emit(OP_INPLACE_BITWISE_OP, 1); break; case TK(">>="): emit(OP_BITWISE_OP, 1); break;
case TK("&="): emit(OP_INPLACE_BITWISE_OP, 2); break; case TK("&="): emit(OP_BITWISE_OP, 2); break;
case TK("|="): emit(OP_INPLACE_BITWISE_OP, 3); break; case TK("|="): emit(OP_BITWISE_OP, 3); break;
case TK("^="): emit(OP_INPLACE_BITWISE_OP, 4); break; case TK("^="): emit(OP_BITWISE_OP, 4); break;
default: UNREACHABLE(); default: UNREACHABLE();
} }
if(is_load_name_ref){
emit(OP_STORE_NAME, _name_arg);
}else{
emit(OP_STORE_REF);
}
} }
co()->_rvalue -= 1; co()->_rvalue -= 1;
} }
@ -791,6 +803,9 @@ private:
consume_end_stmt(); consume_end_stmt();
} }
// a = 1 + 2
// ['a', '1', '2', '+', '=']
//
void parse_expression(Precedence precedence) { void parse_expression(Precedence precedence) {
lex_token(); lex_token();
GrammarFn prefix = rules[parser->prev.type].prefix; GrammarFn prefix = rules[parser->prev.type].prefix;
@ -1003,7 +1018,6 @@ private:
// If last op is not an assignment, pop the result. // If last op is not an assignment, pop the result.
uint8_t last_op = co()->codes.back().op; uint8_t last_op = co()->codes.back().op;
if( last_op!=OP_STORE_NAME && last_op!=OP_STORE_REF && 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){ last_op!=OP_STORE_ALL_NAMES && last_op!=OP_STORE_CLASS_ATTR){
for(int i=begin; i<end; i++){ for(int i=begin; i<end; i++){
if(co()->codes[i].op==OP_BUILD_TUPLE_REF) co()->codes[i].op = OP_BUILD_TUPLE; if(co()->codes[i].op==OP_BUILD_TUPLE_REF) co()->codes[i].op = OP_BUILD_TUPLE;

View File

@ -5,12 +5,46 @@
#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;
int gc_threshold = 700; static const int kMinGCThreshold = 700;
int gc_threshold = kMinGCThreshold;
int gc_counter = 0; int gc_counter = 0;
template<typename T> template<typename T>
@ -29,8 +63,13 @@ struct ManagedHeap{
return obj; return obj;
} }
inline static std::map<Type, int> deleted;
~ManagedHeap(){ ~ManagedHeap(){
for(PyObject* obj: _no_gc) delete obj; for(PyObject* obj: _no_gc) delete obj;
for(auto& [type, count]: deleted){
std::cout << "GC: " << type << "=" << count << std::endl;
}
} }
int sweep(VM* vm){ int sweep(VM* vm){
@ -41,6 +80,7 @@ struct ManagedHeap{
alive.push_back(obj); alive.push_back(obj);
}else{ }else{
// _delete_hook(vm, obj); // _delete_hook(vm, obj);
deleted[obj->type] += 1;
delete obj; delete obj;
} }
} }
@ -49,6 +89,7 @@ struct ManagedHeap{
for(PyObject* obj: _no_gc) obj->gc.marked = false; for(PyObject* obj: _no_gc) obj->gc.marked = false;
int freed = gen.size() - alive.size(); int freed = gen.size() - alive.size();
// std::cout << "GC: " << alive.size() << "/" << gen.size() << " (" << freed << " freed)" << std::endl;
gen.clear(); gen.clear();
gen.swap(alive); gen.swap(alive);
return freed; return freed;
@ -61,12 +102,12 @@ struct ManagedHeap{
gc_counter = 0; gc_counter = 0;
collect(vm); collect(vm);
gc_threshold = gen.size() * 2; gc_threshold = gen.size() * 2;
if(gc_threshold < kMinGCThreshold) gc_threshold = kMinGCThreshold;
} }
int collect(VM* vm){ int collect(VM* vm){
mark(vm); mark(vm);
int freed = sweep(vm); int freed = sweep(vm);
// std::cout << "GC: " << freed << " objects freed" << std::endl;
return freed; return freed;
} }

View File

@ -81,9 +81,6 @@ OPCODE(YIELD_VALUE)
OPCODE(FAST_INDEX) // a[x] OPCODE(FAST_INDEX) // a[x]
OPCODE(FAST_INDEX_REF) // a[x] OPCODE(FAST_INDEX_REF) // a[x]
OPCODE(INPLACE_BINARY_OP)
OPCODE(INPLACE_BITWISE_OP)
OPCODE(SETUP_CLOSURE) OPCODE(SETUP_CLOSURE)
OPCODE(SETUP_DECORATOR) OPCODE(SETUP_DECORATOR)
OPCODE(STORE_ALL_NAMES) OPCODE(STORE_ALL_NAMES)

View File

@ -166,6 +166,7 @@ public:
if(_module == nullptr) _module = _main; if(_module == nullptr) _module = _main;
try { try {
CodeObject_ code = compile(source, filename, mode); CodeObject_ code = compile(source, filename, mode);
if(_module == _main) std::cout << disassemble(code) << '\n';
return _exec(code, _module); return _exec(code, _module);
}catch (const Exception& e){ }catch (const Exception& e){
*_stderr << e.summary() << '\n'; *_stderr << e.summary() << '\n';