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

View File

@ -43,21 +43,29 @@ struct StringIter{
};
struct Generator{
Frame frame;
LinkedFrame* lf;
int state; // 0,1,2
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);
}
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());
}
PyVar next(VM* vm);
static void _register(VM* vm, PyVar mod, PyVar type);
~Generator(){
if(lf){
lf->~LinkedFrame();
pool128_dealloc(lf);
}
}
};
struct DictItemsIter{

View File

@ -479,7 +479,7 @@ public:
PyVar __format_object(PyVar, Str);
PyVar __run_top_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 __prepare_py_call(PyVar*, ArgsView, ArgsView, const FuncDecl_&);
void __unpack_as_list(ArgsView args, List& list);

View File

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

View File

@ -51,12 +51,12 @@ namespace pkpy{
PyVar Generator::next(VM* vm){
if(state == 2) return vm->StopIteration;
// reset frame._sp_base
frame._sp_base = vm->s_data._sp;
frame._locals.a = vm->s_data._sp;
lf->frame._sp_base = vm->s_data._sp;
lf->frame._locals.a = vm->s_data._sp;
// restore the context
for(PyVar obj: s_backup) vm->s_data.push(obj);
// 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){
// TODO: refactor this
int count = p->as<StackMemory>().count;
@ -67,7 +67,8 @@ namespace pkpy{
}
}
s_backup.clear();
vm->callstack.emplace(std::move(frame));
vm->callstack.pushx(lf);
lf = nullptr;
PyVar ret;
try{
@ -79,10 +80,16 @@ namespace pkpy{
if(ret == PY_OP_YIELD){
// backup the context
frame = std::move(vm->callstack.top());
lf = vm->callstack.popx();
ret = vm->s_data.popx();
for(PyVar obj: frame.stack_view(&vm->s_data)) s_backup.push_back(obj);
vm->__pop_frame();
for(PyVar obj: lf->frame.stack_view(&vm->s_data)) s_backup.push_back(obj);
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;
if(ret == vm->StopIteration) state = 2;
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);
}

View File

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