mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
update gc
This commit is contained in:
parent
87e52df142
commit
120773891a
18
src/ceval.h
18
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);
|
||||
|
@ -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; i<end; i++){
|
||||
if(co()->codes[i].op==OP_BUILD_TUPLE_REF) co()->codes[i].op = OP_BUILD_TUPLE;
|
||||
|
45
src/gc.h
45
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<PyObject*> _no_gc;
|
||||
std::vector<PyObject*> gen;
|
||||
|
||||
int gc_threshold = 700;
|
||||
static const int kMinGCThreshold = 700;
|
||||
int gc_threshold = kMinGCThreshold;
|
||||
int gc_counter = 0;
|
||||
|
||||
template<typename T>
|
||||
@ -29,8 +63,13 @@ struct ManagedHeap{
|
||||
return obj;
|
||||
}
|
||||
|
||||
inline static std::map<Type, int> 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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user