1 /*
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
20 #include <algorithm>
21 #include <array>
22 #include <type_traits>
23
24 #include "base/arena_bit_vector.h"
25 #include "base/arena_containers.h"
26 #include "base/arena_object.h"
27 #include "base/array_ref.h"
28 #include "base/iteration_range.h"
29 #include "base/stl_util.h"
30 #include "base/transform_array_ref.h"
31 #include "dex_file.h"
32 #include "dex_file_types.h"
33 #include "deoptimization_kind.h"
34 #include "entrypoints/quick/quick_entrypoints_enum.h"
35 #include "handle.h"
36 #include "handle_scope.h"
37 #include "invoke_type.h"
38 #include "intrinsics_enum.h"
39 #include "locations.h"
40 #include "method_reference.h"
41 #include "mirror/class.h"
42 #include "offsets.h"
43 #include "primitive.h"
44 #include "utils/intrusive_forward_list.h"
45
46 namespace art {
47
48 class GraphChecker;
49 class HBasicBlock;
50 class HCurrentMethod;
51 class HDoubleConstant;
52 class HEnvironment;
53 class HFloatConstant;
54 class HGraphBuilder;
55 class HGraphVisitor;
56 class HInstruction;
57 class HIntConstant;
58 class HInvoke;
59 class HLongConstant;
60 class HNullConstant;
61 class HPhi;
62 class HSuspendCheck;
63 class HTryBoundary;
64 class LiveInterval;
65 class LocationSummary;
66 class SlowPathCode;
67 class SsaBuilder;
68
69 namespace mirror {
70 class DexCache;
71 } // namespace mirror
72
73 static const int kDefaultNumberOfBlocks = 8;
74 static const int kDefaultNumberOfSuccessors = 2;
75 static const int kDefaultNumberOfPredecessors = 2;
76 static const int kDefaultNumberOfExceptionalPredecessors = 0;
77 static const int kDefaultNumberOfDominatedBlocks = 1;
78 static const int kDefaultNumberOfBackEdges = 1;
79
80 // The maximum (meaningful) distance (31) that can be used in an integer shift/rotate operation.
81 static constexpr int32_t kMaxIntShiftDistance = 0x1f;
82 // The maximum (meaningful) distance (63) that can be used in a long shift/rotate operation.
83 static constexpr int32_t kMaxLongShiftDistance = 0x3f;
84
85 static constexpr uint32_t kUnknownFieldIndex = static_cast<uint32_t>(-1);
86 static constexpr uint16_t kUnknownClassDefIndex = static_cast<uint16_t>(-1);
87
88 static constexpr InvokeType kInvalidInvokeType = static_cast<InvokeType>(-1);
89
90 static constexpr uint32_t kNoDexPc = -1;
91
IsSameDexFile(const DexFile & lhs,const DexFile & rhs)92 inline bool IsSameDexFile(const DexFile& lhs, const DexFile& rhs) {
93 // For the purposes of the compiler, the dex files must actually be the same object
94 // if we want to safely treat them as the same. This is especially important for JIT
95 // as custom class loaders can open the same underlying file (or memory) multiple
96 // times and provide different class resolution but no two class loaders should ever
97 // use the same DexFile object - doing so is an unsupported hack that can lead to
98 // all sorts of weird failures.
99 return &lhs == &rhs;
100 }
101
102 enum IfCondition {
103 // All types.
104 kCondEQ, // ==
105 kCondNE, // !=
106 // Signed integers and floating-point numbers.
107 kCondLT, // <
108 kCondLE, // <=
109 kCondGT, // >
110 kCondGE, // >=
111 // Unsigned integers.
112 kCondB, // <
113 kCondBE, // <=
114 kCondA, // >
115 kCondAE, // >=
116 // First and last aliases.
117 kCondFirst = kCondEQ,
118 kCondLast = kCondAE,
119 };
120
121 enum GraphAnalysisResult {
122 kAnalysisSkipped,
123 kAnalysisInvalidBytecode,
124 kAnalysisFailThrowCatchLoop,
125 kAnalysisFailAmbiguousArrayOp,
126 kAnalysisSuccess,
127 };
128
129 template <typename T>
MakeUnsigned(T x)130 static inline typename std::make_unsigned<T>::type MakeUnsigned(T x) {
131 return static_cast<typename std::make_unsigned<T>::type>(x);
132 }
133
134 class HInstructionList : public ValueObject {
135 public:
HInstructionList()136 HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {}
137
138 void AddInstruction(HInstruction* instruction);
139 void RemoveInstruction(HInstruction* instruction);
140
141 // Insert `instruction` before/after an existing instruction `cursor`.
142 void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
143 void InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor);
144
145 // Return true if this list contains `instruction`.
146 bool Contains(HInstruction* instruction) const;
147
148 // Return true if `instruction1` is found before `instruction2` in
149 // this instruction list and false otherwise. Abort if none
150 // of these instructions is found.
151 bool FoundBefore(const HInstruction* instruction1,
152 const HInstruction* instruction2) const;
153
IsEmpty()154 bool IsEmpty() const { return first_instruction_ == nullptr; }
Clear()155 void Clear() { first_instruction_ = last_instruction_ = nullptr; }
156
157 // Update the block of all instructions to be `block`.
158 void SetBlockOfInstructions(HBasicBlock* block) const;
159
160 void AddAfter(HInstruction* cursor, const HInstructionList& instruction_list);
161 void AddBefore(HInstruction* cursor, const HInstructionList& instruction_list);
162 void Add(const HInstructionList& instruction_list);
163
164 // Return the number of instructions in the list. This is an expensive operation.
165 size_t CountSize() const;
166
167 private:
168 HInstruction* first_instruction_;
169 HInstruction* last_instruction_;
170
171 friend class HBasicBlock;
172 friend class HGraph;
173 friend class HInstruction;
174 friend class HInstructionIterator;
175 friend class HInstructionIteratorHandleChanges;
176 friend class HBackwardInstructionIterator;
177
178 DISALLOW_COPY_AND_ASSIGN(HInstructionList);
179 };
180
181 class ReferenceTypeInfo : ValueObject {
182 public:
183 typedef Handle<mirror::Class> TypeHandle;
184
185 static ReferenceTypeInfo Create(TypeHandle type_handle, bool is_exact);
186
Create(TypeHandle type_handle)187 static ReferenceTypeInfo Create(TypeHandle type_handle) REQUIRES_SHARED(Locks::mutator_lock_) {
188 return Create(type_handle, type_handle->CannotBeAssignedFromOtherTypes());
189 }
190
CreateUnchecked(TypeHandle type_handle,bool is_exact)191 static ReferenceTypeInfo CreateUnchecked(TypeHandle type_handle, bool is_exact) {
192 return ReferenceTypeInfo(type_handle, is_exact);
193 }
194
CreateInvalid()195 static ReferenceTypeInfo CreateInvalid() { return ReferenceTypeInfo(); }
196
IsValidHandle(TypeHandle handle)197 static bool IsValidHandle(TypeHandle handle) {
198 return handle.GetReference() != nullptr;
199 }
200
IsValid()201 bool IsValid() const {
202 return IsValidHandle(type_handle_);
203 }
204
IsExact()205 bool IsExact() const { return is_exact_; }
206
IsObjectClass()207 bool IsObjectClass() const REQUIRES_SHARED(Locks::mutator_lock_) {
208 DCHECK(IsValid());
209 return GetTypeHandle()->IsObjectClass();
210 }
211
IsStringClass()212 bool IsStringClass() const REQUIRES_SHARED(Locks::mutator_lock_) {
213 DCHECK(IsValid());
214 return GetTypeHandle()->IsStringClass();
215 }
216
IsObjectArray()217 bool IsObjectArray() const REQUIRES_SHARED(Locks::mutator_lock_) {
218 DCHECK(IsValid());
219 return IsArrayClass() && GetTypeHandle()->GetComponentType()->IsObjectClass();
220 }
221
IsInterface()222 bool IsInterface() const REQUIRES_SHARED(Locks::mutator_lock_) {
223 DCHECK(IsValid());
224 return GetTypeHandle()->IsInterface();
225 }
226
IsArrayClass()227 bool IsArrayClass() const REQUIRES_SHARED(Locks::mutator_lock_) {
228 DCHECK(IsValid());
229 return GetTypeHandle()->IsArrayClass();
230 }
231
IsPrimitiveArrayClass()232 bool IsPrimitiveArrayClass() const REQUIRES_SHARED(Locks::mutator_lock_) {
233 DCHECK(IsValid());
234 return GetTypeHandle()->IsPrimitiveArray();
235 }
236
IsNonPrimitiveArrayClass()237 bool IsNonPrimitiveArrayClass() const REQUIRES_SHARED(Locks::mutator_lock_) {
238 DCHECK(IsValid());
239 return GetTypeHandle()->IsArrayClass() && !GetTypeHandle()->IsPrimitiveArray();
240 }
241
CanArrayHold(ReferenceTypeInfo rti)242 bool CanArrayHold(ReferenceTypeInfo rti) const REQUIRES_SHARED(Locks::mutator_lock_) {
243 DCHECK(IsValid());
244 if (!IsExact()) return false;
245 if (!IsArrayClass()) return false;
246 return GetTypeHandle()->GetComponentType()->IsAssignableFrom(rti.GetTypeHandle().Get());
247 }
248
CanArrayHoldValuesOf(ReferenceTypeInfo rti)249 bool CanArrayHoldValuesOf(ReferenceTypeInfo rti) const REQUIRES_SHARED(Locks::mutator_lock_) {
250 DCHECK(IsValid());
251 if (!IsExact()) return false;
252 if (!IsArrayClass()) return false;
253 if (!rti.IsArrayClass()) return false;
254 return GetTypeHandle()->GetComponentType()->IsAssignableFrom(
255 rti.GetTypeHandle()->GetComponentType());
256 }
257
GetTypeHandle()258 Handle<mirror::Class> GetTypeHandle() const { return type_handle_; }
259
IsSupertypeOf(ReferenceTypeInfo rti)260 bool IsSupertypeOf(ReferenceTypeInfo rti) const REQUIRES_SHARED(Locks::mutator_lock_) {
261 DCHECK(IsValid());
262 DCHECK(rti.IsValid());
263 return GetTypeHandle()->IsAssignableFrom(rti.GetTypeHandle().Get());
264 }
265
IsStrictSupertypeOf(ReferenceTypeInfo rti)266 bool IsStrictSupertypeOf(ReferenceTypeInfo rti) const REQUIRES_SHARED(Locks::mutator_lock_) {
267 DCHECK(IsValid());
268 DCHECK(rti.IsValid());
269 return GetTypeHandle().Get() != rti.GetTypeHandle().Get() &&
270 GetTypeHandle()->IsAssignableFrom(rti.GetTypeHandle().Get());
271 }
272
273 // Returns true if the type information provide the same amount of details.
274 // Note that it does not mean that the instructions have the same actual type
275 // (because the type can be the result of a merge).
IsEqual(ReferenceTypeInfo rti)276 bool IsEqual(ReferenceTypeInfo rti) const REQUIRES_SHARED(Locks::mutator_lock_) {
277 if (!IsValid() && !rti.IsValid()) {
278 // Invalid types are equal.
279 return true;
280 }
281 if (!IsValid() || !rti.IsValid()) {
282 // One is valid, the other not.
283 return false;
284 }
285 return IsExact() == rti.IsExact()
286 && GetTypeHandle().Get() == rti.GetTypeHandle().Get();
287 }
288
289 private:
ReferenceTypeInfo()290 ReferenceTypeInfo() : type_handle_(TypeHandle()), is_exact_(false) {}
ReferenceTypeInfo(TypeHandle type_handle,bool is_exact)291 ReferenceTypeInfo(TypeHandle type_handle, bool is_exact)
292 : type_handle_(type_handle), is_exact_(is_exact) { }
293
294 // The class of the object.
295 TypeHandle type_handle_;
296 // Whether or not the type is exact or a superclass of the actual type.
297 // Whether or not we have any information about this type.
298 bool is_exact_;
299 };
300
301 std::ostream& operator<<(std::ostream& os, const ReferenceTypeInfo& rhs);
302
303 // Control-flow graph of a method. Contains a list of basic blocks.
304 class HGraph : public ArenaObject<kArenaAllocGraph> {
305 public:
306 HGraph(ArenaAllocator* arena,
307 const DexFile& dex_file,
308 uint32_t method_idx,
309 InstructionSet instruction_set,
310 InvokeType invoke_type = kInvalidInvokeType,
311 bool debuggable = false,
312 bool osr = false,
313 int start_instruction_id = 0)
arena_(arena)314 : arena_(arena),
315 blocks_(arena->Adapter(kArenaAllocBlockList)),
316 reverse_post_order_(arena->Adapter(kArenaAllocReversePostOrder)),
317 linear_order_(arena->Adapter(kArenaAllocLinearOrder)),
318 entry_block_(nullptr),
319 exit_block_(nullptr),
320 maximum_number_of_out_vregs_(0),
321 number_of_vregs_(0),
322 number_of_in_vregs_(0),
323 temporaries_vreg_slots_(0),
324 has_bounds_checks_(false),
325 has_try_catch_(false),
326 has_simd_(false),
327 has_loops_(false),
328 has_irreducible_loops_(false),
329 debuggable_(debuggable),
330 current_instruction_id_(start_instruction_id),
331 dex_file_(dex_file),
332 method_idx_(method_idx),
333 invoke_type_(invoke_type),
334 in_ssa_form_(false),
335 number_of_cha_guards_(0),
336 instruction_set_(instruction_set),
337 cached_null_constant_(nullptr),
338 cached_int_constants_(std::less<int32_t>(), arena->Adapter(kArenaAllocConstantsMap)),
339 cached_float_constants_(std::less<int32_t>(), arena->Adapter(kArenaAllocConstantsMap)),
340 cached_long_constants_(std::less<int64_t>(), arena->Adapter(kArenaAllocConstantsMap)),
341 cached_double_constants_(std::less<int64_t>(), arena->Adapter(kArenaAllocConstantsMap)),
342 cached_current_method_(nullptr),
343 art_method_(nullptr),
344 inexact_object_rti_(ReferenceTypeInfo::CreateInvalid()),
345 osr_(osr),
346 cha_single_implementation_list_(arena->Adapter(kArenaAllocCHA)) {
347 blocks_.reserve(kDefaultNumberOfBlocks);
348 }
349
350 // Acquires and stores RTI of inexact Object to be used when creating HNullConstant.
351 void InitializeInexactObjectRTI(VariableSizedHandleScope* handles);
352
GetArena()353 ArenaAllocator* GetArena() const { return arena_; }
GetBlocks()354 const ArenaVector<HBasicBlock*>& GetBlocks() const { return blocks_; }
355
IsInSsaForm()356 bool IsInSsaForm() const { return in_ssa_form_; }
SetInSsaForm()357 void SetInSsaForm() { in_ssa_form_ = true; }
358
GetEntryBlock()359 HBasicBlock* GetEntryBlock() const { return entry_block_; }
GetExitBlock()360 HBasicBlock* GetExitBlock() const { return exit_block_; }
HasExitBlock()361 bool HasExitBlock() const { return exit_block_ != nullptr; }
362
SetEntryBlock(HBasicBlock * block)363 void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
SetExitBlock(HBasicBlock * block)364 void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
365
366 void AddBlock(HBasicBlock* block);
367
368 void ComputeDominanceInformation();
369 void ClearDominanceInformation();
370 void ClearLoopInformation();
371 void FindBackEdges(ArenaBitVector* visited);
372 GraphAnalysisResult BuildDominatorTree();
373 void SimplifyCFG();
374 void SimplifyCatchBlocks();
375
376 // Analyze all natural loops in this graph. Returns a code specifying that it
377 // was successful or the reason for failure. The method will fail if a loop
378 // is a throw-catch loop, i.e. the header is a catch block.
379 GraphAnalysisResult AnalyzeLoops() const;
380
381 // Iterate over blocks to compute try block membership. Needs reverse post
382 // order and loop information.
383 void ComputeTryBlockInformation();
384
385 // Inline this graph in `outer_graph`, replacing the given `invoke` instruction.
386 // Returns the instruction to replace the invoke expression or null if the
387 // invoke is for a void method. Note that the caller is responsible for replacing
388 // and removing the invoke instruction.
389 HInstruction* InlineInto(HGraph* outer_graph, HInvoke* invoke);
390
391 // Update the loop and try membership of `block`, which was spawned from `reference`.
392 // In case `reference` is a back edge, `replace_if_back_edge` notifies whether `block`
393 // should be the new back edge.
394 void UpdateLoopAndTryInformationOfNewBlock(HBasicBlock* block,
395 HBasicBlock* reference,
396 bool replace_if_back_edge);
397
398 // Need to add a couple of blocks to test if the loop body is entered and
399 // put deoptimization instructions, etc.
400 void TransformLoopHeaderForBCE(HBasicBlock* header);
401
402 // Adds a new loop directly after the loop with the given header and exit.
403 // Returns the new preheader.
404 HBasicBlock* TransformLoopForVectorization(HBasicBlock* header,
405 HBasicBlock* body,
406 HBasicBlock* exit);
407
408 // Removes `block` from the graph. Assumes `block` has been disconnected from
409 // other blocks and has no instructions or phis.
410 void DeleteDeadEmptyBlock(HBasicBlock* block);
411
412 // Splits the edge between `block` and `successor` while preserving the
413 // indices in the predecessor/successor lists. If there are multiple edges
414 // between the blocks, the lowest indices are used.
415 // Returns the new block which is empty and has the same dex pc as `successor`.
416 HBasicBlock* SplitEdge(HBasicBlock* block, HBasicBlock* successor);
417
418 void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor);
419 void SimplifyLoop(HBasicBlock* header);
420
GetNextInstructionId()421 int32_t GetNextInstructionId() {
422 DCHECK_NE(current_instruction_id_, INT32_MAX);
423 return current_instruction_id_++;
424 }
425
GetCurrentInstructionId()426 int32_t GetCurrentInstructionId() const {
427 return current_instruction_id_;
428 }
429
SetCurrentInstructionId(int32_t id)430 void SetCurrentInstructionId(int32_t id) {
431 DCHECK_GE(id, current_instruction_id_);
432 current_instruction_id_ = id;
433 }
434
GetMaximumNumberOfOutVRegs()435 uint16_t GetMaximumNumberOfOutVRegs() const {
436 return maximum_number_of_out_vregs_;
437 }
438
SetMaximumNumberOfOutVRegs(uint16_t new_value)439 void SetMaximumNumberOfOutVRegs(uint16_t new_value) {
440 maximum_number_of_out_vregs_ = new_value;
441 }
442
UpdateMaximumNumberOfOutVRegs(uint16_t other_value)443 void UpdateMaximumNumberOfOutVRegs(uint16_t other_value) {
444 maximum_number_of_out_vregs_ = std::max(maximum_number_of_out_vregs_, other_value);
445 }
446
UpdateTemporariesVRegSlots(size_t slots)447 void UpdateTemporariesVRegSlots(size_t slots) {
448 temporaries_vreg_slots_ = std::max(slots, temporaries_vreg_slots_);
449 }
450
GetTemporariesVRegSlots()451 size_t GetTemporariesVRegSlots() const {
452 DCHECK(!in_ssa_form_);
453 return temporaries_vreg_slots_;
454 }
455
SetNumberOfVRegs(uint16_t number_of_vregs)456 void SetNumberOfVRegs(uint16_t number_of_vregs) {
457 number_of_vregs_ = number_of_vregs;
458 }
459
GetNumberOfVRegs()460 uint16_t GetNumberOfVRegs() const {
461 return number_of_vregs_;
462 }
463
SetNumberOfInVRegs(uint16_t value)464 void SetNumberOfInVRegs(uint16_t value) {
465 number_of_in_vregs_ = value;
466 }
467
GetNumberOfInVRegs()468 uint16_t GetNumberOfInVRegs() const {
469 return number_of_in_vregs_;
470 }
471
GetNumberOfLocalVRegs()472 uint16_t GetNumberOfLocalVRegs() const {
473 DCHECK(!in_ssa_form_);
474 return number_of_vregs_ - number_of_in_vregs_;
475 }
476
GetReversePostOrder()477 const ArenaVector<HBasicBlock*>& GetReversePostOrder() const {
478 return reverse_post_order_;
479 }
480
GetReversePostOrderSkipEntryBlock()481 ArrayRef<HBasicBlock* const> GetReversePostOrderSkipEntryBlock() {
482 DCHECK(GetReversePostOrder()[0] == entry_block_);
483 return ArrayRef<HBasicBlock* const>(GetReversePostOrder()).SubArray(1);
484 }
485
GetPostOrder()486 IterationRange<ArenaVector<HBasicBlock*>::const_reverse_iterator> GetPostOrder() const {
487 return ReverseRange(GetReversePostOrder());
488 }
489
GetLinearOrder()490 const ArenaVector<HBasicBlock*>& GetLinearOrder() const {
491 return linear_order_;
492 }
493
GetLinearPostOrder()494 IterationRange<ArenaVector<HBasicBlock*>::const_reverse_iterator> GetLinearPostOrder() const {
495 return ReverseRange(GetLinearOrder());
496 }
497
HasBoundsChecks()498 bool HasBoundsChecks() const {
499 return has_bounds_checks_;
500 }
501
SetHasBoundsChecks(bool value)502 void SetHasBoundsChecks(bool value) {
503 has_bounds_checks_ = value;
504 }
505
IsDebuggable()506 bool IsDebuggable() const { return debuggable_; }
507
508 // Returns a constant of the given type and value. If it does not exist
509 // already, it is created and inserted into the graph. This method is only for
510 // integral types.
511 HConstant* GetConstant(Primitive::Type type, int64_t value, uint32_t dex_pc = kNoDexPc);
512
513 // TODO: This is problematic for the consistency of reference type propagation
514 // because it can be created anytime after the pass and thus it will be left
515 // with an invalid type.
516 HNullConstant* GetNullConstant(uint32_t dex_pc = kNoDexPc);
517
518 HIntConstant* GetIntConstant(int32_t value, uint32_t dex_pc = kNoDexPc) {
519 return CreateConstant(value, &cached_int_constants_, dex_pc);
520 }
521 HLongConstant* GetLongConstant(int64_t value, uint32_t dex_pc = kNoDexPc) {
522 return CreateConstant(value, &cached_long_constants_, dex_pc);
523 }
524 HFloatConstant* GetFloatConstant(float value, uint32_t dex_pc = kNoDexPc) {
525 return CreateConstant(bit_cast<int32_t, float>(value), &cached_float_constants_, dex_pc);
526 }
527 HDoubleConstant* GetDoubleConstant(double value, uint32_t dex_pc = kNoDexPc) {
528 return CreateConstant(bit_cast<int64_t, double>(value), &cached_double_constants_, dex_pc);
529 }
530
531 HCurrentMethod* GetCurrentMethod();
532
GetDexFile()533 const DexFile& GetDexFile() const {
534 return dex_file_;
535 }
536
GetMethodIdx()537 uint32_t GetMethodIdx() const {
538 return method_idx_;
539 }
540
GetInvokeType()541 InvokeType GetInvokeType() const {
542 return invoke_type_;
543 }
544
GetInstructionSet()545 InstructionSet GetInstructionSet() const {
546 return instruction_set_;
547 }
548
IsCompilingOsr()549 bool IsCompilingOsr() const { return osr_; }
550
GetCHASingleImplementationList()551 ArenaSet<ArtMethod*>& GetCHASingleImplementationList() {
552 return cha_single_implementation_list_;
553 }
554
AddCHASingleImplementationDependency(ArtMethod * method)555 void AddCHASingleImplementationDependency(ArtMethod* method) {
556 cha_single_implementation_list_.insert(method);
557 }
558
HasShouldDeoptimizeFlag()559 bool HasShouldDeoptimizeFlag() const {
560 return number_of_cha_guards_ != 0;
561 }
562
HasTryCatch()563 bool HasTryCatch() const { return has_try_catch_; }
SetHasTryCatch(bool value)564 void SetHasTryCatch(bool value) { has_try_catch_ = value; }
565
HasSIMD()566 bool HasSIMD() const { return has_simd_; }
SetHasSIMD(bool value)567 void SetHasSIMD(bool value) { has_simd_ = value; }
568
HasLoops()569 bool HasLoops() const { return has_loops_; }
SetHasLoops(bool value)570 void SetHasLoops(bool value) { has_loops_ = value; }
571
HasIrreducibleLoops()572 bool HasIrreducibleLoops() const { return has_irreducible_loops_; }
SetHasIrreducibleLoops(bool value)573 void SetHasIrreducibleLoops(bool value) { has_irreducible_loops_ = value; }
574
GetArtMethod()575 ArtMethod* GetArtMethod() const { return art_method_; }
SetArtMethod(ArtMethod * method)576 void SetArtMethod(ArtMethod* method) { art_method_ = method; }
577
578 // Returns an instruction with the opposite Boolean value from 'cond'.
579 // The instruction has been inserted into the graph, either as a constant, or
580 // before cursor.
581 HInstruction* InsertOppositeCondition(HInstruction* cond, HInstruction* cursor);
582
GetInexactObjectRti()583 ReferenceTypeInfo GetInexactObjectRti() const { return inexact_object_rti_; }
584
GetNumberOfCHAGuards()585 uint32_t GetNumberOfCHAGuards() { return number_of_cha_guards_; }
SetNumberOfCHAGuards(uint32_t num)586 void SetNumberOfCHAGuards(uint32_t num) { number_of_cha_guards_ = num; }
IncrementNumberOfCHAGuards()587 void IncrementNumberOfCHAGuards() { number_of_cha_guards_++; }
588
589 private:
590 void RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const;
591 void RemoveDeadBlocks(const ArenaBitVector& visited);
592
593 template <class InstructionType, typename ValueType>
594 InstructionType* CreateConstant(ValueType value,
595 ArenaSafeMap<ValueType, InstructionType*>* cache,
596 uint32_t dex_pc = kNoDexPc) {
597 // Try to find an existing constant of the given value.
598 InstructionType* constant = nullptr;
599 auto cached_constant = cache->find(value);
600 if (cached_constant != cache->end()) {
601 constant = cached_constant->second;
602 }
603
604 // If not found or previously deleted, create and cache a new instruction.
605 // Don't bother reviving a previously deleted instruction, for simplicity.
606 if (constant == nullptr || constant->GetBlock() == nullptr) {
607 constant = new (arena_) InstructionType(value, dex_pc);
608 cache->Overwrite(value, constant);
609 InsertConstant(constant);
610 }
611 return constant;
612 }
613
614 void InsertConstant(HConstant* instruction);
615
616 // Cache a float constant into the graph. This method should only be
617 // called by the SsaBuilder when creating "equivalent" instructions.
618 void CacheFloatConstant(HFloatConstant* constant);
619
620 // See CacheFloatConstant comment.
621 void CacheDoubleConstant(HDoubleConstant* constant);
622
623 ArenaAllocator* const arena_;
624
625 // List of blocks in insertion order.
626 ArenaVector<HBasicBlock*> blocks_;
627
628 // List of blocks to perform a reverse post order tree traversal.
629 ArenaVector<HBasicBlock*> reverse_post_order_;
630
631 // List of blocks to perform a linear order tree traversal. Unlike the reverse
632 // post order, this order is not incrementally kept up-to-date.
633 ArenaVector<HBasicBlock*> linear_order_;
634
635 HBasicBlock* entry_block_;
636 HBasicBlock* exit_block_;
637
638 // The maximum number of virtual registers arguments passed to a HInvoke in this graph.
639 uint16_t maximum_number_of_out_vregs_;
640
641 // The number of virtual registers in this method. Contains the parameters.
642 uint16_t number_of_vregs_;
643
644 // The number of virtual registers used by parameters of this method.
645 uint16_t number_of_in_vregs_;
646
647 // Number of vreg size slots that the temporaries use (used in baseline compiler).
648 size_t temporaries_vreg_slots_;
649
650 // Flag whether there are bounds checks in the graph. We can skip
651 // BCE if it's false. It's only best effort to keep it up to date in
652 // the presence of code elimination so there might be false positives.
653 bool has_bounds_checks_;
654
655 // Flag whether there are try/catch blocks in the graph. We will skip
656 // try/catch-related passes if it's false. It's only best effort to keep
657 // it up to date in the presence of code elimination so there might be
658 // false positives.
659 bool has_try_catch_;
660
661 // Flag whether SIMD instructions appear in the graph. If true, the
662 // code generators may have to be more careful spilling the wider
663 // contents of SIMD registers.
664 bool has_simd_;
665
666 // Flag whether there are any loops in the graph. We can skip loop
667 // optimization if it's false. It's only best effort to keep it up
668 // to date in the presence of code elimination so there might be false
669 // positives.
670 bool has_loops_;
671
672 // Flag whether there are any irreducible loops in the graph. It's only
673 // best effort to keep it up to date in the presence of code elimination
674 // so there might be false positives.
675 bool has_irreducible_loops_;
676
677 // Indicates whether the graph should be compiled in a way that
678 // ensures full debuggability. If false, we can apply more
679 // aggressive optimizations that may limit the level of debugging.
680 const bool debuggable_;
681
682 // The current id to assign to a newly added instruction. See HInstruction.id_.
683 int32_t current_instruction_id_;
684
685 // The dex file from which the method is from.
686 const DexFile& dex_file_;
687
688 // The method index in the dex file.
689 const uint32_t method_idx_;
690
691 // If inlined, this encodes how the callee is being invoked.
692 const InvokeType invoke_type_;
693
694 // Whether the graph has been transformed to SSA form. Only used
695 // in debug mode to ensure we are not using properties only valid
696 // for non-SSA form (like the number of temporaries).
697 bool in_ssa_form_;
698
699 // Number of CHA guards in the graph. Used to short-circuit the
700 // CHA guard optimization pass when there is no CHA guard left.
701 uint32_t number_of_cha_guards_;
702
703 const InstructionSet instruction_set_;
704
705 // Cached constants.
706 HNullConstant* cached_null_constant_;
707 ArenaSafeMap<int32_t, HIntConstant*> cached_int_constants_;
708 ArenaSafeMap<int32_t, HFloatConstant*> cached_float_constants_;
709 ArenaSafeMap<int64_t, HLongConstant*> cached_long_constants_;
710 ArenaSafeMap<int64_t, HDoubleConstant*> cached_double_constants_;
711
712 HCurrentMethod* cached_current_method_;
713
714 // The ArtMethod this graph is for. Note that for AOT, it may be null,
715 // for example for methods whose declaring class could not be resolved
716 // (such as when the superclass could not be found).
717 ArtMethod* art_method_;
718
719 // Keep the RTI of inexact Object to avoid having to pass stack handle
720 // collection pointer to passes which may create NullConstant.
721 ReferenceTypeInfo inexact_object_rti_;
722
723 // Whether we are compiling this graph for on stack replacement: this will
724 // make all loops seen as irreducible and emit special stack maps to mark
725 // compiled code entries which the interpreter can directly jump to.
726 const bool osr_;
727
728 // List of methods that are assumed to have single implementation.
729 ArenaSet<ArtMethod*> cha_single_implementation_list_;
730
731 friend class SsaBuilder; // For caching constants.
732 friend class SsaLivenessAnalysis; // For the linear order.
733 friend class HInliner; // For the reverse post order.
734 ART_FRIEND_TEST(GraphTest, IfSuccessorSimpleJoinBlock1);
735 DISALLOW_COPY_AND_ASSIGN(HGraph);
736 };
737
738 class HLoopInformation : public ArenaObject<kArenaAllocLoopInfo> {
739 public:
HLoopInformation(HBasicBlock * header,HGraph * graph)740 HLoopInformation(HBasicBlock* header, HGraph* graph)
741 : header_(header),
742 suspend_check_(nullptr),
743 irreducible_(false),
744 contains_irreducible_loop_(false),
745 back_edges_(graph->GetArena()->Adapter(kArenaAllocLoopInfoBackEdges)),
746 // Make bit vector growable, as the number of blocks may change.
747 blocks_(graph->GetArena(), graph->GetBlocks().size(), true, kArenaAllocLoopInfoBackEdges) {
748 back_edges_.reserve(kDefaultNumberOfBackEdges);
749 }
750
IsIrreducible()751 bool IsIrreducible() const { return irreducible_; }
ContainsIrreducibleLoop()752 bool ContainsIrreducibleLoop() const { return contains_irreducible_loop_; }
753
754 void Dump(std::ostream& os);
755
GetHeader()756 HBasicBlock* GetHeader() const {
757 return header_;
758 }
759
SetHeader(HBasicBlock * block)760 void SetHeader(HBasicBlock* block) {
761 header_ = block;
762 }
763
GetSuspendCheck()764 HSuspendCheck* GetSuspendCheck() const { return suspend_check_; }
SetSuspendCheck(HSuspendCheck * check)765 void SetSuspendCheck(HSuspendCheck* check) { suspend_check_ = check; }
HasSuspendCheck()766 bool HasSuspendCheck() const { return suspend_check_ != nullptr; }
767
AddBackEdge(HBasicBlock * back_edge)768 void AddBackEdge(HBasicBlock* back_edge) {
769 back_edges_.push_back(back_edge);
770 }
771
RemoveBackEdge(HBasicBlock * back_edge)772 void RemoveBackEdge(HBasicBlock* back_edge) {
773 RemoveElement(back_edges_, back_edge);
774 }
775
IsBackEdge(const HBasicBlock & block)776 bool IsBackEdge(const HBasicBlock& block) const {
777 return ContainsElement(back_edges_, &block);
778 }
779
NumberOfBackEdges()780 size_t NumberOfBackEdges() const {
781 return back_edges_.size();
782 }
783
784 HBasicBlock* GetPreHeader() const;
785
GetBackEdges()786 const ArenaVector<HBasicBlock*>& GetBackEdges() const {
787 return back_edges_;
788 }
789
790 // Returns the lifetime position of the back edge that has the
791 // greatest lifetime position.
792 size_t GetLifetimeEnd() const;
793
ReplaceBackEdge(HBasicBlock * existing,HBasicBlock * new_back_edge)794 void ReplaceBackEdge(HBasicBlock* existing, HBasicBlock* new_back_edge) {
795 ReplaceElement(back_edges_, existing, new_back_edge);
796 }
797
798 // Finds blocks that are part of this loop.
799 void Populate();
800
801 // Returns whether this loop information contains `block`.
802 // Note that this loop information *must* be populated before entering this function.
803 bool Contains(const HBasicBlock& block) const;
804
805 // Returns whether this loop information is an inner loop of `other`.
806 // Note that `other` *must* be populated before entering this function.
807 bool IsIn(const HLoopInformation& other) const;
808
809 // Returns true if instruction is not defined within this loop.
810 bool IsDefinedOutOfTheLoop(HInstruction* instruction) const;
811
GetBlocks()812 const ArenaBitVector& GetBlocks() const { return blocks_; }
813
814 void Add(HBasicBlock* block);
815 void Remove(HBasicBlock* block);
816
ClearAllBlocks()817 void ClearAllBlocks() {
818 blocks_.ClearAllBits();
819 }
820
821 bool HasBackEdgeNotDominatedByHeader() const;
822
IsPopulated()823 bool IsPopulated() const {
824 return blocks_.GetHighestBitSet() != -1;
825 }
826
827 bool DominatesAllBackEdges(HBasicBlock* block);
828
829 bool HasExitEdge() const;
830
831 private:
832 // Internal recursive implementation of `Populate`.
833 void PopulateRecursive(HBasicBlock* block);
834 void PopulateIrreducibleRecursive(HBasicBlock* block, ArenaBitVector* finalized);
835
836 HBasicBlock* header_;
837 HSuspendCheck* suspend_check_;
838 bool irreducible_;
839 bool contains_irreducible_loop_;
840 ArenaVector<HBasicBlock*> back_edges_;
841 ArenaBitVector blocks_;
842
843 DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
844 };
845
846 // Stores try/catch information for basic blocks.
847 // Note that HGraph is constructed so that catch blocks cannot simultaneously
848 // be try blocks.
849 class TryCatchInformation : public ArenaObject<kArenaAllocTryCatchInfo> {
850 public:
851 // Try block information constructor.
TryCatchInformation(const HTryBoundary & try_entry)852 explicit TryCatchInformation(const HTryBoundary& try_entry)
853 : try_entry_(&try_entry),
854 catch_dex_file_(nullptr),
855 catch_type_index_(DexFile::kDexNoIndex16) {
856 DCHECK(try_entry_ != nullptr);
857 }
858
859 // Catch block information constructor.
TryCatchInformation(dex::TypeIndex catch_type_index,const DexFile & dex_file)860 TryCatchInformation(dex::TypeIndex catch_type_index, const DexFile& dex_file)
861 : try_entry_(nullptr),
862 catch_dex_file_(&dex_file),
863 catch_type_index_(catch_type_index) {}
864
IsTryBlock()865 bool IsTryBlock() const { return try_entry_ != nullptr; }
866
GetTryEntry()867 const HTryBoundary& GetTryEntry() const {
868 DCHECK(IsTryBlock());
869 return *try_entry_;
870 }
871
IsCatchBlock()872 bool IsCatchBlock() const { return catch_dex_file_ != nullptr; }
873
IsCatchAllTypeIndex()874 bool IsCatchAllTypeIndex() const {
875 DCHECK(IsCatchBlock());
876 return !catch_type_index_.IsValid();
877 }
878
GetCatchTypeIndex()879 dex::TypeIndex GetCatchTypeIndex() const {
880 DCHECK(IsCatchBlock());
881 return catch_type_index_;
882 }
883
GetCatchDexFile()884 const DexFile& GetCatchDexFile() const {
885 DCHECK(IsCatchBlock());
886 return *catch_dex_file_;
887 }
888
889 private:
890 // One of possibly several TryBoundary instructions entering the block's try.
891 // Only set for try blocks.
892 const HTryBoundary* try_entry_;
893
894 // Exception type information. Only set for catch blocks.
895 const DexFile* catch_dex_file_;
896 const dex::TypeIndex catch_type_index_;
897 };
898
899 static constexpr size_t kNoLifetime = -1;
900 static constexpr uint32_t kInvalidBlockId = static_cast<uint32_t>(-1);
901
902 // A block in a method. Contains the list of instructions represented
903 // as a double linked list. Each block knows its predecessors and
904 // successors.
905
906 class HBasicBlock : public ArenaObject<kArenaAllocBasicBlock> {
907 public:
908 explicit HBasicBlock(HGraph* graph, uint32_t dex_pc = kNoDexPc)
graph_(graph)909 : graph_(graph),
910 predecessors_(graph->GetArena()->Adapter(kArenaAllocPredecessors)),
911 successors_(graph->GetArena()->Adapter(kArenaAllocSuccessors)),
912 loop_information_(nullptr),
913 dominator_(nullptr),
914 dominated_blocks_(graph->GetArena()->Adapter(kArenaAllocDominated)),
915 block_id_(kInvalidBlockId),
916 dex_pc_(dex_pc),
917 lifetime_start_(kNoLifetime),
918 lifetime_end_(kNoLifetime),
919 try_catch_information_(nullptr) {
920 predecessors_.reserve(kDefaultNumberOfPredecessors);
921 successors_.reserve(kDefaultNumberOfSuccessors);
922 dominated_blocks_.reserve(kDefaultNumberOfDominatedBlocks);
923 }
924
GetPredecessors()925 const ArenaVector<HBasicBlock*>& GetPredecessors() const {
926 return predecessors_;
927 }
928
GetSuccessors()929 const ArenaVector<HBasicBlock*>& GetSuccessors() const {
930 return successors_;
931 }
932
933 ArrayRef<HBasicBlock* const> GetNormalSuccessors() const;
934 ArrayRef<HBasicBlock* const> GetExceptionalSuccessors() const;
935
936 bool HasSuccessor(const HBasicBlock* block, size_t start_from = 0u) {
937 return ContainsElement(successors_, block, start_from);
938 }
939
GetDominatedBlocks()940 const ArenaVector<HBasicBlock*>& GetDominatedBlocks() const {
941 return dominated_blocks_;
942 }
943
IsEntryBlock()944 bool IsEntryBlock() const {
945 return graph_->GetEntryBlock() == this;
946 }
947
IsExitBlock()948 bool IsExitBlock() const {
949 return graph_->GetExitBlock() == this;
950 }
951
952 bool IsSingleGoto() const;
953 bool IsSingleTryBoundary() const;
954
955 // Returns true if this block emits nothing but a jump.
IsSingleJump()956 bool IsSingleJump() const {
957 HLoopInformation* loop_info = GetLoopInformation();
958 return (IsSingleGoto() || IsSingleTryBoundary())
959 // Back edges generate a suspend check.
960 && (loop_info == nullptr || !loop_info->IsBackEdge(*this));
961 }
962
AddBackEdge(HBasicBlock * back_edge)963 void AddBackEdge(HBasicBlock* back_edge) {
964 if (loop_information_ == nullptr) {
965 loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_);
966 }
967 DCHECK_EQ(loop_information_->GetHeader(), this);
968 loop_information_->AddBackEdge(back_edge);
969 }
970
GetGraph()971 HGraph* GetGraph() const { return graph_; }
SetGraph(HGraph * graph)972 void SetGraph(HGraph* graph) { graph_ = graph; }
973
GetBlockId()974 uint32_t GetBlockId() const { return block_id_; }
SetBlockId(int id)975 void SetBlockId(int id) { block_id_ = id; }
GetDexPc()976 uint32_t GetDexPc() const { return dex_pc_; }
977
GetDominator()978 HBasicBlock* GetDominator() const { return dominator_; }
SetDominator(HBasicBlock * dominator)979 void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
AddDominatedBlock(HBasicBlock * block)980 void AddDominatedBlock(HBasicBlock* block) { dominated_blocks_.push_back(block); }
981
RemoveDominatedBlock(HBasicBlock * block)982 void RemoveDominatedBlock(HBasicBlock* block) {
983 RemoveElement(dominated_blocks_, block);
984 }
985
ReplaceDominatedBlock(HBasicBlock * existing,HBasicBlock * new_block)986 void ReplaceDominatedBlock(HBasicBlock* existing, HBasicBlock* new_block) {
987 ReplaceElement(dominated_blocks_, existing, new_block);
988 }
989
990 void ClearDominanceInformation();
991
NumberOfBackEdges()992 int NumberOfBackEdges() const {
993 return IsLoopHeader() ? loop_information_->NumberOfBackEdges() : 0;
994 }
995
GetFirstInstruction()996 HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
GetLastInstruction()997 HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; }
GetInstructions()998 const HInstructionList& GetInstructions() const { return instructions_; }
GetFirstPhi()999 HInstruction* GetFirstPhi() const { return phis_.first_instruction_; }
GetLastPhi()1000 HInstruction* GetLastPhi() const { return phis_.last_instruction_; }
GetPhis()1001 const HInstructionList& GetPhis() const { return phis_; }
1002
1003 HInstruction* GetFirstInstructionDisregardMoves() const;
1004
AddSuccessor(HBasicBlock * block)1005 void AddSuccessor(HBasicBlock* block) {
1006 successors_.push_back(block);
1007 block->predecessors_.push_back(this);
1008 }
1009
ReplaceSuccessor(HBasicBlock * existing,HBasicBlock * new_block)1010 void ReplaceSuccessor(HBasicBlock* existing, HBasicBlock* new_block) {
1011 size_t successor_index = GetSuccessorIndexOf(existing);
1012 existing->RemovePredecessor(this);
1013 new_block->predecessors_.push_back(this);
1014 successors_[successor_index] = new_block;
1015 }
1016
ReplacePredecessor(HBasicBlock * existing,HBasicBlock * new_block)1017 void ReplacePredecessor(HBasicBlock* existing, HBasicBlock* new_block) {
1018 size_t predecessor_index = GetPredecessorIndexOf(existing);
1019 existing->RemoveSuccessor(this);
1020 new_block->successors_.push_back(this);
1021 predecessors_[predecessor_index] = new_block;
1022 }
1023
1024 // Insert `this` between `predecessor` and `successor. This method
1025 // preserves the indicies, and will update the first edge found between
1026 // `predecessor` and `successor`.
InsertBetween(HBasicBlock * predecessor,HBasicBlock * successor)1027 void InsertBetween(HBasicBlock* predecessor, HBasicBlock* successor) {
1028 size_t predecessor_index = successor->GetPredecessorIndexOf(predecessor);
1029 size_t successor_index = predecessor->GetSuccessorIndexOf(successor);
1030 successor->predecessors_[predecessor_index] = this;
1031 predecessor->successors_[successor_index] = this;
1032 successors_.push_back(successor);
1033 predecessors_.push_back(predecessor);
1034 }
1035
RemovePredecessor(HBasicBlock * block)1036 void RemovePredecessor(HBasicBlock* block) {
1037 predecessors_.erase(predecessors_.begin() + GetPredecessorIndexOf(block));
1038 }
1039
RemoveSuccessor(HBasicBlock * block)1040 void RemoveSuccessor(HBasicBlock* block) {
1041 successors_.erase(successors_.begin() + GetSuccessorIndexOf(block));
1042 }
1043
ClearAllPredecessors()1044 void ClearAllPredecessors() {
1045 predecessors_.clear();
1046 }
1047
AddPredecessor(HBasicBlock * block)1048 void AddPredecessor(HBasicBlock* block) {
1049 predecessors_.push_back(block);
1050 block->successors_.push_back(this);
1051 }
1052
SwapPredecessors()1053 void SwapPredecessors() {
1054 DCHECK_EQ(predecessors_.size(), 2u);
1055 std::swap(predecessors_[0], predecessors_[1]);
1056 }
1057
SwapSuccessors()1058 void SwapSuccessors() {
1059 DCHECK_EQ(successors_.size(), 2u);
1060 std::swap(successors_[0], successors_[1]);
1061 }
1062
GetPredecessorIndexOf(HBasicBlock * predecessor)1063 size_t GetPredecessorIndexOf(HBasicBlock* predecessor) const {
1064 return IndexOfElement(predecessors_, predecessor);
1065 }
1066
GetSuccessorIndexOf(HBasicBlock * successor)1067 size_t GetSuccessorIndexOf(HBasicBlock* successor) const {
1068 return IndexOfElement(successors_, successor);
1069 }
1070
GetSinglePredecessor()1071 HBasicBlock* GetSinglePredecessor() const {
1072 DCHECK_EQ(GetPredecessors().size(), 1u);
1073 return GetPredecessors()[0];
1074 }
1075
GetSingleSuccessor()1076 HBasicBlock* GetSingleSuccessor() const {
1077 DCHECK_EQ(GetSuccessors().size(), 1u);
1078 return GetSuccessors()[0];
1079 }
1080
1081 // Returns whether the first occurrence of `predecessor` in the list of
1082 // predecessors is at index `idx`.
IsFirstIndexOfPredecessor(HBasicBlock * predecessor,size_t idx)1083 bool IsFirstIndexOfPredecessor(HBasicBlock* predecessor, size_t idx) const {
1084 DCHECK_EQ(GetPredecessors()[idx], predecessor);
1085 return GetPredecessorIndexOf(predecessor) == idx;
1086 }
1087
1088 // Create a new block between this block and its predecessors. The new block
1089 // is added to the graph, all predecessor edges are relinked to it and an edge
1090 // is created to `this`. Returns the new empty block. Reverse post order or
1091 // loop and try/catch information are not updated.
1092 HBasicBlock* CreateImmediateDominator();
1093
1094 // Split the block into two blocks just before `cursor`. Returns the newly
1095 // created, latter block. Note that this method will add the block to the
1096 // graph, create a Goto at the end of the former block and will create an edge
1097 // between the blocks. It will not, however, update the reverse post order or
1098 // loop and try/catch information.
1099 HBasicBlock* SplitBefore(HInstruction* cursor);
1100
1101 // Split the block into two blocks just before `cursor`. Returns the newly
1102 // created block. Note that this method just updates raw block information,
1103 // like predecessors, successors, dominators, and instruction list. It does not
1104 // update the graph, reverse post order, loop information, nor make sure the
1105 // blocks are consistent (for example ending with a control flow instruction).
1106 HBasicBlock* SplitBeforeForInlining(HInstruction* cursor);
1107
1108 // Similar to `SplitBeforeForInlining` but does it after `cursor`.
1109 HBasicBlock* SplitAfterForInlining(HInstruction* cursor);
1110
1111 // Merge `other` at the end of `this`. Successors and dominated blocks of
1112 // `other` are changed to be successors and dominated blocks of `this`. Note
1113 // that this method does not update the graph, reverse post order, loop
1114 // information, nor make sure the blocks are consistent (for example ending
1115 // with a control flow instruction).
1116 void MergeWithInlined(HBasicBlock* other);
1117
1118 // Replace `this` with `other`. Predecessors, successors, and dominated blocks
1119 // of `this` are moved to `other`.
1120 // Note that this method does not update the graph, reverse post order, loop
1121 // information, nor make sure the blocks are consistent (for example ending
1122 // with a control flow instruction).
1123 void ReplaceWith(HBasicBlock* other);
1124
1125 // Merges the instructions of `other` at the end of `this`.
1126 void MergeInstructionsWith(HBasicBlock* other);
1127
1128 // Merge `other` at the end of `this`. This method updates loops, reverse post
1129 // order, links to predecessors, successors, dominators and deletes the block
1130 // from the graph. The two blocks must be successive, i.e. `this` the only
1131 // predecessor of `other` and vice versa.
1132 void MergeWith(HBasicBlock* other);
1133
1134 // Disconnects `this` from all its predecessors, successors and dominator,
1135 // removes it from all loops it is included in and eventually from the graph.
1136 // The block must not dominate any other block. Predecessors and successors
1137 // are safely updated.
1138 void DisconnectAndDelete();
1139
1140 void AddInstruction(HInstruction* instruction);
1141 // Insert `instruction` before/after an existing instruction `cursor`.
1142 void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
1143 void InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor);
1144 // Replace instruction `initial` with `replacement` within this block.
1145 void ReplaceAndRemoveInstructionWith(HInstruction* initial,
1146 HInstruction* replacement);
1147 void AddPhi(HPhi* phi);
1148 void InsertPhiAfter(HPhi* instruction, HPhi* cursor);
1149 // RemoveInstruction and RemovePhi delete a given instruction from the respective
1150 // instruction list. With 'ensure_safety' set to true, it verifies that the
1151 // instruction is not in use and removes it from the use lists of its inputs.
1152 void RemoveInstruction(HInstruction* instruction, bool ensure_safety = true);
1153 void RemovePhi(HPhi* phi, bool ensure_safety = true);
1154 void RemoveInstructionOrPhi(HInstruction* instruction, bool ensure_safety = true);
1155
IsLoopHeader()1156 bool IsLoopHeader() const {
1157 return IsInLoop() && (loop_information_->GetHeader() == this);
1158 }
1159
IsLoopPreHeaderFirstPredecessor()1160 bool IsLoopPreHeaderFirstPredecessor() const {
1161 DCHECK(IsLoopHeader());
1162 return GetPredecessors()[0] == GetLoopInformation()->GetPreHeader();
1163 }
1164
IsFirstPredecessorBackEdge()1165 bool IsFirstPredecessorBackEdge() const {
1166 DCHECK(IsLoopHeader());
1167 return GetLoopInformation()->IsBackEdge(*GetPredecessors()[0]);
1168 }
1169
GetLoopInformation()1170 HLoopInformation* GetLoopInformation() const {
1171 return loop_information_;
1172 }
1173
1174 // Set the loop_information_ on this block. Overrides the current
1175 // loop_information if it is an outer loop of the passed loop information.
1176 // Note that this method is called while creating the loop information.
SetInLoop(HLoopInformation * info)1177 void SetInLoop(HLoopInformation* info) {
1178 if (IsLoopHeader()) {
1179 // Nothing to do. This just means `info` is an outer loop.
1180 } else if (!IsInLoop()) {
1181 loop_information_ = info;
1182 } else if (loop_information_->Contains(*info->GetHeader())) {
1183 // Block is currently part of an outer loop. Make it part of this inner loop.
1184 // Note that a non loop header having a loop information means this loop information
1185 // has already been populated
1186 loop_information_ = info;
1187 } else {
1188 // Block is part of an inner loop. Do not update the loop information.
1189 // Note that we cannot do the check `info->Contains(loop_information_)->GetHeader()`
1190 // at this point, because this method is being called while populating `info`.
1191 }
1192 }
1193
1194 // Raw update of the loop information.
SetLoopInformation(HLoopInformation * info)1195 void SetLoopInformation(HLoopInformation* info) {
1196 loop_information_ = info;
1197 }
1198
IsInLoop()1199 bool IsInLoop() const { return loop_information_ != nullptr; }
1200
GetTryCatchInformation()1201 TryCatchInformation* GetTryCatchInformation() const { return try_catch_information_; }
1202
SetTryCatchInformation(TryCatchInformation * try_catch_information)1203 void SetTryCatchInformation(TryCatchInformation* try_catch_information) {
1204 try_catch_information_ = try_catch_information;
1205 }
1206
IsTryBlock()1207 bool IsTryBlock() const {
1208 return try_catch_information_ != nullptr && try_catch_information_->IsTryBlock();
1209 }
1210
IsCatchBlock()1211 bool IsCatchBlock() const {
1212 return try_catch_information_ != nullptr && try_catch_information_->IsCatchBlock();
1213 }
1214
1215 // Returns the try entry that this block's successors should have. They will
1216 // be in the same try, unless the block ends in a try boundary. In that case,
1217 // the appropriate try entry will be returned.
1218 const HTryBoundary* ComputeTryEntryOfSuccessors() const;
1219
1220 bool HasThrowingInstructions() const;
1221
1222 // Returns whether this block dominates the blocked passed as parameter.
1223 bool Dominates(HBasicBlock* block) const;
1224
GetLifetimeStart()1225 size_t GetLifetimeStart() const { return lifetime_start_; }
GetLifetimeEnd()1226 size_t GetLifetimeEnd() const { return lifetime_end_; }
1227
SetLifetimeStart(size_t start)1228 void SetLifetimeStart(size_t start) { lifetime_start_ = start; }
SetLifetimeEnd(size_t end)1229 void SetLifetimeEnd(size_t end) { lifetime_end_ = end; }
1230
1231 bool EndsWithControlFlowInstruction() const;
1232 bool EndsWithIf() const;
1233 bool EndsWithTryBoundary() const;
1234 bool HasSinglePhi() const;
1235
1236 private:
1237 HGraph* graph_;
1238 ArenaVector<HBasicBlock*> predecessors_;
1239 ArenaVector<HBasicBlock*> successors_;
1240 HInstructionList instructions_;
1241 HInstructionList phis_;
1242 HLoopInformation* loop_information_;
1243 HBasicBlock* dominator_;
1244 ArenaVector<HBasicBlock*> dominated_blocks_;
1245 uint32_t block_id_;
1246 // The dex program counter of the first instruction of this block.
1247 const uint32_t dex_pc_;
1248 size_t lifetime_start_;
1249 size_t lifetime_end_;
1250 TryCatchInformation* try_catch_information_;
1251
1252 friend class HGraph;
1253 friend class HInstruction;
1254
1255 DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
1256 };
1257
1258 // Iterates over the LoopInformation of all loops which contain 'block'
1259 // from the innermost to the outermost.
1260 class HLoopInformationOutwardIterator : public ValueObject {
1261 public:
HLoopInformationOutwardIterator(const HBasicBlock & block)1262 explicit HLoopInformationOutwardIterator(const HBasicBlock& block)
1263 : current_(block.GetLoopInformation()) {}
1264
Done()1265 bool Done() const { return current_ == nullptr; }
1266
Advance()1267 void Advance() {
1268 DCHECK(!Done());
1269 current_ = current_->GetPreHeader()->GetLoopInformation();
1270 }
1271
Current()1272 HLoopInformation* Current() const {
1273 DCHECK(!Done());
1274 return current_;
1275 }
1276
1277 private:
1278 HLoopInformation* current_;
1279
1280 DISALLOW_COPY_AND_ASSIGN(HLoopInformationOutwardIterator);
1281 };
1282
1283 #define FOR_EACH_CONCRETE_INSTRUCTION_COMMON(M) \
1284 M(Above, Condition) \
1285 M(AboveOrEqual, Condition) \
1286 M(Add, BinaryOperation) \
1287 M(And, BinaryOperation) \
1288 M(ArrayGet, Instruction) \
1289 M(ArrayLength, Instruction) \
1290 M(ArraySet, Instruction) \
1291 M(Below, Condition) \
1292 M(BelowOrEqual, Condition) \
1293 M(BooleanNot, UnaryOperation) \
1294 M(BoundsCheck, Instruction) \
1295 M(BoundType, Instruction) \
1296 M(CheckCast, Instruction) \
1297 M(ClassTableGet, Instruction) \
1298 M(ClearException, Instruction) \
1299 M(ClinitCheck, Instruction) \
1300 M(Compare, BinaryOperation) \
1301 M(CurrentMethod, Instruction) \
1302 M(ShouldDeoptimizeFlag, Instruction) \
1303 M(Deoptimize, Instruction) \
1304 M(Div, BinaryOperation) \
1305 M(DivZeroCheck, Instruction) \
1306 M(DoubleConstant, Constant) \
1307 M(Equal, Condition) \
1308 M(Exit, Instruction) \
1309 M(FloatConstant, Constant) \
1310 M(Goto, Instruction) \
1311 M(GreaterThan, Condition) \
1312 M(GreaterThanOrEqual, Condition) \
1313 M(If, Instruction) \
1314 M(InstanceFieldGet, Instruction) \
1315 M(InstanceFieldSet, Instruction) \
1316 M(InstanceOf, Instruction) \
1317 M(IntConstant, Constant) \
1318 M(InvokeUnresolved, Invoke) \
1319 M(InvokeInterface, Invoke) \
1320 M(InvokeStaticOrDirect, Invoke) \
1321 M(InvokeVirtual, Invoke) \
1322 M(InvokePolymorphic, Invoke) \
1323 M(LessThan, Condition) \
1324 M(LessThanOrEqual, Condition) \
1325 M(LoadClass, Instruction) \
1326 M(LoadException, Instruction) \
1327 M(LoadString, Instruction) \
1328 M(LongConstant, Constant) \
1329 M(MemoryBarrier, Instruction) \
1330 M(MonitorOperation, Instruction) \
1331 M(Mul, BinaryOperation) \
1332 M(NativeDebugInfo, Instruction) \
1333 M(Neg, UnaryOperation) \
1334 M(NewArray, Instruction) \
1335 M(NewInstance, Instruction) \
1336 M(Not, UnaryOperation) \
1337 M(NotEqual, Condition) \
1338 M(NullConstant, Instruction) \
1339 M(NullCheck, Instruction) \
1340 M(Or, BinaryOperation) \
1341 M(PackedSwitch, Instruction) \
1342 M(ParallelMove, Instruction) \
1343 M(ParameterValue, Instruction) \
1344 M(Phi, Instruction) \
1345 M(Rem, BinaryOperation) \
1346 M(Return, Instruction) \
1347 M(ReturnVoid, Instruction) \
1348 M(Ror, BinaryOperation) \
1349 M(Shl, BinaryOperation) \
1350 M(Shr, BinaryOperation) \
1351 M(StaticFieldGet, Instruction) \
1352 M(StaticFieldSet, Instruction) \
1353 M(UnresolvedInstanceFieldGet, Instruction) \
1354 M(UnresolvedInstanceFieldSet, Instruction) \
1355 M(UnresolvedStaticFieldGet, Instruction) \
1356 M(UnresolvedStaticFieldSet, Instruction) \
1357 M(Select, Instruction) \
1358 M(Sub, BinaryOperation) \
1359 M(SuspendCheck, Instruction) \
1360 M(Throw, Instruction) \
1361 M(TryBoundary, Instruction) \
1362 M(TypeConversion, Instruction) \
1363 M(UShr, BinaryOperation) \
1364 M(Xor, BinaryOperation) \
1365 M(VecReplicateScalar, VecUnaryOperation) \
1366 M(VecSumReduce, VecUnaryOperation) \
1367 M(VecCnv, VecUnaryOperation) \
1368 M(VecNeg, VecUnaryOperation) \
1369 M(VecAbs, VecUnaryOperation) \
1370 M(VecNot, VecUnaryOperation) \
1371 M(VecAdd, VecBinaryOperation) \
1372 M(VecHalvingAdd, VecBinaryOperation) \
1373 M(VecSub, VecBinaryOperation) \
1374 M(VecMul, VecBinaryOperation) \
1375 M(VecDiv, VecBinaryOperation) \
1376 M(VecMin, VecBinaryOperation) \
1377 M(VecMax, VecBinaryOperation) \
1378 M(VecAnd, VecBinaryOperation) \
1379 M(VecAndNot, VecBinaryOperation) \
1380 M(VecOr, VecBinaryOperation) \
1381 M(VecXor, VecBinaryOperation) \
1382 M(VecShl, VecBinaryOperation) \
1383 M(VecShr, VecBinaryOperation) \
1384 M(VecUShr, VecBinaryOperation) \
1385 M(VecSetScalars, VecOperation) \
1386 M(VecMultiplyAccumulate, VecOperation) \
1387 M(VecLoad, VecMemoryOperation) \
1388 M(VecStore, VecMemoryOperation) \
1389
1390 /*
1391 * Instructions, shared across several (not all) architectures.
1392 */
1393 #if !defined(ART_ENABLE_CODEGEN_arm) && !defined(ART_ENABLE_CODEGEN_arm64)
1394 #define FOR_EACH_CONCRETE_INSTRUCTION_SHARED(M)
1395 #else
1396 #define FOR_EACH_CONCRETE_INSTRUCTION_SHARED(M) \
1397 M(BitwiseNegatedRight, Instruction) \
1398 M(DataProcWithShifterOp, Instruction) \
1399 M(MultiplyAccumulate, Instruction) \
1400 M(IntermediateAddress, Instruction)
1401 #endif
1402
1403 #ifndef ART_ENABLE_CODEGEN_arm
1404 #define FOR_EACH_CONCRETE_INSTRUCTION_ARM(M)
1405 #else
1406 #define FOR_EACH_CONCRETE_INSTRUCTION_ARM(M) \
1407 M(ArmDexCacheArraysBase, Instruction)
1408 #endif
1409
1410 #define FOR_EACH_CONCRETE_INSTRUCTION_ARM64(M)
1411
1412 #ifndef ART_ENABLE_CODEGEN_mips
1413 #define FOR_EACH_CONCRETE_INSTRUCTION_MIPS(M)
1414 #else
1415 #define FOR_EACH_CONCRETE_INSTRUCTION_MIPS(M) \
1416 M(MipsComputeBaseMethodAddress, Instruction) \
1417 M(MipsDexCacheArraysBase, Instruction) \
1418 M(MipsPackedSwitch, Instruction)
1419 #endif
1420
1421 #define FOR_EACH_CONCRETE_INSTRUCTION_MIPS64(M)
1422
1423 #ifndef ART_ENABLE_CODEGEN_x86
1424 #define FOR_EACH_CONCRETE_INSTRUCTION_X86(M)
1425 #else
1426 #define FOR_EACH_CONCRETE_INSTRUCTION_X86(M) \
1427 M(X86ComputeBaseMethodAddress, Instruction) \
1428 M(X86LoadFromConstantTable, Instruction) \
1429 M(X86FPNeg, Instruction) \
1430 M(X86PackedSwitch, Instruction)
1431 #endif
1432
1433 #define FOR_EACH_CONCRETE_INSTRUCTION_X86_64(M)
1434
1435 #define FOR_EACH_CONCRETE_INSTRUCTION(M) \
1436 FOR_EACH_CONCRETE_INSTRUCTION_COMMON(M) \
1437 FOR_EACH_CONCRETE_INSTRUCTION_SHARED(M) \
1438 FOR_EACH_CONCRETE_INSTRUCTION_ARM(M) \
1439 FOR_EACH_CONCRETE_INSTRUCTION_ARM64(M) \
1440 FOR_EACH_CONCRETE_INSTRUCTION_MIPS(M) \
1441 FOR_EACH_CONCRETE_INSTRUCTION_MIPS64(M) \
1442 FOR_EACH_CONCRETE_INSTRUCTION_X86(M) \
1443 FOR_EACH_CONCRETE_INSTRUCTION_X86_64(M)
1444
1445 #define FOR_EACH_ABSTRACT_INSTRUCTION(M) \
1446 M(Condition, BinaryOperation) \
1447 M(Constant, Instruction) \
1448 M(UnaryOperation, Instruction) \
1449 M(BinaryOperation, Instruction) \
1450 M(Invoke, Instruction) \
1451 M(VecOperation, Instruction) \
1452 M(VecUnaryOperation, VecOperation) \
1453 M(VecBinaryOperation, VecOperation) \
1454 M(VecMemoryOperation, VecOperation)
1455
1456 #define FOR_EACH_INSTRUCTION(M) \
1457 FOR_EACH_CONCRETE_INSTRUCTION(M) \
1458 FOR_EACH_ABSTRACT_INSTRUCTION(M)
1459
1460 #define FORWARD_DECLARATION(type, super) class H##type;
FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)1461 FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
1462 #undef FORWARD_DECLARATION
1463
1464 #define DECLARE_INSTRUCTION(type) \
1465 InstructionKind GetKindInternal() const OVERRIDE { return k##type; } \
1466 const char* DebugName() const OVERRIDE { return #type; } \
1467 bool InstructionTypeEquals(const HInstruction* other) const OVERRIDE { \
1468 return other->Is##type(); \
1469 } \
1470 void Accept(HGraphVisitor* visitor) OVERRIDE
1471
1472 #define DECLARE_ABSTRACT_INSTRUCTION(type) \
1473 bool Is##type() const { return As##type() != nullptr; } \
1474 const H##type* As##type() const { return this; } \
1475 H##type* As##type() { return this; }
1476
1477 template <typename T>
1478 class HUseListNode : public ArenaObject<kArenaAllocUseListNode> {
1479 public:
1480 T GetUser() const { return user_; }
1481 size_t GetIndex() const { return index_; }
1482 void SetIndex(size_t index) { index_ = index; }
1483
1484 // Hook for the IntrusiveForwardList<>.
1485 // TODO: Hide this better.
1486 IntrusiveForwardListHook hook;
1487
1488 private:
1489 HUseListNode(T user, size_t index)
1490 : user_(user), index_(index) {}
1491
1492 T const user_;
1493 size_t index_;
1494
1495 friend class HInstruction;
1496
1497 DISALLOW_COPY_AND_ASSIGN(HUseListNode);
1498 };
1499
1500 template <typename T>
1501 using HUseList = IntrusiveForwardList<HUseListNode<T>>;
1502
1503 // This class is used by HEnvironment and HInstruction classes to record the
1504 // instructions they use and pointers to the corresponding HUseListNodes kept
1505 // by the used instructions.
1506 template <typename T>
1507 class HUserRecord : public ValueObject {
1508 public:
HUserRecord()1509 HUserRecord() : instruction_(nullptr), before_use_node_() {}
HUserRecord(HInstruction * instruction)1510 explicit HUserRecord(HInstruction* instruction) : instruction_(instruction), before_use_node_() {}
1511
HUserRecord(const HUserRecord<T> & old_record,typename HUseList<T>::iterator before_use_node)1512 HUserRecord(const HUserRecord<T>& old_record, typename HUseList<T>::iterator before_use_node)
1513 : HUserRecord(old_record.instruction_, before_use_node) {}
HUserRecord(HInstruction * instruction,typename HUseList<T>::iterator before_use_node)1514 HUserRecord(HInstruction* instruction, typename HUseList<T>::iterator before_use_node)
1515 : instruction_(instruction), before_use_node_(before_use_node) {
1516 DCHECK(instruction_ != nullptr);
1517 }
1518
GetInstruction()1519 HInstruction* GetInstruction() const { return instruction_; }
GetBeforeUseNode()1520 typename HUseList<T>::iterator GetBeforeUseNode() const { return before_use_node_; }
GetUseNode()1521 typename HUseList<T>::iterator GetUseNode() const { return ++GetBeforeUseNode(); }
1522
1523 private:
1524 // Instruction used by the user.
1525 HInstruction* instruction_;
1526
1527 // Iterator before the corresponding entry in the use list kept by 'instruction_'.
1528 typename HUseList<T>::iterator before_use_node_;
1529 };
1530
1531 // Helper class that extracts the input instruction from HUserRecord<HInstruction*>.
1532 // This is used for HInstruction::GetInputs() to return a container wrapper providing
1533 // HInstruction* values even though the underlying container has HUserRecord<>s.
1534 struct HInputExtractor {
operatorHInputExtractor1535 HInstruction* operator()(HUserRecord<HInstruction*>& record) const {
1536 return record.GetInstruction();
1537 }
operatorHInputExtractor1538 const HInstruction* operator()(const HUserRecord<HInstruction*>& record) const {
1539 return record.GetInstruction();
1540 }
1541 };
1542
1543 using HInputsRef = TransformArrayRef<HUserRecord<HInstruction*>, HInputExtractor>;
1544 using HConstInputsRef = TransformArrayRef<const HUserRecord<HInstruction*>, HInputExtractor>;
1545
1546 /**
1547 * Side-effects representation.
1548 *
1549 * For write/read dependences on fields/arrays, the dependence analysis uses
1550 * type disambiguation (e.g. a float field write cannot modify the value of an
1551 * integer field read) and the access type (e.g. a reference array write cannot
1552 * modify the value of a reference field read [although it may modify the
1553 * reference fetch prior to reading the field, which is represented by its own
1554 * write/read dependence]). The analysis makes conservative points-to
1555 * assumptions on reference types (e.g. two same typed arrays are assumed to be
1556 * the same, and any reference read depends on any reference read without
1557 * further regard of its type).
1558 *
1559 * The internal representation uses 38-bit and is described in the table below.
1560 * The first line indicates the side effect, and for field/array accesses the
1561 * second line indicates the type of the access (in the order of the
1562 * Primitive::Type enum).
1563 * The two numbered lines below indicate the bit position in the bitfield (read
1564 * vertically).
1565 *
1566 * |Depends on GC|ARRAY-R |FIELD-R |Can trigger GC|ARRAY-W |FIELD-W |
1567 * +-------------+---------+---------+--------------+---------+---------+
1568 * | |DFJISCBZL|DFJISCBZL| |DFJISCBZL|DFJISCBZL|
1569 * | 3 |333333322|222222221| 1 |111111110|000000000|
1570 * | 7 |654321098|765432109| 8 |765432109|876543210|
1571 *
1572 * Note that, to ease the implementation, 'changes' bits are least significant
1573 * bits, while 'dependency' bits are most significant bits.
1574 */
1575 class SideEffects : public ValueObject {
1576 public:
SideEffects()1577 SideEffects() : flags_(0) {}
1578
None()1579 static SideEffects None() {
1580 return SideEffects(0);
1581 }
1582
All()1583 static SideEffects All() {
1584 return SideEffects(kAllChangeBits | kAllDependOnBits);
1585 }
1586
AllChanges()1587 static SideEffects AllChanges() {
1588 return SideEffects(kAllChangeBits);
1589 }
1590
AllDependencies()1591 static SideEffects AllDependencies() {
1592 return SideEffects(kAllDependOnBits);
1593 }
1594
AllExceptGCDependency()1595 static SideEffects AllExceptGCDependency() {
1596 return AllWritesAndReads().Union(SideEffects::CanTriggerGC());
1597 }
1598
AllWritesAndReads()1599 static SideEffects AllWritesAndReads() {
1600 return SideEffects(kAllWrites | kAllReads);
1601 }
1602
AllWrites()1603 static SideEffects AllWrites() {
1604 return SideEffects(kAllWrites);
1605 }
1606
AllReads()1607 static SideEffects AllReads() {
1608 return SideEffects(kAllReads);
1609 }
1610
FieldWriteOfType(Primitive::Type type,bool is_volatile)1611 static SideEffects FieldWriteOfType(Primitive::Type type, bool is_volatile) {
1612 return is_volatile
1613 ? AllWritesAndReads()
1614 : SideEffects(TypeFlag(type, kFieldWriteOffset));
1615 }
1616
ArrayWriteOfType(Primitive::Type type)1617 static SideEffects ArrayWriteOfType(Primitive::Type type) {
1618 return SideEffects(TypeFlag(type, kArrayWriteOffset));
1619 }
1620
FieldReadOfType(Primitive::Type type,bool is_volatile)1621 static SideEffects FieldReadOfType(Primitive::Type type, bool is_volatile) {
1622 return is_volatile
1623 ? AllWritesAndReads()
1624 : SideEffects(TypeFlag(type, kFieldReadOffset));
1625 }
1626
ArrayReadOfType(Primitive::Type type)1627 static SideEffects ArrayReadOfType(Primitive::Type type) {
1628 return SideEffects(TypeFlag(type, kArrayReadOffset));
1629 }
1630
CanTriggerGC()1631 static SideEffects CanTriggerGC() {
1632 return SideEffects(1ULL << kCanTriggerGCBit);
1633 }
1634
DependsOnGC()1635 static SideEffects DependsOnGC() {
1636 return SideEffects(1ULL << kDependsOnGCBit);
1637 }
1638
1639 // Combines the side-effects of this and the other.
Union(SideEffects other)1640 SideEffects Union(SideEffects other) const {
1641 return SideEffects(flags_ | other.flags_);
1642 }
1643
Exclusion(SideEffects other)1644 SideEffects Exclusion(SideEffects other) const {
1645 return SideEffects(flags_ & ~other.flags_);
1646 }
1647
Add(SideEffects other)1648 void Add(SideEffects other) {
1649 flags_ |= other.flags_;
1650 }
1651
Includes(SideEffects other)1652 bool Includes(SideEffects other) const {
1653 return (other.flags_ & flags_) == other.flags_;
1654 }
1655
HasSideEffects()1656 bool HasSideEffects() const {
1657 return (flags_ & kAllChangeBits);
1658 }
1659
HasDependencies()1660 bool HasDependencies() const {
1661 return (flags_ & kAllDependOnBits);
1662 }
1663
1664 // Returns true if there are no side effects or dependencies.
DoesNothing()1665 bool DoesNothing() const {
1666 return flags_ == 0;
1667 }
1668
1669 // Returns true if something is written.
DoesAnyWrite()1670 bool DoesAnyWrite() const {
1671 return (flags_ & kAllWrites);
1672 }
1673
1674 // Returns true if something is read.
DoesAnyRead()1675 bool DoesAnyRead() const {
1676 return (flags_ & kAllReads);
1677 }
1678
1679 // Returns true if potentially everything is written and read
1680 // (every type and every kind of access).
DoesAllReadWrite()1681 bool DoesAllReadWrite() const {
1682 return (flags_ & (kAllWrites | kAllReads)) == (kAllWrites | kAllReads);
1683 }
1684
DoesAll()1685 bool DoesAll() const {
1686 return flags_ == (kAllChangeBits | kAllDependOnBits);
1687 }
1688
1689 // Returns true if `this` may read something written by `other`.
MayDependOn(SideEffects other)1690 bool MayDependOn(SideEffects other) const {
1691 const uint64_t depends_on_flags = (flags_ & kAllDependOnBits) >> kChangeBits;
1692 return (other.flags_ & depends_on_flags);
1693 }
1694
1695 // Returns string representation of flags (for debugging only).
1696 // Format: |x|DFJISCBZL|DFJISCBZL|y|DFJISCBZL|DFJISCBZL|
ToString()1697 std::string ToString() const {
1698 std::string flags = "|";
1699 for (int s = kLastBit; s >= 0; s--) {
1700 bool current_bit_is_set = ((flags_ >> s) & 1) != 0;
1701 if ((s == kDependsOnGCBit) || (s == kCanTriggerGCBit)) {
1702 // This is a bit for the GC side effect.
1703 if (current_bit_is_set) {
1704 flags += "GC";
1705 }
1706 flags += "|";
1707 } else {
1708 // This is a bit for the array/field analysis.
1709 // The underscore character stands for the 'can trigger GC' bit.
1710 static const char *kDebug = "LZBCSIJFDLZBCSIJFD_LZBCSIJFDLZBCSIJFD";
1711 if (current_bit_is_set) {
1712 flags += kDebug[s];
1713 }
1714 if ((s == kFieldWriteOffset) || (s == kArrayWriteOffset) ||
1715 (s == kFieldReadOffset) || (s == kArrayReadOffset)) {
1716 flags += "|";
1717 }
1718 }
1719 }
1720 return flags;
1721 }
1722
Equals(const SideEffects & other)1723 bool Equals(const SideEffects& other) const { return flags_ == other.flags_; }
1724
1725 private:
1726 static constexpr int kFieldArrayAnalysisBits = 9;
1727
1728 static constexpr int kFieldWriteOffset = 0;
1729 static constexpr int kArrayWriteOffset = kFieldWriteOffset + kFieldArrayAnalysisBits;
1730 static constexpr int kLastBitForWrites = kArrayWriteOffset + kFieldArrayAnalysisBits - 1;
1731 static constexpr int kCanTriggerGCBit = kLastBitForWrites + 1;
1732
1733 static constexpr int kChangeBits = kCanTriggerGCBit + 1;
1734
1735 static constexpr int kFieldReadOffset = kCanTriggerGCBit + 1;
1736 static constexpr int kArrayReadOffset = kFieldReadOffset + kFieldArrayAnalysisBits;
1737 static constexpr int kLastBitForReads = kArrayReadOffset + kFieldArrayAnalysisBits - 1;
1738 static constexpr int kDependsOnGCBit = kLastBitForReads + 1;
1739
1740 static constexpr int kLastBit = kDependsOnGCBit;
1741 static constexpr int kDependOnBits = kLastBit + 1 - kChangeBits;
1742
1743 // Aliases.
1744
1745 static_assert(kChangeBits == kDependOnBits,
1746 "the 'change' bits should match the 'depend on' bits.");
1747
1748 static constexpr uint64_t kAllChangeBits = ((1ULL << kChangeBits) - 1);
1749 static constexpr uint64_t kAllDependOnBits = ((1ULL << kDependOnBits) - 1) << kChangeBits;
1750 static constexpr uint64_t kAllWrites =
1751 ((1ULL << (kLastBitForWrites + 1 - kFieldWriteOffset)) - 1) << kFieldWriteOffset;
1752 static constexpr uint64_t kAllReads =
1753 ((1ULL << (kLastBitForReads + 1 - kFieldReadOffset)) - 1) << kFieldReadOffset;
1754
1755 // Translates type to bit flag.
TypeFlag(Primitive::Type type,int offset)1756 static uint64_t TypeFlag(Primitive::Type type, int offset) {
1757 CHECK_NE(type, Primitive::kPrimVoid);
1758 const uint64_t one = 1;
1759 const int shift = type; // 0-based consecutive enum
1760 DCHECK_LE(kFieldWriteOffset, shift);
1761 DCHECK_LT(shift, kArrayWriteOffset);
1762 return one << (type + offset);
1763 }
1764
1765 // Private constructor on direct flags value.
SideEffects(uint64_t flags)1766 explicit SideEffects(uint64_t flags) : flags_(flags) {}
1767
1768 uint64_t flags_;
1769 };
1770
1771 // A HEnvironment object contains the values of virtual registers at a given location.
1772 class HEnvironment : public ArenaObject<kArenaAllocEnvironment> {
1773 public:
HEnvironment(ArenaAllocator * arena,size_t number_of_vregs,ArtMethod * method,uint32_t dex_pc,HInstruction * holder)1774 ALWAYS_INLINE HEnvironment(ArenaAllocator* arena,
1775 size_t number_of_vregs,
1776 ArtMethod* method,
1777 uint32_t dex_pc,
1778 HInstruction* holder)
1779 : vregs_(number_of_vregs, arena->Adapter(kArenaAllocEnvironmentVRegs)),
1780 locations_(number_of_vregs, arena->Adapter(kArenaAllocEnvironmentLocations)),
1781 parent_(nullptr),
1782 method_(method),
1783 dex_pc_(dex_pc),
1784 holder_(holder) {
1785 }
1786
HEnvironment(ArenaAllocator * arena,const HEnvironment & to_copy,HInstruction * holder)1787 ALWAYS_INLINE HEnvironment(ArenaAllocator* arena, const HEnvironment& to_copy, HInstruction* holder)
1788 : HEnvironment(arena,
1789 to_copy.Size(),
1790 to_copy.GetMethod(),
1791 to_copy.GetDexPc(),
1792 holder) {}
1793
SetAndCopyParentChain(ArenaAllocator * allocator,HEnvironment * parent)1794 void SetAndCopyParentChain(ArenaAllocator* allocator, HEnvironment* parent) {
1795 if (parent_ != nullptr) {
1796 parent_->SetAndCopyParentChain(allocator, parent);
1797 } else {
1798 parent_ = new (allocator) HEnvironment(allocator, *parent, holder_);
1799 parent_->CopyFrom(parent);
1800 if (parent->GetParent() != nullptr) {
1801 parent_->SetAndCopyParentChain(allocator, parent->GetParent());
1802 }
1803 }
1804 }
1805
1806 void CopyFrom(const ArenaVector<HInstruction*>& locals);
1807 void CopyFrom(HEnvironment* environment);
1808
1809 // Copy from `env`. If it's a loop phi for `loop_header`, copy the first
1810 // input to the loop phi instead. This is for inserting instructions that
1811 // require an environment (like HDeoptimization) in the loop pre-header.
1812 void CopyFromWithLoopPhiAdjustment(HEnvironment* env, HBasicBlock* loop_header);
1813
SetRawEnvAt(size_t index,HInstruction * instruction)1814 void SetRawEnvAt(size_t index, HInstruction* instruction) {
1815 vregs_[index] = HUserRecord<HEnvironment*>(instruction);
1816 }
1817
GetInstructionAt(size_t index)1818 HInstruction* GetInstructionAt(size_t index) const {
1819 return vregs_[index].GetInstruction();
1820 }
1821
1822 void RemoveAsUserOfInput(size_t index) const;
1823
Size()1824 size_t Size() const { return vregs_.size(); }
1825
GetParent()1826 HEnvironment* GetParent() const { return parent_; }
1827
SetLocationAt(size_t index,Location location)1828 void SetLocationAt(size_t index, Location location) {
1829 locations_[index] = location;
1830 }
1831
GetLocationAt(size_t index)1832 Location GetLocationAt(size_t index) const {
1833 return locations_[index];
1834 }
1835
GetDexPc()1836 uint32_t GetDexPc() const {
1837 return dex_pc_;
1838 }
1839
GetMethod()1840 ArtMethod* GetMethod() const {
1841 return method_;
1842 }
1843
GetHolder()1844 HInstruction* GetHolder() const {
1845 return holder_;
1846 }
1847
1848
IsFromInlinedInvoke()1849 bool IsFromInlinedInvoke() const {
1850 return GetParent() != nullptr;
1851 }
1852
1853 private:
1854 ArenaVector<HUserRecord<HEnvironment*>> vregs_;
1855 ArenaVector<Location> locations_;
1856 HEnvironment* parent_;
1857 ArtMethod* method_;
1858 const uint32_t dex_pc_;
1859
1860 // The instruction that holds this environment.
1861 HInstruction* const holder_;
1862
1863 friend class HInstruction;
1864
1865 DISALLOW_COPY_AND_ASSIGN(HEnvironment);
1866 };
1867
1868 class HInstruction : public ArenaObject<kArenaAllocInstruction> {
1869 public:
HInstruction(SideEffects side_effects,uint32_t dex_pc)1870 HInstruction(SideEffects side_effects, uint32_t dex_pc)
1871 : previous_(nullptr),
1872 next_(nullptr),
1873 block_(nullptr),
1874 dex_pc_(dex_pc),
1875 id_(-1),
1876 ssa_index_(-1),
1877 packed_fields_(0u),
1878 environment_(nullptr),
1879 locations_(nullptr),
1880 live_interval_(nullptr),
1881 lifetime_position_(kNoLifetime),
1882 side_effects_(side_effects),
1883 reference_type_handle_(ReferenceTypeInfo::CreateInvalid().GetTypeHandle()) {
1884 SetPackedFlag<kFlagReferenceTypeIsExact>(ReferenceTypeInfo::CreateInvalid().IsExact());
1885 }
1886
~HInstruction()1887 virtual ~HInstruction() {}
1888
1889 #define DECLARE_KIND(type, super) k##type,
1890 enum InstructionKind {
1891 FOR_EACH_INSTRUCTION(DECLARE_KIND)
1892 };
1893 #undef DECLARE_KIND
1894
GetNext()1895 HInstruction* GetNext() const { return next_; }
GetPrevious()1896 HInstruction* GetPrevious() const { return previous_; }
1897
1898 HInstruction* GetNextDisregardingMoves() const;
1899 HInstruction* GetPreviousDisregardingMoves() const;
1900
GetBlock()1901 HBasicBlock* GetBlock() const { return block_; }
GetArena()1902 ArenaAllocator* GetArena() const { return block_->GetGraph()->GetArena(); }
SetBlock(HBasicBlock * block)1903 void SetBlock(HBasicBlock* block) { block_ = block; }
IsInBlock()1904 bool IsInBlock() const { return block_ != nullptr; }
IsInLoop()1905 bool IsInLoop() const { return block_->IsInLoop(); }
IsLoopHeaderPhi()1906 bool IsLoopHeaderPhi() const { return IsPhi() && block_->IsLoopHeader(); }
IsIrreducibleLoopHeaderPhi()1907 bool IsIrreducibleLoopHeaderPhi() const {
1908 return IsLoopHeaderPhi() && GetBlock()->GetLoopInformation()->IsIrreducible();
1909 }
1910
1911 virtual ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() = 0;
1912
GetInputRecords()1913 ArrayRef<const HUserRecord<HInstruction*>> GetInputRecords() const {
1914 // One virtual method is enough, just const_cast<> and then re-add the const.
1915 return ArrayRef<const HUserRecord<HInstruction*>>(
1916 const_cast<HInstruction*>(this)->GetInputRecords());
1917 }
1918
GetInputs()1919 HInputsRef GetInputs() {
1920 return MakeTransformArrayRef(GetInputRecords(), HInputExtractor());
1921 }
1922
GetInputs()1923 HConstInputsRef GetInputs() const {
1924 return MakeTransformArrayRef(GetInputRecords(), HInputExtractor());
1925 }
1926
InputCount()1927 size_t InputCount() const { return GetInputRecords().size(); }
InputAt(size_t i)1928 HInstruction* InputAt(size_t i) const { return InputRecordAt(i).GetInstruction(); }
1929
HasInput(HInstruction * input)1930 bool HasInput(HInstruction* input) const {
1931 for (const HInstruction* i : GetInputs()) {
1932 if (i == input) {
1933 return true;
1934 }
1935 }
1936 return false;
1937 }
1938
SetRawInputAt(size_t index,HInstruction * input)1939 void SetRawInputAt(size_t index, HInstruction* input) {
1940 SetRawInputRecordAt(index, HUserRecord<HInstruction*>(input));
1941 }
1942
1943 virtual void Accept(HGraphVisitor* visitor) = 0;
1944 virtual const char* DebugName() const = 0;
1945
GetType()1946 virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
1947
NeedsEnvironment()1948 virtual bool NeedsEnvironment() const { return false; }
1949
GetDexPc()1950 uint32_t GetDexPc() const { return dex_pc_; }
1951
IsControlFlow()1952 virtual bool IsControlFlow() const { return false; }
1953
1954 // Can the instruction throw?
1955 // TODO: We should rename to CanVisiblyThrow, as some instructions (like HNewInstance),
1956 // could throw OOME, but it is still OK to remove them if they are unused.
CanThrow()1957 virtual bool CanThrow() const { return false; }
CanThrowIntoCatchBlock()1958 bool CanThrowIntoCatchBlock() const { return CanThrow() && block_->IsTryBlock(); }
1959
HasSideEffects()1960 bool HasSideEffects() const { return side_effects_.HasSideEffects(); }
DoesAnyWrite()1961 bool DoesAnyWrite() const { return side_effects_.DoesAnyWrite(); }
1962
1963 // Does not apply for all instructions, but having this at top level greatly
1964 // simplifies the null check elimination.
1965 // TODO: Consider merging can_be_null into ReferenceTypeInfo.
CanBeNull()1966 virtual bool CanBeNull() const {
1967 DCHECK_EQ(GetType(), Primitive::kPrimNot) << "CanBeNull only applies to reference types";
1968 return true;
1969 }
1970
CanDoImplicitNullCheckOn(HInstruction * obj ATTRIBUTE_UNUSED)1971 virtual bool CanDoImplicitNullCheckOn(HInstruction* obj ATTRIBUTE_UNUSED) const {
1972 return false;
1973 }
1974
IsActualObject()1975 virtual bool IsActualObject() const {
1976 return GetType() == Primitive::kPrimNot;
1977 }
1978
1979 void SetReferenceTypeInfo(ReferenceTypeInfo rti);
1980
GetReferenceTypeInfo()1981 ReferenceTypeInfo GetReferenceTypeInfo() const {
1982 DCHECK_EQ(GetType(), Primitive::kPrimNot);
1983 return ReferenceTypeInfo::CreateUnchecked(reference_type_handle_,
1984 GetPackedFlag<kFlagReferenceTypeIsExact>());
1985 }
1986
AddUseAt(HInstruction * user,size_t index)1987 void AddUseAt(HInstruction* user, size_t index) {
1988 DCHECK(user != nullptr);
1989 // Note: fixup_end remains valid across push_front().
1990 auto fixup_end = uses_.empty() ? uses_.begin() : ++uses_.begin();
1991 HUseListNode<HInstruction*>* new_node =
1992 new (GetBlock()->GetGraph()->GetArena()) HUseListNode<HInstruction*>(user, index);
1993 uses_.push_front(*new_node);
1994 FixUpUserRecordsAfterUseInsertion(fixup_end);
1995 }
1996
AddEnvUseAt(HEnvironment * user,size_t index)1997 void AddEnvUseAt(HEnvironment* user, size_t index) {
1998 DCHECK(user != nullptr);
1999 // Note: env_fixup_end remains valid across push_front().
2000 auto env_fixup_end = env_uses_.empty() ? env_uses_.begin() : ++env_uses_.begin();
2001 HUseListNode<HEnvironment*>* new_node =
2002 new (GetBlock()->GetGraph()->GetArena()) HUseListNode<HEnvironment*>(user, index);
2003 env_uses_.push_front(*new_node);
2004 FixUpUserRecordsAfterEnvUseInsertion(env_fixup_end);
2005 }
2006
RemoveAsUserOfInput(size_t input)2007 void RemoveAsUserOfInput(size_t input) {
2008 HUserRecord<HInstruction*> input_use = InputRecordAt(input);
2009 HUseList<HInstruction*>::iterator before_use_node = input_use.GetBeforeUseNode();
2010 input_use.GetInstruction()->uses_.erase_after(before_use_node);
2011 input_use.GetInstruction()->FixUpUserRecordsAfterUseRemoval(before_use_node);
2012 }
2013
RemoveAsUserOfAllInputs()2014 void RemoveAsUserOfAllInputs() {
2015 for (const HUserRecord<HInstruction*>& input_use : GetInputRecords()) {
2016 HUseList<HInstruction*>::iterator before_use_node = input_use.GetBeforeUseNode();
2017 input_use.GetInstruction()->uses_.erase_after(before_use_node);
2018 input_use.GetInstruction()->FixUpUserRecordsAfterUseRemoval(before_use_node);
2019 }
2020 }
2021
GetUses()2022 const HUseList<HInstruction*>& GetUses() const { return uses_; }
GetEnvUses()2023 const HUseList<HEnvironment*>& GetEnvUses() const { return env_uses_; }
2024
HasUses()2025 bool HasUses() const { return !uses_.empty() || !env_uses_.empty(); }
HasEnvironmentUses()2026 bool HasEnvironmentUses() const { return !env_uses_.empty(); }
HasNonEnvironmentUses()2027 bool HasNonEnvironmentUses() const { return !uses_.empty(); }
HasOnlyOneNonEnvironmentUse()2028 bool HasOnlyOneNonEnvironmentUse() const {
2029 return !HasEnvironmentUses() && GetUses().HasExactlyOneElement();
2030 }
2031
IsRemovable()2032 bool IsRemovable() const {
2033 return
2034 !DoesAnyWrite() &&
2035 !CanThrow() &&
2036 !IsSuspendCheck() &&
2037 !IsControlFlow() &&
2038 !IsNativeDebugInfo() &&
2039 !IsParameterValue() &&
2040 // If we added an explicit barrier then we should keep it.
2041 !IsMemoryBarrier();
2042 }
2043
IsDeadAndRemovable()2044 bool IsDeadAndRemovable() const {
2045 return IsRemovable() && !HasUses();
2046 }
2047
2048 // Does this instruction strictly dominate `other_instruction`?
2049 // Returns false if this instruction and `other_instruction` are the same.
2050 // Aborts if this instruction and `other_instruction` are both phis.
2051 bool StrictlyDominates(HInstruction* other_instruction) const;
2052
GetId()2053 int GetId() const { return id_; }
SetId(int id)2054 void SetId(int id) { id_ = id; }
2055
GetSsaIndex()2056 int GetSsaIndex() const { return ssa_index_; }
SetSsaIndex(int ssa_index)2057 void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
HasSsaIndex()2058 bool HasSsaIndex() const { return ssa_index_ != -1; }
2059
HasEnvironment()2060 bool HasEnvironment() const { return environment_ != nullptr; }
GetEnvironment()2061 HEnvironment* GetEnvironment() const { return environment_; }
2062 // Set the `environment_` field. Raw because this method does not
2063 // update the uses lists.
SetRawEnvironment(HEnvironment * environment)2064 void SetRawEnvironment(HEnvironment* environment) {
2065 DCHECK(environment_ == nullptr);
2066 DCHECK_EQ(environment->GetHolder(), this);
2067 environment_ = environment;
2068 }
2069
InsertRawEnvironment(HEnvironment * environment)2070 void InsertRawEnvironment(HEnvironment* environment) {
2071 DCHECK(environment_ != nullptr);
2072 DCHECK_EQ(environment->GetHolder(), this);
2073 DCHECK(environment->GetParent() == nullptr);
2074 environment->parent_ = environment_;
2075 environment_ = environment;
2076 }
2077
2078 void RemoveEnvironment();
2079
2080 // Set the environment of this instruction, copying it from `environment`. While
2081 // copying, the uses lists are being updated.
CopyEnvironmentFrom(HEnvironment * environment)2082 void CopyEnvironmentFrom(HEnvironment* environment) {
2083 DCHECK(environment_ == nullptr);
2084 ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena();
2085 environment_ = new (allocator) HEnvironment(allocator, *environment, this);
2086 environment_->CopyFrom(environment);
2087 if (environment->GetParent() != nullptr) {
2088 environment_->SetAndCopyParentChain(allocator, environment->GetParent());
2089 }
2090 }
2091
CopyEnvironmentFromWithLoopPhiAdjustment(HEnvironment * environment,HBasicBlock * block)2092 void CopyEnvironmentFromWithLoopPhiAdjustment(HEnvironment* environment,
2093 HBasicBlock* block) {
2094 DCHECK(environment_ == nullptr);
2095 ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena();
2096 environment_ = new (allocator) HEnvironment(allocator, *environment, this);
2097 environment_->CopyFromWithLoopPhiAdjustment(environment, block);
2098 if (environment->GetParent() != nullptr) {
2099 environment_->SetAndCopyParentChain(allocator, environment->GetParent());
2100 }
2101 }
2102
2103 // Returns the number of entries in the environment. Typically, that is the
2104 // number of dex registers in a method. It could be more in case of inlining.
2105 size_t EnvironmentSize() const;
2106
GetLocations()2107 LocationSummary* GetLocations() const { return locations_; }
SetLocations(LocationSummary * locations)2108 void SetLocations(LocationSummary* locations) { locations_ = locations; }
2109
2110 void ReplaceWith(HInstruction* instruction);
2111 void ReplaceUsesDominatedBy(HInstruction* dominator, HInstruction* replacement);
2112 void ReplaceInput(HInstruction* replacement, size_t index);
2113
2114 // This is almost the same as doing `ReplaceWith()`. But in this helper, the
2115 // uses of this instruction by `other` are *not* updated.
ReplaceWithExceptInReplacementAtIndex(HInstruction * other,size_t use_index)2116 void ReplaceWithExceptInReplacementAtIndex(HInstruction* other, size_t use_index) {
2117 ReplaceWith(other);
2118 other->ReplaceInput(this, use_index);
2119 }
2120
2121 // Move `this` instruction before `cursor`
2122 void MoveBefore(HInstruction* cursor, bool do_checks = true);
2123
2124 // Move `this` before its first user and out of any loops. If there is no
2125 // out-of-loop user that dominates all other users, move the instruction
2126 // to the end of the out-of-loop common dominator of the user's blocks.
2127 //
2128 // This can be used only on non-throwing instructions with no side effects that
2129 // have at least one use but no environment uses.
2130 void MoveBeforeFirstUserAndOutOfLoops();
2131
2132 #define INSTRUCTION_TYPE_CHECK(type, super) \
2133 bool Is##type() const; \
2134 const H##type* As##type() const; \
2135 H##type* As##type();
2136
2137 FOR_EACH_CONCRETE_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
2138 #undef INSTRUCTION_TYPE_CHECK
2139
2140 #define INSTRUCTION_TYPE_CHECK(type, super) \
2141 bool Is##type() const { return (As##type() != nullptr); } \
2142 virtual const H##type* As##type() const { return nullptr; } \
2143 virtual H##type* As##type() { return nullptr; }
FOR_EACH_ABSTRACT_INSTRUCTION(INSTRUCTION_TYPE_CHECK)2144 FOR_EACH_ABSTRACT_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
2145 #undef INSTRUCTION_TYPE_CHECK
2146
2147 // Returns whether the instruction can be moved within the graph.
2148 // TODO: this method is used by LICM and GVN with possibly different
2149 // meanings? split and rename?
2150 virtual bool CanBeMoved() const { return false; }
2151
2152 // Returns whether the two instructions are of the same kind.
InstructionTypeEquals(const HInstruction * other ATTRIBUTE_UNUSED)2153 virtual bool InstructionTypeEquals(const HInstruction* other ATTRIBUTE_UNUSED) const {
2154 return false;
2155 }
2156
2157 // Returns whether any data encoded in the two instructions is equal.
2158 // This method does not look at the inputs. Both instructions must be
2159 // of the same type, otherwise the method has undefined behavior.
InstructionDataEquals(const HInstruction * other ATTRIBUTE_UNUSED)2160 virtual bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const {
2161 return false;
2162 }
2163
2164 // Returns whether two instructions are equal, that is:
2165 // 1) They have the same type and contain the same data (InstructionDataEquals).
2166 // 2) Their inputs are identical.
2167 bool Equals(const HInstruction* other) const;
2168
2169 // TODO: Remove this indirection when the [[pure]] attribute proposal (n3744)
2170 // is adopted and implemented by our C++ compiler(s). Fow now, we need to hide
2171 // the virtual function because the __attribute__((__pure__)) doesn't really
2172 // apply the strong requirement for virtual functions, preventing optimizations.
2173 InstructionKind GetKind() const PURE;
2174 virtual InstructionKind GetKindInternal() const = 0;
2175
ComputeHashCode()2176 virtual size_t ComputeHashCode() const {
2177 size_t result = GetKind();
2178 for (const HInstruction* input : GetInputs()) {
2179 result = (result * 31) + input->GetId();
2180 }
2181 return result;
2182 }
2183
GetSideEffects()2184 SideEffects GetSideEffects() const { return side_effects_; }
SetSideEffects(SideEffects other)2185 void SetSideEffects(SideEffects other) { side_effects_ = other; }
AddSideEffects(SideEffects other)2186 void AddSideEffects(SideEffects other) { side_effects_.Add(other); }
2187
GetLifetimePosition()2188 size_t GetLifetimePosition() const { return lifetime_position_; }
SetLifetimePosition(size_t position)2189 void SetLifetimePosition(size_t position) { lifetime_position_ = position; }
GetLiveInterval()2190 LiveInterval* GetLiveInterval() const { return live_interval_; }
SetLiveInterval(LiveInterval * interval)2191 void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; }
HasLiveInterval()2192 bool HasLiveInterval() const { return live_interval_ != nullptr; }
2193
IsSuspendCheckEntry()2194 bool IsSuspendCheckEntry() const { return IsSuspendCheck() && GetBlock()->IsEntryBlock(); }
2195
2196 // Returns whether the code generation of the instruction will require to have access
2197 // to the current method. Such instructions are:
2198 // (1): Instructions that require an environment, as calling the runtime requires
2199 // to walk the stack and have the current method stored at a specific stack address.
2200 // (2): HCurrentMethod, potentially used by HInvokeStaticOrDirect, HLoadString, or HLoadClass
2201 // to access the dex cache.
NeedsCurrentMethod()2202 bool NeedsCurrentMethod() const {
2203 return NeedsEnvironment() || IsCurrentMethod();
2204 }
2205
2206 // Returns whether the code generation of the instruction will require to have access
2207 // to the dex cache of the current method's declaring class via the current method.
NeedsDexCacheOfDeclaringClass()2208 virtual bool NeedsDexCacheOfDeclaringClass() const { return false; }
2209
2210 // Does this instruction have any use in an environment before
2211 // control flow hits 'other'?
2212 bool HasAnyEnvironmentUseBefore(HInstruction* other);
2213
2214 // Remove all references to environment uses of this instruction.
2215 // The caller must ensure that this is safe to do.
2216 void RemoveEnvironmentUsers();
2217
IsEmittedAtUseSite()2218 bool IsEmittedAtUseSite() const { return GetPackedFlag<kFlagEmittedAtUseSite>(); }
MarkEmittedAtUseSite()2219 void MarkEmittedAtUseSite() { SetPackedFlag<kFlagEmittedAtUseSite>(true); }
2220
2221 protected:
2222 // If set, the machine code for this instruction is assumed to be generated by
2223 // its users. Used by liveness analysis to compute use positions accordingly.
2224 static constexpr size_t kFlagEmittedAtUseSite = 0u;
2225 static constexpr size_t kFlagReferenceTypeIsExact = kFlagEmittedAtUseSite + 1;
2226 static constexpr size_t kNumberOfGenericPackedBits = kFlagReferenceTypeIsExact + 1;
2227 static constexpr size_t kMaxNumberOfPackedBits = sizeof(uint32_t) * kBitsPerByte;
2228
InputRecordAt(size_t i)2229 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const {
2230 return GetInputRecords()[i];
2231 }
2232
SetRawInputRecordAt(size_t index,const HUserRecord<HInstruction * > & input)2233 void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) {
2234 ArrayRef<HUserRecord<HInstruction*>> input_records = GetInputRecords();
2235 input_records[index] = input;
2236 }
2237
GetPackedFields()2238 uint32_t GetPackedFields() const {
2239 return packed_fields_;
2240 }
2241
2242 template <size_t flag>
GetPackedFlag()2243 bool GetPackedFlag() const {
2244 return (packed_fields_ & (1u << flag)) != 0u;
2245 }
2246
2247 template <size_t flag>
2248 void SetPackedFlag(bool value = true) {
2249 packed_fields_ = (packed_fields_ & ~(1u << flag)) | ((value ? 1u : 0u) << flag);
2250 }
2251
2252 template <typename BitFieldType>
GetPackedField()2253 typename BitFieldType::value_type GetPackedField() const {
2254 return BitFieldType::Decode(packed_fields_);
2255 }
2256
2257 template <typename BitFieldType>
SetPackedField(typename BitFieldType::value_type value)2258 void SetPackedField(typename BitFieldType::value_type value) {
2259 DCHECK(IsUint<BitFieldType::size>(static_cast<uintptr_t>(value)));
2260 packed_fields_ = BitFieldType::Update(value, packed_fields_);
2261 }
2262
2263 private:
FixUpUserRecordsAfterUseInsertion(HUseList<HInstruction * >::iterator fixup_end)2264 void FixUpUserRecordsAfterUseInsertion(HUseList<HInstruction*>::iterator fixup_end) {
2265 auto before_use_node = uses_.before_begin();
2266 for (auto use_node = uses_.begin(); use_node != fixup_end; ++use_node) {
2267 HInstruction* user = use_node->GetUser();
2268 size_t input_index = use_node->GetIndex();
2269 user->SetRawInputRecordAt(input_index, HUserRecord<HInstruction*>(this, before_use_node));
2270 before_use_node = use_node;
2271 }
2272 }
2273
FixUpUserRecordsAfterUseRemoval(HUseList<HInstruction * >::iterator before_use_node)2274 void FixUpUserRecordsAfterUseRemoval(HUseList<HInstruction*>::iterator before_use_node) {
2275 auto next = ++HUseList<HInstruction*>::iterator(before_use_node);
2276 if (next != uses_.end()) {
2277 HInstruction* next_user = next->GetUser();
2278 size_t next_index = next->GetIndex();
2279 DCHECK(next_user->InputRecordAt(next_index).GetInstruction() == this);
2280 next_user->SetRawInputRecordAt(next_index, HUserRecord<HInstruction*>(this, before_use_node));
2281 }
2282 }
2283
FixUpUserRecordsAfterEnvUseInsertion(HUseList<HEnvironment * >::iterator env_fixup_end)2284 void FixUpUserRecordsAfterEnvUseInsertion(HUseList<HEnvironment*>::iterator env_fixup_end) {
2285 auto before_env_use_node = env_uses_.before_begin();
2286 for (auto env_use_node = env_uses_.begin(); env_use_node != env_fixup_end; ++env_use_node) {
2287 HEnvironment* user = env_use_node->GetUser();
2288 size_t input_index = env_use_node->GetIndex();
2289 user->vregs_[input_index] = HUserRecord<HEnvironment*>(this, before_env_use_node);
2290 before_env_use_node = env_use_node;
2291 }
2292 }
2293
FixUpUserRecordsAfterEnvUseRemoval(HUseList<HEnvironment * >::iterator before_env_use_node)2294 void FixUpUserRecordsAfterEnvUseRemoval(HUseList<HEnvironment*>::iterator before_env_use_node) {
2295 auto next = ++HUseList<HEnvironment*>::iterator(before_env_use_node);
2296 if (next != env_uses_.end()) {
2297 HEnvironment* next_user = next->GetUser();
2298 size_t next_index = next->GetIndex();
2299 DCHECK(next_user->vregs_[next_index].GetInstruction() == this);
2300 next_user->vregs_[next_index] = HUserRecord<HEnvironment*>(this, before_env_use_node);
2301 }
2302 }
2303
2304 HInstruction* previous_;
2305 HInstruction* next_;
2306 HBasicBlock* block_;
2307 const uint32_t dex_pc_;
2308
2309 // An instruction gets an id when it is added to the graph.
2310 // It reflects creation order. A negative id means the instruction
2311 // has not been added to the graph.
2312 int id_;
2313
2314 // When doing liveness analysis, instructions that have uses get an SSA index.
2315 int ssa_index_;
2316
2317 // Packed fields.
2318 uint32_t packed_fields_;
2319
2320 // List of instructions that have this instruction as input.
2321 HUseList<HInstruction*> uses_;
2322
2323 // List of environments that contain this instruction.
2324 HUseList<HEnvironment*> env_uses_;
2325
2326 // The environment associated with this instruction. Not null if the instruction
2327 // might jump out of the method.
2328 HEnvironment* environment_;
2329
2330 // Set by the code generator.
2331 LocationSummary* locations_;
2332
2333 // Set by the liveness analysis.
2334 LiveInterval* live_interval_;
2335
2336 // Set by the liveness analysis, this is the position in a linear
2337 // order of blocks where this instruction's live interval start.
2338 size_t lifetime_position_;
2339
2340 SideEffects side_effects_;
2341
2342 // The reference handle part of the reference type info.
2343 // The IsExact() flag is stored in packed fields.
2344 // TODO: for primitive types this should be marked as invalid.
2345 ReferenceTypeInfo::TypeHandle reference_type_handle_;
2346
2347 friend class GraphChecker;
2348 friend class HBasicBlock;
2349 friend class HEnvironment;
2350 friend class HGraph;
2351 friend class HInstructionList;
2352
2353 DISALLOW_COPY_AND_ASSIGN(HInstruction);
2354 };
2355 std::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind& rhs);
2356
2357 // Iterates over the instructions, while preserving the next instruction
2358 // in case the current instruction gets removed from the list by the user
2359 // of this iterator.
2360 class HInstructionIterator : public ValueObject {
2361 public:
HInstructionIterator(const HInstructionList & instructions)2362 explicit HInstructionIterator(const HInstructionList& instructions)
2363 : instruction_(instructions.first_instruction_) {
2364 next_ = Done() ? nullptr : instruction_->GetNext();
2365 }
2366
Done()2367 bool Done() const { return instruction_ == nullptr; }
Current()2368 HInstruction* Current() const { return instruction_; }
Advance()2369 void Advance() {
2370 instruction_ = next_;
2371 next_ = Done() ? nullptr : instruction_->GetNext();
2372 }
2373
2374 private:
2375 HInstruction* instruction_;
2376 HInstruction* next_;
2377
2378 DISALLOW_COPY_AND_ASSIGN(HInstructionIterator);
2379 };
2380
2381 // Iterates over the instructions without saving the next instruction,
2382 // therefore handling changes in the graph potentially made by the user
2383 // of this iterator.
2384 class HInstructionIteratorHandleChanges : public ValueObject {
2385 public:
HInstructionIteratorHandleChanges(const HInstructionList & instructions)2386 explicit HInstructionIteratorHandleChanges(const HInstructionList& instructions)
2387 : instruction_(instructions.first_instruction_) {
2388 }
2389
Done()2390 bool Done() const { return instruction_ == nullptr; }
Current()2391 HInstruction* Current() const { return instruction_; }
Advance()2392 void Advance() {
2393 instruction_ = instruction_->GetNext();
2394 }
2395
2396 private:
2397 HInstruction* instruction_;
2398
2399 DISALLOW_COPY_AND_ASSIGN(HInstructionIteratorHandleChanges);
2400 };
2401
2402
2403 class HBackwardInstructionIterator : public ValueObject {
2404 public:
HBackwardInstructionIterator(const HInstructionList & instructions)2405 explicit HBackwardInstructionIterator(const HInstructionList& instructions)
2406 : instruction_(instructions.last_instruction_) {
2407 next_ = Done() ? nullptr : instruction_->GetPrevious();
2408 }
2409
Done()2410 bool Done() const { return instruction_ == nullptr; }
Current()2411 HInstruction* Current() const { return instruction_; }
Advance()2412 void Advance() {
2413 instruction_ = next_;
2414 next_ = Done() ? nullptr : instruction_->GetPrevious();
2415 }
2416
2417 private:
2418 HInstruction* instruction_;
2419 HInstruction* next_;
2420
2421 DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator);
2422 };
2423
2424 class HVariableInputSizeInstruction : public HInstruction {
2425 public:
2426 using HInstruction::GetInputRecords; // Keep the const version visible.
GetInputRecords()2427 ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() OVERRIDE {
2428 return ArrayRef<HUserRecord<HInstruction*>>(inputs_);
2429 }
2430
2431 void AddInput(HInstruction* input);
2432 void InsertInputAt(size_t index, HInstruction* input);
2433 void RemoveInputAt(size_t index);
2434
2435 protected:
HVariableInputSizeInstruction(SideEffects side_effects,uint32_t dex_pc,ArenaAllocator * arena,size_t number_of_inputs,ArenaAllocKind kind)2436 HVariableInputSizeInstruction(SideEffects side_effects,
2437 uint32_t dex_pc,
2438 ArenaAllocator* arena,
2439 size_t number_of_inputs,
2440 ArenaAllocKind kind)
2441 : HInstruction(side_effects, dex_pc),
2442 inputs_(number_of_inputs, arena->Adapter(kind)) {}
2443
2444 ArenaVector<HUserRecord<HInstruction*>> inputs_;
2445
2446 private:
2447 DISALLOW_COPY_AND_ASSIGN(HVariableInputSizeInstruction);
2448 };
2449
2450 template<size_t N>
2451 class HTemplateInstruction: public HInstruction {
2452 public:
2453 HTemplateInstruction<N>(SideEffects side_effects, uint32_t dex_pc)
HInstruction(side_effects,dex_pc)2454 : HInstruction(side_effects, dex_pc), inputs_() {}
~HTemplateInstruction()2455 virtual ~HTemplateInstruction() {}
2456
2457 using HInstruction::GetInputRecords; // Keep the const version visible.
GetInputRecords()2458 ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() OVERRIDE FINAL {
2459 return ArrayRef<HUserRecord<HInstruction*>>(inputs_);
2460 }
2461
2462 private:
2463 std::array<HUserRecord<HInstruction*>, N> inputs_;
2464
2465 friend class SsaBuilder;
2466 };
2467
2468 // HTemplateInstruction specialization for N=0.
2469 template<>
2470 class HTemplateInstruction<0>: public HInstruction {
2471 public:
2472 explicit HTemplateInstruction<0>(SideEffects side_effects, uint32_t dex_pc)
HInstruction(side_effects,dex_pc)2473 : HInstruction(side_effects, dex_pc) {}
2474
~HTemplateInstruction()2475 virtual ~HTemplateInstruction() {}
2476
2477 using HInstruction::GetInputRecords; // Keep the const version visible.
GetInputRecords()2478 ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() OVERRIDE FINAL {
2479 return ArrayRef<HUserRecord<HInstruction*>>();
2480 }
2481
2482 private:
2483 friend class SsaBuilder;
2484 };
2485
2486 template<intptr_t N>
2487 class HExpression : public HTemplateInstruction<N> {
2488 public:
2489 HExpression<N>(Primitive::Type type, SideEffects side_effects, uint32_t dex_pc)
2490 : HTemplateInstruction<N>(side_effects, dex_pc) {
2491 this->template SetPackedField<TypeField>(type);
2492 }
~HExpression()2493 virtual ~HExpression() {}
2494
GetType()2495 Primitive::Type GetType() const OVERRIDE {
2496 return TypeField::Decode(this->GetPackedFields());
2497 }
2498
2499 protected:
2500 static constexpr size_t kFieldType = HInstruction::kNumberOfGenericPackedBits;
2501 static constexpr size_t kFieldTypeSize =
2502 MinimumBitsToStore(static_cast<size_t>(Primitive::kPrimLast));
2503 static constexpr size_t kNumberOfExpressionPackedBits = kFieldType + kFieldTypeSize;
2504 static_assert(kNumberOfExpressionPackedBits <= HInstruction::kMaxNumberOfPackedBits,
2505 "Too many packed fields.");
2506 using TypeField = BitField<Primitive::Type, kFieldType, kFieldTypeSize>;
2507 };
2508
2509 // Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
2510 // instruction that branches to the exit block.
2511 class HReturnVoid FINAL : public HTemplateInstruction<0> {
2512 public:
2513 explicit HReturnVoid(uint32_t dex_pc = kNoDexPc)
HTemplateInstruction(SideEffects::None (),dex_pc)2514 : HTemplateInstruction(SideEffects::None(), dex_pc) {}
2515
IsControlFlow()2516 bool IsControlFlow() const OVERRIDE { return true; }
2517
2518 DECLARE_INSTRUCTION(ReturnVoid);
2519
2520 private:
2521 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
2522 };
2523
2524 // Represents dex's RETURN opcodes. A HReturn is a control flow
2525 // instruction that branches to the exit block.
2526 class HReturn FINAL : public HTemplateInstruction<1> {
2527 public:
2528 explicit HReturn(HInstruction* value, uint32_t dex_pc = kNoDexPc)
HTemplateInstruction(SideEffects::None (),dex_pc)2529 : HTemplateInstruction(SideEffects::None(), dex_pc) {
2530 SetRawInputAt(0, value);
2531 }
2532
IsControlFlow()2533 bool IsControlFlow() const OVERRIDE { return true; }
2534
2535 DECLARE_INSTRUCTION(Return);
2536
2537 private:
2538 DISALLOW_COPY_AND_ASSIGN(HReturn);
2539 };
2540
2541 class HPhi FINAL : public HVariableInputSizeInstruction {
2542 public:
2543 HPhi(ArenaAllocator* arena,
2544 uint32_t reg_number,
2545 size_t number_of_inputs,
2546 Primitive::Type type,
2547 uint32_t dex_pc = kNoDexPc)
HVariableInputSizeInstruction(SideEffects::None (),dex_pc,arena,number_of_inputs,kArenaAllocPhiInputs)2548 : HVariableInputSizeInstruction(
2549 SideEffects::None(),
2550 dex_pc,
2551 arena,
2552 number_of_inputs,
2553 kArenaAllocPhiInputs),
2554 reg_number_(reg_number) {
2555 SetPackedField<TypeField>(ToPhiType(type));
2556 DCHECK_NE(GetType(), Primitive::kPrimVoid);
2557 // Phis are constructed live and marked dead if conflicting or unused.
2558 // Individual steps of SsaBuilder should assume that if a phi has been
2559 // marked dead, it can be ignored and will be removed by SsaPhiElimination.
2560 SetPackedFlag<kFlagIsLive>(true);
2561 SetPackedFlag<kFlagCanBeNull>(true);
2562 }
2563
2564 // Returns a type equivalent to the given `type`, but that a `HPhi` can hold.
ToPhiType(Primitive::Type type)2565 static Primitive::Type ToPhiType(Primitive::Type type) {
2566 return Primitive::PrimitiveKind(type);
2567 }
2568
IsCatchPhi()2569 bool IsCatchPhi() const { return GetBlock()->IsCatchBlock(); }
2570
GetType()2571 Primitive::Type GetType() const OVERRIDE { return GetPackedField<TypeField>(); }
SetType(Primitive::Type new_type)2572 void SetType(Primitive::Type new_type) {
2573 // Make sure that only valid type changes occur. The following are allowed:
2574 // (1) int -> float/ref (primitive type propagation),
2575 // (2) long -> double (primitive type propagation).
2576 DCHECK(GetType() == new_type ||
2577 (GetType() == Primitive::kPrimInt && new_type == Primitive::kPrimFloat) ||
2578 (GetType() == Primitive::kPrimInt && new_type == Primitive::kPrimNot) ||
2579 (GetType() == Primitive::kPrimLong && new_type == Primitive::kPrimDouble));
2580 SetPackedField<TypeField>(new_type);
2581 }
2582
CanBeNull()2583 bool CanBeNull() const OVERRIDE { return GetPackedFlag<kFlagCanBeNull>(); }
SetCanBeNull(bool can_be_null)2584 void SetCanBeNull(bool can_be_null) { SetPackedFlag<kFlagCanBeNull>(can_be_null); }
2585
GetRegNumber()2586 uint32_t GetRegNumber() const { return reg_number_; }
2587
SetDead()2588 void SetDead() { SetPackedFlag<kFlagIsLive>(false); }
SetLive()2589 void SetLive() { SetPackedFlag<kFlagIsLive>(true); }
IsDead()2590 bool IsDead() const { return !IsLive(); }
IsLive()2591 bool IsLive() const { return GetPackedFlag<kFlagIsLive>(); }
2592
IsVRegEquivalentOf(const HInstruction * other)2593 bool IsVRegEquivalentOf(const HInstruction* other) const {
2594 return other != nullptr
2595 && other->IsPhi()
2596 && other->AsPhi()->GetBlock() == GetBlock()
2597 && other->AsPhi()->GetRegNumber() == GetRegNumber();
2598 }
2599
2600 // Returns the next equivalent phi (starting from the current one) or null if there is none.
2601 // An equivalent phi is a phi having the same dex register and type.
2602 // It assumes that phis with the same dex register are adjacent.
GetNextEquivalentPhiWithSameType()2603 HPhi* GetNextEquivalentPhiWithSameType() {
2604 HInstruction* next = GetNext();
2605 while (next != nullptr && next->AsPhi()->GetRegNumber() == reg_number_) {
2606 if (next->GetType() == GetType()) {
2607 return next->AsPhi();
2608 }
2609 next = next->GetNext();
2610 }
2611 return nullptr;
2612 }
2613
2614 DECLARE_INSTRUCTION(Phi);
2615
2616 private:
2617 static constexpr size_t kFieldType = HInstruction::kNumberOfGenericPackedBits;
2618 static constexpr size_t kFieldTypeSize =
2619 MinimumBitsToStore(static_cast<size_t>(Primitive::kPrimLast));
2620 static constexpr size_t kFlagIsLive = kFieldType + kFieldTypeSize;
2621 static constexpr size_t kFlagCanBeNull = kFlagIsLive + 1;
2622 static constexpr size_t kNumberOfPhiPackedBits = kFlagCanBeNull + 1;
2623 static_assert(kNumberOfPhiPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
2624 using TypeField = BitField<Primitive::Type, kFieldType, kFieldTypeSize>;
2625
2626 const uint32_t reg_number_;
2627
2628 DISALLOW_COPY_AND_ASSIGN(HPhi);
2629 };
2630
2631 // The exit instruction is the only instruction of the exit block.
2632 // Instructions aborting the method (HThrow and HReturn) must branch to the
2633 // exit block.
2634 class HExit FINAL : public HTemplateInstruction<0> {
2635 public:
HTemplateInstruction(SideEffects::None (),dex_pc)2636 explicit HExit(uint32_t dex_pc = kNoDexPc) : HTemplateInstruction(SideEffects::None(), dex_pc) {}
2637
IsControlFlow()2638 bool IsControlFlow() const OVERRIDE { return true; }
2639
2640 DECLARE_INSTRUCTION(Exit);
2641
2642 private:
2643 DISALLOW_COPY_AND_ASSIGN(HExit);
2644 };
2645
2646 // Jumps from one block to another.
2647 class HGoto FINAL : public HTemplateInstruction<0> {
2648 public:
HTemplateInstruction(SideEffects::None (),dex_pc)2649 explicit HGoto(uint32_t dex_pc = kNoDexPc) : HTemplateInstruction(SideEffects::None(), dex_pc) {}
2650
IsControlFlow()2651 bool IsControlFlow() const OVERRIDE { return true; }
2652
GetSuccessor()2653 HBasicBlock* GetSuccessor() const {
2654 return GetBlock()->GetSingleSuccessor();
2655 }
2656
2657 DECLARE_INSTRUCTION(Goto);
2658
2659 private:
2660 DISALLOW_COPY_AND_ASSIGN(HGoto);
2661 };
2662
2663 class HConstant : public HExpression<0> {
2664 public:
2665 explicit HConstant(Primitive::Type type, uint32_t dex_pc = kNoDexPc)
HExpression(type,SideEffects::None (),dex_pc)2666 : HExpression(type, SideEffects::None(), dex_pc) {}
2667
CanBeMoved()2668 bool CanBeMoved() const OVERRIDE { return true; }
2669
2670 // Is this constant -1 in the arithmetic sense?
IsMinusOne()2671 virtual bool IsMinusOne() const { return false; }
2672 // Is this constant 0 in the arithmetic sense?
IsArithmeticZero()2673 virtual bool IsArithmeticZero() const { return false; }
2674 // Is this constant a 0-bit pattern?
IsZeroBitPattern()2675 virtual bool IsZeroBitPattern() const { return false; }
2676 // Is this constant 1 in the arithmetic sense?
IsOne()2677 virtual bool IsOne() const { return false; }
2678
2679 virtual uint64_t GetValueAsUint64() const = 0;
2680
2681 DECLARE_ABSTRACT_INSTRUCTION(Constant);
2682
2683 private:
2684 DISALLOW_COPY_AND_ASSIGN(HConstant);
2685 };
2686
2687 class HNullConstant FINAL : public HConstant {
2688 public:
InstructionDataEquals(const HInstruction * other ATTRIBUTE_UNUSED)2689 bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
2690 return true;
2691 }
2692
GetValueAsUint64()2693 uint64_t GetValueAsUint64() const OVERRIDE { return 0; }
2694
ComputeHashCode()2695 size_t ComputeHashCode() const OVERRIDE { return 0; }
2696
2697 // The null constant representation is a 0-bit pattern.
IsZeroBitPattern()2698 virtual bool IsZeroBitPattern() const { return true; }
2699
2700 DECLARE_INSTRUCTION(NullConstant);
2701
2702 private:
HConstant(Primitive::kPrimNot,dex_pc)2703 explicit HNullConstant(uint32_t dex_pc = kNoDexPc) : HConstant(Primitive::kPrimNot, dex_pc) {}
2704
2705 friend class HGraph;
2706 DISALLOW_COPY_AND_ASSIGN(HNullConstant);
2707 };
2708
2709 // Constants of the type int. Those can be from Dex instructions, or
2710 // synthesized (for example with the if-eqz instruction).
2711 class HIntConstant FINAL : public HConstant {
2712 public:
GetValue()2713 int32_t GetValue() const { return value_; }
2714
GetValueAsUint64()2715 uint64_t GetValueAsUint64() const OVERRIDE {
2716 return static_cast<uint64_t>(static_cast<uint32_t>(value_));
2717 }
2718
InstructionDataEquals(const HInstruction * other)2719 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
2720 DCHECK(other->IsIntConstant()) << other->DebugName();
2721 return other->AsIntConstant()->value_ == value_;
2722 }
2723
ComputeHashCode()2724 size_t ComputeHashCode() const OVERRIDE { return GetValue(); }
2725
IsMinusOne()2726 bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
IsArithmeticZero()2727 bool IsArithmeticZero() const OVERRIDE { return GetValue() == 0; }
IsZeroBitPattern()2728 bool IsZeroBitPattern() const OVERRIDE { return GetValue() == 0; }
IsOne()2729 bool IsOne() const OVERRIDE { return GetValue() == 1; }
2730
2731 // Integer constants are used to encode Boolean values as well,
2732 // where 1 means true and 0 means false.
IsTrue()2733 bool IsTrue() const { return GetValue() == 1; }
IsFalse()2734 bool IsFalse() const { return GetValue() == 0; }
2735
2736 DECLARE_INSTRUCTION(IntConstant);
2737
2738 private:
2739 explicit HIntConstant(int32_t value, uint32_t dex_pc = kNoDexPc)
HConstant(Primitive::kPrimInt,dex_pc)2740 : HConstant(Primitive::kPrimInt, dex_pc), value_(value) {}
2741 explicit HIntConstant(bool value, uint32_t dex_pc = kNoDexPc)
HConstant(Primitive::kPrimInt,dex_pc)2742 : HConstant(Primitive::kPrimInt, dex_pc), value_(value ? 1 : 0) {}
2743
2744 const int32_t value_;
2745
2746 friend class HGraph;
2747 ART_FRIEND_TEST(GraphTest, InsertInstructionBefore);
2748 ART_FRIEND_TYPED_TEST(ParallelMoveTest, ConstantLast);
2749 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
2750 };
2751
2752 class HLongConstant FINAL : public HConstant {
2753 public:
GetValue()2754 int64_t GetValue() const { return value_; }
2755
GetValueAsUint64()2756 uint64_t GetValueAsUint64() const OVERRIDE { return value_; }
2757
InstructionDataEquals(const HInstruction * other)2758 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
2759 DCHECK(other->IsLongConstant()) << other->DebugName();
2760 return other->AsLongConstant()->value_ == value_;
2761 }
2762
ComputeHashCode()2763 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
2764
IsMinusOne()2765 bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
IsArithmeticZero()2766 bool IsArithmeticZero() const OVERRIDE { return GetValue() == 0; }
IsZeroBitPattern()2767 bool IsZeroBitPattern() const OVERRIDE { return GetValue() == 0; }
IsOne()2768 bool IsOne() const OVERRIDE { return GetValue() == 1; }
2769
2770 DECLARE_INSTRUCTION(LongConstant);
2771
2772 private:
2773 explicit HLongConstant(int64_t value, uint32_t dex_pc = kNoDexPc)
HConstant(Primitive::kPrimLong,dex_pc)2774 : HConstant(Primitive::kPrimLong, dex_pc), value_(value) {}
2775
2776 const int64_t value_;
2777
2778 friend class HGraph;
2779 DISALLOW_COPY_AND_ASSIGN(HLongConstant);
2780 };
2781
2782 class HFloatConstant FINAL : public HConstant {
2783 public:
GetValue()2784 float GetValue() const { return value_; }
2785
GetValueAsUint64()2786 uint64_t GetValueAsUint64() const OVERRIDE {
2787 return static_cast<uint64_t>(bit_cast<uint32_t, float>(value_));
2788 }
2789
InstructionDataEquals(const HInstruction * other)2790 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
2791 DCHECK(other->IsFloatConstant()) << other->DebugName();
2792 return other->AsFloatConstant()->GetValueAsUint64() == GetValueAsUint64();
2793 }
2794
ComputeHashCode()2795 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
2796
IsMinusOne()2797 bool IsMinusOne() const OVERRIDE {
2798 return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>((-1.0f));
2799 }
IsArithmeticZero()2800 bool IsArithmeticZero() const OVERRIDE {
2801 return std::fpclassify(value_) == FP_ZERO;
2802 }
IsArithmeticPositiveZero()2803 bool IsArithmeticPositiveZero() const {
2804 return IsArithmeticZero() && !std::signbit(value_);
2805 }
IsArithmeticNegativeZero()2806 bool IsArithmeticNegativeZero() const {
2807 return IsArithmeticZero() && std::signbit(value_);
2808 }
IsZeroBitPattern()2809 bool IsZeroBitPattern() const OVERRIDE {
2810 return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>(0.0f);
2811 }
IsOne()2812 bool IsOne() const OVERRIDE {
2813 return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>(1.0f);
2814 }
IsNaN()2815 bool IsNaN() const {
2816 return std::isnan(value_);
2817 }
2818
2819 DECLARE_INSTRUCTION(FloatConstant);
2820
2821 private:
2822 explicit HFloatConstant(float value, uint32_t dex_pc = kNoDexPc)
HConstant(Primitive::kPrimFloat,dex_pc)2823 : HConstant(Primitive::kPrimFloat, dex_pc), value_(value) {}
2824 explicit HFloatConstant(int32_t value, uint32_t dex_pc = kNoDexPc)
HConstant(Primitive::kPrimFloat,dex_pc)2825 : HConstant(Primitive::kPrimFloat, dex_pc), value_(bit_cast<float, int32_t>(value)) {}
2826
2827 const float value_;
2828
2829 // Only the SsaBuilder and HGraph can create floating-point constants.
2830 friend class SsaBuilder;
2831 friend class HGraph;
2832 DISALLOW_COPY_AND_ASSIGN(HFloatConstant);
2833 };
2834
2835 class HDoubleConstant FINAL : public HConstant {
2836 public:
GetValue()2837 double GetValue() const { return value_; }
2838
GetValueAsUint64()2839 uint64_t GetValueAsUint64() const OVERRIDE { return bit_cast<uint64_t, double>(value_); }
2840
InstructionDataEquals(const HInstruction * other)2841 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
2842 DCHECK(other->IsDoubleConstant()) << other->DebugName();
2843 return other->AsDoubleConstant()->GetValueAsUint64() == GetValueAsUint64();
2844 }
2845
ComputeHashCode()2846 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
2847
IsMinusOne()2848 bool IsMinusOne() const OVERRIDE {
2849 return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>((-1.0));
2850 }
IsArithmeticZero()2851 bool IsArithmeticZero() const OVERRIDE {
2852 return std::fpclassify(value_) == FP_ZERO;
2853 }
IsArithmeticPositiveZero()2854 bool IsArithmeticPositiveZero() const {
2855 return IsArithmeticZero() && !std::signbit(value_);
2856 }
IsArithmeticNegativeZero()2857 bool IsArithmeticNegativeZero() const {
2858 return IsArithmeticZero() && std::signbit(value_);
2859 }
IsZeroBitPattern()2860 bool IsZeroBitPattern() const OVERRIDE {
2861 return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>((0.0));
2862 }
IsOne()2863 bool IsOne() const OVERRIDE {
2864 return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>(1.0);
2865 }
IsNaN()2866 bool IsNaN() const {
2867 return std::isnan(value_);
2868 }
2869
2870 DECLARE_INSTRUCTION(DoubleConstant);
2871
2872 private:
2873 explicit HDoubleConstant(double value, uint32_t dex_pc = kNoDexPc)
HConstant(Primitive::kPrimDouble,dex_pc)2874 : HConstant(Primitive::kPrimDouble, dex_pc), value_(value) {}
2875 explicit HDoubleConstant(int64_t value, uint32_t dex_pc = kNoDexPc)
HConstant(Primitive::kPrimDouble,dex_pc)2876 : HConstant(Primitive::kPrimDouble, dex_pc), value_(bit_cast<double, int64_t>(value)) {}
2877
2878 const double value_;
2879
2880 // Only the SsaBuilder and HGraph can create floating-point constants.
2881 friend class SsaBuilder;
2882 friend class HGraph;
2883 DISALLOW_COPY_AND_ASSIGN(HDoubleConstant);
2884 };
2885
2886 // Conditional branch. A block ending with an HIf instruction must have
2887 // two successors.
2888 class HIf FINAL : public HTemplateInstruction<1> {
2889 public:
2890 explicit HIf(HInstruction* input, uint32_t dex_pc = kNoDexPc)
HTemplateInstruction(SideEffects::None (),dex_pc)2891 : HTemplateInstruction(SideEffects::None(), dex_pc) {
2892 SetRawInputAt(0, input);
2893 }
2894
IsControlFlow()2895 bool IsControlFlow() const OVERRIDE { return true; }
2896
IfTrueSuccessor()2897 HBasicBlock* IfTrueSuccessor() const {
2898 return GetBlock()->GetSuccessors()[0];
2899 }
2900
IfFalseSuccessor()2901 HBasicBlock* IfFalseSuccessor() const {
2902 return GetBlock()->GetSuccessors()[1];
2903 }
2904
2905 DECLARE_INSTRUCTION(If);
2906
2907 private:
2908 DISALLOW_COPY_AND_ASSIGN(HIf);
2909 };
2910
2911
2912 // Abstract instruction which marks the beginning and/or end of a try block and
2913 // links it to the respective exception handlers. Behaves the same as a Goto in
2914 // non-exceptional control flow.
2915 // Normal-flow successor is stored at index zero, exception handlers under
2916 // higher indices in no particular order.
2917 class HTryBoundary FINAL : public HTemplateInstruction<0> {
2918 public:
2919 enum class BoundaryKind {
2920 kEntry,
2921 kExit,
2922 kLast = kExit
2923 };
2924
2925 explicit HTryBoundary(BoundaryKind kind, uint32_t dex_pc = kNoDexPc)
HTemplateInstruction(SideEffects::None (),dex_pc)2926 : HTemplateInstruction(SideEffects::None(), dex_pc) {
2927 SetPackedField<BoundaryKindField>(kind);
2928 }
2929
IsControlFlow()2930 bool IsControlFlow() const OVERRIDE { return true; }
2931
2932 // Returns the block's non-exceptional successor (index zero).
GetNormalFlowSuccessor()2933 HBasicBlock* GetNormalFlowSuccessor() const { return GetBlock()->GetSuccessors()[0]; }
2934
GetExceptionHandlers()2935 ArrayRef<HBasicBlock* const> GetExceptionHandlers() const {
2936 return ArrayRef<HBasicBlock* const>(GetBlock()->GetSuccessors()).SubArray(1u);
2937 }
2938
2939 // Returns whether `handler` is among its exception handlers (non-zero index
2940 // successors).
HasExceptionHandler(const HBasicBlock & handler)2941 bool HasExceptionHandler(const HBasicBlock& handler) const {
2942 DCHECK(handler.IsCatchBlock());
2943 return GetBlock()->HasSuccessor(&handler, 1u /* Skip first successor. */);
2944 }
2945
2946 // If not present already, adds `handler` to its block's list of exception
2947 // handlers.
AddExceptionHandler(HBasicBlock * handler)2948 void AddExceptionHandler(HBasicBlock* handler) {
2949 if (!HasExceptionHandler(*handler)) {
2950 GetBlock()->AddSuccessor(handler);
2951 }
2952 }
2953
GetBoundaryKind()2954 BoundaryKind GetBoundaryKind() const { return GetPackedField<BoundaryKindField>(); }
IsEntry()2955 bool IsEntry() const { return GetBoundaryKind() == BoundaryKind::kEntry; }
2956
2957 bool HasSameExceptionHandlersAs(const HTryBoundary& other) const;
2958
2959 DECLARE_INSTRUCTION(TryBoundary);
2960
2961 private:
2962 static constexpr size_t kFieldBoundaryKind = kNumberOfGenericPackedBits;
2963 static constexpr size_t kFieldBoundaryKindSize =
2964 MinimumBitsToStore(static_cast<size_t>(BoundaryKind::kLast));
2965 static constexpr size_t kNumberOfTryBoundaryPackedBits =
2966 kFieldBoundaryKind + kFieldBoundaryKindSize;
2967 static_assert(kNumberOfTryBoundaryPackedBits <= kMaxNumberOfPackedBits,
2968 "Too many packed fields.");
2969 using BoundaryKindField = BitField<BoundaryKind, kFieldBoundaryKind, kFieldBoundaryKindSize>;
2970
2971 DISALLOW_COPY_AND_ASSIGN(HTryBoundary);
2972 };
2973
2974 // Deoptimize to interpreter, upon checking a condition.
2975 class HDeoptimize FINAL : public HVariableInputSizeInstruction {
2976 public:
2977 // Use this constructor when the `HDeoptimize` acts as a barrier, where no code can move
2978 // across.
HDeoptimize(ArenaAllocator * arena,HInstruction * cond,DeoptimizationKind kind,uint32_t dex_pc)2979 HDeoptimize(ArenaAllocator* arena, HInstruction* cond, DeoptimizationKind kind, uint32_t dex_pc)
2980 : HVariableInputSizeInstruction(
2981 SideEffects::All(),
2982 dex_pc,
2983 arena,
2984 /* number_of_inputs */ 1,
2985 kArenaAllocMisc) {
2986 SetPackedFlag<kFieldCanBeMoved>(false);
2987 SetPackedField<DeoptimizeKindField>(kind);
2988 SetRawInputAt(0, cond);
2989 }
2990
2991 // Use this constructor when the `HDeoptimize` guards an instruction, and any user
2992 // that relies on the deoptimization to pass should have its input be the `HDeoptimize`
2993 // instead of `guard`.
2994 // We set CanTriggerGC to prevent any intermediate address to be live
2995 // at the point of the `HDeoptimize`.
HDeoptimize(ArenaAllocator * arena,HInstruction * cond,HInstruction * guard,DeoptimizationKind kind,uint32_t dex_pc)2996 HDeoptimize(ArenaAllocator* arena,
2997 HInstruction* cond,
2998 HInstruction* guard,
2999 DeoptimizationKind kind,
3000 uint32_t dex_pc)
3001 : HVariableInputSizeInstruction(
3002 SideEffects::CanTriggerGC(),
3003 dex_pc,
3004 arena,
3005 /* number_of_inputs */ 2,
3006 kArenaAllocMisc) {
3007 SetPackedFlag<kFieldCanBeMoved>(true);
3008 SetPackedField<DeoptimizeKindField>(kind);
3009 SetRawInputAt(0, cond);
3010 SetRawInputAt(1, guard);
3011 }
3012
CanBeMoved()3013 bool CanBeMoved() const OVERRIDE { return GetPackedFlag<kFieldCanBeMoved>(); }
3014
InstructionDataEquals(const HInstruction * other)3015 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
3016 return (other->CanBeMoved() == CanBeMoved()) && (other->AsDeoptimize()->GetKind() == GetKind());
3017 }
3018
NeedsEnvironment()3019 bool NeedsEnvironment() const OVERRIDE { return true; }
3020
CanThrow()3021 bool CanThrow() const OVERRIDE { return true; }
3022
GetDeoptimizationKind()3023 DeoptimizationKind GetDeoptimizationKind() const { return GetPackedField<DeoptimizeKindField>(); }
3024
GetType()3025 Primitive::Type GetType() const OVERRIDE {
3026 return GuardsAnInput() ? GuardedInput()->GetType() : Primitive::kPrimVoid;
3027 }
3028
GuardsAnInput()3029 bool GuardsAnInput() const {
3030 return InputCount() == 2;
3031 }
3032
GuardedInput()3033 HInstruction* GuardedInput() const {
3034 DCHECK(GuardsAnInput());
3035 return InputAt(1);
3036 }
3037
RemoveGuard()3038 void RemoveGuard() {
3039 RemoveInputAt(1);
3040 }
3041
3042 DECLARE_INSTRUCTION(Deoptimize);
3043
3044 private:
3045 static constexpr size_t kFieldCanBeMoved = kNumberOfGenericPackedBits;
3046 static constexpr size_t kFieldDeoptimizeKind = kNumberOfGenericPackedBits + 1;
3047 static constexpr size_t kFieldDeoptimizeKindSize =
3048 MinimumBitsToStore(static_cast<size_t>(DeoptimizationKind::kLast));
3049 static constexpr size_t kNumberOfDeoptimizePackedBits =
3050 kFieldDeoptimizeKind + kFieldDeoptimizeKindSize;
3051 static_assert(kNumberOfDeoptimizePackedBits <= kMaxNumberOfPackedBits,
3052 "Too many packed fields.");
3053 using DeoptimizeKindField =
3054 BitField<DeoptimizationKind, kFieldDeoptimizeKind, kFieldDeoptimizeKindSize>;
3055
3056 DISALLOW_COPY_AND_ASSIGN(HDeoptimize);
3057 };
3058
3059 // Represents a should_deoptimize flag. Currently used for CHA-based devirtualization.
3060 // The compiled code checks this flag value in a guard before devirtualized call and
3061 // if it's true, starts to do deoptimization.
3062 // It has a 4-byte slot on stack.
3063 // TODO: allocate a register for this flag.
3064 class HShouldDeoptimizeFlag FINAL : public HVariableInputSizeInstruction {
3065 public:
3066 // CHA guards are only optimized in a separate pass and it has no side effects
3067 // with regard to other passes.
HShouldDeoptimizeFlag(ArenaAllocator * arena,uint32_t dex_pc)3068 HShouldDeoptimizeFlag(ArenaAllocator* arena, uint32_t dex_pc)
3069 : HVariableInputSizeInstruction(SideEffects::None(), dex_pc, arena, 0, kArenaAllocCHA) {
3070 }
3071
GetType()3072 Primitive::Type GetType() const OVERRIDE { return Primitive::kPrimInt; }
3073
3074 // We do all CHA guard elimination/motion in a single pass, after which there is no
3075 // further guard elimination/motion since a guard might have been used for justification
3076 // of the elimination of another guard. Therefore, we pretend this guard cannot be moved
3077 // to avoid other optimizations trying to move it.
CanBeMoved()3078 bool CanBeMoved() const OVERRIDE { return false; }
3079
3080 DECLARE_INSTRUCTION(ShouldDeoptimizeFlag);
3081
3082 private:
3083 DISALLOW_COPY_AND_ASSIGN(HShouldDeoptimizeFlag);
3084 };
3085
3086 // Represents the ArtMethod that was passed as a first argument to
3087 // the method. It is used by instructions that depend on it, like
3088 // instructions that work with the dex cache.
3089 class HCurrentMethod FINAL : public HExpression<0> {
3090 public:
3091 explicit HCurrentMethod(Primitive::Type type, uint32_t dex_pc = kNoDexPc)
HExpression(type,SideEffects::None (),dex_pc)3092 : HExpression(type, SideEffects::None(), dex_pc) {}
3093
3094 DECLARE_INSTRUCTION(CurrentMethod);
3095
3096 private:
3097 DISALLOW_COPY_AND_ASSIGN(HCurrentMethod);
3098 };
3099
3100 // Fetches an ArtMethod from the virtual table or the interface method table
3101 // of a class.
3102 class HClassTableGet FINAL : public HExpression<1> {
3103 public:
3104 enum class TableKind {
3105 kVTable,
3106 kIMTable,
3107 kLast = kIMTable
3108 };
HClassTableGet(HInstruction * cls,Primitive::Type type,TableKind kind,size_t index,uint32_t dex_pc)3109 HClassTableGet(HInstruction* cls,
3110 Primitive::Type type,
3111 TableKind kind,
3112 size_t index,
3113 uint32_t dex_pc)
3114 : HExpression(type, SideEffects::None(), dex_pc),
3115 index_(index) {
3116 SetPackedField<TableKindField>(kind);
3117 SetRawInputAt(0, cls);
3118 }
3119
CanBeMoved()3120 bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(const HInstruction * other)3121 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
3122 return other->AsClassTableGet()->GetIndex() == index_ &&
3123 other->AsClassTableGet()->GetPackedFields() == GetPackedFields();
3124 }
3125
GetTableKind()3126 TableKind GetTableKind() const { return GetPackedField<TableKindField>(); }
GetIndex()3127 size_t GetIndex() const { return index_; }
3128
3129 DECLARE_INSTRUCTION(ClassTableGet);
3130
3131 private:
3132 static constexpr size_t kFieldTableKind = kNumberOfExpressionPackedBits;
3133 static constexpr size_t kFieldTableKindSize =
3134 MinimumBitsToStore(static_cast<size_t>(TableKind::kLast));
3135 static constexpr size_t kNumberOfClassTableGetPackedBits = kFieldTableKind + kFieldTableKindSize;
3136 static_assert(kNumberOfClassTableGetPackedBits <= kMaxNumberOfPackedBits,
3137 "Too many packed fields.");
3138 using TableKindField = BitField<TableKind, kFieldTableKind, kFieldTableKind>;
3139
3140 // The index of the ArtMethod in the table.
3141 const size_t index_;
3142
3143 DISALLOW_COPY_AND_ASSIGN(HClassTableGet);
3144 };
3145
3146 // PackedSwitch (jump table). A block ending with a PackedSwitch instruction will
3147 // have one successor for each entry in the switch table, and the final successor
3148 // will be the block containing the next Dex opcode.
3149 class HPackedSwitch FINAL : public HTemplateInstruction<1> {
3150 public:
3151 HPackedSwitch(int32_t start_value,
3152 uint32_t num_entries,
3153 HInstruction* input,
3154 uint32_t dex_pc = kNoDexPc)
HTemplateInstruction(SideEffects::None (),dex_pc)3155 : HTemplateInstruction(SideEffects::None(), dex_pc),
3156 start_value_(start_value),
3157 num_entries_(num_entries) {
3158 SetRawInputAt(0, input);
3159 }
3160
IsControlFlow()3161 bool IsControlFlow() const OVERRIDE { return true; }
3162
GetStartValue()3163 int32_t GetStartValue() const { return start_value_; }
3164
GetNumEntries()3165 uint32_t GetNumEntries() const { return num_entries_; }
3166
GetDefaultBlock()3167 HBasicBlock* GetDefaultBlock() const {
3168 // Last entry is the default block.
3169 return GetBlock()->GetSuccessors()[num_entries_];
3170 }
3171 DECLARE_INSTRUCTION(PackedSwitch);
3172
3173 private:
3174 const int32_t start_value_;
3175 const uint32_t num_entries_;
3176
3177 DISALLOW_COPY_AND_ASSIGN(HPackedSwitch);
3178 };
3179
3180 class HUnaryOperation : public HExpression<1> {
3181 public:
3182 HUnaryOperation(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
HExpression(result_type,SideEffects::None (),dex_pc)3183 : HExpression(result_type, SideEffects::None(), dex_pc) {
3184 SetRawInputAt(0, input);
3185 }
3186
GetInput()3187 HInstruction* GetInput() const { return InputAt(0); }
GetResultType()3188 Primitive::Type GetResultType() const { return GetType(); }
3189
CanBeMoved()3190 bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(const HInstruction * other ATTRIBUTE_UNUSED)3191 bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
3192 return true;
3193 }
3194
3195 // Try to statically evaluate `this` and return a HConstant
3196 // containing the result of this evaluation. If `this` cannot
3197 // be evaluated as a constant, return null.
3198 HConstant* TryStaticEvaluation() const;
3199
3200 // Apply this operation to `x`.
3201 virtual HConstant* Evaluate(HIntConstant* x) const = 0;
3202 virtual HConstant* Evaluate(HLongConstant* x) const = 0;
3203 virtual HConstant* Evaluate(HFloatConstant* x) const = 0;
3204 virtual HConstant* Evaluate(HDoubleConstant* x) const = 0;
3205
3206 DECLARE_ABSTRACT_INSTRUCTION(UnaryOperation);
3207
3208 private:
3209 DISALLOW_COPY_AND_ASSIGN(HUnaryOperation);
3210 };
3211
3212 class HBinaryOperation : public HExpression<2> {
3213 public:
3214 HBinaryOperation(Primitive::Type result_type,
3215 HInstruction* left,
3216 HInstruction* right,
3217 SideEffects side_effects = SideEffects::None(),
3218 uint32_t dex_pc = kNoDexPc)
HExpression(result_type,side_effects,dex_pc)3219 : HExpression(result_type, side_effects, dex_pc) {
3220 SetRawInputAt(0, left);
3221 SetRawInputAt(1, right);
3222 }
3223
GetLeft()3224 HInstruction* GetLeft() const { return InputAt(0); }
GetRight()3225 HInstruction* GetRight() const { return InputAt(1); }
GetResultType()3226 Primitive::Type GetResultType() const { return GetType(); }
3227
IsCommutative()3228 virtual bool IsCommutative() const { return false; }
3229
3230 // Put constant on the right.
3231 // Returns whether order is changed.
OrderInputsWithConstantOnTheRight()3232 bool OrderInputsWithConstantOnTheRight() {
3233 HInstruction* left = InputAt(0);
3234 HInstruction* right = InputAt(1);
3235 if (left->IsConstant() && !right->IsConstant()) {
3236 ReplaceInput(right, 0);
3237 ReplaceInput(left, 1);
3238 return true;
3239 }
3240 return false;
3241 }
3242
3243 // Order inputs by instruction id, but favor constant on the right side.
3244 // This helps GVN for commutative ops.
OrderInputs()3245 void OrderInputs() {
3246 DCHECK(IsCommutative());
3247 HInstruction* left = InputAt(0);
3248 HInstruction* right = InputAt(1);
3249 if (left == right || (!left->IsConstant() && right->IsConstant())) {
3250 return;
3251 }
3252 if (OrderInputsWithConstantOnTheRight()) {
3253 return;
3254 }
3255 // Order according to instruction id.
3256 if (left->GetId() > right->GetId()) {
3257 ReplaceInput(right, 0);
3258 ReplaceInput(left, 1);
3259 }
3260 }
3261
CanBeMoved()3262 bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(const HInstruction * other ATTRIBUTE_UNUSED)3263 bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
3264 return true;
3265 }
3266
3267 // Try to statically evaluate `this` and return a HConstant
3268 // containing the result of this evaluation. If `this` cannot
3269 // be evaluated as a constant, return null.
3270 HConstant* TryStaticEvaluation() const;
3271
3272 // Apply this operation to `x` and `y`.
Evaluate(HNullConstant * x ATTRIBUTE_UNUSED,HNullConstant * y ATTRIBUTE_UNUSED)3273 virtual HConstant* Evaluate(HNullConstant* x ATTRIBUTE_UNUSED,
3274 HNullConstant* y ATTRIBUTE_UNUSED) const {
3275 LOG(FATAL) << DebugName() << " is not defined for the (null, null) case.";
3276 UNREACHABLE();
3277 }
3278 virtual HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const = 0;
3279 virtual HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const = 0;
Evaluate(HLongConstant * x ATTRIBUTE_UNUSED,HIntConstant * y ATTRIBUTE_UNUSED)3280 virtual HConstant* Evaluate(HLongConstant* x ATTRIBUTE_UNUSED,
3281 HIntConstant* y ATTRIBUTE_UNUSED) const {
3282 LOG(FATAL) << DebugName() << " is not defined for the (long, int) case.";
3283 UNREACHABLE();
3284 }
3285 virtual HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const = 0;
3286 virtual HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const = 0;
3287
3288 // Returns an input that can legally be used as the right input and is
3289 // constant, or null.
3290 HConstant* GetConstantRight() const;
3291
3292 // If `GetConstantRight()` returns one of the input, this returns the other
3293 // one. Otherwise it returns null.
3294 HInstruction* GetLeastConstantLeft() const;
3295
3296 DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation);
3297
3298 private:
3299 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
3300 };
3301
3302 // The comparison bias applies for floating point operations and indicates how NaN
3303 // comparisons are treated:
3304 enum class ComparisonBias {
3305 kNoBias, // bias is not applicable (i.e. for long operation)
3306 kGtBias, // return 1 for NaN comparisons
3307 kLtBias, // return -1 for NaN comparisons
3308 kLast = kLtBias
3309 };
3310
3311 std::ostream& operator<<(std::ostream& os, const ComparisonBias& rhs);
3312
3313 class HCondition : public HBinaryOperation {
3314 public:
3315 HCondition(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
HBinaryOperation(Primitive::kPrimBoolean,first,second,SideEffects::None (),dex_pc)3316 : HBinaryOperation(Primitive::kPrimBoolean, first, second, SideEffects::None(), dex_pc) {
3317 SetPackedField<ComparisonBiasField>(ComparisonBias::kNoBias);
3318 }
3319
3320 // For code generation purposes, returns whether this instruction is just before
3321 // `instruction`, and disregard moves in between.
3322 bool IsBeforeWhenDisregardMoves(HInstruction* instruction) const;
3323
3324 DECLARE_ABSTRACT_INSTRUCTION(Condition);
3325
3326 virtual IfCondition GetCondition() const = 0;
3327
3328 virtual IfCondition GetOppositeCondition() const = 0;
3329
IsGtBias()3330 bool IsGtBias() const { return GetBias() == ComparisonBias::kGtBias; }
IsLtBias()3331 bool IsLtBias() const { return GetBias() == ComparisonBias::kLtBias; }
3332
GetBias()3333 ComparisonBias GetBias() const { return GetPackedField<ComparisonBiasField>(); }
SetBias(ComparisonBias bias)3334 void SetBias(ComparisonBias bias) { SetPackedField<ComparisonBiasField>(bias); }
3335
InstructionDataEquals(const HInstruction * other)3336 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
3337 return GetPackedFields() == other->AsCondition()->GetPackedFields();
3338 }
3339
IsFPConditionTrueIfNaN()3340 bool IsFPConditionTrueIfNaN() const {
3341 DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType();
3342 IfCondition if_cond = GetCondition();
3343 if (if_cond == kCondNE) {
3344 return true;
3345 } else if (if_cond == kCondEQ) {
3346 return false;
3347 }
3348 return ((if_cond == kCondGT) || (if_cond == kCondGE)) && IsGtBias();
3349 }
3350
IsFPConditionFalseIfNaN()3351 bool IsFPConditionFalseIfNaN() const {
3352 DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType();
3353 IfCondition if_cond = GetCondition();
3354 if (if_cond == kCondEQ) {
3355 return true;
3356 } else if (if_cond == kCondNE) {
3357 return false;
3358 }
3359 return ((if_cond == kCondLT) || (if_cond == kCondLE)) && IsGtBias();
3360 }
3361
3362 protected:
3363 // Needed if we merge a HCompare into a HCondition.
3364 static constexpr size_t kFieldComparisonBias = kNumberOfExpressionPackedBits;
3365 static constexpr size_t kFieldComparisonBiasSize =
3366 MinimumBitsToStore(static_cast<size_t>(ComparisonBias::kLast));
3367 static constexpr size_t kNumberOfConditionPackedBits =
3368 kFieldComparisonBias + kFieldComparisonBiasSize;
3369 static_assert(kNumberOfConditionPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
3370 using ComparisonBiasField =
3371 BitField<ComparisonBias, kFieldComparisonBias, kFieldComparisonBiasSize>;
3372
3373 template <typename T>
Compare(T x,T y)3374 int32_t Compare(T x, T y) const { return x > y ? 1 : (x < y ? -1 : 0); }
3375
3376 template <typename T>
CompareFP(T x,T y)3377 int32_t CompareFP(T x, T y) const {
3378 DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType();
3379 DCHECK_NE(GetBias(), ComparisonBias::kNoBias);
3380 // Handle the bias.
3381 return std::isunordered(x, y) ? (IsGtBias() ? 1 : -1) : Compare(x, y);
3382 }
3383
3384 // Return an integer constant containing the result of a condition evaluated at compile time.
MakeConstantCondition(bool value,uint32_t dex_pc)3385 HIntConstant* MakeConstantCondition(bool value, uint32_t dex_pc) const {
3386 return GetBlock()->GetGraph()->GetIntConstant(value, dex_pc);
3387 }
3388
3389 private:
3390 DISALLOW_COPY_AND_ASSIGN(HCondition);
3391 };
3392
3393 // Instruction to check if two inputs are equal to each other.
3394 class HEqual FINAL : public HCondition {
3395 public:
3396 HEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
HCondition(first,second,dex_pc)3397 : HCondition(first, second, dex_pc) {}
3398
IsCommutative()3399 bool IsCommutative() const OVERRIDE { return true; }
3400
Evaluate(HNullConstant * x ATTRIBUTE_UNUSED,HNullConstant * y ATTRIBUTE_UNUSED)3401 HConstant* Evaluate(HNullConstant* x ATTRIBUTE_UNUSED,
3402 HNullConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
3403 return MakeConstantCondition(true, GetDexPc());
3404 }
Evaluate(HIntConstant * x,HIntConstant * y)3405 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
3406 return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
3407 }
3408 // In the following Evaluate methods, a HCompare instruction has
3409 // been merged into this HEqual instruction; evaluate it as
3410 // `Compare(x, y) == 0`.
Evaluate(HLongConstant * x,HLongConstant * y)3411 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
3412 return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0),
3413 GetDexPc());
3414 }
Evaluate(HFloatConstant * x,HFloatConstant * y)3415 HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
3416 return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
3417 }
Evaluate(HDoubleConstant * x,HDoubleConstant * y)3418 HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
3419 return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
3420 }
3421
3422 DECLARE_INSTRUCTION(Equal);
3423
GetCondition()3424 IfCondition GetCondition() const OVERRIDE {
3425 return kCondEQ;
3426 }
3427
GetOppositeCondition()3428 IfCondition GetOppositeCondition() const OVERRIDE {
3429 return kCondNE;
3430 }
3431
3432 private:
Compute(T x,T y)3433 template <typename T> static bool Compute(T x, T y) { return x == y; }
3434
3435 DISALLOW_COPY_AND_ASSIGN(HEqual);
3436 };
3437
3438 class HNotEqual FINAL : public HCondition {
3439 public:
3440 HNotEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
HCondition(first,second,dex_pc)3441 : HCondition(first, second, dex_pc) {}
3442
IsCommutative()3443 bool IsCommutative() const OVERRIDE { return true; }
3444
Evaluate(HNullConstant * x ATTRIBUTE_UNUSED,HNullConstant * y ATTRIBUTE_UNUSED)3445 HConstant* Evaluate(HNullConstant* x ATTRIBUTE_UNUSED,
3446 HNullConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
3447 return MakeConstantCondition(false, GetDexPc());
3448 }
Evaluate(HIntConstant * x,HIntConstant * y)3449 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
3450 return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
3451 }
3452 // In the following Evaluate methods, a HCompare instruction has
3453 // been merged into this HNotEqual instruction; evaluate it as
3454 // `Compare(x, y) != 0`.
Evaluate(HLongConstant * x,HLongConstant * y)3455 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
3456 return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0), GetDexPc());
3457 }
Evaluate(HFloatConstant * x,HFloatConstant * y)3458 HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
3459 return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
3460 }
Evaluate(HDoubleConstant * x,HDoubleConstant * y)3461 HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
3462 return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
3463 }
3464
3465 DECLARE_INSTRUCTION(NotEqual);
3466
GetCondition()3467 IfCondition GetCondition() const OVERRIDE {
3468 return kCondNE;
3469 }
3470
GetOppositeCondition()3471 IfCondition GetOppositeCondition() const OVERRIDE {
3472 return kCondEQ;
3473 }
3474
3475 private:
Compute(T x,T y)3476 template <typename T> static bool Compute(T x, T y) { return x != y; }
3477
3478 DISALLOW_COPY_AND_ASSIGN(HNotEqual);
3479 };
3480
3481 class HLessThan FINAL : public HCondition {
3482 public:
3483 HLessThan(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
HCondition(first,second,dex_pc)3484 : HCondition(first, second, dex_pc) {}
3485
Evaluate(HIntConstant * x,HIntConstant * y)3486 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
3487 return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
3488 }
3489 // In the following Evaluate methods, a HCompare instruction has
3490 // been merged into this HLessThan instruction; evaluate it as
3491 // `Compare(x, y) < 0`.
Evaluate(HLongConstant * x,HLongConstant * y)3492 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
3493 return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0), GetDexPc());
3494 }
Evaluate(HFloatConstant * x,HFloatConstant * y)3495 HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
3496 return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
3497 }
Evaluate(HDoubleConstant * x,HDoubleConstant * y)3498 HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
3499 return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
3500 }
3501
3502 DECLARE_INSTRUCTION(LessThan);
3503
GetCondition()3504 IfCondition GetCondition() const OVERRIDE {
3505 return kCondLT;
3506 }
3507
GetOppositeCondition()3508 IfCondition GetOppositeCondition() const OVERRIDE {
3509 return kCondGE;
3510 }
3511
3512 private:
Compute(T x,T y)3513 template <typename T> static bool Compute(T x, T y) { return x < y; }
3514
3515 DISALLOW_COPY_AND_ASSIGN(HLessThan);
3516 };
3517
3518 class HLessThanOrEqual FINAL : public HCondition {
3519 public:
3520 HLessThanOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
HCondition(first,second,dex_pc)3521 : HCondition(first, second, dex_pc) {}
3522
Evaluate(HIntConstant * x,HIntConstant * y)3523 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
3524 return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
3525 }
3526 // In the following Evaluate methods, a HCompare instruction has
3527 // been merged into this HLessThanOrEqual instruction; evaluate it as
3528 // `Compare(x, y) <= 0`.
Evaluate(HLongConstant * x,HLongConstant * y)3529 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
3530 return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0), GetDexPc());
3531 }
Evaluate(HFloatConstant * x,HFloatConstant * y)3532 HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
3533 return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
3534 }
Evaluate(HDoubleConstant * x,HDoubleConstant * y)3535 HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
3536 return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
3537 }
3538
3539 DECLARE_INSTRUCTION(LessThanOrEqual);
3540
GetCondition()3541 IfCondition GetCondition() const OVERRIDE {
3542 return kCondLE;
3543 }
3544
GetOppositeCondition()3545 IfCondition GetOppositeCondition() const OVERRIDE {
3546 return kCondGT;
3547 }
3548
3549 private:
Compute(T x,T y)3550 template <typename T> static bool Compute(T x, T y) { return x <= y; }
3551
3552 DISALLOW_COPY_AND_ASSIGN(HLessThanOrEqual);
3553 };
3554
3555 class HGreaterThan FINAL : public HCondition {
3556 public:
3557 HGreaterThan(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
HCondition(first,second,dex_pc)3558 : HCondition(first, second, dex_pc) {}
3559
Evaluate(HIntConstant * x,HIntConstant * y)3560 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
3561 return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
3562 }
3563 // In the following Evaluate methods, a HCompare instruction has
3564 // been merged into this HGreaterThan instruction; evaluate it as
3565 // `Compare(x, y) > 0`.
Evaluate(HLongConstant * x,HLongConstant * y)3566 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
3567 return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0), GetDexPc());
3568 }
Evaluate(HFloatConstant * x,HFloatConstant * y)3569 HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
3570 return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
3571 }
Evaluate(HDoubleConstant * x,HDoubleConstant * y)3572 HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
3573 return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
3574 }
3575
3576 DECLARE_INSTRUCTION(GreaterThan);
3577
GetCondition()3578 IfCondition GetCondition() const OVERRIDE {
3579 return kCondGT;
3580 }
3581
GetOppositeCondition()3582 IfCondition GetOppositeCondition() const OVERRIDE {
3583 return kCondLE;
3584 }
3585
3586 private:
Compute(T x,T y)3587 template <typename T> static bool Compute(T x, T y) { return x > y; }
3588
3589 DISALLOW_COPY_AND_ASSIGN(HGreaterThan);
3590 };
3591
3592 class HGreaterThanOrEqual FINAL : public HCondition {
3593 public:
3594 HGreaterThanOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
HCondition(first,second,dex_pc)3595 : HCondition(first, second, dex_pc) {}
3596
Evaluate(HIntConstant * x,HIntConstant * y)3597 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
3598 return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
3599 }
3600 // In the following Evaluate methods, a HCompare instruction has
3601 // been merged into this HGreaterThanOrEqual instruction; evaluate it as
3602 // `Compare(x, y) >= 0`.
Evaluate(HLongConstant * x,HLongConstant * y)3603 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
3604 return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0), GetDexPc());
3605 }
Evaluate(HFloatConstant * x,HFloatConstant * y)3606 HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
3607 return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
3608 }
Evaluate(HDoubleConstant * x,HDoubleConstant * y)3609 HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
3610 return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0), GetDexPc());
3611 }
3612
3613 DECLARE_INSTRUCTION(GreaterThanOrEqual);
3614
GetCondition()3615 IfCondition GetCondition() const OVERRIDE {
3616 return kCondGE;
3617 }
3618
GetOppositeCondition()3619 IfCondition GetOppositeCondition() const OVERRIDE {
3620 return kCondLT;
3621 }
3622
3623 private:
Compute(T x,T y)3624 template <typename T> static bool Compute(T x, T y) { return x >= y; }
3625
3626 DISALLOW_COPY_AND_ASSIGN(HGreaterThanOrEqual);
3627 };
3628
3629 class HBelow FINAL : public HCondition {
3630 public:
3631 HBelow(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
HCondition(first,second,dex_pc)3632 : HCondition(first, second, dex_pc) {}
3633
Evaluate(HIntConstant * x,HIntConstant * y)3634 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
3635 return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
3636 }
Evaluate(HLongConstant * x,HLongConstant * y)3637 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
3638 return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
3639 }
Evaluate(HFloatConstant * x ATTRIBUTE_UNUSED,HFloatConstant * y ATTRIBUTE_UNUSED)3640 HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
3641 HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
3642 LOG(FATAL) << DebugName() << " is not defined for float values";
3643 UNREACHABLE();
3644 }
Evaluate(HDoubleConstant * x ATTRIBUTE_UNUSED,HDoubleConstant * y ATTRIBUTE_UNUSED)3645 HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
3646 HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
3647 LOG(FATAL) << DebugName() << " is not defined for double values";
3648 UNREACHABLE();
3649 }
3650
3651 DECLARE_INSTRUCTION(Below);
3652
GetCondition()3653 IfCondition GetCondition() const OVERRIDE {
3654 return kCondB;
3655 }
3656
GetOppositeCondition()3657 IfCondition GetOppositeCondition() const OVERRIDE {
3658 return kCondAE;
3659 }
3660
3661 private:
Compute(T x,T y)3662 template <typename T> static bool Compute(T x, T y) {
3663 return MakeUnsigned(x) < MakeUnsigned(y);
3664 }
3665
3666 DISALLOW_COPY_AND_ASSIGN(HBelow);
3667 };
3668
3669 class HBelowOrEqual FINAL : public HCondition {
3670 public:
3671 HBelowOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
HCondition(first,second,dex_pc)3672 : HCondition(first, second, dex_pc) {}
3673
Evaluate(HIntConstant * x,HIntConstant * y)3674 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
3675 return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
3676 }
Evaluate(HLongConstant * x,HLongConstant * y)3677 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
3678 return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
3679 }
Evaluate(HFloatConstant * x ATTRIBUTE_UNUSED,HFloatConstant * y ATTRIBUTE_UNUSED)3680 HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
3681 HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
3682 LOG(FATAL) << DebugName() << " is not defined for float values";
3683 UNREACHABLE();
3684 }
Evaluate(HDoubleConstant * x ATTRIBUTE_UNUSED,HDoubleConstant * y ATTRIBUTE_UNUSED)3685 HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
3686 HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
3687 LOG(FATAL) << DebugName() << " is not defined for double values";
3688 UNREACHABLE();
3689 }
3690
3691 DECLARE_INSTRUCTION(BelowOrEqual);
3692
GetCondition()3693 IfCondition GetCondition() const OVERRIDE {
3694 return kCondBE;
3695 }
3696
GetOppositeCondition()3697 IfCondition GetOppositeCondition() const OVERRIDE {
3698 return kCondA;
3699 }
3700
3701 private:
Compute(T x,T y)3702 template <typename T> static bool Compute(T x, T y) {
3703 return MakeUnsigned(x) <= MakeUnsigned(y);
3704 }
3705
3706 DISALLOW_COPY_AND_ASSIGN(HBelowOrEqual);
3707 };
3708
3709 class HAbove FINAL : public HCondition {
3710 public:
3711 HAbove(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
HCondition(first,second,dex_pc)3712 : HCondition(first, second, dex_pc) {}
3713
Evaluate(HIntConstant * x,HIntConstant * y)3714 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
3715 return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
3716 }
Evaluate(HLongConstant * x,HLongConstant * y)3717 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
3718 return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
3719 }
Evaluate(HFloatConstant * x ATTRIBUTE_UNUSED,HFloatConstant * y ATTRIBUTE_UNUSED)3720 HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
3721 HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
3722 LOG(FATAL) << DebugName() << " is not defined for float values";
3723 UNREACHABLE();
3724 }
Evaluate(HDoubleConstant * x ATTRIBUTE_UNUSED,HDoubleConstant * y ATTRIBUTE_UNUSED)3725 HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
3726 HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
3727 LOG(FATAL) << DebugName() << " is not defined for double values";
3728 UNREACHABLE();
3729 }
3730
3731 DECLARE_INSTRUCTION(Above);
3732
GetCondition()3733 IfCondition GetCondition() const OVERRIDE {
3734 return kCondA;
3735 }
3736
GetOppositeCondition()3737 IfCondition GetOppositeCondition() const OVERRIDE {
3738 return kCondBE;
3739 }
3740
3741 private:
Compute(T x,T y)3742 template <typename T> static bool Compute(T x, T y) {
3743 return MakeUnsigned(x) > MakeUnsigned(y);
3744 }
3745
3746 DISALLOW_COPY_AND_ASSIGN(HAbove);
3747 };
3748
3749 class HAboveOrEqual FINAL : public HCondition {
3750 public:
3751 HAboveOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
HCondition(first,second,dex_pc)3752 : HCondition(first, second, dex_pc) {}
3753
Evaluate(HIntConstant * x,HIntConstant * y)3754 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
3755 return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
3756 }
Evaluate(HLongConstant * x,HLongConstant * y)3757 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
3758 return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
3759 }
Evaluate(HFloatConstant * x ATTRIBUTE_UNUSED,HFloatConstant * y ATTRIBUTE_UNUSED)3760 HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
3761 HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
3762 LOG(FATAL) << DebugName() << " is not defined for float values";
3763 UNREACHABLE();
3764 }
Evaluate(HDoubleConstant * x ATTRIBUTE_UNUSED,HDoubleConstant * y ATTRIBUTE_UNUSED)3765 HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
3766 HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
3767 LOG(FATAL) << DebugName() << " is not defined for double values";
3768 UNREACHABLE();
3769 }
3770
3771 DECLARE_INSTRUCTION(AboveOrEqual);
3772
GetCondition()3773 IfCondition GetCondition() const OVERRIDE {
3774 return kCondAE;
3775 }
3776
GetOppositeCondition()3777 IfCondition GetOppositeCondition() const OVERRIDE {
3778 return kCondB;
3779 }
3780
3781 private:
Compute(T x,T y)3782 template <typename T> static bool Compute(T x, T y) {
3783 return MakeUnsigned(x) >= MakeUnsigned(y);
3784 }
3785
3786 DISALLOW_COPY_AND_ASSIGN(HAboveOrEqual);
3787 };
3788
3789 // Instruction to check how two inputs compare to each other.
3790 // Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1.
3791 class HCompare FINAL : public HBinaryOperation {
3792 public:
3793 // Note that `comparison_type` is the type of comparison performed
3794 // between the comparison's inputs, not the type of the instantiated
3795 // HCompare instruction (which is always Primitive::kPrimInt).
HCompare(Primitive::Type comparison_type,HInstruction * first,HInstruction * second,ComparisonBias bias,uint32_t dex_pc)3796 HCompare(Primitive::Type comparison_type,
3797 HInstruction* first,
3798 HInstruction* second,
3799 ComparisonBias bias,
3800 uint32_t dex_pc)
3801 : HBinaryOperation(Primitive::kPrimInt,
3802 first,
3803 second,
3804 SideEffectsForArchRuntimeCalls(comparison_type),
3805 dex_pc) {
3806 SetPackedField<ComparisonBiasField>(bias);
3807 DCHECK_EQ(comparison_type, Primitive::PrimitiveKind(first->GetType()));
3808 DCHECK_EQ(comparison_type, Primitive::PrimitiveKind(second->GetType()));
3809 }
3810
3811 template <typename T>
Compute(T x,T y)3812 int32_t Compute(T x, T y) const { return x > y ? 1 : (x < y ? -1 : 0); }
3813
3814 template <typename T>
ComputeFP(T x,T y)3815 int32_t ComputeFP(T x, T y) const {
3816 DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType();
3817 DCHECK_NE(GetBias(), ComparisonBias::kNoBias);
3818 // Handle the bias.
3819 return std::isunordered(x, y) ? (IsGtBias() ? 1 : -1) : Compute(x, y);
3820 }
3821
Evaluate(HIntConstant * x,HIntConstant * y)3822 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
3823 // Note that there is no "cmp-int" Dex instruction so we shouldn't
3824 // reach this code path when processing a freshly built HIR
3825 // graph. However HCompare integer instructions can be synthesized
3826 // by the instruction simplifier to implement IntegerCompare and
3827 // IntegerSignum intrinsics, so we have to handle this case.
3828 return MakeConstantComparison(Compute(x->GetValue(), y->GetValue()), GetDexPc());
3829 }
Evaluate(HLongConstant * x,HLongConstant * y)3830 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
3831 return MakeConstantComparison(Compute(x->GetValue(), y->GetValue()), GetDexPc());
3832 }
Evaluate(HFloatConstant * x,HFloatConstant * y)3833 HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
3834 return MakeConstantComparison(ComputeFP(x->GetValue(), y->GetValue()), GetDexPc());
3835 }
Evaluate(HDoubleConstant * x,HDoubleConstant * y)3836 HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
3837 return MakeConstantComparison(ComputeFP(x->GetValue(), y->GetValue()), GetDexPc());
3838 }
3839
InstructionDataEquals(const HInstruction * other)3840 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
3841 return GetPackedFields() == other->AsCompare()->GetPackedFields();
3842 }
3843
GetBias()3844 ComparisonBias GetBias() const { return GetPackedField<ComparisonBiasField>(); }
3845
3846 // Does this compare instruction have a "gt bias" (vs an "lt bias")?
3847 // Only meaningful for floating-point comparisons.
IsGtBias()3848 bool IsGtBias() const {
3849 DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType();
3850 return GetBias() == ComparisonBias::kGtBias;
3851 }
3852
SideEffectsForArchRuntimeCalls(Primitive::Type type ATTRIBUTE_UNUSED)3853 static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type type ATTRIBUTE_UNUSED) {
3854 // Comparisons do not require a runtime call in any back end.
3855 return SideEffects::None();
3856 }
3857
3858 DECLARE_INSTRUCTION(Compare);
3859
3860 protected:
3861 static constexpr size_t kFieldComparisonBias = kNumberOfExpressionPackedBits;
3862 static constexpr size_t kFieldComparisonBiasSize =
3863 MinimumBitsToStore(static_cast<size_t>(ComparisonBias::kLast));
3864 static constexpr size_t kNumberOfComparePackedBits =
3865 kFieldComparisonBias + kFieldComparisonBiasSize;
3866 static_assert(kNumberOfComparePackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
3867 using ComparisonBiasField =
3868 BitField<ComparisonBias, kFieldComparisonBias, kFieldComparisonBiasSize>;
3869
3870 // Return an integer constant containing the result of a comparison evaluated at compile time.
MakeConstantComparison(int32_t value,uint32_t dex_pc)3871 HIntConstant* MakeConstantComparison(int32_t value, uint32_t dex_pc) const {
3872 DCHECK(value == -1 || value == 0 || value == 1) << value;
3873 return GetBlock()->GetGraph()->GetIntConstant(value, dex_pc);
3874 }
3875
3876 private:
3877 DISALLOW_COPY_AND_ASSIGN(HCompare);
3878 };
3879
3880 class HNewInstance FINAL : public HExpression<1> {
3881 public:
HNewInstance(HInstruction * cls,uint32_t dex_pc,dex::TypeIndex type_index,const DexFile & dex_file,bool finalizable,QuickEntrypointEnum entrypoint)3882 HNewInstance(HInstruction* cls,
3883 uint32_t dex_pc,
3884 dex::TypeIndex type_index,
3885 const DexFile& dex_file,
3886 bool finalizable,
3887 QuickEntrypointEnum entrypoint)
3888 : HExpression(Primitive::kPrimNot, SideEffects::CanTriggerGC(), dex_pc),
3889 type_index_(type_index),
3890 dex_file_(dex_file),
3891 entrypoint_(entrypoint) {
3892 SetPackedFlag<kFlagFinalizable>(finalizable);
3893 SetRawInputAt(0, cls);
3894 }
3895
GetTypeIndex()3896 dex::TypeIndex GetTypeIndex() const { return type_index_; }
GetDexFile()3897 const DexFile& GetDexFile() const { return dex_file_; }
3898
3899 // Calls runtime so needs an environment.
NeedsEnvironment()3900 bool NeedsEnvironment() const OVERRIDE { return true; }
3901
3902 // Can throw errors when out-of-memory or if it's not instantiable/accessible.
CanThrow()3903 bool CanThrow() const OVERRIDE { return true; }
3904
NeedsChecks()3905 bool NeedsChecks() const {
3906 return entrypoint_ == kQuickAllocObjectWithChecks;
3907 }
3908
IsFinalizable()3909 bool IsFinalizable() const { return GetPackedFlag<kFlagFinalizable>(); }
3910
CanBeNull()3911 bool CanBeNull() const OVERRIDE { return false; }
3912
GetEntrypoint()3913 QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; }
3914
SetEntrypoint(QuickEntrypointEnum entrypoint)3915 void SetEntrypoint(QuickEntrypointEnum entrypoint) {
3916 entrypoint_ = entrypoint;
3917 }
3918
GetLoadClass()3919 HLoadClass* GetLoadClass() const {
3920 HInstruction* input = InputAt(0);
3921 if (input->IsClinitCheck()) {
3922 input = input->InputAt(0);
3923 }
3924 DCHECK(input->IsLoadClass());
3925 return input->AsLoadClass();
3926 }
3927
3928 bool IsStringAlloc() const;
3929
3930 DECLARE_INSTRUCTION(NewInstance);
3931
3932 private:
3933 static constexpr size_t kFlagFinalizable = kNumberOfExpressionPackedBits;
3934 static constexpr size_t kNumberOfNewInstancePackedBits = kFlagFinalizable + 1;
3935 static_assert(kNumberOfNewInstancePackedBits <= kMaxNumberOfPackedBits,
3936 "Too many packed fields.");
3937
3938 const dex::TypeIndex type_index_;
3939 const DexFile& dex_file_;
3940 QuickEntrypointEnum entrypoint_;
3941
3942 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
3943 };
3944
3945 enum IntrinsicNeedsEnvironmentOrCache {
3946 kNoEnvironmentOrCache, // Intrinsic does not require an environment or dex cache.
3947 kNeedsEnvironmentOrCache // Intrinsic requires an environment or requires a dex cache.
3948 };
3949
3950 enum IntrinsicSideEffects {
3951 kNoSideEffects, // Intrinsic does not have any heap memory side effects.
3952 kReadSideEffects, // Intrinsic may read heap memory.
3953 kWriteSideEffects, // Intrinsic may write heap memory.
3954 kAllSideEffects // Intrinsic may read or write heap memory, or trigger GC.
3955 };
3956
3957 enum IntrinsicExceptions {
3958 kNoThrow, // Intrinsic does not throw any exceptions.
3959 kCanThrow // Intrinsic may throw exceptions.
3960 };
3961
3962 class HInvoke : public HVariableInputSizeInstruction {
3963 public:
3964 bool NeedsEnvironment() const OVERRIDE;
3965
SetArgumentAt(size_t index,HInstruction * argument)3966 void SetArgumentAt(size_t index, HInstruction* argument) {
3967 SetRawInputAt(index, argument);
3968 }
3969
3970 // Return the number of arguments. This number can be lower than
3971 // the number of inputs returned by InputCount(), as some invoke
3972 // instructions (e.g. HInvokeStaticOrDirect) can have non-argument
3973 // inputs at the end of their list of inputs.
GetNumberOfArguments()3974 uint32_t GetNumberOfArguments() const { return number_of_arguments_; }
3975
GetType()3976 Primitive::Type GetType() const OVERRIDE { return GetPackedField<ReturnTypeField>(); }
3977
GetDexMethodIndex()3978 uint32_t GetDexMethodIndex() const { return dex_method_index_; }
3979
GetInvokeType()3980 InvokeType GetInvokeType() const {
3981 return GetPackedField<InvokeTypeField>();
3982 }
3983
GetIntrinsic()3984 Intrinsics GetIntrinsic() const {
3985 return intrinsic_;
3986 }
3987
3988 void SetIntrinsic(Intrinsics intrinsic,
3989 IntrinsicNeedsEnvironmentOrCache needs_env_or_cache,
3990 IntrinsicSideEffects side_effects,
3991 IntrinsicExceptions exceptions);
3992
IsFromInlinedInvoke()3993 bool IsFromInlinedInvoke() const {
3994 return GetEnvironment()->IsFromInlinedInvoke();
3995 }
3996
SetCanThrow(bool can_throw)3997 void SetCanThrow(bool can_throw) { SetPackedFlag<kFlagCanThrow>(can_throw); }
3998
CanThrow()3999 bool CanThrow() const OVERRIDE { return GetPackedFlag<kFlagCanThrow>(); }
4000
CanBeMoved()4001 bool CanBeMoved() const OVERRIDE { return IsIntrinsic() && !DoesAnyWrite(); }
4002
InstructionDataEquals(const HInstruction * other)4003 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
4004 return intrinsic_ != Intrinsics::kNone && intrinsic_ == other->AsInvoke()->intrinsic_;
4005 }
4006
GetIntrinsicOptimizations()4007 uint32_t* GetIntrinsicOptimizations() {
4008 return &intrinsic_optimizations_;
4009 }
4010
GetIntrinsicOptimizations()4011 const uint32_t* GetIntrinsicOptimizations() const {
4012 return &intrinsic_optimizations_;
4013 }
4014
IsIntrinsic()4015 bool IsIntrinsic() const { return intrinsic_ != Intrinsics::kNone; }
4016
GetResolvedMethod()4017 ArtMethod* GetResolvedMethod() const { return resolved_method_; }
SetResolvedMethod(ArtMethod * method)4018 void SetResolvedMethod(ArtMethod* method) { resolved_method_ = method; }
4019
4020 DECLARE_ABSTRACT_INSTRUCTION(Invoke);
4021
4022 protected:
4023 static constexpr size_t kFieldInvokeType = kNumberOfGenericPackedBits;
4024 static constexpr size_t kFieldInvokeTypeSize =
4025 MinimumBitsToStore(static_cast<size_t>(kMaxInvokeType));
4026 static constexpr size_t kFieldReturnType =
4027 kFieldInvokeType + kFieldInvokeTypeSize;
4028 static constexpr size_t kFieldReturnTypeSize =
4029 MinimumBitsToStore(static_cast<size_t>(Primitive::kPrimLast));
4030 static constexpr size_t kFlagCanThrow = kFieldReturnType + kFieldReturnTypeSize;
4031 static constexpr size_t kNumberOfInvokePackedBits = kFlagCanThrow + 1;
4032 static_assert(kNumberOfInvokePackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
4033 using InvokeTypeField = BitField<InvokeType, kFieldInvokeType, kFieldInvokeTypeSize>;
4034 using ReturnTypeField = BitField<Primitive::Type, kFieldReturnType, kFieldReturnTypeSize>;
4035
HInvoke(ArenaAllocator * arena,uint32_t number_of_arguments,uint32_t number_of_other_inputs,Primitive::Type return_type,uint32_t dex_pc,uint32_t dex_method_index,ArtMethod * resolved_method,InvokeType invoke_type)4036 HInvoke(ArenaAllocator* arena,
4037 uint32_t number_of_arguments,
4038 uint32_t number_of_other_inputs,
4039 Primitive::Type return_type,
4040 uint32_t dex_pc,
4041 uint32_t dex_method_index,
4042 ArtMethod* resolved_method,
4043 InvokeType invoke_type)
4044 : HVariableInputSizeInstruction(
4045 SideEffects::AllExceptGCDependency(), // Assume write/read on all fields/arrays.
4046 dex_pc,
4047 arena,
4048 number_of_arguments + number_of_other_inputs,
4049 kArenaAllocInvokeInputs),
4050 number_of_arguments_(number_of_arguments),
4051 resolved_method_(resolved_method),
4052 dex_method_index_(dex_method_index),
4053 intrinsic_(Intrinsics::kNone),
4054 intrinsic_optimizations_(0) {
4055 SetPackedField<ReturnTypeField>(return_type);
4056 SetPackedField<InvokeTypeField>(invoke_type);
4057 SetPackedFlag<kFlagCanThrow>(true);
4058 }
4059
4060 uint32_t number_of_arguments_;
4061 ArtMethod* resolved_method_;
4062 const uint32_t dex_method_index_;
4063 Intrinsics intrinsic_;
4064
4065 // A magic word holding optimizations for intrinsics. See intrinsics.h.
4066 uint32_t intrinsic_optimizations_;
4067
4068 private:
4069 DISALLOW_COPY_AND_ASSIGN(HInvoke);
4070 };
4071
4072 class HInvokeUnresolved FINAL : public HInvoke {
4073 public:
HInvokeUnresolved(ArenaAllocator * arena,uint32_t number_of_arguments,Primitive::Type return_type,uint32_t dex_pc,uint32_t dex_method_index,InvokeType invoke_type)4074 HInvokeUnresolved(ArenaAllocator* arena,
4075 uint32_t number_of_arguments,
4076 Primitive::Type return_type,
4077 uint32_t dex_pc,
4078 uint32_t dex_method_index,
4079 InvokeType invoke_type)
4080 : HInvoke(arena,
4081 number_of_arguments,
4082 0u /* number_of_other_inputs */,
4083 return_type,
4084 dex_pc,
4085 dex_method_index,
4086 nullptr,
4087 invoke_type) {
4088 }
4089
4090 DECLARE_INSTRUCTION(InvokeUnresolved);
4091
4092 private:
4093 DISALLOW_COPY_AND_ASSIGN(HInvokeUnresolved);
4094 };
4095
4096 class HInvokePolymorphic FINAL : public HInvoke {
4097 public:
HInvokePolymorphic(ArenaAllocator * arena,uint32_t number_of_arguments,Primitive::Type return_type,uint32_t dex_pc,uint32_t dex_method_index)4098 HInvokePolymorphic(ArenaAllocator* arena,
4099 uint32_t number_of_arguments,
4100 Primitive::Type return_type,
4101 uint32_t dex_pc,
4102 uint32_t dex_method_index)
4103 : HInvoke(arena,
4104 number_of_arguments,
4105 0u /* number_of_other_inputs */,
4106 return_type,
4107 dex_pc,
4108 dex_method_index,
4109 nullptr,
4110 kVirtual) {}
4111
4112 DECLARE_INSTRUCTION(InvokePolymorphic);
4113
4114 private:
4115 DISALLOW_COPY_AND_ASSIGN(HInvokePolymorphic);
4116 };
4117
4118 class HInvokeStaticOrDirect FINAL : public HInvoke {
4119 public:
4120 // Requirements of this method call regarding the class
4121 // initialization (clinit) check of its declaring class.
4122 enum class ClinitCheckRequirement {
4123 kNone, // Class already initialized.
4124 kExplicit, // Static call having explicit clinit check as last input.
4125 kImplicit, // Static call implicitly requiring a clinit check.
4126 kLast = kImplicit
4127 };
4128
4129 // Determines how to load the target ArtMethod*.
4130 enum class MethodLoadKind {
4131 // Use a String init ArtMethod* loaded from Thread entrypoints.
4132 kStringInit,
4133
4134 // Use the method's own ArtMethod* loaded by the register allocator.
4135 kRecursive,
4136
4137 // Use ArtMethod* at a known address, embed the direct address in the code.
4138 // Used for app->boot calls with non-relocatable image and for JIT-compiled calls.
4139 kDirectAddress,
4140
4141 // Load from resolved methods array in the dex cache using a PC-relative load.
4142 // Used when we need to use the dex cache, for example for invoke-static that
4143 // may cause class initialization (the entry may point to a resolution method),
4144 // and we know that we can access the dex cache arrays using a PC-relative load.
4145 kDexCachePcRelative,
4146
4147 // Use ArtMethod* from the resolved methods of the compiled method's own ArtMethod*.
4148 // Used for JIT when we need to use the dex cache. This is also the last-resort-kind
4149 // used when other kinds are unavailable (say, dex cache arrays are not PC-relative)
4150 // or unimplemented or impractical (i.e. slow) on a particular architecture.
4151 kDexCacheViaMethod,
4152 };
4153
4154 // Determines the location of the code pointer.
4155 enum class CodePtrLocation {
4156 // Recursive call, use local PC-relative call instruction.
4157 kCallSelf,
4158
4159 // Use code pointer from the ArtMethod*.
4160 // Used when we don't know the target code. This is also the last-resort-kind used when
4161 // other kinds are unimplemented or impractical (i.e. slow) on a particular architecture.
4162 kCallArtMethod,
4163 };
4164
4165 struct DispatchInfo {
4166 MethodLoadKind method_load_kind;
4167 CodePtrLocation code_ptr_location;
4168 // The method load data holds
4169 // - thread entrypoint offset for kStringInit method if this is a string init invoke.
4170 // Note that there are multiple string init methods, each having its own offset.
4171 // - the method address for kDirectAddress
4172 // - the dex cache arrays offset for kDexCachePcRel.
4173 uint64_t method_load_data;
4174 };
4175
HInvokeStaticOrDirect(ArenaAllocator * arena,uint32_t number_of_arguments,Primitive::Type return_type,uint32_t dex_pc,uint32_t method_index,ArtMethod * resolved_method,DispatchInfo dispatch_info,InvokeType invoke_type,MethodReference target_method,ClinitCheckRequirement clinit_check_requirement)4176 HInvokeStaticOrDirect(ArenaAllocator* arena,
4177 uint32_t number_of_arguments,
4178 Primitive::Type return_type,
4179 uint32_t dex_pc,
4180 uint32_t method_index,
4181 ArtMethod* resolved_method,
4182 DispatchInfo dispatch_info,
4183 InvokeType invoke_type,
4184 MethodReference target_method,
4185 ClinitCheckRequirement clinit_check_requirement)
4186 : HInvoke(arena,
4187 number_of_arguments,
4188 // There is potentially one extra argument for the HCurrentMethod node, and
4189 // potentially one other if the clinit check is explicit, and potentially
4190 // one other if the method is a string factory.
4191 (NeedsCurrentMethodInput(dispatch_info.method_load_kind) ? 1u : 0u) +
4192 (clinit_check_requirement == ClinitCheckRequirement::kExplicit ? 1u : 0u),
4193 return_type,
4194 dex_pc,
4195 method_index,
4196 resolved_method,
4197 invoke_type),
4198 target_method_(target_method),
4199 dispatch_info_(dispatch_info) {
4200 SetPackedField<ClinitCheckRequirementField>(clinit_check_requirement);
4201 }
4202
SetDispatchInfo(const DispatchInfo & dispatch_info)4203 void SetDispatchInfo(const DispatchInfo& dispatch_info) {
4204 bool had_current_method_input = HasCurrentMethodInput();
4205 bool needs_current_method_input = NeedsCurrentMethodInput(dispatch_info.method_load_kind);
4206
4207 // Using the current method is the default and once we find a better
4208 // method load kind, we should not go back to using the current method.
4209 DCHECK(had_current_method_input || !needs_current_method_input);
4210
4211 if (had_current_method_input && !needs_current_method_input) {
4212 DCHECK_EQ(InputAt(GetSpecialInputIndex()), GetBlock()->GetGraph()->GetCurrentMethod());
4213 RemoveInputAt(GetSpecialInputIndex());
4214 }
4215 dispatch_info_ = dispatch_info;
4216 }
4217
GetDispatchInfo()4218 DispatchInfo GetDispatchInfo() const {
4219 return dispatch_info_;
4220 }
4221
AddSpecialInput(HInstruction * input)4222 void AddSpecialInput(HInstruction* input) {
4223 // We allow only one special input.
4224 DCHECK(!IsStringInit() && !HasCurrentMethodInput());
4225 DCHECK(InputCount() == GetSpecialInputIndex() ||
4226 (InputCount() == GetSpecialInputIndex() + 1 && IsStaticWithExplicitClinitCheck()));
4227 InsertInputAt(GetSpecialInputIndex(), input);
4228 }
4229
4230 using HInstruction::GetInputRecords; // Keep the const version visible.
GetInputRecords()4231 ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() OVERRIDE {
4232 ArrayRef<HUserRecord<HInstruction*>> input_records = HInvoke::GetInputRecords();
4233 if (kIsDebugBuild && IsStaticWithExplicitClinitCheck()) {
4234 DCHECK(!input_records.empty());
4235 DCHECK_GT(input_records.size(), GetNumberOfArguments());
4236 HInstruction* last_input = input_records.back().GetInstruction();
4237 // Note: `last_input` may be null during arguments setup.
4238 if (last_input != nullptr) {
4239 // `last_input` is the last input of a static invoke marked as having
4240 // an explicit clinit check. It must either be:
4241 // - an art::HClinitCheck instruction, set by art::HGraphBuilder; or
4242 // - an art::HLoadClass instruction, set by art::PrepareForRegisterAllocation.
4243 DCHECK(last_input->IsClinitCheck() || last_input->IsLoadClass()) << last_input->DebugName();
4244 }
4245 }
4246 return input_records;
4247 }
4248
CanDoImplicitNullCheckOn(HInstruction * obj ATTRIBUTE_UNUSED)4249 bool CanDoImplicitNullCheckOn(HInstruction* obj ATTRIBUTE_UNUSED) const OVERRIDE {
4250 // We access the method via the dex cache so we can't do an implicit null check.
4251 // TODO: for intrinsics we can generate implicit null checks.
4252 return false;
4253 }
4254
CanBeNull()4255 bool CanBeNull() const OVERRIDE {
4256 return GetPackedField<ReturnTypeField>() == Primitive::kPrimNot && !IsStringInit();
4257 }
4258
4259 // Get the index of the special input, if any.
4260 //
4261 // If the invoke HasCurrentMethodInput(), the "special input" is the current
4262 // method pointer; otherwise there may be one platform-specific special input,
4263 // such as PC-relative addressing base.
GetSpecialInputIndex()4264 uint32_t GetSpecialInputIndex() const { return GetNumberOfArguments(); }
HasSpecialInput()4265 bool HasSpecialInput() const { return GetNumberOfArguments() != InputCount(); }
4266
GetMethodLoadKind()4267 MethodLoadKind GetMethodLoadKind() const { return dispatch_info_.method_load_kind; }
GetCodePtrLocation()4268 CodePtrLocation GetCodePtrLocation() const { return dispatch_info_.code_ptr_location; }
IsRecursive()4269 bool IsRecursive() const { return GetMethodLoadKind() == MethodLoadKind::kRecursive; }
4270 bool NeedsDexCacheOfDeclaringClass() const OVERRIDE;
IsStringInit()4271 bool IsStringInit() const { return GetMethodLoadKind() == MethodLoadKind::kStringInit; }
HasMethodAddress()4272 bool HasMethodAddress() const { return GetMethodLoadKind() == MethodLoadKind::kDirectAddress; }
HasPcRelativeDexCache()4273 bool HasPcRelativeDexCache() const {
4274 return GetMethodLoadKind() == MethodLoadKind::kDexCachePcRelative;
4275 }
HasCurrentMethodInput()4276 bool HasCurrentMethodInput() const {
4277 // This function can be called only after the invoke has been fully initialized by the builder.
4278 if (NeedsCurrentMethodInput(GetMethodLoadKind())) {
4279 DCHECK(InputAt(GetSpecialInputIndex())->IsCurrentMethod());
4280 return true;
4281 } else {
4282 DCHECK(InputCount() == GetSpecialInputIndex() ||
4283 !InputAt(GetSpecialInputIndex())->IsCurrentMethod());
4284 return false;
4285 }
4286 }
4287
GetStringInitEntryPoint()4288 QuickEntrypointEnum GetStringInitEntryPoint() const {
4289 DCHECK(IsStringInit());
4290 return static_cast<QuickEntrypointEnum>(dispatch_info_.method_load_data);
4291 }
4292
GetMethodAddress()4293 uint64_t GetMethodAddress() const {
4294 DCHECK(HasMethodAddress());
4295 return dispatch_info_.method_load_data;
4296 }
4297
GetDexCacheArrayOffset()4298 uint32_t GetDexCacheArrayOffset() const {
4299 DCHECK(HasPcRelativeDexCache());
4300 return dispatch_info_.method_load_data;
4301 }
4302
4303 const DexFile& GetDexFileForPcRelativeDexCache() const;
4304
GetClinitCheckRequirement()4305 ClinitCheckRequirement GetClinitCheckRequirement() const {
4306 return GetPackedField<ClinitCheckRequirementField>();
4307 }
4308
4309 // Is this instruction a call to a static method?
IsStatic()4310 bool IsStatic() const {
4311 return GetInvokeType() == kStatic;
4312 }
4313
GetTargetMethod()4314 MethodReference GetTargetMethod() const {
4315 return target_method_;
4316 }
4317
4318 // Remove the HClinitCheck or the replacement HLoadClass (set as last input by
4319 // PrepareForRegisterAllocation::VisitClinitCheck() in lieu of the initial HClinitCheck)
4320 // instruction; only relevant for static calls with explicit clinit check.
RemoveExplicitClinitCheck(ClinitCheckRequirement new_requirement)4321 void RemoveExplicitClinitCheck(ClinitCheckRequirement new_requirement) {
4322 DCHECK(IsStaticWithExplicitClinitCheck());
4323 size_t last_input_index = inputs_.size() - 1u;
4324 HInstruction* last_input = inputs_.back().GetInstruction();
4325 DCHECK(last_input != nullptr);
4326 DCHECK(last_input->IsLoadClass() || last_input->IsClinitCheck()) << last_input->DebugName();
4327 RemoveAsUserOfInput(last_input_index);
4328 inputs_.pop_back();
4329 SetPackedField<ClinitCheckRequirementField>(new_requirement);
4330 DCHECK(!IsStaticWithExplicitClinitCheck());
4331 }
4332
4333 // Is this a call to a static method whose declaring class has an
4334 // explicit initialization check in the graph?
IsStaticWithExplicitClinitCheck()4335 bool IsStaticWithExplicitClinitCheck() const {
4336 return IsStatic() && (GetClinitCheckRequirement() == ClinitCheckRequirement::kExplicit);
4337 }
4338
4339 // Is this a call to a static method whose declaring class has an
4340 // implicit intialization check requirement?
IsStaticWithImplicitClinitCheck()4341 bool IsStaticWithImplicitClinitCheck() const {
4342 return IsStatic() && (GetClinitCheckRequirement() == ClinitCheckRequirement::kImplicit);
4343 }
4344
4345 // Does this method load kind need the current method as an input?
NeedsCurrentMethodInput(MethodLoadKind kind)4346 static bool NeedsCurrentMethodInput(MethodLoadKind kind) {
4347 return kind == MethodLoadKind::kRecursive || kind == MethodLoadKind::kDexCacheViaMethod;
4348 }
4349
4350 DECLARE_INSTRUCTION(InvokeStaticOrDirect);
4351
4352 private:
4353 static constexpr size_t kFieldClinitCheckRequirement = kNumberOfInvokePackedBits;
4354 static constexpr size_t kFieldClinitCheckRequirementSize =
4355 MinimumBitsToStore(static_cast<size_t>(ClinitCheckRequirement::kLast));
4356 static constexpr size_t kNumberOfInvokeStaticOrDirectPackedBits =
4357 kFieldClinitCheckRequirement + kFieldClinitCheckRequirementSize;
4358 static_assert(kNumberOfInvokeStaticOrDirectPackedBits <= kMaxNumberOfPackedBits,
4359 "Too many packed fields.");
4360 using ClinitCheckRequirementField = BitField<ClinitCheckRequirement,
4361 kFieldClinitCheckRequirement,
4362 kFieldClinitCheckRequirementSize>;
4363
4364 // Cached values of the resolved method, to avoid needing the mutator lock.
4365 MethodReference target_method_;
4366 DispatchInfo dispatch_info_;
4367
4368 DISALLOW_COPY_AND_ASSIGN(HInvokeStaticOrDirect);
4369 };
4370 std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::MethodLoadKind rhs);
4371 std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::ClinitCheckRequirement rhs);
4372
4373 class HInvokeVirtual FINAL : public HInvoke {
4374 public:
HInvokeVirtual(ArenaAllocator * arena,uint32_t number_of_arguments,Primitive::Type return_type,uint32_t dex_pc,uint32_t dex_method_index,ArtMethod * resolved_method,uint32_t vtable_index)4375 HInvokeVirtual(ArenaAllocator* arena,
4376 uint32_t number_of_arguments,
4377 Primitive::Type return_type,
4378 uint32_t dex_pc,
4379 uint32_t dex_method_index,
4380 ArtMethod* resolved_method,
4381 uint32_t vtable_index)
4382 : HInvoke(arena,
4383 number_of_arguments,
4384 0u,
4385 return_type,
4386 dex_pc,
4387 dex_method_index,
4388 resolved_method,
4389 kVirtual),
4390 vtable_index_(vtable_index) {}
4391
CanBeNull()4392 bool CanBeNull() const OVERRIDE {
4393 switch (GetIntrinsic()) {
4394 case Intrinsics::kThreadCurrentThread:
4395 case Intrinsics::kStringBufferAppend:
4396 case Intrinsics::kStringBufferToString:
4397 case Intrinsics::kStringBuilderAppend:
4398 case Intrinsics::kStringBuilderToString:
4399 return false;
4400 default:
4401 return HInvoke::CanBeNull();
4402 }
4403 }
4404
CanDoImplicitNullCheckOn(HInstruction * obj)4405 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
4406 // TODO: Add implicit null checks in intrinsics.
4407 return (obj == InputAt(0)) && !GetLocations()->Intrinsified();
4408 }
4409
GetVTableIndex()4410 uint32_t GetVTableIndex() const { return vtable_index_; }
4411
4412 DECLARE_INSTRUCTION(InvokeVirtual);
4413
4414 private:
4415 // Cached value of the resolved method, to avoid needing the mutator lock.
4416 const uint32_t vtable_index_;
4417
4418 DISALLOW_COPY_AND_ASSIGN(HInvokeVirtual);
4419 };
4420
4421 class HInvokeInterface FINAL : public HInvoke {
4422 public:
HInvokeInterface(ArenaAllocator * arena,uint32_t number_of_arguments,Primitive::Type return_type,uint32_t dex_pc,uint32_t dex_method_index,ArtMethod * resolved_method,uint32_t imt_index)4423 HInvokeInterface(ArenaAllocator* arena,
4424 uint32_t number_of_arguments,
4425 Primitive::Type return_type,
4426 uint32_t dex_pc,
4427 uint32_t dex_method_index,
4428 ArtMethod* resolved_method,
4429 uint32_t imt_index)
4430 : HInvoke(arena,
4431 number_of_arguments,
4432 0u,
4433 return_type,
4434 dex_pc,
4435 dex_method_index,
4436 resolved_method,
4437 kInterface),
4438 imt_index_(imt_index) {}
4439
CanDoImplicitNullCheckOn(HInstruction * obj)4440 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
4441 // TODO: Add implicit null checks in intrinsics.
4442 return (obj == InputAt(0)) && !GetLocations()->Intrinsified();
4443 }
4444
NeedsDexCacheOfDeclaringClass()4445 bool NeedsDexCacheOfDeclaringClass() const OVERRIDE {
4446 // The assembly stub currently needs it.
4447 return true;
4448 }
4449
GetImtIndex()4450 uint32_t GetImtIndex() const { return imt_index_; }
GetDexMethodIndex()4451 uint32_t GetDexMethodIndex() const { return dex_method_index_; }
4452
4453 DECLARE_INSTRUCTION(InvokeInterface);
4454
4455 private:
4456 // Cached value of the resolved method, to avoid needing the mutator lock.
4457 const uint32_t imt_index_;
4458
4459 DISALLOW_COPY_AND_ASSIGN(HInvokeInterface);
4460 };
4461
4462 class HNeg FINAL : public HUnaryOperation {
4463 public:
4464 HNeg(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
HUnaryOperation(result_type,input,dex_pc)4465 : HUnaryOperation(result_type, input, dex_pc) {
4466 DCHECK_EQ(result_type, Primitive::PrimitiveKind(input->GetType()));
4467 }
4468
Compute(T x)4469 template <typename T> static T Compute(T x) { return -x; }
4470
Evaluate(HIntConstant * x)4471 HConstant* Evaluate(HIntConstant* x) const OVERRIDE {
4472 return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()), GetDexPc());
4473 }
Evaluate(HLongConstant * x)4474 HConstant* Evaluate(HLongConstant* x) const OVERRIDE {
4475 return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue()), GetDexPc());
4476 }
Evaluate(HFloatConstant * x)4477 HConstant* Evaluate(HFloatConstant* x) const OVERRIDE {
4478 return GetBlock()->GetGraph()->GetFloatConstant(Compute(x->GetValue()), GetDexPc());
4479 }
Evaluate(HDoubleConstant * x)4480 HConstant* Evaluate(HDoubleConstant* x) const OVERRIDE {
4481 return GetBlock()->GetGraph()->GetDoubleConstant(Compute(x->GetValue()), GetDexPc());
4482 }
4483
4484 DECLARE_INSTRUCTION(Neg);
4485
4486 private:
4487 DISALLOW_COPY_AND_ASSIGN(HNeg);
4488 };
4489
4490 class HNewArray FINAL : public HExpression<2> {
4491 public:
HNewArray(HInstruction * cls,HInstruction * length,uint32_t dex_pc)4492 HNewArray(HInstruction* cls, HInstruction* length, uint32_t dex_pc)
4493 : HExpression(Primitive::kPrimNot, SideEffects::CanTriggerGC(), dex_pc) {
4494 SetRawInputAt(0, cls);
4495 SetRawInputAt(1, length);
4496 }
4497
4498 // Calls runtime so needs an environment.
NeedsEnvironment()4499 bool NeedsEnvironment() const OVERRIDE { return true; }
4500
4501 // May throw NegativeArraySizeException, OutOfMemoryError, etc.
CanThrow()4502 bool CanThrow() const OVERRIDE { return true; }
4503
CanBeNull()4504 bool CanBeNull() const OVERRIDE { return false; }
4505
GetLoadClass()4506 HLoadClass* GetLoadClass() const {
4507 DCHECK(InputAt(0)->IsLoadClass());
4508 return InputAt(0)->AsLoadClass();
4509 }
4510
GetLength()4511 HInstruction* GetLength() const {
4512 return InputAt(1);
4513 }
4514
4515 DECLARE_INSTRUCTION(NewArray);
4516
4517 private:
4518 DISALLOW_COPY_AND_ASSIGN(HNewArray);
4519 };
4520
4521 class HAdd FINAL : public HBinaryOperation {
4522 public:
4523 HAdd(Primitive::Type result_type,
4524 HInstruction* left,
4525 HInstruction* right,
4526 uint32_t dex_pc = kNoDexPc)
HBinaryOperation(result_type,left,right,SideEffects::None (),dex_pc)4527 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
4528
IsCommutative()4529 bool IsCommutative() const OVERRIDE { return true; }
4530
Compute(T x,T y)4531 template <typename T> static T Compute(T x, T y) { return x + y; }
4532
Evaluate(HIntConstant * x,HIntConstant * y)4533 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
4534 return GetBlock()->GetGraph()->GetIntConstant(
4535 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4536 }
Evaluate(HLongConstant * x,HLongConstant * y)4537 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
4538 return GetBlock()->GetGraph()->GetLongConstant(
4539 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4540 }
Evaluate(HFloatConstant * x,HFloatConstant * y)4541 HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
4542 return GetBlock()->GetGraph()->GetFloatConstant(
4543 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4544 }
Evaluate(HDoubleConstant * x,HDoubleConstant * y)4545 HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
4546 return GetBlock()->GetGraph()->GetDoubleConstant(
4547 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4548 }
4549
4550 DECLARE_INSTRUCTION(Add);
4551
4552 private:
4553 DISALLOW_COPY_AND_ASSIGN(HAdd);
4554 };
4555
4556 class HSub FINAL : public HBinaryOperation {
4557 public:
4558 HSub(Primitive::Type result_type,
4559 HInstruction* left,
4560 HInstruction* right,
4561 uint32_t dex_pc = kNoDexPc)
HBinaryOperation(result_type,left,right,SideEffects::None (),dex_pc)4562 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
4563
Compute(T x,T y)4564 template <typename T> static T Compute(T x, T y) { return x - y; }
4565
Evaluate(HIntConstant * x,HIntConstant * y)4566 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
4567 return GetBlock()->GetGraph()->GetIntConstant(
4568 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4569 }
Evaluate(HLongConstant * x,HLongConstant * y)4570 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
4571 return GetBlock()->GetGraph()->GetLongConstant(
4572 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4573 }
Evaluate(HFloatConstant * x,HFloatConstant * y)4574 HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
4575 return GetBlock()->GetGraph()->GetFloatConstant(
4576 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4577 }
Evaluate(HDoubleConstant * x,HDoubleConstant * y)4578 HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
4579 return GetBlock()->GetGraph()->GetDoubleConstant(
4580 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4581 }
4582
4583 DECLARE_INSTRUCTION(Sub);
4584
4585 private:
4586 DISALLOW_COPY_AND_ASSIGN(HSub);
4587 };
4588
4589 class HMul FINAL : public HBinaryOperation {
4590 public:
4591 HMul(Primitive::Type result_type,
4592 HInstruction* left,
4593 HInstruction* right,
4594 uint32_t dex_pc = kNoDexPc)
HBinaryOperation(result_type,left,right,SideEffects::None (),dex_pc)4595 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
4596
IsCommutative()4597 bool IsCommutative() const OVERRIDE { return true; }
4598
Compute(T x,T y)4599 template <typename T> static T Compute(T x, T y) { return x * y; }
4600
Evaluate(HIntConstant * x,HIntConstant * y)4601 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
4602 return GetBlock()->GetGraph()->GetIntConstant(
4603 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4604 }
Evaluate(HLongConstant * x,HLongConstant * y)4605 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
4606 return GetBlock()->GetGraph()->GetLongConstant(
4607 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4608 }
Evaluate(HFloatConstant * x,HFloatConstant * y)4609 HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
4610 return GetBlock()->GetGraph()->GetFloatConstant(
4611 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4612 }
Evaluate(HDoubleConstant * x,HDoubleConstant * y)4613 HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
4614 return GetBlock()->GetGraph()->GetDoubleConstant(
4615 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4616 }
4617
4618 DECLARE_INSTRUCTION(Mul);
4619
4620 private:
4621 DISALLOW_COPY_AND_ASSIGN(HMul);
4622 };
4623
4624 class HDiv FINAL : public HBinaryOperation {
4625 public:
HDiv(Primitive::Type result_type,HInstruction * left,HInstruction * right,uint32_t dex_pc)4626 HDiv(Primitive::Type result_type,
4627 HInstruction* left,
4628 HInstruction* right,
4629 uint32_t dex_pc)
4630 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
4631
4632 template <typename T>
ComputeIntegral(T x,T y)4633 T ComputeIntegral(T x, T y) const {
4634 DCHECK(!Primitive::IsFloatingPointType(GetType())) << GetType();
4635 // Our graph structure ensures we never have 0 for `y` during
4636 // constant folding.
4637 DCHECK_NE(y, 0);
4638 // Special case -1 to avoid getting a SIGFPE on x86(_64).
4639 return (y == -1) ? -x : x / y;
4640 }
4641
4642 template <typename T>
ComputeFP(T x,T y)4643 T ComputeFP(T x, T y) const {
4644 DCHECK(Primitive::IsFloatingPointType(GetType())) << GetType();
4645 return x / y;
4646 }
4647
Evaluate(HIntConstant * x,HIntConstant * y)4648 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
4649 return GetBlock()->GetGraph()->GetIntConstant(
4650 ComputeIntegral(x->GetValue(), y->GetValue()), GetDexPc());
4651 }
Evaluate(HLongConstant * x,HLongConstant * y)4652 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
4653 return GetBlock()->GetGraph()->GetLongConstant(
4654 ComputeIntegral(x->GetValue(), y->GetValue()), GetDexPc());
4655 }
Evaluate(HFloatConstant * x,HFloatConstant * y)4656 HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
4657 return GetBlock()->GetGraph()->GetFloatConstant(
4658 ComputeFP(x->GetValue(), y->GetValue()), GetDexPc());
4659 }
Evaluate(HDoubleConstant * x,HDoubleConstant * y)4660 HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
4661 return GetBlock()->GetGraph()->GetDoubleConstant(
4662 ComputeFP(x->GetValue(), y->GetValue()), GetDexPc());
4663 }
4664
4665 DECLARE_INSTRUCTION(Div);
4666
4667 private:
4668 DISALLOW_COPY_AND_ASSIGN(HDiv);
4669 };
4670
4671 class HRem FINAL : public HBinaryOperation {
4672 public:
HRem(Primitive::Type result_type,HInstruction * left,HInstruction * right,uint32_t dex_pc)4673 HRem(Primitive::Type result_type,
4674 HInstruction* left,
4675 HInstruction* right,
4676 uint32_t dex_pc)
4677 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
4678
4679 template <typename T>
ComputeIntegral(T x,T y)4680 T ComputeIntegral(T x, T y) const {
4681 DCHECK(!Primitive::IsFloatingPointType(GetType())) << GetType();
4682 // Our graph structure ensures we never have 0 for `y` during
4683 // constant folding.
4684 DCHECK_NE(y, 0);
4685 // Special case -1 to avoid getting a SIGFPE on x86(_64).
4686 return (y == -1) ? 0 : x % y;
4687 }
4688
4689 template <typename T>
ComputeFP(T x,T y)4690 T ComputeFP(T x, T y) const {
4691 DCHECK(Primitive::IsFloatingPointType(GetType())) << GetType();
4692 return std::fmod(x, y);
4693 }
4694
Evaluate(HIntConstant * x,HIntConstant * y)4695 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
4696 return GetBlock()->GetGraph()->GetIntConstant(
4697 ComputeIntegral(x->GetValue(), y->GetValue()), GetDexPc());
4698 }
Evaluate(HLongConstant * x,HLongConstant * y)4699 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
4700 return GetBlock()->GetGraph()->GetLongConstant(
4701 ComputeIntegral(x->GetValue(), y->GetValue()), GetDexPc());
4702 }
Evaluate(HFloatConstant * x,HFloatConstant * y)4703 HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const OVERRIDE {
4704 return GetBlock()->GetGraph()->GetFloatConstant(
4705 ComputeFP(x->GetValue(), y->GetValue()), GetDexPc());
4706 }
Evaluate(HDoubleConstant * x,HDoubleConstant * y)4707 HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const OVERRIDE {
4708 return GetBlock()->GetGraph()->GetDoubleConstant(
4709 ComputeFP(x->GetValue(), y->GetValue()), GetDexPc());
4710 }
4711
4712 DECLARE_INSTRUCTION(Rem);
4713
4714 private:
4715 DISALLOW_COPY_AND_ASSIGN(HRem);
4716 };
4717
4718 class HDivZeroCheck FINAL : public HExpression<1> {
4719 public:
4720 // `HDivZeroCheck` can trigger GC, as it may call the `ArithmeticException`
4721 // constructor.
HDivZeroCheck(HInstruction * value,uint32_t dex_pc)4722 HDivZeroCheck(HInstruction* value, uint32_t dex_pc)
4723 : HExpression(value->GetType(), SideEffects::CanTriggerGC(), dex_pc) {
4724 SetRawInputAt(0, value);
4725 }
4726
GetType()4727 Primitive::Type GetType() const OVERRIDE { return InputAt(0)->GetType(); }
4728
CanBeMoved()4729 bool CanBeMoved() const OVERRIDE { return true; }
4730
InstructionDataEquals(const HInstruction * other ATTRIBUTE_UNUSED)4731 bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
4732 return true;
4733 }
4734
NeedsEnvironment()4735 bool NeedsEnvironment() const OVERRIDE { return true; }
CanThrow()4736 bool CanThrow() const OVERRIDE { return true; }
4737
4738 DECLARE_INSTRUCTION(DivZeroCheck);
4739
4740 private:
4741 DISALLOW_COPY_AND_ASSIGN(HDivZeroCheck);
4742 };
4743
4744 class HShl FINAL : public HBinaryOperation {
4745 public:
4746 HShl(Primitive::Type result_type,
4747 HInstruction* value,
4748 HInstruction* distance,
4749 uint32_t dex_pc = kNoDexPc)
HBinaryOperation(result_type,value,distance,SideEffects::None (),dex_pc)4750 : HBinaryOperation(result_type, value, distance, SideEffects::None(), dex_pc) {
4751 DCHECK_EQ(result_type, Primitive::PrimitiveKind(value->GetType()));
4752 DCHECK_EQ(Primitive::kPrimInt, Primitive::PrimitiveKind(distance->GetType()));
4753 }
4754
4755 template <typename T>
Compute(T value,int32_t distance,int32_t max_shift_distance)4756 static T Compute(T value, int32_t distance, int32_t max_shift_distance) {
4757 return value << (distance & max_shift_distance);
4758 }
4759
Evaluate(HIntConstant * value,HIntConstant * distance)4760 HConstant* Evaluate(HIntConstant* value, HIntConstant* distance) const OVERRIDE {
4761 return GetBlock()->GetGraph()->GetIntConstant(
4762 Compute(value->GetValue(), distance->GetValue(), kMaxIntShiftDistance), GetDexPc());
4763 }
Evaluate(HLongConstant * value,HIntConstant * distance)4764 HConstant* Evaluate(HLongConstant* value, HIntConstant* distance) const OVERRIDE {
4765 return GetBlock()->GetGraph()->GetLongConstant(
4766 Compute(value->GetValue(), distance->GetValue(), kMaxLongShiftDistance), GetDexPc());
4767 }
Evaluate(HLongConstant * value ATTRIBUTE_UNUSED,HLongConstant * distance ATTRIBUTE_UNUSED)4768 HConstant* Evaluate(HLongConstant* value ATTRIBUTE_UNUSED,
4769 HLongConstant* distance ATTRIBUTE_UNUSED) const OVERRIDE {
4770 LOG(FATAL) << DebugName() << " is not defined for the (long, long) case.";
4771 UNREACHABLE();
4772 }
Evaluate(HFloatConstant * value ATTRIBUTE_UNUSED,HFloatConstant * distance ATTRIBUTE_UNUSED)4773 HConstant* Evaluate(HFloatConstant* value ATTRIBUTE_UNUSED,
4774 HFloatConstant* distance ATTRIBUTE_UNUSED) const OVERRIDE {
4775 LOG(FATAL) << DebugName() << " is not defined for float values";
4776 UNREACHABLE();
4777 }
Evaluate(HDoubleConstant * value ATTRIBUTE_UNUSED,HDoubleConstant * distance ATTRIBUTE_UNUSED)4778 HConstant* Evaluate(HDoubleConstant* value ATTRIBUTE_UNUSED,
4779 HDoubleConstant* distance ATTRIBUTE_UNUSED) const OVERRIDE {
4780 LOG(FATAL) << DebugName() << " is not defined for double values";
4781 UNREACHABLE();
4782 }
4783
4784 DECLARE_INSTRUCTION(Shl);
4785
4786 private:
4787 DISALLOW_COPY_AND_ASSIGN(HShl);
4788 };
4789
4790 class HShr FINAL : public HBinaryOperation {
4791 public:
4792 HShr(Primitive::Type result_type,
4793 HInstruction* value,
4794 HInstruction* distance,
4795 uint32_t dex_pc = kNoDexPc)
HBinaryOperation(result_type,value,distance,SideEffects::None (),dex_pc)4796 : HBinaryOperation(result_type, value, distance, SideEffects::None(), dex_pc) {
4797 DCHECK_EQ(result_type, Primitive::PrimitiveKind(value->GetType()));
4798 DCHECK_EQ(Primitive::kPrimInt, Primitive::PrimitiveKind(distance->GetType()));
4799 }
4800
4801 template <typename T>
Compute(T value,int32_t distance,int32_t max_shift_distance)4802 static T Compute(T value, int32_t distance, int32_t max_shift_distance) {
4803 return value >> (distance & max_shift_distance);
4804 }
4805
Evaluate(HIntConstant * value,HIntConstant * distance)4806 HConstant* Evaluate(HIntConstant* value, HIntConstant* distance) const OVERRIDE {
4807 return GetBlock()->GetGraph()->GetIntConstant(
4808 Compute(value->GetValue(), distance->GetValue(), kMaxIntShiftDistance), GetDexPc());
4809 }
Evaluate(HLongConstant * value,HIntConstant * distance)4810 HConstant* Evaluate(HLongConstant* value, HIntConstant* distance) const OVERRIDE {
4811 return GetBlock()->GetGraph()->GetLongConstant(
4812 Compute(value->GetValue(), distance->GetValue(), kMaxLongShiftDistance), GetDexPc());
4813 }
Evaluate(HLongConstant * value ATTRIBUTE_UNUSED,HLongConstant * distance ATTRIBUTE_UNUSED)4814 HConstant* Evaluate(HLongConstant* value ATTRIBUTE_UNUSED,
4815 HLongConstant* distance ATTRIBUTE_UNUSED) const OVERRIDE {
4816 LOG(FATAL) << DebugName() << " is not defined for the (long, long) case.";
4817 UNREACHABLE();
4818 }
Evaluate(HFloatConstant * value ATTRIBUTE_UNUSED,HFloatConstant * distance ATTRIBUTE_UNUSED)4819 HConstant* Evaluate(HFloatConstant* value ATTRIBUTE_UNUSED,
4820 HFloatConstant* distance ATTRIBUTE_UNUSED) const OVERRIDE {
4821 LOG(FATAL) << DebugName() << " is not defined for float values";
4822 UNREACHABLE();
4823 }
Evaluate(HDoubleConstant * value ATTRIBUTE_UNUSED,HDoubleConstant * distance ATTRIBUTE_UNUSED)4824 HConstant* Evaluate(HDoubleConstant* value ATTRIBUTE_UNUSED,
4825 HDoubleConstant* distance ATTRIBUTE_UNUSED) const OVERRIDE {
4826 LOG(FATAL) << DebugName() << " is not defined for double values";
4827 UNREACHABLE();
4828 }
4829
4830 DECLARE_INSTRUCTION(Shr);
4831
4832 private:
4833 DISALLOW_COPY_AND_ASSIGN(HShr);
4834 };
4835
4836 class HUShr FINAL : public HBinaryOperation {
4837 public:
4838 HUShr(Primitive::Type result_type,
4839 HInstruction* value,
4840 HInstruction* distance,
4841 uint32_t dex_pc = kNoDexPc)
HBinaryOperation(result_type,value,distance,SideEffects::None (),dex_pc)4842 : HBinaryOperation(result_type, value, distance, SideEffects::None(), dex_pc) {
4843 DCHECK_EQ(result_type, Primitive::PrimitiveKind(value->GetType()));
4844 DCHECK_EQ(Primitive::kPrimInt, Primitive::PrimitiveKind(distance->GetType()));
4845 }
4846
4847 template <typename T>
Compute(T value,int32_t distance,int32_t max_shift_distance)4848 static T Compute(T value, int32_t distance, int32_t max_shift_distance) {
4849 typedef typename std::make_unsigned<T>::type V;
4850 V ux = static_cast<V>(value);
4851 return static_cast<T>(ux >> (distance & max_shift_distance));
4852 }
4853
Evaluate(HIntConstant * value,HIntConstant * distance)4854 HConstant* Evaluate(HIntConstant* value, HIntConstant* distance) const OVERRIDE {
4855 return GetBlock()->GetGraph()->GetIntConstant(
4856 Compute(value->GetValue(), distance->GetValue(), kMaxIntShiftDistance), GetDexPc());
4857 }
Evaluate(HLongConstant * value,HIntConstant * distance)4858 HConstant* Evaluate(HLongConstant* value, HIntConstant* distance) const OVERRIDE {
4859 return GetBlock()->GetGraph()->GetLongConstant(
4860 Compute(value->GetValue(), distance->GetValue(), kMaxLongShiftDistance), GetDexPc());
4861 }
Evaluate(HLongConstant * value ATTRIBUTE_UNUSED,HLongConstant * distance ATTRIBUTE_UNUSED)4862 HConstant* Evaluate(HLongConstant* value ATTRIBUTE_UNUSED,
4863 HLongConstant* distance ATTRIBUTE_UNUSED) const OVERRIDE {
4864 LOG(FATAL) << DebugName() << " is not defined for the (long, long) case.";
4865 UNREACHABLE();
4866 }
Evaluate(HFloatConstant * value ATTRIBUTE_UNUSED,HFloatConstant * distance ATTRIBUTE_UNUSED)4867 HConstant* Evaluate(HFloatConstant* value ATTRIBUTE_UNUSED,
4868 HFloatConstant* distance ATTRIBUTE_UNUSED) const OVERRIDE {
4869 LOG(FATAL) << DebugName() << " is not defined for float values";
4870 UNREACHABLE();
4871 }
Evaluate(HDoubleConstant * value ATTRIBUTE_UNUSED,HDoubleConstant * distance ATTRIBUTE_UNUSED)4872 HConstant* Evaluate(HDoubleConstant* value ATTRIBUTE_UNUSED,
4873 HDoubleConstant* distance ATTRIBUTE_UNUSED) const OVERRIDE {
4874 LOG(FATAL) << DebugName() << " is not defined for double values";
4875 UNREACHABLE();
4876 }
4877
4878 DECLARE_INSTRUCTION(UShr);
4879
4880 private:
4881 DISALLOW_COPY_AND_ASSIGN(HUShr);
4882 };
4883
4884 class HAnd FINAL : public HBinaryOperation {
4885 public:
4886 HAnd(Primitive::Type result_type,
4887 HInstruction* left,
4888 HInstruction* right,
4889 uint32_t dex_pc = kNoDexPc)
HBinaryOperation(result_type,left,right,SideEffects::None (),dex_pc)4890 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
4891
IsCommutative()4892 bool IsCommutative() const OVERRIDE { return true; }
4893
Compute(T x,T y)4894 template <typename T> static T Compute(T x, T y) { return x & y; }
4895
Evaluate(HIntConstant * x,HIntConstant * y)4896 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
4897 return GetBlock()->GetGraph()->GetIntConstant(
4898 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4899 }
Evaluate(HLongConstant * x,HLongConstant * y)4900 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
4901 return GetBlock()->GetGraph()->GetLongConstant(
4902 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4903 }
Evaluate(HFloatConstant * x ATTRIBUTE_UNUSED,HFloatConstant * y ATTRIBUTE_UNUSED)4904 HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
4905 HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
4906 LOG(FATAL) << DebugName() << " is not defined for float values";
4907 UNREACHABLE();
4908 }
Evaluate(HDoubleConstant * x ATTRIBUTE_UNUSED,HDoubleConstant * y ATTRIBUTE_UNUSED)4909 HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
4910 HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
4911 LOG(FATAL) << DebugName() << " is not defined for double values";
4912 UNREACHABLE();
4913 }
4914
4915 DECLARE_INSTRUCTION(And);
4916
4917 private:
4918 DISALLOW_COPY_AND_ASSIGN(HAnd);
4919 };
4920
4921 class HOr FINAL : public HBinaryOperation {
4922 public:
4923 HOr(Primitive::Type result_type,
4924 HInstruction* left,
4925 HInstruction* right,
4926 uint32_t dex_pc = kNoDexPc)
HBinaryOperation(result_type,left,right,SideEffects::None (),dex_pc)4927 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
4928
IsCommutative()4929 bool IsCommutative() const OVERRIDE { return true; }
4930
Compute(T x,T y)4931 template <typename T> static T Compute(T x, T y) { return x | y; }
4932
Evaluate(HIntConstant * x,HIntConstant * y)4933 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
4934 return GetBlock()->GetGraph()->GetIntConstant(
4935 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4936 }
Evaluate(HLongConstant * x,HLongConstant * y)4937 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
4938 return GetBlock()->GetGraph()->GetLongConstant(
4939 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4940 }
Evaluate(HFloatConstant * x ATTRIBUTE_UNUSED,HFloatConstant * y ATTRIBUTE_UNUSED)4941 HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
4942 HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
4943 LOG(FATAL) << DebugName() << " is not defined for float values";
4944 UNREACHABLE();
4945 }
Evaluate(HDoubleConstant * x ATTRIBUTE_UNUSED,HDoubleConstant * y ATTRIBUTE_UNUSED)4946 HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
4947 HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
4948 LOG(FATAL) << DebugName() << " is not defined for double values";
4949 UNREACHABLE();
4950 }
4951
4952 DECLARE_INSTRUCTION(Or);
4953
4954 private:
4955 DISALLOW_COPY_AND_ASSIGN(HOr);
4956 };
4957
4958 class HXor FINAL : public HBinaryOperation {
4959 public:
4960 HXor(Primitive::Type result_type,
4961 HInstruction* left,
4962 HInstruction* right,
4963 uint32_t dex_pc = kNoDexPc)
HBinaryOperation(result_type,left,right,SideEffects::None (),dex_pc)4964 : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
4965
IsCommutative()4966 bool IsCommutative() const OVERRIDE { return true; }
4967
Compute(T x,T y)4968 template <typename T> static T Compute(T x, T y) { return x ^ y; }
4969
Evaluate(HIntConstant * x,HIntConstant * y)4970 HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
4971 return GetBlock()->GetGraph()->GetIntConstant(
4972 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4973 }
Evaluate(HLongConstant * x,HLongConstant * y)4974 HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
4975 return GetBlock()->GetGraph()->GetLongConstant(
4976 Compute(x->GetValue(), y->GetValue()), GetDexPc());
4977 }
Evaluate(HFloatConstant * x ATTRIBUTE_UNUSED,HFloatConstant * y ATTRIBUTE_UNUSED)4978 HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
4979 HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
4980 LOG(FATAL) << DebugName() << " is not defined for float values";
4981 UNREACHABLE();
4982 }
Evaluate(HDoubleConstant * x ATTRIBUTE_UNUSED,HDoubleConstant * y ATTRIBUTE_UNUSED)4983 HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
4984 HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
4985 LOG(FATAL) << DebugName() << " is not defined for double values";
4986 UNREACHABLE();
4987 }
4988
4989 DECLARE_INSTRUCTION(Xor);
4990
4991 private:
4992 DISALLOW_COPY_AND_ASSIGN(HXor);
4993 };
4994
4995 class HRor FINAL : public HBinaryOperation {
4996 public:
HRor(Primitive::Type result_type,HInstruction * value,HInstruction * distance)4997 HRor(Primitive::Type result_type, HInstruction* value, HInstruction* distance)
4998 : HBinaryOperation(result_type, value, distance) {
4999 DCHECK_EQ(result_type, Primitive::PrimitiveKind(value->GetType()));
5000 DCHECK_EQ(Primitive::kPrimInt, Primitive::PrimitiveKind(distance->GetType()));
5001 }
5002
5003 template <typename T>
Compute(T value,int32_t distance,int32_t max_shift_value)5004 static T Compute(T value, int32_t distance, int32_t max_shift_value) {
5005 typedef typename std::make_unsigned<T>::type V;
5006 V ux = static_cast<V>(value);
5007 if ((distance & max_shift_value) == 0) {
5008 return static_cast<T>(ux);
5009 } else {
5010 const V reg_bits = sizeof(T) * 8;
5011 return static_cast<T>(ux >> (distance & max_shift_value)) |
5012 (value << (reg_bits - (distance & max_shift_value)));
5013 }
5014 }
5015
Evaluate(HIntConstant * value,HIntConstant * distance)5016 HConstant* Evaluate(HIntConstant* value, HIntConstant* distance) const OVERRIDE {
5017 return GetBlock()->GetGraph()->GetIntConstant(
5018 Compute(value->GetValue(), distance->GetValue(), kMaxIntShiftDistance), GetDexPc());
5019 }
Evaluate(HLongConstant * value,HIntConstant * distance)5020 HConstant* Evaluate(HLongConstant* value, HIntConstant* distance) const OVERRIDE {
5021 return GetBlock()->GetGraph()->GetLongConstant(
5022 Compute(value->GetValue(), distance->GetValue(), kMaxLongShiftDistance), GetDexPc());
5023 }
Evaluate(HLongConstant * value ATTRIBUTE_UNUSED,HLongConstant * distance ATTRIBUTE_UNUSED)5024 HConstant* Evaluate(HLongConstant* value ATTRIBUTE_UNUSED,
5025 HLongConstant* distance ATTRIBUTE_UNUSED) const OVERRIDE {
5026 LOG(FATAL) << DebugName() << " is not defined for the (long, long) case.";
5027 UNREACHABLE();
5028 }
Evaluate(HFloatConstant * value ATTRIBUTE_UNUSED,HFloatConstant * distance ATTRIBUTE_UNUSED)5029 HConstant* Evaluate(HFloatConstant* value ATTRIBUTE_UNUSED,
5030 HFloatConstant* distance ATTRIBUTE_UNUSED) const OVERRIDE {
5031 LOG(FATAL) << DebugName() << " is not defined for float values";
5032 UNREACHABLE();
5033 }
Evaluate(HDoubleConstant * value ATTRIBUTE_UNUSED,HDoubleConstant * distance ATTRIBUTE_UNUSED)5034 HConstant* Evaluate(HDoubleConstant* value ATTRIBUTE_UNUSED,
5035 HDoubleConstant* distance ATTRIBUTE_UNUSED) const OVERRIDE {
5036 LOG(FATAL) << DebugName() << " is not defined for double values";
5037 UNREACHABLE();
5038 }
5039
5040 DECLARE_INSTRUCTION(Ror);
5041
5042 private:
5043 DISALLOW_COPY_AND_ASSIGN(HRor);
5044 };
5045
5046 // The value of a parameter in this method. Its location depends on
5047 // the calling convention.
5048 class HParameterValue FINAL : public HExpression<0> {
5049 public:
5050 HParameterValue(const DexFile& dex_file,
5051 dex::TypeIndex type_index,
5052 uint8_t index,
5053 Primitive::Type parameter_type,
5054 bool is_this = false)
HExpression(parameter_type,SideEffects::None (),kNoDexPc)5055 : HExpression(parameter_type, SideEffects::None(), kNoDexPc),
5056 dex_file_(dex_file),
5057 type_index_(type_index),
5058 index_(index) {
5059 SetPackedFlag<kFlagIsThis>(is_this);
5060 SetPackedFlag<kFlagCanBeNull>(!is_this);
5061 }
5062
GetDexFile()5063 const DexFile& GetDexFile() const { return dex_file_; }
GetTypeIndex()5064 dex::TypeIndex GetTypeIndex() const { return type_index_; }
GetIndex()5065 uint8_t GetIndex() const { return index_; }
IsThis()5066 bool IsThis() const ATTRIBUTE_UNUSED { return GetPackedFlag<kFlagIsThis>(); }
5067
CanBeNull()5068 bool CanBeNull() const OVERRIDE { return GetPackedFlag<kFlagCanBeNull>(); }
SetCanBeNull(bool can_be_null)5069 void SetCanBeNull(bool can_be_null) { SetPackedFlag<kFlagCanBeNull>(can_be_null); }
5070
5071 DECLARE_INSTRUCTION(ParameterValue);
5072
5073 private:
5074 // Whether or not the parameter value corresponds to 'this' argument.
5075 static constexpr size_t kFlagIsThis = kNumberOfExpressionPackedBits;
5076 static constexpr size_t kFlagCanBeNull = kFlagIsThis + 1;
5077 static constexpr size_t kNumberOfParameterValuePackedBits = kFlagCanBeNull + 1;
5078 static_assert(kNumberOfParameterValuePackedBits <= kMaxNumberOfPackedBits,
5079 "Too many packed fields.");
5080
5081 const DexFile& dex_file_;
5082 const dex::TypeIndex type_index_;
5083 // The index of this parameter in the parameters list. Must be less
5084 // than HGraph::number_of_in_vregs_.
5085 const uint8_t index_;
5086
5087 DISALLOW_COPY_AND_ASSIGN(HParameterValue);
5088 };
5089
5090 class HNot FINAL : public HUnaryOperation {
5091 public:
5092 HNot(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
HUnaryOperation(result_type,input,dex_pc)5093 : HUnaryOperation(result_type, input, dex_pc) {}
5094
CanBeMoved()5095 bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(const HInstruction * other ATTRIBUTE_UNUSED)5096 bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
5097 return true;
5098 }
5099
Compute(T x)5100 template <typename T> static T Compute(T x) { return ~x; }
5101
Evaluate(HIntConstant * x)5102 HConstant* Evaluate(HIntConstant* x) const OVERRIDE {
5103 return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()), GetDexPc());
5104 }
Evaluate(HLongConstant * x)5105 HConstant* Evaluate(HLongConstant* x) const OVERRIDE {
5106 return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue()), GetDexPc());
5107 }
Evaluate(HFloatConstant * x ATTRIBUTE_UNUSED)5108 HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED) const OVERRIDE {
5109 LOG(FATAL) << DebugName() << " is not defined for float values";
5110 UNREACHABLE();
5111 }
Evaluate(HDoubleConstant * x ATTRIBUTE_UNUSED)5112 HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED) const OVERRIDE {
5113 LOG(FATAL) << DebugName() << " is not defined for double values";
5114 UNREACHABLE();
5115 }
5116
5117 DECLARE_INSTRUCTION(Not);
5118
5119 private:
5120 DISALLOW_COPY_AND_ASSIGN(HNot);
5121 };
5122
5123 class HBooleanNot FINAL : public HUnaryOperation {
5124 public:
5125 explicit HBooleanNot(HInstruction* input, uint32_t dex_pc = kNoDexPc)
HUnaryOperation(Primitive::Type::kPrimBoolean,input,dex_pc)5126 : HUnaryOperation(Primitive::Type::kPrimBoolean, input, dex_pc) {}
5127
CanBeMoved()5128 bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(const HInstruction * other ATTRIBUTE_UNUSED)5129 bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
5130 return true;
5131 }
5132
Compute(T x)5133 template <typename T> static bool Compute(T x) {
5134 DCHECK(IsUint<1>(x)) << x;
5135 return !x;
5136 }
5137
Evaluate(HIntConstant * x)5138 HConstant* Evaluate(HIntConstant* x) const OVERRIDE {
5139 return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()), GetDexPc());
5140 }
Evaluate(HLongConstant * x ATTRIBUTE_UNUSED)5141 HConstant* Evaluate(HLongConstant* x ATTRIBUTE_UNUSED) const OVERRIDE {
5142 LOG(FATAL) << DebugName() << " is not defined for long values";
5143 UNREACHABLE();
5144 }
Evaluate(HFloatConstant * x ATTRIBUTE_UNUSED)5145 HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED) const OVERRIDE {
5146 LOG(FATAL) << DebugName() << " is not defined for float values";
5147 UNREACHABLE();
5148 }
Evaluate(HDoubleConstant * x ATTRIBUTE_UNUSED)5149 HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED) const OVERRIDE {
5150 LOG(FATAL) << DebugName() << " is not defined for double values";
5151 UNREACHABLE();
5152 }
5153
5154 DECLARE_INSTRUCTION(BooleanNot);
5155
5156 private:
5157 DISALLOW_COPY_AND_ASSIGN(HBooleanNot);
5158 };
5159
5160 class HTypeConversion FINAL : public HExpression<1> {
5161 public:
5162 // Instantiate a type conversion of `input` to `result_type`.
HTypeConversion(Primitive::Type result_type,HInstruction * input,uint32_t dex_pc)5163 HTypeConversion(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc)
5164 : HExpression(result_type, SideEffects::None(), dex_pc) {
5165 SetRawInputAt(0, input);
5166 // Invariant: We should never generate a conversion to a Boolean value.
5167 DCHECK_NE(Primitive::kPrimBoolean, result_type);
5168 }
5169
GetInput()5170 HInstruction* GetInput() const { return InputAt(0); }
GetInputType()5171 Primitive::Type GetInputType() const { return GetInput()->GetType(); }
GetResultType()5172 Primitive::Type GetResultType() const { return GetType(); }
5173
CanBeMoved()5174 bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(const HInstruction * other ATTRIBUTE_UNUSED)5175 bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
5176 return true;
5177 }
5178
5179 // Try to statically evaluate the conversion and return a HConstant
5180 // containing the result. If the input cannot be converted, return nullptr.
5181 HConstant* TryStaticEvaluation() const;
5182
5183 DECLARE_INSTRUCTION(TypeConversion);
5184
5185 private:
5186 DISALLOW_COPY_AND_ASSIGN(HTypeConversion);
5187 };
5188
5189 static constexpr uint32_t kNoRegNumber = -1;
5190
5191 class HNullCheck FINAL : public HExpression<1> {
5192 public:
5193 // `HNullCheck` can trigger GC, as it may call the `NullPointerException`
5194 // constructor.
HNullCheck(HInstruction * value,uint32_t dex_pc)5195 HNullCheck(HInstruction* value, uint32_t dex_pc)
5196 : HExpression(value->GetType(), SideEffects::CanTriggerGC(), dex_pc) {
5197 SetRawInputAt(0, value);
5198 }
5199
CanBeMoved()5200 bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(const HInstruction * other ATTRIBUTE_UNUSED)5201 bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
5202 return true;
5203 }
5204
NeedsEnvironment()5205 bool NeedsEnvironment() const OVERRIDE { return true; }
5206
CanThrow()5207 bool CanThrow() const OVERRIDE { return true; }
5208
CanBeNull()5209 bool CanBeNull() const OVERRIDE { return false; }
5210
5211
5212 DECLARE_INSTRUCTION(NullCheck);
5213
5214 private:
5215 DISALLOW_COPY_AND_ASSIGN(HNullCheck);
5216 };
5217
5218 // Embeds an ArtField and all the information required by the compiler. We cache
5219 // that information to avoid requiring the mutator lock every time we need it.
5220 class FieldInfo : public ValueObject {
5221 public:
FieldInfo(ArtField * field,MemberOffset field_offset,Primitive::Type field_type,bool is_volatile,uint32_t index,uint16_t declaring_class_def_index,const DexFile & dex_file)5222 FieldInfo(ArtField* field,
5223 MemberOffset field_offset,
5224 Primitive::Type field_type,
5225 bool is_volatile,
5226 uint32_t index,
5227 uint16_t declaring_class_def_index,
5228 const DexFile& dex_file)
5229 : field_(field),
5230 field_offset_(field_offset),
5231 field_type_(field_type),
5232 is_volatile_(is_volatile),
5233 index_(index),
5234 declaring_class_def_index_(declaring_class_def_index),
5235 dex_file_(dex_file) {}
5236
GetField()5237 ArtField* GetField() const { return field_; }
GetFieldOffset()5238 MemberOffset GetFieldOffset() const { return field_offset_; }
GetFieldType()5239 Primitive::Type GetFieldType() const { return field_type_; }
GetFieldIndex()5240 uint32_t GetFieldIndex() const { return index_; }
GetDeclaringClassDefIndex()5241 uint16_t GetDeclaringClassDefIndex() const { return declaring_class_def_index_;}
GetDexFile()5242 const DexFile& GetDexFile() const { return dex_file_; }
IsVolatile()5243 bool IsVolatile() const { return is_volatile_; }
5244
5245 private:
5246 ArtField* const field_;
5247 const MemberOffset field_offset_;
5248 const Primitive::Type field_type_;
5249 const bool is_volatile_;
5250 const uint32_t index_;
5251 const uint16_t declaring_class_def_index_;
5252 const DexFile& dex_file_;
5253 };
5254
5255 class HInstanceFieldGet FINAL : public HExpression<1> {
5256 public:
HInstanceFieldGet(HInstruction * value,ArtField * field,Primitive::Type field_type,MemberOffset field_offset,bool is_volatile,uint32_t field_idx,uint16_t declaring_class_def_index,const DexFile & dex_file,uint32_t dex_pc)5257 HInstanceFieldGet(HInstruction* value,
5258 ArtField* field,
5259 Primitive::Type field_type,
5260 MemberOffset field_offset,
5261 bool is_volatile,
5262 uint32_t field_idx,
5263 uint16_t declaring_class_def_index,
5264 const DexFile& dex_file,
5265 uint32_t dex_pc)
5266 : HExpression(field_type, SideEffects::FieldReadOfType(field_type, is_volatile), dex_pc),
5267 field_info_(field,
5268 field_offset,
5269 field_type,
5270 is_volatile,
5271 field_idx,
5272 declaring_class_def_index,
5273 dex_file) {
5274 SetRawInputAt(0, value);
5275 }
5276
CanBeMoved()5277 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); }
5278
InstructionDataEquals(const HInstruction * other)5279 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
5280 const HInstanceFieldGet* other_get = other->AsInstanceFieldGet();
5281 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
5282 }
5283
CanDoImplicitNullCheckOn(HInstruction * obj)5284 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
5285 return (obj == InputAt(0)) && art::CanDoImplicitNullCheckOn(GetFieldOffset().Uint32Value());
5286 }
5287
ComputeHashCode()5288 size_t ComputeHashCode() const OVERRIDE {
5289 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
5290 }
5291
GetFieldInfo()5292 const FieldInfo& GetFieldInfo() const { return field_info_; }
GetFieldOffset()5293 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
GetFieldType()5294 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
IsVolatile()5295 bool IsVolatile() const { return field_info_.IsVolatile(); }
5296
5297 DECLARE_INSTRUCTION(InstanceFieldGet);
5298
5299 private:
5300 const FieldInfo field_info_;
5301
5302 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldGet);
5303 };
5304
5305 class HInstanceFieldSet FINAL : public HTemplateInstruction<2> {
5306 public:
HInstanceFieldSet(HInstruction * object,HInstruction * value,ArtField * field,Primitive::Type field_type,MemberOffset field_offset,bool is_volatile,uint32_t field_idx,uint16_t declaring_class_def_index,const DexFile & dex_file,uint32_t dex_pc)5307 HInstanceFieldSet(HInstruction* object,
5308 HInstruction* value,
5309 ArtField* field,
5310 Primitive::Type field_type,
5311 MemberOffset field_offset,
5312 bool is_volatile,
5313 uint32_t field_idx,
5314 uint16_t declaring_class_def_index,
5315 const DexFile& dex_file,
5316 uint32_t dex_pc)
5317 : HTemplateInstruction(SideEffects::FieldWriteOfType(field_type, is_volatile), dex_pc),
5318 field_info_(field,
5319 field_offset,
5320 field_type,
5321 is_volatile,
5322 field_idx,
5323 declaring_class_def_index,
5324 dex_file) {
5325 SetPackedFlag<kFlagValueCanBeNull>(true);
5326 SetRawInputAt(0, object);
5327 SetRawInputAt(1, value);
5328 }
5329
CanDoImplicitNullCheckOn(HInstruction * obj)5330 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
5331 return (obj == InputAt(0)) && art::CanDoImplicitNullCheckOn(GetFieldOffset().Uint32Value());
5332 }
5333
GetFieldInfo()5334 const FieldInfo& GetFieldInfo() const { return field_info_; }
GetFieldOffset()5335 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
GetFieldType()5336 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
IsVolatile()5337 bool IsVolatile() const { return field_info_.IsVolatile(); }
GetValue()5338 HInstruction* GetValue() const { return InputAt(1); }
GetValueCanBeNull()5339 bool GetValueCanBeNull() const { return GetPackedFlag<kFlagValueCanBeNull>(); }
ClearValueCanBeNull()5340 void ClearValueCanBeNull() { SetPackedFlag<kFlagValueCanBeNull>(false); }
5341
5342 DECLARE_INSTRUCTION(InstanceFieldSet);
5343
5344 private:
5345 static constexpr size_t kFlagValueCanBeNull = kNumberOfGenericPackedBits;
5346 static constexpr size_t kNumberOfInstanceFieldSetPackedBits = kFlagValueCanBeNull + 1;
5347 static_assert(kNumberOfInstanceFieldSetPackedBits <= kMaxNumberOfPackedBits,
5348 "Too many packed fields.");
5349
5350 const FieldInfo field_info_;
5351
5352 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldSet);
5353 };
5354
5355 class HArrayGet FINAL : public HExpression<2> {
5356 public:
5357 HArrayGet(HInstruction* array,
5358 HInstruction* index,
5359 Primitive::Type type,
5360 uint32_t dex_pc,
5361 bool is_string_char_at = false)
HExpression(type,SideEffects::ArrayReadOfType (type),dex_pc)5362 : HExpression(type, SideEffects::ArrayReadOfType(type), dex_pc) {
5363 SetPackedFlag<kFlagIsStringCharAt>(is_string_char_at);
5364 SetRawInputAt(0, array);
5365 SetRawInputAt(1, index);
5366 }
5367
CanBeMoved()5368 bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(const HInstruction * other ATTRIBUTE_UNUSED)5369 bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
5370 return true;
5371 }
CanDoImplicitNullCheckOn(HInstruction * obj ATTRIBUTE_UNUSED)5372 bool CanDoImplicitNullCheckOn(HInstruction* obj ATTRIBUTE_UNUSED) const OVERRIDE {
5373 // TODO: We can be smarter here.
5374 // Currently, the array access is always preceded by an ArrayLength or a NullCheck
5375 // which generates the implicit null check. There are cases when these can be removed
5376 // to produce better code. If we ever add optimizations to do so we should allow an
5377 // implicit check here (as long as the address falls in the first page).
5378 return false;
5379 }
5380
IsEquivalentOf(HArrayGet * other)5381 bool IsEquivalentOf(HArrayGet* other) const {
5382 bool result = (GetDexPc() == other->GetDexPc());
5383 if (kIsDebugBuild && result) {
5384 DCHECK_EQ(GetBlock(), other->GetBlock());
5385 DCHECK_EQ(GetArray(), other->GetArray());
5386 DCHECK_EQ(GetIndex(), other->GetIndex());
5387 if (Primitive::IsIntOrLongType(GetType())) {
5388 DCHECK(Primitive::IsFloatingPointType(other->GetType())) << other->GetType();
5389 } else {
5390 DCHECK(Primitive::IsFloatingPointType(GetType())) << GetType();
5391 DCHECK(Primitive::IsIntOrLongType(other->GetType())) << other->GetType();
5392 }
5393 }
5394 return result;
5395 }
5396
IsStringCharAt()5397 bool IsStringCharAt() const { return GetPackedFlag<kFlagIsStringCharAt>(); }
5398
GetArray()5399 HInstruction* GetArray() const { return InputAt(0); }
GetIndex()5400 HInstruction* GetIndex() const { return InputAt(1); }
5401
5402 DECLARE_INSTRUCTION(ArrayGet);
5403
5404 private:
5405 // We treat a String as an array, creating the HArrayGet from String.charAt()
5406 // intrinsic in the instruction simplifier. We can always determine whether
5407 // a particular HArrayGet is actually a String.charAt() by looking at the type
5408 // of the input but that requires holding the mutator lock, so we prefer to use
5409 // a flag, so that code generators don't need to do the locking.
5410 static constexpr size_t kFlagIsStringCharAt = kNumberOfExpressionPackedBits;
5411 static constexpr size_t kNumberOfArrayGetPackedBits = kFlagIsStringCharAt + 1;
5412 static_assert(kNumberOfArrayGetPackedBits <= HInstruction::kMaxNumberOfPackedBits,
5413 "Too many packed fields.");
5414
5415 DISALLOW_COPY_AND_ASSIGN(HArrayGet);
5416 };
5417
5418 class HArraySet FINAL : public HTemplateInstruction<3> {
5419 public:
HArraySet(HInstruction * array,HInstruction * index,HInstruction * value,Primitive::Type expected_component_type,uint32_t dex_pc)5420 HArraySet(HInstruction* array,
5421 HInstruction* index,
5422 HInstruction* value,
5423 Primitive::Type expected_component_type,
5424 uint32_t dex_pc)
5425 : HTemplateInstruction(SideEffects::None(), dex_pc) {
5426 SetPackedField<ExpectedComponentTypeField>(expected_component_type);
5427 SetPackedFlag<kFlagNeedsTypeCheck>(value->GetType() == Primitive::kPrimNot);
5428 SetPackedFlag<kFlagValueCanBeNull>(true);
5429 SetPackedFlag<kFlagStaticTypeOfArrayIsObjectArray>(false);
5430 SetRawInputAt(0, array);
5431 SetRawInputAt(1, index);
5432 SetRawInputAt(2, value);
5433 // Make a best guess now, may be refined during SSA building.
5434 ComputeSideEffects();
5435 }
5436
NeedsEnvironment()5437 bool NeedsEnvironment() const OVERRIDE {
5438 // We call a runtime method to throw ArrayStoreException.
5439 return NeedsTypeCheck();
5440 }
5441
5442 // Can throw ArrayStoreException.
CanThrow()5443 bool CanThrow() const OVERRIDE { return NeedsTypeCheck(); }
5444
CanDoImplicitNullCheckOn(HInstruction * obj ATTRIBUTE_UNUSED)5445 bool CanDoImplicitNullCheckOn(HInstruction* obj ATTRIBUTE_UNUSED) const OVERRIDE {
5446 // TODO: Same as for ArrayGet.
5447 return false;
5448 }
5449
ClearNeedsTypeCheck()5450 void ClearNeedsTypeCheck() {
5451 SetPackedFlag<kFlagNeedsTypeCheck>(false);
5452 }
5453
ClearValueCanBeNull()5454 void ClearValueCanBeNull() {
5455 SetPackedFlag<kFlagValueCanBeNull>(false);
5456 }
5457
SetStaticTypeOfArrayIsObjectArray()5458 void SetStaticTypeOfArrayIsObjectArray() {
5459 SetPackedFlag<kFlagStaticTypeOfArrayIsObjectArray>(true);
5460 }
5461
GetValueCanBeNull()5462 bool GetValueCanBeNull() const { return GetPackedFlag<kFlagValueCanBeNull>(); }
NeedsTypeCheck()5463 bool NeedsTypeCheck() const { return GetPackedFlag<kFlagNeedsTypeCheck>(); }
StaticTypeOfArrayIsObjectArray()5464 bool StaticTypeOfArrayIsObjectArray() const {
5465 return GetPackedFlag<kFlagStaticTypeOfArrayIsObjectArray>();
5466 }
5467
GetArray()5468 HInstruction* GetArray() const { return InputAt(0); }
GetIndex()5469 HInstruction* GetIndex() const { return InputAt(1); }
GetValue()5470 HInstruction* GetValue() const { return InputAt(2); }
5471
GetComponentType()5472 Primitive::Type GetComponentType() const {
5473 // The Dex format does not type floating point index operations. Since the
5474 // `expected_component_type_` is set during building and can therefore not
5475 // be correct, we also check what is the value type. If it is a floating
5476 // point type, we must use that type.
5477 Primitive::Type value_type = GetValue()->GetType();
5478 return ((value_type == Primitive::kPrimFloat) || (value_type == Primitive::kPrimDouble))
5479 ? value_type
5480 : GetRawExpectedComponentType();
5481 }
5482
GetRawExpectedComponentType()5483 Primitive::Type GetRawExpectedComponentType() const {
5484 return GetPackedField<ExpectedComponentTypeField>();
5485 }
5486
ComputeSideEffects()5487 void ComputeSideEffects() {
5488 Primitive::Type type = GetComponentType();
5489 SetSideEffects(SideEffects::ArrayWriteOfType(type).Union(
5490 SideEffectsForArchRuntimeCalls(type)));
5491 }
5492
SideEffectsForArchRuntimeCalls(Primitive::Type value_type)5493 static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type value_type) {
5494 return (value_type == Primitive::kPrimNot) ? SideEffects::CanTriggerGC() : SideEffects::None();
5495 }
5496
5497 DECLARE_INSTRUCTION(ArraySet);
5498
5499 private:
5500 static constexpr size_t kFieldExpectedComponentType = kNumberOfGenericPackedBits;
5501 static constexpr size_t kFieldExpectedComponentTypeSize =
5502 MinimumBitsToStore(static_cast<size_t>(Primitive::kPrimLast));
5503 static constexpr size_t kFlagNeedsTypeCheck =
5504 kFieldExpectedComponentType + kFieldExpectedComponentTypeSize;
5505 static constexpr size_t kFlagValueCanBeNull = kFlagNeedsTypeCheck + 1;
5506 // Cached information for the reference_type_info_ so that codegen
5507 // does not need to inspect the static type.
5508 static constexpr size_t kFlagStaticTypeOfArrayIsObjectArray = kFlagValueCanBeNull + 1;
5509 static constexpr size_t kNumberOfArraySetPackedBits =
5510 kFlagStaticTypeOfArrayIsObjectArray + 1;
5511 static_assert(kNumberOfArraySetPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
5512 using ExpectedComponentTypeField =
5513 BitField<Primitive::Type, kFieldExpectedComponentType, kFieldExpectedComponentTypeSize>;
5514
5515 DISALLOW_COPY_AND_ASSIGN(HArraySet);
5516 };
5517
5518 class HArrayLength FINAL : public HExpression<1> {
5519 public:
5520 HArrayLength(HInstruction* array, uint32_t dex_pc, bool is_string_length = false)
HExpression(Primitive::kPrimInt,SideEffects::None (),dex_pc)5521 : HExpression(Primitive::kPrimInt, SideEffects::None(), dex_pc) {
5522 SetPackedFlag<kFlagIsStringLength>(is_string_length);
5523 // Note that arrays do not change length, so the instruction does not
5524 // depend on any write.
5525 SetRawInputAt(0, array);
5526 }
5527
CanBeMoved()5528 bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(const HInstruction * other ATTRIBUTE_UNUSED)5529 bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
5530 return true;
5531 }
CanDoImplicitNullCheckOn(HInstruction * obj)5532 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
5533 return obj == InputAt(0);
5534 }
5535
IsStringLength()5536 bool IsStringLength() const { return GetPackedFlag<kFlagIsStringLength>(); }
5537
5538 DECLARE_INSTRUCTION(ArrayLength);
5539
5540 private:
5541 // We treat a String as an array, creating the HArrayLength from String.length()
5542 // or String.isEmpty() intrinsic in the instruction simplifier. We can always
5543 // determine whether a particular HArrayLength is actually a String.length() by
5544 // looking at the type of the input but that requires holding the mutator lock, so
5545 // we prefer to use a flag, so that code generators don't need to do the locking.
5546 static constexpr size_t kFlagIsStringLength = kNumberOfExpressionPackedBits;
5547 static constexpr size_t kNumberOfArrayLengthPackedBits = kFlagIsStringLength + 1;
5548 static_assert(kNumberOfArrayLengthPackedBits <= HInstruction::kMaxNumberOfPackedBits,
5549 "Too many packed fields.");
5550
5551 DISALLOW_COPY_AND_ASSIGN(HArrayLength);
5552 };
5553
5554 class HBoundsCheck FINAL : public HExpression<2> {
5555 public:
5556 // `HBoundsCheck` can trigger GC, as it may call the `IndexOutOfBoundsException`
5557 // constructor.
5558 HBoundsCheck(HInstruction* index,
5559 HInstruction* length,
5560 uint32_t dex_pc,
5561 bool string_char_at = false)
5562 : HExpression(index->GetType(), SideEffects::CanTriggerGC(), dex_pc) {
5563 DCHECK_EQ(Primitive::kPrimInt, Primitive::PrimitiveKind(index->GetType()));
5564 SetPackedFlag<kFlagIsStringCharAt>(string_char_at);
5565 SetRawInputAt(0, index);
5566 SetRawInputAt(1, length);
5567 }
5568
CanBeMoved()5569 bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(const HInstruction * other ATTRIBUTE_UNUSED)5570 bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
5571 return true;
5572 }
5573
NeedsEnvironment()5574 bool NeedsEnvironment() const OVERRIDE { return true; }
5575
CanThrow()5576 bool CanThrow() const OVERRIDE { return true; }
5577
IsStringCharAt()5578 bool IsStringCharAt() const { return GetPackedFlag<kFlagIsStringCharAt>(); }
5579
GetIndex()5580 HInstruction* GetIndex() const { return InputAt(0); }
5581
5582 DECLARE_INSTRUCTION(BoundsCheck);
5583
5584 private:
5585 static constexpr size_t kFlagIsStringCharAt = kNumberOfExpressionPackedBits;
5586
5587 DISALLOW_COPY_AND_ASSIGN(HBoundsCheck);
5588 };
5589
5590 class HSuspendCheck FINAL : public HTemplateInstruction<0> {
5591 public:
5592 explicit HSuspendCheck(uint32_t dex_pc = kNoDexPc)
HTemplateInstruction(SideEffects::CanTriggerGC (),dex_pc)5593 : HTemplateInstruction(SideEffects::CanTriggerGC(), dex_pc), slow_path_(nullptr) {}
5594
NeedsEnvironment()5595 bool NeedsEnvironment() const OVERRIDE {
5596 return true;
5597 }
5598
SetSlowPath(SlowPathCode * slow_path)5599 void SetSlowPath(SlowPathCode* slow_path) { slow_path_ = slow_path; }
GetSlowPath()5600 SlowPathCode* GetSlowPath() const { return slow_path_; }
5601
5602 DECLARE_INSTRUCTION(SuspendCheck);
5603
5604 private:
5605 // Only used for code generation, in order to share the same slow path between back edges
5606 // of a same loop.
5607 SlowPathCode* slow_path_;
5608
5609 DISALLOW_COPY_AND_ASSIGN(HSuspendCheck);
5610 };
5611
5612 // Pseudo-instruction which provides the native debugger with mapping information.
5613 // It ensures that we can generate line number and local variables at this point.
5614 class HNativeDebugInfo : public HTemplateInstruction<0> {
5615 public:
HNativeDebugInfo(uint32_t dex_pc)5616 explicit HNativeDebugInfo(uint32_t dex_pc)
5617 : HTemplateInstruction<0>(SideEffects::None(), dex_pc) {}
5618
NeedsEnvironment()5619 bool NeedsEnvironment() const OVERRIDE {
5620 return true;
5621 }
5622
5623 DECLARE_INSTRUCTION(NativeDebugInfo);
5624
5625 private:
5626 DISALLOW_COPY_AND_ASSIGN(HNativeDebugInfo);
5627 };
5628
5629 /**
5630 * Instruction to load a Class object.
5631 */
5632 class HLoadClass FINAL : public HInstruction {
5633 public:
5634 // Determines how to load the Class.
5635 enum class LoadKind {
5636 // We cannot load this class. See HSharpening::SharpenLoadClass.
5637 kInvalid = -1,
5638
5639 // Use the Class* from the method's own ArtMethod*.
5640 kReferrersClass,
5641
5642 // Use boot image Class* address that will be known at link time.
5643 // Used for boot image classes referenced by boot image code in non-PIC mode.
5644 kBootImageLinkTimeAddress,
5645
5646 // Use PC-relative boot image Class* address that will be known at link time.
5647 // Used for boot image classes referenced by boot image code in PIC mode.
5648 kBootImageLinkTimePcRelative,
5649
5650 // Use a known boot image Class* address, embedded in the code by the codegen.
5651 // Used for boot image classes referenced by apps in AOT- and JIT-compiled code.
5652 kBootImageAddress,
5653
5654 // Load from an entry in the .bss section using a PC-relative load.
5655 // Used for classes outside boot image when .bss is accessible with a PC-relative load.
5656 kBssEntry,
5657
5658 // Load from the root table associated with the JIT compiled method.
5659 kJitTableAddress,
5660
5661 // Load from resolved types array accessed through the class loaded from
5662 // the compiled method's own ArtMethod*. This is the default access type when
5663 // all other types are unavailable.
5664 kDexCacheViaMethod,
5665
5666 kLast = kDexCacheViaMethod
5667 };
5668
HLoadClass(HCurrentMethod * current_method,dex::TypeIndex type_index,const DexFile & dex_file,Handle<mirror::Class> klass,bool is_referrers_class,uint32_t dex_pc,bool needs_access_check)5669 HLoadClass(HCurrentMethod* current_method,
5670 dex::TypeIndex type_index,
5671 const DexFile& dex_file,
5672 Handle<mirror::Class> klass,
5673 bool is_referrers_class,
5674 uint32_t dex_pc,
5675 bool needs_access_check)
5676 : HInstruction(SideEffectsForArchRuntimeCalls(), dex_pc),
5677 special_input_(HUserRecord<HInstruction*>(current_method)),
5678 type_index_(type_index),
5679 dex_file_(dex_file),
5680 klass_(klass),
5681 loaded_class_rti_(ReferenceTypeInfo::CreateInvalid()) {
5682 // Referrers class should not need access check. We never inline unverified
5683 // methods so we can't possibly end up in this situation.
5684 DCHECK(!is_referrers_class || !needs_access_check);
5685
5686 SetPackedField<LoadKindField>(
5687 is_referrers_class ? LoadKind::kReferrersClass : LoadKind::kDexCacheViaMethod);
5688 SetPackedFlag<kFlagNeedsAccessCheck>(needs_access_check);
5689 SetPackedFlag<kFlagIsInBootImage>(false);
5690 SetPackedFlag<kFlagGenerateClInitCheck>(false);
5691 }
5692
5693 void SetLoadKind(LoadKind load_kind);
5694
GetLoadKind()5695 LoadKind GetLoadKind() const {
5696 return GetPackedField<LoadKindField>();
5697 }
5698
CanBeMoved()5699 bool CanBeMoved() const OVERRIDE { return true; }
5700
5701 bool InstructionDataEquals(const HInstruction* other) const;
5702
ComputeHashCode()5703 size_t ComputeHashCode() const OVERRIDE { return type_index_.index_; }
5704
CanBeNull()5705 bool CanBeNull() const OVERRIDE { return false; }
5706
NeedsEnvironment()5707 bool NeedsEnvironment() const OVERRIDE {
5708 return CanCallRuntime();
5709 }
5710
SetMustGenerateClinitCheck(bool generate_clinit_check)5711 void SetMustGenerateClinitCheck(bool generate_clinit_check) {
5712 // The entrypoint the code generator is going to call does not do
5713 // clinit of the class.
5714 DCHECK(!NeedsAccessCheck());
5715 SetPackedFlag<kFlagGenerateClInitCheck>(generate_clinit_check);
5716 }
5717
CanCallRuntime()5718 bool CanCallRuntime() const {
5719 return NeedsAccessCheck() ||
5720 MustGenerateClinitCheck() ||
5721 GetLoadKind() == LoadKind::kDexCacheViaMethod ||
5722 GetLoadKind() == LoadKind::kBssEntry;
5723 }
5724
CanThrow()5725 bool CanThrow() const OVERRIDE {
5726 return NeedsAccessCheck() ||
5727 MustGenerateClinitCheck() ||
5728 // If the class is in the boot image, the lookup in the runtime call cannot throw.
5729 // This keeps CanThrow() consistent between non-PIC (using kBootImageAddress) and
5730 // PIC and subsequently avoids a DCE behavior dependency on the PIC option.
5731 ((GetLoadKind() == LoadKind::kDexCacheViaMethod ||
5732 GetLoadKind() == LoadKind::kBssEntry) &&
5733 !IsInBootImage());
5734 }
5735
GetLoadedClassRTI()5736 ReferenceTypeInfo GetLoadedClassRTI() {
5737 return loaded_class_rti_;
5738 }
5739
SetLoadedClassRTI(ReferenceTypeInfo rti)5740 void SetLoadedClassRTI(ReferenceTypeInfo rti) {
5741 // Make sure we only set exact types (the loaded class should never be merged).
5742 DCHECK(rti.IsExact());
5743 loaded_class_rti_ = rti;
5744 }
5745
GetTypeIndex()5746 dex::TypeIndex GetTypeIndex() const { return type_index_; }
GetDexFile()5747 const DexFile& GetDexFile() const { return dex_file_; }
5748
NeedsDexCacheOfDeclaringClass()5749 bool NeedsDexCacheOfDeclaringClass() const OVERRIDE {
5750 return GetLoadKind() == LoadKind::kDexCacheViaMethod;
5751 }
5752
SideEffectsForArchRuntimeCalls()5753 static SideEffects SideEffectsForArchRuntimeCalls() {
5754 return SideEffects::CanTriggerGC();
5755 }
5756
IsReferrersClass()5757 bool IsReferrersClass() const { return GetLoadKind() == LoadKind::kReferrersClass; }
NeedsAccessCheck()5758 bool NeedsAccessCheck() const { return GetPackedFlag<kFlagNeedsAccessCheck>(); }
IsInBootImage()5759 bool IsInBootImage() const { return GetPackedFlag<kFlagIsInBootImage>(); }
MustGenerateClinitCheck()5760 bool MustGenerateClinitCheck() const { return GetPackedFlag<kFlagGenerateClInitCheck>(); }
5761
MarkInBootImage()5762 void MarkInBootImage() {
5763 SetPackedFlag<kFlagIsInBootImage>(true);
5764 }
5765
5766 void AddSpecialInput(HInstruction* special_input);
5767
5768 using HInstruction::GetInputRecords; // Keep the const version visible.
GetInputRecords()5769 ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() OVERRIDE FINAL {
5770 return ArrayRef<HUserRecord<HInstruction*>>(
5771 &special_input_, (special_input_.GetInstruction() != nullptr) ? 1u : 0u);
5772 }
5773
GetType()5774 Primitive::Type GetType() const OVERRIDE {
5775 return Primitive::kPrimNot;
5776 }
5777
GetClass()5778 Handle<mirror::Class> GetClass() const {
5779 return klass_;
5780 }
5781
5782 DECLARE_INSTRUCTION(LoadClass);
5783
5784 private:
5785 static constexpr size_t kFlagNeedsAccessCheck = kNumberOfGenericPackedBits;
5786 static constexpr size_t kFlagIsInBootImage = kFlagNeedsAccessCheck + 1;
5787 // Whether this instruction must generate the initialization check.
5788 // Used for code generation.
5789 static constexpr size_t kFlagGenerateClInitCheck = kFlagIsInBootImage + 1;
5790 static constexpr size_t kFieldLoadKind = kFlagGenerateClInitCheck + 1;
5791 static constexpr size_t kFieldLoadKindSize =
5792 MinimumBitsToStore(static_cast<size_t>(LoadKind::kLast));
5793 static constexpr size_t kNumberOfLoadClassPackedBits = kFieldLoadKind + kFieldLoadKindSize;
5794 static_assert(kNumberOfLoadClassPackedBits < kMaxNumberOfPackedBits, "Too many packed fields.");
5795 using LoadKindField = BitField<LoadKind, kFieldLoadKind, kFieldLoadKindSize>;
5796
HasTypeReference(LoadKind load_kind)5797 static bool HasTypeReference(LoadKind load_kind) {
5798 return load_kind == LoadKind::kReferrersClass ||
5799 load_kind == LoadKind::kBootImageLinkTimeAddress ||
5800 load_kind == LoadKind::kBootImageLinkTimePcRelative ||
5801 load_kind == LoadKind::kBssEntry ||
5802 load_kind == LoadKind::kDexCacheViaMethod;
5803 }
5804
5805 void SetLoadKindInternal(LoadKind load_kind);
5806
5807 // The special input is the HCurrentMethod for kDexCacheViaMethod or kReferrersClass.
5808 // For other load kinds it's empty or possibly some architecture-specific instruction
5809 // for PC-relative loads, i.e. kBssEntry or kBootImageLinkTimePcRelative.
5810 HUserRecord<HInstruction*> special_input_;
5811
5812 // A type index and dex file where the class can be accessed. The dex file can be:
5813 // - The compiling method's dex file if the class is defined there too.
5814 // - The compiling method's dex file if the class is referenced there.
5815 // - The dex file where the class is defined. When the load kind can only be
5816 // kBssEntry or kDexCacheViaMethod, we cannot emit code for this `HLoadClass`.
5817 const dex::TypeIndex type_index_;
5818 const DexFile& dex_file_;
5819
5820 Handle<mirror::Class> klass_;
5821
5822 ReferenceTypeInfo loaded_class_rti_;
5823
5824 DISALLOW_COPY_AND_ASSIGN(HLoadClass);
5825 };
5826 std::ostream& operator<<(std::ostream& os, HLoadClass::LoadKind rhs);
5827
5828 // Note: defined outside class to see operator<<(., HLoadClass::LoadKind).
AddSpecialInput(HInstruction * special_input)5829 inline void HLoadClass::AddSpecialInput(HInstruction* special_input) {
5830 // The special input is used for PC-relative loads on some architectures,
5831 // including literal pool loads, which are PC-relative too.
5832 DCHECK(GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative ||
5833 GetLoadKind() == LoadKind::kBootImageLinkTimeAddress ||
5834 GetLoadKind() == LoadKind::kBootImageAddress ||
5835 GetLoadKind() == LoadKind::kBssEntry) << GetLoadKind();
5836 DCHECK(special_input_.GetInstruction() == nullptr);
5837 special_input_ = HUserRecord<HInstruction*>(special_input);
5838 special_input->AddUseAt(this, 0);
5839 }
5840
5841 class HLoadString FINAL : public HInstruction {
5842 public:
5843 // Determines how to load the String.
5844 enum class LoadKind {
5845 // Use boot image String* address that will be known at link time.
5846 // Used for boot image strings referenced by boot image code in non-PIC mode.
5847 kBootImageLinkTimeAddress,
5848
5849 // Use PC-relative boot image String* address that will be known at link time.
5850 // Used for boot image strings referenced by boot image code in PIC mode.
5851 kBootImageLinkTimePcRelative,
5852
5853 // Use a known boot image String* address, embedded in the code by the codegen.
5854 // Used for boot image strings referenced by apps in AOT- and JIT-compiled code.
5855 kBootImageAddress,
5856
5857 // Load from an entry in the .bss section using a PC-relative load.
5858 // Used for strings outside boot image when .bss is accessible with a PC-relative load.
5859 kBssEntry,
5860
5861 // Load from the root table associated with the JIT compiled method.
5862 kJitTableAddress,
5863
5864 // Load from resolved strings array accessed through the class loaded from
5865 // the compiled method's own ArtMethod*. This is the default access type when
5866 // all other types are unavailable.
5867 kDexCacheViaMethod,
5868
5869 kLast = kDexCacheViaMethod,
5870 };
5871
HLoadString(HCurrentMethod * current_method,dex::StringIndex string_index,const DexFile & dex_file,uint32_t dex_pc)5872 HLoadString(HCurrentMethod* current_method,
5873 dex::StringIndex string_index,
5874 const DexFile& dex_file,
5875 uint32_t dex_pc)
5876 : HInstruction(SideEffectsForArchRuntimeCalls(), dex_pc),
5877 special_input_(HUserRecord<HInstruction*>(current_method)),
5878 string_index_(string_index),
5879 dex_file_(dex_file) {
5880 SetPackedField<LoadKindField>(LoadKind::kDexCacheViaMethod);
5881 }
5882
5883 void SetLoadKind(LoadKind load_kind);
5884
GetLoadKind()5885 LoadKind GetLoadKind() const {
5886 return GetPackedField<LoadKindField>();
5887 }
5888
GetDexFile()5889 const DexFile& GetDexFile() const {
5890 return dex_file_;
5891 }
5892
GetStringIndex()5893 dex::StringIndex GetStringIndex() const {
5894 return string_index_;
5895 }
5896
GetString()5897 Handle<mirror::String> GetString() const {
5898 return string_;
5899 }
5900
SetString(Handle<mirror::String> str)5901 void SetString(Handle<mirror::String> str) {
5902 string_ = str;
5903 }
5904
CanBeMoved()5905 bool CanBeMoved() const OVERRIDE { return true; }
5906
5907 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE;
5908
ComputeHashCode()5909 size_t ComputeHashCode() const OVERRIDE { return string_index_.index_; }
5910
5911 // Will call the runtime if we need to load the string through
5912 // the dex cache and the string is not guaranteed to be there yet.
NeedsEnvironment()5913 bool NeedsEnvironment() const OVERRIDE {
5914 LoadKind load_kind = GetLoadKind();
5915 if (load_kind == LoadKind::kBootImageLinkTimeAddress ||
5916 load_kind == LoadKind::kBootImageLinkTimePcRelative ||
5917 load_kind == LoadKind::kBootImageAddress ||
5918 load_kind == LoadKind::kJitTableAddress) {
5919 return false;
5920 }
5921 return true;
5922 }
5923
NeedsDexCacheOfDeclaringClass()5924 bool NeedsDexCacheOfDeclaringClass() const OVERRIDE {
5925 return GetLoadKind() == LoadKind::kDexCacheViaMethod;
5926 }
5927
CanBeNull()5928 bool CanBeNull() const OVERRIDE { return false; }
CanThrow()5929 bool CanThrow() const OVERRIDE { return NeedsEnvironment(); }
5930
SideEffectsForArchRuntimeCalls()5931 static SideEffects SideEffectsForArchRuntimeCalls() {
5932 return SideEffects::CanTriggerGC();
5933 }
5934
5935 void AddSpecialInput(HInstruction* special_input);
5936
5937 using HInstruction::GetInputRecords; // Keep the const version visible.
GetInputRecords()5938 ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() OVERRIDE FINAL {
5939 return ArrayRef<HUserRecord<HInstruction*>>(
5940 &special_input_, (special_input_.GetInstruction() != nullptr) ? 1u : 0u);
5941 }
5942
GetType()5943 Primitive::Type GetType() const OVERRIDE {
5944 return Primitive::kPrimNot;
5945 }
5946
5947 DECLARE_INSTRUCTION(LoadString);
5948
5949 private:
5950 static constexpr size_t kFieldLoadKind = kNumberOfGenericPackedBits;
5951 static constexpr size_t kFieldLoadKindSize =
5952 MinimumBitsToStore(static_cast<size_t>(LoadKind::kLast));
5953 static constexpr size_t kNumberOfLoadStringPackedBits = kFieldLoadKind + kFieldLoadKindSize;
5954 static_assert(kNumberOfLoadStringPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
5955 using LoadKindField = BitField<LoadKind, kFieldLoadKind, kFieldLoadKindSize>;
5956
5957 void SetLoadKindInternal(LoadKind load_kind);
5958
5959 // The special input is the HCurrentMethod for kDexCacheViaMethod.
5960 // For other load kinds it's empty or possibly some architecture-specific instruction
5961 // for PC-relative loads, i.e. kBssEntry or kBootImageLinkTimePcRelative.
5962 HUserRecord<HInstruction*> special_input_;
5963
5964 dex::StringIndex string_index_;
5965 const DexFile& dex_file_;
5966
5967 Handle<mirror::String> string_;
5968
5969 DISALLOW_COPY_AND_ASSIGN(HLoadString);
5970 };
5971 std::ostream& operator<<(std::ostream& os, HLoadString::LoadKind rhs);
5972
5973 // Note: defined outside class to see operator<<(., HLoadString::LoadKind).
AddSpecialInput(HInstruction * special_input)5974 inline void HLoadString::AddSpecialInput(HInstruction* special_input) {
5975 // The special input is used for PC-relative loads on some architectures,
5976 // including literal pool loads, which are PC-relative too.
5977 DCHECK(GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative ||
5978 GetLoadKind() == LoadKind::kBssEntry ||
5979 GetLoadKind() == LoadKind::kBootImageLinkTimeAddress ||
5980 GetLoadKind() == LoadKind::kBootImageAddress) << GetLoadKind();
5981 // HLoadString::GetInputRecords() returns an empty array at this point,
5982 // so use the GetInputRecords() from the base class to set the input record.
5983 DCHECK(special_input_.GetInstruction() == nullptr);
5984 special_input_ = HUserRecord<HInstruction*>(special_input);
5985 special_input->AddUseAt(this, 0);
5986 }
5987
5988 /**
5989 * Performs an initialization check on its Class object input.
5990 */
5991 class HClinitCheck FINAL : public HExpression<1> {
5992 public:
HClinitCheck(HLoadClass * constant,uint32_t dex_pc)5993 HClinitCheck(HLoadClass* constant, uint32_t dex_pc)
5994 : HExpression(
5995 Primitive::kPrimNot,
5996 SideEffects::AllChanges(), // Assume write/read on all fields/arrays.
5997 dex_pc) {
5998 SetRawInputAt(0, constant);
5999 }
6000
CanBeMoved()6001 bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(const HInstruction * other ATTRIBUTE_UNUSED)6002 bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
6003 return true;
6004 }
6005
NeedsEnvironment()6006 bool NeedsEnvironment() const OVERRIDE {
6007 // May call runtime to initialize the class.
6008 return true;
6009 }
6010
CanThrow()6011 bool CanThrow() const OVERRIDE { return true; }
6012
GetLoadClass()6013 HLoadClass* GetLoadClass() const {
6014 DCHECK(InputAt(0)->IsLoadClass());
6015 return InputAt(0)->AsLoadClass();
6016 }
6017
6018 DECLARE_INSTRUCTION(ClinitCheck);
6019
6020 private:
6021 DISALLOW_COPY_AND_ASSIGN(HClinitCheck);
6022 };
6023
6024 class HStaticFieldGet FINAL : public HExpression<1> {
6025 public:
HStaticFieldGet(HInstruction * cls,ArtField * field,Primitive::Type field_type,MemberOffset field_offset,bool is_volatile,uint32_t field_idx,uint16_t declaring_class_def_index,const DexFile & dex_file,uint32_t dex_pc)6026 HStaticFieldGet(HInstruction* cls,
6027 ArtField* field,
6028 Primitive::Type field_type,
6029 MemberOffset field_offset,
6030 bool is_volatile,
6031 uint32_t field_idx,
6032 uint16_t declaring_class_def_index,
6033 const DexFile& dex_file,
6034 uint32_t dex_pc)
6035 : HExpression(field_type, SideEffects::FieldReadOfType(field_type, is_volatile), dex_pc),
6036 field_info_(field,
6037 field_offset,
6038 field_type,
6039 is_volatile,
6040 field_idx,
6041 declaring_class_def_index,
6042 dex_file) {
6043 SetRawInputAt(0, cls);
6044 }
6045
6046
CanBeMoved()6047 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); }
6048
InstructionDataEquals(const HInstruction * other)6049 bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
6050 const HStaticFieldGet* other_get = other->AsStaticFieldGet();
6051 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
6052 }
6053
ComputeHashCode()6054 size_t ComputeHashCode() const OVERRIDE {
6055 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
6056 }
6057
GetFieldInfo()6058 const FieldInfo& GetFieldInfo() const { return field_info_; }
GetFieldOffset()6059 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
GetFieldType()6060 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
IsVolatile()6061 bool IsVolatile() const { return field_info_.IsVolatile(); }
6062
6063 DECLARE_INSTRUCTION(StaticFieldGet);
6064
6065 private:
6066 const FieldInfo field_info_;
6067
6068 DISALLOW_COPY_AND_ASSIGN(HStaticFieldGet);
6069 };
6070
6071 class HStaticFieldSet FINAL : public HTemplateInstruction<2> {
6072 public:
HStaticFieldSet(HInstruction * cls,HInstruction * value,ArtField * field,Primitive::Type field_type,MemberOffset field_offset,bool is_volatile,uint32_t field_idx,uint16_t declaring_class_def_index,const DexFile & dex_file,uint32_t dex_pc)6073 HStaticFieldSet(HInstruction* cls,
6074 HInstruction* value,
6075 ArtField* field,
6076 Primitive::Type field_type,
6077 MemberOffset field_offset,
6078 bool is_volatile,
6079 uint32_t field_idx,
6080 uint16_t declaring_class_def_index,
6081 const DexFile& dex_file,
6082 uint32_t dex_pc)
6083 : HTemplateInstruction(SideEffects::FieldWriteOfType(field_type, is_volatile), dex_pc),
6084 field_info_(field,
6085 field_offset,
6086 field_type,
6087 is_volatile,
6088 field_idx,
6089 declaring_class_def_index,
6090 dex_file) {
6091 SetPackedFlag<kFlagValueCanBeNull>(true);
6092 SetRawInputAt(0, cls);
6093 SetRawInputAt(1, value);
6094 }
6095
GetFieldInfo()6096 const FieldInfo& GetFieldInfo() const { return field_info_; }
GetFieldOffset()6097 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
GetFieldType()6098 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
IsVolatile()6099 bool IsVolatile() const { return field_info_.IsVolatile(); }
6100
GetValue()6101 HInstruction* GetValue() const { return InputAt(1); }
GetValueCanBeNull()6102 bool GetValueCanBeNull() const { return GetPackedFlag<kFlagValueCanBeNull>(); }
ClearValueCanBeNull()6103 void ClearValueCanBeNull() { SetPackedFlag<kFlagValueCanBeNull>(false); }
6104
6105 DECLARE_INSTRUCTION(StaticFieldSet);
6106
6107 private:
6108 static constexpr size_t kFlagValueCanBeNull = kNumberOfGenericPackedBits;
6109 static constexpr size_t kNumberOfStaticFieldSetPackedBits = kFlagValueCanBeNull + 1;
6110 static_assert(kNumberOfStaticFieldSetPackedBits <= kMaxNumberOfPackedBits,
6111 "Too many packed fields.");
6112
6113 const FieldInfo field_info_;
6114
6115 DISALLOW_COPY_AND_ASSIGN(HStaticFieldSet);
6116 };
6117
6118 class HUnresolvedInstanceFieldGet FINAL : public HExpression<1> {
6119 public:
HUnresolvedInstanceFieldGet(HInstruction * obj,Primitive::Type field_type,uint32_t field_index,uint32_t dex_pc)6120 HUnresolvedInstanceFieldGet(HInstruction* obj,
6121 Primitive::Type field_type,
6122 uint32_t field_index,
6123 uint32_t dex_pc)
6124 : HExpression(field_type, SideEffects::AllExceptGCDependency(), dex_pc),
6125 field_index_(field_index) {
6126 SetRawInputAt(0, obj);
6127 }
6128
NeedsEnvironment()6129 bool NeedsEnvironment() const OVERRIDE { return true; }
CanThrow()6130 bool CanThrow() const OVERRIDE { return true; }
6131
GetFieldType()6132 Primitive::Type GetFieldType() const { return GetType(); }
GetFieldIndex()6133 uint32_t GetFieldIndex() const { return field_index_; }
6134
6135 DECLARE_INSTRUCTION(UnresolvedInstanceFieldGet);
6136
6137 private:
6138 const uint32_t field_index_;
6139
6140 DISALLOW_COPY_AND_ASSIGN(HUnresolvedInstanceFieldGet);
6141 };
6142
6143 class HUnresolvedInstanceFieldSet FINAL : public HTemplateInstruction<2> {
6144 public:
HUnresolvedInstanceFieldSet(HInstruction * obj,HInstruction * value,Primitive::Type field_type,uint32_t field_index,uint32_t dex_pc)6145 HUnresolvedInstanceFieldSet(HInstruction* obj,
6146 HInstruction* value,
6147 Primitive::Type field_type,
6148 uint32_t field_index,
6149 uint32_t dex_pc)
6150 : HTemplateInstruction(SideEffects::AllExceptGCDependency(), dex_pc),
6151 field_index_(field_index) {
6152 SetPackedField<FieldTypeField>(field_type);
6153 DCHECK_EQ(Primitive::PrimitiveKind(field_type), Primitive::PrimitiveKind(value->GetType()));
6154 SetRawInputAt(0, obj);
6155 SetRawInputAt(1, value);
6156 }
6157
NeedsEnvironment()6158 bool NeedsEnvironment() const OVERRIDE { return true; }
CanThrow()6159 bool CanThrow() const OVERRIDE { return true; }
6160
GetFieldType()6161 Primitive::Type GetFieldType() const { return GetPackedField<FieldTypeField>(); }
GetFieldIndex()6162 uint32_t GetFieldIndex() const { return field_index_; }
6163
6164 DECLARE_INSTRUCTION(UnresolvedInstanceFieldSet);
6165
6166 private:
6167 static constexpr size_t kFieldFieldType = HInstruction::kNumberOfGenericPackedBits;
6168 static constexpr size_t kFieldFieldTypeSize =
6169 MinimumBitsToStore(static_cast<size_t>(Primitive::kPrimLast));
6170 static constexpr size_t kNumberOfUnresolvedStaticFieldSetPackedBits =
6171 kFieldFieldType + kFieldFieldTypeSize;
6172 static_assert(kNumberOfUnresolvedStaticFieldSetPackedBits <= HInstruction::kMaxNumberOfPackedBits,
6173 "Too many packed fields.");
6174 using FieldTypeField = BitField<Primitive::Type, kFieldFieldType, kFieldFieldTypeSize>;
6175
6176 const uint32_t field_index_;
6177
6178 DISALLOW_COPY_AND_ASSIGN(HUnresolvedInstanceFieldSet);
6179 };
6180
6181 class HUnresolvedStaticFieldGet FINAL : public HExpression<0> {
6182 public:
HUnresolvedStaticFieldGet(Primitive::Type field_type,uint32_t field_index,uint32_t dex_pc)6183 HUnresolvedStaticFieldGet(Primitive::Type field_type,
6184 uint32_t field_index,
6185 uint32_t dex_pc)
6186 : HExpression(field_type, SideEffects::AllExceptGCDependency(), dex_pc),
6187 field_index_(field_index) {
6188 }
6189
NeedsEnvironment()6190 bool NeedsEnvironment() const OVERRIDE { return true; }
CanThrow()6191 bool CanThrow() const OVERRIDE { return true; }
6192
GetFieldType()6193 Primitive::Type GetFieldType() const { return GetType(); }
GetFieldIndex()6194 uint32_t GetFieldIndex() const { return field_index_; }
6195
6196 DECLARE_INSTRUCTION(UnresolvedStaticFieldGet);
6197
6198 private:
6199 const uint32_t field_index_;
6200
6201 DISALLOW_COPY_AND_ASSIGN(HUnresolvedStaticFieldGet);
6202 };
6203
6204 class HUnresolvedStaticFieldSet FINAL : public HTemplateInstruction<1> {
6205 public:
HUnresolvedStaticFieldSet(HInstruction * value,Primitive::Type field_type,uint32_t field_index,uint32_t dex_pc)6206 HUnresolvedStaticFieldSet(HInstruction* value,
6207 Primitive::Type field_type,
6208 uint32_t field_index,
6209 uint32_t dex_pc)
6210 : HTemplateInstruction(SideEffects::AllExceptGCDependency(), dex_pc),
6211 field_index_(field_index) {
6212 SetPackedField<FieldTypeField>(field_type);
6213 DCHECK_EQ(Primitive::PrimitiveKind(field_type), Primitive::PrimitiveKind(value->GetType()));
6214 SetRawInputAt(0, value);
6215 }
6216
NeedsEnvironment()6217 bool NeedsEnvironment() const OVERRIDE { return true; }
CanThrow()6218 bool CanThrow() const OVERRIDE { return true; }
6219
GetFieldType()6220 Primitive::Type GetFieldType() const { return GetPackedField<FieldTypeField>(); }
GetFieldIndex()6221 uint32_t GetFieldIndex() const { return field_index_; }
6222
6223 DECLARE_INSTRUCTION(UnresolvedStaticFieldSet);
6224
6225 private:
6226 static constexpr size_t kFieldFieldType = HInstruction::kNumberOfGenericPackedBits;
6227 static constexpr size_t kFieldFieldTypeSize =
6228 MinimumBitsToStore(static_cast<size_t>(Primitive::kPrimLast));
6229 static constexpr size_t kNumberOfUnresolvedStaticFieldSetPackedBits =
6230 kFieldFieldType + kFieldFieldTypeSize;
6231 static_assert(kNumberOfUnresolvedStaticFieldSetPackedBits <= HInstruction::kMaxNumberOfPackedBits,
6232 "Too many packed fields.");
6233 using FieldTypeField = BitField<Primitive::Type, kFieldFieldType, kFieldFieldTypeSize>;
6234
6235 const uint32_t field_index_;
6236
6237 DISALLOW_COPY_AND_ASSIGN(HUnresolvedStaticFieldSet);
6238 };
6239
6240 // Implement the move-exception DEX instruction.
6241 class HLoadException FINAL : public HExpression<0> {
6242 public:
6243 explicit HLoadException(uint32_t dex_pc = kNoDexPc)
HExpression(Primitive::kPrimNot,SideEffects::None (),dex_pc)6244 : HExpression(Primitive::kPrimNot, SideEffects::None(), dex_pc) {}
6245
CanBeNull()6246 bool CanBeNull() const OVERRIDE { return false; }
6247
6248 DECLARE_INSTRUCTION(LoadException);
6249
6250 private:
6251 DISALLOW_COPY_AND_ASSIGN(HLoadException);
6252 };
6253
6254 // Implicit part of move-exception which clears thread-local exception storage.
6255 // Must not be removed because the runtime expects the TLS to get cleared.
6256 class HClearException FINAL : public HTemplateInstruction<0> {
6257 public:
6258 explicit HClearException(uint32_t dex_pc = kNoDexPc)
HTemplateInstruction(SideEffects::AllWrites (),dex_pc)6259 : HTemplateInstruction(SideEffects::AllWrites(), dex_pc) {}
6260
6261 DECLARE_INSTRUCTION(ClearException);
6262
6263 private:
6264 DISALLOW_COPY_AND_ASSIGN(HClearException);
6265 };
6266
6267 class HThrow FINAL : public HTemplateInstruction<1> {
6268 public:
HThrow(HInstruction * exception,uint32_t dex_pc)6269 HThrow(HInstruction* exception, uint32_t dex_pc)
6270 : HTemplateInstruction(SideEffects::CanTriggerGC(), dex_pc) {
6271 SetRawInputAt(0, exception);
6272 }
6273
IsControlFlow()6274 bool IsControlFlow() const OVERRIDE { return true; }
6275
NeedsEnvironment()6276 bool NeedsEnvironment() const OVERRIDE { return true; }
6277
CanThrow()6278 bool CanThrow() const OVERRIDE { return true; }
6279
6280
6281 DECLARE_INSTRUCTION(Throw);
6282
6283 private:
6284 DISALLOW_COPY_AND_ASSIGN(HThrow);
6285 };
6286
6287 /**
6288 * Implementation strategies for the code generator of a HInstanceOf
6289 * or `HCheckCast`.
6290 */
6291 enum class TypeCheckKind {
6292 kUnresolvedCheck, // Check against an unresolved type.
6293 kExactCheck, // Can do a single class compare.
6294 kClassHierarchyCheck, // Can just walk the super class chain.
6295 kAbstractClassCheck, // Can just walk the super class chain, starting one up.
6296 kInterfaceCheck, // No optimization yet when checking against an interface.
6297 kArrayObjectCheck, // Can just check if the array is not primitive.
6298 kArrayCheck, // No optimization yet when checking against a generic array.
6299 kLast = kArrayCheck
6300 };
6301
6302 std::ostream& operator<<(std::ostream& os, TypeCheckKind rhs);
6303
6304 class HInstanceOf FINAL : public HExpression<2> {
6305 public:
HInstanceOf(HInstruction * object,HLoadClass * constant,TypeCheckKind check_kind,uint32_t dex_pc)6306 HInstanceOf(HInstruction* object,
6307 HLoadClass* constant,
6308 TypeCheckKind check_kind,
6309 uint32_t dex_pc)
6310 : HExpression(Primitive::kPrimBoolean,
6311 SideEffectsForArchRuntimeCalls(check_kind),
6312 dex_pc) {
6313 SetPackedField<TypeCheckKindField>(check_kind);
6314 SetPackedFlag<kFlagMustDoNullCheck>(true);
6315 SetRawInputAt(0, object);
6316 SetRawInputAt(1, constant);
6317 }
6318
CanBeMoved()6319 bool CanBeMoved() const OVERRIDE { return true; }
6320
InstructionDataEquals(const HInstruction * other ATTRIBUTE_UNUSED)6321 bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
6322 return true;
6323 }
6324
NeedsEnvironment()6325 bool NeedsEnvironment() const OVERRIDE {
6326 return CanCallRuntime(GetTypeCheckKind());
6327 }
6328
6329 // Used only in code generation.
MustDoNullCheck()6330 bool MustDoNullCheck() const { return GetPackedFlag<kFlagMustDoNullCheck>(); }
ClearMustDoNullCheck()6331 void ClearMustDoNullCheck() { SetPackedFlag<kFlagMustDoNullCheck>(false); }
GetTypeCheckKind()6332