diff options
author | 2017-10-30 11:19:57 -0700 | |
---|---|---|
committer | 2017-11-08 10:53:10 -0800 | |
commit | 025c1a69ea548f1477d160bd477364336109078a (patch) | |
tree | 3ad583c8b8ecc76b800b8da6adb70480b29cb865 | |
parent | 3b5df92d613bb72c8e6f8a766c60835d8313414f (diff) |
Simplify handling of finalizable in LSE.
Finalizable is treated as being returned which simplifies its handling.
Test: run-test on host, 530-checker-lse contains tests on finalizable.
Change-Id: I492470e4d2ba88865029675c51cf10325af47057
-rw-r--r-- | compiler/optimizing/escape.cc | 6 | ||||
-rw-r--r-- | compiler/optimizing/load_store_elimination.cc | 38 | ||||
-rw-r--r-- | test/530-checker-lse/src/Main.java | 12 |
3 files changed, 29 insertions, 27 deletions
diff --git a/compiler/optimizing/escape.cc b/compiler/optimizing/escape.cc index 9df5bf1017..0a92703bd4 100644 --- a/compiler/optimizing/escape.cc +++ b/compiler/optimizing/escape.cc @@ -36,6 +36,12 @@ void CalculateEscape(HInstruction* reference, *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 7dff696e32..a16fdc2a67 100644 --- a/compiler/optimizing/load_store_elimination.cc +++ b/compiler/optimizing/load_store_elimination.cc @@ -183,7 +183,6 @@ class LSEVisitor : public HGraphDelegateVisitor { !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 @@ class LSEVisitor : public HGraphDelegateVisitor { } 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 @@ class LSEVisitor : public HGraphDelegateVisitor { // 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()); - - 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. - } + 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. } } } @@ -575,9 +568,8 @@ class LSEVisitor : public HGraphDelegateVisitor { // 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 7ae873af54..30d4970df1 100644 --- a/test/530-checker-lse/src/Main.java +++ b/test/530-checker-lse/src/Main.java @@ -62,11 +62,12 @@ class TestClass3 { 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 @@ public class Main { /// 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() { |