blob: c3db55143bea1c849ebd582d7ee294e703f7c336 [file] [log] [blame]
Calin Juravle10e244f2015-01-26 18:54:32 +00001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "reference_type_propagation.h"
18
Mathieu Chartiere401d142015-04-22 13:56:20 -070019#include "class_linker-inl.h"
Calin Juravleacf735c2015-02-12 15:25:22 +000020#include "mirror/class-inl.h"
21#include "mirror/dex_cache.h"
22#include "scoped_thread_state_change.h"
23
Calin Juravle10e244f2015-01-26 18:54:32 +000024namespace art {
25
Guillaume "Vermeille" Sanchezae09d2d2015-05-29 10:52:55 +010026class RTPVisitor : public HGraphDelegateVisitor {
27 public:
28 RTPVisitor(HGraph* graph, StackHandleScopeCollection* handles)
29 : HGraphDelegateVisitor(graph),
30 handles_(handles) {}
31
32 void VisitNewInstance(HNewInstance* new_instance) OVERRIDE;
33 void VisitLoadClass(HLoadClass* load_class) OVERRIDE;
34 void VisitNewArray(HNewArray* instr) OVERRIDE;
35 void UpdateFieldAccessTypeInfo(HInstruction* instr, const FieldInfo& info);
36 void SetClassAsTypeInfo(HInstruction* instr, mirror::Class* klass, bool is_exact);
37 void VisitInstanceFieldGet(HInstanceFieldGet* instr) OVERRIDE;
38 void VisitStaticFieldGet(HStaticFieldGet* instr) OVERRIDE;
39 void VisitInvoke(HInvoke* instr) OVERRIDE;
40 void UpdateReferenceTypeInfo(HInstruction* instr,
41 uint16_t type_idx,
42 const DexFile& dex_file,
43 bool is_exact);
44
45 private:
46 StackHandleScopeCollection* handles_;
47};
48
Calin Juravleacf735c2015-02-12 15:25:22 +000049void ReferenceTypePropagation::Run() {
50 // To properly propagate type info we need to visit in the dominator-based order.
Calin Juravle10e244f2015-01-26 18:54:32 +000051 // Reverse post order guarantees a node's dominators are visited first.
52 // We take advantage of this order in `VisitBasicBlock`.
Calin Juravle6c0c4f22015-06-12 15:40:42 +000053 for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
Calin Juravle10e244f2015-01-26 18:54:32 +000054 VisitBasicBlock(it.Current());
55 }
56 ProcessWorklist();
57}
58
Calin Juravleb1498f62015-02-16 13:13:29 +000059void ReferenceTypePropagation::VisitBasicBlock(HBasicBlock* block) {
60 // TODO: handle other instructions that give type info
Guillaume "Vermeille" Sanchezae09d2d2015-05-29 10:52:55 +010061 // (array accesses)
Calin Juravle10e244f2015-01-26 18:54:32 +000062
Guillaume "Vermeille" Sanchezae09d2d2015-05-29 10:52:55 +010063 RTPVisitor visitor(graph_, handles_);
Calin Juravleb1498f62015-02-16 13:13:29 +000064 // Initialize exact types first for faster convergence.
65 for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
66 HInstruction* instr = it.Current();
Guillaume "Vermeille" Sanchezae09d2d2015-05-29 10:52:55 +010067 instr->Accept(&visitor);
Calin Juravleb1498f62015-02-16 13:13:29 +000068 }
69
70 // Handle Phis.
71 for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
72 VisitPhi(it.Current()->AsPhi());
73 }
74
75 // Add extra nodes to bound types.
Calin Juravle61d544b2015-02-23 16:46:57 +000076 BoundTypeForIfNotNull(block);
Calin Juravleb1498f62015-02-16 13:13:29 +000077 BoundTypeForIfInstanceOf(block);
Calin Juravle10e244f2015-01-26 18:54:32 +000078}
79
Calin Juravle61d544b2015-02-23 16:46:57 +000080void ReferenceTypePropagation::BoundTypeForIfNotNull(HBasicBlock* block) {
Calin Juravleb3306642015-04-20 18:30:42 +010081 HIf* ifInstruction = block->GetLastInstruction()->AsIf();
82 if (ifInstruction == nullptr) {
Calin Juravle61d544b2015-02-23 16:46:57 +000083 return;
84 }
Calin Juravleb3306642015-04-20 18:30:42 +010085 HInstruction* ifInput = ifInstruction->InputAt(0);
Calin Juravle61d544b2015-02-23 16:46:57 +000086 if (!ifInput->IsNotEqual() && !ifInput->IsEqual()) {
87 return;
88 }
89 HInstruction* input0 = ifInput->InputAt(0);
90 HInstruction* input1 = ifInput->InputAt(1);
Calin Juravleedad8ad2015-04-23 14:34:33 +010091 HInstruction* obj = nullptr;
Calin Juravle61d544b2015-02-23 16:46:57 +000092
Calin Juravleedad8ad2015-04-23 14:34:33 +010093 if (input1->IsNullConstant()) {
Calin Juravle61d544b2015-02-23 16:46:57 +000094 obj = input0;
Calin Juravleedad8ad2015-04-23 14:34:33 +010095 } else if (input0->IsNullConstant()) {
Calin Juravle61d544b2015-02-23 16:46:57 +000096 obj = input1;
97 } else {
98 return;
99 }
100
Calin Juravleb3306642015-04-20 18:30:42 +0100101 // We only need to bound the type if we have uses in the relevant block.
102 // So start with null and create the HBoundType lazily, only if it's needed.
103 HBoundType* bound_type = nullptr;
Calin Juravle61d544b2015-02-23 16:46:57 +0000104 HBasicBlock* notNullBlock = ifInput->IsNotEqual()
Calin Juravleb3306642015-04-20 18:30:42 +0100105 ? ifInstruction->IfTrueSuccessor()
106 : ifInstruction->IfFalseSuccessor();
107
Calin Juravle61d544b2015-02-23 16:46:57 +0000108 for (HUseIterator<HInstruction*> it(obj->GetUses()); !it.Done(); it.Advance()) {
109 HInstruction* user = it.Current()->GetUser();
110 if (notNullBlock->Dominates(user->GetBlock())) {
Calin Juravleb3306642015-04-20 18:30:42 +0100111 if (bound_type == nullptr) {
Calin Juravle6c0c4f22015-06-12 15:40:42 +0000112 bound_type = new (graph_->GetArena()) HBoundType(obj, ReferenceTypeInfo::CreateTop(false));
Calin Juravleb3306642015-04-20 18:30:42 +0100113 notNullBlock->InsertInstructionBefore(bound_type, notNullBlock->GetFirstInstruction());
114 }
Calin Juravle61d544b2015-02-23 16:46:57 +0000115 user->ReplaceInput(bound_type, it.Current()->GetIndex());
116 }
117 }
118}
119
Calin Juravleb1498f62015-02-16 13:13:29 +0000120// Detects if `block` is the True block for the pattern
121// `if (x instanceof ClassX) { }`
122// If that's the case insert an HBoundType instruction to bound the type of `x`
123// to `ClassX` in the scope of the dominated blocks.
124void ReferenceTypePropagation::BoundTypeForIfInstanceOf(HBasicBlock* block) {
Calin Juravleb3306642015-04-20 18:30:42 +0100125 HIf* ifInstruction = block->GetLastInstruction()->AsIf();
126 if (ifInstruction == nullptr) {
Calin Juravleb1498f62015-02-16 13:13:29 +0000127 return;
128 }
Calin Juravleb3306642015-04-20 18:30:42 +0100129 HInstruction* ifInput = ifInstruction->InputAt(0);
130 HInstruction* instanceOf = nullptr;
131 HBasicBlock* instanceOfTrueBlock = nullptr;
David Brazdil0d13fee2015-04-17 14:52:19 +0100132
Calin Juravleb3306642015-04-20 18:30:42 +0100133 // The instruction simplifier has transformed:
134 // - `if (a instanceof A)` into an HIf with an HInstanceOf input
135 // - `if (!(a instanceof A)` into an HIf with an HBooleanNot input (which in turn
136 // has an HInstanceOf input)
137 // So we should not see the usual HEqual here.
David Brazdil0d13fee2015-04-17 14:52:19 +0100138 if (ifInput->IsInstanceOf()) {
139 instanceOf = ifInput;
Calin Juravleb3306642015-04-20 18:30:42 +0100140 instanceOfTrueBlock = ifInstruction->IfTrueSuccessor();
David Brazdil0d13fee2015-04-17 14:52:19 +0100141 } else if (ifInput->IsBooleanNot() && ifInput->InputAt(0)->IsInstanceOf()) {
142 instanceOf = ifInput->InputAt(0);
Calin Juravleb3306642015-04-20 18:30:42 +0100143 instanceOfTrueBlock = ifInstruction->IfFalseSuccessor();
David Brazdil0d13fee2015-04-17 14:52:19 +0100144 } else {
Calin Juravleb1498f62015-02-16 13:13:29 +0000145 return;
Calin Juravleacf735c2015-02-12 15:25:22 +0000146 }
147
Calin Juravleb3306642015-04-20 18:30:42 +0100148 // We only need to bound the type if we have uses in the relevant block.
149 // So start with null and create the HBoundType lazily, only if it's needed.
150 HBoundType* bound_type = nullptr;
151
Calin Juravleb1498f62015-02-16 13:13:29 +0000152 HInstruction* obj = instanceOf->InputAt(0);
Calin Juravleb1498f62015-02-16 13:13:29 +0000153 for (HUseIterator<HInstruction*> it(obj->GetUses()); !it.Done(); it.Advance()) {
154 HInstruction* user = it.Current()->GetUser();
155 if (instanceOfTrueBlock->Dominates(user->GetBlock())) {
Calin Juravleb3306642015-04-20 18:30:42 +0100156 if (bound_type == nullptr) {
157 HLoadClass* load_class = instanceOf->InputAt(1)->AsLoadClass();
158
159 ReferenceTypeInfo obj_rti = obj->GetReferenceTypeInfo();
160 ReferenceTypeInfo class_rti = load_class->GetLoadedClassRTI();
Calin Juravle6c0c4f22015-06-12 15:40:42 +0000161 bound_type = new (graph_->GetArena()) HBoundType(obj, class_rti);
Calin Juravleb3306642015-04-20 18:30:42 +0100162
163 // Narrow the type as much as possible.
164 {
165 ScopedObjectAccess soa(Thread::Current());
166 if (!load_class->IsResolved() || class_rti.IsSupertypeOf(obj_rti)) {
167 bound_type->SetReferenceTypeInfo(obj_rti);
168 } else {
169 bound_type->SetReferenceTypeInfo(
170 ReferenceTypeInfo::Create(class_rti.GetTypeHandle(), /* is_exact */ false));
171 }
172 }
173
174 instanceOfTrueBlock->InsertInstructionBefore(
175 bound_type, instanceOfTrueBlock->GetFirstInstruction());
176 }
Calin Juravleb1498f62015-02-16 13:13:29 +0000177 user->ReplaceInput(bound_type, it.Current()->GetIndex());
178 }
179 }
Calin Juravleacf735c2015-02-12 15:25:22 +0000180}
181
Guillaume "Vermeille" Sanchezae09d2d2015-05-29 10:52:55 +0100182void RTPVisitor::SetClassAsTypeInfo(HInstruction* instr,
183 mirror::Class* klass,
184 bool is_exact) {
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100185 if (klass != nullptr) {
186 ScopedObjectAccess soa(Thread::Current());
187 MutableHandle<mirror::Class> handle = handles_->NewHandle(klass);
Guillaume Sanchez222862c2015-06-09 18:33:02 +0100188 is_exact = is_exact || klass->IsFinal();
189 instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(handle, is_exact));
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100190 }
191}
192
Guillaume "Vermeille" Sanchezae09d2d2015-05-29 10:52:55 +0100193void RTPVisitor::UpdateReferenceTypeInfo(HInstruction* instr,
194 uint16_t type_idx,
195 const DexFile& dex_file,
196 bool is_exact) {
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +0100197 DCHECK_EQ(instr->GetType(), Primitive::kPrimNot);
198
Calin Juravleacf735c2015-02-12 15:25:22 +0000199 ScopedObjectAccess soa(Thread::Current());
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +0100200 mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file);
Calin Juravleacf735c2015-02-12 15:25:22 +0000201 // Get type from dex cache assuming it was populated by the verifier.
Guillaume Sanchez222862c2015-06-09 18:33:02 +0100202 SetClassAsTypeInfo(instr, dex_cache->GetResolvedType(type_idx), is_exact);
Calin Juravleacf735c2015-02-12 15:25:22 +0000203}
204
Guillaume "Vermeille" Sanchezae09d2d2015-05-29 10:52:55 +0100205void RTPVisitor::VisitNewInstance(HNewInstance* instr) {
Guillaume Sanchez222862c2015-06-09 18:33:02 +0100206 UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile(), /* is_exact */ true);
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +0100207}
208
Guillaume "Vermeille" Sanchezae09d2d2015-05-29 10:52:55 +0100209void RTPVisitor::VisitNewArray(HNewArray* instr) {
Guillaume Sanchez222862c2015-06-09 18:33:02 +0100210 UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile(), /* is_exact */ true);
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +0100211}
212
Guillaume "Vermeille" Sanchezae09d2d2015-05-29 10:52:55 +0100213void RTPVisitor::UpdateFieldAccessTypeInfo(HInstruction* instr,
214 const FieldInfo& info) {
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100215 // The field index is unknown only during tests.
216 if (instr->GetType() != Primitive::kPrimNot || info.GetFieldIndex() == kUnknownFieldIndex) {
217 return;
218 }
219
220 ScopedObjectAccess soa(Thread::Current());
221 ClassLinker* cl = Runtime::Current()->GetClassLinker();
222 mirror::DexCache* dex_cache = cl->FindDexCache(info.GetDexFile());
223 ArtField* field = cl->GetResolvedField(info.GetFieldIndex(), dex_cache);
224 DCHECK(field != nullptr);
225 mirror::Class* klass = field->GetType<false>();
Guillaume Sanchez222862c2015-06-09 18:33:02 +0100226 SetClassAsTypeInfo(instr, klass, /* is_exact */ false);
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100227}
228
Guillaume "Vermeille" Sanchezae09d2d2015-05-29 10:52:55 +0100229void RTPVisitor::VisitInstanceFieldGet(HInstanceFieldGet* instr) {
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100230 UpdateFieldAccessTypeInfo(instr, instr->GetFieldInfo());
231}
232
Guillaume "Vermeille" Sanchezae09d2d2015-05-29 10:52:55 +0100233void RTPVisitor::VisitStaticFieldGet(HStaticFieldGet* instr) {
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100234 UpdateFieldAccessTypeInfo(instr, instr->GetFieldInfo());
235}
236
Guillaume "Vermeille" Sanchezae09d2d2015-05-29 10:52:55 +0100237void RTPVisitor::VisitLoadClass(HLoadClass* instr) {
Calin Juravleacf735c2015-02-12 15:25:22 +0000238 ScopedObjectAccess soa(Thread::Current());
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +0100239 mirror::DexCache* dex_cache =
240 Runtime::Current()->GetClassLinker()->FindDexCache(instr->GetDexFile());
Calin Juravleacf735c2015-02-12 15:25:22 +0000241 // Get type from dex cache assuming it was populated by the verifier.
242 mirror::Class* resolved_class = dex_cache->GetResolvedType(instr->GetTypeIndex());
243 if (resolved_class != nullptr) {
244 Handle<mirror::Class> handle = handles_->NewHandle(resolved_class);
Calin Juravleb1498f62015-02-16 13:13:29 +0000245 instr->SetLoadedClassRTI(ReferenceTypeInfo::Create(handle, /* is_exact */ true));
Calin Juravleacf735c2015-02-12 15:25:22 +0000246 }
247 Handle<mirror::Class> class_handle = handles_->NewHandle(mirror::Class::GetJavaLangClass());
Calin Juravleb1498f62015-02-16 13:13:29 +0000248 instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(class_handle, /* is_exact */ true));
Calin Juravleacf735c2015-02-12 15:25:22 +0000249}
Calin Juravle10e244f2015-01-26 18:54:32 +0000250
Calin Juravleb1498f62015-02-16 13:13:29 +0000251void ReferenceTypePropagation::VisitPhi(HPhi* phi) {
252 if (phi->GetType() != Primitive::kPrimNot) {
253 return;
Calin Juravleacf735c2015-02-12 15:25:22 +0000254 }
Calin Juravleb1498f62015-02-16 13:13:29 +0000255
256 if (phi->GetBlock()->IsLoopHeader()) {
257 // Set the initial type for the phi. Use the non back edge input for reaching
258 // a fixed point faster.
259 AddToWorklist(phi);
260 phi->SetCanBeNull(phi->InputAt(0)->CanBeNull());
261 phi->SetReferenceTypeInfo(phi->InputAt(0)->GetReferenceTypeInfo());
Calin Juravle10e244f2015-01-26 18:54:32 +0000262 } else {
Calin Juravleb1498f62015-02-16 13:13:29 +0000263 // Eagerly compute the type of the phi, for quicker convergence. Note
264 // that we don't need to add users to the worklist because we are
265 // doing a reverse post-order visit, therefore either the phi users are
266 // non-loop phi and will be visited later in the visit, or are loop-phis,
267 // and they are already in the work list.
268 UpdateNullability(phi);
269 UpdateReferenceTypeInfo(phi);
270 }
271}
272
273ReferenceTypeInfo ReferenceTypePropagation::MergeTypes(const ReferenceTypeInfo& a,
274 const ReferenceTypeInfo& b) {
275 bool is_exact = a.IsExact() && b.IsExact();
276 bool is_top = a.IsTop() || b.IsTop();
277 Handle<mirror::Class> type_handle;
278
279 if (!is_top) {
280 if (a.GetTypeHandle().Get() == b.GetTypeHandle().Get()) {
281 type_handle = a.GetTypeHandle();
282 } else if (a.IsSupertypeOf(b)) {
283 type_handle = a.GetTypeHandle();
284 is_exact = false;
285 } else if (b.IsSupertypeOf(a)) {
286 type_handle = b.GetTypeHandle();
287 is_exact = false;
288 } else {
289 // TODO: Find a common super class.
290 is_top = true;
291 is_exact = false;
292 }
293 }
294
295 return is_top
296 ? ReferenceTypeInfo::CreateTop(is_exact)
297 : ReferenceTypeInfo::Create(type_handle, is_exact);
298}
299
300bool ReferenceTypePropagation::UpdateReferenceTypeInfo(HInstruction* instr) {
301 ScopedObjectAccess soa(Thread::Current());
302
303 ReferenceTypeInfo previous_rti = instr->GetReferenceTypeInfo();
304 if (instr->IsBoundType()) {
305 UpdateBoundType(instr->AsBoundType());
306 } else if (instr->IsPhi()) {
307 UpdatePhi(instr->AsPhi());
308 } else {
309 LOG(FATAL) << "Invalid instruction (should not get here)";
310 }
311
312 return !previous_rti.IsEqual(instr->GetReferenceTypeInfo());
313}
314
Guillaume "Vermeille" Sanchezae09d2d2015-05-29 10:52:55 +0100315void RTPVisitor::VisitInvoke(HInvoke* instr) {
316 if (instr->GetType() != Primitive::kPrimNot) {
317 return;
318 }
319
320 ScopedObjectAccess soa(Thread::Current());
321 ClassLinker* cl = Runtime::Current()->GetClassLinker();
322 mirror::DexCache* dex_cache = cl->FindDexCache(instr->GetDexFile());
323 ArtMethod* method = dex_cache->GetResolvedMethod(
324 instr->GetDexMethodIndex(), cl->GetImagePointerSize());
325 DCHECK(method != nullptr);
326 mirror::Class* klass = method->GetReturnType(false);
327 SetClassAsTypeInfo(instr, klass, /* is_exact */ false);
328}
329
Calin Juravleb1498f62015-02-16 13:13:29 +0000330void ReferenceTypePropagation::UpdateBoundType(HBoundType* instr) {
331 ReferenceTypeInfo new_rti = instr->InputAt(0)->GetReferenceTypeInfo();
332 // Be sure that we don't go over the bounded type.
333 ReferenceTypeInfo bound_rti = instr->GetBoundType();
334 if (!bound_rti.IsSupertypeOf(new_rti)) {
335 new_rti = bound_rti;
336 }
337 instr->SetReferenceTypeInfo(new_rti);
338}
339
340void ReferenceTypePropagation::UpdatePhi(HPhi* instr) {
341 ReferenceTypeInfo new_rti = instr->InputAt(0)->GetReferenceTypeInfo();
342 if (new_rti.IsTop() && !new_rti.IsExact()) {
343 // Early return if we are Top and inexact.
344 instr->SetReferenceTypeInfo(new_rti);
345 return;
346 }
347 for (size_t i = 1; i < instr->InputCount(); i++) {
348 new_rti = MergeTypes(new_rti, instr->InputAt(i)->GetReferenceTypeInfo());
349 if (new_rti.IsTop()) {
350 if (!new_rti.IsExact()) {
351 break;
352 } else {
353 continue;
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000354 }
Calin Juravle10e244f2015-01-26 18:54:32 +0000355 }
356 }
Calin Juravleb1498f62015-02-16 13:13:29 +0000357 instr->SetReferenceTypeInfo(new_rti);
358}
359
360// Re-computes and updates the nullability of the instruction. Returns whether or
361// not the nullability was changed.
362bool ReferenceTypePropagation::UpdateNullability(HInstruction* instr) {
363 DCHECK(instr->IsPhi() || instr->IsBoundType());
364
365 if (!instr->IsPhi()) {
366 return false;
367 }
368
369 HPhi* phi = instr->AsPhi();
370 bool existing_can_be_null = phi->CanBeNull();
371 bool new_can_be_null = false;
372 for (size_t i = 0; i < phi->InputCount(); i++) {
373 new_can_be_null |= phi->InputAt(i)->CanBeNull();
374 }
375 phi->SetCanBeNull(new_can_be_null);
376
377 return existing_can_be_null != new_can_be_null;
Calin Juravle10e244f2015-01-26 18:54:32 +0000378}
379
380void ReferenceTypePropagation::ProcessWorklist() {
381 while (!worklist_.IsEmpty()) {
Calin Juravleb1498f62015-02-16 13:13:29 +0000382 HInstruction* instruction = worklist_.Pop();
Calin Juravleacf735c2015-02-12 15:25:22 +0000383 if (UpdateNullability(instruction) || UpdateReferenceTypeInfo(instruction)) {
Calin Juravle10e244f2015-01-26 18:54:32 +0000384 AddDependentInstructionsToWorklist(instruction);
385 }
386 }
387}
388
Calin Juravleb1498f62015-02-16 13:13:29 +0000389void ReferenceTypePropagation::AddToWorklist(HInstruction* instruction) {
390 DCHECK_EQ(instruction->GetType(), Primitive::kPrimNot) << instruction->GetType();
Calin Juravle10e244f2015-01-26 18:54:32 +0000391 worklist_.Add(instruction);
392}
393
Calin Juravleb1498f62015-02-16 13:13:29 +0000394void ReferenceTypePropagation::AddDependentInstructionsToWorklist(HInstruction* instruction) {
Calin Juravle10e244f2015-01-26 18:54:32 +0000395 for (HUseIterator<HInstruction*> it(instruction->GetUses()); !it.Done(); it.Advance()) {
Calin Juravleb1498f62015-02-16 13:13:29 +0000396 HInstruction* user = it.Current()->GetUser();
397 if (user->IsPhi() || user->IsBoundType()) {
398 AddToWorklist(user);
Calin Juravle10e244f2015-01-26 18:54:32 +0000399 }
400 }
401}
Calin Juravle10e244f2015-01-26 18:54:32 +0000402} // namespace art