blueloveTH 2 years ago
parent
commit
1e3e88d832
7 changed files with 75 additions and 81 deletions
  1. 2 0
      benchmarks/fib.py
  2. 16 17
      src/ceval.h
  3. 0 1
      src/codeobject.h
  4. 30 19
      src/compiler.h
  5. 24 30
      src/expr.h
  6. 1 0
      src/opcodes.h
  7. 2 14
      src/vm.h

+ 2 - 0
benchmarks/fib.py

@@ -5,4 +5,6 @@ def fib(n):
 
 assert fib(32) == 2178309
 
+# from dis import dis
+# dis(fib)
 # 7049155 calls

+ 16 - 17
src/ceval.h

@@ -30,7 +30,6 @@ __NEXT_FRAME:
     Bytecode byte = frame->next_bytecode();
     // cache
     const CodeObject* co = frame->co;
-    const auto& co_names = co->names;
     const auto& co_consts = co->consts;
     const auto& co_blocks = co->blocks;
 
@@ -74,6 +73,7 @@ __NEXT_STEP:;
     TARGET(LOAD_NONE) frame->push(None); DISPATCH();
     TARGET(LOAD_TRUE) frame->push(True); DISPATCH();
     TARGET(LOAD_FALSE) frame->push(False); DISPATCH();
