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