summaryrefslogtreecommitdiff
path: root/compiler/optimizing/instruction_builder.cc
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2018-10-30 18:09:55 +0000
committer Vladimir Marko <vmarko@google.com> 2018-10-31 11:13:04 +0000
commit7f260d43e9b440f934270873c1e03eb867fa2873 (patch)
tree3285c18d7b29bb818bedabae6120baae8b444321 /compiler/optimizing/instruction_builder.cc
parent91ddef31f229e6d116cc8988b71aa77bc5083bcb (diff)
Fix and improve ClinitCheck elimination.
Fix erroneous usage of the inner method's access flags while checking the class of the outer method. This allowed erroneous elimination of a needed ClinitCheck when inlining. Treat constructors the same way as static methods as the instance allocation necessarily preceding the constructor call performs the class initialization check. The size of the aosp_taimen-userdebug prebuilts: - before: arm/boot*.oat: 20252196 arm64/boot*.oat: 24030776 oat/arm64/services.odex: 22406664 - after: arm/boot*.oat: 20252092 (-0.1KiB) arm64/boot*.oat: 24027024 (-3.7KiB) oat/arm64/services.odex: 22402528 (-4.0KiB) (Insignificant changes.) Test: Add regression test to 174-escaping-instance-of-bad-class. Test: Add optimization test to 551-checker-clinit. Test: testrunner.py --jvm -t 174 Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Test: Pixel 2 XL boots. Test: m test-art-target-gtest Test: testrunner.py --target --optimizing Bug: 62478025 Change-Id: I591aca2c538d10cf6df1d38d59270af1de380b3e
Diffstat (limited to 'compiler/optimizing/instruction_builder.cc')
-rw-r--r--compiler/optimizing/instruction_builder.cc15
1 files changed, 10 insertions, 5 deletions
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index bd94789144..63b2705b43 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -1304,15 +1304,18 @@ bool HInstructionBuilder::IsInitialized(ScopedObjectAccess& soa, Handle<mirror::
}
}
- // We can avoid the class initialization check for `cls` in static methods in the
- // very same class. Instance methods of the same class can run on an escaped instance
+ // We can avoid the class initialization check for `cls` in static methods and constructors
+ // in the very same class; invoking a static method involves a class initialization check
+ // and so does the instance allocation that must be executed before invoking a constructor.
+ // Other 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.
ObjPtr<mirror::Class> outermost_cls = ResolveOutermostCompilingClass(soa);
- bool is_static = (dex_compilation_unit_->GetAccessFlags() & kAccStatic) != 0u;
- if (is_static && outermost_cls == cls.Get()) {
+ bool is_outer_static_or_constructor =
+ (outer_compilation_unit_->GetAccessFlags() & (kAccStatic | kAccConstructor)) != 0u;
+ if (is_outer_static_or_constructor && outermost_cls == cls.Get()) {
return true;
}
// Remember if the compiled class is a subclass of `cls`. By the time this is used
@@ -1325,7 +1328,9 @@ bool HInstructionBuilder::IsInitialized(ScopedObjectAccess& soa, Handle<mirror::
// TODO: We should walk over the entire inlined method chain, but we don't pass that
// information to the builder.
ObjPtr<mirror::Class> innermost_cls = ResolveCompilingClass(soa);
- if (is_static && innermost_cls == cls.Get()) {
+ bool is_inner_static_or_constructor =
+ (dex_compilation_unit_->GetAccessFlags() & (kAccStatic | kAccConstructor)) != 0u;
+ if (is_inner_static_or_constructor && innermost_cls == cls.Get()) {
return true;
}
is_subclass = is_subclass || IsSubClass(innermost_cls, cls.Get());