blueloveTH 3 лет назад
Родитель
Сommit
cae01cb5b7
5 измененных файлов с 48 добавлено и 24 удалено
  1. 8 1
      src/ceval.h
  2. 2 2
      src/compiler.h
  3. 4 3
      src/opcodes.h
  4. 11 18
      src/pocketpy.h
  5. 23 0
      src/vm.h

+ 8 - 1
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;

+ 2 - 2
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);

+ 4 - 3
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

+ 11 - 18
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", "__json__", [](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])))));
 
-#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]));     \
-    });
+#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]))));
 
-    __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) {

+ 23 - 0
src/vm.h

@@ -464,6 +464,7 @@ public:
         int prev_line = -1;
         for(int i=0; i<co->codes.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;
+        }
     }
 }