Commit ea673dfd authored by Kevin Modzelewski's avatar Kevin Modzelewski

For OSRs, do type analysis starting from OSR edge

Before we would do type analysis starting from the function entry
(using the specialization of the previous function).  This makes things
pretty complicated because we can infer different types than we are OSRing
with!  Ex if the type analysis determines that we should speculate in an
earlier BB, the types we have now might not reflect that speculation.

So instead, start the type analysis starting from the BB that the OSR starts at.
Should also have the side-benefit of requiring less type analysis work.

But this should let us get rid of the OSR-entry guarding, and the rest of
the old deopt system!
parent 222f5a70
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "analysis/scoping_analysis.h" #include "analysis/scoping_analysis.h"
#include "codegen/codegen.h" #include "codegen/codegen.h"
#include "codegen/compvars.h" #include "codegen/compvars.h"
#include "codegen/osrentry.h"
#include "codegen/type_recording.h" #include "codegen/type_recording.h"
#include "core/ast.h" #include "core/ast.h"
#include "core/cfg.h" #include "core/cfg.h"
...@@ -622,6 +623,7 @@ public: ...@@ -622,6 +623,7 @@ public:
return getTypeAtBlockStart(name, block->successors[0]); return getTypeAtBlockStart(name, block->successors[0]);
} }
ConcreteCompilerType* getTypeAtBlockStart(InternedString name, CFGBlock* block) override { ConcreteCompilerType* getTypeAtBlockStart(InternedString name, CFGBlock* block) override {
assert(starting_types.count(block));
CompilerType* base = starting_types[block][name]; CompilerType* base = starting_types[block][name];
ASSERT(base != NULL, "%s %d", name.c_str(), block->idx); ASSERT(base != NULL, "%s %d", name.c_str(), block->idx);
...@@ -672,40 +674,20 @@ public: ...@@ -672,40 +674,20 @@ public:
return changed; return changed;
} }
static PropagatingTypeAnalysis* doAnalysis(CFG* cfg, const ParamNames& arg_names, static PropagatingTypeAnalysis* doAnalysis(CFG* cfg, SpeculationLevel speculation, ScopeInfo* scope_info,
const std::vector<ConcreteCompilerType*>& arg_types, TypeMap&& initial_types, CFGBlock* initial_block) {
SpeculationLevel speculation, ScopeInfo* scope_info) {
Timer _t("PropagatingTypeAnalysis::doAnalysis()"); Timer _t("PropagatingTypeAnalysis::doAnalysis()");
AllTypeMap starting_types; AllTypeMap starting_types;
ExprTypeMap expr_types; ExprTypeMap expr_types;
TypeSpeculations type_speculations; TypeSpeculations type_speculations;
assert(arg_names.totalParameters() == arg_types.size());
TypeMap& initial_types = starting_types[cfg->getStartingBlock()];
int i = 0;
for (; i < arg_names.args.size(); i++) {
initial_types[scope_info->internString(arg_names.args[i])] = unboxedType(arg_types[i]);
}
if (arg_names.vararg.size()) {
initial_types[scope_info->internString(arg_names.vararg)] = unboxedType(arg_types[i]);
i++;
}
if (arg_names.kwarg.size()) {
initial_types[scope_info->internString(arg_names.kwarg)] = unboxedType(arg_types[i]);
i++;
}
assert(i == arg_types.size());
std::unordered_set<CFGBlock*> in_queue; std::unordered_set<CFGBlock*> in_queue;
std::priority_queue<CFGBlock*, std::vector<CFGBlock*>, CFGBlockMinIndex> queue; std::priority_queue<CFGBlock*, std::vector<CFGBlock*>, CFGBlockMinIndex> queue;
queue.push(cfg->getStartingBlock());
in_queue.insert(cfg->getStartingBlock()); starting_types[initial_block] = std::move(initial_types);
queue.push(initial_block);
in_queue.insert(initial_block);
int num_evaluations = 0; int num_evaluations = 0;
while (!queue.empty()) { while (!queue.empty()) {
...@@ -787,6 +769,38 @@ TypeAnalysis* doTypeAnalysis(CFG* cfg, const ParamNames& arg_names, const std::v ...@@ -787,6 +769,38 @@ TypeAnalysis* doTypeAnalysis(CFG* cfg, const ParamNames& arg_names, const std::v
// if (effort == EffortLevel::INTERPRETED) { // if (effort == EffortLevel::INTERPRETED) {
// return new NullTypeAnalysis(); // return new NullTypeAnalysis();
//} //}
return PropagatingTypeAnalysis::doAnalysis(cfg, arg_names, arg_types, speculation, scope_info); assert(arg_names.totalParameters() == arg_types.size());
TypeMap initial_types;
int i = 0;
for (; i < arg_names.args.size(); i++) {
initial_types[scope_info->internString(arg_names.args[i])] = unboxedType(arg_types[i]);
}
if (arg_names.vararg.size()) {
initial_types[scope_info->internString(arg_names.vararg)] = unboxedType(arg_types[i]);
i++;
}
if (arg_names.kwarg.size()) {
initial_types[scope_info->internString(arg_names.kwarg)] = unboxedType(arg_types[i]);
i++;
}
assert(i == arg_types.size());
return PropagatingTypeAnalysis::doAnalysis(cfg, speculation, scope_info, std::move(initial_types),
cfg->getStartingBlock());
}
TypeAnalysis* doTypeAnalysis(CFG* cfg, const OSREntryDescriptor* entry_descriptor, EffortLevel effort,
TypeAnalysis::SpeculationLevel speculation, ScopeInfo* scope_info) {
// if (effort == EffortLevel::INTERPRETED) {
// return new NullTypeAnalysis();
//}
TypeMap initial_types(entry_descriptor->args.begin(), entry_descriptor->args.end());
return PropagatingTypeAnalysis::doAnalysis(cfg, speculation, scope_info, std::move(initial_types),
entry_descriptor->backedge->target);
} }
} }
...@@ -27,6 +27,7 @@ class ScopeInfo; ...@@ -27,6 +27,7 @@ class ScopeInfo;
class CFGBlock; class CFGBlock;
class BoxedClass; class BoxedClass;
class AST_expr; class AST_expr;
class OSREntryDescriptor;
class TypeAnalysis { class TypeAnalysis {
public: public:
...@@ -45,6 +46,8 @@ public: ...@@ -45,6 +46,8 @@ public:
TypeAnalysis* doTypeAnalysis(CFG* cfg, const ParamNames& param_names, TypeAnalysis* doTypeAnalysis(CFG* cfg, const ParamNames& param_names,
const std::vector<ConcreteCompilerType*>& arg_types, EffortLevel effort, const std::vector<ConcreteCompilerType*>& arg_types, EffortLevel effort,
TypeAnalysis::SpeculationLevel speculation, ScopeInfo* scope_info); TypeAnalysis::SpeculationLevel speculation, ScopeInfo* scope_info);
TypeAnalysis* doTypeAnalysis(CFG* cfg, const OSREntryDescriptor* entry_descriptor, EffortLevel effort,
TypeAnalysis::SpeculationLevel speculation, ScopeInfo* scope_info);
} }
#endif #endif
...@@ -439,6 +439,10 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua ...@@ -439,6 +439,10 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
v = converted->getValue(); v = converted->getValue();
delete converted; delete converted;
} else { } else {
printf("OSR'd with a %s into a partial compile that expects a %s?\n", p.second->debugName().c_str(),
phi_type->debugName().c_str());
RELEASE_ASSERT(0, "whyy");
#if 0
ASSERT(p.second == UNKNOWN, "%s", p.second->debugName().c_str()); ASSERT(p.second == UNKNOWN, "%s", p.second->debugName().c_str());
BoxedClass* speculated_class = NULL; BoxedClass* speculated_class = NULL;
if (phi_type == INT) { if (phi_type == INT) {
...@@ -516,6 +520,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua ...@@ -516,6 +520,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
assert(phi_type == typeFromClass(speculated_class)); assert(phi_type == typeFromClass(speculated_class));
v = from_arg; v = from_arg;
} }
#endif
} }
if (VERBOSITY("irgen")) if (VERBOSITY("irgen"))
...@@ -525,6 +530,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua ...@@ -525,6 +530,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
} }
if (guard_val) { if (guard_val) {
abort();
// Create the guard with both branches leading to the success_bb, // Create the guard with both branches leading to the success_bb,
// and let the deopt path change the failure case to point to the // and let the deopt path change the failure case to point to the
// as-yet-unknown deopt block. // as-yet-unknown deopt block.
...@@ -532,7 +538,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua ...@@ -532,7 +538,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
// the guard will just silently be ignored. // the guard will just silently be ignored.
llvm::BranchInst* br llvm::BranchInst* br
= entry_emitter->getBuilder()->CreateCondBr(guard_val, osr_unbox_block, osr_unbox_block); = entry_emitter->getBuilder()->CreateCondBr(guard_val, osr_unbox_block, osr_unbox_block);
out_guards.registerGuardForBlockEntry(target_block, br, *initial_syms); // out_guards.registerGuardForBlockEntry(target_block, br, *initial_syms);
} else { } else {
entry_emitter->getBuilder()->CreateBr(osr_unbox_block); entry_emitter->getBuilder()->CreateBr(osr_unbox_block);
} }
...@@ -1168,8 +1174,13 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O ...@@ -1168,8 +1174,13 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O
EffortLevel min_speculation_level = EffortLevel::MAXIMAL; EffortLevel min_speculation_level = EffortLevel::MAXIMAL;
if (ENABLE_SPECULATION && effort >= min_speculation_level) if (ENABLE_SPECULATION && effort >= min_speculation_level)
speculation_level = TypeAnalysis::SOME; speculation_level = TypeAnalysis::SOME;
TypeAnalysis* types TypeAnalysis* types;
= doTypeAnalysis(source->cfg, *param_names, spec->arg_types, effort, speculation_level, source->getScopeInfo()); if (entry_descriptor)
types = doTypeAnalysis(source->cfg, entry_descriptor, effort, speculation_level, source->getScopeInfo());
else
types = doTypeAnalysis(source->cfg, *param_names, spec->arg_types, effort, speculation_level,
source->getScopeInfo());
_t2.split(); _t2.split();
...@@ -1192,6 +1203,7 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O ...@@ -1192,6 +1203,7 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O
// De-opt handling: // De-opt handling:
if (!guards.isEmpty()) { if (!guards.isEmpty()) {
RELEASE_ASSERT(0, "should not be any guards any more!");
BlockSet deopt_full_blocks, deopt_partial_blocks; BlockSet deopt_full_blocks, deopt_partial_blocks;
GuardList deopt_guards; GuardList deopt_guards;
// typedef std::unordered_map<CFGBlock*, std::unordered_map<AST_expr*, GuardList::ExprTypeGuard*> > Worklist; // typedef std::unordered_map<CFGBlock*, std::unordered_map<AST_expr*, GuardList::ExprTypeGuard*> > Worklist;
......
...@@ -130,11 +130,11 @@ public: ...@@ -130,11 +130,11 @@ public:
bool isEmpty() const { return block_begin_guards.size() == 0; } bool isEmpty() const { return block_begin_guards.size() == 0; }
void registerGuardForBlockEntry(CFGBlock* cfg_block, llvm::BranchInst* branch, const SymbolTable& st) { // void registerGuardForBlockEntry(CFGBlock* cfg_block, llvm::BranchInst* branch, const SymbolTable& st) {
// printf("Adding guard for block %p, in %p\n", cfg_block, this); //// printf("Adding guard for block %p, in %p\n", cfg_block, this);
std::vector<BlockEntryGuard*>& v = block_begin_guards[cfg_block]; // std::vector<BlockEntryGuard*>& v = block_begin_guards[cfg_block];
v.push_back(new BlockEntryGuard(cfg_block, branch, st)); // v.push_back(new BlockEntryGuard(cfg_block, branch, st));
} //}
const std::vector<BlockEntryGuard*>& getGuardsForBlock(CFGBlock* block) const { const std::vector<BlockEntryGuard*>& getGuardsForBlock(CFGBlock* block) const {
std::unordered_map<CFGBlock*, std::vector<BlockEntryGuard*>>::const_iterator it std::unordered_map<CFGBlock*, std::vector<BlockEntryGuard*>>::const_iterator it
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#ifndef PYSTON_CODEGEN_OSRENTRY_H #ifndef PYSTON_CODEGEN_OSRENTRY_H
#define PYSTON_CODEGEN_OSRENTRY_H #define PYSTON_CODEGEN_OSRENTRY_H
#include <map>
#include <vector> #include <vector>
#include "core/stringpool.h" #include "core/stringpool.h"
......
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