some refactor

This commit is contained in:
blueloveTH 2024-04-27 17:01:59 +08:00
parent a99b271a4e
commit b703abbbb2
6 changed files with 79 additions and 61 deletions

View File

@ -125,7 +125,6 @@ struct Type {
struct PyObject; struct PyObject;
#define PK_BITS(p) (reinterpret_cast<i64>(p)) #define PK_BITS(p) (reinterpret_cast<i64>(p))
#define PK_SMALL_INT(val) (reinterpret_cast<PyObject*>(val << 2 | 0b10))
// is_pod<> for c++17 and c++20 // is_pod<> for c++17 and c++20
template<typename T> template<typename T>

View File

@ -14,23 +14,7 @@ OPCODE(LOAD_NONE)
OPCODE(LOAD_TRUE) OPCODE(LOAD_TRUE)
OPCODE(LOAD_FALSE) OPCODE(LOAD_FALSE)
/**************************/ /**************************/
OPCODE(LOAD_INT_0) OPCODE(LOAD_SMALL_INT)
OPCODE(LOAD_INT_1)
OPCODE(LOAD_INT_2)
OPCODE(LOAD_INT_3)
OPCODE(LOAD_INT_4)
OPCODE(LOAD_INT_5)
OPCODE(LOAD_INT_6)
OPCODE(LOAD_INT_7)
OPCODE(LOAD_INT_8)
OPCODE(LOAD_INT_9)
OPCODE(LOAD_INT_10)
OPCODE(LOAD_INT_11)
OPCODE(LOAD_INT_12)
OPCODE(LOAD_INT_13)
OPCODE(LOAD_INT_14)
OPCODE(LOAD_INT_15)
OPCODE(LOAD_INT_16)
/**************************/ /**************************/
OPCODE(LOAD_ELLIPSIS) OPCODE(LOAD_ELLIPSIS)
OPCODE(LOAD_FUNCTION) OPCODE(LOAD_FUNCTION)
@ -44,12 +28,14 @@ OPCODE(LOAD_ATTR)
OPCODE(LOAD_CLASS_GLOBAL) OPCODE(LOAD_CLASS_GLOBAL)
OPCODE(LOAD_METHOD) OPCODE(LOAD_METHOD)
OPCODE(LOAD_SUBSCR) OPCODE(LOAD_SUBSCR)
OPCODE(LOAD_SUBSCR_FAST)
OPCODE(STORE_FAST) OPCODE(STORE_FAST)
OPCODE(STORE_NAME) OPCODE(STORE_NAME)
OPCODE(STORE_GLOBAL) OPCODE(STORE_GLOBAL)
OPCODE(STORE_ATTR) OPCODE(STORE_ATTR)
OPCODE(STORE_SUBSCR) OPCODE(STORE_SUBSCR)
OPCODE(STORE_SUBSCR_FAST)
OPCODE(DELETE_FAST) OPCODE(DELETE_FAST)
OPCODE(DELETE_NAME) OPCODE(DELETE_NAME)

View File

@ -10,7 +10,7 @@ namespace pkpy{
#define PREDICT_INT_DIV_OP(op) \ #define PREDICT_INT_DIV_OP(op) \
if(is_small_int(_0) && is_small_int(_1)){ \ if(is_small_int(_0) && is_small_int(_1)){ \
if(_1 == PK_SMALL_INT(0)) ZeroDivisionError(); \ if(_1 == (PyObject*)0b10) ZeroDivisionError(); \
TOP() = VAR((PK_BITS(_0)>>2) op (PK_BITS(_1)>>2)); \ TOP() = VAR((PK_BITS(_0)>>2) op (PK_BITS(_1)>>2)); \
DISPATCH() \ DISPATCH() \
} }
@ -112,30 +112,13 @@ __NEXT_STEP:;
} DISPATCH(); } DISPATCH();
/*****************************************/ /*****************************************/
TARGET(LOAD_CONST) TARGET(LOAD_CONST)
if(heap._should_auto_collect()) heap._auto_collect();
PUSH(co->consts[byte.arg]); PUSH(co->consts[byte.arg]);
DISPATCH(); DISPATCH();
TARGET(LOAD_NONE) PUSH(None); DISPATCH(); TARGET(LOAD_NONE) PUSH(None); DISPATCH();
TARGET(LOAD_TRUE) PUSH(True); DISPATCH(); TARGET(LOAD_TRUE) PUSH(True); DISPATCH();
TARGET(LOAD_FALSE) PUSH(False); DISPATCH(); TARGET(LOAD_FALSE) PUSH(False); DISPATCH();
/*****************************************/ /*****************************************/
TARGET(LOAD_INT_0) PUSH(PK_SMALL_INT(0)); DISPATCH(); TARGET(LOAD_SMALL_INT) PUSH((PyObject*)(uintptr_t)byte.arg); DISPATCH();
TARGET(LOAD_INT_1) PUSH(PK_SMALL_INT(1)); DISPATCH();
TARGET(LOAD_INT_2) PUSH(PK_SMALL_INT(2)); DISPATCH();
TARGET(LOAD_INT_3) PUSH(PK_SMALL_INT(3)); DISPATCH();
TARGET(LOAD_INT_4) PUSH(PK_SMALL_INT(4)); DISPATCH();
TARGET(LOAD_INT_5) PUSH(PK_SMALL_INT(5)); DISPATCH();
TARGET(LOAD_INT_6) PUSH(PK_SMALL_INT(6)); DISPATCH();
TARGET(LOAD_INT_7) PUSH(PK_SMALL_INT(7)); DISPATCH();
TARGET(LOAD_INT_8) PUSH(PK_SMALL_INT(8)); DISPATCH();
TARGET(LOAD_INT_9) PUSH(PK_SMALL_INT(9)); DISPATCH();
TARGET(LOAD_INT_10) PUSH(PK_SMALL_INT(10)); DISPATCH();
TARGET(LOAD_INT_11) PUSH(PK_SMALL_INT(11)); DISPATCH();
TARGET(LOAD_INT_12) PUSH(PK_SMALL_INT(12)); DISPATCH();
TARGET(LOAD_INT_13) PUSH(PK_SMALL_INT(13)); DISPATCH();
TARGET(LOAD_INT_14) PUSH(PK_SMALL_INT(14)); DISPATCH();
TARGET(LOAD_INT_15) PUSH(PK_SMALL_INT(15)); DISPATCH();
TARGET(LOAD_INT_16) PUSH(PK_SMALL_INT(16)); DISPATCH();
/*****************************************/ /*****************************************/
TARGET(LOAD_ELLIPSIS) PUSH(Ellipsis); DISPATCH(); TARGET(LOAD_ELLIPSIS) PUSH(Ellipsis); DISPATCH();
TARGET(LOAD_FUNCTION) { TARGET(LOAD_FUNCTION) {
@ -153,7 +136,6 @@ __NEXT_STEP:;
TARGET(LOAD_NULL) PUSH(PY_NULL); DISPATCH(); TARGET(LOAD_NULL) PUSH(PY_NULL); DISPATCH();
/*****************************************/ /*****************************************/
TARGET(LOAD_FAST) { TARGET(LOAD_FAST) {
if(heap._should_auto_collect()) heap._auto_collect();
PyObject* _0 = frame->_locals[byte.arg]; PyObject* _0 = frame->_locals[byte.arg];
if(_0 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]); if(_0 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]);
PUSH(_0); PUSH(_0);
@ -175,7 +157,6 @@ __NEXT_STEP:;
vm->NameError(_name); vm->NameError(_name);
} DISPATCH(); } DISPATCH();
TARGET(LOAD_NONLOCAL) { TARGET(LOAD_NONLOCAL) {
if(heap._should_auto_collect()) heap._auto_collect();
StrName _name(byte.arg); StrName _name(byte.arg);
PyObject* _0 = frame->f_closure_try_get(_name); PyObject* _0 = frame->f_closure_try_get(_name);
if(_0 != nullptr) { PUSH(_0); DISPATCH(); } if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
@ -186,7 +167,6 @@ __NEXT_STEP:;
vm->NameError(_name); vm->NameError(_name);
} DISPATCH(); } DISPATCH();
TARGET(LOAD_GLOBAL){ TARGET(LOAD_GLOBAL){
if(heap._should_auto_collect()) heap._auto_collect();
StrName _name(byte.arg); StrName _name(byte.arg);
PyObject* _0 = frame->f_globals().try_get_likely_found(_name); PyObject* _0 = frame->f_globals().try_get_likely_found(_name);
if(_0 != nullptr) { PUSH(_0); DISPATCH(); } if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
@ -224,6 +204,17 @@ __NEXT_STEP:;
TOP() = call_method(_0, __getitem__, _1); TOP() = call_method(_0, __getitem__, _1);
} }
} DISPATCH(); } DISPATCH();
TARGET(LOAD_SUBSCR_FAST){
PyObject* _1 = frame->_locals[byte.arg];
if(_1 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]);
PyObject* _0 = TOP(); // a
auto _ti = _inst_type_info(_0);
if(_ti->m__getitem__){
TOP() = _ti->m__getitem__(this, _0, _1);
}else{
TOP() = call_method(_0, __getitem__, _1);
}
} DISPATCH();
TARGET(STORE_FAST) TARGET(STORE_FAST)
frame->_locals[byte.arg] = POPX(); frame->_locals[byte.arg] = POPX();
DISPATCH(); DISPATCH();
@ -258,6 +249,18 @@ __NEXT_STEP:;
call_method(_1, __setitem__, _2, _0); call_method(_1, __setitem__, _2, _0);
} }
}DISPATCH(); }DISPATCH();
TARGET(STORE_SUBSCR_FAST){
PyObject* _2 = frame->_locals[byte.arg]; // b
if(_2 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]);
PyObject* _1 = POPX(); // a
PyObject* _0 = POPX(); // val
auto _ti = _inst_type_info(_1);
if(_ti->m__setitem__){
_ti->m__setitem__(this, _1, _2, _0);
}else{
call_method(_1, __setitem__, _2, _0);
}
}DISPATCH();
TARGET(DELETE_FAST){ TARGET(DELETE_FAST){
PyObject* _0 = frame->_locals[byte.arg]; PyObject* _0 = frame->_locals[byte.arg];
if(_0 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]); if(_0 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]);
@ -620,6 +623,7 @@ __NEXT_STEP:;
TOP() = py_repr(TOP()); TOP() = py_repr(TOP());
DISPATCH(); DISPATCH();
TARGET(CALL){ TARGET(CALL){
if(heap._should_auto_collect()) heap._auto_collect();
PyObject* _0 = vectorcall( PyObject* _0 = vectorcall(
byte.arg & 0xFF, // ARGC byte.arg & 0xFF, // ARGC
(byte.arg>>8) & 0xFF, // KWARGC (byte.arg>>8) & 0xFF, // KWARGC
@ -629,6 +633,7 @@ __NEXT_STEP:;
PUSH(_0); PUSH(_0);
} DISPATCH(); } DISPATCH();
TARGET(CALL_TP){ TARGET(CALL_TP){
if(heap._should_auto_collect()) heap._auto_collect();
PyObject* _0; PyObject* _0;
PyObject* _1; PyObject* _1;
PyObject* _2; PyObject* _2;
@ -772,14 +777,25 @@ __NEXT_STEP:;
} DISPATCH(); } DISPATCH();
/*****************************************/ /*****************************************/
TARGET(UNPACK_SEQUENCE){ TARGET(UNPACK_SEQUENCE){
auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!! PyObject* _0 = POPX();
PyObject* _0 = py_iter(POPX()); if(is_type(_0, VM::tp_tuple)){
for(int i=0; i<byte.arg; i++){ // fast path for tuple
PyObject* _1 = py_next(_0); Tuple& tuple = PK_OBJ_GET(Tuple, _0);
if(_1 == StopIteration) ValueError("not enough values to unpack"); if(tuple.size() == byte.arg){
PUSH(_1); for(PyObject* obj: tuple) PUSH(obj);
}else{
ValueError(_S("expected ", (int)byte.arg, " values to unpack, got ", (int)tuple.size()));
}
}else{
auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!!
_0 = py_iter(_0);
for(int i=0; i<byte.arg; i++){
PyObject* _1 = py_next(_0);
if(_1 == StopIteration) ValueError("not enough values to unpack");
PUSH(_1);
}
if(py_next(_0) != StopIteration) ValueError("too many values to unpack");
} }
if(py_next(_0) != StopIteration) ValueError("too many values to unpack");
} DISPATCH(); } DISPATCH();
TARGET(UNPACK_EX) { TARGET(UNPACK_EX) {
auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!! auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!!

View File

@ -86,9 +86,9 @@ namespace pkpy{
} }
int CodeEmitContext::emit_int(i64 value, int line){ int CodeEmitContext::emit_int(i64 value, int line){
if(value >= 0 && value <= 16){ if(value >= 0 && value < 1024){
uint8_t op = OP_LOAD_INT_0 + (uint8_t)value; value = (value << 2) | 0b10;
return emit_((Opcode)op, BC_NOARG, line); return emit_(OP_LOAD_SMALL_INT, (uint16_t)value, line);
}else{ }else{
return emit_(OP_LOAD_CONST, add_const(VAR(value)), line); return emit_(OP_LOAD_CONST, add_const(VAR(value)), line);
} }
@ -359,8 +359,7 @@ namespace pkpy{
Bytecode& prev = ctx->co->codes.back(); Bytecode& prev = ctx->co->codes.back();
if(prev.op == OP_BUILD_TUPLE && prev.arg == items.size()){ if(prev.op == OP_BUILD_TUPLE && prev.arg == items.size()){
// build tuple and unpack it is meaningless // build tuple and unpack it is meaningless
prev.op = OP_NO_OP; ctx->revert_last_emit_();
prev.arg = BC_NOARG;
}else{ }else{
ctx->emit_(OP_UNPACK_SEQUENCE, items.size(), line); ctx->emit_(OP_UNPACK_SEQUENCE, items.size(), line);
} }
@ -537,7 +536,26 @@ namespace pkpy{
void SubscrExpr::emit_(CodeEmitContext* ctx){ void SubscrExpr::emit_(CodeEmitContext* ctx){
a->emit_(ctx); a->emit_(ctx);
b->emit_(ctx); b->emit_(ctx);
ctx->emit_(OP_LOAD_SUBSCR, BC_NOARG, line); if(b->is_name() && ctx->co->codes.back().op == OP_LOAD_FAST){
auto arg = ctx->co->codes.back().arg;
ctx->revert_last_emit_();
ctx->emit_(OP_LOAD_SUBSCR_FAST, arg, line);
}else{
ctx->emit_(OP_LOAD_SUBSCR, BC_NOARG, line);
}
}
bool SubscrExpr::emit_store(CodeEmitContext* ctx){
a->emit_(ctx);
b->emit_(ctx);
if(b->is_name() && ctx->co->codes.back().op == OP_LOAD_FAST){
auto arg = ctx->co->codes.back().arg;
ctx->revert_last_emit_();
ctx->emit_(OP_STORE_SUBSCR_FAST, arg, line);
}else{
ctx->emit_(OP_STORE_SUBSCR, BC_NOARG, line);
}
return true;
} }
bool SubscrExpr::emit_del(CodeEmitContext* ctx){ bool SubscrExpr::emit_del(CodeEmitContext* ctx){
@ -547,13 +565,6 @@ namespace pkpy{
return true; return true;
} }
bool SubscrExpr::emit_store(CodeEmitContext* ctx){
a->emit_(ctx);
b->emit_(ctx);
ctx->emit_(OP_STORE_SUBSCR, BC_NOARG, line);
return true;
}
void AttribExpr::emit_(CodeEmitContext* ctx){ void AttribExpr::emit_(CodeEmitContext* ctx){
a->emit_(ctx); a->emit_(ctx);
ctx->emit_(OP_LOAD_ATTR, b.index, line); ctx->emit_(OP_LOAD_ATTR, b.index, line);

View File

@ -577,12 +577,15 @@ static std::string _opcode_argstr(VM* vm, Bytecode byte, const CodeObject* co){
case OP_DELETE_GLOBAL: case OP_INC_GLOBAL: case OP_DEC_GLOBAL: case OP_STORE_CLASS_ATTR: case OP_FOR_ITER_STORE_GLOBAL: case OP_DELETE_GLOBAL: case OP_INC_GLOBAL: case OP_DEC_GLOBAL: case OP_STORE_CLASS_ATTR: case OP_FOR_ITER_STORE_GLOBAL:
argStr += _S(" (", StrName(byte.arg).sv(), ")").sv(); argStr += _S(" (", StrName(byte.arg).sv(), ")").sv();
break; break;
case OP_LOAD_FAST: case OP_STORE_FAST: case OP_DELETE_FAST: case OP_INC_FAST: case OP_DEC_FAST: case OP_FOR_ITER_STORE_FAST: case OP_LOAD_FAST: case OP_STORE_FAST: case OP_DELETE_FAST: case OP_INC_FAST: case OP_DEC_FAST:
case OP_FOR_ITER_STORE_FAST: case OP_LOAD_SUBSCR_FAST: case OP_STORE_SUBSCR_FAST:
argStr += _S(" (", co->varnames[byte.arg].sv(), ")").sv(); argStr += _S(" (", co->varnames[byte.arg].sv(), ")").sv();
break; break;
case OP_LOAD_FUNCTION: case OP_LOAD_FUNCTION:
argStr += _S(" (", co->func_decls[byte.arg]->code->name, ")").sv(); argStr += _S(" (", co->func_decls[byte.arg]->code->name, ")").sv();
break; break;
case OP_LOAD_SMALL_INT:
argStr += _S(" (", (int)(byte.arg >> 2), ")").sv();
} }
return argStr; return argStr;
} }

View File

@ -129,3 +129,6 @@ try:
exit(1) exit(1)
except ValueError: except ValueError:
pass pass
a, b = [1, 2]
assert a == 1 and b == 2