Home | History | Annotate | Download | only in optimizing
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_COMPILER_OPTIMIZING_CODE_GENERATOR_X86_64_H_
     18 #define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_X86_64_H_
     19 
     20 #include "arch/x86_64/instruction_set_features_x86_64.h"
     21 #include "code_generator.h"
     22 #include "driver/compiler_options.h"
     23 #include "nodes.h"
     24 #include "parallel_move_resolver.h"
     25 #include "utils/x86_64/assembler_x86_64.h"
     26 
     27 namespace art {
     28 namespace x86_64 {
     29 
     30 // Use a local definition to prevent copying mistakes.
     31 static constexpr size_t kX86_64WordSize = static_cast<size_t>(kX86_64PointerSize);
     32 
     33 // Some x86_64 instructions require a register to be available as temp.
     34 static constexpr Register TMP = R11;
     35 
     36 static constexpr Register kParameterCoreRegisters[] = { RSI, RDX, RCX, R8, R9 };
     37 static constexpr FloatRegister kParameterFloatRegisters[] =
     38     { XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7 };
     39 
     40 static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
     41 static constexpr size_t kParameterFloatRegistersLength = arraysize(kParameterFloatRegisters);
     42 
     43 static constexpr Register kRuntimeParameterCoreRegisters[] = { RDI, RSI, RDX, RCX };
     44 static constexpr size_t kRuntimeParameterCoreRegistersLength =
     45     arraysize(kRuntimeParameterCoreRegisters);
     46 static constexpr FloatRegister kRuntimeParameterFpuRegisters[] = { XMM0, XMM1 };
     47 static constexpr size_t kRuntimeParameterFpuRegistersLength =
     48     arraysize(kRuntimeParameterFpuRegisters);
     49 
     50 // These XMM registers are non-volatile in ART ABI, but volatile in native ABI.
     51 // If the ART ABI changes, this list must be updated.  It is used to ensure that
     52 // these are not clobbered by any direct call to native code (such as math intrinsics).
     53 static constexpr FloatRegister non_volatile_xmm_regs[] = { XMM12, XMM13, XMM14, XMM15 };
     54 
     55 
     56 class InvokeRuntimeCallingConvention : public CallingConvention<Register, FloatRegister> {
     57  public:
     58   InvokeRuntimeCallingConvention()
     59       : CallingConvention(kRuntimeParameterCoreRegisters,
     60                           kRuntimeParameterCoreRegistersLength,
     61                           kRuntimeParameterFpuRegisters,
     62                           kRuntimeParameterFpuRegistersLength,
     63                           kX86_64PointerSize) {}
     64 
     65  private:
     66   DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
     67 };
     68 
     69 class InvokeDexCallingConvention : public CallingConvention<Register, FloatRegister> {
     70  public:
     71   InvokeDexCallingConvention() : CallingConvention(
     72       kParameterCoreRegisters,
     73       kParameterCoreRegistersLength,
     74       kParameterFloatRegisters,
     75       kParameterFloatRegistersLength,
     76       kX86_64PointerSize) {}
     77 
     78  private:
     79   DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
     80 };
     81 
     82 class FieldAccessCallingConventionX86_64 : public FieldAccessCallingConvention {
     83  public:
     84   FieldAccessCallingConventionX86_64() {}
     85 
     86   Location GetObjectLocation() const OVERRIDE {
     87     return Location::RegisterLocation(RSI);
     88   }
     89   Location GetFieldIndexLocation() const OVERRIDE {
     90     return Location::RegisterLocation(RDI);
     91   }
     92   Location GetReturnLocation(DataType::Type type ATTRIBUTE_UNUSED) const OVERRIDE {
     93     return Location::RegisterLocation(RAX);
     94   }
     95   Location GetSetValueLocation(DataType::Type type ATTRIBUTE_UNUSED, bool is_instance)
     96       const OVERRIDE {
     97     return is_instance
     98         ? Location::RegisterLocation(RDX)
     99         : Location::RegisterLocation(RSI);
    100   }
    101   Location GetFpuLocation(DataType::Type type ATTRIBUTE_UNUSED) const OVERRIDE {
    102     return Location::FpuRegisterLocation(XMM0);
    103   }
    104 
    105  private:
    106   DISALLOW_COPY_AND_ASSIGN(FieldAccessCallingConventionX86_64);
    107 };
    108 
    109 
    110 class InvokeDexCallingConventionVisitorX86_64 : public InvokeDexCallingConventionVisitor {
    111  public:
    112   InvokeDexCallingConventionVisitorX86_64() {}
    113   virtual ~InvokeDexCallingConventionVisitorX86_64() {}
    114 
    115   Location GetNextLocation(DataType::Type type) OVERRIDE;
    116   Location GetReturnLocation(DataType::Type type) const OVERRIDE;
    117   Location GetMethodLocation() const OVERRIDE;
    118 
    119  private:
    120   InvokeDexCallingConvention calling_convention;
    121 
    122   DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitorX86_64);
    123 };
    124 
    125 class CodeGeneratorX86_64;
    126 
    127 class ParallelMoveResolverX86_64 : public ParallelMoveResolverWithSwap {
    128  public:
    129   ParallelMoveResolverX86_64(ArenaAllocator* allocator, CodeGeneratorX86_64* codegen)
    130       : ParallelMoveResolverWithSwap(allocator), codegen_(codegen) {}
    131 
    132   void EmitMove(size_t index) OVERRIDE;
    133   void EmitSwap(size_t index) OVERRIDE;
    134   void SpillScratch(int reg) OVERRIDE;
    135   void RestoreScratch(int reg) OVERRIDE;
    136 
    137   X86_64Assembler* GetAssembler() const;
    138 
    139  private:
    140   void Exchange32(CpuRegister reg, int mem);
    141   void Exchange32(XmmRegister reg, int mem);
    142   void Exchange64(CpuRegister reg1, CpuRegister reg2);
    143   void Exchange64(CpuRegister reg, int mem);
    144   void Exchange64(XmmRegister reg, int mem);
    145   void Exchange128(XmmRegister reg, int mem);
    146   void ExchangeMemory32(int mem1, int mem2);
    147   void ExchangeMemory64(int mem1, int mem2, int num_of_qwords);
    148 
    149   CodeGeneratorX86_64* const codegen_;
    150 
    151   DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverX86_64);
    152 };
    153 
    154 class LocationsBuilderX86_64 : public HGraphVisitor {
    155  public:
    156   LocationsBuilderX86_64(HGraph* graph, CodeGeneratorX86_64* codegen)
    157       : HGraphVisitor(graph), codegen_(codegen) {}
    158 
    159 #define DECLARE_VISIT_INSTRUCTION(name, super)     \
    160   void Visit##name(H##name* instr) OVERRIDE;
    161 
    162   FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION)
    163   FOR_EACH_CONCRETE_INSTRUCTION_X86_64(DECLARE_VISIT_INSTRUCTION)
    164 
    165 #undef DECLARE_VISIT_INSTRUCTION
    166 
    167   void VisitInstruction(HInstruction* instruction) OVERRIDE {
    168     LOG(FATAL) << "Unreachable instruction " << instruction->DebugName()
    169                << " (id " << instruction->GetId() << ")";
    170   }
    171 
    172  private:
    173   void HandleInvoke(HInvoke* invoke);
    174   void HandleBitwiseOperation(HBinaryOperation* operation);
    175   void HandleCondition(HCondition* condition);
    176   void HandleShift(HBinaryOperation* operation);
    177   void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
    178   void HandleFieldGet(HInstruction* instruction);
    179 
    180   CodeGeneratorX86_64* const codegen_;
    181   InvokeDexCallingConventionVisitorX86_64 parameter_visitor_;
    182 
    183   DISALLOW_COPY_AND_ASSIGN(LocationsBuilderX86_64);
    184 };
    185 
    186 class InstructionCodeGeneratorX86_64 : public InstructionCodeGenerator {
    187  public:
    188   InstructionCodeGeneratorX86_64(HGraph* graph, CodeGeneratorX86_64* codegen);
    189 
    190 #define DECLARE_VISIT_INSTRUCTION(name, super)     \
    191   void Visit##name(H##name* instr) OVERRIDE;
    192 
    193   FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION)
    194   FOR_EACH_CONCRETE_INSTRUCTION_X86_64(DECLARE_VISIT_INSTRUCTION)
    195 
    196 #undef DECLARE_VISIT_INSTRUCTION
    197 
    198   void VisitInstruction(HInstruction* instruction) OVERRIDE {
    199     LOG(FATAL) << "Unreachable instruction " << instruction->DebugName()
    200                << " (id " << instruction->GetId() << ")";
    201   }
    202 
    203   X86_64Assembler* GetAssembler() const { return assembler_; }
    204 
    205  private:
    206   // Generate code for the given suspend check. If not null, `successor`
    207   // is the block to branch to if the suspend check is not needed, and after
    208   // the suspend call.
    209   void GenerateSuspendCheck(HSuspendCheck* instruction, HBasicBlock* successor);
    210   void GenerateClassInitializationCheck(SlowPathCode* slow_path, CpuRegister class_reg);
    211   void HandleBitwiseOperation(HBinaryOperation* operation);
    212   void GenerateRemFP(HRem* rem);
    213   void DivRemOneOrMinusOne(HBinaryOperation* instruction);
    214   void DivByPowerOfTwo(HDiv* instruction);
    215   void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction);
    216   void GenerateDivRemIntegral(HBinaryOperation* instruction);
    217   void HandleCondition(HCondition* condition);
    218   void HandleShift(HBinaryOperation* operation);
    219 
    220   void HandleFieldSet(HInstruction* instruction,
    221                       const FieldInfo& field_info,
    222                       bool value_can_be_null);
    223   void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
    224 
    225   // Generate a heap reference load using one register `out`:
    226   //
    227   //   out <- *(out + offset)
    228   //
    229   // while honoring heap poisoning and/or read barriers (if any).
    230   //
    231   // Location `maybe_temp` is used when generating a read barrier and
    232   // shall be a register in that case; it may be an invalid location
    233   // otherwise.
    234   void GenerateReferenceLoadOneRegister(HInstruction* instruction,
    235                                         Location out,
    236                                         uint32_t offset,
    237                                         Location maybe_temp,
    238                                         ReadBarrierOption read_barrier_option);
    239   // Generate a heap reference load using two different registers
    240   // `out` and `obj`:
    241   //
    242   //   out <- *(obj + offset)
    243   //
    244   // while honoring heap poisoning and/or read barriers (if any).
    245   //
    246   // Location `maybe_temp` is used when generating a Baker's (fast
    247   // path) read barrier and shall be a register in that case; it may
    248   // be an invalid location otherwise.
    249   void GenerateReferenceLoadTwoRegisters(HInstruction* instruction,
    250                                          Location out,
    251                                          Location obj,
    252                                          uint32_t offset,
    253                                          ReadBarrierOption read_barrier_option);
    254   // Generate a GC root reference load:
    255   //
    256   //   root <- *address
    257   //
    258   // while honoring read barriers based on read_barrier_option.
    259   void GenerateGcRootFieldLoad(HInstruction* instruction,
    260                                Location root,
    261                                const Address& address,
    262                                Label* fixup_label,
    263                                ReadBarrierOption read_barrier_option);
    264 
    265   void PushOntoFPStack(Location source, uint32_t temp_offset,
    266                        uint32_t stack_adjustment, bool is_float);
    267   void GenerateCompareTest(HCondition* condition);
    268   template<class LabelType>
    269   void GenerateTestAndBranch(HInstruction* instruction,
    270                              size_t condition_input_index,
    271                              LabelType* true_target,
    272                              LabelType* false_target);
    273   template<class LabelType>
    274   void GenerateCompareTestAndBranch(HCondition* condition,
    275                                     LabelType* true_target,
    276                                     LabelType* false_target);
    277   template<class LabelType>
    278   void GenerateFPJumps(HCondition* cond, LabelType* true_label, LabelType* false_label);
    279 
    280   void HandleGoto(HInstruction* got, HBasicBlock* successor);
    281 
    282   X86_64Assembler* const assembler_;
    283   CodeGeneratorX86_64* const codegen_;
    284 
    285   DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorX86_64);
    286 };
    287 
    288 // Class for fixups to jump tables.
    289 class JumpTableRIPFixup;
    290 
    291 class CodeGeneratorX86_64 : public CodeGenerator {
    292  public:
    293   CodeGeneratorX86_64(HGraph* graph,
    294                   const X86_64InstructionSetFeatures& isa_features,
    295                   const CompilerOptions& compiler_options,
    296                   OptimizingCompilerStats* stats = nullptr);
    297   virtual ~CodeGeneratorX86_64() {}
    298 
    299   void GenerateFrameEntry() OVERRIDE;
    300   void GenerateFrameExit() OVERRIDE;
    301   void Bind(HBasicBlock* block) OVERRIDE;
    302   void MoveConstant(Location destination, int32_t value) OVERRIDE;
    303   void MoveLocation(Location dst, Location src, DataType::Type dst_type) OVERRIDE;
    304   void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE;
    305 
    306   size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE;
    307   size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE;
    308   size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE;
    309   size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE;
    310 
    311   // Generate code to invoke a runtime entry point.
    312   void InvokeRuntime(QuickEntrypointEnum entrypoint,
    313                      HInstruction* instruction,
    314                      uint32_t dex_pc,
    315                      SlowPathCode* slow_path = nullptr) OVERRIDE;
    316 
    317   // Generate code to invoke a runtime entry point, but do not record
    318   // PC-related information in a stack map.
    319   void InvokeRuntimeWithoutRecordingPcInfo(int32_t entry_point_offset,
    320                                            HInstruction* instruction,
    321                                            SlowPathCode* slow_path);
    322 
    323   void GenerateInvokeRuntime(int32_t entry_point_offset);
    324 
    325   size_t GetWordSize() const OVERRIDE {
    326     return kX86_64WordSize;
    327   }
    328 
    329   size_t GetFloatingPointSpillSlotSize() const OVERRIDE {
    330     return GetGraph()->HasSIMD()
    331         ? 2 * kX86_64WordSize   // 16 bytes == 2 x86_64 words for each spill
    332         : 1 * kX86_64WordSize;  //  8 bytes == 1 x86_64 words for each spill
    333   }
    334 
    335   HGraphVisitor* GetLocationBuilder() OVERRIDE {
    336     return &location_builder_;
    337   }
    338 
    339   HGraphVisitor* GetInstructionVisitor() OVERRIDE {
    340     return &instruction_visitor_;
    341   }
    342 
    343   X86_64Assembler* GetAssembler() OVERRIDE {
    344     return &assembler_;
    345   }
    346 
    347   const X86_64Assembler& GetAssembler() const OVERRIDE {
    348     return assembler_;
    349   }
    350 
    351   ParallelMoveResolverX86_64* GetMoveResolver() OVERRIDE {
    352     return &move_resolver_;
    353   }
    354 
    355   uintptr_t GetAddressOf(HBasicBlock* block) OVERRIDE {
    356     return GetLabelOf(block)->Position();
    357   }
    358 
    359   void SetupBlockedRegisters() const OVERRIDE;
    360   void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE;
    361   void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE;
    362   void Finalize(CodeAllocator* allocator) OVERRIDE;
    363 
    364   InstructionSet GetInstructionSet() const OVERRIDE {
    365     return InstructionSet::kX86_64;
    366   }
    367 
    368   // Emit a write barrier.
    369   void MarkGCCard(CpuRegister temp,
    370                   CpuRegister card,
    371                   CpuRegister object,
    372                   CpuRegister value,
    373                   bool value_can_be_null);
    374 
    375   void GenerateMemoryBarrier(MemBarrierKind kind);
    376 
    377   // Helper method to move a value between two locations.
    378   void Move(Location destination, Location source);
    379 
    380   Label* GetLabelOf(HBasicBlock* block) const {
    381     return CommonGetLabelOf<Label>(block_labels_, block);
    382   }
    383 
    384   void Initialize() OVERRIDE {
    385     block_labels_ = CommonInitializeLabels<Label>();
    386   }
    387 
    388   bool NeedsTwoRegisters(DataType::Type type ATTRIBUTE_UNUSED) const OVERRIDE {
    389     return false;
    390   }
    391 
    392   // Check if the desired_string_load_kind is supported. If it is, return it,
    393   // otherwise return a fall-back kind that should be used instead.
    394   HLoadString::LoadKind GetSupportedLoadStringKind(
    395       HLoadString::LoadKind desired_string_load_kind) OVERRIDE;
    396 
    397   // Check if the desired_class_load_kind is supported. If it is, return it,
    398   // otherwise return a fall-back kind that should be used instead.
    399   HLoadClass::LoadKind GetSupportedLoadClassKind(
    400       HLoadClass::LoadKind desired_class_load_kind) OVERRIDE;
    401 
    402   // Check if the desired_dispatch_info is supported. If it is, return it,
    403   // otherwise return a fall-back info that should be used instead.
    404   HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch(
    405       const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
    406       HInvokeStaticOrDirect* invoke) OVERRIDE;
    407 
    408   void GenerateStaticOrDirectCall(
    409       HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
    410   void GenerateVirtualCall(
    411       HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
    412 
    413   void RecordBootImageMethodPatch(HInvokeStaticOrDirect* invoke);
    414   void RecordMethodBssEntryPatch(HInvokeStaticOrDirect* invoke);
    415   void RecordBootImageTypePatch(HLoadClass* load_class);
    416   Label* NewTypeBssEntryPatch(HLoadClass* load_class);
    417   void RecordBootImageStringPatch(HLoadString* load_string);
    418   Label* NewStringBssEntryPatch(HLoadString* load_string);
    419   Label* NewJitRootStringPatch(const DexFile& dex_file,
    420                                dex::StringIndex string_index,
    421                                Handle<mirror::String> handle);
    422   Label* NewJitRootClassPatch(const DexFile& dex_file,
    423                               dex::TypeIndex type_index,
    424                               Handle<mirror::Class> handle);
    425 
    426   void MoveFromReturnRegister(Location trg, DataType::Type type) OVERRIDE;
    427 
    428   void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) OVERRIDE;
    429 
    430   void PatchJitRootUse(uint8_t* code,
    431                        const uint8_t* roots_data,
    432                        const PatchInfo<Label>& info,
    433                        uint64_t index_in_table) const;
    434 
    435   void EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) OVERRIDE;
    436 
    437   const X86_64InstructionSetFeatures& GetInstructionSetFeatures() const {
    438     return isa_features_;
    439   }
    440 
    441   // Fast path implementation of ReadBarrier::Barrier for a heap
    442   // reference field load when Baker's read barriers are used.
    443   void GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction,
    444                                              Location ref,
    445                                              CpuRegister obj,
    446                                              uint32_t offset,
    447                                              bool needs_null_check);
    448   // Fast path implementation of ReadBarrier::Barrier for a heap
    449   // reference array load when Baker's read barriers are used.
    450   void GenerateArrayLoadWithBakerReadBarrier(HInstruction* instruction,
    451                                              Location ref,
    452                                              CpuRegister obj,
    453                                              uint32_t data_offset,
    454                                              Location index,
    455                                              bool needs_null_check);
    456   // Factored implementation, used by GenerateFieldLoadWithBakerReadBarrier,
    457   // GenerateArrayLoadWithBakerReadBarrier and some intrinsics.
    458   //
    459   // Load the object reference located at address `src`, held by
    460   // object `obj`, into `ref`, and mark it if needed.  The base of
    461   // address `src` must be `obj`.
    462   //
    463   // If `always_update_field` is true, the value of the reference is
    464   // atomically updated in the holder (`obj`).  This operation
    465   // requires two temporary registers, which must be provided as
    466   // non-null pointers (`temp1` and `temp2`).
    467   void GenerateReferenceLoadWithBakerReadBarrier(HInstruction* instruction,
    468                                                  Location ref,
    469                                                  CpuRegister obj,
    470                                                  const Address& src,
    471                                                  bool needs_null_check,
    472                                                  bool always_update_field = false,
    473                                                  CpuRegister* temp1 = nullptr,
    474                                                  CpuRegister* temp2 = nullptr);
    475 
    476   // Generate a read barrier for a heap reference within `instruction`
    477   // using a slow path.
    478   //
    479   // A read barrier for an object reference read from the heap is
    480   // implemented as a call to the artReadBarrierSlow runtime entry
    481   // point, which is passed the values in locations `ref`, `obj`, and
    482   // `offset`:
    483   //
    484   //   mirror::Object* artReadBarrierSlow(mirror::Object* ref,
    485   //                                      mirror::Object* obj,
    486   //                                      uint32_t offset);
    487   //
    488   // The `out` location contains the value returned by
    489   // artReadBarrierSlow.
    490   //
    491   // When `index` provided (i.e., when it is different from
    492   // Location::NoLocation()), the offset value passed to
    493   // artReadBarrierSlow is adjusted to take `index` into account.
    494   void GenerateReadBarrierSlow(HInstruction* instruction,
    495                                Location out,
    496                                Location ref,
    497                                Location obj,
    498                                uint32_t offset,
    499                                Location index = Location::NoLocation());
    500 
    501   // If read barriers are enabled, generate a read barrier for a heap
    502   // reference using a slow path. If heap poisoning is enabled, also
    503   // unpoison the reference in `out`.
    504   void MaybeGenerateReadBarrierSlow(HInstruction* instruction,
    505                                     Location out,
    506                                     Location ref,
    507                                     Location obj,
    508                                     uint32_t offset,
    509                                     Location index = Location::NoLocation());
    510 
    511   // Generate a read barrier for a GC root within `instruction` using
    512   // a slow path.
    513   //
    514   // A read barrier for an object reference GC root is implemented as
    515   // a call to the artReadBarrierForRootSlow runtime entry point,
    516   // which is passed the value in location `root`:
    517   //
    518   //   mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root);
    519   //
    520   // The `out` location contains the value returned by
    521   // artReadBarrierForRootSlow.
    522   void GenerateReadBarrierForRootSlow(HInstruction* instruction, Location out, Location root);
    523 
    524   int ConstantAreaStart() const {
    525     return constant_area_start_;
    526   }
    527 
    528   Address LiteralDoubleAddress(double v);
    529   Address LiteralFloatAddress(float v);
    530   Address LiteralInt32Address(int32_t v);
    531   Address LiteralInt64Address(int64_t v);
    532 
    533   // Load a 32/64-bit value into a register in the most efficient manner.
    534   void Load32BitValue(CpuRegister dest, int32_t value);
    535   void Load64BitValue(CpuRegister dest, int64_t value);
    536   void Load32BitValue(XmmRegister dest, int32_t value);
    537   void Load64BitValue(XmmRegister dest, int64_t value);
    538   void Load32BitValue(XmmRegister dest, float value);
    539   void Load64BitValue(XmmRegister dest, double value);
    540 
    541   // Compare a register with a 32/64-bit value in the most efficient manner.
    542   void Compare32BitValue(CpuRegister dest, int32_t value);
    543   void Compare64BitValue(CpuRegister dest, int64_t value);
    544 
    545   // Compare int values. Supports register locations for `lhs`.
    546   void GenerateIntCompare(Location lhs, Location rhs);
    547   void GenerateIntCompare(CpuRegister lhs, Location rhs);
    548 
    549   // Compare long values. Supports only register locations for `lhs`.
    550   void GenerateLongCompare(Location lhs, Location rhs);
    551 
    552   // Construct address for array access.
    553   static Address ArrayAddress(CpuRegister obj,
    554                               Location index,
    555                               ScaleFactor scale,
    556                               uint32_t data_offset);
    557 
    558   Address LiteralCaseTable(HPackedSwitch* switch_instr);
    559 
    560   // Store a 64 bit value into a DoubleStackSlot in the most efficient manner.
    561   void Store64BitValueToStack(Location dest, int64_t value);
    562 
    563   // Assign a 64 bit constant to an address.
    564   void MoveInt64ToAddress(const Address& addr_low,
    565                           const Address& addr_high,
    566                           int64_t v,
    567                           HInstruction* instruction);
    568 
    569   // Ensure that prior stores complete to memory before subsequent loads.
    570   // The locked add implementation will avoid serializing device memory, but will
    571   // touch (but not change) the top of the stack.
    572   // The 'non_temporal' parameter should be used to ensure ordering of non-temporal stores.
    573   void MemoryFence(bool force_mfence = false) {
    574     if (!force_mfence) {
    575       assembler_.lock()->addl(Address(CpuRegister(RSP), 0), Immediate(0));
    576     } else {
    577       assembler_.mfence();
    578     }
    579   }
    580 
    581   void GenerateNop() OVERRIDE;
    582   void GenerateImplicitNullCheck(HNullCheck* instruction) OVERRIDE;
    583   void GenerateExplicitNullCheck(HNullCheck* instruction) OVERRIDE;
    584 
    585   // When we don't know the proper offset for the value, we use kDummy32BitOffset.
    586   // We will fix this up in the linker later to have the right value.
    587   static constexpr int32_t kDummy32BitOffset = 256;
    588 
    589  private:
    590   template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)>
    591   static void EmitPcRelativeLinkerPatches(const ArenaDeque<PatchInfo<Label>>& infos,
    592                                           ArenaVector<linker::LinkerPatch>* linker_patches);
    593 
    594   // Labels for each block that will be compiled.
    595   Label* block_labels_;  // Indexed by block id.
    596   Label frame_entry_label_;
    597   LocationsBuilderX86_64 location_builder_;
    598   InstructionCodeGeneratorX86_64 instruction_visitor_;
    599   ParallelMoveResolverX86_64 move_resolver_;
    600   X86_64Assembler assembler_;
    601   const X86_64InstructionSetFeatures& isa_features_;
    602 
    603   // Offset to the start of the constant area in the assembled code.
    604   // Used for fixups to the constant area.
    605   int constant_area_start_;
    606 
    607   // PC-relative method patch info for kBootImageLinkTimePcRelative.
    608   ArenaDeque<PatchInfo<Label>> boot_image_method_patches_;
    609   // PC-relative method patch info for kBssEntry.
    610   ArenaDeque<PatchInfo<Label>> method_bss_entry_patches_;
    611   // PC-relative type patch info for kBootImageLinkTimePcRelative.
    612   ArenaDeque<PatchInfo<Label>> boot_image_type_patches_;
    613   // Type patch locations for kBssEntry.
    614   ArenaDeque<PatchInfo<Label>> type_bss_entry_patches_;
    615   // String patch locations; type depends on configuration (intern table or boot image PIC).
    616   ArenaDeque<PatchInfo<Label>> boot_image_string_patches_;
    617   // String patch locations for kBssEntry.
    618   ArenaDeque<PatchInfo<Label>> string_bss_entry_patches_;
    619 
    620   // Patches for string literals in JIT compiled code.
    621   ArenaDeque<PatchInfo<Label>> jit_string_patches_;
    622   // Patches for class literals in JIT compiled code.
    623   ArenaDeque<PatchInfo<Label>> jit_class_patches_;
    624 
    625   // Fixups for jump tables need to be handled specially.
    626   ArenaVector<JumpTableRIPFixup*> fixups_to_jump_tables_;
    627 
    628   DISALLOW_COPY_AND_ASSIGN(CodeGeneratorX86_64);
    629 };
    630 
    631 }  // namespace x86_64
    632 }  // namespace art
    633 
    634 #endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_X86_64_H_
    635