Merge "Simplify handling of finalizable in LSE."
diff --git a/compiler/optimizing/escape.cc b/compiler/optimizing/escape.cc
index 9df5bf1..0a92703 100644
--- a/compiler/optimizing/escape.cc
+++ b/compiler/optimizing/escape.cc
@@ -36,6 +36,12 @@
*is_singleton = true;
*is_singleton_and_not_returned = true;
*is_singleton_and_not_deopt_visible = true;
+
+ if (reference->IsNewInstance() && reference->AsNewInstance()->IsFinalizable()) {
+ // Finalizable reference is treated as being returned in the end.
+ *is_singleton_and_not_returned = false;
+ }
+
// Visit all uses to determine if this reference can escape into the heap,
// a method call, an alias, etc.
for (const HUseListNode<HInstruction*>& use : reference->GetUses()) {
diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc
index 7dff696..a16fdc2 100644
--- a/compiler/optimizing/load_store_elimination.cc
+++ b/compiler/optimizing/load_store_elimination.cc
@@ -183,7 +183,6 @@
!location->IsValueKilledByLoopSideEffects()) {
// A removable singleton's field that's not stored into inside a loop is
// invariant throughout the loop. Nothing to do.
- DCHECK(ref_info->IsSingletonAndRemovable());
} else {
// heap value is killed by loop side effects (stored into directly, or
// due to aliasing). Or the heap value may be needed after method return
@@ -386,7 +385,7 @@
} else if (index != nullptr && ref_info->HasIndexAliasing()) {
// For array element, don't eliminate stores if the index can be aliased.
} else if (ref_info->IsSingleton()) {
- // Store into a field of a singleton. The value cannot be killed due to
+ // Store into a field/element of a singleton. The value cannot be killed due to
// aliasing/invocation. It can be redundant since future loads can
// directly get the value set by this instruction. The value can still be killed due to
// merging or loop side effects. Stores whose values are killed due to merging/loop side
@@ -394,24 +393,18 @@
// Stores whose values may be needed after method return or deoptimization
// are also removed from possibly_removed_stores_ when that is detected.
possibly_redundant = true;
- HNewInstance* new_instance = ref_info->GetReference()->AsNewInstance();
- if (new_instance != nullptr && new_instance->IsFinalizable()) {
- // Finalizable objects escape globally. Need to keep the store.
- possibly_redundant = false;
- } else {
- HLoopInformation* loop_info = instruction->GetBlock()->GetLoopInformation();
- if (loop_info != nullptr) {
- // instruction is a store in the loop so the loop must does write.
- DCHECK(side_effects_.GetLoopEffects(loop_info->GetHeader()).DoesAnyWrite());
+ HLoopInformation* loop_info = instruction->GetBlock()->GetLoopInformation();
+ if (loop_info != nullptr) {
+ // instruction is a store in the loop so the loop must does write.
+ DCHECK(side_effects_.GetLoopEffects(loop_info->GetHeader()).DoesAnyWrite());
- if (loop_info->IsDefinedOutOfTheLoop(original_ref)) {
- DCHECK(original_ref->GetBlock()->Dominates(loop_info->GetPreHeader()));
- // Keep the store since its value may be needed at the loop header.
- possibly_redundant = false;
- } else {
- // The singleton is created inside the loop. Value stored to it isn't needed at
- // the loop header. This is true for outer loops also.
- }
+ if (loop_info->IsDefinedOutOfTheLoop(original_ref)) {
+ DCHECK(original_ref->GetBlock()->Dominates(loop_info->GetPreHeader()));
+ // Keep the store since its value may be needed at the loop header.
+ possibly_redundant = false;
+ } else {
+ // The singleton is created inside the loop. Value stored to it isn't needed at
+ // the loop header. This is true for outer loops also.
}
}
}
@@ -575,9 +568,8 @@
// new_instance isn't used for field accesses. No need to process it.
return;
}
- if (ref_info->IsSingletonAndRemovable() &&
- !new_instance->IsFinalizable() &&
- !new_instance->NeedsChecks()) {
+ if (ref_info->IsSingletonAndRemovable() && !new_instance->NeedsChecks()) {
+ DCHECK(!new_instance->IsFinalizable());
singleton_new_instances_.push_back(new_instance);
}
ScopedArenaVector<HInstruction*>& heap_values =
diff --git a/test/530-checker-lse/src/Main.java b/test/530-checker-lse/src/Main.java
index 7ae873a..30d4970 100644
--- a/test/530-checker-lse/src/Main.java
+++ b/test/530-checker-lse/src/Main.java
@@ -62,11 +62,12 @@
class Finalizable {
static boolean sVisited = false;
- static final int VALUE = 0xbeef;
+ static final int VALUE1 = 0xbeef;
+ static final int VALUE2 = 0xcafe;
int i;
protected void finalize() {
- if (i != VALUE) {
+ if (i != VALUE1) {
System.out.println("Where is the beef?");
}
sVisited = true;
@@ -620,15 +621,18 @@
/// CHECK-START: void Main.testFinalizable() load_store_elimination (before)
/// CHECK: NewInstance
/// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
/// CHECK-START: void Main.testFinalizable() load_store_elimination (after)
/// CHECK: NewInstance
/// CHECK: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
- // Allocations and stores into finalizable objects cannot be eliminated.
+ // Allocations of finalizable objects cannot be eliminated.
static void testFinalizable() {
Finalizable finalizable = new Finalizable();
- finalizable.i = Finalizable.VALUE;
+ finalizable.i = Finalizable.VALUE2;
+ finalizable.i = Finalizable.VALUE1;
}
static java.lang.ref.WeakReference<Object> getWeakReference() {