From b703abbbb28a6fc6f87cef5321e6f69654ee449f Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sat, 27 Apr 2024 17:01:59 +0800 Subject: [PATCH] some refactor --- include/pocketpy/common.h | 1 - include/pocketpy/opcodes.h | 20 ++--------- src/ceval.cpp | 74 +++++++++++++++++++++++--------------- src/expr.cpp | 37 ++++++++++++------- src/vm.cpp | 5 ++- tests/05_list.py | 3 ++ 6 files changed, 79 insertions(+), 61 deletions(-) diff --git a/include/pocketpy/common.h b/include/pocketpy/common.h index 7f661317..5d2431f2 100644 --- a/include/pocketpy/common.h +++ b/include/pocketpy/common.h @@ -125,7 +125,6 @@ struct Type { struct PyObject; #define PK_BITS(p) (reinterpret_cast(p)) -#define PK_SMALL_INT(val) (reinterpret_cast(val << 2 | 0b10)) // is_pod<> for c++17 and c++20 template diff --git a/include/pocketpy/opcodes.h b/include/pocketpy/opcodes.h index 82368558..374c6e7e 100644 --- a/include/pocketpy/opcodes.h +++ b/include/pocketpy/opcodes.h @@ -14,23 +14,7 @@ OPCODE(LOAD_NONE) OPCODE(LOAD_TRUE) OPCODE(LOAD_FALSE) /**************************/ -OPCODE(LOAD_INT_0) -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_SMALL_INT) /**************************/ OPCODE(LOAD_ELLIPSIS) OPCODE(LOAD_FUNCTION) @@ -44,12 +28,14 @@ OPCODE(LOAD_ATTR) OPCODE(LOAD_CLASS_GLOBAL) OPCODE(LOAD_METHOD) OPCODE(LOAD_SUBSCR) +OPCODE(LOAD_SUBSCR_FAST) OPCODE(STORE_FAST) OPCODE(STORE_NAME) OPCODE(STORE_GLOBAL) OPCODE(STORE_ATTR) OPCODE(STORE_SUBSCR) +OPCODE(STORE_SUBSCR_FAST) OPCODE(DELETE_FAST) OPCODE(DELETE_NAME) diff --git a/src/ceval.cpp b/src/ceval.cpp index 2a45c169..dd9b3ce0 100644 --- a/src/ceval.cpp +++ b/src/ceval.cpp @@ -10,7 +10,7 @@ namespace pkpy{ #define PREDICT_INT_DIV_OP(op) \ 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)); \ DISPATCH() \ } @@ -112,30 +112,13 @@ __NEXT_STEP:; } DISPATCH(); /*****************************************/ TARGET(LOAD_CONST) - if(heap._should_auto_collect()) heap._auto_collect(); PUSH(co->consts[byte.arg]); DISPATCH(); TARGET(LOAD_NONE) PUSH(None); DISPATCH(); TARGET(LOAD_TRUE) PUSH(True); DISPATCH(); TARGET(LOAD_FALSE) PUSH(False); DISPATCH(); /*****************************************/ - TARGET(LOAD_INT_0) PUSH(PK_SMALL_INT(0)); 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_SMALL_INT) PUSH((PyObject*)(uintptr_t)byte.arg); DISPATCH(); /*****************************************/ TARGET(LOAD_ELLIPSIS) PUSH(Ellipsis); DISPATCH(); TARGET(LOAD_FUNCTION) { @@ -153,7 +136,6 @@ __NEXT_STEP:; TARGET(LOAD_NULL) PUSH(PY_NULL); DISPATCH(); /*****************************************/ TARGET(LOAD_FAST) { - if(heap._should_auto_collect()) heap._auto_collect(); PyObject* _0 = frame->_locals[byte.arg]; if(_0 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]); PUSH(_0); @@ -175,7 +157,6 @@ __NEXT_STEP:; vm->NameError(_name); } DISPATCH(); TARGET(LOAD_NONLOCAL) { - if(heap._should_auto_collect()) heap._auto_collect(); StrName _name(byte.arg); PyObject* _0 = frame->f_closure_try_get(_name); if(_0 != nullptr) { PUSH(_0); DISPATCH(); } @@ -186,7 +167,6 @@ __NEXT_STEP:; vm->NameError(_name); } DISPATCH(); TARGET(LOAD_GLOBAL){ - if(heap._should_auto_collect()) heap._auto_collect(); StrName _name(byte.arg); PyObject* _0 = frame->f_globals().try_get_likely_found(_name); if(_0 != nullptr) { PUSH(_0); DISPATCH(); } @@ -224,6 +204,17 @@ __NEXT_STEP:; TOP() = call_method(_0, __getitem__, _1); } } 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) frame->_locals[byte.arg] = POPX(); DISPATCH(); @@ -258,6 +249,18 @@ __NEXT_STEP:; call_method(_1, __setitem__, _2, _0); } }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){ PyObject* _0 = frame->_locals[byte.arg]; if(_0 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]); @@ -620,6 +623,7 @@ __NEXT_STEP:; TOP() = py_repr(TOP()); DISPATCH(); TARGET(CALL){ + if(heap._should_auto_collect()) heap._auto_collect(); PyObject* _0 = vectorcall( byte.arg & 0xFF, // ARGC (byte.arg>>8) & 0xFF, // KWARGC @@ -629,6 +633,7 @@ __NEXT_STEP:; PUSH(_0); } DISPATCH(); TARGET(CALL_TP){ + if(heap._should_auto_collect()) heap._auto_collect(); PyObject* _0; PyObject* _1; PyObject* _2; @@ -772,14 +777,25 @@ __NEXT_STEP:; } DISPATCH(); /*****************************************/ TARGET(UNPACK_SEQUENCE){ - auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!! - PyObject* _0 = py_iter(POPX()); - for(int i=0; i= 0 && value <= 16){ - uint8_t op = OP_LOAD_INT_0 + (uint8_t)value; - return emit_((Opcode)op, BC_NOARG, line); + if(value >= 0 && value < 1024){ + value = (value << 2) | 0b10; + return emit_(OP_LOAD_SMALL_INT, (uint16_t)value, line); }else{ return emit_(OP_LOAD_CONST, add_const(VAR(value)), line); } @@ -359,8 +359,7 @@ namespace pkpy{ Bytecode& prev = ctx->co->codes.back(); if(prev.op == OP_BUILD_TUPLE && prev.arg == items.size()){ // build tuple and unpack it is meaningless - prev.op = OP_NO_OP; - prev.arg = BC_NOARG; + ctx->revert_last_emit_(); }else{ ctx->emit_(OP_UNPACK_SEQUENCE, items.size(), line); } @@ -537,7 +536,26 @@ namespace pkpy{ void SubscrExpr::emit_(CodeEmitContext* ctx){ a->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){ @@ -547,13 +565,6 @@ namespace pkpy{ 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){ a->emit_(ctx); ctx->emit_(OP_LOAD_ATTR, b.index, line); diff --git a/src/vm.cpp b/src/vm.cpp index 2465dc47..b84b4c3f 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -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: argStr += _S(" (", StrName(byte.arg).sv(), ")").sv(); 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(); break; case OP_LOAD_FUNCTION: argStr += _S(" (", co->func_decls[byte.arg]->code->name, ")").sv(); break; + case OP_LOAD_SMALL_INT: + argStr += _S(" (", (int)(byte.arg >> 2), ")").sv(); } return argStr; } diff --git a/tests/05_list.py b/tests/05_list.py index c9bdb7ee..0dc3ee89 100644 --- a/tests/05_list.py +++ b/tests/05_list.py @@ -129,3 +129,6 @@ try: exit(1) except ValueError: pass + +a, b = [1, 2] +assert a == 1 and b == 2