Revert "Support clinit for app image during compilation"

Breaks on bots.

This reverts commit 50ce4414a6154ee2d9eeaa27237d80b685e5acf1.

Change-Id: I39d856dc76b55788b6775ff2269eb8570742c6ff
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 5eee7e0..bd530ac 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -2251,7 +2251,6 @@
     const char* descriptor = dex_file.StringDataByIdx(class_type_id.descriptor_idx_);
     ScopedObjectAccessUnchecked soa(Thread::Current());
     StackHandleScope<3> hs(soa.Self());
-    ClassLinker *class_linker = manager_->GetClassLinker();
     const bool is_boot_image = manager_->GetCompiler()->GetCompilerOptions().IsBootImage();
     const bool is_app_image = manager_->GetCompiler()->GetCompilerOptions().IsAppImage();
 
@@ -2265,7 +2264,7 @@
     if (klass->IsVerified()) {
       // Attempt to initialize the class but bail if we either need to initialize the super-class
       // or static fields.
-      class_linker->EnsureInitialized(soa.Self(), klass, false, false);
+      manager_->GetClassLinker()->EnsureInitialized(soa.Self(), klass, false, false);
       old_status = klass->GetStatus();
       if (!klass->IsInitialized()) {
         // We don't want non-trivial class initialization occurring on multiple threads due to
@@ -2284,7 +2283,7 @@
         bool is_superclass_initialized = !is_app_image ? true :
             InitializeDependencies(klass, class_loader, soa.Self());
         if (!is_app_image || (is_app_image && is_superclass_initialized)) {
-          class_linker->EnsureInitialized(soa.Self(), klass, false, true);
+          manager_->GetClassLinker()->EnsureInitialized(soa.Self(), klass, false, true);
         }
         // Otherwise it's in app image but superclasses can't be initialized, no need to proceed.
         old_status = klass->GetStatus();
@@ -2310,13 +2309,10 @@
             CHECK(is_app_image);
             // The boot image case doesn't need to recursively initialize the dependencies with
             // special logic since the class linker already does this.
-            // Optimization will be disabled in debuggable build, because in debuggable mode we
-            // want the <clinit> behavior to be observable for the debugger, so we don't do the
-            // <clinit> at compile time.
             can_init_static_fields =
-                !manager_->GetCompiler()->GetCompilerOptions().GetDebuggable() &&
                 !soa.Self()->IsExceptionPending() &&
-                is_superclass_initialized;
+                is_superclass_initialized &&
+                NoClinitInDependency(klass, soa.Self(), &class_loader);
             // TODO The checking for clinit can be removed since it's already
             // checked when init superclass. Currently keep it because it contains
             // processing of intern strings. Will be removed later when intern strings
@@ -2330,18 +2326,6 @@
             // a ReaderWriterMutex but we're holding the mutator lock so we fail mutex sanity
             // checks in Thread::AssertThreadSuspensionIsAllowable.
             Runtime* const runtime = Runtime::Current();
-            // Resolve and initialize the exception type before enabling the transaction in case
-            // the transaction aborts and cannot resolve the type.
-            // TransactionAbortError is not initialized ant not in boot image, needed only by
-            // compiler and will be pruned by ImageWriter.
-            Handle<mirror::Class> exception_class =
-                hs.NewHandle(class_linker->FindClass(Thread::Current(),
-                                                     Transaction::kAbortExceptionSignature,
-                                                     class_loader));
-            bool exception_initialized =
-                class_linker->EnsureInitialized(soa.Self(), exception_class, true, true);
-            DCHECK(exception_initialized);
-
             // Run the class initializer in transaction mode.
             runtime->EnterTransactionMode(is_app_image, klass.Get());
             bool success = manager_->GetClassLinker()->EnsureInitialized(soa.Self(), klass, true,
@@ -2379,12 +2363,10 @@
               }
             }
 
-            if (!success && is_boot_image) {
+            if (!success) {
               // On failure, still intern strings of static fields and seen in <clinit>, as these
               // will be created in the zygote. This is separated from the transaction code just
               // above as we will allocate strings, so must be allowed to suspend.
-              // We only need to intern strings for boot image because classes that failed to be
-              // initialized will not appear in app image.
               if (&klass->GetDexFile() == manager_->GetDexFile()) {
                 InternStrings(klass, class_loader);
               } else {
diff --git a/runtime/aot_class_linker.cc b/runtime/aot_class_linker.cc
index d8f9e22..b1bc3f8 100644
--- a/runtime/aot_class_linker.cc
+++ b/runtime/aot_class_linker.cc
@@ -27,16 +27,6 @@
 
 AotClassLinker::~AotClassLinker() {}
 
-bool AotClassLinker::CanAllocClass() {
-  // AllocClass doesn't work under transaction, so we abort.
-  if (Runtime::Current()->IsActiveTransaction()) {
-    Runtime::Current()->AbortTransactionAndThrowAbortError(Thread::Current(), "Can't resolve this "
-        "type within a transaction.");
-    return false;
-  }
-  return ClassLinker::CanAllocClass();
-}
-
 // Wrap the original InitializeClass with creation of transaction when in strict mode.
 bool AotClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
                                   bool can_init_statics, bool can_init_parents) {
@@ -48,13 +38,6 @@
     return ClassLinker::InitializeClass(self, klass, can_init_statics, can_init_parents);
   }
 
-  // When in strict_mode, don't initialize a class if it belongs to boot but not initialized.
-  if (strict_mode_ && klass->IsBootStrapClassLoaded()) {
-    runtime->AbortTransactionAndThrowAbortError(self, "Can't resolve "
-        + klass->PrettyTypeOf() + " because it is an uninitialized boot class.");
-    return false;
-  }
-
   // Don't initialize klass if it's superclass is not initialized, because superclass might abort
   // the transaction and rolled back after klass's change is commited.
   if (strict_mode_ && !klass->IsInterface() && klass->HasSuperClass()) {
@@ -75,8 +58,9 @@
       // Exit Transaction if success.
       runtime->ExitTransactionMode();
     } else {
-      // If not successfully initialized, don't rollback immediately, leave the cleanup to compiler
-      // driver which needs abort message and exception.
+      // If not successfully initialized, the last transaction must abort. Don't rollback
+      // immediately, leave the cleanup to compiler driver which needs abort message and exception.
+      DCHECK(runtime->IsTransactionAborted());
       DCHECK(self->IsExceptionPending());
     }
   }
diff --git a/runtime/aot_class_linker.h b/runtime/aot_class_linker.h
index e9a96fa..11bea86 100644
--- a/runtime/aot_class_linker.h
+++ b/runtime/aot_class_linker.h
@@ -27,13 +27,6 @@
   explicit AotClassLinker(InternTable *intern_table);
   ~AotClassLinker();
 
-  // Override AllocClass because aot compiler will need to perform a transaction check to determine
-  // can we allocate class from heap.
-  bool CanAllocClass()
-      OVERRIDE
-      REQUIRES_SHARED(Locks::mutator_lock_)
-      REQUIRES(!Roles::uninterruptible_);
-
   bool InitializeClass(Thread *self,
                        Handle<mirror::Class> klass,
                        bool can_run_clinit,
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 46b0113..3ac87c5 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2854,11 +2854,7 @@
     // Interface object should get the right size here. Regular class will
     // figure out the right size later and be replaced with one of the right
     // size when the class becomes resolved.
-    if (CanAllocClass()) {
-      klass.Assign(AllocClass(self, SizeOfClassWithoutEmbeddedTables(dex_file, dex_class_def)));
-    } else {
-      return nullptr;
-    }
+    klass.Assign(AllocClass(self, SizeOfClassWithoutEmbeddedTables(dex_file, dex_class_def)));
   }
   if (UNLIKELY(klass == nullptr)) {
     self->AssertPendingOOMException();
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 584bd1d..bf14aeb 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -710,12 +710,6 @@
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::dex_lock_);
 
-  virtual bool CanAllocClass()
-      REQUIRES_SHARED(Locks::mutator_lock_)
-      REQUIRES(!Locks::dex_lock_) {
-    return true;
-  }
-
  private:
   class LinkInterfaceMethodsHelper;
 
diff --git a/test/660-clinit/expected.txt b/test/660-clinit/expected.txt
index ee1b479..9eb4941 100644
--- a/test/660-clinit/expected.txt
+++ b/test/660-clinit/expected.txt
@@ -1,5 +1,4 @@
 JNI_OnLoad called
-hello world
 A.a: 5
 A.a: 10
 B.b: 10
diff --git a/test/660-clinit/profile b/test/660-clinit/profile
index 9eb4924..0239f22 100644
--- a/test/660-clinit/profile
+++ b/test/660-clinit/profile
@@ -4,10 +4,7 @@
 LA;
 LB;
 LC;
-LE;
 LG;
 LGs;
 LObjectRef;
-LInvokeStatic;
-LClinitE;
-LPrint;
+
diff --git a/test/660-clinit/src/Main.java b/test/660-clinit/src/Main.java
index 51b4d60..f9b068e 100644
--- a/test/660-clinit/src/Main.java
+++ b/test/660-clinit/src/Main.java
@@ -24,28 +24,19 @@
     if (!checkAppImageLoaded()) {
       System.out.println("AppImage not loaded.");
     }
-    if (!checkAppImageContains(ClInit.class)) {
-      System.out.println("ClInit class is not in app image!");
-    }
 
-    expectPreInit(ClInit.class);
-    expectPreInit(A.class);
-    expectPreInit(E.class);
-    expectNotPreInit(B.class);
-    expectNotPreInit(C.class);
-    expectNotPreInit(G.class);
-    expectNotPreInit(Gs.class);
-    expectNotPreInit(Gss.class);
-    expectPreInit(InvokeStatic.class);
-    expectNotPreInit(ClinitE.class);
+    expectNotPreInit(Day.class);
+    expectNotPreInit(ClInit.class); // should pass
+    expectNotPreInit(A.class); // should pass
+    expectNotPreInit(B.class); // should fail
+    expectNotPreInit(C.class); // should fail
+    expectNotPreInit(G.class); // should fail
+    expectNotPreInit(Gs.class); // should fail
+    expectNotPreInit(Gss.class); // should fail
 
     expectNotPreInit(Add.class);
     expectNotPreInit(Mul.class);
     expectNotPreInit(ObjectRef.class);
-    expectNotPreInit(Print.class);
-
-    Print p = new Print();
-    Gs gs = new Gs();
 
     A x = new A();
     System.out.println("A.a: " + A.a);
@@ -71,10 +62,6 @@
       System.out.println("a != 101");
     }
 
-    try {
-      ClinitE e = new ClinitE();
-    } catch (Error err) { }
-
     return;
   }
 
