summaryrefslogtreecommitdiff
path: root/compiler/optimizing/instruction_builder.cc
diff options
context:
space:
mode:
authorVladimir Marko <vmarko@google.com>2018-07-12 10:43:28 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2018-07-12 10:43:28 +0000
commitbbd2cc2e23691515def685fc3dcea6cd792a2f4e (patch)
tree45d84f370b70b9aaee23aaa514dd3073d78893ba /compiler/optimizing/instruction_builder.cc
parentc06bfc9b18e6421ac60e7b27f8f1e90b45772f52 (diff)
parent51b8aafd3beb8855a258383a9eb876a783375629 (diff)
Merge "Fix HClinitCheck elimination in instruction builder."
Diffstat (limited to 'compiler/optimizing/instruction_builder.cc')
-rw-r--r--compiler/optimizing/instruction_builder.cc53
1 files changed, 32 insertions, 21 deletions
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index ba160e55f8..771e066d2f 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -1147,32 +1147,48 @@ void HInstructionBuilder::BuildConstructorFenceForAllocation(HInstruction* alloc
MethodCompilationStat::kConstructorFenceGeneratedNew);
}
-static bool IsSubClass(ObjPtr<mirror::Class> to_test, ObjPtr<mirror::Class> super_class)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- return to_test != nullptr && !to_test->IsInterface() && to_test->IsSubClass(super_class);
-}
-
bool HInstructionBuilder::IsInitialized(Handle<mirror::Class> cls) const {
if (cls == nullptr) {
return false;
}
- // `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;
+ // Check if the class will be initialized at runtime.
+ if (cls->IsInitialized()) {
+ Runtime* runtime = Runtime::Current();
+ if (!runtime->IsAotCompiler()) {
+ DCHECK(runtime->UseJitCompilation());
+ // For JIT, the class cannot revert to an uninitialized state.
+ return true;
+ }
+ // Assume loaded only if klass is in the boot image. App classes cannot be assumed
+ // loaded because we don't even know what class loader will be used to load them.
+ const CompilerOptions& compiler_options = compiler_driver_->GetCompilerOptions();
+ if (compiler_options.IsBootImage()) {
+ std::string temp;
+ const char* descriptor = cls->GetDescriptor(&temp);
+ if (compiler_options.IsImageClass(descriptor)) {
+ return true;
+ }
+ } else {
+ if (runtime->GetHeap()->FindSpaceFromObject(cls.Get(), false)->IsImageSpace()) {
+ return true;
+ }
+ }
}
- if (IsSubClass(GetOutermostCompilingClass(), cls.Get())) {
+ // We can avoid the class initialization check for `cls` only in static methods in the
+ // very same class. Instance methods of the same class can run on an escaped instance
+ // of an erroneous class. Even a superclass may need to be checked as the subclass
+ // can be completely initialized while the superclass is initializing and the subclass
+ // remains initialized when the superclass initializer throws afterwards. b/62478025
+ // Note: The HClinitCheck+HInvokeStaticOrDirect merging can still apply.
+ if ((dex_compilation_unit_->GetAccessFlags() & kAccStatic) != 0u &&
+ 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;
- }
+ // Note: We could walk over the inlined methods to avoid allocating excessive
+ // `HClinitCheck`s in inlined static methods but they shall be eliminated by GVN.
return false;
}
@@ -1926,11 +1942,6 @@ void HInstructionBuilder::BuildTypeCheck(const Instruction& instruction,
}
}
-bool HInstructionBuilder::NeedsAccessCheck(dex::TypeIndex type_index, bool* finalizable) const {
- return !compiler_driver_->CanAccessInstantiableTypeWithoutChecks(
- LookupReferrerClass(), LookupResolvedType(type_index, *dex_compilation_unit_), finalizable);
-}
-
bool HInstructionBuilder::CanDecodeQuickenedInfo() const {
return !quicken_info_.IsNull();
}