From cae01cb5b7f9f1bf922b4ecc5ca8993f15bc06e8 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sat, 18 Feb 2023 21:12:32 +0800 Subject: [PATCH] some optimize --- src/ceval.h | 9 ++++++++- src/compiler.h | 4 ++-- src/opcodes.h | 7 ++++--- src/pocketpy.h | 29 +++++++++++------------------ src/vm.h | 23 +++++++++++++++++++++++ 5 files changed, 48 insertions(+), 24 deletions(-) diff --git a/src/ceval.h b/src/ceval.h index 6b4fd83f..b9b71906 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -42,6 +42,13 @@ PyVar VM::run_frame(Frame* frame){ if(byte.arg == 0) frame->push(PyRef(ref)); else frame->push(ref.get(this, frame)); } break; + case OP_FAST_INDEX: case OP_FAST_INDEX_REF: { + auto& a = frame->co->names[byte.arg & 0xFFFF]; + auto& x = frame->co->names[(byte.arg >> 16) & 0xFFFF]; + auto ref = IndexRef(NameRef(a).get(this, frame), NameRef(x).get(this, frame)); + if(byte.op == OP_FAST_INDEX) frame->push(ref.get(this, frame)); + else frame->push(PyRef(ref)); + } break; case OP_STORE_REF: { PyVar obj = frame->pop_value(this); PyVarRef r = frame->pop(); @@ -205,7 +212,7 @@ PyVar VM::run_frame(Frame* frame){ PyVar obj = call(builtins->attr("set"), pkpy::one_arg(list)); frame->push(obj); } break; - case OP_DUP_TOP: frame->push(frame->top_value(this)); break; + case OP_DUP_TOP_VALUE: frame->push(frame->top_value(this)); break; case OP_CALL: { int ARGC = byte.arg & 0xFFFF; diff --git a/src/compiler.h b/src/compiler.h index 63fbde37..0421e1b1 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -406,7 +406,7 @@ private: EXPR_TUPLE(); emit(OP_STORE_REF); }else{ // a += (expr) -> a = a + (expr) - emit(OP_DUP_TOP); + emit(OP_DUP_TOP_VALUE); EXPR(); switch (op) { case TK("+="): emit(OP_BINARY_OP, 0); break; @@ -732,7 +732,7 @@ __LISTCOMP: Token tkmodule = _compile_import(); consume(TK("import")); do { - emit(OP_DUP_TOP); + emit(OP_DUP_TOP_VALUE); consume(TK("@id")); Token tkname = parser->prev; int index = co()->add_name(tkname.str(), NAME_ATTR); diff --git a/src/opcodes.h b/src/opcodes.h index fb1d891b..b31b98d7 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -2,7 +2,7 @@ OPCODE(NO_OP) OPCODE(POP_TOP) -OPCODE(DUP_TOP) +OPCODE(DUP_TOP_VALUE) OPCODE(CALL) OPCODE(RETURN_VALUE) @@ -69,7 +69,8 @@ OPCODE(TRY_BLOCK_ENTER) OPCODE(TRY_BLOCK_EXIT) OPCODE(YIELD_VALUE) -//OPCODE(FAST_INDEX_0) // a[0] -//OPCODE(FAST_INDEX_1) // a[i] + +OPCODE(FAST_INDEX) // a[x] +OPCODE(FAST_INDEX_REF) // a[x] #endif \ No newline at end of file diff --git a/src/pocketpy.h b/src/pocketpy.h index 08880a3b..8c8e83d3 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -184,7 +184,7 @@ void init_builtins(VM* _vm) { if(flag) return vm->PyFloat((f64)(1.0 / ret)); return vm->PyInt(ret); }else{ - return vm->PyFloat((f64)pow(vm->num_to_float(args[0]), vm->num_to_float(args[1]))); + return vm->PyFloat((f64)std::pow(vm->num_to_float(args[0]), vm->num_to_float(args[1]))); } }); @@ -220,26 +220,19 @@ void init_builtins(VM* _vm) { return vm->PyInt(vm->PyInt_AS_C(args[0]) % rhs); }); - _vm->bind_method<0>("int", "__repr__", [](VM* vm, pkpy::Args& args) { - return vm->PyStr(std::to_string(vm->PyInt_AS_C(args[0]))); - }); + _vm->bind_method<0>("int", "__repr__", CPP_LAMBDA(vm->PyStr(std::to_string(vm->PyInt_AS_C(args[0]))))); + _vm->bind_method<0>("int", "__json__", CPP_LAMBDA(vm->PyStr(std::to_string(vm->PyInt_AS_C(args[0]))))); - _vm->bind_method<0>("int", "__json__", [](VM* vm, pkpy::Args& args) { - return vm->PyStr(std::to_string(vm->PyInt_AS_C(args[0]))); - }); +#define INT_BITWISE_OP(name,op) \ + _vm->bind_method<1>("int", #name, CPP_LAMBDA(vm->PyInt(vm->PyInt_AS_C(args[0]) op vm->PyInt_AS_C(args[1])))); -#define __INT_BITWISE_OP(name,op) \ - _vm->bind_method<1>("int", #name, [](VM* vm, pkpy::Args& args) { \ - return vm->PyInt(vm->PyInt_AS_C(args[0]) op vm->PyInt_AS_C(args[1])); \ - }); + INT_BITWISE_OP(__lshift__, <<) + INT_BITWISE_OP(__rshift__, >>) + INT_BITWISE_OP(__and__, &) + INT_BITWISE_OP(__or__, |) + INT_BITWISE_OP(__xor__, ^) - __INT_BITWISE_OP(__lshift__, <<) - __INT_BITWISE_OP(__rshift__, >>) - __INT_BITWISE_OP(__and__, &) - __INT_BITWISE_OP(__or__, |) - __INT_BITWISE_OP(__xor__, ^) - -#undef __INT_BITWISE_OP +#undef INT_BITWISE_OP /************ PyFloat ************/ _vm->bind_static_method<1>("float", "__new__", [](VM* vm, pkpy::Args& args) { diff --git a/src/vm.h b/src/vm.h index 302c5083..ff21045c 100644 --- a/src/vm.h +++ b/src/vm.h @@ -464,6 +464,7 @@ public: int prev_line = -1; for(int i=0; icodes.size(); i++){ const Bytecode& byte = co->codes[i]; + if(byte.op == OP_NO_OP) continue; Str line = std::to_string(byte.line); if(byte.line == prev_line) line = ""; else{ @@ -487,6 +488,11 @@ public: if(byte.op == OP_LOAD_NAME_REF || byte.op == OP_LOAD_NAME || byte.op == OP_RAISE){ argStr += " (" + co->names[byte.arg].first.escape(true) + ")"; } + if(byte.op == OP_FAST_INDEX || byte.op == OP_FAST_INDEX_REF){ + auto& a = co->names[byte.arg & 0xFFFF]; + auto& x = co->names[(byte.arg >> 16) & 0xFFFF]; + argStr += " (" + a.first + '[' + x.first + "])"; + } ss << pad(argStr, 20); // may overflow ss << co->blocks[byte.block].to_string(); if(i != co->codes.size() - 1) ss << '\n'; @@ -835,5 +841,22 @@ void CodeObject::optimize(VM* vm){ int pos = codes[i-1].arg; consts[pos] = vm->num_negated(consts[pos]); } + + if(i>=2 && codes[i].op == OP_BUILD_INDEX){ + const Bytecode& a = codes[i-1]; + const Bytecode& x = codes[i-2]; + if(codes[i].arg == 1){ + if(a.op == OP_LOAD_NAME && x.op == OP_LOAD_NAME){ + codes[i].op = OP_FAST_INDEX; + }else continue; + }else{ + if(a.op == OP_LOAD_NAME_REF && x.op == OP_LOAD_NAME_REF){ + codes[i].op = OP_FAST_INDEX_REF; + }else continue; + } + codes[i].arg = (a.arg << 16) | x.arg; + codes[i-1].op = OP_NO_OP; + codes[i-2].op = OP_NO_OP; + } } } \ No newline at end of file