From 8364adef700d97202e1dfe73da6cd6e0dc90e17d Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 2 Apr 2023 15:50:33 +0800 Subject: [PATCH] up --- src/ceval.h | 102 ++++++++++++++++++++++--------------------------- src/compiler.h | 30 ++++++++------- src/frame.h | 31 ++++++++------- src/gc.h | 2 +- src/namedict.h | 4 +- src/obj.h | 4 +- src/opcodes.h | 15 ++++---- src/str.h | 2 + 8 files changed, 95 insertions(+), 95 deletions(-) diff --git a/src/ceval.h b/src/ceval.h index cb873dc2..21041305 100644 --- a/src/ceval.h +++ b/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; ipush(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; ipop_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); diff --git a/src/compiler.h b/src/compiler.h index 6348e264..08068351 100644 --- a/src/compiler.h +++ b/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 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(std::move(items[0])); consume(TK("]")); return; } - match_newlines(mode()==REPL_MODE); + match_newlines_repl(); } while (match(TK(","))); consume(TK("]")); auto e = make_expr(std::move(items)); @@ -335,7 +339,7 @@ private: bool parsing_dict = false; // {...} may be dict or set std::vector 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(std::move(items[0])); else _consume_comp(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(); 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; diff --git a/src/frame.h b/src/frame.h index e52aff00..1440b2d1 100644 --- a/src/frame.h +++ b/src/frame.h @@ -14,24 +14,23 @@ struct Frame { const CodeObject* co; PyObject* _module; NameDict_ _locals; - NameDict_ _closure; const uint64_t id; std::vector>> 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); } diff --git a/src/gc.h b/src/gc.h index 746bef60..7ce845e6 100644 --- a/src/gc.h +++ b/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); diff --git a/src/namedict.h b/src/namedict.h index 5623fce4..4a98f5d2 100644 --- a/src/namedict.h +++ b/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 }; diff --git a/src/obj.h b/src/obj.h index c7c38a90..ae7f7d3b 100644 --- a/src/obj.h +++ b/src/obj.h @@ -65,9 +65,11 @@ struct StarWrapper { using Super = std::pair; +// 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; diff --git a/src/opcodes.h b/src/opcodes.h index 0a2f2636..b0ebd237 100644 --- a/src/opcodes.h +++ b/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 \ No newline at end of file diff --git a/src/str.h b/src/str.h index d5119619..37102a5f 100644 --- a/src/str.h +++ b/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__");