blueloveTH 2 лет назад
Родитель
Сommit
120773891a
5 измененных файлов с 80 добавлено и 43 удалено
  1. 1 17
      src/ceval.h
  2. 35 21
      src/compiler.h
  3. 43 2
      src/gc.h
  4. 0 3
      src/opcodes.h
  5. 1 0
      src/vm.h

+ 1 - 17
src/ceval.h

@@ -7,7 +7,7 @@ namespace pkpy{
 
 inline PyObject* VM::run_frame(Frame* frame){
     while(frame->has_next_bytecode()){
-        heap._auto_collect(this);
+        // heap._auto_collect(this);
 
         const Bytecode& byte = frame->next_bytecode();
         switch (byte.op)
@@ -115,22 +115,6 @@ inline PyObject* VM::run_frame(Frame* frame){
             args[0] = frame->top_value(this);
             frame->top() = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args));
         } continue;
-        case OP_INPLACE_BINARY_OP: {
-            Args args(2);
-            args[1] = frame->pop();
-            args[0] = frame->top_value(this);
-            PyObject* ret = fast_call(BINARY_SPECIAL_METHODS[byte.arg], std::move(args));
-            PyRef_AS_C(frame->top())->set(this, frame, std::move(ret));
-            frame->_pop();
-        } continue;
-        case OP_INPLACE_BITWISE_OP: {
-            Args args(2);
-            args[1] = frame->pop_value(this);
-            args[0] = frame->top_value(this);
-            PyObject* ret = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args));
-            PyRef_AS_C(frame->top())->set(this, frame, std::move(ret));
-            frame->_pop();
-        } continue;
         case OP_COMPARE_OP: {
             Args args(2);
             args[1] = frame->pop_value(this);

+ 35 - 21
src/compiler.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include "codeobject.h"
+#include "common.h"
 #include "parser.h"
 #include "error.h"
 #include "ceval.h"
@@ -405,40 +406,51 @@ private:
     }
 
     void exprAssign() {
-        int lhs = co()->codes.empty() ? -1 : co()->codes.size() - 1;
+        if(co()->codes.empty()) UNREACHABLE();
+        bool is_load_name_ref = co()->codes.back().op == OP_LOAD_NAME_REF;
+        int _name_arg = co()->codes.back().arg;
+        // if the last op is OP_LOAD_NAME_REF, remove it
+        // because we will emit OP_STORE_NAME or OP_STORE_CLASS_ATTR
+        if(is_load_name_ref) co()->codes.pop_back();
+
         co()->_rvalue += 1;
         TokenIndex op = parser->prev.type;
         if(op == TK("=")) {     // a = (expr)
             EXPR_TUPLE();
-            if(lhs!=-1 && co()->codes[lhs].op == OP_LOAD_NAME_REF){
-                if(co()->_is_compiling_class){
-                    emit(OP_STORE_CLASS_ATTR, co()->codes[lhs].arg);
-                }else{
-                    emit(OP_STORE_NAME, co()->codes[lhs].arg);
-                }
-                co()->codes[lhs].op = OP_NO_OP;
-                co()->codes[lhs].arg = -1;
+            if(is_load_name_ref){
+                auto op = co()->_is_compiling_class ? OP_STORE_CLASS_ATTR : OP_STORE_NAME;
+                emit(op, _name_arg);
             }else{
                 if(co()->_is_compiling_class) SyntaxError();
                 emit(OP_STORE_REF);
             }
         }else{                  // a += (expr) -> a = a + (expr)
             if(co()->_is_compiling_class) SyntaxError();
+            if(is_load_name_ref){
+                emit(OP_LOAD_NAME, _name_arg);
+            }else{
+                emit(OP_DUP_TOP_VALUE);
+            }
             EXPR();
             switch (op) {
-                case TK("+="):      emit(OP_INPLACE_BINARY_OP, 0);  break;
-                case TK("-="):      emit(OP_INPLACE_BINARY_OP, 1);  break;
-                case TK("*="):      emit(OP_INPLACE_BINARY_OP, 2);  break;
-                case TK("/="):      emit(OP_INPLACE_BINARY_OP, 3);  break;
-                case TK("//="):     emit(OP_INPLACE_BINARY_OP, 4);  break;
-                case TK("%="):      emit(OP_INPLACE_BINARY_OP, 5);  break;
-                case TK("<<="):     emit(OP_INPLACE_BITWISE_OP, 0);  break;
-                case TK(">>="):     emit(OP_INPLACE_BITWISE_OP, 1);  break;
-                case TK("&="):      emit(OP_INPLACE_BITWISE_OP, 2);  break;
-                case TK("|="):      emit(OP_INPLACE_BITWISE_OP, 3);  break;
-                case TK("^="):      emit(OP_INPLACE_BITWISE_OP, 4);  break;
+                case TK("+="):      emit(OP_BINARY_OP, 0);  break;
+                case TK("-="):      emit(OP_BINARY_OP, 1);  break;
+                case TK("*="):      emit(OP_BINARY_OP, 2);  break;
+                case TK("/="):      emit(OP_BINARY_OP, 3);  break;
+                case TK("//="):     emit(OP_BINARY_OP, 4);  break;
+                case TK("%="):      emit(OP_BINARY_OP, 5);  break;
+                case TK("<<="):     emit(OP_BITWISE_OP, 0);  break;
+                case TK(">>="):     emit(OP_BITWISE_OP, 1);  break;
+                case TK("&="):      emit(OP_BITWISE_OP, 2);  break;
+                case TK("|="):      emit(OP_BITWISE_OP, 3);  break;
+                case TK("^="):      emit(OP_BITWISE_OP, 4);  break;
                 default: UNREACHABLE();
             }
+            if(is_load_name_ref){
+                emit(OP_STORE_NAME, _name_arg);
+            }else{
+                emit(OP_STORE_REF);
+            }
         }
         co()->_rvalue -= 1;
     }
@@ -791,6 +803,9 @@ private:
         consume_end_stmt();
     }
 
