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