110e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle/*
210e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle * Copyright (C) 2015 The Android Open Source Project
310e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle *
410e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle * Licensed under the Apache License, Version 2.0 (the "License");
510e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle * you may not use this file except in compliance with the License.
610e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle * You may obtain a copy of the License at
710e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle *
810e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle *      http://www.apache.org/licenses/LICENSE-2.0
910e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle *
1010e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle * Unless required by applicable law or agreed to in writing, software
1110e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle * distributed under the License is distributed on an "AS IS" BASIS,
1210e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1310e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle * See the License for the specific language governing permissions and
1410e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle * limitations under the License.
1510e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle */
1610e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle
1710e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle#include "reference_type_propagation.h"
1810e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle
19a1d2f957a21319d1110bebb9a52f46fd1c67ffafAndreas Gampe#include "art_field-inl.h"
20c6ea7d00ad069a2736f603daa3d8eaa9a1f8ea11Andreas Gampe#include "art_method-inl.h"
21542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe#include "base/enums.h"
22e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "class_linker-inl.h"
23acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle#include "mirror/class-inl.h"
24acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle#include "mirror/dex_cache.h"
250795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "scoped_thread_state_change-inl.h"
26acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle
2710e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravlenamespace art {
2810e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle
29cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Markostatic inline ObjPtr<mirror::DexCache> FindDexCacheWithHint(
30cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko    Thread* self, const DexFile& dex_file, Handle<mirror::DexCache> hint_dex_cache)
31bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
32456307a47336e3d6576ed6d8563b67573a4238d3Vladimir Marko  if (LIKELY(hint_dex_cache->GetDexFile() == &dex_file)) {
33456307a47336e3d6576ed6d8563b67573a4238d3Vladimir Marko    return hint_dex_cache.Get();
34456307a47336e3d6576ed6d8563b67573a4238d3Vladimir Marko  } else {
35456307a47336e3d6576ed6d8563b67573a4238d3Vladimir Marko    return Runtime::Current()->GetClassLinker()->FindDexCache(self, dex_file);
36456307a47336e3d6576ed6d8563b67573a4238d3Vladimir Marko  }
37456307a47336e3d6576ed6d8563b67573a4238d3Vladimir Marko}
38456307a47336e3d6576ed6d8563b67573a4238d3Vladimir Marko
39e8a3c576301fd531d5f73a65fc8b84a63619d580Mathieu Chartierstatic inline ReferenceTypeInfo::TypeHandle GetRootHandle(VariableSizedHandleScope* handles,
407d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko                                                          ClassLinker::ClassRoot class_root,
417d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko                                                          ReferenceTypeInfo::TypeHandle* cache) {
427d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  if (!ReferenceTypeInfo::IsValidHandle(*cache)) {
437d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    // Mutator lock is required for NewHandle.
447d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    ClassLinker* linker = Runtime::Current()->GetClassLinker();
457d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    ScopedObjectAccess soa(Thread::Current());
467d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    *cache = handles->NewHandle(linker->GetClassRoot(class_root));
477d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  }
487d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  return *cache;
497d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko}
507d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko
517d1fbf38412078090e81e9d9fa502635d8541707Vladimir MarkoReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetObjectClassHandle() {
527d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  return GetRootHandle(handles_, ClassLinker::kJavaLangObject, &object_class_handle_);
537d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko}
547d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko
557d1fbf38412078090e81e9d9fa502635d8541707Vladimir MarkoReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetClassClassHandle() {
567d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  return GetRootHandle(handles_, ClassLinker::kJavaLangClass, &class_class_handle_);
577d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko}
587d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko
597d1fbf38412078090e81e9d9fa502635d8541707Vladimir MarkoReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetStringClassHandle() {
607d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  return GetRootHandle(handles_, ClassLinker::kJavaLangString, &string_class_handle_);
617d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko}
627d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko
637d1fbf38412078090e81e9d9fa502635d8541707Vladimir MarkoReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetThrowableClassHandle() {
647d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  return GetRootHandle(handles_, ClassLinker::kJavaLangThrowable, &throwable_class_handle_);
657d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko}
667d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko
677d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markoclass ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor {
68ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez public:
692e76830f0b3f23825677436c0633714402715099Calin Juravle  RTPVisitor(HGraph* graph,
708d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko             Handle<mirror::ClassLoader> class_loader,
71456307a47336e3d6576ed6d8563b67573a4238d3Vladimir Marko             Handle<mirror::DexCache> hint_dex_cache,
727d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko             HandleCache* handle_cache,
73d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray             ArenaVector<HInstruction*>* worklist,
74d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray             bool is_first_run)
75ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez    : HGraphDelegateVisitor(graph),
768d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko      class_loader_(class_loader),
77456307a47336e3d6576ed6d8563b67573a4238d3Vladimir Marko      hint_dex_cache_(hint_dex_cache),
787d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko      handle_cache_(handle_cache),
79d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray      worklist_(worklist),
80d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray      is_first_run_(is_first_run) {}
81ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez
82c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  void VisitDeoptimize(HDeoptimize* deopt) OVERRIDE;
83ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  void VisitNewInstance(HNewInstance* new_instance) OVERRIDE;
84ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  void VisitLoadClass(HLoadClass* load_class) OVERRIDE;
852e76830f0b3f23825677436c0633714402715099Calin Juravle  void VisitClinitCheck(HClinitCheck* clinit_check) OVERRIDE;
862e76830f0b3f23825677436c0633714402715099Calin Juravle  void VisitLoadString(HLoadString* instr) OVERRIDE;
87bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil  void VisitLoadException(HLoadException* instr) OVERRIDE;
88ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  void VisitNewArray(HNewArray* instr) OVERRIDE;
892e76830f0b3f23825677436c0633714402715099Calin Juravle  void VisitParameterValue(HParameterValue* instr) OVERRIDE;
90ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  void UpdateFieldAccessTypeInfo(HInstruction* instr, const FieldInfo& info);
913398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier  void SetClassAsTypeInfo(HInstruction* instr, ObjPtr<mirror::Class> klass, bool is_exact)
92bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      REQUIRES_SHARED(Locks::mutator_lock_);
93ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  void VisitInstanceFieldGet(HInstanceFieldGet* instr) OVERRIDE;
94ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  void VisitStaticFieldGet(HStaticFieldGet* instr) OVERRIDE;
95e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  void VisitUnresolvedInstanceFieldGet(HUnresolvedInstanceFieldGet* instr) OVERRIDE;
96e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  void VisitUnresolvedStaticFieldGet(HUnresolvedStaticFieldGet* instr) OVERRIDE;
97ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  void VisitInvoke(HInvoke* instr) OVERRIDE;
9872a5eb5d6784b318750c36e0da25c7338557ce44Guillaume "Vermeille" Sanchez  void VisitArrayGet(HArrayGet* instr) OVERRIDE;
99a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  void VisitCheckCast(HCheckCast* instr) OVERRIDE;
100f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  void VisitBoundType(HBoundType* instr) OVERRIDE;
1012e76830f0b3f23825677436c0633714402715099Calin Juravle  void VisitNullCheck(HNullCheck* instr) OVERRIDE;
102ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  void UpdateReferenceTypeInfo(HInstruction* instr,
103a5b09a67034e57a6e10231dd4bd92f4cb50b824cAndreas Gampe                               dex::TypeIndex type_idx,
104ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez                               const DexFile& dex_file,
105ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez                               bool is_exact);
106ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez
107ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez private:
1088d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko  Handle<mirror::ClassLoader> class_loader_;
109456307a47336e3d6576ed6d8563b67573a4238d3Vladimir Marko  Handle<mirror::DexCache> hint_dex_cache_;
1107d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  HandleCache* handle_cache_;
1112aaa4b5532d30c4e65d8892b556400bb61f9dc8cVladimir Marko  ArenaVector<HInstruction*>* worklist_;
112d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray  const bool is_first_run_;
113ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez};
114ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez
1152e76830f0b3f23825677436c0633714402715099Calin JuravleReferenceTypePropagation::ReferenceTypePropagation(HGraph* graph,
1168d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko                                                   Handle<mirror::ClassLoader> class_loader,
117456307a47336e3d6576ed6d8563b67573a4238d3Vladimir Marko                                                   Handle<mirror::DexCache> hint_dex_cache,
118e8a3c576301fd531d5f73a65fc8b84a63619d580Mathieu Chartier                                                   VariableSizedHandleScope* handles,
119d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray                                                   bool is_first_run,
1202e76830f0b3f23825677436c0633714402715099Calin Juravle                                                   const char* name)
1212e76830f0b3f23825677436c0633714402715099Calin Juravle    : HOptimization(graph, name),
1228d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko      class_loader_(class_loader),
123456307a47336e3d6576ed6d8563b67573a4238d3Vladimir Marko      hint_dex_cache_(hint_dex_cache),
1247d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko      handle_cache_(handles),
125d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray      worklist_(graph->GetArena()->Adapter(kArenaAllocReferenceTypePropagation)),
126d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray      is_first_run_(is_first_run) {
1272e76830f0b3f23825677436c0633714402715099Calin Juravle}
1282e76830f0b3f23825677436c0633714402715099Calin Juravle
129cdfed3dc422d0e1a9a0a948863308e58c39d01baCalin Juravlevoid ReferenceTypePropagation::ValidateTypes() {
130cdfed3dc422d0e1a9a0a948863308e58c39d01baCalin Juravle  // TODO: move this to the graph checker.
1312e76830f0b3f23825677436c0633714402715099Calin Juravle  if (kIsDebugBuild) {
1322e76830f0b3f23825677436c0633714402715099Calin Juravle    ScopedObjectAccess soa(Thread::Current());
1332c45bc9137c29f886e69923535aff31a74d90829Vladimir Marko    for (HBasicBlock* block : graph_->GetReversePostOrder()) {
1342e76830f0b3f23825677436c0633714402715099Calin Juravle      for (HInstructionIterator iti(block->GetInstructions()); !iti.Done(); iti.Advance()) {
1352e76830f0b3f23825677436c0633714402715099Calin Juravle        HInstruction* instr = iti.Current();
1362e76830f0b3f23825677436c0633714402715099Calin Juravle        if (instr->GetType() == Primitive::kPrimNot) {
1372e76830f0b3f23825677436c0633714402715099Calin Juravle          DCHECK(instr->GetReferenceTypeInfo().IsValid())
1382e76830f0b3f23825677436c0633714402715099Calin Juravle              << "Invalid RTI for instruction: " << instr->DebugName();
1392e76830f0b3f23825677436c0633714402715099Calin Juravle          if (instr->IsBoundType()) {
1402e76830f0b3f23825677436c0633714402715099Calin Juravle            DCHECK(instr->AsBoundType()->GetUpperBound().IsValid());
1412e76830f0b3f23825677436c0633714402715099Calin Juravle          } else if (instr->IsLoadClass()) {
14298893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle            HLoadClass* cls = instr->AsLoadClass();
14398893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle            DCHECK(cls->GetReferenceTypeInfo().IsExact());
14498893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle            DCHECK(!cls->GetLoadedClassRTI().IsValid() || cls->GetLoadedClassRTI().IsExact());
1452e76830f0b3f23825677436c0633714402715099Calin Juravle          } else if (instr->IsNullCheck()) {
1462e76830f0b3f23825677436c0633714402715099Calin Juravle            DCHECK(instr->GetReferenceTypeInfo().IsEqual(instr->InputAt(0)->GetReferenceTypeInfo()))
1472e76830f0b3f23825677436c0633714402715099Calin Juravle                << "NullCheck " << instr->GetReferenceTypeInfo()
1482e76830f0b3f23825677436c0633714402715099Calin Juravle                << "Input(0) " << instr->InputAt(0)->GetReferenceTypeInfo();
1492e76830f0b3f23825677436c0633714402715099Calin Juravle          }
1502e76830f0b3f23825677436c0633714402715099Calin Juravle        }
1512e76830f0b3f23825677436c0633714402715099Calin Juravle      }
1522e76830f0b3f23825677436c0633714402715099Calin Juravle    }
1532e76830f0b3f23825677436c0633714402715099Calin Juravle  }
15410e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle}
15510e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle
156be10e8e99a78caae01fb65769218800d465144aeVladimir Markovoid ReferenceTypePropagation::Visit(HInstruction* instruction) {
1578d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko  RTPVisitor visitor(graph_,
1588d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko                     class_loader_,
1598d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko                     hint_dex_cache_,
1608d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko                     &handle_cache_,
1618d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko                     &worklist_,
1628d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko                     is_first_run_);
163be10e8e99a78caae01fb65769218800d465144aeVladimir Marko  instruction->Accept(&visitor);
164be10e8e99a78caae01fb65769218800d465144aeVladimir Marko}
165be10e8e99a78caae01fb65769218800d465144aeVladimir Marko
166a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle// Check if we should create a bound type for the given object at the specified
167a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle// position. Because of inlining and the fact we run RTP more than once and we
168a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle// might have a HBoundType already. If we do, we should not create a new one.
169a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle// In this case we also assert that there are no other uses of the object (except
170a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle// the bound type) dominated by the specified dominator_instr or dominator_block.
171a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravlestatic bool ShouldCreateBoundType(HInstruction* position,
172a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle                                  HInstruction* obj,
173a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle                                  ReferenceTypeInfo upper_bound,
174a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle                                  HInstruction* dominator_instr,
175a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle                                  HBasicBlock* dominator_block)
176bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
177a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  // If the position where we should insert the bound type is not already a
178a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  // a bound type then we need to create one.
179a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  if (position == nullptr || !position->IsBoundType()) {
180a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    return true;
181a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  }
182a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle
183a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  HBoundType* existing_bound_type = position->AsBoundType();
184a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  if (existing_bound_type->GetUpperBound().IsSupertypeOf(upper_bound)) {
185a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    if (kIsDebugBuild) {
186a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle      // Check that the existing HBoundType dominates all the uses.
18746817b876ab00d6b78905b80ed12b4344c522b6cVladimir Marko      for (const HUseListNode<HInstruction*>& use : obj->GetUses()) {
18846817b876ab00d6b78905b80ed12b4344c522b6cVladimir Marko        HInstruction* user = use.GetUser();
189a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        if (dominator_instr != nullptr) {
190a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle          DCHECK(!dominator_instr->StrictlyDominates(user)
191a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle              || user == existing_bound_type
192a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle              || existing_bound_type->StrictlyDominates(user));
193a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        } else if (dominator_block != nullptr) {
194a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle          DCHECK(!dominator_block->Dominates(user->GetBlock())
195a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle              || user == existing_bound_type
196a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle              || existing_bound_type->StrictlyDominates(user));
197a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        }
198a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle      }
199a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    }
200a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  } else {
201a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    // TODO: if the current bound type is a refinement we could update the
202a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    // existing_bound_type with the a new upper limit. However, we also need to
203a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    // update its users and have access to the work list.
204a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  }
205a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  return false;
206a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle}
207a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle
208c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray// Helper method to bound the type of `receiver` for all instructions dominated
209c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray// by `start_block`, or `start_instruction` if `start_block` is null. The new
210c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray// bound type will have its upper bound be `class_rti`.
211c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffraystatic void BoundTypeIn(HInstruction* receiver,
212c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray                        HBasicBlock* start_block,
213c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray                        HInstruction* start_instruction,
214c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray                        const ReferenceTypeInfo& class_rti) {
215c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  // We only need to bound the type if we have uses in the relevant block.
216c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  // So start with null and create the HBoundType lazily, only if it's needed.
217c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  HBoundType* bound_type = nullptr;
218c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  DCHECK(!receiver->IsLoadClass()) << "We should not replace HLoadClass instructions";
219c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  const HUseList<HInstruction*>& uses = receiver->GetUses();
220c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  for (auto it = uses.begin(), end = uses.end(); it != end; /* ++it below */) {
221c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    HInstruction* user = it->GetUser();
222c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    size_t index = it->GetIndex();
223c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    // Increment `it` now because `*it` may disappear thanks to user->ReplaceInput().
224c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    ++it;
225c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    bool dominates = (start_instruction != nullptr)
226c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray        ? start_instruction->StrictlyDominates(user)
227c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray        : start_block->Dominates(user->GetBlock());
228c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    if (!dominates) {
229c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray      continue;
230c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    }
231c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    if (bound_type == nullptr) {
232c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray      ScopedObjectAccess soa(Thread::Current());
233c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray      HInstruction* insert_point = (start_instruction != nullptr)
234c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray          ? start_instruction->GetNext()
235c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray          : start_block->GetFirstInstruction();
236c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray      if (ShouldCreateBoundType(
237c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray            insert_point, receiver, class_rti, start_instruction, start_block)) {
238c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray        bound_type = new (receiver->GetBlock()->GetGraph()->GetArena()) HBoundType(receiver);
239c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray        bound_type->SetUpperBound(class_rti, /* bound_can_be_null */ false);
240c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray        start_block->InsertInstructionBefore(bound_type, insert_point);
241c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray        // To comply with the RTP algorithm, don't type the bound type just yet, it will
242c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray        // be handled in RTPVisitor::VisitBoundType.
243c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray      } else {
244c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray        // We already have a bound type on the position we would need to insert
245c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray        // the new one. The existing bound type should dominate all the users
246c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray        // (dchecked) so there's no need to continue.
247c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray        break;
248c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray      }
249c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    }
250c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    user->ReplaceInput(bound_type, index);
251c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  }
252c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  // If the receiver is a null check, also bound the type of the actual
253c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  // receiver.
254c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  if (receiver->IsNullCheck()) {
255c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    BoundTypeIn(receiver->InputAt(0), start_block, start_instruction, class_rti);
256c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  }
257c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray}
258c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray
259c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray// Recognize the patterns:
260c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray// if (obj.shadow$_klass_ == Foo.class) ...
261c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray// deoptimize if (obj.shadow$_klass_ == Foo.class)
262c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffraystatic void BoundTypeForClassCheck(HInstruction* check) {
263c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  if (!check->IsIf() && !check->IsDeoptimize()) {
264c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    return;
265c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  }
266c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  HInstruction* compare = check->InputAt(0);
267c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  if (!compare->IsEqual() && !compare->IsNotEqual()) {
268c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    return;
269c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  }
270c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  HInstruction* input_one = compare->InputAt(0);
271c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  HInstruction* input_two = compare->InputAt(1);
272c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  HLoadClass* load_class = input_one->IsLoadClass()
273c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray      ? input_one->AsLoadClass()
274c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray      : input_two->AsLoadClass();
275c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  if (load_class == nullptr) {
276c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    return;
277c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  }
278c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray
279c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  ReferenceTypeInfo class_rti = load_class->GetLoadedClassRTI();
280c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  if (!class_rti.IsValid()) {
281c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    // We have loaded an unresolved class. Don't bother bounding the type.
282c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    return;
283c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  }
284c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray
285c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  HInstanceFieldGet* field_get = (load_class == input_one)
286c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray      ? input_two->AsInstanceFieldGet()
287c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray      : input_one->AsInstanceFieldGet();
288c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  if (field_get == nullptr) {
289c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    return;
290c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  }
291c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  HInstruction* receiver = field_get->InputAt(0);
292c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  ReferenceTypeInfo receiver_type = receiver->GetReferenceTypeInfo();
293c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  if (receiver_type.IsExact()) {
294c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    // If we already know the receiver type, don't bother updating its users.
295c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    return;
296c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  }
297c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray
298c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  {
299c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    ScopedObjectAccess soa(Thread::Current());
300c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
301c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    ArtField* field = class_linker->GetClassRoot(ClassLinker::kJavaLangObject)->GetInstanceField(0);
302c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_");
303c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    if (field_get->GetFieldInfo().GetField() != field) {
304c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray      return;
305c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    }
306c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  }
307c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray
308c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  if (check->IsIf()) {
309cd9f85746d56db194252f9319ba3a018a362014cNicolas Geoffray    HBasicBlock* trueBlock = compare->IsEqual()
310c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray        ? check->AsIf()->IfTrueSuccessor()
311c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray        : check->AsIf()->IfFalseSuccessor();
312c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    BoundTypeIn(receiver, trueBlock, /* start_instruction */ nullptr, class_rti);
313c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  } else {
314c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    DCHECK(check->IsDeoptimize());
3156f8e2c9913b24f746a154dda700f609cee3095f9Nicolas Geoffray    if (compare->IsEqual() && check->AsDeoptimize()->GuardsAnInput()) {
3166f8e2c9913b24f746a154dda700f609cee3095f9Nicolas Geoffray      check->SetReferenceTypeInfo(class_rti);
317c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    }
318c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  }
319c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray}
320c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray
321c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffrayvoid ReferenceTypePropagation::Run() {
322c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  worklist_.reserve(kDefaultWorklistSize);
323c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray
324c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  // To properly propagate type info we need to visit in the dominator-based order.
325c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  // Reverse post order guarantees a node's dominators are visited first.
326c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  // We take advantage of this order in `VisitBasicBlock`.
327c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  for (HBasicBlock* block : graph_->GetReversePostOrder()) {
328c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    VisitBasicBlock(block);
329c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  }
330c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray
331c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  ProcessWorklist();
332c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  ValidateTypes();
333c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray}
334c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray
335c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffrayvoid ReferenceTypePropagation::VisitBasicBlock(HBasicBlock* block) {
3368d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko  RTPVisitor visitor(graph_,
3378d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko                     class_loader_,
3388d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko                     hint_dex_cache_,
3398d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko                     &handle_cache_,
3408d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko                     &worklist_,
3418d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko                     is_first_run_);
342c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  // Handle Phis first as there might be instructions in the same block who depend on them.
343c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
344c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    VisitPhi(it.Current()->AsPhi());
345c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  }
346c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray
347c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  // Handle instructions. Since RTP may add HBoundType instructions just after the
348c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  // last visited instruction, use `HInstructionIteratorHandleChanges` iterator.
349c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  for (HInstructionIteratorHandleChanges it(block->GetInstructions()); !it.Done(); it.Advance()) {
350c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    HInstruction* instr = it.Current();
351c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    instr->Accept(&visitor);
352c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  }
353c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray
354c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  // Add extra nodes to bound types.
355c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  BoundTypeForIfNotNull(block);
356c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  BoundTypeForIfInstanceOf(block);
357c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  BoundTypeForClassCheck(block->GetLastInstruction());
358c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray}
359c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray
36061d544bfb812d79f5c9ddad171198836cea719dbCalin Juravlevoid ReferenceTypePropagation::BoundTypeForIfNotNull(HBasicBlock* block) {
361b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  HIf* ifInstruction = block->GetLastInstruction()->AsIf();
362b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  if (ifInstruction == nullptr) {
36361d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle    return;
36461d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  }
365b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  HInstruction* ifInput = ifInstruction->InputAt(0);
36661d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  if (!ifInput->IsNotEqual() && !ifInput->IsEqual()) {
36761d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle    return;
36861d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  }
36961d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  HInstruction* input0 = ifInput->InputAt(0);
37061d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  HInstruction* input1 = ifInput->InputAt(1);
371edad8add1f1216850cb3f179ba6f57b0d885b016Calin Juravle  HInstruction* obj = nullptr;
37261d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle
373edad8add1f1216850cb3f179ba6f57b0d885b016Calin Juravle  if (input1->IsNullConstant()) {
37461d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle    obj = input0;
375edad8add1f1216850cb3f179ba6f57b0d885b016Calin Juravle  } else if (input0->IsNullConstant()) {
37661d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle    obj = input1;
37761d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  } else {
37861d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle    return;
37961d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  }
38061d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle
3817d5ea03b2a7d886325b3ad97942038c2336aa855Nicolas Geoffray  if (!obj->CanBeNull() || obj->IsNullConstant()) {
3827d5ea03b2a7d886325b3ad97942038c2336aa855Nicolas Geoffray    // Null check is dead code and will be removed by DCE.
3837d5ea03b2a7d886325b3ad97942038c2336aa855Nicolas Geoffray    return;
3847d5ea03b2a7d886325b3ad97942038c2336aa855Nicolas Geoffray  }
3857d5ea03b2a7d886325b3ad97942038c2336aa855Nicolas Geoffray  DCHECK(!obj->IsLoadClass()) << "We should not replace HLoadClass instructions";
3867d5ea03b2a7d886325b3ad97942038c2336aa855Nicolas Geoffray
387b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  // We only need to bound the type if we have uses in the relevant block.
388b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  // So start with null and create the HBoundType lazily, only if it's needed.
38961d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  HBasicBlock* notNullBlock = ifInput->IsNotEqual()
390b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle      ? ifInstruction->IfTrueSuccessor()
391b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle      : ifInstruction->IfFalseSuccessor();
392b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle
393c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  ReferenceTypeInfo object_rti = ReferenceTypeInfo::Create(
394c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray      handle_cache_.GetObjectClassHandle(), /* is_exact */ false);
395c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray
396c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  BoundTypeIn(obj, notNullBlock, /* start_instruction */ nullptr, object_rti);
39761d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle}
39861d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle
399d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil// Returns true if one of the patterns below has been recognized. If so, the
400d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil// InstanceOf instruction together with the true branch of `ifInstruction` will
401d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil// be returned using the out parameters.
402d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil// Recognized patterns:
403d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil//   (1) patterns equivalent to `if (obj instanceof X)`
404d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil//     (a) InstanceOf -> Equal to 1 -> If
405d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil//     (b) InstanceOf -> NotEqual to 0 -> If
406d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil//     (c) InstanceOf -> If
407d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil//   (2) patterns equivalent to `if (!(obj instanceof X))`
408d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil//     (a) InstanceOf -> Equal to 0 -> If
409d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil//     (b) InstanceOf -> NotEqual to 1 -> If
410d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil//     (c) InstanceOf -> BooleanNot -> If
411d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdilstatic bool MatchIfInstanceOf(HIf* ifInstruction,
412d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil                              /* out */ HInstanceOf** instanceOf,
413d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil                              /* out */ HBasicBlock** trueBranch) {
414d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  HInstruction* input = ifInstruction->InputAt(0);
415d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil
416d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  if (input->IsEqual()) {
417d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    HInstruction* rhs = input->AsEqual()->GetConstantRight();
418d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    if (rhs != nullptr) {
419d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      HInstruction* lhs = input->AsEqual()->GetLeastConstantLeft();
420d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      if (lhs->IsInstanceOf() && rhs->IsIntConstant()) {
4211a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain        if (rhs->AsIntConstant()->IsTrue()) {
422d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil          // Case (1a)
423d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil          *trueBranch = ifInstruction->IfTrueSuccessor();
424d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil        } else {
425d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil          // Case (2a)
4261a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain          DCHECK(rhs->AsIntConstant()->IsFalse()) << rhs->AsIntConstant()->GetValue();
427d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil          *trueBranch = ifInstruction->IfFalseSuccessor();
428d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil        }
429d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil        *instanceOf = lhs->AsInstanceOf();
430d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil        return true;
431d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      }
432d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    }
433d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  } else if (input->IsNotEqual()) {
434d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    HInstruction* rhs = input->AsNotEqual()->GetConstantRight();
435d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    if (rhs != nullptr) {
436d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      HInstruction* lhs = input->AsNotEqual()->GetLeastConstantLeft();
437d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      if (lhs->IsInstanceOf() && rhs->IsIntConstant()) {
4381a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain        if (rhs->AsIntConstant()->IsFalse()) {
439d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil          // Case (1b)
440d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil          *trueBranch = ifInstruction->IfTrueSuccessor();
441d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil        } else {
442d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil          // Case (2b)
4431a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain          DCHECK(rhs->AsIntConstant()->IsTrue()) << rhs->AsIntConstant()->GetValue();
444d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil          *trueBranch = ifInstruction->IfFalseSuccessor();
445d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil        }
446d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil        *instanceOf = lhs->AsInstanceOf();
447d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil        return true;
448d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      }
449d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    }
450d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  } else if (input->IsInstanceOf()) {
451d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    // Case (1c)
452d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    *instanceOf = input->AsInstanceOf();
453d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    *trueBranch = ifInstruction->IfTrueSuccessor();
454d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    return true;
455d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  } else if (input->IsBooleanNot()) {
456d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    HInstruction* not_input = input->InputAt(0);
457d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    if (not_input->IsInstanceOf()) {
458d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      // Case (2c)
459d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      *instanceOf = not_input->AsInstanceOf();
460d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      *trueBranch = ifInstruction->IfFalseSuccessor();
461d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      return true;
462d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    }
463d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  }
464d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil
465d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  return false;
466d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil}
467d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil
468b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle// Detects if `block` is the True block for the pattern
469b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle// `if (x instanceof ClassX) { }`
470b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle// If that's the case insert an HBoundType instruction to bound the type of `x`
471b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle// to `ClassX` in the scope of the dominated blocks.
472b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlevoid ReferenceTypePropagation::BoundTypeForIfInstanceOf(HBasicBlock* block) {
473b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  HIf* ifInstruction = block->GetLastInstruction()->AsIf();
474b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  if (ifInstruction == nullptr) {
475b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    return;
476b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  }
477b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle
478d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  // Try to recognize common `if (instanceof)` and `if (!instanceof)` patterns.
479d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  HInstanceOf* instanceOf = nullptr;
480d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  HBasicBlock* instanceOfTrueBlock = nullptr;
481d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  if (!MatchIfInstanceOf(ifInstruction, &instanceOf, &instanceOfTrueBlock)) {
482b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    return;
483acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle  }
484acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle
48598893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle  HLoadClass* load_class = instanceOf->InputAt(1)->AsLoadClass();
48698893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle  ReferenceTypeInfo class_rti = load_class->GetLoadedClassRTI();
487c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  if (!class_rti.IsValid()) {
488c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    // He have loaded an unresolved class. Don't bother bounding the type.
489c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    return;
49098893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle  }
491acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle
492b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  HInstruction* obj = instanceOf->InputAt(0);
493f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray  if (obj->GetReferenceTypeInfo().IsExact() && !obj->IsPhi()) {
494f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray    // This method is being called while doing a fixed-point calculation
495f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray    // over phis. Non-phis instruction whose type is already known do
496f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray    // not need to be bound to another type.
497f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray    // Not that this also prevents replacing `HLoadClass` with a `HBoundType`.
498f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray    // `HCheckCast` and `HInstanceOf` expect a `HLoadClass` as a second
499f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray    // input.
500f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray    return;
501f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray  }
502c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray
503c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  {
504c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    ScopedObjectAccess soa(Thread::Current());
505c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    if (!class_rti.GetTypeHandle()->CannotBeAssignedFromOtherTypes()) {
506c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray      class_rti = ReferenceTypeInfo::Create(class_rti.GetTypeHandle(), /* is_exact */ false);
507acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle    }
508acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle  }
509c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  BoundTypeIn(obj, instanceOfTrueBlock, /* start_instruction */ nullptr, class_rti);
510acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle}
511acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle
5127d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::SetClassAsTypeInfo(HInstruction* instr,
5133398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier                                                              ObjPtr<mirror::Class> klass,
5147d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko                                                              bool is_exact) {
5152e76830f0b3f23825677436c0633714402715099Calin Juravle  if (instr->IsInvokeStaticOrDirect() && instr->AsInvokeStaticOrDirect()->IsStringInit()) {
5162e76830f0b3f23825677436c0633714402715099Calin Juravle    // Calls to String.<init> are replaced with a StringFactory.
5172e76830f0b3f23825677436c0633714402715099Calin Juravle    if (kIsDebugBuild) {
5185d37c152f21a0807459c6f53bc25e2d84f56d259Nicolas Geoffray      HInvokeStaticOrDirect* invoke = instr->AsInvokeStaticOrDirect();
5192e76830f0b3f23825677436c0633714402715099Calin Juravle      ClassLinker* cl = Runtime::Current()->GetClassLinker();
52062977ff198deb673a6990202a2fb8b993217c57cVladimir Marko      Thread* self = Thread::Current();
52162977ff198deb673a6990202a2fb8b993217c57cVladimir Marko      StackHandleScope<2> hs(self);
5225d37c152f21a0807459c6f53bc25e2d84f56d259Nicolas Geoffray      const DexFile& dex_file = *invoke->GetTargetMethod().dex_file;
523c89715ccaf4c8a8ce298ce2c0c1da479de4c63e7Nicolas Geoffray      Handle<mirror::DexCache> dex_cache(
5245d37c152f21a0807459c6f53bc25e2d84f56d259Nicolas Geoffray          hs.NewHandle(FindDexCacheWithHint(self, dex_file, hint_dex_cache_)));
525c89715ccaf4c8a8ce298ce2c0c1da479de4c63e7Nicolas Geoffray      // Use a null loader. We should probably use the compiling method's class loader,
526c89715ccaf4c8a8ce298ce2c0c1da479de4c63e7Nicolas Geoffray      // but then we would need to pass it to RTPVisitor just for this debug check. Since
527c89715ccaf4c8a8ce298ce2c0c1da479de4c63e7Nicolas Geoffray      // the method is from the String class, the null loader is good enough.
528c89715ccaf4c8a8ce298ce2c0c1da479de4c63e7Nicolas Geoffray      Handle<mirror::ClassLoader> loader;
52942ef8ab151a3d0cbb42cb43f6841c3708d65fca3Andreas Gampe      ArtMethod* method = cl->ResolveMethod<ClassLinker::kNoICCECheckForCache>(
5305d37c152f21a0807459c6f53bc25e2d84f56d259Nicolas Geoffray          dex_file, invoke->GetDexMethodIndex(), dex_cache, loader, nullptr, kDirect);
5312e76830f0b3f23825677436c0633714402715099Calin Juravle      DCHECK(method != nullptr);
5322e76830f0b3f23825677436c0633714402715099Calin Juravle      mirror::Class* declaring_class = method->GetDeclaringClass();
5332e76830f0b3f23825677436c0633714402715099Calin Juravle      DCHECK(declaring_class != nullptr);
5342e76830f0b3f23825677436c0633714402715099Calin Juravle      DCHECK(declaring_class->IsStringClass())
535709b070044354d9f47641f273edacaeeb0240ab7David Sehr          << "Expected String class: " << declaring_class->PrettyDescriptor();
5362e76830f0b3f23825677436c0633714402715099Calin Juravle      DCHECK(method->IsConstructor())
537709b070044354d9f47641f273edacaeeb0240ab7David Sehr          << "Expected String.<init>: " << method->PrettyMethod();
5382e76830f0b3f23825677436c0633714402715099Calin Juravle    }
5392e76830f0b3f23825677436c0633714402715099Calin Juravle    instr->SetReferenceTypeInfo(
5407d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko        ReferenceTypeInfo::Create(handle_cache_->GetStringClassHandle(), /* is_exact */ true));
5411cc62e4ea24828fdb3f3da0b8603f0b107d09a04Mathieu Chartier  } else if (IsAdmissible(klass.Ptr())) {
542f417ff44d1eb111854d7a213f106912b3dd9e3d4Aart Bik    ReferenceTypeInfo::TypeHandle handle = handle_cache_->NewHandle(klass);
543f417ff44d1eb111854d7a213f106912b3dd9e3d4Aart Bik    is_exact = is_exact || handle->CannotBeAssignedFromOtherTypes();
544f417ff44d1eb111854d7a213f106912b3dd9e3d4Aart Bik    instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(handle, is_exact));
5452e76830f0b3f23825677436c0633714402715099Calin Juravle  } else {
54618401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray    instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
547104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez  }
548104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez}
549104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez
550c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffrayvoid ReferenceTypePropagation::RTPVisitor::VisitDeoptimize(HDeoptimize* instr) {
551c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  BoundTypeForClassCheck(instr);
552c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray}
553c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray
5547d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::UpdateReferenceTypeInfo(HInstruction* instr,
555a5b09a67034e57a6e10231dd4bd92f4cb50b824cAndreas Gampe                                                                   dex::TypeIndex type_idx,
5567d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko                                                                   const DexFile& dex_file,
5577d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko                                                                   bool is_exact) {
55881d804a51d4fc415e1544a5a09505db049f4eda6Guillaume "Vermeille" Sanchez  DCHECK_EQ(instr->GetType(), Primitive::kPrimNot);
55981d804a51d4fc415e1544a5a09505db049f4eda6Guillaume "Vermeille" Sanchez
560acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle  ScopedObjectAccess soa(Thread::Current());
561cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko  ObjPtr<mirror::DexCache> dex_cache = FindDexCacheWithHint(soa.Self(), dex_file, hint_dex_cache_);
5628d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko  ObjPtr<mirror::Class> klass =
5638d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko      ClassLinker::LookupResolvedType(type_idx, dex_cache, class_loader_.Get());
5648d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko  SetClassAsTypeInfo(instr, klass, is_exact);
565acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle}
566acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle
5677d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitNewInstance(HNewInstance* instr) {
568e761bccf9f0d884cc4d4ec104568cef968296492Nicolas Geoffray  ScopedObjectAccess soa(Thread::Current());
569e761bccf9f0d884cc4d4ec104568cef968296492Nicolas Geoffray  SetClassAsTypeInfo(instr, instr->GetLoadClass()->GetClass().Get(), /* is_exact */ true);
57081d804a51d4fc415e1544a5a09505db049f4eda6Guillaume "Vermeille" Sanchez}
57181d804a51d4fc415e1544a5a09505db049f4eda6Guillaume "Vermeille" Sanchez
5727d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitNewArray(HNewArray* instr) {
573e761bccf9f0d884cc4d4ec104568cef968296492Nicolas Geoffray  ScopedObjectAccess soa(Thread::Current());
574e761bccf9f0d884cc4d4ec104568cef968296492Nicolas Geoffray  SetClassAsTypeInfo(instr, instr->GetLoadClass()->GetClass().Get(), /* is_exact */ true);
57581d804a51d4fc415e1544a5a09505db049f4eda6Guillaume "Vermeille" Sanchez}
57681d804a51d4fc415e1544a5a09505db049f4eda6Guillaume "Vermeille" Sanchez
5777d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitParameterValue(HParameterValue* instr) {
578e418dda75998e0186f7580c2c54705767c3c8f1fNicolas Geoffray  // We check if the existing type is valid: the inliner may have set it.
579e418dda75998e0186f7580c2c54705767c3c8f1fNicolas Geoffray  if (instr->GetType() == Primitive::kPrimNot && !instr->GetReferenceTypeInfo().IsValid()) {
5808d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko    UpdateReferenceTypeInfo(instr,
5818d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko                            instr->GetTypeIndex(),
5828d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko                            instr->GetDexFile(),
5838d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko                            /* is_exact */ false);
5842e76830f0b3f23825677436c0633714402715099Calin Juravle  }
5852e76830f0b3f23825677436c0633714402715099Calin Juravle}
5862e76830f0b3f23825677436c0633714402715099Calin Juravle
5877d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::UpdateFieldAccessTypeInfo(HInstruction* instr,
5887d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko                                                                     const FieldInfo& info) {
589d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  if (instr->GetType() != Primitive::kPrimNot) {
590104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez    return;
591104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez  }
592104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez
59362977ff198deb673a6990202a2fb8b993217c57cVladimir Marko  ScopedObjectAccess soa(Thread::Current());
5943398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier  ObjPtr<mirror::Class> klass;
595d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil
596c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  // The field is unknown only during tests.
597c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray  if (info.GetField() != nullptr) {
598c52b26d4fb5b1ca91f34ce4b535b764853e538f6Nicolas Geoffray    klass = info.GetField()->GetType<false>();
599d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  }
600d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil
6012e76830f0b3f23825677436c0633714402715099Calin Juravle  SetClassAsTypeInfo(instr, klass, /* is_exact */ false);
602104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez}
603104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez
6047d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitInstanceFieldGet(HInstanceFieldGet* instr) {
605104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez  UpdateFieldAccessTypeInfo(instr, instr->GetFieldInfo());
606104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez}
607104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez
6087d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitStaticFieldGet(HStaticFieldGet* instr) {
609104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez  UpdateFieldAccessTypeInfo(instr, instr->GetFieldInfo());
610104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez}
611104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez
6127d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitUnresolvedInstanceFieldGet(
6137d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    HUnresolvedInstanceFieldGet* instr) {
614e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  // TODO: Use descriptor to get the actual type.
615e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  if (instr->GetFieldType() == Primitive::kPrimNot) {
61618401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray    instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
617e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
618e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle}
619e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
6207d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitUnresolvedStaticFieldGet(
6217d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    HUnresolvedStaticFieldGet* instr) {
622e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  // TODO: Use descriptor to get the actual type.
623e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  if (instr->GetFieldType() == Primitive::kPrimNot) {
62418401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray    instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
625e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
626e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle}
627e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
6287d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitLoadClass(HLoadClass* instr) {
629acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle  ScopedObjectAccess soa(Thread::Current());
6305247c08fb186a5a2ac02226827cf6b994f41a681Nicolas Geoffray  Handle<mirror::Class> resolved_class = instr->GetClass();
6315247c08fb186a5a2ac02226827cf6b994f41a681Nicolas Geoffray  if (IsAdmissible(resolved_class.Get())) {
63298893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle    instr->SetLoadedClassRTI(ReferenceTypeInfo::Create(
6335247c08fb186a5a2ac02226827cf6b994f41a681Nicolas Geoffray        resolved_class, /* is_exact */ true));
63498893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle  }
6357d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  instr->SetReferenceTypeInfo(
6367d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko      ReferenceTypeInfo::Create(handle_cache_->GetClassClassHandle(), /* is_exact */ true));
6372e76830f0b3f23825677436c0633714402715099Calin Juravle}
6382e76830f0b3f23825677436c0633714402715099Calin Juravle
6397d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitClinitCheck(HClinitCheck* instr) {
6402e76830f0b3f23825677436c0633714402715099Calin Juravle  instr->SetReferenceTypeInfo(instr->InputAt(0)->GetReferenceTypeInfo());
6412e76830f0b3f23825677436c0633714402715099Calin Juravle}
6422e76830f0b3f23825677436c0633714402715099Calin Juravle
6437d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitLoadString(HLoadString* instr) {
6447d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  instr->SetReferenceTypeInfo(
6457d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko      ReferenceTypeInfo::Create(handle_cache_->GetStringClassHandle(), /* is_exact */ true));
6462e76830f0b3f23825677436c0633714402715099Calin Juravle}
6472e76830f0b3f23825677436c0633714402715099Calin Juravle
6487d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitLoadException(HLoadException* instr) {
649bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil  DCHECK(instr->GetBlock()->IsCatchBlock());
650bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil  TryCatchInformation* catch_info = instr->GetBlock()->GetTryCatchInformation();
651bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil
652bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil  if (catch_info->IsCatchAllTypeIndex()) {
6537d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    instr->SetReferenceTypeInfo(
6547d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko        ReferenceTypeInfo::Create(handle_cache_->GetThrowableClassHandle(), /* is_exact */ false));
655bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil  } else {
656bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil    UpdateReferenceTypeInfo(instr,
657bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil                            catch_info->GetCatchTypeIndex(),
658bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil                            catch_info->GetCatchDexFile(),
659bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil                            /* is_exact */ false);
660bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil  }
661bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil}
662bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil
6637d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitNullCheck(HNullCheck* instr) {
6642e76830f0b3f23825677436c0633714402715099Calin Juravle  ReferenceTypeInfo parent_rti = instr->InputAt(0)->GetReferenceTypeInfo();
665fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil  if (parent_rti.IsValid()) {
666fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil    instr->SetReferenceTypeInfo(parent_rti);
667fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil  }
6682e76830f0b3f23825677436c0633714402715099Calin Juravle}
6692e76830f0b3f23825677436c0633714402715099Calin Juravle
6707d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitBoundType(HBoundType* instr) {
671f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  ReferenceTypeInfo class_rti = instr->GetUpperBound();
672f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  if (class_rti.IsValid()) {
673456307a47336e3d6576ed6d8563b67573a4238d3Vladimir Marko    ScopedObjectAccess soa(Thread::Current());
674f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // Narrow the type as much as possible.
675f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    HInstruction* obj = instr->InputAt(0);
676f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    ReferenceTypeInfo obj_rti = obj->GetReferenceTypeInfo();
6778c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray    if (class_rti.IsExact()) {
6788c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray      instr->SetReferenceTypeInfo(class_rti);
679744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil    } else if (obj_rti.IsValid()) {
680744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil      if (class_rti.IsSupertypeOf(obj_rti)) {
681744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil        // Object type is more specific.
682744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil        instr->SetReferenceTypeInfo(obj_rti);
683744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil      } else {
6848c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray        // Upper bound is more specific, or unrelated to the object's type.
6858c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray        // Note that the object might then be exact, and we know the code dominated by this
6868c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray        // bound type is dead. To not confuse potential other optimizations, we mark
6878c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray        // the bound as non-exact.
688744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil        instr->SetReferenceTypeInfo(
689744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil            ReferenceTypeInfo::Create(class_rti.GetTypeHandle(), /* is_exact */ false));
690744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil      }
691f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    } else {
692744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil      // Object not typed yet. Leave BoundType untyped for now rather than
693744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil      // assign the type conservatively.
694f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    }
695f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    instr->SetCanBeNull(obj->CanBeNull() && instr->GetUpperCanBeNull());
696f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  } else {
697f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // The owner of the BoundType was already visited. If the class is unresolved,
698f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // the BoundType should have been removed from the data flow and this method
699f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // should remove it from the graph.
700f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    DCHECK(!instr->HasUses());
701f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    instr->GetBlock()->RemoveInstruction(instr);
702f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  }
703f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil}
704f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil
7057d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitCheckCast(HCheckCast* check_cast) {
70698893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle  HLoadClass* load_class = check_cast->InputAt(1)->AsLoadClass();
70798893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle  ReferenceTypeInfo class_rti = load_class->GetLoadedClassRTI();
708f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  HBoundType* bound_type = check_cast->GetNext()->AsBoundType();
709f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  if (bound_type == nullptr || bound_type->GetUpperBound().IsValid()) {
710f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // The next instruction is not an uninitialized BoundType. This must be
711f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // an RTP pass after SsaBuilder and we do not need to do anything.
712f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    return;
71398893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle  }
714f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  DCHECK_EQ(bound_type->InputAt(0), check_cast->InputAt(0));
715f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil
716f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  if (class_rti.IsValid()) {
717d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray    DCHECK(is_first_run_);
7188c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray    ScopedObjectAccess soa(Thread::Current());
719f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // This is the first run of RTP and class is resolved.
7208c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray    bool is_exact = class_rti.GetTypeHandle()->CannotBeAssignedFromOtherTypes();
7218c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray    bound_type->SetUpperBound(ReferenceTypeInfo::Create(class_rti.GetTypeHandle(), is_exact),
7228c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray                              /* CheckCast succeeds for nulls. */ true);
723f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  } else {
724f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // This is the first run of RTP and class is unresolved. Remove the binding.
725f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // The instruction itself is removed in VisitBoundType so as to not
726f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // invalidate HInstructionIterator.
727f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    bound_type->ReplaceWith(bound_type->InputAt(0));
728a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  }
729a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle}
730a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle
731b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlevoid ReferenceTypePropagation::VisitPhi(HPhi* phi) {
732d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  if (phi->IsDead() || phi->GetType() != Primitive::kPrimNot) {
733b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    return;
734acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle  }
735b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
736b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  if (phi->GetBlock()->IsLoopHeader()) {
737b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    // Set the initial type for the phi. Use the non back edge input for reaching
738b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    // a fixed point faster.
739fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil    HInstruction* first_input = phi->InputAt(0);
740fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil    ReferenceTypeInfo first_input_rti = first_input->GetReferenceTypeInfo();
741fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil    if (first_input_rti.IsValid() && !first_input->IsNullConstant()) {
742fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil      phi->SetCanBeNull(first_input->CanBeNull());
743fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil      phi->SetReferenceTypeInfo(first_input_rti);
744fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil    }
745b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    AddToWorklist(phi);
746b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  } else {
747b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    // Eagerly compute the type of the phi, for quicker convergence. Note
748b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    // that we don't need to add users to the worklist because we are
749b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    // doing a reverse post-order visit, therefore either the phi users are
750b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    // non-loop phi and will be visited later in the visit, or are loop-phis,
751b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    // and they are already in the work list.
752b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    UpdateNullability(phi);
753b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    UpdateReferenceTypeInfo(phi);
754b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  }
755b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle}
756b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
757b1498f67b444c897fa8f1530777ef118e05aa631Calin JuravleReferenceTypeInfo ReferenceTypePropagation::MergeTypes(const ReferenceTypeInfo& a,
758b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle                                                       const ReferenceTypeInfo& b) {
7592e76830f0b3f23825677436c0633714402715099Calin Juravle  if (!b.IsValid()) {
7602e76830f0b3f23825677436c0633714402715099Calin Juravle    return a;
7612e76830f0b3f23825677436c0633714402715099Calin Juravle  }
7622e76830f0b3f23825677436c0633714402715099Calin Juravle  if (!a.IsValid()) {
7632e76830f0b3f23825677436c0633714402715099Calin Juravle    return b;
7642e76830f0b3f23825677436c0633714402715099Calin Juravle  }
7652e76830f0b3f23825677436c0633714402715099Calin Juravle
766b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  bool is_exact = a.IsExact() && b.IsExact();
76752503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle  ReferenceTypeInfo::TypeHandle result_type_handle;
76852503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle  ReferenceTypeInfo::TypeHandle a_type_handle = a.GetTypeHandle();
76952503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle  ReferenceTypeInfo::TypeHandle b_type_handle = b.GetTypeHandle();
77052503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle  bool a_is_interface = a_type_handle->IsInterface();
77152503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle  bool b_is_interface = b_type_handle->IsInterface();
772b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
7732e76830f0b3f23825677436c0633714402715099Calin Juravle  if (a.GetTypeHandle().Get() == b.GetTypeHandle().Get()) {
77452503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    result_type_handle = a_type_handle;
7752e76830f0b3f23825677436c0633714402715099Calin Juravle  } else if (a.IsSupertypeOf(b)) {
77652503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    result_type_handle = a_type_handle;
7772e76830f0b3f23825677436c0633714402715099Calin Juravle    is_exact = false;
7782e76830f0b3f23825677436c0633714402715099Calin Juravle  } else if (b.IsSupertypeOf(a)) {
77952503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    result_type_handle = b_type_handle;
78052503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    is_exact = false;
78152503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle  } else if (!a_is_interface && !b_is_interface) {
7827d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    result_type_handle =
7837d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko        handle_cache_.NewHandle(a_type_handle->GetCommonSuperClass(b_type_handle));
7842e76830f0b3f23825677436c0633714402715099Calin Juravle    is_exact = false;
7852e76830f0b3f23825677436c0633714402715099Calin Juravle  } else {
78652503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    // This can happen if:
78752503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    //    - both types are interfaces. TODO(calin): implement
78852503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    //    - one is an interface, the other a class, and the type does not implement the interface
78952503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    //      e.g:
79052503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    //        void foo(Interface i, boolean cond) {
79152503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    //          Object o = cond ? i : new Object();
79252503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    //        }
7937d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    result_type_handle = handle_cache_.GetObjectClassHandle();
7942e76830f0b3f23825677436c0633714402715099Calin Juravle    is_exact = false;
7952e76830f0b3f23825677436c0633714402715099Calin Juravle  }
7962e76830f0b3f23825677436c0633714402715099Calin Juravle
79752503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle  return ReferenceTypeInfo::Create(result_type_handle, is_exact);
7982e76830f0b3f23825677436c0633714402715099Calin Juravle}
7992e76830f0b3f23825677436c0633714402715099Calin Juravle
8007d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::UpdateArrayGet(HArrayGet* instr, HandleCache* handle_cache) {
8012e76830f0b3f23825677436c0633714402715099Calin Juravle  DCHECK_EQ(Primitive::kPrimNot, instr->GetType());
8022e76830f0b3f23825677436c0633714402715099Calin Juravle
8032e76830f0b3f23825677436c0633714402715099Calin Juravle  ReferenceTypeInfo parent_rti = instr->InputAt(0)->GetReferenceTypeInfo();
804fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil  if (!parent_rti.IsValid()) {
805fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil    return;
806fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil  }
8072e76830f0b3f23825677436c0633714402715099Calin Juravle
8082e76830f0b3f23825677436c0633714402715099Calin Juravle  Handle<mirror::Class> handle = parent_rti.GetTypeHandle();
809f417ff44d1eb111854d7a213f106912b3dd9e3d4Aart Bik  if (handle->IsObjectArrayClass() && IsAdmissible(handle->GetComponentType())) {
8107d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    ReferenceTypeInfo::TypeHandle component_handle =
8117d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko        handle_cache->NewHandle(handle->GetComponentType());
81218401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray    bool is_exact = component_handle->CannotBeAssignedFromOtherTypes();
81318401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray    instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(component_handle, is_exact));
8142e76830f0b3f23825677436c0633714402715099Calin Juravle  } else {
8152e76830f0b3f23825677436c0633714402715099Calin Juravle    // We don't know what the parent actually is, so we fallback to object.
81618401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray    instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
81720e6071362b84a9782b633a893c29ebde458205eCalin Juravle  }
818b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle}
819b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
820b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlebool ReferenceTypePropagation::UpdateReferenceTypeInfo(HInstruction* instr) {
821b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  ScopedObjectAccess soa(Thread::Current());
822b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
823b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  ReferenceTypeInfo previous_rti = instr->GetReferenceTypeInfo();
824b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  if (instr->IsBoundType()) {
825b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    UpdateBoundType(instr->AsBoundType());
826b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  } else if (instr->IsPhi()) {
827b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    UpdatePhi(instr->AsPhi());
8282e76830f0b3f23825677436c0633714402715099Calin Juravle  } else if (instr->IsNullCheck()) {
8292e76830f0b3f23825677436c0633714402715099Calin Juravle    ReferenceTypeInfo parent_rti = instr->InputAt(0)->GetReferenceTypeInfo();
8302e76830f0b3f23825677436c0633714402715099Calin Juravle    if (parent_rti.IsValid()) {
8312e76830f0b3f23825677436c0633714402715099Calin Juravle      instr->SetReferenceTypeInfo(parent_rti);
8322e76830f0b3f23825677436c0633714402715099Calin Juravle    }
8332e76830f0b3f23825677436c0633714402715099Calin Juravle  } else if (instr->IsArrayGet()) {
834fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil    // TODO: consider if it's worth "looking back" and binding the input object
8352e76830f0b3f23825677436c0633714402715099Calin Juravle    // to an array type.
8367d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    UpdateArrayGet(instr->AsArrayGet(), &handle_cache_);
83710e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle  } else {
838b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    LOG(FATAL) << "Invalid instruction (should not get here)";
839b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  }
840b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
841b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  return !previous_rti.IsEqual(instr->GetReferenceTypeInfo());
842b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle}
843b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
8447d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitInvoke(HInvoke* instr) {
845ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  if (instr->GetType() != Primitive::kPrimNot) {
846ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez    return;
847ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  }
848ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez
849ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  ScopedObjectAccess soa(Thread::Current());
8505d37c152f21a0807459c6f53bc25e2d84f56d259Nicolas Geoffray  ArtMethod* method = instr->GetResolvedMethod();
851942fd3130254d8276cbfe8e6201825e9c49e9b2cVladimir Marko  mirror::Class* klass = (method == nullptr) ? nullptr : method->GetReturnType(/* resolve */ false);
8522e76830f0b3f23825677436c0633714402715099Calin Juravle  SetClassAsTypeInfo(instr, klass, /* is_exact */ false);
853ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez}
854ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez
8557d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitArrayGet(HArrayGet* instr) {
85672a5eb5d6784b318750c36e0da25c7338557ce44Guillaume "Vermeille" Sanchez  if (instr->GetType() != Primitive::kPrimNot) {
85772a5eb5d6784b318750c36e0da25c7338557ce44Guillaume "Vermeille" Sanchez    return;
85872a5eb5d6784b318750c36e0da25c7338557ce44Guillaume "Vermeille" Sanchez  }
859fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil
86072a5eb5d6784b318750c36e0da25c7338557ce44Guillaume "Vermeille" Sanchez  ScopedObjectAccess soa(Thread::Current());
8617d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  UpdateArrayGet(instr, handle_cache_);
8622e76830f0b3f23825677436c0633714402715099Calin Juravle  if (!instr->GetReferenceTypeInfo().IsValid()) {
8632aaa4b5532d30c4e65d8892b556400bb61f9dc8cVladimir Marko    worklist_->push_back(instr);
86472a5eb5d6784b318750c36e0da25c7338557ce44Guillaume "Vermeille" Sanchez  }
86572a5eb5d6784b318750c36e0da25c7338557ce44Guillaume "Vermeille" Sanchez}
86672a5eb5d6784b318750c36e0da25c7338557ce44Guillaume "Vermeille" Sanchez
867b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlevoid ReferenceTypePropagation::UpdateBoundType(HBoundType* instr) {
8688c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray  ReferenceTypeInfo input_rti = instr->InputAt(0)->GetReferenceTypeInfo();
8698c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray  if (!input_rti.IsValid()) {
8702e76830f0b3f23825677436c0633714402715099Calin Juravle    return;  // No new info yet.
8712e76830f0b3f23825677436c0633714402715099Calin Juravle  }
8722e76830f0b3f23825677436c0633714402715099Calin Juravle
873a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  ReferenceTypeInfo upper_bound_rti = instr->GetUpperBound();
8748c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray  if (upper_bound_rti.IsExact()) {
8758c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray    instr->SetReferenceTypeInfo(upper_bound_rti);
8768c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray  } else if (upper_bound_rti.IsSupertypeOf(input_rti)) {
8778c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray    // input is more specific.
8788c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray    instr->SetReferenceTypeInfo(input_rti);
8798c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray  } else {
8808c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray    // upper_bound is more specific or unrelated.
8818c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray    // Note that the object might then be exact, and we know the code dominated by this
8828c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray    // bound type is dead. To not confuse potential other optimizations, we mark
8838c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray    // the bound as non-exact.
8848c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray    instr->SetReferenceTypeInfo(
8858c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray        ReferenceTypeInfo::Create(upper_bound_rti.GetTypeHandle(), /* is_exact */ false));
8868c3794ca997268c9434e4a8e8ddee2922aad2c99Nicolas Geoffray  }
887b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle}
888b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
889617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle// NullConstant inputs are ignored during merging as they do not provide any useful information.
890617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle// If all the inputs are NullConstants then the type of the phi will be set to Object.
891b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlevoid ReferenceTypePropagation::UpdatePhi(HPhi* instr) {
892d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  DCHECK(instr->IsLive());
893d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil
894e90049140fdfb89080e5cc9b000b0c9be8c18bcdVladimir Marko  HInputsRef inputs = instr->GetInputs();
895617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle  size_t first_input_index_not_null = 0;
896372f10e5b0b34e2bb6e2b79aeba6c441e14afd1fVladimir Marko  while (first_input_index_not_null < inputs.size() &&
897e90049140fdfb89080e5cc9b000b0c9be8c18bcdVladimir Marko         inputs[first_input_index_not_null]->IsNullConstant()) {
898617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle    first_input_index_not_null++;
899617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle  }
900372f10e5b0b34e2bb6e2b79aeba6c441e14afd1fVladimir Marko  if (first_input_index_not_null == inputs.size()) {
901617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle    // All inputs are NullConstants, set the type to object.
902617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle    // This may happen in the presence of inlining.
90318401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray    instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
904617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle    return;
905617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle  }
906617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle
907617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle  ReferenceTypeInfo new_rti = instr->InputAt(first_input_index_not_null)->GetReferenceTypeInfo();
908617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle
9092e76830f0b3f23825677436c0633714402715099Calin Juravle  if (new_rti.IsValid() && new_rti.IsObjectClass() && !new_rti.IsExact()) {
9102e76830f0b3f23825677436c0633714402715099Calin Juravle    // Early return if we are Object and inexact.
911b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    instr->SetReferenceTypeInfo(new_rti);
912b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    return;
913b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  }
914617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle
915372f10e5b0b34e2bb6e2b79aeba6c441e14afd1fVladimir Marko  for (size_t i = first_input_index_not_null + 1; i < inputs.size(); i++) {
916372f10e5b0b34e2bb6e2b79aeba6c441e14afd1fVladimir Marko    if (inputs[i]->IsNullConstant()) {
917617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle      continue;
918617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle    }
919372f10e5b0b34e2bb6e2b79aeba6c441e14afd1fVladimir Marko    new_rti = MergeTypes(new_rti, inputs[i]->GetReferenceTypeInfo());
9202e76830f0b3f23825677436c0633714402715099Calin Juravle    if (new_rti.IsValid() && new_rti.IsObjectClass()) {
921b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle      if (!new_rti.IsExact()) {
922b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle        break;
923b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle      } else {
924b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle        continue;
925d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      }
92610e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle    }
92710e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle  }
928fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil
929fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil  if (new_rti.IsValid()) {
930fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil    instr->SetReferenceTypeInfo(new_rti);
931fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil  }
932b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle}
933b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
934b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle// Re-computes and updates the nullability of the instruction. Returns whether or
935b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle// not the nullability was changed.
936b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlebool ReferenceTypePropagation::UpdateNullability(HInstruction* instr) {
937d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  DCHECK((instr->IsPhi() && instr->AsPhi()->IsLive())
9382e76830f0b3f23825677436c0633714402715099Calin Juravle      || instr->IsBoundType()
9392e76830f0b3f23825677436c0633714402715099Calin Juravle      || instr->IsNullCheck()
9402e76830f0b3f23825677436c0633714402715099Calin Juravle      || instr->IsArrayGet());
9412e76830f0b3f23825677436c0633714402715099Calin Juravle
9422e76830f0b3f23825677436c0633714402715099Calin Juravle  if (!instr->IsPhi() && !instr->IsBoundType()) {
9432e76830f0b3f23825677436c0633714402715099Calin Juravle    return false;
9442e76830f0b3f23825677436c0633714402715099Calin Juravle  }
945b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
946a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  bool existing_can_be_null = instr->CanBeNull();
947a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  if (instr->IsPhi()) {
948a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    HPhi* phi = instr->AsPhi();
949a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    bool new_can_be_null = false;
950372f10e5b0b34e2bb6e2b79aeba6c441e14afd1fVladimir Marko    for (HInstruction* input : phi->GetInputs()) {
951372f10e5b0b34e2bb6e2b79aeba6c441e14afd1fVladimir Marko      if (input->CanBeNull()) {
952a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        new_can_be_null = true;
953a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        break;
954a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle      }
955a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    }
956a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    phi->SetCanBeNull(new_can_be_null);
957a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  } else if (instr->IsBoundType()) {
958a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    HBoundType* bound_type = instr->AsBoundType();
959a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    bound_type->SetCanBeNull(instr->InputAt(0)->CanBeNull() && bound_type->GetUpperCanBeNull());
960b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  }
961a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  return existing_can_be_null != instr->CanBeNull();
96210e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle}
96310e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle
96410e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravlevoid ReferenceTypePropagation::ProcessWorklist() {
9652aaa4b5532d30c4e65d8892b556400bb61f9dc8cVladimir Marko  while (!worklist_.empty()) {
9662aaa4b5532d30c4e65d8892b556400bb61f9dc8cVladimir Marko    HInstruction* instruction = worklist_.back();
9672aaa4b5532d30c4e65d8892b556400bb61f9dc8cVladimir Marko    worklist_.pop_back();
96812617599757b625bd59e6c62e022c30735073622Calin Juravle    bool updated_nullability = UpdateNullability(instruction);
96912617599757b625bd59e6c62e022c30735073622Calin Juravle    bool updated_reference_type = UpdateReferenceTypeInfo(instruction);
97012617599757b625bd59e6c62e022c30735073622Calin Juravle    if (updated_nullability || updated_reference_type) {
97110e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle      AddDependentInstructionsToWorklist(instruction);
97210e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle    }
97310e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle  }
97410e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle}
97510e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle
976b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlevoid ReferenceTypePropagation::AddToWorklist(HInstruction* instruction) {
9772e76830f0b3f23825677436c0633714402715099Calin Juravle  DCHECK_EQ(instruction->GetType(), Primitive::kPrimNot)
9782e76830f0b3f23825677436c0633714402715099Calin Juravle      << instruction->DebugName() << ":" << instruction->GetType();
9792aaa4b5532d30c4e65d8892b556400bb61f9dc8cVladimir Marko  worklist_.push_back(instruction);
98010e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle}
98110e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle
982b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlevoid ReferenceTypePropagation::AddDependentInstructionsToWorklist(HInstruction* instruction) {
98346817b876ab00d6b78905b80ed12b4344c522b6cVladimir Marko  for (const HUseListNode<HInstruction*>& use : instruction->GetUses()) {
98446817b876ab00d6b78905b80ed12b4344c522b6cVladimir Marko    HInstruction* user = use.GetUser();
985d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    if ((user->IsPhi() && user->AsPhi()->IsLive())
9862e76830f0b3f23825677436c0633714402715099Calin Juravle       || user->IsBoundType()
9872e76830f0b3f23825677436c0633714402715099Calin Juravle       || user->IsNullCheck()
9882e76830f0b3f23825677436c0633714402715099Calin Juravle       || (user->IsArrayGet() && (user->GetType() == Primitive::kPrimNot))) {
989beba9302bec33d72beb582970bf23d056f62641fCalin Juravle      AddToWorklist(user);
99010e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle    }
99110e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle  }
99210e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle}
9937d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko
99410e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle}  // namespace art
995