1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set.h" 21*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set_features.h" 22*795d594fSAndroid Build Coastguard Worker #include "base/arena_containers.h" 23*795d594fSAndroid Build Coastguard Worker #include "base/arena_object.h" 24*795d594fSAndroid Build Coastguard Worker #include "base/array_ref.h" 25*795d594fSAndroid Build Coastguard Worker #include "base/bit_field.h" 26*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h" 27*795d594fSAndroid Build Coastguard Worker #include "base/globals.h" 28*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 29*795d594fSAndroid Build Coastguard Worker #include "base/memory_region.h" 30*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h" 31*795d594fSAndroid Build Coastguard Worker #include "class_root.h" 32*795d594fSAndroid Build Coastguard Worker #include "dex/proto_reference.h" 33*795d594fSAndroid Build Coastguard Worker #include "dex/string_reference.h" 34*795d594fSAndroid Build Coastguard Worker #include "dex/type_reference.h" 35*795d594fSAndroid Build Coastguard Worker #include "graph_visualizer.h" 36*795d594fSAndroid Build Coastguard Worker #include "locations.h" 37*795d594fSAndroid Build Coastguard Worker #include "mirror/method_type.h" 38*795d594fSAndroid Build Coastguard Worker #include "nodes.h" 39*795d594fSAndroid Build Coastguard Worker #include "oat/oat_quick_method_header.h" 40*795d594fSAndroid Build Coastguard Worker #include "optimizing_compiler_stats.h" 41*795d594fSAndroid Build Coastguard Worker #include "read_barrier_option.h" 42*795d594fSAndroid Build Coastguard Worker #include "stack.h" 43*795d594fSAndroid Build Coastguard Worker #include "subtype_check.h" 44*795d594fSAndroid Build Coastguard Worker #include "utils/assembler.h" 45*795d594fSAndroid Build Coastguard Worker #include "utils/label.h" 46*795d594fSAndroid Build Coastguard Worker 47*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN { 48*795d594fSAndroid Build Coastguard Worker 49*795d594fSAndroid Build Coastguard Worker // Binary encoding of 2^32 for type double. 50*795d594fSAndroid Build Coastguard Worker static int64_t constexpr k2Pow32EncodingForDouble = INT64_C(0x41F0000000000000); 51*795d594fSAndroid Build Coastguard Worker // Binary encoding of 2^31 for type double. 52*795d594fSAndroid Build Coastguard Worker static int64_t constexpr k2Pow31EncodingForDouble = INT64_C(0x41E0000000000000); 53*795d594fSAndroid Build Coastguard Worker 54*795d594fSAndroid Build Coastguard Worker // Minimum value for a primitive integer. 55*795d594fSAndroid Build Coastguard Worker static int32_t constexpr kPrimIntMin = 0x80000000; 56*795d594fSAndroid Build Coastguard Worker // Minimum value for a primitive long. 57*795d594fSAndroid Build Coastguard Worker static int64_t constexpr kPrimLongMin = INT64_C(0x8000000000000000); 58*795d594fSAndroid Build Coastguard Worker 59*795d594fSAndroid Build Coastguard Worker // Maximum value for a primitive integer. 60*795d594fSAndroid Build Coastguard Worker static int32_t constexpr kPrimIntMax = 0x7fffffff; 61*795d594fSAndroid Build Coastguard Worker // Maximum value for a primitive long. 62*795d594fSAndroid Build Coastguard Worker static int64_t constexpr kPrimLongMax = INT64_C(0x7fffffffffffffff); 63*795d594fSAndroid Build Coastguard Worker 64*795d594fSAndroid Build Coastguard Worker constexpr size_t kClassStatusLsbPosition = SubtypeCheckBits::BitStructSizeOf(); 65*795d594fSAndroid Build Coastguard Worker constexpr size_t kClassStatusByteOffset = 66*795d594fSAndroid Build Coastguard Worker mirror::Class::StatusOffset().SizeValue() + (kClassStatusLsbPosition / kBitsPerByte); 67*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kShiftedVisiblyInitializedValue = enum_cast<uint32_t>( 68*795d594fSAndroid Build Coastguard Worker ClassStatus::kVisiblyInitialized) << (kClassStatusLsbPosition % kBitsPerByte); 69*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kShiftedInitializingValue = 70*795d594fSAndroid Build Coastguard Worker enum_cast<uint32_t>(ClassStatus::kInitializing) << (kClassStatusLsbPosition % kBitsPerByte); 71*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kShiftedInitializedValue = 72*795d594fSAndroid Build Coastguard Worker enum_cast<uint32_t>(ClassStatus::kInitialized) << (kClassStatusLsbPosition % kBitsPerByte); 73*795d594fSAndroid Build Coastguard Worker 74*795d594fSAndroid Build Coastguard Worker class Assembler; 75*795d594fSAndroid Build Coastguard Worker class CodeGenerationData; 76*795d594fSAndroid Build Coastguard Worker class CodeGenerator; 77*795d594fSAndroid Build Coastguard Worker class CompilerOptions; 78*795d594fSAndroid Build Coastguard Worker class StackMapStream; 79*795d594fSAndroid Build Coastguard Worker class ParallelMoveResolver; 80*795d594fSAndroid Build Coastguard Worker 81*795d594fSAndroid Build Coastguard Worker namespace linker { 82*795d594fSAndroid Build Coastguard Worker class LinkerPatch; 83*795d594fSAndroid Build Coastguard Worker } // namespace linker 84*795d594fSAndroid Build Coastguard Worker 85*795d594fSAndroid Build Coastguard Worker class SlowPathCode : public DeletableArenaObject<kArenaAllocSlowPaths> { 86*795d594fSAndroid Build Coastguard Worker public: SlowPathCode(HInstruction * instruction)87*795d594fSAndroid Build Coastguard Worker explicit SlowPathCode(HInstruction* instruction) : instruction_(instruction) { 88*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < kMaximumNumberOfExpectedRegisters; ++i) { 89*795d594fSAndroid Build Coastguard Worker saved_core_stack_offsets_[i] = kRegisterNotSaved; 90*795d594fSAndroid Build Coastguard Worker saved_fpu_stack_offsets_[i] = kRegisterNotSaved; 91*795d594fSAndroid Build Coastguard Worker } 92*795d594fSAndroid Build Coastguard Worker } 93*795d594fSAndroid Build Coastguard Worker ~SlowPathCode()94*795d594fSAndroid Build Coastguard Worker virtual ~SlowPathCode() {} 95*795d594fSAndroid Build Coastguard Worker 96*795d594fSAndroid Build Coastguard Worker virtual void EmitNativeCode(CodeGenerator* codegen) = 0; 97*795d594fSAndroid Build Coastguard Worker 98*795d594fSAndroid Build Coastguard Worker // Save live core and floating-point caller-save registers and 99*795d594fSAndroid Build Coastguard Worker // update the stack mask in `locations` for registers holding object 100*795d594fSAndroid Build Coastguard Worker // references. 101*795d594fSAndroid Build Coastguard Worker virtual void SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations); 102*795d594fSAndroid Build Coastguard Worker // Restore live core and floating-point caller-save registers. 103*795d594fSAndroid Build Coastguard Worker virtual void RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations); 104*795d594fSAndroid Build Coastguard Worker IsCoreRegisterSaved(int reg)105*795d594fSAndroid Build Coastguard Worker bool IsCoreRegisterSaved(int reg) const { 106*795d594fSAndroid Build Coastguard Worker return saved_core_stack_offsets_[reg] != kRegisterNotSaved; 107*795d594fSAndroid Build Coastguard Worker } 108*795d594fSAndroid Build Coastguard Worker IsFpuRegisterSaved(int reg)109*795d594fSAndroid Build Coastguard Worker bool IsFpuRegisterSaved(int reg) const { 110*795d594fSAndroid Build Coastguard Worker return saved_fpu_stack_offsets_[reg] != kRegisterNotSaved; 111*795d594fSAndroid Build Coastguard Worker } 112*795d594fSAndroid Build Coastguard Worker GetStackOffsetOfCoreRegister(int reg)113*795d594fSAndroid Build Coastguard Worker uint32_t GetStackOffsetOfCoreRegister(int reg) const { 114*795d594fSAndroid Build Coastguard Worker return saved_core_stack_offsets_[reg]; 115*795d594fSAndroid Build Coastguard Worker } 116*795d594fSAndroid Build Coastguard Worker GetStackOffsetOfFpuRegister(int reg)117*795d594fSAndroid Build Coastguard Worker uint32_t GetStackOffsetOfFpuRegister(int reg) const { 118*795d594fSAndroid Build Coastguard Worker return saved_fpu_stack_offsets_[reg]; 119*795d594fSAndroid Build Coastguard Worker } 120*795d594fSAndroid Build Coastguard Worker IsFatal()121*795d594fSAndroid Build Coastguard Worker virtual bool IsFatal() const { return false; } 122*795d594fSAndroid Build Coastguard Worker 123*795d594fSAndroid Build Coastguard Worker virtual const char* GetDescription() const = 0; 124*795d594fSAndroid Build Coastguard Worker GetEntryLabel()125*795d594fSAndroid Build Coastguard Worker Label* GetEntryLabel() { return &entry_label_; } GetExitLabel()126*795d594fSAndroid Build Coastguard Worker Label* GetExitLabel() { return &exit_label_; } 127*795d594fSAndroid Build Coastguard Worker GetInstruction()128*795d594fSAndroid Build Coastguard Worker HInstruction* GetInstruction() const { 129*795d594fSAndroid Build Coastguard Worker return instruction_; 130*795d594fSAndroid Build Coastguard Worker } 131*795d594fSAndroid Build Coastguard Worker GetDexPc()132*795d594fSAndroid Build Coastguard Worker uint32_t GetDexPc() const { 133*795d594fSAndroid Build Coastguard Worker return instruction_ != nullptr ? instruction_->GetDexPc() : kNoDexPc; 134*795d594fSAndroid Build Coastguard Worker } 135*795d594fSAndroid Build Coastguard Worker 136*795d594fSAndroid Build Coastguard Worker protected: 137*795d594fSAndroid Build Coastguard Worker static constexpr size_t kMaximumNumberOfExpectedRegisters = 32; 138*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kRegisterNotSaved = -1; 139*795d594fSAndroid Build Coastguard Worker // The instruction where this slow path is happening. 140*795d594fSAndroid Build Coastguard Worker HInstruction* instruction_; 141*795d594fSAndroid Build Coastguard Worker uint32_t saved_core_stack_offsets_[kMaximumNumberOfExpectedRegisters]; 142*795d594fSAndroid Build Coastguard Worker uint32_t saved_fpu_stack_offsets_[kMaximumNumberOfExpectedRegisters]; 143*795d594fSAndroid Build Coastguard Worker 144*795d594fSAndroid Build Coastguard Worker private: 145*795d594fSAndroid Build Coastguard Worker Label entry_label_; 146*795d594fSAndroid Build Coastguard Worker Label exit_label_; 147*795d594fSAndroid Build Coastguard Worker 148*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(SlowPathCode); 149*795d594fSAndroid Build Coastguard Worker }; 150*795d594fSAndroid Build Coastguard Worker 151*795d594fSAndroid Build Coastguard Worker class InvokeDexCallingConventionVisitor { 152*795d594fSAndroid Build Coastguard Worker public: 153*795d594fSAndroid Build Coastguard Worker virtual Location GetNextLocation(DataType::Type type) = 0; 154*795d594fSAndroid Build Coastguard Worker virtual Location GetReturnLocation(DataType::Type type) const = 0; 155*795d594fSAndroid Build Coastguard Worker virtual Location GetMethodLocation() const = 0; 156*795d594fSAndroid Build Coastguard Worker 157*795d594fSAndroid Build Coastguard Worker protected: InvokeDexCallingConventionVisitor()158*795d594fSAndroid Build Coastguard Worker InvokeDexCallingConventionVisitor() {} ~InvokeDexCallingConventionVisitor()159*795d594fSAndroid Build Coastguard Worker virtual ~InvokeDexCallingConventionVisitor() {} 160*795d594fSAndroid Build Coastguard Worker 161*795d594fSAndroid Build Coastguard Worker // The current index for core registers. 162*795d594fSAndroid Build Coastguard Worker uint32_t gp_index_ = 0u; 163*795d594fSAndroid Build Coastguard Worker // The current index for floating-point registers. 164*795d594fSAndroid Build Coastguard Worker uint32_t float_index_ = 0u; 165*795d594fSAndroid Build Coastguard Worker // The current stack index. 166*795d594fSAndroid Build Coastguard Worker uint32_t stack_index_ = 0u; 167*795d594fSAndroid Build Coastguard Worker 168*795d594fSAndroid Build Coastguard Worker private: 169*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor); 170*795d594fSAndroid Build Coastguard Worker }; 171*795d594fSAndroid Build Coastguard Worker 172*795d594fSAndroid Build Coastguard Worker class FieldAccessCallingConvention { 173*795d594fSAndroid Build Coastguard Worker public: 174*795d594fSAndroid Build Coastguard Worker virtual Location GetObjectLocation() const = 0; 175*795d594fSAndroid Build Coastguard Worker virtual Location GetFieldIndexLocation() const = 0; 176*795d594fSAndroid Build Coastguard Worker virtual Location GetReturnLocation(DataType::Type type) const = 0; 177*795d594fSAndroid Build Coastguard Worker virtual Location GetSetValueLocation(DataType::Type type, bool is_instance) const = 0; 178*795d594fSAndroid Build Coastguard Worker virtual Location GetFpuLocation(DataType::Type type) const = 0; ~FieldAccessCallingConvention()179*795d594fSAndroid Build Coastguard Worker virtual ~FieldAccessCallingConvention() {} 180*795d594fSAndroid Build Coastguard Worker 181*795d594fSAndroid Build Coastguard Worker protected: FieldAccessCallingConvention()182*795d594fSAndroid Build Coastguard Worker FieldAccessCallingConvention() {} 183*795d594fSAndroid Build Coastguard Worker 184*795d594fSAndroid Build Coastguard Worker private: 185*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(FieldAccessCallingConvention); 186*795d594fSAndroid Build Coastguard Worker }; 187*795d594fSAndroid Build Coastguard Worker 188*795d594fSAndroid Build Coastguard Worker class CodeGenerator : public DeletableArenaObject<kArenaAllocCodeGenerator> { 189*795d594fSAndroid Build Coastguard Worker public: 190*795d594fSAndroid Build Coastguard Worker // Compiles the graph to executable instructions. 191*795d594fSAndroid Build Coastguard Worker void Compile(); 192*795d594fSAndroid Build Coastguard Worker static std::unique_ptr<CodeGenerator> Create(HGraph* graph, 193*795d594fSAndroid Build Coastguard Worker const CompilerOptions& compiler_options, 194*795d594fSAndroid Build Coastguard Worker OptimizingCompilerStats* stats = nullptr); 195*795d594fSAndroid Build Coastguard Worker virtual ~CodeGenerator(); 196*795d594fSAndroid Build Coastguard Worker 197*795d594fSAndroid Build Coastguard Worker // Get the graph. This is the outermost graph, never the graph of a method being inlined. GetGraph()198*795d594fSAndroid Build Coastguard Worker HGraph* GetGraph() const { return graph_; } 199*795d594fSAndroid Build Coastguard Worker 200*795d594fSAndroid Build Coastguard Worker HBasicBlock* GetNextBlockToEmit() const; 201*795d594fSAndroid Build Coastguard Worker HBasicBlock* FirstNonEmptyBlock(HBasicBlock* block) const; 202*795d594fSAndroid Build Coastguard Worker bool GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) const; 203*795d594fSAndroid Build Coastguard Worker GetStackSlotOfParameter(HParameterValue * parameter)204*795d594fSAndroid Build Coastguard Worker size_t GetStackSlotOfParameter(HParameterValue* parameter) const { 205*795d594fSAndroid Build Coastguard Worker // Note that this follows the current calling convention. 206*795d594fSAndroid Build Coastguard Worker return GetFrameSize() 207*795d594fSAndroid Build Coastguard Worker + static_cast<size_t>(InstructionSetPointerSize(GetInstructionSet())) // Art method 208*795d594fSAndroid Build Coastguard Worker + parameter->GetIndex() * kVRegSize; 209*795d594fSAndroid Build Coastguard Worker } 210*795d594fSAndroid Build Coastguard Worker 211*795d594fSAndroid Build Coastguard Worker virtual void Initialize() = 0; 212*795d594fSAndroid Build Coastguard Worker virtual void Finalize(); 213*795d594fSAndroid Build Coastguard Worker virtual void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches); 214*795d594fSAndroid Build Coastguard Worker virtual bool NeedsThunkCode(const linker::LinkerPatch& patch) const; 215*795d594fSAndroid Build Coastguard Worker virtual void EmitThunkCode(const linker::LinkerPatch& patch, 216*795d594fSAndroid Build Coastguard Worker /*out*/ ArenaVector<uint8_t>* code, 217*795d594fSAndroid Build Coastguard Worker /*out*/ std::string* debug_name); 218*795d594fSAndroid Build Coastguard Worker virtual void GenerateFrameEntry() = 0; 219*795d594fSAndroid Build Coastguard Worker virtual void GenerateFrameExit() = 0; 220*795d594fSAndroid Build Coastguard Worker virtual void Bind(HBasicBlock* block) = 0; 221*795d594fSAndroid Build Coastguard Worker virtual void MoveConstant(Location destination, int32_t value) = 0; 222*795d594fSAndroid Build Coastguard Worker virtual void MoveLocation(Location dst, Location src, DataType::Type dst_type) = 0; 223*795d594fSAndroid Build Coastguard Worker virtual void AddLocationAsTemp(Location location, LocationSummary* locations) = 0; 224*795d594fSAndroid Build Coastguard Worker 225*795d594fSAndroid Build Coastguard Worker virtual Assembler* GetAssembler() = 0; 226*795d594fSAndroid Build Coastguard Worker virtual const Assembler& GetAssembler() const = 0; 227*795d594fSAndroid Build Coastguard Worker virtual size_t GetWordSize() const = 0; 228*795d594fSAndroid Build Coastguard Worker 229*795d594fSAndroid Build Coastguard Worker // Returns whether the target supports predicated SIMD instructions. SupportsPredicatedSIMD()230*795d594fSAndroid Build Coastguard Worker virtual bool SupportsPredicatedSIMD() const { return false; } 231*795d594fSAndroid Build Coastguard Worker 232*795d594fSAndroid Build Coastguard Worker // Get FP register width in bytes for spilling/restoring in the slow paths. 233*795d594fSAndroid Build Coastguard Worker // 234*795d594fSAndroid Build Coastguard Worker // Note: In SIMD graphs this should return SIMD register width as all FP and SIMD registers 235*795d594fSAndroid Build Coastguard Worker // alias and live SIMD registers are forced to be spilled in full size in the slow paths. GetSlowPathFPWidth()236*795d594fSAndroid Build Coastguard Worker virtual size_t GetSlowPathFPWidth() const { 237*795d594fSAndroid Build Coastguard Worker // Default implementation. 238*795d594fSAndroid Build Coastguard Worker return GetCalleePreservedFPWidth(); 239*795d594fSAndroid Build Coastguard Worker } 240*795d594fSAndroid Build Coastguard Worker 241*795d594fSAndroid Build Coastguard Worker // Get FP register width required to be preserved by the target ABI. 242*795d594fSAndroid Build Coastguard Worker virtual size_t GetCalleePreservedFPWidth() const = 0; 243*795d594fSAndroid Build Coastguard Worker 244*795d594fSAndroid Build Coastguard Worker // Get the size of the target SIMD register in bytes. 245*795d594fSAndroid Build Coastguard Worker virtual size_t GetSIMDRegisterWidth() const = 0; 246*795d594fSAndroid Build Coastguard Worker virtual uintptr_t GetAddressOf(HBasicBlock* block) = 0; 247*795d594fSAndroid Build Coastguard Worker void InitializeCodeGeneration(size_t number_of_spill_slots, 248*795d594fSAndroid Build Coastguard Worker size_t maximum_safepoint_spill_size, 249*795d594fSAndroid Build Coastguard Worker size_t number_of_out_slots, 250*795d594fSAndroid Build Coastguard Worker const ArenaVector<HBasicBlock*>& block_order); 251*795d594fSAndroid Build Coastguard Worker // Backends can override this as necessary. For most, no special alignment is required. GetPreferredSlotsAlignment()252*795d594fSAndroid Build Coastguard Worker virtual uint32_t GetPreferredSlotsAlignment() const { return 1; } 253*795d594fSAndroid Build Coastguard Worker GetFrameSize()254*795d594fSAndroid Build Coastguard Worker uint32_t GetFrameSize() const { return frame_size_; } SetFrameSize(uint32_t size)255*795d594fSAndroid Build Coastguard Worker void SetFrameSize(uint32_t size) { frame_size_ = size; } GetMaximumFrameSize()256*795d594fSAndroid Build Coastguard Worker uint32_t GetMaximumFrameSize() const { 257*795d594fSAndroid Build Coastguard Worker return GetStackOverflowReservedBytes(GetInstructionSet()); 258*795d594fSAndroid Build Coastguard Worker } 259*795d594fSAndroid Build Coastguard Worker GetCoreSpillMask()260*795d594fSAndroid Build Coastguard Worker uint32_t GetCoreSpillMask() const { return core_spill_mask_; } GetFpuSpillMask()261*795d594fSAndroid Build Coastguard Worker uint32_t GetFpuSpillMask() const { return fpu_spill_mask_; } 262*795d594fSAndroid Build Coastguard Worker GetNumberOfCoreRegisters()263*795d594fSAndroid Build Coastguard Worker size_t GetNumberOfCoreRegisters() const { return number_of_core_registers_; } GetNumberOfFloatingPointRegisters()264*795d594fSAndroid Build Coastguard Worker size_t GetNumberOfFloatingPointRegisters() const { return number_of_fpu_registers_; } 265*795d594fSAndroid Build Coastguard Worker virtual void SetupBlockedRegisters() const = 0; 266*795d594fSAndroid Build Coastguard Worker ComputeSpillMask()267*795d594fSAndroid Build Coastguard Worker virtual void ComputeSpillMask() { 268*795d594fSAndroid Build Coastguard Worker core_spill_mask_ = allocated_registers_.GetCoreRegisters() & core_callee_save_mask_; 269*795d594fSAndroid Build Coastguard Worker DCHECK_NE(core_spill_mask_, 0u) << "At least the return address register must be saved"; 270*795d594fSAndroid Build Coastguard Worker fpu_spill_mask_ = allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_; 271*795d594fSAndroid Build Coastguard Worker } 272*795d594fSAndroid Build Coastguard Worker 273*795d594fSAndroid Build Coastguard Worker virtual void DumpCoreRegister(std::ostream& stream, int reg) const = 0; 274*795d594fSAndroid Build Coastguard Worker virtual void DumpFloatingPointRegister(std::ostream& stream, int reg) const = 0; 275*795d594fSAndroid Build Coastguard Worker virtual InstructionSet GetInstructionSet() const = 0; 276*795d594fSAndroid Build Coastguard Worker 277*795d594fSAndroid Build Coastguard Worker // Saves the register in the stack. Returns the size taken on stack. 278*795d594fSAndroid Build Coastguard Worker virtual size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) = 0; 279*795d594fSAndroid Build Coastguard Worker // Restores the register from the stack. Returns the size taken on stack. 280*795d594fSAndroid Build Coastguard Worker virtual size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) = 0; 281*795d594fSAndroid Build Coastguard Worker 282*795d594fSAndroid Build Coastguard Worker virtual size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0; 283*795d594fSAndroid Build Coastguard Worker virtual size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0; 284*795d594fSAndroid Build Coastguard Worker 285*795d594fSAndroid Build Coastguard Worker virtual bool NeedsTwoRegisters(DataType::Type type) const = 0; 286*795d594fSAndroid Build Coastguard Worker // Returns whether we should split long moves in parallel moves. ShouldSplitLongMoves()287*795d594fSAndroid Build Coastguard Worker virtual bool ShouldSplitLongMoves() const { return false; } 288*795d594fSAndroid Build Coastguard Worker 289*795d594fSAndroid Build Coastguard Worker // Returns true if `invoke` is an implemented intrinsic in this codegen's arch. IsImplementedIntrinsic(HInvoke * invoke)290*795d594fSAndroid Build Coastguard Worker bool IsImplementedIntrinsic(HInvoke* invoke) const { 291*795d594fSAndroid Build Coastguard Worker return invoke->IsIntrinsic() && 292*795d594fSAndroid Build Coastguard Worker !unimplemented_intrinsics_[static_cast<size_t>(invoke->GetIntrinsic())]; 293*795d594fSAndroid Build Coastguard Worker } 294*795d594fSAndroid Build Coastguard Worker GetNumberOfCoreCalleeSaveRegisters()295*795d594fSAndroid Build Coastguard Worker size_t GetNumberOfCoreCalleeSaveRegisters() const { 296*795d594fSAndroid Build Coastguard Worker return POPCOUNT(core_callee_save_mask_); 297*795d594fSAndroid Build Coastguard Worker } 298*795d594fSAndroid Build Coastguard Worker GetNumberOfCoreCallerSaveRegisters()299*795d594fSAndroid Build Coastguard Worker size_t GetNumberOfCoreCallerSaveRegisters() const { 300*795d594fSAndroid Build Coastguard Worker DCHECK_GE(GetNumberOfCoreRegisters(), GetNumberOfCoreCalleeSaveRegisters()); 301*795d594fSAndroid Build Coastguard Worker return GetNumberOfCoreRegisters() - GetNumberOfCoreCalleeSaveRegisters(); 302*795d594fSAndroid Build Coastguard Worker } 303*795d594fSAndroid Build Coastguard Worker IsCoreCalleeSaveRegister(int reg)304*795d594fSAndroid Build Coastguard Worker bool IsCoreCalleeSaveRegister(int reg) const { 305*795d594fSAndroid Build Coastguard Worker return (core_callee_save_mask_ & (1 << reg)) != 0; 306*795d594fSAndroid Build Coastguard Worker } 307*795d594fSAndroid Build Coastguard Worker IsFloatingPointCalleeSaveRegister(int reg)308*795d594fSAndroid Build Coastguard Worker bool IsFloatingPointCalleeSaveRegister(int reg) const { 309*795d594fSAndroid Build Coastguard Worker return (fpu_callee_save_mask_ & (1 << reg)) != 0; 310*795d594fSAndroid Build Coastguard Worker } 311*795d594fSAndroid Build Coastguard Worker GetSlowPathSpills(LocationSummary * locations,bool core_registers)312*795d594fSAndroid Build Coastguard Worker uint32_t GetSlowPathSpills(LocationSummary* locations, bool core_registers) const { 313*795d594fSAndroid Build Coastguard Worker DCHECK(locations->OnlyCallsOnSlowPath() || 314*795d594fSAndroid Build Coastguard Worker (locations->Intrinsified() && locations->CallsOnMainAndSlowPath() && 315*795d594fSAndroid Build Coastguard Worker !locations->HasCustomSlowPathCallingConvention())); 316*795d594fSAndroid Build Coastguard Worker uint32_t live_registers = core_registers 317*795d594fSAndroid Build Coastguard Worker ? locations->GetLiveRegisters()->GetCoreRegisters() 318*795d594fSAndroid Build Coastguard Worker : locations->GetLiveRegisters()->GetFloatingPointRegisters(); 319*795d594fSAndroid Build Coastguard Worker if (locations->HasCustomSlowPathCallingConvention()) { 320*795d594fSAndroid Build Coastguard Worker // Save only the live registers that the custom calling convention wants us to save. 321*795d594fSAndroid Build Coastguard Worker uint32_t caller_saves = core_registers 322*795d594fSAndroid Build Coastguard Worker ? locations->GetCustomSlowPathCallerSaves().GetCoreRegisters() 323*795d594fSAndroid Build Coastguard Worker : locations->GetCustomSlowPathCallerSaves().GetFloatingPointRegisters(); 324*795d594fSAndroid Build Coastguard Worker return live_registers & caller_saves; 325*795d594fSAndroid Build Coastguard Worker } else { 326*795d594fSAndroid Build Coastguard Worker // Default ABI, we need to spill non-callee-save live registers. 327*795d594fSAndroid Build Coastguard Worker uint32_t callee_saves = core_registers ? core_callee_save_mask_ : fpu_callee_save_mask_; 328*795d594fSAndroid Build Coastguard Worker return live_registers & ~callee_saves; 329*795d594fSAndroid Build Coastguard Worker } 330*795d594fSAndroid Build Coastguard Worker } 331*795d594fSAndroid Build Coastguard Worker GetNumberOfSlowPathSpills(LocationSummary * locations,bool core_registers)332*795d594fSAndroid Build Coastguard Worker size_t GetNumberOfSlowPathSpills(LocationSummary* locations, bool core_registers) const { 333*795d594fSAndroid Build Coastguard Worker return POPCOUNT(GetSlowPathSpills(locations, core_registers)); 334*795d594fSAndroid Build Coastguard Worker } 335*795d594fSAndroid Build Coastguard Worker GetStackOffsetOfShouldDeoptimizeFlag()336*795d594fSAndroid Build Coastguard Worker size_t GetStackOffsetOfShouldDeoptimizeFlag() const { 337*795d594fSAndroid Build Coastguard Worker DCHECK(GetGraph()->HasShouldDeoptimizeFlag()); 338*795d594fSAndroid Build Coastguard Worker DCHECK_GE(GetFrameSize(), FrameEntrySpillSize() + kShouldDeoptimizeFlagSize); 339*795d594fSAndroid Build Coastguard Worker return GetFrameSize() - FrameEntrySpillSize() - kShouldDeoptimizeFlagSize; 340*795d594fSAndroid Build Coastguard Worker } 341*795d594fSAndroid Build Coastguard Worker 342*795d594fSAndroid Build Coastguard Worker // Record native to dex mapping for a suspend point. Required by runtime. 343*795d594fSAndroid Build Coastguard Worker void RecordPcInfo(HInstruction* instruction, 344*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc, 345*795d594fSAndroid Build Coastguard Worker uint32_t native_pc, 346*795d594fSAndroid Build Coastguard Worker SlowPathCode* slow_path = nullptr, 347*795d594fSAndroid Build Coastguard Worker bool native_debug_info = false); 348*795d594fSAndroid Build Coastguard Worker 349*795d594fSAndroid Build Coastguard Worker // Record native to dex mapping for a suspend point. 350*795d594fSAndroid Build Coastguard Worker // The native_pc is used from Assembler::CodePosition. 351*795d594fSAndroid Build Coastguard Worker // 352*795d594fSAndroid Build Coastguard Worker // Note: As Assembler::CodePosition is target dependent, it does not guarantee the exact native_pc 353*795d594fSAndroid Build Coastguard Worker // for the instruction. If the exact native_pc is required it must be provided explicitly. 354*795d594fSAndroid Build Coastguard Worker void RecordPcInfo(HInstruction* instruction, 355*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc, 356*795d594fSAndroid Build Coastguard Worker SlowPathCode* slow_path = nullptr, 357*795d594fSAndroid Build Coastguard Worker bool native_debug_info = false); 358*795d594fSAndroid Build Coastguard Worker 359*795d594fSAndroid Build Coastguard Worker // Check whether we have already recorded mapping at this PC. 360*795d594fSAndroid Build Coastguard Worker bool HasStackMapAtCurrentPc(); 361*795d594fSAndroid Build Coastguard Worker 362*795d594fSAndroid Build Coastguard Worker // Record extra stack maps if we support native debugging. 363*795d594fSAndroid Build Coastguard Worker // 364*795d594fSAndroid Build Coastguard Worker // ARM specific behaviour: The recorded native PC might be a branch over pools to instructions 365*795d594fSAndroid Build Coastguard Worker // corresponding the dex PC. 366*795d594fSAndroid Build Coastguard Worker void MaybeRecordNativeDebugInfo(HInstruction* instruction, 367*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc, 368*795d594fSAndroid Build Coastguard Worker SlowPathCode* slow_path = nullptr); 369*795d594fSAndroid Build Coastguard Worker 370*795d594fSAndroid Build Coastguard Worker bool CanMoveNullCheckToUser(HNullCheck* null_check); 371*795d594fSAndroid Build Coastguard Worker virtual void MaybeRecordImplicitNullCheck(HInstruction* instruction); 372*795d594fSAndroid Build Coastguard Worker LocationSummary* CreateThrowingSlowPathLocations( 373*795d594fSAndroid Build Coastguard Worker HInstruction* instruction, RegisterSet caller_saves = RegisterSet::Empty()); 374*795d594fSAndroid Build Coastguard Worker void GenerateNullCheck(HNullCheck* null_check); 375*795d594fSAndroid Build Coastguard Worker virtual void GenerateImplicitNullCheck(HNullCheck* null_check) = 0; 376*795d594fSAndroid Build Coastguard Worker virtual void GenerateExplicitNullCheck(HNullCheck* null_check) = 0; 377*795d594fSAndroid Build Coastguard Worker 378*795d594fSAndroid Build Coastguard Worker // Records a stack map which the runtime might use to set catch phi values 379*795d594fSAndroid Build Coastguard Worker // during exception delivery. 380*795d594fSAndroid Build Coastguard Worker // TODO: Replace with a catch-entering instruction that records the environment. 381*795d594fSAndroid Build Coastguard Worker void RecordCatchBlockInfo(); 382*795d594fSAndroid Build Coastguard Worker GetCompilerOptions()383*795d594fSAndroid Build Coastguard Worker const CompilerOptions& GetCompilerOptions() const { return compiler_options_; } 384*795d594fSAndroid Build Coastguard Worker bool EmitReadBarrier() const; 385*795d594fSAndroid Build Coastguard Worker bool EmitBakerReadBarrier() const; 386*795d594fSAndroid Build Coastguard Worker bool EmitNonBakerReadBarrier() const; 387*795d594fSAndroid Build Coastguard Worker ReadBarrierOption GetCompilerReadBarrierOption() const; 388*795d594fSAndroid Build Coastguard Worker 389*795d594fSAndroid Build Coastguard Worker // Returns true if we should check the GC card for consistency purposes. 390*795d594fSAndroid Build Coastguard Worker bool ShouldCheckGCCard(DataType::Type type, 391*795d594fSAndroid Build Coastguard Worker HInstruction* value, 392*795d594fSAndroid Build Coastguard Worker WriteBarrierKind write_barrier_kind) const; 393*795d594fSAndroid Build Coastguard Worker 394*795d594fSAndroid Build Coastguard Worker // Get the ScopedArenaAllocator used for codegen memory allocation. 395*795d594fSAndroid Build Coastguard Worker ScopedArenaAllocator* GetScopedAllocator(); 396*795d594fSAndroid Build Coastguard Worker 397*795d594fSAndroid Build Coastguard Worker void AddSlowPath(SlowPathCode* slow_path); 398*795d594fSAndroid Build Coastguard Worker 399*795d594fSAndroid Build Coastguard Worker ScopedArenaVector<uint8_t> BuildStackMaps(const dex::CodeItem* code_item_for_osr_check); 400*795d594fSAndroid Build Coastguard Worker size_t GetNumberOfJitRoots() const; 401*795d594fSAndroid Build Coastguard Worker 402*795d594fSAndroid Build Coastguard Worker // Fills the `literals` array with literals collected during code generation. 403*795d594fSAndroid Build Coastguard Worker // Also emits literal patches. 404*795d594fSAndroid Build Coastguard Worker void EmitJitRoots(uint8_t* code, 405*795d594fSAndroid Build Coastguard Worker const uint8_t* roots_data, 406*795d594fSAndroid Build Coastguard Worker /*out*/std::vector<Handle<mirror::Object>>* roots) 407*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 408*795d594fSAndroid Build Coastguard Worker IsLeafMethod()409*795d594fSAndroid Build Coastguard Worker bool IsLeafMethod() const { 410*795d594fSAndroid Build Coastguard Worker return is_leaf_; 411*795d594fSAndroid Build Coastguard Worker } 412*795d594fSAndroid Build Coastguard Worker MarkNotLeaf()413*795d594fSAndroid Build Coastguard Worker void MarkNotLeaf() { 414*795d594fSAndroid Build Coastguard Worker is_leaf_ = false; 415*795d594fSAndroid Build Coastguard Worker requires_current_method_ = true; 416*795d594fSAndroid Build Coastguard Worker } 417*795d594fSAndroid Build Coastguard Worker NeedsSuspendCheckEntry()418*795d594fSAndroid Build Coastguard Worker bool NeedsSuspendCheckEntry() const { 419*795d594fSAndroid Build Coastguard Worker return needs_suspend_check_entry_; 420*795d594fSAndroid Build Coastguard Worker } 421*795d594fSAndroid Build Coastguard Worker MarkNeedsSuspendCheckEntry()422*795d594fSAndroid Build Coastguard Worker void MarkNeedsSuspendCheckEntry() { 423*795d594fSAndroid Build Coastguard Worker needs_suspend_check_entry_ = true; 424*795d594fSAndroid Build Coastguard Worker } 425*795d594fSAndroid Build Coastguard Worker SetRequiresCurrentMethod()426*795d594fSAndroid Build Coastguard Worker void SetRequiresCurrentMethod() { 427*795d594fSAndroid Build Coastguard Worker requires_current_method_ = true; 428*795d594fSAndroid Build Coastguard Worker } 429*795d594fSAndroid Build Coastguard Worker RequiresCurrentMethod()430*795d594fSAndroid Build Coastguard Worker bool RequiresCurrentMethod() const { 431*795d594fSAndroid Build Coastguard Worker return requires_current_method_; 432*795d594fSAndroid Build Coastguard Worker } 433*795d594fSAndroid Build Coastguard Worker 434*795d594fSAndroid Build Coastguard Worker // Clears the spill slots taken by loop phis in the `LocationSummary` of the 435*795d594fSAndroid Build Coastguard Worker // suspend check. This is called when the code generator generates code 436*795d594fSAndroid Build Coastguard Worker // for the suspend check at the back edge (instead of where the suspend check 437*795d594fSAndroid Build Coastguard Worker // is, which is the loop entry). At this point, the spill slots for the phis 438*795d594fSAndroid Build Coastguard Worker // have not been written to. 439*795d594fSAndroid Build Coastguard Worker void ClearSpillSlotsFromLoopPhisInStackMap(HSuspendCheck* suspend_check, 440*795d594fSAndroid Build Coastguard Worker HParallelMove* spills) const; 441*795d594fSAndroid Build Coastguard Worker GetBlockedCoreRegisters()442*795d594fSAndroid Build Coastguard Worker bool* GetBlockedCoreRegisters() const { return blocked_core_registers_; } GetBlockedFloatingPointRegisters()443*795d594fSAndroid Build Coastguard Worker bool* GetBlockedFloatingPointRegisters() const { return blocked_fpu_registers_; } 444*795d594fSAndroid Build Coastguard Worker IsBlockedCoreRegister(size_t i)445*795d594fSAndroid Build Coastguard Worker bool IsBlockedCoreRegister(size_t i) { return blocked_core_registers_[i]; } IsBlockedFloatingPointRegister(size_t i)446*795d594fSAndroid Build Coastguard Worker bool IsBlockedFloatingPointRegister(size_t i) { return blocked_fpu_registers_[i]; } 447*795d594fSAndroid Build Coastguard Worker 448*795d594fSAndroid Build Coastguard Worker // Helper that returns the offset of the array's length field. 449*795d594fSAndroid Build Coastguard Worker // Note: Besides the normal arrays, we also use the HArrayLength for 450*795d594fSAndroid Build Coastguard Worker // accessing the String's `count` field in String intrinsics. 451*795d594fSAndroid Build Coastguard Worker static uint32_t GetArrayLengthOffset(HArrayLength* array_length); 452*795d594fSAndroid Build Coastguard Worker 453*795d594fSAndroid Build Coastguard Worker // Helper that returns the offset of the array's data. 454*795d594fSAndroid Build Coastguard Worker // Note: Besides the normal arrays, we also use the HArrayGet for 455*795d594fSAndroid Build Coastguard Worker // accessing the String's `value` field in String intrinsics. 456*795d594fSAndroid Build Coastguard Worker static uint32_t GetArrayDataOffset(HArrayGet* array_get); 457*795d594fSAndroid Build Coastguard Worker 458*795d594fSAndroid Build Coastguard Worker void EmitParallelMoves(Location from1, 459*795d594fSAndroid Build Coastguard Worker Location to1, 460*795d594fSAndroid Build Coastguard Worker DataType::Type type1, 461*795d594fSAndroid Build Coastguard Worker Location from2, 462*795d594fSAndroid Build Coastguard Worker Location to2, 463*795d594fSAndroid Build Coastguard Worker DataType::Type type2); 464*795d594fSAndroid Build Coastguard Worker InstanceOfNeedsReadBarrier(HInstanceOf * instance_of)465*795d594fSAndroid Build Coastguard Worker bool InstanceOfNeedsReadBarrier(HInstanceOf* instance_of) { 466*795d594fSAndroid Build Coastguard Worker // Used only for `kExactCheck`, `kAbstractClassCheck`, `kClassHierarchyCheck`, 467*795d594fSAndroid Build Coastguard Worker // `kArrayObjectCheck` and `kInterfaceCheck`. 468*795d594fSAndroid Build Coastguard Worker DCHECK(instance_of->GetTypeCheckKind() == TypeCheckKind::kExactCheck || 469*795d594fSAndroid Build Coastguard Worker instance_of->GetTypeCheckKind() == TypeCheckKind::kAbstractClassCheck || 470*795d594fSAndroid Build Coastguard Worker instance_of->GetTypeCheckKind() == TypeCheckKind::kClassHierarchyCheck || 471*795d594fSAndroid Build Coastguard Worker instance_of->GetTypeCheckKind() == TypeCheckKind::kArrayObjectCheck || 472*795d594fSAndroid Build Coastguard Worker instance_of->GetTypeCheckKind() == TypeCheckKind::kInterfaceCheck) 473*795d594fSAndroid Build Coastguard Worker << instance_of->GetTypeCheckKind(); 474*795d594fSAndroid Build Coastguard Worker // If the target class is in the boot or app image, it's non-moveable and it doesn't matter 475*795d594fSAndroid Build Coastguard Worker // if we compare it with a from-space or to-space reference, the result is the same. 476*795d594fSAndroid Build Coastguard Worker // It's OK to traverse a class hierarchy jumping between from-space and to-space. 477*795d594fSAndroid Build Coastguard Worker return EmitReadBarrier() && !instance_of->GetTargetClass()->IsInImage(); 478*795d594fSAndroid Build Coastguard Worker } 479*795d594fSAndroid Build Coastguard Worker ReadBarrierOptionForInstanceOf(HInstanceOf * instance_of)480*795d594fSAndroid Build Coastguard Worker ReadBarrierOption ReadBarrierOptionForInstanceOf(HInstanceOf* instance_of) { 481*795d594fSAndroid Build Coastguard Worker return InstanceOfNeedsReadBarrier(instance_of) ? kWithReadBarrier : kWithoutReadBarrier; 482*795d594fSAndroid Build Coastguard Worker } 483*795d594fSAndroid Build Coastguard Worker IsTypeCheckSlowPathFatal(HCheckCast * check_cast)484*795d594fSAndroid Build Coastguard Worker bool IsTypeCheckSlowPathFatal(HCheckCast* check_cast) { 485*795d594fSAndroid Build Coastguard Worker switch (check_cast->GetTypeCheckKind()) { 486*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kExactCheck: 487*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kAbstractClassCheck: 488*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kClassHierarchyCheck: 489*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kArrayObjectCheck: 490*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kInterfaceCheck: { 491*795d594fSAndroid Build Coastguard Worker bool needs_read_barrier = 492*795d594fSAndroid Build Coastguard Worker EmitReadBarrier() && !check_cast->GetTargetClass()->IsInImage(); 493*795d594fSAndroid Build Coastguard Worker // We do not emit read barriers for HCheckCast, so we can get false negatives 494*795d594fSAndroid Build Coastguard Worker // and the slow path shall re-check and simply return if the cast is actually OK. 495*795d594fSAndroid Build Coastguard Worker return !needs_read_barrier; 496*795d594fSAndroid Build Coastguard Worker } 497*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kArrayCheck: 498*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kUnresolvedCheck: 499*795d594fSAndroid Build Coastguard Worker return false; 500*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kBitstringCheck: 501*795d594fSAndroid Build Coastguard Worker return true; 502*795d594fSAndroid Build Coastguard Worker } 503*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unreachable"; 504*795d594fSAndroid Build Coastguard Worker UNREACHABLE(); 505*795d594fSAndroid Build Coastguard Worker } 506*795d594fSAndroid Build Coastguard Worker GetCheckCastCallKind(HCheckCast * check_cast)507*795d594fSAndroid Build Coastguard Worker LocationSummary::CallKind GetCheckCastCallKind(HCheckCast* check_cast) { 508*795d594fSAndroid Build Coastguard Worker return (IsTypeCheckSlowPathFatal(check_cast) && !check_cast->CanThrowIntoCatchBlock()) 509*795d594fSAndroid Build Coastguard Worker ? LocationSummary::kNoCall // In fact, call on a fatal (non-returning) slow path. 510*795d594fSAndroid Build Coastguard Worker : LocationSummary::kCallOnSlowPath; 511*795d594fSAndroid Build Coastguard Worker } 512*795d594fSAndroid Build Coastguard Worker StoreNeedsWriteBarrier(DataType::Type type,HInstruction * value)513*795d594fSAndroid Build Coastguard Worker static bool StoreNeedsWriteBarrier(DataType::Type type, HInstruction* value) { 514*795d594fSAndroid Build Coastguard Worker // Check that null value is not represented as an integer constant. 515*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(type == DataType::Type::kReference, !value->IsIntConstant()); 516*795d594fSAndroid Build Coastguard Worker return type == DataType::Type::kReference && !value->IsNullConstant(); 517*795d594fSAndroid Build Coastguard Worker } 518*795d594fSAndroid Build Coastguard Worker 519*795d594fSAndroid Build Coastguard Worker // If we are compiling a graph with the WBE pass enabled, we want to honor the WriteBarrierKind 520*795d594fSAndroid Build Coastguard Worker // set during the WBE pass. 521*795d594fSAndroid Build Coastguard Worker bool StoreNeedsWriteBarrier(DataType::Type type, 522*795d594fSAndroid Build Coastguard Worker HInstruction* value, 523*795d594fSAndroid Build Coastguard Worker WriteBarrierKind write_barrier_kind) const; 524*795d594fSAndroid Build Coastguard Worker 525*795d594fSAndroid Build Coastguard Worker // Performs checks pertaining to an InvokeRuntime call. 526*795d594fSAndroid Build Coastguard Worker void ValidateInvokeRuntime(QuickEntrypointEnum entrypoint, 527*795d594fSAndroid Build Coastguard Worker HInstruction* instruction, 528*795d594fSAndroid Build Coastguard Worker SlowPathCode* slow_path); 529*795d594fSAndroid Build Coastguard Worker 530*795d594fSAndroid Build Coastguard Worker // Performs checks pertaining to an InvokeRuntimeWithoutRecordingPcInfo call. 531*795d594fSAndroid Build Coastguard Worker static void ValidateInvokeRuntimeWithoutRecordingPcInfo(HInstruction* instruction, 532*795d594fSAndroid Build Coastguard Worker SlowPathCode* slow_path); 533*795d594fSAndroid Build Coastguard Worker AddAllocatedRegister(Location location)534*795d594fSAndroid Build Coastguard Worker void AddAllocatedRegister(Location location) { 535*795d594fSAndroid Build Coastguard Worker allocated_registers_.Add(location); 536*795d594fSAndroid Build Coastguard Worker } 537*795d594fSAndroid Build Coastguard Worker HasAllocatedRegister(bool is_core,int reg)538*795d594fSAndroid Build Coastguard Worker bool HasAllocatedRegister(bool is_core, int reg) const { 539*795d594fSAndroid Build Coastguard Worker return is_core 540*795d594fSAndroid Build Coastguard Worker ? allocated_registers_.ContainsCoreRegister(reg) 541*795d594fSAndroid Build Coastguard Worker : allocated_registers_.ContainsFloatingPointRegister(reg); 542*795d594fSAndroid Build Coastguard Worker } 543*795d594fSAndroid Build Coastguard Worker 544*795d594fSAndroid Build Coastguard Worker void AllocateLocations(HInstruction* instruction); 545*795d594fSAndroid Build Coastguard Worker 546*795d594fSAndroid Build Coastguard Worker // Tells whether the stack frame of the compiled method is 547*795d594fSAndroid Build Coastguard Worker // considered "empty", that is either actually having a size of zero, 548*795d594fSAndroid Build Coastguard Worker // or just containing the saved return address register. HasEmptyFrame()549*795d594fSAndroid Build Coastguard Worker bool HasEmptyFrame() const { 550*795d594fSAndroid Build Coastguard Worker return GetFrameSize() == (CallPushesPC() ? GetWordSize() : 0); 551*795d594fSAndroid Build Coastguard Worker } 552*795d594fSAndroid Build Coastguard Worker GetInt8ValueOf(HConstant * constant)553*795d594fSAndroid Build Coastguard Worker static int8_t GetInt8ValueOf(HConstant* constant) { 554*795d594fSAndroid Build Coastguard Worker DCHECK(constant->IsIntConstant()); 555*795d594fSAndroid Build Coastguard Worker return constant->AsIntConstant()->GetValue(); 556*795d594fSAndroid Build Coastguard Worker } 557*795d594fSAndroid Build Coastguard Worker GetInt16ValueOf(HConstant * constant)558*795d594fSAndroid Build Coastguard Worker static int16_t GetInt16ValueOf(HConstant* constant) { 559*795d594fSAndroid Build Coastguard Worker DCHECK(constant->IsIntConstant()); 560*795d594fSAndroid Build Coastguard Worker return constant->AsIntConstant()->GetValue(); 561*795d594fSAndroid Build Coastguard Worker } 562*795d594fSAndroid Build Coastguard Worker GetInt32ValueOf(HConstant * constant)563*795d594fSAndroid Build Coastguard Worker static int32_t GetInt32ValueOf(HConstant* constant) { 564*795d594fSAndroid Build Coastguard Worker if (constant->IsIntConstant()) { 565*795d594fSAndroid Build Coastguard Worker return constant->AsIntConstant()->GetValue(); 566*795d594fSAndroid Build Coastguard Worker } else if (constant->IsNullConstant()) { 567*795d594fSAndroid Build Coastguard Worker return 0; 568*795d594fSAndroid Build Coastguard Worker } else { 569*795d594fSAndroid Build Coastguard Worker DCHECK(constant->IsFloatConstant()); 570*795d594fSAndroid Build Coastguard Worker return bit_cast<int32_t, float>(constant->AsFloatConstant()->GetValue()); 571*795d594fSAndroid Build Coastguard Worker } 572*795d594fSAndroid Build Coastguard Worker } 573*795d594fSAndroid Build Coastguard Worker GetInt64ValueOf(HConstant * constant)574*795d594fSAndroid Build Coastguard Worker static int64_t GetInt64ValueOf(HConstant* constant) { 575*795d594fSAndroid Build Coastguard Worker if (constant->IsIntConstant()) { 576*795d594fSAndroid Build Coastguard Worker return constant->AsIntConstant()->GetValue(); 577*795d594fSAndroid Build Coastguard Worker } else if (constant->IsNullConstant()) { 578*795d594fSAndroid Build Coastguard Worker return 0; 579*795d594fSAndroid Build Coastguard Worker } else if (constant->IsFloatConstant()) { 580*795d594fSAndroid Build Coastguard Worker return bit_cast<int32_t, float>(constant->AsFloatConstant()->GetValue()); 581*795d594fSAndroid Build Coastguard Worker } else if (constant->IsLongConstant()) { 582*795d594fSAndroid Build Coastguard Worker return constant->AsLongConstant()->GetValue(); 583*795d594fSAndroid Build Coastguard Worker } else { 584*795d594fSAndroid Build Coastguard Worker DCHECK(constant->IsDoubleConstant()); 585*795d594fSAndroid Build Coastguard Worker return bit_cast<int64_t, double>(constant->AsDoubleConstant()->GetValue()); 586*795d594fSAndroid Build Coastguard Worker } 587*795d594fSAndroid Build Coastguard Worker } 588*795d594fSAndroid Build Coastguard Worker GetFirstRegisterSlotInSlowPath()589*795d594fSAndroid Build Coastguard Worker size_t GetFirstRegisterSlotInSlowPath() const { 590*795d594fSAndroid Build Coastguard Worker return first_register_slot_in_slow_path_; 591*795d594fSAndroid Build Coastguard Worker } 592*795d594fSAndroid Build Coastguard Worker FrameEntrySpillSize()593*795d594fSAndroid Build Coastguard Worker uint32_t FrameEntrySpillSize() const { 594*795d594fSAndroid Build Coastguard Worker return GetFpuSpillSize() + GetCoreSpillSize(); 595*795d594fSAndroid Build Coastguard Worker } 596*795d594fSAndroid Build Coastguard Worker 597*795d594fSAndroid Build Coastguard Worker virtual ParallelMoveResolver* GetMoveResolver() = 0; 598*795d594fSAndroid Build Coastguard Worker 599*795d594fSAndroid Build Coastguard Worker static void CreateCommonInvokeLocationSummary( 600*795d594fSAndroid Build Coastguard Worker HInvoke* invoke, InvokeDexCallingConventionVisitor* visitor); 601*795d594fSAndroid Build Coastguard Worker 602*795d594fSAndroid Build Coastguard Worker template <typename CriticalNativeCallingConventionVisitor, 603*795d594fSAndroid Build Coastguard Worker size_t kNativeStackAlignment, 604*795d594fSAndroid Build Coastguard Worker size_t GetCriticalNativeDirectCallFrameSize(std::string_view shorty)> PrepareCriticalNativeCall(HInvokeStaticOrDirect * invoke)605*795d594fSAndroid Build Coastguard Worker size_t PrepareCriticalNativeCall(HInvokeStaticOrDirect* invoke) { 606*795d594fSAndroid Build Coastguard Worker DCHECK(!invoke->GetLocations()->Intrinsified()); 607*795d594fSAndroid Build Coastguard Worker CriticalNativeCallingConventionVisitor calling_convention_visitor( 608*795d594fSAndroid Build Coastguard Worker /*for_register_allocation=*/ false); 609*795d594fSAndroid Build Coastguard Worker HParallelMove parallel_move(GetGraph()->GetAllocator()); 610*795d594fSAndroid Build Coastguard Worker PrepareCriticalNativeArgumentMoves(invoke, &calling_convention_visitor, ¶llel_move); 611*795d594fSAndroid Build Coastguard Worker size_t out_frame_size = 612*795d594fSAndroid Build Coastguard Worker RoundUp(calling_convention_visitor.GetStackOffset(), kNativeStackAlignment); 613*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) { 614*795d594fSAndroid Build Coastguard Worker std::string_view shorty = GetCriticalNativeShorty(invoke); 615*795d594fSAndroid Build Coastguard Worker CHECK_EQ(GetCriticalNativeDirectCallFrameSize(shorty), out_frame_size); 616*795d594fSAndroid Build Coastguard Worker } 617*795d594fSAndroid Build Coastguard Worker if (out_frame_size != 0u) { 618*795d594fSAndroid Build Coastguard Worker FinishCriticalNativeFrameSetup(out_frame_size, ¶llel_move); 619*795d594fSAndroid Build Coastguard Worker } 620*795d594fSAndroid Build Coastguard Worker return out_frame_size; 621*795d594fSAndroid Build Coastguard Worker } 622*795d594fSAndroid Build Coastguard Worker 623*795d594fSAndroid Build Coastguard Worker void GenerateInvokeStaticOrDirectRuntimeCall( 624*795d594fSAndroid Build Coastguard Worker HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path); 625*795d594fSAndroid Build Coastguard Worker 626*795d594fSAndroid Build Coastguard Worker void GenerateInvokeUnresolvedRuntimeCall(HInvokeUnresolved* invoke); 627*795d594fSAndroid Build Coastguard Worker 628*795d594fSAndroid Build Coastguard Worker void GenerateInvokePolymorphicCall(HInvokePolymorphic* invoke, SlowPathCode* slow_path = nullptr); 629*795d594fSAndroid Build Coastguard Worker 630*795d594fSAndroid Build Coastguard Worker void GenerateInvokeCustomCall(HInvokeCustom* invoke); 631*795d594fSAndroid Build Coastguard Worker 632*795d594fSAndroid Build Coastguard Worker void CreateStringBuilderAppendLocations(HStringBuilderAppend* instruction, Location out); 633*795d594fSAndroid Build Coastguard Worker 634*795d594fSAndroid Build Coastguard Worker void CreateUnresolvedFieldLocationSummary( 635*795d594fSAndroid Build Coastguard Worker HInstruction* field_access, 636*795d594fSAndroid Build Coastguard Worker DataType::Type field_type, 637*795d594fSAndroid Build Coastguard Worker const FieldAccessCallingConvention& calling_convention); 638*795d594fSAndroid Build Coastguard Worker 639*795d594fSAndroid Build Coastguard Worker void GenerateUnresolvedFieldAccess( 640*795d594fSAndroid Build Coastguard Worker HInstruction* field_access, 641*795d594fSAndroid Build Coastguard Worker DataType::Type field_type, 642*795d594fSAndroid Build Coastguard Worker uint32_t field_index, 643*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc, 644*795d594fSAndroid Build Coastguard Worker const FieldAccessCallingConvention& calling_convention); 645*795d594fSAndroid Build Coastguard Worker 646*795d594fSAndroid Build Coastguard Worker static void CreateLoadClassRuntimeCallLocationSummary(HLoadClass* cls, 647*795d594fSAndroid Build Coastguard Worker Location runtime_type_index_location, 648*795d594fSAndroid Build Coastguard Worker Location runtime_return_location); 649*795d594fSAndroid Build Coastguard Worker void GenerateLoadClassRuntimeCall(HLoadClass* cls); 650*795d594fSAndroid Build Coastguard Worker 651*795d594fSAndroid Build Coastguard Worker static void CreateLoadMethodHandleRuntimeCallLocationSummary(HLoadMethodHandle* method_handle, 652*795d594fSAndroid Build Coastguard Worker Location runtime_handle_index_location, 653*795d594fSAndroid Build Coastguard Worker Location runtime_return_location); 654*795d594fSAndroid Build Coastguard Worker void GenerateLoadMethodHandleRuntimeCall(HLoadMethodHandle* method_handle); 655*795d594fSAndroid Build Coastguard Worker 656*795d594fSAndroid Build Coastguard Worker static void CreateLoadMethodTypeRuntimeCallLocationSummary(HLoadMethodType* method_type, 657*795d594fSAndroid Build Coastguard Worker Location runtime_type_index_location, 658*795d594fSAndroid Build Coastguard Worker Location runtime_return_location); 659*795d594fSAndroid Build Coastguard Worker void GenerateLoadMethodTypeRuntimeCall(HLoadMethodType* method_type); 660*795d594fSAndroid Build Coastguard Worker 661*795d594fSAndroid Build Coastguard Worker static uint32_t GetBootImageOffset(ObjPtr<mirror::Object> object) 662*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 663*795d594fSAndroid Build Coastguard Worker static uint32_t GetBootImageOffset(HLoadClass* load_class); 664*795d594fSAndroid Build Coastguard Worker static uint32_t GetBootImageOffset(HLoadString* load_string); 665*795d594fSAndroid Build Coastguard Worker static uint32_t GetBootImageOffset(HInvoke* invoke); 666*795d594fSAndroid Build Coastguard Worker static uint32_t GetBootImageOffset(ClassRoot class_root); 667*795d594fSAndroid Build Coastguard Worker static uint32_t GetBootImageOffsetOfIntrinsicDeclaringClass(HInvoke* invoke); 668*795d594fSAndroid Build Coastguard Worker 669*795d594fSAndroid Build Coastguard Worker static LocationSummary* CreateSystemArrayCopyLocationSummary( 670*795d594fSAndroid Build Coastguard Worker HInvoke* invoke, int32_t length_threshold = -1, size_t num_temps = 3); 671*795d594fSAndroid Build Coastguard Worker SetDisassemblyInformation(DisassemblyInformation * info)672*795d594fSAndroid Build Coastguard Worker void SetDisassemblyInformation(DisassemblyInformation* info) { disasm_info_ = info; } GetDisassemblyInformation()673*795d594fSAndroid Build Coastguard Worker DisassemblyInformation* GetDisassemblyInformation() const { return disasm_info_; } 674*795d594fSAndroid Build Coastguard Worker 675*795d594fSAndroid Build Coastguard Worker virtual void InvokeRuntime(QuickEntrypointEnum entrypoint, 676*795d594fSAndroid Build Coastguard Worker HInstruction* instruction, 677*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc, 678*795d594fSAndroid Build Coastguard Worker SlowPathCode* slow_path = nullptr) = 0; 679*795d594fSAndroid Build Coastguard Worker 680*795d594fSAndroid Build Coastguard Worker // Check if the desired_string_load_kind is supported. If it is, return it, 681*795d594fSAndroid Build Coastguard Worker // otherwise return a fall-back kind that should be used instead. 682*795d594fSAndroid Build Coastguard Worker virtual HLoadString::LoadKind GetSupportedLoadStringKind( 683*795d594fSAndroid Build Coastguard Worker HLoadString::LoadKind desired_string_load_kind) = 0; 684*795d594fSAndroid Build Coastguard Worker 685*795d594fSAndroid Build Coastguard Worker // Check if the desired_class_load_kind is supported. If it is, return it, 686*795d594fSAndroid Build Coastguard Worker // otherwise return a fall-back kind that should be used instead. 687*795d594fSAndroid Build Coastguard Worker virtual HLoadClass::LoadKind GetSupportedLoadClassKind( 688*795d594fSAndroid Build Coastguard Worker HLoadClass::LoadKind desired_class_load_kind) = 0; 689*795d594fSAndroid Build Coastguard Worker GetLoadStringCallKind(HLoadString * load)690*795d594fSAndroid Build Coastguard Worker LocationSummary::CallKind GetLoadStringCallKind(HLoadString* load) { 691*795d594fSAndroid Build Coastguard Worker switch (load->GetLoadKind()) { 692*795d594fSAndroid Build Coastguard Worker case HLoadString::LoadKind::kBssEntry: 693*795d594fSAndroid Build Coastguard Worker DCHECK(load->NeedsEnvironment()); 694*795d594fSAndroid Build Coastguard Worker return LocationSummary::kCallOnSlowPath; 695*795d594fSAndroid Build Coastguard Worker case HLoadString::LoadKind::kRuntimeCall: 696*795d594fSAndroid Build Coastguard Worker DCHECK(load->NeedsEnvironment()); 697*795d594fSAndroid Build Coastguard Worker return LocationSummary::kCallOnMainOnly; 698*795d594fSAndroid Build Coastguard Worker case HLoadString::LoadKind::kJitTableAddress: 699*795d594fSAndroid Build Coastguard Worker DCHECK(!load->NeedsEnvironment()); 700*795d594fSAndroid Build Coastguard Worker return EmitReadBarrier() 701*795d594fSAndroid Build Coastguard Worker ? LocationSummary::kCallOnSlowPath 702*795d594fSAndroid Build Coastguard Worker : LocationSummary::kNoCall; 703*795d594fSAndroid Build Coastguard Worker break; 704*795d594fSAndroid Build Coastguard Worker default: 705*795d594fSAndroid Build Coastguard Worker DCHECK(!load->NeedsEnvironment()); 706*795d594fSAndroid Build Coastguard Worker return LocationSummary::kNoCall; 707*795d594fSAndroid Build Coastguard Worker } 708*795d594fSAndroid Build Coastguard Worker } 709*795d594fSAndroid Build Coastguard Worker 710*795d594fSAndroid Build Coastguard Worker // Check if the desired_dispatch_info is supported. If it is, return it, 711*795d594fSAndroid Build Coastguard Worker // otherwise return a fall-back info that should be used instead. 712*795d594fSAndroid Build Coastguard Worker virtual HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch( 713*795d594fSAndroid Build Coastguard Worker const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info, 714*795d594fSAndroid Build Coastguard Worker ArtMethod* method) = 0; 715*795d594fSAndroid Build Coastguard Worker 716*795d594fSAndroid Build Coastguard Worker // Generate a call to a static or direct method. 717*795d594fSAndroid Build Coastguard Worker virtual void GenerateStaticOrDirectCall( 718*795d594fSAndroid Build Coastguard Worker HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) = 0; 719*795d594fSAndroid Build Coastguard Worker // Generate a call to a virtual method. 720*795d594fSAndroid Build Coastguard Worker virtual void GenerateVirtualCall( 721*795d594fSAndroid Build Coastguard Worker HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) = 0; 722*795d594fSAndroid Build Coastguard Worker 723*795d594fSAndroid Build Coastguard Worker // Copy the result of a call into the given target. 724*795d594fSAndroid Build Coastguard Worker virtual void MoveFromReturnRegister(Location trg, DataType::Type type) = 0; 725*795d594fSAndroid Build Coastguard Worker 726*795d594fSAndroid Build Coastguard Worker virtual void IncreaseFrame(size_t adjustment) = 0; 727*795d594fSAndroid Build Coastguard Worker virtual void DecreaseFrame(size_t adjustment) = 0; 728*795d594fSAndroid Build Coastguard Worker 729*795d594fSAndroid Build Coastguard Worker virtual void GenerateNop() = 0; 730*795d594fSAndroid Build Coastguard Worker 731*795d594fSAndroid Build Coastguard Worker static QuickEntrypointEnum GetArrayAllocationEntrypoint(HNewArray* new_array); 732*795d594fSAndroid Build Coastguard Worker static ScaleFactor ScaleFactorForType(DataType::Type type); 733*795d594fSAndroid Build Coastguard Worker GetCode()734*795d594fSAndroid Build Coastguard Worker ArrayRef<const uint8_t> GetCode() const { 735*795d594fSAndroid Build Coastguard Worker return ArrayRef<const uint8_t>(GetAssembler().CodeBufferBaseAddress(), 736*795d594fSAndroid Build Coastguard Worker GetAssembler().CodeSize()); 737*795d594fSAndroid Build Coastguard Worker } 738*795d594fSAndroid Build Coastguard Worker 739*795d594fSAndroid Build Coastguard Worker protected: 740*795d594fSAndroid Build Coastguard Worker // Patch info used for recording locations of required linker patches and their targets, 741*795d594fSAndroid Build Coastguard Worker // i.e. target method, string, type or code identified by their dex file and index, 742*795d594fSAndroid Build Coastguard Worker // or boot image .data.img.rel.ro entries identified by the boot image offset. 743*795d594fSAndroid Build Coastguard Worker template <typename LabelType> 744*795d594fSAndroid Build Coastguard Worker struct PatchInfo { PatchInfoPatchInfo745*795d594fSAndroid Build Coastguard Worker PatchInfo(const DexFile* dex_file, uint32_t off_or_idx) 746*795d594fSAndroid Build Coastguard Worker : target_dex_file(dex_file), offset_or_index(off_or_idx), label() { } 747*795d594fSAndroid Build Coastguard Worker 748*795d594fSAndroid Build Coastguard Worker // Target dex file or null for boot image .data.img.rel.ro patches. 749*795d594fSAndroid Build Coastguard Worker const DexFile* target_dex_file; 750*795d594fSAndroid Build Coastguard Worker // Either the boot image offset (to write to .data.img.rel.ro) or string/type/method index. 751*795d594fSAndroid Build Coastguard Worker uint32_t offset_or_index; 752*795d594fSAndroid Build Coastguard Worker // Label for the instruction to patch. 753*795d594fSAndroid Build Coastguard Worker LabelType label; 754*795d594fSAndroid Build Coastguard Worker }; 755*795d594fSAndroid Build Coastguard Worker 756*795d594fSAndroid Build Coastguard Worker CodeGenerator(HGraph* graph, 757*795d594fSAndroid Build Coastguard Worker size_t number_of_core_registers, 758*795d594fSAndroid Build Coastguard Worker size_t number_of_fpu_registers, 759*795d594fSAndroid Build Coastguard Worker size_t number_of_register_pairs, 760*795d594fSAndroid Build Coastguard Worker uint32_t core_callee_save_mask, 761*795d594fSAndroid Build Coastguard Worker uint32_t fpu_callee_save_mask, 762*795d594fSAndroid Build Coastguard Worker const CompilerOptions& compiler_options, 763*795d594fSAndroid Build Coastguard Worker OptimizingCompilerStats* stats, 764*795d594fSAndroid Build Coastguard Worker const art::ArrayRef<const bool>& unimplemented_intrinsics); 765*795d594fSAndroid Build Coastguard Worker 766*795d594fSAndroid Build Coastguard Worker virtual HGraphVisitor* GetLocationBuilder() = 0; 767*795d594fSAndroid Build Coastguard Worker virtual HGraphVisitor* GetInstructionVisitor() = 0; 768*795d594fSAndroid Build Coastguard Worker 769*795d594fSAndroid Build Coastguard Worker template <typename RegType> ComputeRegisterMask(const RegType * registers,size_t length)770*795d594fSAndroid Build Coastguard Worker static uint32_t ComputeRegisterMask(const RegType* registers, size_t length) { 771*795d594fSAndroid Build Coastguard Worker uint32_t mask = 0; 772*795d594fSAndroid Build Coastguard Worker for (size_t i = 0, e = length; i < e; ++i) { 773*795d594fSAndroid Build Coastguard Worker mask |= (1 << registers[i]); 774*795d594fSAndroid Build Coastguard Worker } 775*795d594fSAndroid Build Coastguard Worker return mask; 776*795d594fSAndroid Build Coastguard Worker } 777*795d594fSAndroid Build Coastguard Worker 778*795d594fSAndroid Build Coastguard Worker // Returns the location of the first spilled entry for floating point registers, 779*795d594fSAndroid Build Coastguard Worker // relative to the stack pointer. GetFpuSpillStart()780*795d594fSAndroid Build Coastguard Worker uint32_t GetFpuSpillStart() const { 781*795d594fSAndroid Build Coastguard Worker return GetFrameSize() - FrameEntrySpillSize(); 782*795d594fSAndroid Build Coastguard Worker } 783*795d594fSAndroid Build Coastguard Worker GetFpuSpillSize()784*795d594fSAndroid Build Coastguard Worker uint32_t GetFpuSpillSize() const { 785*795d594fSAndroid Build Coastguard Worker return POPCOUNT(fpu_spill_mask_) * GetCalleePreservedFPWidth(); 786*795d594fSAndroid Build Coastguard Worker } 787*795d594fSAndroid Build Coastguard Worker GetCoreSpillSize()788*795d594fSAndroid Build Coastguard Worker uint32_t GetCoreSpillSize() const { 789*795d594fSAndroid Build Coastguard Worker return POPCOUNT(core_spill_mask_) * GetWordSize(); 790*795d594fSAndroid Build Coastguard Worker } 791*795d594fSAndroid Build Coastguard Worker HasAllocatedCalleeSaveRegisters()792*795d594fSAndroid Build Coastguard Worker virtual bool HasAllocatedCalleeSaveRegisters() const { 793*795d594fSAndroid Build Coastguard Worker // We check the core registers against 1 because it always comprises the return PC. 794*795d594fSAndroid Build Coastguard Worker return (POPCOUNT(allocated_registers_.GetCoreRegisters() & core_callee_save_mask_) != 1) 795*795d594fSAndroid Build Coastguard Worker || (POPCOUNT(allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_) != 0); 796*795d594fSAndroid Build Coastguard Worker } 797*795d594fSAndroid Build Coastguard Worker CallPushesPC()798*795d594fSAndroid Build Coastguard Worker bool CallPushesPC() const { 799*795d594fSAndroid Build Coastguard Worker InstructionSet instruction_set = GetInstructionSet(); 800*795d594fSAndroid Build Coastguard Worker return instruction_set == InstructionSet::kX86 || instruction_set == InstructionSet::kX86_64; 801*795d594fSAndroid Build Coastguard Worker } 802*795d594fSAndroid Build Coastguard Worker 803*795d594fSAndroid Build Coastguard Worker // Arm64 has its own type for a label, so we need to templatize these methods 804*795d594fSAndroid Build Coastguard Worker // to share the logic. 805*795d594fSAndroid Build Coastguard Worker 806*795d594fSAndroid Build Coastguard Worker template <typename LabelType> CommonInitializeLabels()807*795d594fSAndroid Build Coastguard Worker LabelType* CommonInitializeLabels() { 808*795d594fSAndroid Build Coastguard Worker // We use raw array allocations instead of ArenaVector<> because Labels are 809*795d594fSAndroid Build Coastguard Worker // non-constructible and non-movable and as such cannot be held in a vector. 810*795d594fSAndroid Build Coastguard Worker size_t size = GetGraph()->GetBlocks().size(); 811*795d594fSAndroid Build Coastguard Worker LabelType* labels = 812*795d594fSAndroid Build Coastguard Worker GetGraph()->GetAllocator()->AllocArray<LabelType>(size, kArenaAllocCodeGenerator); 813*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i != size; ++i) { 814*795d594fSAndroid Build Coastguard Worker new(labels + i) LabelType(); 815*795d594fSAndroid Build Coastguard Worker } 816*795d594fSAndroid Build Coastguard Worker return labels; 817*795d594fSAndroid Build Coastguard Worker } 818*795d594fSAndroid Build Coastguard Worker 819*795d594fSAndroid Build Coastguard Worker template <typename LabelType> CommonGetLabelOf(LabelType * raw_pointer_to_labels_array,HBasicBlock * block)820*795d594fSAndroid Build Coastguard Worker LabelType* CommonGetLabelOf(LabelType* raw_pointer_to_labels_array, HBasicBlock* block) const { 821*795d594fSAndroid Build Coastguard Worker block = FirstNonEmptyBlock(block); 822*795d594fSAndroid Build Coastguard Worker return raw_pointer_to_labels_array + block->GetBlockId(); 823*795d594fSAndroid Build Coastguard Worker } 824*795d594fSAndroid Build Coastguard Worker GetCurrentSlowPath()825*795d594fSAndroid Build Coastguard Worker SlowPathCode* GetCurrentSlowPath() { 826*795d594fSAndroid Build Coastguard Worker return current_slow_path_; 827*795d594fSAndroid Build Coastguard Worker } 828*795d594fSAndroid Build Coastguard Worker 829*795d594fSAndroid Build Coastguard Worker StackMapStream* GetStackMapStream(); 830*795d594fSAndroid Build Coastguard Worker GetCodeGenerationData()831*795d594fSAndroid Build Coastguard Worker CodeGenerationData* GetCodeGenerationData() { 832*795d594fSAndroid Build Coastguard Worker return code_generation_data_.get(); 833*795d594fSAndroid Build Coastguard Worker } 834*795d594fSAndroid Build Coastguard Worker 835*795d594fSAndroid Build Coastguard Worker void ReserveJitStringRoot(StringReference string_reference, Handle<mirror::String> string); 836*795d594fSAndroid Build Coastguard Worker uint64_t GetJitStringRootIndex(StringReference string_reference); 837*795d594fSAndroid Build Coastguard Worker void ReserveJitClassRoot(TypeReference type_reference, Handle<mirror::Class> klass); 838*795d594fSAndroid Build Coastguard Worker uint64_t GetJitClassRootIndex(TypeReference type_reference); 839*795d594fSAndroid Build Coastguard Worker void ReserveJitMethodTypeRoot(ProtoReference proto_reference, 840*795d594fSAndroid Build Coastguard Worker Handle<mirror::MethodType> method_type); 841*795d594fSAndroid Build Coastguard Worker uint64_t GetJitMethodTypeRootIndex(ProtoReference proto_reference); 842*795d594fSAndroid Build Coastguard Worker 843*795d594fSAndroid Build Coastguard Worker // Emit the patches assocatied with JIT roots. Only applies to JIT compiled code. 844*795d594fSAndroid Build Coastguard Worker virtual void EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data); 845*795d594fSAndroid Build Coastguard Worker 846*795d594fSAndroid Build Coastguard Worker // Frame size required for this method. 847*795d594fSAndroid Build Coastguard Worker uint32_t frame_size_; 848*795d594fSAndroid Build Coastguard Worker uint32_t core_spill_mask_; 849*795d594fSAndroid Build Coastguard Worker uint32_t fpu_spill_mask_; 850*795d594fSAndroid Build Coastguard Worker uint32_t first_register_slot_in_slow_path_; 851*795d594fSAndroid Build Coastguard Worker 852*795d594fSAndroid Build Coastguard Worker // Registers that were allocated during linear scan. 853*795d594fSAndroid Build Coastguard Worker RegisterSet allocated_registers_; 854*795d594fSAndroid Build Coastguard Worker 855*795d594fSAndroid Build Coastguard Worker // Arrays used when doing register allocation to know which 856*795d594fSAndroid Build Coastguard Worker // registers we can allocate. `SetupBlockedRegisters` updates the 857*795d594fSAndroid Build Coastguard Worker // arrays. 858*795d594fSAndroid Build Coastguard Worker bool* const blocked_core_registers_; 859*795d594fSAndroid Build Coastguard Worker bool* const blocked_fpu_registers_; 860*795d594fSAndroid Build Coastguard Worker size_t number_of_core_registers_; 861*795d594fSAndroid Build Coastguard Worker size_t number_of_fpu_registers_; 862*795d594fSAndroid Build Coastguard Worker size_t number_of_register_pairs_; 863*795d594fSAndroid Build Coastguard Worker const uint32_t core_callee_save_mask_; 864*795d594fSAndroid Build Coastguard Worker const uint32_t fpu_callee_save_mask_; 865*795d594fSAndroid Build Coastguard Worker 866*795d594fSAndroid Build Coastguard Worker // The order to use for code generation. 867*795d594fSAndroid Build Coastguard Worker const ArenaVector<HBasicBlock*>* block_order_; 868*795d594fSAndroid Build Coastguard Worker 869*795d594fSAndroid Build Coastguard Worker DisassemblyInformation* disasm_info_; 870*795d594fSAndroid Build Coastguard Worker 871*795d594fSAndroid Build Coastguard Worker private: 872*795d594fSAndroid Build Coastguard Worker void InitializeCodeGenerationData(); 873*795d594fSAndroid Build Coastguard Worker size_t GetStackOffsetOfSavedRegister(size_t index); 874*795d594fSAndroid Build Coastguard Worker void GenerateSlowPaths(); 875*795d594fSAndroid Build Coastguard Worker void BlockIfInRegister(Location location, bool is_out = false) const; 876*795d594fSAndroid Build Coastguard Worker void EmitEnvironment(HEnvironment* environment, 877*795d594fSAndroid Build Coastguard Worker SlowPathCode* slow_path, 878*795d594fSAndroid Build Coastguard Worker bool needs_vreg_info = true, 879*795d594fSAndroid Build Coastguard Worker bool is_for_catch_handler = false, 880*795d594fSAndroid Build Coastguard Worker bool innermost_environment = true); 881*795d594fSAndroid Build Coastguard Worker void EmitVRegInfo(HEnvironment* environment, SlowPathCode* slow_path, bool is_for_catch_handler); 882*795d594fSAndroid Build Coastguard Worker void EmitVRegInfoOnlyCatchPhis(HEnvironment* environment); 883*795d594fSAndroid Build Coastguard Worker 884*795d594fSAndroid Build Coastguard Worker static void PrepareCriticalNativeArgumentMoves( 885*795d594fSAndroid Build Coastguard Worker HInvokeStaticOrDirect* invoke, 886*795d594fSAndroid Build Coastguard Worker /*inout*/InvokeDexCallingConventionVisitor* visitor, 887*795d594fSAndroid Build Coastguard Worker /*out*/HParallelMove* parallel_move); 888*795d594fSAndroid Build Coastguard Worker 889*795d594fSAndroid Build Coastguard Worker void FinishCriticalNativeFrameSetup(size_t out_frame_size, /*inout*/HParallelMove* parallel_move); 890*795d594fSAndroid Build Coastguard Worker 891*795d594fSAndroid Build Coastguard Worker static std::string_view GetCriticalNativeShorty(HInvokeStaticOrDirect* invoke); 892*795d594fSAndroid Build Coastguard Worker 893*795d594fSAndroid Build Coastguard Worker OptimizingCompilerStats* stats_; 894*795d594fSAndroid Build Coastguard Worker 895*795d594fSAndroid Build Coastguard Worker HGraph* const graph_; 896*795d594fSAndroid Build Coastguard Worker const CompilerOptions& compiler_options_; 897*795d594fSAndroid Build Coastguard Worker 898*795d594fSAndroid Build Coastguard Worker // The current slow-path that we're generating code for. 899*795d594fSAndroid Build Coastguard Worker SlowPathCode* current_slow_path_; 900*795d594fSAndroid Build Coastguard Worker 901*795d594fSAndroid Build Coastguard Worker // The current block index in `block_order_` of the block 902*795d594fSAndroid Build Coastguard Worker // we are generating code for. 903*795d594fSAndroid Build Coastguard Worker size_t current_block_index_; 904*795d594fSAndroid Build Coastguard Worker 905*795d594fSAndroid Build Coastguard Worker // Whether the method is a leaf method. 906*795d594fSAndroid Build Coastguard Worker bool is_leaf_; 907*795d594fSAndroid Build Coastguard Worker 908*795d594fSAndroid Build Coastguard Worker // Whether the method has to emit a SuspendCheck at entry. 909*795d594fSAndroid Build Coastguard Worker bool needs_suspend_check_entry_; 910*795d594fSAndroid Build Coastguard Worker 911*795d594fSAndroid Build Coastguard Worker // Whether an instruction in the graph accesses the current method. 912*795d594fSAndroid Build Coastguard Worker // TODO: Rename: this actually indicates that some instruction in the method 913*795d594fSAndroid Build Coastguard Worker // needs the environment including a valid stack frame. 914*795d594fSAndroid Build Coastguard Worker bool requires_current_method_; 915*795d594fSAndroid Build Coastguard Worker 916*795d594fSAndroid Build Coastguard Worker // The CodeGenerationData contains a ScopedArenaAllocator intended for reusing the 917*795d594fSAndroid Build Coastguard Worker // ArenaStack memory allocated in previous passes instead of adding to the memory 918*795d594fSAndroid Build Coastguard Worker // held by the ArenaAllocator. This ScopedArenaAllocator is created in 919*795d594fSAndroid Build Coastguard Worker // CodeGenerator::Compile() and remains alive until the CodeGenerator is destroyed. 920*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CodeGenerationData> code_generation_data_; 921*795d594fSAndroid Build Coastguard Worker 922*795d594fSAndroid Build Coastguard Worker // Which intrinsics we don't have handcrafted code for. 923*795d594fSAndroid Build Coastguard Worker art::ArrayRef<const bool> unimplemented_intrinsics_; 924*795d594fSAndroid Build Coastguard Worker 925*795d594fSAndroid Build Coastguard Worker friend class OptimizingCFITest; 926*795d594fSAndroid Build Coastguard Worker ART_FRIEND_TEST(CodegenTest, ARM64FrameSizeSIMD); 927*795d594fSAndroid Build Coastguard Worker ART_FRIEND_TEST(CodegenTest, ARM64FrameSizeNoSIMD); 928*795d594fSAndroid Build Coastguard Worker 929*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(CodeGenerator); 930*795d594fSAndroid Build Coastguard Worker }; 931*795d594fSAndroid Build Coastguard Worker 932*795d594fSAndroid Build Coastguard Worker template <typename C, typename F> 933*795d594fSAndroid Build Coastguard Worker class CallingConvention { 934*795d594fSAndroid Build Coastguard Worker public: CallingConvention(const C * registers,size_t number_of_registers,const F * fpu_registers,size_t number_of_fpu_registers,PointerSize pointer_size)935*795d594fSAndroid Build Coastguard Worker CallingConvention(const C* registers, 936*795d594fSAndroid Build Coastguard Worker size_t number_of_registers, 937*795d594fSAndroid Build Coastguard Worker const F* fpu_registers, 938*795d594fSAndroid Build Coastguard Worker size_t number_of_fpu_registers, 939*795d594fSAndroid Build Coastguard Worker PointerSize pointer_size) 940*795d594fSAndroid Build Coastguard Worker : registers_(registers), 941*795d594fSAndroid Build Coastguard Worker number_of_registers_(number_of_registers), 942*795d594fSAndroid Build Coastguard Worker fpu_registers_(fpu_registers), 943*795d594fSAndroid Build Coastguard Worker number_of_fpu_registers_(number_of_fpu_registers), 944*795d594fSAndroid Build Coastguard Worker pointer_size_(pointer_size) {} 945*795d594fSAndroid Build Coastguard Worker GetNumberOfRegisters()946*795d594fSAndroid Build Coastguard Worker size_t GetNumberOfRegisters() const { return number_of_registers_; } GetNumberOfFpuRegisters()947*795d594fSAndroid Build Coastguard Worker size_t GetNumberOfFpuRegisters() const { return number_of_fpu_registers_; } 948*795d594fSAndroid Build Coastguard Worker GetRegisterAt(size_t index)949*795d594fSAndroid Build Coastguard Worker C GetRegisterAt(size_t index) const { 950*795d594fSAndroid Build Coastguard Worker DCHECK_LT(index, number_of_registers_); 951*795d594fSAndroid Build Coastguard Worker return registers_[index]; 952*795d594fSAndroid Build Coastguard Worker } 953*795d594fSAndroid Build Coastguard Worker GetFpuRegisterAt(size_t index)954*795d594fSAndroid Build Coastguard Worker F GetFpuRegisterAt(size_t index) const { 955*795d594fSAndroid Build Coastguard Worker DCHECK_LT(index, number_of_fpu_registers_); 956*795d594fSAndroid Build Coastguard Worker return fpu_registers_[index]; 957*795d594fSAndroid Build Coastguard Worker } 958*795d594fSAndroid Build Coastguard Worker GetStackOffsetOf(size_t index)959*795d594fSAndroid Build Coastguard Worker size_t GetStackOffsetOf(size_t index) const { 960*795d594fSAndroid Build Coastguard Worker // We still reserve the space for parameters passed by registers. 961*795d594fSAndroid Build Coastguard Worker // Add space for the method pointer. 962*795d594fSAndroid Build Coastguard Worker return static_cast<size_t>(pointer_size_) + index * kVRegSize; 963*795d594fSAndroid Build Coastguard Worker } 964*795d594fSAndroid Build Coastguard Worker 965*795d594fSAndroid Build Coastguard Worker private: 966*795d594fSAndroid Build Coastguard Worker const C* registers_; 967*795d594fSAndroid Build Coastguard Worker const size_t number_of_registers_; 968*795d594fSAndroid Build Coastguard Worker const F* fpu_registers_; 969*795d594fSAndroid Build Coastguard Worker const size_t number_of_fpu_registers_; 970*795d594fSAndroid Build Coastguard Worker const PointerSize pointer_size_; 971*795d594fSAndroid Build Coastguard Worker 972*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(CallingConvention); 973*795d594fSAndroid Build Coastguard Worker }; 974*795d594fSAndroid Build Coastguard Worker 975*795d594fSAndroid Build Coastguard Worker /** 976*795d594fSAndroid Build Coastguard Worker * A templated class SlowPathGenerator with a templated method NewSlowPath() 977*795d594fSAndroid Build Coastguard Worker * that can be used by any code generator to share equivalent slow-paths with 978*795d594fSAndroid Build Coastguard Worker * the objective of reducing generated code size. 979*795d594fSAndroid Build Coastguard Worker * 980*795d594fSAndroid Build Coastguard Worker * InstructionType: instruction that requires SlowPathCodeType 981*795d594fSAndroid Build Coastguard Worker * SlowPathCodeType: subclass of SlowPathCode, with constructor SlowPathCodeType(InstructionType *) 982*795d594fSAndroid Build Coastguard Worker */ 983*795d594fSAndroid Build Coastguard Worker template <typename InstructionType> 984*795d594fSAndroid Build Coastguard Worker class SlowPathGenerator { 985*795d594fSAndroid Build Coastguard Worker static_assert(std::is_base_of<HInstruction, InstructionType>::value, 986*795d594fSAndroid Build Coastguard Worker "InstructionType is not a subclass of art::HInstruction"); 987*795d594fSAndroid Build Coastguard Worker 988*795d594fSAndroid Build Coastguard Worker public: SlowPathGenerator(HGraph * graph,CodeGenerator * codegen)989*795d594fSAndroid Build Coastguard Worker SlowPathGenerator(HGraph* graph, CodeGenerator* codegen) 990*795d594fSAndroid Build Coastguard Worker : graph_(graph), 991*795d594fSAndroid Build Coastguard Worker codegen_(codegen), 992*795d594fSAndroid Build Coastguard Worker slow_path_map_(std::less<uint32_t>(), 993*795d594fSAndroid Build Coastguard Worker graph->GetAllocator()->Adapter(kArenaAllocSlowPaths)) {} 994*795d594fSAndroid Build Coastguard Worker 995*795d594fSAndroid Build Coastguard Worker // Creates and adds a new slow-path, if needed, or returns existing one otherwise. 996*795d594fSAndroid Build Coastguard Worker // Templating the method (rather than the whole class) on the slow-path type enables 997*795d594fSAndroid Build Coastguard Worker // keeping this code at a generic, non architecture-specific place. 998*795d594fSAndroid Build Coastguard Worker // 999*795d594fSAndroid Build Coastguard Worker // NOTE: This approach assumes each InstructionType only generates one SlowPathCodeType. 1000*795d594fSAndroid Build Coastguard Worker // To relax this requirement, we would need some RTTI on the stored slow-paths, 1001*795d594fSAndroid Build Coastguard Worker // or template the class as a whole on SlowPathType. 1002*795d594fSAndroid Build Coastguard Worker template <typename SlowPathCodeType> NewSlowPath(InstructionType * instruction)1003*795d594fSAndroid Build Coastguard Worker SlowPathCodeType* NewSlowPath(InstructionType* instruction) { 1004*795d594fSAndroid Build Coastguard Worker static_assert(std::is_base_of<SlowPathCode, SlowPathCodeType>::value, 1005*795d594fSAndroid Build Coastguard Worker "SlowPathCodeType is not a subclass of art::SlowPathCode"); 1006*795d594fSAndroid Build Coastguard Worker static_assert(std::is_constructible<SlowPathCodeType, InstructionType*>::value, 1007*795d594fSAndroid Build Coastguard Worker "SlowPathCodeType is not constructible from InstructionType*"); 1008*795d594fSAndroid Build Coastguard Worker // Iterate over potential candidates for sharing. Currently, only same-typed 1009*795d594fSAndroid Build Coastguard Worker // slow-paths with exactly the same dex-pc are viable candidates. 1010*795d594fSAndroid Build Coastguard Worker // TODO: pass dex-pc/slow-path-type to run-time to allow even more sharing? 1011*795d594fSAndroid Build Coastguard Worker const uint32_t dex_pc = instruction->GetDexPc(); 1012*795d594fSAndroid Build Coastguard Worker auto iter = slow_path_map_.find(dex_pc); 1013*795d594fSAndroid Build Coastguard Worker if (iter != slow_path_map_.end()) { 1014*795d594fSAndroid Build Coastguard Worker const ArenaVector<std::pair<InstructionType*, SlowPathCode*>>& candidates = iter->second; 1015*795d594fSAndroid Build Coastguard Worker for (const auto& it : candidates) { 1016*795d594fSAndroid Build Coastguard Worker InstructionType* other_instruction = it.first; 1017*795d594fSAndroid Build Coastguard Worker SlowPathCodeType* other_slow_path = down_cast<SlowPathCodeType*>(it.second); 1018*795d594fSAndroid Build Coastguard Worker // Determine if the instructions allow for slow-path sharing. 1019*795d594fSAndroid Build Coastguard Worker if (HaveSameLiveRegisters(instruction, other_instruction) && 1020*795d594fSAndroid Build Coastguard Worker HaveSameStackMap(instruction, other_instruction)) { 1021*795d594fSAndroid Build Coastguard Worker // Can share: reuse existing one. 1022*795d594fSAndroid Build Coastguard Worker return other_slow_path; 1023*795d594fSAndroid Build Coastguard Worker } 1024*795d594fSAndroid Build Coastguard Worker } 1025*795d594fSAndroid Build Coastguard Worker } else { 1026*795d594fSAndroid Build Coastguard Worker // First time this dex-pc is seen. 1027*795d594fSAndroid Build Coastguard Worker iter = slow_path_map_.Put(dex_pc, 1028*795d594fSAndroid Build Coastguard Worker {{}, {graph_->GetAllocator()->Adapter(kArenaAllocSlowPaths)}}); 1029*795d594fSAndroid Build Coastguard Worker } 1030*795d594fSAndroid Build Coastguard Worker // Cannot share: create and add new slow-path for this particular dex-pc. 1031*795d594fSAndroid Build Coastguard Worker SlowPathCodeType* slow_path = 1032*795d594fSAndroid Build Coastguard Worker new (codegen_->GetScopedAllocator()) SlowPathCodeType(instruction); 1033*795d594fSAndroid Build Coastguard Worker iter->second.emplace_back(std::make_pair(instruction, slow_path)); 1034*795d594fSAndroid Build Coastguard Worker codegen_->AddSlowPath(slow_path); 1035*795d594fSAndroid Build Coastguard Worker return slow_path; 1036*795d594fSAndroid Build Coastguard Worker } 1037*795d594fSAndroid Build Coastguard Worker 1038*795d594fSAndroid Build Coastguard Worker private: 1039*795d594fSAndroid Build Coastguard Worker // Tests if both instructions have same set of live physical registers. This ensures 1040*795d594fSAndroid Build Coastguard Worker // the slow-path has exactly the same preamble on saving these registers to stack. HaveSameLiveRegisters(const InstructionType * i1,const InstructionType * i2)1041*795d594fSAndroid Build Coastguard Worker bool HaveSameLiveRegisters(const InstructionType* i1, const InstructionType* i2) const { 1042*795d594fSAndroid Build Coastguard Worker const uint32_t core_spill = ~codegen_->GetCoreSpillMask(); 1043*795d594fSAndroid Build Coastguard Worker const uint32_t fpu_spill = ~codegen_->GetFpuSpillMask(); 1044*795d594fSAndroid Build Coastguard Worker RegisterSet* live1 = i1->GetLocations()->GetLiveRegisters(); 1045*795d594fSAndroid Build Coastguard Worker RegisterSet* live2 = i2->GetLocations()->GetLiveRegisters(); 1046*795d594fSAndroid Build Coastguard Worker return (((live1->GetCoreRegisters() & core_spill) == 1047*795d594fSAndroid Build Coastguard Worker (live2->GetCoreRegisters() & core_spill)) && 1048*795d594fSAndroid Build Coastguard Worker ((live1->GetFloatingPointRegisters() & fpu_spill) == 1049*795d594fSAndroid Build Coastguard Worker (live2->GetFloatingPointRegisters() & fpu_spill))); 1050*795d594fSAndroid Build Coastguard Worker } 1051*795d594fSAndroid Build Coastguard Worker 1052*795d594fSAndroid Build Coastguard Worker // Tests if both instructions have the same stack map. This ensures the interpreter 1053*795d594fSAndroid Build Coastguard Worker // will find exactly the same dex-registers at the same entries. HaveSameStackMap(const InstructionType * i1,const InstructionType * i2)1054*795d594fSAndroid Build Coastguard Worker bool HaveSameStackMap(const InstructionType* i1, const InstructionType* i2) const { 1055*795d594fSAndroid Build Coastguard Worker DCHECK(i1->HasEnvironment()); 1056*795d594fSAndroid Build Coastguard Worker DCHECK(i2->HasEnvironment()); 1057*795d594fSAndroid Build Coastguard Worker // We conservatively test if the two instructions find exactly the same instructions 1058*795d594fSAndroid Build Coastguard Worker // and location in each dex-register. This guarantees they will have the same stack map. 1059*795d594fSAndroid Build Coastguard Worker HEnvironment* e1 = i1->GetEnvironment(); 1060*795d594fSAndroid Build Coastguard Worker HEnvironment* e2 = i2->GetEnvironment(); 1061*795d594fSAndroid Build Coastguard Worker if (e1->GetParent() != e2->GetParent() || e1->Size() != e2->Size()) { 1062*795d594fSAndroid Build Coastguard Worker return false; 1063*795d594fSAndroid Build Coastguard Worker } 1064*795d594fSAndroid Build Coastguard Worker for (size_t i = 0, sz = e1->Size(); i < sz; ++i) { 1065*795d594fSAndroid Build Coastguard Worker if (e1->GetInstructionAt(i) != e2->GetInstructionAt(i) || 1066*795d594fSAndroid Build Coastguard Worker !e1->GetLocationAt(i).Equals(e2->GetLocationAt(i))) { 1067*795d594fSAndroid Build Coastguard Worker return false; 1068*795d594fSAndroid Build Coastguard Worker } 1069*795d594fSAndroid Build Coastguard Worker } 1070*795d594fSAndroid Build Coastguard Worker return true; 1071*795d594fSAndroid Build Coastguard Worker } 1072*795d594fSAndroid Build Coastguard Worker 1073*795d594fSAndroid Build Coastguard Worker HGraph* const graph_; 1074*795d594fSAndroid Build Coastguard Worker CodeGenerator* const codegen_; 1075*795d594fSAndroid Build Coastguard Worker 1076*795d594fSAndroid Build Coastguard Worker // Map from dex-pc to vector of already existing instruction/slow-path pairs. 1077*795d594fSAndroid Build Coastguard Worker ArenaSafeMap<uint32_t, ArenaVector<std::pair<InstructionType*, SlowPathCode*>>> slow_path_map_; 1078*795d594fSAndroid Build Coastguard Worker 1079*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(SlowPathGenerator); 1080*795d594fSAndroid Build Coastguard Worker }; 1081*795d594fSAndroid Build Coastguard Worker 1082*795d594fSAndroid Build Coastguard Worker class InstructionCodeGenerator : public HGraphVisitor { 1083*795d594fSAndroid Build Coastguard Worker public: InstructionCodeGenerator(HGraph * graph,CodeGenerator * codegen)1084*795d594fSAndroid Build Coastguard Worker InstructionCodeGenerator(HGraph* graph, CodeGenerator* codegen) 1085*795d594fSAndroid Build Coastguard Worker : HGraphVisitor(graph), 1086*795d594fSAndroid Build Coastguard Worker deopt_slow_paths_(graph, codegen) {} 1087*795d594fSAndroid Build Coastguard Worker 1088*795d594fSAndroid Build Coastguard Worker protected: 1089*795d594fSAndroid Build Coastguard Worker // Add slow-path generator for each instruction/slow-path combination that desires sharing. 1090*795d594fSAndroid Build Coastguard Worker // TODO: under current regime, only deopt sharing make sense; extend later. 1091*795d594fSAndroid Build Coastguard Worker SlowPathGenerator<HDeoptimize> deopt_slow_paths_; 1092*795d594fSAndroid Build Coastguard Worker }; 1093*795d594fSAndroid Build Coastguard Worker 1094*795d594fSAndroid Build Coastguard Worker } // namespace art 1095*795d594fSAndroid Build Coastguard Worker 1096*795d594fSAndroid Build Coastguard Worker #endif // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_ 1097