@@ -167,13 +154,6 @@
   }
 }
 
-class E {
-  public static final int e;
-  static {
-    e = 100;
-  }
-}
-
 class G {
   static G g;
   static int i;
@@ -202,36 +182,9 @@
   }
 }
 
-// test of INVOKE_STATIC instruction
-class InvokeStatic {
-  static int a;
-  static int b;
-  static {
-    a = Add.exec(10, 20);
-    b = Mul.exec(10, 20);
-  }
-}
-
 // non-image
 class Mul {
   static int exec(int a, int b) {
     return a * b;
   }
 }
-
-class ClinitE {
-  static {
-    if (Math.sin(3) < 0.5) {
-      // throw anyway, can't initialized
-      throw new ExceptionInInitializerError("Can't initialize this class!");
-    }
-  }
-}
-
-// fail because JNI
-class Print {
-  static {
-    System.out.println("hello world");
-  }
-}
-
diff --git a/test/906-iterate-heap/expected.txt b/test/906-iterate-heap/expected.txt
index 85391fa..73b7129 100644
--- a/test/906-iterate-heap/expected.txt
+++ b/test/906-iterate-heap/expected.txt
@@ -19,7 +19,9 @@
 1@0 (32, 2xD '0000000000000000000000000000f03f')
 2
 doTestPrimitiveFieldsClasses