+    TARGET(LOAD_INTEGER) frame->push(VAR(byte.arg)); DISPATCH();
     TARGET(LOAD_ELLIPSIS) frame->push(Ellipsis); DISPATCH();
     TARGET(LOAD_BUILTIN_EVAL) frame->push(builtins->attr(m_eval)); DISPATCH();
     TARGET(LOAD_FUNCTION) {
@@ -96,7 +96,7 @@ __NEXT_STEP:;
     } DISPATCH();
     TARGET(LOAD_NAME) {
         heap._auto_collect();
-        StrName name = co_names[byte.arg];
+        StrName name(byte.arg);
         PyObject* val;
         val = frame->_locals.try_get(name);
         if(val != nullptr) { frame->push(val); DISPATCH(); }
@@ -110,7 +110,7 @@ __NEXT_STEP:;
     } DISPATCH();
     TARGET(LOAD_NONLOCAL) {
         heap._auto_collect();
-        StrName name = co_names[byte.arg];
+        StrName name(byte.arg);
         PyObject* val;
         val = frame->_closure.try_get(name);
         if(val != nullptr) { frame->push(val); DISPATCH(); }
@@ -122,7 +122,7 @@ __NEXT_STEP:;
     } DISPATCH();
     TARGET(LOAD_GLOBAL) {
         heap._auto_collect();
-        StrName name = co_names[byte.arg];
+        StrName name(byte.arg);
         PyObject* val = frame->f_globals().try_get(name);
         if(val != nullptr) { frame->push(val); DISPATCH(); }
         val = vm->builtins->attr().try_get(name);
@@ -131,12 +131,12 @@ __NEXT_STEP:;
     } DISPATCH();
     TARGET(LOAD_ATTR) {
         PyObject* a = frame->top();
-        StrName name = co_names[byte.arg];
+        StrName name(byte.arg);
         frame->top() = getattr(a, name);
     } DISPATCH();
     TARGET(LOAD_METHOD) {
         PyObject* a = frame->top();
-        StrName name = co_names[byte.arg];
+        StrName name(byte.arg);
         PyObject* self;
         frame->top() = get_unbound_method(a, name, &self, true, true);
         frame->push(self);
@@ -151,11 +151,11 @@ __NEXT_STEP:;
         frame->_locals[byte.arg] = frame->popx();
         DISPATCH();
     TARGET(STORE_GLOBAL) {
-        StrName name = co_names[byte.arg];
+        StrName name(byte.arg);
         frame->f_globals().set(name, frame->popx());
     } DISPATCH();
     TARGET(STORE_ATTR) {
-        StrName name = co_names[byte.arg];
+        StrName name(byte.arg);
         PyObject* a = frame->top();
         PyObject* val = frame->top_1();
         setattr(a, name, val);
@@ -174,7 +174,7 @@ __NEXT_STEP:;
         frame->_locals[byte.arg] = nullptr;
     } DISPATCH();
     TARGET(DELETE_GLOBAL) {
-        StrName name = co_names[byte.arg];
+        StrName name(byte.arg);
         if(frame->f_globals().contains(name)){
             frame->f_globals().erase(name);
         }else{
@@ -183,7 +183,7 @@ __NEXT_STEP:;
     } DISPATCH();
     TARGET(DELETE_ATTR) {
         PyObject* a = frame->popx();
-        StrName name = co_names[byte.arg];
+        StrName name(byte.arg);
         if(!a->is_attr_valid()) TypeError("cannot delete attribute");
         if(!a->attr().contains(name)) AttributeError(a, name);
         a->attr().erase(name);
@@ -335,7 +335,7 @@ __NEXT_STEP:;
         frame->jump_abs_break(target);
     } DISPATCH();
     TARGET(GOTO) {
-        StrName name = co_names[byte.arg];
+        StrName name(byte.arg);
         int index = co->labels->try_get(name);
         if(index < 0) _error("KeyError", fmt("label ", name.escape(), " not found"));
         frame->jump_abs_break(index);
@@ -437,7 +437,7 @@ __NEXT_STEP:;
     } DISPATCH();
     /*****************************************/
     TARGET(IMPORT_NAME) {
-        StrName name = co_names[byte.arg];
+        StrName name(byte.arg);
         PyObject* ext_mod = _modules.try_get(name);
         if(ext_mod == nullptr){
             Str source;
@@ -494,7 +494,7 @@ __NEXT_STEP:;
     }; DISPATCH();
     /*****************************************/
     TARGET(BEGIN_CLASS) {
-        StrName name = co_names[byte.arg];
+        StrName name(byte.arg);
         PyObject* super_cls = frame->popx();
         if(super_cls == None) super_cls = _t(tp_object);
         check_type(super_cls, tp_type);
@@ -506,7 +506,7 @@ __NEXT_STEP:;
         cls->attr()._try_perfect_rehash();
     }; DISPATCH();
     TARGET(STORE_CLASS_ATTR) {
-        StrName name = co_names[byte.arg];
+        StrName name(byte.arg);
         PyObject* obj = frame->popx();
         PyObject* cls = frame->top();
         cls->attr().set(name, obj);
@@ -531,14 +531,13 @@ __NEXT_STEP:;
     } DISPATCH();
     TARGET(EXCEPTION_MATCH) {
         const auto& e = CAST(Exception&, frame->top());
-        StrName name = co_names[byte.arg];
+        StrName name(byte.arg);
         frame->push(VAR(e.match_type(name)));
     } DISPATCH();
     TARGET(RAISE) {
         PyObject* obj = frame->popx();
         Str msg = obj == None ? "" : CAST(Str, asStr(obj));
-        StrName type = co_names[byte.arg];
-        _error(type, msg);
+        _error(StrName(byte.arg), msg);
     } DISPATCH();
     TARGET(RE_RAISE) _raise(); DISPATCH();
 #if !PK_ENABLE_COMPUTED_GOTO

+ 0 - 1
src/codeobject.h

@@ -61,7 +61,6 @@ struct CodeObject {
     std::vector<Bytecode> codes;
     std::vector<int> lines; // line number for each bytecode
     List consts;
-    std::vector<StrName> names;         // other names
     std::vector<StrName> varnames;      // local variables
     NameDictInt_ varnames_inv;
     std::set<Str> global_names;

+ 30 - 19
src/compiler.h

@@ -524,8 +524,7 @@ __SUBSCR_END:
         if(name_scope() != NAME_GLOBAL) SyntaxError("import statement should be used in global scope");
         consume(TK("@id"));
         Str name = prev().str();
-        int index = ctx()->add_name(name);
-        ctx()->emit(OP_IMPORT_NAME, index, prev().line);
+        ctx()->emit(OP_IMPORT_NAME, StrName(name).index, prev().line);
         return name;
     }
 
@@ -537,7 +536,7 @@ __SUBSCR_END:
                 consume(TK("@id"));
                 name = prev().str();
             }
-            ctx()->emit(OP_STORE_GLOBAL, ctx()->add_name(name), prev().line);
+            ctx()->emit(OP_STORE_GLOBAL, StrName(name).index, prev().line);
         } while (match(TK(",")));
         consume_end_stmt();
     }
