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