This commit is contained in:
BLUELOVETH 2023-04-16 17:23:49 +00:00
parent 8aa6893e29
commit adc2f2cc3f
5 changed files with 80 additions and 91 deletions

View File

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

View File

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

View File

@ -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]; } ValueStack(): _sp(_begin) {}
PyObject* peek(int n) const { return (*this)[size()-n]; }
void push(PyObject* v){ push_back(v); } PyObject*& top(){ return _sp[-1]; }
void pop(){ pop_back(); } PyObject* top() const { return _sp[-1]; }
PyObject* popx(){ return popx_back(); } PyObject*& second(){ return _sp[-2]; }
ArgsView view(int n){ return ArgsView(end()-n, end()); } PyObject* second() const { return _sp[-2]; }
void shrink(int n){ resize(size() - n); } PyObject*& peek(int n){ return _sp[-n]; }
PyObject* peek(int n) const { return _sp[-n]; }
void push(PyObject* v){ *_sp++ = v; }
void pop(){ --_sp; }
PyObject* popx(){ return *--_sp; }
ArgsView view(int n){ return ArgsView(_sp-n, _sp); }
void shrink(int n){ _sp -= n; }
// int size() const { return _sp - _begin; }
// bool empty() const { return _sp == _begin; }
PyObject** begin() { return _begin; }
PyObject** end() { return _sp; }
void reset(PyObject** sp) { _sp = sp; }
// void resize(int n) { _sp = _begin + n; }
bool is_overflow() const { return _sp >= _begin + MAX_SIZE; }
ValueStack(const ValueStack&) = delete;
ValueStack(ValueStack&&) = delete;
ValueStack& operator=(const ValueStack&) = delete;
ValueStack& operator=(ValueStack&&) = delete;
}; };
// struct ValueStack {
// 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*& second(){ return _sp[-2]; }
// PyObject* second() const { return _sp[-2]; }
// PyObject*& peek(int n){ return _sp[-n]; }
// PyObject* peek(int n) const { return _sp[-n]; }
// void push(PyObject* v){ *_sp++ = v; }
// void pop(){ --_sp; }
// PyObject* popx(){ return *--_sp; }
// ArgsView view(int n){ return ArgsView(_sp-n, _sp); }
// void shrink(int n){ _sp -= n; }
// int size() const { return _sp - _begin; }
// bool empty() const { return _sp == _begin; }
// PyObject** begin() const { return _begin; }
// PyObject** end() const { return _sp; }
// void resize(int n) { _sp = _begin + n; }
// ValueStack(ValueStack&& other) noexcept{
// _begin = other._begin;
// _sp = other._sp;
// other._begin = nullptr;
// }
// 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();

View File

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

View File

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