blob: c221282b9b99688c116b30a8f4e79bd90649305f [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#ifndef ART_COMPILER_OPTIMIZING_REFERENCE_TYPE_PROPAGATION_H_
18#define ART_COMPILER_OPTIMIZING_REFERENCE_TYPE_PROPAGATION_H_
19
Vladimir Marko2aaa4b52015-09-17 17:03:26 +010020#include "base/arena_containers.h"
Calin Juravleacf735c2015-02-12 15:25:22 +000021#include "driver/dex_compilation_unit.h"
22#include "handle_scope-inl.h"
Calin Juravle10e244f2015-01-26 18:54:32 +000023#include "nodes.h"
Mathieu Chartier3398c782016-09-30 10:27:43 -070024#include "obj_ptr.h"
Calin Juravle10e244f2015-01-26 18:54:32 +000025#include "optimization.h"
Calin Juravleb1498f62015-02-16 13:13:29 +000026#include "optimizing_compiler_stats.h"
Calin Juravle10e244f2015-01-26 18:54:32 +000027
28namespace art {
29
30/**
31 * Propagates reference types to instructions.
Calin Juravle10e244f2015-01-26 18:54:32 +000032 */
Calin Juravle6c0c4f22015-06-12 15:40:42 +000033class ReferenceTypePropagation : public HOptimization {
Calin Juravle10e244f2015-01-26 18:54:32 +000034 public:
Calin Juravlea5ae3c32015-07-28 14:40:50 +000035 ReferenceTypePropagation(HGraph* graph,
Vladimir Marko8d6768d2017-03-14 10:13:21 +000036 Handle<mirror::ClassLoader> class_loader,
Vladimir Marko456307a2016-04-19 14:12:13 +000037 Handle<mirror::DexCache> hint_dex_cache,
Mathieu Chartiere8a3c572016-10-11 16:52:17 -070038 VariableSizedHandleScope* handles,
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +000039 bool is_first_run,
Calin Juravle2e768302015-07-28 14:41:11 +000040 const char* name = kReferenceTypePropagationPassName);
Calin Juravle10e244f2015-01-26 18:54:32 +000041
Vladimir Markobe10e8e2016-01-22 12:09:44 +000042 // Visit a single instruction.
43 void Visit(HInstruction* instruction);
44
Calin Juravle10e244f2015-01-26 18:54:32 +000045 void Run() OVERRIDE;
46
David Brazdil94ab38f2016-06-21 17:48:19 +010047 // Returns true if klass is admissible to the propagation: non-null and resolved.
48 // For an array type, we also check if the component type is admissible.
Vladimir Markob45528c2017-07-27 14:14:28 +010049 static bool IsAdmissible(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
David Brazdil94ab38f2016-06-21 17:48:19 +010050 return klass != nullptr &&
51 klass->IsResolved() &&
52 (!klass->IsArrayClass() || IsAdmissible(klass->GetComponentType()));
53 }
54
Andreas Gampe7c3952f2015-02-19 18:21:24 -080055 static constexpr const char* kReferenceTypePropagationPassName = "reference_type_propagation";
56
Mads Ager16e52892017-07-14 13:11:37 +020057 // Fix the reference type for an instruction whose inputs have changed.
58 // For a select instruction, the reference types of the inputs are merged
59 // and the resulting reference type is set on the select instruction.
60 static void FixUpInstructionType(HInstruction* instruction,
61 VariableSizedHandleScope* handle_scope);
62
Calin Juravle10e244f2015-01-26 18:54:32 +000063 private:
Vladimir Marko7d1fbf32016-01-26 15:01:12 +000064 class HandleCache {
65 public:
Mathieu Chartiere8a3c572016-10-11 16:52:17 -070066 explicit HandleCache(VariableSizedHandleScope* handles) : handles_(handles) { }
Vladimir Marko7d1fbf32016-01-26 15:01:12 +000067
68 template <typename T>
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070069 MutableHandle<T> NewHandle(T* object) REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko7d1fbf32016-01-26 15:01:12 +000070 return handles_->NewHandle(object);
71 }
72
Mathieu Chartier3398c782016-09-30 10:27:43 -070073 template <typename T>
74 MutableHandle<T> NewHandle(ObjPtr<T> object) REQUIRES_SHARED(Locks::mutator_lock_) {
75 return handles_->NewHandle(object);
76 }
77
Vladimir Marko7d1fbf32016-01-26 15:01:12 +000078 ReferenceTypeInfo::TypeHandle GetObjectClassHandle();
79 ReferenceTypeInfo::TypeHandle GetClassClassHandle();
80 ReferenceTypeInfo::TypeHandle GetStringClassHandle();
81 ReferenceTypeInfo::TypeHandle GetThrowableClassHandle();
82
83 private:
Mathieu Chartiere8a3c572016-10-11 16:52:17 -070084 VariableSizedHandleScope* handles_;
Vladimir Marko7d1fbf32016-01-26 15:01:12 +000085
86 ReferenceTypeInfo::TypeHandle object_class_handle_;
87 ReferenceTypeInfo::TypeHandle class_class_handle_;
88 ReferenceTypeInfo::TypeHandle string_class_handle_;
89 ReferenceTypeInfo::TypeHandle throwable_class_handle_;
90 };
91
92 class RTPVisitor;
93
Calin Juravleb1498f62015-02-16 13:13:29 +000094 void VisitPhi(HPhi* phi);
Calin Juravle10e244f2015-01-26 18:54:32 +000095 void VisitBasicBlock(HBasicBlock* block);
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070096 void UpdateBoundType(HBoundType* bound_type) REQUIRES_SHARED(Locks::mutator_lock_);
97 void UpdatePhi(HPhi* phi) REQUIRES_SHARED(Locks::mutator_lock_);
Calin Juravle61d544b2015-02-23 16:46:57 +000098 void BoundTypeForIfNotNull(HBasicBlock* block);
Calin Juravleb1498f62015-02-16 13:13:29 +000099 void BoundTypeForIfInstanceOf(HBasicBlock* block);
Calin Juravle10e244f2015-01-26 18:54:32 +0000100 void ProcessWorklist();
Calin Juravleb1498f62015-02-16 13:13:29 +0000101 void AddToWorklist(HInstruction* instr);
102 void AddDependentInstructionsToWorklist(HInstruction* instr);
103
104 bool UpdateNullability(HInstruction* instr);
105 bool UpdateReferenceTypeInfo(HInstruction* instr);
106
Vladimir Marko7d1fbf32016-01-26 15:01:12 +0000107 static void UpdateArrayGet(HArrayGet* instr, HandleCache* handle_cache)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700108 REQUIRES_SHARED(Locks::mutator_lock_);
Vladimir Marko7d1fbf32016-01-26 15:01:12 +0000109
Mads Ager16e52892017-07-14 13:11:37 +0200110 static ReferenceTypeInfo MergeTypes(const ReferenceTypeInfo& a,
111 const ReferenceTypeInfo& b,
112 HandleCache* handle_cache)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700113 REQUIRES_SHARED(Locks::mutator_lock_);
Calin Juravleacf735c2015-02-12 15:25:22 +0000114
Calin Juravlecdfed3d2015-10-26 14:05:01 +0000115 void ValidateTypes();
116
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000117 Handle<mirror::ClassLoader> class_loader_;
118
Vladimir Marko456307a2016-04-19 14:12:13 +0000119 // Note: hint_dex_cache_ is usually, but not necessarily, the dex cache associated with
120 // graph_->GetDexFile(). Since we may look up also in other dex files, it's used only
121 // as a hint, to reduce the number of calls to the costly ClassLinker::FindDexCache().
122 Handle<mirror::DexCache> hint_dex_cache_;
Vladimir Marko7d1fbf32016-01-26 15:01:12 +0000123 HandleCache handle_cache_;
Calin Juravle10e244f2015-01-26 18:54:32 +0000124
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100125 ArenaVector<HInstruction*> worklist_;
Calin Juravle10e244f2015-01-26 18:54:32 +0000126
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000127 // Whether this reference type propagation is the first run we are doing.
128 const bool is_first_run_;
Calin Juravle2e768302015-07-28 14:41:11 +0000129
Calin Juravle10e244f2015-01-26 18:54:32 +0000130 static constexpr size_t kDefaultWorklistSize = 8;
131
Aart Bik8b3f9b22016-04-06 11:22:12 -0700132 friend class ReferenceTypePropagationTest;
133
Calin Juravle10e244f2015-01-26 18:54:32 +0000134 DISALLOW_COPY_AND_ASSIGN(ReferenceTypePropagation);
135};
136
137} // namespace art
138
139#endif // ART_COMPILER_OPTIMIZING_REFERENCE_TYPE_PROPAGATION_H_