diff --git a/src/analysis/type_analysis.cpp b/src/analysis/type_analysis.cpp index dfc66e4b1..c463d0dac 100644 --- a/src/analysis/type_analysis.cpp +++ b/src/analysis/type_analysis.cpp @@ -89,17 +89,17 @@ class BasicBlockTypePropagator : public StmtVisitor { ExprTypeMap& expr_types; TypeSpeculations& type_speculations; TypeAnalysis::SpeculationLevel speculation; - const ConstantVRegInfo& constant_vregs; + const CodeConstants& code_constants; BasicBlockTypePropagator(CFGBlock* block, TypeMap& initial, ExprTypeMap& expr_types, TypeSpeculations& type_speculations, TypeAnalysis::SpeculationLevel speculation, - const ConstantVRegInfo& constant_vregs) + const CodeConstants& code_constants) : block(block), sym_table(initial), expr_types(expr_types), type_speculations(type_speculations), speculation(speculation), - constant_vregs(constant_vregs) {} + code_constants(code_constants) {} void run() { for (int i = 0; i < block->body.size(); i++) { @@ -118,7 +118,7 @@ class BasicBlockTypePropagator : public StmtVisitor { printf("in propagator, speculating that %s would actually be %s, at ", old_type->debugName().c_str(), speculated_type->debugName().c_str()); fflush(stdout); - print_bst(node, constant_vregs); + print_bst(node, code_constants); llvm::outs().flush(); printf("\n"); } @@ -131,7 +131,7 @@ class BasicBlockTypePropagator : public StmtVisitor { } CompilerType* getConstantType(int vreg) { - Box* o = constant_vregs.getConstant(vreg); + Box* o = code_constants.getConstant(vreg); if (o->cls == int_cls) return INT; else if (o->cls == float_cls) @@ -284,7 +284,7 @@ class BasicBlockTypePropagator : public StmtVisitor { if (VERBOSITY() >= 2 && func == UNDEF) { printf("Think %s.%s is undefined, at %d\n", t->debugName().c_str(), node->attr.c_str(), node->lineno); - print_bst(node, constant_vregs); + print_bst(node, code_constants); printf("\n"); } @@ -297,7 +297,7 @@ class BasicBlockTypePropagator : public StmtVisitor { if (VERBOSITY() >= 2 && func == UNDEF) { printf("Think %s.%s is undefined, at %d\n", t->debugName().c_str(), node->attr.c_str(), node->lineno); - print_bst(node, constant_vregs); + print_bst(node, code_constants); printf("\n"); } @@ -399,7 +399,7 @@ class BasicBlockTypePropagator : public StmtVisitor { if (VERBOSITY() >= 2 && rtn == UNDEF) { printf("Think %s.%s is undefined, at %d\n", t->debugName().c_str(), node->attr.c_str(), node->lineno); - print_bst(node, constant_vregs); + print_bst(node, code_constants); printf("\n"); } _doSet(node->vreg_dst, rtn); @@ -551,9 +551,9 @@ class BasicBlockTypePropagator : public StmtVisitor { public: static TypeMap propagate(CFGBlock* block, const TypeMap& starting, ExprTypeMap& expr_types, TypeSpeculations& type_speculations, TypeAnalysis::SpeculationLevel speculation, - const ConstantVRegInfo& constant_vregs) { + const CodeConstants& code_constants) { TypeMap ending = starting; - BasicBlockTypePropagator(block, ending, expr_types, type_speculations, speculation, constant_vregs).run(); + BasicBlockTypePropagator(block, ending, expr_types, type_speculations, speculation, code_constants).run(); return ending; } }; @@ -632,7 +632,7 @@ class PropagatingTypeAnalysis : public TypeAnalysis { } static PropagatingTypeAnalysis* doAnalysis(SpeculationLevel speculation, TypeMap&& initial_types, - CFGBlock* initial_block, const ConstantVRegInfo& constant_vregs) { + CFGBlock* initial_block, const CodeConstants& code_constants) { Timer _t("PropagatingTypeAnalysis::doAnalysis()"); CFG* cfg = initial_block->cfg; @@ -673,7 +673,7 @@ class PropagatingTypeAnalysis : public TypeAnalysis { } TypeMap ending = BasicBlockTypePropagator::propagate(block, starting_types.find(block)->second, expr_types, - type_speculations, speculation, constant_vregs); + type_speculations, speculation, code_constants); if (VERBOSITY("types") >= 3) { printf("before (after):\n"); @@ -730,7 +730,7 @@ class PropagatingTypeAnalysis : public TypeAnalysis { // public entry point: TypeAnalysis* doTypeAnalysis(CFG* cfg, const ParamNames& arg_names, const std::vector& arg_types, EffortLevel effort, TypeAnalysis::SpeculationLevel speculation, - const ConstantVRegInfo& constant_vregs) { + const CodeConstants& code_constants) { // if (effort == EffortLevel::INTERPRETED) { // return new NullTypeAnalysis(); //} @@ -750,11 +750,11 @@ TypeAnalysis* doTypeAnalysis(CFG* cfg, const ParamNames& arg_names, const std::v assert(i == arg_types.size()); return PropagatingTypeAnalysis::doAnalysis(speculation, std::move(initial_types), cfg->getStartingBlock(), - constant_vregs); + code_constants); } TypeAnalysis* doTypeAnalysis(const OSREntryDescriptor* entry_descriptor, EffortLevel effort, - TypeAnalysis::SpeculationLevel speculation, const ConstantVRegInfo& constant_vregs) { + TypeAnalysis::SpeculationLevel speculation, const CodeConstants& code_constants) { auto cfg = entry_descriptor->code->source->cfg; auto&& vreg_info = cfg->getVRegInfo(); TypeMap initial_types(vreg_info.getTotalNumOfVRegs()); @@ -764,6 +764,6 @@ TypeAnalysis* doTypeAnalysis(const OSREntryDescriptor* entry_descriptor, EffortL } return PropagatingTypeAnalysis::doAnalysis(speculation, std::move(initial_types), - entry_descriptor->backedge->target, constant_vregs); + entry_descriptor->backedge->target, code_constants); } } diff --git a/src/analysis/type_analysis.h b/src/analysis/type_analysis.h index 3a9e7a09c..33187797e 100644 --- a/src/analysis/type_analysis.h +++ b/src/analysis/type_analysis.h @@ -24,7 +24,7 @@ namespace pyston { class CFGBlock; -class ConstantVRegInfo; +class CodeConstants; class BoxedClass; class BST_stmt_with_dest; class OSREntryDescriptor; @@ -45,9 +45,9 @@ class TypeAnalysis { TypeAnalysis* doTypeAnalysis(CFG* cfg, const ParamNames& param_names, const std::vector& arg_types, EffortLevel effort, - TypeAnalysis::SpeculationLevel speculation, const ConstantVRegInfo& constant_vregs); + TypeAnalysis::SpeculationLevel speculation, const CodeConstants& code_constants); TypeAnalysis* doTypeAnalysis(const OSREntryDescriptor* entry_descriptor, EffortLevel effort, - TypeAnalysis::SpeculationLevel speculation, const ConstantVRegInfo& constant_vregs); + TypeAnalysis::SpeculationLevel speculation, const CodeConstants& code_constants); } #endif diff --git a/src/codegen/ast_interpreter.cpp b/src/codegen/ast_interpreter.cpp index 736a5dd8b..af5feaf5d 100644 --- a/src/codegen/ast_interpreter.cpp +++ b/src/codegen/ast_interpreter.cpp @@ -181,7 +181,7 @@ class ASTInterpreter { BoxedClosure* getPassedClosure() { return frame_info.passed_closure; } Box** getVRegs() { return vregs; } const ScopingResults& getScopeInfo() { return scope_info; } - const ConstantVRegInfo& getConstantVRegInfo() { return getCode()->constant_vregs; } + const CodeConstants& getCodeConstants() { return getCode()->code_constants; } void addSymbol(int vreg, Box* value, bool allow_duplicates); void setGenerator(Box* gen); @@ -900,7 +900,7 @@ Value ASTInterpreter::visit_stmt(BST_stmt* node) { if (0) { printf("%20s % 2d ", getCode()->name->c_str(), current_block->idx); - print_bst(node, getConstantVRegInfo()); + print_bst(node, getCodeConstants()); printf("\n"); } @@ -1528,7 +1528,7 @@ Value ASTInterpreter::visit_set(BST_Set* node) { Value ASTInterpreter::getVReg(int vreg, bool is_kill) { assert(vreg != VREG_UNDEFINED); if (vreg < 0) { - Box* o = getConstantVRegInfo().getConstant(vreg); + Box* o = getCodeConstants().getConstant(vreg); return Value(incref(o), jit ? jit->imm(o)->setType(RefType::BORROWED) : NULL); } @@ -1564,10 +1564,10 @@ Value ASTInterpreter::getVReg(int vreg, bool is_kill) { } - current_block->print(getConstantVRegInfo()); + current_block->print(getCodeConstants()); printf("vreg: %d num cross: %d\n", vreg, getVRegInfo().getNumOfCrossBlockVRegs()); printf("\n\n"); - current_block->cfg->print(getConstantVRegInfo()); + current_block->cfg->print(getCodeConstants()); assert(0); return Value(); diff --git a/src/codegen/irgen.cpp b/src/codegen/irgen.cpp index a5608fea9..85aaf8219 100644 --- a/src/codegen/irgen.cpp +++ b/src/codegen/irgen.cpp @@ -1027,7 +1027,7 @@ std::pair doCompile(BoxedCode* code, SourceI assert((entry_descriptor != NULL) + (spec != NULL) == 1); if (VERBOSITY("irgen") >= 2) - source->cfg->print(code->constant_vregs); + source->cfg->print(code->code_constants); assert(g.cur_module == NULL); @@ -1101,10 +1101,10 @@ std::pair doCompile(BoxedCode* code, SourceI speculation_level = TypeAnalysis::SOME; TypeAnalysis* types; if (entry_descriptor) - types = doTypeAnalysis(entry_descriptor, effort, speculation_level, code->constant_vregs); + types = doTypeAnalysis(entry_descriptor, effort, speculation_level, code->code_constants); else types = doTypeAnalysis(source->cfg, *param_names, spec->arg_types, effort, speculation_level, - code->constant_vregs); + code->code_constants); _t2.split(); diff --git a/src/codegen/irgen/hooks.cpp b/src/codegen/irgen/hooks.cpp index 009e88d15..2a19c59ab 100644 --- a/src/codegen/irgen/hooks.cpp +++ b/src/codegen/irgen/hooks.cpp @@ -694,6 +694,9 @@ void BoxedCode::addVersion(void* f, ConcreteCompilerType* rtn_type, const std::v } bool BoxedCode::tryDeallocatingTheBJitCode() { + if (code_blocks.empty()) + return true; + // we can only delete the code object if we are not executing it currently assert(bjit_num_inside >= 0); if (bjit_num_inside != 0) { diff --git a/src/codegen/irgen/irgenerator.cpp b/src/codegen/irgen/irgenerator.cpp index 0ea9f45c8..4e5d46f53 100644 --- a/src/codegen/irgen/irgenerator.cpp +++ b/src/codegen/irgen/irgenerator.cpp @@ -69,6 +69,10 @@ IRGenState::IRGenState(BoxedCode* code, CompiledFunction* cf, llvm::Function* fu IRGenState::~IRGenState() { } +const CodeConstants& IRGenState::getCodeConstants() { + return code->code_constants; +} + llvm::Value* IRGenState::getPassedClosure() { assert(getScopeInfo().takesClosure()); assert(passed_closure); @@ -721,9 +725,9 @@ class IREmitterImpl : public IREmitter { return rtn; } - Box* getIntConstant(int64_t n) override { return irstate->getSourceInfo()->parent_module->getIntConstant(n); } + Box* getIntConstant(int64_t n) override { return irstate->getCodeConstants().getIntConstant(n); } - Box* getFloatConstant(double d) override { return irstate->getSourceInfo()->parent_module->getFloatConstant(d); } + Box* getFloatConstant(double d) override { return irstate->getCodeConstants().getFloatConstant(d); } void refConsumed(llvm::Value* v, llvm::Instruction* inst) override { irstate->getRefcounts()->refConsumed(v, inst); @@ -1225,7 +1229,7 @@ class IRGeneratorImpl : public IRGenerator { CompilerVariable* evalVReg(int vreg, bool is_kill = true) { assert(vreg != VREG_UNDEFINED); if (vreg < 0) { - Box* o = irstate->getCode()->constant_vregs.getConstant(vreg); + Box* o = irstate->getCode()->code_constants.getConstant(vreg); if (o->cls == int_cls) { return makeInt(((BoxedInt*)o)->n); } else if (o->cls == float_cls) { @@ -1612,7 +1616,7 @@ class IRGeneratorImpl : public IRGenerator { printf("Speculating that %s is actually %s, at ", rtn->getType()->debugName().c_str(), speculated_type->debugName().c_str()); fflush(stdout); - print_bst(node, irstate->getCode()->constant_vregs); + print_bst(node, irstate->getCode()->code_constants); llvm::outs().flush(); printf("\n"); } @@ -1624,7 +1628,7 @@ class IRGeneratorImpl : public IRGenerator { auto source = irstate->getSourceInfo(); printf("On %s:%d, function %s:\n", irstate->getCode()->filename->c_str(), irstate->getCode()->firstlineno, irstate->getCode()->name->c_str()); - irstate->getSourceInfo()->cfg->print(irstate->getCode()->constant_vregs); + irstate->getSourceInfo()->cfg->print(irstate->getCode()->code_constants); } RELEASE_ASSERT(!rtn->canConvertTo(speculated_type), "%s %s", rtn->getType()->debugName().c_str(), speculated_type->debugName().c_str()); diff --git a/src/codegen/irgen/irgenerator.h b/src/codegen/irgen/irgenerator.h index 42806f7bc..99cc9bbd8 100644 --- a/src/codegen/irgen/irgenerator.h +++ b/src/codegen/irgen/irgenerator.h @@ -92,6 +92,7 @@ class IRGenState { CompiledFunction* getCurFunction() { return cf; } BoxedCode* getCode() { return code; } + const CodeConstants& getCodeConstants(); ExceptionStyle getExceptionStyle() { return cf->exception_style; } diff --git a/src/core/bst.cpp b/src/core/bst.cpp index d90a17015..68b0b6404 100644 --- a/src/core/bst.cpp +++ b/src/core/bst.cpp @@ -754,8 +754,8 @@ void BST_MakeSlice::accept_stmt(StmtVisitor* v) { return v->visit_makeslice(this); } -void print_bst(BST_stmt* bst, const ConstantVRegInfo& constant_vregs) { - PrintVisitor v(constant_vregs, 0, llvm::outs()); +void print_bst(BST_stmt* bst, const CodeConstants& code_constants) { + PrintVisitor v(code_constants, 0, llvm::outs()); bst->accept(&v); v.flush(); } @@ -771,7 +771,7 @@ bool PrintVisitor::visit_vreg(int* vreg, bool is_dst) { if (*vreg != VREG_UNDEFINED) { stream << "%" << *vreg; if (*vreg < 0) - stream << "|" << autoDecref(repr(constant_vregs.getConstant(*vreg)))->s() << "|"; + stream << "|" << autoDecref(repr(code_constants.getConstant(*vreg)))->s() << "|"; } else stream << "%undef"; diff --git a/src/core/bst.h b/src/core/bst.h index 3cf2a773f..933ba8769 100644 --- a/src/core/bst.h +++ b/src/core/bst.h @@ -165,8 +165,18 @@ class BST_stmt_with_dest : public BST_stmt { bool has_dest_vreg() const override { return true; } }; +#define BSTNODE(opcode) \ + virtual void accept(BSTVisitor* v); \ + virtual void accept_stmt(StmtVisitor* v); \ + static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::opcode; + +#define BSTFIXEDVREGS(opcode, base_class) \ + BSTNODE(opcode) \ + BST_##opcode() : base_class(BST_TYPE::opcode) {} + #define BSTVARVREGS(opcode, base_class, num_elts, vreg_dst) \ public: \ + BSTNODE(opcode) \ static BST_##opcode* create(int num_elts) { return new (num_elts) BST_##opcode(num_elts); } \ static void operator delete(void* ptr) { ::operator delete[](ptr); } \ \ @@ -182,6 +192,7 @@ private: #define BSTVARVREGS2(opcode, base_class, num_elts, num_elts2, vreg_dst) \ public: \ + BSTNODE(opcode) \ static BST_##opcode* create(int num_elts, int num_elts2) { \ return new (num_elts + num_elts2) BST_##opcode(num_elts, num_elts2); \ } \ @@ -200,6 +211,7 @@ private: #define BSTVARVREGS2CALL(opcode, num_elts, num_elts2, vreg_dst) \ public: \ + BSTNODE(opcode) \ static BST_##opcode* create(int num_elts, int num_elts2) { \ return new (num_elts + num_elts2) BST_##opcode(num_elts, num_elts2); \ } \ @@ -219,12 +231,7 @@ class BST_Assert : public BST_stmt { public: int vreg_msg = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_Assert() : BST_stmt(BST_TYPE::Assert) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::Assert; + BSTFIXEDVREGS(Assert, BST_stmt) }; class BST_UnpackIntoArray : public BST_stmt { @@ -233,11 +240,6 @@ class BST_UnpackIntoArray : public BST_stmt { const int num_elts; int vreg_dst[1]; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::UnpackIntoArray; - BSTVARVREGS(UnpackIntoArray, BST_stmt, num_elts, vreg_dst) }; @@ -248,12 +250,7 @@ class BST_CopyVReg : public BST_stmt_with_dest { public: int vreg_src = VREG_UNDEFINED; // this vreg will not get killed! - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_CopyVReg() : BST_stmt_with_dest(BST_TYPE::CopyVReg) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::CopyVReg; + BSTFIXEDVREGS(CopyVReg, BST_stmt_with_dest) }; @@ -270,13 +267,7 @@ class BST_StoreName : public BST_stmt { // Only valid for lookup_type == CLOSURE: int closure_offset = -1; - - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_StoreName() : BST_stmt(BST_TYPE::StoreName) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::StoreName; + BSTFIXEDVREGS(StoreName, BST_stmt) }; class BST_StoreAttr : public BST_stmt { @@ -285,12 +276,7 @@ class BST_StoreAttr : public BST_stmt { int vreg_target = VREG_UNDEFINED; int vreg_value = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_StoreAttr() : BST_stmt(BST_TYPE::StoreAttr) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::StoreAttr; + BSTFIXEDVREGS(StoreAttr, BST_stmt) }; class BST_StoreSub : public BST_stmt { @@ -299,12 +285,7 @@ class BST_StoreSub : public BST_stmt { int vreg_slice = VREG_UNDEFINED; int vreg_value = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_StoreSub() : BST_stmt(BST_TYPE::StoreSub) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::StoreSub; + BSTFIXEDVREGS(StoreSub, BST_stmt) }; class BST_StoreSubSlice : public BST_stmt { @@ -313,12 +294,7 @@ class BST_StoreSubSlice : public BST_stmt { int vreg_lower = VREG_UNDEFINED, vreg_upper = VREG_UNDEFINED; int vreg_value = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_StoreSubSlice() : BST_stmt(BST_TYPE::StoreSubSlice) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::StoreSubSlice; + BSTFIXEDVREGS(StoreSubSlice, BST_stmt) }; class BST_LoadName : public BST_stmt_with_dest { @@ -333,12 +309,7 @@ class BST_LoadName : public BST_stmt_with_dest { // Only valid for lookup_type == CLOSURE: int closure_offset = -1; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_LoadName() : BST_stmt_with_dest(BST_TYPE::LoadName) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::LoadName; + BSTFIXEDVREGS(LoadName, BST_stmt_with_dest) }; class BST_LoadAttr : public BST_stmt_with_dest { @@ -347,12 +318,7 @@ class BST_LoadAttr : public BST_stmt_with_dest { int vreg_value = VREG_UNDEFINED; bool clsonly = false; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_LoadAttr() : BST_stmt_with_dest(BST_TYPE::LoadAttr) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::LoadAttr; + BSTFIXEDVREGS(LoadAttr, BST_stmt_with_dest) }; class BST_LoadSub : public BST_stmt_with_dest { @@ -360,12 +326,7 @@ class BST_LoadSub : public BST_stmt_with_dest { int vreg_value = VREG_UNDEFINED; int vreg_slice = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_LoadSub() : BST_stmt_with_dest(BST_TYPE::LoadSub) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::LoadSub; + BSTFIXEDVREGS(LoadSub, BST_stmt_with_dest) }; class BST_LoadSubSlice : public BST_stmt_with_dest { @@ -373,12 +334,7 @@ class BST_LoadSubSlice : public BST_stmt_with_dest { int vreg_value = VREG_UNDEFINED; int vreg_lower = VREG_UNDEFINED, vreg_upper = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_LoadSubSlice() : BST_stmt_with_dest(BST_TYPE::LoadSubSlice) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::LoadSubSlice; + BSTFIXEDVREGS(LoadSubSlice, BST_stmt_with_dest) }; class BST_AugBinOp : public BST_stmt_with_dest { @@ -386,12 +342,7 @@ class BST_AugBinOp : public BST_stmt_with_dest { AST_TYPE::AST_TYPE op_type; int vreg_left = VREG_UNDEFINED, vreg_right = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_AugBinOp() : BST_stmt_with_dest(BST_TYPE::AugBinOp) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::AugBinOp; + BSTFIXEDVREGS(AugBinOp, BST_stmt_with_dest) }; class BST_BinOp : public BST_stmt_with_dest { @@ -399,12 +350,7 @@ class BST_BinOp : public BST_stmt_with_dest { AST_TYPE::AST_TYPE op_type; int vreg_left = VREG_UNDEFINED, vreg_right = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_BinOp() : BST_stmt_with_dest(BST_TYPE::BinOp) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::BinOp; + BSTFIXEDVREGS(BinOp, BST_stmt_with_dest) }; class BST_Call : public BST_stmt_with_dest { @@ -425,11 +371,6 @@ class BST_CallFunc : public BST_Call { int vreg_func = VREG_UNDEFINED; int elts[1]; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::CallFunc; - BSTVARVREGS2CALL(CallFunc, num_args, num_keywords, elts) }; @@ -439,11 +380,6 @@ class BST_CallAttr : public BST_Call { InternedString attr; int elts[1]; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::CallAttr; - BSTVARVREGS2CALL(CallAttr, num_args, num_keywords, elts) }; @@ -453,11 +389,6 @@ class BST_CallClsAttr : public BST_Call { InternedString attr; int elts[1]; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::CallClsAttr; - BSTVARVREGS2CALL(CallClsAttr, num_args, num_keywords, elts) }; @@ -468,19 +399,11 @@ class BST_Compare : public BST_stmt_with_dest { int vreg_comparator = VREG_UNDEFINED; int vreg_left = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_Compare() : BST_stmt_with_dest(BST_TYPE::Compare) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::Compare; + BSTFIXEDVREGS(Compare, BST_stmt_with_dest) }; class BST_ClassDef : public BST_stmt { public: - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - BoxedCode* code; InternedString name; @@ -488,19 +411,12 @@ class BST_ClassDef : public BST_stmt { const int num_decorator; int decorator[1]; - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::ClassDef; - BSTVARVREGS(ClassDef, BST_stmt, num_decorator, decorator) }; class BST_Dict : public BST_stmt_with_dest { public: - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_Dict() : BST_stmt_with_dest(BST_TYPE::Dict) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::Dict; + BSTFIXEDVREGS(Dict, BST_stmt_with_dest) }; class BST_DeleteAttr : public BST_stmt { @@ -508,12 +424,7 @@ class BST_DeleteAttr : public BST_stmt { int vreg_value = VREG_UNDEFINED; InternedString attr; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_DeleteAttr() : BST_stmt(BST_TYPE::DeleteAttr) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::DeleteAttr; + BSTFIXEDVREGS(DeleteAttr, BST_stmt) }; class BST_DeleteName : public BST_stmt { @@ -527,13 +438,7 @@ class BST_DeleteName : public BST_stmt { // Only valid for lookup_type == CLOSURE: int closure_offset = -1; - - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_DeleteName() : BST_stmt(BST_TYPE::DeleteName) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::DeleteName; + BSTFIXEDVREGS(DeleteName, BST_stmt) }; class BST_DeleteSub : public BST_stmt { @@ -541,12 +446,7 @@ class BST_DeleteSub : public BST_stmt { int vreg_value = VREG_UNDEFINED; int vreg_slice = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_DeleteSub() : BST_stmt(BST_TYPE::DeleteSub) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::DeleteSub; + BSTFIXEDVREGS(DeleteSub, BST_stmt) }; class BST_DeleteSubSlice : public BST_stmt { @@ -555,12 +455,7 @@ class BST_DeleteSubSlice : public BST_stmt { int vreg_lower = VREG_UNDEFINED; int vreg_upper = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_DeleteSubSlice() : BST_stmt(BST_TYPE::DeleteSubSlice) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::DeleteSubSlice; + BSTFIXEDVREGS(DeleteSubSlice, BST_stmt) }; class BST_Exec : public BST_stmt { @@ -569,12 +464,7 @@ class BST_Exec : public BST_stmt { int vreg_globals = VREG_UNDEFINED; int vreg_locals = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_Exec() : BST_stmt(BST_TYPE::Exec) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::Exec; + BSTFIXEDVREGS(Exec, BST_stmt) }; class BST_FunctionDef : public BST_stmt { @@ -588,12 +478,6 @@ class BST_FunctionDef : public BST_stmt { int elts[1]; // decorators followed by defaults - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::FunctionDef; - BSTVARVREGS2(FunctionDef, BST_stmt, num_decorator, num_defaults, elts) }; @@ -602,11 +486,6 @@ class BST_List : public BST_stmt_with_dest { const int num_elts; int elts[1]; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::List; - BSTVARVREGS(List, BST_stmt_with_dest, num_elts, elts) }; @@ -614,12 +493,7 @@ class BST_Repr : public BST_stmt_with_dest { public: int vreg_value = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_Repr() : BST_stmt_with_dest(BST_TYPE::Repr) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::Repr; + BSTFIXEDVREGS(Repr, BST_stmt_with_dest) }; class BST_Print : public BST_stmt { @@ -628,12 +502,7 @@ class BST_Print : public BST_stmt { bool nl; int vreg_value = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_Print() : BST_stmt(BST_TYPE::Print) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::Print; + BSTFIXEDVREGS(Print, BST_stmt) }; class BST_Raise : public BST_stmt { @@ -644,24 +513,14 @@ class BST_Raise : public BST_stmt { // Ie "raise Exception()" will have type==Exception(), inst==None, tback==None int vreg_arg0 = VREG_UNDEFINED, vreg_arg1 = VREG_UNDEFINED, vreg_arg2 = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_Raise() : BST_stmt(BST_TYPE::Raise) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::Raise; + BSTFIXEDVREGS(Raise, BST_stmt) }; class BST_Return : public BST_stmt { public: int vreg_value = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_Return() : BST_stmt(BST_TYPE::Return) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::Return; + BSTFIXEDVREGS(Return, BST_stmt) }; class BST_Set : public BST_stmt_with_dest { @@ -669,11 +528,6 @@ class BST_Set : public BST_stmt_with_dest { const int num_elts; int elts[1]; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::Set; - BSTVARVREGS(Set, BST_stmt_with_dest, num_elts, elts) }; @@ -681,12 +535,7 @@ class BST_MakeSlice : public BST_stmt_with_dest { public: int vreg_lower = VREG_UNDEFINED, vreg_upper = VREG_UNDEFINED, vreg_step = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_MakeSlice() : BST_stmt_with_dest(BST_TYPE::MakeSlice) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::MakeSlice; + BSTFIXEDVREGS(MakeSlice, BST_stmt_with_dest) }; class BST_Tuple : public BST_stmt_with_dest { @@ -694,11 +543,6 @@ class BST_Tuple : public BST_stmt_with_dest { const int num_elts; int elts[1]; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::Tuple; - BSTVARVREGS(Tuple, BST_stmt_with_dest, num_elts, elts) }; @@ -707,54 +551,34 @@ class BST_UnaryOp : public BST_stmt_with_dest { int vreg_operand = VREG_UNDEFINED; AST_TYPE::AST_TYPE op_type; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_UnaryOp() : BST_stmt_with_dest(BST_TYPE::UnaryOp) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::UnaryOp; + BSTFIXEDVREGS(UnaryOp, BST_stmt_with_dest) }; class BST_Yield : public BST_stmt_with_dest { public: int vreg_value = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_Yield() : BST_stmt_with_dest(BST_TYPE::Yield) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::Yield; + BSTFIXEDVREGS(Yield, BST_stmt_with_dest) }; class BST_MakeFunction : public BST_stmt_with_dest { public: BST_FunctionDef* function_def; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - BST_MakeFunction(BST_FunctionDef* fd) : BST_stmt_with_dest(BST_TYPE::MakeFunction, fd->lineno), function_def(fd) {} - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::MakeFunction; + BSTNODE(MakeFunction) }; class BST_MakeClass : public BST_stmt_with_dest { public: BST_ClassDef* class_def; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - BST_MakeClass(BST_ClassDef* cd) : BST_stmt_with_dest(BST_TYPE::MakeClass, cd->lineno), class_def(cd) {} - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::MakeClass; + BSTNODE(MakeClass) }; - -// BST pseudo-nodes that will get added during CFG-construction. These don't exist in the input BST, but adding them in -// lets us avoid creating a completely new IR for this phase - class CFGBlock; class BST_Branch : public BST_stmt { @@ -762,24 +586,14 @@ class BST_Branch : public BST_stmt { int vreg_test = VREG_UNDEFINED; CFGBlock* iftrue, *iffalse; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_Branch() : BST_stmt(BST_TYPE::Branch) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::Branch; + BSTFIXEDVREGS(Branch, BST_stmt) }; class BST_Jump : public BST_stmt { public: CFGBlock* target; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_Jump() : BST_stmt(BST_TYPE::Jump) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::Jump; + BSTFIXEDVREGS(Jump, BST_stmt) }; class BST_Invoke : public BST_stmt { @@ -788,46 +602,28 @@ class BST_Invoke : public BST_stmt { CFGBlock* normal_dest, *exc_dest; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - BST_Invoke(BST_stmt* stmt) : BST_stmt(BST_TYPE::Invoke), stmt(stmt) {} - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::Invoke; + BSTNODE(Invoke) }; // grabs the info about the last raised exception class BST_Landingpad : public BST_stmt_with_dest { public: - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_Landingpad() : BST_stmt_with_dest(BST_TYPE::Landingpad) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::Landingpad; + BSTFIXEDVREGS(Landingpad, BST_stmt_with_dest) }; class BST_Locals : public BST_stmt_with_dest { public: - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_Locals() : BST_stmt_with_dest(BST_TYPE::Locals) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::Locals; + BSTFIXEDVREGS(Locals, BST_stmt_with_dest) }; class BST_GetIter : public BST_stmt_with_dest { public: int vreg_value = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_GetIter() : BST_stmt_with_dest(BST_TYPE::GetIter) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::GetIter; + BSTFIXEDVREGS(GetIter, BST_stmt_with_dest) }; class BST_ImportFrom : public BST_stmt_with_dest { @@ -835,12 +631,7 @@ class BST_ImportFrom : public BST_stmt_with_dest { int vreg_module = VREG_UNDEFINED; int vreg_name = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_ImportFrom() : BST_stmt_with_dest(BST_TYPE::ImportFrom) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::ImportFrom; + BSTFIXEDVREGS(ImportFrom, BST_stmt_with_dest) }; class BST_ImportName : public BST_stmt_with_dest { @@ -849,25 +640,14 @@ class BST_ImportName : public BST_stmt_with_dest { int level = VREG_UNDEFINED; int vreg_name = VREG_UNDEFINED; - - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_ImportName() : BST_stmt_with_dest(BST_TYPE::ImportName) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::ImportName; + BSTFIXEDVREGS(ImportName, BST_stmt_with_dest) }; class BST_ImportStar : public BST_stmt_with_dest { public: int vreg_name = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_ImportStar() : BST_stmt_with_dest(BST_TYPE::ImportStar) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::ImportStar; + BSTFIXEDVREGS(ImportStar, BST_stmt_with_dest) }; // determines whether something is "true" for purposes of `if' and so forth @@ -875,12 +655,7 @@ class BST_Nonzero : public BST_stmt_with_dest { public: int vreg_value = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_Nonzero() : BST_stmt_with_dest(BST_TYPE::Nonzero) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::Nonzero; + BSTFIXEDVREGS(Nonzero, BST_stmt_with_dest) }; class BST_CheckExcMatch : public BST_stmt_with_dest { @@ -888,12 +663,7 @@ class BST_CheckExcMatch : public BST_stmt_with_dest { int vreg_value = VREG_UNDEFINED; int vreg_cls = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_CheckExcMatch() : BST_stmt_with_dest(BST_TYPE::CheckExcMatch) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::CheckExcMatch; + BSTFIXEDVREGS(CheckExcMatch, BST_stmt_with_dest) }; class BST_SetExcInfo : public BST_stmt { @@ -902,46 +672,26 @@ class BST_SetExcInfo : public BST_stmt { int vreg_value = VREG_UNDEFINED; int vreg_traceback = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_SetExcInfo() : BST_stmt(BST_TYPE::SetExcInfo) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::SetExcInfo; + BSTFIXEDVREGS(SetExcInfo, BST_stmt) }; class BST_UncacheExcInfo : public BST_stmt { public: - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_UncacheExcInfo() : BST_stmt(BST_TYPE::UncacheExcInfo) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::UncacheExcInfo; + BSTFIXEDVREGS(UncacheExcInfo, BST_stmt) }; class BST_HasNext : public BST_stmt_with_dest { public: int vreg_value = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_HasNext() : BST_stmt_with_dest(BST_TYPE::HasNext) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::HasNext; + BSTFIXEDVREGS(HasNext, BST_stmt_with_dest) }; class BST_PrintExpr : public BST_stmt { public: int vreg_value = VREG_UNDEFINED; - virtual void accept(BSTVisitor* v); - virtual void accept_stmt(StmtVisitor* v); - - BST_PrintExpr() : BST_stmt(BST_TYPE::PrintExpr) {} - - static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::PrintExpr; + BSTFIXEDVREGS(PrintExpr, BST_stmt) }; @@ -1156,20 +906,20 @@ class StmtVisitor { virtual void visit_yield(BST_Yield* node) { RELEASE_ASSERT(0, ""); } }; -class ConstantVRegInfo; -void print_bst(BST_stmt* bst, const ConstantVRegInfo& constant_vregs); +class CodeConstants; +void print_bst(BST_stmt* bst, const CodeConstants& code_constants); class PrintVisitor : public BSTVisitor { private: llvm::raw_ostream& stream; - const ConstantVRegInfo& constant_vregs; + const CodeConstants& code_constants; int indent; void printIndent(); void printOp(AST_TYPE::AST_TYPE op_type); public: - PrintVisitor(const ConstantVRegInfo& constant_vregs, int indent, llvm::raw_ostream& stream) - : BSTVisitor(false /* visit child CFG */), stream(stream), constant_vregs(constant_vregs), indent(indent) {} + PrintVisitor(const CodeConstants& code_constants, int indent, llvm::raw_ostream& stream) + : BSTVisitor(false /* visit child CFG */), stream(stream), code_constants(code_constants), indent(indent) {} virtual ~PrintVisitor() {} void flush() { stream.flush(); } diff --git a/src/core/cfg.cpp b/src/core/cfg.cpp index 0c01f9a49..0f8233dec 100644 --- a/src/core/cfg.cpp +++ b/src/core/cfg.cpp @@ -27,6 +27,8 @@ #include "core/bst.h" #include "core/options.h" #include "core/types.h" +#include "runtime/complex.h" +#include "runtime/long.h" #include "runtime/objmodel.h" #include "runtime/types.h" @@ -185,7 +187,7 @@ void CFGBlock::unconnectFrom(CFGBlock* successor) { successor->predecessors.end()); } -void CFGBlock::print(const ConstantVRegInfo& constant_vregs, llvm::raw_ostream& stream) { +void CFGBlock::print(const CodeConstants& code_constants, llvm::raw_ostream& stream) { stream << "Block " << idx; if (info) stream << " '" << info << "'"; @@ -200,7 +202,7 @@ void CFGBlock::print(const ConstantVRegInfo& constant_vregs, llvm::raw_ostream& } stream << "\n"; - PrintVisitor pv(constant_vregs, 4, stream); + PrintVisitor pv(code_constants, 4, stream); for (int j = 0; j < body.size(); j++) { stream << " "; body[j]->accept(&pv); @@ -246,10 +248,10 @@ class ModuleCFGProcessor { AST* orig_node); }; -static std::pair computeCFG(llvm::ArrayRef body, AST_TYPE::AST_TYPE ast_type, - int lineno, AST_arguments* args, BoxedString* filename, - SourceInfo* source, const ParamNames& param_names, - ScopeInfo* scoping, ModuleCFGProcessor* cfgizer); +static std::pair computeCFG(llvm::ArrayRef body, AST_TYPE::AST_TYPE ast_type, + int lineno, AST_arguments* args, BoxedString* filename, + SourceInfo* source, const ParamNames& param_names, ScopeInfo* scoping, + ModuleCFGProcessor* cfgizer); // This keeps track of the result of an instruction it's either a name, const or undefined. struct TmpValue { @@ -362,15 +364,25 @@ class CFGVisitor : public ASTVisitor { CFGBlock* curblock; std::vector continuations; std::vector exc_handlers; + + // maps constants to their vreg number llvm::DenseMap consts; - ConstantVRegInfo constant_vregs; + CodeConstants code_constants; + + llvm::StringMap str_constants; + llvm::StringMap unicode_constants; + // I'm not sure how well it works to use doubles as hashtable keys; thankfully + // it's not a big deal if we get misses. + std::unordered_map imaginary_constants; + llvm::StringMap long_constants; + llvm::DenseMap interned_string_constants; unsigned int next_var_index = 0; - friend std::pair computeCFG(llvm::ArrayRef body, AST_TYPE::AST_TYPE ast_type, - int lineno, AST_arguments* args, BoxedString* filename, - SourceInfo* source, const ParamNames& param_names, - ScopeInfo* scoping, ModuleCFGProcessor* cfgizer); + friend std::pair computeCFG(llvm::ArrayRef body, AST_TYPE::AST_TYPE ast_type, + int lineno, AST_arguments* args, BoxedString* filename, + SourceInfo* source, const ParamNames& param_names, + ScopeInfo* scoping, ModuleCFGProcessor* cfgizer); public: CFGVisitor(BoxedString* filename, SourceInfo* source, InternedStringPool& stringpool, ScopeInfo* scoping, @@ -513,21 +525,44 @@ class CFGVisitor : public ASTVisitor { auto it = consts.find(o); if (it != consts.end()) return it->second; - int vreg = constant_vregs.addConstant(o); + int vreg = code_constants.createVRegEntryForConstant(o); consts[o] = vreg; return vreg; } + static int64_t getDoubleBits(double d) { + int64_t rtn; + static_assert(sizeof(rtn) == sizeof(d), ""); + memcpy(&rtn, &d, sizeof(d)); + return rtn; + } + + TmpValue makeNum(int64_t n, int lineno) { + Box* o = code_constants.getIntConstant(n); + int vreg_const = addConst(o); + return TmpValue(vreg_const, lineno); + } + TmpValue remapNum(AST_Num* num) { Box* o = NULL; if (num->num_type == AST_Num::INT) { - o = source->parent_module->getIntConstant(num->n_int); + o = code_constants.getIntConstant(num->n_int); } else if (num->num_type == AST_Num::FLOAT) { - o = source->parent_module->getFloatConstant(num->n_float); + o = code_constants.getFloatConstant(num->n_float); } else if (num->num_type == AST_Num::LONG) { - o = source->parent_module->getLongConstant(num->n_long); + Box*& r = long_constants[num->n_long]; + if (!r) { + r = createLong(num->n_long); + code_constants.addOwnedRef(r); + } + o = r; } else if (num->num_type == AST_Num::COMPLEX) { - o = source->parent_module->getPureImaginaryConstant(num->n_float); + Box*& r = imaginary_constants[getDoubleBits(num->n_float)]; + if (!r) { + r = createPureImaginary(num->n_float); + code_constants.addOwnedRef(r); + } + o = r; } else RELEASE_ASSERT(0, "not implemented"); @@ -535,23 +570,34 @@ class CFGVisitor : public ASTVisitor { return TmpValue(vreg_const, num->lineno); } + TmpValue makeStr(llvm::StringRef str, int lineno = 0) { + BoxedString*& o = str_constants[str]; + // we always intern the string + if (!o) { + o = internStringMortal(str); + code_constants.addOwnedRef(o); + } + int vreg_const = addConst(o); + return TmpValue(vreg_const, lineno); + } + TmpValue remapStr(AST_Str* str) { // TODO make this serializable - Box* o = NULL; if (str->str_type == AST_Str::STR) { - o = source->parent_module->getStringConstant(str->str_data, true); + return makeStr(str->str_data, str->lineno); } else if (str->str_type == AST_Str::UNICODE) { - o = source->parent_module->getUnicodeConstant(str->str_data); - } else { - RELEASE_ASSERT(0, "%d", str->str_type); + Box*& r = unicode_constants[str->str_data]; + if (!r) { + r = decodeUTF8StringPtr(str->str_data); + code_constants.addOwnedRef(r); + } + return TmpValue(addConst(r), str->lineno); } - - int vreg_const = addConst(o); - return TmpValue(vreg_const, str->lineno); + RELEASE_ASSERT(0, "%d", str->str_type); } TmpValue makeNum(int n, int lineno) { - Box* o = source->parent_module->getIntConstant(n); + Box* o = code_constants.getIntConstant(n); int vreg_const = addConst(o); return TmpValue(vreg_const, lineno); } @@ -561,12 +607,6 @@ class CFGVisitor : public ASTVisitor { return TmpValue(vreg_const, lineno); } - TmpValue makeStr(llvm::StringRef str, int lineno = 0) { - Box* o = source->parent_module->getStringConstant(str, true); - int vreg_const = addConst(o); - return TmpValue(vreg_const, lineno); - } - TmpValue applyComprehensionCall(AST_ListComp* node, TmpValue name) { TmpValue elt = remapExpr(node->elt); return makeCallAttr(name, internString("append"), true, { elt }); @@ -2855,11 +2895,11 @@ class CFGVisitor : public ASTVisitor { } }; -void CFG::print(const ConstantVRegInfo& constant_vregs, llvm::raw_ostream& stream) { +void CFG::print(const CodeConstants& code_constants, llvm::raw_ostream& stream) { stream << "CFG:\n"; stream << blocks.size() << " blocks\n"; for (int i = 0; i < blocks.size(); i++) - blocks[i]->print(constant_vregs, stream); + blocks[i]->print(code_constants, stream); stream.flush(); } @@ -3047,10 +3087,10 @@ void VRegInfo::assignVRegs(CFG* cfg, const ParamNames& param_names, llvm::DenseM } -static std::pair computeCFG(llvm::ArrayRef body, AST_TYPE::AST_TYPE ast_type, - int lineno, AST_arguments* args, BoxedString* filename, - SourceInfo* source, const ParamNames& param_names, - ScopeInfo* scoping, ModuleCFGProcessor* cfgizer) { +static std::pair computeCFG(llvm::ArrayRef body, AST_TYPE::AST_TYPE ast_type, + int lineno, AST_arguments* args, BoxedString* filename, + SourceInfo* source, const ParamNames& param_names, ScopeInfo* scoping, + ModuleCFGProcessor* cfgizer) { STAT_TIMER(t0, "us_timer_computecfg", 0); CFG* rtn = new CFG(); @@ -3139,7 +3179,7 @@ static std::pair computeCFG(llvm::ArrayRef bo if (VERBOSITY("cfg") >= 3) { printf("Before cfg checking and transformations:\n"); - rtn->print(visitor.constant_vregs); + rtn->print(visitor.code_constants); } #ifndef NDEBUG @@ -3167,7 +3207,7 @@ static std::pair computeCFG(llvm::ArrayRef bo if (b->predecessors.size() == 0) { if (b != rtn->getStartingBlock()) { - rtn->print(visitor.constant_vregs); + rtn->print(visitor.code_constants); } ASSERT(b == rtn->getStartingBlock(), "%d", b->idx); } @@ -3222,13 +3262,13 @@ static std::pair computeCFG(llvm::ArrayRef bo deduped[e]++; if (deduped[e] == 2) { printf("Duplicated: "); - print_bst(e, visitor.constant_vregs); + print_bst(e, visitor.code_constants); printf("\n"); no_dups = false; } } if (!no_dups) - rtn->print(visitor.constant_vregs); + rtn->print(visitor.code_constants); assert(no_dups); // Uncomment this for some heavy checking to make sure that we don't forget @@ -3331,10 +3371,10 @@ static std::pair computeCFG(llvm::ArrayRef bo if (VERBOSITY("cfg") >= 2) { printf("Final cfg:\n"); - rtn->print(visitor.constant_vregs, llvm::outs()); + rtn->print(visitor.code_constants, llvm::outs()); } - return std::make_pair(rtn, visitor.constant_vregs); + return std::make_pair(rtn, std::move(visitor.code_constants)); } @@ -3381,17 +3421,17 @@ BoxedCode* ModuleCFGProcessor::runRecursively(llvm::ArrayRef body, Bo for (auto e : param_names.allArgsAsName()) fillScopingInfo(e, scope_info); - ConstantVRegInfo constant_vregs; - std::tie(si->cfg, constant_vregs) + CodeConstants code_constants; + std::tie(si->cfg, code_constants) = computeCFG(body, ast_type, lineno, args, fn, si.get(), param_names, scope_info, this); BoxedCode* code; if (args) code = new BoxedCode(args->args.size(), args->vararg, args->kwarg, lineno, std::move(si), - std::move(constant_vregs), std::move(param_names), fn, name, + std::move(code_constants), std::move(param_names), fn, name, autoDecref(getDocString(body))); else - code = new BoxedCode(0, false, false, lineno, std::move(si), std::move(constant_vregs), std::move(param_names), + code = new BoxedCode(0, false, false, lineno, std::move(si), std::move(code_constants), std::move(param_names), fn, name, autoDecref(getDocString(body))); return code; @@ -3403,7 +3443,7 @@ BoxedCode* computeAllCFGs(AST* ast, bool globals_from_module, FutureFlags future .runRecursively(ast->getBody(), ast->getName(), ast->lineno, nullptr, ast); } -void printCFG(CFG* cfg, const ConstantVRegInfo& constant_vregs) { - cfg->print(constant_vregs); +void printCFG(CFG* cfg, const CodeConstants& code_constants) { + cfg->print(code_constants); } } diff --git a/src/core/cfg.h b/src/core/cfg.h index f24cb03f3..5183ed68f 100644 --- a/src/core/cfg.h +++ b/src/core/cfg.h @@ -88,7 +88,7 @@ class CFGBlock { void unconnectFrom(CFGBlock* successor); void push_back(BST_stmt* node) { body.push_back(node); } - void print(const ConstantVRegInfo& constant_vregs, llvm::raw_ostream& stream = llvm::outs()); + void print(const CodeConstants& code_constants, llvm::raw_ostream& stream = llvm::outs()); }; // the vregs are split into three parts. @@ -210,7 +210,7 @@ class CFG { blocks.push_back(block); } - void print(const ConstantVRegInfo& constant_vregs, llvm::raw_ostream& stream = llvm::outs()); + void print(const CodeConstants& code_constants, llvm::raw_ostream& stream = llvm::outs()); }; class VRegSet { @@ -331,7 +331,7 @@ template class VRegMap { BoxedCode* computeAllCFGs(AST* ast, bool globals_from_module, FutureFlags future_flags, BoxedString* fn, BoxedModule* bm); -void printCFG(CFG* cfg, const ConstantVRegInfo& constant_vregs); +void printCFG(CFG* cfg, const CodeConstants& code_constants); } #endif diff --git a/src/runtime/code.cpp b/src/runtime/code.cpp index 8144dac43..d8af81a8c 100644 --- a/src/runtime/code.cpp +++ b/src/runtime/code.cpp @@ -107,16 +107,18 @@ void BoxedCode::dealloc(Box* b) noexcept { Py_XDECREF(o->name); Py_XDECREF(o->_doc); + o->tryDeallocatingTheBJitCode(); o->source.reset(nullptr); + o->~BoxedCode(); o->cls->tp_free(o); } BoxedCode::BoxedCode(int num_args, bool takes_varargs, bool takes_kwargs, int firstlineno, - std::unique_ptr source, ConstantVRegInfo constant_vregs, ParamNames param_names, + std::unique_ptr source, CodeConstants code_constants, ParamNames param_names, BoxedString* filename, BoxedString* name, Box* doc) : source(std::move(source)), - constant_vregs(std::move(constant_vregs)), + code_constants(std::move(code_constants)), filename(incref(filename)), name(incref(name)), firstlineno(firstlineno), diff --git a/src/runtime/types.cpp b/src/runtime/types.cpp index 4fb66de34..7fe1fd628 100644 --- a/src/runtime/types.cpp +++ b/src/runtime/types.cpp @@ -480,68 +480,6 @@ std::string BoxedModule::name() { } } -BORROWED(BoxedString*) BoxedModule::getStringConstant(llvm::StringRef ast_str, bool intern) { - BoxedString*& r = str_constants[ast_str]; - if (intern) { - // If we had previously created a box for this string, we have to create a new - // string (or at least, be prepared to return a different value that we had already - // interned). This is fine, except we have to be careful because we promised - // that we would keep the previously-created string alive. - // So, make sure to put it onto the keep_alive list. - if (r && !PyString_CHECK_INTERNED(r)) { - RELEASE_ASSERT(0, "this codepath has been dead for a little while, make sure it still works"); - keep_alive.push_back(r); - r = NULL; - } - if (!r) - r = internStringMortal(ast_str); - } else if (!r) - r = boxString(ast_str); - return r; -} - -BORROWED(Box*) BoxedModule::getUnicodeConstant(llvm::StringRef ast_str) { - Box*& r = unicode_constants[ast_str]; - if (!r) - r = decodeUTF8StringPtr(ast_str); - return r; -} - -BORROWED(BoxedInt*) BoxedModule::getIntConstant(int64_t n) { - BoxedInt*& r = int_constants[n]; - if (!r) - r = (BoxedInt*)boxInt(n); - return r; -} - -static int64_t getDoubleBits(double d) { - int64_t rtn; - static_assert(sizeof(rtn) == sizeof(d), ""); - memcpy(&rtn, &d, sizeof(d)); - return rtn; -} - -BORROWED(BoxedFloat*) BoxedModule::getFloatConstant(double d) { - BoxedFloat*& r = float_constants[getDoubleBits(d)]; - if (!r) - r = static_cast(boxFloat(d)); - return r; -} - -BORROWED(Box*) BoxedModule::getPureImaginaryConstant(double d) { - Box*& r = imaginary_constants[getDoubleBits(d)]; - if (!r) - r = createPureImaginary(d); - return r; -} - -BORROWED(Box*) BoxedModule::getLongConstant(llvm::StringRef ast_str) { - Box*& r = long_constants[ast_str]; - if (!r) - r = createLong(ast_str); - return r; -} - // This mustn't throw; our IR generator generates calls to it without "invoke" even when there are exception handlers / // finally-blocks in scope. extern "C" Box* createFunctionFromMetadata(BoxedCode* code, BoxedClosure* closure, Box* globals, @@ -3817,21 +3755,12 @@ void BoxedModule::dealloc(Box* b) noexcept { BoxedModule::clear(self); - self->str_constants.~ContiguousMap(); - self->unicode_constants.~ContiguousMap(); - self->int_constants.~ContiguousMap(); - self->float_constants.~ContiguousMap(); - self->imaginary_constants.~ContiguousMap(); - self->long_constants.~ContiguousMap(); - assert(!self->keep_alive.size()); - b->cls->tp_free(self); } int BoxedModule::traverse(Box* _m, visitproc visit, void* arg) noexcept { BoxedModule* m = static_cast(_m); Py_TRAVERSE(m->attrs); - assert(!m->keep_alive.size()); return 0; } @@ -3849,15 +3778,6 @@ extern "C" void _PyModule_Clear(PyObject* b) noexcept { HCAttrs* attrs = self->getHCAttrsPtr(); attrs->moduleClear(); - - clearContiguousMap(self->str_constants); - clearContiguousMap(self->unicode_constants); - clearContiguousMap(self->int_constants); - clearContiguousMap(self->float_constants); - clearContiguousMap(self->imaginary_constants); - clearContiguousMap(self->long_constants); - - assert(!self->keep_alive.size()); } int BoxedModule::clear(Box* b) noexcept { @@ -4102,6 +4022,33 @@ int BoxedClosure::clear(Box* _o) noexcept { return 0; } +BORROWED(BoxedInt*) CodeConstants::getIntConstant(int64_t n) const { + BoxedInt*& r = int_constants[n]; + if (!r) { + r = (BoxedInt*)boxInt(n); + addOwnedRef(r); + } + return r; +} + +BORROWED(BoxedFloat*) CodeConstants::getFloatConstant(double d) const { + int64_t double_as_int64; + static_assert(sizeof(double_as_int64) == sizeof(d), ""); + memcpy(&double_as_int64, &d, sizeof(d)); + + BoxedFloat*& r = float_constants[double_as_int64]; + if (!r) { + r = (BoxedFloat*)boxFloat(d); + addOwnedRef(r); + } + return r; +} + +void CodeConstants::dealloc() const { + decrefArray(owned_refs.data(), owned_refs.size()); + owned_refs.clear(); +} + #ifndef Py_REF_DEBUG #define PRINT_TOTAL_REFS() #else /* Py_REF_DEBUG */ diff --git a/src/runtime/types.h b/src/runtime/types.h index 6054c876e..10f7cfb4f 100644 --- a/src/runtime/types.h +++ b/src/runtime/types.h @@ -1070,20 +1070,42 @@ class BoxedDict : public Box { }; static_assert(sizeof(BoxedDict) == sizeof(PyDictObject), ""); -class ConstantVRegInfo { +class CodeConstants { private: + // stores all constants accessible by vregs in the corrext order + // constants[-(vreg + 1)] will allow one to retrieve the constant for a vreg std::vector constants; + // all objects we need to decref when the code object dies + mutable std::vector owned_refs; + + // Note: DenseMap doesn't work here since we don't prevent the tombstone/empty + // keys from reaching it. + mutable std::unordered_map int_constants; + // I'm not sure how well it works to use doubles as hashtable keys; thankfully + // it's not a big deal if we get misses. + mutable std::unordered_map float_constants; + public: - ConstantVRegInfo(){}; + CodeConstants() {} + CodeConstants(CodeConstants&&) = default; + CodeConstants& operator=(CodeConstants&&) = default; + ~CodeConstants() { dealloc(); } - Box* getConstant(int vreg) const { return constants[-(vreg + 1)]; } + BORROWED(Box*) getConstant(int vreg) const { return constants[-(vreg + 1)]; } // returns the vreg num for the constant (which is a negative number) - int addConstant(Box* o) { + int createVRegEntryForConstant(Box* o) { constants.push_back(o); return -constants.size(); } + + void addOwnedRef(Box* o) const { owned_refs.emplace_back(o); } + + BORROWED(BoxedInt*) getIntConstant(int64_t n) const; + BORROWED(BoxedFloat*) getFloatConstant(double d) const; + + void dealloc() const; }; @@ -1095,8 +1117,8 @@ class ConstantVRegInfo { // BoxedCode objects also keep track of any machine code that we have available for this function. class BoxedCode : public Box { public: - std::unique_ptr source; // source can be NULL for functions defined in the C/C++ runtime - const ConstantVRegInfo BORROWED(constant_vregs); // keeps track of all constants inside the bytecode + std::unique_ptr source; // source can be NULL for functions defined in the C/C++ runtime + const CodeConstants BORROWED(code_constants); // keeps track of all constants inside the bytecode BoxedString* filename = nullptr; BoxedString* name = nullptr; @@ -1135,8 +1157,7 @@ class BoxedCode : public Box { // Constructor for Python code objects: BoxedCode(int num_args, bool takes_varargs, bool takes_kwargs, int firstlineno, std::unique_ptr source, - ConstantVRegInfo constant_vregs, ParamNames param_names, BoxedString* filename, BoxedString* name, - Box* doc); + CodeConstants code_constants, ParamNames param_names, BoxedString* filename, BoxedString* name, Box* doc); // Constructor for code objects created by the runtime: BoxedCode(int num_args, bool takes_varargs, bool takes_kwargs, const char* name, const char* doc = "", diff --git a/src/runtime/util.cpp b/src/runtime/util.cpp index 6f2382a33..f519436ea 100644 --- a/src/runtime/util.cpp +++ b/src/runtime/util.cpp @@ -254,7 +254,7 @@ extern "C" void dumpEx(void* p, int levels) { printf("Defined at %s:%d\n", code->filename->c_str(), code->firstlineno); if (code->source->cfg && levels > 0) { - code->source->cfg->print(code->constant_vregs); + code->source->cfg->print(code->code_constants); } } else { printf("A builtin function\n");