summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/builder.cc70
-rw-r--r--compiler/optimizing/builder.h9
-rw-r--r--compiler/optimizing/inliner.cc75
-rw-r--r--compiler/optimizing/inliner.h6
-rw-r--r--compiler/optimizing/nodes.h6
-rw-r--r--compiler/optimizing/optimizing_compiler.cc2
6 files changed, 114 insertions, 54 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index a21c311..8786ed4 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -616,8 +616,8 @@ bool HGraphBuilder::BuildInvoke(const Instruction& instruction,
DCHECK((optimized_invoke_type == invoke_type) || (optimized_invoke_type != kDirect)
|| compiler_driver_->GetCompilerOptions().GetCompilePic());
bool is_recursive =
- (target_method.dex_method_index == outer_compilation_unit_->GetDexMethodIndex());
- DCHECK(!is_recursive || (target_method.dex_file == outer_compilation_unit_->GetDexFile()));
+ (target_method.dex_method_index == dex_compilation_unit_->GetDexMethodIndex());
+ DCHECK(!is_recursive || (target_method.dex_file == dex_compilation_unit_->GetDexFile()));
invoke = new (arena_) HInvokeStaticOrDirect(
arena_, number_of_arguments, return_type, dex_pc, target_method.dex_method_index,
is_recursive, optimized_invoke_type);
@@ -704,6 +704,34 @@ bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction,
return true;
}
+mirror::Class* HGraphBuilder::GetOutermostCompilingClass() const {
+ ScopedObjectAccess soa(Thread::Current());
+ StackHandleScope<2> hs(soa.Self());
+ const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile();
+ Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
+ soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
+ Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle(
+ outer_compilation_unit_->GetClassLinker()->FindDexCache(outer_dex_file)));
+
+ return compiler_driver_->ResolveCompilingMethodsClass(
+ soa, outer_dex_cache, class_loader, outer_compilation_unit_);
+}
+
+bool HGraphBuilder::IsOutermostCompilingClass(uint16_t type_index) const {
+ ScopedObjectAccess soa(Thread::Current());
+ StackHandleScope<4> hs(soa.Self());
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(
+ dex_compilation_unit_->GetClassLinker()->FindDexCache(*dex_compilation_unit_->GetDexFile())));
+ Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
+ soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
+ Handle<mirror::Class> cls(hs.NewHandle(compiler_driver_->ResolveClass(
+ soa, dex_cache, class_loader, type_index, dex_compilation_unit_)));
+ Handle<mirror::Class> compiling_class(hs.NewHandle(GetOutermostCompilingClass()));
+
+ return compiling_class.Get() == cls.Get();
+}
+
+
bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction,
uint32_t dex_pc,
bool is_put) {
@@ -711,7 +739,7 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction,
uint16_t field_index = instruction.VRegB_21c();
ScopedObjectAccess soa(Thread::Current());
- StackHandleScope<4> hs(soa.Self());
+ StackHandleScope<5> hs(soa.Self());
Handle<mirror::DexCache> dex_cache(hs.NewHandle(
dex_compilation_unit_->GetClassLinker()->FindDexCache(*dex_compilation_unit_->GetDexFile())));
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
@@ -724,23 +752,36 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction,
return false;
}
- Handle<mirror::Class> referrer_class(hs.NewHandle(compiler_driver_->ResolveCompilingMethodsClass(
- soa, dex_cache, class_loader, outer_compilation_unit_)));
+ const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile();
+ Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle(
+ outer_compilation_unit_->GetClassLinker()->FindDexCache(outer_dex_file)));
+ Handle<mirror::Class> referrer_class(hs.NewHandle(GetOutermostCompilingClass()));
// The index at which the field's class is stored in the DexCache's type array.
uint32_t storage_index;
- std::pair<bool, bool> pair = compiler_driver_->IsFastStaticField(
- dex_cache.Get(), referrer_class.Get(), resolved_field.Get(), field_index, &storage_index);
- bool can_easily_access = is_put ? pair.second : pair.first;
- if (!can_easily_access) {
+ bool is_referrer_class = (referrer_class.Get() == resolved_field->GetDeclaringClass());
+ if (is_referrer_class) {
+ storage_index = referrer_class->GetDexTypeIndex();
+ } else if (outer_dex_cache.Get() != dex_cache.Get()) {
+ // The compiler driver cannot currently understand multple dex caches involved. Just bailout.
return false;
+ } else {
+ std::pair<bool, bool> pair = compiler_driver_->IsFastStaticField(
+ outer_dex_cache.Get(),
+ referrer_class.Get(),
+ resolved_field.Get(),
+ field_index,
+ &storage_index);
+ bool can_easily_access = is_put ? pair.second : pair.first;
+ if (!can_easily_access) {
+ return false;
+ }
}
// TODO: find out why this check is needed.
bool is_in_dex_cache = compiler_driver_->CanAssumeTypeIsPresentInDexCache(
*outer_compilation_unit_->GetDexFile(), storage_index);
bool is_initialized = resolved_field->GetDeclaringClass()->IsInitialized() && is_in_dex_cache;
- bool is_referrer_class = (referrer_class.Get() == resolved_field->GetDeclaringClass());
HLoadClass* constant = new (arena_) HLoadClass(storage_index, is_referrer_class, dex_pc);
current_block_->AddInstruction(constant);
@@ -966,7 +1007,7 @@ bool HGraphBuilder::BuildTypeCheck(const Instruction& instruction,
// `CanAccessTypeWithoutChecks` will tell whether the method being
// built is trying to access its own class, so that the generated
// code can optimize for this case. However, the optimization does not
- // work for inlining, so we use `IsCompilingClass` instead.
+ // work for inlining, so we use `IsOutermostCompilingClass` instead.
bool dont_use_is_referrers_class;
bool can_access = compiler_driver_->CanAccessTypeWithoutChecks(
dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index,
@@ -976,7 +1017,8 @@ bool HGraphBuilder::BuildTypeCheck(const Instruction& instruction,
return false;
}
HInstruction* object = LoadLocal(reference, Primitive::kPrimNot);
- HLoadClass* cls = new (arena_) HLoadClass(type_index, IsCompilingClass(type_index), dex_pc);
+ HLoadClass* cls = new (arena_) HLoadClass(
+ type_index, IsOutermostCompilingClass(type_index), dex_pc);
current_block_->AddInstruction(cls);
// The class needs a temporary before being used by the type check.
Temporaries temps(graph_);
@@ -1971,7 +2013,7 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32
// `CanAccessTypeWithoutChecks` will tell whether the method being
// built is trying to access its own class, so that the generated
// code can optimize for this case. However, the optimization does not
- // work for inlining, so we use `IsCompilingClass` instead.
+ // work for inlining, so we use `IsOutermostCompilingClass` instead.
bool can_access = compiler_driver_->CanAccessTypeWithoutChecks(
dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index,
&type_known_final, &type_known_abstract, &dont_use_is_referrers_class);
@@ -1980,7 +2022,7 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32
return false;
}
current_block_->AddInstruction(
- new (arena_) HLoadClass(type_index, IsCompilingClass(type_index), dex_pc));
+ new (arena_) HLoadClass(type_index, IsOutermostCompilingClass(type_index), dex_pc));
UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
break;
}
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h
index c70170b..b206660 100644
--- a/compiler/optimizing/builder.h
+++ b/compiler/optimizing/builder.h
@@ -225,13 +225,10 @@ class HGraphBuilder : public ValueObject {
void MaybeRecordStat(MethodCompilationStat compilation_stat);
+ mirror::Class* GetOutermostCompilingClass() const;
+
// Returns whether `type_index` points to the outer-most compiling method's class.
- bool IsCompilingClass(uint16_t type_index) const {
- uint32_t referrer_index = outer_compilation_unit_->GetDexMethodIndex();
- const DexFile::MethodId& method_id =
- outer_compilation_unit_->GetDexFile()->GetMethodId(referrer_index);
- return method_id.class_idx_ == type_index;
- }
+ bool IsOutermostCompilingClass(uint16_t type_index) const;
ArenaAllocator* const arena_;
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 968fe3e..256e85b 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -68,87 +68,87 @@ bool HInliner::TryInline(HInvoke* invoke_instruction,
uint32_t method_index,
InvokeType invoke_type) const {
ScopedObjectAccess soa(Thread::Current());
- const DexFile& outer_dex_file = *outer_compilation_unit_.GetDexFile();
- VLOG(compiler) << "Try inlining " << PrettyMethod(method_index, outer_dex_file);
+ const DexFile& caller_dex_file = *caller_compilation_unit_.GetDexFile();
+ VLOG(compiler) << "Try inlining " << PrettyMethod(method_index, caller_dex_file);
StackHandleScope<3> hs(soa.Self());
Handle<mirror::DexCache> dex_cache(
- hs.NewHandle(outer_compilation_unit_.GetClassLinker()->FindDexCache(outer_dex_file)));
+ hs.NewHandle(caller_compilation_unit_.GetClassLinker()->FindDexCache(caller_dex_file)));
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
- soa.Decode<mirror::ClassLoader*>(outer_compilation_unit_.GetClassLoader())));
+ soa.Decode<mirror::ClassLoader*>(caller_compilation_unit_.GetClassLoader())));
Handle<mirror::ArtMethod> resolved_method(hs.NewHandle(
compiler_driver_->ResolveMethod(
- soa, dex_cache, class_loader, &outer_compilation_unit_, method_index, invoke_type)));
+ soa, dex_cache, class_loader, &caller_compilation_unit_, method_index, invoke_type)));
if (resolved_method.Get() == nullptr) {
- VLOG(compiler) << "Method cannot be resolved " << PrettyMethod(method_index, outer_dex_file);
+ VLOG(compiler) << "Method cannot be resolved " << PrettyMethod(method_index, caller_dex_file);
return false;
}
+ bool can_use_dex_cache = true;
+ const DexFile& outer_dex_file = *outer_compilation_unit_.GetDexFile();
if (resolved_method->GetDexFile()->GetLocation().compare(outer_dex_file.GetLocation()) != 0) {
- VLOG(compiler) << "Did not inline "
- << PrettyMethod(method_index, outer_dex_file)
- << " because it is in a different dex file";
- return false;
+ can_use_dex_cache = false;
}
const DexFile::CodeItem* code_item = resolved_method->GetCodeItem();
if (code_item == nullptr) {
- VLOG(compiler) << "Method " << PrettyMethod(method_index, outer_dex_file)
+ VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
<< " is not inlined because it is native";
return false;
}
if (code_item->insns_size_in_code_units_ > kMaxInlineCodeUnits) {
- VLOG(compiler) << "Method " << PrettyMethod(method_index, outer_dex_file)
+ VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
<< " is too big to inline";
return false;
}
if (code_item->tries_size_ != 0) {
- VLOG(compiler) << "Method " << PrettyMethod(method_index, outer_dex_file)
+ VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
<< " is not inlined because of try block";
return false;
}
if (!resolved_method->GetDeclaringClass()->IsVerified()) {
- VLOG(compiler) << "Method " << PrettyMethod(method_index, outer_dex_file)
+ VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
<< " is not inlined because its class could not be verified";
return false;
}
if (resolved_method->ShouldNotInline()) {
- VLOG(compiler) << "Method " << PrettyMethod(method_index, outer_dex_file)
+ VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
<< " was already flagged as non inlineable";
return false;
}
- if (!TryBuildAndInline(resolved_method, invoke_instruction, method_index)) {
+ if (!TryBuildAndInline(resolved_method, invoke_instruction, method_index, can_use_dex_cache)) {
resolved_method->SetShouldNotInline();
return false;
}
- VLOG(compiler) << "Successfully inlined " << PrettyMethod(method_index, outer_dex_file);
+ VLOG(compiler) << "Successfully inlined " << PrettyMethod(method_index, caller_dex_file);
MaybeRecordStat(kInlinedInvoke);
return true;
}
bool HInliner::TryBuildAndInline(Handle<mirror::ArtMethod> resolved_method,
HInvoke* invoke_instruction,
- uint32_t method_index) const {
+ uint32_t method_index,
+ bool can_use_dex_cache) const {
ScopedObjectAccess soa(Thread::Current());
const DexFile::CodeItem* code_item = resolved_method->GetCodeItem();
- const DexFile& outer_dex_file = *outer_compilation_unit_.GetDexFile();
+ const DexFile& caller_dex_file = *caller_compilation_unit_.GetDexFile();
DexCompilationUnit dex_compilation_unit(
nullptr,
- outer_compilation_unit_.GetClassLoader(),
- outer_compilation_unit_.GetClassLinker(),
- outer_dex_file,
+ caller_compilation_unit_.GetClassLoader(),
+ caller_compilation_unit_.GetClassLinker(),
+ *resolved_method->GetDexFile(),
code_item,
resolved_method->GetDeclaringClass()->GetDexClassDefIndex(),
- method_index,
+ resolved_method->GetDexMethodIndex(),
resolved_method->GetAccessFlags(),
nullptr);
@@ -159,25 +159,25 @@ bool HInliner::TryBuildAndInline(Handle<mirror::ArtMethod> resolved_method,
HGraphBuilder builder(callee_graph,
&dex_compilation_unit,
&outer_compilation_unit_,
- &outer_dex_file,
+ resolved_method->GetDexFile(),
compiler_driver_,
&inline_stats);
if (!builder.BuildGraph(*code_item)) {
- VLOG(compiler) << "Method " << PrettyMethod(method_index, outer_dex_file)
+ VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
<< " could not be built, so cannot be inlined";
return false;
}
if (!RegisterAllocator::CanAllocateRegistersFor(*callee_graph,
compiler_driver_->GetInstructionSet())) {
- VLOG(compiler) << "Method " << PrettyMethod(method_index, outer_dex_file)
+ VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
<< " cannot be inlined because of the register allocator";
return false;
}
if (!callee_graph->TryBuildingSsa()) {
- VLOG(compiler) << "Method " << PrettyMethod(method_index, outer_dex_file)
+ VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
<< " could not be transformed to SSA";
return false;
}
@@ -199,8 +199,12 @@ bool HInliner::TryBuildAndInline(Handle<mirror::ArtMethod> resolved_method,
}
if (depth_ + 1 < kDepthLimit) {
- HInliner inliner(
- callee_graph, outer_compilation_unit_, compiler_driver_, stats_, depth_ + 1);
+ HInliner inliner(callee_graph,
+ outer_compilation_unit_,
+ dex_compilation_unit,
+ compiler_driver_,
+ stats_,
+ depth_ + 1);
inliner.Run();
}
@@ -209,7 +213,7 @@ bool HInliner::TryBuildAndInline(Handle<mirror::ArtMethod> resolved_method,
for (; !it.Done(); it.Advance()) {
HBasicBlock* block = it.Current();
if (block->IsLoopHeader()) {
- VLOG(compiler) << "Method " << PrettyMethod(method_index, outer_dex_file)
+ VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
<< " could not be inlined because it contains a loop";
return false;
}
@@ -223,18 +227,25 @@ bool HInliner::TryBuildAndInline(Handle<mirror::ArtMethod> resolved_method,
}
if (current->CanThrow()) {
- VLOG(compiler) << "Method " << PrettyMethod(method_index, outer_dex_file)
+ VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
<< " could not be inlined because " << current->DebugName()
<< " can throw";
return false;
}
if (current->NeedsEnvironment()) {
- VLOG(compiler) << "Method " << PrettyMethod(method_index, outer_dex_file)
+ VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
<< " could not be inlined because " << current->DebugName()
<< " needs an environment";
return false;
}
+
+ if (!can_use_dex_cache && current->NeedsDexCache()) {
+ VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
+ << " could not be inlined because " << current->DebugName()
+ << " it is in a different dex file and requires access to the dex cache";
+ return false;
+ }
}
}
diff --git a/compiler/optimizing/inliner.h b/compiler/optimizing/inliner.h
index 1251977..1dbc7d3 100644
--- a/compiler/optimizing/inliner.h
+++ b/compiler/optimizing/inliner.h
@@ -32,11 +32,13 @@ class HInliner : public HOptimization {
public:
HInliner(HGraph* outer_graph,
const DexCompilationUnit& outer_compilation_unit,
+ const DexCompilationUnit& caller_compilation_unit,
CompilerDriver* compiler_driver,
OptimizingCompilerStats* stats,
size_t depth = 0)
: HOptimization(outer_graph, true, kInlinerPassName, stats),
outer_compilation_unit_(outer_compilation_unit),
+ caller_compilation_unit_(caller_compilation_unit),
compiler_driver_(compiler_driver),
depth_(depth) {}
@@ -48,9 +50,11 @@ class HInliner : public HOptimization {
bool TryInline(HInvoke* invoke_instruction, uint32_t method_index, InvokeType invoke_type) const;
bool TryBuildAndInline(Handle<mirror::ArtMethod> resolved_method,
HInvoke* invoke_instruction,
- uint32_t method_index) const;
+ uint32_t method_index,
+ bool can_use_dex_cache) const;
const DexCompilationUnit& outer_compilation_unit_;
+ const DexCompilationUnit& caller_compilation_unit_;
CompilerDriver* const compiler_driver_;
const size_t depth_;
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index db7873b..a38ee45 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1220,6 +1220,8 @@ class HInstruction : public ArenaObject<kArenaAllocMisc> {
return NeedsEnvironment() || IsLoadClass() || IsLoadString();
}
+ virtual bool NeedsDexCache() const { return false; }
+
protected:
virtual const HUserRecord<HInstruction*> InputRecordAt(size_t i) const = 0;
virtual void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) = 0;
@@ -2114,6 +2116,7 @@ class HInvokeStaticOrDirect : public HInvoke {
InvokeType GetInvokeType() const { return invoke_type_; }
bool IsRecursive() const { return is_recursive_; }
+ bool NeedsDexCache() const OVERRIDE { return !IsRecursive(); }
DECLARE_INSTRUCTION(InvokeStaticOrDirect);
@@ -2996,6 +2999,8 @@ class HLoadClass : public HExpression<0> {
return loaded_class_rti_.IsExact();
}
+ bool NeedsDexCache() const OVERRIDE { return !is_referrers_class_; }
+
DECLARE_INSTRUCTION(LoadClass);
private:
@@ -3031,6 +3036,7 @@ class HLoadString : public HExpression<0> {
// TODO: Can we deopt or debug when we resolve a string?
bool NeedsEnvironment() const OVERRIDE { return false; }
+ bool NeedsDexCache() const OVERRIDE { return true; }
DECLARE_INSTRUCTION(LoadString);
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index eaa30df..5ce73ba 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -316,7 +316,7 @@ static void RunOptimizations(HGraph* graph,
InstructionSimplifier simplify1(graph, stats);
HBooleanSimplifier boolean_not(graph);
- HInliner inliner(graph, dex_compilation_unit, driver, stats);
+ HInliner inliner(graph, dex_compilation_unit, dex_compilation_unit, driver, stats);
HConstantFolding fold2(graph);
SideEffectsAnalysis side_effects(graph);