summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
author David Brazdil <dbrazdil@google.com> 2015-08-19 19:02:45 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2015-08-19 19:02:45 +0000
commit83f8b5bb9e9c52791a02a84d7b0889cab898efe4 (patch)
tree59de59bcd9f166fd892df1887019c846abd539ba /compiler
parent99429ae0610e8d67d417542942c4befb35950bd3 (diff)
parentbbd733e4ef277eff19bf9a6601032da081e9b68f (diff)
Merge "ART: Enable basic optimizations for try/catch"
Diffstat (limited to 'compiler')
-rw-r--r--compiler/optimizing/dead_code_elimination.cc5
-rw-r--r--compiler/optimizing/nodes.cc10
-rw-r--r--compiler/optimizing/nodes.h5
-rw-r--r--compiler/optimizing/optimizing_compiler.cc35
-rw-r--r--compiler/optimizing/reference_type_propagation.cc27
-rw-r--r--compiler/optimizing/reference_type_propagation.h1
6 files changed, 62 insertions, 21 deletions
diff --git a/compiler/optimizing/dead_code_elimination.cc b/compiler/optimizing/dead_code_elimination.cc
index 5de629d605..78470db834 100644
--- a/compiler/optimizing/dead_code_elimination.cc
+++ b/compiler/optimizing/dead_code_elimination.cc
@@ -142,7 +142,10 @@ void HDeadCodeElimination::RemoveDeadInstructions() {
}
void HDeadCodeElimination::Run() {
- RemoveDeadBlocks();
+ if (!graph_->HasTryCatch()) {
+ // TODO: Update dead block elimination and enable for try/catch.
+ RemoveDeadBlocks();
+ }
SsaRedundantPhiElimination(graph_).Run();
RemoveDeadInstructions();
}
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 64c680c3fb..4332d7ed02 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -346,6 +346,16 @@ void HGraph::ComputeTryBlockInformation() {
}
}
+bool HGraph::HasTryCatch() const {
+ for (size_t i = 0, e = blocks_.Size(); i < e; ++i) {
+ HBasicBlock* block = blocks_.Get(i);
+ if (block != nullptr && (block->IsTryBlock() || block->IsCatchBlock())) {
+ return true;
+ }
+ }
+ return false;
+}
+
void HGraph::SimplifyCFG() {
// Simplify the CFG for future analysis, and code generation:
// (1): Split critical edges.
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 35bc928620..7e49199b69 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -351,6 +351,9 @@ class HGraph : public ArenaObject<kArenaAllocMisc> {
return instruction_set_;
}
+ // TODO: Remove once the full compilation pipeline is enabled for try/catch.
+ bool HasTryCatch() const;
+
private:
void VisitBlockForDominatorTree(HBasicBlock* block,
HBasicBlock* predecessor,
@@ -4566,6 +4569,8 @@ class HLoadException : public HExpression<0> {
public:
HLoadException() : HExpression(Primitive::kPrimNot, SideEffects::None()) {}
+ bool CanBeNull() const OVERRIDE { return false; }
+
DECLARE_INSTRUCTION(LoadException);
private:
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 569522d34c..f6bbace664 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -359,11 +359,6 @@ static bool IsInstructionSetSupported(InstructionSet instruction_set) {
|| instruction_set == kX86_64;
}
-static bool CanOptimize(const DexFile::CodeItem& code_item) {
- // TODO: We currently cannot optimize methods with try/catch.
- return code_item.tries_size_ == 0;
-}
-
static void RunOptimizations(HOptimization* optimizations[],
size_t length,
PassObserver* pass_observer) {
@@ -470,6 +465,13 @@ static void RunOptimizations(HGraph* graph,
RunOptimizations(optimizations1, arraysize(optimizations1), pass_observer);
+ if (graph->HasTryCatch()) {
+ // TODO: Update the optimizations below to work correctly under try/catch
+ // semantics. The optimizations above suffice for running codegen
+ // in the meanwhile.
+ return;
+ }
+
MaybeRunInliner(graph, driver, stats, dex_compilation_unit, pass_observer, handles);
HOptimization* optimizations2[] = {
@@ -542,6 +544,10 @@ CompiledMethod* OptimizingCompiler::CompileOptimized(HGraph* graph,
RunOptimizations(graph, compiler_driver, compilation_stats_.get(),
dex_compilation_unit, pass_observer, &handles);
+ if (graph->HasTryCatch()) {
+ return nullptr;
+ }
+
AllocateRegisters(graph, codegen, pass_observer);
CodeVectorAllocator allocator;
@@ -734,7 +740,6 @@ CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_ite
}
}
- bool can_optimize = CanOptimize(*code_item);
bool can_allocate_registers = RegisterAllocator::CanAllocateRegistersFor(*graph, instruction_set);
// `run_optimizations_` is set explicitly (either through a compiler filter
@@ -755,16 +760,12 @@ CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_ite
}
}
- if (can_optimize) {
- return CompileOptimized(graph,
- codegen.get(),
- compiler_driver,
- dex_compilation_unit,
- &pass_observer);
- }
- }
-
- if (shouldOptimize && can_allocate_registers) {
+ return CompileOptimized(graph,
+ codegen.get(),
+ compiler_driver,
+ dex_compilation_unit,
+ &pass_observer);
+ } else if (shouldOptimize && can_allocate_registers) {
LOG(FATAL) << "Could not allocate registers in optimizing compiler";
UNREACHABLE();
} else if (can_use_baseline) {
@@ -772,8 +773,6 @@ CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_ite
if (!run_optimizations_) {
MaybeRecordStat(MethodCompilationStat::kNotOptimizedDisabled);
- } else if (!can_optimize) {
- MaybeRecordStat(MethodCompilationStat::kNotOptimizedTryCatch);
} else if (!can_allocate_registers) {
MaybeRecordStat(MethodCompilationStat::kNotOptimizedRegisterAllocator);
}
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 1349df9b16..5d029488fd 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -30,12 +30,14 @@ class RTPVisitor : public HGraphDelegateVisitor {
GrowableArray<HInstruction*>* worklist,
ReferenceTypeInfo::TypeHandle object_class_handle,
ReferenceTypeInfo::TypeHandle class_class_handle,
- ReferenceTypeInfo::TypeHandle string_class_handle)
+ ReferenceTypeInfo::TypeHandle string_class_handle,
+ ReferenceTypeInfo::TypeHandle throwable_class_handle)
: HGraphDelegateVisitor(graph),
handles_(handles),
object_class_handle_(object_class_handle),
class_class_handle_(class_class_handle),
string_class_handle_(string_class_handle),
+ throwable_class_handle_(throwable_class_handle),
worklist_(worklist) {}
void VisitNullConstant(HNullConstant* null_constant) OVERRIDE;
@@ -43,6 +45,7 @@ class RTPVisitor : public HGraphDelegateVisitor {
void VisitLoadClass(HLoadClass* load_class) OVERRIDE;
void VisitClinitCheck(HClinitCheck* clinit_check) OVERRIDE;
void VisitLoadString(HLoadString* instr) OVERRIDE;
+ void VisitLoadException(HLoadException* instr) OVERRIDE;
void VisitNewArray(HNewArray* instr) OVERRIDE;
void VisitParameterValue(HParameterValue* instr) OVERRIDE;
void UpdateFieldAccessTypeInfo(HInstruction* instr, const FieldInfo& info);
@@ -64,6 +67,7 @@ class RTPVisitor : public HGraphDelegateVisitor {
ReferenceTypeInfo::TypeHandle object_class_handle_;
ReferenceTypeInfo::TypeHandle class_class_handle_;
ReferenceTypeInfo::TypeHandle string_class_handle_;
+ ReferenceTypeInfo::TypeHandle throwable_class_handle_;
GrowableArray<HInstruction*>* worklist_;
static constexpr size_t kDefaultWorklistSize = 8;
@@ -79,12 +83,15 @@ ReferenceTypePropagation::ReferenceTypePropagation(HGraph* graph,
object_class_handle_ = handles_->NewHandle(linker->GetClassRoot(ClassLinker::kJavaLangObject));
string_class_handle_ = handles_->NewHandle(linker->GetClassRoot(ClassLinker::kJavaLangString));
class_class_handle_ = handles_->NewHandle(linker->GetClassRoot(ClassLinker::kJavaLangClass));
+ throwable_class_handle_ =
+ handles_->NewHandle(linker->GetClassRoot(ClassLinker::kJavaLangThrowable));
if (kIsDebugBuild) {
ScopedObjectAccess soa(Thread::Current());
DCHECK(ReferenceTypeInfo::IsValidHandle(object_class_handle_));
DCHECK(ReferenceTypeInfo::IsValidHandle(class_class_handle_));
DCHECK(ReferenceTypeInfo::IsValidHandle(string_class_handle_));
+ DCHECK(ReferenceTypeInfo::IsValidHandle(throwable_class_handle_));
}
}
@@ -129,7 +136,8 @@ void ReferenceTypePropagation::VisitBasicBlock(HBasicBlock* block) {
&worklist_,
object_class_handle_,
class_class_handle_,
- string_class_handle_);
+ string_class_handle_,
+ throwable_class_handle_);
// Handle Phis first as there might be instructions in the same block who depend on them.
for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
VisitPhi(it.Current()->AsPhi());
@@ -459,6 +467,21 @@ void RTPVisitor::VisitLoadString(HLoadString* instr) {
instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(string_class_handle_, /* is_exact */ true));
}
+void RTPVisitor::VisitLoadException(HLoadException* instr) {
+ DCHECK(instr->GetBlock()->IsCatchBlock());
+ TryCatchInformation* catch_info = instr->GetBlock()->GetTryCatchInformation();
+
+ if (catch_info->IsCatchAllTypeIndex()) {
+ instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(throwable_class_handle_,
+ /* is_exact */ false));
+ } else {
+ UpdateReferenceTypeInfo(instr,
+ catch_info->GetCatchTypeIndex(),
+ catch_info->GetCatchDexFile(),
+ /* is_exact */ false);
+ }
+}
+
void RTPVisitor::VisitNullCheck(HNullCheck* instr) {
ScopedObjectAccess soa(Thread::Current());
ReferenceTypeInfo parent_rti = instr->InputAt(0)->GetReferenceTypeInfo();
diff --git a/compiler/optimizing/reference_type_propagation.h b/compiler/optimizing/reference_type_propagation.h
index 14d4a82e9b..62f6ab80b3 100644
--- a/compiler/optimizing/reference_type_propagation.h
+++ b/compiler/optimizing/reference_type_propagation.h
@@ -62,6 +62,7 @@ class ReferenceTypePropagation : public HOptimization {
ReferenceTypeInfo::TypeHandle object_class_handle_;
ReferenceTypeInfo::TypeHandle class_class_handle_;
ReferenceTypeInfo::TypeHandle string_class_handle_;
+ ReferenceTypeInfo::TypeHandle throwable_class_handle_;
static constexpr size_t kDefaultWorklistSize = 8;