mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-22 20:40:18 +00:00
up
This commit is contained in:
parent
d0b9d8b7ff
commit
3581e06ed5
@ -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!
|
||||
|
21
src/frame.h
21
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
src/gc.h
1
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);
|
||||
|
@ -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>
|
||||
|
14
src/vector.h
14
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>
|
||||
|
59
src/vm.h
59
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");
|
||||
}
|
||||
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){
|
||||
|
Loading…
x
Reference in New Issue
Block a user