blueloveTH %!s(int64=2) %!d(string=hai) anos
pai
achega
3581e06ed5
Modificáronse 6 ficheiros con 61 adicións e 42 borrados
  1. 1 1
      src/ceval.h
  2. 7 14
      src/frame.h
  3. 1 0
      src/gc.h
  4. 3 3
      src/iter.h
  5. 12 2
      src/vector.h
  6. 37 22
      src/vm.h

+ 1 - 1
src/ceval.h

@@ -7,7 +7,7 @@ namespace pkpy{
 
 #define DISPATCH() goto __NEXT_STEP
 
-inline PyObject* VM::run_frame(Frame* frame){
+inline PyObject* VM::run_frame(FrameId frame){
 __NEXT_STEP:;
     /* NOTE: 
     * Be aware of accidental gc!

+ 7 - 14
src/frame.h

@@ -6,8 +6,6 @@
 
 namespace pkpy{
 
-static THREAD_LOCAL i64 kFrameGlobalId = 0;
-
 using ValueStack = pod_vector<PyObject*>;
 
 struct Frame {
@@ -19,7 +17,6 @@ struct Frame {
     PyObject* _module;
     NameDict_ _locals;
     NameDict_ _closure;
-    const i64 id;
     std::vector<std::pair<int, ValueStack>> s_try_block;
 
     NameDict& f_locals() noexcept { return _locals!=nullptr ? *_locals : _module->attr(); }
@@ -30,9 +27,14 @@ struct Frame {
     }
 
     Frame(const CodeObject_& co, PyObject* _module, NameDict_ _locals=nullptr, NameDict_ _closure=nullptr)
-            : co(co.get()), _module(_module), _locals(_locals), _closure(_closure), id(kFrameGlobalId++) {
+            : co(co.get()), _module(_module), _locals(_locals), _closure(_closure) {
     }
 
+    Frame(const Frame& other) = delete;
+    Frame& operator=(const Frame& other) = delete;
+    Frame(Frame&& other) noexcept = default;
+    Frame& operator=(Frame&& other) noexcept = default;
+
     const Bytecode& next_bytecode() {
         _ip = _next_ip++;
         return co->codes[_ip];
@@ -45,7 +47,7 @@ struct Frame {
 
     std::string stack_info(){
         std::stringstream ss;
-        ss << id << " [";
+        ss << " [";
         for(int i=0; i<_data.size(); i++){
             ss << (i64)_data[i];
             if(i != _data.size()-1) ss << ", ";
@@ -162,13 +164,4 @@ struct Frame {
     }
 };
 
-
-struct FrameDeleter{
-    void operator()(Frame* frame) const {
-        frame->~Frame();
-        pool128.dealloc(frame);
-    }
-};
-using Frame_ = std::unique_ptr<Frame, FrameDeleter>;
-
 }; // namespace pkpy

+ 1 - 0
src/gc.h

@@ -109,6 +109,7 @@ struct ManagedHeap{
 };
 
 inline void NameDict::_gc_mark() const{
+    if(size() == 0) return;
     for(uint16_t i=0; i<_capacity; i++){
         if(_items[i].first.empty()) continue;
         OBJ_MARK(_items[i].second);

+ 3 - 3
src/iter.h

@@ -63,13 +63,13 @@ public:
 
 inline PyObject* Generator::next(){
     if(state == 2) return nullptr;
-    vm->callstack.push(std::move(frame));
+    vm->_push_new_frame(std::move(frame));
     PyObject* ret = vm->_exec();
     if(ret == vm->_py_op_yield){
         frame = std::move(vm->callstack.top());
         vm->callstack.pop();
         state = 1;
-        return frame->popx();
+        return frame.popx();
     }else{
         state = 2;
         return nullptr;
@@ -77,7 +77,7 @@ inline PyObject* Generator::next(){
 }
 
 inline void Generator::_gc_mark() const{
-    if(frame != nullptr) frame->_gc_mark();
+    frame._gc_mark();
 }
 
 template<typename T>

+ 12 - 2
src/vector.h

@@ -53,8 +53,14 @@ struct pod_vector{
         _data[_size++] = std::forward<__ValueT>(t);
     }
 
+    template<typename... Args>
+    void emplace_back(Args&&... args) {
+        if (_size == _capacity) reserve(_capacity*2);
+        new (&_data[_size++]) T(std::forward<Args>(args)...);
+    }
+
     void reserve(int cap){
-        if(cap < _capacity) return;
+        if(cap <= _capacity) return;
         _capacity = cap;
         T* old_data = _data;
         _data = (T*)pool128.alloc(_capacity * sizeof(T));
@@ -111,6 +117,10 @@ class stack{
 public:
 	void push(const T& t){ vec.push_back(t); }
 	void push(T&& t){ vec.push_back(std::move(t)); }
+    template<typename... Args>
+    void emplace(Args&&... args){
+        vec.emplace_back(std::forward<Args>(args)...);
+    }
 	void pop(){ vec.pop_back(); }
 	void clear(){ vec.clear(); }
 	bool empty() const { return vec.empty(); }
@@ -118,7 +128,7 @@ public:
 	T& top(){ return vec.back(); }
 	const T& top() const { return vec.back(); }
 	T popx(){ T t = std::move(vec.back()); vec.pop_back(); return t; }
-	const Container& data() const { return vec; }
+	Container& data() { return vec; }
 };
 
 template <typename T>

+ 37 - 22
src/vm.h

@@ -33,10 +33,11 @@ Str _read_file_cwd(const Str& name, bool* ok);
 
 
 class Generator: public BaseIter {
-    Frame_ frame;
+    Frame frame;
     int state; // 0,1,2
 public:
-    Generator(VM* vm, Frame_&& frame)
+    template<typename... Args>
+    Generator(VM* vm, Frame&& frame)
         : BaseIter(vm), frame(std::move(frame)), state(0) {}
 
     PyObject* next() override;
@@ -49,14 +50,21 @@ struct PyTypeInfo{
     Str name;
 };
 
+struct FrameId{
+    std::vector<pkpy::Frame>* data;
+    int index;
+    FrameId(std::vector<pkpy::Frame>* data, int index) : data(data), index(index) {}
+    Frame* operator->() const { return &data->operator[](index); }
+};
+
 class VM {
     VM* vm;     // self reference for simplify code
 public:
     ManagedHeap heap;
-    stack< Frame_ > callstack;
+    stack< Frame > callstack;
     std::vector<PyTypeInfo> _all_types;
 
-    PyObject* run_frame(Frame* frame);
+    PyObject* run_frame(FrameId frame);
 
     NameDict _modules;                                  // loaded modules
     std::map<StrName, Str> _lazy_modules;               // lazy loaded modules
@@ -93,11 +101,11 @@ public:
 
     bool is_stdio_used() const { return _stdout == &std::cout; }
 
-    Frame* top_frame() const {
+    FrameId top_frame() {
 #if DEBUG_EXTRA_CHECK
         if(callstack.empty()) UNREACHABLE();
 #endif
-        return callstack.top().get();
+        return FrameId(&callstack.data(), callstack.size()-1);
     }
 
     PyObject* asStr(PyObject* obj){
@@ -176,22 +184,28 @@ public:
             *_stderr << e.what() << '\n';
         }
 #endif
-        callstack = {};
+        callstack.clear();
         return nullptr;
     }
 
     template<typename ...Args>
-    Frame_ _new_frame(Args&&... args){
+    void _push_new_frame(Args&&... args){
+        if(callstack.size() > recursionlimit){
+            _error("RecursionError", "maximum recursion depth exceeded");
+        }
+        callstack.emplace(std::forward<Args>(args)...);
+    }
+
+    void _push_new_frame(Frame&& frame){
         if(callstack.size() > recursionlimit){
             _error("RecursionError", "maximum recursion depth exceeded");
         }
-        Frame* frame = new(pool128.alloc<Frame>()) Frame(std::forward<Args>(args)...);
-        return Frame_(frame);
+        callstack.emplace(std::move(frame));
     }
 
     template<typename ...Args>
     PyObject* _exec(Args&&... args){
-        callstack.push(_new_frame(std::forward<Args>(args)...));
+        _push_new_frame(std::forward<Args>(args)...);
         return _exec();
     }
 
@@ -728,9 +742,10 @@ inline PyObject* VM::call(PyObject* callable, Args args, const Args& kwargs, boo
             locals->set(key, kwargs[i+1]);
         }
         PyObject* _module = fn._module != nullptr ? fn._module : top_frame()->_module;
-        auto _frame = _new_frame(fn.decl->code, _module, locals, fn._closure);
-        if(fn.decl->code->is_generator) return PyIter(Generator(this, std::move(_frame)));
-        callstack.push(std::move(_frame));
+        if(fn.decl->code->is_generator){
+            return PyIter(Generator(this, Frame(fn.decl->code, _module, locals, fn._closure)));
+        }
+        _push_new_frame(fn.decl->code, _module, locals, fn._closure);
         if(opCall) return _py_op_call;
         return _exec();
     }
@@ -892,8 +907,8 @@ inline void VM::_error(Exception e){
 }
 
 inline PyObject* VM::_exec(){
-    Frame* frame = top_frame();
-    const i64 base_id = frame->id;
+    FrameId frame = top_frame();
+    const int base_id = frame.index;
     bool need_raise = false;
 
     while(true){
@@ -905,16 +920,16 @@ inline PyObject* VM::_exec(){
             PyObject* ret = run_frame(frame);
             if(ret == _py_op_yield) return _py_op_yield;
             if(ret != _py_op_call){
-                if(frame->id == base_id){      // [ frameBase<- ]
+                if(frame.index == base_id){       // [ frameBase<- ]
                     callstack.pop();
                     return ret;
                 }else{
                     callstack.pop();
-                    frame = callstack.top().get();
+                    frame = top_frame();
                     frame->push(ret);
                 }
             }else{
-                frame = callstack.top().get();  // [ frameBase, newFrame<- ]
+                frame = top_frame();            // [ frameBase, newFrame<- ]
             }
         }catch(HandledException& e){
             continue;
@@ -929,9 +944,9 @@ inline PyObject* VM::_exec(){
 #endif
                 throw _e;
             }
-            frame = callstack.top().get();
+            frame = top_frame();
             frame->push(obj);
-            if(frame->id < base_id) throw ToBeRaisedException();
+            if(frame.index < base_id) throw ToBeRaisedException();
             need_raise = true;
         }catch(ToBeRaisedException& e){
             need_raise = true;
@@ -941,7 +956,7 @@ inline PyObject* VM::_exec(){
 
 inline void ManagedHeap::mark() {
     for(PyObject* obj: _no_gc) OBJ_MARK(obj);
-    for(auto& frame : vm->callstack.data()) frame->_gc_mark();
+    for(auto& frame : vm->callstack.data()) frame._gc_mark();
 }
 
 inline Str obj_type_name(VM *vm, Type type){