refactor frameobject

This commit is contained in:
blueloveTH 2024-05-26 18:28:19 +08:00
parent 51170e4a47
commit 57b4595c11
6 changed files with 54 additions and 19 deletions

View File

@ -84,6 +84,8 @@ struct UnwindTarget{
}; };
struct Frame { struct Frame {
PK_ALWAYS_PASS_BY_POINTER(Frame)
const Bytecode* _ip; const Bytecode* _ip;
// This is for unwinding only, use `actual_sp_base()` for value stack access // This is for unwinding only, use `actual_sp_base()` for value stack access
PyVar* _sp_base; PyVar* _sp_base;
@ -129,9 +131,9 @@ struct Frame {
void set_unwind_target(PyVar* _sp); void set_unwind_target(PyVar* _sp);
UnwindTarget* find_unwind_target(int iblock); UnwindTarget* find_unwind_target(int iblock);
void free_unwind_target();
void _gc_mark(VM* vm) const; void _gc_mark(VM* vm) const;
~Frame();
}; };
struct LinkedFrame{ struct LinkedFrame{
@ -141,8 +143,9 @@ struct LinkedFrame{
LinkedFrame(LinkedFrame* f_back, Args&&... args) : f_back(f_back), frame(std::forward<Args>(args)...) {} LinkedFrame(LinkedFrame* f_back, Args&&... args) : f_back(f_back), frame(std::forward<Args>(args)...) {}
}; };
struct CallStack{ struct CallStack{
static_assert(sizeof(LinkedFrame) <= 128 && std::is_trivially_destructible_v<LinkedFrame>); static_assert(sizeof(LinkedFrame) <= 128);
LinkedFrame* _tail; LinkedFrame* _tail;
int _size; int _size;
@ -162,10 +165,26 @@ struct CallStack{
PK_DEBUG_ASSERT(!empty()) PK_DEBUG_ASSERT(!empty())
LinkedFrame* p = _tail; LinkedFrame* p = _tail;
_tail = p->f_back; _tail = p->f_back;
p->~LinkedFrame();
pool128_dealloc(p); pool128_dealloc(p);
--_size; --_size;
} }
LinkedFrame* popx(){
PK_DEBUG_ASSERT(!empty())
LinkedFrame* p = _tail;
_tail = p->f_back;
--_size;
p->f_back = nullptr; // unlink
return p;
}
void pushx(LinkedFrame* p){
p->f_back = _tail;
_tail = p;
++_size;
}
Frame& top() const { Frame& top() const {
PK_DEBUG_ASSERT(!empty()) PK_DEBUG_ASSERT(!empty())
return _tail->frame; return _tail->frame;
@ -175,6 +194,8 @@ struct CallStack{
void apply(Func&& f){ void apply(Func&& f){
for(LinkedFrame* p = _tail; p != nullptr; p = p->f_back) f(p->frame); for(LinkedFrame* p = _tail; p != nullptr; p = p->f_back) f(p->frame);
} }
~CallStack(){ clear(); }
}; };
}; // namespace pkpy }; // namespace pkpy

View File

@ -43,21 +43,29 @@ struct StringIter{
}; };
struct Generator{ struct Generator{
Frame frame; LinkedFrame* lf;
int state; // 0,1,2 int state; // 0,1,2
List s_backup; List s_backup;
Generator(Frame&& frame, ArgsView buffer): frame(std::move(frame)), state(0) { Generator(LinkedFrame* lf, ArgsView buffer): lf(lf), state(0) {
for(PyVar obj: buffer) s_backup.push_back(obj); for(PyVar obj: buffer) s_backup.push_back(obj);
} }
void _gc_mark(VM* vm) { void _gc_mark(VM* vm) {
frame._gc_mark(vm); if(lf == nullptr) return;
lf->frame._gc_mark(vm);
vm->__stack_gc_mark(s_backup.begin(), s_backup.end()); vm->__stack_gc_mark(s_backup.begin(), s_backup.end());
} }
PyVar next(VM* vm); PyVar next(VM* vm);
static void _register(VM* vm, PyVar mod, PyVar type); static void _register(VM* vm, PyVar mod, PyVar type);
~Generator(){
if(lf){
lf->~LinkedFrame();
pool128_dealloc(lf);
}
}
}; };
struct DictItemsIter{ struct DictItemsIter{

View File

@ -479,7 +479,7 @@ public:
PyVar __format_object(PyVar, Str); PyVar __format_object(PyVar, Str);
PyVar __run_top_frame(); PyVar __run_top_frame();
void __pop_frame(); void __pop_frame();
PyVar __py_generator(Frame&& frame, ArgsView buffer); PyVar __py_generator(LinkedFrame* frame, ArgsView buffer);
void __op_unpack_sequence(uint16_t arg); void __op_unpack_sequence(uint16_t arg);
void __prepare_py_call(PyVar*, ArgsView, ArgsView, const FuncDecl_&); void __prepare_py_call(PyVar*, ArgsView, ArgsView, const FuncDecl_&);
void __unpack_as_list(ArgsView args, List& list); void __unpack_as_list(ArgsView args, List& list);

View File

@ -91,7 +91,7 @@ namespace pkpy{
return nullptr; return nullptr;
} }
void Frame::free_unwind_target(){ Frame::~Frame(){
while(_uw_list != nullptr){ while(_uw_list != nullptr){
UnwindTarget* p = _uw_list; UnwindTarget* p = _uw_list;
_uw_list = p->next; _uw_list = p->next;

View File

@ -51,12 +51,12 @@ namespace pkpy{
PyVar Generator::next(VM* vm){ PyVar Generator::next(VM* vm){
if(state == 2) return vm->StopIteration; if(state == 2) return vm->StopIteration;
// reset frame._sp_base // reset frame._sp_base
frame._sp_base = vm->s_data._sp; lf->frame._sp_base = vm->s_data._sp;
frame._locals.a = vm->s_data._sp; lf->frame._locals.a = vm->s_data._sp;
// restore the context // restore the context
for(PyVar obj: s_backup) vm->s_data.push(obj); for(PyVar obj: s_backup) vm->s_data.push(obj);
// relocate stack objects (their addresses become invalid) // relocate stack objects (their addresses become invalid)
for(PyVar* p=frame.actual_sp_base(); p!=vm->s_data.end(); p++){ for(PyVar* p=lf->frame.actual_sp_base(); p!=vm->s_data.end(); p++){
if(p->type == VM::tp_stack_memory){ if(p->type == VM::tp_stack_memory){
// TODO: refactor this // TODO: refactor this
int count = p->as<StackMemory>().count; int count = p->as<StackMemory>().count;
@ -67,7 +67,8 @@ namespace pkpy{
} }
} }
s_backup.clear(); s_backup.clear();
vm->callstack.emplace(std::move(frame)); vm->callstack.pushx(lf);
lf = nullptr;
PyVar ret; PyVar ret;
try{ try{
@ -79,10 +80,16 @@ namespace pkpy{
if(ret == PY_OP_YIELD){ if(ret == PY_OP_YIELD){
// backup the context // backup the context
frame = std::move(vm->callstack.top()); lf = vm->callstack.popx();
ret = vm->s_data.popx(); ret = vm->s_data.popx();
for(PyVar obj: frame.stack_view(&vm->s_data)) s_backup.push_back(obj); for(PyVar obj: lf->frame.stack_view(&vm->s_data)) s_backup.push_back(obj);
vm->__pop_frame(); vm->s_data.reset(lf->frame._sp_base);
// TODO: should we add this snippet here?
// #if PK_ENABLE_PROFILER
// if(!_next_breakpoint.empty() && callstack.size()<_next_breakpoint.callstack_size){
// _next_breakpoint = NextBreakpoint();
// }
// #endif
state = 1; state = 1;
if(ret == vm->StopIteration) state = 2; if(ret == vm->StopIteration) state = 2;
return ret; return ret;
@ -116,7 +123,7 @@ namespace pkpy{
}); });
} }
PyVar VM::__py_generator(Frame&& frame, ArgsView buffer){ PyVar VM::__py_generator(LinkedFrame* frame, ArgsView buffer){
return vm->new_user_object<Generator>(std::move(frame), buffer); return vm->new_user_object<Generator>(std::move(frame), buffer);
} }

View File

@ -1093,8 +1093,9 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call){
case FuncType::GENERATOR: case FuncType::GENERATOR:
__prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl); __prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
s_data.reset(p0); s_data.reset(p0);
callstack.emplace(nullptr, co, fn._module, callable, nullptr);
return __py_generator( return __py_generator(
Frame(nullptr, co, fn._module, callable, nullptr), callstack.popx(),
ArgsView(__vectorcall_buffer, __vectorcall_buffer + co->nlocals) ArgsView(__vectorcall_buffer, __vectorcall_buffer + co->nlocals)
); );
#if PK_DEBUG_EXTRA_CHECK #if PK_DEBUG_EXTRA_CHECK
@ -1644,9 +1645,7 @@ void NextBreakpoint::_step(VM* vm){
#endif #endif
void VM::__pop_frame(){ void VM::__pop_frame(){
Frame& frame = callstack.top(); s_data.reset(callstack.top()._sp_base);
s_data.reset(frame._sp_base);
frame.free_unwind_target();
callstack.pop(); callstack.pop();
#if PK_ENABLE_PROFILER #if PK_ENABLE_PROFILER