@@ -555,13 +554,12 @@ __SUBSCR_END:
             ctx()->emit(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
             consume(TK("@id"));
             Str name = prev().str();
-            int index = ctx()->add_name(name);
-            ctx()->emit(OP_LOAD_ATTR, index, prev().line);
+            ctx()->emit(OP_LOAD_ATTR, StrName(name).index, prev().line);
             if (match(TK("as"))) {
                 consume(TK("@id"));
                 name = prev().str();
             }
-            ctx()->emit(OP_STORE_GLOBAL, ctx()->add_name(name), prev().line);
+            ctx()->emit(OP_STORE_GLOBAL, StrName(name).index, prev().line);
         } while (match(TK(",")));
         ctx()->emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
         consume_end_stmt();
@@ -638,8 +636,7 @@ __SUBSCR_END:
         do {
             consume(TK("except"));
             if(match(TK("@id"))){
-                int namei = ctx()->add_name(prev().str());
-                ctx()->emit(OP_EXCEPTION_MATCH, namei, prev().line);
+                ctx()->emit(OP_EXCEPTION_MATCH, StrName(prev().str()).index, prev().line);
             }else{
                 ctx()->emit(OP_LOAD_TRUE, BC_NOARG, BC_KEEPLINE);
             }
@@ -760,7 +757,7 @@ __SUBSCR_END:
                 break;
             case TK("raise"): {
                 consume(TK("@id"));
-                int dummy_t = ctx()->add_name(prev().str());
+                int dummy_t = StrName(prev().str()).index;
                 if(match(TK("(")) && !match(TK(")"))){
                     EXPR(false); consume(TK(")"));
                 }else{
@@ -782,7 +779,6 @@ __SUBSCR_END:
                 ctx()->emit(OP_POP_TOP, BC_NOARG, prev().line);
                 consume(TK("as"));
                 consume(TK("@id"));
-                // int index = ctx()->add_name(prev().str());
                 // emit(OP_STORE_NAME, index);
                 // emit(OP_LOAD_NAME_REF, index);
                 // emit(OP_WITH_ENTER);
@@ -802,7 +798,7 @@ __SUBSCR_END:
             case TK("goto"):
                 if(mode()!=EXEC_MODE) SyntaxError("'goto' is only available in EXEC_MODE");
                 consume(TK(".")); consume(TK("@id"));
-                ctx()->emit(OP_GOTO, ctx()->add_name(prev().str()), prev().line);
+                ctx()->emit(OP_GOTO, StrName(prev().str()).index, prev().line);
                 consume_end_stmt();
                 break;
             /*************************************************/
@@ -826,10 +822,10 @@ __SUBSCR_END:
     
     void compile_class(){
         consume(TK("@id"));
-        int namei = ctx()->add_name(prev().str());
+        int namei = StrName(prev().str()).index;
         int super_namei = -1;
         if(match(TK("(")) && match(TK("@id"))){
-            super_namei = ctx()->add_name(prev().str());
+            super_namei = StrName(prev().str()).index;
             consume(TK(")"));
         }
         if(super_namei == -1) ctx()->emit(OP_LOAD_NONE, BC_NOARG, prev().line);
@@ -932,26 +928,41 @@ __SUBSCR_END:
                 auto e = make_expr<NameExpr>(decl_name, name_scope());
                 e->emit_store(ctx());
             } else {
-                ctx()->emit(OP_LOAD_GLOBAL, ctx()->add_name(obj_name), prev().line);
-                int index = ctx()->add_name(decl_name);
+                ctx()->emit(OP_LOAD_GLOBAL, StrName(obj_name).index, prev().line);
+                int index = StrName(decl_name).index;
                 ctx()->emit(OP_STORE_ATTR, index, prev().line);
             }
         }else{
-            int index = ctx()->add_name(decl_name);
+            int index = StrName(decl_name).index;
             ctx()->emit(OP_STORE_CLASS_ATTR, index, prev().line);
         }
     }
 
+    PyObject* to_object(const TokenValue& value){
+        PyObject* obj = nullptr;
+        if(std::holds_alternative<i64>(value)){
+            obj = VAR(std::get<i64>(value));
+        }
+        if(std::holds_alternative<f64>(value)){
+            obj = VAR(std::get<f64>(value));
+        }
+        if(std::holds_alternative<Str>(value)){
+            obj = VAR(std::get<Str>(value));
+        }
+        if(obj == nullptr) FATAL_ERROR();
+        return obj;
+    }
+
     PyObject* read_literal(){
         advance();
         switch(prev().type){
             case TK("-"): {
                 consume(TK("@num"));
-                PyObject* val = LiteralExpr(prev().value).to_object(ctx());
+                PyObject* val = to_object(prev().value);
                 return vm->num_negated(val);
             }
-            case TK("@num"): return LiteralExpr(prev().value).to_object(ctx());
-            case TK("@str"): return LiteralExpr(prev().value).to_object(ctx());
+            case TK("@num"): return to_object(prev().value);
+            case TK("@str"): return to_object(prev().value);
             case TK("True"): return VAR(true);
             case TK("False"): return VAR(false);
             case TK("None"): return vm->None;

+ 24 - 30
src/expr.h

@@ -99,14 +99,6 @@ struct CodeEmitContext{
         return true;
     }
 
-    int add_name(StrName name){
-        for(int i=0; i<co->names.size(); i++){
-            if(co->names[i] == name) return i;
-        }
-        co->names.push_back(name);
-        return co->names.size() - 1;
-    }
-
     int add_varname(StrName name){
         int index = co->varnames_inv->try_get(name);
         if(index >= 0) return index;
@@ -144,7 +136,7 @@ struct NameExpr: Expr{
             ctx->emit(OP_LOAD_FAST, index, line);
         }else{
             Opcode op = ctx->level <= 1 ? OP_LOAD_GLOBAL : OP_LOAD_NONLOCAL;
-            ctx->emit(op, ctx->add_name(name), line);
+            ctx->emit(op, StrName(name).index, line);
         }
     }
 
@@ -154,7 +146,7 @@ struct NameExpr: Expr{
                 ctx->emit(OP_DELETE_FAST, ctx->add_varname(name), line);
                 break;
             case NAME_GLOBAL:
-                ctx->emit(OP_DELETE_GLOBAL, ctx->add_name(name), line);
+                ctx->emit(OP_DELETE_GLOBAL, StrName(name).index, line);
                 break;
             default: FATAL_ERROR(); break;
         }
@@ -163,7 +155,7 @@ struct NameExpr: Expr{
 
     bool emit_store(CodeEmitContext* ctx) override {
         if(ctx->is_compiling_class){
-            int index = ctx->add_name(name);
+            int index = StrName(name).index;
             ctx->emit(OP_STORE_CLASS_ATTR, index, line);
             return true;
         }
@@ -172,7 +164,7 @@ struct NameExpr: Expr{
                 ctx->emit(OP_STORE_FAST, ctx->add_varname(name), line);
                 break;
             case NAME_GLOBAL:
-                ctx->emit(OP_STORE_GLOBAL, ctx->add_name(name), line);
+                ctx->emit(OP_STORE_GLOBAL, StrName(name).index, line);
                 break;
             default: FATAL_ERROR(); break;
         }
@@ -276,11 +268,16 @@ struct LiteralExpr: Expr{
         FATAL_ERROR();
     }
 
-    PyObject* to_object(CodeEmitContext* ctx){
+    void emit(CodeEmitContext* ctx) override {
         VM* vm = ctx->vm;
         PyObject* obj = nullptr;
         if(std::holds_alternative<i64>(value)){
-            obj = VAR(std::get<i64>(value));
+            i64 _val = std::get<i64>(value);
+            if(_val >= INT16_MIN && _val <= INT16_MAX){
+                ctx->emit(OP_LOAD_INTEGER, (int)_val, line);
+                return;
+            }
+            obj = VAR(_val);
         }
         if(std::holds_alternative<f64>(value)){
             obj = VAR(std::get<f64>(value));
@@ -288,14 +285,8 @@ struct LiteralExpr: Expr{
         if(std::holds_alternative<Str>(value)){
             obj = VAR(std::get<Str>(value));
         }
-        return obj;
-    }
-
-    void emit(CodeEmitContext* ctx) override {
-        PyObject* obj = to_object(ctx);
         if(obj == nullptr) FATAL_ERROR();
-        int index = ctx->add_const(obj);
-        ctx->emit(OP_LOAD_CONST, index, line);
+        ctx->emit(OP_LOAD_CONST, ctx->add_const(obj), line);
     }
 
     bool is_literal() const override { return true; }
@@ -312,14 +303,17 @@ struct NegatedExpr: Expr{
         // if child is a int of float, do constant folding
         if(child->is_literal()){
             LiteralExpr* lit = static_cast<LiteralExpr*>(child.get());
-            PyObject* obj = nullptr;
             if(std::holds_alternative<i64>(lit->value)){
-                obj = VAR(-std::get<i64>(lit->value));
+                i64 _val = -std::get<i64>(lit->value);
+                if(_val >= INT16_MIN && _val <= INT16_MAX){
+                    ctx->emit(OP_LOAD_INTEGER, (int)_val, line);
+                }else{
+                    ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(_val)), line);
+                }
+                return;
             }
             if(std::holds_alternative<f64>(lit->value)){
-                obj = VAR(-std::get<f64>(lit->value));
-            }
-            if(obj != nullptr){
+                PyObject* obj = VAR(-std::get<f64>(lit->value));
                 ctx->emit(OP_LOAD_CONST, ctx->add_const(obj), line);
                 return;
             }
@@ -585,27 +579,27 @@ struct AttribExpr: Expr{
 
     void emit(CodeEmitContext* ctx) override{
         a->emit(ctx);
-        int index = ctx->add_name(b);
+        int index = StrName(b).index;
         ctx->emit(OP_LOAD_ATTR, index, line);
     }
 
     bool emit_del(CodeEmitContext* ctx) override {
         a->emit(ctx);
-        int index = ctx->add_name(b);
+        int index = StrName(b).index;
         ctx->emit(OP_DELETE_ATTR, index, line);
         return true;
     }
 
     bool emit_store(CodeEmitContext* ctx) override {
         a->emit(ctx);
-        int index = ctx->add_name(b);
+        int index = StrName(b).index;
         ctx->emit(OP_STORE_ATTR, index, line);
         return true;
     }
 
     void emit_method(CodeEmitContext* ctx) {
         a->emit(ctx);
-        int index = ctx->add_name(b);
+        int index = StrName(b).index;
         ctx->emit(OP_LOAD_METHOD, index, line);
     }
 

+ 1 - 0
src/opcodes.h

@@ -12,6 +12,7 @@ OPCODE(LOAD_CONST)
 OPCODE(LOAD_NONE)
 OPCODE(LOAD_TRUE)
 OPCODE(LOAD_FALSE)
+OPCODE(LOAD_INTEGER)
 OPCODE(LOAD_ELLIPSIS)
 OPCODE(LOAD_BUILTIN_EVAL)
 OPCODE(LOAD_FUNCTION)

+ 2 - 14
src/vm.h

@@ -597,7 +597,7 @@ inline Str VM::disassemble(CodeObject_ co){
             case OP_LOAD_ATTR: case OP_LOAD_METHOD: case OP_STORE_ATTR: case OP_DELETE_ATTR:
             case OP_IMPORT_NAME: case OP_BEGIN_CLASS:
             case OP_DELETE_GLOBAL:
-                argStr += fmt(" (", co->names[byte.arg].sv(), ")");
+                argStr += fmt(" (", StrName(byte.arg).sv(), ")");
                 break;
             case OP_LOAD_FAST: case OP_STORE_FAST: case OP_DELETE_FAST:
                 argStr += fmt(" (", co->varnames[byte.arg].sv(), ")");
@@ -614,23 +614,11 @@ inline Str VM::disassemble(CodeObject_ co){
         if(i != co->codes.size() - 1) ss << '\n';
     }
 
-    // std::stringstream consts;
-    // consts << "co_consts: ";
-    // consts << CAST(Str&, asRepr(VAR(co->consts)));
-
-    // std::stringstream names;
-    // names << "co_names: ";
-    // List list;
-    // for(int i=0; i<co->names.size(); i++){
-    //     list.push_back(VAR(co->names[i].sv()));
-    // }
-    // names << CAST(Str, asRepr(VAR(list)));
-    // ss << '\n' << consts.str() << '\n' << names.str();
-
     for(auto& decl: co->func_decls){
         ss << "\n\n" << "Disassembly of " << decl->code->name << ":\n";
         ss << disassemble(decl->code);
     }
+    ss << "\n";
     return Str(ss.str());
 }