Revert "Enable store elimination for singleton objects."

This reverts commit 7f43a3d48fc29045875d50e10bbc5d6ffc25d61e.

Fails booting.

Bug: 25357772
Change-Id: Ied19536f3ce8d81e76885cb6baed4853e2ed6714
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index 5da7214..2b60a51 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -1104,11 +1104,7 @@
   // access because the verifier was unable to?
   const DexFile* dex_file = cu_->dex_file;
   CompilerDriver* driver = cu_->compiler_driver;
-  bool finalizable;
-  if (driver->CanAccessInstantiableTypeWithoutChecks(cu_->method_idx,
-                                                     *dex_file,
-                                                     type_idx,
-                                                     &finalizable)) {
+  if (driver->CanAccessInstantiableTypeWithoutChecks(cu_->method_idx, *dex_file, type_idx)) {
     bool is_type_initialized;
     bool use_direct_type_ptr;
     uintptr_t direct_type_ptr;
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index fa3598e..8750aa8 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -1247,8 +1247,7 @@
 
 bool CompilerDriver::CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_idx,
                                                             const DexFile& dex_file,
-                                                            uint32_t type_idx,
-                                                            bool* finalizable) {
+                                                            uint32_t type_idx) {
   ScopedObjectAccess soa(Thread::Current());
   mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(
       soa.Self(), dex_file, false);
@@ -1256,11 +1255,8 @@
   mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx);
   if (resolved_class == nullptr) {
     stats_->TypeNeedsAccessCheck();
-    // Be conservative.
-    *finalizable = true;
     return false;  // Unknown class needs access checks.
   }
-  *finalizable = resolved_class->IsFinalizable();
   const DexFile::MethodId& method_id = dex_file.GetMethodId(referrer_idx);
   mirror::Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_);
   if (referrer_class == nullptr) {
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 15806b5..485cdcf 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -200,10 +200,8 @@
       REQUIRES(!Locks::mutator_lock_);
 
   // Are runtime access and instantiable checks necessary in the code?
-  bool CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_idx,
-                                              const DexFile& dex_file,
-                                              uint32_t type_idx,
-                                              bool* finalizable)
+  bool CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_idx, const DexFile& dex_file,
+                                              uint32_t type_idx)
       REQUIRES(!Locks::mutator_lock_);
 
   bool CanEmbedTypeInCode(const DexFile& dex_file, uint32_t type_idx,
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index ee5b929..ed193c7 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -1455,8 +1455,7 @@
                                         uint32_t* args,
                                         uint32_t register_index) {
   HInstruction* length = graph_->GetIntConstant(number_of_vreg_arguments, dex_pc);
-  bool finalizable;
-  QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index, &finalizable)
+  QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
       ? kQuickAllocArrayWithAccessCheck
       : kQuickAllocArray;
   HInstruction* object = new (arena_) HNewArray(length,
@@ -1636,9 +1635,9 @@
   }
 }
 
-bool HGraphBuilder::NeedsAccessCheck(uint32_t type_index, bool* finalizable) const {
+bool HGraphBuilder::NeedsAccessCheck(uint32_t type_index) const {
   return !compiler_driver_->CanAccessInstantiableTypeWithoutChecks(
-      dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index, finalizable);
+      dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index);
 }
 
 void HGraphBuilder::BuildSwitchJumpTable(const SwitchTable& table,
@@ -2515,9 +2514,7 @@
         current_block_->AddInstruction(fake_string);
         UpdateLocal(register_index, fake_string, dex_pc);
       } else {
-        bool finalizable;
-        bool can_throw = NeedsAccessCheck(type_index, &finalizable);
-        QuickEntrypointEnum entrypoint = can_throw
+        QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
             ? kQuickAllocObjectWithAccessCheck
             : kQuickAllocObject;
 
@@ -2526,8 +2523,6 @@
             dex_pc,
             type_index,
             *dex_compilation_unit_->GetDexFile(),
-            can_throw,
-            finalizable,
             entrypoint));
         UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
       }
