summaryrefslogtreecommitdiff
path: root/compiler/optimizing/code_sinking.cc
diff options
context:
space:
mode:
author Igor Murashkin <iam@google.com> 2017-04-18 09:37:23 -0700
committer Igor Murashkin <iam@google.com> 2017-05-18 14:14:13 +0000
commit79d8fa7c52c1810d4618c9bd1d43994be5abb53d (patch)
tree411a76dec2adf4139328d5e607b498b72c9aa2af /compiler/optimizing/code_sinking.cc
parentacac09dad3d5aa3922e6cdf54ff2e4fa6f176484 (diff)
optimizing: Build HConstructorFence for HNewArray/HNewInstance nodes
Also fixes: * LSE, code_sinking to keep optimizing new-instance if it did so before * Various tests to expect constructor fences after new-instance Sidenote: new-instance String does not get a ConstructorFence; the special StringFactory calls are assumed to be self-fencing. Metric changes on go/lem: * CodeSize -0.262% in ART-Compile (ARMv8) * RunTime -0.747% for all (linux-armv8) (No changes expected to x86, constructor fences are no-op). The RunTime regression is temporary until art_quick_alloc_* entrypoints have their DMBs removed in a follow up CL. Test: art/test.py Bug: 36656456 Change-Id: I6a936a6e51c623e1c6b5b22eee5c3c72bebbed35
Diffstat (limited to 'compiler/optimizing/code_sinking.cc')
-rw-r--r--compiler/optimizing/code_sinking.cc19
1 files changed, 16 insertions, 3 deletions
diff --git a/compiler/optimizing/code_sinking.cc b/compiler/optimizing/code_sinking.cc
index 0b4dcd30a1..e598e19b67 100644
--- a/compiler/optimizing/code_sinking.cc
+++ b/compiler/optimizing/code_sinking.cc
@@ -56,6 +56,17 @@ static bool IsInterestingInstruction(HInstruction* instruction) {
return true;
}
+ // Check it is safe to move ConstructorFence.
+ // (Safe to move ConstructorFence for only protecting the new-instance but not for finals.)
+ if (instruction->IsConstructorFence()) {
+ HConstructorFence* ctor_fence = instruction->AsConstructorFence();
+
+ // A fence with "0" inputs is dead and should've been removed in a prior pass.
+ DCHECK_NE(0u, ctor_fence->InputCount());
+
+ return ctor_fence->GetAssociatedAllocation() != nullptr;
+ }
+
// All other instructions that can throw cannot be moved.
if (instruction->CanThrow()) {
return false;
@@ -134,11 +145,11 @@ static bool ShouldFilterUse(HInstruction* instruction,
HInstruction* user,
const ArenaBitVector& post_dominated) {
if (instruction->IsNewInstance()) {
- return user->IsInstanceFieldSet() &&
+ return (user->IsInstanceFieldSet() || user->IsConstructorFence()) &&
(user->InputAt(0) == instruction) &&
!post_dominated.IsBitSet(user->GetBlock()->GetBlockId());
} else if (instruction->IsNewArray()) {
- return user->IsArraySet() &&
+ return (user->IsArraySet() || user->IsConstructorFence()) &&
(user->InputAt(0) == instruction) &&
!post_dominated.IsBitSet(user->GetBlock()->GetBlockId());
}
@@ -372,7 +383,9 @@ void CodeSinking::SinkCodeToUncommonBranch(HBasicBlock* end_block) {
// Step (3): Try to move sinking candidates.
for (HInstruction* instruction : move_in_order) {
HInstruction* position = nullptr;
- if (instruction->IsArraySet() || instruction->IsInstanceFieldSet()) {
+ if (instruction->IsArraySet()
+ || instruction->IsInstanceFieldSet()
+ || instruction->IsConstructorFence()) {
if (!instructions_that_can_move.IsBitSet(instruction->InputAt(0)->GetId())) {
// A store can trivially move, but it can safely do so only if the heap
// location it stores to can also move.