mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
...
This commit is contained in:
parent
8aa6893e29
commit
adc2f2cc3f
31
src/ceval.h
31
src/ceval.h
@ -28,14 +28,14 @@ inline PyObject* VM::_run_top_frame(){
|
|||||||
|
|
||||||
/* Stack manipulation macros */
|
/* Stack manipulation macros */
|
||||||
// https://github.com/python/cpython/blob/3.9/Python/ceval.c#L1123
|
// https://github.com/python/cpython/blob/3.9/Python/ceval.c#L1123
|
||||||
#define TOP() (frame->_s.top())
|
#define TOP() (s_data.top())
|
||||||
#define SECOND() (frame->_s.second())
|
#define SECOND() (s_data.second())
|
||||||
#define PEEK(n) (frame->_s.peek(n))
|
#define PEEK(n) (s_data.peek(n))
|
||||||
#define STACK_SHRINK(n) (frame->_s.shrink(n))
|
#define STACK_SHRINK(n) (s_data.shrink(n))
|
||||||
#define PUSH(v) (frame->_s.push(v))
|
#define PUSH(v) (s_data.push(v))
|
||||||
#define POP() (frame->_s.pop())
|
#define POP() (s_data.pop())
|
||||||
#define POPX() (frame->_s.popx())
|
#define POPX() (s_data.popx())
|
||||||
#define STACK_VIEW(n) (frame->_s.view(n))
|
#define STACK_VIEW(n) (s_data.view(n))
|
||||||
|
|
||||||
#define DISPATCH_OP_CALL() { frame = top_frame(); goto __NEXT_FRAME; }
|
#define DISPATCH_OP_CALL() { frame = top_frame(); goto __NEXT_FRAME; }
|
||||||
__NEXT_FRAME:
|
__NEXT_FRAME:
|
||||||
@ -392,6 +392,8 @@ __NEXT_STEP:;
|
|||||||
if(byte.op==OP_CALL && is_type(callable, tp_function)){
|
if(byte.op==OP_CALL && is_type(callable, tp_function)){
|
||||||
PyObject* ret = _py_call(callable, STACK_VIEW(ARGC + int(method_call)), {});
|
PyObject* ret = _py_call(callable, STACK_VIEW(ARGC + int(method_call)), {});
|
||||||
STACK_SHRINK(ARGC + 2);
|
STACK_SHRINK(ARGC + 2);
|
||||||
|
// TODO: _sp_base is incorrect
|
||||||
|
top_frame()->_sp_base = s_data._sp;
|
||||||
if(ret == nullptr) { DISPATCH_OP_CALL(); }
|
if(ret == nullptr) { DISPATCH_OP_CALL(); }
|
||||||
else PUSH(ret); // a generator
|
else PUSH(ret); // a generator
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
@ -424,18 +426,23 @@ __NEXT_STEP:;
|
|||||||
PUSH(ret);
|
PUSH(ret);
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
TARGET(RETURN_VALUE) {
|
TARGET(RETURN_VALUE) {
|
||||||
PyObject* __ret = POPX();
|
#if DEBUG_EXTRA_CHECK
|
||||||
|
if(frame->stack_size() != 1) FATAL_ERROR();
|
||||||
|
#endif
|
||||||
if(frame.index == base_id){ // [ frameBase<- ]
|
if(frame.index == base_id){ // [ frameBase<- ]
|
||||||
callstack.pop();
|
callstack.pop();
|
||||||
return __ret;
|
return POPX();
|
||||||
}else{
|
}else{
|
||||||
callstack.pop();
|
callstack.pop();
|
||||||
frame = top_frame();
|
frame = top_frame();
|
||||||
PUSH(__ret);
|
|
||||||
goto __NEXT_FRAME;
|
goto __NEXT_FRAME;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TARGET(YIELD_VALUE) return _py_op_yield;
|
TARGET(YIELD_VALUE)
|
||||||
|
#if DEBUG_EXTRA_CHECK
|
||||||
|
if(frame->stack_size() != 1) FATAL_ERROR();
|
||||||
|
#endif
|
||||||
|
return _py_op_yield;
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
TARGET(LIST_APPEND) {
|
TARGET(LIST_APPEND) {
|
||||||
PyObject* obj = POPX();
|
PyObject* obj = POPX();
|
||||||
|
@ -33,9 +33,9 @@
|
|||||||
|
|
||||||
// debug macros
|
// debug macros
|
||||||
#define DEBUG_NO_BUILTIN_MODULES 0
|
#define DEBUG_NO_BUILTIN_MODULES 0
|
||||||
#define DEBUG_EXTRA_CHECK 0
|
#define DEBUG_EXTRA_CHECK 1
|
||||||
#define DEBUG_DIS_EXEC 0
|
#define DEBUG_DIS_EXEC 1
|
||||||
#define DEBUG_CEVAL_STEP 0
|
#define DEBUG_CEVAL_STEP 1
|
||||||
#define DEBUG_CEVAL_STEP_MIN 0
|
#define DEBUG_CEVAL_STEP_MIN 0
|
||||||
#define DEBUG_FULL_EXCEPTION 0
|
#define DEBUG_FULL_EXCEPTION 0
|
||||||
#define DEBUG_MEMORY_POOL 0
|
#define DEBUG_MEMORY_POOL 0
|
||||||
@ -53,7 +53,7 @@
|
|||||||
#define PK_ENABLE_COMPUTED_GOTO 0
|
#define PK_ENABLE_COMPUTED_GOTO 0
|
||||||
#define UNREACHABLE() __assume(0)
|
#define UNREACHABLE() __assume(0)
|
||||||
#else
|
#else
|
||||||
#define PK_ENABLE_COMPUTED_GOTO 1
|
#define PK_ENABLE_COMPUTED_GOTO 0
|
||||||
#define UNREACHABLE() __builtin_unreachable()
|
#define UNREACHABLE() __builtin_unreachable()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
111
src/frame.h
111
src/frame.h
@ -3,6 +3,7 @@
|
|||||||
#include "codeobject.h"
|
#include "codeobject.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "obj.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
@ -124,80 +125,59 @@ template<> inline void gc_mark<Function>(Function& t){
|
|||||||
t._closure._gc_mark();
|
t._closure._gc_mark();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ValueStack: pod_vector<PyObject*> {
|
struct ValueStack {
|
||||||
PyObject*& top(){ return back(); }
|
static const int MAX_SIZE = 32768;
|
||||||
PyObject* top() const { return back(); }
|
PyObject* _begin[MAX_SIZE];
|
||||||
PyObject*& second(){ return (*this)[size()-2]; }
|
PyObject** _sp;
|
||||||
PyObject* second() const { return (*this)[size()-2]; }
|
|
||||||
PyObject*& peek(int n){ return (*this)[size()-n]; }
|
|
||||||
PyObject* peek(int n) const { return (*this)[size()-n]; }
|
|
||||||
void push(PyObject* v){ push_back(v); }
|
|
||||||
void pop(){ pop_back(); }
|
|
||||||
PyObject* popx(){ return popx_back(); }
|
|
||||||
ArgsView view(int n){ return ArgsView(end()-n, end()); }
|
|
||||||
void shrink(int n){ resize(size() - n); }
|
|
||||||
};
|
|
||||||
|
|
||||||
// struct ValueStack {
|
ValueStack(): _sp(_begin) {}
|
||||||
// PyObject** _begin;
|
|
||||||
// PyObject** _sp;
|
|
||||||
|
|
||||||
// ValueStack(int n=16): _begin((PyObject**)pool128.alloc(n * sizeof(void*))), _sp(_begin) { }
|
PyObject*& top(){ return _sp[-1]; }
|
||||||
|
PyObject* top() const { return _sp[-1]; }
|
||||||
// PyObject*& top(){ return _sp[-1]; }
|
PyObject*& second(){ return _sp[-2]; }
|
||||||
// PyObject* top() const { return _sp[-1]; }
|
PyObject* second() const { return _sp[-2]; }
|
||||||
// PyObject*& second(){ return _sp[-2]; }
|
PyObject*& peek(int n){ return _sp[-n]; }
|
||||||
// PyObject* second() const { return _sp[-2]; }
|
PyObject* peek(int n) const { return _sp[-n]; }
|
||||||
// PyObject*& peek(int n){ return _sp[-n]; }
|
void push(PyObject* v){ *_sp++ = v; }
|
||||||
// PyObject* peek(int n) const { return _sp[-n]; }
|
void pop(){ --_sp; }
|
||||||
// void push(PyObject* v){ *_sp++ = v; }
|
PyObject* popx(){ return *--_sp; }
|
||||||
// void pop(){ --_sp; }
|
ArgsView view(int n){ return ArgsView(_sp-n, _sp); }
|
||||||
// PyObject* popx(){ return *--_sp; }
|
void shrink(int n){ _sp -= n; }
|
||||||
// ArgsView view(int n){ return ArgsView(_sp-n, _sp); }
|
|
||||||
// void shrink(int n){ _sp -= n; }
|
|
||||||
// int size() const { return _sp - _begin; }
|
// int size() const { return _sp - _begin; }
|
||||||
// bool empty() const { return _sp == _begin; }
|
// bool empty() const { return _sp == _begin; }
|
||||||
// PyObject** begin() const { return _begin; }
|
PyObject** begin() { return _begin; }
|
||||||
// PyObject** end() const { return _sp; }
|
PyObject** end() { return _sp; }
|
||||||
|
void reset(PyObject** sp) { _sp = sp; }
|
||||||
// void resize(int n) { _sp = _begin + n; }
|
// void resize(int n) { _sp = _begin + n; }
|
||||||
|
bool is_overflow() const { return _sp >= _begin + MAX_SIZE; }
|
||||||
|
|
||||||
// ValueStack(ValueStack&& other) noexcept{
|
ValueStack(const ValueStack&) = delete;
|
||||||
// _begin = other._begin;
|
ValueStack(ValueStack&&) = delete;
|
||||||
// _sp = other._sp;
|
ValueStack& operator=(const ValueStack&) = delete;
|
||||||
// other._begin = nullptr;
|
ValueStack& operator=(ValueStack&&) = delete;
|
||||||
// }
|
};
|
||||||
|
|
||||||
// ValueStack& operator=(ValueStack&& other) noexcept{
|
|
||||||
// if(_begin != nullptr) pool128.dealloc(_begin);
|
|
||||||
// _begin = other._begin;
|
|
||||||
// _sp = other._sp;
|
|
||||||
// other._begin = nullptr;
|
|
||||||
// return *this;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ~ValueStack(){ if(_begin!=nullptr) pool128.dealloc(_begin); }
|
|
||||||
// };
|
|
||||||
|
|
||||||
struct Frame {
|
struct Frame {
|
||||||
int _ip = -1;
|
int _ip = -1;
|
||||||
int _next_ip = 0;
|
int _next_ip = 0;
|
||||||
|
ValueStack* _s;
|
||||||
|
PyObject** _sp_base;
|
||||||
const CodeObject* co;
|
const CodeObject* co;
|
||||||
PyObject* _module;
|
|
||||||
|
|
||||||
|
PyObject* _module;
|
||||||
FastLocals _locals;
|
FastLocals _locals;
|
||||||
FastLocals _closure;
|
FastLocals _closure;
|
||||||
ValueStack _s;
|
|
||||||
|
|
||||||
NameDict& f_globals() noexcept { return _module->attr(); }
|
NameDict& f_globals() noexcept { return _module->attr(); }
|
||||||
|
|
||||||
Frame(const CodeObject* co, PyObject* _module, FastLocals&& _locals, const FastLocals& _closure)
|
Frame(ValueStack* _s, const CodeObject* co, PyObject* _module, FastLocals&& _locals, const FastLocals& _closure)
|
||||||
: co(co), _module(_module), _locals(std::move(_locals)), _closure(_closure) { }
|
: _s(_s), _sp_base(_s->_sp), co(co), _module(_module), _locals(std::move(_locals)), _closure(_closure) { }
|
||||||
|
|
||||||
Frame(const CodeObject* co, PyObject* _module, const FastLocals& _locals, const FastLocals& _closure)
|
Frame(ValueStack* _s, const CodeObject* co, PyObject* _module, const FastLocals& _locals, const FastLocals& _closure)
|
||||||
: co(co), _module(_module), _locals(_locals), _closure(_closure) { }
|
: _s(_s), _sp_base(_s->_sp), co(co), _module(_module), _locals(_locals), _closure(_closure) { }
|
||||||
|
|
||||||
Frame(const CodeObject_& co, PyObject* _module)
|
Frame(ValueStack* _s, const CodeObject_& co, PyObject* _module)
|
||||||
: co(co.get()), _module(_module), _locals(), _closure() { }
|
: _s(_s), _sp_base(_s->_sp), co(co.get()), _module(_module), _locals(), _closure() { }
|
||||||
|
|
||||||
Frame(const Frame& other) = delete;
|
Frame(const Frame& other) = delete;
|
||||||
Frame& operator=(const Frame& other) = delete;
|
Frame& operator=(const Frame& other) = delete;
|
||||||
@ -214,12 +194,14 @@ struct Frame {
|
|||||||
return co->src->snapshot(line);
|
return co->src->snapshot(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int stack_size() const { return _s->_sp - _sp_base; }
|
||||||
|
|
||||||
std::string stack_info(){
|
std::string stack_info(){
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << this << ": [";
|
ss << this << ": [";
|
||||||
for(PyObject** t=_s.begin(); t<_s.end(); t++){
|
for(PyObject** t=_sp_base; t<_s->end(); t++){
|
||||||
ss << *t;
|
ss << *t;
|
||||||
if(t != _s.end()-1) ss << ", ";
|
if(t != _s->end()-1) ss << ", ";
|
||||||
}
|
}
|
||||||
ss << "]";
|
ss << "]";
|
||||||
return ss.str();
|
return ss.str();
|
||||||
@ -236,18 +218,18 @@ struct Frame {
|
|||||||
block = co->blocks[block].parent;
|
block = co->blocks[block].parent;
|
||||||
}
|
}
|
||||||
if(block < 0) return false;
|
if(block < 0) return false;
|
||||||
PyObject* obj = _s.popx(); // pop exception object
|
PyObject* obj = _s->popx(); // pop exception object
|
||||||
// get the stack size of the try block (depth of for loops)
|
// get the stack size of the try block (depth of for loops)
|
||||||
int stack_size = co->blocks[block].for_loop_depth;
|
int _stack_size = co->blocks[block].for_loop_depth;
|
||||||
if(_s.size() < stack_size) throw std::runtime_error("invalid stack size");
|
if(stack_size() < _stack_size) throw std::runtime_error("invalid stack size");
|
||||||
_s.resize(stack_size); // rollback the stack
|
_s->reset(_sp_base + _stack_size); // rollback the stack
|
||||||
_s.push(obj); // push exception object
|
_s->push(obj); // push exception object
|
||||||
_next_ip = co->blocks[block].end;
|
_next_ip = co->blocks[block].end;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _exit_block(int i){
|
int _exit_block(int i){
|
||||||
if(co->blocks[i].type == FOR_LOOP) _s.pop();
|
if(co->blocks[i].type == FOR_LOOP) _s->pop();
|
||||||
return co->blocks[i].parent;
|
return co->blocks[i].parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,8 +248,7 @@ struct Frame {
|
|||||||
|
|
||||||
void _gc_mark() const {
|
void _gc_mark() const {
|
||||||
// do return if this frame has been moved
|
// do return if this frame has been moved
|
||||||
if(_s.data() == nullptr) return;
|
// TODO: fix here
|
||||||
for(PyObject* obj: _s) OBJ_MARK(obj);
|
|
||||||
OBJ_MARK(_module);
|
OBJ_MARK(_module);
|
||||||
_locals._gc_mark();
|
_locals._gc_mark();
|
||||||
_closure._gc_mark();
|
_closure._gc_mark();
|
||||||
|
@ -69,7 +69,7 @@ inline PyObject* Generator::next(){
|
|||||||
frame = std::move(vm->callstack.top());
|
frame = std::move(vm->callstack.top());
|
||||||
vm->callstack.pop();
|
vm->callstack.pop();
|
||||||
state = 1;
|
state = 1;
|
||||||
return frame._s.popx();
|
return frame._s->popx();
|
||||||
}else{
|
}else{
|
||||||
state = 2;
|
state = 2;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
9
src/vm.h
9
src/vm.h
@ -61,6 +61,7 @@ class VM {
|
|||||||
VM* vm; // self reference for simplify code
|
VM* vm; // self reference for simplify code
|
||||||
public:
|
public:
|
||||||
ManagedHeap heap;
|
ManagedHeap heap;
|
||||||
|
ValueStack s_data;
|
||||||
stack< Frame > callstack;
|
stack< Frame > callstack;
|
||||||
std::vector<PyTypeInfo> _all_types;
|
std::vector<PyTypeInfo> _all_types;
|
||||||
|
|
||||||
@ -192,7 +193,7 @@ public:
|
|||||||
if(callstack.size() > recursionlimit){
|
if(callstack.size() > recursionlimit){
|
||||||
_error("RecursionError", "maximum recursion depth exceeded");
|
_error("RecursionError", "maximum recursion depth exceeded");
|
||||||
}
|
}
|
||||||
callstack.emplace(std::forward<Args>(args)...);
|
callstack.emplace(&s_data, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _push_new_frame(Frame&& frame){
|
void _push_new_frame(Frame&& frame){
|
||||||
@ -731,7 +732,7 @@ inline PyObject* VM::_py_call(PyObject* callable, ArgsView args, ArgsView kwargs
|
|||||||
}
|
}
|
||||||
PyObject* _module = fn._module != nullptr ? fn._module : top_frame()->_module;
|
PyObject* _module = fn._module != nullptr ? fn._module : top_frame()->_module;
|
||||||
if(co->is_generator){
|
if(co->is_generator){
|
||||||
return PyIter(Generator(this, Frame(co, _module, std::move(locals), fn._closure)));
|
return PyIter(Generator(this, Frame(&s_data, co, _module, std::move(locals), fn._closure)));
|
||||||
}
|
}
|
||||||
_push_new_frame(co, _module, std::move(locals), fn._closure);
|
_push_new_frame(co, _module, std::move(locals), fn._closure);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -913,14 +914,14 @@ inline void VM::_error(Exception e){
|
|||||||
e.is_re = false;
|
e.is_re = false;
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
Frame* frame = &callstack.top();
|
s_data.push(VAR(e));
|
||||||
frame->_s.push(VAR(e));
|
|
||||||
_raise();
|
_raise();
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
|
for(PyObject* obj: vm->s_data) OBJ_MARK(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
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