blob: daec096f3ee250b90780c0748190abcf4f90d855 [file] [log] [blame]
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001/*
2 * Copyright (C) 2014 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_NODES_H_
18#define ART_COMPILER_OPTIMIZING_NODES_H_
19
Vladimir Marko60584552015-09-03 13:35:12 +000020#include <algorithm>
Vladimir Markof9f64412015-09-02 14:05:49 +010021#include <array>
Roland Levillain9867bc72015-08-05 10:21:34 +010022#include <type_traits>
23
Mathieu Chartiere5d80f82015-10-15 17:47:48 -070024#include "base/arena_bit_vector.h"
David Brazdil8d5b8b22015-03-24 10:51:52 +000025#include "base/arena_containers.h"
Mathieu Chartierb666f482015-02-18 14:33:14 -080026#include "base/arena_object.h"
Vladimir Marko60584552015-09-03 13:35:12 +000027#include "base/stl_util.h"
Calin Juravle27df7582015-04-17 19:12:31 +010028#include "dex/compiler_enums.h"
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +000029#include "entrypoints/quick/quick_entrypoints_enum.h"
Calin Juravleacf735c2015-02-12 15:25:22 +000030#include "handle.h"
31#include "handle_scope.h"
Nicolas Geoffraye53798a2014-12-01 10:31:54 +000032#include "invoke_type.h"
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010033#include "locations.h"
Vladimir Marko58155012015-08-19 12:49:41 +000034#include "method_reference.h"
Calin Juravleacf735c2015-02-12 15:25:22 +000035#include "mirror/class.h"
Nicolas Geoffraye5038322014-07-04 09:41:32 +010036#include "offsets.h"
Ian Rogerse63db272014-07-15 15:36:11 -070037#include "primitive.h"
David Brazdild26a4112015-11-10 11:07:31 +000038#include "utils/array_ref.h"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000039
40namespace art {
41
David Brazdil1abb4192015-02-17 18:33:36 +000042class GraphChecker;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000043class HBasicBlock;
Nicolas Geoffray76b1e172015-05-27 17:18:33 +010044class HCurrentMethod;
David Brazdil8d5b8b22015-03-24 10:51:52 +000045class HDoubleConstant;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010046class HEnvironment;
David Brazdil8d5b8b22015-03-24 10:51:52 +000047class HFloatConstant;
David Brazdilfc6a86a2015-06-26 10:33:45 +000048class HGraphBuilder;
David Brazdil8d5b8b22015-03-24 10:51:52 +000049class HGraphVisitor;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000050class HInstruction;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000051class HIntConstant;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +000052class HInvoke;
David Brazdil8d5b8b22015-03-24 10:51:52 +000053class HLongConstant;
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +000054class HNullConstant;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010055class HPhi;
Nicolas Geoffray3c049742014-09-24 18:10:46 +010056class HSuspendCheck;
David Brazdilffee3d32015-07-06 11:48:53 +010057class HTryBoundary;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010058class LiveInterval;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000059class LocationSummary;
Nicolas Geoffraydb216f42015-05-05 17:02:20 +010060class SlowPathCode;
David Brazdil8d5b8b22015-03-24 10:51:52 +000061class SsaBuilder;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000062
Mathieu Chartier736b5602015-09-02 14:54:11 -070063namespace mirror {
64class DexCache;
65} // namespace mirror
66
Nicolas Geoffray818f2102014-02-18 16:43:35 +000067static const int kDefaultNumberOfBlocks = 8;
68static const int kDefaultNumberOfSuccessors = 2;
69static const int kDefaultNumberOfPredecessors = 2;
David Brazdilb618ade2015-07-29 10:31:29 +010070static const int kDefaultNumberOfExceptionalPredecessors = 0;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010071static const int kDefaultNumberOfDominatedBlocks = 1;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000072static const int kDefaultNumberOfBackEdges = 1;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000073
Calin Juravle9aec02f2014-11-18 23:06:35 +000074static constexpr uint32_t kMaxIntShiftValue = 0x1f;
75static constexpr uint64_t kMaxLongShiftValue = 0x3f;
76
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010077static constexpr uint32_t kUnknownFieldIndex = static_cast<uint32_t>(-1);
Mingyao Yang8df69d42015-10-22 15:40:58 -070078static constexpr uint16_t kUnknownClassDefIndex = static_cast<uint16_t>(-1);
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010079
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +010080static constexpr InvokeType kInvalidInvokeType = static_cast<InvokeType>(-1);
81
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +060082static constexpr uint32_t kNoDexPc = -1;
83
Dave Allison20dfc792014-06-16 20:44:29 -070084enum IfCondition {
Aart Bike9f37602015-10-09 11:15:55 -070085 // All types.
86 kCondEQ, // ==
87 kCondNE, // !=
88 // Signed integers and floating-point numbers.
89 kCondLT, // <
90 kCondLE, // <=
91 kCondGT, // >
92 kCondGE, // >=
93 // Unsigned integers.
94 kCondB, // <
95 kCondBE, // <=
96 kCondA, // >
97 kCondAE, // >=
Dave Allison20dfc792014-06-16 20:44:29 -070098};
99
Nicolas Geoffray15bd2282016-01-05 15:55:41 +0000100enum GraphAnalysisResult {
101 kAnalysisFailThrowCatchLoop,
102 kAnalysisFailAmbiguousArrayOp,
103 kAnalysisSuccess,
David Brazdil4833f5a2015-12-16 10:37:39 +0000104};
105
Vladimir Markof9f64412015-09-02 14:05:49 +0100106class HInstructionList : public ValueObject {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100107 public:
108 HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {}
109
110 void AddInstruction(HInstruction* instruction);
111 void RemoveInstruction(HInstruction* instruction);
112
David Brazdilc3d743f2015-04-22 13:40:50 +0100113 // Insert `instruction` before/after an existing instruction `cursor`.
114 void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
115 void InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor);
116
Roland Levillain6b469232014-09-25 10:10:38 +0100117 // Return true if this list contains `instruction`.
118 bool Contains(HInstruction* instruction) const;
119
Roland Levillainccc07a92014-09-16 14:48:16 +0100120 // Return true if `instruction1` is found before `instruction2` in
121 // this instruction list and false otherwise. Abort if none
122 // of these instructions is found.
123 bool FoundBefore(const HInstruction* instruction1,
124 const HInstruction* instruction2) const;
125
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000126 bool IsEmpty() const { return first_instruction_ == nullptr; }
127 void Clear() { first_instruction_ = last_instruction_ = nullptr; }
128
129 // Update the block of all instructions to be `block`.
130 void SetBlockOfInstructions(HBasicBlock* block) const;
131
132 void AddAfter(HInstruction* cursor, const HInstructionList& instruction_list);
133 void Add(const HInstructionList& instruction_list);
134
David Brazdil2d7352b2015-04-20 14:52:42 +0100135 // Return the number of instructions in the list. This is an expensive operation.
136 size_t CountSize() const;
137
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100138 private:
139 HInstruction* first_instruction_;
140 HInstruction* last_instruction_;
141
142 friend class HBasicBlock;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000143 friend class HGraph;
144 friend class HInstruction;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100145 friend class HInstructionIterator;
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100146 friend class HBackwardInstructionIterator;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100147
148 DISALLOW_COPY_AND_ASSIGN(HInstructionList);
149};
150
David Brazdil4833f5a2015-12-16 10:37:39 +0000151class ReferenceTypeInfo : ValueObject {
152 public:
153 typedef Handle<mirror::Class> TypeHandle;
154
155 static ReferenceTypeInfo Create(TypeHandle type_handle, bool is_exact) {
156 // The constructor will check that the type_handle is valid.
157 return ReferenceTypeInfo(type_handle, is_exact);
158 }
159
160 static ReferenceTypeInfo CreateInvalid() { return ReferenceTypeInfo(); }
161
Vladimir Markof39745e2016-01-26 12:16:55 +0000162 static bool IsValidHandle(TypeHandle handle) {
David Brazdil4833f5a2015-12-16 10:37:39 +0000163 return handle.GetReference() != nullptr;
164 }
165
166 bool IsValid() const SHARED_REQUIRES(Locks::mutator_lock_) {
167 return IsValidHandle(type_handle_);
168 }
169
170 bool IsExact() const { return is_exact_; }
171
172 bool IsObjectClass() const SHARED_REQUIRES(Locks::mutator_lock_) {
173 DCHECK(IsValid());
174 return GetTypeHandle()->IsObjectClass();
175 }
176
177 bool IsStringClass() const SHARED_REQUIRES(Locks::mutator_lock_) {
178 DCHECK(IsValid());
179 return GetTypeHandle()->IsStringClass();
180 }
181
182 bool IsObjectArray() const SHARED_REQUIRES(Locks::mutator_lock_) {
183 DCHECK(IsValid());
184 return IsArrayClass() && GetTypeHandle()->GetComponentType()->IsObjectClass();
185 }
186
187 bool IsInterface() const SHARED_REQUIRES(Locks::mutator_lock_) {
188 DCHECK(IsValid());
189 return GetTypeHandle()->IsInterface();
190 }
191
192 bool IsArrayClass() const SHARED_REQUIRES(Locks::mutator_lock_) {
193 DCHECK(IsValid());
194 return GetTypeHandle()->IsArrayClass();
195 }
196
197 bool IsPrimitiveArrayClass() const SHARED_REQUIRES(Locks::mutator_lock_) {
198 DCHECK(IsValid());
199 return GetTypeHandle()->IsPrimitiveArray();
200 }
201
202 bool IsNonPrimitiveArrayClass() const SHARED_REQUIRES(Locks::mutator_lock_) {
203 DCHECK(IsValid());
204 return GetTypeHandle()->IsArrayClass() && !GetTypeHandle()->IsPrimitiveArray();
205 }
206
207 bool CanArrayHold(ReferenceTypeInfo rti) const SHARED_REQUIRES(Locks::mutator_lock_) {
208 DCHECK(IsValid());
209 if (!IsExact()) return false;
210 if (!IsArrayClass()) return false;
211 return GetTypeHandle()->GetComponentType()->IsAssignableFrom(rti.GetTypeHandle().Get());
212 }
213
214 bool CanArrayHoldValuesOf(ReferenceTypeInfo rti) const SHARED_REQUIRES(Locks::mutator_lock_) {
215 DCHECK(IsValid());
216 if (!IsExact()) return false;
217 if (!IsArrayClass()) return false;
218 if (!rti.IsArrayClass()) return false;
219 return GetTypeHandle()->GetComponentType()->IsAssignableFrom(
220 rti.GetTypeHandle()->GetComponentType());
221 }
222
223 Handle<mirror::Class> GetTypeHandle() const { return type_handle_; }
224
225 bool IsSupertypeOf(ReferenceTypeInfo rti) const SHARED_REQUIRES(Locks::mutator_lock_) {
226 DCHECK(IsValid());
227 DCHECK(rti.IsValid());
228 return GetTypeHandle()->IsAssignableFrom(rti.GetTypeHandle().Get());
229 }
230
231 bool IsStrictSupertypeOf(ReferenceTypeInfo rti) const SHARED_REQUIRES(Locks::mutator_lock_) {
232 DCHECK(IsValid());
233 DCHECK(rti.IsValid());
234 return GetTypeHandle().Get() != rti.GetTypeHandle().Get() &&
235 GetTypeHandle()->IsAssignableFrom(rti.GetTypeHandle().Get());
236 }
237
238 // Returns true if the type information provide the same amount of details.
239 // Note that it does not mean that the instructions have the same actual type
240 // (because the type can be the result of a merge).
David Brazdilf5552582015-12-27 13:36:12 +0000241 bool IsEqual(ReferenceTypeInfo rti) const SHARED_REQUIRES(Locks::mutator_lock_) {
David Brazdil4833f5a2015-12-16 10:37:39 +0000242 if (!IsValid() && !rti.IsValid()) {
243 // Invalid types are equal.
244 return true;
245 }
246 if (!IsValid() || !rti.IsValid()) {
247 // One is valid, the other not.
248 return false;
249 }
250 return IsExact() == rti.IsExact()
251 && GetTypeHandle().Get() == rti.GetTypeHandle().Get();
252 }
253
254 private:
255 ReferenceTypeInfo();
256 ReferenceTypeInfo(TypeHandle type_handle, bool is_exact);
257
258 // The class of the object.
259 TypeHandle type_handle_;
260 // Whether or not the type is exact or a superclass of the actual type.
261 // Whether or not we have any information about this type.
262 bool is_exact_;
263};
264
265std::ostream& operator<<(std::ostream& os, const ReferenceTypeInfo& rhs);
266
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000267// Control-flow graph of a method. Contains a list of basic blocks.
Vladimir Markof9f64412015-09-02 14:05:49 +0100268class HGraph : public ArenaObject<kArenaAllocGraph> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000269 public:
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100270 HGraph(ArenaAllocator* arena,
271 const DexFile& dex_file,
272 uint32_t method_idx,
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100273 bool should_generate_constructor_barrier,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700274 InstructionSet instruction_set,
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100275 InvokeType invoke_type = kInvalidInvokeType,
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100276 bool debuggable = false,
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000277 bool osr = false,
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100278 int start_instruction_id = 0)
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000279 : arena_(arena),
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100280 blocks_(arena->Adapter(kArenaAllocBlockList)),
281 reverse_post_order_(arena->Adapter(kArenaAllocReversePostOrder)),
282 linear_order_(arena->Adapter(kArenaAllocLinearOrder)),
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700283 entry_block_(nullptr),
284 exit_block_(nullptr),
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100285 maximum_number_of_out_vregs_(0),
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100286 number_of_vregs_(0),
287 number_of_in_vregs_(0),
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000288 temporaries_vreg_slots_(0),
Mark Mendell1152c922015-04-24 17:06:35 -0400289 has_bounds_checks_(false),
David Brazdil77a48ae2015-09-15 12:34:04 +0000290 has_try_catch_(false),
Nicolas Geoffray15bd2282016-01-05 15:55:41 +0000291 has_irreducible_loops_(false),
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000292 debuggable_(debuggable),
David Brazdil8d5b8b22015-03-24 10:51:52 +0000293 current_instruction_id_(start_instruction_id),
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100294 dex_file_(dex_file),
295 method_idx_(method_idx),
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100296 invoke_type_(invoke_type),
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100297 in_ssa_form_(false),
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100298 should_generate_constructor_barrier_(should_generate_constructor_barrier),
Mathieu Chartiere401d142015-04-22 13:56:20 -0700299 instruction_set_(instruction_set),
David Brazdil8d5b8b22015-03-24 10:51:52 +0000300 cached_null_constant_(nullptr),
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100301 cached_int_constants_(std::less<int32_t>(), arena->Adapter(kArenaAllocConstantsMap)),
302 cached_float_constants_(std::less<int32_t>(), arena->Adapter(kArenaAllocConstantsMap)),
303 cached_long_constants_(std::less<int64_t>(), arena->Adapter(kArenaAllocConstantsMap)),
304 cached_double_constants_(std::less<int64_t>(), arena->Adapter(kArenaAllocConstantsMap)),
David Brazdil4833f5a2015-12-16 10:37:39 +0000305 cached_current_method_(nullptr),
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000306 inexact_object_rti_(ReferenceTypeInfo::CreateInvalid()),
307 osr_(osr) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100308 blocks_.reserve(kDefaultNumberOfBlocks);
309 }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000310
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000311 ArenaAllocator* GetArena() const { return arena_; }
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100312 const ArenaVector<HBasicBlock*>& GetBlocks() const { return blocks_; }
313
David Brazdil69ba7b72015-06-23 18:27:30 +0100314 bool IsInSsaForm() const { return in_ssa_form_; }
315
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000316 HBasicBlock* GetEntryBlock() const { return entry_block_; }
317 HBasicBlock* GetExitBlock() const { return exit_block_; }
David Brazdilc7af85d2015-05-26 12:05:55 +0100318 bool HasExitBlock() const { return exit_block_ != nullptr; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000319
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000320 void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
321 void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000322
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000323 void AddBlock(HBasicBlock* block);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100324
David Brazdil4833f5a2015-12-16 10:37:39 +0000325 // Try building the SSA form of this graph, with dominance computation and
326 // loop recognition. Returns a code specifying that it was successful or the
327 // reason for failure.
Nicolas Geoffray15bd2282016-01-05 15:55:41 +0000328 GraphAnalysisResult TryBuildingSsa(StackHandleScopeCollection* handles);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000329
Nicolas Geoffray1f82ecc2015-06-24 12:20:24 +0100330 void ComputeDominanceInformation();
331 void ClearDominanceInformation();
Nicolas Geoffray15bd2282016-01-05 15:55:41 +0000332 void ClearLoopInformation();
333 void FindBackEdges(ArenaBitVector* visited);
334 GraphAnalysisResult BuildDominatorTree();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100335 void SimplifyCFG();
David Brazdilffee3d32015-07-06 11:48:53 +0100336 void SimplifyCatchBlocks();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000337
David Brazdil4833f5a2015-12-16 10:37:39 +0000338 // Analyze all natural loops in this graph. Returns a code specifying that it
339 // was successful or the reason for failure. The method will fail if a loop
David Brazdil4833f5a2015-12-16 10:37:39 +0000340 // is a throw-catch loop, i.e. the header is a catch block.
Nicolas Geoffray15bd2282016-01-05 15:55:41 +0000341 GraphAnalysisResult AnalyzeLoops() const;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100342
David Brazdilffee3d32015-07-06 11:48:53 +0100343 // Iterate over blocks to compute try block membership. Needs reverse post
344 // order and loop information.
345 void ComputeTryBlockInformation();
346
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000347 // Inline this graph in `outer_graph`, replacing the given `invoke` instruction.
Calin Juravle2e768302015-07-28 14:41:11 +0000348 // Returns the instruction used to replace the invoke expression or null if the
349 // invoke is for a void method.
350 HInstruction* InlineInto(HGraph* outer_graph, HInvoke* invoke);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000351
Mingyao Yang3584bce2015-05-19 16:01:59 -0700352 // Need to add a couple of blocks to test if the loop body is entered and
353 // put deoptimization instructions, etc.
354 void TransformLoopHeaderForBCE(HBasicBlock* header);
355
David Brazdil8a7c0fe2015-11-02 20:24:55 +0000356 // Removes `block` from the graph. Assumes `block` has been disconnected from
357 // other blocks and has no instructions or phis.
358 void DeleteDeadEmptyBlock(HBasicBlock* block);
David Brazdil46e2a392015-03-16 17:31:52 +0000359
David Brazdilfc6a86a2015-06-26 10:33:45 +0000360 // Splits the edge between `block` and `successor` while preserving the
361 // indices in the predecessor/successor lists. If there are multiple edges
362 // between the blocks, the lowest indices are used.
363 // Returns the new block which is empty and has the same dex pc as `successor`.
364 HBasicBlock* SplitEdge(HBasicBlock* block, HBasicBlock* successor);
365
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100366 void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor);
367 void SimplifyLoop(HBasicBlock* header);
368
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000369 int32_t GetNextInstructionId() {
370 DCHECK_NE(current_instruction_id_, INT32_MAX);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000371 return current_instruction_id_++;
372 }
373
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000374 int32_t GetCurrentInstructionId() const {
375 return current_instruction_id_;
376 }
377
378 void SetCurrentInstructionId(int32_t id) {
379 current_instruction_id_ = id;
380 }
381
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100382 uint16_t GetMaximumNumberOfOutVRegs() const {
383 return maximum_number_of_out_vregs_;
384 }
385
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000386 void SetMaximumNumberOfOutVRegs(uint16_t new_value) {
387 maximum_number_of_out_vregs_ = new_value;
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100388 }
389
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100390 void UpdateMaximumNumberOfOutVRegs(uint16_t other_value) {
391 maximum_number_of_out_vregs_ = std::max(maximum_number_of_out_vregs_, other_value);
392 }
393
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000394 void UpdateTemporariesVRegSlots(size_t slots) {
395 temporaries_vreg_slots_ = std::max(slots, temporaries_vreg_slots_);
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100396 }
397
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000398 size_t GetTemporariesVRegSlots() const {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100399 DCHECK(!in_ssa_form_);
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000400 return temporaries_vreg_slots_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100401 }
402
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100403 void SetNumberOfVRegs(uint16_t number_of_vregs) {
404 number_of_vregs_ = number_of_vregs;
405 }
406
407 uint16_t GetNumberOfVRegs() const {
408 return number_of_vregs_;
409 }
410
411 void SetNumberOfInVRegs(uint16_t value) {
412 number_of_in_vregs_ = value;
413 }
414
Nicolas Geoffrayab032bc2014-07-15 12:55:21 +0100415 uint16_t GetNumberOfLocalVRegs() const {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100416 DCHECK(!in_ssa_form_);
Nicolas Geoffrayab032bc2014-07-15 12:55:21 +0100417 return number_of_vregs_ - number_of_in_vregs_;
418 }
419
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100420 const ArenaVector<HBasicBlock*>& GetReversePostOrder() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100421 return reverse_post_order_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100422 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100423
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100424 const ArenaVector<HBasicBlock*>& GetLinearOrder() const {
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100425 return linear_order_;
426 }
427
Mark Mendell1152c922015-04-24 17:06:35 -0400428 bool HasBoundsChecks() const {
429 return has_bounds_checks_;
Mingyao Yange4335eb2015-03-02 15:14:13 -0800430 }
431
Mark Mendell1152c922015-04-24 17:06:35 -0400432 void SetHasBoundsChecks(bool value) {
433 has_bounds_checks_ = value;
Mingyao Yange4335eb2015-03-02 15:14:13 -0800434 }
435
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100436 bool ShouldGenerateConstructorBarrier() const {
437 return should_generate_constructor_barrier_;
438 }
439
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000440 bool IsDebuggable() const { return debuggable_; }
441
David Brazdil8d5b8b22015-03-24 10:51:52 +0000442 // Returns a constant of the given type and value. If it does not exist
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000443 // already, it is created and inserted into the graph. This method is only for
444 // integral types.
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600445 HConstant* GetConstant(Primitive::Type type, int64_t value, uint32_t dex_pc = kNoDexPc);
Calin Juravle2e768302015-07-28 14:41:11 +0000446
447 // TODO: This is problematic for the consistency of reference type propagation
448 // because it can be created anytime after the pass and thus it will be left
449 // with an invalid type.
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600450 HNullConstant* GetNullConstant(uint32_t dex_pc = kNoDexPc);
Calin Juravle2e768302015-07-28 14:41:11 +0000451
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600452 HIntConstant* GetIntConstant(int32_t value, uint32_t dex_pc = kNoDexPc) {
453 return CreateConstant(value, &cached_int_constants_, dex_pc);
David Brazdil8d5b8b22015-03-24 10:51:52 +0000454 }
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600455 HLongConstant* GetLongConstant(int64_t value, uint32_t dex_pc = kNoDexPc) {
456 return CreateConstant(value, &cached_long_constants_, dex_pc);
David Brazdil8d5b8b22015-03-24 10:51:52 +0000457 }
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600458 HFloatConstant* GetFloatConstant(float value, uint32_t dex_pc = kNoDexPc) {
459 return CreateConstant(bit_cast<int32_t, float>(value), &cached_float_constants_, dex_pc);
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000460 }
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600461 HDoubleConstant* GetDoubleConstant(double value, uint32_t dex_pc = kNoDexPc) {
462 return CreateConstant(bit_cast<int64_t, double>(value), &cached_double_constants_, dex_pc);
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000463 }
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000464
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100465 HCurrentMethod* GetCurrentMethod();
466
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100467 const DexFile& GetDexFile() const {
468 return dex_file_;
469 }
470
471 uint32_t GetMethodIdx() const {
472 return method_idx_;
473 }
474
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100475 InvokeType GetInvokeType() const {
476 return invoke_type_;
477 }
478
Mark Mendellc4701932015-04-10 13:18:51 -0400479 InstructionSet GetInstructionSet() const {
480 return instruction_set_;
481 }
482
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000483 bool IsCompilingOsr() const { return osr_; }
484
David Brazdil77a48ae2015-09-15 12:34:04 +0000485 bool HasTryCatch() const { return has_try_catch_; }
486 void SetHasTryCatch(bool value) { has_try_catch_ = value; }
David Brazdilbbd733e2015-08-18 17:48:17 +0100487
Nicolas Geoffray15bd2282016-01-05 15:55:41 +0000488 bool HasIrreducibleLoops() const { return has_irreducible_loops_; }
489 void SetHasIrreducibleLoops(bool value) { has_irreducible_loops_ = value; }
490
Nicolas Geoffray73be1e82015-09-17 15:22:56 +0100491 ArtMethod* GetArtMethod() const { return art_method_; }
492 void SetArtMethod(ArtMethod* method) { art_method_ = method; }
493
Mark Mendellf6529172015-11-17 11:16:56 -0500494 // Returns an instruction with the opposite boolean value from 'cond'.
495 // The instruction has been inserted into the graph, either as a constant, or
496 // before cursor.
497 HInstruction* InsertOppositeCondition(HInstruction* cond, HInstruction* cursor);
498
David Brazdil2d7352b2015-04-20 14:52:42 +0100499 private:
Roland Levillainfc600dc2014-12-02 17:16:31 +0000500 void RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const;
Nicolas Geoffrayf776b922015-04-15 18:22:45 +0100501 void RemoveDeadBlocks(const ArenaBitVector& visited);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000502
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000503 template <class InstructionType, typename ValueType>
504 InstructionType* CreateConstant(ValueType value,
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600505 ArenaSafeMap<ValueType, InstructionType*>* cache,
506 uint32_t dex_pc = kNoDexPc) {
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000507 // Try to find an existing constant of the given value.
508 InstructionType* constant = nullptr;
509 auto cached_constant = cache->find(value);
510 if (cached_constant != cache->end()) {
511 constant = cached_constant->second;
512 }
513
514 // If not found or previously deleted, create and cache a new instruction.
Nicolas Geoffrayf78848f2015-06-17 11:57:56 +0100515 // Don't bother reviving a previously deleted instruction, for simplicity.
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000516 if (constant == nullptr || constant->GetBlock() == nullptr) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600517 constant = new (arena_) InstructionType(value, dex_pc);
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000518 cache->Overwrite(value, constant);
519 InsertConstant(constant);
520 }
521 return constant;
522 }
523
David Brazdil8d5b8b22015-03-24 10:51:52 +0000524 void InsertConstant(HConstant* instruction);
525
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000526 // Cache a float constant into the graph. This method should only be
527 // called by the SsaBuilder when creating "equivalent" instructions.
528 void CacheFloatConstant(HFloatConstant* constant);
529
530 // See CacheFloatConstant comment.
531 void CacheDoubleConstant(HDoubleConstant* constant);
532
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000533 ArenaAllocator* const arena_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000534
535 // List of blocks in insertion order.
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100536 ArenaVector<HBasicBlock*> blocks_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000537
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100538 // List of blocks to perform a reverse post order tree traversal.
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100539 ArenaVector<HBasicBlock*> reverse_post_order_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000540
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100541 // List of blocks to perform a linear order tree traversal.
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100542 ArenaVector<HBasicBlock*> linear_order_;
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100543
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000544 HBasicBlock* entry_block_;
545 HBasicBlock* exit_block_;
546
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100547 // The maximum number of virtual registers arguments passed to a HInvoke in this graph.
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100548 uint16_t maximum_number_of_out_vregs_;
549
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100550 // The number of virtual registers in this method. Contains the parameters.
551 uint16_t number_of_vregs_;
552
553 // The number of virtual registers used by parameters of this method.
554 uint16_t number_of_in_vregs_;
555
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000556 // Number of vreg size slots that the temporaries use (used in baseline compiler).
557 size_t temporaries_vreg_slots_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100558
Mark Mendell1152c922015-04-24 17:06:35 -0400559 // Has bounds checks. We can totally skip BCE if it's false.
560 bool has_bounds_checks_;
Mingyao Yange4335eb2015-03-02 15:14:13 -0800561
David Brazdil77a48ae2015-09-15 12:34:04 +0000562 // Flag whether there are any try/catch blocks in the graph. We will skip
563 // try/catch-related passes if false.
564 bool has_try_catch_;
565
Nicolas Geoffray15bd2282016-01-05 15:55:41 +0000566 // Flag whether there are any irreducible loops in the graph.
567 bool has_irreducible_loops_;
568
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000569 // Indicates whether the graph should be compiled in a way that
570 // ensures full debuggability. If false, we can apply more
571 // aggressive optimizations that may limit the level of debugging.
572 const bool debuggable_;
573
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000574 // The current id to assign to a newly added instruction. See HInstruction.id_.
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000575 int32_t current_instruction_id_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000576
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100577 // The dex file from which the method is from.
578 const DexFile& dex_file_;
579
580 // The method index in the dex file.
581 const uint32_t method_idx_;
582
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100583 // If inlined, this encodes how the callee is being invoked.
584 const InvokeType invoke_type_;
585
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100586 // Whether the graph has been transformed to SSA form. Only used
587 // in debug mode to ensure we are not using properties only valid
588 // for non-SSA form (like the number of temporaries).
589 bool in_ssa_form_;
590
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100591 const bool should_generate_constructor_barrier_;
592
Mathieu Chartiere401d142015-04-22 13:56:20 -0700593 const InstructionSet instruction_set_;
594
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000595 // Cached constants.
David Brazdil8d5b8b22015-03-24 10:51:52 +0000596 HNullConstant* cached_null_constant_;
597 ArenaSafeMap<int32_t, HIntConstant*> cached_int_constants_;
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000598 ArenaSafeMap<int32_t, HFloatConstant*> cached_float_constants_;
David Brazdil8d5b8b22015-03-24 10:51:52 +0000599 ArenaSafeMap<int64_t, HLongConstant*> cached_long_constants_;
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000600 ArenaSafeMap<int64_t, HDoubleConstant*> cached_double_constants_;
David Brazdil46e2a392015-03-16 17:31:52 +0000601
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100602 HCurrentMethod* cached_current_method_;
603
Nicolas Geoffray73be1e82015-09-17 15:22:56 +0100604 // The ArtMethod this graph is for. Note that for AOT, it may be null,
605 // for example for methods whose declaring class could not be resolved
606 // (such as when the superclass could not be found).
607 ArtMethod* art_method_;
608
David Brazdil4833f5a2015-12-16 10:37:39 +0000609 // Keep the RTI of inexact Object to avoid having to pass stack handle
610 // collection pointer to passes which may create NullConstant.
611 ReferenceTypeInfo inexact_object_rti_;
612
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000613 // Whether we are compiling this graph for on stack replacement: this will
614 // make all loops seen as irreducible and emit special stack maps to mark
615 // compiled code entries which the interpreter can directly jump to.
616 const bool osr_;
617
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000618 friend class SsaBuilder; // For caching constants.
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100619 friend class SsaLivenessAnalysis; // For the linear order.
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000620 ART_FRIEND_TEST(GraphTest, IfSuccessorSimpleJoinBlock1);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000621 DISALLOW_COPY_AND_ASSIGN(HGraph);
622};
623
Vladimir Markof9f64412015-09-02 14:05:49 +0100624class HLoopInformation : public ArenaObject<kArenaAllocLoopInfo> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000625 public:
626 HLoopInformation(HBasicBlock* header, HGraph* graph)
627 : header_(header),
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100628 suspend_check_(nullptr),
Nicolas Geoffray15bd2282016-01-05 15:55:41 +0000629 irreducible_(false),
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100630 back_edges_(graph->GetArena()->Adapter(kArenaAllocLoopInfoBackEdges)),
Nicolas Geoffrayb09aacb2014-09-17 18:21:53 +0100631 // Make bit vector growable, as the number of blocks may change.
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100632 blocks_(graph->GetArena(), graph->GetBlocks().size(), true) {
633 back_edges_.reserve(kDefaultNumberOfBackEdges);
634 }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100635
Nicolas Geoffray15bd2282016-01-05 15:55:41 +0000636 bool IsIrreducible() const { return irreducible_; }
637
638 void Dump(std::ostream& os);
639
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100640 HBasicBlock* GetHeader() const {
641 return header_;
642 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000643
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000644 void SetHeader(HBasicBlock* block) {
645 header_ = block;
646 }
647
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100648 HSuspendCheck* GetSuspendCheck() const { return suspend_check_; }
649 void SetSuspendCheck(HSuspendCheck* check) { suspend_check_ = check; }
650 bool HasSuspendCheck() const { return suspend_check_ != nullptr; }
651
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000652 void AddBackEdge(HBasicBlock* back_edge) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100653 back_edges_.push_back(back_edge);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000654 }
655
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100656 void RemoveBackEdge(HBasicBlock* back_edge) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100657 RemoveElement(back_edges_, back_edge);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100658 }
659
David Brazdil46e2a392015-03-16 17:31:52 +0000660 bool IsBackEdge(const HBasicBlock& block) const {
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100661 return ContainsElement(back_edges_, &block);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100662 }
663
Nicolas Geoffraya8eed3a2014-11-24 17:47:10 +0000664 size_t NumberOfBackEdges() const {
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100665 return back_edges_.size();
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000666 }
667
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100668 HBasicBlock* GetPreHeader() const;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100669
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100670 const ArenaVector<HBasicBlock*>& GetBackEdges() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100671 return back_edges_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100672 }
673
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100674 // Returns the lifetime position of the back edge that has the
675 // greatest lifetime position.
676 size_t GetLifetimeEnd() const;
677
678 void ReplaceBackEdge(HBasicBlock* existing, HBasicBlock* new_back_edge) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100679 ReplaceElement(back_edges_, existing, new_back_edge);
Nicolas Geoffray57902602015-04-21 14:28:41 +0100680 }
681
Nicolas Geoffray15bd2282016-01-05 15:55:41 +0000682 // Finds blocks that are part of this loop.
683 void Populate();
David Brazdila4b8c212015-05-07 09:59:30 +0100684
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100685 // Returns whether this loop information contains `block`.
686 // Note that this loop information *must* be populated before entering this function.
687 bool Contains(const HBasicBlock& block) const;
688
689 // Returns whether this loop information is an inner loop of `other`.
690 // Note that `other` *must* be populated before entering this function.
691 bool IsIn(const HLoopInformation& other) const;
692
Mingyao Yang4b467ed2015-11-19 17:04:22 -0800693 // Returns true if instruction is not defined within this loop.
694 bool IsDefinedOutOfTheLoop(HInstruction* instruction) const;
Aart Bik73f1f3b2015-10-28 15:28:08 -0700695
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100696 const ArenaBitVector& GetBlocks() const { return blocks_; }
697
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000698 void Add(HBasicBlock* block);
David Brazdil46e2a392015-03-16 17:31:52 +0000699 void Remove(HBasicBlock* block);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000700
Nicolas Geoffray788f2f02016-01-22 12:41:38 +0000701 void ClearAllBlocks() {
702 blocks_.ClearAllBits();
703 }
704
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000705 private:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100706 // Internal recursive implementation of `Populate`.
707 void PopulateRecursive(HBasicBlock* block);
Nicolas Geoffray15bd2282016-01-05 15:55:41 +0000708 void PopulateIrreducibleRecursive(HBasicBlock* block);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100709
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000710 HBasicBlock* header_;
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100711 HSuspendCheck* suspend_check_;
Nicolas Geoffray15bd2282016-01-05 15:55:41 +0000712 bool irreducible_;
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100713 ArenaVector<HBasicBlock*> back_edges_;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100714 ArenaBitVector blocks_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000715
716 DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
717};
718
David Brazdilec16f792015-08-19 15:04:01 +0100719// Stores try/catch information for basic blocks.
720// Note that HGraph is constructed so that catch blocks cannot simultaneously
721// be try blocks.
Vladimir Markof9f64412015-09-02 14:05:49 +0100722class TryCatchInformation : public ArenaObject<kArenaAllocTryCatchInfo> {
David Brazdilec16f792015-08-19 15:04:01 +0100723 public:
724 // Try block information constructor.
725 explicit TryCatchInformation(const HTryBoundary& try_entry)
726 : try_entry_(&try_entry),
727 catch_dex_file_(nullptr),
728 catch_type_index_(DexFile::kDexNoIndex16) {
729 DCHECK(try_entry_ != nullptr);
730 }
731
732 // Catch block information constructor.
733 TryCatchInformation(uint16_t catch_type_index, const DexFile& dex_file)
734 : try_entry_(nullptr),
735 catch_dex_file_(&dex_file),
736 catch_type_index_(catch_type_index) {}
737
738 bool IsTryBlock() const { return try_entry_ != nullptr; }
739
740 const HTryBoundary& GetTryEntry() const {
741 DCHECK(IsTryBlock());
742 return *try_entry_;
743 }
744
745 bool IsCatchBlock() const { return catch_dex_file_ != nullptr; }
746
747 bool IsCatchAllTypeIndex() const {
748 DCHECK(IsCatchBlock());
749 return catch_type_index_ == DexFile::kDexNoIndex16;
750 }
751
752 uint16_t GetCatchTypeIndex() const {
753 DCHECK(IsCatchBlock());
754 return catch_type_index_;
755 }
756
757 const DexFile& GetCatchDexFile() const {
758 DCHECK(IsCatchBlock());
759 return *catch_dex_file_;
760 }
761
762 private:
763 // One of possibly several TryBoundary instructions entering the block's try.
764 // Only set for try blocks.
765 const HTryBoundary* try_entry_;
766
767 // Exception type information. Only set for catch blocks.
768 const DexFile* catch_dex_file_;
769 const uint16_t catch_type_index_;
770};
771
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100772static constexpr size_t kNoLifetime = -1;
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100773static constexpr uint32_t kInvalidBlockId = static_cast<uint32_t>(-1);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100774
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000775// A block in a method. Contains the list of instructions represented
776// as a double linked list. Each block knows its predecessors and
777// successors.
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100778
Vladimir Markof9f64412015-09-02 14:05:49 +0100779class HBasicBlock : public ArenaObject<kArenaAllocBasicBlock> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000780 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600781 HBasicBlock(HGraph* graph, uint32_t dex_pc = kNoDexPc)
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000782 : graph_(graph),
Vladimir Marko60584552015-09-03 13:35:12 +0000783 predecessors_(graph->GetArena()->Adapter(kArenaAllocPredecessors)),
784 successors_(graph->GetArena()->Adapter(kArenaAllocSuccessors)),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000785 loop_information_(nullptr),
786 dominator_(nullptr),
Vladimir Marko60584552015-09-03 13:35:12 +0000787 dominated_blocks_(graph->GetArena()->Adapter(kArenaAllocDominated)),
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100788 block_id_(kInvalidBlockId),
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100789 dex_pc_(dex_pc),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100790 lifetime_start_(kNoLifetime),
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000791 lifetime_end_(kNoLifetime),
Vladimir Marko60584552015-09-03 13:35:12 +0000792 try_catch_information_(nullptr) {
793 predecessors_.reserve(kDefaultNumberOfPredecessors);
794 successors_.reserve(kDefaultNumberOfSuccessors);
795 dominated_blocks_.reserve(kDefaultNumberOfDominatedBlocks);
796 }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000797
Vladimir Marko60584552015-09-03 13:35:12 +0000798 const ArenaVector<HBasicBlock*>& GetPredecessors() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100799 return predecessors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000800 }
801
Vladimir Marko60584552015-09-03 13:35:12 +0000802 const ArenaVector<HBasicBlock*>& GetSuccessors() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100803 return successors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000804 }
805
David Brazdild26a4112015-11-10 11:07:31 +0000806 ArrayRef<HBasicBlock* const> GetNormalSuccessors() const;
807 ArrayRef<HBasicBlock* const> GetExceptionalSuccessors() const;
808
Vladimir Marko60584552015-09-03 13:35:12 +0000809 bool HasSuccessor(const HBasicBlock* block, size_t start_from = 0u) {
810 return ContainsElement(successors_, block, start_from);
811 }
812
813 const ArenaVector<HBasicBlock*>& GetDominatedBlocks() const {
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100814 return dominated_blocks_;
815 }
816
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100817 bool IsEntryBlock() const {
818 return graph_->GetEntryBlock() == this;
819 }
820
821 bool IsExitBlock() const {
822 return graph_->GetExitBlock() == this;
823 }
824
David Brazdil46e2a392015-03-16 17:31:52 +0000825 bool IsSingleGoto() const;
David Brazdilfc6a86a2015-06-26 10:33:45 +0000826 bool IsSingleTryBoundary() const;
827
828 // Returns true if this block emits nothing but a jump.
829 bool IsSingleJump() const {
830 HLoopInformation* loop_info = GetLoopInformation();
831 return (IsSingleGoto() || IsSingleTryBoundary())
832 // Back edges generate a suspend check.
833 && (loop_info == nullptr || !loop_info->IsBackEdge(*this));
834 }
David Brazdil46e2a392015-03-16 17:31:52 +0000835
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000836 void AddBackEdge(HBasicBlock* back_edge) {
837 if (loop_information_ == nullptr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000838 loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000839 }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100840 DCHECK_EQ(loop_information_->GetHeader(), this);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000841 loop_information_->AddBackEdge(back_edge);
842 }
843
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000844 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000845 void SetGraph(HGraph* graph) { graph_ = graph; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000846
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100847 uint32_t GetBlockId() const { return block_id_; }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000848 void SetBlockId(int id) { block_id_ = id; }
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600849 uint32_t GetDexPc() const { return dex_pc_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000850
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000851 HBasicBlock* GetDominator() const { return dominator_; }
852 void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
Vladimir Marko60584552015-09-03 13:35:12 +0000853 void AddDominatedBlock(HBasicBlock* block) { dominated_blocks_.push_back(block); }
854
855 void RemoveDominatedBlock(HBasicBlock* block) {
856 RemoveElement(dominated_blocks_, block);
Vladimir Marko91e11c02015-09-02 17:03:22 +0100857 }
Vladimir Marko60584552015-09-03 13:35:12 +0000858
859 void ReplaceDominatedBlock(HBasicBlock* existing, HBasicBlock* new_block) {
860 ReplaceElement(dominated_blocks_, existing, new_block);
861 }
862
Nicolas Geoffray1f82ecc2015-06-24 12:20:24 +0100863 void ClearDominanceInformation();
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000864
865 int NumberOfBackEdges() const {
Nicolas Geoffray1f82ecc2015-06-24 12:20:24 +0100866 return IsLoopHeader() ? loop_information_->NumberOfBackEdges() : 0;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000867 }
868
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100869 HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
870 HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; }
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100871 const HInstructionList& GetInstructions() const { return instructions_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100872 HInstruction* GetFirstPhi() const { return phis_.first_instruction_; }
David Brazdilc3d743f2015-04-22 13:40:50 +0100873 HInstruction* GetLastPhi() const { return phis_.last_instruction_; }
874 const HInstructionList& GetPhis() const { return phis_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000875
Nicolas Geoffray09aa1472016-01-19 10:52:54 +0000876 HInstruction* GetFirstInstructionDisregardMoves() const;
877
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000878 void AddSuccessor(HBasicBlock* block) {
Vladimir Marko60584552015-09-03 13:35:12 +0000879 successors_.push_back(block);
880 block->predecessors_.push_back(this);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000881 }
882
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100883 void ReplaceSuccessor(HBasicBlock* existing, HBasicBlock* new_block) {
884 size_t successor_index = GetSuccessorIndexOf(existing);
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100885 existing->RemovePredecessor(this);
Vladimir Marko60584552015-09-03 13:35:12 +0000886 new_block->predecessors_.push_back(this);
887 successors_[successor_index] = new_block;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000888 }
889
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000890 void ReplacePredecessor(HBasicBlock* existing, HBasicBlock* new_block) {
891 size_t predecessor_index = GetPredecessorIndexOf(existing);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000892 existing->RemoveSuccessor(this);
Vladimir Marko60584552015-09-03 13:35:12 +0000893 new_block->successors_.push_back(this);
894 predecessors_[predecessor_index] = new_block;
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000895 }
896
Nicolas Geoffray8b20f882015-06-19 16:17:05 +0100897 // Insert `this` between `predecessor` and `successor. This method
898 // preserves the indicies, and will update the first edge found between
899 // `predecessor` and `successor`.
900 void InsertBetween(HBasicBlock* predecessor, HBasicBlock* successor) {
901 size_t predecessor_index = successor->GetPredecessorIndexOf(predecessor);
Nicolas Geoffray8b20f882015-06-19 16:17:05 +0100902 size_t successor_index = predecessor->GetSuccessorIndexOf(successor);
Vladimir Marko60584552015-09-03 13:35:12 +0000903 successor->predecessors_[predecessor_index] = this;
904 predecessor->successors_[successor_index] = this;
905 successors_.push_back(successor);
906 predecessors_.push_back(predecessor);
Nicolas Geoffray8b20f882015-06-19 16:17:05 +0100907 }
908
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100909 void RemovePredecessor(HBasicBlock* block) {
Vladimir Marko60584552015-09-03 13:35:12 +0000910 predecessors_.erase(predecessors_.begin() + GetPredecessorIndexOf(block));
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100911 }
912
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000913 void RemoveSuccessor(HBasicBlock* block) {
Vladimir Marko60584552015-09-03 13:35:12 +0000914 successors_.erase(successors_.begin() + GetSuccessorIndexOf(block));
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000915 }
916
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100917 void ClearAllPredecessors() {
Vladimir Marko60584552015-09-03 13:35:12 +0000918 predecessors_.clear();
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100919 }
920
921 void AddPredecessor(HBasicBlock* block) {
Vladimir Marko60584552015-09-03 13:35:12 +0000922 predecessors_.push_back(block);
923 block->successors_.push_back(this);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100924 }
925
Nicolas Geoffray604c6e42014-09-17 12:08:44 +0100926 void SwapPredecessors() {
Vladimir Marko60584552015-09-03 13:35:12 +0000927 DCHECK_EQ(predecessors_.size(), 2u);
928 std::swap(predecessors_[0], predecessors_[1]);
Nicolas Geoffray604c6e42014-09-17 12:08:44 +0100929 }
930
David Brazdil769c9e52015-04-27 13:54:09 +0100931 void SwapSuccessors() {
Vladimir Marko60584552015-09-03 13:35:12 +0000932 DCHECK_EQ(successors_.size(), 2u);
933 std::swap(successors_[0], successors_[1]);
David Brazdil769c9e52015-04-27 13:54:09 +0100934 }
935
David Brazdilfc6a86a2015-06-26 10:33:45 +0000936 size_t GetPredecessorIndexOf(HBasicBlock* predecessor) const {
Vladimir Marko60584552015-09-03 13:35:12 +0000937 return IndexOfElement(predecessors_, predecessor);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100938 }
939
David Brazdilfc6a86a2015-06-26 10:33:45 +0000940 size_t GetSuccessorIndexOf(HBasicBlock* successor) const {
Vladimir Marko60584552015-09-03 13:35:12 +0000941 return IndexOfElement(successors_, successor);
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100942 }
943
David Brazdilfc6a86a2015-06-26 10:33:45 +0000944 HBasicBlock* GetSinglePredecessor() const {
Vladimir Marko60584552015-09-03 13:35:12 +0000945 DCHECK_EQ(GetPredecessors().size(), 1u);
Vladimir Markoec7802a2015-10-01 20:57:57 +0100946 return GetPredecessors()[0];
David Brazdilfc6a86a2015-06-26 10:33:45 +0000947 }
948
949 HBasicBlock* GetSingleSuccessor() const {
Vladimir Marko60584552015-09-03 13:35:12 +0000950 DCHECK_EQ(GetSuccessors().size(), 1u);
Vladimir Markoec7802a2015-10-01 20:57:57 +0100951 return GetSuccessors()[0];
David Brazdilfc6a86a2015-06-26 10:33:45 +0000952 }
953
954 // Returns whether the first occurrence of `predecessor` in the list of
955 // predecessors is at index `idx`.
956 bool IsFirstIndexOfPredecessor(HBasicBlock* predecessor, size_t idx) const {
Vladimir Markoec7802a2015-10-01 20:57:57 +0100957 DCHECK_EQ(GetPredecessors()[idx], predecessor);
David Brazdilfc6a86a2015-06-26 10:33:45 +0000958 return GetPredecessorIndexOf(predecessor) == idx;
959 }
960
David Brazdild7558da2015-09-22 13:04:14 +0100961 // Create a new block between this block and its predecessors. The new block
962 // is added to the graph, all predecessor edges are relinked to it and an edge
963 // is created to `this`. Returns the new empty block. Reverse post order or
964 // loop and try/catch information are not updated.
965 HBasicBlock* CreateImmediateDominator();
966
David Brazdilfc6a86a2015-06-26 10:33:45 +0000967 // Split the block into two blocks just before `cursor`. Returns the newly
David Brazdil56e1acc2015-06-30 15:41:36 +0100968 // created, latter block. Note that this method will add the block to the
969 // graph, create a Goto at the end of the former block and will create an edge
970 // between the blocks. It will not, however, update the reverse post order or
David Brazdild7558da2015-09-22 13:04:14 +0100971 // loop and try/catch information.
David Brazdilfc6a86a2015-06-26 10:33:45 +0000972 HBasicBlock* SplitBefore(HInstruction* cursor);
973
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000974 // Split the block into two blocks just after `cursor`. Returns the newly
975 // created block. Note that this method just updates raw block information,
976 // like predecessors, successors, dominators, and instruction list. It does not
977 // update the graph, reverse post order, loop information, nor make sure the
978 // blocks are consistent (for example ending with a control flow instruction).
979 HBasicBlock* SplitAfter(HInstruction* cursor);
980
David Brazdil9bc43612015-11-05 21:25:24 +0000981 // Split catch block into two blocks after the original move-exception bytecode
982 // instruction, or at the beginning if not present. Returns the newly created,
983 // latter block, or nullptr if such block could not be created (must be dead
984 // in that case). Note that this method just updates raw block information,
985 // like predecessors, successors, dominators, and instruction list. It does not
986 // update the graph, reverse post order, loop information, nor make sure the
987 // blocks are consistent (for example ending with a control flow instruction).
988 HBasicBlock* SplitCatchBlockAfterMoveException();
989
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000990 // Merge `other` at the end of `this`. Successors and dominated blocks of
991 // `other` are changed to be successors and dominated blocks of `this`. Note
992 // that this method does not update the graph, reverse post order, loop
993 // information, nor make sure the blocks are consistent (for example ending
994 // with a control flow instruction).
David Brazdil2d7352b2015-04-20 14:52:42 +0100995 void MergeWithInlined(HBasicBlock* other);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000996
997 // Replace `this` with `other`. Predecessors, successors, and dominated blocks
998 // of `this` are moved to `other`.
999 // Note that this method does not update the graph, reverse post order, loop
1000 // information, nor make sure the blocks are consistent (for example ending
David Brazdil46e2a392015-03-16 17:31:52 +00001001 // with a control flow instruction).
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001002 void ReplaceWith(HBasicBlock* other);
1003
David Brazdil2d7352b2015-04-20 14:52:42 +01001004 // Merge `other` at the end of `this`. This method updates loops, reverse post
1005 // order, links to predecessors, successors, dominators and deletes the block
1006 // from the graph. The two blocks must be successive, i.e. `this` the only
1007 // predecessor of `other` and vice versa.
1008 void MergeWith(HBasicBlock* other);
1009
1010 // Disconnects `this` from all its predecessors, successors and dominator,
1011 // removes it from all loops it is included in and eventually from the graph.
1012 // The block must not dominate any other block. Predecessors and successors
1013 // are safely updated.
1014 void DisconnectAndDelete();
David Brazdil46e2a392015-03-16 17:31:52 +00001015
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001016 void AddInstruction(HInstruction* instruction);
Guillaume "Vermeille" Sanchez2967ec62015-04-24 16:36:52 +01001017 // Insert `instruction` before/after an existing instruction `cursor`.
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001018 void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
Guillaume "Vermeille" Sanchez2967ec62015-04-24 16:36:52 +01001019 void InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor);
Roland Levillainccc07a92014-09-16 14:48:16 +01001020 // Replace instruction `initial` with `replacement` within this block.
1021 void ReplaceAndRemoveInstructionWith(HInstruction* initial,
1022 HInstruction* replacement);
David Brazdil74eb1b22015-12-14 11:44:01 +00001023 void MoveInstructionBefore(HInstruction* insn, HInstruction* cursor);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001024 void AddPhi(HPhi* phi);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001025 void InsertPhiAfter(HPhi* instruction, HPhi* cursor);
David Brazdil1abb4192015-02-17 18:33:36 +00001026 // RemoveInstruction and RemovePhi delete a given instruction from the respective
1027 // instruction list. With 'ensure_safety' set to true, it verifies that the
1028 // instruction is not in use and removes it from the use lists of its inputs.
1029 void RemoveInstruction(HInstruction* instruction, bool ensure_safety = true);
1030 void RemovePhi(HPhi* phi, bool ensure_safety = true);
David Brazdilc7508e92015-04-27 13:28:57 +01001031 void RemoveInstructionOrPhi(HInstruction* instruction, bool ensure_safety = true);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001032
1033 bool IsLoopHeader() const {
David Brazdil69a28042015-04-29 17:16:07 +01001034 return IsInLoop() && (loop_information_->GetHeader() == this);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001035 }
1036
Roland Levillain6b879dd2014-09-22 17:13:44 +01001037 bool IsLoopPreHeaderFirstPredecessor() const {
1038 DCHECK(IsLoopHeader());
Vladimir Markoec7802a2015-10-01 20:57:57 +01001039 return GetPredecessors()[0] == GetLoopInformation()->GetPreHeader();
Roland Levillain6b879dd2014-09-22 17:13:44 +01001040 }
1041
Nicolas Geoffray15bd2282016-01-05 15:55:41 +00001042 bool IsFirstPredecessorBackEdge() const {
1043 DCHECK(IsLoopHeader());
1044 return GetLoopInformation()->IsBackEdge(*GetPredecessors()[0]);
1045 }
1046
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001047 HLoopInformation* GetLoopInformation() const {
1048 return loop_information_;
1049 }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001050
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001051 // Set the loop_information_ on this block. Overrides the current
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001052 // loop_information if it is an outer loop of the passed loop information.
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001053 // Note that this method is called while creating the loop information.
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001054 void SetInLoop(HLoopInformation* info) {
1055 if (IsLoopHeader()) {
1056 // Nothing to do. This just means `info` is an outer loop.
David Brazdil69a28042015-04-29 17:16:07 +01001057 } else if (!IsInLoop()) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001058 loop_information_ = info;
1059 } else if (loop_information_->Contains(*info->GetHeader())) {
1060 // Block is currently part of an outer loop. Make it part of this inner loop.
1061 // Note that a non loop header having a loop information means this loop information
1062 // has already been populated
1063 loop_information_ = info;
1064 } else {
1065 // Block is part of an inner loop. Do not update the loop information.
1066 // Note that we cannot do the check `info->Contains(loop_information_)->GetHeader()`
1067 // at this point, because this method is being called while populating `info`.
1068 }
1069 }
1070
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001071 // Raw update of the loop information.
1072 void SetLoopInformation(HLoopInformation* info) {
1073 loop_information_ = info;
1074 }
1075
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01001076 bool IsInLoop() const { return loop_information_ != nullptr; }
1077
David Brazdilec16f792015-08-19 15:04:01 +01001078 TryCatchInformation* GetTryCatchInformation() const { return try_catch_information_; }
1079
1080 void SetTryCatchInformation(TryCatchInformation* try_catch_information) {
1081 try_catch_information_ = try_catch_information;
1082 }
1083
1084 bool IsTryBlock() const {
1085 return try_catch_information_ != nullptr && try_catch_information_->IsTryBlock();
1086 }
1087
1088 bool IsCatchBlock() const {
1089 return try_catch_information_ != nullptr && try_catch_information_->IsCatchBlock();
1090 }
David Brazdilffee3d32015-07-06 11:48:53 +01001091
1092 // Returns the try entry that this block's successors should have. They will
1093 // be in the same try, unless the block ends in a try boundary. In that case,
1094 // the appropriate try entry will be returned.
David Brazdilec16f792015-08-19 15:04:01 +01001095 const HTryBoundary* ComputeTryEntryOfSuccessors() const;
David Brazdilffee3d32015-07-06 11:48:53 +01001096
David Brazdild7558da2015-09-22 13:04:14 +01001097 bool HasThrowingInstructions() const;
1098
David Brazdila4b8c212015-05-07 09:59:30 +01001099 // Returns whether this block dominates the blocked passed as parameter.
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001100 bool Dominates(HBasicBlock* block) const;
1101
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001102 size_t GetLifetimeStart() const { return lifetime_start_; }
1103 size_t GetLifetimeEnd() const { return lifetime_end_; }
1104
1105 void SetLifetimeStart(size_t start) { lifetime_start_ = start; }
1106 void SetLifetimeEnd(size_t end) { lifetime_end_ = end; }
1107
David Brazdil8d5b8b22015-03-24 10:51:52 +00001108 bool EndsWithControlFlowInstruction() const;
David Brazdilb2bd1c52015-03-25 11:17:37 +00001109 bool EndsWithIf() const;
David Brazdilffee3d32015-07-06 11:48:53 +01001110 bool EndsWithTryBoundary() const;
David Brazdilb2bd1c52015-03-25 11:17:37 +00001111 bool HasSinglePhi() const;
1112
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001113 private:
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00001114 HGraph* graph_;
Vladimir Marko60584552015-09-03 13:35:12 +00001115 ArenaVector<HBasicBlock*> predecessors_;
1116 ArenaVector<HBasicBlock*> successors_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001117 HInstructionList instructions_;
1118 HInstructionList phis_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001119 HLoopInformation* loop_information_;
1120 HBasicBlock* dominator_;
Vladimir Marko60584552015-09-03 13:35:12 +00001121 ArenaVector<HBasicBlock*> dominated_blocks_;
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001122 uint32_t block_id_;
Nicolas Geoffray3c049742014-09-24 18:10:46 +01001123 // The dex program counter of the first instruction of this block.
1124 const uint32_t dex_pc_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001125 size_t lifetime_start_;
1126 size_t lifetime_end_;
David Brazdilec16f792015-08-19 15:04:01 +01001127 TryCatchInformation* try_catch_information_;
David Brazdilffee3d32015-07-06 11:48:53 +01001128
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001129 friend class HGraph;
1130 friend class HInstruction;
1131
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001132 DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
1133};
1134
David Brazdilb2bd1c52015-03-25 11:17:37 +00001135// Iterates over the LoopInformation of all loops which contain 'block'
1136// from the innermost to the outermost.
1137class HLoopInformationOutwardIterator : public ValueObject {
1138 public:
1139 explicit HLoopInformationOutwardIterator(const HBasicBlock& block)
1140 : current_(block.GetLoopInformation()) {}
1141
1142 bool Done() const { return current_ == nullptr; }
1143
1144 void Advance() {
1145 DCHECK(!Done());
David Brazdil69a28042015-04-29 17:16:07 +01001146 current_ = current_->GetPreHeader()->GetLoopInformation();
David Brazdilb2bd1c52015-03-25 11:17:37 +00001147 }
1148
1149 HLoopInformation* Current() const {
1150 DCHECK(!Done());
1151 return current_;
1152 }
1153
1154 private:
1155 HLoopInformation* current_;
1156
1157 DISALLOW_COPY_AND_ASSIGN(HLoopInformationOutwardIterator);
1158};
1159
Alexandre Ramesef20f712015-06-09 10:29:30 +01001160#define FOR_EACH_CONCRETE_INSTRUCTION_COMMON(M) \
Aart Bike9f37602015-10-09 11:15:55 -07001161 M(Above, Condition) \
1162 M(AboveOrEqual, Condition) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001163 M(Add, BinaryOperation) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00001164 M(And, BinaryOperation) \
Calin Juravle7c4954d2014-10-28 16:57:40 +00001165 M(ArrayGet, Instruction) \
1166 M(ArrayLength, Instruction) \
1167 M(ArraySet, Instruction) \
Aart Bike9f37602015-10-09 11:15:55 -07001168 M(Below, Condition) \
1169 M(BelowOrEqual, Condition) \
David Brazdil66d126e2015-04-03 16:02:44 +01001170 M(BooleanNot, UnaryOperation) \
Calin Juravle7c4954d2014-10-28 16:57:40 +00001171 M(BoundsCheck, Instruction) \
Calin Juravleb1498f62015-02-16 13:13:29 +00001172 M(BoundType, Instruction) \
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001173 M(CheckCast, Instruction) \
Nicolas Geoffraya42363f2015-12-17 14:57:09 +00001174 M(ClassTableGet, Instruction) \
David Brazdilcb1c0552015-08-04 16:22:25 +01001175 M(ClearException, Instruction) \
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001176 M(ClinitCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +00001177 M(Compare, BinaryOperation) \
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001178 M(CurrentMethod, Instruction) \
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001179 M(Deoptimize, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +00001180 M(Div, BinaryOperation) \
Calin Juravled0d48522014-11-04 16:40:20 +00001181 M(DivZeroCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +00001182 M(DoubleConstant, Constant) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001183 M(Equal, Condition) \
Calin Juravle7c4954d2014-10-28 16:57:40 +00001184 M(Exit, Instruction) \
1185 M(FloatConstant, Constant) \
1186 M(Goto, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001187 M(GreaterThan, Condition) \
1188 M(GreaterThanOrEqual, Condition) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001189 M(If, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +00001190 M(InstanceFieldGet, Instruction) \
1191 M(InstanceFieldSet, Instruction) \
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001192 M(InstanceOf, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001193 M(IntConstant, Constant) \
Calin Juravle175dc732015-08-25 15:42:32 +01001194 M(InvokeUnresolved, Invoke) \
Nicolas Geoffray52839d12014-11-07 17:47:25 +00001195 M(InvokeInterface, Invoke) \
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001196 M(InvokeStaticOrDirect, Invoke) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001197 M(InvokeVirtual, Invoke) \
Calin Juravle7c4954d2014-10-28 16:57:40 +00001198 M(LessThan, Condition) \
1199 M(LessThanOrEqual, Condition) \
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00001200 M(LoadClass, Instruction) \
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00001201 M(LoadException, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001202 M(LoadLocal, Instruction) \
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00001203 M(LoadString, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001204 M(Local, Instruction) \
1205 M(LongConstant, Constant) \
Calin Juravle27df7582015-04-17 19:12:31 +01001206 M(MemoryBarrier, Instruction) \
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00001207 M(MonitorOperation, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +00001208 M(Mul, BinaryOperation) \
David Srbecky0cf44932015-12-09 14:09:59 +00001209 M(NativeDebugInfo, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +00001210 M(Neg, UnaryOperation) \
1211 M(NewArray, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001212 M(NewInstance, Instruction) \
Roland Levillain1cc5f2512014-10-22 18:06:21 +01001213 M(Not, UnaryOperation) \
Calin Juravle7c4954d2014-10-28 16:57:40 +00001214 M(NotEqual, Condition) \
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00001215 M(NullConstant, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +00001216 M(NullCheck, Instruction) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00001217 M(Or, BinaryOperation) \
Mark Mendellfe57faa2015-09-18 09:26:15 -04001218 M(PackedSwitch, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001219 M(ParallelMove, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +00001220 M(ParameterValue, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001221 M(Phi, Instruction) \
Calin Juravle9aec02f2014-11-18 23:06:35 +00001222 M(Rem, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001223 M(Return, Instruction) \
1224 M(ReturnVoid, Instruction) \
Scott Wakeling40a04bf2015-12-11 09:50:36 +00001225 M(Ror, BinaryOperation) \
Calin Juravle9aec02f2014-11-18 23:06:35 +00001226 M(Shl, BinaryOperation) \
1227 M(Shr, BinaryOperation) \
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001228 M(StaticFieldGet, Instruction) \
1229 M(StaticFieldSet, Instruction) \
Calin Juravlee460d1d2015-09-29 04:52:17 +01001230 M(UnresolvedInstanceFieldGet, Instruction) \
1231 M(UnresolvedInstanceFieldSet, Instruction) \
1232 M(UnresolvedStaticFieldGet, Instruction) \
1233 M(UnresolvedStaticFieldSet, Instruction) \
David Brazdil74eb1b22015-12-14 11:44:01 +00001234 M(Select, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001235 M(StoreLocal, Instruction) \
1236 M(Sub, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001237 M(SuspendCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +00001238 M(Temporary, Instruction) \
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00001239 M(Throw, Instruction) \
David Brazdilfc6a86a2015-06-26 10:33:45 +00001240 M(TryBoundary, Instruction) \
Roland Levillaindff1f282014-11-05 14:15:05 +00001241 M(TypeConversion, Instruction) \
Calin Juravle9aec02f2014-11-18 23:06:35 +00001242 M(UShr, BinaryOperation) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00001243 M(Xor, BinaryOperation) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001244
Vladimir Markob4536b72015-11-24 13:45:23 +00001245#ifndef ART_ENABLE_CODEGEN_arm
Alexandre Ramesef20f712015-06-09 10:29:30 +01001246#define FOR_EACH_CONCRETE_INSTRUCTION_ARM(M)
Vladimir Markob4536b72015-11-24 13:45:23 +00001247#else
1248#define FOR_EACH_CONCRETE_INSTRUCTION_ARM(M) \
1249 M(ArmDexCacheArraysBase, Instruction)
1250#endif
Alexandre Ramesef20f712015-06-09 10:29:30 +01001251
Alexandre Ramese6dbf482015-10-19 10:10:41 +01001252#ifndef ART_ENABLE_CODEGEN_arm64
Alexandre Ramesef20f712015-06-09 10:29:30 +01001253#define FOR_EACH_CONCRETE_INSTRUCTION_ARM64(M)
Alexandre Ramese6dbf482015-10-19 10:10:41 +01001254#else
1255#define FOR_EACH_CONCRETE_INSTRUCTION_ARM64(M) \
Alexandre Rames8626b742015-11-25 16:28:08 +00001256 M(Arm64DataProcWithShifterOp, Instruction) \
Nicolas Geoffray6b5afdd2016-01-22 09:31:52 +00001257 M(Arm64IntermediateAddress, Instruction) \
1258 M(Arm64MultiplyAccumulate, Instruction)
Alexandre Ramese6dbf482015-10-19 10:10:41 +01001259#endif
Alexandre Ramesef20f712015-06-09 10:29:30 +01001260
Goran Jakovljevicf652cec2015-08-25 16:11:42 +02001261#define FOR_EACH_CONCRETE_INSTRUCTION_MIPS(M)
1262
Alexandre Ramesf39e0642015-06-23 11:33:45 +01001263#define FOR_EACH_CONCRETE_INSTRUCTION_MIPS64(M)
1264
Alexandre Ramese6dbf482015-10-19 10:10:41 +01001265#ifndef ART_ENABLE_CODEGEN_x86
1266#define FOR_EACH_CONCRETE_INSTRUCTION_X86(M)
1267#else
Mark Mendell0616ae02015-04-17 12:49:27 -04001268#define FOR_EACH_CONCRETE_INSTRUCTION_X86(M) \
1269 M(X86ComputeBaseMethodAddress, Instruction) \
Mark Mendell805b3b52015-09-18 14:10:29 -04001270 M(X86LoadFromConstantTable, Instruction) \
Mark P Mendell2f10a5f2016-01-25 14:47:50 +00001271 M(X86FPNeg, Instruction) \
Mark Mendell805b3b52015-09-18 14:10:29 -04001272 M(X86PackedSwitch, Instruction)
Alexandre Ramese6dbf482015-10-19 10:10:41 +01001273#endif
Alexandre Ramesef20f712015-06-09 10:29:30 +01001274
1275#define FOR_EACH_CONCRETE_INSTRUCTION_X86_64(M)
1276
1277#define FOR_EACH_CONCRETE_INSTRUCTION(M) \
1278 FOR_EACH_CONCRETE_INSTRUCTION_COMMON(M) \
1279 FOR_EACH_CONCRETE_INSTRUCTION_ARM(M) \
1280 FOR_EACH_CONCRETE_INSTRUCTION_ARM64(M) \
Goran Jakovljevicf652cec2015-08-25 16:11:42 +02001281 FOR_EACH_CONCRETE_INSTRUCTION_MIPS(M) \
Alexandre Ramesf39e0642015-06-23 11:33:45 +01001282 FOR_EACH_CONCRETE_INSTRUCTION_MIPS64(M) \
Alexandre Ramesef20f712015-06-09 10:29:30 +01001283 FOR_EACH_CONCRETE_INSTRUCTION_X86(M) \
1284 FOR_EACH_CONCRETE_INSTRUCTION_X86_64(M)
1285
Vladimir Marko5f7b58e2015-11-23 19:49:34 +00001286#define FOR_EACH_ABSTRACT_INSTRUCTION(M) \
1287 M(Condition, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001288 M(Constant, Instruction) \
Roland Levillain88cb1752014-10-20 16:36:47 +01001289 M(UnaryOperation, Instruction) \
Calin Juravle34bacdf2014-10-07 20:23:36 +01001290 M(BinaryOperation, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001291 M(Invoke, Instruction)
Dave Allison20dfc792014-06-16 20:44:29 -07001292
Vladimir Marko5f7b58e2015-11-23 19:49:34 +00001293#define FOR_EACH_INSTRUCTION(M) \
1294 FOR_EACH_CONCRETE_INSTRUCTION(M) \
1295 FOR_EACH_ABSTRACT_INSTRUCTION(M)
1296
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001297#define FORWARD_DECLARATION(type, super) class H##type;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001298FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
1299#undef FORWARD_DECLARATION
1300
Roland Levillainccc07a92014-09-16 14:48:16 +01001301#define DECLARE_INSTRUCTION(type) \
Vladimir Marko5f7b58e2015-11-23 19:49:34 +00001302 InstructionKind GetKindInternal() const OVERRIDE { return k##type; } \
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001303 const char* DebugName() const OVERRIDE { return #type; } \
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001304 bool InstructionTypeEquals(HInstruction* other) const OVERRIDE { \
Roland Levillainccc07a92014-09-16 14:48:16 +01001305 return other->Is##type(); \
1306 } \
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001307 void Accept(HGraphVisitor* visitor) OVERRIDE
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001308
Vladimir Marko5f7b58e2015-11-23 19:49:34 +00001309#define DECLARE_ABSTRACT_INSTRUCTION(type) \
1310 bool Is##type() const { return As##type() != nullptr; } \
1311 const H##type* As##type() const { return this; } \
1312 H##type* As##type() { return this; }
1313
David Brazdiled596192015-01-23 10:39:45 +00001314template <typename T> class HUseList;
1315
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001316template <typename T>
Vladimir Markof9f64412015-09-02 14:05:49 +01001317class HUseListNode : public ArenaObject<kArenaAllocUseListNode> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001318 public:
David Brazdiled596192015-01-23 10:39:45 +00001319 HUseListNode* GetPrevious() const { return prev_; }
1320 HUseListNode* GetNext() const { return next_; }
1321 T GetUser() const { return user_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001322 size_t GetIndex() const { return index_; }
Nicolas Geoffray5d7b7f82015-04-28 00:52:43 +01001323 void SetIndex(size_t index) { index_ = index; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001324
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001325 private:
David Brazdiled596192015-01-23 10:39:45 +00001326 HUseListNode(T user, size_t index)
1327 : user_(user), index_(index), prev_(nullptr), next_(nullptr) {}
1328
1329 T const user_;
Nicolas Geoffray5d7b7f82015-04-28 00:52:43 +01001330 size_t index_;
David Brazdiled596192015-01-23 10:39:45 +00001331 HUseListNode<T>* prev_;
1332 HUseListNode<T>* next_;
1333
1334 friend class HUseList<T>;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001335
1336 DISALLOW_COPY_AND_ASSIGN(HUseListNode);
1337};
1338
David Brazdiled596192015-01-23 10:39:45 +00001339template <typename T>
1340class HUseList : public ValueObject {
1341 public:
1342 HUseList() : first_(nullptr) {}
1343
1344 void Clear() {
1345 first_ = nullptr;
1346 }
1347
1348 // Adds a new entry at the beginning of the use list and returns
1349 // the newly created node.
1350 HUseListNode<T>* AddUse(T user, size_t index, ArenaAllocator* arena) {
David Brazdilea55b932015-01-27 17:12:29 +00001351 HUseListNode<T>* new_node = new (arena) HUseListNode<T>(user, index);
David Brazdiled596192015-01-23 10:39:45 +00001352 if (IsEmpty()) {
1353 first_ = new_node;
1354 } else {
1355 first_->prev_ = new_node;
1356 new_node->next_ = first_;
1357 first_ = new_node;
1358 }
1359 return new_node;
1360 }
1361
1362 HUseListNode<T>* GetFirst() const {
1363 return first_;
1364 }
1365
1366 void Remove(HUseListNode<T>* node) {
David Brazdil1abb4192015-02-17 18:33:36 +00001367 DCHECK(node != nullptr);
1368 DCHECK(Contains(node));
1369
David Brazdiled596192015-01-23 10:39:45 +00001370 if (node->prev_ != nullptr) {
1371 node->prev_->next_ = node->next_;
1372 }
1373 if (node->next_ != nullptr) {
1374 node->next_->prev_ = node->prev_;
1375 }
1376 if (node == first_) {
1377 first_ = node->next_;
1378 }
1379 }
1380
David Brazdil1abb4192015-02-17 18:33:36 +00001381 bool Contains(const HUseListNode<T>* node) const {
1382 if (node == nullptr) {
1383 return false;
1384 }
1385 for (HUseListNode<T>* current = first_; current != nullptr; current = current->GetNext()) {
1386 if (current == node) {
1387 return true;
1388 }
1389 }
1390 return false;
1391 }
1392
David Brazdiled596192015-01-23 10:39:45 +00001393 bool IsEmpty() const {
1394 return first_ == nullptr;
1395 }
1396
1397 bool HasOnlyOneUse() const {
1398 return first_ != nullptr && first_->next_ == nullptr;
1399 }
1400
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001401 size_t SizeSlow() const {
1402 size_t count = 0;
1403 for (HUseListNode<T>* current = first_; current != nullptr; current = current->GetNext()) {
1404 ++count;
1405 }
1406 return count;
1407 }
1408
David Brazdiled596192015-01-23 10:39:45 +00001409 private:
1410 HUseListNode<T>* first_;
1411};
1412
1413template<typename T>
1414class HUseIterator : public ValueObject {
1415 public:
1416 explicit HUseIterator(const HUseList<T>& uses) : current_(uses.GetFirst()) {}
1417
1418 bool Done() const { return current_ == nullptr; }
1419
1420 void Advance() {
1421 DCHECK(!Done());
1422 current_ = current_->GetNext();
1423 }
1424
1425 HUseListNode<T>* Current() const {
1426 DCHECK(!Done());
1427 return current_;
1428 }
1429
1430 private:
1431 HUseListNode<T>* current_;
1432
1433 friend class HValue;
1434};
1435
David Brazdil1abb4192015-02-17 18:33:36 +00001436// This class is used by HEnvironment and HInstruction classes to record the
1437// instructions they use and pointers to the corresponding HUseListNodes kept
1438// by the used instructions.
1439template <typename T>
Vladimir Marko76c92ac2015-09-17 15:39:16 +01001440class HUserRecord : public ValueObject {
David Brazdil1abb4192015-02-17 18:33:36 +00001441 public:
1442 HUserRecord() : instruction_(nullptr), use_node_(nullptr) {}
1443 explicit HUserRecord(HInstruction* instruction) : instruction_(instruction), use_node_(nullptr) {}
1444
1445 HUserRecord(const HUserRecord<T>& old_record, HUseListNode<T>* use_node)
1446 : instruction_(old_record.instruction_), use_node_(use_node) {
1447 DCHECK(instruction_ != nullptr);
1448 DCHECK(use_node_ != nullptr);
1449 DCHECK(old_record.use_node_ == nullptr);
1450 }
1451
1452 HInstruction* GetInstruction() const { return instruction_; }
1453 HUseListNode<T>* GetUseNode() const { return use_node_; }
1454
1455 private:
1456 // Instruction used by the user.
1457 HInstruction* instruction_;
1458
1459 // Corresponding entry in the use list kept by 'instruction_'.
1460 HUseListNode<T>* use_node_;
1461};
1462
Aart Bik854a02b2015-07-14 16:07:00 -07001463/**
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001464 * Side-effects representation.
Aart Bik854a02b2015-07-14 16:07:00 -07001465 *
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001466 * For write/read dependences on fields/arrays, the dependence analysis uses
1467 * type disambiguation (e.g. a float field write cannot modify the value of an
1468 * integer field read) and the access type (e.g. a reference array write cannot
1469 * modify the value of a reference field read [although it may modify the
1470 * reference fetch prior to reading the field, which is represented by its own
1471 * write/read dependence]). The analysis makes conservative points-to
1472 * assumptions on reference types (e.g. two same typed arrays are assumed to be
1473 * the same, and any reference read depends on any reference read without
1474 * further regard of its type).
Aart Bik854a02b2015-07-14 16:07:00 -07001475 *
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001476 * The internal representation uses 38-bit and is described in the table below.
1477 * The first line indicates the side effect, and for field/array accesses the
1478 * second line indicates the type of the access (in the order of the
1479 * Primitive::Type enum).
1480 * The two numbered lines below indicate the bit position in the bitfield (read
1481 * vertically).
Aart Bik854a02b2015-07-14 16:07:00 -07001482 *
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001483 * |Depends on GC|ARRAY-R |FIELD-R |Can trigger GC|ARRAY-W |FIELD-W |
1484 * +-------------+---------+---------+--------------+---------+---------+
1485 * | |DFJISCBZL|DFJISCBZL| |DFJISCBZL|DFJISCBZL|
1486 * | 3 |333333322|222222221| 1 |111111110|000000000|
1487 * | 7 |654321098|765432109| 8 |765432109|876543210|
1488 *
1489 * Note that, to ease the implementation, 'changes' bits are least significant
1490 * bits, while 'dependency' bits are most significant bits.
Aart Bik854a02b2015-07-14 16:07:00 -07001491 */
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001492class SideEffects : public ValueObject {
1493 public:
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001494 SideEffects() : flags_(0) {}
1495
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001496 static SideEffects None() {
1497 return SideEffects(0);
1498 }
1499
1500 static SideEffects All() {
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001501 return SideEffects(kAllChangeBits | kAllDependOnBits);
1502 }
1503
1504 static SideEffects AllChanges() {
1505 return SideEffects(kAllChangeBits);
1506 }
1507
1508 static SideEffects AllDependencies() {
1509 return SideEffects(kAllDependOnBits);
1510 }
1511
1512 static SideEffects AllExceptGCDependency() {
1513 return AllWritesAndReads().Union(SideEffects::CanTriggerGC());
1514 }
1515
1516 static SideEffects AllWritesAndReads() {
Aart Bik854a02b2015-07-14 16:07:00 -07001517 return SideEffects(kAllWrites | kAllReads);
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001518 }
1519
Aart Bik34c3ba92015-07-20 14:08:59 -07001520 static SideEffects AllWrites() {
1521 return SideEffects(kAllWrites);
1522 }
1523
1524 static SideEffects AllReads() {
1525 return SideEffects(kAllReads);
1526 }
1527
1528 static SideEffects FieldWriteOfType(Primitive::Type type, bool is_volatile) {
1529 return is_volatile
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001530 ? AllWritesAndReads()
Aart Bik34c3ba92015-07-20 14:08:59 -07001531 : SideEffects(TypeFlagWithAlias(type, kFieldWriteOffset));
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001532 }
1533
Aart Bik854a02b2015-07-14 16:07:00 -07001534 static SideEffects ArrayWriteOfType(Primitive::Type type) {
1535 return SideEffects(TypeFlagWithAlias(type, kArrayWriteOffset));
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001536 }
1537
Aart Bik34c3ba92015-07-20 14:08:59 -07001538 static SideEffects FieldReadOfType(Primitive::Type type, bool is_volatile) {
1539 return is_volatile
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001540 ? AllWritesAndReads()
Aart Bik34c3ba92015-07-20 14:08:59 -07001541 : SideEffects(TypeFlagWithAlias(type, kFieldReadOffset));
Aart Bik854a02b2015-07-14 16:07:00 -07001542 }
1543
1544 static SideEffects ArrayReadOfType(Primitive::Type type) {
1545 return SideEffects(TypeFlagWithAlias(type, kArrayReadOffset));
1546 }
1547
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001548 static SideEffects CanTriggerGC() {
1549 return SideEffects(1ULL << kCanTriggerGCBit);
1550 }
1551
1552 static SideEffects DependsOnGC() {
1553 return SideEffects(1ULL << kDependsOnGCBit);
1554 }
1555
Aart Bik854a02b2015-07-14 16:07:00 -07001556 // Combines the side-effects of this and the other.
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001557 SideEffects Union(SideEffects other) const {
1558 return SideEffects(flags_ | other.flags_);
1559 }
1560
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001561 SideEffects Exclusion(SideEffects other) const {
1562 return SideEffects(flags_ & ~other.flags_);
1563 }
1564
Alexandre Ramese6dbf482015-10-19 10:10:41 +01001565 void Add(SideEffects other) {
1566 flags_ |= other.flags_;
1567 }
1568
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001569 bool Includes(SideEffects other) const {
1570 return (other.flags_ & flags_) == other.flags_;
1571 }
1572
1573 bool HasSideEffects() const {
1574 return (flags_ & kAllChangeBits);
1575 }
1576
1577 bool HasDependencies() const {
1578 return (flags_ & kAllDependOnBits);
1579 }
1580
1581 // Returns true if there are no side effects or dependencies.
1582 bool DoesNothing() const {
1583 return flags_ == 0;
1584 }
1585
Aart Bik854a02b2015-07-14 16:07:00 -07001586 // Returns true if something is written.
1587 bool DoesAnyWrite() const {
1588 return (flags_ & kAllWrites);
Roland Levillain72bceff2014-09-15 18:29:00 +01001589 }
1590
Aart Bik854a02b2015-07-14 16:07:00 -07001591 // Returns true if something is read.
1592 bool DoesAnyRead() const {
1593 return (flags_ & kAllReads);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001594 }
1595
Aart Bik854a02b2015-07-14 16:07:00 -07001596 // Returns true if potentially everything is written and read
1597 // (every type and every kind of access).
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001598 bool DoesAllReadWrite() const {
1599 return (flags_ & (kAllWrites | kAllReads)) == (kAllWrites | kAllReads);
1600 }
1601
Aart Bik854a02b2015-07-14 16:07:00 -07001602 bool DoesAll() const {
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001603 return flags_ == (kAllChangeBits | kAllDependOnBits);
Aart Bik854a02b2015-07-14 16:07:00 -07001604 }
1605
Roland Levillain0d5a2812015-11-13 10:07:31 +00001606 // Returns true if `this` may read something written by `other`.
Aart Bik854a02b2015-07-14 16:07:00 -07001607 bool MayDependOn(SideEffects other) const {
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001608 const uint64_t depends_on_flags = (flags_ & kAllDependOnBits) >> kChangeBits;
1609 return (other.flags_ & depends_on_flags);
Aart Bik854a02b2015-07-14 16:07:00 -07001610 }
1611
1612 // Returns string representation of flags (for debugging only).
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001613 // Format: |x|DFJISCBZL|DFJISCBZL|y|DFJISCBZL|DFJISCBZL|
Aart Bik854a02b2015-07-14 16:07:00 -07001614 std::string ToString() const {
Aart Bik854a02b2015-07-14 16:07:00 -07001615 std::string flags = "|";
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001616 for (int s = kLastBit; s >= 0; s--) {
1617 bool current_bit_is_set = ((flags_ >> s) & 1) != 0;
1618 if ((s == kDependsOnGCBit) || (s == kCanTriggerGCBit)) {
1619 // This is a bit for the GC side effect.
1620 if (current_bit_is_set) {
1621 flags += "GC";
1622 }
Aart Bik854a02b2015-07-14 16:07:00 -07001623 flags += "|";
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001624 } else {
1625 // This is a bit for the array/field analysis.
1626 // The underscore character stands for the 'can trigger GC' bit.
1627 static const char *kDebug = "LZBCSIJFDLZBCSIJFD_LZBCSIJFDLZBCSIJFD";
1628 if (current_bit_is_set) {
1629 flags += kDebug[s];
1630 }
1631 if ((s == kFieldWriteOffset) || (s == kArrayWriteOffset) ||
1632 (s == kFieldReadOffset) || (s == kArrayReadOffset)) {
1633 flags += "|";
1634 }
1635 }
Aart Bik854a02b2015-07-14 16:07:00 -07001636 }
1637 return flags;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001638 }
1639
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001640 bool Equals(const SideEffects& other) const { return flags_ == other.flags_; }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001641
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001642 private:
1643 static constexpr int kFieldArrayAnalysisBits = 9;
1644
1645 static constexpr int kFieldWriteOffset = 0;
1646 static constexpr int kArrayWriteOffset = kFieldWriteOffset + kFieldArrayAnalysisBits;
1647 static constexpr int kLastBitForWrites = kArrayWriteOffset + kFieldArrayAnalysisBits - 1;
1648 static constexpr int kCanTriggerGCBit = kLastBitForWrites + 1;
1649
1650 static constexpr int kChangeBits = kCanTriggerGCBit + 1;
1651
1652 static constexpr int kFieldReadOffset = kCanTriggerGCBit + 1;
1653 static constexpr int kArrayReadOffset = kFieldReadOffset + kFieldArrayAnalysisBits;
1654 static constexpr int kLastBitForReads = kArrayReadOffset + kFieldArrayAnalysisBits - 1;
1655 static constexpr int kDependsOnGCBit = kLastBitForReads + 1;
1656
1657 static constexpr int kLastBit = kDependsOnGCBit;
1658 static constexpr int kDependOnBits = kLastBit + 1 - kChangeBits;
1659
1660 // Aliases.
1661
1662 static_assert(kChangeBits == kDependOnBits,
1663 "the 'change' bits should match the 'depend on' bits.");
1664
1665 static constexpr uint64_t kAllChangeBits = ((1ULL << kChangeBits) - 1);
1666 static constexpr uint64_t kAllDependOnBits = ((1ULL << kDependOnBits) - 1) << kChangeBits;
1667 static constexpr uint64_t kAllWrites =
1668 ((1ULL << (kLastBitForWrites + 1 - kFieldWriteOffset)) - 1) << kFieldWriteOffset;
1669 static constexpr uint64_t kAllReads =
1670 ((1ULL << (kLastBitForReads + 1 - kFieldReadOffset)) - 1) << kFieldReadOffset;
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001671
Aart Bik854a02b2015-07-14 16:07:00 -07001672 // Work around the fact that HIR aliases I/F and J/D.
1673 // TODO: remove this interceptor once HIR types are clean
1674 static uint64_t TypeFlagWithAlias(Primitive::Type type, int offset) {
1675 switch (type) {
1676 case Primitive::kPrimInt:
1677 case Primitive::kPrimFloat:
1678 return TypeFlag(Primitive::kPrimInt, offset) |
1679 TypeFlag(Primitive::kPrimFloat, offset);
1680 case Primitive::kPrimLong:
1681 case Primitive::kPrimDouble:
1682 return TypeFlag(Primitive::kPrimLong, offset) |
1683 TypeFlag(Primitive::kPrimDouble, offset);
1684 default:
1685 return TypeFlag(type, offset);
1686 }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001687 }
1688
Aart Bik854a02b2015-07-14 16:07:00 -07001689 // Translates type to bit flag.
1690 static uint64_t TypeFlag(Primitive::Type type, int offset) {
1691 CHECK_NE(type, Primitive::kPrimVoid);
1692 const uint64_t one = 1;
1693 const int shift = type; // 0-based consecutive enum
1694 DCHECK_LE(kFieldWriteOffset, shift);
1695 DCHECK_LT(shift, kArrayWriteOffset);
1696 return one << (type + offset);
1697 }
1698
1699 // Private constructor on direct flags value.
1700 explicit SideEffects(uint64_t flags) : flags_(flags) {}
1701
1702 uint64_t flags_;
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001703};
1704
David Brazdiled596192015-01-23 10:39:45 +00001705// A HEnvironment object contains the values of virtual registers at a given location.
Vladimir Markof9f64412015-09-02 14:05:49 +01001706class HEnvironment : public ArenaObject<kArenaAllocEnvironment> {
David Brazdiled596192015-01-23 10:39:45 +00001707 public:
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001708 HEnvironment(ArenaAllocator* arena,
1709 size_t number_of_vregs,
1710 const DexFile& dex_file,
1711 uint32_t method_idx,
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001712 uint32_t dex_pc,
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001713 InvokeType invoke_type,
1714 HInstruction* holder)
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001715 : vregs_(number_of_vregs, arena->Adapter(kArenaAllocEnvironmentVRegs)),
1716 locations_(number_of_vregs, arena->Adapter(kArenaAllocEnvironmentLocations)),
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001717 parent_(nullptr),
1718 dex_file_(dex_file),
1719 method_idx_(method_idx),
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001720 dex_pc_(dex_pc),
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001721 invoke_type_(invoke_type),
1722 holder_(holder) {
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001723 }
1724
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001725 HEnvironment(ArenaAllocator* arena, const HEnvironment& to_copy, HInstruction* holder)
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001726 : HEnvironment(arena,
1727 to_copy.Size(),
1728 to_copy.GetDexFile(),
1729 to_copy.GetMethodIdx(),
1730 to_copy.GetDexPc(),
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001731 to_copy.GetInvokeType(),
1732 holder) {}
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001733
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001734 void SetAndCopyParentChain(ArenaAllocator* allocator, HEnvironment* parent) {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001735 if (parent_ != nullptr) {
1736 parent_->SetAndCopyParentChain(allocator, parent);
1737 } else {
1738 parent_ = new (allocator) HEnvironment(allocator, *parent, holder_);
1739 parent_->CopyFrom(parent);
1740 if (parent->GetParent() != nullptr) {
1741 parent_->SetAndCopyParentChain(allocator, parent->GetParent());
1742 }
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001743 }
David Brazdiled596192015-01-23 10:39:45 +00001744 }
1745
Vladimir Marko71bf8092015-09-15 15:33:14 +01001746 void CopyFrom(const ArenaVector<HInstruction*>& locals);
Nicolas Geoffray8c0c91a2015-05-07 11:46:05 +01001747 void CopyFrom(HEnvironment* environment);
1748
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001749 // Copy from `env`. If it's a loop phi for `loop_header`, copy the first
1750 // input to the loop phi instead. This is for inserting instructions that
1751 // require an environment (like HDeoptimization) in the loop pre-header.
1752 void CopyFromWithLoopPhiAdjustment(HEnvironment* env, HBasicBlock* loop_header);
David Brazdiled596192015-01-23 10:39:45 +00001753
1754 void SetRawEnvAt(size_t index, HInstruction* instruction) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001755 vregs_[index] = HUserRecord<HEnvironment*>(instruction);
David Brazdiled596192015-01-23 10:39:45 +00001756 }
1757
1758 HInstruction* GetInstructionAt(size_t index) const {
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001759 return vregs_[index].GetInstruction();
David Brazdiled596192015-01-23 10:39:45 +00001760 }
1761
David Brazdil1abb4192015-02-17 18:33:36 +00001762 void RemoveAsUserOfInput(size_t index) const;
David Brazdiled596192015-01-23 10:39:45 +00001763
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001764 size_t Size() const { return vregs_.size(); }
David Brazdiled596192015-01-23 10:39:45 +00001765
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001766 HEnvironment* GetParent() const { return parent_; }
1767
1768 void SetLocationAt(size_t index, Location location) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001769 locations_[index] = location;
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001770 }
1771
1772 Location GetLocationAt(size_t index) const {
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001773 return locations_[index];
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001774 }
1775
1776 uint32_t GetDexPc() const {
1777 return dex_pc_;
1778 }
1779
1780 uint32_t GetMethodIdx() const {
1781 return method_idx_;
1782 }
1783
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001784 InvokeType GetInvokeType() const {
1785 return invoke_type_;
1786 }
1787
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001788 const DexFile& GetDexFile() const {
1789 return dex_file_;
1790 }
1791
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001792 HInstruction* GetHolder() const {
1793 return holder_;
1794 }
1795
Nicolas Geoffray8e1ef532015-11-23 12:04:37 +00001796
1797 bool IsFromInlinedInvoke() const {
1798 return GetParent() != nullptr;
1799 }
1800
David Brazdiled596192015-01-23 10:39:45 +00001801 private:
David Brazdil1abb4192015-02-17 18:33:36 +00001802 // Record instructions' use entries of this environment for constant-time removal.
1803 // It should only be called by HInstruction when a new environment use is added.
1804 void RecordEnvUse(HUseListNode<HEnvironment*>* env_use) {
1805 DCHECK(env_use->GetUser() == this);
1806 size_t index = env_use->GetIndex();
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001807 vregs_[index] = HUserRecord<HEnvironment*>(vregs_[index], env_use);
David Brazdil1abb4192015-02-17 18:33:36 +00001808 }
David Brazdiled596192015-01-23 10:39:45 +00001809
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001810 ArenaVector<HUserRecord<HEnvironment*>> vregs_;
1811 ArenaVector<Location> locations_;
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001812 HEnvironment* parent_;
1813 const DexFile& dex_file_;
1814 const uint32_t method_idx_;
1815 const uint32_t dex_pc_;
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001816 const InvokeType invoke_type_;
David Brazdiled596192015-01-23 10:39:45 +00001817
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +01001818 // The instruction that holds this environment.
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001819 HInstruction* const holder_;
1820
Nicolas Geoffray5d7b7f82015-04-28 00:52:43 +01001821 friend class HInstruction;
David Brazdiled596192015-01-23 10:39:45 +00001822
1823 DISALLOW_COPY_AND_ASSIGN(HEnvironment);
1824};
1825
Vladimir Markof9f64412015-09-02 14:05:49 +01001826class HInstruction : public ArenaObject<kArenaAllocInstruction> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001827 public:
Calin Juravle154746b2015-10-06 15:46:54 +01001828 HInstruction(SideEffects side_effects, uint32_t dex_pc)
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001829 : previous_(nullptr),
1830 next_(nullptr),
1831 block_(nullptr),
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001832 dex_pc_(dex_pc),
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001833 id_(-1),
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001834 ssa_index_(-1),
David Brazdilb3e773e2016-01-26 11:28:37 +00001835 emitted_at_use_site_(false),
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001836 environment_(nullptr),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001837 locations_(nullptr),
1838 live_interval_(nullptr),
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001839 lifetime_position_(kNoLifetime),
Calin Juravleb1498f62015-02-16 13:13:29 +00001840 side_effects_(side_effects),
Calin Juravle2e768302015-07-28 14:41:11 +00001841 reference_type_info_(ReferenceTypeInfo::CreateInvalid()) {}
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001842
Dave Allison20dfc792014-06-16 20:44:29 -07001843 virtual ~HInstruction() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001844
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001845#define DECLARE_KIND(type, super) k##type,
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001846 enum InstructionKind {
1847 FOR_EACH_INSTRUCTION(DECLARE_KIND)
1848 };
1849#undef DECLARE_KIND
1850
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001851 HInstruction* GetNext() const { return next_; }
1852 HInstruction* GetPrevious() const { return previous_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001853
Calin Juravle77520bc2015-01-12 18:45:46 +00001854 HInstruction* GetNextDisregardingMoves() const;
1855 HInstruction* GetPreviousDisregardingMoves() const;
1856
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001857 HBasicBlock* GetBlock() const { return block_; }
Roland Levillain9867bc72015-08-05 10:21:34 +01001858 ArenaAllocator* GetArena() const { return block_->GetGraph()->GetArena(); }
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001859 void SetBlock(HBasicBlock* block) { block_ = block; }
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01001860 bool IsInBlock() const { return block_ != nullptr; }
1861 bool IsInLoop() const { return block_->IsInLoop(); }
Nicolas Geoffray15bd2282016-01-05 15:55:41 +00001862 bool IsLoopHeaderPhi() const { return IsPhi() && block_->IsLoopHeader(); }
1863 bool IsIrreducibleLoopHeaderPhi() const {
1864 return IsLoopHeaderPhi() && GetBlock()->GetLoopInformation()->IsIrreducible();
1865 }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001866
Roland Levillain6b879dd2014-09-22 17:13:44 +01001867 virtual size_t InputCount() const = 0;
David Brazdil1abb4192015-02-17 18:33:36 +00001868 HInstruction* InputAt(size_t i) const { return InputRecordAt(i).GetInstruction(); }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001869
1870 virtual void Accept(HGraphVisitor* visitor) = 0;
1871 virtual const char* DebugName() const = 0;
1872
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001873 virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
David Brazdil1abb4192015-02-17 18:33:36 +00001874 void SetRawInputAt(size_t index, HInstruction* input) {
1875 SetRawInputRecordAt(index, HUserRecord<HInstruction*>(input));
1876 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001877
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001878 virtual bool NeedsEnvironment() const { return false; }
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001879
1880 uint32_t GetDexPc() const { return dex_pc_; }
1881
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001882 virtual bool IsControlFlow() const { return false; }
David Brazdilec16f792015-08-19 15:04:01 +01001883
Roland Levillaine161a2a2014-10-03 12:45:18 +01001884 virtual bool CanThrow() const { return false; }
David Brazdilec16f792015-08-19 15:04:01 +01001885 bool CanThrowIntoCatchBlock() const { return CanThrow() && block_->IsTryBlock(); }
Aart Bik854a02b2015-07-14 16:07:00 -07001886
Alexandre Rames78e3ef62015-08-12 13:43:29 +01001887 bool HasSideEffects() const { return side_effects_.HasSideEffects(); }
Aart Bik854a02b2015-07-14 16:07:00 -07001888 bool DoesAnyWrite() const { return side_effects_.DoesAnyWrite(); }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001889
Calin Juravle10e244f2015-01-26 18:54:32 +00001890 // Does not apply for all instructions, but having this at top level greatly
1891 // simplifies the null check elimination.
Calin Juravlea5ae3c32015-07-28 14:40:50 +00001892 // TODO: Consider merging can_be_null into ReferenceTypeInfo.
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00001893 virtual bool CanBeNull() const {
1894 DCHECK_EQ(GetType(), Primitive::kPrimNot) << "CanBeNull only applies to reference types";
1895 return true;
1896 }
Calin Juravle10e244f2015-01-26 18:54:32 +00001897
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01001898 virtual bool CanDoImplicitNullCheckOn(HInstruction* obj ATTRIBUTE_UNUSED) const {
Calin Juravle641547a2015-04-21 22:08:51 +01001899 return false;
1900 }
Calin Juravle77520bc2015-01-12 18:45:46 +00001901
Nicolas Geoffraya3eca2d2016-01-12 16:03:16 +00001902 virtual bool IsActualObject() const {
1903 return GetType() == Primitive::kPrimNot;
1904 }
1905
Calin Juravle2e768302015-07-28 14:41:11 +00001906 void SetReferenceTypeInfo(ReferenceTypeInfo rti);
Calin Juravleacf735c2015-02-12 15:25:22 +00001907
Calin Juravle61d544b2015-02-23 16:46:57 +00001908 ReferenceTypeInfo GetReferenceTypeInfo() const {
1909 DCHECK_EQ(GetType(), Primitive::kPrimNot);
1910 return reference_type_info_;
1911 }
Calin Juravleacf735c2015-02-12 15:25:22 +00001912
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001913 void AddUseAt(HInstruction* user, size_t index) {
David Brazdil1abb4192015-02-17 18:33:36 +00001914 DCHECK(user != nullptr);
1915 HUseListNode<HInstruction*>* use =
1916 uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena());
1917 user->SetRawInputRecordAt(index, HUserRecord<HInstruction*>(user->InputRecordAt(index), use));
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001918 }
1919
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001920 void AddEnvUseAt(HEnvironment* user, size_t index) {
Nicolas Geoffray724c9632014-09-22 12:27:27 +01001921 DCHECK(user != nullptr);
David Brazdiled596192015-01-23 10:39:45 +00001922 HUseListNode<HEnvironment*>* env_use =
1923 env_uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena());
1924 user->RecordEnvUse(env_use);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001925 }
1926
David Brazdil1abb4192015-02-17 18:33:36 +00001927 void RemoveAsUserOfInput(size_t input) {
1928 HUserRecord<HInstruction*> input_use = InputRecordAt(input);
1929 input_use.GetInstruction()->uses_.Remove(input_use.GetUseNode());
1930 }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001931
David Brazdil1abb4192015-02-17 18:33:36 +00001932 const HUseList<HInstruction*>& GetUses() const { return uses_; }
1933 const HUseList<HEnvironment*>& GetEnvUses() const { return env_uses_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001934
David Brazdiled596192015-01-23 10:39:45 +00001935 bool HasUses() const { return !uses_.IsEmpty() || !env_uses_.IsEmpty(); }
1936 bool HasEnvironmentUses() const { return !env_uses_.IsEmpty(); }
Nicolas Geoffray915b9d02015-03-11 15:11:19 +00001937 bool HasNonEnvironmentUses() const { return !uses_.IsEmpty(); }
Alexandre Rames188d4312015-04-09 18:30:21 +01001938 bool HasOnlyOneNonEnvironmentUse() const {
1939 return !HasEnvironmentUses() && GetUses().HasOnlyOneUse();
1940 }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001941
Roland Levillain6c82d402014-10-13 16:10:27 +01001942 // Does this instruction strictly dominate `other_instruction`?
1943 // Returns false if this instruction and `other_instruction` are the same.
1944 // Aborts if this instruction and `other_instruction` are both phis.
1945 bool StrictlyDominates(HInstruction* other_instruction) const;
Roland Levillainccc07a92014-09-16 14:48:16 +01001946
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001947 int GetId() const { return id_; }
1948 void SetId(int id) { id_ = id; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001949
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001950 int GetSsaIndex() const { return ssa_index_; }
1951 void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
1952 bool HasSsaIndex() const { return ssa_index_ != -1; }
1953
1954 bool HasEnvironment() const { return environment_ != nullptr; }
1955 HEnvironment* GetEnvironment() const { return environment_; }
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001956 // Set the `environment_` field. Raw because this method does not
1957 // update the uses lists.
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001958 void SetRawEnvironment(HEnvironment* environment) {
1959 DCHECK(environment_ == nullptr);
1960 DCHECK_EQ(environment->GetHolder(), this);
1961 environment_ = environment;
1962 }
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001963
1964 // Set the environment of this instruction, copying it from `environment`. While
1965 // copying, the uses lists are being updated.
1966 void CopyEnvironmentFrom(HEnvironment* environment) {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001967 DCHECK(environment_ == nullptr);
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001968 ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena();
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001969 environment_ = new (allocator) HEnvironment(allocator, *environment, this);
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001970 environment_->CopyFrom(environment);
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001971 if (environment->GetParent() != nullptr) {
1972 environment_->SetAndCopyParentChain(allocator, environment->GetParent());
1973 }
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001974 }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001975
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001976 void CopyEnvironmentFromWithLoopPhiAdjustment(HEnvironment* environment,
1977 HBasicBlock* block) {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001978 DCHECK(environment_ == nullptr);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001979 ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena();
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001980 environment_ = new (allocator) HEnvironment(allocator, *environment, this);
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001981 environment_->CopyFromWithLoopPhiAdjustment(environment, block);
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001982 if (environment->GetParent() != nullptr) {
1983 environment_->SetAndCopyParentChain(allocator, environment->GetParent());
1984 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001985 }
1986
Nicolas Geoffray39468442014-09-02 15:17:15 +01001987 // Returns the number of entries in the environment. Typically, that is the
1988 // number of dex registers in a method. It could be more in case of inlining.
1989 size_t EnvironmentSize() const;
1990
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001991 LocationSummary* GetLocations() const { return locations_; }
1992 void SetLocations(LocationSummary* locations) { locations_ = locations; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001993
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001994 void ReplaceWith(HInstruction* instruction);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001995 void ReplaceInput(HInstruction* replacement, size_t index);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001996
Alexandre Rames188d4312015-04-09 18:30:21 +01001997 // This is almost the same as doing `ReplaceWith()`. But in this helper, the
1998 // uses of this instruction by `other` are *not* updated.
1999 void ReplaceWithExceptInReplacementAtIndex(HInstruction* other, size_t use_index) {
2000 ReplaceWith(other);
2001 other->ReplaceInput(this, use_index);
2002 }
2003
Nicolas Geoffray82091da2015-01-26 10:02:45 +00002004 // Move `this` instruction before `cursor`.
2005 void MoveBefore(HInstruction* cursor);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002006
Vladimir Markofb337ea2015-11-25 15:25:10 +00002007 // Move `this` before its first user and out of any loops. If there is no
2008 // out-of-loop user that dominates all other users, move the instruction
2009 // to the end of the out-of-loop common dominator of the user's blocks.
2010 //
2011 // This can be used only on non-throwing instructions with no side effects that
2012 // have at least one use but no environment uses.
2013 void MoveBeforeFirstUserAndOutOfLoops();
2014
Nicolas Geoffray360231a2014-10-08 21:07:48 +01002015#define INSTRUCTION_TYPE_CHECK(type, super) \
Vladimir Marko5f7b58e2015-11-23 19:49:34 +00002016 bool Is##type() const; \
2017 const H##type* As##type() const; \
2018 H##type* As##type();
2019
2020 FOR_EACH_CONCRETE_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
2021#undef INSTRUCTION_TYPE_CHECK
2022
2023#define INSTRUCTION_TYPE_CHECK(type, super) \
Roland Levillainccc07a92014-09-16 14:48:16 +01002024 bool Is##type() const { return (As##type() != nullptr); } \
2025 virtual const H##type* As##type() const { return nullptr; } \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002026 virtual H##type* As##type() { return nullptr; }
Vladimir Marko5f7b58e2015-11-23 19:49:34 +00002027 FOR_EACH_ABSTRACT_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002028#undef INSTRUCTION_TYPE_CHECK
2029
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002030 // Returns whether the instruction can be moved within the graph.
2031 virtual bool CanBeMoved() const { return false; }
2032
2033 // Returns whether the two instructions are of the same kind.
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01002034 virtual bool InstructionTypeEquals(HInstruction* other ATTRIBUTE_UNUSED) const {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002035 return false;
2036 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002037
2038 // Returns whether any data encoded in the two instructions is equal.
2039 // This method does not look at the inputs. Both instructions must be
2040 // of the same type, otherwise the method has undefined behavior.
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01002041 virtual bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002042 return false;
2043 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002044
2045 // Returns whether two instructions are equal, that is:
Calin Juravleddb7df22014-11-25 20:56:51 +00002046 // 1) They have the same type and contain the same data (InstructionDataEquals).
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002047 // 2) Their inputs are identical.
2048 bool Equals(HInstruction* other) const;
2049
Vladimir Marko5f7b58e2015-11-23 19:49:34 +00002050 // TODO: Remove this indirection when the [[pure]] attribute proposal (n3744)
2051 // is adopted and implemented by our C++ compiler(s). Fow now, we need to hide
2052 // the virtual function because the __attribute__((__pure__)) doesn't really
2053 // apply the strong requirement for virtual functions, preventing optimizations.
2054 InstructionKind GetKind() const PURE;
2055 virtual InstructionKind GetKindInternal() const = 0;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01002056
2057 virtual size_t ComputeHashCode() const {
2058 size_t result = GetKind();
2059 for (size_t i = 0, e = InputCount(); i < e; ++i) {
2060 result = (result * 31) + InputAt(i)->GetId();
2061 }
2062 return result;
2063 }
2064
2065 SideEffects GetSideEffects() const { return side_effects_; }
Alexandre Ramese6dbf482015-10-19 10:10:41 +01002066 void AddSideEffects(SideEffects other) { side_effects_.Add(other); }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01002067
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01002068 size_t GetLifetimePosition() const { return lifetime_position_; }
2069 void SetLifetimePosition(size_t position) { lifetime_position_ = position; }
2070 LiveInterval* GetLiveInterval() const { return live_interval_; }
2071 void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; }
2072 bool HasLiveInterval() const { return live_interval_ != nullptr; }
2073
Nicolas Geoffrayc0572a42015-02-06 14:35:25 +00002074 bool IsSuspendCheckEntry() const { return IsSuspendCheck() && GetBlock()->IsEntryBlock(); }
2075
2076 // Returns whether the code generation of the instruction will require to have access
2077 // to the current method. Such instructions are:
2078 // (1): Instructions that require an environment, as calling the runtime requires
2079 // to walk the stack and have the current method stored at a specific stack address.
2080 // (2): Object literals like classes and strings, that are loaded from the dex cache
2081 // fields of the current method.
2082 bool NeedsCurrentMethod() const {
2083 return NeedsEnvironment() || IsLoadClass() || IsLoadString();
2084 }
2085
Vladimir Markodc151b22015-10-15 18:02:30 +01002086 // Returns whether the code generation of the instruction will require to have access
2087 // to the dex cache of the current method's declaring class via the current method.
2088 virtual bool NeedsDexCacheOfDeclaringClass() const { return false; }
Nicolas Geoffray9437b782015-03-25 10:08:51 +00002089
Mark Mendellc4701932015-04-10 13:18:51 -04002090 // Does this instruction have any use in an environment before
2091 // control flow hits 'other'?
2092 bool HasAnyEnvironmentUseBefore(HInstruction* other);
2093
2094 // Remove all references to environment uses of this instruction.
2095 // The caller must ensure that this is safe to do.
2096 void RemoveEnvironmentUsers();
2097
David Brazdilb3e773e2016-01-26 11:28:37 +00002098 bool IsEmittedAtUseSite() const { return emitted_at_use_site_; }
2099 void MarkEmittedAtUseSite() { emitted_at_use_site_ = true; }
2100
David Brazdil1abb4192015-02-17 18:33:36 +00002101 protected:
2102 virtual const HUserRecord<HInstruction*> InputRecordAt(size_t i) const = 0;
2103 virtual void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) = 0;
Aart Bik5d75afe2015-12-14 11:57:01 -08002104 void SetSideEffects(SideEffects other) { side_effects_ = other; }
David Brazdil1abb4192015-02-17 18:33:36 +00002105
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002106 private:
David Brazdil1abb4192015-02-17 18:33:36 +00002107 void RemoveEnvironmentUser(HUseListNode<HEnvironment*>* use_node) { env_uses_.Remove(use_node); }
2108
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002109 HInstruction* previous_;
2110 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00002111 HBasicBlock* block_;
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002112 const uint32_t dex_pc_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002113
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002114 // An instruction gets an id when it is added to the graph.
2115 // It reflects creation order. A negative id means the instruction
Nicolas Geoffray39468442014-09-02 15:17:15 +01002116 // has not been added to the graph.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002117 int id_;
2118
Nicolas Geoffray804d0932014-05-02 08:46:00 +01002119 // When doing liveness analysis, instructions that have uses get an SSA index.
2120 int ssa_index_;
2121
David Brazdilb3e773e2016-01-26 11:28:37 +00002122 // If set, the machine code for this instruction is assumed to be generated by
2123 // its users. Used by liveness analysis to compute use positions accordingly.
2124 bool emitted_at_use_site_;
2125
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002126 // List of instructions that have this instruction as input.
David Brazdiled596192015-01-23 10:39:45 +00002127 HUseList<HInstruction*> uses_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002128
2129 // List of environments that contain this instruction.
David Brazdiled596192015-01-23 10:39:45 +00002130 HUseList<HEnvironment*> env_uses_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002131
Nicolas Geoffray39468442014-09-02 15:17:15 +01002132 // The environment associated with this instruction. Not null if the instruction
2133 // might jump out of the method.
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002134 HEnvironment* environment_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002135
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002136 // Set by the code generator.
2137 LocationSummary* locations_;
2138
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01002139 // Set by the liveness analysis.
2140 LiveInterval* live_interval_;
2141
2142 // Set by the liveness analysis, this is the position in a linear
2143 // order of blocks where this instruction's live interval start.
2144 size_t lifetime_position_;
2145
Alexandre Ramese6dbf482015-10-19 10:10:41 +01002146 SideEffects side_effects_;
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002147
Calin Juravleacf735c2015-02-12 15:25:22 +00002148 // TODO: for primitive types this should be marked as invalid.
2149 ReferenceTypeInfo reference_type_info_;
2150
David Brazdil1abb4192015-02-17 18:33:36 +00002151 friend class GraphChecker;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002152 friend class HBasicBlock;
David Brazdil1abb4192015-02-17 18:33:36 +00002153 friend class HEnvironment;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002154 friend class HGraph;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002155 friend class HInstructionList;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002156
2157 DISALLOW_COPY_AND_ASSIGN(HInstruction);
2158};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002159std::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind& rhs);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002160
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002161class HInputIterator : public ValueObject {
2162 public:
Dave Allison20dfc792014-06-16 20:44:29 -07002163 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002164
2165 bool Done() const { return index_ == instruction_->InputCount(); }
2166 HInstruction* Current() const { return instruction_->InputAt(index_); }
2167 void Advance() { index_++; }
2168
2169 private:
2170 HInstruction* instruction_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002171 size_t index_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002172
2173 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
2174};
2175
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002176class HInstructionIterator : public ValueObject {
2177 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002178 explicit HInstructionIterator(const HInstructionList& instructions)
2179 : instruction_(instructions.first_instruction_) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +00002180 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002181 }
2182
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002183 bool Done() const { return instruction_ == nullptr; }
2184 HInstruction* Current() const { return instruction_; }
2185 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002186 instruction_ = next_;
Nicolas Geoffray787c3072014-03-17 10:20:19 +00002187 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002188 }
2189
2190 private:
2191 HInstruction* instruction_;
2192 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01002193
2194 DISALLOW_COPY_AND_ASSIGN(HInstructionIterator);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002195};
2196
Nicolas Geoffray804d0932014-05-02 08:46:00 +01002197class HBackwardInstructionIterator : public ValueObject {
2198 public:
2199 explicit HBackwardInstructionIterator(const HInstructionList& instructions)
2200 : instruction_(instructions.last_instruction_) {
2201 next_ = Done() ? nullptr : instruction_->GetPrevious();
2202 }
2203
2204 bool Done() const { return instruction_ == nullptr; }
2205 HInstruction* Current() const { return instruction_; }
2206 void Advance() {
2207 instruction_ = next_;
2208 next_ = Done() ? nullptr : instruction_->GetPrevious();
2209 }
2210
2211 private:
2212 HInstruction* instruction_;
2213 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01002214
2215 DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01002216};
2217
Vladimir Markof9f64412015-09-02 14:05:49 +01002218template<size_t N>
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002219class HTemplateInstruction: public HInstruction {
2220 public:
Calin Juravle154746b2015-10-06 15:46:54 +01002221 HTemplateInstruction<N>(SideEffects side_effects, uint32_t dex_pc)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002222 : HInstruction(side_effects, dex_pc), inputs_() {}
Dave Allison20dfc792014-06-16 20:44:29 -07002223 virtual ~HTemplateInstruction() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002224
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002225 size_t InputCount() const OVERRIDE { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002226
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002227 protected:
Vladimir Markof9f64412015-09-02 14:05:49 +01002228 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE {
2229 DCHECK_LT(i, N);
2230 return inputs_[i];
2231 }
David Brazdil1abb4192015-02-17 18:33:36 +00002232
2233 void SetRawInputRecordAt(size_t i, const HUserRecord<HInstruction*>& input) OVERRIDE {
Vladimir Markof9f64412015-09-02 14:05:49 +01002234 DCHECK_LT(i, N);
David Brazdil1abb4192015-02-17 18:33:36 +00002235 inputs_[i] = input;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002236 }
2237
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002238 private:
Vladimir Markof9f64412015-09-02 14:05:49 +01002239 std::array<HUserRecord<HInstruction*>, N> inputs_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002240
2241 friend class SsaBuilder;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002242};
2243
Vladimir Markof9f64412015-09-02 14:05:49 +01002244// HTemplateInstruction specialization for N=0.
2245template<>
2246class HTemplateInstruction<0>: public HInstruction {
2247 public:
Calin Juravle154746b2015-10-06 15:46:54 +01002248 explicit HTemplateInstruction<0>(SideEffects side_effects, uint32_t dex_pc)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002249 : HInstruction(side_effects, dex_pc) {}
2250
Vladimir Markof9f64412015-09-02 14:05:49 +01002251 virtual ~HTemplateInstruction() {}
2252
2253 size_t InputCount() const OVERRIDE { return 0; }
2254
2255 protected:
2256 const HUserRecord<HInstruction*> InputRecordAt(size_t i ATTRIBUTE_UNUSED) const OVERRIDE {
2257 LOG(FATAL) << "Unreachable";
2258 UNREACHABLE();
2259 }
2260
2261 void SetRawInputRecordAt(size_t i ATTRIBUTE_UNUSED,
2262 const HUserRecord<HInstruction*>& input ATTRIBUTE_UNUSED) OVERRIDE {
2263 LOG(FATAL) << "Unreachable";
2264 UNREACHABLE();
2265 }
2266
2267 private:
2268 friend class SsaBuilder;
2269};
2270
Dave Allison20dfc792014-06-16 20:44:29 -07002271template<intptr_t N>
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002272class HExpression : public HTemplateInstruction<N> {
Dave Allison20dfc792014-06-16 20:44:29 -07002273 public:
Calin Juravle154746b2015-10-06 15:46:54 +01002274 HExpression<N>(Primitive::Type type, SideEffects side_effects, uint32_t dex_pc)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002275 : HTemplateInstruction<N>(side_effects, dex_pc), type_(type) {}
Dave Allison20dfc792014-06-16 20:44:29 -07002276 virtual ~HExpression() {}
2277
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002278 Primitive::Type GetType() const OVERRIDE { return type_; }
Dave Allison20dfc792014-06-16 20:44:29 -07002279
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002280 protected:
2281 Primitive::Type type_;
Dave Allison20dfc792014-06-16 20:44:29 -07002282};
2283
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002284// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
2285// instruction that branches to the exit block.
2286class HReturnVoid : public HTemplateInstruction<0> {
2287 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002288 explicit HReturnVoid(uint32_t dex_pc = kNoDexPc)
2289 : HTemplateInstruction(SideEffects::None(), dex_pc) {}
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01002290
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002291 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002292
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002293 DECLARE_INSTRUCTION(ReturnVoid);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002294
2295 private:
2296 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
2297};
2298
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002299// Represents dex's RETURN opcodes. A HReturn is a control flow
2300// instruction that branches to the exit block.
2301class HReturn : public HTemplateInstruction<1> {
2302 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002303 explicit HReturn(HInstruction* value, uint32_t dex_pc = kNoDexPc)
2304 : HTemplateInstruction(SideEffects::None(), dex_pc) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002305 SetRawInputAt(0, value);
2306 }
2307
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002308 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01002309
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002310 DECLARE_INSTRUCTION(Return);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002311
2312 private:
2313 DISALLOW_COPY_AND_ASSIGN(HReturn);
2314};
2315
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002316// The exit instruction is the only instruction of the exit block.
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002317// Instructions aborting the method (HThrow and HReturn) must branch to the
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002318// exit block.
2319class HExit : public HTemplateInstruction<0> {
2320 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002321 explicit HExit(uint32_t dex_pc = kNoDexPc) : HTemplateInstruction(SideEffects::None(), dex_pc) {}
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01002322
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002323 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002324
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002325 DECLARE_INSTRUCTION(Exit);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002326
2327 private:
2328 DISALLOW_COPY_AND_ASSIGN(HExit);
2329};
2330
2331// Jumps from one block to another.
2332class HGoto : public HTemplateInstruction<0> {
2333 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002334 explicit HGoto(uint32_t dex_pc = kNoDexPc) : HTemplateInstruction(SideEffects::None(), dex_pc) {}
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002335
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002336 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002337
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00002338 HBasicBlock* GetSuccessor() const {
David Brazdilfc6a86a2015-06-26 10:33:45 +00002339 return GetBlock()->GetSingleSuccessor();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00002340 }
2341
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002342 DECLARE_INSTRUCTION(Goto);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002343
2344 private:
2345 DISALLOW_COPY_AND_ASSIGN(HGoto);
2346};
2347
Roland Levillain9867bc72015-08-05 10:21:34 +01002348class HConstant : public HExpression<0> {
2349 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002350 explicit HConstant(Primitive::Type type, uint32_t dex_pc = kNoDexPc)
2351 : HExpression(type, SideEffects::None(), dex_pc) {}
Roland Levillain9867bc72015-08-05 10:21:34 +01002352
2353 bool CanBeMoved() const OVERRIDE { return true; }
2354
2355 virtual bool IsMinusOne() const { return false; }
2356 virtual bool IsZero() const { return false; }
2357 virtual bool IsOne() const { return false; }
2358
David Brazdil77a48ae2015-09-15 12:34:04 +00002359 virtual uint64_t GetValueAsUint64() const = 0;
2360
Vladimir Marko5f7b58e2015-11-23 19:49:34 +00002361 DECLARE_ABSTRACT_INSTRUCTION(Constant);
Roland Levillain9867bc72015-08-05 10:21:34 +01002362
2363 private:
2364 DISALLOW_COPY_AND_ASSIGN(HConstant);
2365};
2366
2367class HNullConstant : public HConstant {
2368 public:
2369 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
2370 return true;
2371 }
2372
David Brazdil77a48ae2015-09-15 12:34:04 +00002373 uint64_t GetValueAsUint64() const OVERRIDE { return 0; }
2374
Roland Levillain9867bc72015-08-05 10:21:34 +01002375 size_t ComputeHashCode() const OVERRIDE { return 0; }
2376
2377 DECLARE_INSTRUCTION(NullConstant);
2378
2379 private:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002380 explicit HNullConstant(uint32_t dex_pc = kNoDexPc) : HConstant(Primitive::kPrimNot, dex_pc) {}
Roland Levillain9867bc72015-08-05 10:21:34 +01002381
2382 friend class HGraph;
2383 DISALLOW_COPY_AND_ASSIGN(HNullConstant);
2384};
2385
2386// Constants of the type int. Those can be from Dex instructions, or
2387// synthesized (for example with the if-eqz instruction).
2388class HIntConstant : public HConstant {
2389 public:
2390 int32_t GetValue() const { return value_; }
2391
David Brazdil9f389d42015-10-01 14:32:56 +01002392 uint64_t GetValueAsUint64() const OVERRIDE {
2393 return static_cast<uint64_t>(static_cast<uint32_t>(value_));
2394 }
David Brazdil77a48ae2015-09-15 12:34:04 +00002395
Roland Levillain9867bc72015-08-05 10:21:34 +01002396 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2397 DCHECK(other->IsIntConstant());
2398 return other->AsIntConstant()->value_ == value_;
2399 }
2400
2401 size_t ComputeHashCode() const OVERRIDE { return GetValue(); }
2402
2403 bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
2404 bool IsZero() const OVERRIDE { return GetValue() == 0; }
2405 bool IsOne() const OVERRIDE { return GetValue() == 1; }
2406
2407 DECLARE_INSTRUCTION(IntConstant);
2408
2409 private:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002410 explicit HIntConstant(int32_t value, uint32_t dex_pc = kNoDexPc)
2411 : HConstant(Primitive::kPrimInt, dex_pc), value_(value) {}
2412 explicit HIntConstant(bool value, uint32_t dex_pc = kNoDexPc)
2413 : HConstant(Primitive::kPrimInt, dex_pc), value_(value ? 1 : 0) {}
Roland Levillain9867bc72015-08-05 10:21:34 +01002414
2415 const int32_t value_;
2416
2417 friend class HGraph;
2418 ART_FRIEND_TEST(GraphTest, InsertInstructionBefore);
2419 ART_FRIEND_TYPED_TEST(ParallelMoveTest, ConstantLast);
2420 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
2421};
2422
2423class HLongConstant : public HConstant {
2424 public:
2425 int64_t GetValue() const { return value_; }
2426
David Brazdil77a48ae2015-09-15 12:34:04 +00002427 uint64_t GetValueAsUint64() const OVERRIDE { return value_; }
2428
Roland Levillain9867bc72015-08-05 10:21:34 +01002429 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2430 DCHECK(other->IsLongConstant());
2431 return other->AsLongConstant()->value_ == value_;
2432 }
2433
2434 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
2435
2436 bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
2437 bool IsZero() const OVERRIDE { return GetValue() == 0; }
2438 bool IsOne() const OVERRIDE { return GetValue() == 1; }
2439
2440 DECLARE_INSTRUCTION(LongConstant);
2441
2442 private:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002443 explicit HLongConstant(int64_t value, uint32_t dex_pc = kNoDexPc)
2444 : HConstant(Primitive::kPrimLong, dex_pc), value_(value) {}
Roland Levillain9867bc72015-08-05 10:21:34 +01002445
2446 const int64_t value_;
2447
2448 friend class HGraph;
2449 DISALLOW_COPY_AND_ASSIGN(HLongConstant);
2450};
Dave Allison20dfc792014-06-16 20:44:29 -07002451
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00002452// Conditional branch. A block ending with an HIf instruction must have
2453// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002454class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00002455 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002456 explicit HIf(HInstruction* input, uint32_t dex_pc = kNoDexPc)
2457 : HTemplateInstruction(SideEffects::None(), dex_pc) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002458 SetRawInputAt(0, input);
2459 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00002460
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002461 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002462
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002463 HBasicBlock* IfTrueSuccessor() const {
Vladimir Markoec7802a2015-10-01 20:57:57 +01002464 return GetBlock()->GetSuccessors()[0];
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002465 }
2466
2467 HBasicBlock* IfFalseSuccessor() const {
Vladimir Markoec7802a2015-10-01 20:57:57 +01002468 return GetBlock()->GetSuccessors()[1];
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002469 }
2470
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002471 DECLARE_INSTRUCTION(If);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00002472
2473 private:
2474 DISALLOW_COPY_AND_ASSIGN(HIf);
2475};
2476
David Brazdilfc6a86a2015-06-26 10:33:45 +00002477
2478// Abstract instruction which marks the beginning and/or end of a try block and
2479// links it to the respective exception handlers. Behaves the same as a Goto in
2480// non-exceptional control flow.
2481// Normal-flow successor is stored at index zero, exception handlers under
2482// higher indices in no particular order.
2483class HTryBoundary : public HTemplateInstruction<0> {
2484 public:
David Brazdil56e1acc2015-06-30 15:41:36 +01002485 enum BoundaryKind {
2486 kEntry,
2487 kExit,
2488 };
2489
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002490 explicit HTryBoundary(BoundaryKind kind, uint32_t dex_pc = kNoDexPc)
2491 : HTemplateInstruction(SideEffects::None(), dex_pc), kind_(kind) {}
David Brazdilfc6a86a2015-06-26 10:33:45 +00002492
2493 bool IsControlFlow() const OVERRIDE { return true; }
2494
2495 // Returns the block's non-exceptional successor (index zero).
Vladimir Markoec7802a2015-10-01 20:57:57 +01002496 HBasicBlock* GetNormalFlowSuccessor() const { return GetBlock()->GetSuccessors()[0]; }
David Brazdilfc6a86a2015-06-26 10:33:45 +00002497
David Brazdild26a4112015-11-10 11:07:31 +00002498 ArrayRef<HBasicBlock* const> GetExceptionHandlers() const {
2499 return ArrayRef<HBasicBlock* const>(GetBlock()->GetSuccessors()).SubArray(1u);
2500 }
2501
David Brazdilfc6a86a2015-06-26 10:33:45 +00002502 // Returns whether `handler` is among its exception handlers (non-zero index
2503 // successors).
David Brazdilffee3d32015-07-06 11:48:53 +01002504 bool HasExceptionHandler(const HBasicBlock& handler) const {
2505 DCHECK(handler.IsCatchBlock());
Vladimir Marko60584552015-09-03 13:35:12 +00002506 return GetBlock()->HasSuccessor(&handler, 1u /* Skip first successor. */);
David Brazdilfc6a86a2015-06-26 10:33:45 +00002507 }
2508
2509 // If not present already, adds `handler` to its block's list of exception
2510 // handlers.
2511 void AddExceptionHandler(HBasicBlock* handler) {
David Brazdilffee3d32015-07-06 11:48:53 +01002512 if (!HasExceptionHandler(*handler)) {
David Brazdilfc6a86a2015-06-26 10:33:45 +00002513 GetBlock()->AddSuccessor(handler);
2514 }
2515 }
2516
David Brazdil56e1acc2015-06-30 15:41:36 +01002517 bool IsEntry() const { return kind_ == BoundaryKind::kEntry; }
David Brazdilfc6a86a2015-06-26 10:33:45 +00002518
David Brazdilffee3d32015-07-06 11:48:53 +01002519 bool HasSameExceptionHandlersAs(const HTryBoundary& other) const;
2520
David Brazdilfc6a86a2015-06-26 10:33:45 +00002521 DECLARE_INSTRUCTION(TryBoundary);
2522
2523 private:
David Brazdil56e1acc2015-06-30 15:41:36 +01002524 const BoundaryKind kind_;
David Brazdilfc6a86a2015-06-26 10:33:45 +00002525
2526 DISALLOW_COPY_AND_ASSIGN(HTryBoundary);
2527};
2528
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07002529// Deoptimize to interpreter, upon checking a condition.
2530class HDeoptimize : public HTemplateInstruction<1> {
2531 public:
Nicolas Geoffray1cde0582016-01-13 13:56:20 +00002532 // We set CanTriggerGC to prevent any intermediate address to be live
2533 // at the point of the `HDeoptimize`.
Nicolas Geoffray73be1e82015-09-17 15:22:56 +01002534 HDeoptimize(HInstruction* cond, uint32_t dex_pc)
Nicolas Geoffray1cde0582016-01-13 13:56:20 +00002535 : HTemplateInstruction(SideEffects::CanTriggerGC(), dex_pc) {
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07002536 SetRawInputAt(0, cond);
2537 }
2538
Nicolas Geoffray73be1e82015-09-17 15:22:56 +01002539 bool CanBeMoved() const OVERRIDE { return true; }
2540 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
2541 return true;
2542 }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07002543 bool NeedsEnvironment() const OVERRIDE { return true; }
2544 bool CanThrow() const OVERRIDE { return true; }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07002545
2546 DECLARE_INSTRUCTION(Deoptimize);
2547
2548 private:
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07002549 DISALLOW_COPY_AND_ASSIGN(HDeoptimize);
2550};
2551
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01002552// Represents the ArtMethod that was passed as a first argument to
2553// the method. It is used by instructions that depend on it, like
2554// instructions that work with the dex cache.
2555class HCurrentMethod : public HExpression<0> {
2556 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002557 explicit HCurrentMethod(Primitive::Type type, uint32_t dex_pc = kNoDexPc)
2558 : HExpression(type, SideEffects::None(), dex_pc) {}
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01002559
2560 DECLARE_INSTRUCTION(CurrentMethod);
2561
2562 private:
2563 DISALLOW_COPY_AND_ASSIGN(HCurrentMethod);
2564};
2565
Nicolas Geoffraya42363f2015-12-17 14:57:09 +00002566// Fetches an ArtMethod from the virtual table or the interface method table
2567// of a class.
2568class HClassTableGet : public HExpression<1> {
2569 public:
2570 enum TableKind {
2571 kVTable,
2572 kIMTable,
2573 };
2574 HClassTableGet(HInstruction* cls,
2575 Primitive::Type type,
2576 TableKind kind,
2577 size_t index,
2578 uint32_t dex_pc)
2579 : HExpression(type, SideEffects::None(), dex_pc),
2580 index_(index),
2581 table_kind_(kind) {
2582 SetRawInputAt(0, cls);
2583 }
2584
2585 bool CanBeMoved() const OVERRIDE { return true; }
2586 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2587 return other->AsClassTableGet()->GetIndex() == index_ &&
2588 other->AsClassTableGet()->GetTableKind() == table_kind_;
2589 }
2590
2591 TableKind GetTableKind() const { return table_kind_; }
2592 size_t GetIndex() const { return index_; }
2593
2594 DECLARE_INSTRUCTION(ClassTableGet);
2595
2596 private:
2597 // The index of the ArtMethod in the table.
2598 const size_t index_;
2599 const TableKind table_kind_;
2600
2601 DISALLOW_COPY_AND_ASSIGN(HClassTableGet);
2602};
2603
Mark Mendellfe57faa2015-09-18 09:26:15 -04002604// PackedSwitch (jump table). A block ending with a PackedSwitch instruction will
2605// have one successor for each entry in the switch table, and the final successor
2606// will be the block containing the next Dex opcode.
2607class HPackedSwitch : public HTemplateInstruction<1> {
2608 public:
Mark Mendell3b9f3042015-09-24 08:43:40 -04002609 HPackedSwitch(int32_t start_value,
2610 uint32_t num_entries,
2611 HInstruction* input,
Mark Mendellfe57faa2015-09-18 09:26:15 -04002612 uint32_t dex_pc = kNoDexPc)
2613 : HTemplateInstruction(SideEffects::None(), dex_pc),
2614 start_value_(start_value),
2615 num_entries_(num_entries) {
2616 SetRawInputAt(0, input);
2617 }
2618
2619 bool IsControlFlow() const OVERRIDE { return true; }
2620
2621 int32_t GetStartValue() const { return start_value_; }
2622
Vladimir Marko211c2112015-09-24 16:52:33 +01002623 uint32_t GetNumEntries() const { return num_entries_; }
Mark Mendellfe57faa2015-09-18 09:26:15 -04002624
2625 HBasicBlock* GetDefaultBlock() const {
2626 // Last entry is the default block.
Vladimir Markoec7802a2015-10-01 20:57:57 +01002627 return GetBlock()->GetSuccessors()[num_entries_];
Mark Mendellfe57faa2015-09-18 09:26:15 -04002628 }
2629 DECLARE_INSTRUCTION(PackedSwitch);
2630
2631 private:
Mark Mendell3b9f3042015-09-24 08:43:40 -04002632 const int32_t start_value_;
2633 const uint32_t num_entries_;
Mark Mendellfe57faa2015-09-18 09:26:15 -04002634
2635 DISALLOW_COPY_AND_ASSIGN(HPackedSwitch);
2636};
2637
Roland Levillain88cb1752014-10-20 16:36:47 +01002638class HUnaryOperation : public HExpression<1> {
2639 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002640 HUnaryOperation(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
2641 : HExpression(result_type, SideEffects::None(), dex_pc) {
Roland Levillain88cb1752014-10-20 16:36:47 +01002642 SetRawInputAt(0, input);
2643 }
2644
2645 HInstruction* GetInput() const { return InputAt(0); }
2646 Primitive::Type GetResultType() const { return GetType(); }
2647
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002648 bool CanBeMoved() const OVERRIDE { return true; }
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01002649 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002650 return true;
2651 }
Roland Levillain88cb1752014-10-20 16:36:47 +01002652
Roland Levillain9240d6a2014-10-20 16:47:04 +01002653 // Try to statically evaluate `operation` and return a HConstant
2654 // containing the result of this evaluation. If `operation` cannot
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002655 // be evaluated as a constant, return null.
Roland Levillain9240d6a2014-10-20 16:47:04 +01002656 HConstant* TryStaticEvaluation() const;
2657
2658 // Apply this operation to `x`.
Roland Levillain9867bc72015-08-05 10:21:34 +01002659 virtual HConstant* Evaluate(HIntConstant* x) const = 0;
2660 virtual HConstant* Evaluate(HLongConstant* x) const = 0;
Roland Levillain9240d6a2014-10-20 16:47:04 +01002661
Vladimir Marko5f7b58e2015-11-23 19:49:34 +00002662 DECLARE_ABSTRACT_INSTRUCTION(UnaryOperation);
Roland Levillain88cb1752014-10-20 16:36:47 +01002663
2664 private:
2665 DISALLOW_COPY_AND_ASSIGN(HUnaryOperation);
2666};
2667
Dave Allison20dfc792014-06-16 20:44:29 -07002668class HBinaryOperation : public HExpression<2> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002669 public:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002670 HBinaryOperation(Primitive::Type result_type,
2671 HInstruction* left,
Alexandre Rames78e3ef62015-08-12 13:43:29 +01002672 HInstruction* right,
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002673 SideEffects side_effects = SideEffects::None(),
2674 uint32_t dex_pc = kNoDexPc)
2675 : HExpression(result_type, side_effects, dex_pc) {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002676 SetRawInputAt(0, left);
2677 SetRawInputAt(1, right);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002678 }
2679
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002680 HInstruction* GetLeft() const { return InputAt(0); }
2681 HInstruction* GetRight() const { return InputAt(1); }
Dave Allison20dfc792014-06-16 20:44:29 -07002682 Primitive::Type GetResultType() const { return GetType(); }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002683
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002684 virtual bool IsCommutative() const { return false; }
2685
2686 // Put constant on the right.
2687 // Returns whether order is changed.
2688 bool OrderInputsWithConstantOnTheRight() {
2689 HInstruction* left = InputAt(0);
2690 HInstruction* right = InputAt(1);
2691 if (left->IsConstant() && !right->IsConstant()) {
2692 ReplaceInput(right, 0);
2693 ReplaceInput(left, 1);
2694 return true;
2695 }
2696 return false;
2697 }
2698
2699 // Order inputs by instruction id, but favor constant on the right side.
2700 // This helps GVN for commutative ops.
2701 void OrderInputs() {
2702 DCHECK(IsCommutative());
2703 HInstruction* left = InputAt(0);
2704 HInstruction* right = InputAt(1);
2705 if (left == right || (!left->IsConstant() && right->IsConstant())) {
2706 return;
2707 }
2708 if (OrderInputsWithConstantOnTheRight()) {
2709 return;
2710 }
2711 // Order according to instruction id.
2712 if (left->GetId() > right->GetId()) {
2713 ReplaceInput(right, 0);
2714 ReplaceInput(left, 1);
2715 }
2716 }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002717
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002718 bool CanBeMoved() const OVERRIDE { return true; }
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01002719 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002720 return true;
2721 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002722
Roland Levillain9240d6a2014-10-20 16:47:04 +01002723 // Try to statically evaluate `operation` and return a HConstant
Roland Levillain556c3d12014-09-18 15:25:07 +01002724 // containing the result of this evaluation. If `operation` cannot
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002725 // be evaluated as a constant, return null.
Roland Levillain9240d6a2014-10-20 16:47:04 +01002726 HConstant* TryStaticEvaluation() const;
Roland Levillain556c3d12014-09-18 15:25:07 +01002727
2728 // Apply this operation to `x` and `y`.
Roland Levillain9867bc72015-08-05 10:21:34 +01002729 virtual HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const = 0;
2730 virtual HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const = 0;
2731 virtual HConstant* Evaluate(HIntConstant* x ATTRIBUTE_UNUSED,
2732 HLongConstant* y ATTRIBUTE_UNUSED) const {
2733 VLOG(compiler) << DebugName() << " is not defined for the (int, long) case.";
2734 return nullptr;
2735 }
2736 virtual HConstant* Evaluate(HLongConstant* x ATTRIBUTE_UNUSED,
2737 HIntConstant* y ATTRIBUTE_UNUSED) const {
2738 VLOG(compiler) << DebugName() << " is not defined for the (long, int) case.";
2739 return nullptr;
2740 }
Vladimir Marko9e23df52015-11-10 17:14:35 +00002741 virtual HConstant* Evaluate(HNullConstant* x ATTRIBUTE_UNUSED,
2742 HNullConstant* y ATTRIBUTE_UNUSED) const {
2743 VLOG(compiler) << DebugName() << " is not defined for the (null, null) case.";
2744 return nullptr;
2745 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002746
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002747 // Returns an input that can legally be used as the right input and is
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002748 // constant, or null.
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002749 HConstant* GetConstantRight() const;
2750
2751 // If `GetConstantRight()` returns one of the input, this returns the other
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002752 // one. Otherwise it returns null.
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002753 HInstruction* GetLeastConstantLeft() const;
2754
Vladimir Marko5f7b58e2015-11-23 19:49:34 +00002755 DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation);
Roland Levillainccc07a92014-09-16 14:48:16 +01002756
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002757 private:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002758 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
2759};
2760
Mark Mendellc4701932015-04-10 13:18:51 -04002761// The comparison bias applies for floating point operations and indicates how NaN
2762// comparisons are treated:
Roland Levillain4fa13f62015-07-06 18:11:54 +01002763enum class ComparisonBias {
Mark Mendellc4701932015-04-10 13:18:51 -04002764 kNoBias, // bias is not applicable (i.e. for long operation)
2765 kGtBias, // return 1 for NaN comparisons
2766 kLtBias, // return -1 for NaN comparisons
2767};
2768
Dave Allison20dfc792014-06-16 20:44:29 -07002769class HCondition : public HBinaryOperation {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002770 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002771 HCondition(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
2772 : HBinaryOperation(Primitive::kPrimBoolean, first, second, SideEffects::None(), dex_pc),
Roland Levillain4fa13f62015-07-06 18:11:54 +01002773 bias_(ComparisonBias::kNoBias) {}
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002774
Nicolas Geoffray18efde52014-09-22 15:51:11 +01002775 // For code generation purposes, returns whether this instruction is just before
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07002776 // `instruction`, and disregard moves in between.
2777 bool IsBeforeWhenDisregardMoves(HInstruction* instruction) const;
Nicolas Geoffray18efde52014-09-22 15:51:11 +01002778
Vladimir Marko5f7b58e2015-11-23 19:49:34 +00002779 DECLARE_ABSTRACT_INSTRUCTION(Condition);
Dave Allison20dfc792014-06-16 20:44:29 -07002780
2781 virtual IfCondition GetCondition() const = 0;
2782
Mark Mendellc4701932015-04-10 13:18:51 -04002783 virtual IfCondition GetOppositeCondition() const = 0;
2784
Roland Levillain4fa13f62015-07-06 18:11:54 +01002785 bool IsGtBias() const { return bias_ == ComparisonBias::kGtBias; }
Mark Mendellc4701932015-04-10 13:18:51 -04002786
2787 void SetBias(ComparisonBias bias) { bias_ = bias; }
2788
2789 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2790 return bias_ == other->AsCondition()->bias_;
2791 }
2792
Roland Levillain4fa13f62015-07-06 18:11:54 +01002793 bool IsFPConditionTrueIfNaN() const {
2794 DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType()));
2795 IfCondition if_cond = GetCondition();
Nicolas Geoffrayd4aee942016-01-22 12:35:26 +00002796 return IsGtBias() ? ((if_cond == kCondGT) || (if_cond == kCondGE)) : (if_cond == kCondNE);
Roland Levillain4fa13f62015-07-06 18:11:54 +01002797 }
2798
2799 bool IsFPConditionFalseIfNaN() const {
2800 DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType()));
2801 IfCondition if_cond = GetCondition();
Nicolas Geoffrayd4aee942016-01-22 12:35:26 +00002802 return IsGtBias() ? ((if_cond == kCondLT) || (if_cond == kCondLE)) : (if_cond == kCondEQ);
Roland Levillain4fa13f62015-07-06 18:11:54 +01002803 }
2804
Dave Allison20dfc792014-06-16 20:44:29 -07002805 private:
Mark Mendellc4701932015-04-10 13:18:51 -04002806 // Needed if we merge a HCompare into a HCondition.
2807 ComparisonBias bias_;
2808
Dave Allison20dfc792014-06-16 20:44:29 -07002809 DISALLOW_COPY_AND_ASSIGN(HCondition);
2810};
2811
2812// Instruction to check if two inputs are equal to each other.
2813class HEqual : public HCondition {
2814 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002815 HEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
2816 : HCondition(first, second, dex_pc) {}
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002817
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002818 bool IsCommutative() const OVERRIDE { return true; }
2819
Roland Levillain9867bc72015-08-05 10:21:34 +01002820 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002821 return GetBlock()->GetGraph()->GetIntConstant(
2822 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain93445682014-10-06 19:24:02 +01002823 }
Roland Levillain9867bc72015-08-05 10:21:34 +01002824 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002825 return GetBlock()->GetGraph()->GetIntConstant(
2826 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain93445682014-10-06 19:24:02 +01002827 }
Vladimir Marko9e23df52015-11-10 17:14:35 +00002828 HConstant* Evaluate(HNullConstant* x ATTRIBUTE_UNUSED,
2829 HNullConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
Vladimir Marko040db342015-11-10 19:53:01 +00002830 return GetBlock()->GetGraph()->GetIntConstant(1);
Vladimir Marko9e23df52015-11-10 17:14:35 +00002831 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002832
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002833 DECLARE_INSTRUCTION(Equal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002834
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002835 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002836 return kCondEQ;
2837 }
2838
Mark Mendellc4701932015-04-10 13:18:51 -04002839 IfCondition GetOppositeCondition() const OVERRIDE {
2840 return kCondNE;
2841 }
2842
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002843 private:
Aart Bike9f37602015-10-09 11:15:55 -07002844 template <typename T> bool Compute(T x, T y) const { return x == y; }
2845
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002846 DISALLOW_COPY_AND_ASSIGN(HEqual);
2847};
2848
Dave Allison20dfc792014-06-16 20:44:29 -07002849class HNotEqual : public HCondition {
2850 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002851 HNotEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
2852 : HCondition(first, second, dex_pc) {}
Dave Allison20dfc792014-06-16 20:44:29 -07002853
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002854 bool IsCommutative() const OVERRIDE { return true; }
2855
Roland Levillain9867bc72015-08-05 10:21:34 +01002856 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002857 return GetBlock()->GetGraph()->GetIntConstant(
2858 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain93445682014-10-06 19:24:02 +01002859 }
Roland Levillain9867bc72015-08-05 10:21:34 +01002860 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002861 return GetBlock()->GetGraph()->GetIntConstant(
2862 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain93445682014-10-06 19:24:02 +01002863 }
Vladimir Marko9e23df52015-11-10 17:14:35 +00002864 HConstant* Evaluate(HNullConstant* x ATTRIBUTE_UNUSED,
2865 HNullConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
Vladimir Marko040db342015-11-10 19:53:01 +00002866 return GetBlock()->GetGraph()->GetIntConstant(0);
Vladimir Marko9e23df52015-11-10 17:14:35 +00002867 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002868
Dave Allison20dfc792014-06-16 20:44:29 -07002869 DECLARE_INSTRUCTION(NotEqual);
2870
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002871 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002872 return kCondNE;
2873 }
2874
Mark Mendellc4701932015-04-10 13:18:51 -04002875 IfCondition GetOppositeCondition() const OVERRIDE {
2876 return kCondEQ;
2877 }
2878
Dave Allison20dfc792014-06-16 20:44:29 -07002879 private:
Aart Bike9f37602015-10-09 11:15:55 -07002880 template <typename T> bool Compute(T x, T y) const { return x != y; }
2881
Dave Allison20dfc792014-06-16 20:44:29 -07002882 DISALLOW_COPY_AND_ASSIGN(HNotEqual);
2883};
2884
2885class HLessThan : public HCondition {
2886 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002887 HLessThan(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
2888 : HCondition(first, second, dex_pc) {}
Dave Allison20dfc792014-06-16 20:44:29 -07002889
Roland Levillain9867bc72015-08-05 10:21:34 +01002890 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002891 return GetBlock()->GetGraph()->GetIntConstant(
2892 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain93445682014-10-06 19:24:02 +01002893 }
Roland Levillain9867bc72015-08-05 10:21:34 +01002894 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002895 return GetBlock()->GetGraph()->GetIntConstant(
2896 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain93445682014-10-06 19:24:02 +01002897 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002898
Dave Allison20dfc792014-06-16 20:44:29 -07002899 DECLARE_INSTRUCTION(LessThan);
2900
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002901 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002902 return kCondLT;
2903 }
2904
Mark Mendellc4701932015-04-10 13:18:51 -04002905 IfCondition GetOppositeCondition() const OVERRIDE {
2906 return kCondGE;
2907 }
2908
Dave Allison20dfc792014-06-16 20:44:29 -07002909 private:
Aart Bike9f37602015-10-09 11:15:55 -07002910 template <typename T> bool Compute(T x, T y) const { return x < y; }
2911
Dave Allison20dfc792014-06-16 20:44:29 -07002912 DISALLOW_COPY_AND_ASSIGN(HLessThan);
2913};
2914
2915class HLessThanOrEqual : public HCondition {
2916 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002917 HLessThanOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
2918 : HCondition(first, second, dex_pc) {}
Dave Allison20dfc792014-06-16 20:44:29 -07002919
Roland Levillain9867bc72015-08-05 10:21:34 +01002920 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002921 return GetBlock()->GetGraph()->GetIntConstant(
2922 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain93445682014-10-06 19:24:02 +01002923 }
Roland Levillain9867bc72015-08-05 10:21:34 +01002924 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002925 return GetBlock()->GetGraph()->GetIntConstant(
2926 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain93445682014-10-06 19:24:02 +01002927 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002928
Dave Allison20dfc792014-06-16 20:44:29 -07002929 DECLARE_INSTRUCTION(LessThanOrEqual);
2930
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002931 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002932 return kCondLE;
2933 }
2934
Mark Mendellc4701932015-04-10 13:18:51 -04002935 IfCondition GetOppositeCondition() const OVERRIDE {
2936 return kCondGT;
2937 }
2938
Dave Allison20dfc792014-06-16 20:44:29 -07002939 private:
Aart Bike9f37602015-10-09 11:15:55 -07002940 template <typename T> bool Compute(T x, T y) const { return x <= y; }
2941
Dave Allison20dfc792014-06-16 20:44:29 -07002942 DISALLOW_COPY_AND_ASSIGN(HLessThanOrEqual);
2943};
2944
2945class HGreaterThan : public HCondition {
2946 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002947 HGreaterThan(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
2948 : HCondition(first, second, dex_pc) {}
Dave Allison20dfc792014-06-16 20:44:29 -07002949
Roland Levillain9867bc72015-08-05 10:21:34 +01002950 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002951 return GetBlock()->GetGraph()->GetIntConstant(
2952 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain93445682014-10-06 19:24:02 +01002953 }
Roland Levillain9867bc72015-08-05 10:21:34 +01002954 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002955 return GetBlock()->GetGraph()->GetIntConstant(
2956 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain93445682014-10-06 19:24:02 +01002957 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002958
Dave Allison20dfc792014-06-16 20:44:29 -07002959 DECLARE_INSTRUCTION(GreaterThan);
2960
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002961 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002962 return kCondGT;
2963 }
2964
Mark Mendellc4701932015-04-10 13:18:51 -04002965 IfCondition GetOppositeCondition() const OVERRIDE {
2966 return kCondLE;
2967 }
2968
Dave Allison20dfc792014-06-16 20:44:29 -07002969 private:
Aart Bike9f37602015-10-09 11:15:55 -07002970 template <typename T> bool Compute(T x, T y) const { return x > y; }
2971
Dave Allison20dfc792014-06-16 20:44:29 -07002972 DISALLOW_COPY_AND_ASSIGN(HGreaterThan);
2973};
2974
2975class HGreaterThanOrEqual : public HCondition {
2976 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002977 HGreaterThanOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
2978 : HCondition(first, second, dex_pc) {}
Dave Allison20dfc792014-06-16 20:44:29 -07002979
Roland Levillain9867bc72015-08-05 10:21:34 +01002980 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002981 return GetBlock()->GetGraph()->GetIntConstant(
2982 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain93445682014-10-06 19:24:02 +01002983 }
Roland Levillain9867bc72015-08-05 10:21:34 +01002984 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002985 return GetBlock()->GetGraph()->GetIntConstant(
2986 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain93445682014-10-06 19:24:02 +01002987 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002988
Dave Allison20dfc792014-06-16 20:44:29 -07002989 DECLARE_INSTRUCTION(GreaterThanOrEqual);
2990
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002991 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002992 return kCondGE;
2993 }
2994
Mark Mendellc4701932015-04-10 13:18:51 -04002995 IfCondition GetOppositeCondition() const OVERRIDE {
2996 return kCondLT;
2997 }
2998
Dave Allison20dfc792014-06-16 20:44:29 -07002999 private:
Aart Bike9f37602015-10-09 11:15:55 -07003000 template <typename T> bool Compute(T x, T y) const { return x >= y; }
3001
Dave Allison20dfc792014-06-16 20:44:29 -07003002 DISALLOW_COPY_AND_ASSIGN(HGreaterThanOrEqual);
3003};
3004
Aart Bike9f37602015-10-09 11:15:55 -07003005class HBelow : public HCondition {
3006 public:
3007 HBelow(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
3008 : HCondition(first, second, dex_pc) {}
3009
3010 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
3011 return GetBlock()->GetGraph()->GetIntConstant(
3012 Compute(static_cast<uint32_t>(x->GetValue()),
3013 static_cast<uint32_t>(y->GetValue())), GetDexPc());
3014 }
3015 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
3016 return GetBlock()->GetGraph()->GetIntConstant(
3017 Compute(static_cast<uint64_t>(x->GetValue()),
3018 static_cast<uint64_t>(y->GetValue())), GetDexPc());
3019 }
3020
3021 DECLARE_INSTRUCTION(Below);
3022
3023 IfCondition GetCondition() const OVERRIDE {
3024 return kCondB;
3025 }
3026
3027 IfCondition GetOppositeCondition() const OVERRIDE {
3028 return kCondAE;
3029 }
3030
3031 private:
3032 template <typename T> bool Compute(T x, T y) const { return x < y; }
3033
3034 DISALLOW_COPY_AND_ASSIGN(HBelow);
3035};
3036
3037class HBelowOrEqual : public HCondition {
3038 public:
3039 HBelowOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
3040 : HCondition(first, second, dex_pc) {}
3041
3042 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
3043 return GetBlock()->GetGraph()->GetIntConstant(
3044 Compute(static_cast<uint32_t>(x->GetValue()),
3045 static_cast<uint32_t>(y->GetValue())), GetDexPc());
3046 }
3047 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
3048 return GetBlock()->GetGraph()->GetIntConstant(
3049 Compute(static_cast<uint64_t>(x->GetValue()),
3050 static_cast<uint64_t>(y->GetValue())), GetDexPc());
3051 }
3052
3053 DECLARE_INSTRUCTION(BelowOrEqual);
3054
3055 IfCondition GetCondition() const OVERRIDE {
3056 return kCondBE;
3057 }
3058
3059 IfCondition GetOppositeCondition() const OVERRIDE {
3060 return kCondA;
3061 }
3062
3063 private:
3064 template <typename T> bool Compute(T x, T y) const { return x <= y; }
3065
3066 DISALLOW_COPY_AND_ASSIGN(HBelowOrEqual);
3067};
3068
3069class HAbove : public HCondition {
3070 public:
3071 HAbove(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
3072 : HCondition(first, second, dex_pc) {}
3073
3074 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
3075 return GetBlock()->GetGraph()->GetIntConstant(
3076 Compute(static_cast<uint32_t>(x->GetValue()),
3077 static_cast<uint32_t>(y->GetValue())), GetDexPc());
3078 }
3079 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
3080 return GetBlock()->GetGraph()->GetIntConstant(
3081 Compute(static_cast<uint64_t>(x->GetValue()),
3082 static_cast<uint64_t>(y->GetValue())), GetDexPc());
3083 }
3084
3085 DECLARE_INSTRUCTION(Above);
3086
3087 IfCondition GetCondition() const OVERRIDE {
3088 return kCondA;
3089 }
3090
3091 IfCondition GetOppositeCondition() const OVERRIDE {
3092 return kCondBE;
3093 }
3094
3095 private:
3096 template <typename T> bool Compute(T x, T y) const { return x > y; }
3097
3098 DISALLOW_COPY_AND_ASSIGN(HAbove);
3099};
3100
3101class HAboveOrEqual : public HCondition {
3102 public:
3103 HAboveOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
3104 : HCondition(first, second, dex_pc) {}
3105
3106 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
3107 return GetBlock()->GetGraph()->GetIntConstant(
3108 Compute(static_cast<uint32_t>(x->GetValue()),
3109 static_cast<uint32_t>(y->GetValue())), GetDexPc());
3110 }
3111 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
3112 return GetBlock()->GetGraph()->GetIntConstant(
3113 Compute(static_cast<uint64_t>(x->GetValue()),
3114 static_cast<uint64_t>(y->GetValue())), GetDexPc());
3115 }
3116
3117 DECLARE_INSTRUCTION(AboveOrEqual);
3118
3119 IfCondition GetCondition() const OVERRIDE {
3120 return kCondAE;
3121 }
3122
3123 IfCondition GetOppositeCondition() const OVERRIDE {
3124 return kCondB;
3125 }
3126
3127 private:
3128 template <typename T> bool Compute(T x, T y) const { return x >= y; }
3129
3130 DISALLOW_COPY_AND_ASSIGN(HAboveOrEqual);
3131};
Dave Allison20dfc792014-06-16 20:44:29 -07003132
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01003133// Instruction to check how two inputs compare to each other.
3134// Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1.
3135class HCompare : public HBinaryOperation {
3136 public:
Alexey Frunze4dda3372015-06-01 18:31:49 -07003137 HCompare(Primitive::Type type,
3138 HInstruction* first,
3139 HInstruction* second,
Mark Mendellc4701932015-04-10 13:18:51 -04003140 ComparisonBias bias,
Alexey Frunze4dda3372015-06-01 18:31:49 -07003141 uint32_t dex_pc)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003142 : HBinaryOperation(Primitive::kPrimInt,
3143 first,
3144 second,
3145 SideEffectsForArchRuntimeCalls(type),
3146 dex_pc),
3147 bias_(bias) {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01003148 DCHECK_EQ(type, first->GetType());
3149 DCHECK_EQ(type, second->GetType());
3150 }
3151
Roland Levillain9867bc72015-08-05 10:21:34 +01003152 template <typename T>
3153 int32_t Compute(T x, T y) const { return x == y ? 0 : x > y ? 1 : -1; }
Calin Juravleddb7df22014-11-25 20:56:51 +00003154
Roland Levillain9867bc72015-08-05 10:21:34 +01003155 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003156 return GetBlock()->GetGraph()->GetIntConstant(
3157 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01003158 }
3159 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003160 return GetBlock()->GetGraph()->GetIntConstant(
3161 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain556c3d12014-09-18 15:25:07 +01003162 }
3163
Calin Juravleddb7df22014-11-25 20:56:51 +00003164 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3165 return bias_ == other->AsCompare()->bias_;
3166 }
3167
Mark Mendellc4701932015-04-10 13:18:51 -04003168 ComparisonBias GetBias() const { return bias_; }
3169
Roland Levillain4fa13f62015-07-06 18:11:54 +01003170 bool IsGtBias() { return bias_ == ComparisonBias::kGtBias; }
Calin Juravleddb7df22014-11-25 20:56:51 +00003171
Alexandre Rames78e3ef62015-08-12 13:43:29 +01003172
3173 static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type type) {
3174 // MIPS64 uses a runtime call for FP comparisons.
3175 return Primitive::IsFloatingPointType(type) ? SideEffects::CanTriggerGC() : SideEffects::None();
3176 }
Alexey Frunze4dda3372015-06-01 18:31:49 -07003177
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01003178 DECLARE_INSTRUCTION(Compare);
3179
3180 private:
Mark Mendellc4701932015-04-10 13:18:51 -04003181 const ComparisonBias bias_;
Calin Juravleddb7df22014-11-25 20:56:51 +00003182
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01003183 DISALLOW_COPY_AND_ASSIGN(HCompare);
3184};
3185
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00003186// A local in the graph. Corresponds to a Dex register.
3187class HLocal : public HTemplateInstruction<0> {
3188 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003189 explicit HLocal(uint16_t reg_number)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003190 : HTemplateInstruction(SideEffects::None(), kNoDexPc), reg_number_(reg_number) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00003191
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01003192 DECLARE_INSTRUCTION(Local);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00003193
Nicolas Geoffray787c3072014-03-17 10:20:19 +00003194 uint16_t GetRegNumber() const { return reg_number_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00003195
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00003196 private:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00003197 // The Dex register number.
3198 const uint16_t reg_number_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00003199
3200 DISALLOW_COPY_AND_ASSIGN(HLocal);
3201};
3202
3203// Load a given local. The local is an input of this instruction.
Dave Allison20dfc792014-06-16 20:44:29 -07003204class HLoadLocal : public HExpression<1> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00003205 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003206 HLoadLocal(HLocal* local, Primitive::Type type, uint32_t dex_pc = kNoDexPc)
3207 : HExpression(type, SideEffects::None(), dex_pc) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00003208 SetRawInputAt(0, local);
3209 }
3210
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00003211 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
3212
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01003213 DECLARE_INSTRUCTION(LoadLocal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00003214
3215 private:
3216 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
3217};
3218
3219// Store a value in a given local. This instruction has two inputs: the value
3220// and the local.
3221class HStoreLocal : public HTemplateInstruction<2> {
3222 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003223 HStoreLocal(HLocal* local, HInstruction* value, uint32_t dex_pc = kNoDexPc)
3224 : HTemplateInstruction(SideEffects::None(), dex_pc) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00003225 SetRawInputAt(0, local);
3226 SetRawInputAt(1, value);
3227 }
3228
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00003229 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
3230
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01003231 DECLARE_INSTRUCTION(StoreLocal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00003232
3233 private:
3234 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
3235};
3236
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003237class HFloatConstant : public HConstant {
3238 public:
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003239 float GetValue() const { return value_; }
3240
David Brazdil77a48ae2015-09-15 12:34:04 +00003241 uint64_t GetValueAsUint64() const OVERRIDE {
3242 return static_cast<uint64_t>(bit_cast<uint32_t, float>(value_));
3243 }
3244
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003245 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Roland Levillain9867bc72015-08-05 10:21:34 +01003246 DCHECK(other->IsFloatConstant());
David Brazdil77a48ae2015-09-15 12:34:04 +00003247 return other->AsFloatConstant()->GetValueAsUint64() == GetValueAsUint64();
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003248 }
3249
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003250 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003251
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00003252 bool IsMinusOne() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01003253 return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>((-1.0f));
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00003254 }
3255 bool IsZero() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01003256 return value_ == 0.0f;
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00003257 }
3258 bool IsOne() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01003259 return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>(1.0f);
3260 }
3261 bool IsNaN() const {
3262 return std::isnan(value_);
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00003263 }
3264
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003265 DECLARE_INSTRUCTION(FloatConstant);
3266
3267 private:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003268 explicit HFloatConstant(float value, uint32_t dex_pc = kNoDexPc)
3269 : HConstant(Primitive::kPrimFloat, dex_pc), value_(value) {}
3270 explicit HFloatConstant(int32_t value, uint32_t dex_pc = kNoDexPc)
3271 : HConstant(Primitive::kPrimFloat, dex_pc), value_(bit_cast<float, int32_t>(value)) {}
David Brazdil8d5b8b22015-03-24 10:51:52 +00003272
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003273 const float value_;
3274
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00003275 // Only the SsaBuilder and HGraph can create floating-point constants.
David Brazdil8d5b8b22015-03-24 10:51:52 +00003276 friend class SsaBuilder;
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00003277 friend class HGraph;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003278 DISALLOW_COPY_AND_ASSIGN(HFloatConstant);
3279};
3280
3281class HDoubleConstant : public HConstant {
3282 public:
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003283 double GetValue() const { return value_; }
3284
David Brazdil77a48ae2015-09-15 12:34:04 +00003285 uint64_t GetValueAsUint64() const OVERRIDE { return bit_cast<uint64_t, double>(value_); }
3286
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003287 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Roland Levillain9867bc72015-08-05 10:21:34 +01003288 DCHECK(other->IsDoubleConstant());
David Brazdil77a48ae2015-09-15 12:34:04 +00003289 return other->AsDoubleConstant()->GetValueAsUint64() == GetValueAsUint64();
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003290 }
3291
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003292 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003293
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00003294 bool IsMinusOne() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01003295 return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>((-1.0));
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00003296 }
3297 bool IsZero() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01003298 return value_ == 0.0;
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00003299 }
3300 bool IsOne() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01003301 return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>(1.0);
3302 }
3303 bool IsNaN() const {
3304 return std::isnan(value_);
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00003305 }
3306
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003307 DECLARE_INSTRUCTION(DoubleConstant);
3308
3309 private:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003310 explicit HDoubleConstant(double value, uint32_t dex_pc = kNoDexPc)
3311 : HConstant(Primitive::kPrimDouble, dex_pc), value_(value) {}
3312 explicit HDoubleConstant(int64_t value, uint32_t dex_pc = kNoDexPc)
3313 : HConstant(Primitive::kPrimDouble, dex_pc), value_(bit_cast<double, int64_t>(value)) {}
David Brazdil8d5b8b22015-03-24 10:51:52 +00003314
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003315 const double value_;
3316
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00003317 // Only the SsaBuilder and HGraph can create floating-point constants.
David Brazdil8d5b8b22015-03-24 10:51:52 +00003318 friend class SsaBuilder;
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00003319 friend class HGraph;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003320 DISALLOW_COPY_AND_ASSIGN(HDoubleConstant);
3321};
3322
David Brazdil6de19382016-01-08 17:37:10 +00003323class HNewInstance : public HExpression<2> {
3324 public:
3325 HNewInstance(HInstruction* cls,
3326 HCurrentMethod* current_method,
3327 uint32_t dex_pc,
3328 uint16_t type_index,
3329 const DexFile& dex_file,
3330 bool can_throw,
3331 bool finalizable,
3332 QuickEntrypointEnum entrypoint)
3333 : HExpression(Primitive::kPrimNot, SideEffects::CanTriggerGC(), dex_pc),
3334 type_index_(type_index),
3335 dex_file_(dex_file),
3336 can_throw_(can_throw),
3337 finalizable_(finalizable),
3338 entrypoint_(entrypoint) {
3339 SetRawInputAt(0, cls);
3340 SetRawInputAt(1, current_method);
3341 }
3342
3343 uint16_t GetTypeIndex() const { return type_index_; }
3344 const DexFile& GetDexFile() const { return dex_file_; }
3345
3346 // Calls runtime so needs an environment.
3347 bool NeedsEnvironment() const OVERRIDE { return true; }
3348
3349 // It may throw when called on type that's not instantiable/accessible.
3350 // It can throw OOME.
3351 // TODO: distinguish between the two cases so we can for example allow allocation elimination.
3352 bool CanThrow() const OVERRIDE { return can_throw_ || true; }
3353
3354 bool IsFinalizable() const { return finalizable_; }
3355
3356 bool CanBeNull() const OVERRIDE { return false; }
3357
3358 QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; }
3359
3360 void SetEntrypoint(QuickEntrypointEnum entrypoint) {
3361 entrypoint_ = entrypoint;
3362 }
3363
3364 bool IsStringAlloc() const;
3365
3366 DECLARE_INSTRUCTION(NewInstance);
3367
3368 private:
3369 const uint16_t type_index_;
3370 const DexFile& dex_file_;
3371 const bool can_throw_;
3372 const bool finalizable_;
3373 QuickEntrypointEnum entrypoint_;
3374
3375 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
3376};
3377
Andreas Gampe71fb52f2014-12-29 17:43:08 -08003378enum class Intrinsics {
Aart Bik5d75afe2015-12-14 11:57:01 -08003379#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
3380 k ## Name,
Andreas Gampe71fb52f2014-12-29 17:43:08 -08003381#include "intrinsics_list.h"
3382 kNone,
3383 INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
3384#undef INTRINSICS_LIST
3385#undef OPTIMIZING_INTRINSICS
3386};
3387std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic);
3388
Agi Csaki05f20562015-08-19 14:58:14 -07003389enum IntrinsicNeedsEnvironmentOrCache {
3390 kNoEnvironmentOrCache, // Intrinsic does not require an environment or dex cache.
3391 kNeedsEnvironmentOrCache // Intrinsic requires an environment or requires a dex cache.
agicsaki57b81ec2015-08-11 17:39:37 -07003392};
3393
Aart Bik5d75afe2015-12-14 11:57:01 -08003394enum IntrinsicSideEffects {
3395 kNoSideEffects, // Intrinsic does not have any heap memory side effects.
3396 kReadSideEffects, // Intrinsic may read heap memory.
3397 kWriteSideEffects, // Intrinsic may write heap memory.
3398 kAllSideEffects // Intrinsic may read or write heap memory, or trigger GC.
3399};
3400
3401enum IntrinsicExceptions {
3402 kNoThrow, // Intrinsic does not throw any exceptions.
3403 kCanThrow // Intrinsic may throw exceptions.
3404};
3405
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00003406class HInvoke : public HInstruction {
3407 public:
Vladimir Markofa6b93c2015-09-15 10:15:55 +01003408 size_t InputCount() const OVERRIDE { return inputs_.size(); }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003409
Nicolas Geoffraya83a54d2015-10-02 17:30:26 +01003410 bool NeedsEnvironment() const OVERRIDE;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00003411
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01003412 void SetArgumentAt(size_t index, HInstruction* argument) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003413 SetRawInputAt(index, argument);
3414 }
3415
Roland Levillain3e3d7332015-04-28 11:00:54 +01003416 // Return the number of arguments. This number can be lower than
3417 // the number of inputs returned by InputCount(), as some invoke
3418 // instructions (e.g. HInvokeStaticOrDirect) can have non-argument
3419 // inputs at the end of their list of inputs.
3420 uint32_t GetNumberOfArguments() const { return number_of_arguments_; }
3421
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003422 Primitive::Type GetType() const OVERRIDE { return return_type_; }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01003423
Andreas Gampe71fb52f2014-12-29 17:43:08 -08003424 uint32_t GetDexMethodIndex() const { return dex_method_index_; }
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01003425 const DexFile& GetDexFile() const { return GetEnvironment()->GetDexFile(); }
Andreas Gampe71fb52f2014-12-29 17:43:08 -08003426
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01003427 InvokeType GetOriginalInvokeType() const { return original_invoke_type_; }
3428
Nicolas Geoffray1ba19812015-04-21 09:12:40 +01003429 Intrinsics GetIntrinsic() const {
Andreas Gampe71fb52f2014-12-29 17:43:08 -08003430 return intrinsic_;
3431 }
3432
Aart Bik5d75afe2015-12-14 11:57:01 -08003433 void SetIntrinsic(Intrinsics intrinsic,
3434 IntrinsicNeedsEnvironmentOrCache needs_env_or_cache,
3435 IntrinsicSideEffects side_effects,
3436 IntrinsicExceptions exceptions);
Andreas Gampe71fb52f2014-12-29 17:43:08 -08003437
Nicolas Geoffray78f4fa72015-06-12 09:35:05 +01003438 bool IsFromInlinedInvoke() const {
Nicolas Geoffray8e1ef532015-11-23 12:04:37 +00003439 return GetEnvironment()->IsFromInlinedInvoke();
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01003440 }
3441
Aart Bik5d75afe2015-12-14 11:57:01 -08003442 bool CanThrow() const OVERRIDE { return can_throw_; }
3443
3444 bool CanBeMoved() const OVERRIDE { return IsIntrinsic(); }
3445
3446 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3447 return intrinsic_ != Intrinsics::kNone && intrinsic_ == other->AsInvoke()->intrinsic_;
3448 }
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01003449
Nicolas Geoffraya83a54d2015-10-02 17:30:26 +01003450 uint32_t* GetIntrinsicOptimizations() {
3451 return &intrinsic_optimizations_;
3452 }
3453
3454 const uint32_t* GetIntrinsicOptimizations() const {
3455 return &intrinsic_optimizations_;
3456 }
3457
3458 bool IsIntrinsic() const { return intrinsic_ != Intrinsics::kNone; }
3459
Vladimir Marko5f7b58e2015-11-23 19:49:34 +00003460 DECLARE_ABSTRACT_INSTRUCTION(Invoke);
Nicolas Geoffray360231a2014-10-08 21:07:48 +01003461
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00003462 protected:
Andreas Gampe71fb52f2014-12-29 17:43:08 -08003463 HInvoke(ArenaAllocator* arena,
3464 uint32_t number_of_arguments,
Roland Levillain3e3d7332015-04-28 11:00:54 +01003465 uint32_t number_of_other_inputs,
Andreas Gampe71fb52f2014-12-29 17:43:08 -08003466 Primitive::Type return_type,
3467 uint32_t dex_pc,
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01003468 uint32_t dex_method_index,
3469 InvokeType original_invoke_type)
Alexandre Rames78e3ef62015-08-12 13:43:29 +01003470 : HInstruction(
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003471 SideEffects::AllExceptGCDependency(), dex_pc), // Assume write/read on all fields/arrays.
Roland Levillain3e3d7332015-04-28 11:00:54 +01003472 number_of_arguments_(number_of_arguments),
Vladimir Markob7d8e8c2015-09-17 15:47:05 +01003473 inputs_(number_of_arguments + number_of_other_inputs,
3474 arena->Adapter(kArenaAllocInvokeInputs)),
Andreas Gampe71fb52f2014-12-29 17:43:08 -08003475 return_type_(return_type),
Andreas Gampe71fb52f2014-12-29 17:43:08 -08003476 dex_method_index_(dex_method_index),
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01003477 original_invoke_type_(original_invoke_type),
Aart Bik5d75afe2015-12-14 11:57:01 -08003478 can_throw_(true),
agicsaki57b81ec2015-08-11 17:39:37 -07003479 intrinsic_(Intrinsics::kNone),
Nicolas Geoffraya83a54d2015-10-02 17:30:26 +01003480 intrinsic_optimizations_(0) {
Andreas Gampe71fb52f2014-12-29 17:43:08 -08003481 }
3482
Vladimir Markofa6b93c2015-09-15 10:15:55 +01003483 const HUserRecord<HInstruction*> InputRecordAt(size_t index) const OVERRIDE {
Vladimir Markofa6b93c2015-09-15 10:15:55 +01003484 return inputs_[index];
3485 }
3486
David Brazdil1abb4192015-02-17 18:33:36 +00003487 void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) OVERRIDE {
Vladimir Markofa6b93c2015-09-15 10:15:55 +01003488 inputs_[index] = input;
David Brazdil1abb4192015-02-17 18:33:36 +00003489 }
3490
Aart Bik5d75afe2015-12-14 11:57:01 -08003491 void SetCanThrow(bool can_throw) { can_throw_ = can_throw; }
3492
Roland Levillain3e3d7332015-04-28 11:00:54 +01003493 uint32_t number_of_arguments_;
Vladimir Markofa6b93c2015-09-15 10:15:55 +01003494 ArenaVector<HUserRecord<HInstruction*>> inputs_;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01003495 const Primitive::Type return_type_;
Andreas Gampe71fb52f2014-12-29 17:43:08 -08003496 const uint32_t dex_method_index_;
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01003497 const InvokeType original_invoke_type_;
Aart Bik5d75afe2015-12-14 11:57:01 -08003498 bool can_throw_;
Andreas Gampe71fb52f2014-12-29 17:43:08 -08003499 Intrinsics intrinsic_;
Nicolas Geoffraya83a54d2015-10-02 17:30:26 +01003500
3501 // A magic word holding optimizations for intrinsics. See intrinsics.h.
3502 uint32_t intrinsic_optimizations_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00003503
3504 private:
3505 DISALLOW_COPY_AND_ASSIGN(HInvoke);
3506};
3507
Calin Juravle175dc732015-08-25 15:42:32 +01003508class HInvokeUnresolved : public HInvoke {
3509 public:
3510 HInvokeUnresolved(ArenaAllocator* arena,
3511 uint32_t number_of_arguments,
3512 Primitive::Type return_type,
3513 uint32_t dex_pc,
3514 uint32_t dex_method_index,
3515 InvokeType invoke_type)
3516 : HInvoke(arena,
3517 number_of_arguments,
3518 0u /* number_of_other_inputs */,
3519 return_type,
3520 dex_pc,
3521 dex_method_index,
3522 invoke_type) {
3523 }
3524
3525 DECLARE_INSTRUCTION(InvokeUnresolved);
3526
3527 private:
3528 DISALLOW_COPY_AND_ASSIGN(HInvokeUnresolved);
3529};
3530
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00003531class HInvokeStaticOrDirect : public HInvoke {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00003532 public:
Roland Levillain4c0eb422015-04-24 16:43:49 +01003533 // Requirements of this method call regarding the class
3534 // initialization (clinit) check of its declaring class.
3535 enum class ClinitCheckRequirement {
3536 kNone, // Class already initialized.
3537 kExplicit, // Static call having explicit clinit check as last input.
3538 kImplicit, // Static call implicitly requiring a clinit check.
3539 };
3540
Vladimir Marko58155012015-08-19 12:49:41 +00003541 // Determines how to load the target ArtMethod*.
3542 enum class MethodLoadKind {
3543 // Use a String init ArtMethod* loaded from Thread entrypoints.
3544 kStringInit,
3545
3546 // Use the method's own ArtMethod* loaded by the register allocator.
3547 kRecursive,
3548
3549 // Use ArtMethod* at a known address, embed the direct address in the code.
3550 // Used for app->boot calls with non-relocatable image and for JIT-compiled calls.
3551 kDirectAddress,
3552
3553 // Use ArtMethod* at an address that will be known at link time, embed the direct
3554 // address in the code. If the image is relocatable, emit .patch_oat entry.
3555 // Used for app->boot calls with relocatable image and boot->boot calls, whether
3556 // the image relocatable or not.
3557 kDirectAddressWithFixup,
3558
3559 // Load from resoved methods array in the dex cache using a PC-relative load.
3560 // Used when we need to use the dex cache, for example for invoke-static that
3561 // may cause class initialization (the entry may point to a resolution method),
3562 // and we know that we can access the dex cache arrays using a PC-relative load.
3563 kDexCachePcRelative,
3564
3565 // Use ArtMethod* from the resolved methods of the compiled method's own ArtMethod*.
3566 // Used for JIT when we need to use the dex cache. This is also the last-resort-kind
3567 // used when other kinds are unavailable (say, dex cache arrays are not PC-relative)
3568 // or unimplemented or impractical (i.e. slow) on a particular architecture.
3569 kDexCacheViaMethod,
3570 };
3571
3572 // Determines the location of the code pointer.
3573 enum class CodePtrLocation {
3574 // Recursive call, use local PC-relative call instruction.
3575 kCallSelf,
3576
3577 // Use PC-relative call instruction patched at link time.
3578 // Used for calls within an oat file, boot->boot or app->app.
3579 kCallPCRelative,
3580
3581 // Call to a known target address, embed the direct address in code.
3582 // Used for app->boot call with non-relocatable image and for JIT-compiled calls.
3583 kCallDirect,
3584
3585 // Call to a target address that will be known at link time, embed the direct
3586 // address in code. If the image is relocatable, emit .patch_oat entry.
3587 // Used for app->boot calls with relocatable image and boot->boot calls, whether
3588 // the image relocatable or not.
3589 kCallDirectWithFixup,
3590
3591 // Use code pointer from the ArtMethod*.
3592 // Used when we don't know the target code. This is also the last-resort-kind used when
3593 // other kinds are unimplemented or impractical (i.e. slow) on a particular architecture.
3594 kCallArtMethod,
3595 };
3596
3597 struct DispatchInfo {
Vladimir Markodc151b22015-10-15 18:02:30 +01003598 MethodLoadKind method_load_kind;
3599 CodePtrLocation code_ptr_location;
Vladimir Marko58155012015-08-19 12:49:41 +00003600 // The method load data holds
3601 // - thread entrypoint offset for kStringInit method if this is a string init invoke.
3602 // Note that there are multiple string init methods, each having its own offset.
3603 // - the method address for kDirectAddress
3604 // - the dex cache arrays offset for kDexCachePcRel.
Vladimir Markodc151b22015-10-15 18:02:30 +01003605 uint64_t method_load_data;
3606 uint64_t direct_code_ptr;
Vladimir Marko58155012015-08-19 12:49:41 +00003607 };
3608
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00003609 HInvokeStaticOrDirect(ArenaAllocator* arena,
3610 uint32_t number_of_arguments,
3611 Primitive::Type return_type,
3612 uint32_t dex_pc,
Vladimir Marko58155012015-08-19 12:49:41 +00003613 uint32_t method_index,
3614 MethodReference target_method,
3615 DispatchInfo dispatch_info,
Nicolas Geoffray79041292015-03-26 10:05:54 +00003616 InvokeType original_invoke_type,
Nicolas Geoffraye5234232015-12-02 09:06:11 +00003617 InvokeType optimized_invoke_type,
Roland Levillain4c0eb422015-04-24 16:43:49 +01003618 ClinitCheckRequirement clinit_check_requirement)
Roland Levillain3e3d7332015-04-28 11:00:54 +01003619 : HInvoke(arena,
3620 number_of_arguments,
Vladimir Markob554b5a2015-11-06 12:57:55 +00003621 // There is potentially one extra argument for the HCurrentMethod node, and
3622 // potentially one other if the clinit check is explicit, and potentially
3623 // one other if the method is a string factory.
3624 (NeedsCurrentMethodInput(dispatch_info.method_load_kind) ? 1u : 0u) +
3625 (clinit_check_requirement == ClinitCheckRequirement::kExplicit ? 1u : 0u) +
3626 (dispatch_info.method_load_kind == MethodLoadKind::kStringInit ? 1u : 0u),
Roland Levillain3e3d7332015-04-28 11:00:54 +01003627 return_type,
3628 dex_pc,
Vladimir Marko58155012015-08-19 12:49:41 +00003629 method_index,
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01003630 original_invoke_type),
Nicolas Geoffraye5234232015-12-02 09:06:11 +00003631 optimized_invoke_type_(optimized_invoke_type),
Jeff Hao848f70a2014-01-15 13:49:50 -08003632 clinit_check_requirement_(clinit_check_requirement),
Vladimir Marko58155012015-08-19 12:49:41 +00003633 target_method_(target_method),
Vladimir Markob554b5a2015-11-06 12:57:55 +00003634 dispatch_info_(dispatch_info) { }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00003635
Vladimir Markodc151b22015-10-15 18:02:30 +01003636 void SetDispatchInfo(const DispatchInfo& dispatch_info) {
Vladimir Markob554b5a2015-11-06 12:57:55 +00003637 bool had_current_method_input = HasCurrentMethodInput();
3638 bool needs_current_method_input = NeedsCurrentMethodInput(dispatch_info.method_load_kind);
3639
3640 // Using the current method is the default and once we find a better
3641 // method load kind, we should not go back to using the current method.
3642 DCHECK(had_current_method_input || !needs_current_method_input);
3643
3644 if (had_current_method_input && !needs_current_method_input) {
Vladimir Markoc53c0792015-11-19 15:48:33 +00003645 DCHECK_EQ(InputAt(GetSpecialInputIndex()), GetBlock()->GetGraph()->GetCurrentMethod());
3646 RemoveInputAt(GetSpecialInputIndex());
Vladimir Markob554b5a2015-11-06 12:57:55 +00003647 }
Vladimir Markodc151b22015-10-15 18:02:30 +01003648 dispatch_info_ = dispatch_info;
3649 }
3650
Vladimir Markoc53c0792015-11-19 15:48:33 +00003651 void AddSpecialInput(HInstruction* input) {
3652 // We allow only one special input.
3653 DCHECK(!IsStringInit() && !HasCurrentMethodInput());
3654 DCHECK(InputCount() == GetSpecialInputIndex() ||
3655 (InputCount() == GetSpecialInputIndex() + 1 && IsStaticWithExplicitClinitCheck()));
3656 InsertInputAt(GetSpecialInputIndex(), input);
3657 }
Vladimir Markob554b5a2015-11-06 12:57:55 +00003658
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01003659 bool CanDoImplicitNullCheckOn(HInstruction* obj ATTRIBUTE_UNUSED) const OVERRIDE {
Calin Juravle77520bc2015-01-12 18:45:46 +00003660 // We access the method via the dex cache so we can't do an implicit null check.
3661 // TODO: for intrinsics we can generate implicit null checks.
3662 return false;
3663 }
3664
Nicolas Geoffrayefa84682015-08-12 18:28:14 -07003665 bool CanBeNull() const OVERRIDE {
3666 return return_type_ == Primitive::kPrimNot && !IsStringInit();
3667 }
3668
Vladimir Markoc53c0792015-11-19 15:48:33 +00003669 // Get the index of the special input, if any.
3670 //
David Brazdil6de19382016-01-08 17:37:10 +00003671 // If the invoke HasCurrentMethodInput(), the "special input" is the current
3672 // method pointer; otherwise there may be one platform-specific special input,
3673 // such as PC-relative addressing base.
Vladimir Markoc53c0792015-11-19 15:48:33 +00003674 uint32_t GetSpecialInputIndex() const { return GetNumberOfArguments(); }
3675
Nicolas Geoffraye5234232015-12-02 09:06:11 +00003676 InvokeType GetOptimizedInvokeType() const { return optimized_invoke_type_; }
3677 void SetOptimizedInvokeType(InvokeType invoke_type) {
3678 optimized_invoke_type_ = invoke_type;
3679 }
3680
Vladimir Marko58155012015-08-19 12:49:41 +00003681 MethodLoadKind GetMethodLoadKind() const { return dispatch_info_.method_load_kind; }
3682 CodePtrLocation GetCodePtrLocation() const { return dispatch_info_.code_ptr_location; }
3683 bool IsRecursive() const { return GetMethodLoadKind() == MethodLoadKind::kRecursive; }
Vladimir Markodc151b22015-10-15 18:02:30 +01003684 bool NeedsDexCacheOfDeclaringClass() const OVERRIDE;
Vladimir Marko58155012015-08-19 12:49:41 +00003685 bool IsStringInit() const { return GetMethodLoadKind() == MethodLoadKind::kStringInit; }
Vladimir Marko58155012015-08-19 12:49:41 +00003686 bool HasMethodAddress() const { return GetMethodLoadKind() == MethodLoadKind::kDirectAddress; }
Vladimir Marko0f7dca42015-11-02 14:36:43 +00003687 bool HasPcRelativeDexCache() const {
Vladimir Markodc151b22015-10-15 18:02:30 +01003688 return GetMethodLoadKind() == MethodLoadKind::kDexCachePcRelative;
3689 }
Vladimir Markob554b5a2015-11-06 12:57:55 +00003690 bool HasCurrentMethodInput() const {
3691 // This function can be called only after the invoke has been fully initialized by the builder.
3692 if (NeedsCurrentMethodInput(GetMethodLoadKind())) {
Vladimir Markoc53c0792015-11-19 15:48:33 +00003693 DCHECK(InputAt(GetSpecialInputIndex())->IsCurrentMethod());
Vladimir Markob554b5a2015-11-06 12:57:55 +00003694 return true;
3695 } else {
Vladimir Markoc53c0792015-11-19 15:48:33 +00003696 DCHECK(InputCount() == GetSpecialInputIndex() ||
3697 !InputAt(GetSpecialInputIndex())->IsCurrentMethod());
Vladimir Markob554b5a2015-11-06 12:57:55 +00003698 return false;
3699 }
3700 }
Vladimir Marko58155012015-08-19 12:49:41 +00003701 bool HasDirectCodePtr() const { return GetCodePtrLocation() == CodePtrLocation::kCallDirect; }
3702 MethodReference GetTargetMethod() const { return target_method_; }
Nicolas Geoffraye5234232015-12-02 09:06:11 +00003703 void SetTargetMethod(MethodReference method) { target_method_ = method; }
Vladimir Marko58155012015-08-19 12:49:41 +00003704
3705 int32_t GetStringInitOffset() const {
3706 DCHECK(IsStringInit());
3707 return dispatch_info_.method_load_data;
3708 }
3709
3710 uint64_t GetMethodAddress() const {
3711 DCHECK(HasMethodAddress());
3712 return dispatch_info_.method_load_data;
3713 }
3714
3715 uint32_t GetDexCacheArrayOffset() const {
Vladimir Marko0f7dca42015-11-02 14:36:43 +00003716 DCHECK(HasPcRelativeDexCache());
Vladimir Marko58155012015-08-19 12:49:41 +00003717 return dispatch_info_.method_load_data;
3718 }
3719
3720 uint64_t GetDirectCodePtr() const {
3721 DCHECK(HasDirectCodePtr());
3722 return dispatch_info_.direct_code_ptr;
3723 }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00003724
Calin Juravle68ad6492015-08-18 17:08:12 +01003725 ClinitCheckRequirement GetClinitCheckRequirement() const { return clinit_check_requirement_; }
3726
Roland Levillain4c0eb422015-04-24 16:43:49 +01003727 // Is this instruction a call to a static method?
3728 bool IsStatic() const {
Nicolas Geoffraye5234232015-12-02 09:06:11 +00003729 return GetOriginalInvokeType() == kStatic;
Roland Levillain4c0eb422015-04-24 16:43:49 +01003730 }
3731
Vladimir Markofbb184a2015-11-13 14:47:00 +00003732 // Remove the HClinitCheck or the replacement HLoadClass (set as last input by
3733 // PrepareForRegisterAllocation::VisitClinitCheck() in lieu of the initial HClinitCheck)
3734 // instruction; only relevant for static calls with explicit clinit check.
3735 void RemoveExplicitClinitCheck(ClinitCheckRequirement new_requirement) {
Roland Levillain4c0eb422015-04-24 16:43:49 +01003736 DCHECK(IsStaticWithExplicitClinitCheck());
3737 size_t last_input_index = InputCount() - 1;
3738 HInstruction* last_input = InputAt(last_input_index);
3739 DCHECK(last_input != nullptr);
Vladimir Markofbb184a2015-11-13 14:47:00 +00003740 DCHECK(last_input->IsLoadClass() || last_input->IsClinitCheck()) << last_input->DebugName();
Roland Levillain4c0eb422015-04-24 16:43:49 +01003741 RemoveAsUserOfInput(last_input_index);
Vladimir Markofa6b93c2015-09-15 10:15:55 +01003742 inputs_.pop_back();
Vladimir Markofbb184a2015-11-13 14:47:00 +00003743 clinit_check_requirement_ = new_requirement;
3744 DCHECK(!IsStaticWithExplicitClinitCheck());
Roland Levillain4c0eb422015-04-24 16:43:49 +01003745 }
3746
David Brazdilbc9ab162016-01-20 14:50:19 +00003747 HInstruction* GetAndRemoveThisArgumentOfStringInit() {
David Brazdil6de19382016-01-08 17:37:10 +00003748 DCHECK(IsStringInit());
3749 size_t index = InputCount() - 1;
David Brazdilbc9ab162016-01-20 14:50:19 +00003750 HInstruction* input = InputAt(index);
David Brazdil6de19382016-01-08 17:37:10 +00003751 RemoveAsUserOfInput(index);
Vladimir Markofa6b93c2015-09-15 10:15:55 +01003752 inputs_.pop_back();
David Brazdilbc9ab162016-01-20 14:50:19 +00003753 return input;
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +01003754 }
3755
Roland Levillain4c0eb422015-04-24 16:43:49 +01003756 // Is this a call to a static method whose declaring class has an
Vladimir Markofbb184a2015-11-13 14:47:00 +00003757 // explicit initialization check in the graph?
Roland Levillain4c0eb422015-04-24 16:43:49 +01003758 bool IsStaticWithExplicitClinitCheck() const {
3759 return IsStatic() && (clinit_check_requirement_ == ClinitCheckRequirement::kExplicit);
3760 }
3761
3762 // Is this a call to a static method whose declaring class has an
3763 // implicit intialization check requirement?
3764 bool IsStaticWithImplicitClinitCheck() const {
3765 return IsStatic() && (clinit_check_requirement_ == ClinitCheckRequirement::kImplicit);
3766 }
3767
Vladimir Markob554b5a2015-11-06 12:57:55 +00003768 // Does this method load kind need the current method as an input?
3769 static bool NeedsCurrentMethodInput(MethodLoadKind kind) {
3770 return kind == MethodLoadKind::kRecursive || kind == MethodLoadKind::kDexCacheViaMethod;
3771 }
3772
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00003773 DECLARE_INSTRUCTION(InvokeStaticOrDirect);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00003774
Roland Levillain4c0eb422015-04-24 16:43:49 +01003775 protected:
3776 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE {
3777 const HUserRecord<HInstruction*> input_record = HInvoke::InputRecordAt(i);
3778 if (kIsDebugBuild && IsStaticWithExplicitClinitCheck() && (i == InputCount() - 1)) {
3779 HInstruction* input = input_record.GetInstruction();
3780 // `input` is the last input of a static invoke marked as having
3781 // an explicit clinit check. It must either be:
3782 // - an art::HClinitCheck instruction, set by art::HGraphBuilder; or
3783 // - an art::HLoadClass instruction, set by art::PrepareForRegisterAllocation.
3784 DCHECK(input != nullptr);
3785 DCHECK(input->IsClinitCheck() || input->IsLoadClass()) << input->DebugName();
3786 }
3787 return input_record;
3788 }
3789
Vladimir Markoc53c0792015-11-19 15:48:33 +00003790 void InsertInputAt(size_t index, HInstruction* input);
3791 void RemoveInputAt(size_t index);
3792
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00003793 private:
Nicolas Geoffraye5234232015-12-02 09:06:11 +00003794 InvokeType optimized_invoke_type_;
Roland Levillain4c0eb422015-04-24 16:43:49 +01003795 ClinitCheckRequirement clinit_check_requirement_;
Vladimir Marko58155012015-08-19 12:49:41 +00003796 // The target method may refer to different dex file or method index than the original
3797 // invoke. This happens for sharpened calls and for calls where a method was redeclared
3798 // in derived class to increase visibility.
3799 MethodReference target_method_;
3800 DispatchInfo dispatch_info_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00003801
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00003802 DISALLOW_COPY_AND_ASSIGN(HInvokeStaticOrDirect);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00003803};
Vladimir Markof64242a2015-12-01 14:58:23 +00003804std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::MethodLoadKind rhs);
Vladimir Markofbb184a2015-11-13 14:47:00 +00003805std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::ClinitCheckRequirement rhs);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00003806
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01003807class HInvokeVirtual : public HInvoke {
3808 public:
3809 HInvokeVirtual(ArenaAllocator* arena,
3810 uint32_t number_of_arguments,
3811 Primitive::Type return_type,
3812 uint32_t dex_pc,
Andreas Gampe71fb52f2014-12-29 17:43:08 -08003813 uint32_t dex_method_index,
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01003814 uint32_t vtable_index)
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01003815 : HInvoke(arena, number_of_arguments, 0u, return_type, dex_pc, dex_method_index, kVirtual),
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01003816 vtable_index_(vtable_index) {}
3817
Calin Juravle641547a2015-04-21 22:08:51 +01003818 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
Calin Juravle77520bc2015-01-12 18:45:46 +00003819 // TODO: Add implicit null checks in intrinsics.
Calin Juravle641547a2015-04-21 22:08:51 +01003820 return (obj == InputAt(0)) && !GetLocations()->Intrinsified();
Calin Juravle77520bc2015-01-12 18:45:46 +00003821 }
3822
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01003823 uint32_t GetVTableIndex() const { return vtable_index_; }
3824
3825 DECLARE_INSTRUCTION(InvokeVirtual);
3826
3827 private:
3828 const uint32_t vtable_index_;
3829
3830 DISALLOW_COPY_AND_ASSIGN(HInvokeVirtual);
3831};
3832
Nicolas Geoffray52839d12014-11-07 17:47:25 +00003833class HInvokeInterface : public HInvoke {
3834 public:
3835 HInvokeInterface(ArenaAllocator* arena,
3836 uint32_t number_of_arguments,
3837 Primitive::Type return_type,
3838 uint32_t dex_pc,
3839 uint32_t dex_method_index,
3840 uint32_t imt_index)
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01003841 : HInvoke(arena, number_of_arguments, 0u, return_type, dex_pc, dex_method_index, kInterface),
Nicolas Geoffray52839d12014-11-07 17:47:25 +00003842 imt_index_(imt_index) {}
3843
Calin Juravle641547a2015-04-21 22:08:51 +01003844 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
Calin Juravle77520bc2015-01-12 18:45:46 +00003845 // TODO: Add implicit null checks in intrinsics.
Calin Juravle641547a2015-04-21 22:08:51 +01003846 return (obj == InputAt(0)) && !GetLocations()->Intrinsified();
Calin Juravle77520bc2015-01-12 18:45:46 +00003847 }
3848
Nicolas Geoffray52839d12014-11-07 17:47:25 +00003849 uint32_t GetImtIndex() const { return imt_index_; }
3850 uint32_t GetDexMethodIndex() const { return dex_method_index_; }
3851
3852 DECLARE_INSTRUCTION(InvokeInterface);
3853
3854 private:
Nicolas Geoffray52839d12014-11-07 17:47:25 +00003855 const uint32_t imt_index_;
3856
3857 DISALLOW_COPY_AND_ASSIGN(HInvokeInterface);
3858};
3859
Roland Levillain88cb1752014-10-20 16:36:47 +01003860class HNeg : public HUnaryOperation {
3861 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003862 HNeg(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
3863 : HUnaryOperation(result_type, input, dex_pc) {}
Roland Levillain88cb1752014-10-20 16:36:47 +01003864
Roland Levillain9867bc72015-08-05 10:21:34 +01003865 template <typename T> T Compute(T x) const { return -x; }
3866
3867 HConstant* Evaluate(HIntConstant* x) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003868 return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01003869 }
3870 HConstant* Evaluate(HLongConstant* x) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003871 return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01003872 }
Roland Levillain9240d6a2014-10-20 16:47:04 +01003873
Roland Levillain88cb1752014-10-20 16:36:47 +01003874 DECLARE_INSTRUCTION(Neg);
3875
3876 private:
3877 DISALLOW_COPY_AND_ASSIGN(HNeg);
3878};
3879
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01003880class HNewArray : public HExpression<2> {
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01003881 public:
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00003882 HNewArray(HInstruction* length,
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01003883 HCurrentMethod* current_method,
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00003884 uint32_t dex_pc,
3885 uint16_t type_index,
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01003886 const DexFile& dex_file,
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00003887 QuickEntrypointEnum entrypoint)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003888 : HExpression(Primitive::kPrimNot, SideEffects::CanTriggerGC(), dex_pc),
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00003889 type_index_(type_index),
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01003890 dex_file_(dex_file),
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00003891 entrypoint_(entrypoint) {
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01003892 SetRawInputAt(0, length);
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01003893 SetRawInputAt(1, current_method);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01003894 }
3895
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01003896 uint16_t GetTypeIndex() const { return type_index_; }
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01003897 const DexFile& GetDexFile() const { return dex_file_; }
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01003898
3899 // Calls runtime so needs an environment.
Calin Juravle10e244f2015-01-26 18:54:32 +00003900 bool NeedsEnvironment() const OVERRIDE { return true; }
3901
Mingyao Yang0c365e62015-03-31 15:09:29 -07003902 // May throw NegativeArraySizeException, OutOfMemoryError, etc.
3903 bool CanThrow() const OVERRIDE { return true; }
3904
Calin Juravle10e244f2015-01-26 18:54:32 +00003905 bool CanBeNull() const OVERRIDE { return false; }
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01003906
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00003907 QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; }
3908
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01003909 DECLARE_INSTRUCTION(NewArray);
3910
3911 private:
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01003912 const uint16_t type_index_;
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01003913 const DexFile& dex_file_;
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00003914 const QuickEntrypointEnum entrypoint_;
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01003915
3916 DISALLOW_COPY_AND_ASSIGN(HNewArray);
3917};
3918
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00003919class HAdd : public HBinaryOperation {
3920 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003921 HAdd(Primitive::Type result_type,
3922 HInstruction* left,
3923 HInstruction* right,
3924 uint32_t dex_pc = kNoDexPc)
3925 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00003926
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003927 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00003928
Roland Levillain9867bc72015-08-05 10:21:34 +01003929 template <typename T> T Compute(T x, T y) const { return x + y; }
3930
3931 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003932 return GetBlock()->GetGraph()->GetIntConstant(
3933 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain93445682014-10-06 19:24:02 +01003934 }
Roland Levillain9867bc72015-08-05 10:21:34 +01003935 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003936 return GetBlock()->GetGraph()->GetLongConstant(
3937 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain93445682014-10-06 19:24:02 +01003938 }
Roland Levillain556c3d12014-09-18 15:25:07 +01003939
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00003940 DECLARE_INSTRUCTION(Add);
3941
3942 private:
3943 DISALLOW_COPY_AND_ASSIGN(HAdd);
3944};
3945
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01003946class HSub : public HBinaryOperation {
3947 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003948 HSub(Primitive::Type result_type,
3949 HInstruction* left,
3950 HInstruction* right,
3951 uint32_t dex_pc = kNoDexPc)
3952 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01003953
Roland Levillain9867bc72015-08-05 10:21:34 +01003954 template <typename T> T Compute(T x, T y) const { return x - y; }
3955
3956 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003957 return GetBlock()->GetGraph()->GetIntConstant(
3958 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain93445682014-10-06 19:24:02 +01003959 }
Roland Levillain9867bc72015-08-05 10:21:34 +01003960 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003961 return GetBlock()->GetGraph()->GetLongConstant(
3962 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain93445682014-10-06 19:24:02 +01003963 }
Roland Levillain556c3d12014-09-18 15:25:07 +01003964
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01003965 DECLARE_INSTRUCTION(Sub);
3966
3967 private:
3968 DISALLOW_COPY_AND_ASSIGN(HSub);
3969};
3970
Calin Juravle34bacdf2014-10-07 20:23:36 +01003971class HMul : public HBinaryOperation {
3972 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003973 HMul(Primitive::Type result_type,
3974 HInstruction* left,
3975 HInstruction* right,
3976 uint32_t dex_pc = kNoDexPc)
3977 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
Calin Juravle34bacdf2014-10-07 20:23:36 +01003978
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003979 bool IsCommutative() const OVERRIDE { return true; }
Calin Juravle34bacdf2014-10-07 20:23:36 +01003980
Roland Levillain9867bc72015-08-05 10:21:34 +01003981 template <typename T> T Compute(T x, T y) const { return x * y; }
3982
3983 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003984 return GetBlock()->GetGraph()->GetIntConstant(
3985 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01003986 }
3987 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06003988 return GetBlock()->GetGraph()->GetLongConstant(
3989 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01003990 }
Calin Juravle34bacdf2014-10-07 20:23:36 +01003991
3992 DECLARE_INSTRUCTION(Mul);
3993
3994 private:
3995 DISALLOW_COPY_AND_ASSIGN(HMul);
3996};
3997
Calin Juravle7c4954d2014-10-28 16:57:40 +00003998class HDiv : public HBinaryOperation {
3999 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004000 HDiv(Primitive::Type result_type,
4001 HInstruction* left,
4002 HInstruction* right,
4003 uint32_t dex_pc)
4004 : HBinaryOperation(result_type, left, right, SideEffectsForArchRuntimeCalls(), dex_pc) {}
Calin Juravle7c4954d2014-10-28 16:57:40 +00004005
Roland Levillain9867bc72015-08-05 10:21:34 +01004006 template <typename T>
4007 T Compute(T x, T y) const {
4008 // Our graph structure ensures we never have 0 for `y` during
4009 // constant folding.
Nicolas Geoffraycd2de0c2014-11-06 15:59:38 +00004010 DCHECK_NE(y, 0);
Calin Juravlebacfec32014-11-14 15:54:36 +00004011 // Special case -1 to avoid getting a SIGFPE on x86(_64).
Nicolas Geoffraycd2de0c2014-11-06 15:59:38 +00004012 return (y == -1) ? -x : x / y;
4013 }
Calin Juravlebacfec32014-11-14 15:54:36 +00004014
Roland Levillain9867bc72015-08-05 10:21:34 +01004015 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004016 return GetBlock()->GetGraph()->GetIntConstant(
4017 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004018 }
4019 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004020 return GetBlock()->GetGraph()->GetLongConstant(
4021 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Calin Juravlebacfec32014-11-14 15:54:36 +00004022 }
Calin Juravle7c4954d2014-10-28 16:57:40 +00004023
Alexandre Rames78e3ef62015-08-12 13:43:29 +01004024 static SideEffects SideEffectsForArchRuntimeCalls() {
4025 // The generated code can use a runtime call.
4026 return SideEffects::CanTriggerGC();
4027 }
4028
Calin Juravle7c4954d2014-10-28 16:57:40 +00004029 DECLARE_INSTRUCTION(Div);
4030
4031 private:
4032 DISALLOW_COPY_AND_ASSIGN(HDiv);
4033};
4034
Calin Juravlebacfec32014-11-14 15:54:36 +00004035class HRem : public HBinaryOperation {
4036 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004037 HRem(Primitive::Type result_type,
4038 HInstruction* left,
4039 HInstruction* right,
4040 uint32_t dex_pc)
4041 : HBinaryOperation(result_type, left, right, SideEffectsForArchRuntimeCalls(), dex_pc) {}
Calin Juravlebacfec32014-11-14 15:54:36 +00004042
Roland Levillain9867bc72015-08-05 10:21:34 +01004043 template <typename T>
4044 T Compute(T x, T y) const {
4045 // Our graph structure ensures we never have 0 for `y` during
4046 // constant folding.
Calin Juravlebacfec32014-11-14 15:54:36 +00004047 DCHECK_NE(y, 0);
4048 // Special case -1 to avoid getting a SIGFPE on x86(_64).
4049 return (y == -1) ? 0 : x % y;
4050 }
4051
Roland Levillain9867bc72015-08-05 10:21:34 +01004052 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004053 return GetBlock()->GetGraph()->GetIntConstant(
4054 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004055 }
4056 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004057 return GetBlock()->GetGraph()->GetLongConstant(
4058 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Calin Juravlebacfec32014-11-14 15:54:36 +00004059 }
4060
Calin Juravlebacfec32014-11-14 15:54:36 +00004061
Alexandre Rames78e3ef62015-08-12 13:43:29 +01004062 static SideEffects SideEffectsForArchRuntimeCalls() {
4063 return SideEffects::CanTriggerGC();
4064 }
4065
Calin Juravlebacfec32014-11-14 15:54:36 +00004066 DECLARE_INSTRUCTION(Rem);
4067
4068 private:
Calin Juravlebacfec32014-11-14 15:54:36 +00004069 DISALLOW_COPY_AND_ASSIGN(HRem);
4070};
4071
Calin Juravled0d48522014-11-04 16:40:20 +00004072class HDivZeroCheck : public HExpression<1> {
4073 public:
Alexandre Rames780aece2016-01-13 14:34:39 +00004074 // `HDivZeroCheck` can trigger GC, as it may call the `ArithmeticException`
4075 // constructor.
Calin Juravled0d48522014-11-04 16:40:20 +00004076 HDivZeroCheck(HInstruction* value, uint32_t dex_pc)
Alexandre Rames780aece2016-01-13 14:34:39 +00004077 : HExpression(value->GetType(), SideEffects::CanTriggerGC(), dex_pc) {
Calin Juravled0d48522014-11-04 16:40:20 +00004078 SetRawInputAt(0, value);
4079 }
4080
Serguei Katkov8c0676c2015-08-03 13:55:33 +06004081 Primitive::Type GetType() const OVERRIDE { return InputAt(0)->GetType(); }
4082
Calin Juravled0d48522014-11-04 16:40:20 +00004083 bool CanBeMoved() const OVERRIDE { return true; }
4084
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01004085 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
Calin Juravled0d48522014-11-04 16:40:20 +00004086 return true;
4087 }
4088
4089 bool NeedsEnvironment() const OVERRIDE { return true; }
4090 bool CanThrow() const OVERRIDE { return true; }
4091
Calin Juravled0d48522014-11-04 16:40:20 +00004092 DECLARE_INSTRUCTION(DivZeroCheck);
4093
4094 private:
Calin Juravled0d48522014-11-04 16:40:20 +00004095 DISALLOW_COPY_AND_ASSIGN(HDivZeroCheck);
4096};
4097
Calin Juravle9aec02f2014-11-18 23:06:35 +00004098class HShl : public HBinaryOperation {
4099 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004100 HShl(Primitive::Type result_type,
4101 HInstruction* left,
4102 HInstruction* right,
4103 uint32_t dex_pc = kNoDexPc)
4104 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
Calin Juravle9aec02f2014-11-18 23:06:35 +00004105
Roland Levillain9867bc72015-08-05 10:21:34 +01004106 template <typename T, typename U, typename V>
4107 T Compute(T x, U y, V max_shift_value) const {
4108 static_assert(std::is_same<V, typename std::make_unsigned<T>::type>::value,
4109 "V is not the unsigned integer type corresponding to T");
4110 return x << (y & max_shift_value);
4111 }
4112
4113 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
4114 return GetBlock()->GetGraph()->GetIntConstant(
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004115 Compute(x->GetValue(), y->GetValue(), kMaxIntShiftValue), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004116 }
4117 // There is no `Evaluate(HIntConstant* x, HLongConstant* y)`, as this
4118 // case is handled as `x << static_cast<int>(y)`.
4119 HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
4120 return GetBlock()->GetGraph()->GetLongConstant(
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004121 Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004122 }
4123 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
4124 return GetBlock()->GetGraph()->GetLongConstant(
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004125 Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004126 }
Calin Juravle9aec02f2014-11-18 23:06:35 +00004127
4128 DECLARE_INSTRUCTION(Shl);
4129
4130 private:
4131 DISALLOW_COPY_AND_ASSIGN(HShl);
4132};
4133
4134class HShr : public HBinaryOperation {
4135 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004136 HShr(Primitive::Type result_type,
4137 HInstruction* left,
4138 HInstruction* right,
4139 uint32_t dex_pc = kNoDexPc)
4140 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
Calin Juravle9aec02f2014-11-18 23:06:35 +00004141
Roland Levillain9867bc72015-08-05 10:21:34 +01004142 template <typename T, typename U, typename V>
4143 T Compute(T x, U y, V max_shift_value) const {
4144 static_assert(std::is_same<V, typename std::make_unsigned<T>::type>::value,
4145 "V is not the unsigned integer type corresponding to T");
4146 return x >> (y & max_shift_value);
4147 }
4148
4149 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
4150 return GetBlock()->GetGraph()->GetIntConstant(
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004151 Compute(x->GetValue(), y->GetValue(), kMaxIntShiftValue), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004152 }
4153 // There is no `Evaluate(HIntConstant* x, HLongConstant* y)`, as this
4154 // case is handled as `x >> static_cast<int>(y)`.
4155 HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
4156 return GetBlock()->GetGraph()->GetLongConstant(
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004157 Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004158 }
4159 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
4160 return GetBlock()->GetGraph()->GetLongConstant(
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004161 Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004162 }
Calin Juravle9aec02f2014-11-18 23:06:35 +00004163
4164 DECLARE_INSTRUCTION(Shr);
4165
4166 private:
4167 DISALLOW_COPY_AND_ASSIGN(HShr);
4168};
4169
4170class HUShr : public HBinaryOperation {
4171 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004172 HUShr(Primitive::Type result_type,
4173 HInstruction* left,
4174 HInstruction* right,
4175 uint32_t dex_pc = kNoDexPc)
4176 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
Calin Juravle9aec02f2014-11-18 23:06:35 +00004177
Roland Levillain9867bc72015-08-05 10:21:34 +01004178 template <typename T, typename U, typename V>
4179 T Compute(T x, U y, V max_shift_value) const {
4180 static_assert(std::is_same<V, typename std::make_unsigned<T>::type>::value,
4181 "V is not the unsigned integer type corresponding to T");
4182 V ux = static_cast<V>(x);
4183 return static_cast<T>(ux >> (y & max_shift_value));
Calin Juravle9aec02f2014-11-18 23:06:35 +00004184 }
4185
Roland Levillain9867bc72015-08-05 10:21:34 +01004186 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
4187 return GetBlock()->GetGraph()->GetIntConstant(
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004188 Compute(x->GetValue(), y->GetValue(), kMaxIntShiftValue), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004189 }
4190 // There is no `Evaluate(HIntConstant* x, HLongConstant* y)`, as this
4191 // case is handled as `x >>> static_cast<int>(y)`.
4192 HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
4193 return GetBlock()->GetGraph()->GetLongConstant(
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004194 Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004195 }
4196 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
4197 return GetBlock()->GetGraph()->GetLongConstant(
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004198 Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
Calin Juravle9aec02f2014-11-18 23:06:35 +00004199 }
4200
4201 DECLARE_INSTRUCTION(UShr);
4202
4203 private:
4204 DISALLOW_COPY_AND_ASSIGN(HUShr);
4205};
4206
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00004207class HAnd : public HBinaryOperation {
4208 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004209 HAnd(Primitive::Type result_type,
4210 HInstruction* left,
4211 HInstruction* right,
4212 uint32_t dex_pc = kNoDexPc)
4213 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00004214
Mingyao Yangdc5ac732015-02-25 11:28:05 -08004215 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00004216
Roland Levillain9867bc72015-08-05 10:21:34 +01004217 template <typename T, typename U>
4218 auto Compute(T x, U y) const -> decltype(x & y) { return x & y; }
4219
4220 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004221 return GetBlock()->GetGraph()->GetIntConstant(
4222 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004223 }
4224 HConstant* Evaluate(HIntConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004225 return GetBlock()->GetGraph()->GetLongConstant(
4226 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004227 }
4228 HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004229 return GetBlock()->GetGraph()->GetLongConstant(
4230 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004231 }
4232 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004233 return GetBlock()->GetGraph()->GetLongConstant(
4234 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004235 }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00004236
4237 DECLARE_INSTRUCTION(And);
4238
4239 private:
4240 DISALLOW_COPY_AND_ASSIGN(HAnd);
4241};
4242
4243class HOr : public HBinaryOperation {
4244 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004245 HOr(Primitive::Type result_type,
4246 HInstruction* left,
4247 HInstruction* right,
4248 uint32_t dex_pc = kNoDexPc)
4249 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00004250
Mingyao Yangdc5ac732015-02-25 11:28:05 -08004251 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00004252
Roland Levillain9867bc72015-08-05 10:21:34 +01004253 template <typename T, typename U>
4254 auto Compute(T x, U y) const -> decltype(x | y) { return x | y; }
4255
4256 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004257 return GetBlock()->GetGraph()->GetIntConstant(
4258 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004259 }
4260 HConstant* Evaluate(HIntConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004261 return GetBlock()->GetGraph()->GetLongConstant(
4262 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004263 }
4264 HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004265 return GetBlock()->GetGraph()->GetLongConstant(
4266 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004267 }
4268 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004269 return GetBlock()->GetGraph()->GetLongConstant(
4270 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004271 }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00004272
4273 DECLARE_INSTRUCTION(Or);
4274
4275 private:
4276 DISALLOW_COPY_AND_ASSIGN(HOr);
4277};
4278
4279class HXor : public HBinaryOperation {
4280 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004281 HXor(Primitive::Type result_type,
4282 HInstruction* left,
4283 HInstruction* right,
4284 uint32_t dex_pc = kNoDexPc)
4285 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00004286
Mingyao Yangdc5ac732015-02-25 11:28:05 -08004287 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00004288
Roland Levillain9867bc72015-08-05 10:21:34 +01004289 template <typename T, typename U>
4290 auto Compute(T x, U y) const -> decltype(x ^ y) { return x ^ y; }
4291
4292 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004293 return GetBlock()->GetGraph()->GetIntConstant(
4294 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004295 }
4296 HConstant* Evaluate(HIntConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004297 return GetBlock()->GetGraph()->GetLongConstant(
4298 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004299 }
4300 HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004301 return GetBlock()->GetGraph()->GetLongConstant(
4302 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004303 }
4304 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004305 return GetBlock()->GetGraph()->GetLongConstant(
4306 Compute(x->GetValue(), y->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004307 }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00004308
4309 DECLARE_INSTRUCTION(Xor);
4310
4311 private:
4312 DISALLOW_COPY_AND_ASSIGN(HXor);
4313};
4314
Scott Wakeling40a04bf2015-12-11 09:50:36 +00004315class HRor : public HBinaryOperation {
4316 public:
4317 HRor(Primitive::Type result_type, HInstruction* value, HInstruction* distance)
4318 : HBinaryOperation(result_type, value, distance) {}
4319
4320 template <typename T, typename U, typename V>
4321 T Compute(T x, U y, V max_shift_value) const {
4322 static_assert(std::is_same<V, typename std::make_unsigned<T>::type>::value,
4323 "V is not the unsigned integer type corresponding to T");
4324 V ux = static_cast<V>(x);
4325 if ((y & max_shift_value) == 0) {
4326 return static_cast<T>(ux);
4327 } else {
4328 const V reg_bits = sizeof(T) * 8;
4329 return static_cast<T>(ux >> (y & max_shift_value)) |
4330 (x << (reg_bits - (y & max_shift_value)));
4331 }
4332 }
4333
4334 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
4335 return GetBlock()->GetGraph()->GetIntConstant(
4336 Compute(x->GetValue(), y->GetValue(), kMaxIntShiftValue), GetDexPc());
4337 }
4338 HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
4339 return GetBlock()->GetGraph()->GetLongConstant(
4340 Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
4341 }
4342 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
4343 return GetBlock()->GetGraph()->GetLongConstant(
4344 Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
4345 }
4346
4347 DECLARE_INSTRUCTION(Ror);
4348
4349 private:
4350 DISALLOW_COPY_AND_ASSIGN(HRor);
4351};
4352
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01004353// The value of a parameter in this method. Its location depends on
4354// the calling convention.
Dave Allison20dfc792014-06-16 20:44:29 -07004355class HParameterValue : public HExpression<0> {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01004356 public:
Calin Juravlee6e3bea2015-10-14 13:53:10 +00004357 HParameterValue(const DexFile& dex_file,
4358 uint16_t type_index,
4359 uint8_t index,
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004360 Primitive::Type parameter_type,
4361 bool is_this = false)
4362 : HExpression(parameter_type, SideEffects::None(), kNoDexPc),
Calin Juravlee6e3bea2015-10-14 13:53:10 +00004363 dex_file_(dex_file),
4364 type_index_(type_index),
Nicolas Geoffraye418dda2015-08-11 20:03:09 -07004365 index_(index),
4366 is_this_(is_this),
4367 can_be_null_(!is_this) {}
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01004368
Calin Juravlee6e3bea2015-10-14 13:53:10 +00004369 const DexFile& GetDexFile() const { return dex_file_; }
4370 uint16_t GetTypeIndex() const { return type_index_; }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01004371 uint8_t GetIndex() const { return index_; }
Calin Juravlee6e3bea2015-10-14 13:53:10 +00004372 bool IsThis() const { return is_this_; }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01004373
Nicolas Geoffraye418dda2015-08-11 20:03:09 -07004374 bool CanBeNull() const OVERRIDE { return can_be_null_; }
4375 void SetCanBeNull(bool can_be_null) { can_be_null_ = can_be_null; }
Calin Juravle10e244f2015-01-26 18:54:32 +00004376
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01004377 DECLARE_INSTRUCTION(ParameterValue);
4378
4379 private:
Calin Juravlee6e3bea2015-10-14 13:53:10 +00004380 const DexFile& dex_file_;
4381 const uint16_t type_index_;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01004382 // The index of this parameter in the parameters list. Must be less
Calin Juravle10e244f2015-01-26 18:54:32 +00004383 // than HGraph::number_of_in_vregs_.
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01004384 const uint8_t index_;
4385
Calin Juravle10e244f2015-01-26 18:54:32 +00004386 // Whether or not the parameter value corresponds to 'this' argument.
4387 const bool is_this_;
4388
Nicolas Geoffraye418dda2015-08-11 20:03:09 -07004389 bool can_be_null_;
4390
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01004391 DISALLOW_COPY_AND_ASSIGN(HParameterValue);
4392};
4393
Roland Levillain1cc5f2512014-10-22 18:06:21 +01004394class HNot : public HUnaryOperation {
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01004395 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004396 HNot(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
4397 : HUnaryOperation(result_type, input, dex_pc) {}
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01004398
Alexandre Rames2ed20af2015-03-06 13:55:35 +00004399 bool CanBeMoved() const OVERRIDE { return true; }
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01004400 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07004401 return true;
4402 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01004403
Roland Levillain9867bc72015-08-05 10:21:34 +01004404 template <typename T> T Compute(T x) const { return ~x; }
4405
4406 HConstant* Evaluate(HIntConstant* x) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004407 return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004408 }
4409 HConstant* Evaluate(HLongConstant* x) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004410 return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004411 }
Roland Levillain1cc5f2512014-10-22 18:06:21 +01004412
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01004413 DECLARE_INSTRUCTION(Not);
4414
4415 private:
4416 DISALLOW_COPY_AND_ASSIGN(HNot);
4417};
4418
David Brazdil66d126e2015-04-03 16:02:44 +01004419class HBooleanNot : public HUnaryOperation {
4420 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004421 explicit HBooleanNot(HInstruction* input, uint32_t dex_pc = kNoDexPc)
4422 : HUnaryOperation(Primitive::Type::kPrimBoolean, input, dex_pc) {}
David Brazdil66d126e2015-04-03 16:02:44 +01004423
4424 bool CanBeMoved() const OVERRIDE { return true; }
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01004425 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
David Brazdil66d126e2015-04-03 16:02:44 +01004426 return true;
4427 }
4428
Roland Levillain9867bc72015-08-05 10:21:34 +01004429 template <typename T> bool Compute(T x) const {
David Brazdil66d126e2015-04-03 16:02:44 +01004430 DCHECK(IsUint<1>(x));
4431 return !x;
4432 }
4433
Roland Levillain9867bc72015-08-05 10:21:34 +01004434 HConstant* Evaluate(HIntConstant* x) const OVERRIDE {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004435 return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()), GetDexPc());
Roland Levillain9867bc72015-08-05 10:21:34 +01004436 }
4437 HConstant* Evaluate(HLongConstant* x ATTRIBUTE_UNUSED) const OVERRIDE {
4438 LOG(FATAL) << DebugName() << " is not defined for long values";
David Brazdil66d126e2015-04-03 16:02:44 +01004439 UNREACHABLE();
4440 }
4441
4442 DECLARE_INSTRUCTION(BooleanNot);
4443
4444 private:
4445 DISALLOW_COPY_AND_ASSIGN(HBooleanNot);
4446};
4447
Roland Levillaindff1f282014-11-05 14:15:05 +00004448class HTypeConversion : public HExpression<1> {
4449 public:
4450 // Instantiate a type conversion of `input` to `result_type`.
Roland Levillain624279f2014-12-04 11:54:28 +00004451 HTypeConversion(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004452 : HExpression(result_type,
4453 SideEffectsForArchRuntimeCalls(input->GetType(), result_type),
4454 dex_pc) {
Roland Levillaindff1f282014-11-05 14:15:05 +00004455 SetRawInputAt(0, input);
4456 DCHECK_NE(input->GetType(), result_type);
4457 }
4458
4459 HInstruction* GetInput() const { return InputAt(0); }
4460 Primitive::Type GetInputType() const { return GetInput()->GetType(); }
4461 Primitive::Type GetResultType() const { return GetType(); }
4462
4463 bool CanBeMoved() const OVERRIDE { return true; }
Roland Levillained9b1952014-11-06 11:10:17 +00004464 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { return true; }
Roland Levillaindff1f282014-11-05 14:15:05 +00004465
Mark Mendelle82549b2015-05-06 10:55:34 -04004466 // Try to statically evaluate the conversion and return a HConstant
4467 // containing the result. If the input cannot be converted, return nullptr.
4468 HConstant* TryStaticEvaluation() const;
4469
Alexandre Rames78e3ef62015-08-12 13:43:29 +01004470 static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type input_type,
4471 Primitive::Type result_type) {
4472 // Some architectures may not require the 'GC' side effects, but at this point
4473 // in the compilation process we do not know what architecture we will
4474 // generate code for, so we must be conservative.
Roland Levillaindf3f8222015-08-13 12:31:44 +01004475 if ((Primitive::IsFloatingPointType(input_type) && Primitive::IsIntegralType(result_type))
4476 || (input_type == Primitive::kPrimLong && Primitive::IsFloatingPointType(result_type))) {
Alexandre Rames78e3ef62015-08-12 13:43:29 +01004477 return SideEffects::CanTriggerGC();
4478 }
4479 return SideEffects::None();
4480 }
4481
Roland Levillaindff1f282014-11-05 14:15:05 +00004482 DECLARE_INSTRUCTION(TypeConversion);
4483
4484 private:
4485 DISALLOW_COPY_AND_ASSIGN(HTypeConversion);
4486};
4487
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00004488static constexpr uint32_t kNoRegNumber = -1;
4489
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01004490class HPhi : public HInstruction {
4491 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004492 HPhi(ArenaAllocator* arena,
4493 uint32_t reg_number,
4494 size_t number_of_inputs,
4495 Primitive::Type type,
4496 uint32_t dex_pc = kNoDexPc)
4497 : HInstruction(SideEffects::None(), dex_pc),
Vladimir Markofa6b93c2015-09-15 10:15:55 +01004498 inputs_(number_of_inputs, arena->Adapter(kArenaAllocPhiInputs)),
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01004499 reg_number_(reg_number),
David Brazdil809d70f2015-11-19 10:29:39 +00004500 type_(ToPhiType(type)),
4501 // Phis are constructed live and marked dead if conflicting or unused.
4502 // Individual steps of SsaBuilder should assume that if a phi has been
4503 // marked dead, it can be ignored and will be removed by SsaPhiElimination.
4504 is_live_(true),
Calin Juravle10e244f2015-01-26 18:54:32 +00004505 can_be_null_(true) {
David Brazdil809d70f2015-11-19 10:29:39 +00004506 DCHECK_NE(type_, Primitive::kPrimVoid);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01004507 }
4508
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +00004509 // Returns a type equivalent to the given `type`, but that a `HPhi` can hold.
4510 static Primitive::Type ToPhiType(Primitive::Type type) {
4511 switch (type) {
4512 case Primitive::kPrimBoolean:
4513 case Primitive::kPrimByte:
4514 case Primitive::kPrimShort:
4515 case Primitive::kPrimChar:
4516 return Primitive::kPrimInt;
4517 default:
4518 return type;
4519 }
4520 }
4521
David Brazdilffee3d32015-07-06 11:48:53 +01004522 bool IsCatchPhi() const { return GetBlock()->IsCatchBlock(); }
4523
Vladimir Markofa6b93c2015-09-15 10:15:55 +01004524 size_t InputCount() const OVERRIDE { return inputs_.size(); }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01004525
4526 void AddInput(HInstruction* input);
David Brazdil2d7352b2015-04-20 14:52:42 +01004527 void RemoveInputAt(size_t index);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01004528
Calin Juravle10e244f2015-01-26 18:54:32 +00004529 Primitive::Type GetType() const OVERRIDE { return type_; }
David Brazdil4833f5a2015-12-16 10:37:39 +00004530 void SetType(Primitive::Type new_type) {
4531 // Make sure that only valid type changes occur. The following are allowed:
4532 // (1) int -> float/ref (primitive type propagation),
4533 // (2) long -> double (primitive type propagation).
4534 DCHECK(type_ == new_type ||
4535 (type_ == Primitive::kPrimInt && new_type == Primitive::kPrimFloat) ||
4536 (type_ == Primitive::kPrimInt && new_type == Primitive::kPrimNot) ||
4537 (type_ == Primitive::kPrimLong && new_type == Primitive::kPrimDouble));
4538 type_ = new_type;
4539 }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01004540
Calin Juravle10e244f2015-01-26 18:54:32 +00004541 bool CanBeNull() const OVERRIDE { return can_be_null_; }
4542 void SetCanBeNull(bool can_be_null) { can_be_null_ = can_be_null; }
4543
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01004544 uint32_t GetRegNumber() const { return reg_number_; }
4545
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01004546 void SetDead() { is_live_ = false; }
4547 void SetLive() { is_live_ = true; }
4548 bool IsDead() const { return !is_live_; }
4549 bool IsLive() const { return is_live_; }
4550
David Brazdil77a48ae2015-09-15 12:34:04 +00004551 bool IsVRegEquivalentOf(HInstruction* other) const {
4552 return other != nullptr
4553 && other->IsPhi()
4554 && other->AsPhi()->GetBlock() == GetBlock()
4555 && other->AsPhi()->GetRegNumber() == GetRegNumber();
4556 }
4557
Calin Juravlea4f88312015-04-16 12:57:19 +01004558 // Returns the next equivalent phi (starting from the current one) or null if there is none.
4559 // An equivalent phi is a phi having the same dex register and type.
4560 // It assumes that phis with the same dex register are adjacent.
4561 HPhi* GetNextEquivalentPhiWithSameType() {
4562 HInstruction* next = GetNext();
4563 while (next != nullptr && next->AsPhi()->GetRegNumber() == reg_number_) {
4564 if (next->GetType() == GetType()) {
4565 return next->AsPhi();
4566 }
4567 next = next->GetNext();
4568 }
4569 return nullptr;
4570 }
4571
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01004572 DECLARE_INSTRUCTION(Phi);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01004573
David Brazdil1abb4192015-02-17 18:33:36 +00004574 protected:
Vladimir Markofa6b93c2015-09-15 10:15:55 +01004575 const HUserRecord<HInstruction*> InputRecordAt(size_t index) const OVERRIDE {
Vladimir Markofa6b93c2015-09-15 10:15:55 +01004576 return inputs_[index];
4577 }
David Brazdil1abb4192015-02-17 18:33:36 +00004578
4579 void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) OVERRIDE {
Vladimir Markofa6b93c2015-09-15 10:15:55 +01004580 inputs_[index] = input;
David Brazdil1abb4192015-02-17 18:33:36 +00004581 }
4582
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01004583 private:
Vladimir Markofa6b93c2015-09-15 10:15:55 +01004584 ArenaVector<HUserRecord<HInstruction*> > inputs_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01004585 const uint32_t reg_number_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01004586 Primitive::Type type_;
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01004587 bool is_live_;
Calin Juravle10e244f2015-01-26 18:54:32 +00004588 bool can_be_null_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01004589
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01004590 DISALLOW_COPY_AND_ASSIGN(HPhi);
4591};
4592
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004593class HNullCheck : public HExpression<1> {
4594 public:
Nicolas Geoffray1af564e2016-01-13 12:09:39 +00004595 // `HNullCheck` can trigger GC, as it may call the `NullPointerException`
4596 // constructor.
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004597 HNullCheck(HInstruction* value, uint32_t dex_pc)
Nicolas Geoffray1af564e2016-01-13 12:09:39 +00004598 : HExpression(value->GetType(), SideEffects::CanTriggerGC(), dex_pc) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004599 SetRawInputAt(0, value);
4600 }
4601
Calin Juravle10e244f2015-01-26 18:54:32 +00004602 bool CanBeMoved() const OVERRIDE { return true; }
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01004603 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07004604 return true;
4605 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01004606
Calin Juravle10e244f2015-01-26 18:54:32 +00004607 bool NeedsEnvironment() const OVERRIDE { return true; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004608
Calin Juravle10e244f2015-01-26 18:54:32 +00004609 bool CanThrow() const OVERRIDE { return true; }
4610
4611 bool CanBeNull() const OVERRIDE { return false; }
Roland Levillaine161a2a2014-10-03 12:45:18 +01004612
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004613
4614 DECLARE_INSTRUCTION(NullCheck);
4615
4616 private:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004617 DISALLOW_COPY_AND_ASSIGN(HNullCheck);
4618};
4619
4620class FieldInfo : public ValueObject {
4621 public:
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01004622 FieldInfo(MemberOffset field_offset,
4623 Primitive::Type field_type,
4624 bool is_volatile,
4625 uint32_t index,
Mingyao Yang8df69d42015-10-22 15:40:58 -07004626 uint16_t declaring_class_def_index,
Mathieu Chartier736b5602015-09-02 14:54:11 -07004627 const DexFile& dex_file,
4628 Handle<mirror::DexCache> dex_cache)
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01004629 : field_offset_(field_offset),
4630 field_type_(field_type),
4631 is_volatile_(is_volatile),
4632 index_(index),
Mingyao Yang8df69d42015-10-22 15:40:58 -07004633 declaring_class_def_index_(declaring_class_def_index),
Mathieu Chartier736b5602015-09-02 14:54:11 -07004634 dex_file_(dex_file),
4635 dex_cache_(dex_cache) {}
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004636
4637 MemberOffset GetFieldOffset() const { return field_offset_; }
Nicolas Geoffray39468442014-09-02 15:17:15 +01004638 Primitive::Type GetFieldType() const { return field_type_; }
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01004639 uint32_t GetFieldIndex() const { return index_; }
Mingyao Yang8df69d42015-10-22 15:40:58 -07004640 uint16_t GetDeclaringClassDefIndex() const { return declaring_class_def_index_;}
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01004641 const DexFile& GetDexFile() const { return dex_file_; }
Calin Juravle52c48962014-12-16 17:02:57 +00004642 bool IsVolatile() const { return is_volatile_; }
Mathieu Chartier736b5602015-09-02 14:54:11 -07004643 Handle<mirror::DexCache> GetDexCache() const { return dex_cache_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004644
4645 private:
4646 const MemberOffset field_offset_;
Nicolas Geoffray39468442014-09-02 15:17:15 +01004647 const Primitive::Type field_type_;
Calin Juravle52c48962014-12-16 17:02:57 +00004648 const bool is_volatile_;
Mathieu Chartier736b5602015-09-02 14:54:11 -07004649 const uint32_t index_;
Mingyao Yang8df69d42015-10-22 15:40:58 -07004650 const uint16_t declaring_class_def_index_;
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01004651 const DexFile& dex_file_;
Mathieu Chartier736b5602015-09-02 14:54:11 -07004652 const Handle<mirror::DexCache> dex_cache_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004653};
4654
4655class HInstanceFieldGet : public HExpression<1> {
4656 public:
4657 HInstanceFieldGet(HInstruction* value,
4658 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00004659 MemberOffset field_offset,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01004660 bool is_volatile,
4661 uint32_t field_idx,
Mingyao Yang8df69d42015-10-22 15:40:58 -07004662 uint16_t declaring_class_def_index,
Mathieu Chartier736b5602015-09-02 14:54:11 -07004663 const DexFile& dex_file,
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004664 Handle<mirror::DexCache> dex_cache,
Calin Juravle154746b2015-10-06 15:46:54 +01004665 uint32_t dex_pc)
Mingyao Yang8df69d42015-10-22 15:40:58 -07004666 : HExpression(field_type,
4667 SideEffects::FieldReadOfType(field_type, is_volatile),
4668 dex_pc),
4669 field_info_(field_offset,
4670 field_type,
4671 is_volatile,
4672 field_idx,
4673 declaring_class_def_index,
4674 dex_file,
4675 dex_cache) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004676 SetRawInputAt(0, value);
4677 }
4678
Calin Juravle10c9cbe2014-12-19 10:50:19 +00004679 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); }
Calin Juravle52c48962014-12-16 17:02:57 +00004680
4681 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
4682 HInstanceFieldGet* other_get = other->AsInstanceFieldGet();
4683 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
Nicolas Geoffray065bf772014-09-03 14:51:22 +01004684 }
4685
Calin Juravle641547a2015-04-21 22:08:51 +01004686 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
4687 return (obj == InputAt(0)) && GetFieldOffset().Uint32Value() < kPageSize;
Calin Juravle77520bc2015-01-12 18:45:46 +00004688 }
4689
4690 size_t ComputeHashCode() const OVERRIDE {
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01004691 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
4692 }
4693
Calin Juravle52c48962014-12-16 17:02:57 +00004694 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004695 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
Nicolas Geoffray39468442014-09-02 15:17:15 +01004696 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00004697 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004698
4699 DECLARE_INSTRUCTION(InstanceFieldGet);
4700
4701 private:
4702 const FieldInfo field_info_;
4703
4704 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldGet);
4705};
4706
4707class HInstanceFieldSet : public HTemplateInstruction<2> {
4708 public:
4709 HInstanceFieldSet(HInstruction* object,
4710 HInstruction* value,
Nicolas Geoffray39468442014-09-02 15:17:15 +01004711 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00004712 MemberOffset field_offset,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01004713 bool is_volatile,
4714 uint32_t field_idx,
Mingyao Yang8df69d42015-10-22 15:40:58 -07004715 uint16_t declaring_class_def_index,
Mathieu Chartier736b5602015-09-02 14:54:11 -07004716 const DexFile& dex_file,
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004717 Handle<mirror::DexCache> dex_cache,
Calin Juravle154746b2015-10-06 15:46:54 +01004718 uint32_t dex_pc)
Mingyao Yang8df69d42015-10-22 15:40:58 -07004719 : HTemplateInstruction(SideEffects::FieldWriteOfType(field_type, is_volatile),
4720 dex_pc),
4721 field_info_(field_offset,
4722 field_type,
4723 is_volatile,
4724 field_idx,
4725 declaring_class_def_index,
4726 dex_file,
4727 dex_cache),
Nicolas Geoffray07276db2015-05-18 14:22:09 +01004728 value_can_be_null_(true) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004729 SetRawInputAt(0, object);
4730 SetRawInputAt(1, value);
4731 }
4732
Calin Juravle641547a2015-04-21 22:08:51 +01004733 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
4734 return (obj == InputAt(0)) && GetFieldOffset().Uint32Value() < kPageSize;
Calin Juravle77520bc2015-01-12 18:45:46 +00004735 }
4736
Calin Juravle52c48962014-12-16 17:02:57 +00004737 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004738 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
Nicolas Geoffray39468442014-09-02 15:17:15 +01004739 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00004740 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00004741 HInstruction* GetValue() const { return InputAt(1); }
Nicolas Geoffray07276db2015-05-18 14:22:09 +01004742 bool GetValueCanBeNull() const { return value_can_be_null_; }
4743 void ClearValueCanBeNull() { value_can_be_null_ = false; }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00004744
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004745 DECLARE_INSTRUCTION(InstanceFieldSet);
4746
4747 private:
4748 const FieldInfo field_info_;
Nicolas Geoffray07276db2015-05-18 14:22:09 +01004749 bool value_can_be_null_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004750
4751 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldSet);
4752};
4753
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01004754class HArrayGet : public HExpression<2> {
4755 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004756 HArrayGet(HInstruction* array,
4757 HInstruction* index,
4758 Primitive::Type type,
Alexandre Ramese6dbf482015-10-19 10:10:41 +01004759 uint32_t dex_pc,
4760 SideEffects additional_side_effects = SideEffects::None())
4761 : HExpression(type,
4762 SideEffects::ArrayReadOfType(type).Union(additional_side_effects),
David Brazdil2bd4c5c2015-11-04 22:48:45 +00004763 dex_pc) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01004764 SetRawInputAt(0, array);
4765 SetRawInputAt(1, index);
4766 }
4767
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00004768 bool CanBeMoved() const OVERRIDE { return true; }
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01004769 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07004770 return true;
4771 }
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01004772 bool CanDoImplicitNullCheckOn(HInstruction* obj ATTRIBUTE_UNUSED) const OVERRIDE {
Calin Juravle77520bc2015-01-12 18:45:46 +00004773 // TODO: We can be smarter here.
4774 // Currently, the array access is always preceded by an ArrayLength or a NullCheck
4775 // which generates the implicit null check. There are cases when these can be removed
4776 // to produce better code. If we ever add optimizations to do so we should allow an
4777 // implicit check here (as long as the address falls in the first page).
4778 return false;
4779 }
4780
David Brazdil4833f5a2015-12-16 10:37:39 +00004781 bool IsEquivalentOf(HArrayGet* other) const {
4782 bool result = (GetDexPc() == other->GetDexPc());
4783 if (kIsDebugBuild && result) {
4784 DCHECK_EQ(GetBlock(), other->GetBlock());
4785 DCHECK_EQ(GetArray(), other->GetArray());
4786 DCHECK_EQ(GetIndex(), other->GetIndex());
4787 if (Primitive::IsIntOrLongType(GetType())) {
4788 DCHECK(Primitive::IsFloatingPointType(other->GetType()));
4789 } else {
4790 DCHECK(Primitive::IsFloatingPointType(GetType()));
4791 DCHECK(Primitive::IsIntOrLongType(other->GetType()));
4792 }
4793 }
4794 return result;
4795 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01004796
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00004797 HInstruction* GetArray() const { return InputAt(0); }
4798 HInstruction* GetIndex() const { return InputAt(1); }
4799
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01004800 DECLARE_INSTRUCTION(ArrayGet);
4801
4802 private:
4803 DISALLOW_COPY_AND_ASSIGN(HArrayGet);
4804};
4805
4806class HArraySet : public HTemplateInstruction<3> {
4807 public:
4808 HArraySet(HInstruction* array,
4809 HInstruction* index,
4810 HInstruction* value,
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01004811 Primitive::Type expected_component_type,
Alexandre Ramese6dbf482015-10-19 10:10:41 +01004812 uint32_t dex_pc,
4813 SideEffects additional_side_effects = SideEffects::None())
Alexandre Rames78e3ef62015-08-12 13:43:29 +01004814 : HTemplateInstruction(
4815 SideEffects::ArrayWriteOfType(expected_component_type).Union(
Alexandre Ramese6dbf482015-10-19 10:10:41 +01004816 SideEffectsForArchRuntimeCalls(value->GetType())).Union(
4817 additional_side_effects),
4818 dex_pc),
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00004819 expected_component_type_(expected_component_type),
Nicolas Geoffray07276db2015-05-18 14:22:09 +01004820 needs_type_check_(value->GetType() == Primitive::kPrimNot),
Nicolas Geoffraye0395dd2015-09-25 11:04:45 +01004821 value_can_be_null_(true),
4822 static_type_of_array_is_object_array_(false) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01004823 SetRawInputAt(0, array);
4824 SetRawInputAt(1, index);
4825 SetRawInputAt(2, value);
4826 }
4827
Calin Juravle77520bc2015-01-12 18:45:46 +00004828 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffray03196cf2016-02-01 12:23:22 +00004829 // We call a runtime method to throw ArrayStoreException.
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00004830 return needs_type_check_;
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01004831 }
4832
Mingyao Yang81014cb2015-06-02 03:16:27 -07004833 // Can throw ArrayStoreException.
4834 bool CanThrow() const OVERRIDE { return needs_type_check_; }
4835
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01004836 bool CanDoImplicitNullCheckOn(HInstruction* obj ATTRIBUTE_UNUSED) const OVERRIDE {
Calin Juravle77520bc2015-01-12 18:45:46 +00004837 // TODO: Same as for ArrayGet.
4838 return false;
4839 }
4840
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00004841 void ClearNeedsTypeCheck() {
4842 needs_type_check_ = false;
4843 }
4844
Nicolas Geoffray07276db2015-05-18 14:22:09 +01004845 void ClearValueCanBeNull() {
4846 value_can_be_null_ = false;
4847 }
4848
Nicolas Geoffraye0395dd2015-09-25 11:04:45 +01004849 void SetStaticTypeOfArrayIsObjectArray() {
4850 static_type_of_array_is_object_array_ = true;
4851 }
4852
Nicolas Geoffray07276db2015-05-18 14:22:09 +01004853 bool GetValueCanBeNull() const { return value_can_be_null_; }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00004854 bool NeedsTypeCheck() const { return needs_type_check_; }
Nicolas Geoffraye0395dd2015-09-25 11:04:45 +01004855 bool StaticTypeOfArrayIsObjectArray() const { return static_type_of_array_is_object_array_; }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00004856
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00004857 HInstruction* GetArray() const { return InputAt(0); }
4858 HInstruction* GetIndex() const { return InputAt(1); }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01004859 HInstruction* GetValue() const { return InputAt(2); }
4860
4861 Primitive::Type GetComponentType() const {
4862 // The Dex format does not type floating point index operations. Since the
4863 // `expected_component_type_` is set during building and can therefore not
4864 // be correct, we also check what is the value type. If it is a floating
4865 // point type, we must use that type.
4866 Primitive::Type value_type = GetValue()->GetType();
4867 return ((value_type == Primitive::kPrimFloat) || (value_type == Primitive::kPrimDouble))
4868 ? value_type
4869 : expected_component_type_;
4870 }
Nicolas Geoffray39468442014-09-02 15:17:15 +01004871
Alexandre Ramese6dbf482015-10-19 10:10:41 +01004872 Primitive::Type GetRawExpectedComponentType() const {
4873 return expected_component_type_;
4874 }
4875
Alexandre Rames78e3ef62015-08-12 13:43:29 +01004876 static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type value_type) {
4877 return (value_type == Primitive::kPrimNot) ? SideEffects::CanTriggerGC() : SideEffects::None();
4878 }
4879
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01004880 DECLARE_INSTRUCTION(ArraySet);
4881
4882 private:
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01004883 const Primitive::Type expected_component_type_;
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00004884 bool needs_type_check_;
Nicolas Geoffray07276db2015-05-18 14:22:09 +01004885 bool value_can_be_null_;
Nicolas Geoffraye0395dd2015-09-25 11:04:45 +01004886 // Cached information for the reference_type_info_ so that codegen
4887 // does not need to inspect the static type.
4888 bool static_type_of_array_is_object_array_;
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01004889
4890 DISALLOW_COPY_AND_ASSIGN(HArraySet);
4891};
4892
4893class HArrayLength : public HExpression<1> {
4894 public:
Nicolas Geoffrayee3cf072015-10-06 11:45:02 +01004895 HArrayLength(HInstruction* array, uint32_t dex_pc)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004896 : HExpression(Primitive::kPrimInt, SideEffects::None(), dex_pc) {
Nicolas Geoffray065bf772014-09-03 14:51:22 +01004897 // Note that arrays do not change length, so the instruction does not
4898 // depend on any write.
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01004899 SetRawInputAt(0, array);
4900 }
4901
Calin Juravle77520bc2015-01-12 18:45:46 +00004902 bool CanBeMoved() const OVERRIDE { return true; }
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01004903 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07004904 return true;
4905 }
Calin Juravle641547a2015-04-21 22:08:51 +01004906 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
4907 return obj == InputAt(0);
4908 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01004909
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01004910 DECLARE_INSTRUCTION(ArrayLength);
4911
4912 private:
4913 DISALLOW_COPY_AND_ASSIGN(HArrayLength);
4914};
4915
4916class HBoundsCheck : public HExpression<2> {
4917 public:
Nicolas Geoffray1af564e2016-01-13 12:09:39 +00004918 // `HBoundsCheck` can trigger GC, as it may call the `IndexOutOfBoundsException`
4919 // constructor.
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01004920 HBoundsCheck(HInstruction* index, HInstruction* length, uint32_t dex_pc)
Nicolas Geoffray1af564e2016-01-13 12:09:39 +00004921 : HExpression(index->GetType(), SideEffects::CanTriggerGC(), dex_pc) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01004922 DCHECK(index->GetType() == Primitive::kPrimInt);
4923 SetRawInputAt(0, index);
4924 SetRawInputAt(1, length);
4925 }
4926
Alexandre Rames2ed20af2015-03-06 13:55:35 +00004927 bool CanBeMoved() const OVERRIDE { return true; }
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01004928 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07004929 return true;
4930 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01004931
Alexandre Rames2ed20af2015-03-06 13:55:35 +00004932 bool NeedsEnvironment() const OVERRIDE { return true; }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01004933
Alexandre Rames2ed20af2015-03-06 13:55:35 +00004934 bool CanThrow() const OVERRIDE { return true; }
Roland Levillaine161a2a2014-10-03 12:45:18 +01004935
Alexandre Ramese6dbf482015-10-19 10:10:41 +01004936 HInstruction* GetIndex() const { return InputAt(0); }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01004937
4938 DECLARE_INSTRUCTION(BoundsCheck);
4939
4940 private:
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01004941 DISALLOW_COPY_AND_ASSIGN(HBoundsCheck);
4942};
4943
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004944/**
4945 * Some DEX instructions are folded into multiple HInstructions that need
4946 * to stay live until the last HInstruction. This class
4947 * is used as a marker for the baseline compiler to ensure its preceding
Calin Juravlef97f9fb2014-11-11 15:38:19 +00004948 * HInstruction stays live. `index` represents the stack location index of the
4949 * instruction (the actual offset is computed as index * vreg_size).
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004950 */
4951class HTemporary : public HTemplateInstruction<0> {
4952 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004953 explicit HTemporary(size_t index, uint32_t dex_pc = kNoDexPc)
4954 : HTemplateInstruction(SideEffects::None(), dex_pc), index_(index) {}
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004955
4956 size_t GetIndex() const { return index_; }
4957
Nicolas Geoffray421e9f92014-11-11 18:21:53 +00004958 Primitive::Type GetType() const OVERRIDE {
4959 // The previous instruction is the one that will be stored in the temporary location.
4960 DCHECK(GetPrevious() != nullptr);
4961 return GetPrevious()->GetType();
4962 }
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +00004963
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004964 DECLARE_INSTRUCTION(Temporary);
4965
4966 private:
4967 const size_t index_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +01004968 DISALLOW_COPY_AND_ASSIGN(HTemporary);
4969};
4970
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00004971class HSuspendCheck : public HTemplateInstruction<0> {
4972 public:
4973 explicit HSuspendCheck(uint32_t dex_pc)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06004974 : HTemplateInstruction(SideEffects::CanTriggerGC(), dex_pc), slow_path_(nullptr) {}
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00004975
Alexandre Rames2ed20af2015-03-06 13:55:35 +00004976 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00004977 return true;
4978 }
4979
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01004980 void SetSlowPath(SlowPathCode* slow_path) { slow_path_ = slow_path; }
4981 SlowPathCode* GetSlowPath() const { return slow_path_; }
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00004982
4983 DECLARE_INSTRUCTION(SuspendCheck);
4984
4985 private:
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01004986 // Only used for code generation, in order to share the same slow path between back edges
4987 // of a same loop.
4988 SlowPathCode* slow_path_;
4989
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00004990 DISALLOW_COPY_AND_ASSIGN(HSuspendCheck);
4991};
4992
David Srbecky0cf44932015-12-09 14:09:59 +00004993// Pseudo-instruction which provides the native debugger with mapping information.
4994// It ensures that we can generate line number and local variables at this point.
4995class HNativeDebugInfo : public HTemplateInstruction<0> {
4996 public:
4997 explicit HNativeDebugInfo(uint32_t dex_pc)
4998 : HTemplateInstruction<0>(SideEffects::None(), dex_pc) {}
4999
5000 bool NeedsEnvironment() const OVERRIDE {
5001 return true;
5002 }
5003
5004 DECLARE_INSTRUCTION(NativeDebugInfo);
5005
5006 private:
5007 DISALLOW_COPY_AND_ASSIGN(HNativeDebugInfo);
5008};
5009
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005010/**
5011 * Instruction to load a Class object.
5012 */
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01005013class HLoadClass : public HExpression<1> {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005014 public:
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01005015 HLoadClass(HCurrentMethod* current_method,
5016 uint16_t type_index,
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01005017 const DexFile& dex_file,
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005018 bool is_referrers_class,
Calin Juravle98893e12015-10-02 21:05:03 +01005019 uint32_t dex_pc,
Nicolas Geoffray42e372e2015-11-24 15:48:56 +00005020 bool needs_access_check,
5021 bool is_in_dex_cache)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005022 : HExpression(Primitive::kPrimNot, SideEffectsForArchRuntimeCalls(), dex_pc),
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005023 type_index_(type_index),
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01005024 dex_file_(dex_file),
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005025 is_referrers_class_(is_referrers_class),
Calin Juravleb1498f62015-02-16 13:13:29 +00005026 generate_clinit_check_(false),
Calin Juravle98893e12015-10-02 21:05:03 +01005027 needs_access_check_(needs_access_check),
Nicolas Geoffray42e372e2015-11-24 15:48:56 +00005028 is_in_dex_cache_(is_in_dex_cache),
Calin Juravle2e768302015-07-28 14:41:11 +00005029 loaded_class_rti_(ReferenceTypeInfo::CreateInvalid()) {
Calin Juravle4e2a5572015-10-07 18:55:43 +01005030 // Referrers class should not need access check. We never inline unverified
5031 // methods so we can't possibly end up in this situation.
5032 DCHECK(!is_referrers_class_ || !needs_access_check_);
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01005033 SetRawInputAt(0, current_method);
5034 }
Nicolas Geoffray424f6762014-11-03 14:51:25 +00005035
5036 bool CanBeMoved() const OVERRIDE { return true; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005037
5038 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Calin Juravlea9a306d2015-10-08 16:48:31 +01005039 // Note that we don't need to test for generate_clinit_check_.
5040 // Whether or not we need to generate the clinit check is processed in
5041 // prepare_for_register_allocator based on existing HInvokes and HClinitChecks.
Calin Juravle386062d2015-10-07 18:55:43 +01005042 return other->AsLoadClass()->type_index_ == type_index_ &&
5043 other->AsLoadClass()->needs_access_check_ == needs_access_check_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005044 }
5045
5046 size_t ComputeHashCode() const OVERRIDE { return type_index_; }
5047
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005048 uint16_t GetTypeIndex() const { return type_index_; }
Nicolas Geoffray424f6762014-11-03 14:51:25 +00005049 bool IsReferrersClass() const { return is_referrers_class_; }
Nicolas Geoffray7d5ea032015-07-02 15:48:27 +01005050 bool CanBeNull() const OVERRIDE { return false; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005051
Nicolas Geoffray424f6762014-11-03 14:51:25 +00005052 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffray42e372e2015-11-24 15:48:56 +00005053 return CanCallRuntime();
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005054 }
5055
Nicolas Geoffray424f6762014-11-03 14:51:25 +00005056 bool MustGenerateClinitCheck() const {
5057 return generate_clinit_check_;
5058 }
Nicolas Geoffray42e372e2015-11-24 15:48:56 +00005059
Calin Juravle0ba218d2015-05-19 18:46:01 +01005060 void SetMustGenerateClinitCheck(bool generate_clinit_check) {
Nicolas Geoffrayd9309292015-10-31 22:21:31 +00005061 // The entrypoint the code generator is going to call does not do
5062 // clinit of the class.
5063 DCHECK(!NeedsAccessCheck());
Calin Juravle0ba218d2015-05-19 18:46:01 +01005064 generate_clinit_check_ = generate_clinit_check;
Nicolas Geoffray424f6762014-11-03 14:51:25 +00005065 }
5066
5067 bool CanCallRuntime() const {
Nicolas Geoffray42e372e2015-11-24 15:48:56 +00005068 return MustGenerateClinitCheck() ||
5069 (!is_referrers_class_ && !is_in_dex_cache_) ||
5070 needs_access_check_;
Calin Juravle98893e12015-10-02 21:05:03 +01005071 }
5072
5073 bool NeedsAccessCheck() const {
5074 return needs_access_check_;
Nicolas Geoffray424f6762014-11-03 14:51:25 +00005075 }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005076
Nicolas Geoffray82091da2015-01-26 10:02:45 +00005077 bool CanThrow() const OVERRIDE {
Nicolas Geoffray78f4fa72015-06-12 09:35:05 +01005078 return CanCallRuntime();
Nicolas Geoffray82091da2015-01-26 10:02:45 +00005079 }
5080
Calin Juravleacf735c2015-02-12 15:25:22 +00005081 ReferenceTypeInfo GetLoadedClassRTI() {
5082 return loaded_class_rti_;
5083 }
5084
5085 void SetLoadedClassRTI(ReferenceTypeInfo rti) {
5086 // Make sure we only set exact types (the loaded class should never be merged).
5087 DCHECK(rti.IsExact());
5088 loaded_class_rti_ = rti;
5089 }
5090
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01005091 const DexFile& GetDexFile() { return dex_file_; }
5092
Vladimir Markodc151b22015-10-15 18:02:30 +01005093 bool NeedsDexCacheOfDeclaringClass() const OVERRIDE { return !is_referrers_class_; }
Nicolas Geoffray9437b782015-03-25 10:08:51 +00005094
Alexandre Rames78e3ef62015-08-12 13:43:29 +01005095 static SideEffects SideEffectsForArchRuntimeCalls() {
5096 return SideEffects::CanTriggerGC();
5097 }
5098
Nicolas Geoffray42e372e2015-11-24 15:48:56 +00005099 bool IsInDexCache() const { return is_in_dex_cache_; }
5100
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005101 DECLARE_INSTRUCTION(LoadClass);
5102
5103 private:
5104 const uint16_t type_index_;
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01005105 const DexFile& dex_file_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005106 const bool is_referrers_class_;
Nicolas Geoffray424f6762014-11-03 14:51:25 +00005107 // Whether this instruction must generate the initialization check.
5108 // Used for code generation.
5109 bool generate_clinit_check_;
Nicolas Geoffray42e372e2015-11-24 15:48:56 +00005110 const bool needs_access_check_;
5111 const bool is_in_dex_cache_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005112
Calin Juravleacf735c2015-02-12 15:25:22 +00005113 ReferenceTypeInfo loaded_class_rti_;
5114
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005115 DISALLOW_COPY_AND_ASSIGN(HLoadClass);
5116};
5117
Nicolas Geoffrayfbdaa302015-05-29 12:06:56 +01005118class HLoadString : public HExpression<1> {
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00005119 public:
Nicolas Geoffray917d0162015-11-24 18:25:35 +00005120 HLoadString(HCurrentMethod* current_method,
5121 uint32_t string_index,
5122 uint32_t dex_pc,
5123 bool is_in_dex_cache)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005124 : HExpression(Primitive::kPrimNot, SideEffectsForArchRuntimeCalls(), dex_pc),
Nicolas Geoffray917d0162015-11-24 18:25:35 +00005125 string_index_(string_index),
5126 is_in_dex_cache_(is_in_dex_cache) {
Nicolas Geoffrayfbdaa302015-05-29 12:06:56 +01005127 SetRawInputAt(0, current_method);
5128 }
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00005129
Nicolas Geoffray424f6762014-11-03 14:51:25 +00005130 bool CanBeMoved() const OVERRIDE { return true; }
5131
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00005132 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
5133 return other->AsLoadString()->string_index_ == string_index_;
5134 }
5135
5136 size_t ComputeHashCode() const OVERRIDE { return string_index_; }
5137
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00005138 uint32_t GetStringIndex() const { return string_index_; }
5139
Nicolas Geoffray03196cf2016-02-01 12:23:22 +00005140 // Will call the runtime if the string is not already in the dex cache.
5141 bool NeedsEnvironment() const OVERRIDE { return !IsInDexCache(); }
5142
Vladimir Markodc151b22015-10-15 18:02:30 +01005143 bool NeedsDexCacheOfDeclaringClass() const OVERRIDE { return true; }
Nicolas Geoffraye418dda2015-08-11 20:03:09 -07005144 bool CanBeNull() const OVERRIDE { return false; }
Nicolas Geoffray917d0162015-11-24 18:25:35 +00005145 bool IsInDexCache() const { return is_in_dex_cache_; }
Nicolas Geoffray03196cf2016-02-01 12:23:22 +00005146 bool CanThrow() const OVERRIDE { return !IsInDexCache(); }
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00005147
Alexandre Rames78e3ef62015-08-12 13:43:29 +01005148 static SideEffects SideEffectsForArchRuntimeCalls() {
5149 return SideEffects::CanTriggerGC();
5150 }
5151
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00005152 DECLARE_INSTRUCTION(LoadString);
5153
5154 private:
5155 const uint32_t string_index_;
Nicolas Geoffray917d0162015-11-24 18:25:35 +00005156 const bool is_in_dex_cache_;
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00005157
5158 DISALLOW_COPY_AND_ASSIGN(HLoadString);
5159};
5160
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005161/**
5162 * Performs an initialization check on its Class object input.
5163 */
5164class HClinitCheck : public HExpression<1> {
5165 public:
Roland Levillain3887c462015-08-12 18:15:42 +01005166 HClinitCheck(HLoadClass* constant, uint32_t dex_pc)
Aart Bik854a02b2015-07-14 16:07:00 -07005167 : HExpression(
Alexandre Rames78e3ef62015-08-12 13:43:29 +01005168 Primitive::kPrimNot,
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005169 SideEffects::AllChanges(), // Assume write/read on all fields/arrays.
5170 dex_pc) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005171 SetRawInputAt(0, constant);
5172 }
5173
Nicolas Geoffray424f6762014-11-03 14:51:25 +00005174 bool CanBeMoved() const OVERRIDE { return true; }
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01005175 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
Nicolas Geoffray424f6762014-11-03 14:51:25 +00005176 return true;
5177 }
5178
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005179 bool NeedsEnvironment() const OVERRIDE {
5180 // May call runtime to initialize the class.
5181 return true;
5182 }
5183
Nicolas Geoffray729645a2015-11-19 13:29:02 +00005184 bool CanThrow() const OVERRIDE { return true; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005185
5186 HLoadClass* GetLoadClass() const { return InputAt(0)->AsLoadClass(); }
5187
5188 DECLARE_INSTRUCTION(ClinitCheck);
5189
5190 private:
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005191 DISALLOW_COPY_AND_ASSIGN(HClinitCheck);
5192};
5193
5194class HStaticFieldGet : public HExpression<1> {
5195 public:
5196 HStaticFieldGet(HInstruction* cls,
5197 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00005198 MemberOffset field_offset,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01005199 bool is_volatile,
5200 uint32_t field_idx,
Mingyao Yang8df69d42015-10-22 15:40:58 -07005201 uint16_t declaring_class_def_index,
Mathieu Chartier736b5602015-09-02 14:54:11 -07005202 const DexFile& dex_file,
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005203 Handle<mirror::DexCache> dex_cache,
Calin Juravle154746b2015-10-06 15:46:54 +01005204 uint32_t dex_pc)
Mingyao Yang8df69d42015-10-22 15:40:58 -07005205 : HExpression(field_type,
5206 SideEffects::FieldReadOfType(field_type, is_volatile),
5207 dex_pc),
5208 field_info_(field_offset,
5209 field_type,
5210 is_volatile,
5211 field_idx,
5212 declaring_class_def_index,
5213 dex_file,
5214 dex_cache) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005215 SetRawInputAt(0, cls);
5216 }
5217
Calin Juravle52c48962014-12-16 17:02:57 +00005218
Calin Juravle10c9cbe2014-12-19 10:50:19 +00005219 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); }
Calin Juravle52c48962014-12-16 17:02:57 +00005220
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005221 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Calin Juravle52c48962014-12-16 17:02:57 +00005222 HStaticFieldGet* other_get = other->AsStaticFieldGet();
5223 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005224 }
5225
5226 size_t ComputeHashCode() const OVERRIDE {
5227 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
5228 }
5229
Calin Juravle52c48962014-12-16 17:02:57 +00005230 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005231 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
5232 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00005233 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005234
5235 DECLARE_INSTRUCTION(StaticFieldGet);
5236
5237 private:
5238 const FieldInfo field_info_;
5239
5240 DISALLOW_COPY_AND_ASSIGN(HStaticFieldGet);
5241};
5242
5243class HStaticFieldSet : public HTemplateInstruction<2> {
5244 public:
5245 HStaticFieldSet(HInstruction* cls,
5246 HInstruction* value,
5247 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00005248 MemberOffset field_offset,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01005249 bool is_volatile,
5250 uint32_t field_idx,
Mingyao Yang8df69d42015-10-22 15:40:58 -07005251 uint16_t declaring_class_def_index,
Mathieu Chartier736b5602015-09-02 14:54:11 -07005252 const DexFile& dex_file,
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005253 Handle<mirror::DexCache> dex_cache,
Calin Juravle154746b2015-10-06 15:46:54 +01005254 uint32_t dex_pc)
Mingyao Yang8df69d42015-10-22 15:40:58 -07005255 : HTemplateInstruction(SideEffects::FieldWriteOfType(field_type, is_volatile),
5256 dex_pc),
5257 field_info_(field_offset,
5258 field_type,
5259 is_volatile,
5260 field_idx,
5261 declaring_class_def_index,
5262 dex_file,
5263 dex_cache),
Nicolas Geoffray07276db2015-05-18 14:22:09 +01005264 value_can_be_null_(true) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005265 SetRawInputAt(0, cls);
5266 SetRawInputAt(1, value);
5267 }
5268
Calin Juravle52c48962014-12-16 17:02:57 +00005269 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005270 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
5271 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00005272 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005273
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00005274 HInstruction* GetValue() const { return InputAt(1); }
Nicolas Geoffray07276db2015-05-18 14:22:09 +01005275 bool GetValueCanBeNull() const { return value_can_be_null_; }
5276 void ClearValueCanBeNull() { value_can_be_null_ = false; }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00005277
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005278 DECLARE_INSTRUCTION(StaticFieldSet);
5279
5280 private:
5281 const FieldInfo field_info_;
Nicolas Geoffray07276db2015-05-18 14:22:09 +01005282 bool value_can_be_null_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01005283
5284 DISALLOW_COPY_AND_ASSIGN(HStaticFieldSet);
5285};
5286
Calin Juravlee460d1d2015-09-29 04:52:17 +01005287class HUnresolvedInstanceFieldGet : public HExpression<1> {
5288 public:
5289 HUnresolvedInstanceFieldGet(HInstruction* obj,
5290 Primitive::Type field_type,
5291 uint32_t field_index,
5292 uint32_t dex_pc)
5293 : HExpression(field_type, SideEffects::AllExceptGCDependency(), dex_pc),
5294 field_index_(field_index) {
5295 SetRawInputAt(0, obj);
5296 }
5297
5298 bool NeedsEnvironment() const OVERRIDE { return true; }
5299 bool CanThrow() const OVERRIDE { return true; }
5300
5301 Primitive::Type GetFieldType() const { return GetType(); }
5302 uint32_t GetFieldIndex() const { return field_index_; }
5303
5304 DECLARE_INSTRUCTION(UnresolvedInstanceFieldGet);
5305
5306 private:
5307 const uint32_t field_index_;
5308
5309 DISALLOW_COPY_AND_ASSIGN(HUnresolvedInstanceFieldGet);
5310};
5311
5312class HUnresolvedInstanceFieldSet : public HTemplateInstruction<2> {
5313 public:
5314 HUnresolvedInstanceFieldSet(HInstruction* obj,
5315 HInstruction* value,
5316 Primitive::Type field_type,
5317 uint32_t field_index,
5318 uint32_t dex_pc)
5319 : HTemplateInstruction(SideEffects::AllExceptGCDependency(), dex_pc),
5320 field_type_(field_type),
5321 field_index_(field_index) {
5322 DCHECK_EQ(field_type, value->GetType());
5323 SetRawInputAt(0, obj);
5324 SetRawInputAt(1, value);
5325 }
5326
5327 bool NeedsEnvironment() const OVERRIDE { return true; }
5328 bool CanThrow() const OVERRIDE { return true; }
5329
5330 Primitive::Type GetFieldType() const { return field_type_; }
5331 uint32_t GetFieldIndex() const { return field_index_; }
5332
5333 DECLARE_INSTRUCTION(UnresolvedInstanceFieldSet);
5334
5335 private:
5336 const Primitive::Type field_type_;
5337 const uint32_t field_index_;
5338
5339 DISALLOW_COPY_AND_ASSIGN(HUnresolvedInstanceFieldSet);
5340};
5341
5342class HUnresolvedStaticFieldGet : public HExpression<0> {
5343 public:
5344 HUnresolvedStaticFieldGet(Primitive::Type field_type,
5345 uint32_t field_index,
5346 uint32_t dex_pc)
5347 : HExpression(field_type, SideEffects::AllExceptGCDependency(), dex_pc),
5348 field_index_(field_index) {
5349 }
5350
5351 bool NeedsEnvironment() const OVERRIDE { return true; }
5352 bool CanThrow() const OVERRIDE { return true; }
5353
5354 Primitive::Type GetFieldType() const { return GetType(); }
5355 uint32_t GetFieldIndex() const { return field_index_; }
5356
5357 DECLARE_INSTRUCTION(UnresolvedStaticFieldGet);
5358
5359 private:
5360 const uint32_t field_index_;
5361
5362 DISALLOW_COPY_AND_ASSIGN(HUnresolvedStaticFieldGet);
5363};
5364
5365class HUnresolvedStaticFieldSet : public HTemplateInstruction<1> {
5366 public:
5367 HUnresolvedStaticFieldSet(HInstruction* value,
5368 Primitive::Type field_type,
5369 uint32_t field_index,
5370 uint32_t dex_pc)
5371 : HTemplateInstruction(SideEffects::AllExceptGCDependency(), dex_pc),
5372 field_type_(field_type),
5373 field_index_(field_index) {
5374 DCHECK_EQ(field_type, value->GetType());
5375 SetRawInputAt(0, value);
5376 }
5377
5378 bool NeedsEnvironment() const OVERRIDE { return true; }
5379 bool CanThrow() const OVERRIDE { return true; }
5380
5381 Primitive::Type GetFieldType() const { return field_type_; }
5382 uint32_t GetFieldIndex() const { return field_index_; }
5383
5384 DECLARE_INSTRUCTION(UnresolvedStaticFieldSet);
5385
5386 private:
5387 const Primitive::Type field_type_;
5388 const uint32_t field_index_;
5389
5390 DISALLOW_COPY_AND_ASSIGN(HUnresolvedStaticFieldSet);
5391};
5392
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00005393// Implement the move-exception DEX instruction.
5394class HLoadException : public HExpression<0> {
5395 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005396 explicit HLoadException(uint32_t dex_pc = kNoDexPc)
5397 : HExpression(Primitive::kPrimNot, SideEffects::None(), dex_pc) {}
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00005398
David Brazdilbbd733e2015-08-18 17:48:17 +01005399 bool CanBeNull() const OVERRIDE { return false; }
5400
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00005401 DECLARE_INSTRUCTION(LoadException);
5402
5403 private:
5404 DISALLOW_COPY_AND_ASSIGN(HLoadException);
5405};
5406
David Brazdilcb1c0552015-08-04 16:22:25 +01005407// Implicit part of move-exception which clears thread-local exception storage.
5408// Must not be removed because the runtime expects the TLS to get cleared.
5409class HClearException : public HTemplateInstruction<0> {
5410 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005411 explicit HClearException(uint32_t dex_pc = kNoDexPc)
5412 : HTemplateInstruction(SideEffects::AllWrites(), dex_pc) {}
David Brazdilcb1c0552015-08-04 16:22:25 +01005413
5414 DECLARE_INSTRUCTION(ClearException);
5415
5416 private:
5417 DISALLOW_COPY_AND_ASSIGN(HClearException);
5418};
5419
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00005420class HThrow : public HTemplateInstruction<1> {
5421 public:
5422 HThrow(HInstruction* exception, uint32_t dex_pc)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005423 : HTemplateInstruction(SideEffects::CanTriggerGC(), dex_pc) {
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00005424 SetRawInputAt(0, exception);
5425 }
5426
5427 bool IsControlFlow() const OVERRIDE { return true; }
5428
5429 bool NeedsEnvironment() const OVERRIDE { return true; }
5430
Nicolas Geoffray82091da2015-01-26 10:02:45 +00005431 bool CanThrow() const OVERRIDE { return true; }
5432
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00005433
5434 DECLARE_INSTRUCTION(Throw);
5435
5436 private:
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00005437 DISALLOW_COPY_AND_ASSIGN(HThrow);
5438};
5439
Nicolas Geoffray85c7bab2015-09-18 13:40:46 +00005440/**
5441 * Implementation strategies for the code generator of a HInstanceOf
5442 * or `HCheckCast`.
5443 */
5444enum class TypeCheckKind {
Calin Juravle98893e12015-10-02 21:05:03 +01005445 kUnresolvedCheck, // Check against an unresolved type.
Nicolas Geoffray85c7bab2015-09-18 13:40:46 +00005446 kExactCheck, // Can do a single class compare.
5447 kClassHierarchyCheck, // Can just walk the super class chain.
5448 kAbstractClassCheck, // Can just walk the super class chain, starting one up.
5449 kInterfaceCheck, // No optimization yet when checking against an interface.
5450 kArrayObjectCheck, // Can just check if the array is not primitive.
5451 kArrayCheck // No optimization yet when checking against a generic array.
5452};
5453
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00005454class HInstanceOf : public HExpression<2> {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00005455 public:
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00005456 HInstanceOf(HInstruction* object,
5457 HLoadClass* constant,
Nicolas Geoffray85c7bab2015-09-18 13:40:46 +00005458 TypeCheckKind check_kind,
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00005459 uint32_t dex_pc)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005460 : HExpression(Primitive::kPrimBoolean,
Nicolas Geoffray85c7bab2015-09-18 13:40:46 +00005461 SideEffectsForArchRuntimeCalls(check_kind),
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005462 dex_pc),
Nicolas Geoffray85c7bab2015-09-18 13:40:46 +00005463 check_kind_(check_kind),
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005464 must_do_null_check_(true) {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00005465 SetRawInputAt(0, object);
5466 SetRawInputAt(1, constant);
5467 }
5468
5469 bool CanBeMoved() const OVERRIDE { return true; }
5470
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00005471 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00005472 return true;
5473 }
5474
5475 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffray03196cf2016-02-01 12:23:22 +00005476 return CanCallRuntime(check_kind_);
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00005477 }
5478
Nicolas Geoffray85c7bab2015-09-18 13:40:46 +00005479 bool IsExactCheck() const { return check_kind_ == TypeCheckKind::kExactCheck; }
5480
5481 TypeCheckKind GetTypeCheckKind() const { return check_kind_; }
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00005482
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01005483 // Used only in code generation.
5484 bool MustDoNullCheck() const { return must_do_null_check_; }
5485 void ClearMustDoNullCheck() { must_do_null_check_ = false; }
5486
Nicolas Geoffray03196cf2016-02-01 12:23:22 +00005487 static bool CanCallRuntime(TypeCheckKind check_kind) {
5488 // Mips currently does runtime calls for any other checks.
5489 return check_kind != TypeCheckKind::kExactCheck;
5490 }
5491
Nicolas Geoffray85c7bab2015-09-18 13:40:46 +00005492 static SideEffects SideEffectsForArchRuntimeCalls(TypeCheckKind check_kind) {
Nicolas Geoffray03196cf2016-02-01 12:23:22 +00005493 return CanCallRuntime(check_kind) ? SideEffects::CanTriggerGC() : SideEffects::None();
Alexandre Rames78e3ef62015-08-12 13:43:29 +01005494 }
5495
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00005496 DECLARE_INSTRUCTION(InstanceOf);
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00005497
5498 private:
Nicolas Geoffray85c7bab2015-09-18 13:40:46 +00005499 const TypeCheckKind check_kind_;
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01005500 bool must_do_null_check_;
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00005501
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00005502 DISALLOW_COPY_AND_ASSIGN(HInstanceOf);
5503};
5504
Calin Juravleb1498f62015-02-16 13:13:29 +00005505class HBoundType : public HExpression<1> {
5506 public:
David Brazdilf5552582015-12-27 13:36:12 +00005507 HBoundType(HInstruction* input, uint32_t dex_pc = kNoDexPc)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005508 : HExpression(Primitive::kPrimNot, SideEffects::None(), dex_pc),
David Brazdilf5552582015-12-27 13:36:12 +00005509 upper_bound_(ReferenceTypeInfo::CreateInvalid()),
5510 upper_can_be_null_(true),
5511 can_be_null_(true) {
Calin Juravle61d544b2015-02-23 16:46:57 +00005512 DCHECK_EQ(input->GetType(), Primitive::kPrimNot);
Calin Juravleb1498f62015-02-16 13:13:29 +00005513 SetRawInputAt(0, input);
5514 }
5515
David Brazdilf5552582015-12-27 13:36:12 +00005516 // {Get,Set}Upper* should only be used in reference type propagation.
Calin Juravlea5ae3c32015-07-28 14:40:50 +00005517 const ReferenceTypeInfo& GetUpperBound() const { return upper_bound_; }
5518 bool GetUpperCanBeNull() const { return upper_can_be_null_; }
David Brazdilf5552582015-12-27 13:36:12 +00005519 void SetUpperBound(const ReferenceTypeInfo& upper_bound, bool can_be_null);
Calin Juravleb1498f62015-02-16 13:13:29 +00005520
Calin Juravlea5ae3c32015-07-28 14:40:50 +00005521 void SetCanBeNull(bool can_be_null) {
5522 DCHECK(upper_can_be_null_ || !can_be_null);
5523 can_be_null_ = can_be_null;
Calin Juravleb1498f62015-02-16 13:13:29 +00005524 }
5525
Calin Juravlea5ae3c32015-07-28 14:40:50 +00005526 bool CanBeNull() const OVERRIDE { return can_be_null_; }
5527
Calin Juravleb1498f62015-02-16 13:13:29 +00005528 DECLARE_INSTRUCTION(BoundType);
5529
5530 private:
5531 // Encodes the most upper class that this instruction can have. In other words
Calin Juravlea5ae3c32015-07-28 14:40:50 +00005532 // it is always the case that GetUpperBound().IsSupertypeOf(GetReferenceType()).
5533 // It is used to bound the type in cases like:
5534 // if (x instanceof ClassX) {
5535 // // uper_bound_ will be ClassX
5536 // }
David Brazdilf5552582015-12-27 13:36:12 +00005537 ReferenceTypeInfo upper_bound_;
Calin Juravlea5ae3c32015-07-28 14:40:50 +00005538 // Represents the top constraint that can_be_null_ cannot exceed (i.e. if this
5539 // is false then can_be_null_ cannot be true).
David Brazdilf5552582015-12-27 13:36:12 +00005540 bool upper_can_be_null_;
Calin Juravlea5ae3c32015-07-28 14:40:50 +00005541 bool can_be_null_;
Calin Juravleb1498f62015-02-16 13:13:29 +00005542
5543 DISALLOW_COPY_AND_ASSIGN(HBoundType);
5544};
5545
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00005546class HCheckCast : public HTemplateInstruction<2> {
5547 public:
5548 HCheckCast(HInstruction* object,
5549 HLoadClass* constant,
Nicolas Geoffray85c7bab2015-09-18 13:40:46 +00005550 TypeCheckKind check_kind,
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00005551 uint32_t dex_pc)
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005552 : HTemplateInstruction(SideEffects::CanTriggerGC(), dex_pc),
Nicolas Geoffray85c7bab2015-09-18 13:40:46 +00005553 check_kind_(check_kind),
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005554 must_do_null_check_(true) {
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00005555 SetRawInputAt(0, object);
5556 SetRawInputAt(1, constant);
5557 }
5558
5559 bool CanBeMoved() const OVERRIDE { return true; }
5560
5561 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
5562 return true;
5563 }
5564
5565 bool NeedsEnvironment() const OVERRIDE {
5566 // Instruction may throw a CheckCastError.
5567 return true;
5568 }
5569
5570 bool CanThrow() const OVERRIDE { return true; }
5571
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01005572 bool MustDoNullCheck() const { return must_do_null_check_; }
5573 void ClearMustDoNullCheck() { must_do_null_check_ = false; }
Nicolas Geoffray85c7bab2015-09-18 13:40:46 +00005574 TypeCheckKind GetTypeCheckKind() const { return check_kind_; }
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01005575
Nicolas Geoffray85c7bab2015-09-18 13:40:46 +00005576 bool IsExactCheck() const { return check_kind_ == TypeCheckKind::kExactCheck; }
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00005577
5578 DECLARE_INSTRUCTION(CheckCast);
5579
5580 private:
Nicolas Geoffray85c7bab2015-09-18 13:40:46 +00005581 const TypeCheckKind check_kind_;
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01005582 bool must_do_null_check_;
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00005583
5584 DISALLOW_COPY_AND_ASSIGN(HCheckCast);
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00005585};
5586
Calin Juravle27df7582015-04-17 19:12:31 +01005587class HMemoryBarrier : public HTemplateInstruction<0> {
5588 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005589 explicit HMemoryBarrier(MemBarrierKind barrier_kind, uint32_t dex_pc = kNoDexPc)
Aart Bik34c3ba92015-07-20 14:08:59 -07005590 : HTemplateInstruction(
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005591 SideEffects::AllWritesAndReads(), dex_pc), // Assume write/read on all fields/arrays.
Calin Juravle27df7582015-04-17 19:12:31 +01005592 barrier_kind_(barrier_kind) {}
5593
5594 MemBarrierKind GetBarrierKind() { return barrier_kind_; }
5595
5596 DECLARE_INSTRUCTION(MemoryBarrier);
5597
5598 private:
5599 const MemBarrierKind barrier_kind_;
5600
5601 DISALLOW_COPY_AND_ASSIGN(HMemoryBarrier);
5602};
5603
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00005604class HMonitorOperation : public HTemplateInstruction<1> {
5605 public:
5606 enum OperationKind {
5607 kEnter,
5608 kExit,
5609 };
5610
5611 HMonitorOperation(HInstruction* object, OperationKind kind, uint32_t dex_pc)
Alexandre Rames78e3ef62015-08-12 13:43:29 +01005612 : HTemplateInstruction(
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005613 SideEffects::AllExceptGCDependency(), dex_pc), // Assume write/read on all fields/arrays.
5614 kind_(kind) {
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00005615 SetRawInputAt(0, object);
5616 }
5617
Nicolas Geoffray03196cf2016-02-01 12:23:22 +00005618 // Instruction may go into runtime, so we need an environment.
5619 bool NeedsEnvironment() const OVERRIDE { return true; }
David Brazdilbff75032015-07-08 17:26:51 +00005620
5621 bool CanThrow() const OVERRIDE {
5622 // Verifier guarantees that monitor-exit cannot throw.
5623 // This is important because it allows the HGraphBuilder to remove
5624 // a dead throw-catch loop generated for `synchronized` blocks/methods.
5625 return IsEnter();
5626 }
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00005627
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00005628
5629 bool IsEnter() const { return kind_ == kEnter; }
5630
5631 DECLARE_INSTRUCTION(MonitorOperation);
5632
Calin Juravle52c48962014-12-16 17:02:57 +00005633 private:
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00005634 const OperationKind kind_;
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00005635
5636 private:
5637 DISALLOW_COPY_AND_ASSIGN(HMonitorOperation);
5638};
5639
David Brazdil74eb1b22015-12-14 11:44:01 +00005640class HSelect : public HExpression<3> {
5641 public:
5642 HSelect(HInstruction* condition,
5643 HInstruction* true_value,
5644 HInstruction* false_value,
5645 uint32_t dex_pc)
5646 : HExpression(HPhi::ToPhiType(true_value->GetType()), SideEffects::None(), dex_pc) {
5647 DCHECK_EQ(HPhi::ToPhiType(true_value->GetType()), HPhi::ToPhiType(false_value->GetType()));
5648
5649 // First input must be `true_value` or `false_value` to allow codegens to
5650 // use the SameAsFirstInput allocation policy. We make it `false_value`, so
5651 // that architectures which implement HSelect as a conditional move also
5652 // will not need to invert the condition.
5653 SetRawInputAt(0, false_value);
5654 SetRawInputAt(1, true_value);
5655 SetRawInputAt(2, condition);
5656 }
5657
5658 HInstruction* GetFalseValue() const { return InputAt(0); }
5659 HInstruction* GetTrueValue() const { return InputAt(1); }
5660 HInstruction* GetCondition() const { return InputAt(2); }
5661
5662 bool CanBeMoved() const OVERRIDE { return true; }
5663 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { return true; }
5664
5665 bool CanBeNull() const OVERRIDE {
5666 return GetTrueValue()->CanBeNull() || GetFalseValue()->CanBeNull();
5667 }
5668
5669 DECLARE_INSTRUCTION(Select);
5670
5671 private:
5672 DISALLOW_COPY_AND_ASSIGN(HSelect);
5673};
5674
Vladimir Markof9f64412015-09-02 14:05:49 +01005675class MoveOperands : public ArenaObject<kArenaAllocMoveOperands> {
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01005676 public:
Nicolas Geoffray90218252015-04-15 11:56:51 +01005677 MoveOperands(Location source,
5678 Location destination,
5679 Primitive::Type type,
5680 HInstruction* instruction)
5681 : source_(source), destination_(destination), type_(type), instruction_(instruction) {}
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01005682
5683 Location GetSource() const { return source_; }
5684 Location GetDestination() const { return destination_; }
5685
5686 void SetSource(Location value) { source_ = value; }
5687 void SetDestination(Location value) { destination_ = value; }
5688
5689 // The parallel move resolver marks moves as "in-progress" by clearing the
5690 // destination (but not the source).
5691 Location MarkPending() {
5692 DCHECK(!IsPending());
5693 Location dest = destination_;
5694 destination_ = Location::NoLocation();
5695 return dest;
5696 }
5697
5698 void ClearPending(Location dest) {
5699 DCHECK(IsPending());
5700 destination_ = dest;
5701 }
5702
5703 bool IsPending() const {
Roland Levillainc9285912015-12-18 10:38:42 +00005704 DCHECK(source_.IsValid() || destination_.IsInvalid());
5705 return destination_.IsInvalid() && source_.IsValid();
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01005706 }
5707
5708 // True if this blocks a move from the given location.
5709 bool Blocks(Location loc) const {
Zheng Xuad4450e2015-04-17 18:48:56 +08005710 return !IsEliminated() && source_.OverlapsWith(loc);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01005711 }
5712
5713 // A move is redundant if it's been eliminated, if its source and
5714 // destination are the same, or if its destination is unneeded.
5715 bool IsRedundant() const {
5716 return IsEliminated() || destination_.IsInvalid() || source_.Equals(destination_);
5717 }
5718
5719 // We clear both operands to indicate move that's been eliminated.
5720 void Eliminate() {
5721 source_ = destination_ = Location::NoLocation();
5722 }
5723
5724 bool IsEliminated() const {
5725 DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
5726 return source_.IsInvalid();
5727 }
5728
Alexey Frunze4dda3372015-06-01 18:31:49 -07005729 Primitive::Type GetType() const { return type_; }
5730
Nicolas Geoffray90218252015-04-15 11:56:51 +01005731 bool Is64BitMove() const {
5732 return Primitive::Is64BitType(type_);
5733 }
5734
Nicolas Geoffray740475d2014-09-29 10:33:25 +01005735 HInstruction* GetInstruction() const { return instruction_; }
5736
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01005737 private:
5738 Location source_;
5739 Location destination_;
Nicolas Geoffray90218252015-04-15 11:56:51 +01005740 // The type this move is for.
5741 Primitive::Type type_;
Nicolas Geoffray740475d2014-09-29 10:33:25 +01005742 // The instruction this move is assocatied with. Null when this move is
5743 // for moving an input in the expected locations of user (including a phi user).
5744 // This is only used in debug mode, to ensure we do not connect interval siblings
5745 // in the same parallel move.
5746 HInstruction* instruction_;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01005747};
5748
Roland Levillainc9285912015-12-18 10:38:42 +00005749std::ostream& operator<<(std::ostream& os, const MoveOperands& rhs);
5750
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01005751static constexpr size_t kDefaultNumberOfMoves = 4;
5752
5753class HParallelMove : public HTemplateInstruction<0> {
5754 public:
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06005755 explicit HParallelMove(ArenaAllocator* arena, uint32_t dex_pc = kNoDexPc)
Vladimir Marko225b6462015-09-28 12:17:40 +01005756 : HTemplateInstruction(SideEffects::None(), dex_pc),
5757 moves_(arena->Adapter(kArenaAllocMoveOperands)) {
5758 moves_.reserve(kDefaultNumberOfMoves);
5759 }
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01005760
Nicolas Geoffray90218252015-04-15 11:56:51 +01005761 void AddMove(Location source,
5762 Location destination,
5763 Primitive::Type type,
5764 HInstruction* instruction) {
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +00005765 DCHECK(source.IsValid());
5766 DCHECK(destination.IsValid());
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00005767 if (kIsDebugBuild) {
5768 if (instruction != nullptr) {
Vladimir Marko225b6462015-09-28 12:17:40 +01005769 for (const MoveOperands& move : moves_) {
5770 if (move.GetInstruction() == instruction) {
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00005771 // Special case the situation where the move is for the spill slot
5772 // of the instruction.
5773 if ((GetPrevious() == instruction)
5774 || ((GetPrevious() == nullptr)
5775 && instruction->IsPhi()
5776 && instruction->GetBlock() == GetBlock())) {
Vladimir Marko225b6462015-09-28 12:17:40 +01005777 DCHECK_NE(destination.GetKind(), move.GetDestination().GetKind())
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00005778 << "Doing parallel moves for the same instruction.";
5779 } else {
5780 DCHECK(false) << "Doing parallel moves for the same instruction.";
5781 }
5782 }
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00005783 }
5784 }
Vladimir Marko225b6462015-09-28 12:17:40 +01005785 for (const MoveOperands& move : moves_) {
5786 DCHECK(!destination.OverlapsWith(move.GetDestination()))
Guillaume "Vermeille" Sanchez8909baf2015-04-23 21:35:11 +01005787 << "Overlapped destination for two moves in a parallel move: "
Vladimir Marko225b6462015-09-28 12:17:40 +01005788 << move.GetSource() << " ==> " << move.GetDestination() << " and "
Guillaume "Vermeille" Sanchez8909baf2015-04-23 21:35:11 +01005789 << source << " ==> " << destination;
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00005790 }
Nicolas Geoffray740475d2014-09-29 10:33:25 +01005791 }
Vladimir Marko225b6462015-09-28 12:17:40 +01005792 moves_.emplace_back(source, destination, type, instruction);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01005793 }
5794
Vladimir Marko225b6462015-09-28 12:17:40 +01005795 MoveOperands* MoveOperandsAt(size_t index) {
Vladimir Marko225b6462015-09-28 12:17:40 +01005796 return &moves_[index];
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01005797 }
5798
Vladimir Marko225b6462015-09-28 12:17:40 +01005799 size_t NumMoves() const { return moves_.size(); }
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01005800
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01005801 DECLARE_INSTRUCTION(ParallelMove);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01005802
5803 private:
Vladimir Marko225b6462015-09-28 12:17:40 +01005804 ArenaVector<MoveOperands> moves_;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01005805
5806 DISALLOW_COPY_AND_ASSIGN(HParallelMove);
5807};
5808
Mark Mendell0616ae02015-04-17 12:49:27 -04005809} // namespace art
5810
Vladimir Markob4536b72015-11-24 13:45:23 +00005811#ifdef ART_ENABLE_CODEGEN_arm
5812#include "nodes_arm.h"
5813#endif
Alexandre Ramese6dbf482015-10-19 10:10:41 +01005814#ifdef ART_ENABLE_CODEGEN_arm64
5815#include "nodes_arm64.h"
5816#endif
Mark Mendell0616ae02015-04-17 12:49:27 -04005817#ifdef ART_ENABLE_CODEGEN_x86
5818#include "nodes_x86.h"
5819#endif
5820
5821namespace art {
5822
Nicolas Geoffray818f2102014-02-18 16:43:35 +00005823class HGraphVisitor : public ValueObject {
5824 public:
Dave Allison20dfc792014-06-16 20:44:29 -07005825 explicit HGraphVisitor(HGraph* graph) : graph_(graph) {}
5826 virtual ~HGraphVisitor() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00005827
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01005828 virtual void VisitInstruction(HInstruction* instruction ATTRIBUTE_UNUSED) {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00005829 virtual void VisitBasicBlock(HBasicBlock* block);
5830
Roland Levillain633021e2014-10-01 14:12:25 +01005831 // Visit the graph following basic block insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +00005832 void VisitInsertionOrder();
5833
Roland Levillain633021e2014-10-01 14:12:25 +01005834 // Visit the graph following dominator tree reverse post-order.
5835 void VisitReversePostOrder();
5836
Nicolas Geoffray787c3072014-03-17 10:20:19 +00005837 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00005838
Nicolas Geoffray818f2102014-02-18 16:43:35 +00005839 // Visit functions for instruction classes.
Nicolas Geoffray360231a2014-10-08 21:07:48 +01005840#define DECLARE_VISIT_INSTRUCTION(name, super) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +00005841 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
5842
5843 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
5844
5845#undef DECLARE_VISIT_INSTRUCTION
5846
5847 private:
Ian Rogerscf7f1912014-10-22 22:06:39 -07005848 HGraph* const graph_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00005849
5850 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
5851};
5852
Nicolas Geoffray360231a2014-10-08 21:07:48 +01005853class HGraphDelegateVisitor : public HGraphVisitor {
5854 public:
5855 explicit HGraphDelegateVisitor(HGraph* graph) : HGraphVisitor(graph) {}
5856 virtual ~HGraphDelegateVisitor() {}
5857
5858 // Visit functions that delegate to to super class.
5859#define DECLARE_VISIT_INSTRUCTION(name, super) \
Alexandre Rames2ed20af2015-03-06 13:55:35 +00005860 void Visit##name(H##name* instr) OVERRIDE { Visit##super(instr); }
Nicolas Geoffray360231a2014-10-08 21:07:48 +01005861
5862 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
5863
5864#undef DECLARE_VISIT_INSTRUCTION
5865
5866 private:
5867 DISALLOW_COPY_AND_ASSIGN(HGraphDelegateVisitor);
5868};
5869
Nicolas Geoffray804d0932014-05-02 08:46:00 +01005870class HInsertionOrderIterator : public ValueObject {
5871 public:
5872 explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
5873
Vladimir Markofa6b93c2015-09-15 10:15:55 +01005874 bool Done() const { return index_ == graph_.GetBlocks().size(); }
Vladimir Markoec7802a2015-10-01 20:57:57 +01005875 HBasicBlock* Current() const { return graph_.GetBlocks()[index_]; }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01005876 void Advance() { ++index_; }
5877
5878 private:
5879 const HGraph& graph_;
5880 size_t index_;
5881
5882 DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator);
5883};
5884
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01005885class HReversePostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01005886 public:
David Brazdil10f56cb2015-03-24 18:49:14 +00005887 explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {
5888 // Check that reverse post order of the graph has been built.
Vladimir Markofa6b93c2015-09-15 10:15:55 +01005889 DCHECK(!graph.GetReversePostOrder().empty());
David Brazdil10f56cb2015-03-24 18:49:14 +00005890 }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01005891
Vladimir Markofa6b93c2015-09-15 10:15:55 +01005892 bool Done() const { return index_ == graph_.GetReversePostOrder().size(); }
5893 HBasicBlock* Current() const { return graph_.GetReversePostOrder()[index_]; }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01005894 void Advance() { ++index_; }
5895
5896 private:
5897 const HGraph& graph_;
5898 size_t index_;
5899
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01005900 DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01005901};
5902
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01005903class HPostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01005904 public:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01005905 explicit HPostOrderIterator(const HGraph& graph)
Vladimir Markofa6b93c2015-09-15 10:15:55 +01005906 : graph_(graph), index_(graph_.GetReversePostOrder().size()) {
David Brazdil10f56cb2015-03-24 18:49:14 +00005907 // Check that reverse post order of the graph has been built.
Vladimir Markofa6b93c2015-09-15 10:15:55 +01005908 DCHECK(!graph.GetReversePostOrder().empty());
David Brazdil10f56cb2015-03-24 18:49:14 +00005909 }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01005910
5911 bool Done() const { return index_ == 0; }
Vladimir Markofa6b93c2015-09-15 10:15:55 +01005912 HBasicBlock* Current() const { return graph_.GetReversePostOrder()[index_ - 1u]; }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01005913 void Advance() { --index_; }
5914
5915 private:
5916 const HGraph& graph_;
5917 size_t index_;
5918
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01005919 DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01005920};
5921
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +01005922class HLinearPostOrderIterator : public ValueObject {
5923 public:
5924 explicit HLinearPostOrderIterator(const HGraph& graph)
Vladimir Markofa6b93c2015-09-15 10:15:55 +01005925 : order_(graph.GetLinearOrder()), index_(graph.GetLinearOrder().size()) {}
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +01005926
5927 bool Done() const { return index_ == 0; }
5928
Vladimir Markofa6b93c2015-09-15 10:15:55 +01005929 HBasicBlock* Current() const { return order_[index_ - 1u]; }
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +01005930
5931 void Advance() {
5932 --index_;
5933 DCHECK_GE(index_, 0U);
5934 }
5935
5936 private:
Vladimir Markofa6b93c2015-09-15 10:15:55 +01005937 const ArenaVector<HBasicBlock*>& order_;
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +01005938 size_t index_;
5939
5940 DISALLOW_COPY_AND_ASSIGN(HLinearPostOrderIterator);
5941};
5942
5943class HLinearOrderIterator : public ValueObject {
5944 public:
5945 explicit HLinearOrderIterator(const HGraph& graph)
5946 : order_(graph.GetLinearOrder()), index_(0) {}
5947
Vladimir Markofa6b93c2015-09-15 10:15:55 +01005948 bool Done() const { return index_ == order_.size(); }
5949 HBasicBlock* Current() const { return order_[index_]; }
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +01005950 void Advance() { ++index_; }
5951
5952 private:
Vladimir Markofa6b93c2015-09-15 10:15:55 +01005953 const ArenaVector<HBasicBlock*>& order_;
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +01005954 size_t index_;
5955
5956 DISALLOW_COPY_AND_ASSIGN(HLinearOrderIterator);
5957};
5958
Nicolas Geoffray82091da2015-01-26 10:02:45 +00005959// Iterator over the blocks that art part of the loop. Includes blocks part
5960// of an inner loop. The order in which the blocks are iterated is on their
5961// block id.
5962class HBlocksInLoopIterator : public ValueObject {
5963 public:
5964 explicit HBlocksInLoopIterator(const HLoopInformation& info)
5965 : blocks_in_loop_(info.GetBlocks()),
5966 blocks_(info.GetHeader()->GetGraph()->GetBlocks()),
5967 index_(0) {
5968 if (!blocks_in_loop_.IsBitSet(index_)) {
5969 Advance();
5970 }
5971 }
5972
Vladimir Markofa6b93c2015-09-15 10:15:55 +01005973 bool Done() const { return index_ == blocks_.size(); }
5974 HBasicBlock* Current() const { return blocks_[index_]; }
Nicolas Geoffray82091da2015-01-26 10:02:45 +00005975 void Advance() {
5976 ++index_;
Vladimir Markofa6b93c2015-09-15 10:15:55 +01005977 for (size_t e = blocks_.size(); index_ < e; ++index_) {
Nicolas Geoffray82091da2015-01-26 10:02:45 +00005978 if (blocks_in_loop_.IsBitSet(index_)) {
5979 break;
5980 }
5981 }
5982 }
5983
5984 private:
5985 const BitVector& blocks_in_loop_;
Vladimir Markofa6b93c2015-09-15 10:15:55 +01005986 const ArenaVector<HBasicBlock*>& blocks_;
Nicolas Geoffray82091da2015-01-26 10:02:45 +00005987 size_t index_;
5988
5989 DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopIterator);
5990};
5991
Mingyao Yang3584bce2015-05-19 16:01:59 -07005992// Iterator over the blocks that art part of the loop. Includes blocks part
5993// of an inner loop. The order in which the blocks are iterated is reverse
5994// post order.
5995class HBlocksInLoopReversePostOrderIterator : public ValueObject {
5996 public:
5997 explicit HBlocksInLoopReversePostOrderIterator(const HLoopInformation& info)
5998 : blocks_in_loop_(info.GetBlocks()),
5999 blocks_(info.GetHeader()->GetGraph()->GetReversePostOrder()),
6000 index_(0) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +01006001 if (!blocks_in_loop_.IsBitSet(blocks_[index_]->GetBlockId())) {
Mingyao Yang3584bce2015-05-19 16:01:59 -07006002 Advance();
6003 }
6004 }
6005
Vladimir Markofa6b93c2015-09-15 10:15:55 +01006006 bool Done() const { return index_ == blocks_.size(); }
6007 HBasicBlock* Current() const { return blocks_[index_]; }
Mingyao Yang3584bce2015-05-19 16:01:59 -07006008 void Advance() {
6009 ++index_;
Vladimir Markofa6b93c2015-09-15 10:15:55 +01006010 for (size_t e = blocks_.size(); index_ < e; ++index_) {
6011 if (blocks_in_loop_.IsBitSet(blocks_[index_]->GetBlockId())) {
Mingyao Yang3584bce2015-05-19 16:01:59 -07006012 break;
6013 }
6014 }
6015 }
6016
6017 private:
6018 const BitVector& blocks_in_loop_;
Vladimir Markofa6b93c2015-09-15 10:15:55 +01006019 const ArenaVector<HBasicBlock*>& blocks_;
Mingyao Yang3584bce2015-05-19 16:01:59 -07006020 size_t index_;
6021
6022 DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopReversePostOrderIterator);
6023};
6024
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00006025inline int64_t Int64FromConstant(HConstant* constant) {
6026 DCHECK(constant->IsIntConstant() || constant->IsLongConstant());
6027 return constant->IsIntConstant() ? constant->AsIntConstant()->GetValue()
6028 : constant->AsLongConstant()->GetValue();
6029}
6030
Vladimir Marko58155012015-08-19 12:49:41 +00006031inline bool IsSameDexFile(const DexFile& lhs, const DexFile& rhs) {
6032 // For the purposes of the compiler, the dex files must actually be the same object
6033 // if we want to safely treat them as the same. This is especially important for JIT
6034 // as custom class loaders can open the same underlying file (or memory) multiple
6035 // times and provide different class resolution but no two class loaders should ever
6036 // use the same DexFile object - doing so is an unsupported hack that can lead to
6037 // all sorts of weird failures.
6038 return &lhs == &rhs;
6039}
6040
Vladimir Marko5f7b58e2015-11-23 19:49:34 +00006041#define INSTRUCTION_TYPE_CHECK(type, super) \
6042 inline bool HInstruction::Is##type() const { return GetKind() == k##type; } \
6043 inline const H##type* HInstruction::As##type() const { \
6044 return Is##type() ? down_cast<const H##type*>(this) : nullptr; \
6045 } \
6046 inline H##type* HInstruction::As##type() { \
6047 return Is##type() ? static_cast<H##type*>(this) : nullptr; \
6048 }
6049
6050 FOR_EACH_CONCRETE_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
6051#undef INSTRUCTION_TYPE_CHECK
6052
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +00006053class SwitchTable : public ValueObject {
6054 public:
6055 SwitchTable(const Instruction& instruction, uint32_t dex_pc, bool sparse)
6056 : instruction_(instruction), dex_pc_(dex_pc), sparse_(sparse) {
6057 int32_t table_offset = instruction.VRegB_31t();
6058 const uint16_t* table = reinterpret_cast<const uint16_t*>(&instruction) + table_offset;
6059 if (sparse) {
6060 CHECK_EQ(table[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature));
6061 } else {
6062 CHECK_EQ(table[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature));
6063 }
6064 num_entries_ = table[1];
6065 values_ = reinterpret_cast<const int32_t*>(&table[2]);
6066 }
6067
6068 uint16_t GetNumEntries() const {
6069 return num_entries_;
6070 }
6071
6072 void CheckIndex(size_t index) const {
6073 if (sparse_) {
6074 // In a sparse table, we have num_entries_ keys and num_entries_ values, in that order.
6075 DCHECK_LT(index, 2 * static_cast<size_t>(num_entries_));
6076 } else {
6077 // In a packed table, we have the starting key and num_entries_ values.
6078 DCHECK_LT(index, 1 + static_cast<size_t>(num_entries_));
6079 }
6080 }
6081
6082 int32_t GetEntryAt(size_t index) const {
6083 CheckIndex(index);
6084 return values_[index];
6085 }
6086
6087 uint32_t GetDexPcForIndex(size_t index) const {
6088 CheckIndex(index);
6089 return dex_pc_ +
6090 (reinterpret_cast<const int16_t*>(values_ + index) -
6091 reinterpret_cast<const int16_t*>(&instruction_));
6092 }
6093
6094 // Index of the first value in the table.
6095 size_t GetFirstValueIndex() const {
6096 if (sparse_) {
6097 // In a sparse table, we have num_entries_ keys and num_entries_ values, in that order.
6098 return num_entries_;
6099 } else {
6100 // In a packed table, we have the starting key and num_entries_ values.
6101 return 1;
6102 }
6103 }
6104
6105 private:
6106 const Instruction& instruction_;
6107 const uint32_t dex_pc_;
6108
6109 // Whether this is a sparse-switch table (or a packed-switch one).
6110 const bool sparse_;
6111
6112 // This can't be const as it needs to be computed off of the given instruction, and complicated
6113 // expressions in the initializer list seemed very ugly.
6114 uint16_t num_entries_;
6115
6116 const int32_t* values_;
6117
6118 DISALLOW_COPY_AND_ASSIGN(SwitchTable);
6119};
6120
Nicolas Geoffray818f2102014-02-18 16:43:35 +00006121} // namespace art
6122
6123#endif // ART_COMPILER_OPTIMIZING_NODES_H_