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
19e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "class_linker-inl.h"
20acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle#include "mirror/class-inl.h"
21acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle#include "mirror/dex_cache.h"
22acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle#include "scoped_thread_state_change.h"
23acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle
2410e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravlenamespace art {
2510e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle
26a4336d253b88f95c49891a8084579a4599785e90Vladimir Markostatic inline mirror::DexCache* FindDexCacheWithHint(Thread* self,
27a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko                                                     const DexFile& dex_file,
28a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko                                                     Handle<mirror::DexCache> hint_dex_cache)
29a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko    SHARED_REQUIRES(Locks::mutator_lock_) {
30a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko  if (LIKELY(hint_dex_cache->GetDexFile() == &dex_file)) {
31a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko    return hint_dex_cache.Get();
32a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko  } else {
33a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko    return Runtime::Current()->GetClassLinker()->FindDexCache(self, dex_file);
34a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko  }
35a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko}
36a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko
377d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markostatic inline ReferenceTypeInfo::TypeHandle GetRootHandle(StackHandleScopeCollection* handles,
387d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko                                                          ClassLinker::ClassRoot class_root,
397d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko                                                          ReferenceTypeInfo::TypeHandle* cache) {
407d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  if (!ReferenceTypeInfo::IsValidHandle(*cache)) {
417d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    // Mutator lock is required for NewHandle.
427d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    ClassLinker* linker = Runtime::Current()->GetClassLinker();
437d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    ScopedObjectAccess soa(Thread::Current());
447d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    *cache = handles->NewHandle(linker->GetClassRoot(class_root));
457d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  }
467d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  return *cache;
477d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko}
487d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko
49f7d994622aabcc689f62253a9253e0c67d9e787eNicolas Geoffray// Returns true if klass is admissible to the propagation: non-null and resolved.
50d1d7c40c8004303d1131ebb1956fd0ade54f8404Aart Bik// For an array type, we also check if the component type is admissible.
51d1d7c40c8004303d1131ebb1956fd0ade54f8404Aart Bikstatic bool IsAdmissible(mirror::Class* klass) SHARED_REQUIRES(Locks::mutator_lock_) {
52f7d994622aabcc689f62253a9253e0c67d9e787eNicolas Geoffray  return klass != nullptr && klass->IsResolved() &&
53d1d7c40c8004303d1131ebb1956fd0ade54f8404Aart Bik      (!klass->IsArrayClass() || IsAdmissible(klass->GetComponentType()));
54d1d7c40c8004303d1131ebb1956fd0ade54f8404Aart Bik}
55d1d7c40c8004303d1131ebb1956fd0ade54f8404Aart Bik
567d1fbf38412078090e81e9d9fa502635d8541707Vladimir MarkoReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetObjectClassHandle() {
577d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  return GetRootHandle(handles_, ClassLinker::kJavaLangObject, &object_class_handle_);
587d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko}
597d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko
607d1fbf38412078090e81e9d9fa502635d8541707Vladimir MarkoReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetClassClassHandle() {
617d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  return GetRootHandle(handles_, ClassLinker::kJavaLangClass, &class_class_handle_);
627d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko}
637d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko
647d1fbf38412078090e81e9d9fa502635d8541707Vladimir MarkoReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetStringClassHandle() {
657d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  return GetRootHandle(handles_, ClassLinker::kJavaLangString, &string_class_handle_);
667d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko}
677d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko
687d1fbf38412078090e81e9d9fa502635d8541707Vladimir MarkoReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetThrowableClassHandle() {
697d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  return GetRootHandle(handles_, ClassLinker::kJavaLangThrowable, &throwable_class_handle_);
707d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko}
717d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko
727d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markoclass ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor {
73ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez public:
742e76830f0b3f23825677436c0633714402715099Calin Juravle  RTPVisitor(HGraph* graph,
75a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko             Handle<mirror::DexCache> hint_dex_cache,
767d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko             HandleCache* handle_cache,
77d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray             ArenaVector<HInstruction*>* worklist,
78d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray             bool is_first_run)
79ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez    : HGraphDelegateVisitor(graph),
80a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko      hint_dex_cache_(hint_dex_cache),
817d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko      handle_cache_(handle_cache),
82d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray      worklist_(worklist),
83d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray      is_first_run_(is_first_run) {}
84ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez
85ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  void VisitNewInstance(HNewInstance* new_instance) OVERRIDE;
86ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  void VisitLoadClass(HLoadClass* load_class) OVERRIDE;
872e76830f0b3f23825677436c0633714402715099Calin Juravle  void VisitClinitCheck(HClinitCheck* clinit_check) OVERRIDE;
882e76830f0b3f23825677436c0633714402715099Calin Juravle  void VisitLoadString(HLoadString* instr) OVERRIDE;
89bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil  void VisitLoadException(HLoadException* instr) OVERRIDE;
90ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  void VisitNewArray(HNewArray* instr) OVERRIDE;
912e76830f0b3f23825677436c0633714402715099Calin Juravle  void VisitParameterValue(HParameterValue* instr) OVERRIDE;
92ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  void UpdateFieldAccessTypeInfo(HInstruction* instr, const FieldInfo& info);
93a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko  void SetClassAsTypeInfo(HInstruction* instr, mirror::Class* klass, bool is_exact)
94a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko      SHARED_REQUIRES(Locks::mutator_lock_);
95ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  void VisitInstanceFieldGet(HInstanceFieldGet* instr) OVERRIDE;
96ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  void VisitStaticFieldGet(HStaticFieldGet* instr) OVERRIDE;
97e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  void VisitUnresolvedInstanceFieldGet(HUnresolvedInstanceFieldGet* instr) OVERRIDE;
98e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  void VisitUnresolvedStaticFieldGet(HUnresolvedStaticFieldGet* instr) OVERRIDE;
99ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  void VisitInvoke(HInvoke* instr) OVERRIDE;
10072a5eb5d6784b318750c36e0da25c7338557ce44Guillaume "Vermeille" Sanchez  void VisitArrayGet(HArrayGet* instr) OVERRIDE;
101a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  void VisitCheckCast(HCheckCast* instr) OVERRIDE;
102f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  void VisitBoundType(HBoundType* instr) OVERRIDE;
1032e76830f0b3f23825677436c0633714402715099Calin Juravle  void VisitNullCheck(HNullCheck* instr) OVERRIDE;
104ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  void UpdateReferenceTypeInfo(HInstruction* instr,
105ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez                               uint16_t type_idx,
106ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez                               const DexFile& dex_file,
107ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez                               bool is_exact);
108ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez
109ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez private:
110a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko  Handle<mirror::DexCache> hint_dex_cache_;
1117d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  HandleCache* handle_cache_;
1122aaa4b5532d30c4e65d8892b556400bb61f9dc8cVladimir Marko  ArenaVector<HInstruction*>* worklist_;
113d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray  const bool is_first_run_;
114ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez};
115ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez
1162e76830f0b3f23825677436c0633714402715099Calin JuravleReferenceTypePropagation::ReferenceTypePropagation(HGraph* graph,
117a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko                                                   Handle<mirror::DexCache> hint_dex_cache,
1182e76830f0b3f23825677436c0633714402715099Calin Juravle                                                   StackHandleScopeCollection* handles,
119d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray                                                   bool is_first_run,
1202e76830f0b3f23825677436c0633714402715099Calin Juravle                                                   const char* name)
1212e76830f0b3f23825677436c0633714402715099Calin Juravle    : HOptimization(graph, name),
122a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko      hint_dex_cache_(hint_dex_cache),
1237d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko      handle_cache_(handles),
124d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray      worklist_(graph->GetArena()->Adapter(kArenaAllocReferenceTypePropagation)),
125d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray      is_first_run_(is_first_run) {
1262e76830f0b3f23825677436c0633714402715099Calin Juravle}
1272e76830f0b3f23825677436c0633714402715099Calin Juravle
128cdfed3dc422d0e1a9a0a948863308e58c39d01baCalin Juravlevoid ReferenceTypePropagation::ValidateTypes() {
129cdfed3dc422d0e1a9a0a948863308e58c39d01baCalin Juravle  // TODO: move this to the graph checker.
1302e76830f0b3f23825677436c0633714402715099Calin Juravle  if (kIsDebugBuild) {
1312e76830f0b3f23825677436c0633714402715099Calin Juravle    ScopedObjectAccess soa(Thread::Current());
1322e76830f0b3f23825677436c0633714402715099Calin Juravle    for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
1332e76830f0b3f23825677436c0633714402715099Calin Juravle      HBasicBlock* block = it.Current();
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) {
157a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko  RTPVisitor visitor(graph_, hint_dex_cache_, &handle_cache_, &worklist_, is_first_run_);
158be10e8e99a78caae01fb65769218800d465144aeVladimir Marko  instruction->Accept(&visitor);
159be10e8e99a78caae01fb65769218800d465144aeVladimir Marko}
160be10e8e99a78caae01fb65769218800d465144aeVladimir Marko
161cdfed3dc422d0e1a9a0a948863308e58c39d01baCalin Juravlevoid ReferenceTypePropagation::Run() {
162be10e8e99a78caae01fb65769218800d465144aeVladimir Marko  worklist_.reserve(kDefaultWorklistSize);
163be10e8e99a78caae01fb65769218800d465144aeVladimir Marko
164cdfed3dc422d0e1a9a0a948863308e58c39d01baCalin Juravle  // To properly propagate type info we need to visit in the dominator-based order.
165cdfed3dc422d0e1a9a0a948863308e58c39d01baCalin Juravle  // Reverse post order guarantees a node's dominators are visited first.
166cdfed3dc422d0e1a9a0a948863308e58c39d01baCalin Juravle  // We take advantage of this order in `VisitBasicBlock`.
167cdfed3dc422d0e1a9a0a948863308e58c39d01baCalin Juravle  for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
168cdfed3dc422d0e1a9a0a948863308e58c39d01baCalin Juravle    VisitBasicBlock(it.Current());
169cdfed3dc422d0e1a9a0a948863308e58c39d01baCalin Juravle  }
170cdfed3dc422d0e1a9a0a948863308e58c39d01baCalin Juravle
171cdfed3dc422d0e1a9a0a948863308e58c39d01baCalin Juravle  ProcessWorklist();
172cdfed3dc422d0e1a9a0a948863308e58c39d01baCalin Juravle  ValidateTypes();
173cdfed3dc422d0e1a9a0a948863308e58c39d01baCalin Juravle}
174cdfed3dc422d0e1a9a0a948863308e58c39d01baCalin Juravle
175b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlevoid ReferenceTypePropagation::VisitBasicBlock(HBasicBlock* block) {
176a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko  RTPVisitor visitor(graph_, hint_dex_cache_, &handle_cache_, &worklist_, is_first_run_);
1772e76830f0b3f23825677436c0633714402715099Calin Juravle  // Handle Phis first as there might be instructions in the same block who depend on them.
1782e76830f0b3f23825677436c0633714402715099Calin Juravle  for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
1792e76830f0b3f23825677436c0633714402715099Calin Juravle    VisitPhi(it.Current()->AsPhi());
1802e76830f0b3f23825677436c0633714402715099Calin Juravle  }
181beba9302bec33d72beb582970bf23d056f62641fCalin Juravle
1822e76830f0b3f23825677436c0633714402715099Calin Juravle  // Handle instructions.
183b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
184b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    HInstruction* instr = it.Current();
185ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez    instr->Accept(&visitor);
186b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  }
18710e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle
188b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  // Add extra nodes to bound types.
18961d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  BoundTypeForIfNotNull(block);
190b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  BoundTypeForIfInstanceOf(block);
191b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle}
192acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle
193a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle// Check if we should create a bound type for the given object at the specified
194a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle// position. Because of inlining and the fact we run RTP more than once and we
195a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle// might have a HBoundType already. If we do, we should not create a new one.
196a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle// In this case we also assert that there are no other uses of the object (except
197a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle// the bound type) dominated by the specified dominator_instr or dominator_block.
198a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravlestatic bool ShouldCreateBoundType(HInstruction* position,
199a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle                                  HInstruction* obj,
200a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle                                  ReferenceTypeInfo upper_bound,
201a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle                                  HInstruction* dominator_instr,
202a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle                                  HBasicBlock* dominator_block)
203a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    SHARED_REQUIRES(Locks::mutator_lock_) {
204a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  // If the position where we should insert the bound type is not already a
205a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  // a bound type then we need to create one.
206a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  if (position == nullptr || !position->IsBoundType()) {
207a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    return true;
208a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  }
209a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle
210a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  HBoundType* existing_bound_type = position->AsBoundType();
211a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  if (existing_bound_type->GetUpperBound().IsSupertypeOf(upper_bound)) {
212a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    if (kIsDebugBuild) {
213a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle      // Check that the existing HBoundType dominates all the uses.
214d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko      for (const HUseListNode<HInstruction*>& use : obj->GetUses()) {
215d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko        HInstruction* user = use.GetUser();
216a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        if (dominator_instr != nullptr) {
217a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle          DCHECK(!dominator_instr->StrictlyDominates(user)
218a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle              || user == existing_bound_type
219a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle              || existing_bound_type->StrictlyDominates(user));
220a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        } else if (dominator_block != nullptr) {
221a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle          DCHECK(!dominator_block->Dominates(user->GetBlock())
222a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle              || user == existing_bound_type
223a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle              || existing_bound_type->StrictlyDominates(user));
224a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        }
225a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle      }
226a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    }
227a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  } else {
228a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    // TODO: if the current bound type is a refinement we could update the
229a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    // existing_bound_type with the a new upper limit. However, we also need to
230a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    // update its users and have access to the work list.
231a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  }
232a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  return false;
233a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle}
234a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle
23561d544bfb812d79f5c9ddad171198836cea719dbCalin Juravlevoid ReferenceTypePropagation::BoundTypeForIfNotNull(HBasicBlock* block) {
236b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  HIf* ifInstruction = block->GetLastInstruction()->AsIf();
237b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  if (ifInstruction == nullptr) {
23861d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle    return;
23961d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  }
240b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  HInstruction* ifInput = ifInstruction->InputAt(0);
24161d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  if (!ifInput->IsNotEqual() && !ifInput->IsEqual()) {
24261d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle    return;
24361d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  }
24461d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  HInstruction* input0 = ifInput->InputAt(0);
24561d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  HInstruction* input1 = ifInput->InputAt(1);
246edad8add1f1216850cb3f179ba6f57b0d885b016Calin Juravle  HInstruction* obj = nullptr;
24761d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle
248edad8add1f1216850cb3f179ba6f57b0d885b016Calin Juravle  if (input1->IsNullConstant()) {
24961d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle    obj = input0;
250edad8add1f1216850cb3f179ba6f57b0d885b016Calin Juravle  } else if (input0->IsNullConstant()) {
25161d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle    obj = input1;
25261d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  } else {
25361d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle    return;
25461d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  }
25561d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle
2567d5ea03b2a7d886325b3ad97942038c2336aa855Nicolas Geoffray  if (!obj->CanBeNull() || obj->IsNullConstant()) {
2577d5ea03b2a7d886325b3ad97942038c2336aa855Nicolas Geoffray    // Null check is dead code and will be removed by DCE.
2587d5ea03b2a7d886325b3ad97942038c2336aa855Nicolas Geoffray    return;
2597d5ea03b2a7d886325b3ad97942038c2336aa855Nicolas Geoffray  }
2607d5ea03b2a7d886325b3ad97942038c2336aa855Nicolas Geoffray  DCHECK(!obj->IsLoadClass()) << "We should not replace HLoadClass instructions";
2617d5ea03b2a7d886325b3ad97942038c2336aa855Nicolas Geoffray
262b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  // We only need to bound the type if we have uses in the relevant block.
263b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  // So start with null and create the HBoundType lazily, only if it's needed.
264b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  HBoundType* bound_type = nullptr;
26561d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  HBasicBlock* notNullBlock = ifInput->IsNotEqual()
266b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle      ? ifInstruction->IfTrueSuccessor()
267b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle      : ifInstruction->IfFalseSuccessor();
268b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle
269d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  const HUseList<HInstruction*>& uses = obj->GetUses();
270d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  for (auto it = uses.begin(), end = uses.end(); it != end; /* ++it below */) {
271d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    HInstruction* user = it->GetUser();
272d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    size_t index = it->GetIndex();
273d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    // Increment `it` now because `*it` may disappear thanks to user->ReplaceInput().
274d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    ++it;
27561d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle    if (notNullBlock->Dominates(user->GetBlock())) {
276b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle      if (bound_type == nullptr) {
277a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        ScopedObjectAccess soa(Thread::Current());
278a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        HInstruction* insert_point = notNullBlock->GetFirstInstruction();
2792e76830f0b3f23825677436c0633714402715099Calin Juravle        ReferenceTypeInfo object_rti = ReferenceTypeInfo::Create(
2807d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko            handle_cache_.GetObjectClassHandle(), /* is_exact */ true);
281a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        if (ShouldCreateBoundType(insert_point, obj, object_rti, nullptr, notNullBlock)) {
282f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil          bound_type = new (graph_->GetArena()) HBoundType(obj);
283f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil          bound_type->SetUpperBound(object_rti, /* bound_can_be_null */ false);
2842e76830f0b3f23825677436c0633714402715099Calin Juravle          if (obj->GetReferenceTypeInfo().IsValid()) {
2852e76830f0b3f23825677436c0633714402715099Calin Juravle            bound_type->SetReferenceTypeInfo(obj->GetReferenceTypeInfo());
2862e76830f0b3f23825677436c0633714402715099Calin Juravle          }
287a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle          notNullBlock->InsertInstructionBefore(bound_type, insert_point);
288a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        } else {
289a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle          // We already have a bound type on the position we would need to insert
290a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle          // the new one. The existing bound type should dominate all the users
291a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle          // (dchecked) so there's no need to continue.
292a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle          break;
293a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        }
294b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle      }
295d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko      user->ReplaceInput(bound_type, index);
29661d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle    }
29761d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle  }
29861d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle}
29961d544bfb812d79f5c9ddad171198836cea719dbCalin Juravle
300d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil// Returns true if one of the patterns below has been recognized. If so, the
301d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil// InstanceOf instruction together with the true branch of `ifInstruction` will
302d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil// be returned using the out parameters.
303d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil// Recognized patterns:
304d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil//   (1) patterns equivalent to `if (obj instanceof X)`
305d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil//     (a) InstanceOf -> Equal to 1 -> If
306d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil//     (b) InstanceOf -> NotEqual to 0 -> If
307d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil//     (c) InstanceOf -> If
308d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil//   (2) patterns equivalent to `if (!(obj instanceof X))`
309d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil//     (a) InstanceOf -> Equal to 0 -> If
310d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil//     (b) InstanceOf -> NotEqual to 1 -> If
311d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil//     (c) InstanceOf -> BooleanNot -> If
312d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdilstatic bool MatchIfInstanceOf(HIf* ifInstruction,
313d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil                              /* out */ HInstanceOf** instanceOf,
314d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil                              /* out */ HBasicBlock** trueBranch) {
315d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  HInstruction* input = ifInstruction->InputAt(0);
316d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil
317d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  if (input->IsEqual()) {
318d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    HInstruction* rhs = input->AsEqual()->GetConstantRight();
319d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    if (rhs != nullptr) {
320d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      HInstruction* lhs = input->AsEqual()->GetLeastConstantLeft();
321d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      if (lhs->IsInstanceOf() && rhs->IsIntConstant()) {
3221a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain        if (rhs->AsIntConstant()->IsTrue()) {
323d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil          // Case (1a)
324d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil          *trueBranch = ifInstruction->IfTrueSuccessor();
325d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil        } else {
326d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil          // Case (2a)
3271a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain          DCHECK(rhs->AsIntConstant()->IsFalse()) << rhs->AsIntConstant()->GetValue();
328d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil          *trueBranch = ifInstruction->IfFalseSuccessor();
329d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil        }
330d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil        *instanceOf = lhs->AsInstanceOf();
331d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil        return true;
332d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      }
333d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    }
334d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  } else if (input->IsNotEqual()) {
335d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    HInstruction* rhs = input->AsNotEqual()->GetConstantRight();
336d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    if (rhs != nullptr) {
337d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      HInstruction* lhs = input->AsNotEqual()->GetLeastConstantLeft();
338d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      if (lhs->IsInstanceOf() && rhs->IsIntConstant()) {
3391a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain        if (rhs->AsIntConstant()->IsFalse()) {
340d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil          // Case (1b)
341d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil          *trueBranch = ifInstruction->IfTrueSuccessor();
342d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil        } else {
343d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil          // Case (2b)
3441a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain          DCHECK(rhs->AsIntConstant()->IsTrue()) << rhs->AsIntConstant()->GetValue();
345d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil          *trueBranch = ifInstruction->IfFalseSuccessor();
346d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil        }
347d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil        *instanceOf = lhs->AsInstanceOf();
348d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil        return true;
349d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      }
350d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    }
351d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  } else if (input->IsInstanceOf()) {
352d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    // Case (1c)
353d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    *instanceOf = input->AsInstanceOf();
354d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    *trueBranch = ifInstruction->IfTrueSuccessor();
355d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    return true;
356d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  } else if (input->IsBooleanNot()) {
357d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    HInstruction* not_input = input->InputAt(0);
358d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    if (not_input->IsInstanceOf()) {
359d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      // Case (2c)
360d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      *instanceOf = not_input->AsInstanceOf();
361d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      *trueBranch = ifInstruction->IfFalseSuccessor();
362d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      return true;
363d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    }
364d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  }
365d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil
366d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  return false;
367d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil}
368d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil
369b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle// Detects if `block` is the True block for the pattern
370b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle// `if (x instanceof ClassX) { }`
371b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle// If that's the case insert an HBoundType instruction to bound the type of `x`
372b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle// to `ClassX` in the scope of the dominated blocks.
373b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlevoid ReferenceTypePropagation::BoundTypeForIfInstanceOf(HBasicBlock* block) {
374b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  HIf* ifInstruction = block->GetLastInstruction()->AsIf();
375b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  if (ifInstruction == nullptr) {
376b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    return;
377b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  }
378b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle
379d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  // Try to recognize common `if (instanceof)` and `if (!instanceof)` patterns.
380d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  HInstanceOf* instanceOf = nullptr;
381d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  HBasicBlock* instanceOfTrueBlock = nullptr;
382d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  if (!MatchIfInstanceOf(ifInstruction, &instanceOf, &instanceOfTrueBlock)) {
383b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    return;
384acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle  }
385acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle
38698893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle  HLoadClass* load_class = instanceOf->InputAt(1)->AsLoadClass();
38798893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle  ReferenceTypeInfo class_rti = load_class->GetLoadedClassRTI();
38898893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle  {
38998893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle    if (!class_rti.IsValid()) {
39098893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle      // He have loaded an unresolved class. Don't bother bounding the type.
39198893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle      return;
39298893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle    }
39398893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle  }
394b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  // We only need to bound the type if we have uses in the relevant block.
395b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  // So start with null and create the HBoundType lazily, only if it's needed.
396b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  HBoundType* bound_type = nullptr;
397acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle
398b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle  HInstruction* obj = instanceOf->InputAt(0);
399f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray  if (obj->GetReferenceTypeInfo().IsExact() && !obj->IsPhi()) {
400f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray    // This method is being called while doing a fixed-point calculation
401f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray    // over phis. Non-phis instruction whose type is already known do
402f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray    // not need to be bound to another type.
403f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray    // Not that this also prevents replacing `HLoadClass` with a `HBoundType`.
404f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray    // `HCheckCast` and `HInstanceOf` expect a `HLoadClass` as a second
405f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray    // input.
406f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray    return;
407f9a199571417b5a5a62d94d05a064077e14dd2c4Nicolas Geoffray  }
4087d5ea03b2a7d886325b3ad97942038c2336aa855Nicolas Geoffray  DCHECK(!obj->IsLoadClass()) << "We should not replace HLoadClass instructions";
409d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  const HUseList<HInstruction*>& uses = obj->GetUses();
410d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  for (auto it = uses.begin(), end = uses.end(); it != end; /* ++it below */) {
411d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    HInstruction* user = it->GetUser();
412d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    size_t index = it->GetIndex();
413d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    // Increment `it` now because `*it` may disappear thanks to user->ReplaceInput().
414d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    ++it;
415b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    if (instanceOfTrueBlock->Dominates(user->GetBlock())) {
416b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle      if (bound_type == nullptr) {
417a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        ScopedObjectAccess soa(Thread::Current());
418a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        HInstruction* insert_point = instanceOfTrueBlock->GetFirstInstruction();
419a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        if (ShouldCreateBoundType(insert_point, obj, class_rti, nullptr, instanceOfTrueBlock)) {
420f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil          bound_type = new (graph_->GetArena()) HBoundType(obj);
421f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil          bound_type->SetUpperBound(class_rti, /* InstanceOf fails for null. */ false);
422a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle          instanceOfTrueBlock->InsertInstructionBefore(bound_type, insert_point);
423a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        } else {
424a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle          // We already have a bound type on the position we would need to insert
425a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle          // the new one. The existing bound type should dominate all the users
426a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle          // (dchecked) so there's no need to continue.
427a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle          break;
428b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle        }
429b3306642f42d47ddb4d021a2f48ce9b1bd235857Calin Juravle      }
430d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko      user->ReplaceInput(bound_type, index);
431acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle    }
432acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle  }
433acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle}
434acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle
4357d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::SetClassAsTypeInfo(HInstruction* instr,
4367d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko                                                              mirror::Class* klass,
4377d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko                                                              bool is_exact) {
4382e76830f0b3f23825677436c0633714402715099Calin Juravle  if (instr->IsInvokeStaticOrDirect() && instr->AsInvokeStaticOrDirect()->IsStringInit()) {
4392e76830f0b3f23825677436c0633714402715099Calin Juravle    // Calls to String.<init> are replaced with a StringFactory.
4402e76830f0b3f23825677436c0633714402715099Calin Juravle    if (kIsDebugBuild) {
441c89715ccaf4c8a8ce298ce2c0c1da479de4c63e7Nicolas Geoffray      HInvoke* invoke = instr->AsInvoke();
4422e76830f0b3f23825677436c0633714402715099Calin Juravle      ClassLinker* cl = Runtime::Current()->GetClassLinker();
443a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko      Thread* self = Thread::Current();
444a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko      StackHandleScope<2> hs(self);
445c89715ccaf4c8a8ce298ce2c0c1da479de4c63e7Nicolas Geoffray      Handle<mirror::DexCache> dex_cache(
446a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko          hs.NewHandle(FindDexCacheWithHint(self, invoke->GetDexFile(), hint_dex_cache_)));
447c89715ccaf4c8a8ce298ce2c0c1da479de4c63e7Nicolas Geoffray      // Use a null loader. We should probably use the compiling method's class loader,
448c89715ccaf4c8a8ce298ce2c0c1da479de4c63e7Nicolas Geoffray      // but then we would need to pass it to RTPVisitor just for this debug check. Since
449c89715ccaf4c8a8ce298ce2c0c1da479de4c63e7Nicolas Geoffray      // the method is from the String class, the null loader is good enough.
450c89715ccaf4c8a8ce298ce2c0c1da479de4c63e7Nicolas Geoffray      Handle<mirror::ClassLoader> loader;
45142ef8ab151a3d0cbb42cb43f6841c3708d65fca3Andreas Gampe      ArtMethod* method = cl->ResolveMethod<ClassLinker::kNoICCECheckForCache>(
452c89715ccaf4c8a8ce298ce2c0c1da479de4c63e7Nicolas Geoffray          invoke->GetDexFile(), invoke->GetDexMethodIndex(), dex_cache, loader, nullptr, kDirect);
4532e76830f0b3f23825677436c0633714402715099Calin Juravle      DCHECK(method != nullptr);
4542e76830f0b3f23825677436c0633714402715099Calin Juravle      mirror::Class* declaring_class = method->GetDeclaringClass();
4552e76830f0b3f23825677436c0633714402715099Calin Juravle      DCHECK(declaring_class != nullptr);
4562e76830f0b3f23825677436c0633714402715099Calin Juravle      DCHECK(declaring_class->IsStringClass())
4572e76830f0b3f23825677436c0633714402715099Calin Juravle          << "Expected String class: " << PrettyDescriptor(declaring_class);
4582e76830f0b3f23825677436c0633714402715099Calin Juravle      DCHECK(method->IsConstructor())
4592e76830f0b3f23825677436c0633714402715099Calin Juravle          << "Expected String.<init>: " << PrettyMethod(method);
4602e76830f0b3f23825677436c0633714402715099Calin Juravle    }
4612e76830f0b3f23825677436c0633714402715099Calin Juravle    instr->SetReferenceTypeInfo(
4627d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko        ReferenceTypeInfo::Create(handle_cache_->GetStringClassHandle(), /* is_exact */ true));
463d1d7c40c8004303d1131ebb1956fd0ade54f8404Aart Bik  } else if (IsAdmissible(klass)) {
464d1d7c40c8004303d1131ebb1956fd0ade54f8404Aart Bik    ReferenceTypeInfo::TypeHandle handle = handle_cache_->NewHandle(klass);
465d1d7c40c8004303d1131ebb1956fd0ade54f8404Aart Bik    is_exact = is_exact || handle->CannotBeAssignedFromOtherTypes();
466d1d7c40c8004303d1131ebb1956fd0ade54f8404Aart Bik    instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(handle, is_exact));
4672e76830f0b3f23825677436c0633714402715099Calin Juravle  } else {
46818401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray    instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
469104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez  }
470104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez}
471104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez
4727d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::UpdateReferenceTypeInfo(HInstruction* instr,
4737d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko                                                                   uint16_t type_idx,
4747d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko                                                                   const DexFile& dex_file,
4757d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko                                                                   bool is_exact) {
47681d804a51d4fc415e1544a5a09505db049f4eda6Guillaume "Vermeille" Sanchez  DCHECK_EQ(instr->GetType(), Primitive::kPrimNot);
47781d804a51d4fc415e1544a5a09505db049f4eda6Guillaume "Vermeille" Sanchez
478acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle  ScopedObjectAccess soa(Thread::Current());
479a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko  mirror::DexCache* dex_cache = FindDexCacheWithHint(soa.Self(), dex_file, hint_dex_cache_);
480acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle  // Get type from dex cache assuming it was populated by the verifier.
481222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez  SetClassAsTypeInfo(instr, dex_cache->GetResolvedType(type_idx), is_exact);
482acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle}
483acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle
4847d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitNewInstance(HNewInstance* instr) {
485222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez  UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile(), /* is_exact */ true);
48681d804a51d4fc415e1544a5a09505db049f4eda6Guillaume "Vermeille" Sanchez}
48781d804a51d4fc415e1544a5a09505db049f4eda6Guillaume "Vermeille" Sanchez
4887d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitNewArray(HNewArray* instr) {
489222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez  UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile(), /* is_exact */ true);
49081d804a51d4fc415e1544a5a09505db049f4eda6Guillaume "Vermeille" Sanchez}
49181d804a51d4fc415e1544a5a09505db049f4eda6Guillaume "Vermeille" Sanchez
492a4336d253b88f95c49891a8084579a4599785e90Vladimir Markostatic mirror::Class* GetClassFromDexCache(Thread* self,
493a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko                                           const DexFile& dex_file,
494a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko                                           uint16_t type_idx,
495a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko                                           Handle<mirror::DexCache> hint_dex_cache)
496e6e3beaf2d35d18a79f5e7b60a21e75fac9fd15dCalin Juravle    SHARED_REQUIRES(Locks::mutator_lock_) {
497a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko  mirror::DexCache* dex_cache = FindDexCacheWithHint(self, dex_file, hint_dex_cache);
498e6e3beaf2d35d18a79f5e7b60a21e75fac9fd15dCalin Juravle  // Get type from dex cache assuming it was populated by the verifier.
499e6e3beaf2d35d18a79f5e7b60a21e75fac9fd15dCalin Juravle  return dex_cache->GetResolvedType(type_idx);
500e6e3beaf2d35d18a79f5e7b60a21e75fac9fd15dCalin Juravle}
501e6e3beaf2d35d18a79f5e7b60a21e75fac9fd15dCalin Juravle
5027d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitParameterValue(HParameterValue* instr) {
503e418dda75998e0186f7580c2c54705767c3c8f1fNicolas Geoffray  // We check if the existing type is valid: the inliner may have set it.
504e418dda75998e0186f7580c2c54705767c3c8f1fNicolas Geoffray  if (instr->GetType() == Primitive::kPrimNot && !instr->GetReferenceTypeInfo().IsValid()) {
505a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko    ScopedObjectAccess soa(Thread::Current());
506a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko    mirror::Class* resolved_class = GetClassFromDexCache(soa.Self(),
507a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko                                                         instr->GetDexFile(),
508a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko                                                         instr->GetTypeIndex(),
509a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko                                                         hint_dex_cache_);
510e6e3beaf2d35d18a79f5e7b60a21e75fac9fd15dCalin Juravle    SetClassAsTypeInfo(instr, resolved_class, /* is_exact */ false);
5112e76830f0b3f23825677436c0633714402715099Calin Juravle  }
5122e76830f0b3f23825677436c0633714402715099Calin Juravle}
5132e76830f0b3f23825677436c0633714402715099Calin Juravle
5147d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::UpdateFieldAccessTypeInfo(HInstruction* instr,
5157d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko                                                                     const FieldInfo& info) {
516d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  if (instr->GetType() != Primitive::kPrimNot) {
517104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez    return;
518104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez  }
519104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez
520104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez  ScopedObjectAccess soa(Thread::Current());
521d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  mirror::Class* klass = nullptr;
522d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil
523d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  // The field index is unknown only during tests.
524d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  if (info.GetFieldIndex() != kUnknownFieldIndex) {
525d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    ClassLinker* cl = Runtime::Current()->GetClassLinker();
526d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    ArtField* field = cl->GetResolvedField(info.GetFieldIndex(), info.GetDexCache().Get());
527d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    // TODO: There are certain cases where we can't resolve the field.
528d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    // b/21914925 is open to keep track of a repro case for this issue.
529d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    if (field != nullptr) {
530d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil      klass = field->GetType<false>();
531d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    }
532d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  }
533d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil
5342e76830f0b3f23825677436c0633714402715099Calin Juravle  SetClassAsTypeInfo(instr, klass, /* is_exact */ false);
535104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez}
536104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez
5377d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitInstanceFieldGet(HInstanceFieldGet* instr) {
538104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez  UpdateFieldAccessTypeInfo(instr, instr->GetFieldInfo());
539104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez}
540104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez
5417d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitStaticFieldGet(HStaticFieldGet* instr) {
542104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez  UpdateFieldAccessTypeInfo(instr, instr->GetFieldInfo());
543104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez}
544104fd8a3f30ddcf07831250571aa2a233cd5c04dGuillaume "Vermeille" Sanchez
5457d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitUnresolvedInstanceFieldGet(
5467d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    HUnresolvedInstanceFieldGet* instr) {
547e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  // TODO: Use descriptor to get the actual type.
548e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  if (instr->GetFieldType() == Primitive::kPrimNot) {
54918401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray    instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
550e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
551e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle}
552e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
5537d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitUnresolvedStaticFieldGet(
5547d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    HUnresolvedStaticFieldGet* instr) {
555e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  // TODO: Use descriptor to get the actual type.
556e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  if (instr->GetFieldType() == Primitive::kPrimNot) {
55718401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray    instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
558e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
559e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle}
560e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
5617d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitLoadClass(HLoadClass* instr) {
562acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle  ScopedObjectAccess soa(Thread::Current());
563acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle  // Get type from dex cache assuming it was populated by the verifier.
564a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko  mirror::Class* resolved_class = GetClassFromDexCache(soa.Self(),
565a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko                                                       instr->GetDexFile(),
566a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko                                                       instr->GetTypeIndex(),
567a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko                                                       hint_dex_cache_);
568d1d7c40c8004303d1131ebb1956fd0ade54f8404Aart Bik  if (IsAdmissible(resolved_class)) {
56998893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle    instr->SetLoadedClassRTI(ReferenceTypeInfo::Create(
5707d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko        handle_cache_->NewHandle(resolved_class), /* is_exact */ true));
57198893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle  }
5727d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  instr->SetReferenceTypeInfo(
5737d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko      ReferenceTypeInfo::Create(handle_cache_->GetClassClassHandle(), /* is_exact */ true));
5742e76830f0b3f23825677436c0633714402715099Calin Juravle}
5752e76830f0b3f23825677436c0633714402715099Calin Juravle
5767d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitClinitCheck(HClinitCheck* instr) {
5772e76830f0b3f23825677436c0633714402715099Calin Juravle  instr->SetReferenceTypeInfo(instr->InputAt(0)->GetReferenceTypeInfo());
5782e76830f0b3f23825677436c0633714402715099Calin Juravle}
5792e76830f0b3f23825677436c0633714402715099Calin Juravle
5807d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitLoadString(HLoadString* instr) {
5817d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  instr->SetReferenceTypeInfo(
5827d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko      ReferenceTypeInfo::Create(handle_cache_->GetStringClassHandle(), /* is_exact */ true));
5832e76830f0b3f23825677436c0633714402715099Calin Juravle}
5842e76830f0b3f23825677436c0633714402715099Calin Juravle
5857d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitLoadException(HLoadException* instr) {
586bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil  DCHECK(instr->GetBlock()->IsCatchBlock());
587bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil  TryCatchInformation* catch_info = instr->GetBlock()->GetTryCatchInformation();
588bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil
589bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil  if (catch_info->IsCatchAllTypeIndex()) {
5907d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    instr->SetReferenceTypeInfo(
5917d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko        ReferenceTypeInfo::Create(handle_cache_->GetThrowableClassHandle(), /* is_exact */ false));
592bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil  } else {
593bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil    UpdateReferenceTypeInfo(instr,
594bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil                            catch_info->GetCatchTypeIndex(),
595bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil                            catch_info->GetCatchDexFile(),
596bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil                            /* is_exact */ false);
597bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil  }
598bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil}
599bbd733e4ef277eff19bf9a6601032da081e9b68fDavid Brazdil
6007d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitNullCheck(HNullCheck* instr) {
6012e76830f0b3f23825677436c0633714402715099Calin Juravle  ReferenceTypeInfo parent_rti = instr->InputAt(0)->GetReferenceTypeInfo();
602fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil  if (parent_rti.IsValid()) {
603fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil    instr->SetReferenceTypeInfo(parent_rti);
604fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil  }
6052e76830f0b3f23825677436c0633714402715099Calin Juravle}
6062e76830f0b3f23825677436c0633714402715099Calin Juravle
6077d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitBoundType(HBoundType* instr) {
608f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  ReferenceTypeInfo class_rti = instr->GetUpperBound();
609f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  if (class_rti.IsValid()) {
610a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko    ScopedObjectAccess soa(Thread::Current());
611f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // Narrow the type as much as possible.
612f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    HInstruction* obj = instr->InputAt(0);
613f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    ReferenceTypeInfo obj_rti = obj->GetReferenceTypeInfo();
614f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    if (class_rti.GetTypeHandle()->CannotBeAssignedFromOtherTypes()) {
615f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil      instr->SetReferenceTypeInfo(
616f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil          ReferenceTypeInfo::Create(class_rti.GetTypeHandle(), /* is_exact */ true));
617744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil    } else if (obj_rti.IsValid()) {
618744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil      if (class_rti.IsSupertypeOf(obj_rti)) {
619744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil        // Object type is more specific.
620744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil        instr->SetReferenceTypeInfo(obj_rti);
621744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil      } else {
622744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil        // Upper bound is more specific.
623744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil        instr->SetReferenceTypeInfo(
624744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil            ReferenceTypeInfo::Create(class_rti.GetTypeHandle(), /* is_exact */ false));
625744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil      }
626f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    } else {
627744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil      // Object not typed yet. Leave BoundType untyped for now rather than
628744a1c687fb92050828e188838b0ce5e0474f94aDavid Brazdil      // assign the type conservatively.
629f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    }
630f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    instr->SetCanBeNull(obj->CanBeNull() && instr->GetUpperCanBeNull());
631f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  } else {
632f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // The owner of the BoundType was already visited. If the class is unresolved,
633f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // the BoundType should have been removed from the data flow and this method
634f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // should remove it from the graph.
635f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    DCHECK(!instr->HasUses());
636f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    instr->GetBlock()->RemoveInstruction(instr);
637f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  }
638f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil}
639f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil
6407d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitCheckCast(HCheckCast* check_cast) {
64198893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle  HLoadClass* load_class = check_cast->InputAt(1)->AsLoadClass();
64298893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle  ReferenceTypeInfo class_rti = load_class->GetLoadedClassRTI();
643f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  HBoundType* bound_type = check_cast->GetNext()->AsBoundType();
644f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  if (bound_type == nullptr || bound_type->GetUpperBound().IsValid()) {
645f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // The next instruction is not an uninitialized BoundType. This must be
646f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // an RTP pass after SsaBuilder and we do not need to do anything.
647f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    return;
64898893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle  }
649f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  DCHECK_EQ(bound_type->InputAt(0), check_cast->InputAt(0));
650f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil
651f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  if (class_rti.IsValid()) {
652d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray    DCHECK(is_first_run_);
653f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // This is the first run of RTP and class is resolved.
654f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    bound_type->SetUpperBound(class_rti, /* CheckCast succeeds for nulls. */ true);
655f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil  } else {
656f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // This is the first run of RTP and class is unresolved. Remove the binding.
657f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // The instruction itself is removed in VisitBoundType so as to not
658f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    // invalidate HInstructionIterator.
659f555258861aea7df8af9c2241ab761227fd2f66aDavid Brazdil    bound_type->ReplaceWith(bound_type->InputAt(0));
660a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  }
661a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle}
662a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle
663b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlevoid ReferenceTypePropagation::VisitPhi(HPhi* phi) {
664d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  if (phi->IsDead() || phi->GetType() != Primitive::kPrimNot) {
665b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    return;
666acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle  }
667b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
668b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  if (phi->GetBlock()->IsLoopHeader()) {
669b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    // Set the initial type for the phi. Use the non back edge input for reaching
670b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    // a fixed point faster.
671fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil    HInstruction* first_input = phi->InputAt(0);
672fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil    ReferenceTypeInfo first_input_rti = first_input->GetReferenceTypeInfo();
673fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil    if (first_input_rti.IsValid() && !first_input->IsNullConstant()) {
674fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil      phi->SetCanBeNull(first_input->CanBeNull());
675fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil      phi->SetReferenceTypeInfo(first_input_rti);
676fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil    }
677b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    AddToWorklist(phi);
678b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  } else {
679b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    // Eagerly compute the type of the phi, for quicker convergence. Note
680b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    // that we don't need to add users to the worklist because we are
681b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    // doing a reverse post-order visit, therefore either the phi users are
682b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    // non-loop phi and will be visited later in the visit, or are loop-phis,
683b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    // and they are already in the work list.
684b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    UpdateNullability(phi);
685b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    UpdateReferenceTypeInfo(phi);
686b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  }
687b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle}
688b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
689b1498f67b444c897fa8f1530777ef118e05aa631Calin JuravleReferenceTypeInfo ReferenceTypePropagation::MergeTypes(const ReferenceTypeInfo& a,
690b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle                                                       const ReferenceTypeInfo& b) {
6912e76830f0b3f23825677436c0633714402715099Calin Juravle  if (!b.IsValid()) {
6922e76830f0b3f23825677436c0633714402715099Calin Juravle    return a;
6932e76830f0b3f23825677436c0633714402715099Calin Juravle  }
6942e76830f0b3f23825677436c0633714402715099Calin Juravle  if (!a.IsValid()) {
6952e76830f0b3f23825677436c0633714402715099Calin Juravle    return b;
6962e76830f0b3f23825677436c0633714402715099Calin Juravle  }
6972e76830f0b3f23825677436c0633714402715099Calin Juravle
698b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  bool is_exact = a.IsExact() && b.IsExact();
69952503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle  ReferenceTypeInfo::TypeHandle result_type_handle;
70052503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle  ReferenceTypeInfo::TypeHandle a_type_handle = a.GetTypeHandle();
70152503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle  ReferenceTypeInfo::TypeHandle b_type_handle = b.GetTypeHandle();
70252503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle  bool a_is_interface = a_type_handle->IsInterface();
70352503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle  bool b_is_interface = b_type_handle->IsInterface();
704b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
7052e76830f0b3f23825677436c0633714402715099Calin Juravle  if (a.GetTypeHandle().Get() == b.GetTypeHandle().Get()) {
70652503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    result_type_handle = a_type_handle;
7072e76830f0b3f23825677436c0633714402715099Calin Juravle  } else if (a.IsSupertypeOf(b)) {
70852503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    result_type_handle = a_type_handle;
7092e76830f0b3f23825677436c0633714402715099Calin Juravle    is_exact = false;
7102e76830f0b3f23825677436c0633714402715099Calin Juravle  } else if (b.IsSupertypeOf(a)) {
71152503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    result_type_handle = b_type_handle;
71252503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    is_exact = false;
71352503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle  } else if (!a_is_interface && !b_is_interface) {
7147d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    result_type_handle =
7157d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko        handle_cache_.NewHandle(a_type_handle->GetCommonSuperClass(b_type_handle));
7162e76830f0b3f23825677436c0633714402715099Calin Juravle    is_exact = false;
7172e76830f0b3f23825677436c0633714402715099Calin Juravle  } else {
71852503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    // This can happen if:
71952503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    //    - both types are interfaces. TODO(calin): implement
72052503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    //    - one is an interface, the other a class, and the type does not implement the interface
72152503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    //      e.g:
72252503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    //        void foo(Interface i, boolean cond) {
72352503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    //          Object o = cond ? i : new Object();
72452503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle    //        }
7257d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    result_type_handle = handle_cache_.GetObjectClassHandle();
7262e76830f0b3f23825677436c0633714402715099Calin Juravle    is_exact = false;
7272e76830f0b3f23825677436c0633714402715099Calin Juravle  }
7282e76830f0b3f23825677436c0633714402715099Calin Juravle
72952503d83d057c66ea50eed491290e267b80e1fd3Calin Juravle  return ReferenceTypeInfo::Create(result_type_handle, is_exact);
7302e76830f0b3f23825677436c0633714402715099Calin Juravle}
7312e76830f0b3f23825677436c0633714402715099Calin Juravle
7327d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::UpdateArrayGet(HArrayGet* instr, HandleCache* handle_cache) {
7332e76830f0b3f23825677436c0633714402715099Calin Juravle  DCHECK_EQ(Primitive::kPrimNot, instr->GetType());
7342e76830f0b3f23825677436c0633714402715099Calin Juravle
7352e76830f0b3f23825677436c0633714402715099Calin Juravle  ReferenceTypeInfo parent_rti = instr->InputAt(0)->GetReferenceTypeInfo();
736fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil  if (!parent_rti.IsValid()) {
737fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil    return;
738fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil  }
7392e76830f0b3f23825677436c0633714402715099Calin Juravle
7402e76830f0b3f23825677436c0633714402715099Calin Juravle  Handle<mirror::Class> handle = parent_rti.GetTypeHandle();
741d1d7c40c8004303d1131ebb1956fd0ade54f8404Aart Bik  if (handle->IsObjectArrayClass() && IsAdmissible(handle->GetComponentType())) {
7427d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    ReferenceTypeInfo::TypeHandle component_handle =
7437d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko        handle_cache->NewHandle(handle->GetComponentType());
74418401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray    bool is_exact = component_handle->CannotBeAssignedFromOtherTypes();
74518401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray    instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(component_handle, is_exact));
7462e76830f0b3f23825677436c0633714402715099Calin Juravle  } else {
7472e76830f0b3f23825677436c0633714402715099Calin Juravle    // We don't know what the parent actually is, so we fallback to object.
74818401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray    instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
74920e6071362b84a9782b633a893c29ebde458205eCalin Juravle  }
750b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle}
751b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
752b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlebool ReferenceTypePropagation::UpdateReferenceTypeInfo(HInstruction* instr) {
753b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  ScopedObjectAccess soa(Thread::Current());
754b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
755b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  ReferenceTypeInfo previous_rti = instr->GetReferenceTypeInfo();
756b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  if (instr->IsBoundType()) {
757b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    UpdateBoundType(instr->AsBoundType());
758b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  } else if (instr->IsPhi()) {
759b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    UpdatePhi(instr->AsPhi());
7602e76830f0b3f23825677436c0633714402715099Calin Juravle  } else if (instr->IsNullCheck()) {
7612e76830f0b3f23825677436c0633714402715099Calin Juravle    ReferenceTypeInfo parent_rti = instr->InputAt(0)->GetReferenceTypeInfo();
7622e76830f0b3f23825677436c0633714402715099Calin Juravle    if (parent_rti.IsValid()) {
7632e76830f0b3f23825677436c0633714402715099Calin Juravle      instr->SetReferenceTypeInfo(parent_rti);
7642e76830f0b3f23825677436c0633714402715099Calin Juravle    }
7652e76830f0b3f23825677436c0633714402715099Calin Juravle  } else if (instr->IsArrayGet()) {
766fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil    // TODO: consider if it's worth "looking back" and binding the input object
7672e76830f0b3f23825677436c0633714402715099Calin Juravle    // to an array type.
7687d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko    UpdateArrayGet(instr->AsArrayGet(), &handle_cache_);
76910e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle  } else {
770b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    LOG(FATAL) << "Invalid instruction (should not get here)";
771b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  }
772b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
773b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  return !previous_rti.IsEqual(instr->GetReferenceTypeInfo());
774b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle}
775b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
7767d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitInvoke(HInvoke* instr) {
777ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  if (instr->GetType() != Primitive::kPrimNot) {
778ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez    return;
779ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  }
780ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez
781ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  ScopedObjectAccess soa(Thread::Current());
782ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez  ClassLinker* cl = Runtime::Current()->GetClassLinker();
783a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko  mirror::DexCache* dex_cache =
784a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko      FindDexCacheWithHint(soa.Self(), instr->GetDexFile(), hint_dex_cache_);
78505792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko  size_t pointer_size = cl->GetImagePointerSize();
78605792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko  ArtMethod* method = dex_cache->GetResolvedMethod(instr->GetDexMethodIndex(), pointer_size);
78705792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko  mirror::Class* klass = (method == nullptr) ? nullptr : method->GetReturnType(false, pointer_size);
7882e76830f0b3f23825677436c0633714402715099Calin Juravle  SetClassAsTypeInfo(instr, klass, /* is_exact */ false);
789ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez}
790ae09d2d244cf2f506822b3e14731b81c3b278f9dGuillaume "Vermeille" Sanchez
7917d1fbf38412078090e81e9d9fa502635d8541707Vladimir Markovoid ReferenceTypePropagation::RTPVisitor::VisitArrayGet(HArrayGet* instr) {
79272a5eb5d6784b318750c36e0da25c7338557ce44Guillaume "Vermeille" Sanchez  if (instr->GetType() != Primitive::kPrimNot) {
79372a5eb5d6784b318750c36e0da25c7338557ce44Guillaume "Vermeille" Sanchez    return;
79472a5eb5d6784b318750c36e0da25c7338557ce44Guillaume "Vermeille" Sanchez  }
795fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil
79672a5eb5d6784b318750c36e0da25c7338557ce44Guillaume "Vermeille" Sanchez  ScopedObjectAccess soa(Thread::Current());
7977d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko  UpdateArrayGet(instr, handle_cache_);
7982e76830f0b3f23825677436c0633714402715099Calin Juravle  if (!instr->GetReferenceTypeInfo().IsValid()) {
7992aaa4b5532d30c4e65d8892b556400bb61f9dc8cVladimir Marko    worklist_->push_back(instr);
80072a5eb5d6784b318750c36e0da25c7338557ce44Guillaume "Vermeille" Sanchez  }
80172a5eb5d6784b318750c36e0da25c7338557ce44Guillaume "Vermeille" Sanchez}
80272a5eb5d6784b318750c36e0da25c7338557ce44Guillaume "Vermeille" Sanchez
803b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlevoid ReferenceTypePropagation::UpdateBoundType(HBoundType* instr) {
804b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  ReferenceTypeInfo new_rti = instr->InputAt(0)->GetReferenceTypeInfo();
8052e76830f0b3f23825677436c0633714402715099Calin Juravle  if (!new_rti.IsValid()) {
8062e76830f0b3f23825677436c0633714402715099Calin Juravle    return;  // No new info yet.
8072e76830f0b3f23825677436c0633714402715099Calin Juravle  }
8082e76830f0b3f23825677436c0633714402715099Calin Juravle
8092e76830f0b3f23825677436c0633714402715099Calin Juravle  // Make sure that we don't go over the bounded type.
810a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  ReferenceTypeInfo upper_bound_rti = instr->GetUpperBound();
811a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  if (!upper_bound_rti.IsSupertypeOf(new_rti)) {
812e1dfa0c120c8aaa3794d9712e37231b4295d7c46Nicolas Geoffray    // Note that the input might be exact, in which case we know the branch leading
813e1dfa0c120c8aaa3794d9712e37231b4295d7c46Nicolas Geoffray    // to the bound type is dead. We play it safe by not marking the bound type as
814e1dfa0c120c8aaa3794d9712e37231b4295d7c46Nicolas Geoffray    // exact.
815e1dfa0c120c8aaa3794d9712e37231b4295d7c46Nicolas Geoffray    bool is_exact = upper_bound_rti.GetTypeHandle()->CannotBeAssignedFromOtherTypes();
816e1dfa0c120c8aaa3794d9712e37231b4295d7c46Nicolas Geoffray    new_rti = ReferenceTypeInfo::Create(upper_bound_rti.GetTypeHandle(), is_exact);
817b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  }
818b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  instr->SetReferenceTypeInfo(new_rti);
819b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle}
820b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
821617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle// NullConstant inputs are ignored during merging as they do not provide any useful information.
822617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle// If all the inputs are NullConstants then the type of the phi will be set to Object.
823b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlevoid ReferenceTypePropagation::UpdatePhi(HPhi* instr) {
824d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  DCHECK(instr->IsLive());
825d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil
826617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle  size_t input_count = instr->InputCount();
827617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle  size_t first_input_index_not_null = 0;
828617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle  while (first_input_index_not_null < input_count &&
829617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle      instr->InputAt(first_input_index_not_null)->IsNullConstant()) {
830617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle    first_input_index_not_null++;
831617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle  }
832617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle  if (first_input_index_not_null == input_count) {
833617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle    // All inputs are NullConstants, set the type to object.
834617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle    // This may happen in the presence of inlining.
83518401b748a3180f52e42547ede22d1b184fe8c43Nicolas Geoffray    instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
836617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle    return;
837617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle  }
838617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle
839617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle  ReferenceTypeInfo new_rti = instr->InputAt(first_input_index_not_null)->GetReferenceTypeInfo();
840617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle
8412e76830f0b3f23825677436c0633714402715099Calin Juravle  if (new_rti.IsValid() && new_rti.IsObjectClass() && !new_rti.IsExact()) {
8422e76830f0b3f23825677436c0633714402715099Calin Juravle    // Early return if we are Object and inexact.
843b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    instr->SetReferenceTypeInfo(new_rti);
844b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    return;
845b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  }
846617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle
847617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle  for (size_t i = first_input_index_not_null + 1; i < input_count; i++) {
848617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle    if (instr->InputAt(i)->IsNullConstant()) {
849617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle      continue;
850617bd9255bbdb9890e9d80462d293b94ba41c1f2Calin Juravle    }
851b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle    new_rti = MergeTypes(new_rti, instr->InputAt(i)->GetReferenceTypeInfo());
8522e76830f0b3f23825677436c0633714402715099Calin Juravle    if (new_rti.IsValid() && new_rti.IsObjectClass()) {
853b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle      if (!new_rti.IsExact()) {
854b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle        break;
855b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle      } else {
856b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle        continue;
857d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      }
85810e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle    }
85910e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle  }
860fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil
861fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil  if (new_rti.IsValid()) {
862fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil    instr->SetReferenceTypeInfo(new_rti);
863fe86070bcbe938a5c8dec02b5a7d5efb632deed1David Brazdil  }
864b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle}
865b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
866b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle// Re-computes and updates the nullability of the instruction. Returns whether or
867b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle// not the nullability was changed.
868b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlebool ReferenceTypePropagation::UpdateNullability(HInstruction* instr) {
869d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil  DCHECK((instr->IsPhi() && instr->AsPhi()->IsLive())
8702e76830f0b3f23825677436c0633714402715099Calin Juravle      || instr->IsBoundType()
8712e76830f0b3f23825677436c0633714402715099Calin Juravle      || instr->IsNullCheck()
8722e76830f0b3f23825677436c0633714402715099Calin Juravle      || instr->IsArrayGet());
8732e76830f0b3f23825677436c0633714402715099Calin Juravle
8742e76830f0b3f23825677436c0633714402715099Calin Juravle  if (!instr->IsPhi() && !instr->IsBoundType()) {
8752e76830f0b3f23825677436c0633714402715099Calin Juravle    return false;
8762e76830f0b3f23825677436c0633714402715099Calin Juravle  }
877b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle
878a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  bool existing_can_be_null = instr->CanBeNull();
879a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  if (instr->IsPhi()) {
880a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    HPhi* phi = instr->AsPhi();
881a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    bool new_can_be_null = false;
882a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    for (size_t i = 0; i < phi->InputCount(); i++) {
883a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle      if (phi->InputAt(i)->CanBeNull()) {
884a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        new_can_be_null = true;
885a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle        break;
886a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle      }
887a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    }
888a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    phi->SetCanBeNull(new_can_be_null);
889a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  } else if (instr->IsBoundType()) {
890a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    HBoundType* bound_type = instr->AsBoundType();
891a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle    bound_type->SetCanBeNull(instr->InputAt(0)->CanBeNull() && bound_type->GetUpperCanBeNull());
892b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravle  }
893a5ae3c3f468ffe3a317b498d7fde1f8e9325346aCalin Juravle  return existing_can_be_null != instr->CanBeNull();
89410e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle}
89510e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle
89610e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravlevoid ReferenceTypePropagation::ProcessWorklist() {
8972aaa4b5532d30c4e65d8892b556400bb61f9dc8cVladimir Marko  while (!worklist_.empty()) {
8982aaa4b5532d30c4e65d8892b556400bb61f9dc8cVladimir Marko    HInstruction* instruction = worklist_.back();
8992aaa4b5532d30c4e65d8892b556400bb61f9dc8cVladimir Marko    worklist_.pop_back();
90012617599757b625bd59e6c62e022c30735073622Calin Juravle    bool updated_nullability = UpdateNullability(instruction);
90112617599757b625bd59e6c62e022c30735073622Calin Juravle    bool updated_reference_type = UpdateReferenceTypeInfo(instruction);
90212617599757b625bd59e6c62e022c30735073622Calin Juravle    if (updated_nullability || updated_reference_type) {
90310e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle      AddDependentInstructionsToWorklist(instruction);
90410e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle    }
90510e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle  }
90610e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle}
90710e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle
908b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlevoid ReferenceTypePropagation::AddToWorklist(HInstruction* instruction) {
9092e76830f0b3f23825677436c0633714402715099Calin Juravle  DCHECK_EQ(instruction->GetType(), Primitive::kPrimNot)
9102e76830f0b3f23825677436c0633714402715099Calin Juravle      << instruction->DebugName() << ":" << instruction->GetType();
9112aaa4b5532d30c4e65d8892b556400bb61f9dc8cVladimir Marko  worklist_.push_back(instruction);
91210e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle}
91310e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle
914b1498f67b444c897fa8f1530777ef118e05aa631Calin Juravlevoid ReferenceTypePropagation::AddDependentInstructionsToWorklist(HInstruction* instruction) {
915d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  for (const HUseListNode<HInstruction*>& use : instruction->GetUses()) {
916d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    HInstruction* user = use.GetUser();
917d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil    if ((user->IsPhi() && user->AsPhi()->IsLive())
9182e76830f0b3f23825677436c0633714402715099Calin Juravle       || user->IsBoundType()
9192e76830f0b3f23825677436c0633714402715099Calin Juravle       || user->IsNullCheck()
9202e76830f0b3f23825677436c0633714402715099Calin Juravle       || (user->IsArrayGet() && (user->GetType() == Primitive::kPrimNot))) {
921beba9302bec33d72beb582970bf23d056f62641fCalin Juravle      AddToWorklist(user);
92210e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle    }
92310e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle  }
92410e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle}
9257d1fbf38412078090e81e9d9fa502635d8541707Vladimir Marko
92610e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle}  // namespace art
927