This commit is contained in:
blueloveTH 2023-04-17 17:19:03 +08:00
parent 51cf6d42e8
commit bccabaa872
8 changed files with 59 additions and 60 deletions

View File

@ -145,7 +145,9 @@ __NEXT_STEP:;
PUSH(self);
} DISPATCH();
TARGET(LOAD_SUBSCR) {
TOP() = fast_call_method(SECOND(), __getitem__, 2);
PyObject* b = POPX();
PyObject* a = TOP();
TOP() = call_method(a, __getitem__, b);
} DISPATCH();
TARGET(STORE_FAST)
frame->_locals[byte.arg] = POPX();
@ -171,12 +173,13 @@ __NEXT_STEP:;
setattr(a, name, val);
STACK_SHRINK(2);
} DISPATCH();
TARGET(STORE_SUBSCR)
// val a b -> a b val
std::swap(SECOND(), THIRD());
std::swap(TOP(), SECOND());
fast_call_method(THIRD(), __setitem__, 3);
DISPATCH();
TARGET(STORE_SUBSCR) {
// val a b
PyObject* b = POPX();
PyObject* a = POPX();
PyObject* val = POPX();
call_method(a, __setitem__, b, val);
} DISPATCH();
TARGET(DELETE_FAST) {
PyObject* val = frame->_locals[byte.arg];
if(val == nullptr) vm->NameError(co->varnames[byte.arg]);
@ -207,9 +210,11 @@ __NEXT_STEP:;
if(!a->attr().contains(name)) AttributeError(a, name);
a->attr().erase(name);
} DISPATCH();
TARGET(DELETE_SUBSCR)
fast_call_method(SECOND(), __delitem__, 2);
DISPATCH();
TARGET(DELETE_SUBSCR) {
PyObject* b = POPX();
PyObject* a = POPX();
call_method(a, __delitem__, b);
} DISPATCH();
/*****************************************/
TARGET(BUILD_LIST) {
PyObject* obj = VAR(STACK_VIEW(byte.arg).to_list());
@ -251,9 +256,11 @@ __NEXT_STEP:;
PUSH(VAR(ss.str()));
} DISPATCH();
/*****************************************/
TARGET(BINARY_OP)
TOP() = fast_call_method(SECOND(), BINARY_SPECIAL_METHODS[byte.arg], 2);
DISPATCH();
TARGET(BINARY_OP) {
PyObject* b = POPX();
PyObject* a = TOP();
TOP() = call_method(a, BINARY_SPECIAL_METHODS[byte.arg], b);
} DISPATCH();
#define INT_BINARY_OP(op, func) \
if(is_both_int(TOP(), SECOND())){ \
@ -262,7 +269,9 @@ __NEXT_STEP:;
POP(); \
TOP() = VAR(a op b); \
}else{ \
TOP() = fast_call_method(SECOND(), func, 2); \
PyObject* b = POPX(); \
PyObject* a = TOP(); \
TOP() = call_method(a, func, b); \
}
TARGET(BINARY_ADD)
@ -323,8 +332,7 @@ __NEXT_STEP:;
} DISPATCH();
TARGET(CONTAINS_OP) {
// a in b -> b __contains__ a
std::swap(TOP(), SECOND());
PyObject* ret = fast_call_method(SECOND(), __contains__, 2);
PyObject* ret = call_method(TOP(), __contains__, SECOND());
bool ret_c = CAST(bool, ret);
if(byte.arg == 1) ret_c = !ret_c;
TOP() = VAR(ret_c);
@ -357,6 +365,9 @@ __NEXT_STEP:;
frame->jump_abs_break(index);
} DISPATCH();
/*****************************************/
TARGET(BEGIN_CALL)
PUSH(_py_begin_call);
DISPATCH();
TARGET(CALL) {
int ARGC = byte.arg & 0xFFFF;
int KWARGC = (byte.arg >> 16) & 0xFFFF;
@ -406,9 +417,6 @@ __NEXT_STEP:;
TARGET(UNARY_NOT)
TOP() = VAR(!asBool(TOP()));
DISPATCH();
TARGET(UNARY_STAR)
TOP() = VAR(StarWrapper(TOP()));
DISPATCH();
/*****************************************/
TARGET(GET_ITER)
TOP() = asIter(TOP());
@ -479,7 +487,18 @@ __NEXT_STEP:;
}else{
if(iter->next() != nullptr) ValueError("too many values to unpack");
}
}; DISPATCH();
} DISPATCH();
TARGET(UNPACK_UNLIMITED) {
auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!!
PyObject* obj = asIter(POPX());
BaseIter* iter = PyIter_AS_C(obj);
obj = iter->next();
while(obj != nullptr){
PUSH(obj);
// if(s_data.is_overflow()) StackOverflowError();
obj = iter->next();
}
} DISPATCH();
/*****************************************/
TARGET(BEGIN_CLASS) {
StrName name(byte.arg);

View File

@ -189,7 +189,7 @@ struct StarredExpr: Expr{
void emit(CodeEmitContext* ctx) override {
child->emit(ctx);
ctx->emit(OP_UNARY_STAR, BC_NOARG, line);
ctx->emit(OP_UNPACK_UNLIMITED, BC_NOARG, line);
}
bool emit_store(CodeEmitContext* ctx) override {
@ -627,6 +627,7 @@ struct CallExpr: Expr{
void emit(CodeEmitContext* ctx) override {
VM* vm = ctx->vm;
if(need_unpack()) ctx->emit(OP_BEGIN_CALL, BC_NOARG, line);
// if callable is a AttrExpr, we should try to use `fast_call` instead of use `boundmethod` proxy
if(callable->is_attrib()){
auto p = static_cast<AttribExpr*>(callable.get());
@ -645,11 +646,8 @@ struct CallExpr: Expr{
}
int KWARGC = (int)kwargs.size();
int ARGC = (int)args.size();
if(KWARGC > 0){
ctx->emit(need_unpack() ? OP_CALL_KWARGS_UNPACK : OP_CALL_KWARGS, (KWARGC<<16)|ARGC, line);
}else{
ctx->emit(need_unpack() ? OP_CALL_UNPACK : OP_CALL, ARGC, line);
}
if(need_unpack()) ARGC = 0xFFFF;
ctx->emit(OP_CALL, (KWARGC<<16)|ARGC, line);
}
};

View File

@ -212,6 +212,8 @@ struct Frame {
int stack_size() const { return _s->_sp - _sp_base; }
ArgsView stack_view() const { return ArgsView(_sp_base, _s->_sp); }
std::string stack_info(){
std::stringstream ss;
ss << this << ": [";

View File

@ -141,10 +141,6 @@ template<> inline void gc_mark<BoundMethod>(BoundMethod& t){
OBJ_MARK(t.method);
}
template<> inline void gc_mark<StarWrapper>(StarWrapper& t){
OBJ_MARK(t.obj);
}
template<> inline void gc_mark<Super>(Super& t){
OBJ_MARK(t.first);
}

View File

@ -63,10 +63,15 @@ public:
inline PyObject* Generator::next(){
if(state == 2) return nullptr;
vm->_push_new_frame(std::move(frame));
// restore the context
for(PyObject* obj: s_data) frame._s->push(obj);
s_data.clear();
vm->callstack.push(std::move(frame));
PyObject* ret = vm->_run_top_frame();
if(ret == vm->_py_op_yield){
// backup the context
frame = std::move(vm->callstack.top());
for(PyObject* obj: frame.stack_view()) s_data.push_back(obj);
vm->callstack.pop();
state = 1;
return frame._s->popx();

View File

@ -50,11 +50,6 @@ struct Range {
i64 step = 1;
};
struct StarWrapper {
PyObject* obj;
StarWrapper(PyObject* obj): obj(obj) {}
};
using Super = std::pair<PyObject*, Type>;
// TODO: re-examine the design of Slice

View File

@ -76,6 +76,7 @@ OPCODE(LOOP_CONTINUE)
OPCODE(LOOP_BREAK)
OPCODE(GOTO)
/**************************/
OPCODE(BEGIN_CALL)
OPCODE(CALL)
OPCODE(RETURN_VALUE)
OPCODE(YIELD_VALUE)
@ -86,7 +87,6 @@ OPCODE(SET_ADD)
/**************************/
OPCODE(UNARY_NEGATIVE)
OPCODE(UNARY_NOT)
OPCODE(UNARY_STAR)
/**************************/
OPCODE(GET_ITER)
OPCODE(FOR_ITER)
@ -96,6 +96,7 @@ OPCODE(IMPORT_STAR)
/**************************/
OPCODE(UNPACK_SEQUENCE)
OPCODE(UNPACK_EX)
OPCODE(UNPACK_UNLIMITED)
/**************************/
OPCODE(BEGIN_CLASS)
OPCODE(END_CLASS)

View File

@ -48,11 +48,10 @@ Str _read_file_cwd(const Str& name, bool* ok);
class Generator final: public BaseIter {
Frame frame;
int state; // 0,1,2
int state; // 0,1,2
List s_data; // backup
public:
template<typename... Args>
Generator(VM* vm, Frame&& frame)
: BaseIter(vm), frame(std::move(frame)), state(0) {}
Generator(VM* vm, Frame&& frame): BaseIter(vm), frame(std::move(frame)), state(0) {}
PyObject* next() override;
void _gc_mark() const override;
@ -103,7 +102,7 @@ public:
Type tp_list, tp_tuple;
Type tp_function, tp_native_function, tp_iterator, tp_bound_method;
Type tp_slice, tp_range, tp_module;
Type tp_super, tp_exception, tp_star_wrapper;
Type tp_super, tp_exception;
VM(bool use_stdio) : heap(this){
this->vm = this;
@ -167,20 +166,6 @@ public:
return false;
}
PyObject* fast_call_method(PyObject* obj, StrName name, int ARGC){
PyObject* callable = find_name_in_mro(_t(obj), name);
if(callable == nullptr) AttributeError(obj, name);
// [a, b]
// [......., a, b]
// [unbound, a, b]
// ^^^^^^^
s_data._sp++;
PyObject** t = s_data._sp;
for(; t>s_data._sp-ARGC; t--) *t = t[-1];
*t = obj;
return _vectorcall(ARGC-1);
}
PyObject* exec(Str source, Str filename, CompileMode mode, PyObject* _module=nullptr){
if(_module == nullptr) _module = _main;
try {
@ -333,6 +318,7 @@ public:
}
void RecursionError() { _error("RecursionError", "maximum recursion depth exceeded"); }
void StackOverflowError() { _error("StackOverflowError", ""); }
void IOError(const Str& msg) { _error("IOError", msg); }
void NotImplementedError(){ _error("NotImplementedError", ""); }
void TypeError(const Str& msg){ _error("TypeError", msg); }
@ -417,7 +403,6 @@ DEF_NATIVE_2(BoundMethod, tp_bound_method)
DEF_NATIVE_2(Range, tp_range)
DEF_NATIVE_2(Slice, tp_slice)
DEF_NATIVE_2(Exception, tp_exception)
DEF_NATIVE_2(StarWrapper, tp_star_wrapper)
#define PY_CAST_INT(T) \
template<> inline T py_cast<T>(VM* vm, PyObject* obj){ \
@ -586,8 +571,7 @@ inline i64 VM::hash(PyObject* obj){
}
inline PyObject* VM::asRepr(PyObject* obj){
// TODO: fastcall does not take care of super() proxy!
return fast_call_method(obj, __repr__, 0);
return call_method(obj, __repr__);
}
inline PyObject* VM::new_module(StrName name) {
@ -682,7 +666,6 @@ inline void VM::init_builtin_types(){
tp_slice = _new_type_object("slice");
tp_range = _new_type_object("range");
tp_module = _new_type_object("module");
tp_star_wrapper = _new_type_object("_star_wrapper");
tp_function = _new_type_object("function");
tp_native_function = _new_type_object("native_function");
tp_iterator = _new_type_object("iterator");