+10000@0 (static, int, index=3) 0000000000000000
 10001
+10000@0 (static, int, index=11) 0000000000000000
 10001
 10001
 10001
diff --git a/test/906-iterate-heap/src/art/Test906.java b/test/906-iterate-heap/src/art/Test906.java
index 1878687..65c2c8c 100644
--- a/test/906-iterate-heap/src/art/Test906.java
+++ b/test/906-iterate-heap/src/art/Test906.java
@@ -143,40 +143,19 @@
 
   private static void doTestPrimitiveFieldsClasses() {
     System.out.println("doTestPrimitiveFieldsClasses");
-    boolean correctHeapValue = false;
-
     setTag(IntObject.class, 10000);
-    String heapTrace = iterateThroughHeapPrimitiveFields(10000);
-
-    if (!checkInitialized(IntObject.class)) {
-      correctHeapValue = heapTrace.equals("10000@0 (static, int, index=3) 0000000000000000");
-    } else {
-      correctHeapValue = heapTrace.equals("10000@0 (static, int, index=3) 0000000000000005");
-    }
-
-    if (!correctHeapValue)
-      System.out.println("Heap Trace for IntObject is not as expected:\n" + heapTrace);
-
+    System.out.println(iterateThroughHeapPrimitiveFields(10000));
     System.out.println(getTag(IntObject.class));
     setTag(IntObject.class, 0);
 
     setTag(FloatObject.class, 10000);
-    heapTrace = iterateThroughHeapPrimitiveFields(10000);
-
-    if (!checkInitialized(FloatObject.class)) {
-      correctHeapValue = heapTrace.equals("10000@0 (static, int, index=11) 0000000000000000");
-    } else {
-      correctHeapValue = heapTrace.equals("10000@0 (static, int, index=11) 0000000000000006");
-    }
-
-    if (!correctHeapValue)
-      System.out.println("Heap Trace for FloatObject is not as expected:\n" + heapTrace);
-
+    System.out.println(iterateThroughHeapPrimitiveFields(10000));
     System.out.println(getTag(FloatObject.class));
     setTag(FloatObject.class, 0);
 
+    boolean correctHeapValue = false;
     setTag(Inf1.class, 10000);
-    heapTrace = iterateThroughHeapPrimitiveFields(10000);
+    String heapTrace = iterateThroughHeapPrimitiveFields(10000);
 
     if (!checkInitialized(Inf1.class)) {
       correctHeapValue = heapTrace.equals("10000@0 (static, int, index=0) 0000000000000000");
diff --git a/test/913-heaps/expected.txt b/test/913-heaps/expected.txt
index 844afe8..6144881 100644
--- a/test/913-heaps/expected.txt
+++ b/test/913-heaps/expected.txt
@@ -136,7 +136,9 @@
 4@0 (18, 3xS '010002000300')
 1@0 (14, 2xZ '0001')
 23456789
+10000@0 (static, int, index=3) 0000000000000000
 10001
+10000@0 (static, int, index=11) 0000000000000000
 10001
 10001
 10001
diff --git a/test/913-heaps/src/art/Test913.java b/test/913-heaps/src/art/Test913.java
index 28f9546..b999001 100644
--- a/test/913-heaps/src/art/Test913.java
+++ b/test/913-heaps/src/art/Test913.java
@@ -185,40 +185,19 @@
   }
 
   private static void doTestPrimitiveFieldsClasses() {
-    boolean correctHeapValue = false;
-
     setTag(IntObject.class, 10000);
-    String heapTrace = followReferencesPrimitiveFields(IntObject.class);
-
-    if (!checkInitialized(IntObject.class)) {
-      correctHeapValue = heapTrace.equals("10000@0 (static, int, index=3) 0000000000000000");
-    } else {
-      correctHeapValue = heapTrace.equals("10000@0 (static, int, index=3) 0000000000000005");
-    }
-
-    if (!correctHeapValue)
-      System.out.println("Heap Trace for IntObject is not as expected:\n" + heapTrace);
-
+    System.out.println(followReferencesPrimitiveFields(IntObject.class));
     System.out.println(getTag(IntObject.class));
     setTag(IntObject.class, 0);
 
     setTag(FloatObject.class, 10000);
-    heapTrace = followReferencesPrimitiveFields(FloatObject.class);
-
-    if (!checkInitialized(FloatObject.class)) {
-      correctHeapValue = heapTrace.equals("10000@0 (static, int, index=11) 0000000000000000");
-    } else {
-      correctHeapValue = heapTrace.equals("10000@0 (static, int, index=11) 0000000000000006");
-    }
-
-    if (!correctHeapValue)
-      System.out.println("Heap Trace for FloatObject is not as expected:\n" + heapTrace);
-
+    System.out.println(followReferencesPrimitiveFields(FloatObject.class));
     System.out.println(getTag(FloatObject.class));
     setTag(FloatObject.class, 0);
 
+    boolean correctHeapValue = false;
     setTag(Inf1.class, 10000);
-    heapTrace = followReferencesPrimitiveFields(Inf1.class);
+    String heapTrace = followReferencesPrimitiveFields(Inf1.class);
 
     if (!checkInitialized(Inf1.class)) {
       correctHeapValue = heapTrace.equals("10000@0 (static, int, index=0) 0000000000000000");
diff --git a/test/knownfailures.json b/test/knownfailures.json
index 04de7a1..5a67fbc 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -708,8 +708,8 @@
     },
     {
         "tests": "660-clinit",
-        "variant": "no-image | no-dex2oat | no-prebuild | interp-ac",
-        "description": ["Tests <clinit> for app images, which --no-image, --no-prebuild, interp-ac",
-                        "and --no-dex2oat do not create"]
+        "variant": "no-image | no-dex2oat | no-prebuild",
+        "description": ["Tests <clinit> for app images, which --no-image, --no-prebuild and",
+                        "--no-dex2oat do not create"]
     }
 ]