From 3581e06ed5f6e37c2c5f0cdb7706a03bf51e9c27 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 9 Apr 2023 21:36:44 +0800 Subject: [PATCH] up --- src/ceval.h | 2 +- src/frame.h | 21 +++++++------------ src/gc.h | 1 + src/iter.h | 6 +++--- src/vector.h | 14 +++++++++++-- src/vm.h | 59 ++++++++++++++++++++++++++++++++-------------------- 6 files changed, 61 insertions(+), 42 deletions(-) diff --git a/src/ceval.h b/src/ceval.h index 6e4c268d..e8429a5b 100644 --- a/src/ceval.h +++ b/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! diff --git a/src/frame.h b/src/frame.h index 752e7cac..99bf9da4 100644 --- a/src/frame.h +++ b/src/frame.h @@ -6,8 +6,6 @@ namespace pkpy{ -static THREAD_LOCAL i64 kFrameGlobalId = 0; - using ValueStack = pod_vector; struct Frame { @@ -19,7 +17,6 @@ struct Frame { PyObject* _module; NameDict_ _locals; NameDict_ _closure; - const i64 id; std::vector> 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; - }; // namespace pkpy \ No newline at end of file diff --git a/src/gc.h b/src/gc.h index 752a18cb..9e620197 100644 --- a/src/gc.h +++ b/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); diff --git a/src/iter.h b/src/iter.h index bd048c05..07d3faea 100644 --- a/src/iter.h +++ b/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 diff --git a/src/vector.h b/src/vector.h index 8caeb362..f10f52fd 100644 --- a/src/vector.h +++ b/src/vector.h @@ -53,8 +53,14 @@ struct pod_vector{ _data[_size++] = std::forward<__ValueT>(t); } + template + void emplace_back(Args&&... args) { + if (_size == _capacity) reserve(_capacity*2); + new (&_data[_size++]) T(std::forward(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 + void emplace(Args&&... args){ + vec.emplace_back(std::forward(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 diff --git a/src/vm.h b/src/vm.h index cb82baca..ef786725 100644 --- a/src/vm.h +++ b/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 + 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* data; + int index; + FrameId(std::vector* 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 _all_types; - PyObject* run_frame(Frame* frame); + PyObject* run_frame(FrameId frame); NameDict _modules; // loaded modules std::map _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 - Frame_ _new_frame(Args&&... args){ + void _push_new_frame(Args&&... args){ if(callstack.size() > recursionlimit){ _error("RecursionError", "maximum recursion depth exceeded"); } - Frame* frame = new(pool128.alloc()) Frame(std::forward(args)...); - return Frame_(frame); + callstack.emplace(std::forward(args)...); + } + + void _push_new_frame(Frame&& frame){ + if(callstack.size() > recursionlimit){ + _error("RecursionError", "maximum recursion depth exceeded"); + } + callstack.emplace(std::move(frame)); } template PyObject* _exec(Args&&... args){ - callstack.push(_new_frame(std::forward(args)...)); + _push_new_frame(std::forward(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){