Commit ceb6517e authored by Marius Wachtler's avatar Marius Wachtler

VRegInfo: reduce memory usage

parent a4e6f099
...@@ -155,9 +155,12 @@ public: ...@@ -155,9 +155,12 @@ public:
~ASTInterpreter() { Py_XDECREF(this->created_closure); } ~ASTInterpreter() { Py_XDECREF(this->created_closure); }
const VRegInfo& getVRegInfo() const { return source_info->cfg->getVRegInfo(); } const VRegInfo& getVRegInfo() const { return source_info->cfg->getVRegInfo(); }
#ifndef NDEBUG
const llvm::DenseMap<InternedString, DefaultedInt<-1>>& getSymVRegMap() const { const llvm::DenseMap<InternedString, DefaultedInt<-1>>& getSymVRegMap() const {
return source_info->cfg->getVRegInfo().getSymVRegMap(); return getVRegInfo().getSymVRegMap();
} }
#endif
AST_stmt* getCurrentStatement() { AST_stmt* getCurrentStatement() {
assert(frame_info.stmt); assert(frame_info.stmt);
...@@ -755,12 +758,13 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) { ...@@ -755,12 +758,13 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
= computeRequiredPhis(getMD()->param_names, source_info->cfg, liveness, scope_info); = computeRequiredPhis(getMD()->param_names, source_info->cfg, liveness, scope_info);
llvm::SmallVector<int, 16> dead_vregs; llvm::SmallVector<int, 16> dead_vregs;
for (auto&& sym : getSymVRegMap()) {
if (!liveness->isLiveAtEnd(sym.second, current_block)) { for (int vreg = 0; vreg < getVRegInfo().getTotalNumOfVRegs(); ++vreg) {
dead_vregs.push_back(sym.second); if (!liveness->isLiveAtEnd(vreg, current_block)) {
} else if (phis->isRequiredAfter(sym.second, current_block)) { dead_vregs.push_back(vreg);
assert(scope_info->getScopeTypeOfName(sym.first) != ScopeInfo::VarScopeType::GLOBAL); } else if (phis->isRequiredAfter(vreg, current_block)) {
} else { assert(!getVRegInfo().vregHasName(vreg)
|| scope_info->getScopeTypeOfName(getVRegInfo().getName(vreg)) != ScopeInfo::VarScopeType::GLOBAL);
} }
} }
for (auto&& vreg_num : dead_vregs) { for (auto&& vreg_num : dead_vregs) {
......
...@@ -2663,18 +2663,6 @@ private: ...@@ -2663,18 +2663,6 @@ private:
} }
} }
void loadArgument(InternedString name, ConcreteCompilerType* t, llvm::Value* v, const UnwindInfo& unw_info) {
assert(name.s() != FRAME_INFO_PTR_NAME);
CompilerVariable* var = unboxVar(t, v);
auto cfg = irstate->getSourceInfo()->cfg;
auto vst = irstate->getScopeInfo()->getScopeTypeOfName(name);
int vreg = -1;
if (vst == ScopeInfo::VarScopeType::FAST || vst == ScopeInfo::VarScopeType::CLOSURE) {
vreg = cfg->getVRegInfo().getVReg(name);
}
_doSet(vreg, name, vst, var, unw_info);
}
void loadArgument(AST_expr* name, ConcreteCompilerType* t, llvm::Value* v, const UnwindInfo& unw_info) { void loadArgument(AST_expr* name, ConcreteCompilerType* t, llvm::Value* v, const UnwindInfo& unw_info) {
CompilerVariable* var = unboxVar(t, v); CompilerVariable* var = unboxVar(t, v);
_doSet(name, var, unw_info); _doSet(name, var, unw_info);
...@@ -2882,6 +2870,7 @@ public: ...@@ -2882,6 +2870,7 @@ public:
setDefinedVar(vreg, val); setDefinedVar(vreg, val);
} }
#ifndef NDEBUG
void giveLocalSymbol(InternedString name, CompilerVariable* var) override { void giveLocalSymbol(InternedString name, CompilerVariable* var) override {
assert(name.s() != "None"); assert(name.s() != "None");
assert(name.s() != FRAME_INFO_PTR_NAME); assert(name.s() != FRAME_INFO_PTR_NAME);
...@@ -2895,6 +2884,7 @@ public: ...@@ -2895,6 +2884,7 @@ public:
int vreg = irstate->getSourceInfo()->cfg->getVRegInfo().getVReg(name); int vreg = irstate->getSourceInfo()->cfg->getVRegInfo().getVReg(name);
giveLocalSymbol(vreg, var); giveLocalSymbol(vreg, var);
} }
#endif
void giveLocalSymbol(int vreg, CompilerVariable* var) override { void giveLocalSymbol(int vreg, CompilerVariable* var) override {
assert(var->getType()->isUsable()); assert(var->getType()->isUsable());
...@@ -2994,13 +2984,11 @@ public: ...@@ -2994,13 +2984,11 @@ public:
int i = 0; int i = 0;
for (; i < param_names.args.size(); i++) { for (; i < param_names.args.size(); i++) {
loadArgument(internString(param_names.args[i]), arg_types[i], python_parameters[i], loadArgument(param_names.arg_names[i], arg_types[i], python_parameters[i], UnwindInfo::cantUnwind());
UnwindInfo::cantUnwind());
} }
if (param_names.vararg.size()) { if (param_names.vararg.size()) {
loadArgument(internString(param_names.vararg), arg_types[i], python_parameters[i], loadArgument(param_names.vararg_name, arg_types[i], python_parameters[i], UnwindInfo::cantUnwind());
UnwindInfo::cantUnwind());
i++; i++;
} }
...@@ -3030,7 +3018,7 @@ public: ...@@ -3030,7 +3018,7 @@ public:
emitter.refConsumed(passed_dict, null_check); emitter.refConsumed(passed_dict, null_check);
emitter.refConsumed(created_dict, isnull_terminator); emitter.refConsumed(created_dict, isnull_terminator);
loadArgument(internString(param_names.kwarg), arg_types[i], phi, UnwindInfo::cantUnwind()); loadArgument(param_names.kwarg_name, arg_types[i], phi, UnwindInfo::cantUnwind());
i++; i++;
} }
......
...@@ -179,7 +179,9 @@ public: ...@@ -179,7 +179,9 @@ public:
virtual void doFunctionEntry(const ParamNames& param_names, const std::vector<ConcreteCompilerType*>& arg_types) virtual void doFunctionEntry(const ParamNames& param_names, const std::vector<ConcreteCompilerType*>& arg_types)
= 0; = 0;
#ifndef NDEBUG
virtual void giveLocalSymbol(InternedString name, CompilerVariable* var) = 0; virtual void giveLocalSymbol(InternedString name, CompilerVariable* var) = 0;
#endif
virtual void giveLocalSymbol(int vreg, CompilerVariable* var) = 0; virtual void giveLocalSymbol(int vreg, CompilerVariable* var) = 0;
virtual void giveDefinednessVar(int vreg, llvm::Value* val) = 0; virtual void giveDefinednessVar(int vreg, llvm::Value* val) = 0;
virtual void copySymbolsFrom(SymbolTable* st) = 0; virtual void copySymbolsFrom(SymbolTable* st) = 0;
......
...@@ -890,15 +890,16 @@ DeoptState getDeoptState() { ...@@ -890,15 +890,16 @@ DeoptState getDeoptState() {
// and assigning them to the new vregs array... // and assigning them to the new vregs array...
// But deopts are so rare it's not really worth it. // But deopts are so rare it's not really worth it.
Box** vregs = frame_iter->getFrameInfo()->vregs; Box** vregs = frame_iter->getFrameInfo()->vregs;
for (const auto& p : cf->md->source->cfg->getVRegInfo().getUserVisibleSymVRegMap()) { int num_vregs_user_visible = cf->md->source->cfg->getVRegInfo().getNumOfUserVisibleVRegs();
if (is_undefined.count(p.second)) for (int vreg = 0; vreg < num_vregs_user_visible; ++vreg) {
if (is_undefined.count(vreg))
assert(0); assert(0);
Box* v = vregs[p.second]; Box* v = vregs[vreg];
if (!v) if (!v)
continue; continue;
d->d[boxInt(p.second)] = incref(v); d->d[boxInt(vreg)] = incref(v);
} }
for (const auto& p : cf->location_map->vars) { for (const auto& p : cf->location_map->vars) {
...@@ -930,12 +931,14 @@ BORROWED(Box*) fastLocalsToBoxedLocals() { ...@@ -930,12 +931,14 @@ BORROWED(Box*) fastLocalsToBoxedLocals() {
static BoxedDict* localsForFrame(Box** vregs, CFG* cfg) { static BoxedDict* localsForFrame(Box** vregs, CFG* cfg) {
BoxedDict* rtn = new BoxedDict(); BoxedDict* rtn = new BoxedDict();
rtn->d.grow(cfg->getVRegInfo().getNumOfUserVisibleVRegs()); auto vregs_sym_map = cfg->getVRegInfo().getVRegSymUserVisibleMap();
for (auto& l : cfg->getVRegInfo().getUserVisibleSymVRegMap()) { int num_user_visible_vregs = vregs_sym_map.size();
Box* val = vregs[l.second]; rtn->d.grow(num_user_visible_vregs);
for (int vreg = 0; vreg < num_user_visible_vregs; ++vreg) {
Box* val = vregs[vreg];
if (val) { if (val) {
assert(!rtn->d.count(l.first.getBox())); assert(!rtn->d.count(vregs_sym_map[vreg].getBox()));
rtn->d[incref(l.first.getBox())] = incref(val); rtn->d[incref(vregs_sym_map[vreg].getBox())] = incref(val);
} }
} }
return rtn; return rtn;
......
...@@ -2847,12 +2847,17 @@ void VRegInfo::assignVRegs(CFG* cfg, const ParamNames& param_names, ScopeInfo* s ...@@ -2847,12 +2847,17 @@ void VRegInfo::assignVRegs(CFG* cfg, const ParamNames& param_names, ScopeInfo* s
num_vregs = std::max(num_vregs, visitor.next_vreg); num_vregs = std::max(num_vregs, visitor.next_vreg);
} }
if (step == AssignVRegsVisitor::UserVisible) if (step == AssignVRegsVisitor::UserVisible) {
num_vregs_user_visible = visitor.sym_vreg_map.size();
#ifndef NDEBUG
sym_vreg_map_user_visible = visitor.sym_vreg_map; sym_vreg_map_user_visible = visitor.sym_vreg_map;
else if (step == AssignVRegsVisitor::CrossBlock) #endif
} else if (step == AssignVRegsVisitor::CrossBlock)
num_vregs = num_vregs_cross_block = visitor.next_vreg; num_vregs = num_vregs_cross_block = visitor.next_vreg;
} }
#ifndef NDEBUG
sym_vreg_map = std::move(visitor.sym_vreg_map); sym_vreg_map = std::move(visitor.sym_vreg_map);
#endif
vreg_sym_map = std::move(visitor.vreg_sym_map); vreg_sym_map = std::move(visitor.vreg_sym_map);
assert(hasVRegsAssigned()); assert(hasVRegsAssigned());
#if REUSE_VREGS #if REUSE_VREGS
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <vector> #include <vector>
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h" #include "llvm/ADT/BitVector.h"
#include "core/ast.h" #include "core/ast.h"
...@@ -107,21 +108,26 @@ public: ...@@ -107,21 +108,26 @@ public:
// llvm jit : [user visible] // llvm jit : [user visible]
class VRegInfo { class VRegInfo {
private: private:
#ifndef NDEBUG
// this maps use too much memory, we only use them in the debug build for asserts
llvm::DenseMap<InternedString, DefaultedInt<-1>> sym_vreg_map_user_visible; llvm::DenseMap<InternedString, DefaultedInt<-1>> sym_vreg_map_user_visible;
llvm::DenseMap<InternedString, DefaultedInt<-1>> sym_vreg_map; llvm::DenseMap<InternedString, DefaultedInt<-1>> sym_vreg_map;
#endif
// Reverse map, from vreg->symbol name. // Reverse map, from vreg->symbol name.
// Entries won't exist for all vregs // Entries won't exist for all vregs (=no entries for reused vregs)
std::vector<InternedString> vreg_sym_map; std::vector<InternedString> vreg_sym_map;
int num_vregs_cross_block = -1; int num_vregs_cross_block = -1;
int num_vregs_user_visible = -1;
int num_vregs = -1; int num_vregs = -1;
public: public:
#ifndef NDEBUG
// map of all assigned names. if the name is block local the vreg number is not unique because this vregs get reused // map of all assigned names. if the name is block local the vreg number is not unique because this vregs get reused
// between blocks. // between blocks.
const llvm::DenseMap<InternedString, DefaultedInt<-1>>& getSymVRegMap() { return sym_vreg_map; } const llvm::DenseMap<InternedString, DefaultedInt<-1>>& getSymVRegMap() const { return sym_vreg_map; }
const llvm::DenseMap<InternedString, DefaultedInt<-1>>& getUserVisibleSymVRegMap() { const llvm::DenseMap<InternedString, DefaultedInt<-1>>& getUserVisibleSymVRegMap() const {
return sym_vreg_map_user_visible; return sym_vreg_map_user_visible;
} }
...@@ -133,6 +139,11 @@ public: ...@@ -133,6 +139,11 @@ public:
assert(it->second != -1); assert(it->second != -1);
return it->second; return it->second;
} }
#endif
llvm::ArrayRef<InternedString> getVRegSymUserVisibleMap() const {
return llvm::makeArrayRef(vreg_sym_map).slice(0, num_vregs_user_visible);
}
// Not all vregs correspond to a name; many are our compiler-generated variables. // Not all vregs correspond to a name; many are our compiler-generated variables.
bool vregHasName(int vreg) const { return vreg < num_vregs_cross_block; } bool vregHasName(int vreg) const { return vreg < num_vregs_cross_block; }
...@@ -149,12 +160,12 @@ public: ...@@ -149,12 +160,12 @@ public:
return vreg_sym_map[vreg]; return vreg_sym_map[vreg];
} }
bool isUserVisibleVReg(int vreg) const { return vreg < sym_vreg_map_user_visible.size(); } bool isUserVisibleVReg(int vreg) const { return vreg < num_vregs_user_visible; }
bool isCrossBlockVReg(int vreg) const { return !isUserVisibleVReg(vreg) && vreg < num_vregs_cross_block; } bool isCrossBlockVReg(int vreg) const { return !isUserVisibleVReg(vreg) && vreg < num_vregs_cross_block; }
bool isBlockLocalVReg(int vreg) const { return vreg >= num_vregs_cross_block; } bool isBlockLocalVReg(int vreg) const { return vreg >= num_vregs_cross_block; }
int getTotalNumOfVRegs() const { return num_vregs; } int getTotalNumOfVRegs() const { return num_vregs; }
int getNumOfUserVisibleVRegs() const { return sym_vreg_map_user_visible.size(); } int getNumOfUserVisibleVRegs() const { return num_vregs_user_visible; }
int getNumOfCrossBlockVRegs() const { return num_vregs_cross_block; } int getNumOfCrossBlockVRegs() const { return num_vregs_cross_block; }
bool hasVRegsAssigned() const { return num_vregs != -1; } bool hasVRegsAssigned() const { return num_vregs != -1; }
......
...@@ -24,6 +24,8 @@ protected: ...@@ -24,6 +24,8 @@ protected:
} }
}; };
// this test use functions (VRegInfo::getVReg) which are only available in a debug build
#ifndef NDEBUG
TEST_F(AnalysisTest, augassign) { TEST_F(AnalysisTest, augassign) {
const std::string fn("test/unittests/analysis_listcomp.py"); const std::string fn("test/unittests/analysis_listcomp.py");
AST_Module* module = caching_parse_file(fn.c_str(), 0); AST_Module* module = caching_parse_file(fn.c_str(), 0);
...@@ -146,3 +148,4 @@ TEST_F(AnalysisTest, osr1) { ...@@ -146,3 +148,4 @@ TEST_F(AnalysisTest, osr1) {
TEST_F(AnalysisTest, osr2) { TEST_F(AnalysisTest, osr2) {
doOsrTest(true, true); doOsrTest(true, true);
} }
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment