From f4da675bbc4615c5f854c81964cac9dd1153baea Mon Sep 17 00:00:00 2001 From: Vladimir Marko Date: Fri, 1 Aug 2014 19:04:18 +0100 Subject: Implement method calls using relative BL on ARM. Store the linker patches with each CompiledMethod instead of keeping them in CompilerDriver. Reorganize oat file creation to apply the patches as we're writing the method code. Add framework for platform-specific relative call patches in the OatWriter. Implement relative call patches for ARM. Change-Id: Ie2effb3d92b61ac8f356140eba09dc37d62290f8 --- compiler/compiled_method.h | 106 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 1 deletion(-) (limited to 'compiler/compiled_method.h') diff --git a/compiler/compiled_method.h b/compiler/compiled_method.h index cc46b92dc5..cdae8d2d24 100644 --- a/compiler/compiled_method.h +++ b/compiler/compiled_method.h @@ -22,7 +22,9 @@ #include #include "instruction_set.h" +#include "method_reference.h" #include "utils.h" +#include "utils/array_ref.h" namespace llvm { class Function; @@ -171,6 +173,101 @@ class SrcMap FINAL : public std::vector { } }; +enum LinkerPatchType { + kLinkerPatchMethod, + kLinkerPatchCall, + kLinkerPatchCallRelative, // NOTE: Actual patching is instruction_set-dependent. + kLinkerPatchType, +}; + +class LinkerPatch { + public: + static LinkerPatch MethodPatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t target_method_idx) { + return LinkerPatch(literal_offset, kLinkerPatchMethod, + target_method_idx, target_dex_file); + } + + static LinkerPatch CodePatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t target_method_idx) { + return LinkerPatch(literal_offset, kLinkerPatchCall, + target_method_idx, target_dex_file); + } + + static LinkerPatch RelativeCodePatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t target_method_idx) { + return LinkerPatch(literal_offset, kLinkerPatchCallRelative, + target_method_idx, target_dex_file); + } + + static LinkerPatch TypePatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t target_type_idx) { + return LinkerPatch(literal_offset, kLinkerPatchType, target_type_idx, target_dex_file); + } + + LinkerPatch(const LinkerPatch& other) = default; + LinkerPatch& operator=(const LinkerPatch& other) = default; + + size_t LiteralOffset() const { + return literal_offset_; + } + + LinkerPatchType Type() const { + return patch_type_; + } + + MethodReference TargetMethod() const { + DCHECK(patch_type_ == kLinkerPatchMethod || + patch_type_ == kLinkerPatchCall || patch_type_ == kLinkerPatchCallRelative); + return MethodReference(target_dex_file_, target_idx_); + } + + const DexFile* TargetTypeDexFile() const { + DCHECK(patch_type_ == kLinkerPatchType); + return target_dex_file_; + } + + uint32_t TargetTypeIndex() const { + DCHECK(patch_type_ == kLinkerPatchType); + return target_idx_; + } + + private: + LinkerPatch(size_t literal_offset, LinkerPatchType patch_type, + uint32_t target_idx, const DexFile* target_dex_file) + : literal_offset_(literal_offset), + patch_type_(patch_type), + target_idx_(target_idx), + target_dex_file_(target_dex_file) { + } + + size_t literal_offset_; + LinkerPatchType patch_type_; + uint32_t target_idx_; // Method index (Call/Method patches) or type index (Type patches). + const DexFile* target_dex_file_; + + friend bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs); + friend bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs); +}; + +inline bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs) { + return lhs.literal_offset_ == rhs.literal_offset_ && + lhs.patch_type_ == rhs.patch_type_ && + lhs.target_idx_ == rhs.target_idx_ && + lhs.target_dex_file_ == rhs.target_dex_file_; +} + +inline bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs) { + return (lhs.literal_offset_ != rhs.literal_offset_) ? lhs.literal_offset_ < rhs.literal_offset_ + : (lhs.patch_type_ != rhs.patch_type_) ? lhs.patch_type_ < rhs.patch_type_ + : (lhs.target_idx_ != rhs.target_idx_) ? lhs.target_idx_ < rhs.target_idx_ + : lhs.target_dex_file_ < rhs.target_dex_file_; +} + class CompiledMethod FINAL : public CompiledCode { public: // Constructs a CompiledMethod for Quick. @@ -184,7 +281,8 @@ class CompiledMethod FINAL : public CompiledCode { const std::vector& mapping_table, const std::vector& vmap_table, const std::vector& native_gc_map, - const std::vector* cfi_info); + const std::vector* cfi_info, + const ArrayRef& patches = ArrayRef()); // Constructs a CompiledMethod for Optimizing. CompiledMethod(CompilerDriver* driver, @@ -250,6 +348,10 @@ class CompiledMethod FINAL : public CompiledCode { return cfi_info_; } + const std::vector& GetPatches() const { + return patches_; + } + private: // For quick code, the size of the activation used by the code. const size_t frame_size_in_bytes_; @@ -269,6 +371,8 @@ class CompiledMethod FINAL : public CompiledCode { std::vector* gc_map_; // For quick code, a FDE entry for the debug_frame section. std::vector* cfi_info_; + // For quick code, linker patches needed by the method. + std::vector patches_; }; } // namespace art -- cgit v1.2.3-59-g8ed1b