@@ -2537,8 +2532,7 @@
     case Instruction::NEW_ARRAY: {
       uint16_t type_index = instruction.VRegC_22c();
       HInstruction* length = LoadLocal(instruction.VRegB_22c(), Primitive::kPrimInt, dex_pc);
-      bool finalizable;
-      QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index, &finalizable)
+      QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
           ? kQuickAllocArrayWithAccessCheck
           : kQuickAllocArray;
       current_block_->AddInstruction(new (arena_) HNewArray(length,
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h
index 0f64489..9eaa4b6 100644
--- a/compiler/optimizing/builder.h
+++ b/compiler/optimizing/builder.h
@@ -138,7 +138,7 @@
   HInstruction* LoadLocal(uint32_t register_index, Primitive::Type type, uint32_t dex_pc) const;
   void PotentiallyAddSuspendCheck(HBasicBlock* target, uint32_t dex_pc);
   void InitializeParameters(uint16_t number_of_parameters);
-  bool NeedsAccessCheck(uint32_t type_index, bool* finalizable) const;
+  bool NeedsAccessCheck(uint32_t type_index) const;
 
   template<typename T>
   void Unop_12x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc
index aa9c315..90f28e5 100644
--- a/compiler/optimizing/load_store_elimination.cc
+++ b/compiler/optimizing/load_store_elimination.cc
@@ -695,12 +695,8 @@
       } else {
         redundant_store = true;
       }
-      HNewInstance* new_instance = ref_info->GetReference()->AsNewInstance();
-      DCHECK(new_instance != nullptr);
-      if (new_instance->IsFinalizable()) {
-        // Finalizable objects escape globally. Need to keep the store.
-        redundant_store = false;
-      }
+      // TODO: eliminate the store if the singleton object is not finalizable.
+      redundant_store = false;
     }
     if (redundant_store) {
       removed_instructions_.push_back(instruction);
@@ -838,9 +834,7 @@
       return;
     }
     if (!heap_location_collector_.MayDeoptimize() &&
-        ref_info->IsSingletonAndNotReturned() &&
-        !new_instance->IsFinalizable() &&
-        !new_instance->CanThrow()) {
+        ref_info->IsSingletonAndNotReturned()) {
       // The allocation might be eliminated.
       singleton_new_instances_.push_back(new_instance);
     }
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 7ac39d1..6028d4b 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -3595,14 +3595,10 @@
                uint32_t dex_pc,
                uint16_t type_index,
                const DexFile& dex_file,
-               bool can_throw,
-               bool finalizable,
                QuickEntrypointEnum entrypoint)
       : HExpression(Primitive::kPrimNot, SideEffects::CanTriggerGC(), dex_pc),
         type_index_(type_index),
         dex_file_(dex_file),
-        can_throw_(can_throw),
-        finalizable_(finalizable),
         entrypoint_(entrypoint) {
     SetRawInputAt(0, current_method);
   }
@@ -3612,11 +3608,11 @@
 
   // Calls runtime so needs an environment.
   bool NeedsEnvironment() const OVERRIDE { return true; }
-
-  // It may throw when called on type that's not instantiable/accessible.
-  bool CanThrow() const OVERRIDE { return can_throw_; }
-
-  bool IsFinalizable() const { return finalizable_; }
+  // It may throw when called on:
+  //   - interfaces
+  //   - abstract/innaccessible/unknown classes
+  // TODO: optimize when possible.
+  bool CanThrow() const OVERRIDE { return true; }
 
   bool CanBeNull() const OVERRIDE { return false; }
 
@@ -3627,8 +3623,6 @@
  private:
   const uint16_t type_index_;
   const DexFile& dex_file_;
-  const bool can_throw_;
-  const bool finalizable_;
   const QuickEntrypointEnum entrypoint_;
 
   DISALLOW_COPY_AND_ASSIGN(HNewInstance);
diff --git a/test/530-checker-lse/src/Main.java b/test/530-checker-lse/src/Main.java
index 924ff67..c766aaa 100644
--- a/test/530-checker-lse/src/Main.java
+++ b/test/530-checker-lse/src/Main.java
@@ -22,7 +22,7 @@
     return radius * radius * Math.PI;
   }
   private double radius;
