diff --git a/include/pocketpy/opcodes.h b/include/pocketpy/opcodes.h index 374c6e7e..6a13a478 100644 --- a/include/pocketpy/opcodes.h +++ b/include/pocketpy/opcodes.h @@ -29,6 +29,7 @@ OPCODE(LOAD_CLASS_GLOBAL) OPCODE(LOAD_METHOD) OPCODE(LOAD_SUBSCR) OPCODE(LOAD_SUBSCR_FAST) +OPCODE(LOAD_SUBSCR_SMALL_INT) OPCODE(STORE_FAST) OPCODE(STORE_NAME) diff --git a/src/ceval.cpp b/src/ceval.cpp index dd9b3ce0..8eb82e00 100644 --- a/src/ceval.cpp +++ b/src/ceval.cpp @@ -215,6 +215,16 @@ __NEXT_STEP:; TOP() = call_method(_0, __getitem__, _1); } } DISPATCH(); + TARGET(LOAD_SUBSCR_SMALL_INT){ + PyObject* _1 = (PyObject*)(uintptr_t)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(); diff --git a/src/expr.cpp b/src/expr.cpp index aa98d958..d023660e 100644 --- a/src/expr.cpp +++ b/src/expr.cpp @@ -9,6 +9,10 @@ namespace pkpy{ return true; } + inline bool is_small_int(i64 value){ + return value >= 0 && value < 1024; + } + int CodeEmitContext::get_loop() const { int index = curr_block_i; while(index >= 0){ @@ -86,7 +90,7 @@ namespace pkpy{ } int CodeEmitContext::emit_int(i64 value, int line){ - if(value >= 0 && value < 1024){ + if(is_small_int(value)){ value = (value << 2) | 0b10; return emit_(OP_LOAD_SMALL_INT, (uint16_t)value, line); }else{ @@ -536,10 +540,13 @@ namespace pkpy{ void SubscrExpr::emit_(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; + Bytecode last_bc = ctx->co->codes.back(); + if(b->is_name() && last_bc.op == OP_LOAD_FAST){ ctx->revert_last_emit_(); - ctx->emit_(OP_LOAD_SUBSCR_FAST, arg, line); + ctx->emit_(OP_LOAD_SUBSCR_FAST, last_bc.arg, line); + }else if(b->is_literal() && last_bc.op == OP_LOAD_SMALL_INT){ + ctx->revert_last_emit_(); + ctx->emit_(OP_LOAD_SUBSCR_SMALL_INT, last_bc.arg, line); }else{ ctx->emit_(OP_LOAD_SUBSCR, BC_NOARG, line); } @@ -548,10 +555,10 @@ namespace pkpy{ 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; + Bytecode last_bc = ctx->co->codes.back(); + if(b->is_name() && last_bc.op == OP_LOAD_FAST){ ctx->revert_last_emit_(); - ctx->emit_(OP_STORE_SUBSCR_FAST, arg, line); + ctx->emit_(OP_STORE_SUBSCR_FAST, last_bc.arg, line); }else{ ctx->emit_(OP_STORE_SUBSCR, BC_NOARG, line); } diff --git a/src/vm.cpp b/src/vm.cpp index b84b4c3f..325b9107 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -584,7 +584,7 @@ static std::string _opcode_argstr(VM* vm, Bytecode byte, const CodeObject* co){ case OP_LOAD_FUNCTION: argStr += _S(" (", co->func_decls[byte.arg]->code->name, ")").sv(); break; - case OP_LOAD_SMALL_INT: + case OP_LOAD_SMALL_INT: case OP_LOAD_SUBSCR_SMALL_INT: argStr += _S(" (", (int)(byte.arg >> 2), ")").sv(); } return argStr;