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
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index bd94789..63b2705 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -1304,15 +1304,18 @@
     }
   }
 
-  // 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 @@
     // 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());