diff options
Diffstat (limited to 'compiler/compiled_method.h')
| -rw-r--r-- | compiler/compiled_method.h | 103 |
1 files changed, 78 insertions, 25 deletions
diff --git a/compiler/compiled_method.h b/compiler/compiled_method.h index 58876200ca..70161eb221 100644 --- a/compiler/compiled_method.h +++ b/compiler/compiled_method.h @@ -18,6 +18,7 @@ #define ART_COMPILER_COMPILED_METHOD_H_ #include <memory> +#include <iosfwd> #include <string> #include <vector> @@ -158,21 +159,34 @@ class SrcMap FINAL : public std::vector<SrcMapElem, Allocator> { using DefaultSrcMap = SrcMap<std::allocator<SrcMapElem>>; - -enum LinkerPatchType { - kLinkerPatchMethod, - kLinkerPatchCall, - kLinkerPatchCallRelative, // NOTE: Actual patching is instruction_set-dependent. - kLinkerPatchType, - kLinkerPatchDexCacheArray, // NOTE: Actual patching is instruction_set-dependent. -}; - class LinkerPatch { public: + // Note: We explicitly specify the underlying type of the enum because GCC + // would otherwise select a bigger underlying type and then complain that + // 'art::LinkerPatch::patch_type_' is too small to hold all + // values of 'enum class art::LinkerPatch::Type' + // which is ridiculous given we have only a handful of values here. If we + // choose to squeeze the Type into fewer than 8 bits, we'll have to declare + // patch_type_ as an uintN_t and do explicit static_cast<>s. + enum class Type : uint8_t { + kRecordPosition, // Just record patch position for patchoat. + kMethod, + kCall, + kCallRelative, // NOTE: Actual patching is instruction_set-dependent. + kType, + kString, + kStringRelative, // NOTE: Actual patching is instruction_set-dependent. + kDexCacheArray, // NOTE: Actual patching is instruction_set-dependent. + }; + + static LinkerPatch RecordPosition(size_t literal_offset) { + return LinkerPatch(literal_offset, Type::kRecordPosition, /* target_dex_file */ nullptr); + } + static LinkerPatch MethodPatch(size_t literal_offset, const DexFile* target_dex_file, uint32_t target_method_idx) { - LinkerPatch patch(literal_offset, kLinkerPatchMethod, target_dex_file); + LinkerPatch patch(literal_offset, Type::kMethod, target_dex_file); patch.method_idx_ = target_method_idx; return patch; } @@ -180,7 +194,7 @@ class LinkerPatch { static LinkerPatch CodePatch(size_t literal_offset, const DexFile* target_dex_file, uint32_t target_method_idx) { - LinkerPatch patch(literal_offset, kLinkerPatchCall, target_dex_file); + LinkerPatch patch(literal_offset, Type::kCall, target_dex_file); patch.method_idx_ = target_method_idx; return patch; } @@ -188,7 +202,7 @@ class LinkerPatch { static LinkerPatch RelativeCodePatch(size_t literal_offset, const DexFile* target_dex_file, uint32_t target_method_idx) { - LinkerPatch patch(literal_offset, kLinkerPatchCallRelative, target_dex_file); + LinkerPatch patch(literal_offset, Type::kCallRelative, target_dex_file); patch.method_idx_ = target_method_idx; return patch; } @@ -196,17 +210,35 @@ class LinkerPatch { static LinkerPatch TypePatch(size_t literal_offset, const DexFile* target_dex_file, uint32_t target_type_idx) { - LinkerPatch patch(literal_offset, kLinkerPatchType, target_dex_file); + LinkerPatch patch(literal_offset, Type::kType, target_dex_file); patch.type_idx_ = target_type_idx; return patch; } + static LinkerPatch StringPatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t target_string_idx) { + LinkerPatch patch(literal_offset, Type::kString, target_dex_file); + patch.string_idx_ = target_string_idx; + return patch; + } + + static LinkerPatch RelativeStringPatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t pc_insn_offset, + uint32_t target_string_idx) { + LinkerPatch patch(literal_offset, Type::kStringRelative, target_dex_file); + patch.string_idx_ = target_string_idx; + patch.pc_insn_offset_ = pc_insn_offset; + return patch; + } + static LinkerPatch DexCacheArrayPatch(size_t literal_offset, const DexFile* target_dex_file, uint32_t pc_insn_offset, size_t element_offset) { DCHECK(IsUint<32>(element_offset)); - LinkerPatch patch(literal_offset, kLinkerPatchDexCacheArray, target_dex_file); + LinkerPatch patch(literal_offset, Type::kDexCacheArray, target_dex_file); patch.pc_insn_offset_ = pc_insn_offset; patch.element_offset_ = element_offset; return patch; @@ -219,47 +251,65 @@ class LinkerPatch { return literal_offset_; } - LinkerPatchType Type() const { + Type GetType() const { return patch_type_; } bool IsPcRelative() const { - return Type() == kLinkerPatchCallRelative || Type() == kLinkerPatchDexCacheArray; + switch (GetType()) { + case Type::kCallRelative: + case Type::kStringRelative: + case Type::kDexCacheArray: + return true; + default: + return false; + } } MethodReference TargetMethod() const { - DCHECK(patch_type_ == kLinkerPatchMethod || - patch_type_ == kLinkerPatchCall || patch_type_ == kLinkerPatchCallRelative); + DCHECK(patch_type_ == Type::kMethod || + patch_type_ == Type::kCall || + patch_type_ == Type::kCallRelative); return MethodReference(target_dex_file_, method_idx_); } const DexFile* TargetTypeDexFile() const { - DCHECK(patch_type_ == kLinkerPatchType); + DCHECK(patch_type_ == Type::kType); return target_dex_file_; } uint32_t TargetTypeIndex() const { - DCHECK(patch_type_ == kLinkerPatchType); + DCHECK(patch_type_ == Type::kType); return type_idx_; } + const DexFile* TargetStringDexFile() const { + DCHECK(patch_type_ == Type::kString || patch_type_ == Type::kStringRelative); + return target_dex_file_; + } + + uint32_t TargetStringIndex() const { + DCHECK(patch_type_ == Type::kString || patch_type_ == Type::kStringRelative); + return string_idx_; + } + const DexFile* TargetDexCacheDexFile() const { - DCHECK(patch_type_ == kLinkerPatchDexCacheArray); + DCHECK(patch_type_ == Type::kDexCacheArray); return target_dex_file_; } size_t TargetDexCacheElementOffset() const { - DCHECK(patch_type_ == kLinkerPatchDexCacheArray); + DCHECK(patch_type_ == Type::kDexCacheArray); return element_offset_; } uint32_t PcInsnOffset() const { - DCHECK(patch_type_ == kLinkerPatchDexCacheArray); + DCHECK(patch_type_ == Type::kStringRelative || patch_type_ == Type::kDexCacheArray); return pc_insn_offset_; } private: - LinkerPatch(size_t literal_offset, LinkerPatchType patch_type, const DexFile* target_dex_file) + LinkerPatch(size_t literal_offset, Type patch_type, const DexFile* target_dex_file) : target_dex_file_(target_dex_file), literal_offset_(literal_offset), patch_type_(patch_type) { @@ -272,14 +322,16 @@ class LinkerPatch { const DexFile* target_dex_file_; uint32_t literal_offset_ : 24; // Method code size up to 16MiB. - LinkerPatchType patch_type_ : 8; + Type patch_type_ : 8; union { uint32_t cmp1_; // Used for relational operators. uint32_t method_idx_; // Method index for Call/Method patches. uint32_t type_idx_; // Type index for Type patches. + uint32_t string_idx_; // String index for String patches. uint32_t element_offset_; // Element offset in the dex cache arrays. static_assert(sizeof(method_idx_) == sizeof(cmp1_), "needed by relational operators"); static_assert(sizeof(type_idx_) == sizeof(cmp1_), "needed by relational operators"); + static_assert(sizeof(string_idx_) == sizeof(cmp1_), "needed by relational operators"); static_assert(sizeof(element_offset_) == sizeof(cmp1_), "needed by relational operators"); }; union { @@ -295,6 +347,7 @@ class LinkerPatch { friend bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs); friend bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs); }; +std::ostream& operator<<(std::ostream& os, const LinkerPatch::Type& type); inline bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs) { return lhs.literal_offset_ == rhs.literal_offset_ && |