This commit is contained in:
blueloveTH 2023-04-09 21:36:44 +08:00
parent d0b9d8b7ff
commit 3581e06ed5
6 changed files with 61 additions and 42 deletions

View File

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

View File

@ -6,8 +6,6 @@
namespace pkpy{ namespace pkpy{
static THREAD_LOCAL i64 kFrameGlobalId = 0;
using ValueStack = pod_vector<PyObject*>; using ValueStack = pod_vector<PyObject*>;
struct Frame { struct Frame {
@ -19,7 +17,6 @@ struct Frame {
PyObject* _module; PyObject* _module;
NameDict_ _locals; NameDict_ _locals;
NameDict_ _closure; NameDict_ _closure;
const i64 id;
std::vector<std::pair<int, ValueStack>> s_try_block; std::vector<std::pair<int, ValueStack>> s_try_block;
NameDict& f_locals() noexcept { return _locals!=nullptr ? *_locals : _module->attr(); } 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) 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() { const Bytecode& next_bytecode() {
_ip = _next_ip++; _ip = _next_ip++;
return co->codes[_ip]; return co->codes[_ip];
@ -45,7 +47,7 @@ struct Frame {
std::string stack_info(){ std::string stack_info(){
std::stringstream ss; std::stringstream ss;
ss << id << " ["; ss << " [";
for(int i=0; i<_data.size(); i++){ for(int i=0; i<_data.size(); i++){
ss << (i64)_data[i]; ss << (i64)_data[i];
if(i != _data.size()-1) ss << ", "; 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 }; // namespace pkpy

View File

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

View File

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

View File

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

View File

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