blueloveTH 2 лет назад
Родитель
Сommit
8364adef70
8 измененных файлов с 95 добавлено и 95 удалено
  1. 46 56
      src/ceval.h
  2. 17 13
      src/compiler.h
  3. 17 14
      src/frame.h
  4. 1 1
      src/gc.h
  5. 2 2
      src/namedict.h
  6. 3 1
      src/obj.h
  7. 7 8
      src/opcodes.h
  8. 2 0
      src/str.h

+ 46 - 56
src/ceval.h

@@ -26,23 +26,15 @@ inline PyObject* VM::run_frame(Frame* frame){
             f._closure = frame->_locals;
         } continue;
         case OP_ROT_TWO: ::std::swap(frame->top(), frame->top_1()); continue;
-        case OP_BUILD_TUPLE: {
-            Args items = frame->pop_n_values_reversed(this, byte.arg);
-            frame->push(VAR(std::move(items)));
-        } continue;
         /*****************************************/
         case OP_LOAD_NAME: {
-            // TODO: use name resolution linked list to optimize this
             StrName name = frame->co->names[byte.arg];
             PyObject* val;
-            val = frame->f_locals().try_get(name);
-            if(val != nullptr) { frame->push(val); continue; }
-            val = frame->f_closure_try_get(name);
-            if(val != nullptr) { frame->push(val); continue; }
-            val = frame->f_globals().try_get(name);
-            if(val != nullptr) { frame->push(val); continue; }
-            val = vm->builtins->attr().try_get(name);
-            if(val != nullptr) { frame->push(val); continue; }
+            int i = 0;  // names[0] is ensured to be non-null
+            do{
+                val = frame->names[i++]->try_get(name);
+                if(val != nullptr){ frame->push(val); break; }
+            }while(frame->names[i] != nullptr);
             vm->NameError(name);
         } continue;
         case OP_LOAD_ATTR: {
@@ -51,9 +43,10 @@ inline PyObject* VM::run_frame(Frame* frame){
             frame->top() = getattr(a, name);
         } continue;
         case OP_LOAD_SUBSCR: {
-            PyObject* b = frame->popx();
-            PyObject* a = frame->top();
-            frame->top() = fast_call(__getitem__, Args{a, b});
+            Args args(2);
+            args[1] = frame->popx();    // b
+            args[0] = frame->top();     // a
+            frame->top() = fast_call(__getitem__, std::move(args));
         } continue;
         case OP_STORE_LOCAL: {
             StrName name = frame->co->names[byte.arg];
@@ -105,34 +98,58 @@ inline PyObject* VM::run_frame(Frame* frame){
             fast_call(__delitem__, Args{a, b});
         } continue;
         /*****************************************/
-        case OP_BUILD_TUPLE_REF: {
-            Args items = frame->pop_n_reversed(byte.arg);
-            frame->push(PyRef(TupleRef(std::move(items))));
+        case OP_BUILD_LIST:
+            frame->push(VAR(frame->popx_n_reversed(byte.arg).to_list()));
+            continue;
+        case OP_BUILD_DICT: {
+            PyObject* t = VAR(frame->popx_n_reversed(byte.arg));
+            PyObject* obj = call(builtins->attr(m_dict), Args{t});
+            frame->push(obj);
+        } continue;
+        case OP_BUILD_SET: {
+            PyObject* t = VAR(frame->popx_n_reversed(byte.arg));
+            PyObject* obj = call(builtins->attr(m_set), Args{t});
+            frame->push(obj);
+        } continue;
+        case OP_BUILD_SLICE: {
+            PyObject* step = frame->popx();
+            PyObject* stop = frame->popx();
+            PyObject* start = frame->popx();
+            Slice s;
+            if(start != None) { s.start = CAST(int, start);}
+            if(stop != None) { s.stop = CAST(int, stop);}
+            if(step != None) { s.step = CAST(int, step);}
+            frame->push(VAR(s));
+        } continue;
+        case OP_BUILD_TUPLE: {
+            Tuple items = frame->popx_n_reversed(byte.arg);
+            frame->push(VAR(std::move(items)));
         } continue;
         case OP_BUILD_STRING: {
-            Args items = frame->pop_n_values_reversed(this, byte.arg);
+            Args items = frame->popx_n_reversed(byte.arg);
             StrStream ss;
             for(int i=0; i<items.size(); i++) ss << CAST(Str, asStr(items[i]));
             frame->push(VAR(ss.str()));
         } continue;
+        /*****************************************/
         case OP_LOAD_EVAL_FN: frame->push(builtins->attr(m_eval)); continue;
         case OP_BEGIN_CLASS: {
-            auto& name = frame->co->names[byte.arg];
-            PyObject* clsBase = frame->pop_value(this);
+            StrName name = frame->co->names[byte.arg];
+            PyObject* clsBase = frame->popx();
             if(clsBase == None) clsBase = _t(tp_object);
             check_type(clsBase, tp_type);
-            PyObject* cls = new_type_object(frame->_module, name.first, OBJ_GET(Type, clsBase));
+            PyObject* cls = new_type_object(frame->_module, name, OBJ_GET(Type, clsBase));
             frame->push(cls);
         } continue;
         case OP_END_CLASS: {
-            PyObject* cls = frame->pop();
+            PyObject* cls = frame->popx();
             cls->attr()._try_perfect_rehash();
         }; continue;
         case OP_STORE_CLASS_ATTR: {
-            auto& name = frame->co->names[byte.arg];
-            PyObject* obj = frame->pop_value(this);
+            StrName name = frame->co->names[byte.arg];
+            PyObject* obj = frame->popx();
             PyObject* cls = frame->top();
-            cls->attr().set(name.first, std::move(obj));
+            cls->attr().set(name, obj);
         } continue;
         case OP_RETURN_VALUE: return frame->popx();
         case OP_PRINT_EXPR: {
@@ -204,27 +221,7 @@ inline PyObject* VM::run_frame(Frame* frame){
             _error(type, msg);
         } continue;
         case OP_RE_RAISE: _raise(); continue;
-        case OP_BUILD_LIST:
-            frame->push(VAR(frame->pop_n_values_reversed(this, byte.arg).to_list()));
-            continue;
-        case OP_BUILD_MAP: {
-            List list(byte.arg);
-            for(int i=0; i<byte.arg; i++){
-                PyObject* value = frame->pop_value(this);
-                PyObject* key = frame->pop_value(this);
-                list[i] = VAR(Tuple({key, value}));
-            }
-            PyObject* d_arg = VAR(std::move(list));
-            PyObject* obj = call(builtins->attr("dict"), Args{d_arg});
-            frame->push(obj);
-        } continue;
-        case OP_BUILD_SET: {
-            PyObject* list = VAR(
-                frame->pop_n_values_reversed(this, byte.arg).to_list()
-            );
-            PyObject* obj = call(builtins->attr("set"), Args{list});
-            frame->push(obj);
-        } continue;
+
         case OP_LIST_APPEND: {
             PyObject* obj = frame->pop_value(this);
             List& list = CAST(List&, frame->top_1());
@@ -310,14 +307,7 @@ inline PyObject* VM::run_frame(Frame* frame){
             if(asBool(expr)==True) frame->jump_abs(byte.arg);
             else frame->pop_value(this);
         } continue;
-        case OP_BUILD_SLICE: {
-            PyObject* stop = frame->pop_value(this);
-            PyObject* start = frame->pop_value(this);
-            Slice s;
-            if(start != None) { s.start = CAST(int, start);}
-            if(stop != None) { s.stop = CAST(int, stop);}
-            frame->push(VAR(s));
-        } continue;
+
         case OP_IMPORT_NAME: {
             StrName name = frame->co->names[byte.arg].first;
             PyObject* ext_mod = _modules.try_get(name);

+ 17 - 13
src/compiler.h

@@ -142,6 +142,10 @@ private:
         }
     }
 
+    bool match_newlines_repl(){
+        return match_newlines(mode()==REPL_MODE);
+    }
+
     bool match_newlines(bool repl_throw=false) {
         bool consumed = false;
         if (curr().type == TK("@eol")) {
@@ -281,9 +285,9 @@ private:
 
     // PASS
     void exprGroup(){
-        match_newlines(mode()==REPL_MODE);
+        match_newlines_repl();
         EXPR_TUPLE();   // () is just for change precedence
-        match_newlines(mode()==REPL_MODE);
+        match_newlines_repl();
         consume(TK(")"));
     }
 
@@ -298,13 +302,13 @@ private:
         consume(TK("in"));
         EXPR();
         ce->iter = ctx()->s_expr.popx();
-        match_newlines(mode()==REPL_MODE);
+        match_newlines_repl();
         if(match(TK("if"))){
             EXPR();
             ce->cond = ctx()->s_expr.popx();
         }
         ctx()->s_expr.push(std::move(ce));
-        match_newlines(mode()==REPL_MODE);
+        match_newlines_repl();
     }
 
     // PASS
@@ -312,17 +316,17 @@ private:
         int line = prev().line;
         std::vector<Expr_> items;
         do {
-            match_newlines(mode()==REPL_MODE);
+            match_newlines_repl();
             if (curr().type == TK("]")) break;
             EXPR();
             items.push_back(ctx()->s_expr.popx());
-            match_newlines(mode()==REPL_MODE);
+            match_newlines_repl();
             if(items.size()==1 && match(TK("for"))){
                 _consume_comp<ListCompExpr>(std::move(items[0]));
                 consume(TK("]"));
                 return;
             }
-            match_newlines(mode()==REPL_MODE);
+            match_newlines_repl();
         } while (match(TK(",")));
         consume(TK("]"));
         auto e = make_expr<ListExpr>(std::move(items));
@@ -335,7 +339,7 @@ private:
         bool parsing_dict = false;  // {...} may be dict or set
         std::vector<Expr_> items;
         do {
-            match_newlines(mode()==REPL_MODE);
+            match_newlines_repl();
             if (curr().type == TK("}")) break;
             EXPR();
             if(curr().type == TK(":")) parsing_dict = true;
@@ -349,14 +353,14 @@ private:
             }else{
                 items.push_back(ctx()->s_expr.popx());
             }
-            match_newlines(mode()==REPL_MODE);
+            match_newlines_repl();
             if(items.size()==1 && match(TK("for"))){
                 if(parsing_dict) _consume_comp<DictCompExpr>(std::move(items[0]));
                 else _consume_comp<SetCompExpr>(std::move(items[0]));
                 consume(TK("}"));
                 return;
             }
-            match_newlines(mode()==REPL_MODE);
+            match_newlines_repl();
         } while (match(TK(",")));
         consume(TK("}"));
         if(items.size()==0 || parsing_dict){
@@ -373,7 +377,7 @@ private:
         auto e = make_expr<CallExpr>();
         e->callable = ctx()->s_expr.popx();
         do {
-            match_newlines(mode()==REPL_MODE);
+            match_newlines_repl();
             if (curr().type==TK(")")) break;
             if(curr().type==TK("@id") && next().type==TK("=")) {
                 consume(TK("@id"));
@@ -386,7 +390,7 @@ private:
                 EXPR();
                 e->args.push_back(ctx()->s_expr.popx());
             }
-            match_newlines(mode()==REPL_MODE);
+            match_newlines_repl();
         } while (match(TK(",")));
         consume(TK(")"));
         if(e->args.size() > 32767) SyntaxError("too many positional arguments");
@@ -709,7 +713,7 @@ private:
             case TK("label"):
                 if(mode()!=EXEC_MODE) SyntaxError("'label' is only available in EXEC_MODE");
                 consume(TK(".")); consume(TK("@id"));
-                bool ok = co()->add_label(prev().str());
+                bool ok = ctx()->add_label(prev().str());
                 if(!ok) SyntaxError("label " + prev().str().escape(true) + " already exists");
                 consume_end_stmt();
                 break;

+ 17 - 14
src/frame.h

@@ -14,24 +14,23 @@ struct Frame {
     const CodeObject* co;
     PyObject* _module;
     NameDict_ _locals;
-    NameDict_ _closure;
     const uint64_t id;
     std::vector<std::pair<int, std::vector<PyObject*>>> s_try_block;
+    const NameDict* names[5];     // name resolution array, zero terminated
 
-    NameDict& f_locals() noexcept { return _locals != nullptr ? *_locals : _module->attr(); }
+    NameDict& f_locals() noexcept { return *_locals; }
     NameDict& f_globals() noexcept { return _module->attr(); }
 
-    PyObject* f_closure_try_get(StrName name) noexcept {
-        if(_closure == nullptr) return nullptr;
-        return _closure->try_get(name);
+    Frame(const CodeObject_& co, PyObject* _module, NameDict_ _locals=nullptr, NameDict_ _closure=nullptr)
+            : co(co.get()), _module(_module), _locals(_locals), id(kFrameGlobalId++) {
+        memset(names, 0, sizeof(names));
+        int i = 0;
+        if(_locals != nullptr) names[i++] = _locals.get();
+        if(_closure != nullptr) names[i++] = _closure.get();
+        names[i++] = &_module->attr();
+        // names[i++] = builtins
     }
 
-    Frame(const CodeObject_& co,
-        PyObject* _module,
-        const NameDict_& _locals=nullptr,
-        const NameDict_& _closure=nullptr)
-            : co(co.get()), _module(_module), _locals(_locals), _closure(_closure), id(kFrameGlobalId++) { }
-
     const Bytecode& next_bytecode() {
         _ip = _next_ip++;
         return co->codes[_ip];
@@ -127,7 +126,7 @@ struct Frame {
         }
     }
 
-    Args pop_n_reversed(int n){
+    Args popx_n_reversed(int n){
         Args v(n);
         for(int i=n-1; i>=0; i--) v[i] = popx();
         return v;
@@ -135,9 +134,13 @@ struct Frame {
 
     void _mark() const {
         for(PyObject* obj : _data) OBJ_MARK(obj);
-        if(_locals != nullptr) _locals->_mark();
-        if(_closure != nullptr) _closure->_mark();
         OBJ_MARK(_module);
+
+        int i = 0;  // names[0] is ensured to be non-null
+        do{
+            names[i++]->_mark();
+        }while(names[i] != nullptr);
+
         for(auto& p : s_try_block){
             for(PyObject* obj : p.second) OBJ_MARK(obj);
         }

+ 1 - 1
src/gc.h

@@ -114,7 +114,7 @@ struct ManagedHeap{
     void mark(VM* vm);
 };
 
-inline void NameDict::_mark(){
+inline void NameDict::_mark() const{
     for(uint16_t i=0; i<_capacity; i++){
         if(_items[i].first.empty()) continue;
         OBJ_MARK(_items[i].second);

+ 2 - 2
src/namedict.h

@@ -125,7 +125,7 @@ while(!_items[i].first.empty()) {       \
         _rehash(false); // do not resize
     }
 
-    PyObject* try_get(StrName key){
+    PyObject* try_get(StrName key) const{
         bool ok; uint16_t i;
         HASH_PROBE(key, ok, i);
         if(!ok) return nullptr;
@@ -180,7 +180,7 @@ while(!_items[i].first.empty()) {       \
         return v;
     }
 
-    void _mark();
+    void _mark() const;
 #undef HASH_PROBE
 #undef _hash
 };

+ 3 - 1
src/obj.h

@@ -65,9 +65,11 @@ struct StarWrapper {
 
 using Super = std::pair<PyObject*, Type>;
 
+// TODO: re-examine the design of Slice
 struct Slice {
     int start = 0;
-    int stop = 0x7fffffff; 
+    int stop = 0x7fffffff;
+    int step = 1;
 
     void normalize(int len){
         if(start < 0) start += len;

+ 7 - 8
src/opcodes.h

@@ -20,14 +20,6 @@ OPCODE(UNARY_NEGATIVE)
 OPCODE(UNARY_NOT)
 OPCODE(UNARY_STAR)
 
-OPCODE(BUILD_LIST)
-OPCODE(BUILD_MAP)
-OPCODE(BUILD_SET)
-OPCODE(BUILD_SLICE)
-OPCODE(BUILD_TUPLE)
-OPCODE(BUILD_TUPLE_REF)
-OPCODE(BUILD_STRING)
-
 OPCODE(LIST_APPEND)
 OPCODE(MAP_ADD)
 OPCODE(SET_ADD)
@@ -96,5 +88,12 @@ OPCODE(DELETE_GLOBAL)
 OPCODE(DELETE_ATTR)
 OPCODE(DELETE_SUBSCR)
 /**************************/
+OPCODE(BUILD_LIST)
+OPCODE(BUILD_DICT)
+OPCODE(BUILD_SET)
+OPCODE(BUILD_SLICE)
+OPCODE(BUILD_TUPLE)
+OPCODE(BUILD_STRING)
+/**************************/
 
 #endif

+ 2 - 0
src/str.h

@@ -209,6 +209,8 @@ const StrName __call__ = StrName::get("__call__");
 
 const StrName m_eval = StrName::get("eval");
 const StrName m_self = StrName::get("self");
+const StrName m_dict = StrName::get("dict");
+const StrName m_set = StrName::get("set");
 const StrName __enter__ = StrName::get("__enter__");
 const StrName __exit__ = StrName::get("__exit__");