Home | History | Annotate | Download | only in optimizing
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "reference_type_propagation.h"
     18 
     19 #include "art_field-inl.h"
     20 #include "art_method-inl.h"
     21 #include "base/scoped_arena_allocator.h"
     22 #include "base/scoped_arena_containers.h"
     23 #include "base/enums.h"
     24 #include "class_linker-inl.h"
     25 #include "handle_scope-inl.h"
     26 #include "mirror/class-inl.h"
     27 #include "mirror/dex_cache.h"
     28 #include "scoped_thread_state_change-inl.h"
     29 
     30 namespace art {
     31 
     32 static inline ObjPtr<mirror::DexCache> FindDexCacheWithHint(
     33     Thread* self, const DexFile& dex_file, Handle<mirror::DexCache> hint_dex_cache)
     34     REQUIRES_SHARED(Locks::mutator_lock_) {
     35   if (LIKELY(hint_dex_cache->GetDexFile() == &dex_file)) {
     36     return hint_dex_cache.Get();
     37   } else {
     38     return Runtime::Current()->GetClassLinker()->FindDexCache(self, dex_file);
     39   }
     40 }
     41 
     42 static inline ReferenceTypeInfo::TypeHandle GetRootHandle(VariableSizedHandleScope* handles,
     43                                                           ClassLinker::ClassRoot class_root,
     44                                                           ReferenceTypeInfo::TypeHandle* cache) {
     45   if (!ReferenceTypeInfo::IsValidHandle(*cache)) {
     46     // Mutator lock is required for NewHandle.
     47     ClassLinker* linker = Runtime::Current()->GetClassLinker();
     48     ScopedObjectAccess soa(Thread::Current());
     49     *cache = handles->NewHandle(linker->GetClassRoot(class_root));
     50   }
     51   return *cache;
     52 }
     53 
     54 ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetObjectClassHandle() {
     55   return GetRootHandle(handles_, ClassLinker::kJavaLangObject, &object_class_handle_);
     56 }
     57 
     58 ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetClassClassHandle() {
     59   return GetRootHandle(handles_, ClassLinker::kJavaLangClass, &class_class_handle_);
     60 }
     61 
     62 ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetStringClassHandle() {
     63   return GetRootHandle(handles_, ClassLinker::kJavaLangString, &string_class_handle_);
     64 }
     65 
     66 ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetThrowableClassHandle() {
     67   return GetRootHandle(handles_, ClassLinker::kJavaLangThrowable, &throwable_class_handle_);
     68 }
     69 
     70 class ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor {
     71  public:
     72   RTPVisitor(HGraph* graph,
     73              Handle<mirror::ClassLoader> class_loader,
     74              Handle<mirror::DexCache> hint_dex_cache,
     75              HandleCache* handle_cache,
     76              bool is_first_run)
     77     : HGraphDelegateVisitor(graph),
     78       class_loader_(class_loader),
     79       hint_dex_cache_(hint_dex_cache),
     80       handle_cache_(handle_cache),
     81       allocator_(graph->GetArenaStack()),
     82       worklist_(allocator_.Adapter(kArenaAllocReferenceTypePropagation)),
     83       is_first_run_(is_first_run) {
     84     worklist_.reserve(kDefaultWorklistSize);
     85   }
     86 
     87   void VisitDeoptimize(HDeoptimize* deopt) OVERRIDE;
     88   void VisitNewInstance(HNewInstance* new_instance) OVERRIDE;
     89   void VisitLoadClass(HLoadClass* load_class) OVERRIDE;
     90   void VisitClinitCheck(HClinitCheck* clinit_check) OVERRIDE;
     91   void VisitLoadString(HLoadString* instr) OVERRIDE;
     92   void VisitLoadException(HLoadException* instr) OVERRIDE;
     93   void VisitNewArray(HNewArray* instr) OVERRIDE;
     94   void VisitParameterValue(HParameterValue* instr) OVERRIDE;
     95   void VisitInstanceFieldGet(HInstanceFieldGet* instr) OVERRIDE;
     96   void VisitStaticFieldGet(HStaticFieldGet* instr) OVERRIDE;
     97   void VisitUnresolvedInstanceFieldGet(HUnresolvedInstanceFieldGet* instr) OVERRIDE;
     98   void VisitUnresolvedStaticFieldGet(HUnresolvedStaticFieldGet* instr) OVERRIDE;
     99   void VisitInvoke(HInvoke* instr) OVERRIDE;
    100   void VisitArrayGet(HArrayGet* instr) OVERRIDE;
    101   void VisitCheckCast(HCheckCast* instr) OVERRIDE;
    102   void VisitBoundType(HBoundType* instr) OVERRIDE;
    103   void VisitNullCheck(HNullCheck* instr) OVERRIDE;
    104   void VisitPhi(HPhi* phi);
    105 
    106   void VisitBasicBlock(HBasicBlock* block);
    107   void ProcessWorklist();
    108 
    109  private:
    110   void UpdateFieldAccessTypeInfo(HInstruction* instr, const FieldInfo& info);
    111   void SetClassAsTypeInfo(HInstruction* instr, ObjPtr<mirror::Class> klass, bool is_exact)
    112       REQUIRES_SHARED(Locks::mutator_lock_);
    113   void BoundTypeForIfNotNull(HBasicBlock* block);
    114   static void BoundTypeForIfInstanceOf(HBasicBlock* block);
    115   static bool UpdateNullability(HInstruction* instr);
    116   static void UpdateBoundType(HBoundType* bound_type) REQUIRES_SHARED(Locks::mutator_lock_);
    117   void UpdateArrayGet(HArrayGet* instr) REQUIRES_SHARED(Locks::mutator_lock_);
    118   void UpdatePhi(HPhi* phi) REQUIRES_SHARED(Locks::mutator_lock_);
    119   bool UpdateReferenceTypeInfo(HInstruction* instr);
    120   void UpdateReferenceTypeInfo(HInstruction* instr,
    121                                dex::TypeIndex type_idx,
    122                                const DexFile& dex_file,
    123                                bool is_exact);
    124 
    125   void AddToWorklist(HInstruction* instruction);
    126   void AddDependentInstructionsToWorklist(HInstruction* instruction);
    127 
    128   static constexpr size_t kDefaultWorklistSize = 8;
    129 
    130   Handle<mirror::ClassLoader> class_loader_;
    131   Handle<mirror::DexCache> hint_dex_cache_;
    132   HandleCache* const handle_cache_;
    133 
    134   // Use local allocator for allocating memory.
    135   ScopedArenaAllocator allocator_;
    136   ScopedArenaVector<HInstruction*> worklist_;
    137   const bool is_first_run_;
    138 };
    139 
    140 ReferenceTypePropagation::ReferenceTypePropagation(HGraph* graph,
    141                                                    Handle<mirror::ClassLoader> class_loader,
    142                                                    Handle<mirror::DexCache> hint_dex_cache,
    143                                                    VariableSizedHandleScope* handles,
    144                                                    bool is_first_run,
    145                                                    const char* name)
    146     : HOptimization(graph, name),
    147       class_loader_(class_loader),
    148       hint_dex_cache_(hint_dex_cache),
    149       handle_cache_(handles),
    150       is_first_run_(is_first_run) {
    151 }
    152 
    153 void ReferenceTypePropagation::ValidateTypes() {
    154   // TODO: move this to the graph checker.
    155   if (kIsDebugBuild) {
    156     ScopedObjectAccess soa(Thread::Current());
    157     for (HBasicBlock* block : graph_->GetReversePostOrder()) {
    158       for (HInstructionIterator iti(block->GetInstructions()); !iti.Done(); iti.Advance()) {
    159         HInstruction* instr = iti.Current();
    160         if (instr->GetType() == DataType::Type::kReference) {
    161           DCHECK(instr->GetReferenceTypeInfo().IsValid())
    162               << "Invalid RTI for instruction: " << instr->DebugName();
    163           if (instr->IsBoundType()) {
    164             DCHECK(instr->AsBoundType()->GetUpperBound().IsValid());
    165           } else if (instr->IsLoadClass()) {
    166             HLoadClass* cls = instr->AsLoadClass();
    167             DCHECK(cls->GetReferenceTypeInfo().IsExact());
    168             DCHECK(!cls->GetLoadedClassRTI().IsValid() || cls->GetLoadedClassRTI().IsExact());
    169           } else if (instr->IsNullCheck()) {
    170             DCHECK(instr->GetReferenceTypeInfo().IsEqual(instr->InputAt(0)->GetReferenceTypeInfo()))
    171                 << "NullCheck " << instr->GetReferenceTypeInfo()
    172                 << "Input(0) " << instr->InputAt(0)->GetReferenceTypeInfo();
    173           }
    174         }
    175       }
    176     }
    177   }
    178 }
    179 
    180 void ReferenceTypePropagation::Visit(HInstruction* instruction) {
    181   RTPVisitor visitor(graph_,
    182                      class_loader_,
    183                      hint_dex_cache_,
    184                      &handle_cache_,
    185                      is_first_run_);
    186   instruction->Accept(&visitor);
    187 }
    188 
    189 // Check if we should create a bound type for the given object at the specified
    190 // position. Because of inlining and the fact we run RTP more than once and we
    191 // might have a HBoundType already. If we do, we should not create a new one.
    192 // In this case we also assert that there are no other uses of the object (except
    193 // the bound type) dominated by the specified dominator_instr or dominator_block.
    194 static bool ShouldCreateBoundType(HInstruction* position,
    195                                   HInstruction* obj,
    196                                   ReferenceTypeInfo upper_bound,
    197                                   HInstruction* dominator_instr,
    198                                   HBasicBlock* dominator_block)
    199     REQUIRES_SHARED(Locks::mutator_lock_) {
    200   // If the position where we should insert the bound type is not already a
    201   // a bound type then we need to create one.
    202   if (position == nullptr || !position->IsBoundType()) {
    203     return true;
    204   }
    205 
    206   HBoundType* existing_bound_type = position->AsBoundType();
    207   if (existing_bound_type->GetUpperBound().IsSupertypeOf(upper_bound)) {
    208     if (kIsDebugBuild) {
    209       // Check that the existing HBoundType dominates all the uses.
    210       for (const HUseListNode<HInstruction*>& use : obj->GetUses()) {
    211         HInstruction* user = use.GetUser();
    212         if (dominator_instr != nullptr) {
    213           DCHECK(!dominator_instr->StrictlyDominates(user)
    214               || user == existing_bound_type
    215               || existing_bound_type->StrictlyDominates(user));
    216         } else if (dominator_block != nullptr) {
    217           DCHECK(!dominator_block->Dominates(user->GetBlock())
    218               || user == existing_bound_type
    219               || existing_bound_type->StrictlyDominates(user));
    220         }
    221       }
    222     }
    223   } else {
    224     // TODO: if the current bound type is a refinement we could update the
    225     // existing_bound_type with the a new upper limit. However, we also need to
    226     // update its users and have access to the work list.
    227   }
    228   return false;
    229 }
    230 
    231 // Helper method to bound the type of `receiver` for all instructions dominated
    232 // by `start_block`, or `start_instruction` if `start_block` is null. The new
    233 // bound type will have its upper bound be `class_rti`.
    234 static void BoundTypeIn(HInstruction* receiver,
    235                         HBasicBlock* start_block,
    236                         HInstruction* start_instruction,
    237                         const ReferenceTypeInfo& class_rti) {
    238   // We only need to bound the type if we have uses in the relevant block.
    239   // So start with null and create the HBoundType lazily, only if it's needed.
    240   HBoundType* bound_type = nullptr;
    241   DCHECK(!receiver->IsLoadClass()) << "We should not replace HLoadClass instructions";
    242   const HUseList<HInstruction*>& uses = receiver->GetUses();
    243   for (auto it = uses.begin(), end = uses.end(); it != end; /* ++it below */) {
    244     HInstruction* user = it->GetUser();
    245     size_t index = it->GetIndex();
    246     // Increment `it` now because `*it` may disappear thanks to user->ReplaceInput().
    247     ++it;
    248     bool dominates = (start_instruction != nullptr)
    249         ? start_instruction->StrictlyDominates(user)
    250         : start_block->Dominates(user->GetBlock());
    251     if (!dominates) {
    252       continue;
    253     }
    254     if (bound_type == nullptr) {
    255       ScopedObjectAccess soa(Thread::Current());
    256       HInstruction* insert_point = (start_instruction != nullptr)
    257           ? start_instruction->GetNext()
    258           : start_block->GetFirstInstruction();
    259       if (ShouldCreateBoundType(
    260             insert_point, receiver, class_rti, start_instruction, start_block)) {
    261         bound_type = new (receiver->GetBlock()->GetGraph()->GetAllocator()) HBoundType(receiver);
    262         bound_type->SetUpperBound(class_rti, /* bound_can_be_null */ false);
    263         start_block->InsertInstructionBefore(bound_type, insert_point);
    264         // To comply with the RTP algorithm, don't type the bound type just yet, it will
    265         // be handled in RTPVisitor::VisitBoundType.
    266       } else {
    267         // We already have a bound type on the position we would need to insert
    268         // the new one. The existing bound type should dominate all the users
    269         // (dchecked) so there's no need to continue.
    270         break;
    271       }
    272     }
    273     user->ReplaceInput(bound_type, index);
    274   }
    275   // If the receiver is a null check, also bound the type of the actual
    276   // receiver.
    277   if (receiver->IsNullCheck()) {
    278     BoundTypeIn(receiver->InputAt(0), start_block, start_instruction, class_rti);
    279   }
    280 }
    281 
    282 // Recognize the patterns:
    283 // if (obj.shadow$_klass_ == Foo.class) ...
    284 // deoptimize if (obj.shadow$_klass_ == Foo.class)
    285 static void BoundTypeForClassCheck(HInstruction* check) {
    286   if (!check->IsIf() && !check->IsDeoptimize()) {
    287     return;
    288   }
    289   HInstruction* compare = check->InputAt(0);
    290   if (!compare->IsEqual() && !compare->IsNotEqual()) {
    291     return;
    292   }
    293   HInstruction* input_one = compare->InputAt(0);
    294   HInstruction* input_two = compare->InputAt(1);
    295   HLoadClass* load_class = input_one->IsLoadClass()
    296       ? input_one->AsLoadClass()
    297       : input_two->AsLoadClass();
    298   if (load_class == nullptr) {
    299     return;
    300   }
    301 
    302   ReferenceTypeInfo class_rti = load_class->GetLoadedClassRTI();
    303   if (!class_rti.IsValid()) {
    304     // We have loaded an unresolved class. Don't bother bounding the type.
    305     return;
    306   }
    307 
    308   HInstanceFieldGet* field_get = (load_class == input_one)
    309       ? input_two->AsInstanceFieldGet()
    310       : input_one->AsInstanceFieldGet();
    311   if (field_get == nullptr) {
    312     return;
    313   }
    314   HInstruction* receiver = field_get->InputAt(0);
    315   ReferenceTypeInfo receiver_type = receiver->GetReferenceTypeInfo();
    316   if (receiver_type.IsExact()) {
    317     // If we already know the receiver type, don't bother updating its users.
    318     return;
    319   }
    320 
    321   {
    322     ScopedObjectAccess soa(Thread::Current());
    323     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    324     ArtField* field = class_linker->GetClassRoot(ClassLinker::kJavaLangObject)->GetInstanceField(0);
    325     DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_");
    326     if (field_get->GetFieldInfo().GetField() != field) {
    327       return;
    328     }
    329   }
    330 
    331   if (check->IsIf()) {
    332     HBasicBlock* trueBlock = compare->IsEqual()
    333         ? check->AsIf()->IfTrueSuccessor()
    334         : check->AsIf()->IfFalseSuccessor();
    335     BoundTypeIn(receiver, trueBlock, /* start_instruction */ nullptr, class_rti);
    336   } else {
    337     DCHECK(check->IsDeoptimize());
    338     if (compare->IsEqual() && check->AsDeoptimize()->GuardsAnInput()) {
    339       check->SetReferenceTypeInfo(class_rti);
    340     }
    341   }
    342 }
    343 
    344 void ReferenceTypePropagation::Run() {
    345   RTPVisitor visitor(graph_, class_loader_, hint_dex_cache_, &handle_cache_, is_first_run_);
    346 
    347   // To properly propagate type info we need to visit in the dominator-based order.
    348   // Reverse post order guarantees a node's dominators are visited first.
    349   // We take advantage of this order in `VisitBasicBlock`.
    350   for (HBasicBlock* block : graph_->GetReversePostOrder()) {
    351     visitor.VisitBasicBlock(block);
    352   }
    353 
    354   visitor.ProcessWorklist();
    355   ValidateTypes();
    356 }
    357 
    358 void ReferenceTypePropagation::RTPVisitor::VisitBasicBlock(HBasicBlock* block) {
    359   // Handle Phis first as there might be instructions in the same block who depend on them.
    360   for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
    361     VisitPhi(it.Current()->AsPhi());
    362   }
    363 
    364   // Handle instructions. Since RTP may add HBoundType instructions just after the
    365   // last visited instruction, use `HInstructionIteratorHandleChanges` iterator.
    366   for (HInstructionIteratorHandleChanges it(block->GetInstructions()); !it.Done(); it.Advance()) {
    367     HInstruction* instr = it.Current();
    368     instr->Accept(this);
    369   }
    370 
    371   // Add extra nodes to bound types.
    372   BoundTypeForIfNotNull(block);
    373   BoundTypeForIfInstanceOf(block);
    374   BoundTypeForClassCheck(block->GetLastInstruction());
    375 }
    376 
    377 void ReferenceTypePropagation::RTPVisitor::BoundTypeForIfNotNull(HBasicBlock* block) {
    378   HIf* ifInstruction = block->GetLastInstruction()->AsIf();
    379   if (ifInstruction == nullptr) {
    380     return;
    381   }
    382   HInstruction* ifInput = ifInstruction->InputAt(0);
    383   if (!ifInput->IsNotEqual() && !ifInput->IsEqual()) {
    384     return;
    385   }
    386   HInstruction* input0 = ifInput->InputAt(0);
    387   HInstruction* input1 = ifInput->InputAt(1);
    388   HInstruction* obj = nullptr;
    389 
    390   if (input1->IsNullConstant()) {
    391     obj = input0;
    392   } else if (input0->IsNullConstant()) {
    393     obj = input1;
    394   } else {
    395     return;
    396   }
    397 
    398   if (!obj->CanBeNull() || obj->IsNullConstant()) {
    399     // Null check is dead code and will be removed by DCE.
    400     return;
    401   }
    402   DCHECK(!obj->IsLoadClass()) << "We should not replace HLoadClass instructions";
    403 
    404   // We only need to bound the type if we have uses in the relevant block.
    405   // So start with null and create the HBoundType lazily, only if it's needed.
    406   HBasicBlock* notNullBlock = ifInput->IsNotEqual()
    407       ? ifInstruction->IfTrueSuccessor()
    408       : ifInstruction->IfFalseSuccessor();
    409 
    410   ReferenceTypeInfo object_rti = ReferenceTypeInfo::Create(
    411       handle_cache_->GetObjectClassHandle(), /* is_exact */ false);
    412 
    413   BoundTypeIn(obj, notNullBlock, /* start_instruction */ nullptr, object_rti);
    414 }
    415 
    416 // Returns true if one of the patterns below has been recognized. If so, the
    417 // InstanceOf instruction together with the true branch of `ifInstruction` will
    418 // be returned using the out parameters.
    419 // Recognized patterns:
    420 //   (1) patterns equivalent to `if (obj instanceof X)`
    421 //     (a) InstanceOf -> Equal to 1 -> If
    422 //     (b) InstanceOf -> NotEqual to 0 -> If
    423 //     (c) InstanceOf -> If
    424 //   (2) patterns equivalent to `if (!(obj instanceof X))`
    425 //     (a) InstanceOf -> Equal to 0 -> If
    426 //     (b) InstanceOf -> NotEqual to 1 -> If
    427 //     (c) InstanceOf -> BooleanNot -> If
    428 static bool MatchIfInstanceOf(HIf* ifInstruction,
    429                               /* out */ HInstanceOf** instanceOf,
    430                               /* out */ HBasicBlock** trueBranch) {
    431   HInstruction* input = ifInstruction->InputAt(0);
    432 
    433   if (input->IsEqual()) {
    434     HInstruction* rhs = input->AsEqual()->GetConstantRight();
    435     if (rhs != nullptr) {
    436       HInstruction* lhs = input->AsEqual()->GetLeastConstantLeft();
    437       if (lhs->IsInstanceOf() && rhs->IsIntConstant()) {
    438         if (rhs->AsIntConstant()->IsTrue()) {
    439           // Case (1a)
    440           *trueBranch = ifInstruction->IfTrueSuccessor();
    441         } else {
    442           // Case (2a)
    443           DCHECK(rhs->AsIntConstant()->IsFalse()) << rhs->AsIntConstant()->GetValue();
    444           *trueBranch = ifInstruction->IfFalseSuccessor();
    445         }
    446         *instanceOf = lhs->AsInstanceOf();
    447         return true;
    448       }
    449     }
    450   } else if (input->IsNotEqual()) {
    451     HInstruction* rhs = input->AsNotEqual()->GetConstantRight();
    452     if (rhs != nullptr) {
    453       HInstruction* lhs = input->AsNotEqual()->GetLeastConstantLeft();
    454       if (lhs->IsInstanceOf() && rhs->IsIntConstant()) {
    455         if (rhs->AsIntConstant()->IsFalse()) {
    456           // Case (1b)
    457           *trueBranch = ifInstruction->IfTrueSuccessor();
    458         } else {
    459           // Case (2b)
    460           DCHECK(rhs->AsIntConstant()->IsTrue()) << rhs->AsIntConstant()->GetValue();
    461           *trueBranch = ifInstruction->IfFalseSuccessor();
    462         }
    463         *instanceOf = lhs->AsInstanceOf();
    464         return true;
    465       }
    466     }
    467   } else if (input->IsInstanceOf()) {
    468     // Case (1c)
    469     *instanceOf = input->AsInstanceOf();
    470     *trueBranch = ifInstruction->IfTrueSuccessor();
    471     return true;
    472   } else if (input->IsBooleanNot()) {
    473     HInstruction* not_input = input->InputAt(0);
    474     if (not_input->IsInstanceOf()) {
    475       // Case (2c)
    476       *instanceOf = not_input->AsInstanceOf();
    477       *trueBranch = ifInstruction->IfFalseSuccessor();
    478       return true;
    479     }
    480   }
    481 
    482   return false;
    483 }
    484 
    485 // Detects if `block` is the True block for the pattern
    486 // `if (x instanceof ClassX) { }`
    487 // If that's the case insert an HBoundType instruction to bound the type of `x`
    488 // to `ClassX` in the scope of the dominated blocks.
    489 void ReferenceTypePropagation::RTPVisitor::BoundTypeForIfInstanceOf(HBasicBlock* block) {
    490   HIf* ifInstruction = block->GetLastInstruction()->AsIf();
    491   if (ifInstruction == nullptr) {
    492     return;
    493   }
    494 
    495   // Try to recognize common `if (instanceof)` and `if (!instanceof)` patterns.
    496   HInstanceOf* instanceOf = nullptr;
    497   HBasicBlock* instanceOfTrueBlock = nullptr;
    498   if (!MatchIfInstanceOf(ifInstruction, &instanceOf, &instanceOfTrueBlock)) {
    499     return;
    500   }
    501 
    502   HLoadClass* load_class = instanceOf->InputAt(1)->AsLoadClass();
    503   ReferenceTypeInfo class_rti = load_class->GetLoadedClassRTI();
    504   if (!class_rti.IsValid()) {
    505     // He have loaded an unresolved class. Don't bother bounding the type.
    506     return;
    507   }
    508 
    509   HInstruction* obj = instanceOf->InputAt(0);
    510   if (obj->GetReferenceTypeInfo().IsExact() && !obj->IsPhi()) {
    511     // This method is being called while doing a fixed-point calculation
    512     // over phis. Non-phis instruction whose type is already known do
    513     // not need to be bound to another type.
    514     // Not that this also prevents replacing `HLoadClass` with a `HBoundType`.
    515     // `HCheckCast` and `HInstanceOf` expect a `HLoadClass` as a second
    516     // input.
    517     return;
    518   }
    519 
    520   {
    521     ScopedObjectAccess soa(Thread::Current());
    522     if (!class_rti.GetTypeHandle()->CannotBeAssignedFromOtherTypes()) {
    523       class_rti = ReferenceTypeInfo::Create(class_rti.GetTypeHandle(), /* is_exact */ false);
    524     }
    525   }
    526   BoundTypeIn(obj, instanceOfTrueBlock, /* start_instruction */ nullptr, class_rti);
    527 }
    528 
    529 void ReferenceTypePropagation::RTPVisitor::SetClassAsTypeInfo(HInstruction* instr,
    530                                                               ObjPtr<mirror::Class> klass,
    531                                                               bool is_exact) {
    532   if (instr->IsInvokeStaticOrDirect() && instr->AsInvokeStaticOrDirect()->IsStringInit()) {
    533     // Calls to String.<init> are replaced with a StringFactory.
    534     if (kIsDebugBuild) {
    535       HInvokeStaticOrDirect* invoke = instr->AsInvokeStaticOrDirect();
    536       ClassLinker* cl = Runtime::Current()->GetClassLinker();
    537       Thread* self = Thread::Current();
    538       StackHandleScope<2> hs(self);
    539       const DexFile& dex_file = *invoke->GetTargetMethod().dex_file;
    540       uint32_t dex_method_index = invoke->GetTargetMethod().index;
    541       Handle<mirror::DexCache> dex_cache(
    542           hs.NewHandle(FindDexCacheWithHint(self, dex_file, hint_dex_cache_)));
    543       // Use a null loader, the target method is in a boot classpath dex file.
    544       Handle<mirror::ClassLoader> loader(hs.NewHandle<mirror::ClassLoader>(nullptr));
    545       ArtMethod* method = cl->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
    546           dex_method_index, dex_cache, loader, /* referrer */ nullptr, kDirect);
    547       DCHECK(method != nullptr);
    548       mirror::Class* declaring_class = method->GetDeclaringClass();
    549       DCHECK(declaring_class != nullptr);
    550       DCHECK(declaring_class->IsStringClass())
    551           << "Expected String class: " << declaring_class->PrettyDescriptor();
    552       DCHECK(method->IsConstructor())
    553           << "Expected String.<init>: " << method->PrettyMethod();
    554     }
    555     instr->SetReferenceTypeInfo(
    556         ReferenceTypeInfo::Create(handle_cache_->GetStringClassHandle(), /* is_exact */ true));
    557   } else if (IsAdmissible(klass.Ptr())) {
    558     ReferenceTypeInfo::TypeHandle handle = handle_cache_->NewHandle(klass);
    559     is_exact = is_exact || handle->CannotBeAssignedFromOtherTypes();
    560     instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(handle, is_exact));
    561   } else {
    562     instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
    563   }
    564 }
    565 
    566 void ReferenceTypePropagation::RTPVisitor::VisitDeoptimize(HDeoptimize* instr) {
    567   BoundTypeForClassCheck(instr);
    568 }
    569 
    570 void ReferenceTypePropagation::RTPVisitor::UpdateReferenceTypeInfo(HInstruction* instr,
    571                                                                    dex::TypeIndex type_idx,
    572                                                                    const DexFile& dex_file,
    573                                                                    bool is_exact) {
    574   DCHECK_EQ(instr->GetType(), DataType::Type::kReference);
    575 
    576   ScopedObjectAccess soa(Thread::Current());
    577   ObjPtr<mirror::DexCache> dex_cache = FindDexCacheWithHint(soa.Self(), dex_file, hint_dex_cache_);
    578   ObjPtr<mirror::Class> klass = Runtime::Current()->GetClassLinker()->LookupResolvedType(
    579       type_idx, dex_cache, class_loader_.Get());
    580   SetClassAsTypeInfo(instr, klass, is_exact);
    581 }
    582 
    583 void ReferenceTypePropagation::RTPVisitor::VisitNewInstance(HNewInstance* instr) {
    584   ScopedObjectAccess soa(Thread::Current());
    585   SetClassAsTypeInfo(instr, instr->GetLoadClass()->GetClass().Get(), /* is_exact */ true);
    586 }
    587 
    588 void ReferenceTypePropagation::RTPVisitor::VisitNewArray(HNewArray* instr) {
    589   ScopedObjectAccess soa(Thread::Current());
    590   SetClassAsTypeInfo(instr, instr->GetLoadClass()->GetClass().Get(), /* is_exact */ true);
    591 }
    592 
    593 void ReferenceTypePropagation::RTPVisitor::VisitParameterValue(HParameterValue* instr) {
    594   // We check if the existing type is valid: the inliner may have set it.
    595   if (instr->GetType() == DataType::Type::kReference && !instr->GetReferenceTypeInfo().IsValid()) {
    596     UpdateReferenceTypeInfo(instr,
    597                             instr->GetTypeIndex(),
    598                             instr->GetDexFile(),
    599                             /* is_exact */ false);
    600   }
    601 }
    602 
    603 void ReferenceTypePropagation::RTPVisitor::UpdateFieldAccessTypeInfo(HInstruction* instr,
    604                                                                      const FieldInfo& info) {
    605   if (instr->GetType() != DataType::Type::kReference) {
    606     return;
    607   }
    608 
    609   ScopedObjectAccess soa(Thread::Current());
    610   ObjPtr<mirror::Class> klass;
    611 
    612   // The field is unknown only during tests.
    613   if (info.GetField() != nullptr) {
    614     klass = info.GetField()->LookupResolvedType();
    615   }
    616 
    617   SetClassAsTypeInfo(instr, klass, /* is_exact */ false);
    618 }
    619 
    620 void ReferenceTypePropagation::RTPVisitor::VisitInstanceFieldGet(HInstanceFieldGet* instr) {
    621   UpdateFieldAccessTypeInfo(instr, instr->GetFieldInfo());
    622 }
    623 
    624 void ReferenceTypePropagation::RTPVisitor::VisitStaticFieldGet(HStaticFieldGet* instr) {
    625   UpdateFieldAccessTypeInfo(instr, instr->GetFieldInfo());
    626 }
    627 
    628 void ReferenceTypePropagation::RTPVisitor::VisitUnresolvedInstanceFieldGet(
    629     HUnresolvedInstanceFieldGet* instr) {
    630   // TODO: Use descriptor to get the actual type.
    631   if (instr->GetFieldType() == DataType::Type::kReference) {
    632     instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
    633   }
    634 }
    635 
    636 void ReferenceTypePropagation::RTPVisitor::VisitUnresolvedStaticFieldGet(
    637     HUnresolvedStaticFieldGet* instr) {
    638   // TODO: Use descriptor to get the actual type.
    639   if (instr->GetFieldType() == DataType::Type::kReference) {
    640     instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
    641   }
    642 }
    643 
    644 void ReferenceTypePropagation::RTPVisitor::VisitLoadClass(HLoadClass* instr) {
    645   ScopedObjectAccess soa(Thread::Current());
    646   Handle<mirror::Class> resolved_class = instr->GetClass();
    647   if (IsAdmissible(resolved_class.Get())) {
    648     instr->SetLoadedClassRTI(ReferenceTypeInfo::Create(
    649         resolved_class, /* is_exact */ true));
    650   }
    651   instr->SetReferenceTypeInfo(
    652       ReferenceTypeInfo::Create(handle_cache_->GetClassClassHandle(), /* is_exact */ true));
    653 }
    654 
    655 void ReferenceTypePropagation::RTPVisitor::VisitClinitCheck(HClinitCheck* instr) {
    656   instr->SetReferenceTypeInfo(instr->InputAt(0)->GetReferenceTypeInfo());
    657 }
    658 
    659 void ReferenceTypePropagation::RTPVisitor::VisitLoadString(HLoadString* instr) {
    660   instr->SetReferenceTypeInfo(
    661       ReferenceTypeInfo::Create(handle_cache_->GetStringClassHandle(), /* is_exact */ true));
    662 }
    663 
    664 void ReferenceTypePropagation::RTPVisitor::VisitLoadException(HLoadException* instr) {
    665   DCHECK(instr->GetBlock()->IsCatchBlock());
    666   TryCatchInformation* catch_info = instr->GetBlock()->GetTryCatchInformation();
    667 
    668   if (catch_info->IsCatchAllTypeIndex()) {
    669     instr->SetReferenceTypeInfo(
    670         ReferenceTypeInfo::Create(handle_cache_->GetThrowableClassHandle(), /* is_exact */ false));
    671   } else {
    672     UpdateReferenceTypeInfo(instr,
    673                             catch_info->GetCatchTypeIndex(),
    674                             catch_info->GetCatchDexFile(),
    675                             /* is_exact */ false);
    676   }
    677 }
    678 
    679 void ReferenceTypePropagation::RTPVisitor::VisitNullCheck(HNullCheck* instr) {
    680   ReferenceTypeInfo parent_rti = instr->InputAt(0)->GetReferenceTypeInfo();
    681   if (parent_rti.IsValid()) {
    682     instr->SetReferenceTypeInfo(parent_rti);
    683   }
    684 }
    685 
    686 void ReferenceTypePropagation::RTPVisitor::VisitBoundType(HBoundType* instr) {
    687   ReferenceTypeInfo class_rti = instr->GetUpperBound();
    688   if (class_rti.IsValid()) {
    689     ScopedObjectAccess soa(Thread::Current());
    690     // Narrow the type as much as possible.
    691     HInstruction* obj = instr->InputAt(0);
    692     ReferenceTypeInfo obj_rti = obj->GetReferenceTypeInfo();
    693     if (class_rti.IsExact()) {
    694       instr->SetReferenceTypeInfo(class_rti);
    695     } else if (obj_rti.IsValid()) {
    696       if (class_rti.IsSupertypeOf(obj_rti)) {
    697         // Object type is more specific.
    698         instr->SetReferenceTypeInfo(obj_rti);
    699       } else {
    700         // Upper bound is more specific, or unrelated to the object's type.
    701         // Note that the object might then be exact, and we know the code dominated by this
    702         // bound type is dead. To not confuse potential other optimizations, we mark
    703         // the bound as non-exact.
    704         instr->SetReferenceTypeInfo(
    705             ReferenceTypeInfo::Create(class_rti.GetTypeHandle(), /* is_exact */ false));
    706       }
    707     } else {
    708       // Object not typed yet. Leave BoundType untyped for now rather than
    709       // assign the type conservatively.
    710     }
    711     instr->SetCanBeNull(obj->CanBeNull() && instr->GetUpperCanBeNull());
    712   } else {
    713     // The owner of the BoundType was already visited. If the class is unresolved,
    714     // the BoundType should have been removed from the data flow and this method
    715     // should remove it from the graph.
    716     DCHECK(!instr->HasUses());
    717     instr->GetBlock()->RemoveInstruction(instr);
    718   }
    719 }
    720 
    721 void ReferenceTypePropagation::RTPVisitor::VisitCheckCast(HCheckCast* check_cast) {
    722   HLoadClass* load_class = check_cast->InputAt(1)->AsLoadClass();
    723   ReferenceTypeInfo class_rti = load_class->GetLoadedClassRTI();
    724   HBoundType* bound_type = check_cast->GetNext()->AsBoundType();
    725   if (bound_type == nullptr || bound_type->GetUpperBound().IsValid()) {
    726     // The next instruction is not an uninitialized BoundType. This must be
    727     // an RTP pass after SsaBuilder and we do not need to do anything.
    728     return;
    729   }
    730   DCHECK_EQ(bound_type->InputAt(0), check_cast->InputAt(0));
    731 
    732   if (class_rti.IsValid()) {
    733     DCHECK(is_first_run_);
    734     ScopedObjectAccess soa(Thread::Current());
    735     // This is the first run of RTP and class is resolved.
    736     bool is_exact = class_rti.GetTypeHandle()->CannotBeAssignedFromOtherTypes();
    737     bound_type->SetUpperBound(ReferenceTypeInfo::Create(class_rti.GetTypeHandle(), is_exact),
    738                               /* CheckCast succeeds for nulls. */ true);
    739   } else {
    740     // This is the first run of RTP and class is unresolved. Remove the binding.
    741     // The instruction itself is removed in VisitBoundType so as to not
    742     // invalidate HInstructionIterator.
    743     bound_type->ReplaceWith(bound_type->InputAt(0));
    744   }
    745 }
    746 
    747 void ReferenceTypePropagation::RTPVisitor::VisitPhi(HPhi* phi) {
    748   if (phi->IsDead() || phi->GetType() != DataType::Type::kReference) {
    749     return;
    750   }
    751 
    752   if (phi->GetBlock()->IsLoopHeader()) {
    753     // Set the initial type for the phi. Use the non back edge input for reaching
    754     // a fixed point faster.
    755     HInstruction* first_input = phi->InputAt(0);
    756     ReferenceTypeInfo first_input_rti = first_input->GetReferenceTypeInfo();
    757     if (first_input_rti.IsValid() && !first_input->IsNullConstant()) {
    758       phi->SetCanBeNull(first_input->CanBeNull());
    759       phi->SetReferenceTypeInfo(first_input_rti);
    760     }
    761     AddToWorklist(phi);
    762   } else {
    763     // Eagerly compute the type of the phi, for quicker convergence. Note
    764     // that we don't need to add users to the worklist because we are
    765     // doing a reverse post-order visit, therefore either the phi users are
    766     // non-loop phi and will be visited later in the visit, or are loop-phis,
    767     // and they are already in the work list.
    768     UpdateNullability(phi);
    769     UpdateReferenceTypeInfo(phi);
    770   }
    771 }
    772 
    773 void ReferenceTypePropagation::FixUpInstructionType(HInstruction* instruction,
    774                                                     VariableSizedHandleScope* handle_scope) {
    775   if (instruction->IsSelect()) {
    776     ScopedObjectAccess soa(Thread::Current());
    777     HandleCache handle_cache(handle_scope);
    778     HSelect* select = instruction->AsSelect();
    779     ReferenceTypeInfo false_rti = select->GetFalseValue()->GetReferenceTypeInfo();
    780     ReferenceTypeInfo true_rti = select->GetTrueValue()->GetReferenceTypeInfo();
    781     select->SetReferenceTypeInfo(MergeTypes(false_rti, true_rti, &handle_cache));
    782   } else {
    783     LOG(FATAL) << "Invalid instruction in FixUpInstructionType";
    784   }
    785 }
    786 
    787 ReferenceTypeInfo ReferenceTypePropagation::MergeTypes(const ReferenceTypeInfo& a,
    788                                                        const ReferenceTypeInfo& b,
    789                                                        HandleCache* handle_cache) {
    790   if (!b.IsValid()) {
    791     return a;
    792   }
    793   if (!a.IsValid()) {
    794     return b;
    795   }
    796 
    797   bool is_exact = a.IsExact() && b.IsExact();
    798   ReferenceTypeInfo::TypeHandle result_type_handle;
    799   ReferenceTypeInfo::TypeHandle a_type_handle = a.GetTypeHandle();
    800   ReferenceTypeInfo::TypeHandle b_type_handle = b.GetTypeHandle();
    801   bool a_is_interface = a_type_handle->IsInterface();
    802   bool b_is_interface = b_type_handle->IsInterface();
    803 
    804   if (a.GetTypeHandle().Get() == b.GetTypeHandle().Get()) {
    805     result_type_handle = a_type_handle;
    806   } else if (a.IsSupertypeOf(b)) {
    807     result_type_handle = a_type_handle;
    808     is_exact = false;
    809   } else if (b.IsSupertypeOf(a)) {
    810     result_type_handle = b_type_handle;
    811     is_exact = false;
    812   } else if (!a_is_interface && !b_is_interface) {
    813     result_type_handle =
    814         handle_cache->NewHandle(a_type_handle->GetCommonSuperClass(b_type_handle));
    815     is_exact = false;
    816   } else {
    817     // This can happen if:
    818     //    - both types are interfaces. TODO(calin): implement
    819     //    - one is an interface, the other a class, and the type does not implement the interface
    820     //      e.g:
    821     //        void foo(Interface i, boolean cond) {
    822     //          Object o = cond ? i : new Object();
    823     //        }
    824     result_type_handle = handle_cache->GetObjectClassHandle();
    825     is_exact = false;
    826   }
    827 
    828   return ReferenceTypeInfo::Create(result_type_handle, is_exact);
    829 }
    830 
    831 void ReferenceTypePropagation::RTPVisitor::UpdateArrayGet(HArrayGet* instr) {
    832   DCHECK_EQ(DataType::Type::kReference, instr->GetType());
    833 
    834   ReferenceTypeInfo parent_rti = instr->InputAt(0)->GetReferenceTypeInfo();
    835   if (!parent_rti.IsValid()) {
    836     return;
    837   }
    838 
    839   Handle<mirror::Class> handle = parent_rti.GetTypeHandle();
    840   if (handle->IsObjectArrayClass() && IsAdmissible(handle->GetComponentType())) {
    841     ReferenceTypeInfo::TypeHandle component_handle =
    842         handle_cache_->NewHandle(handle->GetComponentType());
    843     bool is_exact = component_handle->CannotBeAssignedFromOtherTypes();
    844     instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(component_handle, is_exact));
    845   } else {
    846     // We don't know what the parent actually is, so we fallback to object.
    847     instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
    848   }
    849 }
    850 
    851 bool ReferenceTypePropagation::RTPVisitor::UpdateReferenceTypeInfo(HInstruction* instr) {
    852   ScopedObjectAccess soa(Thread::Current());
    853 
    854   ReferenceTypeInfo previous_rti = instr->GetReferenceTypeInfo();
    855   if (instr->IsBoundType()) {
    856     UpdateBoundType(instr->AsBoundType());
    857   } else if (instr->IsPhi()) {
    858     UpdatePhi(instr->AsPhi());
    859   } else if (instr->IsNullCheck()) {
    860     ReferenceTypeInfo parent_rti = instr->InputAt(0)->GetReferenceTypeInfo();
    861     if (parent_rti.IsValid()) {
    862       instr->SetReferenceTypeInfo(parent_rti);
    863     }
    864   } else if (instr->IsArrayGet()) {
    865     // TODO: consider if it's worth "looking back" and binding the input object
    866     // to an array type.
    867     UpdateArrayGet(instr->AsArrayGet());
    868   } else {
    869     LOG(FATAL) << "Invalid instruction (should not get here)";
    870   }
    871 
    872   return !previous_rti.IsEqual(instr->GetReferenceTypeInfo());
    873 }
    874 
    875 void ReferenceTypePropagation::RTPVisitor::VisitInvoke(HInvoke* instr) {
    876   if (instr->GetType() != DataType::Type::kReference) {
    877     return;
    878   }
    879 
    880   ScopedObjectAccess soa(Thread::Current());
    881   ArtMethod* method = instr->GetResolvedMethod();
    882   ObjPtr<mirror::Class> klass = (method == nullptr) ? nullptr : method->LookupResolvedReturnType();
    883   SetClassAsTypeInfo(instr, klass, /* is_exact */ false);
    884 }
    885 
    886 void ReferenceTypePropagation::RTPVisitor::VisitArrayGet(HArrayGet* instr) {
    887   if (instr->GetType() != DataType::Type::kReference) {
    888     return;
    889   }
    890 
    891   ScopedObjectAccess soa(Thread::Current());
    892   UpdateArrayGet(instr);
    893   if (!instr->GetReferenceTypeInfo().IsValid()) {
    894     worklist_.push_back(instr);
    895   }
    896 }
    897 
    898 void ReferenceTypePropagation::RTPVisitor::UpdateBoundType(HBoundType* instr) {
    899   ReferenceTypeInfo input_rti = instr->InputAt(0)->GetReferenceTypeInfo();
    900   if (!input_rti.IsValid()) {
    901     return;  // No new info yet.
    902   }
    903 
    904   ReferenceTypeInfo upper_bound_rti = instr->GetUpperBound();
    905   if (upper_bound_rti.IsExact()) {
    906     instr->SetReferenceTypeInfo(upper_bound_rti);
    907   } else if (upper_bound_rti.IsSupertypeOf(input_rti)) {
    908     // input is more specific.
    909     instr->SetReferenceTypeInfo(input_rti);
    910   } else {
    911     // upper_bound is more specific or unrelated.
    912     // Note that the object might then be exact, and we know the code dominated by this
    913     // bound type is dead. To not confuse potential other optimizations, we mark
    914     // the bound as non-exact.
    915     instr->SetReferenceTypeInfo(
    916         ReferenceTypeInfo::Create(upper_bound_rti.GetTypeHandle(), /* is_exact */ false));
    917   }
    918 }
    919 
    920 // NullConstant inputs are ignored during merging as they do not provide any useful information.
    921 // If all the inputs are NullConstants then the type of the phi will be set to Object.
    922 void ReferenceTypePropagation::RTPVisitor::UpdatePhi(HPhi* instr) {
    923   DCHECK(instr->IsLive());
    924 
    925   HInputsRef inputs = instr->GetInputs();
    926   size_t first_input_index_not_null = 0;
    927   while (first_input_index_not_null < inputs.size() &&
    928          inputs[first_input_index_not_null]->IsNullConstant()) {
    929     first_input_index_not_null++;
    930   }
    931   if (first_input_index_not_null == inputs.size()) {
    932     // All inputs are NullConstants, set the type to object.
    933     // This may happen in the presence of inlining.
    934     instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
    935     return;
    936   }
    937 
    938   ReferenceTypeInfo new_rti = instr->InputAt(first_input_index_not_null)->GetReferenceTypeInfo();
    939 
    940   if (new_rti.IsValid() && new_rti.IsObjectClass() && !new_rti.IsExact()) {
    941     // Early return if we are Object and inexact.
    942     instr->SetReferenceTypeInfo(new_rti);
    943     return;
    944   }
    945 
    946   for (size_t i = first_input_index_not_null + 1; i < inputs.size(); i++) {
    947     if (inputs[i]->IsNullConstant()) {
    948       continue;
    949     }
    950     new_rti = MergeTypes(new_rti, inputs[i]->GetReferenceTypeInfo(), handle_cache_);
    951     if (new_rti.IsValid() && new_rti.IsObjectClass()) {
    952       if (!new_rti.IsExact()) {
    953         break;
    954       } else {
    955         continue;
    956       }
    957     }
    958   }
    959 
    960   if (new_rti.IsValid()) {
    961     instr->SetReferenceTypeInfo(new_rti);
    962   }
    963 }
    964 
    965 // Re-computes and updates the nullability of the instruction. Returns whether or
    966 // not the nullability was changed.
    967 bool ReferenceTypePropagation::RTPVisitor::UpdateNullability(HInstruction* instr) {
    968   DCHECK((instr->IsPhi() && instr->AsPhi()->IsLive())
    969       || instr->IsBoundType()
    970       || instr->IsNullCheck()
    971       || instr->IsArrayGet());
    972 
    973   if (!instr->IsPhi() && !instr->IsBoundType()) {
    974     return false;
    975   }
    976 
    977   bool existing_can_be_null = instr->CanBeNull();
    978   if (instr->IsPhi()) {
    979     HPhi* phi = instr->AsPhi();
    980     bool new_can_be_null = false;
    981     for (HInstruction* input : phi->GetInputs()) {
    982       if (input->CanBeNull()) {
    983         new_can_be_null = true;
    984         break;
    985       }
    986     }
    987     phi->SetCanBeNull(new_can_be_null);
    988   } else if (instr->IsBoundType()) {
    989     HBoundType* bound_type = instr->AsBoundType();
    990     bound_type->SetCanBeNull(instr->InputAt(0)->CanBeNull() && bound_type->GetUpperCanBeNull());
    991   }
    992   return existing_can_be_null != instr->CanBeNull();
    993 }
    994 
    995 void ReferenceTypePropagation::RTPVisitor::ProcessWorklist() {
    996   while (!worklist_.empty()) {
    997     HInstruction* instruction = worklist_.back();
    998     worklist_.pop_back();
    999     bool updated_nullability = UpdateNullability(instruction);
   1000     bool updated_reference_type = UpdateReferenceTypeInfo(instruction);
   1001     if (updated_nullability || updated_reference_type) {
   1002       AddDependentInstructionsToWorklist(instruction);
   1003     }
   1004   }
   1005 }
   1006 
   1007 void ReferenceTypePropagation::RTPVisitor::AddToWorklist(HInstruction* instruction) {
   1008   DCHECK_EQ(instruction->GetType(), DataType::Type::kReference)
   1009       << instruction->DebugName() << ":" << instruction->GetType();
   1010   worklist_.push_back(instruction);
   1011 }
   1012 
   1013 void ReferenceTypePropagation::RTPVisitor::AddDependentInstructionsToWorklist(
   1014     HInstruction* instruction) {
   1015   for (const HUseListNode<HInstruction*>& use : instruction->GetUses()) {
   1016     HInstruction* user = use.GetUser();
   1017     if ((user->IsPhi() && user->AsPhi()->IsLive())
   1018        || user->IsBoundType()
   1019        || user->IsNullCheck()
   1020        || (user->IsArrayGet() && (user->GetType() == DataType::Type::kReference))) {
   1021       AddToWorklist(user);
   1022     }
   1023   }
   1024 }
   1025 
   1026 }  // namespace art
   1027