// These XMM registers are non-volatile in ART ABI, but volatile in native ABI. // If the ART ABI changes, this list must be updated. It is used to ensure that // these are not clobbered by any direct call to native code (such as math intrinsics). static constexpr FloatRegister non_volatile_xmm_regs[] = { XMM12, XMM13, XMM14, XMM15 };
private: // Register allocator does not support adjusting frame size, so we cannot provide final locations // of stack arguments for register allocation. We ask the register allocator for any location and // move these arguments to the right place after adjusting the SP when generating the call. constbool for_register_allocation_;
size_t gpr_index_ = 0u;
size_t fpr_index_ = 0u;
size_t stack_offset_ = 0u;
private: // Generate code for the given suspend check. If not null, `successor` // is the block to branch to if the suspend check is not needed, and after // the suspend call. void GenerateSuspendCheck(HSuspendCheck* instruction, HBasicBlock* successor); void GenerateClassInitializationCheck(SlowPathCodeX86_64* slow_path, CpuRegister class_reg); void GenerateBitstringTypeCheckCompare(HTypeCheckInstruction* check, CpuRegister temp); void HandleBitwiseOperation(HBinaryOperation* operation); void GenerateRemFP(HRem* rem); void DivRemOneOrMinusOne(HBinaryOperation* instruction); void DivByPowerOfTwo(HDiv* instruction); void RemByPowerOfTwo(HRem* instruction); void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction); void GenerateDivRemIntegral(HBinaryOperation* instruction); void HandleCondition(HCondition* condition); void HandleShift(HBinaryOperation* operation); void HandleRotate(HBinaryOperation* rotate);
// Generate a heap reference load using one register `out`: // // out <- *(out + offset) // // while honoring heap poisoning and/or read barriers (if any). // // Location `maybe_temp` is used when generating a read barrier and // shall be a register in that case; it may be an invalid location // otherwise. void GenerateReferenceLoadOneRegister(HInstruction* instruction,
Location out,
uint32_t offset,
Location maybe_temp,
ReadBarrierOption read_barrier_option); // Generate a heap reference load using two different registers // `out` and `obj`: // // out <- *(obj + offset) // // while honoring heap poisoning and/or read barriers (if any). // // Location `maybe_temp` is used when generating a Baker's (fast // path) read barrier and shall be a register in that case; it may // be an invalid location otherwise. void GenerateReferenceLoadTwoRegisters(HInstruction* instruction,
Location out,
Location obj,
uint32_t offset,
ReadBarrierOption read_barrier_option);
// Generate code to invoke a runtime entry point. void InvokeRuntime(QuickEntrypointEnum entrypoint,
HInstruction* instruction,
SlowPathCode* slow_path = nullptr) override;
// Generate code to invoke a runtime entry point, but do not record // PC-related information in a stack map. void InvokeRuntimeWithoutRecordingPcInfo(int32_t entry_point_offset,
HInstruction* instruction,
SlowPathCode* slow_path);
// Emit a write barrier if: // A) emit_null_check is false // B) emit_null_check is true, and value is not null. void MaybeMarkGCCard(CpuRegister temp,
CpuRegister card,
CpuRegister object,
CpuRegister value, bool emit_null_check);
// Crash if the card table is not valid. This check is only emitted for the CC GC. We assert // `(!clean || !self->is_gc_marking)`, since the card table should not be set to clean when the CC // GC is marking for eliminated write barriers. void CheckGCCardIsValid(CpuRegister temp, CpuRegister card, CpuRegister object);
void GenerateMemoryBarrier(MemBarrierKind kind);
// Helper method to move a value between two locations. void Move(Location destination, Location source); // Helper method to load a value of non-reference type from memory. void LoadFromMemoryNoReference(DataType::Type type, Location dst, Address src);
// Check if the desired_string_load_kind is supported. If it is, return it, // otherwise return a fall-back kind that should be used instead.
HLoadString::LoadKind GetSupportedLoadStringKind(
HLoadString::LoadKind desired_string_load_kind) override;
// Check if the desired_class_load_kind is supported. If it is, return it, // otherwise return a fall-back kind that should be used instead.
HLoadClass::LoadKind GetSupportedLoadClassKind(
HLoadClass::LoadKind desired_class_load_kind) override;
// Check if the desired_dispatch_info is supported. If it is, return it, // otherwise return a fall-back info that should be used instead.
HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch( const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
ArtMethod* method) override;
// Fast path implementation of ReadBarrier::Barrier for a heap // reference field load when Baker's read barriers are used. void GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction,
Location ref,
CpuRegister obj,
uint32_t offset, bool needs_null_check); // Fast path implementation of ReadBarrier::Barrier for a heap // reference array load when Baker's read barriers are used. void GenerateArrayLoadWithBakerReadBarrier(HInstruction* instruction,
Location ref,
CpuRegister obj,
uint32_t data_offset,
Location index, bool needs_null_check); // Factored implementation, used by GenerateFieldLoadWithBakerReadBarrier, // GenerateArrayLoadWithBakerReadBarrier and some intrinsics. // // Load the object reference located at address `src`, held by // object `obj`, into `ref`, and mark it if needed. The base of // address `src` must be `obj`. // // If `always_update_field` is true, the value of the reference is // atomically updated in the holder (`obj`). This operation // requires two temporary registers, which must be provided as // non-null pointers (`temp1` and `temp2`). void GenerateReferenceLoadWithBakerReadBarrier(HInstruction* instruction,
Location ref,
CpuRegister obj, const Address& src, bool needs_null_check, bool always_update_field = false,
CpuRegister* temp1 = nullptr,
CpuRegister* temp2 = nullptr);
// Generate a read barrier for a heap reference within `instruction` // using a slow path. // // A read barrier for an object reference read from the heap is // implemented as a call to the artReadBarrierSlow runtime entry // point, which is passed the values in locations `ref`, `obj`, and // `offset`: // // mirror::Object* artReadBarrierSlow(mirror::Object* ref, // mirror::Object* obj, // uint32_t offset); // // The `out` location contains the value returned by // artReadBarrierSlow. // // When `index` provided (i.e., when it is different from // Location::NoLocation()), the offset value passed to // artReadBarrierSlow is adjusted to take `index` into account. void GenerateReadBarrierSlow(HInstruction* instruction,
Location out,
Location ref,
Location obj,
uint32_t offset,
Location index = Location::NoLocation());
// If read barriers are enabled, generate a read barrier for a heap // reference using a slow path. If heap poisoning is enabled, also // unpoison the reference in `out`. void MaybeGenerateReadBarrierSlow(HInstruction* instruction,
Location out,
Location ref,
Location obj,
uint32_t offset,
Location index = Location::NoLocation());
// Generate a read barrier for a GC root within `instruction` using // a slow path. // // A read barrier for an object reference GC root is implemented as // a call to the artReadBarrierForRootSlow runtime entry point, // which is passed the value in location `root`: // // mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root); // // The `out` location contains the value returned by // artReadBarrierForRootSlow. void GenerateReadBarrierForRootSlow(HInstruction* instruction, Location out, Location root);
int ConstantAreaStart() const { return constant_area_start_;
}
// Load a 32/64-bit value into a register in the most efficient manner. void Load32BitValue(CpuRegister dest, int32_t value); void Load64BitValue(CpuRegister dest, int64_t value); void Load32BitValue(XmmRegister dest, int32_t value); void Load64BitValue(XmmRegister dest, int64_t value); void Load32BitValue(XmmRegister dest, float value); void Load64BitValue(XmmRegister dest, double value);
// Compare a register with a 32/64-bit value in the most efficient manner. void Compare32BitValue(CpuRegister dest, int32_t value); void Compare64BitValue(CpuRegister dest, int64_t value);
// Compare int values. Supports register locations for `lhs`. void GenerateIntCompare(Location lhs, Location rhs); void GenerateIntCompare(CpuRegister lhs, Location rhs);
// Compare long values. Supports only register locations for `lhs`. void GenerateLongCompare(Location lhs, Location rhs);
// Assign a 64 bit constant to an address. void MoveInt64ToAddress(const Address& addr_low, const Address& addr_high,
int64_t v,
HInstruction* instruction);
// Ensure that prior stores complete to memory before subsequent loads. // The locked add implementation will avoid serializing device memory, but will // touch (but not change) the top of the stack. // The 'non_temporal' parameter should be used to ensure ordering of non-temporal stores. void MemoryFence(bool force_mfence = false) { if (!force_mfence) {
assembler_.lock()->addl(Address(CpuRegister(RSP), 0), Immediate(0));
} else {
assembler_.mfence();
}
}
// When we don't know the proper offset for the value, we use kPlaceholder32BitOffset. // We will fix this up in the linker later to have the right value. static constexpr int32_t kPlaceholder32BitOffset = 256;
// Labels for each block that will be compiled.
Label* block_labels_; // Indexed by block id.
Label frame_entry_label_;
LocationsBuilderX86_64 location_builder_;
InstructionCodeGeneratorX86_64 instruction_visitor_;
ParallelMoveResolverX86_64 move_resolver_;
X86_64Assembler assembler_;
// Offset to the start of the constant area in the assembled code. // Used for fixups to the constant area. int constant_area_start_;
// PC-relative method patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PatchInfo<Label>> boot_image_method_patches_; // PC-relative method patch info for kAppImageRelRo.
ArenaDeque<PatchInfo<Label>> app_image_method_patches_; // PC-relative method patch info for kBssEntry.
ArenaDeque<PatchInfo<Label>> method_bss_entry_patches_; // PC-relative type patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PatchInfo<Label>> boot_image_type_patches_; // PC-relative type patch info for kAppImageRelRo.
ArenaDeque<PatchInfo<Label>> app_image_type_patches_; // PC-relative type patch info for kBssEntry.
ArenaDeque<PatchInfo<Label>> type_bss_entry_patches_; // PC-relative public type patch info for kBssEntryPublic.
ArenaDeque<PatchInfo<Label>> public_type_bss_entry_patches_; // PC-relative package type patch info for kBssEntryPackage.
ArenaDeque<PatchInfo<Label>> package_type_bss_entry_patches_; // PC-relative String patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PatchInfo<Label>> boot_image_string_patches_; // PC-relative String patch info for kAppImageRelRo.
ArenaDeque<PatchInfo<Label>> app_image_string_patches_; // PC-relative String patch info for kBssEntry.
ArenaDeque<PatchInfo<Label>> string_bss_entry_patches_; // PC-relative MethodType patch info for kBssEntry.
ArenaDeque<PatchInfo<Label>> method_type_bss_entry_patches_; // PC-relative method patch info for kBootImageLinkTimePcRelative+kCallCriticalNative.
ArenaDeque<PatchInfo<Label>> boot_image_jni_entrypoint_patches_; // PC-relative patch info for IntrinsicObjects for the boot image, // and for method/type/string patches for kBootImageRelRo otherwise.
ArenaDeque<PatchInfo<Label>> boot_image_other_patches_;
// Patches for string literals in JIT compiled code.
ArenaDeque<PatchInfo<Label>> jit_string_patches_; // Patches for class literals in JIT compiled code.
ArenaDeque<PatchInfo<Label>> jit_class_patches_; // Patches for method type in JIT compiled code.
ArenaDeque<PatchInfo<Label>> jit_method_type_patches_;
// Fixups for jump tables need to be handled specially.
ArenaVector<JumpTableRIPFixup*> fixups_to_jump_tables_;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.