nodes.h revision 8d5b8b295930aaa43255c4f0b74ece3ee8b43a47
1d195e5ab401432ddac659791640a2927fc668699Elliott Hughes/* 2d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * Copyright (C) 2014 The Android Open Source Project 3d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * 4d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 5d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * you may not use this file except in compliance with the License. 6d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * You may obtain a copy of the License at 7d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * 8d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 9d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * 10d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * Unless required by applicable law or agreed to in writing, software 11d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 12d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * See the License for the specific language governing permissions and 14d195e5ab401432ddac659791640a2927fc668699Elliott Hughes * limitations under the License. 15d195e5ab401432ddac659791640a2927fc668699Elliott Hughes */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifndef ART_COMPILER_OPTIMIZING_NODES_H_ 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define ART_COMPILER_OPTIMIZING_NODES_H_ 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "base/arena_containers.h" 210795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopian#include "base/arena_object.h" 220bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick#include "entrypoints/quick/quick_entrypoints_enum.h" 230795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopian#include "handle.h" 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "handle_scope.h" 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "invoke_type.h" 260795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopian#include "locations.h" 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "mirror/class.h" 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "offsets.h" 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "primitive.h" 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "utils/arena_bit_vector.h" 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "utils/growable_array.h" 32fc8db53eee11568b286e8d9c17e211bd6781fab6Mike Reed 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace art { 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass GraphChecker; 369f8203a159d46124a0907a0d9500e599533beed3Brian Carlstromclass HBasicBlock; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HDoubleConstant; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HEnvironment; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HFloatConstant; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HGraphVisitor; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HInstruction; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HIntConstant; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HInvoke; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HLongConstant; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HNullConstant; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HPhi; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HSuspendCheck; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass LiveInterval; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass LocationSummary; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass SsaBuilder; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const int kDefaultNumberOfBlocks = 8; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const int kDefaultNumberOfSuccessors = 2; 546b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic const int kDefaultNumberOfPredecessors = 2; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const int kDefaultNumberOfDominatedBlocks = 1; 56d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins IIIstatic const int kDefaultNumberOfBackEdges = 1; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic constexpr uint32_t kMaxIntShiftValue = 0x1f; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic constexpr uint64_t kMaxLongShiftValue = 0x3f; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectenum IfCondition { 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project kCondEQ, 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project kCondNE, 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project kCondLT, 65bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen kCondLE, 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project kCondGT, 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project kCondGE, 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 696b1e838fc16d397359f82c3a4f5700f1ed7dd910Thomas Tafertshofer 70237c2b871f66e06498ad03aaa92964f4434982c5Jesse Hallclass HInstructionList { 711c4907ee77392afb768c2f088e0dedbe4239f6fbJack Palevich public: 721c4907ee77392afb768c2f088e0dedbe4239f6fbJack Palevich HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {} 731c4907ee77392afb768c2f088e0dedbe4239f6fbJack Palevich 741c4907ee77392afb768c2f088e0dedbe4239f6fbJack Palevich void AddInstruction(HInstruction* instruction); 75560814f6b11abe83ff0c4ed18cac015c276b3181Jack Palevich void RemoveInstruction(HInstruction* instruction); 76d877efe3b12afdd84f06c180369f9d7399858f6eJesse Hall 777ab63acdd0a257272512d0bcf5e06036fa0b9fdfJesse Hall // Return true if this list contains `instruction`. 787ab63acdd0a257272512d0bcf5e06036fa0b9fdfJesse Hall bool Contains(HInstruction* instruction) const; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Return true if `instruction1` is found before `instruction2` in 812f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvala // this instruction list and false otherwise. Abort if none 82feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk // of these instructions is found. 83b6079005ed0631c3972ff427f56e12523ec214a7Ruben Brunk bool FoundBefore(const HInstruction* instruction1, 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const HInstruction* instruction2) const; 85b01e8bf57b7492b77e3445db51471edcbadda75eMike Lockwood 86e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood bool IsEmpty() const { return first_instruction_ == nullptr; } 87acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood void Clear() { first_instruction_ = last_instruction_ = nullptr; } 88e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Update the block of all instructions to be `block`. 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void SetBlockOfInstructions(HBasicBlock* block) const; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void AddAfter(HInstruction* cursor, const HInstructionList& instruction_list); 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void Add(const HInstructionList& instruction_list); 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private: 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HInstruction* first_instruction_; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HInstruction* last_instruction_; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project friend class HBasicBlock; 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project friend class HGraph; 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project friend class HInstruction; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project friend class HInstructionIterator; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project friend class HBackwardInstructionIterator; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DISALLOW_COPY_AND_ASSIGN(HInstructionList); 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Control-flow graph of a method. Contains a list of basic blocks. 109b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Projectclass HGraph : public ArenaObject<kArenaAllocMisc> { 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public: 11152244fff29042926e21fa897ef5ab11148e35299John Reck HGraph(ArenaAllocator* arena, bool debuggable = false, int start_instruction_id = 0) 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : arena_(arena), 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project blocks_(arena, kDefaultNumberOfBlocks), 1141a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien reverse_post_order_(arena, kDefaultNumberOfBlocks), 1154c9355c35a0f62805739823a62ad41ca1cbc6502Mike Reed entry_block_(nullptr), 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exit_block_(nullptr), 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project maximum_number_of_out_vregs_(0), 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project number_of_vregs_(0), 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project number_of_in_vregs_(0), 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project temporaries_vreg_slots_(0), 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project has_array_accesses_(false), 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project debuggable_(debuggable), 123fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown current_instruction_id_(start_instruction_id), 124aa0ce3396c096c97e3394c53e3912cb08b66fe20Jamie Gennis cached_null_constant_(nullptr), 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cached_int_constants_(std::less<int32_t>(), arena->Adapter()), 1266811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav cached_long_constants_(std::less<int64_t>(), arena->Adapter()) {} 1272961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 1280a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown ArenaAllocator* GetArena() const { return arena_; } 129f666ad7046c0b1b255835f75aeb7d1391067df93John Reck const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; } 130e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck HBasicBlock* GetBlock(size_t id) const { return blocks_.Get(id); } 1313b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 132e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy HBasicBlock* GetEntryBlock() const { return entry_block_; } 1333083579424785e55ca8f82856a6553ee983c3ffbJohn Reck HBasicBlock* GetExitBlock() const { return exit_block_; } 13404fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck 135cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; } 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void SetExitBlock(HBasicBlock* block) { exit_block_ = block; } 1373866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian 13864a55af0ac700baecb0877235eb42caac59a3560Jeff Brown void AddBlock(HBasicBlock* block); 1398f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy 140315c329544d7c593d1072b071cbb92d9afe74021John Reck // Try building the SSA form of this graph, with dominance computation and loop 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // recognition. Returns whether it was successful in doing all these steps. 142e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown bool TryBuildingSsa() { 143e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown BuildDominatorTree(); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The SSA builder requires loops to all be natural. Specifically, the dead phi 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // elimination phase checks the consistency of the graph when doing a post-order 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // visit for eliminating dead phis: a dead phi can only have loop header phi 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // users remaining when being visited. 148fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate if (!AnalyzeNaturalLoops()) return false; 149d84e1ce0b535128f03416145554fb405f9fade3eJeff Sharkey TransformToSsa(); 150c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley return true; 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 153481c1570dc5cdf58265b53f657801709dd05d1dfJeff Brown void BuildDominatorTree(); 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void TransformToSsa(); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void SimplifyCFG(); 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Analyze all natural loops in this graph. Returns false if one 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // loop is not natural, that is the header does not dominate the 1592b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor // back edge. 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool AnalyzeNaturalLoops() const; 161dae8e94cce0881f3e10ef5e34b881f512bb52a75Doug Felt 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Inline this graph in `outer_graph`, replacing the given `invoke` instruction. 16398a4f7e7e12effb78b3d1035e5a670ccbbf5bca1JP Abgrall void InlineInto(HGraph* outer_graph, HInvoke* invoke); 164ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void MergeEmptyBranches(HBasicBlock* start_block, HBasicBlock* end_block); 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1671cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor); 168d2110dbce071a236b6176de344ca797b737542ebJoe Onorato void SimplifyLoop(HBasicBlock* header); 16906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato 1704ababd922eac5931e0222862ff082dc29e012816Joe Onorato int32_t GetNextInstructionId() { 1714a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate DCHECK_NE(current_instruction_id_, INT32_MAX); 1729c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase return current_instruction_id_++; 17369969e48f2bca9339662dddfacff0bbf6374ed7fDianne Hackborn } 174cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 17546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown int32_t GetCurrentInstructionId() const { 1769f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown return current_instruction_id_; 17732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown } 178c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 179a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright void SetCurrentInstructionId(int32_t id) { 1809f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown current_instruction_id_ = id; 18146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 18246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 1832352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown uint16_t GetMaximumNumberOfOutVRegs() const { 1842ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown return maximum_number_of_out_vregs_; 18502c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root } 18608d5b8fad8d46ccb64db2fdcb4d66972ec87bf48Dianne Hackborn 1876e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase void SetMaximumNumberOfOutVRegs(uint16_t new_value) { 18866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root maximum_number_of_out_vregs_ = new_value; 1899a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey } 190973b4663b0b5ee62006522bf4742af076096e548Narayan Kamath 1919fa4071c4768c63902c6a74a4b480b51a8b95d43John Reck void UpdateTemporariesVRegSlots(size_t slots) { 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project temporaries_vreg_slots_ = std::max(slots, temporaries_vreg_slots_); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t GetTemporariesVRegSlots() const { 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return temporaries_vreg_slots_; 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void SetNumberOfVRegs(uint16_t number_of_vregs) { 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project number_of_vregs_ = number_of_vregs; 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint16_t GetNumberOfVRegs() const { 20416f5f5cc9d4c480fac3dc7f176f3f1edfbd256f4Jeff Brown return number_of_vregs_; 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void SetNumberOfInVRegs(uint16_t value) { 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project number_of_in_vregs_ = value; 20916f5f5cc9d4c480fac3dc7f176f3f1edfbd256f4Jeff Brown } 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint16_t GetNumberOfLocalVRegs() const { 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return number_of_vregs_ - number_of_in_vregs_; 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2144280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown 2154280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown const GrowableArray<HBasicBlock*>& GetReversePostOrder() const { 2164280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown return reverse_post_order_; 2174280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown } 2184280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown 2194280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown bool HasArrayAccesses() const { 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return has_array_accesses_; 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void SetHasArrayAccesses(bool value) { 22416f5f5cc9d4c480fac3dc7f176f3f1edfbd256f4Jeff Brown has_array_accesses_ = value; 22516f5f5cc9d4c480fac3dc7f176f3f1edfbd256f4Jeff Brown } 22616f5f5cc9d4c480fac3dc7f176f3f1edfbd256f4Jeff Brown 22716f5f5cc9d4c480fac3dc7f176f3f1edfbd256f4Jeff Brown bool IsDebuggable() const { return debuggable_; } 2284280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown 2294280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown // Returns a constant of the given type and value. If it does not exist 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // already, it is created and inserted into the graph. Only integral types 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // are currently supported. 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HConstant* GetConstant(Primitive::Type type, int64_t value); 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HNullConstant* GetNullConstant(); 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HIntConstant* GetIntConstant(int32_t value) { 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return CreateConstant(value, &cached_int_constants_); 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HLongConstant* GetLongConstant(int64_t value) { 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return CreateConstant(value, &cached_long_constants_); 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2409ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber 2419ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber private: 242a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const; 243a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath void VisitBlockForDominatorTree(HBasicBlock* block, 244a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath HBasicBlock* predecessor, 245a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath GrowableArray<size_t>* visits); 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void FindBackEdges(ArenaBitVector* visited); 247c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project void VisitBlockForBackEdges(HBasicBlock* block, 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArenaBitVector* visited, 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArenaBitVector* visiting); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const; 251fc8db53eee11568b286e8d9c17e211bd6781fab6Mike Reed void RemoveDeadBlocks(const ArenaBitVector& visited) const; 252fc8db53eee11568b286e8d9c17e211bd6781fab6Mike Reed 253fc8db53eee11568b286e8d9c17e211bd6781fab6Mike Reed template <class InstType, typename ValueType> 254fc8db53eee11568b286e8d9c17e211bd6781fab6Mike Reed InstType* CreateConstant(ValueType value, ArenaSafeMap<ValueType, InstType*>* cache); 255fc8db53eee11568b286e8d9c17e211bd6781fab6Mike Reed void InsertConstant(HConstant* instruction); 256fc8db53eee11568b286e8d9c17e211bd6781fab6Mike Reed 257fc8db53eee11568b286e8d9c17e211bd6781fab6Mike Reed ArenaAllocator* const arena_; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // List of blocks in insertion order. 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GrowableArray<HBasicBlock*> blocks_; 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // List of blocks to perform a reverse post order tree traversal. 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GrowableArray<HBasicBlock*> reverse_post_order_; 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HBasicBlock* entry_block_; 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HBasicBlock* exit_block_; 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The maximum number of virtual registers arguments passed to a HInvoke in this graph. 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint16_t maximum_number_of_out_vregs_; 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2719ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber // The number of virtual registers in this method. Contains the parameters. 2729ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber uint16_t number_of_vregs_; 2739ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber 2749ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber // The number of virtual registers used by parameters of this method. 2759ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber uint16_t number_of_in_vregs_; 2769ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber 2779ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber // Number of vreg size slots that the temporaries use (used in baseline compiler). 2789ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber size_t temporaries_vreg_slots_; 2799ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber 280a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // Has array accesses. We can totally skip BCE if it's false. 281a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath bool has_array_accesses_; 282a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath 283a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath // Indicates whether the graph should be compiled in a way that 28422ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // ensures full debuggability. If false, we can apply more 28522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath // aggressive optimizations that may limit the level of debugging. 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const bool debuggable_; 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The current id to assign to a newly added instruction. See HInstruction.id_. 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t current_instruction_id_; 29022ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath 29108e60f2a165d23b53f41993374aa074165bb5863Dianne Hackborn // Cached common constants often needed by optimization passes. 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HNullConstant* cached_null_constant_; 293d195e5ab401432ddac659791640a2927fc668699Elliott Hughes ArenaSafeMap<int32_t, HIntConstant*> cached_int_constants_; 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArenaSafeMap<int64_t, HLongConstant*> cached_long_constants_; 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ART_FRIEND_TEST(GraphTest, IfSuccessorSimpleJoinBlock1); 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DISALLOW_COPY_AND_ASSIGN(HGraph); 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 29922ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HLoopInformation : public ArenaObject<kArenaAllocMisc> { 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public: 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HLoopInformation(HBasicBlock* header, HGraph* graph) 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : header_(header), 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project suspend_check_(nullptr), 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges), 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Make bit vector growable, as the number of blocks may change. 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project blocks_(graph->GetArena(), graph->GetBlocks().Size(), true) {} 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HBasicBlock* GetHeader() const { 31022ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath return header_; 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31222ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void SetHeader(HBasicBlock* block) { 31422ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath header_ = block; 31522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath } 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HSuspendCheck* GetSuspendCheck() const { return suspend_check_; } 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void SetSuspendCheck(HSuspendCheck* check) { suspend_check_ = check; } 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool HasSuspendCheck() const { return suspend_check_ != nullptr; } 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void AddBackEdge(HBasicBlock* back_edge) { 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project back_edges_.Add(back_edge); 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void RemoveBackEdge(HBasicBlock* back_edge) { 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project back_edges_.Delete(back_edge); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3284280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool IsBackEdge(const HBasicBlock& block) const { 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) { 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (back_edges_.Get(i) == &block) return true; 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t NumberOfBackEdges() const { 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return back_edges_.Size(); 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HBasicBlock* GetPreHeader() const; 3410bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick 3420bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick const GrowableArray<HBasicBlock*>& GetBackEdges() const { 3430bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick return back_edges_; 3440bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick } 3450bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick 3460bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick void ClearBackEdges() { 3470bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick back_edges_.Reset(); 3480bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick } 3490bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick 3500bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick // Find blocks that are part of this loop. Returns whether the loop is a natural loop, 3510bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick // that is the header dominates the back edge. 3520bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick bool Populate(); 3530bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick 3540bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick // Returns whether this loop information contains `block`. 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Note that this loop information *must* be populated before entering this function. 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool Contains(const HBasicBlock& block) const; 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Returns whether this loop information is an inner loop of `other`. 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Note that `other` *must* be populated before entering this function. 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool IsIn(const HLoopInformation& other) const; 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const ArenaBitVector& GetBlocks() const { return blocks_; } 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 364d195e5ab401432ddac659791640a2927fc668699Elliott Hughes void Add(HBasicBlock* block); 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void Remove(HBasicBlock* block); 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private: 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Internal recursive implementation of `Populate`. 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void PopulateRecursive(HBasicBlock* block); 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HBasicBlock* header_; 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HSuspendCheck* suspend_check_; 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GrowableArray<HBasicBlock*> back_edges_; 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArenaBitVector blocks_; 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DISALLOW_COPY_AND_ASSIGN(HLoopInformation); 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic constexpr size_t kNoLifetime = -1; 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic constexpr uint32_t kNoDexPc = -1; 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// A block in a method. Contains the list of instructions represented 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// as a double linked list. Each block knows its predecessors and 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// successors. 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HBasicBlock : public ArenaObject<kArenaAllocMisc> { 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public: 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project explicit HBasicBlock(HGraph* graph, uint32_t dex_pc = kNoDexPc) 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : graph_(graph), 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors), 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project successors_(graph->GetArena(), kDefaultNumberOfSuccessors), 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project loop_information_(nullptr), 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dominator_(nullptr), 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dominated_blocks_(graph->GetArena(), kDefaultNumberOfDominatedBlocks), 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project block_id_(-1), 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dex_pc_(dex_pc), 397171ea89fb99385146e159ef75849a87c49ffee76Brian Carlstrom lifetime_start_(kNoLifetime), 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lifetime_end_(kNoLifetime), 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project is_catch_block_(false) {} 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const GrowableArray<HBasicBlock*>& GetPredecessors() const { 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return predecessors_; 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const GrowableArray<HBasicBlock*>& GetSuccessors() const { 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return successors_; 4075baa3a62a97544669fba6d65a11c07f252e654ddSteve Block } 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const GrowableArray<HBasicBlock*>& GetDominatedBlocks() const { 410f70188aa4716625781d9952c6b883180528d4644Andy McFadden return dominated_blocks_; 411e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden } 412e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden 413e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden bool IsEntryBlock() const { 414e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden return graph_->GetEntryBlock() == this; 415e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden } 4163beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom 4173beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom bool IsExitBlock() const { 418e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden return graph_->GetExitBlock() == this; 419e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden } 4203beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom 421e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden bool IsSingleGoto() const; 422e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden 423e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden void AddBackEdge(HBasicBlock* back_edge) { 4243beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom if (loop_information_ == nullptr) { 4253beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_); 426e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden } 427e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden DCHECK_EQ(loop_information_->GetHeader(), this); 428e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden loop_information_->AddBackEdge(back_edge); 429e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden } 430e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden 431e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden HGraph* GetGraph() const { return graph_; } 432e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden void SetGraph(HGraph* graph) { graph_ = graph; } 433e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden 434e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden int GetBlockId() const { return block_id_; } 435e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden void SetBlockId(int id) { block_id_ = id; } 436e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden 437e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden HBasicBlock* GetDominator() const { return dominator_; } 438e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; } 4393beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom void AddDominatedBlock(HBasicBlock* block) { dominated_blocks_.Add(block); } 4403beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom void ReplaceDominatedBlock(HBasicBlock* existing, HBasicBlock* new_block) { 4413beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom for (size_t i = 0, e = dominated_blocks_.Size(); i < e; ++i) { 4423beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom if (dominated_blocks_.Get(i) == existing) { 4433beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom dominated_blocks_.Put(i, new_block); 444e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden return; 445e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden } 446e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden } 447e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden LOG(FATAL) << "Unreachable"; 448e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden UNREACHABLE(); 449e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden } 450f70188aa4716625781d9952c6b883180528d4644Andy McFadden 451f70188aa4716625781d9952c6b883180528d4644Andy McFadden int NumberOfBackEdges() const { 452f70188aa4716625781d9952c6b883180528d4644Andy McFadden return loop_information_ == nullptr 453f70188aa4716625781d9952c6b883180528d4644Andy McFadden ? 0 454f70188aa4716625781d9952c6b883180528d4644Andy McFadden : loop_information_->NumberOfBackEdges(); 45507a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison } 45607a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison 45707a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; } 45807a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; } 45907a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison const HInstructionList& GetInstructions() const { return instructions_; } 46007a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison const HInstructionList& GetPhis() const { return phis_; } 46107a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison HInstruction* GetFirstPhi() const { return phis_.first_instruction_; } 46207a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison 463f70188aa4716625781d9952c6b883180528d4644Andy McFadden void AddSuccessor(HBasicBlock* block) { 464f70188aa4716625781d9952c6b883180528d4644Andy McFadden successors_.Add(block); 465f70188aa4716625781d9952c6b883180528d4644Andy McFadden block->predecessors_.Add(this); 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 467f70188aa4716625781d9952c6b883180528d4644Andy McFadden 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void ReplaceSuccessor(HBasicBlock* existing, HBasicBlock* new_block) { 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t successor_index = GetSuccessorIndexOf(existing); 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DCHECK_NE(successor_index, static_cast<size_t>(-1)); 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project existing->RemovePredecessor(this); 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new_block->predecessors_.Add(this); 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project successors_.Put(successor_index, new_block); 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 47538cfa8ca8bc67f4342431cea7e35643ddf9254ccCarl Shapiro 476bdcef70e15e86e592d725355c96c7fab0b85ac83Dianne Hackborn void ReplacePredecessor(HBasicBlock* existing, HBasicBlock* new_block) { 4778cdf27c36a5b697396144925b3f61e4802dd3558Carl Shapiro size_t predecessor_index = GetPredecessorIndexOf(existing); 4785325010486a13553a8597aab92f90abc141a25e8Ian Rogers DCHECK_NE(predecessor_index, static_cast<size_t>(-1)); 4795325010486a13553a8597aab92f90abc141a25e8Ian Rogers existing->RemoveSuccessor(this); 4807e4fdec6f0ac6385c5f8aeaf0f2e12e162138ac3Mathieu Chartier new_block->successors_.Add(this); 481c01936a686ff75c872629b219898021e8ae49afaMathieu Chartier predecessors_.Put(predecessor_index, new_block); 4825325010486a13553a8597aab92f90abc141a25e8Ian Rogers } 483b63de6de026b8ebe0b7d7b7f188afc30fff42411buzbee 4843beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom void RemovePredecessor(HBasicBlock* block) { 4853beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom predecessors_.Delete(block); 4863beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom } 487e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void RemoveSuccessor(HBasicBlock* block) { 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project successors_.Delete(block); 490e2b23e11a5475e5c35eb07ba883cb05eca18796fAndy McFadden } 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 49252b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng void ClearAllPredecessors() { 49352b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng predecessors_.Reset(); 49452b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng } 49552b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng 49652b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng void AddPredecessor(HBasicBlock* block) { 49752b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng predecessors_.Add(block); 49807a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison block->successors_.Add(this); 49907a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison } 50007a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison 50107a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison void SwapPredecessors() { 50207a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison DCHECK_EQ(predecessors_.Size(), 2u); 50307a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison HBasicBlock* temp = predecessors_.Get(0); 50407a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison predecessors_.Put(0, predecessors_.Get(1)); 50507a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison predecessors_.Put(1, temp); 50607a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison } 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t GetPredecessorIndexOf(HBasicBlock* predecessor) { 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) { 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (predecessors_.Get(i) == predecessor) { 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return i; 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t GetSuccessorIndexOf(HBasicBlock* successor) { 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (size_t i = 0, e = successors_.Size(); i < e; ++i) { 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (successors_.Get(i) == successor) { 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return i; 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 52452b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng } 52552b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Split the block into two blocks just after `cursor`. Returns the newly 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // created block. Note that this method just updates raw block information, 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // like predecessors, successors, dominators, and instruction list. It does not 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // update the graph, reverse post order, loop information, nor make sure the 530e2b23e11a5475e5c35eb07ba883cb05eca18796fAndy McFadden // blocks are consistent (for example ending with a control flow instruction). 531e2b23e11a5475e5c35eb07ba883cb05eca18796fAndy McFadden HBasicBlock* SplitAfter(HInstruction* cursor); 532e2b23e11a5475e5c35eb07ba883cb05eca18796fAndy McFadden 533e2b23e11a5475e5c35eb07ba883cb05eca18796fAndy McFadden // Merge `other` at the end of `this`. Successors and dominated blocks of 534e2b23e11a5475e5c35eb07ba883cb05eca18796fAndy McFadden // `other` are changed to be successors and dominated blocks of `this`. Note 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // that this method does not update the graph, reverse post order, loop 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // information, nor make sure the blocks are consistent (for example ending 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // with a control flow instruction). 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void MergeWith(HBasicBlock* other); 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Replace `this` with `other`. Predecessors, successors, and dominated blocks 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // of `this` are moved to `other`. 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Note that this method does not update the graph, reverse post order, loop 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // information, nor make sure the blocks are consistent (for example ending 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // with a control flow instruction). 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void ReplaceWith(HBasicBlock* other); 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Disconnects `this` from all its predecessors, successors and the dominator. 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It assumes that `this` does not dominate any blocks. 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Note that this method does not update the graph, reverse post order, loop 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // information, nor make sure the blocks are consistent (for example ending 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // with a control flow instruction). 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void DisconnectFromAll(); 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void AddInstruction(HInstruction* instruction); 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor); 5560bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick // Replace instruction `initial` with `replacement` within this block. 5570bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick void ReplaceAndRemoveInstructionWith(HInstruction* initial, 5580bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick HInstruction* replacement); 5590bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick void AddPhi(HPhi* phi); 5600bd5243b751c9cad317758158f79b3347e7948afBrad Fitzpatrick void InsertPhiAfter(HPhi* instruction, HPhi* cursor); 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // RemoveInstruction and RemovePhi delete a given instruction from the respective 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // instruction list. With 'ensure_safety' set to true, it verifies that the 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // instruction is not in use and removes it from the use lists of its inputs. 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void RemoveInstruction(HInstruction* instruction, bool ensure_safety = true); 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void RemovePhi(HPhi* phi, bool ensure_safety = true); 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool IsLoopHeader() const { 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (loop_information_ != nullptr) && (loop_information_->GetHeader() == this); 5699e4c884e7a7acd6b75399b180dc339295cda5a43Carl Shapiro } 5709e4c884e7a7acd6b75399b180dc339295cda5a43Carl Shapiro 5719e4c884e7a7acd6b75399b180dc339295cda5a43Carl Shapiro bool IsLoopPreHeaderFirstPredecessor() const { 5729e4c884e7a7acd6b75399b180dc339295cda5a43Carl Shapiro DCHECK(IsLoopHeader()); 57338cfa8ca8bc67f4342431cea7e35643ddf9254ccCarl Shapiro DCHECK(!GetPredecessors().IsEmpty()); 5749e4c884e7a7acd6b75399b180dc339295cda5a43Carl Shapiro return GetPredecessors().Get(0) == GetLoopInformation()->GetPreHeader(); 57538cfa8ca8bc67f4342431cea7e35643ddf9254ccCarl Shapiro } 57638cfa8ca8bc67f4342431cea7e35643ddf9254ccCarl Shapiro 577bdcef70e15e86e592d725355c96c7fab0b85ac83Dianne Hackborn HLoopInformation* GetLoopInformation() const { 578bdcef70e15e86e592d725355c96c7fab0b85ac83Dianne Hackborn return loop_information_; 579bdcef70e15e86e592d725355c96c7fab0b85ac83Dianne Hackborn } 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set the loop_information_ on this block. Overrides the current 5823f177d7c9a5c8ac727b0c6c3a5131e1e00ea52e8Elliott Hughes // loop_information if it is an outer loop of the passed loop information. 5833f177d7c9a5c8ac727b0c6c3a5131e1e00ea52e8Elliott Hughes // Note that this method is called while creating the loop information. 5843f177d7c9a5c8ac727b0c6c3a5131e1e00ea52e8Elliott Hughes void SetInLoop(HLoopInformation* info) { 5853f177d7c9a5c8ac727b0c6c3a5131e1e00ea52e8Elliott Hughes if (IsLoopHeader()) { 586b63de6de026b8ebe0b7d7b7f188afc30fff42411buzbee // Nothing to do. This just means `info` is an outer loop. 587b63de6de026b8ebe0b7d7b7f188afc30fff42411buzbee } else if (loop_information_ == nullptr) { 588b63de6de026b8ebe0b7d7b7f188afc30fff42411buzbee loop_information_ = info; 589b63de6de026b8ebe0b7d7b7f188afc30fff42411buzbee } else if (loop_information_->Contains(*info->GetHeader())) { 590b63de6de026b8ebe0b7d7b7f188afc30fff42411buzbee // Block is currently part of an outer loop. Make it part of this inner loop. 591b63de6de026b8ebe0b7d7b7f188afc30fff42411buzbee // Note that a non loop header having a loop information means this loop information 592b63de6de026b8ebe0b7d7b7f188afc30fff42411buzbee // has already been populated 593b63de6de026b8ebe0b7d7b7f188afc30fff42411buzbee loop_information_ = info; 5948cdf27c36a5b697396144925b3f61e4802dd3558Carl Shapiro } else { 5958cdf27c36a5b697396144925b3f61e4802dd3558Carl Shapiro // Block is part of an inner loop. Do not update the loop information. 5968cdf27c36a5b697396144925b3f61e4802dd3558Carl Shapiro // Note that we cannot do the check `info->Contains(loop_information_)->GetHeader()` 5978cdf27c36a5b697396144925b3f61e4802dd3558Carl Shapiro // at this point, because this method is being called while populating `info`. 5988cdf27c36a5b697396144925b3f61e4802dd3558Carl Shapiro } 5998cdf27c36a5b697396144925b3f61e4802dd3558Carl Shapiro } 6008cdf27c36a5b697396144925b3f61e4802dd3558Carl Shapiro 6015325010486a13553a8597aab92f90abc141a25e8Ian Rogers // Raw update of the loop information. 6025325010486a13553a8597aab92f90abc141a25e8Ian Rogers void SetLoopInformation(HLoopInformation* info) { 6035325010486a13553a8597aab92f90abc141a25e8Ian Rogers loop_information_ = info; 6045325010486a13553a8597aab92f90abc141a25e8Ian Rogers } 6055325010486a13553a8597aab92f90abc141a25e8Ian Rogers 6065325010486a13553a8597aab92f90abc141a25e8Ian Rogers bool IsInLoop() const { return loop_information_ != nullptr; } 6075325010486a13553a8597aab92f90abc141a25e8Ian Rogers 6085325010486a13553a8597aab92f90abc141a25e8Ian Rogers // Returns wheter this block dominates the blocked passed as parameter. 6095325010486a13553a8597aab92f90abc141a25e8Ian Rogers bool Dominates(HBasicBlock* block) const; 6105325010486a13553a8597aab92f90abc141a25e8Ian Rogers 6115325010486a13553a8597aab92f90abc141a25e8Ian Rogers size_t GetLifetimeStart() const { return lifetime_start_; } 6125325010486a13553a8597aab92f90abc141a25e8Ian Rogers size_t GetLifetimeEnd() const { return lifetime_end_; } 6135325010486a13553a8597aab92f90abc141a25e8Ian Rogers 6145325010486a13553a8597aab92f90abc141a25e8Ian Rogers void SetLifetimeStart(size_t start) { lifetime_start_ = start; } 6155325010486a13553a8597aab92f90abc141a25e8Ian Rogers void SetLifetimeEnd(size_t end) { lifetime_end_ = end; } 6165325010486a13553a8597aab92f90abc141a25e8Ian Rogers 6177fef2b8a3782a94e1ad6bfef98807167db300aabIan Rogers uint32_t GetDexPc() const { return dex_pc_; } 6185325010486a13553a8597aab92f90abc141a25e8Ian Rogers 6195325010486a13553a8597aab92f90abc141a25e8Ian Rogers bool IsCatchBlock() const { return is_catch_block_; } 6205325010486a13553a8597aab92f90abc141a25e8Ian Rogers void SetIsCatchBlock() { is_catch_block_ = true; } 6215325010486a13553a8597aab92f90abc141a25e8Ian Rogers 622e6c2241f7a1e6bca3fd8d5d0c49abbbd348366b7Mathieu Chartier bool EndsWithControlFlowInstruction() const; 623e6c2241f7a1e6bca3fd8d5d0c49abbbd348366b7Mathieu Chartier bool EndsWithIf() const; 624e6c2241f7a1e6bca3fd8d5d0c49abbbd348366b7Mathieu Chartier bool HasSinglePhi() const; 625e6c2241f7a1e6bca3fd8d5d0c49abbbd348366b7Mathieu Chartier 626e6c2241f7a1e6bca3fd8d5d0c49abbbd348366b7Mathieu Chartier private: 627e6c2241f7a1e6bca3fd8d5d0c49abbbd348366b7Mathieu Chartier HGraph* graph_; 6287e4fdec6f0ac6385c5f8aeaf0f2e12e162138ac3Mathieu Chartier GrowableArray<HBasicBlock*> predecessors_; 6297e4fdec6f0ac6385c5f8aeaf0f2e12e162138ac3Mathieu Chartier GrowableArray<HBasicBlock*> successors_; 6307e4fdec6f0ac6385c5f8aeaf0f2e12e162138ac3Mathieu Chartier HInstructionList instructions_; 6317e4fdec6f0ac6385c5f8aeaf0f2e12e162138ac3Mathieu Chartier HInstructionList phis_; 6327e4fdec6f0ac6385c5f8aeaf0f2e12e162138ac3Mathieu Chartier HLoopInformation* loop_information_; 6337e4fdec6f0ac6385c5f8aeaf0f2e12e162138ac3Mathieu Chartier HBasicBlock* dominator_; 6347e4fdec6f0ac6385c5f8aeaf0f2e12e162138ac3Mathieu Chartier GrowableArray<HBasicBlock*> dominated_blocks_; 635c01936a686ff75c872629b219898021e8ae49afaMathieu Chartier int block_id_; 636c01936a686ff75c872629b219898021e8ae49afaMathieu Chartier // The dex program counter of the first instruction of this block. 637c01936a686ff75c872629b219898021e8ae49afaMathieu Chartier const uint32_t dex_pc_; 638c01936a686ff75c872629b219898021e8ae49afaMathieu Chartier size_t lifetime_start_; 639c01936a686ff75c872629b219898021e8ae49afaMathieu Chartier size_t lifetime_end_; 640c01936a686ff75c872629b219898021e8ae49afaMathieu Chartier bool is_catch_block_; 641c01936a686ff75c872629b219898021e8ae49afaMathieu Chartier 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project friend class HGraph; 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project friend class HInstruction; 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DISALLOW_COPY_AND_ASSIGN(HBasicBlock); 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Iterates over the LoopInformation of all loops which contain 'block' 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// from the innermost to the outermost. 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HLoopInformationOutwardIterator : public ValueObject { 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public: 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project explicit HLoopInformationOutwardIterator(const HBasicBlock& block) 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : current_(block.GetLoopInformation()) {} 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool Done() const { return current_ == nullptr; } 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void Advance() { 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DCHECK(!Done()); 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project current_ = current_->GetHeader()->GetDominator()->GetLoopInformation(); 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HLoopInformation* Current() const { 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DCHECK(!Done()); 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return current_; 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private: 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HLoopInformation* current_; 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DISALLOW_COPY_AND_ASSIGN(HLoopInformationOutwardIterator); 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 67208065b9f09ead8895d97b2971622af8c179e1768Brian Carlstrom 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define FOR_EACH_CONCRETE_INSTRUCTION(M) \ 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(Add, BinaryOperation) \ 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(And, BinaryOperation) \ 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(ArrayGet, Instruction) \ 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(ArrayLength, Instruction) \ 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(ArraySet, Instruction) \ 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(BoundsCheck, Instruction) \ 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(BoundType, Instruction) \ 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(CheckCast, Instruction) \ 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(ClinitCheck, Instruction) \ 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(Compare, BinaryOperation) \ 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(Condition, BinaryOperation) \ 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(Div, BinaryOperation) \ 6867b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project M(DivZeroCheck, Instruction) \ 6877b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project M(DoubleConstant, Constant) \ 6887b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project M(Equal, Condition) \ 6897b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project M(Exit, Instruction) \ 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(FloatConstant, Constant) \ 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(Goto, Instruction) \ 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(GreaterThan, Condition) \ 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(GreaterThanOrEqual, Condition) \ 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(If, Instruction) \ 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(InstanceFieldGet, Instruction) \ 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(InstanceFieldSet, Instruction) \ 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(InstanceOf, Instruction) \ 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(IntConstant, Constant) \ 6995baa3a62a97544669fba6d65a11c07f252e654ddSteve Block M(InvokeInterface, Invoke) \ 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(InvokeStaticOrDirect, Invoke) \ 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(InvokeVirtual, Invoke) \ 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(LessThan, Condition) \ 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(LessThanOrEqual, Condition) \ 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(LoadClass, Instruction) \ 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(LoadException, Instruction) \ 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(LoadLocal, Instruction) \ 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(LoadString, Instruction) \ 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(Local, Instruction) \ 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(LongConstant, Constant) \ 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(MonitorOperation, Instruction) \ 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(Mul, BinaryOperation) \ 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(Neg, UnaryOperation) \ 71352b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng M(NewArray, Instruction) \ 714d8f3ec6e8308400e9446b254fcca457f6e53ea13Carl Shapiro M(NewInstance, Instruction) \ 715d8f3ec6e8308400e9446b254fcca457f6e53ea13Carl Shapiro M(Not, UnaryOperation) \ 716d8f3ec6e8308400e9446b254fcca457f6e53ea13Carl Shapiro M(NotEqual, Condition) \ 717d8f3ec6e8308400e9446b254fcca457f6e53ea13Carl Shapiro M(NullConstant, Instruction) \ 718d8f3ec6e8308400e9446b254fcca457f6e53ea13Carl Shapiro M(NullCheck, Instruction) \ 719d8f3ec6e8308400e9446b254fcca457f6e53ea13Carl Shapiro M(Or, BinaryOperation) \ 720d8f3ec6e8308400e9446b254fcca457f6e53ea13Carl Shapiro M(ParallelMove, Instruction) \ 721d8f3ec6e8308400e9446b254fcca457f6e53ea13Carl Shapiro M(ParameterValue, Instruction) \ 72252b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng M(Phi, Instruction) \ 72352b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng M(Rem, BinaryOperation) \ 72452b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng M(Return, Instruction) \ 72552b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng M(ReturnVoid, Instruction) \ 72652b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng M(Shl, BinaryOperation) \ 72752b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng M(Shr, BinaryOperation) \ 72852b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng M(StaticFieldGet, Instruction) \ 72952b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng M(StaticFieldSet, Instruction) \ 73052b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng M(StoreLocal, Instruction) \ 73152b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng M(Sub, BinaryOperation) \ 73252b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng M(SuspendCheck, Instruction) \ 73352b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng M(Temporary, Instruction) \ 73452b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng M(Throw, Instruction) \ 73552b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng M(TypeConversion, Instruction) \ 73652b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng M(UShr, BinaryOperation) \ 73752b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng M(Xor, BinaryOperation) \ 73852b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng 73952b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng#define FOR_EACH_INSTRUCTION(M) \ 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FOR_EACH_CONCRETE_INSTRUCTION(M) \ 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(Constant, Instruction) \ 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(UnaryOperation, Instruction) \ 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(BinaryOperation, Instruction) \ 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project M(Invoke, Instruction) 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 74652b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng#define FORWARD_DECLARATION(type, super) class H##type; 74752b0e73443ff8da195fbf0df851a028e07a691b2Ben ChengFOR_EACH_INSTRUCTION(FORWARD_DECLARATION) 74852b0e73443ff8da195fbf0df851a028e07a691b2Ben Cheng#undef FORWARD_DECLARATION 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 750e2b23e11a5475e5c35eb07ba883cb05eca18796fAndy McFadden#define DECLARE_INSTRUCTION(type) \ 751e2b23e11a5475e5c35eb07ba883cb05eca18796fAndy McFadden InstructionKind GetKind() const OVERRIDE { return k##type; } \ 752e2b23e11a5475e5c35eb07ba883cb05eca18796fAndy McFadden const char* DebugName() const OVERRIDE { return #type; } \ 753e2b23e11a5475e5c35eb07ba883cb05eca18796fAndy McFadden const H##type* As##type() const OVERRIDE { return this; } \ 754e2b23e11a5475e5c35eb07ba883cb05eca18796fAndy McFadden H##type* As##type() OVERRIDE { return this; } \ 755e2b23e11a5475e5c35eb07ba883cb05eca18796fAndy McFadden bool InstructionTypeEquals(HInstruction* other) const OVERRIDE { \ 756e2b23e11a5475e5c35eb07ba883cb05eca18796fAndy McFadden return other->Is##type(); \ 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } \ 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void Accept(HGraphVisitor* visitor) OVERRIDE 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttemplate <typename T> class HUseList; 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttemplate <typename T> 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HUseListNode : public ArenaObject<kArenaAllocMisc> { 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public: 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HUseListNode* GetPrevious() const { return prev_; } 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HUseListNode* GetNext() const { return next_; } 7676215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block T GetUser() const { return user_; } 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t GetIndex() const { return index_; } 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private: 77171f2cf116aab893e224056c38ab146bd1538dd3eSteve Block HUseListNode(T user, size_t index) 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : user_(user), index_(index), prev_(nullptr), next_(nullptr) {} 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project T const user_; 7756215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block const size_t index_; 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HUseListNode<T>* prev_; 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HUseListNode<T>* next_; 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project friend class HUseList<T>; 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DISALLOW_COPY_AND_ASSIGN(HUseListNode); 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttemplate <typename T> 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HUseList : public ValueObject { 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public: 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HUseList() : first_(nullptr) {} 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void Clear() { 790e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden first_ = nullptr; 79198ba7bd5d1942edd7c2881cc6fd0e777ae8baa2eBrian Carlstrom } 7923beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom 79398ba7bd5d1942edd7c2881cc6fd0e777ae8baa2eBrian Carlstrom // Adds a new entry at the beginning of the use list and returns 7943beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom // the newly created node. 79598ba7bd5d1942edd7c2881cc6fd0e777ae8baa2eBrian Carlstrom HUseListNode<T>* AddUse(T user, size_t index, ArenaAllocator* arena) { 7963beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom HUseListNode<T>* new_node = new (arena) HUseListNode<T>(user, index); 7973beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom if (IsEmpty()) { 7983beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom first_ = new_node; 7993beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom } else { 8003beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom first_->prev_ = new_node; 8013beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom new_node->next_ = first_; 8023beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom first_ = new_node; 8033beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom } 8043beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom return new_node; 805e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden } 806e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden 8073beff1e023193b485c67a3003a7f363f105d96d4Brian Carlstrom HUseListNode<T>* GetFirst() const { 808e4d81f25bd4dc1a5c909b56ab56a56406290da30Andy McFadden return first_; 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void Remove(HUseListNode<T>* node) { 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DCHECK(node != nullptr); 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DCHECK(Contains(node)); 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (node->prev_ != nullptr) { 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project node->prev_->next_ = node->next_; 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (node->next_ != nullptr) { 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project node->next_->prev_ = node->prev_; 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8210efbd9a463c848118c7685f4bfc8765a82caa761Dave Allison if (node == first_) { 8220efbd9a463c848118c7685f4bfc8765a82caa761Dave Allison first_ = node->next_; 8230efbd9a463c848118c7685f4bfc8765a82caa761Dave Allison } 82498ba7bd5d1942edd7c2881cc6fd0e777ae8baa2eBrian Carlstrom } 8250efbd9a463c848118c7685f4bfc8765a82caa761Dave Allison 82607a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison bool Contains(const HUseListNode<T>* node) const { 82707a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison if (node == nullptr) { 82807a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison return false; 8290efbd9a463c848118c7685f4bfc8765a82caa761Dave Allison } 8300efbd9a463c848118c7685f4bfc8765a82caa761Dave Allison for (HUseListNode<T>* current = first_; current != nullptr; current = current->GetNext()) { 8310efbd9a463c848118c7685f4bfc8765a82caa761Dave Allison if (current == node) { 83207a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison return true; 83307a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison } 83407a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison } 8350efbd9a463c848118c7685f4bfc8765a82caa761Dave Allison return false; 8360efbd9a463c848118c7685f4bfc8765a82caa761Dave Allison } 8370efbd9a463c848118c7685f4bfc8765a82caa761Dave Allison 8380efbd9a463c848118c7685f4bfc8765a82caa761Dave Allison bool IsEmpty() const { 83907a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison return first_ == nullptr; 84007a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison } 84107a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison 8420efbd9a463c848118c7685f4bfc8765a82caa761Dave Allison bool HasOnlyOneUse() const { 8430efbd9a463c848118c7685f4bfc8765a82caa761Dave Allison return first_ != nullptr && first_->next_ == nullptr; 8440efbd9a463c848118c7685f4bfc8765a82caa761Dave Allison } 8450efbd9a463c848118c7685f4bfc8765a82caa761Dave Allison 84607a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison private: 84707a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison HUseListNode<T>* first_; 84807a1e2323b1e6765f220a045bd05783dd99b2914Dave Allison}; 8490efbd9a463c848118c7685f4bfc8765a82caa761Dave Allison 8500efbd9a463c848118c7685f4bfc8765a82caa761Dave Allisontemplate<typename T> 8510efbd9a463c848118c7685f4bfc8765a82caa761Dave Allisonclass HUseIterator : public ValueObject { 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public: 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project explicit HUseIterator(const HUseList<T>& uses) : current_(uses.GetFirst()) {} 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool Done() const { return current_ == nullptr; } 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void Advance() { 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DCHECK(!Done()); 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project current_ = current_->GetNext(); 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HUseListNode<T>* Current() const { 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DCHECK(!Done()); 864f70188aa4716625781d9952c6b883180528d4644Andy McFadden return current_; 8653762c311729fe9f3af085c14c5c1fb471d994c03Steve Block } 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private: 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HUseListNode<T>* current_; 869f70188aa4716625781d9952c6b883180528d4644Andy McFadden 870f70188aa4716625781d9952c6b883180528d4644Andy McFadden friend class HValue; 871f70188aa4716625781d9952c6b883180528d4644Andy McFadden}; 872f70188aa4716625781d9952c6b883180528d4644Andy McFadden 873f70188aa4716625781d9952c6b883180528d4644Andy McFadden// This class is used by HEnvironment and HInstruction classes to record the 874f70188aa4716625781d9952c6b883180528d4644Andy McFadden// instructions they use and pointers to the corresponding HUseListNodes kept 875f70188aa4716625781d9952c6b883180528d4644Andy McFadden// by the used instructions. 876d195e5ab401432ddac659791640a2927fc668699Elliott Hughestemplate <typename T> 877d195e5ab401432ddac659791640a2927fc668699Elliott Hughesclass HUserRecord : public ValueObject { 878d195e5ab401432ddac659791640a2927fc668699Elliott Hughes public: 879d195e5ab401432ddac659791640a2927fc668699Elliott Hughes HUserRecord() : instruction_(nullptr), use_node_(nullptr) {} 880d195e5ab401432ddac659791640a2927fc668699Elliott Hughes explicit HUserRecord(HInstruction* instruction) : instruction_(instruction), use_node_(nullptr) {} 881d195e5ab401432ddac659791640a2927fc668699Elliott Hughes 882d195e5ab401432ddac659791640a2927fc668699Elliott Hughes HUserRecord(const HUserRecord<T>& old_record, HUseListNode<T>* use_node) 883d195e5ab401432ddac659791640a2927fc668699Elliott Hughes : instruction_(old_record.instruction_), use_node_(use_node) { 884d195e5ab401432ddac659791640a2927fc668699Elliott Hughes DCHECK(instruction_ != nullptr); 885d195e5ab401432ddac659791640a2927fc668699Elliott Hughes DCHECK(use_node_ != nullptr); 886d195e5ab401432ddac659791640a2927fc668699Elliott Hughes DCHECK(old_record.use_node_ == nullptr); 887f70188aa4716625781d9952c6b883180528d4644Andy McFadden } 888f70188aa4716625781d9952c6b883180528d4644Andy McFadden 889f70188aa4716625781d9952c6b883180528d4644Andy McFadden HInstruction* GetInstruction() const { return instruction_; } 890f70188aa4716625781d9952c6b883180528d4644Andy McFadden HUseListNode<T>* GetUseNode() const { return use_node_; } 891ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown 892ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown private: 893ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown // Instruction used by the user. 894f70188aa4716625781d9952c6b883180528d4644Andy McFadden HInstruction* instruction_; 89522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath 896f70188aa4716625781d9952c6b883180528d4644Andy McFadden // Corresponding entry in the use list kept by 'instruction_'. 8975baa3a62a97544669fba6d65a11c07f252e654ddSteve Block HUseListNode<T>* use_node_; 89808e60f2a165d23b53f41993374aa074165bb5863Dianne Hackborn}; 899f70188aa4716625781d9952c6b883180528d4644Andy McFadden 90022ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath// Represents the side effects an instruction may have. 90122ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamathclass SideEffects : public ValueObject { 902d195e5ab401432ddac659791640a2927fc668699Elliott Hughes public: 903d195e5ab401432ddac659791640a2927fc668699Elliott Hughes SideEffects() : flags_(0) {} 904f70188aa4716625781d9952c6b883180528d4644Andy McFadden 905f70188aa4716625781d9952c6b883180528d4644Andy McFadden static SideEffects None() { 90622ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath return SideEffects(0); 90722ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath } 90822ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath 90922ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath static SideEffects All() { 91022ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath return SideEffects(ChangesSomething().flags_ | DependsOnSomething().flags_); 91122ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath } 912f70188aa4716625781d9952c6b883180528d4644Andy McFadden 913f70188aa4716625781d9952c6b883180528d4644Andy McFadden static SideEffects ChangesSomething() { 914f70188aa4716625781d9952c6b883180528d4644Andy McFadden return SideEffects((1 << kFlagChangesCount) - 1); 915f70188aa4716625781d9952c6b883180528d4644Andy McFadden } 916f70188aa4716625781d9952c6b883180528d4644Andy McFadden 917f70188aa4716625781d9952c6b883180528d4644Andy McFadden static SideEffects DependsOnSomething() { 918f70188aa4716625781d9952c6b883180528d4644Andy McFadden int count = kFlagDependsOnCount - kFlagChangesCount; 919d195e5ab401432ddac659791640a2927fc668699Elliott Hughes return SideEffects(((1 << count) - 1) << kFlagChangesCount); 920f70188aa4716625781d9952c6b883180528d4644Andy McFadden } 921f70188aa4716625781d9952c6b883180528d4644Andy McFadden 922f70188aa4716625781d9952c6b883180528d4644Andy McFadden SideEffects Union(SideEffects other) const { 923f70188aa4716625781d9952c6b883180528d4644Andy McFadden return SideEffects(flags_ | other.flags_); 924f70188aa4716625781d9952c6b883180528d4644Andy McFadden } 9255baa3a62a97544669fba6d65a11c07f252e654ddSteve Block 926f70188aa4716625781d9952c6b883180528d4644Andy McFadden bool HasSideEffects() const { 927f70188aa4716625781d9952c6b883180528d4644Andy McFadden size_t all_bits_set = (1 << kFlagChangesCount) - 1; 9289f8203a159d46124a0907a0d9500e599533beed3Brian Carlstrom return (flags_ & all_bits_set) != 0; 9299f8203a159d46124a0907a0d9500e599533beed3Brian Carlstrom } 930d195e5ab401432ddac659791640a2927fc668699Elliott Hughes 931d195e5ab401432ddac659791640a2927fc668699Elliott Hughes bool HasAllSideEffects() const { 932d195e5ab401432ddac659791640a2927fc668699Elliott Hughes size_t all_bits_set = (1 << kFlagChangesCount) - 1; 933d195e5ab401432ddac659791640a2927fc668699Elliott Hughes return all_bits_set == (flags_ & all_bits_set); 934d195e5ab401432ddac659791640a2927fc668699Elliott Hughes } 935f70188aa4716625781d9952c6b883180528d4644Andy McFadden 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool DependsOn(SideEffects other) const { 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t depends_flags = other.ComputeDependsFlags(); 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (flags_ & depends_flags) != 0; 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9403762c311729fe9f3af085c14c5c1fb471d994c03Steve Block 941d195e5ab401432ddac659791640a2927fc668699Elliott Hughes bool HasDependencies() const { 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = kFlagDependsOnCount - kFlagChangesCount; 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t all_bits_set = (1 << count) - 1; 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ((flags_ >> kFlagChangesCount) & all_bits_set) != 0; 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 946ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown 947ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown private: 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static constexpr int kFlagChangesSomething = 0; 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static constexpr int kFlagChangesCount = kFlagChangesSomething + 1; 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static constexpr int kFlagDependsOnSomething = kFlagChangesCount; 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static constexpr int kFlagDependsOnCount = kFlagDependsOnSomething + 1; 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project explicit SideEffects(size_t flags) : flags_(flags) {} 95522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t ComputeDependsFlags() const { 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return flags_ << kFlagChangesCount; 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 96022ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath size_t flags_; 96122ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath}; 96222ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath 96322ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath// A HEnvironment object contains the values of virtual registers at a given location. 96422ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamathclass HEnvironment : public ArenaObject<kArenaAllocMisc> { 96522ec1eefa4dc8e12f7da8e8750d4770144941526Narayan Kamath public: 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HEnvironment(ArenaAllocator* arena, size_t number_of_vregs) 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : vregs_(arena, number_of_vregs) { 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vregs_.SetSize(number_of_vregs); 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (size_t i = 0; i < number_of_vregs; i++) { 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vregs_.Put(i, HUserRecord<HEnvironment*>()); 971d195e5ab401432ddac659791640a2927fc668699Elliott Hughes } 972d195e5ab401432ddac659791640a2927fc668699Elliott Hughes } 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9743762c311729fe9f3af085c14c5c1fb471d994c03Steve Block void CopyFrom(HEnvironment* env); 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void SetRawEnvAt(size_t index, HInstruction* instruction) { 977d195e5ab401432ddac659791640a2927fc668699Elliott Hughes vregs_.Put(index, HUserRecord<HEnvironment*>(instruction)); 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9803762c311729fe9f3af085c14c5c1fb471d994c03Steve Block HInstruction* GetInstructionAt(size_t index) const { 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return vregs_.Get(index).GetInstruction(); 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void RemoveAsUserOfInput(size_t index) const; 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t Size() const { return vregs_.Size(); } 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private: 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Record instructions' use entries of this environment for constant-time removal. 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It should only be called by HInstruction when a new environment use is added. 991d195e5ab401432ddac659791640a2927fc668699Elliott Hughes void RecordEnvUse(HUseListNode<HEnvironment*>* env_use) { 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DCHECK(env_use->GetUser() == this); 9935baa3a62a97544669fba6d65a11c07f252e654ddSteve Block size_t index = env_use->GetIndex(); 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vregs_.Put(index, HUserRecord<HEnvironment*>(vregs_.Get(index), env_use)); 9958564c8da817a845353d213acd8636b76f567b234Steve Block } 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9978564c8da817a845353d213acd8636b76f567b234Steve Block GrowableArray<HUserRecord<HEnvironment*> > vregs_; 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project friend HInstruction; 10004280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DISALLOW_COPY_AND_ASSIGN(HEnvironment); 10024280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown}; 10034280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown 10044280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brownclass ReferenceTypeInfo : ValueObject { 10054280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown public: 10064280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown typedef Handle<mirror::Class> TypeHandle; 10074280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown 10084280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown static ReferenceTypeInfo Create(TypeHandle type_handle, bool is_exact) 10094280c4a93ea17f2e9d3f651e49d8c13dc3fb92aaJeff Brown SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (type_handle->IsObjectClass()) { 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Override the type handle to be consistent with the case when we get to 1012d195e5ab401432ddac659791640a2927fc668699Elliott Hughes // Top but don't have the Object class available. It avoids having to guess 1013d195e5ab401432ddac659791640a2927fc668699Elliott Hughes // what value the type_handle has when it's Top. 1014d195e5ab401432ddac659791640a2927fc668699Elliott Hughes return ReferenceTypeInfo(TypeHandle(), is_exact, true); 1015d195e5ab401432ddac659791640a2927fc668699Elliott Hughes } else { 1016d195e5ab401432ddac659791640a2927fc668699Elliott Hughes return ReferenceTypeInfo(type_handle, is_exact, false); 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10189ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber } 10199ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber 10209ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber static ReferenceTypeInfo CreateTop(bool is_exact) { 10219ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber return ReferenceTypeInfo(TypeHandle(), is_exact, true); 10229ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber } 10239ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber 10249ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber bool IsExact() const { return is_exact_; } 10259ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber bool IsTop() const { return is_top_; } 10269ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber 10279ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber Handle<mirror::Class> GetTypeHandle() const { return type_handle_; } 10289ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber 10299ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber bool IsSupertypeOf(ReferenceTypeInfo rti) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 10309ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber if (IsTop()) { 10319ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber // Top (equivalent for java.lang.Object) is supertype of anything. 10329ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber return true; 10339ae000ca8c05ad6f700ad7bf119bbc92fb964b57Andreas Huber } 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (rti.IsTop()) { 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If we get here `this` is not Top() so it can't be a supertype. 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return GetTypeHandle()->IsAssignableFrom(rti.GetTypeHandle().Get()); 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Returns true if the type information provide the same amount of details. 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Note that it does not mean that the instructions have the same actual type 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // (e.g. tops are equal but they can be the result of a merge). 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool IsEqual(ReferenceTypeInfo rti) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (IsExact() != rti.IsExact()) { 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (IsTop() && rti.IsTop()) { 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // `Top` means java.lang.Object, so the types are equivalent. 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (IsTop() || rti.IsTop()) { 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If only one is top or object than they are not equivalent. 10546215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block // NB: We need this extra check because the type_handle of `Top` is invalid 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // and we cannot inspect its reference. 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Finally check the types. 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return GetTypeHandle().Get() == rti.GetTypeHandle().Get(); 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private: 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ReferenceTypeInfo() : ReferenceTypeInfo(TypeHandle(), false, true) {} 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ReferenceTypeInfo(TypeHandle type_handle, bool is_exact, bool is_top) 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : type_handle_(type_handle), is_exact_(is_exact), is_top_(is_top) {} 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The class of the object. 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TypeHandle type_handle_; 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Whether or not the type is exact or a superclass of the actual type. 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Whether or not we have any information about this type. 10723762c311729fe9f3af085c14c5c1fb471d994c03Steve Block bool is_exact_; 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // A true value here means that the object type should be java.lang.Object. 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We don't have access to the corresponding mirror object every time so this 10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // flag acts as a substitute. When true, the TypeHandle refers to a null 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // pointer and should not be used. 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool is_top_; 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstd::ostream& operator<<(std::ostream& os, const ReferenceTypeInfo& rhs); 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HInstruction : public ArenaObject<kArenaAllocMisc> { 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public: 10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project explicit HInstruction(SideEffects side_effects) 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : previous_(nullptr), 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project next_(nullptr), 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project block_(nullptr), 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project id_(-1), 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssa_index_(-1), 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project environment_(nullptr), 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project locations_(nullptr), 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project live_interval_(nullptr), 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lifetime_position_(kNoLifetime), 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project side_effects_(side_effects), 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reference_type_info_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {} 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual ~HInstruction() {} 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define DECLARE_KIND(type, super) k##type, 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project enum InstructionKind { 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FOR_EACH_INSTRUCTION(DECLARE_KIND) 11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#undef DECLARE_KIND 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HInstruction* GetNext() const { return next_; } 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HInstruction* GetPrevious() const { return previous_; } 11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HInstruction* GetNextDisregardingMoves() const; 11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HInstruction* GetPreviousDisregardingMoves() const; 11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1111d195e5ab401432ddac659791640a2927fc668699Elliott Hughes HBasicBlock* GetBlock() const { return block_; } 11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void SetBlock(HBasicBlock* block) { block_ = block; } 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool IsInBlock() const { return block_ != nullptr; } 11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool IsInLoop() const { return block_->IsInLoop(); } 11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool IsLoopHeaderPhi() { return IsPhi() && block_->IsLoopHeader(); } 11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual size_t InputCount() const = 0; 11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HInstruction* InputAt(size_t i) const { return InputRecordAt(i).GetInstruction(); } 11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual void Accept(HGraphVisitor* visitor) = 0; 112132f2e6267481bd4b81b71061c539748143342fefMike Lockwood virtual const char* DebugName() const = 0; 112232f2e6267481bd4b81b71061c539748143342fefMike Lockwood 11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; } 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void SetRawInputAt(size_t index, HInstruction* input) { 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SetRawInputRecordAt(index, HUserRecord<HInstruction*>(input)); 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual bool NeedsEnvironment() const { return false; } 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual bool IsControlFlow() const { return false; } 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual bool CanThrow() const { return false; } 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool HasSideEffects() const { return side_effects_.HasSideEffects(); } 11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual bool ActAsNullConstant() const { return false; } 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Does not apply for all instructions, but having this at top level greatly 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // simplifies the null check elimination. 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual bool CanBeNull() const { 1138f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood DCHECK_EQ(GetType(), Primitive::kPrimNot) << "CanBeNull only applies to reference types"; 11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1141f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood 11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual bool CanDoImplicitNullCheck() const { return false; } 1143f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood 1144f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood void SetReferenceTypeInfo(ReferenceTypeInfo reference_type_info) { 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DCHECK_EQ(GetType(), Primitive::kPrimNot); 11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reference_type_info_ = reference_type_info; 11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ReferenceTypeInfo GetReferenceTypeInfo() const { 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DCHECK_EQ(GetType(), Primitive::kPrimNot); 11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return reference_type_info_; 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void AddUseAt(HInstruction* user, size_t index) { 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DCHECK(user != nullptr); 11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HUseListNode<HInstruction*>* use = 11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena()); 11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project user->SetRawInputRecordAt(index, HUserRecord<HInstruction*>(user->InputRecordAt(index), use)); 11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void AddEnvUseAt(HEnvironment* user, size_t index) { 11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DCHECK(user != nullptr); 11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HUseListNode<HEnvironment*>* env_use = 11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env_uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena()); 11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project user->RecordEnvUse(env_use); 11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void RemoveAsUserOfInput(size_t input) { 11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HUserRecord<HInstruction*> input_use = InputRecordAt(input); 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project input_use.GetInstruction()->uses_.Remove(input_use.GetUseNode()); 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const HUseList<HInstruction*>& GetUses() const { return uses_; } 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const HUseList<HEnvironment*>& GetEnvUses() const { return env_uses_; } 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11765baa3a62a97544669fba6d65a11c07f252e654ddSteve Block bool HasUses() const { return !uses_.IsEmpty() || !env_uses_.IsEmpty(); } 11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool HasEnvironmentUses() const { return !env_uses_.IsEmpty(); } 11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool HasNonEnvironmentUses() const { return !uses_.IsEmpty(); } 11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Does this instruction strictly dominate `other_instruction`? 11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Returns false if this instruction and `other_instruction` are the same. 11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Aborts if this instruction and `other_instruction` are both phis. 11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool StrictlyDominates(HInstruction* other_instruction) const; 11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int GetId() const { return id_; } 11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void SetId(int id) { id_ = id; } 11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int GetSsaIndex() const { return ssa_index_; } 11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; } 11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool HasSsaIndex() const { return ssa_index_ != -1; } 11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool HasEnvironment() const { return environment_ != nullptr; } 11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HEnvironment* GetEnvironment() const { return environment_; } 11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void SetEnvironment(HEnvironment* environment) { environment_ = environment; } 11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Returns the number of entries in the environment. Typically, that is the 11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // number of dex registers in a method. It could be more in case of inlining. 11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t EnvironmentSize() const; 11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LocationSummary* GetLocations() const { return locations_; } 1201b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project void SetLocations(LocationSummary* locations) { locations_ = locations; } 12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1203dae8e94cce0881f3e10ef5e34b881f512bb52a75Doug Felt void ReplaceWith(HInstruction* instruction); 12049f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown void ReplaceInput(HInstruction* replacement, size_t index); 12059f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Move `this` instruction before `cursor`. 1207a8079bfb9a738a7f24f103cd640e5317c4fd2510Andreas Huber void MoveBefore(HInstruction* cursor); 12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1209d84e1ce0b535128f03416145554fb405f9fade3eJeff Sharkey#define INSTRUCTION_TYPE_CHECK(type, super) \ 12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool Is##type() const { return (As##type() != nullptr); } \ 12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual const H##type* As##type() const { return nullptr; } \ 12125438979e498750b6a28ada7974d4e9fe17fd8394Chris Craik virtual H##type* As##type() { return nullptr; } 1213f666ad7046c0b1b255835f75aeb7d1391067df93John Reck 1214e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK) 12153b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#undef INSTRUCTION_TYPE_CHECK 1216e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 12173083579424785e55ca8f82856a6553ee983c3ffbJohn Reck // Returns whether the instruction can be moved within the graph. 121804fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck virtual bool CanBeMoved() const { return false; } 1219cec24ae16e9a0a7c3075f1a8d9149bb7fb3813fcJohn Reck 12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Returns whether the two instructions are of the same kind. 12213866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian virtual bool InstructionTypeEquals(HInstruction* other) const { 122264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown UNUSED(other); 12238f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy return false; 1224315c329544d7c593d1072b071cbb92d9afe74021John Reck } 12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Returns whether any data encoded in the two instructions is equal. 12276b1e838fc16d397359f82c3a4f5700f1ed7dd910Thomas Tafertshofer // This method does not look at the inputs. Both instructions must be 1228237c2b871f66e06498ad03aaa92964f4434982c5Jesse Hall // of the same type, otherwise the method has undefined behavior. 12291c4907ee77392afb768c2f088e0dedbe4239f6fbJack Palevich virtual bool InstructionDataEquals(HInstruction* other) const { 12301c4907ee77392afb768c2f088e0dedbe4239f6fbJack Palevich UNUSED(other); 12311c4907ee77392afb768c2f088e0dedbe4239f6fbJack Palevich return false; 12321c4907ee77392afb768c2f088e0dedbe4239f6fbJack Palevich } 1233560814f6b11abe83ff0c4ed18cac015c276b3181Jack Palevich 1234d877efe3b12afdd84f06c180369f9d7399858f6eJesse Hall // Returns whether two instructions are equal, that is: 12357ab63acdd0a257272512d0bcf5e06036fa0b9fdfJesse Hall // 1) They have the same type and contain the same data (InstructionDataEquals). 12367ab63acdd0a257272512d0bcf5e06036fa0b9fdfJesse Hall // 2) Their inputs are identical. 12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool Equals(HInstruction* other) const; 12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual InstructionKind GetKind() const = 0; 12406b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual size_t ComputeHashCode() const { 1242d0d7eaf129b48ea04c06902a11c2a4f74056d76cLeon Scroggins III size_t result = GetKind(); 12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (size_t i = 0, e = InputCount(); i < e; ++i) { 124452244fff29042926e21fa897ef5ab11148e35299John Reck result = (result * 31) + InputAt(i)->GetId(); 12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 12471a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien } 12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SideEffects GetSideEffects() const { return side_effects_; } 12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t GetLifetimePosition() const { return lifetime_position_; } 12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void SetLifetimePosition(size_t position) { lifetime_position_ = position; } 12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LiveInterval* GetLiveInterval() const { return live_interval_; } 12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; } 12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool HasLiveInterval() const { return live_interval_ != nullptr; } 12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool IsSuspendCheckEntry() const { return IsSuspendCheck() && GetBlock()->IsEntryBlock(); } 12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Returns whether the code generation of the instruction will require to have access 12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // to the current method. Such instructions are: 12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // (1): Instructions that require an environment, as calling the runtime requires 12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // to walk the stack and have the current method stored at a specific stack address. 1263aa0ce3396c096c97e3394c53e3912cb08b66fe20Jamie Gennis // (2): Object literals like classes and strings, that are loaded from the dex cache 12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // fields of the current method. 12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool NeedsCurrentMethod() const { 1266bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen return NeedsEnvironment() || IsLoadClass() || IsLoadString(); 12676811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav } 12682961769ea94f69c191a2dd785b2504666c7292d0Svetoslav 12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual bool NeedsDexCache() const { return false; } 12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1271e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown protected: 1272e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown virtual const HUserRecord<HInstruction*> InputRecordAt(size_t i) const = 0; 12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project virtual void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) = 0; 12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private: 1276fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate void RemoveEnvironmentUser(HUseListNode<HEnvironment*>* use_node) { env_uses_.Remove(use_node); } 1277c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 1278481c1570dc5cdf58265b53f657801709dd05d1dfJeff Brown HInstruction* previous_; 12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HInstruction* next_; 12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HBasicBlock* block_; 12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12822b4abcd0c7c4361af8ab6d5d7b073fb75ac6d219Dan Egnor // An instruction gets an id when it is added to the graph. 12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It reflects creation order. A negative id means the instruction 12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // has not been added to the graph. 1285973b4663b0b5ee62006522bf4742af076096e548Narayan Kamath int id_; 12869fa4071c4768c63902c6a74a4b480b51a8b95d43John Reck 12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // When doing liveness analysis, instructions that have uses get an SSA index. 12882f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvala int ssa_index_; 1289feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 1290b6079005ed0631c3972ff427f56e12523ec214a7Ruben Brunk // List of instructions that have this instruction as input. 12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HUseList<HInstruction*> uses_; 1292b01e8bf57b7492b77e3445db51471edcbadda75eMike Lockwood 1293e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood // List of environments that contain this instruction. 1294acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood HUseList<HEnvironment*> env_uses_; 1295e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The environment associated with this instruction. Not null if the instruction 12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // might jump out of the method. 12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HEnvironment* environment_; 12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1300cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Set by the code generator. 13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LocationSummary* locations_; 13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set by the liveness analysis. 130498a4f7e7e12effb78b3d1035e5a670ccbbf5bca1JP Abgrall LiveInterval* live_interval_; 1305ecaa7b41ca49154ceaa9a7504eb0a86b89a96026Christopher Tate 13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set by the liveness analysis, this is the position in a linear 13071cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato // order of blocks where this instruction's live interval start. 1308d2110dbce071a236b6176de344ca797b737542ebJoe Onorato size_t lifetime_position_; 130906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato 13104ababd922eac5931e0222862ff082dc29e012816Joe Onorato const SideEffects side_effects_; 13114a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate 13129c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase // TODO: for primitive types this should be marked as invalid. 131369969e48f2bca9339662dddfacff0bbf6374ed7fDianne Hackborn ReferenceTypeInfo reference_type_info_; 131446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 131532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown friend class GraphChecker; 1316c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown friend class HBasicBlock; 1317a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright friend class HEnvironment; 131846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown friend class HGraph; 131946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown friend class HInstructionList; 13202352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown 13212ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown DISALLOW_COPY_AND_ASSIGN(HInstruction); 132202c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Root}; 132302c8730c1bf19daf48bec8c6995df676a00a73b1Kenny Rootstd::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind& rhs); 132408d5b8fad8d46ccb64db2fdcb4d66972ec87bf48Dianne Hackborn 13256e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haaseclass HInputIterator : public ValueObject { 13266e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase public: 132766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) {} 13289a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey 13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool Done() const { return index_ == instruction_->InputCount(); } 13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HInstruction* Current() const { return instruction_->InputAt(index_); } 13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void Advance() { index_++; } 13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private: 13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HInstruction* instruction_; 13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t index_; 13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DISALLOW_COPY_AND_ASSIGN(HInputIterator); 13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HInstructionIterator : public ValueObject { 13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public: 13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project explicit HInstructionIterator(const HInstructionList& instructions) 134371f2cf116aab893e224056c38ab146bd1538dd3eSteve Block : instruction_(instructions.first_instruction_) { 13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project next_ = Done() ? nullptr : instruction_->GetNext(); 13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool Done() const { return instruction_ == nullptr; } 13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HInstruction* Current() const { return instruction_; } 13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void Advance() { 13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project instruction_ = next_; 13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project next_ = Done() ? nullptr : instruction_->GetNext(); 13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private: 13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HInstruction* instruction_; 13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HInstruction* next_; 13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DISALLOW_COPY_AND_ASSIGN(HInstructionIterator); 13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HBackwardInstructionIterator : public ValueObject { 13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public: 13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project explicit HBackwardInstructionIterator(const HInstructionList& instructions) 13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : instruction_(instructions.last_instruction_) { 13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project next_ = Done() ? nullptr : instruction_->GetPrevious(); 13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool Done() const { return instruction_ == nullptr; } 13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HInstruction* Current() const { return instruction_; } 13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void Advance() { 13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project instruction_ = next_; 13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project next_ = Done() ? nullptr : instruction_->GetPrevious(); 13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private: 13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HInstruction* instruction_; 13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HInstruction* next_; 13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator); 13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// An embedded container with N elements of type T. Used (with partial 13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// specialization for N=0) because embedded arrays cannot have size 0. 13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttemplate<typename T, intptr_t N> 13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass EmbeddedArray { 13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public: 1387 EmbeddedArray() : elements_() {} 1388 1389 intptr_t GetLength() const { return N; } 1390 1391 const T& operator[](intptr_t i) const { 1392 DCHECK_LT(i, GetLength()); 1393 return elements_[i]; 1394 } 1395 1396 T& operator[](intptr_t i) { 1397 DCHECK_LT(i, GetLength()); 1398 return elements_[i]; 1399 } 1400 1401 const T& At(intptr_t i) const { 1402 return (*this)[i]; 1403 } 1404 1405 void SetAt(intptr_t i, const T& val) { 1406 (*this)[i] = val; 1407 } 1408 1409 private: 1410 T elements_[N]; 1411}; 1412 1413template<typename T> 1414class EmbeddedArray<T, 0> { 1415 public: 1416 intptr_t length() const { return 0; } 1417 const T& operator[](intptr_t i) const { 1418 UNUSED(i); 1419 LOG(FATAL) << "Unreachable"; 1420 UNREACHABLE(); 1421 } 1422 T& operator[](intptr_t i) { 1423 UNUSED(i); 1424 LOG(FATAL) << "Unreachable"; 1425 UNREACHABLE(); 1426 } 1427}; 1428 1429template<intptr_t N> 1430class HTemplateInstruction: public HInstruction { 1431 public: 1432 HTemplateInstruction<N>(SideEffects side_effects) 1433 : HInstruction(side_effects), inputs_() {} 1434 virtual ~HTemplateInstruction() {} 1435 1436 size_t InputCount() const OVERRIDE { return N; } 1437 1438 protected: 1439 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_[i]; } 1440 1441 void SetRawInputRecordAt(size_t i, const HUserRecord<HInstruction*>& input) OVERRIDE { 1442 inputs_[i] = input; 1443 } 1444 1445 private: 1446 EmbeddedArray<HUserRecord<HInstruction*>, N> inputs_; 1447 1448 friend class SsaBuilder; 1449}; 1450 1451template<intptr_t N> 1452class HExpression : public HTemplateInstruction<N> { 1453 public: 1454 HExpression<N>(Primitive::Type type, SideEffects side_effects) 1455 : HTemplateInstruction<N>(side_effects), type_(type) {} 1456 virtual ~HExpression() {} 1457 1458 Primitive::Type GetType() const OVERRIDE { return type_; } 1459 1460 protected: 1461 Primitive::Type type_; 1462}; 1463 1464// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow 1465// instruction that branches to the exit block. 1466class HReturnVoid : public HTemplateInstruction<0> { 1467 public: 1468 HReturnVoid() : HTemplateInstruction(SideEffects::None()) {} 1469 1470 bool IsControlFlow() const OVERRIDE { return true; } 1471 1472 DECLARE_INSTRUCTION(ReturnVoid); 1473 1474 private: 1475 DISALLOW_COPY_AND_ASSIGN(HReturnVoid); 1476}; 1477 1478// Represents dex's RETURN opcodes. A HReturn is a control flow 1479// instruction that branches to the exit block. 1480class HReturn : public HTemplateInstruction<1> { 1481 public: 1482 explicit HReturn(HInstruction* value) : HTemplateInstruction(SideEffects::None()) { 1483 SetRawInputAt(0, value); 1484 } 1485 1486 bool IsControlFlow() const OVERRIDE { return true; } 1487 1488 DECLARE_INSTRUCTION(Return); 1489 1490 private: 1491 DISALLOW_COPY_AND_ASSIGN(HReturn); 1492}; 1493 1494// The exit instruction is the only instruction of the exit block. 1495// Instructions aborting the method (HThrow and HReturn) must branch to the 1496// exit block. 1497class HExit : public HTemplateInstruction<0> { 1498 public: 1499 HExit() : HTemplateInstruction(SideEffects::None()) {} 1500 1501 bool IsControlFlow() const OVERRIDE { return true; } 1502 1503 DECLARE_INSTRUCTION(Exit); 1504 1505 private: 1506 DISALLOW_COPY_AND_ASSIGN(HExit); 1507}; 1508 1509// Jumps from one block to another. 1510class HGoto : public HTemplateInstruction<0> { 1511 public: 1512 HGoto() : HTemplateInstruction(SideEffects::None()) {} 1513 1514 bool IsControlFlow() const OVERRIDE { return true; } 1515 1516 HBasicBlock* GetSuccessor() const { 1517 return GetBlock()->GetSuccessors().Get(0); 1518 } 1519 1520 DECLARE_INSTRUCTION(Goto); 1521 1522 private: 1523 DISALLOW_COPY_AND_ASSIGN(HGoto); 1524}; 1525 1526 1527// Conditional branch. A block ending with an HIf instruction must have 1528// two successors. 1529class HIf : public HTemplateInstruction<1> { 1530 public: 1531 explicit HIf(HInstruction* input) : HTemplateInstruction(SideEffects::None()) { 1532 SetRawInputAt(0, input); 1533 } 1534 1535 bool IsControlFlow() const OVERRIDE { return true; } 1536 1537 HBasicBlock* IfTrueSuccessor() const { 1538 return GetBlock()->GetSuccessors().Get(0); 1539 } 1540 1541 HBasicBlock* IfFalseSuccessor() const { 1542 return GetBlock()->GetSuccessors().Get(1); 1543 } 1544 1545 DECLARE_INSTRUCTION(If); 1546 1547 virtual bool IsIfInstruction() const { return true; } 1548 1549 private: 1550 DISALLOW_COPY_AND_ASSIGN(HIf); 1551}; 1552 1553class HUnaryOperation : public HExpression<1> { 1554 public: 1555 HUnaryOperation(Primitive::Type result_type, HInstruction* input) 1556 : HExpression(result_type, SideEffects::None()) { 1557 SetRawInputAt(0, input); 1558 } 1559 1560 HInstruction* GetInput() const { return InputAt(0); } 1561 Primitive::Type GetResultType() const { return GetType(); } 1562 1563 bool CanBeMoved() const OVERRIDE { return true; } 1564 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 1565 UNUSED(other); 1566 return true; 1567 } 1568 1569 // Try to statically evaluate `operation` and return a HConstant 1570 // containing the result of this evaluation. If `operation` cannot 1571 // be evaluated as a constant, return nullptr. 1572 HConstant* TryStaticEvaluation() const; 1573 1574 // Apply this operation to `x`. 1575 virtual int32_t Evaluate(int32_t x) const = 0; 1576 virtual int64_t Evaluate(int64_t x) const = 0; 1577 1578 DECLARE_INSTRUCTION(UnaryOperation); 1579 1580 private: 1581 DISALLOW_COPY_AND_ASSIGN(HUnaryOperation); 1582}; 1583 1584class HBinaryOperation : public HExpression<2> { 1585 public: 1586 HBinaryOperation(Primitive::Type result_type, 1587 HInstruction* left, 1588 HInstruction* right) : HExpression(result_type, SideEffects::None()) { 1589 SetRawInputAt(0, left); 1590 SetRawInputAt(1, right); 1591 } 1592 1593 HInstruction* GetLeft() const { return InputAt(0); } 1594 HInstruction* GetRight() const { return InputAt(1); } 1595 Primitive::Type GetResultType() const { return GetType(); } 1596 1597 virtual bool IsCommutative() const { return false; } 1598 1599 // Put constant on the right. 1600 // Returns whether order is changed. 1601 bool OrderInputsWithConstantOnTheRight() { 1602 HInstruction* left = InputAt(0); 1603 HInstruction* right = InputAt(1); 1604 if (left->IsConstant() && !right->IsConstant()) { 1605 ReplaceInput(right, 0); 1606 ReplaceInput(left, 1); 1607 return true; 1608 } 1609 return false; 1610 } 1611 1612 // Order inputs by instruction id, but favor constant on the right side. 1613 // This helps GVN for commutative ops. 1614 void OrderInputs() { 1615 DCHECK(IsCommutative()); 1616 HInstruction* left = InputAt(0); 1617 HInstruction* right = InputAt(1); 1618 if (left == right || (!left->IsConstant() && right->IsConstant())) { 1619 return; 1620 } 1621 if (OrderInputsWithConstantOnTheRight()) { 1622 return; 1623 } 1624 // Order according to instruction id. 1625 if (left->GetId() > right->GetId()) { 1626 ReplaceInput(right, 0); 1627 ReplaceInput(left, 1); 1628 } 1629 } 1630 1631 bool CanBeMoved() const OVERRIDE { return true; } 1632 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 1633 UNUSED(other); 1634 return true; 1635 } 1636 1637 // Try to statically evaluate `operation` and return a HConstant 1638 // containing the result of this evaluation. If `operation` cannot 1639 // be evaluated as a constant, return nullptr. 1640 HConstant* TryStaticEvaluation() const; 1641 1642 // Apply this operation to `x` and `y`. 1643 virtual int32_t Evaluate(int32_t x, int32_t y) const = 0; 1644 virtual int64_t Evaluate(int64_t x, int64_t y) const = 0; 1645 1646 // Returns an input that can legally be used as the right input and is 1647 // constant, or nullptr. 1648 HConstant* GetConstantRight() const; 1649 1650 // If `GetConstantRight()` returns one of the input, this returns the other 1651 // one. Otherwise it returns nullptr. 1652 HInstruction* GetLeastConstantLeft() const; 1653 1654 DECLARE_INSTRUCTION(BinaryOperation); 1655 1656 private: 1657 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation); 1658}; 1659 1660class HCondition : public HBinaryOperation { 1661 public: 1662 HCondition(HInstruction* first, HInstruction* second) 1663 : HBinaryOperation(Primitive::kPrimBoolean, first, second), 1664 needs_materialization_(true) {} 1665 1666 bool NeedsMaterialization() const { return needs_materialization_; } 1667 void ClearNeedsMaterialization() { needs_materialization_ = false; } 1668 1669 // For code generation purposes, returns whether this instruction is just before 1670 // `if_`, and disregard moves in between. 1671 bool IsBeforeWhenDisregardMoves(HIf* if_) const; 1672 1673 DECLARE_INSTRUCTION(Condition); 1674 1675 virtual IfCondition GetCondition() const = 0; 1676 1677 private: 1678 // For register allocation purposes, returns whether this instruction needs to be 1679 // materialized (that is, not just be in the processor flags). 1680 bool needs_materialization_; 1681 1682 DISALLOW_COPY_AND_ASSIGN(HCondition); 1683}; 1684 1685// Instruction to check if two inputs are equal to each other. 1686class HEqual : public HCondition { 1687 public: 1688 HEqual(HInstruction* first, HInstruction* second) 1689 : HCondition(first, second) {} 1690 1691 bool IsCommutative() const OVERRIDE { return true; } 1692 1693 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 1694 return x == y ? 1 : 0; 1695 } 1696 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 1697 return x == y ? 1 : 0; 1698 } 1699 1700 DECLARE_INSTRUCTION(Equal); 1701 1702 IfCondition GetCondition() const OVERRIDE { 1703 return kCondEQ; 1704 } 1705 1706 private: 1707 DISALLOW_COPY_AND_ASSIGN(HEqual); 1708}; 1709 1710class HNotEqual : public HCondition { 1711 public: 1712 HNotEqual(HInstruction* first, HInstruction* second) 1713 : HCondition(first, second) {} 1714 1715 bool IsCommutative() const OVERRIDE { return true; } 1716 1717 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 1718 return x != y ? 1 : 0; 1719 } 1720 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 1721 return x != y ? 1 : 0; 1722 } 1723 1724 DECLARE_INSTRUCTION(NotEqual); 1725 1726 IfCondition GetCondition() const OVERRIDE { 1727 return kCondNE; 1728 } 1729 1730 private: 1731 DISALLOW_COPY_AND_ASSIGN(HNotEqual); 1732}; 1733 1734class HLessThan : public HCondition { 1735 public: 1736 HLessThan(HInstruction* first, HInstruction* second) 1737 : HCondition(first, second) {} 1738 1739 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 1740 return x < y ? 1 : 0; 1741 } 1742 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 1743 return x < y ? 1 : 0; 1744 } 1745 1746 DECLARE_INSTRUCTION(LessThan); 1747 1748 IfCondition GetCondition() const OVERRIDE { 1749 return kCondLT; 1750 } 1751 1752 private: 1753 DISALLOW_COPY_AND_ASSIGN(HLessThan); 1754}; 1755 1756class HLessThanOrEqual : public HCondition { 1757 public: 1758 HLessThanOrEqual(HInstruction* first, HInstruction* second) 1759 : HCondition(first, second) {} 1760 1761 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 1762 return x <= y ? 1 : 0; 1763 } 1764 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 1765 return x <= y ? 1 : 0; 1766 } 1767 1768 DECLARE_INSTRUCTION(LessThanOrEqual); 1769 1770 IfCondition GetCondition() const OVERRIDE { 1771 return kCondLE; 1772 } 1773 1774 private: 1775 DISALLOW_COPY_AND_ASSIGN(HLessThanOrEqual); 1776}; 1777 1778class HGreaterThan : public HCondition { 1779 public: 1780 HGreaterThan(HInstruction* first, HInstruction* second) 1781 : HCondition(first, second) {} 1782 1783 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 1784 return x > y ? 1 : 0; 1785 } 1786 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 1787 return x > y ? 1 : 0; 1788 } 1789 1790 DECLARE_INSTRUCTION(GreaterThan); 1791 1792 IfCondition GetCondition() const OVERRIDE { 1793 return kCondGT; 1794 } 1795 1796 private: 1797 DISALLOW_COPY_AND_ASSIGN(HGreaterThan); 1798}; 1799 1800class HGreaterThanOrEqual : public HCondition { 1801 public: 1802 HGreaterThanOrEqual(HInstruction* first, HInstruction* second) 1803 : HCondition(first, second) {} 1804 1805 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 1806 return x >= y ? 1 : 0; 1807 } 1808 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 1809 return x >= y ? 1 : 0; 1810 } 1811 1812 DECLARE_INSTRUCTION(GreaterThanOrEqual); 1813 1814 IfCondition GetCondition() const OVERRIDE { 1815 return kCondGE; 1816 } 1817 1818 private: 1819 DISALLOW_COPY_AND_ASSIGN(HGreaterThanOrEqual); 1820}; 1821 1822 1823// Instruction to check how two inputs compare to each other. 1824// Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1. 1825class HCompare : public HBinaryOperation { 1826 public: 1827 // The bias applies for floating point operations and indicates how NaN 1828 // comparisons are treated: 1829 enum Bias { 1830 kNoBias, // bias is not applicable (i.e. for long operation) 1831 kGtBias, // return 1 for NaN comparisons 1832 kLtBias, // return -1 for NaN comparisons 1833 }; 1834 1835 HCompare(Primitive::Type type, HInstruction* first, HInstruction* second, Bias bias) 1836 : HBinaryOperation(Primitive::kPrimInt, first, second), bias_(bias) { 1837 DCHECK_EQ(type, first->GetType()); 1838 DCHECK_EQ(type, second->GetType()); 1839 } 1840 1841 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 1842 return 1843 x == y ? 0 : 1844 x > y ? 1 : 1845 -1; 1846 } 1847 1848 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 1849 return 1850 x == y ? 0 : 1851 x > y ? 1 : 1852 -1; 1853 } 1854 1855 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 1856 return bias_ == other->AsCompare()->bias_; 1857 } 1858 1859 bool IsGtBias() { return bias_ == kGtBias; } 1860 1861 DECLARE_INSTRUCTION(Compare); 1862 1863 private: 1864 const Bias bias_; 1865 1866 DISALLOW_COPY_AND_ASSIGN(HCompare); 1867}; 1868 1869// A local in the graph. Corresponds to a Dex register. 1870class HLocal : public HTemplateInstruction<0> { 1871 public: 1872 explicit HLocal(uint16_t reg_number) 1873 : HTemplateInstruction(SideEffects::None()), reg_number_(reg_number) {} 1874 1875 DECLARE_INSTRUCTION(Local); 1876 1877 uint16_t GetRegNumber() const { return reg_number_; } 1878 1879 private: 1880 // The Dex register number. 1881 const uint16_t reg_number_; 1882 1883 DISALLOW_COPY_AND_ASSIGN(HLocal); 1884}; 1885 1886// Load a given local. The local is an input of this instruction. 1887class HLoadLocal : public HExpression<1> { 1888 public: 1889 HLoadLocal(HLocal* local, Primitive::Type type) 1890 : HExpression(type, SideEffects::None()) { 1891 SetRawInputAt(0, local); 1892 } 1893 1894 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); } 1895 1896 DECLARE_INSTRUCTION(LoadLocal); 1897 1898 private: 1899 DISALLOW_COPY_AND_ASSIGN(HLoadLocal); 1900}; 1901 1902// Store a value in a given local. This instruction has two inputs: the value 1903// and the local. 1904class HStoreLocal : public HTemplateInstruction<2> { 1905 public: 1906 HStoreLocal(HLocal* local, HInstruction* value) : HTemplateInstruction(SideEffects::None()) { 1907 SetRawInputAt(0, local); 1908 SetRawInputAt(1, value); 1909 } 1910 1911 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); } 1912 1913 DECLARE_INSTRUCTION(StoreLocal); 1914 1915 private: 1916 DISALLOW_COPY_AND_ASSIGN(HStoreLocal); 1917}; 1918 1919class HConstant : public HExpression<0> { 1920 public: 1921 explicit HConstant(Primitive::Type type) : HExpression(type, SideEffects::None()) {} 1922 1923 bool CanBeMoved() const OVERRIDE { return true; } 1924 1925 virtual bool IsMinusOne() const { return false; } 1926 virtual bool IsZero() const { return false; } 1927 virtual bool IsOne() const { return false; } 1928 1929 DECLARE_INSTRUCTION(Constant); 1930 1931 private: 1932 DISALLOW_COPY_AND_ASSIGN(HConstant); 1933}; 1934 1935class HFloatConstant : public HConstant { 1936 public: 1937 float GetValue() const { return value_; } 1938 1939 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 1940 return bit_cast<uint32_t, float>(other->AsFloatConstant()->value_) == 1941 bit_cast<uint32_t, float>(value_); 1942 } 1943 1944 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); } 1945 1946 bool IsMinusOne() const OVERRIDE { 1947 return bit_cast<uint32_t, float>(AsFloatConstant()->GetValue()) == 1948 bit_cast<uint32_t, float>((-1.0f)); 1949 } 1950 bool IsZero() const OVERRIDE { 1951 return AsFloatConstant()->GetValue() == 0.0f; 1952 } 1953 bool IsOne() const OVERRIDE { 1954 return bit_cast<uint32_t, float>(AsFloatConstant()->GetValue()) == 1955 bit_cast<uint32_t, float>(1.0f); 1956 } 1957 1958 DECLARE_INSTRUCTION(FloatConstant); 1959 1960 private: 1961 explicit HFloatConstant(float value) : HConstant(Primitive::kPrimFloat), value_(value) {} 1962 1963 const float value_; 1964 1965 // Only the SsaBuilder can currently create floating-point constants. If we 1966 // ever need to create them later in the pipeline, we will have to handle them 1967 // the same way as integral constants. 1968 friend class SsaBuilder; 1969 DISALLOW_COPY_AND_ASSIGN(HFloatConstant); 1970}; 1971 1972class HDoubleConstant : public HConstant { 1973 public: 1974 double GetValue() const { return value_; } 1975 1976 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 1977 return bit_cast<uint64_t, double>(other->AsDoubleConstant()->value_) == 1978 bit_cast<uint64_t, double>(value_); 1979 } 1980 1981 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); } 1982 1983 bool IsMinusOne() const OVERRIDE { 1984 return bit_cast<uint64_t, double>(AsDoubleConstant()->GetValue()) == 1985 bit_cast<uint64_t, double>((-1.0)); 1986 } 1987 bool IsZero() const OVERRIDE { 1988 return AsDoubleConstant()->GetValue() == 0.0; 1989 } 1990 bool IsOne() const OVERRIDE { 1991 return bit_cast<uint64_t, double>(AsDoubleConstant()->GetValue()) == 1992 bit_cast<uint64_t, double>(1.0); 1993 } 1994 1995 DECLARE_INSTRUCTION(DoubleConstant); 1996 1997 private: 1998 explicit HDoubleConstant(double value) : HConstant(Primitive::kPrimDouble), value_(value) {} 1999 2000 const double value_; 2001 2002 // Only the SsaBuilder can currently create floating-point constants. If we 2003 // ever need to create them later in the pipeline, we will have to handle them 2004 // the same way as integral constants. 2005 friend class SsaBuilder; 2006 DISALLOW_COPY_AND_ASSIGN(HDoubleConstant); 2007}; 2008 2009class HNullConstant : public HConstant { 2010 public: 2011 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { 2012 return true; 2013 } 2014 2015 size_t ComputeHashCode() const OVERRIDE { return 0; } 2016 2017 bool ActAsNullConstant() const OVERRIDE { return true; } 2018 2019 DECLARE_INSTRUCTION(NullConstant); 2020 2021 private: 2022 HNullConstant() : HConstant(Primitive::kPrimNot) {} 2023 2024 friend class HGraph; 2025 DISALLOW_COPY_AND_ASSIGN(HNullConstant); 2026}; 2027 2028// Constants of the type int. Those can be from Dex instructions, or 2029// synthesized (for example with the if-eqz instruction). 2030class HIntConstant : public HConstant { 2031 public: 2032 int32_t GetValue() const { return value_; } 2033 2034 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 2035 return other->AsIntConstant()->value_ == value_; 2036 } 2037 2038 size_t ComputeHashCode() const OVERRIDE { return GetValue(); } 2039 2040 // TODO: Null is represented by the `0` constant. In most cases we replace it 2041 // with a HNullConstant but we don't do it when comparing (a != null). This 2042 // method is an workaround until we fix the above. 2043 bool ActAsNullConstant() const OVERRIDE { return value_ == 0; } 2044 2045 bool IsMinusOne() const OVERRIDE { return GetValue() == -1; } 2046 bool IsZero() const OVERRIDE { return GetValue() == 0; } 2047 bool IsOne() const OVERRIDE { return GetValue() == 1; } 2048 2049 DECLARE_INSTRUCTION(IntConstant); 2050 2051 private: 2052 explicit HIntConstant(int32_t value) : HConstant(Primitive::kPrimInt), value_(value) {} 2053 2054 const int32_t value_; 2055 2056 friend class HGraph; 2057 ART_FRIEND_TEST(GraphTest, InsertInstructionBefore); 2058 ART_FRIEND_TEST(ParallelMoveTest, ConstantLast); 2059 DISALLOW_COPY_AND_ASSIGN(HIntConstant); 2060}; 2061 2062class HLongConstant : public HConstant { 2063 public: 2064 int64_t GetValue() const { return value_; } 2065 2066 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 2067 return other->AsLongConstant()->value_ == value_; 2068 } 2069 2070 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); } 2071 2072 bool IsMinusOne() const OVERRIDE { return GetValue() == -1; } 2073 bool IsZero() const OVERRIDE { return GetValue() == 0; } 2074 bool IsOne() const OVERRIDE { return GetValue() == 1; } 2075 2076 DECLARE_INSTRUCTION(LongConstant); 2077 2078 private: 2079 explicit HLongConstant(int64_t value) : HConstant(Primitive::kPrimLong), value_(value) {} 2080 2081 const int64_t value_; 2082 2083 friend class HGraph; 2084 DISALLOW_COPY_AND_ASSIGN(HLongConstant); 2085}; 2086 2087enum class Intrinsics { 2088#define OPTIMIZING_INTRINSICS(Name, IsStatic) k ## Name, 2089#include "intrinsics_list.h" 2090 kNone, 2091 INTRINSICS_LIST(OPTIMIZING_INTRINSICS) 2092#undef INTRINSICS_LIST 2093#undef OPTIMIZING_INTRINSICS 2094}; 2095std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic); 2096 2097class HInvoke : public HInstruction { 2098 public: 2099 size_t InputCount() const OVERRIDE { return inputs_.Size(); } 2100 2101 // Runtime needs to walk the stack, so Dex -> Dex calls need to 2102 // know their environment. 2103 bool NeedsEnvironment() const OVERRIDE { return true; } 2104 2105 void SetArgumentAt(size_t index, HInstruction* argument) { 2106 SetRawInputAt(index, argument); 2107 } 2108 2109 Primitive::Type GetType() const OVERRIDE { return return_type_; } 2110 2111 uint32_t GetDexPc() const { return dex_pc_; } 2112 2113 uint32_t GetDexMethodIndex() const { return dex_method_index_; } 2114 2115 Intrinsics GetIntrinsic() { 2116 return intrinsic_; 2117 } 2118 2119 void SetIntrinsic(Intrinsics intrinsic) { 2120 intrinsic_ = intrinsic; 2121 } 2122 2123 DECLARE_INSTRUCTION(Invoke); 2124 2125 protected: 2126 HInvoke(ArenaAllocator* arena, 2127 uint32_t number_of_arguments, 2128 Primitive::Type return_type, 2129 uint32_t dex_pc, 2130 uint32_t dex_method_index) 2131 : HInstruction(SideEffects::All()), 2132 inputs_(arena, number_of_arguments), 2133 return_type_(return_type), 2134 dex_pc_(dex_pc), 2135 dex_method_index_(dex_method_index), 2136 intrinsic_(Intrinsics::kNone) { 2137 inputs_.SetSize(number_of_arguments); 2138 } 2139 2140 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_.Get(i); } 2141 void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) OVERRIDE { 2142 inputs_.Put(index, input); 2143 } 2144 2145 GrowableArray<HUserRecord<HInstruction*> > inputs_; 2146 const Primitive::Type return_type_; 2147 const uint32_t dex_pc_; 2148 const uint32_t dex_method_index_; 2149 Intrinsics intrinsic_; 2150 2151 private: 2152 DISALLOW_COPY_AND_ASSIGN(HInvoke); 2153}; 2154 2155class HInvokeStaticOrDirect : public HInvoke { 2156 public: 2157 HInvokeStaticOrDirect(ArenaAllocator* arena, 2158 uint32_t number_of_arguments, 2159 Primitive::Type return_type, 2160 uint32_t dex_pc, 2161 uint32_t dex_method_index, 2162 bool is_recursive, 2163 InvokeType original_invoke_type, 2164 InvokeType invoke_type) 2165 : HInvoke(arena, number_of_arguments, return_type, dex_pc, dex_method_index), 2166 original_invoke_type_(original_invoke_type), 2167 invoke_type_(invoke_type), 2168 is_recursive_(is_recursive) {} 2169 2170 bool CanDoImplicitNullCheck() const OVERRIDE { 2171 // We access the method via the dex cache so we can't do an implicit null check. 2172 // TODO: for intrinsics we can generate implicit null checks. 2173 return false; 2174 } 2175 2176 InvokeType GetOriginalInvokeType() const { return original_invoke_type_; } 2177 InvokeType GetInvokeType() const { return invoke_type_; } 2178 bool IsRecursive() const { return is_recursive_; } 2179 bool NeedsDexCache() const OVERRIDE { return !IsRecursive(); } 2180 2181 DECLARE_INSTRUCTION(InvokeStaticOrDirect); 2182 2183 private: 2184 const InvokeType original_invoke_type_; 2185 const InvokeType invoke_type_; 2186 const bool is_recursive_; 2187 2188 DISALLOW_COPY_AND_ASSIGN(HInvokeStaticOrDirect); 2189}; 2190 2191class HInvokeVirtual : public HInvoke { 2192 public: 2193 HInvokeVirtual(ArenaAllocator* arena, 2194 uint32_t number_of_arguments, 2195 Primitive::Type return_type, 2196 uint32_t dex_pc, 2197 uint32_t dex_method_index, 2198 uint32_t vtable_index) 2199 : HInvoke(arena, number_of_arguments, return_type, dex_pc, dex_method_index), 2200 vtable_index_(vtable_index) {} 2201 2202 bool CanDoImplicitNullCheck() const OVERRIDE { 2203 // TODO: Add implicit null checks in intrinsics. 2204 return !GetLocations()->Intrinsified(); 2205 } 2206 2207 uint32_t GetVTableIndex() const { return vtable_index_; } 2208 2209 DECLARE_INSTRUCTION(InvokeVirtual); 2210 2211 private: 2212 const uint32_t vtable_index_; 2213 2214 DISALLOW_COPY_AND_ASSIGN(HInvokeVirtual); 2215}; 2216 2217class HInvokeInterface : public HInvoke { 2218 public: 2219 HInvokeInterface(ArenaAllocator* arena, 2220 uint32_t number_of_arguments, 2221 Primitive::Type return_type, 2222 uint32_t dex_pc, 2223 uint32_t dex_method_index, 2224 uint32_t imt_index) 2225 : HInvoke(arena, number_of_arguments, return_type, dex_pc, dex_method_index), 2226 imt_index_(imt_index) {} 2227 2228 bool CanDoImplicitNullCheck() const OVERRIDE { 2229 // TODO: Add implicit null checks in intrinsics. 2230 return !GetLocations()->Intrinsified(); 2231 } 2232 2233 uint32_t GetImtIndex() const { return imt_index_; } 2234 uint32_t GetDexMethodIndex() const { return dex_method_index_; } 2235 2236 DECLARE_INSTRUCTION(InvokeInterface); 2237 2238 private: 2239 const uint32_t imt_index_; 2240 2241 DISALLOW_COPY_AND_ASSIGN(HInvokeInterface); 2242}; 2243 2244class HNewInstance : public HExpression<0> { 2245 public: 2246 HNewInstance(uint32_t dex_pc, uint16_t type_index, QuickEntrypointEnum entrypoint) 2247 : HExpression(Primitive::kPrimNot, SideEffects::None()), 2248 dex_pc_(dex_pc), 2249 type_index_(type_index), 2250 entrypoint_(entrypoint) {} 2251 2252 uint32_t GetDexPc() const { return dex_pc_; } 2253 uint16_t GetTypeIndex() const { return type_index_; } 2254 2255 // Calls runtime so needs an environment. 2256 bool NeedsEnvironment() const OVERRIDE { return true; } 2257 // It may throw when called on: 2258 // - interfaces 2259 // - abstract/innaccessible/unknown classes 2260 // TODO: optimize when possible. 2261 bool CanThrow() const OVERRIDE { return true; } 2262 2263 bool CanBeNull() const OVERRIDE { return false; } 2264 2265 QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; } 2266 2267 DECLARE_INSTRUCTION(NewInstance); 2268 2269 private: 2270 const uint32_t dex_pc_; 2271 const uint16_t type_index_; 2272 const QuickEntrypointEnum entrypoint_; 2273 2274 DISALLOW_COPY_AND_ASSIGN(HNewInstance); 2275}; 2276 2277class HNeg : public HUnaryOperation { 2278 public: 2279 explicit HNeg(Primitive::Type result_type, HInstruction* input) 2280 : HUnaryOperation(result_type, input) {} 2281 2282 int32_t Evaluate(int32_t x) const OVERRIDE { return -x; } 2283 int64_t Evaluate(int64_t x) const OVERRIDE { return -x; } 2284 2285 DECLARE_INSTRUCTION(Neg); 2286 2287 private: 2288 DISALLOW_COPY_AND_ASSIGN(HNeg); 2289}; 2290 2291class HNewArray : public HExpression<1> { 2292 public: 2293 HNewArray(HInstruction* length, 2294 uint32_t dex_pc, 2295 uint16_t type_index, 2296 QuickEntrypointEnum entrypoint) 2297 : HExpression(Primitive::kPrimNot, SideEffects::None()), 2298 dex_pc_(dex_pc), 2299 type_index_(type_index), 2300 entrypoint_(entrypoint) { 2301 SetRawInputAt(0, length); 2302 } 2303 2304 uint32_t GetDexPc() const { return dex_pc_; } 2305 uint16_t GetTypeIndex() const { return type_index_; } 2306 2307 // Calls runtime so needs an environment. 2308 bool NeedsEnvironment() const OVERRIDE { return true; } 2309 2310 bool CanBeNull() const OVERRIDE { return false; } 2311 2312 QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; } 2313 2314 DECLARE_INSTRUCTION(NewArray); 2315 2316 private: 2317 const uint32_t dex_pc_; 2318 const uint16_t type_index_; 2319 const QuickEntrypointEnum entrypoint_; 2320 2321 DISALLOW_COPY_AND_ASSIGN(HNewArray); 2322}; 2323 2324class HAdd : public HBinaryOperation { 2325 public: 2326 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2327 : HBinaryOperation(result_type, left, right) {} 2328 2329 bool IsCommutative() const OVERRIDE { return true; } 2330 2331 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 2332 return x + y; 2333 } 2334 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 2335 return x + y; 2336 } 2337 2338 DECLARE_INSTRUCTION(Add); 2339 2340 private: 2341 DISALLOW_COPY_AND_ASSIGN(HAdd); 2342}; 2343 2344class HSub : public HBinaryOperation { 2345 public: 2346 HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2347 : HBinaryOperation(result_type, left, right) {} 2348 2349 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 2350 return x - y; 2351 } 2352 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 2353 return x - y; 2354 } 2355 2356 DECLARE_INSTRUCTION(Sub); 2357 2358 private: 2359 DISALLOW_COPY_AND_ASSIGN(HSub); 2360}; 2361 2362class HMul : public HBinaryOperation { 2363 public: 2364 HMul(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2365 : HBinaryOperation(result_type, left, right) {} 2366 2367 bool IsCommutative() const OVERRIDE { return true; } 2368 2369 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x * y; } 2370 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x * y; } 2371 2372 DECLARE_INSTRUCTION(Mul); 2373 2374 private: 2375 DISALLOW_COPY_AND_ASSIGN(HMul); 2376}; 2377 2378class HDiv : public HBinaryOperation { 2379 public: 2380 HDiv(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc) 2381 : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {} 2382 2383 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 2384 // Our graph structure ensures we never have 0 for `y` during constant folding. 2385 DCHECK_NE(y, 0); 2386 // Special case -1 to avoid getting a SIGFPE on x86(_64). 2387 return (y == -1) ? -x : x / y; 2388 } 2389 2390 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 2391 DCHECK_NE(y, 0); 2392 // Special case -1 to avoid getting a SIGFPE on x86(_64). 2393 return (y == -1) ? -x : x / y; 2394 } 2395 2396 uint32_t GetDexPc() const { return dex_pc_; } 2397 2398 DECLARE_INSTRUCTION(Div); 2399 2400 private: 2401 const uint32_t dex_pc_; 2402 2403 DISALLOW_COPY_AND_ASSIGN(HDiv); 2404}; 2405 2406class HRem : public HBinaryOperation { 2407 public: 2408 HRem(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc) 2409 : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {} 2410 2411 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 2412 DCHECK_NE(y, 0); 2413 // Special case -1 to avoid getting a SIGFPE on x86(_64). 2414 return (y == -1) ? 0 : x % y; 2415 } 2416 2417 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 2418 DCHECK_NE(y, 0); 2419 // Special case -1 to avoid getting a SIGFPE on x86(_64). 2420 return (y == -1) ? 0 : x % y; 2421 } 2422 2423 uint32_t GetDexPc() const { return dex_pc_; } 2424 2425 DECLARE_INSTRUCTION(Rem); 2426 2427 private: 2428 const uint32_t dex_pc_; 2429 2430 DISALLOW_COPY_AND_ASSIGN(HRem); 2431}; 2432 2433class HDivZeroCheck : public HExpression<1> { 2434 public: 2435 HDivZeroCheck(HInstruction* value, uint32_t dex_pc) 2436 : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) { 2437 SetRawInputAt(0, value); 2438 } 2439 2440 bool CanBeMoved() const OVERRIDE { return true; } 2441 2442 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 2443 UNUSED(other); 2444 return true; 2445 } 2446 2447 bool NeedsEnvironment() const OVERRIDE { return true; } 2448 bool CanThrow() const OVERRIDE { return true; } 2449 2450 uint32_t GetDexPc() const { return dex_pc_; } 2451 2452 DECLARE_INSTRUCTION(DivZeroCheck); 2453 2454 private: 2455 const uint32_t dex_pc_; 2456 2457 DISALLOW_COPY_AND_ASSIGN(HDivZeroCheck); 2458}; 2459 2460class HShl : public HBinaryOperation { 2461 public: 2462 HShl(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2463 : HBinaryOperation(result_type, left, right) {} 2464 2465 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x << (y & kMaxIntShiftValue); } 2466 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x << (y & kMaxLongShiftValue); } 2467 2468 DECLARE_INSTRUCTION(Shl); 2469 2470 private: 2471 DISALLOW_COPY_AND_ASSIGN(HShl); 2472}; 2473 2474class HShr : public HBinaryOperation { 2475 public: 2476 HShr(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2477 : HBinaryOperation(result_type, left, right) {} 2478 2479 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x >> (y & kMaxIntShiftValue); } 2480 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x >> (y & kMaxLongShiftValue); } 2481 2482 DECLARE_INSTRUCTION(Shr); 2483 2484 private: 2485 DISALLOW_COPY_AND_ASSIGN(HShr); 2486}; 2487 2488class HUShr : public HBinaryOperation { 2489 public: 2490 HUShr(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2491 : HBinaryOperation(result_type, left, right) {} 2492 2493 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { 2494 uint32_t ux = static_cast<uint32_t>(x); 2495 uint32_t uy = static_cast<uint32_t>(y) & kMaxIntShiftValue; 2496 return static_cast<int32_t>(ux >> uy); 2497 } 2498 2499 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { 2500 uint64_t ux = static_cast<uint64_t>(x); 2501 uint64_t uy = static_cast<uint64_t>(y) & kMaxLongShiftValue; 2502 return static_cast<int64_t>(ux >> uy); 2503 } 2504 2505 DECLARE_INSTRUCTION(UShr); 2506 2507 private: 2508 DISALLOW_COPY_AND_ASSIGN(HUShr); 2509}; 2510 2511class HAnd : public HBinaryOperation { 2512 public: 2513 HAnd(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2514 : HBinaryOperation(result_type, left, right) {} 2515 2516 bool IsCommutative() const OVERRIDE { return true; } 2517 2518 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x & y; } 2519 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x & y; } 2520 2521 DECLARE_INSTRUCTION(And); 2522 2523 private: 2524 DISALLOW_COPY_AND_ASSIGN(HAnd); 2525}; 2526 2527class HOr : public HBinaryOperation { 2528 public: 2529 HOr(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2530 : HBinaryOperation(result_type, left, right) {} 2531 2532 bool IsCommutative() const OVERRIDE { return true; } 2533 2534 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x | y; } 2535 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x | y; } 2536 2537 DECLARE_INSTRUCTION(Or); 2538 2539 private: 2540 DISALLOW_COPY_AND_ASSIGN(HOr); 2541}; 2542 2543class HXor : public HBinaryOperation { 2544 public: 2545 HXor(Primitive::Type result_type, HInstruction* left, HInstruction* right) 2546 : HBinaryOperation(result_type, left, right) {} 2547 2548 bool IsCommutative() const OVERRIDE { return true; } 2549 2550 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x ^ y; } 2551 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x ^ y; } 2552 2553 DECLARE_INSTRUCTION(Xor); 2554 2555 private: 2556 DISALLOW_COPY_AND_ASSIGN(HXor); 2557}; 2558 2559// The value of a parameter in this method. Its location depends on 2560// the calling convention. 2561class HParameterValue : public HExpression<0> { 2562 public: 2563 HParameterValue(uint8_t index, Primitive::Type parameter_type, bool is_this = false) 2564 : HExpression(parameter_type, SideEffects::None()), index_(index), is_this_(is_this) {} 2565 2566 uint8_t GetIndex() const { return index_; } 2567 2568 bool CanBeNull() const OVERRIDE { return !is_this_; } 2569 2570 DECLARE_INSTRUCTION(ParameterValue); 2571 2572 private: 2573 // The index of this parameter in the parameters list. Must be less 2574 // than HGraph::number_of_in_vregs_. 2575 const uint8_t index_; 2576 2577 // Whether or not the parameter value corresponds to 'this' argument. 2578 const bool is_this_; 2579 2580 DISALLOW_COPY_AND_ASSIGN(HParameterValue); 2581}; 2582 2583class HNot : public HUnaryOperation { 2584 public: 2585 explicit HNot(Primitive::Type result_type, HInstruction* input) 2586 : HUnaryOperation(result_type, input) {} 2587 2588 bool CanBeMoved() const OVERRIDE { return true; } 2589 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 2590 UNUSED(other); 2591 return true; 2592 } 2593 2594 int32_t Evaluate(int32_t x) const OVERRIDE { return ~x; } 2595 int64_t Evaluate(int64_t x) const OVERRIDE { return ~x; } 2596 2597 DECLARE_INSTRUCTION(Not); 2598 2599 private: 2600 DISALLOW_COPY_AND_ASSIGN(HNot); 2601}; 2602 2603class HTypeConversion : public HExpression<1> { 2604 public: 2605 // Instantiate a type conversion of `input` to `result_type`. 2606 HTypeConversion(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc) 2607 : HExpression(result_type, SideEffects::None()), dex_pc_(dex_pc) { 2608 SetRawInputAt(0, input); 2609 DCHECK_NE(input->GetType(), result_type); 2610 } 2611 2612 HInstruction* GetInput() const { return InputAt(0); } 2613 Primitive::Type GetInputType() const { return GetInput()->GetType(); } 2614 Primitive::Type GetResultType() const { return GetType(); } 2615 2616 // Required by the x86 and ARM code generators when producing calls 2617 // to the runtime. 2618 uint32_t GetDexPc() const { return dex_pc_; } 2619 2620 bool CanBeMoved() const OVERRIDE { return true; } 2621 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { return true; } 2622 2623 DECLARE_INSTRUCTION(TypeConversion); 2624 2625 private: 2626 const uint32_t dex_pc_; 2627 2628 DISALLOW_COPY_AND_ASSIGN(HTypeConversion); 2629}; 2630 2631static constexpr uint32_t kNoRegNumber = -1; 2632 2633class HPhi : public HInstruction { 2634 public: 2635 HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type) 2636 : HInstruction(SideEffects::None()), 2637 inputs_(arena, number_of_inputs), 2638 reg_number_(reg_number), 2639 type_(type), 2640 is_live_(false), 2641 can_be_null_(true) { 2642 inputs_.SetSize(number_of_inputs); 2643 } 2644 2645 // Returns a type equivalent to the given `type`, but that a `HPhi` can hold. 2646 static Primitive::Type ToPhiType(Primitive::Type type) { 2647 switch (type) { 2648 case Primitive::kPrimBoolean: 2649 case Primitive::kPrimByte: 2650 case Primitive::kPrimShort: 2651 case Primitive::kPrimChar: 2652 return Primitive::kPrimInt; 2653 default: 2654 return type; 2655 } 2656 } 2657 2658 size_t InputCount() const OVERRIDE { return inputs_.Size(); } 2659 2660 void AddInput(HInstruction* input); 2661 2662 Primitive::Type GetType() const OVERRIDE { return type_; } 2663 void SetType(Primitive::Type type) { type_ = type; } 2664 2665 bool CanBeNull() const OVERRIDE { return can_be_null_; } 2666 void SetCanBeNull(bool can_be_null) { can_be_null_ = can_be_null; } 2667 2668 uint32_t GetRegNumber() const { return reg_number_; } 2669 2670 void SetDead() { is_live_ = false; } 2671 void SetLive() { is_live_ = true; } 2672 bool IsDead() const { return !is_live_; } 2673 bool IsLive() const { return is_live_; } 2674 2675 DECLARE_INSTRUCTION(Phi); 2676 2677 protected: 2678 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_.Get(i); } 2679 2680 void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) OVERRIDE { 2681 inputs_.Put(index, input); 2682 } 2683 2684 private: 2685 GrowableArray<HUserRecord<HInstruction*> > inputs_; 2686 const uint32_t reg_number_; 2687 Primitive::Type type_; 2688 bool is_live_; 2689 bool can_be_null_; 2690 2691 DISALLOW_COPY_AND_ASSIGN(HPhi); 2692}; 2693 2694class HNullCheck : public HExpression<1> { 2695 public: 2696 HNullCheck(HInstruction* value, uint32_t dex_pc) 2697 : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) { 2698 SetRawInputAt(0, value); 2699 } 2700 2701 bool CanBeMoved() const OVERRIDE { return true; } 2702 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 2703 UNUSED(other); 2704 return true; 2705 } 2706 2707 bool NeedsEnvironment() const OVERRIDE { return true; } 2708 2709 bool CanThrow() const OVERRIDE { return true; } 2710 2711 bool CanBeNull() const OVERRIDE { return false; } 2712 2713 uint32_t GetDexPc() const { return dex_pc_; } 2714 2715 DECLARE_INSTRUCTION(NullCheck); 2716 2717 private: 2718 const uint32_t dex_pc_; 2719 2720 DISALLOW_COPY_AND_ASSIGN(HNullCheck); 2721}; 2722 2723class FieldInfo : public ValueObject { 2724 public: 2725 FieldInfo(MemberOffset field_offset, Primitive::Type field_type, bool is_volatile) 2726 : field_offset_(field_offset), field_type_(field_type), is_volatile_(is_volatile) {} 2727 2728 MemberOffset GetFieldOffset() const { return field_offset_; } 2729 Primitive::Type GetFieldType() const { return field_type_; } 2730 bool IsVolatile() const { return is_volatile_; } 2731 2732 private: 2733 const MemberOffset field_offset_; 2734 const Primitive::Type field_type_; 2735 const bool is_volatile_; 2736}; 2737 2738class HInstanceFieldGet : public HExpression<1> { 2739 public: 2740 HInstanceFieldGet(HInstruction* value, 2741 Primitive::Type field_type, 2742 MemberOffset field_offset, 2743 bool is_volatile) 2744 : HExpression(field_type, SideEffects::DependsOnSomething()), 2745 field_info_(field_offset, field_type, is_volatile) { 2746 SetRawInputAt(0, value); 2747 } 2748 2749 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); } 2750 2751 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 2752 HInstanceFieldGet* other_get = other->AsInstanceFieldGet(); 2753 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue(); 2754 } 2755 2756 bool CanDoImplicitNullCheck() const OVERRIDE { 2757 return GetFieldOffset().Uint32Value() < kPageSize; 2758 } 2759 2760 size_t ComputeHashCode() const OVERRIDE { 2761 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue(); 2762 } 2763 2764 const FieldInfo& GetFieldInfo() const { return field_info_; } 2765 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } 2766 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } 2767 bool IsVolatile() const { return field_info_.IsVolatile(); } 2768 2769 DECLARE_INSTRUCTION(InstanceFieldGet); 2770 2771 private: 2772 const FieldInfo field_info_; 2773 2774 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldGet); 2775}; 2776 2777class HInstanceFieldSet : public HTemplateInstruction<2> { 2778 public: 2779 HInstanceFieldSet(HInstruction* object, 2780 HInstruction* value, 2781 Primitive::Type field_type, 2782 MemberOffset field_offset, 2783 bool is_volatile) 2784 : HTemplateInstruction(SideEffects::ChangesSomething()), 2785 field_info_(field_offset, field_type, is_volatile) { 2786 SetRawInputAt(0, object); 2787 SetRawInputAt(1, value); 2788 } 2789 2790 bool CanDoImplicitNullCheck() const OVERRIDE { 2791 return GetFieldOffset().Uint32Value() < kPageSize; 2792 } 2793 2794 const FieldInfo& GetFieldInfo() const { return field_info_; } 2795 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } 2796 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } 2797 bool IsVolatile() const { return field_info_.IsVolatile(); } 2798 HInstruction* GetValue() const { return InputAt(1); } 2799 2800 DECLARE_INSTRUCTION(InstanceFieldSet); 2801 2802 private: 2803 const FieldInfo field_info_; 2804 2805 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldSet); 2806}; 2807 2808class HArrayGet : public HExpression<2> { 2809 public: 2810 HArrayGet(HInstruction* array, HInstruction* index, Primitive::Type type) 2811 : HExpression(type, SideEffects::DependsOnSomething()) { 2812 SetRawInputAt(0, array); 2813 SetRawInputAt(1, index); 2814 } 2815 2816 bool CanBeMoved() const OVERRIDE { return true; } 2817 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 2818 UNUSED(other); 2819 return true; 2820 } 2821 bool CanDoImplicitNullCheck() const OVERRIDE { 2822 // TODO: We can be smarter here. 2823 // Currently, the array access is always preceded by an ArrayLength or a NullCheck 2824 // which generates the implicit null check. There are cases when these can be removed 2825 // to produce better code. If we ever add optimizations to do so we should allow an 2826 // implicit check here (as long as the address falls in the first page). 2827 return false; 2828 } 2829 2830 void SetType(Primitive::Type type) { type_ = type; } 2831 2832 HInstruction* GetArray() const { return InputAt(0); } 2833 HInstruction* GetIndex() const { return InputAt(1); } 2834 2835 DECLARE_INSTRUCTION(ArrayGet); 2836 2837 private: 2838 DISALLOW_COPY_AND_ASSIGN(HArrayGet); 2839}; 2840 2841class HArraySet : public HTemplateInstruction<3> { 2842 public: 2843 HArraySet(HInstruction* array, 2844 HInstruction* index, 2845 HInstruction* value, 2846 Primitive::Type expected_component_type, 2847 uint32_t dex_pc) 2848 : HTemplateInstruction(SideEffects::ChangesSomething()), 2849 dex_pc_(dex_pc), 2850 expected_component_type_(expected_component_type), 2851 needs_type_check_(value->GetType() == Primitive::kPrimNot) { 2852 SetRawInputAt(0, array); 2853 SetRawInputAt(1, index); 2854 SetRawInputAt(2, value); 2855 } 2856 2857 bool NeedsEnvironment() const OVERRIDE { 2858 // We currently always call a runtime method to catch array store 2859 // exceptions. 2860 return needs_type_check_; 2861 } 2862 2863 bool CanDoImplicitNullCheck() const OVERRIDE { 2864 // TODO: Same as for ArrayGet. 2865 return false; 2866 } 2867 2868 void ClearNeedsTypeCheck() { 2869 needs_type_check_ = false; 2870 } 2871 2872 bool NeedsTypeCheck() const { return needs_type_check_; } 2873 2874 uint32_t GetDexPc() const { return dex_pc_; } 2875 2876 HInstruction* GetArray() const { return InputAt(0); } 2877 HInstruction* GetIndex() const { return InputAt(1); } 2878 HInstruction* GetValue() const { return InputAt(2); } 2879 2880 Primitive::Type GetComponentType() const { 2881 // The Dex format does not type floating point index operations. Since the 2882 // `expected_component_type_` is set during building and can therefore not 2883 // be correct, we also check what is the value type. If it is a floating 2884 // point type, we must use that type. 2885 Primitive::Type value_type = GetValue()->GetType(); 2886 return ((value_type == Primitive::kPrimFloat) || (value_type == Primitive::kPrimDouble)) 2887 ? value_type 2888 : expected_component_type_; 2889 } 2890 2891 DECLARE_INSTRUCTION(ArraySet); 2892 2893 private: 2894 const uint32_t dex_pc_; 2895 const Primitive::Type expected_component_type_; 2896 bool needs_type_check_; 2897 2898 DISALLOW_COPY_AND_ASSIGN(HArraySet); 2899}; 2900 2901class HArrayLength : public HExpression<1> { 2902 public: 2903 explicit HArrayLength(HInstruction* array) 2904 : HExpression(Primitive::kPrimInt, SideEffects::None()) { 2905 // Note that arrays do not change length, so the instruction does not 2906 // depend on any write. 2907 SetRawInputAt(0, array); 2908 } 2909 2910 bool CanBeMoved() const OVERRIDE { return true; } 2911 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 2912 UNUSED(other); 2913 return true; 2914 } 2915 bool CanDoImplicitNullCheck() const OVERRIDE { return true; } 2916 2917 DECLARE_INSTRUCTION(ArrayLength); 2918 2919 private: 2920 DISALLOW_COPY_AND_ASSIGN(HArrayLength); 2921}; 2922 2923class HBoundsCheck : public HExpression<2> { 2924 public: 2925 HBoundsCheck(HInstruction* index, HInstruction* length, uint32_t dex_pc) 2926 : HExpression(index->GetType(), SideEffects::None()), dex_pc_(dex_pc) { 2927 DCHECK(index->GetType() == Primitive::kPrimInt); 2928 SetRawInputAt(0, index); 2929 SetRawInputAt(1, length); 2930 } 2931 2932 bool CanBeMoved() const OVERRIDE { return true; } 2933 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 2934 UNUSED(other); 2935 return true; 2936 } 2937 2938 bool NeedsEnvironment() const OVERRIDE { return true; } 2939 2940 bool CanThrow() const OVERRIDE { return true; } 2941 2942 uint32_t GetDexPc() const { return dex_pc_; } 2943 2944 DECLARE_INSTRUCTION(BoundsCheck); 2945 2946 private: 2947 const uint32_t dex_pc_; 2948 2949 DISALLOW_COPY_AND_ASSIGN(HBoundsCheck); 2950}; 2951 2952/** 2953 * Some DEX instructions are folded into multiple HInstructions that need 2954 * to stay live until the last HInstruction. This class 2955 * is used as a marker for the baseline compiler to ensure its preceding 2956 * HInstruction stays live. `index` represents the stack location index of the 2957 * instruction (the actual offset is computed as index * vreg_size). 2958 */ 2959class HTemporary : public HTemplateInstruction<0> { 2960 public: 2961 explicit HTemporary(size_t index) : HTemplateInstruction(SideEffects::None()), index_(index) {} 2962 2963 size_t GetIndex() const { return index_; } 2964 2965 Primitive::Type GetType() const OVERRIDE { 2966 // The previous instruction is the one that will be stored in the temporary location. 2967 DCHECK(GetPrevious() != nullptr); 2968 return GetPrevious()->GetType(); 2969 } 2970 2971 DECLARE_INSTRUCTION(Temporary); 2972 2973 private: 2974 const size_t index_; 2975 2976 DISALLOW_COPY_AND_ASSIGN(HTemporary); 2977}; 2978 2979class HSuspendCheck : public HTemplateInstruction<0> { 2980 public: 2981 explicit HSuspendCheck(uint32_t dex_pc) 2982 : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc) {} 2983 2984 bool NeedsEnvironment() const OVERRIDE { 2985 return true; 2986 } 2987 2988 uint32_t GetDexPc() const { return dex_pc_; } 2989 2990 DECLARE_INSTRUCTION(SuspendCheck); 2991 2992 private: 2993 const uint32_t dex_pc_; 2994 2995 DISALLOW_COPY_AND_ASSIGN(HSuspendCheck); 2996}; 2997 2998/** 2999 * Instruction to load a Class object. 3000 */ 3001class HLoadClass : public HExpression<0> { 3002 public: 3003 HLoadClass(uint16_t type_index, 3004 bool is_referrers_class, 3005 uint32_t dex_pc) 3006 : HExpression(Primitive::kPrimNot, SideEffects::None()), 3007 type_index_(type_index), 3008 is_referrers_class_(is_referrers_class), 3009 dex_pc_(dex_pc), 3010 generate_clinit_check_(false), 3011 loaded_class_rti_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {} 3012 3013 bool CanBeMoved() const OVERRIDE { return true; } 3014 3015 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 3016 return other->AsLoadClass()->type_index_ == type_index_; 3017 } 3018 3019 size_t ComputeHashCode() const OVERRIDE { return type_index_; } 3020 3021 uint32_t GetDexPc() const { return dex_pc_; } 3022 uint16_t GetTypeIndex() const { return type_index_; } 3023 bool IsReferrersClass() const { return is_referrers_class_; } 3024 3025 bool NeedsEnvironment() const OVERRIDE { 3026 // Will call runtime and load the class if the class is not loaded yet. 3027 // TODO: finer grain decision. 3028 return !is_referrers_class_; 3029 } 3030 3031 bool MustGenerateClinitCheck() const { 3032 return generate_clinit_check_; 3033 } 3034 3035 void SetMustGenerateClinitCheck() { 3036 generate_clinit_check_ = true; 3037 } 3038 3039 bool CanCallRuntime() const { 3040 return MustGenerateClinitCheck() || !is_referrers_class_; 3041 } 3042 3043 bool CanThrow() const OVERRIDE { 3044 // May call runtime and and therefore can throw. 3045 // TODO: finer grain decision. 3046 return !is_referrers_class_; 3047 } 3048 3049 ReferenceTypeInfo GetLoadedClassRTI() { 3050 return loaded_class_rti_; 3051 } 3052 3053 void SetLoadedClassRTI(ReferenceTypeInfo rti) { 3054 // Make sure we only set exact types (the loaded class should never be merged). 3055 DCHECK(rti.IsExact()); 3056 loaded_class_rti_ = rti; 3057 } 3058 3059 bool IsResolved() { 3060 return loaded_class_rti_.IsExact(); 3061 } 3062 3063 bool NeedsDexCache() const OVERRIDE { return !is_referrers_class_; } 3064 3065 DECLARE_INSTRUCTION(LoadClass); 3066 3067 private: 3068 const uint16_t type_index_; 3069 const bool is_referrers_class_; 3070 const uint32_t dex_pc_; 3071 // Whether this instruction must generate the initialization check. 3072 // Used for code generation. 3073 bool generate_clinit_check_; 3074 3075 ReferenceTypeInfo loaded_class_rti_; 3076 3077 DISALLOW_COPY_AND_ASSIGN(HLoadClass); 3078}; 3079 3080class HLoadString : public HExpression<0> { 3081 public: 3082 HLoadString(uint32_t string_index, uint32_t dex_pc) 3083 : HExpression(Primitive::kPrimNot, SideEffects::None()), 3084 string_index_(string_index), 3085 dex_pc_(dex_pc) {} 3086 3087 bool CanBeMoved() const OVERRIDE { return true; } 3088 3089 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 3090 return other->AsLoadString()->string_index_ == string_index_; 3091 } 3092 3093 size_t ComputeHashCode() const OVERRIDE { return string_index_; } 3094 3095 uint32_t GetDexPc() const { return dex_pc_; } 3096 uint32_t GetStringIndex() const { return string_index_; } 3097 3098 // TODO: Can we deopt or debug when we resolve a string? 3099 bool NeedsEnvironment() const OVERRIDE { return false; } 3100 bool NeedsDexCache() const OVERRIDE { return true; } 3101 3102 DECLARE_INSTRUCTION(LoadString); 3103 3104 private: 3105 const uint32_t string_index_; 3106 const uint32_t dex_pc_; 3107 3108 DISALLOW_COPY_AND_ASSIGN(HLoadString); 3109}; 3110 3111// TODO: Pass this check to HInvokeStaticOrDirect nodes. 3112/** 3113 * Performs an initialization check on its Class object input. 3114 */ 3115class HClinitCheck : public HExpression<1> { 3116 public: 3117 explicit HClinitCheck(HLoadClass* constant, uint32_t dex_pc) 3118 : HExpression(Primitive::kPrimNot, SideEffects::All()), 3119 dex_pc_(dex_pc) { 3120 SetRawInputAt(0, constant); 3121 } 3122 3123 bool CanBeMoved() const OVERRIDE { return true; } 3124 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 3125 UNUSED(other); 3126 return true; 3127 } 3128 3129 bool NeedsEnvironment() const OVERRIDE { 3130 // May call runtime to initialize the class. 3131 return true; 3132 } 3133 3134 uint32_t GetDexPc() const { return dex_pc_; } 3135 3136 HLoadClass* GetLoadClass() const { return InputAt(0)->AsLoadClass(); } 3137 3138 DECLARE_INSTRUCTION(ClinitCheck); 3139 3140 private: 3141 const uint32_t dex_pc_; 3142 3143 DISALLOW_COPY_AND_ASSIGN(HClinitCheck); 3144}; 3145 3146class HStaticFieldGet : public HExpression<1> { 3147 public: 3148 HStaticFieldGet(HInstruction* cls, 3149 Primitive::Type field_type, 3150 MemberOffset field_offset, 3151 bool is_volatile) 3152 : HExpression(field_type, SideEffects::DependsOnSomething()), 3153 field_info_(field_offset, field_type, is_volatile) { 3154 SetRawInputAt(0, cls); 3155 } 3156 3157 3158 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); } 3159 3160 bool InstructionDataEquals(HInstruction* other) const OVERRIDE { 3161 HStaticFieldGet* other_get = other->AsStaticFieldGet(); 3162 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue(); 3163 } 3164 3165 size_t ComputeHashCode() const OVERRIDE { 3166 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue(); 3167 } 3168 3169 const FieldInfo& GetFieldInfo() const { return field_info_; } 3170 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } 3171 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } 3172 bool IsVolatile() const { return field_info_.IsVolatile(); } 3173 3174 DECLARE_INSTRUCTION(StaticFieldGet); 3175 3176 private: 3177 const FieldInfo field_info_; 3178 3179 DISALLOW_COPY_AND_ASSIGN(HStaticFieldGet); 3180}; 3181 3182class HStaticFieldSet : public HTemplateInstruction<2> { 3183 public: 3184 HStaticFieldSet(HInstruction* cls, 3185 HInstruction* value, 3186 Primitive::Type field_type, 3187 MemberOffset field_offset, 3188 bool is_volatile) 3189 : HTemplateInstruction(SideEffects::ChangesSomething()), 3190 field_info_(field_offset, field_type, is_volatile) { 3191 SetRawInputAt(0, cls); 3192 SetRawInputAt(1, value); 3193 } 3194 3195 const FieldInfo& GetFieldInfo() const { return field_info_; } 3196 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } 3197 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } 3198 bool IsVolatile() const { return field_info_.IsVolatile(); } 3199 3200 HInstruction* GetValue() const { return InputAt(1); } 3201 3202 DECLARE_INSTRUCTION(StaticFieldSet); 3203 3204 private: 3205 const FieldInfo field_info_; 3206 3207 DISALLOW_COPY_AND_ASSIGN(HStaticFieldSet); 3208}; 3209 3210// Implement the move-exception DEX instruction. 3211class HLoadException : public HExpression<0> { 3212 public: 3213 HLoadException() : HExpression(Primitive::kPrimNot, SideEffects::None()) {} 3214 3215 DECLARE_INSTRUCTION(LoadException); 3216 3217 private: 3218 DISALLOW_COPY_AND_ASSIGN(HLoadException); 3219}; 3220 3221class HThrow : public HTemplateInstruction<1> { 3222 public: 3223 HThrow(HInstruction* exception, uint32_t dex_pc) 3224 : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc) { 3225 SetRawInputAt(0, exception); 3226 } 3227 3228 bool IsControlFlow() const OVERRIDE { return true; } 3229 3230 bool NeedsEnvironment() const OVERRIDE { return true; } 3231 3232 bool CanThrow() const OVERRIDE { return true; } 3233 3234 uint32_t GetDexPc() const { return dex_pc_; } 3235 3236 DECLARE_INSTRUCTION(Throw); 3237 3238 private: 3239 const uint32_t dex_pc_; 3240 3241 DISALLOW_COPY_AND_ASSIGN(HThrow); 3242}; 3243 3244class HInstanceOf : public HExpression<2> { 3245 public: 3246 HInstanceOf(HInstruction* object, 3247 HLoadClass* constant, 3248 bool class_is_final, 3249 uint32_t dex_pc) 3250 : HExpression(Primitive::kPrimBoolean, SideEffects::None()), 3251 class_is_final_(class_is_final), 3252 dex_pc_(dex_pc) { 3253 SetRawInputAt(0, object); 3254 SetRawInputAt(1, constant); 3255 } 3256 3257 bool CanBeMoved() const OVERRIDE { return true; } 3258 3259 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { 3260 return true; 3261 } 3262 3263 bool NeedsEnvironment() const OVERRIDE { 3264 return false; 3265 } 3266 3267 uint32_t GetDexPc() const { return dex_pc_; } 3268 3269 bool IsClassFinal() const { return class_is_final_; } 3270 3271 DECLARE_INSTRUCTION(InstanceOf); 3272 3273 private: 3274 const bool class_is_final_; 3275 const uint32_t dex_pc_; 3276 3277 DISALLOW_COPY_AND_ASSIGN(HInstanceOf); 3278}; 3279 3280class HBoundType : public HExpression<1> { 3281 public: 3282 HBoundType(HInstruction* input, ReferenceTypeInfo bound_type) 3283 : HExpression(Primitive::kPrimNot, SideEffects::None()), 3284 bound_type_(bound_type) { 3285 DCHECK_EQ(input->GetType(), Primitive::kPrimNot); 3286 SetRawInputAt(0, input); 3287 } 3288 3289 const ReferenceTypeInfo& GetBoundType() const { return bound_type_; } 3290 3291 bool CanBeNull() const OVERRIDE { 3292 // `null instanceof ClassX` always return false so we can't be null. 3293 return false; 3294 } 3295 3296 DECLARE_INSTRUCTION(BoundType); 3297 3298 private: 3299 // Encodes the most upper class that this instruction can have. In other words 3300 // it is always the case that GetBoundType().IsSupertypeOf(GetReferenceType()). 3301 // It is used to bound the type in cases like `if (x instanceof ClassX) {}` 3302 const ReferenceTypeInfo bound_type_; 3303 3304 DISALLOW_COPY_AND_ASSIGN(HBoundType); 3305}; 3306 3307class HCheckCast : public HTemplateInstruction<2> { 3308 public: 3309 HCheckCast(HInstruction* object, 3310 HLoadClass* constant, 3311 bool class_is_final, 3312 uint32_t dex_pc) 3313 : HTemplateInstruction(SideEffects::None()), 3314 class_is_final_(class_is_final), 3315 dex_pc_(dex_pc) { 3316 SetRawInputAt(0, object); 3317 SetRawInputAt(1, constant); 3318 } 3319 3320 bool CanBeMoved() const OVERRIDE { return true; } 3321 3322 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { 3323 return true; 3324 } 3325 3326 bool NeedsEnvironment() const OVERRIDE { 3327 // Instruction may throw a CheckCastError. 3328 return true; 3329 } 3330 3331 bool CanThrow() const OVERRIDE { return true; } 3332 3333 uint32_t GetDexPc() const { return dex_pc_; } 3334 3335 bool IsClassFinal() const { return class_is_final_; } 3336 3337 DECLARE_INSTRUCTION(CheckCast); 3338 3339 private: 3340 const bool class_is_final_; 3341 const uint32_t dex_pc_; 3342 3343 DISALLOW_COPY_AND_ASSIGN(HCheckCast); 3344}; 3345 3346class HMonitorOperation : public HTemplateInstruction<1> { 3347 public: 3348 enum OperationKind { 3349 kEnter, 3350 kExit, 3351 }; 3352 3353 HMonitorOperation(HInstruction* object, OperationKind kind, uint32_t dex_pc) 3354 : HTemplateInstruction(SideEffects::None()), kind_(kind), dex_pc_(dex_pc) { 3355 SetRawInputAt(0, object); 3356 } 3357 3358 // Instruction may throw a Java exception, so we need an environment. 3359 bool NeedsEnvironment() const OVERRIDE { return true; } 3360 bool CanThrow() const OVERRIDE { return true; } 3361 3362 uint32_t GetDexPc() const { return dex_pc_; } 3363 3364 bool IsEnter() const { return kind_ == kEnter; } 3365 3366 DECLARE_INSTRUCTION(MonitorOperation); 3367 3368 private: 3369 const OperationKind kind_; 3370 const uint32_t dex_pc_; 3371 3372 private: 3373 DISALLOW_COPY_AND_ASSIGN(HMonitorOperation); 3374}; 3375 3376class MoveOperands : public ArenaObject<kArenaAllocMisc> { 3377 public: 3378 MoveOperands(Location source, Location destination, HInstruction* instruction) 3379 : source_(source), destination_(destination), instruction_(instruction) {} 3380 3381 Location GetSource() const { return source_; } 3382 Location GetDestination() const { return destination_; } 3383 3384 void SetSource(Location value) { source_ = value; } 3385 void SetDestination(Location value) { destination_ = value; } 3386 3387 // The parallel move resolver marks moves as "in-progress" by clearing the 3388 // destination (but not the source). 3389 Location MarkPending() { 3390 DCHECK(!IsPending()); 3391 Location dest = destination_; 3392 destination_ = Location::NoLocation(); 3393 return dest; 3394 } 3395 3396 void ClearPending(Location dest) { 3397 DCHECK(IsPending()); 3398 destination_ = dest; 3399 } 3400 3401 bool IsPending() const { 3402 DCHECK(!source_.IsInvalid() || destination_.IsInvalid()); 3403 return destination_.IsInvalid() && !source_.IsInvalid(); 3404 } 3405 3406 // True if this blocks a move from the given location. 3407 bool Blocks(Location loc) const { 3408 return !IsEliminated() && (source_.Contains(loc) || loc.Contains(source_)); 3409 } 3410 3411 // A move is redundant if it's been eliminated, if its source and 3412 // destination are the same, or if its destination is unneeded. 3413 bool IsRedundant() const { 3414 return IsEliminated() || destination_.IsInvalid() || source_.Equals(destination_); 3415 } 3416 3417 // We clear both operands to indicate move that's been eliminated. 3418 void Eliminate() { 3419 source_ = destination_ = Location::NoLocation(); 3420 } 3421 3422 bool IsEliminated() const { 3423 DCHECK(!source_.IsInvalid() || destination_.IsInvalid()); 3424 return source_.IsInvalid(); 3425 } 3426 3427 HInstruction* GetInstruction() const { return instruction_; } 3428 3429 private: 3430 Location source_; 3431 Location destination_; 3432 // The instruction this move is assocatied with. Null when this move is 3433 // for moving an input in the expected locations of user (including a phi user). 3434 // This is only used in debug mode, to ensure we do not connect interval siblings 3435 // in the same parallel move. 3436 HInstruction* instruction_; 3437}; 3438 3439static constexpr size_t kDefaultNumberOfMoves = 4; 3440 3441class HParallelMove : public HTemplateInstruction<0> { 3442 public: 3443 explicit HParallelMove(ArenaAllocator* arena) 3444 : HTemplateInstruction(SideEffects::None()), moves_(arena, kDefaultNumberOfMoves) {} 3445 3446 void AddMove(Location source, Location destination, HInstruction* instruction) { 3447 DCHECK(source.IsValid()); 3448 DCHECK(destination.IsValid()); 3449 if (kIsDebugBuild) { 3450 if (instruction != nullptr) { 3451 for (size_t i = 0, e = moves_.Size(); i < e; ++i) { 3452 if (moves_.Get(i).GetInstruction() == instruction) { 3453 // Special case the situation where the move is for the spill slot 3454 // of the instruction. 3455 if ((GetPrevious() == instruction) 3456 || ((GetPrevious() == nullptr) 3457 && instruction->IsPhi() 3458 && instruction->GetBlock() == GetBlock())) { 3459 DCHECK_NE(destination.GetKind(), moves_.Get(i).GetDestination().GetKind()) 3460 << "Doing parallel moves for the same instruction."; 3461 } else { 3462 DCHECK(false) << "Doing parallel moves for the same instruction."; 3463 } 3464 } 3465 } 3466 } 3467 for (size_t i = 0, e = moves_.Size(); i < e; ++i) { 3468 DCHECK(!destination.Equals(moves_.Get(i).GetDestination())) 3469 << "Same destination for two moves in a parallel move."; 3470 } 3471 } 3472 moves_.Add(MoveOperands(source, destination, instruction)); 3473 } 3474 3475 MoveOperands* MoveOperandsAt(size_t index) const { 3476 return moves_.GetRawStorage() + index; 3477 } 3478 3479 size_t NumMoves() const { return moves_.Size(); } 3480 3481 DECLARE_INSTRUCTION(ParallelMove); 3482 3483 private: 3484 GrowableArray<MoveOperands> moves_; 3485 3486 DISALLOW_COPY_AND_ASSIGN(HParallelMove); 3487}; 3488 3489class HGraphVisitor : public ValueObject { 3490 public: 3491 explicit HGraphVisitor(HGraph* graph) : graph_(graph) {} 3492 virtual ~HGraphVisitor() {} 3493 3494 virtual void VisitInstruction(HInstruction* instruction) { UNUSED(instruction); } 3495 virtual void VisitBasicBlock(HBasicBlock* block); 3496 3497 // Visit the graph following basic block insertion order. 3498 void VisitInsertionOrder(); 3499 3500 // Visit the graph following dominator tree reverse post-order. 3501 void VisitReversePostOrder(); 3502 3503 HGraph* GetGraph() const { return graph_; } 3504 3505 // Visit functions for instruction classes. 3506#define DECLARE_VISIT_INSTRUCTION(name, super) \ 3507 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); } 3508 3509 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) 3510 3511#undef DECLARE_VISIT_INSTRUCTION 3512 3513 private: 3514 HGraph* const graph_; 3515 3516 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor); 3517}; 3518 3519class HGraphDelegateVisitor : public HGraphVisitor { 3520 public: 3521 explicit HGraphDelegateVisitor(HGraph* graph) : HGraphVisitor(graph) {} 3522 virtual ~HGraphDelegateVisitor() {} 3523 3524 // Visit functions that delegate to to super class. 3525#define DECLARE_VISIT_INSTRUCTION(name, super) \ 3526 void Visit##name(H##name* instr) OVERRIDE { Visit##super(instr); } 3527 3528 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) 3529 3530#undef DECLARE_VISIT_INSTRUCTION 3531 3532 private: 3533 DISALLOW_COPY_AND_ASSIGN(HGraphDelegateVisitor); 3534}; 3535 3536class HInsertionOrderIterator : public ValueObject { 3537 public: 3538 explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {} 3539 3540 bool Done() const { return index_ == graph_.GetBlocks().Size(); } 3541 HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); } 3542 void Advance() { ++index_; } 3543 3544 private: 3545 const HGraph& graph_; 3546 size_t index_; 3547 3548 DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator); 3549}; 3550 3551class HReversePostOrderIterator : public ValueObject { 3552 public: 3553 explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) { 3554 // Check that reverse post order of the graph has been built. 3555 DCHECK(!graph.GetReversePostOrder().IsEmpty()); 3556 } 3557 3558 bool Done() const { return index_ == graph_.GetReversePostOrder().Size(); } 3559 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_); } 3560 void Advance() { ++index_; } 3561 3562 private: 3563 const HGraph& graph_; 3564 size_t index_; 3565 3566 DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator); 3567}; 3568 3569class HPostOrderIterator : public ValueObject { 3570 public: 3571 explicit HPostOrderIterator(const HGraph& graph) 3572 : graph_(graph), index_(graph_.GetReversePostOrder().Size()) { 3573 // Check that reverse post order of the graph has been built. 3574 DCHECK(!graph.GetReversePostOrder().IsEmpty()); 3575 } 3576 3577 bool Done() const { return index_ == 0; } 3578 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_ - 1); } 3579 void Advance() { --index_; } 3580 3581 private: 3582 const HGraph& graph_; 3583 size_t index_; 3584 3585 DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator); 3586}; 3587 3588// Iterator over the blocks that art part of the loop. Includes blocks part 3589// of an inner loop. The order in which the blocks are iterated is on their 3590// block id. 3591class HBlocksInLoopIterator : public ValueObject { 3592 public: 3593 explicit HBlocksInLoopIterator(const HLoopInformation& info) 3594 : blocks_in_loop_(info.GetBlocks()), 3595 blocks_(info.GetHeader()->GetGraph()->GetBlocks()), 3596 index_(0) { 3597 if (!blocks_in_loop_.IsBitSet(index_)) { 3598 Advance(); 3599 } 3600 } 3601 3602 bool Done() const { return index_ == blocks_.Size(); } 3603 HBasicBlock* Current() const { return blocks_.Get(index_); } 3604 void Advance() { 3605 ++index_; 3606 for (size_t e = blocks_.Size(); index_ < e; ++index_) { 3607 if (blocks_in_loop_.IsBitSet(index_)) { 3608 break; 3609 } 3610 } 3611 } 3612 3613 private: 3614 const BitVector& blocks_in_loop_; 3615 const GrowableArray<HBasicBlock*>& blocks_; 3616 size_t index_; 3617 3618 DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopIterator); 3619}; 3620 3621inline int64_t Int64FromConstant(HConstant* constant) { 3622 DCHECK(constant->IsIntConstant() || constant->IsLongConstant()); 3623 return constant->IsIntConstant() ? constant->AsIntConstant()->GetValue() 3624 : constant->AsLongConstant()->GetValue(); 3625} 3626 3627} // namespace art 3628 3629#endif // ART_COMPILER_OPTIMIZING_NODES_H_ 3630