-}
+};
 
 class TestClass {
   TestClass() {
@@ -36,29 +36,16 @@
   volatile int k;
   TestClass next;
   static int si;
-}
+};
 
 class SubTestClass extends TestClass {
   int k;
-}
+};
 
 class TestClass2 {
   int i;
   int j;
-}
-
-class Finalizable {
-  static boolean sVisited = false;
-  static final int VALUE = 0xbeef;
-  int i;
-
-  protected void finalize() {
-    if (i != VALUE) {
-      System.out.println("Where is the beef?");
-    }
-    sVisited = true;
-  }
-}
+};
 
 public class Main {
 
@@ -69,7 +56,7 @@
 
   /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (after)
   /// CHECK: NewInstance
-  /// CHECK-NOT: InstanceFieldSet
+  /// CHECK: InstanceFieldSet
   /// CHECK-NOT: InstanceFieldGet
 
   static double calcCircleArea(double radius) {
@@ -130,7 +117,7 @@
   /// CHECK: InstanceFieldGet
   /// CHECK: InstanceFieldSet
   /// CHECK: NewInstance
-  /// CHECK-NOT: InstanceFieldSet
+  /// CHECK: InstanceFieldSet
   /// CHECK-NOT: InstanceFieldGet
 
   // A new allocation shouldn't alias with pre-existing values.
@@ -236,7 +223,7 @@
 
   /// CHECK-START: int Main.test8() load_store_elimination (after)
   /// CHECK: NewInstance
-  /// CHECK-NOT: InstanceFieldSet
+  /// CHECK: InstanceFieldSet
   /// CHECK: InvokeVirtual
   /// CHECK-NOT: NullCheck
   /// CHECK-NOT: InstanceFieldGet
@@ -394,8 +381,8 @@
 
   /// CHECK-START: int Main.test16() load_store_elimination (after)
   /// CHECK: NewInstance
-  /// CHECK-NOT: InstanceFieldSet
-  /// CHECK-NOT: InstanceFieldGet
+  /// CHECK-NOT: StaticFieldSet
+  /// CHECK-NOT: StaticFieldGet
 
   // Test inlined constructor.
   static int test16() {
@@ -411,8 +398,8 @@
   /// CHECK-START: int Main.test17() load_store_elimination (after)
   /// CHECK: <<Const0:i\d+>> IntConstant 0
   /// CHECK: NewInstance
-  /// CHECK-NOT: InstanceFieldSet
-  /// CHECK-NOT: InstanceFieldGet
+  /// CHECK-NOT: StaticFieldSet
+  /// CHECK-NOT: StaticFieldGet
   /// CHECK: Return [<<Const0>>]
 
   // Test getting default value.
@@ -468,55 +455,6 @@
     return obj;
   }
 
-  /// CHECK-START: void Main.testFinalizable() load_store_elimination (before)
-  /// CHECK: NewInstance
-  /// CHECK: InstanceFieldSet
-
-  /// CHECK-START: void Main.testFinalizable() load_store_elimination (after)
-  /// CHECK: NewInstance
-  /// CHECK: InstanceFieldSet
-
-  // Allocations and stores into finalizable objects cannot be eliminated.
-  static void testFinalizable() {
-    Finalizable finalizable = new Finalizable();
-    finalizable.i = Finalizable.VALUE;
-  }
-
-  static java.lang.ref.WeakReference<Object> getWeakReference() {
-    return new java.lang.ref.WeakReference<>(new Object());
-  }
-
-  static void testFinalizableByForcingGc() {
-    testFinalizable();
-    java.lang.ref.WeakReference<Object> reference = getWeakReference();
-
-    Runtime runtime = Runtime.getRuntime();
-    for (int i = 0; i < 20; ++i) {
-      runtime.gc();
-      System.runFinalization();
-      try {
-        Thread.sleep(1);
-      } catch (InterruptedException e) {
-        throw new AssertionError(e);
-      }
-
-      // Check to see if the weak reference has been garbage collected.
-      if (reference.get() == null) {
-        // A little bit more sleep time to make sure.
-        try {
-          Thread.sleep(100);
-        } catch (InterruptedException e) {
-          throw new AssertionError(e);
-        }
-        if (!Finalizable.sVisited) {
-          System.out.println("finalize() not called.");
-        }
-        return;
-      }
-    }
-    System.out.println("testFinalizableByForcingGc() failed to force gc.");
-  }
-
   public static void assertIntEquals(int expected, int result) {
     if (expected != result) {
       throw new Error("Expected: " + expected + ", found: " + result);
@@ -570,6 +508,5 @@
     float[] fa2 = { 1.8f };
     assertFloatEquals(test19(fa1, fa2), 1.8f);
     assertFloatEquals(test20().i, 0);
-    testFinalizableByForcingGc();
   }
 }