Commit 1923d116 authored by Kevin Modzelewski's avatar Kevin Modzelewski Committed by GitHub

Merge pull request #1277 from kmod/vregs_everywhere

Switch almost everything to use vregs when possible
parents 44ccbe1b a044540d
...@@ -337,7 +337,7 @@ STDOBJECT_SRCS := \ ...@@ -337,7 +337,7 @@ STDOBJECT_SRCS := \
iterobject.c \ iterobject.c \
bufferobject.c \ bufferobject.c \
cobject.c \ cobject.c \
dictproxy.c \ descrobject.c \
$(EXTRA_STDOBJECT_SRCS) $(EXTRA_STDOBJECT_SRCS)
STDPYTHON_SRCS := \ STDPYTHON_SRCS := \
......
This diff is collapsed.
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "analysis/function_analysis.h"
#include "core/cfg.h" #include "core/cfg.h"
#include "core/common.h" #include "core/common.h"
#include "core/options.h" #include "core/options.h"
...@@ -29,13 +30,12 @@ namespace pyston { ...@@ -29,13 +30,12 @@ namespace pyston {
template <typename T> class BBAnalyzer { template <typename T> class BBAnalyzer {
public: public:
typedef llvm::DenseMap<InternedString, T> Map; typedef VRegMap<T> Map;
typedef llvm::DenseMap<CFGBlock*, Map> AllMap; typedef llvm::DenseMap<CFGBlock*, Map> AllMap;
virtual ~BBAnalyzer() {} virtual ~BBAnalyzer() {}
virtual T merge(T from, T into) const = 0; virtual T merge(T from, T into) const = 0;
virtual T mergeBlank(T into) const = 0;
virtual void processBB(Map& starting, CFGBlock* block) const = 0; virtual void processBB(Map& starting, CFGBlock* block) const = 0;
}; };
...@@ -56,10 +56,12 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init ...@@ -56,10 +56,12 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init
assert(!starting_states.size()); assert(!starting_states.size());
assert(!ending_states.size()); assert(!ending_states.size());
int num_vregs = initial_map.numVregs();
llvm::SmallPtrSet<CFGBlock*, 32> in_queue; llvm::SmallPtrSet<CFGBlock*, 32> in_queue;
std::priority_queue<CFGBlock*, llvm::SmallVector<CFGBlock*, 32>, CFGBlockMinIndex> q; std::priority_queue<CFGBlock*, llvm::SmallVector<CFGBlock*, 32>, CFGBlockMinIndex> q;
starting_states.insert(make_pair(initial_block, std::move(initial_map))); starting_states.insert(std::make_pair(initial_block, std::move(initial_map)));
q.push(initial_block); q.push(initial_block);
in_queue.insert(initial_block); in_queue.insert(initial_block);
...@@ -70,9 +72,10 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init ...@@ -70,9 +72,10 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init
q.pop(); q.pop();
in_queue.erase(block); in_queue.erase(block);
Map& initial = starting_states[block]; assert(starting_states.count(block));
Map& initial = starting_states.find(block)->second;
if (VERBOSITY("analysis") >= 2) if (VERBOSITY("analysis") >= 2)
printf("fpc on block %d - %d entries\n", block->idx, initial.size()); printf("fpc on block %d - %d entries\n", block->idx, initial.numVregs());
Map ending = Map(initial); Map ending = Map(initial);
...@@ -87,43 +90,34 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init ...@@ -87,43 +90,34 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init
initial = true; initial = true;
} }
Map& next = starting_states[next_block]; auto it = starting_states.find(next_block);
for (const auto& p : ending) { if (it == starting_states.end())
if (next.count(p.first) == 0) { it = starting_states.insert(std::make_pair(next_block, Map(num_vregs))).first;
changed = true;
if (initial) { Map& next = it->second;
next[p.first] = p.second; // merge ending->next
} else { for (int vreg = 0; vreg < num_vregs; vreg++) {
next[p.first] = analyzer.mergeBlank(p.second); T& next_elt = next[vreg];
}
} else { T new_elt = analyzer.merge(ending[vreg], next_elt);
T& next_elt = next[p.first];
T new_elt = analyzer.merge(p.second, next_elt);
if (next_elt != new_elt) { if (next_elt != new_elt) {
next_elt = new_elt; next_elt = new_elt;
changed = true; changed = true;
} }
} }
}
for (const auto& p : next) { #ifndef NDEBUG
if (ending.count(p.first)) assert(next.numVregs() == ending.numVregs());
continue; #endif
T next_elt = analyzer.mergeBlank(p.second);
if (next_elt != p.second) {
next[p.first] = next_elt;
changed = true;
}
}
if (changed && in_queue.insert(next_block).second) { if (changed && in_queue.insert(next_block).second) {
q.push(next_block); q.push(next_block);
} }
} }
ending_states[block] = std::move(ending); ending_states.erase(block);
ending_states.insert(std::make_pair(block, std::move(ending)));
} }
if (VERBOSITY("analysis")) { if (VERBOSITY("analysis")) {
......
This diff is collapsed.
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/DenseSet.h"
#include "core/cfg.h"
#include "core/stringpool.h" #include "core/stringpool.h"
#include "core/types.h" #include "core/types.h"
...@@ -41,7 +42,7 @@ private: ...@@ -41,7 +42,7 @@ private:
typedef llvm::DenseMap<CFGBlock*, std::unique_ptr<LivenessBBVisitor>> LivenessCacheMap; typedef llvm::DenseMap<CFGBlock*, std::unique_ptr<LivenessBBVisitor>> LivenessCacheMap;
LivenessCacheMap liveness_cache; LivenessCacheMap liveness_cache;
llvm::DenseMap<InternedString, llvm::DenseMap<CFGBlock*, bool>> result_cache; VRegMap<llvm::DenseMap<CFGBlock*, bool>> result_cache;
public: public:
LivenessAnalysis(CFG* cfg); LivenessAnalysis(CFG* cfg);
...@@ -50,60 +51,59 @@ public: ...@@ -50,60 +51,59 @@ public:
// we don't keep track of node->parent_block relationships, so you have to pass both: // we don't keep track of node->parent_block relationships, so you have to pass both:
bool isKill(AST_Name* node, CFGBlock* parent_block); bool isKill(AST_Name* node, CFGBlock* parent_block);
bool isLiveAtEnd(InternedString name, CFGBlock* block); bool isLiveAtEnd(int vreg, CFGBlock* block);
}; };
class PhiAnalysis; class PhiAnalysis;
class DefinednessAnalysis { class DefinednessAnalysis {
public: public:
enum DefinitionLevel { enum DefinitionLevel : char {
Unknown,
Undefined, Undefined,
PotentiallyDefined, PotentiallyDefined,
Defined, Defined,
}; };
typedef llvm::DenseSet<InternedString> RequiredSet;
private: private:
llvm::DenseMap<CFGBlock*, llvm::DenseMap<InternedString, DefinitionLevel>> defined_at_beginning, defined_at_end; llvm::DenseMap<CFGBlock*, VRegMap<DefinitionLevel>> defined_at_beginning, defined_at_end;
llvm::DenseMap<CFGBlock*, RequiredSet> defined_at_end_sets; llvm::DenseMap<CFGBlock*, VRegSet> defined_at_end_sets;
public: public:
DefinednessAnalysis() {} DefinednessAnalysis() {}
void run(llvm::DenseMap<InternedString, DefinitionLevel> initial_map, CFGBlock* initial_block, void run(VRegMap<DefinitionLevel> initial_map, CFGBlock* initial_block, ScopeInfo* scope_info);
ScopeInfo* scope_info);
DefinitionLevel isDefinedAtEnd(InternedString name, CFGBlock* block); DefinitionLevel isDefinedAtEnd(int vreg, CFGBlock* block);
const RequiredSet& getDefinedNamesAtEnd(CFGBlock* block); const VRegSet& getDefinedVregsAtEnd(CFGBlock* block);
friend class PhiAnalysis; friend class PhiAnalysis;
}; };
class PhiAnalysis { class PhiAnalysis {
public: public:
typedef llvm::DenseSet<InternedString> RequiredSet;
DefinednessAnalysis definedness; DefinednessAnalysis definedness;
VRegSet empty_set;
private: private:
LivenessAnalysis* liveness; LivenessAnalysis* liveness;
llvm::DenseMap<CFGBlock*, RequiredSet> required_phis; llvm::DenseMap<CFGBlock*, VRegSet> required_phis;
public: public:
// Initials_need_phis specifies that initial_map should count as an additional entry point // Initials_need_phis specifies that initial_map should count as an additional entry point
// that may require phis. // that may require phis.
PhiAnalysis(llvm::DenseMap<InternedString, DefinednessAnalysis::DefinitionLevel> initial_map, PhiAnalysis(VRegMap<DefinednessAnalysis::DefinitionLevel> initial_map, CFGBlock* initial_block,
CFGBlock* initial_block, bool initials_need_phis, LivenessAnalysis* liveness, ScopeInfo* scope_info); bool initials_need_phis, LivenessAnalysis* liveness, ScopeInfo* scope_info);
bool isRequired(InternedString name, CFGBlock* block); bool isRequired(int vreg, CFGBlock* block);
bool isRequiredAfter(InternedString name, CFGBlock* block); bool isRequiredAfter(int vreg, CFGBlock* block);
const RequiredSet& getAllRequiredAfter(CFGBlock* block); const VRegSet& getAllRequiredAfter(CFGBlock* block);
const RequiredSet& getAllRequiredFor(CFGBlock* block); const VRegSet& getAllRequiredFor(CFGBlock* block);
// If "name" may be undefined at the beginning of any immediate successor block of "block": // If "name" may be undefined at the beginning of any immediate successor block of "block":
bool isPotentiallyUndefinedAfter(InternedString name, CFGBlock* block); bool isPotentiallyUndefinedAfter(int vreg, CFGBlock* block);
// If "name" may be undefined at the beginning of "block" // If "name" may be undefined at the beginning of "block"
bool isPotentiallyUndefinedAt(InternedString name, CFGBlock* block); bool isPotentiallyUndefinedAt(int vreg, CFGBlock* block);
}; };
std::unique_ptr<LivenessAnalysis> computeLivenessInfo(CFG*); std::unique_ptr<LivenessAnalysis> computeLivenessInfo(CFG*);
......
...@@ -587,12 +587,11 @@ public: ...@@ -587,12 +587,11 @@ public:
} }
} }
bool visit_functiondef(AST_FunctionDef* node) override { void visitOrignodeArgs(AST_arguments* args) {
if (node == orig_node) {
this->currently_visiting_functiondef_args = true; this->currently_visiting_functiondef_args = true;
int counter = 0; int counter = 0;
for (AST_expr* e : node->args->args) { for (AST_expr* e : args->args) {
if (e->type == AST_TYPE::Tuple) { if (e->type == AST_TYPE::Tuple) {
doWrite(scoping->getInternedStrings().get("." + std::to_string(counter))); doWrite(scoping->getInternedStrings().get("." + std::to_string(counter)));
} }
...@@ -600,16 +599,21 @@ public: ...@@ -600,16 +599,21 @@ public:
e->accept(this); e->accept(this);
} }
if (node->args->vararg.s().size()) { if (args->vararg) {
mangleNameInPlace(node->args->vararg, cur->private_name, scoping->getInternedStrings()); mangleNameInPlace(args->vararg->id, cur->private_name, scoping->getInternedStrings());
doWrite(node->args->vararg); doWrite(args->vararg->id);
} }
if (node->args->kwarg.s().size()) { if (args->kwarg) {
mangleNameInPlace(node->args->kwarg, cur->private_name, scoping->getInternedStrings()); mangleNameInPlace(args->kwarg->id, cur->private_name, scoping->getInternedStrings());
doWrite(node->args->kwarg); doWrite(args->kwarg->id);
} }
this->currently_visiting_functiondef_args = false; this->currently_visiting_functiondef_args = false;
}
bool visit_functiondef(AST_FunctionDef* node) override {
if (node == orig_node) {
visitOrignodeArgs(node->args);
for (AST_stmt* s : node->body) for (AST_stmt* s : node->body)
s->accept(this); s->accept(this);
...@@ -666,16 +670,7 @@ public: ...@@ -666,16 +670,7 @@ public:
bool visit_lambda(AST_Lambda* node) override { bool visit_lambda(AST_Lambda* node) override {
if (node == orig_node) { if (node == orig_node) {
for (AST_expr* e : node->args->args) visitOrignodeArgs(node->args);
e->accept(this);
if (node->args->vararg.s().size()) {
mangleNameInPlace(node->args->vararg, cur->private_name, scoping->getInternedStrings());
doWrite(node->args->vararg);
}
if (node->args->kwarg.s().size()) {
mangleNameInPlace(node->args->kwarg, cur->private_name, scoping->getInternedStrings());
doWrite(node->args->kwarg);
}
node->body->accept(this); node->body->accept(this);
} else { } else {
for (auto* e : node->args->defaults) for (auto* e : node->args->defaults)
......
This diff is collapsed.
...@@ -39,8 +39,8 @@ public: ...@@ -39,8 +39,8 @@ public:
virtual ~TypeAnalysis() {} virtual ~TypeAnalysis() {}
virtual ConcreteCompilerType* getTypeAtBlockStart(InternedString name, CFGBlock* block) = 0; virtual ConcreteCompilerType* getTypeAtBlockStart(int vreg, CFGBlock* block) = 0;
virtual ConcreteCompilerType* getTypeAtBlockEnd(InternedString name, CFGBlock* block) = 0; virtual ConcreteCompilerType* getTypeAtBlockEnd(int vreg, CFGBlock* block) = 0;
virtual BoxedClass* speculatedExprClass(AST_expr*) = 0; virtual BoxedClass* speculatedExprClass(AST_expr*) = 0;
virtual BoxedClass* speculatedExprClass(AST_slice*) = 0; virtual BoxedClass* speculatedExprClass(AST_slice*) = 0;
}; };
......
...@@ -155,7 +155,7 @@ public: ...@@ -155,7 +155,7 @@ 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(); }
const llvm::DenseMap<InternedString, int>& getSymVRegMap() const { const llvm::DenseMap<InternedString, DefaultedInt<-1>>& getSymVRegMap() const {
return source_info->cfg->getVRegInfo().getSymVRegMap(); return source_info->cfg->getVRegInfo().getSymVRegMap();
} }
...@@ -172,7 +172,7 @@ public: ...@@ -172,7 +172,7 @@ public:
Box** getVRegs() { return vregs; } Box** getVRegs() { return vregs; }
const ScopeInfo* getScopeInfo() { return scope_info; } const ScopeInfo* getScopeInfo() { return scope_info; }
void addSymbol(InternedString name, Box* value, bool allow_duplicates); void addSymbol(int vreg, Box* value, bool allow_duplicates);
void setGenerator(Box* gen); void setGenerator(Box* gen);
void setPassedClosure(Box* closure); void setPassedClosure(Box* closure);
void setCreatedClosure(Box* closure); void setCreatedClosure(Box* closure);
...@@ -182,8 +182,8 @@ public: ...@@ -182,8 +182,8 @@ public:
friend struct pyston::ASTInterpreterJitInterface; friend struct pyston::ASTInterpreterJitInterface;
}; };
void ASTInterpreter::addSymbol(InternedString name, Box* new_value, bool allow_duplicates) { void ASTInterpreter::addSymbol(int vreg, Box* new_value, bool allow_duplicates) {
Box*& value = vregs[getVRegInfo().getVReg(name)]; Box*& value = vregs[vreg];
Box* old_value = value; Box* old_value = value;
value = incref(new_value); value = incref(new_value);
if (allow_duplicates) if (allow_duplicates)
...@@ -478,7 +478,7 @@ void ASTInterpreter::doStore(AST_Name* node, STOLEN(Value) value) { ...@@ -478,7 +478,7 @@ void ASTInterpreter::doStore(AST_Name* node, STOLEN(Value) value) {
if (jit) { if (jit) {
bool is_live = true; bool is_live = true;
if (!closure) if (!closure)
is_live = source_info->getLiveness()->isLiveAtEnd(name, current_block); is_live = source_info->getLiveness()->isLiveAtEnd(node->vreg, current_block);
if (is_live) if (is_live)
jit->emitSetLocal(name, node->vreg, closure, value); jit->emitSetLocal(name, node->vreg, closure, value);
else else
...@@ -720,9 +720,9 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) { ...@@ -720,9 +720,9 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
llvm::SmallVector<int, 16> dead_vregs; llvm::SmallVector<int, 16> dead_vregs;
for (auto&& sym : getSymVRegMap()) { for (auto&& sym : getSymVRegMap()) {
if (!liveness->isLiveAtEnd(sym.first, current_block)) { if (!liveness->isLiveAtEnd(sym.second, current_block)) {
dead_vregs.push_back(sym.second); dead_vregs.push_back(sym.second);
} else if (phis->isRequiredAfter(sym.first, current_block)) { } else if (phis->isRequiredAfter(sym.second, current_block)) {
assert(scope_info->getScopeTypeOfName(sym.first) != ScopeInfo::VarScopeType::GLOBAL); assert(scope_info->getScopeTypeOfName(sym.first) != ScopeInfo::VarScopeType::GLOBAL);
} else { } else {
} }
...@@ -739,25 +739,29 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) { ...@@ -739,25 +739,29 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
found_entry = p.first; found_entry = p.first;
} }
std::map<InternedString, Box*> sorted_symbol_table; int num_vregs = source_info->cfg->getVRegInfo().getTotalNumOfVRegs();
VRegMap<Box*> sorted_symbol_table(num_vregs);
VRegSet potentially_undefined(num_vregs);
// TODO: maybe use a different placeholder (=NULL)? // TODO: maybe use a different placeholder (=NULL)?
// - new issue with that -- we can no longer distinguish NULL from unset-in-sorted_symbol_table
// Currently we pass None because the LLVM jit will decref this value even though it may not be set. // Currently we pass None because the LLVM jit will decref this value even though it may not be set.
static Box* const VAL_UNDEFINED = (Box*)None; static Box* const VAL_UNDEFINED = (Box*)None;
for (auto& name : phis->definedness.getDefinedNamesAtEnd(current_block)) { const VRegSet& defined = phis->definedness.getDefinedVregsAtEnd(current_block);
Box* val = vregs[getVRegInfo().getVReg(name)]; for (int vreg : defined) {
if (!liveness->isLiveAtEnd(name, current_block))
if (!liveness->isLiveAtEnd(vreg, current_block))
continue; continue;
if (phis->isPotentiallyUndefinedAfter(name, current_block)) { Box* val = vregs[vreg];
if (phis->isPotentiallyUndefinedAfter(vreg, current_block)) {
potentially_undefined.set(vreg);
bool is_defined = val != NULL; bool is_defined = val != NULL;
// TODO only mangle once sorted_symbol_table[vreg] = is_defined ? incref(val) : incref(VAL_UNDEFINED);
sorted_symbol_table[getIsDefinedName(name, source_info->getInternedStrings())] = (Box*)is_defined;
sorted_symbol_table[name] = is_defined ? incref(val) : incref(VAL_UNDEFINED);
} else { } else {
ASSERT(val != NULL, "%s", name.c_str()); assert(val != NULL);
sorted_symbol_table[name] = incref(val); sorted_symbol_table[vreg] = incref(val);
} }
} }
...@@ -766,61 +770,42 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) { ...@@ -766,61 +770,42 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
// LLVM has a limit on the number of operands a machine instruction can have (~255), // LLVM has a limit on the number of operands a machine instruction can have (~255),
// in order to not hit the limit with the patchpoints cancel OSR when we have a high number of symbols. // in order to not hit the limit with the patchpoints cancel OSR when we have a high number of symbols.
if (sorted_symbol_table.size() > 225) { if (sorted_symbol_table.numSet() > 225) {
static StatCounter times_osr_cancel("num_osr_cancel_too_many_syms"); static StatCounter times_osr_cancel("num_osr_cancel_too_many_syms");
times_osr_cancel.log(); times_osr_cancel.log();
return nullptr; return nullptr;
} }
if (generator) {
// generated is only borrowed in order to not introduce cycles
sorted_symbol_table[source_info->getInternedStrings().get(PASSED_GENERATOR_NAME)] = generator;
}
if (frame_info.passed_closure)
sorted_symbol_table[source_info->getInternedStrings().get(PASSED_CLOSURE_NAME)]
= incref(frame_info.passed_closure);
if (created_closure)
sorted_symbol_table[source_info->getInternedStrings().get(CREATED_CLOSURE_NAME)] = incref(created_closure);
sorted_symbol_table[source_info->getInternedStrings().get(FRAME_INFO_PTR_NAME)] = (Box*)&frame_info;
if (found_entry == nullptr) { if (found_entry == nullptr) {
OSREntryDescriptor* entry = OSREntryDescriptor::create(getMD(), node, CXX); OSREntryDescriptor* entry = OSREntryDescriptor::create(getMD(), node, CXX);
for (auto& it : sorted_symbol_table) { // TODO can we just get rid of this?
if (isIsDefinedName(it.first)) for (auto&& p : sorted_symbol_table) {
entry->args[it.first] = BOOL; entry->args[p.first] = UNKNOWN;
else if (it.first.s() == PASSED_GENERATOR_NAME)
entry->args[it.first] = GENERATOR;
else if (it.first.s() == PASSED_CLOSURE_NAME || it.first.s() == CREATED_CLOSURE_NAME)
entry->args[it.first] = CLOSURE;
else if (it.first.s() == FRAME_INFO_PTR_NAME)
entry->args[it.first] = FRAME_INFO;
else {
assert(it.first.s()[0] != '!');
entry->args[it.first] = UNKNOWN;
}
} }
entry->potentially_undefined = potentially_undefined;
found_entry = entry; found_entry = entry;
} }
OSRExit exit(found_entry); OSRExit exit(found_entry);
std::vector<Box*> arg_array; std::vector<Box*> arg_array;
arg_array.reserve(sorted_symbol_table.size()); arg_array.reserve(sorted_symbol_table.numSet() + potentially_undefined.numSet());
for (auto& it : sorted_symbol_table) { for (auto&& p : sorted_symbol_table) {
arg_array.push_back(it.second); arg_array.push_back(p.second);
}
for (int vreg : potentially_undefined) {
bool is_defined = sorted_symbol_table[vreg] != VAL_UNDEFINED;
arg_array.push_back((Box*)is_defined);
} }
UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_jitted_code"); UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_jitted_code");
CompiledFunction* partial_func = compilePartialFuncInternal(&exit); CompiledFunction* partial_func = compilePartialFuncInternal(&exit);
auto arg_tuple = getTupleFromArgsArray(&arg_array[0], arg_array.size()); // generated is only borrowed in order to not introduce cycles
Box* r = partial_func->call(std::get<0>(arg_tuple), std::get<1>(arg_tuple), std::get<2>(arg_tuple), Box* r = partial_func->call_osr(generator, created_closure, &frame_info, &arg_array[0]);
std::get<3>(arg_tuple));
if (partial_func->exception_style == CXX) { if (partial_func->exception_style == CXX) {
assert(r); assert(r);
...@@ -1687,8 +1672,10 @@ Value ASTInterpreter::visit_name(AST_Name* node) { ...@@ -1687,8 +1672,10 @@ Value ASTInterpreter::visit_name(AST_Name* node) {
bool is_live = true; bool is_live = true;
if (node->is_kill) { if (node->is_kill) {
is_live = false; is_live = false;
} else if (node->lookup_type == ScopeInfo::VarScopeType::FAST) } else if (node->lookup_type == ScopeInfo::VarScopeType::FAST) {
is_live = source_info->getLiveness()->isLiveAtEnd(node->id, current_block); assert(node->vreg != -1);
is_live = source_info->getLiveness()->isLiveAtEnd(node->vreg, current_block);
}
if (is_live) { if (is_live) {
assert(!node->is_kill); assert(!node->is_kill);
...@@ -2087,6 +2074,10 @@ extern "C" Box* astInterpretDeoptFromASM(FunctionMetadata* md, AST_expr* after_e ...@@ -2087,6 +2074,10 @@ extern "C" Box* astInterpretDeoptFromASM(FunctionMetadata* md, AST_expr* after_e
ASTInterpreter interpreter(md, vregs, frame_state.frame_info); ASTInterpreter interpreter(md, vregs, frame_state.frame_info);
for (const auto& p : *frame_state.locals) { for (const auto& p : *frame_state.locals) {
if (p.first->cls == int_cls) {
int vreg = static_cast<BoxedInt*>(p.first)->n;
interpreter.addSymbol(vreg, p.second, false);
} else {
assert(p.first->cls == str_cls); assert(p.first->cls == str_cls);
auto name = static_cast<BoxedString*>(p.first)->s(); auto name = static_cast<BoxedString*>(p.first)->s();
if (name == PASSED_GENERATOR_NAME) { if (name == PASSED_GENERATOR_NAME) {
...@@ -2097,8 +2088,8 @@ extern "C" Box* astInterpretDeoptFromASM(FunctionMetadata* md, AST_expr* after_e ...@@ -2097,8 +2088,8 @@ extern "C" Box* astInterpretDeoptFromASM(FunctionMetadata* md, AST_expr* after_e
} else if (name == CREATED_CLOSURE_NAME) { } else if (name == CREATED_CLOSURE_NAME) {
interpreter.setCreatedClosure(p.second); interpreter.setCreatedClosure(p.second);
} else { } else {
InternedString interned = md->source->getInternedStrings().get(name); RELEASE_ASSERT(0, "");
interpreter.addSymbol(interned, p.second, false); }
} }
} }
...@@ -2112,7 +2103,7 @@ extern "C" Box* astInterpretDeoptFromASM(FunctionMetadata* md, AST_expr* after_e ...@@ -2112,7 +2103,7 @@ extern "C" Box* astInterpretDeoptFromASM(FunctionMetadata* md, AST_expr* after_e
assert(asgn->targets[0]->type == AST_TYPE::Name); assert(asgn->targets[0]->type == AST_TYPE::Name);
auto name = ast_cast<AST_Name>(asgn->targets[0]); auto name = ast_cast<AST_Name>(asgn->targets[0]);
assert(name->id.s()[0] == '#'); assert(name->id.s()[0] == '#');
interpreter.addSymbol(name->id, expr_val, true); interpreter.addSymbol(name->vreg, expr_val, true);
break; break;
} else if (enclosing_stmt->type == AST_TYPE::Expr) { } else if (enclosing_stmt->type == AST_TYPE::Expr) {
auto expr = ast_cast<AST_Expr>(enclosing_stmt); auto expr = ast_cast<AST_Expr>(enclosing_stmt);
......
...@@ -76,9 +76,8 @@ BORROWED(BoxedCode*) FunctionMetadata::getCode() { ...@@ -76,9 +76,8 @@ BORROWED(BoxedCode*) FunctionMetadata::getCode() {
void FunctionMetadata::addVersion(CompiledFunction* compiled) { void FunctionMetadata::addVersion(CompiledFunction* compiled) {
assert(compiled); assert(compiled);
assert((compiled->spec != NULL) + (compiled->entry_descriptor != NULL) == 1); assert((compiled->spec != NULL) + (compiled->entry_descriptor != NULL) == 1);
assert(compiled->md == NULL); assert(compiled->md);
assert(compiled->code); assert(compiled->code);
compiled->md = this;
if (compiled->entry_descriptor == NULL) { if (compiled->entry_descriptor == NULL) {
bool could_have_speculations = (source.get() != NULL); bool could_have_speculations = (source.get() != NULL);
......
...@@ -821,19 +821,15 @@ ConcreteCompilerVariable* UnknownType::hasnext(IREmitter& emitter, const OpInfo& ...@@ -821,19 +821,15 @@ ConcreteCompilerVariable* UnknownType::hasnext(IREmitter& emitter, const OpInfo&
return boolFromI1(emitter, rtn_val); return boolFromI1(emitter, rtn_val);
} }
CompilerVariable* makeFunction(IREmitter& emitter, FunctionMetadata* f, CompilerVariable* closure, llvm::Value* globals, CompilerVariable* makeFunction(IREmitter& emitter, FunctionMetadata* f, llvm::Value* closure, llvm::Value* globals,
const std::vector<ConcreteCompilerVariable*>& defaults) { const std::vector<ConcreteCompilerVariable*>& defaults) {
// Unlike the FunctionMetadata*, which can be shared between recompilations, the Box* around it // Unlike the FunctionMetadata*, which can be shared between recompilations, the Box* around it
// should be created anew every time the functiondef is encountered // should be created anew every time the functiondef is encountered
llvm::Value* closure_v;
ConcreteCompilerVariable* convertedClosure = NULL; ConcreteCompilerVariable* convertedClosure = NULL;
if (closure) { if (!closure) {
convertedClosure = closure->makeConverted(emitter, closure->getConcreteType()); closure = getNullPtr(g.llvm_closure_type_ptr);
closure_v = convertedClosure->getValue(); emitter.setType(closure, RefType::BORROWED);
} else {
closure_v = getNullPtr(g.llvm_closure_type_ptr);
emitter.setType(closure_v, RefType::BORROWED);
} }
llvm::SmallVector<llvm::Value*, 4> array_passed_args; llvm::SmallVector<llvm::Value*, 4> array_passed_args;
...@@ -860,8 +856,8 @@ CompilerVariable* makeFunction(IREmitter& emitter, FunctionMetadata* f, Compiler ...@@ -860,8 +856,8 @@ CompilerVariable* makeFunction(IREmitter& emitter, FunctionMetadata* f, Compiler
// emitter.createCall(). // emitter.createCall().
llvm::Instruction* boxed = emitter.getBuilder()->CreateCall( llvm::Instruction* boxed = emitter.getBuilder()->CreateCall(
g.funcs.createFunctionFromMetadata, g.funcs.createFunctionFromMetadata,
std::vector<llvm::Value*>{ embedRelocatablePtr(f, g.llvm_functionmetadata_type_ptr), closure_v, globals, std::vector<llvm::Value*>{ embedRelocatablePtr(f, g.llvm_functionmetadata_type_ptr), closure, globals, scratch,
scratch, getConstantInt(defaults.size(), g.i64) }); getConstantInt(defaults.size(), g.i64) });
emitter.setType(boxed, RefType::OWNED); emitter.setType(boxed, RefType::OWNED);
// The refcounter needs to know that this call "uses" the arguments that got passed via scratch. // The refcounter needs to know that this call "uses" the arguments that got passed via scratch.
...@@ -2433,8 +2429,11 @@ public: ...@@ -2433,8 +2429,11 @@ public:
} }
}; };
ConcreteCompilerType* BOOL = new BoolType(); ConcreteCompilerType* BOOL = new BoolType();
llvm::Value* makeLLVMBool(bool b) {
return llvm::ConstantInt::get(BOOL->llvmType(), b, false);
}
ConcreteCompilerVariable* makeBool(bool b) { ConcreteCompilerVariable* makeBool(bool b) {
return new ConcreteCompilerVariable(BOOL, llvm::ConstantInt::get(BOOL->llvmType(), b, false)); return new ConcreteCompilerVariable(BOOL, makeLLVMBool(b));
} }
ConcreteCompilerVariable* doIs(IREmitter& emitter, CompilerVariable* lhs, CompilerVariable* rhs, bool negate) { ConcreteCompilerVariable* doIs(IREmitter& emitter, CompilerVariable* lhs, CompilerVariable* rhs, bool negate) {
...@@ -2862,6 +2861,17 @@ llvm::Value* i1FromBool(IREmitter& emitter, ConcreteCompilerVariable* v) { ...@@ -2862,6 +2861,17 @@ llvm::Value* i1FromBool(IREmitter& emitter, ConcreteCompilerVariable* v) {
} }
} }
llvm::Value* i1FromLLVMBool(IREmitter& emitter, llvm::Value* v) {
if (BOOLS_AS_I64) {
assert(v->getType() == BOOL->llvmType());
assert(BOOL->llvmType() == g.i64);
llvm::Value* v2 = emitter.getBuilder()->CreateTrunc(v, g.i1);
return v2;
} else {
return v;
}
}
ConcreteCompilerType* LIST, *SLICE, *MODULE, *DICT, *SET, *FROZENSET, *LONG, *BOXED_COMPLEX; ConcreteCompilerType* LIST, *SLICE, *MODULE, *DICT, *SET, *FROZENSET, *LONG, *BOXED_COMPLEX;
......
...@@ -346,6 +346,7 @@ CompilerVariable* makeFloat(double); ...@@ -346,6 +346,7 @@ CompilerVariable* makeFloat(double);
CompilerVariable* makeUnboxedFloat(IREmitter&, ConcreteCompilerVariable*); CompilerVariable* makeUnboxedFloat(IREmitter&, ConcreteCompilerVariable*);
CompilerVariable* makeUnboxedFloat(IREmitter&, llvm::Value*); CompilerVariable* makeUnboxedFloat(IREmitter&, llvm::Value*);
llvm::Value* makeLLVMBool(bool b);
ConcreteCompilerVariable* makeBool(bool); ConcreteCompilerVariable* makeBool(bool);
ConcreteCompilerVariable* makeLong(IREmitter&, Box*); ConcreteCompilerVariable* makeLong(IREmitter&, Box*);
ConcreteCompilerVariable* makePureImaginary(IREmitter&, Box*); ConcreteCompilerVariable* makePureImaginary(IREmitter&, Box*);
...@@ -361,7 +362,7 @@ UnboxedSlice extractSlice(CompilerVariable* slice); ...@@ -361,7 +362,7 @@ UnboxedSlice extractSlice(CompilerVariable* slice);
#if 0 #if 0
CompilerVariable* makeUnicode(IREmitter& emitter, llvm::StringRef); CompilerVariable* makeUnicode(IREmitter& emitter, llvm::StringRef);
#endif #endif
CompilerVariable* makeFunction(IREmitter& emitter, FunctionMetadata*, CompilerVariable* closure, llvm::Value* globals, CompilerVariable* makeFunction(IREmitter& emitter, FunctionMetadata*, llvm::Value* closure, llvm::Value* globals,
const std::vector<ConcreteCompilerVariable*>& defaults); const std::vector<ConcreteCompilerVariable*>& defaults);
ConcreteCompilerVariable* undefVariable(); ConcreteCompilerVariable* undefVariable();
CompilerVariable* makeTuple(const std::vector<CompilerVariable*>& elts); CompilerVariable* makeTuple(const std::vector<CompilerVariable*>& elts);
...@@ -372,6 +373,7 @@ CompilerType* makeFuncType(ConcreteCompilerType* rtn_type, const std::vector<Con ...@@ -372,6 +373,7 @@ CompilerType* makeFuncType(ConcreteCompilerType* rtn_type, const std::vector<Con
ConcreteCompilerVariable* boolFromI1(IREmitter&, llvm::Value*); ConcreteCompilerVariable* boolFromI1(IREmitter&, llvm::Value*);
llvm::Value* i1FromBool(IREmitter&, ConcreteCompilerVariable*); llvm::Value* i1FromBool(IREmitter&, ConcreteCompilerVariable*);
llvm::Value* i1FromLLVMBool(IREmitter&, llvm::Value*);
template <typename V> template <typename V>
CompilerVariable* _ValuedCompilerType<V>::getPystonIter(IREmitter& emitter, const OpInfo& info, VAR* var) { CompilerVariable* _ValuedCompilerType<V>::getPystonIter(IREmitter& emitter, const OpInfo& info, VAR* var) {
......
...@@ -97,26 +97,32 @@ public: ...@@ -97,26 +97,32 @@ public:
return pool->get(static_cast<BoxedString*>(ident)->s()); return pool->get(static_cast<BoxedString*>(ident)->s());
} }
AST_Name* convertToName(identifier ident) {
if (!ident)
return NULL;
return new AST_Name(convert(ident), AST_TYPE::Store, -1, -1);
}
AST_arguments* convert(arguments_ty ident, AST* parent) { AST_arguments* convert(arguments_ty ident, AST* parent) {
auto r = new AST_arguments(); auto r = new AST_arguments();
convertAll<expr_ty>(ident->args, r->args); convertAll<expr_ty>(ident->args, r->args);
convertAll<expr_ty>(ident->defaults, r->defaults); convertAll<expr_ty>(ident->defaults, r->defaults);
r->vararg = convert(ident->vararg); r->vararg = convertToName(ident->vararg);
r->kwarg = convert(ident->kwarg); r->kwarg = convertToName(ident->kwarg);
if ((!r->vararg.s().empty()) && (!r->kwarg.s().empty()) && (r->vararg == r->kwarg)) { if (r->vararg && r->kwarg && (r->vararg->id == r->kwarg->id)) {
char buf[1024]; char buf[1024];
snprintf(buf, sizeof(buf), "duplicate argument '%s' in function definition", r->vararg.c_str()); snprintf(buf, sizeof(buf), "duplicate argument '%s' in function definition", r->vararg->id.c_str());
raiseSyntaxError(buf, parent->lineno, parent->col_offset, fn, "", true); raiseSyntaxError(buf, parent->lineno, parent->col_offset, fn, "", true);
} }
std::set<InternedString> seen; std::set<InternedString> seen;
if (!r->vararg.s().empty()) { if (r->vararg) {
seen.insert(r->vararg); seen.insert(r->vararg->id);
} }
if (!r->kwarg.s().empty()) { if (r->kwarg) {
seen.insert(r->kwarg); seen.insert(r->kwarg->id);
} }
checkDuplicateArgs(parent, r->args, &seen); checkDuplicateArgs(parent, r->args, &seen);
......
This diff is collapsed.
...@@ -77,13 +77,13 @@ ParamNames::ParamNames(AST* ast, InternedStringPool& pool) ...@@ -77,13 +77,13 @@ ParamNames::ParamNames(AST* ast, InternedStringPool& pool)
} }
} }
vararg = arguments->vararg.s(); vararg_name = arguments->vararg;
if (vararg.size()) if (vararg_name)
vararg_name = new AST_Name(pool.get(vararg), AST_TYPE::Param, arguments->lineno, arguments->col_offset); vararg = vararg_name->id.s();
kwarg = arguments->kwarg.s(); kwarg_name = arguments->kwarg;
if (kwarg.size()) if (kwarg_name)
kwarg_name = new AST_Name(pool.get(kwarg), AST_TYPE::Param, arguments->lineno, arguments->col_offset); kwarg = kwarg_name->id.s();
} else { } else {
RELEASE_ASSERT(0, "%d", ast->type); RELEASE_ASSERT(0, "%d", ast->type);
} }
...@@ -261,7 +261,7 @@ CompiledFunction* compileFunction(FunctionMetadata* f, FunctionSpecialization* s ...@@ -261,7 +261,7 @@ CompiledFunction* compileFunction(FunctionMetadata* f, FunctionSpecialization* s
if (entry_descriptor && VERBOSITY("irgen") >= 2) { if (entry_descriptor && VERBOSITY("irgen") >= 2) {
for (const auto& p : entry_descriptor->args) { for (const auto& p : entry_descriptor->args) {
ss << p.first.s() << ": " << p.second->debugName() << '\n'; ss << p.first << ": " << p.second->debugName() << '\n';
} }
} }
...@@ -680,10 +680,10 @@ void CompiledFunction::speculationFailed() { ...@@ -680,10 +680,10 @@ void CompiledFunction::speculationFailed() {
} }
std::unordered_set<CompiledFunction*> all_compiled_functions; std::unordered_set<CompiledFunction*> all_compiled_functions;
CompiledFunction::CompiledFunction(llvm::Function* func, FunctionSpecialization* spec, void* code, EffortLevel effort, CompiledFunction::CompiledFunction(FunctionMetadata* md, FunctionSpecialization* spec, void* code, EffortLevel effort,
ExceptionStyle exception_style, const OSREntryDescriptor* entry_descriptor) ExceptionStyle exception_style, const OSREntryDescriptor* entry_descriptor)
: md(NULL), : md(md),
func(func), func(NULL),
effort(effort), effort(effort),
exception_style(exception_style), exception_style(exception_style),
spec(spec), spec(spec),
...@@ -827,6 +827,6 @@ void FunctionMetadata::addVersion(void* f, ConcreteCompilerType* rtn_type, ...@@ -827,6 +827,6 @@ void FunctionMetadata::addVersion(void* f, ConcreteCompilerType* rtn_type,
#endif #endif
FunctionSpecialization* spec = new FunctionSpecialization(processType(rtn_type), arg_types); FunctionSpecialization* spec = new FunctionSpecialization(processType(rtn_type), arg_types);
addVersion(new CompiledFunction(NULL, spec, f, EffortLevel::MAXIMAL, exception_style, NULL)); addVersion(new CompiledFunction(this, spec, f, EffortLevel::MAXIMAL, exception_style, NULL));
} }
} }
This diff is collapsed.
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Instructions.h" #include "llvm/IR/Instructions.h"
#include "core/cfg.h"
#include "core/stringpool.h" #include "core/stringpool.h"
#include "core/types.h" #include "core/types.h"
...@@ -43,9 +44,9 @@ class TypeAnalysis; ...@@ -43,9 +44,9 @@ class TypeAnalysis;
class RefcountTracker; class RefcountTracker;
class UnwindInfo; class UnwindInfo;
typedef std::unordered_map<InternedString, CompilerVariable*> SymbolTable; typedef VRegMap<CompilerVariable*> SymbolTable;
typedef std::map<InternedString, CompilerVariable*> SortedSymbolTable; typedef VRegMap<llvm::Value*> DefinednessTable;
typedef std::unordered_map<InternedString, ConcreteCompilerVariable*> ConcreteSymbolTable; typedef VRegMap<ConcreteCompilerVariable*> ConcreteSymbolTable;
extern const std::string CREATED_CLOSURE_NAME; extern const std::string CREATED_CLOSURE_NAME;
extern const std::string PASSED_CLOSURE_NAME; extern const std::string PASSED_CLOSURE_NAME;
...@@ -75,6 +76,9 @@ private: ...@@ -75,6 +76,9 @@ private:
llvm::Value* globals; llvm::Value* globals;
llvm::Value* vregs; llvm::Value* vregs;
llvm::Value* stmt; llvm::Value* stmt;
llvm::Value* passed_closure = NULL, * created_closure = NULL, * passed_generator = NULL;
int scratch_size; int scratch_size;
public: public:
...@@ -82,6 +86,8 @@ public: ...@@ -82,6 +86,8 @@ public:
ParamNames* param_names, GCBuilder* gc, llvm::MDNode* func_dbg_info, RefcountTracker* refcount_tracker); ParamNames* param_names, GCBuilder* gc, llvm::MDNode* func_dbg_info, RefcountTracker* refcount_tracker);
~IRGenState(); ~IRGenState();
CFG* getCFG() { return getSourceInfo()->cfg; }
CompiledFunction* getCurFunction() { return cf; } CompiledFunction* getCurFunction() { return cf; }
FunctionMetadata* getMD() { return md; } FunctionMetadata* getMD() { return md; }
...@@ -119,6 +125,14 @@ public: ...@@ -119,6 +125,14 @@ public:
ParamNames* getParamNames() { return param_names; } ParamNames* getParamNames() { return param_names; }
llvm::Value* getPassedClosure();
llvm::Value* getCreatedClosure();
llvm::Value* getPassedGenerator();
void setPassedClosure(llvm::Value*);
void setCreatedClosure(llvm::Value*);
void setPassedGenerator(llvm::Value*);
// Returns the custom globals, or the module if the globals come from the module. // Returns the custom globals, or the module if the globals come from the module.
llvm::Value* getGlobals(); llvm::Value* getGlobals();
// Returns the custom globals, or null if the globals come from the module. // Returns the custom globals, or null if the globals come from the module.
...@@ -140,15 +154,20 @@ public: ...@@ -140,15 +154,20 @@ public:
// symbol_table records which Python variables are bound to what CompilerVariables at the end of this block. // symbol_table records which Python variables are bound to what CompilerVariables at the end of this block.
// phi_symbol_table records the ones that will need to be `phi'd. // phi_symbol_table records the ones that will need to be `phi'd.
// both only record non-globals. // both only record non-globals.
// TODO: switch these to unique_ptr's
SymbolTable* symbol_table; SymbolTable* symbol_table;
ConcreteSymbolTable* phi_symbol_table; ConcreteSymbolTable* phi_symbol_table;
DefinednessTable* definedness_vars;
llvm::BasicBlock* ending_block; llvm::BasicBlock* ending_block;
llvm::SmallVector<ExceptionState, 2> exception_state; llvm::SmallVector<ExceptionState, 2> exception_state;
EndingState(SymbolTable* symbol_table, ConcreteSymbolTable* phi_symbol_table, llvm::BasicBlock* ending_block, EndingState(SymbolTable* symbol_table, ConcreteSymbolTable* phi_symbol_table,
DefinednessTable* definedness_vars, llvm::BasicBlock* ending_block,
llvm::ArrayRef<ExceptionState> exception_state) llvm::ArrayRef<ExceptionState> exception_state)
: symbol_table(symbol_table), : symbol_table(symbol_table),
phi_symbol_table(phi_symbol_table), phi_symbol_table(phi_symbol_table),
definedness_vars(definedness_vars),
ending_block(ending_block), ending_block(ending_block),
exception_state(exception_state.begin(), exception_state.end()) {} exception_state(exception_state.begin(), exception_state.end()) {}
}; };
...@@ -159,6 +178,8 @@ public: ...@@ -159,6 +178,8 @@ public:
= 0; = 0;
virtual void giveLocalSymbol(InternedString name, CompilerVariable* var) = 0; virtual void giveLocalSymbol(InternedString name, CompilerVariable* var) = 0;
virtual void giveLocalSymbol(int vreg, CompilerVariable* var) = 0;
virtual void giveDefinednessVar(int vreg, llvm::Value* val) = 0;
virtual void copySymbolsFrom(SymbolTable* st) = 0; virtual void copySymbolsFrom(SymbolTable* st) = 0;
virtual void run(const CFGBlock* block) = 0; // primary entry point virtual void run(const CFGBlock* block) = 0; // primary entry point
virtual EndingState getEndingSymbolTable() = 0; virtual EndingState getEndingSymbolTable() = 0;
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include "core/cfg.h"
#include "core/stringpool.h" #include "core/stringpool.h"
namespace llvm { namespace llvm {
...@@ -32,7 +33,11 @@ struct StackMap; ...@@ -32,7 +33,11 @@ struct StackMap;
class OSREntryDescriptor { class OSREntryDescriptor {
private: private:
OSREntryDescriptor(FunctionMetadata* md, AST_Jump* backedge, ExceptionStyle exception_style) OSREntryDescriptor(FunctionMetadata* md, AST_Jump* backedge, ExceptionStyle exception_style)
: md(md), backedge(backedge), exception_style(exception_style) { : md(md),
backedge(backedge),
exception_style(exception_style),
args(md->source->cfg->getVRegInfo().getTotalNumOfVRegs()),
potentially_undefined(md->source->cfg->getVRegInfo().getTotalNumOfVRegs()) {
assert(md); assert(md);
} }
...@@ -40,8 +45,9 @@ public: ...@@ -40,8 +45,9 @@ public:
FunctionMetadata* md; FunctionMetadata* md;
AST_Jump* const backedge; AST_Jump* const backedge;
ExceptionStyle exception_style; ExceptionStyle exception_style;
typedef std::map<InternedString, ConcreteCompilerType*> ArgMap; typedef VRegMap<ConcreteCompilerType*> ArgMap;
ArgMap args; ArgMap args;
VRegSet potentially_undefined;
static OSREntryDescriptor* create(FunctionMetadata* md, AST_Jump* backedge, ExceptionStyle exception_style) { static OSREntryDescriptor* create(FunctionMetadata* md, AST_Jump* backedge, ExceptionStyle exception_style) {
return new OSREntryDescriptor(md, backedge, exception_style); return new OSREntryDescriptor(md, backedge, exception_style);
......
...@@ -218,9 +218,9 @@ AST_arguments* read_arguments(BufferedReader* reader) { ...@@ -218,9 +218,9 @@ AST_arguments* read_arguments(BufferedReader* reader) {
readExprVector(rtn->args, reader); readExprVector(rtn->args, reader);
rtn->col_offset = -1; rtn->col_offset = -1;
readExprVector(rtn->defaults, reader); readExprVector(rtn->defaults, reader);
rtn->kwarg = reader->readAndInternString(); rtn->kwarg = ast_cast<AST_Name>(readASTExpr(reader));
rtn->lineno = -1; rtn->lineno = -1;
rtn->vararg = reader->readAndInternString(); rtn->vararg = ast_cast<AST_Name>(readASTExpr(reader));
return rtn; return rtn;
} }
...@@ -1042,9 +1042,9 @@ AST_Module* parse_file(const char* fn, FutureFlags inherited_flags) { ...@@ -1042,9 +1042,9 @@ AST_Module* parse_file(const char* fn, FutureFlags inherited_flags) {
const char* getMagic() { const char* getMagic() {
if (ENABLE_PYPA_PARSER) if (ENABLE_PYPA_PARSER)
return "a\ncQ"; return "a\ncR";
else else
return "a\nCQ"; return "a\nCR";
} }
#define MAGIC_STRING_LENGTH 4 #define MAGIC_STRING_LENGTH 4
......
...@@ -30,10 +30,6 @@ ...@@ -30,10 +30,6 @@
namespace pyston { namespace pyston {
void PatchpointInfo::addFrameVar(llvm::StringRef name, CompilerType* type) {
frame_vars.push_back(FrameVarInfo({.name = name, .type = type }));
}
int ICSetupInfo::totalSize() const { int ICSetupInfo::totalSize() const {
if (isDeopt()) if (isDeopt())
return DEOPT_CALL_ONLY_SIZE; return DEOPT_CALL_ONLY_SIZE;
...@@ -74,30 +70,46 @@ bool StackMap::Record::Location::operator==(const StackMap::Record::Location& rh ...@@ -74,30 +70,46 @@ bool StackMap::Record::Location::operator==(const StackMap::Record::Location& rh
} }
void PatchpointInfo::parseLocationMap(StackMap::Record* r, LocationMap* map) { void PatchpointInfo::parseLocationMap(StackMap::Record* r, LocationMap* map) {
if (!this->isDeopt())
return;
assert(r->locations.size() == totalStackmapArgs()); assert(r->locations.size() == totalStackmapArgs());
int cur_arg = frameStackmapArgsStart(); int cur_arg = frameStackmapArgsStart();
// printf("parsing pp %ld:\n", reinterpret_cast<int64_t>(this)); // printf("parsing pp %ld:\n", reinterpret_cast<int64_t>(this));
for (FrameVarInfo& frame_var : frame_vars) { auto parse_type = [&](CompilerType* type) {
int num_args = frame_var.type->numFrameArgs(); int num_args = type->numFrameArgs();
llvm::SmallVector<StackMap::Record::Location, 1> locations; llvm::SmallVector<StackMap::Record::Location, 1> locations;
locations.append(r->locations.data() + cur_arg, r->locations.data() + cur_arg + num_args); locations.append(r->locations.data() + cur_arg, r->locations.data() + cur_arg + num_args);
cur_arg += num_args;
// printf("%s %d %d\n", frame_var.name.c_str(), r->locations[cur_arg].type, r->locations[cur_arg].regnum); return LocationMap::LocationTable::LocationEntry({._debug_pp_id = (uint64_t) this,
map->names[frame_var.name].locations.push_back(
LocationMap::LocationTable::LocationEntry({._debug_pp_id = (uint64_t) this,
.offset = r->offset, .offset = r->offset,
.length = patchpointSize(), .length = patchpointSize(),
.type = frame_var.type, .type = type,
.locations = std::move(locations) })); .locations = std::move(locations) });
};
cur_arg += num_args;
auto&& source = parentFunction()->md->source;
if (source->is_generator)
map->generator.locations.push_back(parse_type(GENERATOR));
if (source->getScopeInfo()->takesClosure())
map->passed_closure.locations.push_back(parse_type(CLOSURE));
if (source->getScopeInfo()->createsClosure())
map->created_closure.locations.push_back(parse_type(CLOSURE));
for (FrameVarInfo& frame_var : frame_info_desc.vars) {
map->vars[frame_var.vreg].locations.push_back(parse_type(frame_var.type));
} }
assert(cur_arg - frameStackmapArgsStart() == numFrameStackmapArgs()); for (int vreg : frame_info_desc.potentially_undefined) {
map->definedness_vars[vreg].locations.push_back(parse_type(BOOL));
}
ASSERT(cur_arg - frameStackmapArgsStart() == numFrameStackmapArgs(), "%d %d %d", cur_arg, frameStackmapArgsStart(),
numFrameStackmapArgs());
} }
static int extractScratchOffset(PatchpointInfo* pp, StackMap::Record* r) { static int extractScratchOffset(PatchpointInfo* pp, StackMap::Record* r) {
......
...@@ -96,9 +96,13 @@ public: ...@@ -96,9 +96,13 @@ public:
struct PatchpointInfo { struct PatchpointInfo {
public: public:
struct FrameVarInfo { struct FrameVarInfo {
llvm::StringRef name; int vreg;
CompilerType* type; CompilerType* type;
}; };
struct FrameInfoDesc {
std::vector<FrameVarInfo> vars;
llvm::SmallVector<int, 2> potentially_undefined;
};
private: private:
CompiledFunction* const parent_cf; CompiledFunction* const parent_cf;
...@@ -106,10 +110,10 @@ private: ...@@ -106,10 +110,10 @@ private:
int num_ic_stackmap_args; int num_ic_stackmap_args;
int num_frame_stackmap_args; int num_frame_stackmap_args;
bool is_frame_info_stackmap; bool is_frame_info_stackmap;
std::vector<FrameVarInfo> frame_vars;
unsigned int id; unsigned int id;
FrameInfoDesc frame_info_desc;
PatchpointInfo(CompiledFunction* parent_cf, const ICSetupInfo* icinfo, int num_ic_stackmap_args) PatchpointInfo(CompiledFunction* parent_cf, const ICSetupInfo* icinfo, int num_ic_stackmap_args)
: parent_cf(parent_cf), : parent_cf(parent_cf),
icinfo(icinfo), icinfo(icinfo),
...@@ -125,7 +129,7 @@ public: ...@@ -125,7 +129,7 @@ public:
int patchpointSize(); int patchpointSize();
CompiledFunction* parentFunction() { return parent_cf; } CompiledFunction* parentFunction() { return parent_cf; }
const std::vector<FrameVarInfo>& getFrameVars() { return frame_vars; } FrameInfoDesc& getFrameDesc() { return frame_info_desc; }
int scratchStackmapArg() { return 0; } int scratchStackmapArg() { return 0; }
int scratchSize() { return isDeopt() ? MAX_FRAME_SPILLS * sizeof(void*) : 96; } int scratchSize() { return isDeopt() ? MAX_FRAME_SPILLS * sizeof(void*) : 96; }
...@@ -133,7 +137,11 @@ public: ...@@ -133,7 +137,11 @@ public:
bool isFrameInfoStackmap() const { return is_frame_info_stackmap; } bool isFrameInfoStackmap() const { return is_frame_info_stackmap; }
int numFrameSpillsSupported() const { return isDeopt() ? MAX_FRAME_SPILLS : 0; } int numFrameSpillsSupported() const { return isDeopt() ? MAX_FRAME_SPILLS : 0; }
void addFrameVar(llvm::StringRef name, CompilerType* type); void addFrameVar(int vreg, CompilerType* type) {
frame_info_desc.vars.push_back(FrameVarInfo({.vreg = vreg, .type = type }));
}
void addPotentiallyUndefined(int vreg) { frame_info_desc.potentially_undefined.push_back(vreg); }
void setNumFrameArgs(int num_frame_args) { void setNumFrameArgs(int num_frame_args) {
assert(num_frame_stackmap_args == -1); assert(num_frame_stackmap_args == -1);
num_frame_stackmap_args = num_frame_args; num_frame_stackmap_args = num_frame_args;
......
...@@ -301,8 +301,12 @@ AST_arguments* readItem(pypa::AstArguments& a, InternedStringPool& interned_stri ...@@ -301,8 +301,12 @@ AST_arguments* readItem(pypa::AstArguments& a, InternedStringPool& interned_stri
readVector(ptr->defaults, a.defaults, interned_strings); readVector(ptr->defaults, a.defaults, interned_strings);
ptr->defaults.erase(std::remove(ptr->defaults.begin(), ptr->defaults.end(), nullptr), ptr->defaults.end()); ptr->defaults.erase(std::remove(ptr->defaults.begin(), ptr->defaults.end(), nullptr), ptr->defaults.end());
readVector(ptr->args, a.arguments, interned_strings); readVector(ptr->args, a.arguments, interned_strings);
ptr->kwarg = readName(a.kwargs, interned_strings); InternedString kwarg_name = readName(a.kwargs, interned_strings);
ptr->vararg = readName(a.args, interned_strings); if (kwarg_name.s().size())
ptr->kwarg = new AST_Name(kwarg_name, AST_TYPE::Store, -1, -1);
InternedString vararg_name = readName(a.args, interned_strings);
if (vararg_name.s().size())
ptr->vararg = new AST_Name(vararg_name, AST_TYPE::Store, -1, -1);
return ptr; return ptr;
} }
......
...@@ -176,8 +176,8 @@ private: ...@@ -176,8 +176,8 @@ private:
virtual bool visit_arguments(AST_arguments* node) { virtual bool visit_arguments(AST_arguments* node) {
writeExprVector(node->args); writeExprVector(node->args);
writeExprVector(node->defaults); writeExprVector(node->defaults);
writeString(node->kwarg); writeExpr(node->kwarg);
writeString(node->vararg); writeExpr(node->vararg);
return true; return true;
} }
virtual bool visit_assert(AST_Assert* node) { virtual bool visit_assert(AST_Assert* node) {
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
...@@ -101,7 +102,9 @@ public: ...@@ -101,7 +102,9 @@ public:
} }
}; };
llvm::StringMap<LocationTable> names; llvm::DenseMap<int, LocationTable> vars;
LocationTable generator, passed_closure, created_closure;
llvm::DenseMap<int, LocationTable> definedness_vars;
}; };
StackMap* parseStackMap(); StackMap* parseStackMap();
......
...@@ -329,25 +329,6 @@ public: ...@@ -329,25 +329,6 @@ public:
} }
} }
llvm::ArrayRef<StackMap::Record::Location> findLocations(llvm::StringRef name) {
assert(id.type == PythonFrameId::COMPILED);
CompiledFunction* cf = getCF();
uint64_t ip = getId().ip;
assert(ip > cf->code_start);
unsigned offset = ip - cf->code_start;
assert(cf->location_map);
const LocationMap::LocationTable& table = cf->location_map->names[name];
auto entry = table.findEntry(offset);
if (!entry)
return {};
assert(entry->locations.size());
return entry->locations;
}
AST_stmt* getCurrentStatement() { AST_stmt* getCurrentStatement() {
assert(getFrameInfo()->stmt); assert(getFrameInfo()->stmt);
return getFrameInfo()->stmt; return getFrameInfo()->stmt;
...@@ -870,20 +851,37 @@ DeoptState getDeoptState() { ...@@ -870,20 +851,37 @@ DeoptState getDeoptState() {
// We have to detect + ignore any entries for variables that // We have to detect + ignore any entries for variables that
// could have been defined (so they have entries) but aren't (so the // could have been defined (so they have entries) but aren't (so the
// entries point to uninitialized memory). // entries point to uninitialized memory).
std::unordered_set<std::string> is_undefined; std::unordered_set<int> is_undefined;
for (const auto& p : cf->location_map->names) { auto readEntry = [&](const LocationMap::LocationTable::LocationEntry* e) {
if (!startswith(p.first(), "!is_defined_")) auto locs = e->locations;
continue;
llvm::SmallVector<uint64_t, 1> vals;
// printf("%s: %s\n", p.first().c_str(), e.type->debugName().c_str());
for (auto& loc : locs) {
vals.push_back(frame_iter->readLocation(loc));
}
// this returns an owned reference so we don't incref it
Box* v = e->type->deserializeFromFrame(vals);
return v;
};
if (auto e = cf->location_map->generator.findEntry(offset))
d->d[boxString(PASSED_GENERATOR_NAME)] = readEntry(e);
if (auto e = cf->location_map->passed_closure.findEntry(offset))
d->d[boxString(PASSED_CLOSURE_NAME)] = readEntry(e);
if (auto e = cf->location_map->created_closure.findEntry(offset))
d->d[boxString(CREATED_CLOSURE_NAME)] = readEntry(e);
for (const auto& p : cf->location_map->definedness_vars) {
auto e = p.second.findEntry(offset); auto e = p.second.findEntry(offset);
if (e) { if (e) {
auto locs = e->locations; Box* b = readEntry(e);
AUTO_DECREF(b);
assert(locs.size() == 1); if (b == Py_False)
uint64_t v = frame_iter->readLocation(locs[0]); is_undefined.insert(p.first);
if ((v & 1) == 0)
is_undefined.insert(p.first().substr(12));
} }
} }
...@@ -893,40 +891,23 @@ DeoptState getDeoptState() { ...@@ -893,40 +891,23 @@ DeoptState getDeoptState() {
// 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()) { for (const auto& p : cf->md->source->cfg->getVRegInfo().getUserVisibleSymVRegMap()) {
if (is_undefined.count(p.first.s())) if (is_undefined.count(p.second))
continue; assert(0);
Box* v = vregs[p.second]; Box* v = vregs[p.second];
if (!v) if (!v)
continue; continue;
assert(!d->d.count(p.first.getBox())); d->d[boxInt(p.second)] = incref(v);
d->d[incref(p.first.getBox())] = incref(v);
} }
for (const auto& p : cf->location_map->names) { for (const auto& p : cf->location_map->vars) {
if (p.first()[0] == '!') if (is_undefined.count(p.first))
continue;
if (is_undefined.count(p.first()))
continue; continue;
auto e = p.second.findEntry(offset); auto e = p.second.findEntry(offset);
if (e) { if (e)
auto locs = e->locations; d->d[boxInt(p.first)] = readEntry(e);
llvm::SmallVector<uint64_t, 1> vals;
// printf("%s: %s\n", p.first().c_str(), e.type->debugName().c_str());
for (auto& loc : locs) {
vals.push_back(frame_iter->readLocation(loc));
}
// this returns an owned reference so we don't incref it
Box* v = e->type->deserializeFromFrame(vals);
// printf("%s: (pp id %ld) %p\n", p.first().c_str(), e._debug_pp_id, v);
d->d[boxString(p.first())] = v;
}
} }
} else { } else {
abort(); abort();
...@@ -1093,6 +1074,10 @@ extern "C" void abort() { ...@@ -1093,6 +1074,10 @@ extern "C" void abort() {
// In case displaying the traceback recursively calls abort: // In case displaying the traceback recursively calls abort:
static bool recursive = false; static bool recursive = false;
if (recursive) {
fprintf(stderr, "Recursively called abort! Make sure to check the stack trace\n");
}
if (!recursive && !IN_SHUTDOWN) { if (!recursive && !IN_SHUTDOWN) {
recursive = true; recursive = true;
Stats::dump(); Stats::dump();
......
...@@ -256,6 +256,10 @@ void AST_arguments::accept(ASTVisitor* v) { ...@@ -256,6 +256,10 @@ void AST_arguments::accept(ASTVisitor* v) {
visitVector(defaults, v); visitVector(defaults, v);
visitVector(args, v); visitVector(args, v);
if (kwarg)
kwarg->accept(v);
if (vararg)
vararg->accept(v);
} }
void AST_Assert::accept(ASTVisitor* v) { void AST_Assert::accept(ASTVisitor* v) {
......
...@@ -217,6 +217,7 @@ public: ...@@ -217,6 +217,7 @@ public:
class AST_alias : public AST { class AST_alias : public AST {
public: public:
InternedString name, asname; InternedString name, asname;
int name_vreg = -1, asname_vreg = -1;
virtual void accept(ASTVisitor* v); virtual void accept(ASTVisitor* v);
...@@ -225,14 +226,14 @@ public: ...@@ -225,14 +226,14 @@ public:
static const AST_TYPE::AST_TYPE TYPE = AST_TYPE::alias; static const AST_TYPE::AST_TYPE TYPE = AST_TYPE::alias;
}; };
class AST_Name;
class AST_arguments : public AST { class AST_arguments : public AST {
public: public:
// no lineno, col_offset attributes // no lineno, col_offset attributes
std::vector<AST_expr*> args, defaults; std::vector<AST_expr*> args, defaults;
// These are represented as strings, not names; not sure why. AST_Name* kwarg = NULL, * vararg = NULL;
// If they don't exist, the string is empty.
InternedString kwarg, vararg;
virtual void accept(ASTVisitor* v); virtual void accept(ASTVisitor* v);
...@@ -1116,7 +1117,7 @@ public: ...@@ -1116,7 +1117,7 @@ public:
}; };
template <typename T> T* ast_cast(AST* node) { template <typename T> T* ast_cast(AST* node) {
assert(node->type == T::TYPE); assert(!node || node->type == T::TYPE);
return static_cast<T*>(node); return static_cast<T*>(node);
} }
......
...@@ -232,6 +232,9 @@ private: ...@@ -232,6 +232,9 @@ private:
CFGBlock* exc_dest; CFGBlock* exc_dest;
// variable names to store the exception (type, value, traceback) in // variable names to store the exception (type, value, traceback) in
InternedString exc_type_name, exc_value_name, exc_traceback_name; InternedString exc_type_name, exc_value_name, exc_traceback_name;
// Similar to did_why: says whether the block might have been jumped-to
bool maybe_taken;
}; };
// ---------- Member fields ---------- // ---------- Member fields ----------
...@@ -517,9 +520,11 @@ private: ...@@ -517,9 +520,11 @@ private:
return node; return node;
} }
void pushJump(CFGBlock* target, bool allow_backedge = false) { void pushJump(CFGBlock* target, bool allow_backedge = false, int lineno = 0) {
AST_Jump* rtn = new AST_Jump(); AST_Jump* rtn = new AST_Jump();
rtn->target = target; rtn->target = target;
rtn->lineno = lineno;
push_back(rtn); push_back(rtn);
curblock->connectTo(target, allow_backedge); curblock->connectTo(target, allow_backedge);
curblock = nullptr; curblock = nullptr;
...@@ -1007,8 +1012,8 @@ private: ...@@ -1007,8 +1012,8 @@ private:
InternedString func_name = internString("<comprehension>"); InternedString func_name = internString("<comprehension>");
func->name = func_name; func->name = func_name;
func->args = new AST_arguments(); func->args = new AST_arguments();
func->args->vararg = internString(""); func->args->vararg = NULL;
func->args->kwarg = internString(""); func->args->kwarg = NULL;
scoping_analysis->registerScopeReplacement(node, func); // critical bit scoping_analysis->registerScopeReplacement(node, func); // critical bit
return new AST_MakeFunction(func); return new AST_MakeFunction(func);
} }
...@@ -1574,6 +1579,7 @@ public: ...@@ -1574,6 +1579,7 @@ public:
curblock->connectTo(exc_dest); curblock->connectTo(exc_dest);
ExcBlockInfo& exc_info = exc_handlers.back(); ExcBlockInfo& exc_info = exc_handlers.back();
exc_info.maybe_taken = true;
curblock = exc_dest; curblock = exc_dest;
// TODO: need to clear some temporaries here // TODO: need to clear some temporaries here
...@@ -1613,7 +1619,6 @@ public: ...@@ -1613,7 +1619,6 @@ public:
auto tmp = nodeName(); auto tmp = nodeName();
pushAssign(tmp, new AST_MakeClass(def)); pushAssign(tmp, new AST_MakeClass(def));
// is this name mangling correct?
pushAssign(source->mangleName(def->name), makeName(tmp, AST_TYPE::Load, node->lineno, 0, true)); pushAssign(source->mangleName(def->name), makeName(tmp, AST_TYPE::Load, node->lineno, 0, true));
return true; return true;
...@@ -1635,7 +1640,6 @@ public: ...@@ -1635,7 +1640,6 @@ public:
auto tmp = nodeName(); auto tmp = nodeName();
pushAssign(tmp, new AST_MakeFunction(def)); pushAssign(tmp, new AST_MakeFunction(def));
// is this name mangling correct?
pushAssign(source->mangleName(def->name), makeName(tmp, AST_TYPE::Load, node->lineno, node->col_offset, true)); pushAssign(source->mangleName(def->name), makeName(tmp, AST_TYPE::Load, node->lineno, node->col_offset, true));
return true; return true;
...@@ -2266,7 +2270,7 @@ public: ...@@ -2266,7 +2270,7 @@ public:
curblock->connectTo(end_false); curblock->connectTo(end_false);
curblock = end_true; curblock = end_true;
pushJump(loop_block, true); pushJump(loop_block, true, getLastLinenoSub(node->body.back()));
curblock = end_false; curblock = end_false;
pushJump(else_block); pushJump(else_block);
...@@ -2341,7 +2345,7 @@ public: ...@@ -2341,7 +2345,7 @@ public:
InternedString exc_type_name = nodeName("type"); InternedString exc_type_name = nodeName("type");
InternedString exc_value_name = nodeName("value"); InternedString exc_value_name = nodeName("value");
InternedString exc_traceback_name = nodeName("traceback"); InternedString exc_traceback_name = nodeName("traceback");
exc_handlers.push_back({ exc_handler_block, exc_type_name, exc_value_name, exc_traceback_name }); exc_handlers.push_back({ exc_handler_block, exc_type_name, exc_value_name, exc_traceback_name, false });
for (AST_stmt* subnode : node->body) { for (AST_stmt* subnode : node->body) {
subnode->accept(this); subnode->accept(this);
...@@ -2464,7 +2468,7 @@ public: ...@@ -2464,7 +2468,7 @@ public:
InternedString exc_value_name = nodeName("value"); InternedString exc_value_name = nodeName("value");
InternedString exc_traceback_name = nodeName("traceback"); InternedString exc_traceback_name = nodeName("traceback");
InternedString exc_why_name = nodeName("why"); InternedString exc_why_name = nodeName("why");
exc_handlers.push_back({ exc_handler_block, exc_type_name, exc_value_name, exc_traceback_name }); exc_handlers.push_back({ exc_handler_block, exc_type_name, exc_value_name, exc_traceback_name, false });
CFGBlock* finally_block = cfg->addDeferredBlock(); CFGBlock* finally_block = cfg->addDeferredBlock();
pushFinallyContinuation(finally_block, exc_why_name); pushFinallyContinuation(finally_block, exc_why_name);
...@@ -2475,6 +2479,7 @@ public: ...@@ -2475,6 +2479,7 @@ public:
break; break;
} }
bool maybe_exception = exc_handlers.back().maybe_taken;
exc_handlers.pop_back(); exc_handlers.pop_back();
int did_why = continuations.back().did_why; // bad to just reach in like this int did_why = continuations.back().did_why; // bad to just reach in like this
...@@ -2512,16 +2517,18 @@ public: ...@@ -2512,16 +2517,18 @@ public:
exitFinallyIf(node, Why::BREAK, exc_why_name); exitFinallyIf(node, Why::BREAK, exc_why_name);
if (did_why & (1 << Why::CONTINUE)) if (did_why & (1 << Why::CONTINUE))
exitFinallyIf(node, Why::CONTINUE, exc_why_name); exitFinallyIf(node, Why::CONTINUE, exc_why_name);
if (maybe_exception) {
CFGBlock* reraise = cfg->addDeferredBlock(); CFGBlock* reraise = cfg->addDeferredBlock();
CFGBlock* noexc = makeFinallyCont(Why::EXCEPTION, makeLoad(exc_why_name, node, true), reraise); CFGBlock* noexc = makeFinallyCont(Why::EXCEPTION, makeLoad(exc_why_name, node, true), reraise);
cfg->placeBlock(reraise); cfg->placeBlock(reraise);
curblock = reraise; curblock = reraise;
pushReraise(getLastLinenoSub(node->finalbody.back()), exc_type_name, exc_value_name, exc_traceback_name); pushReraise(getLastLinenoSub(node->finalbody.back()), exc_type_name, exc_value_name,
exc_traceback_name);
curblock = noexc; curblock = noexc;
} }
}
return true; return true;
} }
...@@ -2585,7 +2592,7 @@ public: ...@@ -2585,7 +2592,7 @@ public:
CFGBlock* exc_block = cfg->addDeferredBlock(); CFGBlock* exc_block = cfg->addDeferredBlock();
exc_block->info = "with_exc"; exc_block->info = "with_exc";
exc_handlers.push_back({ exc_block, exc_type_name, exc_value_name, exc_traceback_name }); exc_handlers.push_back({ exc_block, exc_type_name, exc_value_name, exc_traceback_name, false });
for (int i = 0; i < node->body.size(); i++) { for (int i = 0; i < node->body.size(); i++) {
node->body[i]->accept(this); node->body[i]->accept(this);
...@@ -2679,13 +2686,16 @@ public: ...@@ -2679,13 +2686,16 @@ public:
ScopeInfo* scope_info; ScopeInfo* scope_info;
CFGBlock* current_block; CFGBlock* current_block;
int next_vreg; int next_vreg;
llvm::DenseMap<InternedString, int> sym_vreg_map; llvm::DenseMap<InternedString, DefaultedInt<-1>> sym_vreg_map;
llvm::DenseMap<InternedString, std::unordered_set<CFGBlock*>> sym_blocks_map; llvm::DenseMap<InternedString, std::unordered_set<CFGBlock*>> sym_blocks_map;
std::vector<InternedString> vreg_sym_map;
enum Step { TrackBlockUsage = 0, UserVisible, CrossBlock, SingleBlockUse } step; enum Step { TrackBlockUsage = 0, UserVisible, CrossBlock, SingleBlockUse } step;
AssignVRegsVisitor(ScopeInfo* scope_info) : scope_info(scope_info), current_block(0), next_vreg(0) {} AssignVRegsVisitor(ScopeInfo* scope_info) : scope_info(scope_info), current_block(0), next_vreg(0) {}
bool visit_alias(AST_alias* node) override { RELEASE_ASSERT(0, "these should be removed by the cfg"); }
bool visit_arguments(AST_arguments* node) override { bool visit_arguments(AST_arguments* node) override {
for (AST_expr* d : node->defaults) for (AST_expr* d : node->defaults)
d->accept(this); d->accept(this);
...@@ -2748,9 +2758,16 @@ public: ...@@ -2748,9 +2758,16 @@ public:
} }
int assignVReg(InternedString id) { int assignVReg(InternedString id) {
assert(id.s().size());
auto it = sym_vreg_map.find(id); auto it = sym_vreg_map.find(id);
if (sym_vreg_map.end() == it) { if (sym_vreg_map.end() == it) {
sym_vreg_map[id] = next_vreg; sym_vreg_map[id] = next_vreg;
if (!REUSE_VREGS || step == UserVisible || step == CrossBlock) {
assert(next_vreg == vreg_sym_map.size());
vreg_sym_map.push_back(id);
}
return next_vreg++; return next_vreg++;
} }
return it->second; return it->second;
...@@ -2768,8 +2785,10 @@ void VRegInfo::assignVRegs(CFG* cfg, const ParamNames& param_names, ScopeInfo* s ...@@ -2768,8 +2785,10 @@ void VRegInfo::assignVRegs(CFG* cfg, const ParamNames& param_names, ScopeInfo* s
for (CFGBlock* b : cfg->blocks) { for (CFGBlock* b : cfg->blocks) {
visitor.current_block = b; visitor.current_block = b;
#if REUSE_VREGS
if (step == AssignVRegsVisitor::SingleBlockUse) if (step == AssignVRegsVisitor::SingleBlockUse)
visitor.next_vreg = num_vregs_cross_block; visitor.next_vreg = num_vregs_cross_block;
#endif
if (b == cfg->getStartingBlock()) { if (b == cfg->getStartingBlock()) {
for (auto* name : param_names.arg_names) { for (auto* name : param_names.arg_names) {
...@@ -2796,7 +2815,13 @@ void VRegInfo::assignVRegs(CFG* cfg, const ParamNames& param_names, ScopeInfo* s ...@@ -2796,7 +2815,13 @@ void VRegInfo::assignVRegs(CFG* cfg, const ParamNames& param_names, ScopeInfo* s
num_vregs = num_vregs_cross_block = visitor.next_vreg; num_vregs = num_vregs_cross_block = visitor.next_vreg;
} }
sym_vreg_map = std::move(visitor.sym_vreg_map); sym_vreg_map = std::move(visitor.sym_vreg_map);
vreg_sym_map = std::move(visitor.vreg_sym_map);
assert(hasVRegsAssigned()); assert(hasVRegsAssigned());
#if REUSE_VREGS
assert(vreg_sym_map.size() == num_vregs_cross_block);
#else
assert(vreg_sym_map.size() == num_vregs);
#endif
} }
CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body, const ParamNames& param_names) { CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body, const ParamNames& param_names) {
......
...@@ -42,6 +42,26 @@ class CFG; ...@@ -42,6 +42,26 @@ class CFG;
class ParamNames; class ParamNames;
class ScopeInfo; class ScopeInfo;
// Simple class to override the default value of an int.
template <int D = -1> class DefaultedInt {
private:
int x;
public:
DefaultedInt() : x(D) {}
DefaultedInt(int x) : x(x) {}
DefaultedInt(const DefaultedInt& rhs) : x(rhs.x) {}
DefaultedInt(DefaultedInt&& rhs) : x(rhs.x) {}
void operator=(const DefaultedInt& rhs) { x = rhs.x; }
void operator=(DefaultedInt&& rhs) { x = rhs.x; }
template <typename T> bool operator<(T rhs) const { return x < rhs; }
template <typename T> bool operator>(T rhs) const { return x > rhs; }
template <typename T> bool operator<=(T rhs) const { return x <= rhs; }
template <typename T> bool operator>=(T rhs) const { return x >= rhs; }
operator int() const { return x; }
};
class CFGBlock { class CFGBlock {
public: public:
CFG* cfg; CFG* cfg;
...@@ -85,26 +105,48 @@ public: ...@@ -85,26 +105,48 @@ public:
// llvm jit : [user visible] // llvm jit : [user visible]
class VRegInfo { class VRegInfo {
private: private:
llvm::DenseMap<InternedString, int> sym_vreg_map_user_visible; llvm::DenseMap<InternedString, DefaultedInt<-1>> sym_vreg_map_user_visible;
llvm::DenseMap<InternedString, int> sym_vreg_map; llvm::DenseMap<InternedString, DefaultedInt<-1>> sym_vreg_map;
// Reverse map, from vreg->symbol name.
// Entries won't exist for all vregs
std::vector<InternedString> vreg_sym_map;
int num_vregs_cross_block = -1; int num_vregs_cross_block = -1;
int num_vregs = -1; int num_vregs = -1;
public: public:
// 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, int>& getSymVRegMap() { return sym_vreg_map; } const llvm::DenseMap<InternedString, DefaultedInt<-1>>& getSymVRegMap() { return sym_vreg_map; }
const llvm::DenseMap<InternedString, int>& getUserVisibleSymVRegMap() { return sym_vreg_map_user_visible; } const llvm::DenseMap<InternedString, DefaultedInt<-1>>& getUserVisibleSymVRegMap() {
return sym_vreg_map_user_visible;
}
int getVReg(InternedString name) const { int getVReg(InternedString name) const {
assert(hasVRegsAssigned()); assert(hasVRegsAssigned());
assert(sym_vreg_map.count(name)); ASSERT(sym_vreg_map.count(name), "%s", name.c_str());
auto it = sym_vreg_map.find(name); auto it = sym_vreg_map.find(name);
assert(it != sym_vreg_map.end()); assert(it != sym_vreg_map.end());
assert(it->second != -1); assert(it->second != -1);
return it->second; return it->second;
} }
// Not all vregs correspond to a name; many are our compiler-generated variables.
bool vregHasName(int vreg) const { return vreg < num_vregs_cross_block; }
// Testing flag to turn off the "vreg reuse" optimization.
#define REUSE_VREGS 1
InternedString getName(int vreg) const {
assert(hasVRegsAssigned());
assert(vreg >= 0 && vreg < num_vregs);
#if REUSE_VREGS
assert(vregHasName(vreg));
#endif
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 < sym_vreg_map_user_visible.size(); }
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; }
...@@ -159,6 +201,138 @@ public: ...@@ -159,6 +201,138 @@ public:
void print(llvm::raw_ostream& stream = llvm::outs()); void print(llvm::raw_ostream& stream = llvm::outs());
}; };
class VRegSet {
private:
// TODO: switch just to a bool*?
std::vector<bool> v;
public:
VRegSet(int num_vregs) : v(num_vregs, false) {}
// TODO: what is the referenc type here?
bool operator[](int vreg) const {
assert(vreg >= 0 && vreg < v.size());
return v[vreg];
}
void set(int vreg) {
assert(vreg >= 0 && vreg < v.size());
v[vreg] = true;
}
int numSet() const {
int r = 0;
for (auto b : v)
if (b)
r++;
return r;
}
class iterator {
public:
const VRegSet& set;
int i;
iterator(const VRegSet& set, int i) : set(set), i(i) {}
iterator& operator++() {
do {
i++;
} while (i < set.v.size() && !set.v[i]);
return *this;
}
bool operator==(const iterator& rhs) const { return i == rhs.i; }
bool operator!=(const iterator& rhs) const { return !(*this == rhs); }
int operator*() { return i; }
};
iterator begin() const {
for (int i = 0; i < v.size(); i++) {
if (v[i])
return iterator(*this, i);
}
return iterator(*this, this->v.size());
}
iterator end() const { return iterator(*this, this->v.size()); }
};
// VRegMap: A compact way of representing a value per vreg.
//
// One thing to note is that every vreg will get a value by default
// (the default value of T()), and fetching an unset vreg will return
// that value.
//
// Iterating will skip over these values though. If you want to see them,
// you can iterate from 0 to numVregs().
template <typename T> class VRegMap {
private:
// TODO: switch just to a T*?
std::vector<T> v;
public:
VRegMap(int num_vregs) : v(num_vregs) {}
T& operator[](int vreg) {
assert(vreg >= 0 && vreg < v.size());
return v[vreg];
}
const T& operator[](int vreg) const {
assert(vreg >= 0 && vreg < v.size());
return v[vreg];
}
void clear() {
int n = v.size();
for (int i = 0; i < n; i++) {
v[i] = T();
}
}
int numSet() {
int n = v.size();
int r = 0;
for (int i = 0; i < n; i++) {
if (v[i] != T())
r++;
}
return r;
}
class iterator {
public:
const VRegMap<T>& map;
int i;
iterator(const VRegMap<T>& map, int i) : map(map), i(i) {}
// TODO: make this skip unset values?
iterator& operator++() {
do {
i++;
} while (i < map.numVregs() && map[i] == T());
return *this;
}
bool operator==(const iterator& rhs) const { return i == rhs.i; }
bool operator!=(const iterator& rhs) const { return !(*this == rhs); }
std::pair<int, const T&> operator*() { return std::pair<int, const T&>(i, map[i]); }
int first() const { return i; }
const T& second() const { return map[i]; }
};
int numVregs() const { return v.size(); }
iterator begin() const {
iterator it = iterator(*this, -1);
++it;
return it;
}
iterator end() const { return iterator(*this, this->v.size()); }
};
class SourceInfo; class SourceInfo;
CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body, const ParamNames& param_names); CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body, const ParamNames& param_names);
void printCFG(CFG* cfg); void printCFG(CFG* cfg);
......
...@@ -316,6 +316,7 @@ class BoxedGenerator; ...@@ -316,6 +316,7 @@ class BoxedGenerator;
class ICInfo; class ICInfo;
class LocationMap; class LocationMap;
class JitCodeBlock; class JitCodeBlock;
class FrameInfo;
extern std::vector<Box*> constants; extern std::vector<Box*> constants;
extern std::vector<Box*> late_constants; // constants that should be freed after normal constants extern std::vector<Box*> late_constants; // constants that should be freed after normal constants
...@@ -346,6 +347,8 @@ public: ...@@ -346,6 +347,8 @@ public:
// The function pointer to the generated code. For convenience, it can be accessed // The function pointer to the generated code. For convenience, it can be accessed
// as one of many different types. // as one of many different types.
// TODO: we instead make these accessor-functions that make sure that the code actually
// matches the C signature that we would return.
union { union {
Box* (*call)(Box*, Box*, Box*, Box**); Box* (*call)(Box*, Box*, Box*, Box**);
Box* (*closure_call)(BoxedClosure*, Box*, Box*, Box*, Box**); Box* (*closure_call)(BoxedClosure*, Box*, Box*, Box*, Box**);
...@@ -354,6 +357,7 @@ public: ...@@ -354,6 +357,7 @@ public:
Box* (*call1)(Box*, Box*, Box*, Box*, Box**); Box* (*call1)(Box*, Box*, Box*, Box*, Box**);
Box* (*call2)(Box*, Box*, Box*, Box*, Box*, Box**); Box* (*call2)(Box*, Box*, Box*, Box*, Box*, Box**);
Box* (*call3)(Box*, Box*, Box*, Box*, Box*, Box*, Box**); Box* (*call3)(Box*, Box*, Box*, Box*, Box*, Box*, Box**);
Box* (*call_osr)(BoxedGenerator*, BoxedClosure*, FrameInfo*, Box**);
void* code; void* code;
uintptr_t code_start; uintptr_t code_start;
}; };
...@@ -375,7 +379,7 @@ public: ...@@ -375,7 +379,7 @@ public:
// List of metadata objects for ICs inside this compilation // List of metadata objects for ICs inside this compilation
std::vector<ICInfo*> ics; std::vector<ICInfo*> ics;
CompiledFunction(llvm::Function* func, FunctionSpecialization* spec, void* code, EffortLevel effort, CompiledFunction(FunctionMetadata* func, FunctionSpecialization* spec, void* code, EffortLevel effort,
ExceptionStyle exception_style, const OSREntryDescriptor* entry_descriptor); ExceptionStyle exception_style, const OSREntryDescriptor* entry_descriptor);
ConcreteCompilerType* getReturnType(); ConcreteCompilerType* getReturnType();
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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