code_generator.h revision 175dc732c80e6f2afd83209348124df349290ba8
1d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray/* 2d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Copyright (C) 2014 The Android Open Source Project 3d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * 4d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License"); 5d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * you may not use this file except in compliance with the License. 6d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * You may obtain a copy of the License at 7d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * 8d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * http://www.apache.org/licenses/LICENSE-2.0 9d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * 10d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Unless required by applicable law or agreed to in writing, software 11d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS, 12d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * See the License for the specific language governing permissions and 14d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * limitations under the License. 15d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray */ 16d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 17d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#ifndef ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_ 18d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_ 19d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 20d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "arch/instruction_set.h" 213416601a9e9be81bb7494864287fd3602d18ef13Calin Juravle#include "arch/instruction_set_features.h" 22f9f6441c665b5ff9004d3ed55014f46d416fb1bbVladimir Marko#include "base/arena_containers.h" 23f9f6441c665b5ff9004d3ed55014f46d416fb1bbVladimir Marko#include "base/arena_object.h" 2401bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray#include "base/bit_field.h" 25cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle#include "driver/compiler_options.h" 26bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray#include "globals.h" 27eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames#include "graph_visualizer.h" 284e3d23aa1523718ea1fdf3a32516d2f9d81e84feNicolas Geoffray#include "locations.h" 29d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "memory_region.h" 30d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "nodes.h" 31ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu#include "optimizing_compiler_stats.h" 323946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray#include "stack_map_stream.h" 33d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 34d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffraynamespace art { 35d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 366d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain// Binary encoding of 2^32 for type double. 376d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillainstatic int64_t constexpr k2Pow32EncodingForDouble = INT64_C(0x41F0000000000000); 386d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain// Binary encoding of 2^31 for type double. 396d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillainstatic int64_t constexpr k2Pow31EncodingForDouble = INT64_C(0x41E0000000000000); 406d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain 41e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell// Minimum value for a primitive integer. 42e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendellstatic int32_t constexpr kPrimIntMin = 0x80000000; 43e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell// Minimum value for a primitive long. 44e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendellstatic int64_t constexpr kPrimLongMin = INT64_C(0x8000000000000000); 45e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell 463f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillain// Maximum value for a primitive integer. 473f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillainstatic int32_t constexpr kPrimIntMax = 0x7fffffff; 48624279f3c70f9904cbaf428078981b05d3b324c0Roland Levillain// Maximum value for a primitive long. 49e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendellstatic int64_t constexpr kPrimLongMax = INT64_C(0x7fffffffffffffff); 503f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillain 5192a73aef279be78e3c2b04db1713076183933436Nicolas Geoffrayclass Assembler; 52e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffrayclass CodeGenerator; 5392cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffrayclass DexCompilationUnit; 54581550137ee3a068a14224870e71aeee924a0646Vladimir Markoclass LinkerPatch; 55f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffrayclass ParallelMoveResolver; 56e21dc3db191df04c100620965bee4617b3b24397Andreas Gampeclass SrcMapElem; 57e21dc3db191df04c100620965bee4617b3b24397Andreas Gampetemplate <class Alloc> 58e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanclass SrcMap; 59e21dc3db191df04c100620965bee4617b3b24397Andreas Gampeusing DefaultSrcMap = SrcMap<std::allocator<SrcMapElem>>; 6092cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffray 61d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffrayclass CodeAllocator { 62d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public: 63e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray CodeAllocator() {} 64e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray virtual ~CodeAllocator() {} 65d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 66d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray virtual uint8_t* Allocate(size_t size) = 0; 67d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 68d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray private: 69d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(CodeAllocator); 70d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}; 71d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 726a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersclass SlowPathCode : public ArenaObject<kArenaAllocSlowPaths> { 73e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray public: 74eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray SlowPathCode() { 75eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray for (size_t i = 0; i < kMaximumNumberOfExpectedRegisters; ++i) { 76eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray saved_core_stack_offsets_[i] = kRegisterNotSaved; 77eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray saved_fpu_stack_offsets_[i] = kRegisterNotSaved; 78eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray } 79eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray } 80eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray 81e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray virtual ~SlowPathCode() {} 82e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray 83e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray virtual void EmitNativeCode(CodeGenerator* codegen) = 0; 84e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray 85da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu virtual void SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations); 86da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu virtual void RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations); 87a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray 88eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray bool IsCoreRegisterSaved(int reg) const { 89eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray return saved_core_stack_offsets_[reg] != kRegisterNotSaved; 90eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray } 91eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray 92eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray bool IsFpuRegisterSaved(int reg) const { 93eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray return saved_fpu_stack_offsets_[reg] != kRegisterNotSaved; 94eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray } 95eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray 96eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray uint32_t GetStackOffsetOfCoreRegister(int reg) const { 97eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray return saved_core_stack_offsets_[reg]; 98eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray } 99eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray 100eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray uint32_t GetStackOffsetOfFpuRegister(int reg) const { 101eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray return saved_fpu_stack_offsets_[reg]; 102eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray } 103eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray 1048158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames virtual bool IsFatal() const { return false; } 1058158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames 1069931f319cf86c56c2855d800339a3410697633a6Alexandre Rames virtual const char* GetDescription() const = 0; 1079931f319cf86c56c2855d800339a3410697633a6Alexandre Rames 108da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu protected: 109eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray static constexpr size_t kMaximumNumberOfExpectedRegisters = 32; 110eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray static constexpr uint32_t kRegisterNotSaved = -1; 111eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray uint32_t saved_core_stack_offsets_[kMaximumNumberOfExpectedRegisters]; 112eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray uint32_t saved_fpu_stack_offsets_[kMaximumNumberOfExpectedRegisters]; 113da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu 114da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu private: 115e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray DISALLOW_COPY_AND_ASSIGN(SlowPathCode); 116e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray}; 117e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray 1182d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillainclass InvokeDexCallingConventionVisitor { 1192d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain public: 1202d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain virtual Location GetNextLocation(Primitive::Type type) = 0; 121fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray virtual Location GetReturnLocation(Primitive::Type type) const = 0; 122fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray virtual Location GetMethodLocation() const = 0; 1232d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain 1242d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain protected: 1252d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain InvokeDexCallingConventionVisitor() {} 1262d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain virtual ~InvokeDexCallingConventionVisitor() {} 1272d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain 1282d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain // The current index for core registers. 1292d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain uint32_t gp_index_ = 0u; 1302d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain // The current index for floating-point registers. 1312d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain uint32_t float_index_ = 0u; 1322d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain // The current stack index. 1332d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain uint32_t stack_index_ = 0u; 1342d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain 1352d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain private: 1362d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor); 1372d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain}; 1382d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain 13912df9ebf72255544b0147c81b1dca6644a29764eNicolas Geoffrayclass CodeGenerator { 140d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public: 141d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray // Compiles the graph to executable instructions. Returns whether the compilation 142d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray // succeeded. 14373e80c3ae76fafdb53afe3a85306dcb491fb5b00Nicolas Geoffray void CompileBaseline(CodeAllocator* allocator, bool is_leaf = false); 14486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray void CompileOptimized(CodeAllocator* allocator); 14512df9ebf72255544b0147c81b1dca6644a29764eNicolas Geoffray static CodeGenerator* Create(HGraph* graph, 1463416601a9e9be81bb7494864287fd3602d18ef13Calin Juravle InstructionSet instruction_set, 147cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle const InstructionSetFeatures& isa_features, 148ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu const CompilerOptions& compiler_options, 149ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu OptimizingCompilerStats* stats = nullptr); 15012df9ebf72255544b0147c81b1dca6644a29764eNicolas Geoffray virtual ~CodeGenerator() {} 151d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 152787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray HGraph* GetGraph() const { return graph_; } 153d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 154dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray HBasicBlock* GetNextBlockToEmit() const; 155dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray HBasicBlock* FirstNonEmptyBlock(HBasicBlock* block) const; 156bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray bool GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) const; 157bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 15886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray size_t GetStackSlotOfParameter(HParameterValue* parameter) const { 15986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // Note that this follows the current calling convention. 16086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray return GetFrameSize() 161e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier + InstructionSetPointerSize(GetInstructionSet()) // Art method 162e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray + parameter->GetIndex() * kVRegSize; 16386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 16486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 16592a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray virtual void Initialize() = 0; 16632f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu virtual void Finalize(CodeAllocator* allocator); 167581550137ee3a068a14224870e71aeee924a0646Vladimir Marko virtual void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches); 168d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray virtual void GenerateFrameEntry() = 0; 169d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray virtual void GenerateFrameExit() = 0; 17092a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray virtual void Bind(HBasicBlock* block) = 0; 1714a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray virtual void Move(HInstruction* instruction, Location location, HInstruction* move_for) = 0; 172175dc732c80e6f2afd83209348124df349290ba8Calin Juravle virtual void MoveConstant(Location destination, int32_t value) = 0; 173787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray virtual Assembler* GetAssembler() = 0; 174eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames virtual const Assembler& GetAssembler() const = 0; 175707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray virtual size_t GetWordSize() const = 0; 176f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell virtual size_t GetFloatingPointSpillSlotSize() const = 0; 177de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray virtual uintptr_t GetAddressOf(HBasicBlock* block) const = 0; 1784c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray void InitializeCodeGeneration(size_t number_of_spill_slots, 1794c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray size_t maximum_number_of_live_core_registers, 1804c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray size_t maximum_number_of_live_fp_registers, 1814c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray size_t number_of_out_slots, 182fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko const ArenaVector<HBasicBlock*>& block_order); 183ab032bc1ff57831106fdac6a91a136293609401fNicolas Geoffray int32_t GetStackSlot(HLocal* local) const; 184ab032bc1ff57831106fdac6a91a136293609401fNicolas Geoffray Location GetTemporaryLocation(HTemporary* temp) const; 185787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 186787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray uint32_t GetFrameSize() const { return frame_size_; } 187787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray void SetFrameSize(uint32_t size) { frame_size_ = size; } 1888ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray uint32_t GetCoreSpillMask() const { return core_spill_mask_; } 189d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray uint32_t GetFpuSpillMask() const { return fpu_spill_mask_; } 1908ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray 19171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray size_t GetNumberOfCoreRegisters() const { return number_of_core_registers_; } 19271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray size_t GetNumberOfFloatingPointRegisters() const { return number_of_fpu_registers_; } 193988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray virtual void SetupBlockedRegisters(bool is_baseline) const = 0; 19471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray 1954dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray virtual void ComputeSpillMask() { 1964dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray core_spill_mask_ = allocated_registers_.GetCoreRegisters() & core_callee_save_mask_; 1974dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray DCHECK_NE(core_spill_mask_, 0u) << "At least the return address register must be saved"; 1984dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray fpu_spill_mask_ = allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_; 1994dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray } 2004dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray 2014dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray static uint32_t ComputeRegisterMask(const int* registers, size_t length) { 2024dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray uint32_t mask = 0; 2034dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray for (size_t i = 0, e = length; i < e; ++i) { 2044dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray mask |= (1 << registers[i]); 2054dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray } 2064dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray return mask; 2074dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray } 2084dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray 209a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray virtual void DumpCoreRegister(std::ostream& stream, int reg) const = 0; 210a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray virtual void DumpFloatingPointRegister(std::ostream& stream, int reg) const = 0; 211412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray virtual InstructionSet GetInstructionSet() const = 0; 212cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle 213cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle const CompilerOptions& GetCompilerOptions() const { return compiler_options_; } 214cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle 215ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu void MaybeRecordStat(MethodCompilationStat compilation_stat, size_t count = 1) const; 216ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu 217102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray // Saves the register in the stack. Returns the size taken on stack. 218102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray virtual size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) = 0; 219102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray // Restores the register from the stack. Returns the size taken on stack. 220102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray virtual size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) = 0; 221234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray 222234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray virtual size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0; 223234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray virtual size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0; 224234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray 225840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray virtual bool NeedsTwoRegisters(Primitive::Type type) const = 0; 226234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray // Returns whether we should split long moves in parallel moves. 227234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray virtual bool ShouldSplitLongMoves() const { return false; } 228a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 229988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray bool IsCoreCalleeSaveRegister(int reg) const { 230988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray return (core_callee_save_mask_ & (1 << reg)) != 0; 231988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray } 232988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray 233988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray bool IsFloatingPointCalleeSaveRegister(int reg) const { 234988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray return (fpu_callee_save_mask_ & (1 << reg)) != 0; 235988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray } 236988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray 2372a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban // Record native to dex mapping for a suspend point. Required by runtime. 238eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray void RecordPcInfo(HInstruction* instruction, uint32_t dex_pc, SlowPathCode* slow_path = nullptr); 2392a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban // Record additional native to dex mappings for native debugging/profiling tools. 2402a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban void RecordNativeDebugInfo(uint32_t dex_pc, uintptr_t native_pc_begin, uintptr_t native_pc_end); 2412a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban 24277520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle bool CanMoveNullCheckToUser(HNullCheck* null_check); 24377520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle void MaybeRecordImplicitNullCheck(HInstruction* instruction); 244787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 24577a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // Records a stack map which the runtime might use to set catch phi values 24677a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // during exception delivery. 24777a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // TODO: Replace with a catch-entering instruction that records the environment. 24877a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil void RecordCatchBlockInfo(); 24977a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil 25077a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // Returns true if implicit null checks are allowed in the compiler options 25177a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // and if the null check is not inside a try block. We currently cannot do 25277a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // implicit null checks in that case because we need the NullCheckSlowPath to 25377a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // save live registers, which may be needed by the runtime to set catch phis. 25477a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil bool IsImplicitNullCheckAllowed(HNullCheck* null_check) const; 25577a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil 256e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray void AddSlowPath(SlowPathCode* slow_path) { 257e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray slow_paths_.Add(slow_path); 258e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray } 259e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray 2602a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban void SetSrcMap(DefaultSrcMap* src_map) { src_map_ = src_map; } 2612a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban 262f9f6441c665b5ff9004d3ed55014f46d416fb1bbVladimir Marko void BuildMappingTable(ArenaVector<uint8_t>* vector) const; 263f9f6441c665b5ff9004d3ed55014f46d416fb1bbVladimir Marko void BuildVMapTable(ArenaVector<uint8_t>* vector) const; 26492cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffray void BuildNativeGCMap( 265f9f6441c665b5ff9004d3ed55014f46d416fb1bbVladimir Marko ArenaVector<uint8_t>* vector, const DexCompilationUnit& dex_compilation_unit) const; 266f9f6441c665b5ff9004d3ed55014f46d416fb1bbVladimir Marko void BuildStackMaps(ArenaVector<uint8_t>* vector); 267787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 2683e3d73349a2de81d14e2279f60ffbd9ab3f3ac28Roland Levillain bool IsBaseline() const { 2693e3d73349a2de81d14e2279f60ffbd9ab3f3ac28Roland Levillain return is_baseline_; 2703e3d73349a2de81d14e2279f60ffbd9ab3f3ac28Roland Levillain } 2713e3d73349a2de81d14e2279f60ffbd9ab3f3ac28Roland Levillain 272f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray bool IsLeafMethod() const { 273f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray return is_leaf_; 274f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray } 275f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray 276f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray void MarkNotLeaf() { 277f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray is_leaf_ = false; 278c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray requires_current_method_ = true; 279c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray } 280c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray 281c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray void SetRequiresCurrentMethod() { 282c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray requires_current_method_ = true; 283c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray } 284c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray 285c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray bool RequiresCurrentMethod() const { 286c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray return requires_current_method_; 287f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray } 288f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray 2893c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // Clears the spill slots taken by loop phis in the `LocationSummary` of the 2903c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // suspend check. This is called when the code generator generates code 2913c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // for the suspend check at the back edge (instead of where the suspend check 2923c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // is, which is the loop entry). At this point, the spill slots for the phis 2933c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // have not been written to. 2943c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray void ClearSpillSlotsFromLoopPhisInStackMap(HSuspendCheck* suspend_check) const; 2953c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray 29671175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray bool* GetBlockedCoreRegisters() const { return blocked_core_registers_; } 297102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray bool* GetBlockedFloatingPointRegisters() const { return blocked_fpu_registers_; } 29871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray 29919a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray // Helper that returns the pointer offset of an index in an object array. 30019a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray // Note: this method assumes we always have the same pointer size, regardless 30119a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray // of the architecture. 30219a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray static size_t GetCacheOffset(uint32_t index); 303e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier // Pointer variant for ArtMethod and ArtField arrays. 304e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier size_t GetCachePointerOffset(uint32_t index); 30519a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray 3069021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray void EmitParallelMoves(Location from1, 3079021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray Location to1, 3089021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray Primitive::Type type1, 3099021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray Location from2, 3109021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray Location to2, 3119021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray Primitive::Type type2); 312f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray 313af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray static bool StoreNeedsWriteBarrier(Primitive::Type type, HInstruction* value) { 314522e2241f5b5f331d0aa2f8508f4c97973f7f012David Brazdil // Check that null value is not represented as an integer constant. 315522e2241f5b5f331d0aa2f8508f4c97973f7f012David Brazdil DCHECK(type != Primitive::kPrimNot || !value->IsIntConstant()); 316522e2241f5b5f331d0aa2f8508f4c97973f7f012David Brazdil return type == Primitive::kPrimNot && !value->IsNullConstant(); 317af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray } 318af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray 31978e3ef6bc5f8aa149f2f8bf0c78ce854c2f910faAlexandre Rames void ValidateInvokeRuntime(HInstruction* instruction, SlowPathCode* slow_path); 32078e3ef6bc5f8aa149f2f8bf0c78ce854c2f910faAlexandre Rames 321988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray void AddAllocatedRegister(Location location) { 322988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray allocated_registers_.Add(location); 323988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray } 324988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray 32545b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray bool HasAllocatedRegister(bool is_core, int reg) const { 32645b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray return is_core 32745b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray ? allocated_registers_.ContainsCoreRegister(reg) 32845b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray : allocated_registers_.ContainsFloatingPointRegister(reg); 32945b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray } 33045b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray 331c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray void AllocateLocations(HInstruction* instruction); 332c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray 333aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain // Tells whether the stack frame of the compiled method is 334aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain // considered "empty", that is either actually having a size of zero, 335aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain // or just containing the saved return address register. 336aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain bool HasEmptyFrame() const { 337aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain return GetFrameSize() == (CallPushesPC() ? GetWordSize() : 0); 338aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain } 339aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain 340d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray static int32_t GetInt32ValueOf(HConstant* constant) { 341d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray if (constant->IsIntConstant()) { 342d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray return constant->AsIntConstant()->GetValue(); 343d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } else if (constant->IsNullConstant()) { 344d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray return 0; 345d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } else { 346d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray DCHECK(constant->IsFloatConstant()); 347da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain return bit_cast<int32_t, float>(constant->AsFloatConstant()->GetValue()); 348d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } 349d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } 350d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray 351d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray static int64_t GetInt64ValueOf(HConstant* constant) { 352d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray if (constant->IsIntConstant()) { 353d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray return constant->AsIntConstant()->GetValue(); 354d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } else if (constant->IsNullConstant()) { 355d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray return 0; 356d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } else if (constant->IsFloatConstant()) { 357da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain return bit_cast<int32_t, float>(constant->AsFloatConstant()->GetValue()); 358d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } else if (constant->IsLongConstant()) { 359d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray return constant->AsLongConstant()->GetValue(); 360d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } else { 361d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray DCHECK(constant->IsDoubleConstant()); 362da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain return bit_cast<int64_t, double>(constant->AsDoubleConstant()->GetValue()); 363d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } 364d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } 365d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray 366a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray size_t GetFirstRegisterSlotInSlowPath() const { 367a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray return first_register_slot_in_slow_path_; 368a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray } 369a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray 370a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray uint32_t FrameEntrySpillSize() const { 371a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray return GetFpuSpillSize() + GetCoreSpillSize(); 372a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray } 373a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray 374ec525fc30848189051b888da53ba051bc0878b78Roland Levillain virtual ParallelMoveResolver* GetMoveResolver() = 0; 375a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray 376fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray static void CreateCommonInvokeLocationSummary( 377fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray HInvoke* invoke, InvokeDexCallingConventionVisitor* visitor); 378fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray 379175dc732c80e6f2afd83209348124df349290ba8Calin Juravle void GenerateInvokeUnresolvedRuntimeCall(HInvokeUnresolved* invoke); 380175dc732c80e6f2afd83209348124df349290ba8Calin Juravle 381eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames void SetDisassemblyInformation(DisassemblyInformation* info) { disasm_info_ = info; } 382eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames DisassemblyInformation* GetDisassemblyInformation() const { return disasm_info_; } 383eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames 384175dc732c80e6f2afd83209348124df349290ba8Calin Juravle virtual void InvokeRuntime(QuickEntrypointEnum entrypoint, 385175dc732c80e6f2afd83209348124df349290ba8Calin Juravle HInstruction* instruction, 386175dc732c80e6f2afd83209348124df349290ba8Calin Juravle uint32_t dex_pc, 387175dc732c80e6f2afd83209348124df349290ba8Calin Juravle SlowPathCode* slow_path) = 0; 388175dc732c80e6f2afd83209348124df349290ba8Calin Juravle 389787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray protected: 390581550137ee3a068a14224870e71aeee924a0646Vladimir Marko // Method patch info used for recording locations of required linker patches and 391581550137ee3a068a14224870e71aeee924a0646Vladimir Marko // target methods. The target method can be used for various purposes, whether for 392581550137ee3a068a14224870e71aeee924a0646Vladimir Marko // patching the address of the method or the code pointer or a PC-relative call. 393581550137ee3a068a14224870e71aeee924a0646Vladimir Marko template <typename LabelType> 394581550137ee3a068a14224870e71aeee924a0646Vladimir Marko struct MethodPatchInfo { 395581550137ee3a068a14224870e71aeee924a0646Vladimir Marko explicit MethodPatchInfo(MethodReference m) : target_method(m), label() { } 396581550137ee3a068a14224870e71aeee924a0646Vladimir Marko 397581550137ee3a068a14224870e71aeee924a0646Vladimir Marko MethodReference target_method; 398581550137ee3a068a14224870e71aeee924a0646Vladimir Marko LabelType label; 399581550137ee3a068a14224870e71aeee924a0646Vladimir Marko }; 400581550137ee3a068a14224870e71aeee924a0646Vladimir Marko 40171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray CodeGenerator(HGraph* graph, 40271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray size_t number_of_core_registers, 40371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray size_t number_of_fpu_registers, 404cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle size_t number_of_register_pairs, 405988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray uint32_t core_callee_save_mask, 406988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray uint32_t fpu_callee_save_mask, 407ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu const CompilerOptions& compiler_options, 408ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu OptimizingCompilerStats* stats) 409c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray : frame_size_(0), 4104361beff5bc540c43ab7c072c99994adc4ed78f9Nicolas Geoffray core_spill_mask_(0), 411d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray fpu_spill_mask_(0), 4123bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray first_register_slot_in_slow_path_(0), 41371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray blocked_core_registers_(graph->GetArena()->AllocArray<bool>(number_of_core_registers)), 41471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray blocked_fpu_registers_(graph->GetArena()->AllocArray<bool>(number_of_fpu_registers)), 41571175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray blocked_register_pairs_(graph->GetArena()->AllocArray<bool>(number_of_register_pairs)), 41671175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray number_of_core_registers_(number_of_core_registers), 41771175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray number_of_fpu_registers_(number_of_fpu_registers), 41871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray number_of_register_pairs_(number_of_register_pairs), 419988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray core_callee_save_mask_(core_callee_save_mask), 420988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray fpu_callee_save_mask_(fpu_callee_save_mask), 421cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko stack_map_stream_(graph->GetArena()), 422cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko block_order_(nullptr), 4233e3d73349a2de81d14e2279f60ffbd9ab3f3ac28Roland Levillain is_baseline_(false), 424eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames disasm_info_(nullptr), 425ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu stats_(stats), 426787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray graph_(graph), 427cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle compiler_options_(compiler_options), 4282a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban src_map_(nullptr), 429e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray slow_paths_(graph->GetArena(), 8), 4304c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray current_block_index_(0), 4313946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray is_leaf_(true), 432cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko requires_current_method_(false) {} 433d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 434a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray // Register allocation logic. 435a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray void AllocateRegistersLocally(HInstruction* instruction) const; 436a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray 437a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray // Backend specific implementation for allocating a register. 43871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray virtual Location AllocateFreeRegister(Primitive::Type type) const = 0; 439a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray 44071175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray static size_t FindFreeEntry(bool* array, size_t length); 4413c03503d66df3b4440f851ae7d0c4fae5e7872dfNicolas Geoffray static size_t FindTwoFreeConsecutiveAlignedEntries(bool* array, size_t length); 442a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray 443a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray virtual Location GetStackLocation(HLoadLocal* load) const = 0; 444a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray 445c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray virtual HGraphVisitor* GetLocationBuilder() = 0; 446c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray virtual HGraphVisitor* GetInstructionVisitor() = 0; 447f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray 448d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray // Returns the location of the first spilled entry for floating point registers, 449d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray // relative to the stack pointer. 450d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray uint32_t GetFpuSpillStart() const { 451d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray return GetFrameSize() - FrameEntrySpillSize(); 452d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray } 453d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray 454d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray uint32_t GetFpuSpillSize() const { 455d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray return POPCOUNT(fpu_spill_mask_) * GetFloatingPointSpillSlotSize(); 456d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray } 457d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray 458d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray uint32_t GetCoreSpillSize() const { 459d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray return POPCOUNT(core_spill_mask_) * GetWordSize(); 460d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray } 461d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray 462c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray bool HasAllocatedCalleeSaveRegisters() const { 463c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray // We check the core registers against 1 because it always comprises the return PC. 464c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray return (POPCOUNT(allocated_registers_.GetCoreRegisters() & core_callee_save_mask_) != 1) 465c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray || (POPCOUNT(allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_) != 0); 466c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray } 467c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray 468c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray bool CallPushesPC() const { 469c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray InstructionSet instruction_set = GetInstructionSet(); 470c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray return instruction_set == kX86 || instruction_set == kX86_64; 471c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray } 472c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray 473dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray // Arm64 has its own type for a label, so we need to templatize this method 474dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray // to share the logic. 475581550137ee3a068a14224870e71aeee924a0646Vladimir Marko template <typename LabelType> 476581550137ee3a068a14224870e71aeee924a0646Vladimir Marko LabelType* CommonGetLabelOf(LabelType* raw_pointer_to_labels_array, HBasicBlock* block) const { 477dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray block = FirstNonEmptyBlock(block); 478dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray return raw_pointer_to_labels_array + block->GetBlockId(); 479dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray } 480dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray 4818ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray // Frame size required for this method. 4828ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray uint32_t frame_size_; 4838ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray uint32_t core_spill_mask_; 484d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray uint32_t fpu_spill_mask_; 4853bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray uint32_t first_register_slot_in_slow_path_; 4868ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray 487988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray // Registers that were allocated during linear scan. 488988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray RegisterSet allocated_registers_; 489988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray 49071175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray // Arrays used when doing register allocation to know which 49171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray // registers we can allocate. `SetupBlockedRegisters` updates the 49271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray // arrays. 49371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray bool* const blocked_core_registers_; 49471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray bool* const blocked_fpu_registers_; 49571175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray bool* const blocked_register_pairs_; 49671175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray size_t number_of_core_registers_; 49771175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray size_t number_of_fpu_registers_; 49871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray size_t number_of_register_pairs_; 499988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray const uint32_t core_callee_save_mask_; 500988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray const uint32_t fpu_callee_save_mask_; 50171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray 502cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko StackMapStream stack_map_stream_; 503cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 504cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // The order to use for code generation. 505fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko const ArenaVector<HBasicBlock*>* block_order_; 506cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 5073e3d73349a2de81d14e2279f60ffbd9ab3f3ac28Roland Levillain // Whether we are using baseline. 5083e3d73349a2de81d14e2279f60ffbd9ab3f3ac28Roland Levillain bool is_baseline_; 5093e3d73349a2de81d14e2279f60ffbd9ab3f3ac28Roland Levillain 510eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames DisassemblyInformation* disasm_info_; 511eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames 512bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray private: 513c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray void InitLocationsBaseline(HInstruction* instruction); 5143bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray size_t GetStackOffsetOfSavedRegister(size_t index); 515eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames void GenerateSlowPaths(); 5164c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray void CompileInternal(CodeAllocator* allocator, bool is_baseline); 5175f8741860d465410bfed495dbb5f794590d338daMark Mendell void BlockIfInRegister(Location location, bool is_out = false) const; 518b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray void EmitEnvironment(HEnvironment* environment, SlowPathCode* slow_path); 519d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 520ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu OptimizingCompilerStats* stats_; 521ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu 522787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray HGraph* const graph_; 523cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle const CompilerOptions& compiler_options_; 524d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 5252a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban // Native to dex_pc map used for native debugging/profiling tools. 5262a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban DefaultSrcMap* src_map_; 527e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray GrowableArray<SlowPathCode*> slow_paths_; 528d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 5294c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray // The current block index in `block_order_` of the block 5304c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray // we are generating code for. 5314c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray size_t current_block_index_; 5324c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray 533c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray // Whether the method is a leaf method. 534f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray bool is_leaf_; 535f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray 536c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray // Whether an instruction in the graph accesses the current method. 537c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray bool requires_current_method_; 538c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray 539c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky friend class OptimizingCFITest; 540c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky 541d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(CodeGenerator); 542d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}; 543d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 5447fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffraytemplate <typename C, typename F> 5454a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffrayclass CallingConvention { 5464a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray public: 5477fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray CallingConvention(const C* registers, 5487fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray size_t number_of_registers, 5497fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray const F* fpu_registers, 550e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier size_t number_of_fpu_registers, 551e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier size_t pointer_size) 5527fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray : registers_(registers), 5537fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray number_of_registers_(number_of_registers), 5547fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray fpu_registers_(fpu_registers), 555e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier number_of_fpu_registers_(number_of_fpu_registers), 556e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier pointer_size_(pointer_size) {} 5574a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray 5584a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray size_t GetNumberOfRegisters() const { return number_of_registers_; } 5597fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray size_t GetNumberOfFpuRegisters() const { return number_of_fpu_registers_; } 5604a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray 5617fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray C GetRegisterAt(size_t index) const { 5624a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray DCHECK_LT(index, number_of_registers_); 5634a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray return registers_[index]; 5644a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray } 5654a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray 5667fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray F GetFpuRegisterAt(size_t index) const { 5677fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray DCHECK_LT(index, number_of_fpu_registers_); 5687fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray return fpu_registers_[index]; 5697fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray } 5707fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray 5717fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray size_t GetStackOffsetOf(size_t index) const { 5724a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray // We still reserve the space for parameters passed by registers. 573e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier // Add space for the method pointer. 574e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier return pointer_size_ + index * kVRegSize; 5754a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray } 5764a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray 5774a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray private: 5787fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray const C* registers_; 5794a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray const size_t number_of_registers_; 5807fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray const F* fpu_registers_; 5817fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray const size_t number_of_fpu_registers_; 582e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier const size_t pointer_size_; 5834a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray 5844a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(CallingConvention); 5854a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray}; 5864a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray 587d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray} // namespace art 588d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 589d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#endif // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_ 590