summaryrefslogtreecommitdiff
path: root/compiler/optimizing/builder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/builder.cc')
-rw-r--r--compiler/optimizing/builder.cc101
1 files changed, 55 insertions, 46 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 32968a597b..d7754e8ea9 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -905,14 +905,15 @@ bool HGraphBuilder::BuildNewInstance(uint16_t type_index, uint32_t dex_pc) {
HLoadClass* load_class = new (arena_) HLoadClass(
graph_->GetCurrentMethod(),
type_index,
- *dex_compilation_unit_->GetDexFile(),
+ outer_dex_file,
IsOutermostCompilingClass(type_index),
dex_pc,
- /*needs_access_check*/ can_throw);
+ /*needs_access_check*/ can_throw,
+ compiler_driver_->CanAssumeTypeIsPresentInDexCache(outer_dex_file, type_index));
current_block_->AddInstruction(load_class);
HInstruction* cls = load_class;
- if (!IsInitialized(resolved_class, type_index)) {
+ if (!IsInitialized(resolved_class)) {
cls = new (arena_) HClinitCheck(load_class, dex_pc);
current_block_->AddInstruction(cls);
}
@@ -929,17 +930,34 @@ bool HGraphBuilder::BuildNewInstance(uint16_t type_index, uint32_t dex_pc) {
return true;
}
-bool HGraphBuilder::IsInitialized(Handle<mirror::Class> cls, uint16_t type_index) const {
+static bool IsSubClass(mirror::Class* to_test, mirror::Class* super_class)
+ SHARED_REQUIRES(Locks::mutator_lock_) {
+ return to_test != nullptr && !to_test->IsInterface() && to_test->IsSubClass(super_class);
+}
+
+bool HGraphBuilder::IsInitialized(Handle<mirror::Class> cls) const {
if (cls.Get() == nullptr) {
return false;
}
- if (GetOutermostCompilingClass() == cls.Get()) {
+
+ // `CanAssumeClassIsLoaded` will return true if we're JITting, or will
+ // check whether the class is in an image for the AOT compilation.
+ if (cls->IsInitialized() &&
+ compiler_driver_->CanAssumeClassIsLoaded(cls.Get())) {
+ return true;
+ }
+
+ if (IsSubClass(GetOutermostCompilingClass(), cls.Get())) {
+ return true;
+ }
+
+ // TODO: We should walk over the inlined methods, but we don't pass
+ // that information to the builder.
+ if (IsSubClass(GetCompilingClass(), cls.Get())) {
return true;
}
- // TODO: find out why this check is needed.
- bool is_in_dex_cache = compiler_driver_->CanAssumeTypeIsPresentInDexCache(
- *outer_compilation_unit_->GetDexFile(), type_index);
- return cls->IsInitialized() && is_in_dex_cache;
+
+ return false;
}
HClinitCheck* HGraphBuilder::ProcessClinitCheckForInvoke(
@@ -962,6 +980,7 @@ HClinitCheck* HGraphBuilder::ProcessClinitCheckForInvoke(
Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle(
outer_compilation_unit_->GetClassLinker()->FindDexCache(soa.Self(), outer_dex_file)));
Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
+ Handle<mirror::Class> resolved_method_class(hs.NewHandle(resolved_method->GetDeclaringClass()));
// The index at which the method's class is stored in the DexCache's type array.
uint32_t storage_index = DexFile::kDexNoIndex;
@@ -979,36 +998,21 @@ HClinitCheck* HGraphBuilder::ProcessClinitCheckForInvoke(
HClinitCheck* clinit_check = nullptr;
- if (!outer_class->IsInterface()
- && outer_class->IsSubClass(resolved_method->GetDeclaringClass())) {
- // If the outer class is the declaring class or a subclass
- // of the declaring class, no class initialization is needed
- // before the static method call.
- // Note that in case of inlining, we do not need to add clinit checks
- // to calls that satisfy this subclass check with any inlined methods. This
- // will be detected by the optimization passes.
+ if (IsInitialized(resolved_method_class)) {
*clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
} else if (storage_index != DexFile::kDexNoIndex) {
- // If the method's class type index is available, check
- // whether we should add an explicit class initialization
- // check for its declaring class before the static method call.
-
- Handle<mirror::Class> cls(hs.NewHandle(resolved_method->GetDeclaringClass()));
- if (IsInitialized(cls, storage_index)) {
- *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
- } else {
- *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit;
- HLoadClass* load_class = new (arena_) HLoadClass(
- graph_->GetCurrentMethod(),
- storage_index,
- *dex_compilation_unit_->GetDexFile(),
- is_outer_class,
- dex_pc,
- /*needs_access_check*/ false);
- current_block_->AddInstruction(load_class);
- clinit_check = new (arena_) HClinitCheck(load_class, dex_pc);
- current_block_->AddInstruction(clinit_check);
- }
+ *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit;
+ HLoadClass* load_class = new (arena_) HLoadClass(
+ graph_->GetCurrentMethod(),
+ storage_index,
+ outer_dex_file,
+ is_outer_class,
+ dex_pc,
+ /*needs_access_check*/ false,
+ compiler_driver_->CanAssumeTypeIsPresentInDexCache(outer_dex_file, storage_index));
+ current_block_->AddInstruction(load_class);
+ clinit_check = new (arena_) HClinitCheck(load_class, dex_pc);
+ current_block_->AddInstruction(clinit_check);
}
return clinit_check;
}
@@ -1379,18 +1383,21 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction,
}
}
+ bool is_in_cache =
+ compiler_driver_->CanAssumeTypeIsPresentInDexCache(outer_dex_file, storage_index);
HLoadClass* constant = new (arena_) HLoadClass(graph_->GetCurrentMethod(),
storage_index,
- *dex_compilation_unit_->GetDexFile(),
+ outer_dex_file,
is_outer_class,
dex_pc,
- /*needs_access_check*/ false);
+ /*needs_access_check*/ false,
+ is_in_cache);
current_block_->AddInstruction(constant);
HInstruction* cls = constant;
Handle<mirror::Class> klass(hs.NewHandle(resolved_field->GetDeclaringClass()));
- if (!IsInitialized(klass, storage_index)) {
+ if (!IsInitialized(klass)) {
cls = new (arena_) HClinitCheck(constant, dex_pc);
current_block_->AddInstruction(cls);
}
@@ -1659,19 +1666,20 @@ void HGraphBuilder::BuildTypeCheck(const Instruction& instruction,
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<2> hs(soa.Self());
+ const DexFile& dex_file = *dex_compilation_unit_->GetDexFile();
Handle<mirror::DexCache> dex_cache(hs.NewHandle(
- dex_compilation_unit_->GetClassLinker()->FindDexCache(
- soa.Self(), *dex_compilation_unit_->GetDexFile())));
+ dex_compilation_unit_->GetClassLinker()->FindDexCache(soa.Self(), dex_file)));
Handle<mirror::Class> resolved_class(hs.NewHandle(dex_cache->GetResolvedType(type_index)));
HInstruction* object = LoadLocal(reference, Primitive::kPrimNot, dex_pc);
HLoadClass* cls = new (arena_) HLoadClass(
graph_->GetCurrentMethod(),
type_index,
- *dex_compilation_unit_->GetDexFile(),
+ dex_file,
IsOutermostCompilingClass(type_index),
dex_pc,
- !can_access);
+ !can_access,
+ compiler_driver_->CanAssumeTypeIsPresentInDexCache(dex_file, type_index));
current_block_->AddInstruction(cls);
// The class needs a temporary before being used by the type check.
@@ -2797,10 +2805,11 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32
current_block_->AddInstruction(new (arena_) HLoadClass(
graph_->GetCurrentMethod(),
type_index,
- *dex_compilation_unit_->GetDexFile(),
+ *dex_file_,
IsOutermostCompilingClass(type_index),
dex_pc,
- !can_access));
+ !can_access,
+ compiler_driver_->CanAssumeTypeIsPresentInDexCache(*dex_file_, type_index)));
UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction(), dex_pc);
break;
}