diff --git a/benchmarks/fib.py b/benchmarks/fib.py index 1bb89670..349453d2 100644 --- a/benchmarks/fib.py +++ b/benchmarks/fib.py @@ -5,4 +5,6 @@ def fib(n): assert fib(32) == 2178309 +# from dis import dis +# dis(fib) # 7049155 calls \ No newline at end of file diff --git a/src/ceval.h b/src/ceval.h index 22b93ede..e4cd3ba9 100644 --- a/src/ceval.h +++ b/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 diff --git a/src/codeobject.h b/src/codeobject.h index 4ebadb3e..ec869834 100644 --- a/src/codeobject.h +++ b/src/codeobject.h @@ -61,7 +61,6 @@ struct CodeObject { std::vector codes; std::vector lines; // line number for each bytecode List consts; - std::vector names; // other names std::vector varnames; // local variables NameDictInt_ varnames_inv; std::set global_names; diff --git a/src/compiler.h b/src/compiler.h index 3725a206..59dbb5fb 100644 --- a/src/compiler.h +++ b/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(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(value)){ + obj = VAR(std::get(value)); + } + if(std::holds_alternative(value)){ + obj = VAR(std::get(value)); + } + if(std::holds_alternative(value)){ + obj = VAR(std::get(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; diff --git a/src/expr.h b/src/expr.h index 9ef88e4b..dc1bf5a3 100644 --- a/src/expr.h +++ b/src/expr.h @@ -99,14 +99,6 @@ struct CodeEmitContext{ return true; } - int add_name(StrName name){ - for(int i=0; inames.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(value)){ - obj = VAR(std::get(value)); + i64 _val = std::get(value); + if(_val >= INT16_MIN && _val <= INT16_MAX){ + ctx->emit(OP_LOAD_INTEGER, (int)_val, line); + return; + } + obj = VAR(_val); } if(std::holds_alternative(value)){ obj = VAR(std::get(value)); @@ -288,14 +285,8 @@ struct LiteralExpr: Expr{ if(std::holds_alternative(value)){ obj = VAR(std::get(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(child.get()); - PyObject* obj = nullptr; if(std::holds_alternative(lit->value)){ - obj = VAR(-std::get(lit->value)); + i64 _val = -std::get(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(lit->value)){ - obj = VAR(-std::get(lit->value)); - } - if(obj != nullptr){ + PyObject* obj = VAR(-std::get(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); } diff --git a/src/opcodes.h b/src/opcodes.h index bb8d7956..28658d52 100644 --- a/src/opcodes.h +++ b/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) diff --git a/src/vm.h b/src/vm.h index 269d34e4..fcf33d6e 100644 --- a/src/vm.h +++ b/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; inames.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()); }