소스 검색

refactor frameobject

blueloveTH 1 년 전
부모
커밋
57b4595c11
6개의 변경된 파일54개의 추가작업 그리고 19개의 파일을 삭제
  1. 23 2
      include/pocketpy/frame.h
  2. 11 3
      include/pocketpy/iter.h
  3. 1 1
      include/pocketpy/vm.h
  4. 1 1
      src/frame.cpp
  5. 15 8
      src/iter.cpp
  6. 3 4
      src/vm.cpp

+ 23 - 2
include/pocketpy/frame.h

@@ -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

+ 11 - 3
include/pocketpy/iter.h

@@ -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{

+ 1 - 1
include/pocketpy/vm.h

@@ -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);

+ 1 - 1
src/frame.cpp

@@ -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;

+ 15 - 8
src/iter.cpp

@@ -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);
 }
 

+ 3 - 4
src/vm.cpp

@@ -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