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
inline PyObject* VM::run_frame(Frame* frame){
inline PyObject* VM::run_frame(FrameId frame){
__NEXT_STEP:;
/* NOTE:
* Be aware of accidental gc!

View File

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

View File

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

View File

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

View File

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

View File

@ -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");
}
Frame* frame = new(pool128.alloc<Frame>()) Frame(std::forward<Args>(args)...);
return Frame_(frame);
callstack.emplace(std::forward<Args>(args)...);
}
void _push_new_frame(Frame&& frame){
if(callstack.size() > recursionlimit){
_error("RecursionError", "maximum recursion depth exceeded");
}
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){