126a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray/*
226a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray * Copyright (C) 2014 The Android Open Source Project
326a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray *
426a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License");
526a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray * you may not use this file except in compliance with the License.
626a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray * You may obtain a copy of the License at
726a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray *
826a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray *      http://www.apache.org/licenses/LICENSE-2.0
926a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray *
1026a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray * Unless required by applicable law or agreed to in writing, software
1126a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS,
1226a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1326a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray * See the License for the specific language governing permissions and
1426a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray * limitations under the License.
1526a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray */
1626a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray
1726a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray#include "prepare_for_register_allocation.h"
1826a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray
195d37c152f21a0807459c6f53bc25e2d84f56d259Nicolas Geoffray#include "jni_internal.h"
205d37c152f21a0807459c6f53bc25e2d84f56d259Nicolas Geoffray#include "well_known_classes.h"
215d37c152f21a0807459c6f53bc25e2d84f56d259Nicolas Geoffray
2226a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffraynamespace art {
2326a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray
2426a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffrayvoid PrepareForRegisterAllocation::Run() {
2526a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray  // Order does not matter.
262c45bc9137c29f886e69923535aff31a74d90829Vladimir Marko  for (HBasicBlock* block : GetGraph()->GetReversePostOrder()) {
2726a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray    // No need to visit the phis.
28277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe    for (HInstructionIterator inst_it(block->GetInstructions()); !inst_it.Done();
29277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe         inst_it.Advance()) {
30277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe      inst_it.Current()->Accept(this);
3126a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray    }
3226a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray  }
3326a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray}
3426a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray
3526a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffrayvoid PrepareForRegisterAllocation::VisitNullCheck(HNullCheck* check) {
3626a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray  check->ReplaceWith(check->InputAt(0));
3726a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray}
3826a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray
39d0d4852847432368b090c184d6639e573538dccfCalin Juravlevoid PrepareForRegisterAllocation::VisitDivZeroCheck(HDivZeroCheck* check) {
40d0d4852847432368b090c184d6639e573538dccfCalin Juravle  check->ReplaceWith(check->InputAt(0));
41d0d4852847432368b090c184d6639e573538dccfCalin Juravle}
42d0d4852847432368b090c184d6639e573538dccfCalin Juravle
43dd0fc0481cdc4e04abb7b7300e76edbd2f07f011Nicolas Geoffrayvoid PrepareForRegisterAllocation::VisitDeoptimize(HDeoptimize* deoptimize) {
44dd0fc0481cdc4e04abb7b7300e76edbd2f07f011Nicolas Geoffray  if (deoptimize->GuardsAnInput()) {
45dd0fc0481cdc4e04abb7b7300e76edbd2f07f011Nicolas Geoffray    // Replace the uses with the actual guarded instruction.
46dd0fc0481cdc4e04abb7b7300e76edbd2f07f011Nicolas Geoffray    deoptimize->ReplaceWith(deoptimize->GuardedInput());
47dd0fc0481cdc4e04abb7b7300e76edbd2f07f011Nicolas Geoffray    deoptimize->RemoveGuard();
48dd0fc0481cdc4e04abb7b7300e76edbd2f07f011Nicolas Geoffray  }
49dd0fc0481cdc4e04abb7b7300e76edbd2f07f011Nicolas Geoffray}
50dd0fc0481cdc4e04abb7b7300e76edbd2f07f011Nicolas Geoffray
5126a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffrayvoid PrepareForRegisterAllocation::VisitBoundsCheck(HBoundsCheck* check) {
5226a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray  check->ReplaceWith(check->InputAt(0));
5387f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko  if (check->IsStringCharAt()) {
5487f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko    // Add a fake environment for String.charAt() inline info as we want
5587f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko    // the exception to appear as being thrown from there.
565d37c152f21a0807459c6f53bc25e2d84f56d259Nicolas Geoffray    ArtMethod* char_at_method = jni::DecodeArtMethod(WellKnownClasses::java_lang_String_charAt);
5787f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko    ArenaAllocator* arena = GetGraph()->GetArena();
5887f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko    HEnvironment* environment = new (arena) HEnvironment(arena,
5987f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko                                                         /* number_of_vregs */ 0u,
605d37c152f21a0807459c6f53bc25e2d84f56d259Nicolas Geoffray                                                         char_at_method,
6187f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko                                                         /* dex_pc */ DexFile::kDexNoIndex,
6287f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko                                                         check);
6387f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko    check->InsertRawEnvironment(environment);
6487f3fcbd0db352157fc59148e94647ef21b73bceVladimir Marko  }
6526a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray}
6626a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray
67b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlevoid PrepareForRegisterAllocation::VisitBoundType(HBoundType* bound_type) {
68b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  bound_type->ReplaceWith(bound_type->InputAt(0));
69b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  bound_type->GetBlock()->RemoveInstruction(bound_type);
70b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle}
71b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
72b133ec6c39b4c953ed815ec731b0270f0d8f0ed9Roland Levillainvoid PrepareForRegisterAllocation::VisitArraySet(HArraySet* instruction) {
73b133ec6c39b4c953ed815ec731b0270f0d8f0ed9Roland Levillain  HInstruction* value = instruction->GetValue();
74b133ec6c39b4c953ed815ec731b0270f0d8f0ed9Roland Levillain  // PrepareForRegisterAllocation::VisitBoundType may have replaced a
75b133ec6c39b4c953ed815ec731b0270f0d8f0ed9Roland Levillain  // BoundType (as value input of this ArraySet) with a NullConstant.
76b133ec6c39b4c953ed815ec731b0270f0d8f0ed9Roland Levillain  // If so, this ArraySet no longer needs a type check.
77b133ec6c39b4c953ed815ec731b0270f0d8f0ed9Roland Levillain  if (value->IsNullConstant()) {
78b133ec6c39b4c953ed815ec731b0270f0d8f0ed9Roland Levillain    DCHECK_EQ(value->GetType(), Primitive::kPrimNot);
79b133ec6c39b4c953ed815ec731b0270f0d8f0ed9Roland Levillain    if (instruction->NeedsTypeCheck()) {
80b133ec6c39b4c953ed815ec731b0270f0d8f0ed9Roland Levillain      instruction->ClearNeedsTypeCheck();
81b133ec6c39b4c953ed815ec731b0270f0d8f0ed9Roland Levillain    }
82b133ec6c39b4c953ed815ec731b0270f0d8f0ed9Roland Levillain  }
83b133ec6c39b4c953ed815ec731b0270f0d8f0ed9Roland Levillain}
84b133ec6c39b4c953ed815ec731b0270f0d8f0ed9Roland Levillain
8519a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffrayvoid PrepareForRegisterAllocation::VisitClinitCheck(HClinitCheck* check) {
86729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray  // Try to find a static invoke or a new-instance from which this check originated.
87729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray  HInstruction* implicit_clinit = nullptr;
8846817b876ab00d6b78905b80ed12b4344c522b6cVladimir Marko  for (const HUseListNode<HInstruction*>& use : check->GetUses()) {
8946817b876ab00d6b78905b80ed12b4344c522b6cVladimir Marko    HInstruction* user = use.GetUser();
90729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray    if ((user->IsInvokeStaticOrDirect() || user->IsNewInstance()) &&
91729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray        CanMoveClinitCheck(check, user)) {
92729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray      implicit_clinit = user;
93729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray      if (user->IsInvokeStaticOrDirect()) {
94729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray        DCHECK(user->AsInvokeStaticOrDirect()->IsStaticWithExplicitClinitCheck());
95729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray        user->AsInvokeStaticOrDirect()->RemoveExplicitClinitCheck(
96729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray            HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit);
97729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray      } else {
98729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray        DCHECK(user->IsNewInstance());
99729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray        // We delegate the initialization duty to the allocation.
100729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray        if (user->AsNewInstance()->GetEntrypoint() == kQuickAllocObjectInitialized) {
101729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray          user->AsNewInstance()->SetEntrypoint(kQuickAllocObjectResolved);
102729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray        }
103729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray      }
104fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko      break;
105fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    }
106fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  }
107729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray  // If we found a static invoke or new-instance for merging, remove the check
108729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray  // from dominated static invokes.
109729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray  if (implicit_clinit != nullptr) {
11046817b876ab00d6b78905b80ed12b4344c522b6cVladimir Marko    const HUseList<HInstruction*>& uses = check->GetUses();
11146817b876ab00d6b78905b80ed12b4344c522b6cVladimir Marko    for (auto it = uses.begin(), end = uses.end(); it != end; /* ++it below */) {
11246817b876ab00d6b78905b80ed12b4344c522b6cVladimir Marko      HInstruction* user = it->GetUser();
113729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray      // All other uses must be dominated.
114729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray      DCHECK(implicit_clinit->StrictlyDominates(user) || (implicit_clinit == user));
11546817b876ab00d6b78905b80ed12b4344c522b6cVladimir Marko      ++it;  // Advance before we remove the node, reference to the next node is preserved.
116fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko      if (user->IsInvokeStaticOrDirect()) {
117fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko        user->AsInvokeStaticOrDirect()->RemoveExplicitClinitCheck(
118fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
119fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko      }
120fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    }
121fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  }
122fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko
123fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  HLoadClass* load_class = check->GetLoadClass();
124fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  bool can_merge_with_load_class = CanMoveClinitCheck(load_class, check);
125fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko
126fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  check->ReplaceWith(load_class);
127fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko
128729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray  if (implicit_clinit != nullptr) {
129729645a937eb9f04a311b3c22471dcf3ebe9bcecNicolas Geoffray    // Remove the check from the graph. It has been merged into the invoke or new-instance.
130fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    check->GetBlock()->RemoveInstruction(check);
131fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    // Check if we can merge the load class as well.
132fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    if (can_merge_with_load_class && !load_class->HasUses()) {
133fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko      load_class->GetBlock()->RemoveInstruction(load_class);
134fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    }
1350580d96231c3143f50d14bbc834662715faf6cdfNicolas Geoffray  } else if (can_merge_with_load_class && !load_class->NeedsAccessCheck()) {
136424f676379f2f872acd1478672022f19f3240fc1Nicolas Geoffray    // Pass the initialization duty to the `HLoadClass` instruction,
137424f676379f2f872acd1478672022f19f3240fc1Nicolas Geoffray    // and remove the instruction from the graph.
1381ceb37c75544c5285fb87f27e1d9fa7261ced60cMathieu Chartier    DCHECK(load_class->HasEnvironment());
139fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    load_class->SetMustGenerateClinitCheck(true);
140424f676379f2f872acd1478672022f19f3240fc1Nicolas Geoffray    check->GetBlock()->RemoveInstruction(check);
141424f676379f2f872acd1478672022f19f3240fc1Nicolas Geoffray  }
14219a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray}
14319a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray
144b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdilbool PrepareForRegisterAllocation::CanEmitConditionAt(HCondition* condition,
145b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil                                                      HInstruction* user) const {
146b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil  if (condition->GetNext() != user) {
147b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil    return false;
148b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil  }
149b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil
150b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil  if (user->IsIf() || user->IsDeoptimize()) {
151b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil    return true;
152b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil  }
153b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil
15474eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil  if (user->IsSelect() && user->AsSelect()->GetCondition() == condition) {
1550c5b18edd1308975804ccf29a02a130a7b6f7fa7Mark Mendell    return true;
15674eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil  }
15774eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil
158b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil  return false;
159b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil}
160b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil
161360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffrayvoid PrepareForRegisterAllocation::VisitCondition(HCondition* condition) {
162b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil  if (condition->HasOnlyOneNonEnvironmentUse()) {
16346817b876ab00d6b78905b80ed12b4344c522b6cVladimir Marko    HInstruction* user = condition->GetUses().front().GetUser();
164b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil    if (CanEmitConditionAt(condition, user)) {
165b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil      condition->MarkEmittedAtUseSite();
166360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray    }
167360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  }
168360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray}
169360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
1704c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillainvoid PrepareForRegisterAllocation::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) {
1714c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain  if (invoke->IsStaticWithExplicitClinitCheck()) {
172372f10e5b0b34e2bb6e2b79aeba6c441e14afd1fVladimir Marko    HLoadClass* last_input = invoke->GetInputs().back()->AsLoadClass();
1730ba218df92d2130295eccd2c564f8fdd2efc3a71Calin Juravle    DCHECK(last_input != nullptr)
1740ba218df92d2130295eccd2c564f8fdd2efc3a71Calin Juravle        << "Last input is not HLoadClass. It is " << last_input->DebugName();
1750ba218df92d2130295eccd2c564f8fdd2efc3a71Calin Juravle
176fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    // Detach the explicit class initialization check from the invoke.
177fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    // Keeping track of the initializing instruction is no longer required
178fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    // at this stage (i.e., after inlining has been performed).
179fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    invoke->RemoveExplicitClinitCheck(HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
180fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko
181fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    // Merging with load class should have happened in VisitClinitCheck().
182fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    DCHECK(!CanMoveClinitCheck(last_input, invoke));
183fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  }
184fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko}
185fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko
186b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdilbool PrepareForRegisterAllocation::CanMoveClinitCheck(HInstruction* input,
187b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil                                                      HInstruction* user) const {
188fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  // Determine if input and user come from the same dex instruction, so that we can move
189fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  // the clinit check responsibility from one to the other, i.e. from HClinitCheck (user)
190c7591b4c0dd405a766f4d701deea6c3750101978Vladimir Marko  // to HLoadClass (input), or from HClinitCheck (input) to HInvokeStaticOrDirect (user),
191c7591b4c0dd405a766f4d701deea6c3750101978Vladimir Marko  // or from HLoadClass (input) to HNewInstance (user).
192fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko
193fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  // Start with a quick dex pc check.
194fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  if (user->GetDexPc() != input->GetDexPc()) {
195fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    return false;
196fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  }
197fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko
198fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  // Now do a thorough environment check that this is really coming from the same instruction in
199fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  // the same inlined graph. Unfortunately, we have to go through the whole environment chain.
200fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  HEnvironment* user_environment = user->GetEnvironment();
201fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  HEnvironment* input_environment = input->GetEnvironment();
202fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  while (user_environment != nullptr || input_environment != nullptr) {
203fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    if (user_environment == nullptr || input_environment == nullptr) {
204fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko      // Different environment chain length. This happens when a method is called
205fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko      // once directly and once indirectly through another inlined method.
206fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko      return false;
207fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    }
208fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    if (user_environment->GetDexPc() != input_environment->GetDexPc() ||
2095d37c152f21a0807459c6f53bc25e2d84f56d259Nicolas Geoffray        user_environment->GetMethod() != input_environment->GetMethod()) {
210fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko      return false;
211fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    }
212fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    user_environment = user_environment->GetParent();
213fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    input_environment = input_environment->GetParent();
214fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  }
215fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko
216fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  // Check for code motion taking the input to a different block.
217fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  if (user->GetBlock() != input->GetBlock()) {
218fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    return false;
219fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  }
220fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko
221fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  // In debug mode, check that we have not inserted a throwing instruction
222fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  // or an instruction with side effects between input and user.
223fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  if (kIsDebugBuild) {
224fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko    for (HInstruction* between = input->GetNext(); between != user; between = between->GetNext()) {
225fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko      CHECK(between != nullptr);  // User must be after input in the same block.
226fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko      CHECK(!between->CanThrow());
227fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko      CHECK(!between->HasSideEffects());
2284c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain    }
2294c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain  }
230fbb184a1c6df22d9302b32b55206396c8278edcfVladimir Marko  return true;
2314c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain}
2324c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain
23326a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray}  // namespace art
234