diff options
author | 2022-06-24 11:16:35 +0100 | |
---|---|---|
committer | 2022-09-06 12:35:47 +0000 | |
commit | f976aa822dd35496e4e936b5802af0d53d39ac95 (patch) | |
tree | 41fd63809b52f7ffcbc6b7c81e8fb2d1c03af307 /compiler/optimizing/code_sinking.cc | |
parent | 65fd6a37398356112316946358e2c58e1a5df631 (diff) |
Add an environment to the beginning of catch blocks
We can use the HNop to generate an environment for us and start
using the existing environment infrastructure (e.g. EmitEnvironment)
for recording the catch block's environment.
This is done to provide support for try catch inlining since it
requires several environments rather than just the one.
When doing so, we now have a HNop at the beginning of each catch
block. We have to modify code sinking to allow it to sink code
past this HNop because if we don't we will sink code right before
this instruction which will break the invariant of that HNop being
the first instruction of a catch block.
Test: art/test/testrunner/testrunner.py --host --64 --optimizing -b
Change-Id: I16e7b8cad499fd2d6f7415112b46206db8daf544
Diffstat (limited to 'compiler/optimizing/code_sinking.cc')
-rw-r--r-- | compiler/optimizing/code_sinking.cc | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/compiler/optimizing/code_sinking.cc b/compiler/optimizing/code_sinking.cc index 766bb01978..930675b401 100644 --- a/compiler/optimizing/code_sinking.cc +++ b/compiler/optimizing/code_sinking.cc @@ -271,10 +271,21 @@ static HInstruction* FindIdealPosition(HInstruction* instruction, } } for (const HUseListNode<HEnvironment*>& use : instruction->GetEnvUses()) { - HInstruction* user = use.GetUser()->GetHolder(); + HEnvironment* env = use.GetUser(); + HInstruction* user = env->GetHolder(); if (user->GetBlock() == target_block && (insert_pos == nullptr || user->StrictlyDominates(insert_pos))) { - insert_pos = user; + if (target_block->IsCatchBlock() && target_block->GetFirstInstruction() == user) { + // We can sink the instructions past the environment setting Nop. If we do that, we have to + // remove said instruction from the environment. Since we know that we will be sinking the + // instruction to this block and there are no more instructions to consider, we can safely + // remove it from the environment now. + DCHECK(target_block->GetFirstInstruction()->IsNop()); + env->RemoveAsUserOfInput(use.GetIndex()); + env->SetRawEnvAt(use.GetIndex(), /*instruction=*/ nullptr); + } else { + insert_pos = user; + } } } if (insert_pos == nullptr) { |