mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30: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){
|
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);
|
||||||
|
@ -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;
|
||||||
|
45
src/gc.h
45
src/gc.h
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
1
src/vm.h
1
src/vm.h
@ -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';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user