+    // a = 1 + 2
+    // ['a', '1', '2', '+', '=']
+    // 
     void parse_expression(Precedence precedence) {
         lex_token();
         GrammarFn prefix = rules[parser->prev.type].prefix;
@@ -1003,7 +1018,6 @@ private:
             // If last op is not an assignment, pop the result.
             uint8_t last_op = co()->codes.back().op;
             if( last_op!=OP_STORE_NAME && last_op!=OP_STORE_REF &&
-            last_op!=OP_INPLACE_BINARY_OP && last_op!=OP_INPLACE_BITWISE_OP &&
             last_op!=OP_STORE_ALL_NAMES && last_op!=OP_STORE_CLASS_ATTR){
                 for(int i=begin; i<end; i++){
                     if(co()->codes[i].op==OP_BUILD_TUPLE_REF) co()->codes[i].op = OP_BUILD_TUPLE;

+ 43 - 2
src/gc.h

@@ -5,12 +5,46 @@
 #include "codeobject.h"
 #include "namedict.h"
 
+/*
+0: object
+1: type
+2: int
+3: float
+4: bool
+5: str
+6: list
+7: tuple
+8: slice
+9: range
+10: module
+11: _ref
+12: _star_wrapper
+13: function
+14: native_function
+15: iterator
+16: bound_method
+17: super
+18: Exception
+19: NoneType
+20: ellipsis
+21: _py_op_call
+22: _py_op_yield
+23: re.Match
+24: random.Random
+25: io.FileIO
+26: property
+27: staticmethod
+28: dict
+29: set
+*/
+
 namespace pkpy {
 struct ManagedHeap{
     std::vector<PyObject*> _no_gc;
     std::vector<PyObject*> gen;
     
-    int gc_threshold = 700;
+    static const int kMinGCThreshold = 700;
+    int gc_threshold = kMinGCThreshold;
     int gc_counter = 0;
 
     template<typename T>
@@ -29,8 +63,13 @@ struct ManagedHeap{
         return obj;
     }
 
+    inline static std::map<Type, int> deleted;
+
     ~ManagedHeap(){
         for(PyObject* obj: _no_gc) delete obj;
+        for(auto& [type, count]: deleted){
+            std::cout << "GC: " << type << "=" << count << std::endl;
+        }
     }
 
     int sweep(VM* vm){
@@ -41,6 +80,7 @@ struct ManagedHeap{
                 alive.push_back(obj);
             }else{
                 // _delete_hook(vm, obj);
+                deleted[obj->type] += 1;
                 delete obj;
             }
         }
@@ -49,6 +89,7 @@ struct ManagedHeap{
         for(PyObject* obj: _no_gc) obj->gc.marked = false;
 
         int freed = gen.size() - alive.size();
+        // std::cout << "GC: " << alive.size() << "/" << gen.size() << " (" << freed << " freed)" << std::endl;
         gen.clear();
         gen.swap(alive);
         return freed;
@@ -61,12 +102,12 @@ struct ManagedHeap{
         gc_counter = 0;
         collect(vm);
         gc_threshold = gen.size() * 2;
+        if(gc_threshold < kMinGCThreshold) gc_threshold = kMinGCThreshold;
     }
 
     int collect(VM* vm){
         mark(vm);
         int freed = sweep(vm);
-        // std::cout << "GC: " << freed << " objects freed" << std::endl;
         return freed;
     }
 

+ 0 - 3
src/opcodes.h

@@ -81,9 +81,6 @@ OPCODE(YIELD_VALUE)
 OPCODE(FAST_INDEX)      // a[x]
 OPCODE(FAST_INDEX_REF)       // a[x]
 
-OPCODE(INPLACE_BINARY_OP)
-OPCODE(INPLACE_BITWISE_OP)
-
 OPCODE(SETUP_CLOSURE)
 OPCODE(SETUP_DECORATOR)
 OPCODE(STORE_ALL_NAMES)

+ 1 - 0
src/vm.h

@@ -166,6 +166,7 @@ public:
         if(_module == nullptr) _module = _main;
         try {
             CodeObject_ code = compile(source, filename, mode);
+            if(_module == _main) std::cout << disassemble(code) << '\n';
             return _exec(code, _module);
         }catch (const Exception& e){
             *_stderr << e.summary() << '\n';