Split RelativePatcher::ReserveSpace() into two.
Instead of passing nullptr and MethodReference(nullptr, 0u)
to ReserveSpace() at the end, call a newly created function
ReserveSpaceEnd().
Change-Id: I38815fe9464b4e1a919878b6e8577614f1058d00
diff --git a/compiler/linker/arm/relative_patcher_arm_base.cc b/compiler/linker/arm/relative_patcher_arm_base.cc
index 2eae2a8..ceace82 100644
--- a/compiler/linker/arm/relative_patcher_arm_base.cc
+++ b/compiler/linker/arm/relative_patcher_arm_base.cc
@@ -29,6 +29,21 @@
return ReserveSpaceInternal(offset, compiled_method, method_ref, 0u);
}
+uint32_t ArmBaseRelativePatcher::ReserveSpaceEnd(uint32_t offset) {
+ // NOTE: The final thunk can be reserved from InitCodeMethodVisitor::EndClass() while it
+ // may be written early by WriteCodeMethodVisitor::VisitMethod() for a deduplicated chunk
+ // of code. To avoid any alignment discrepancies for the final chunk, we always align the
+ // offset after reserving of writing any chunk.
+ uint32_t aligned_offset = CompiledMethod::AlignCode(offset, instruction_set_);
+ bool needs_thunk = ReserveSpaceProcessPatches(aligned_offset, MethodReference(nullptr, 0u),
+ aligned_offset);
+ if (needs_thunk) {
+ thunk_locations_.push_back(aligned_offset);
+ offset = CompiledMethod::AlignCode(aligned_offset + thunk_code_.size(), instruction_set_);
+ }
+ return offset;
+}
+
uint32_t ArmBaseRelativePatcher::WriteThunks(OutputStream* out, uint32_t offset) {
if (current_thunk_to_write_ == thunk_locations_.size()) {
return offset;
@@ -69,20 +84,6 @@
const CompiledMethod* compiled_method,
MethodReference method_ref,
uint32_t max_extra_space) {
- // NOTE: The final thunk can be reserved from InitCodeMethodVisitor::EndClass() while it
- // may be written early by WriteCodeMethodVisitor::VisitMethod() for a deduplicated chunk
- // of code. To avoid any alignment discrepancies for the final chunk, we always align the
- // offset after reserving of writing any chunk.
- if (UNLIKELY(compiled_method == nullptr)) {
- uint32_t aligned_offset = CompiledMethod::AlignCode(offset, instruction_set_);
- DCHECK(method_ref.dex_file == nullptr && method_ref.dex_method_index == 0u);
- bool needs_thunk = ReserveSpaceProcessPatches(aligned_offset, method_ref, aligned_offset);
- if (needs_thunk) {
- thunk_locations_.push_back(aligned_offset);
- offset = CompiledMethod::AlignCode(aligned_offset + thunk_code_.size(), instruction_set_);
- }
- return offset;
- }
DCHECK(compiled_method->GetQuickCode() != nullptr);
uint32_t quick_code_size = compiled_method->GetQuickCode()->size();
uint32_t quick_code_offset = compiled_method->AlignCode(offset) + sizeof(OatQuickMethodHeader);
diff --git a/compiler/linker/arm/relative_patcher_arm_base.h b/compiler/linker/arm/relative_patcher_arm_base.h
index 78bc941..f80dd96 100644
--- a/compiler/linker/arm/relative_patcher_arm_base.h
+++ b/compiler/linker/arm/relative_patcher_arm_base.h
@@ -29,6 +29,7 @@
public:
uint32_t ReserveSpace(uint32_t offset, const CompiledMethod* compiled_method,
MethodReference method_ref) OVERRIDE;
+ uint32_t ReserveSpaceEnd(uint32_t offset) OVERRIDE;
uint32_t WriteThunks(OutputStream* out, uint32_t offset) OVERRIDE;
protected:
diff --git a/compiler/linker/arm64/relative_patcher_arm64.cc b/compiler/linker/arm64/relative_patcher_arm64.cc
index b61b3d8..1cbe481 100644
--- a/compiler/linker/arm64/relative_patcher_arm64.cc
+++ b/compiler/linker/arm64/relative_patcher_arm64.cc
@@ -58,12 +58,11 @@
// Count the number of ADRP insns as the upper bound on the number of thunks needed
// and use it to reserve space for other linker patches.
size_t num_adrp = 0u;
- if (LIKELY(compiled_method != nullptr)) {
- for (const LinkerPatch& patch : compiled_method->GetPatches()) {
- if (patch.Type() == kLinkerPatchDexCacheArray &&
- patch.LiteralOffset() == patch.PcInsnOffset()) { // ADRP patch
- ++num_adrp;
- }
+ DCHECK(compiled_method != nullptr);
+ for (const LinkerPatch& patch : compiled_method->GetPatches()) {
+ if (patch.Type() == kLinkerPatchDexCacheArray &&
+ patch.LiteralOffset() == patch.PcInsnOffset()) { // ADRP patch
+ ++num_adrp;
}
}
offset = ReserveSpaceInternal(offset, compiled_method, method_ref, kAdrpThunkSize * num_adrp);
@@ -90,6 +89,20 @@
return offset;
}
+uint32_t Arm64RelativePatcher::ReserveSpaceEnd(uint32_t offset) {
+ if (!fix_cortex_a53_843419_) {
+ DCHECK(adrp_thunk_locations_.empty());
+ } else {
+ // Add thunks for the last method if any.
+ if (reserved_adrp_thunks_ != adrp_thunk_locations_.size()) {
+ size_t num_adrp_thunks = adrp_thunk_locations_.size() - reserved_adrp_thunks_;
+ offset = CompiledMethod::AlignCode(offset, kArm64) + kAdrpThunkSize * num_adrp_thunks;
+ reserved_adrp_thunks_ = adrp_thunk_locations_.size();
+ }
+ }
+ return ArmBaseRelativePatcher::ReserveSpaceEnd(offset);
+}
+
uint32_t Arm64RelativePatcher::WriteThunks(OutputStream* out, uint32_t offset) {
if (fix_cortex_a53_843419_) {
if (!current_method_thunks_.empty()) {
diff --git a/compiler/linker/arm64/relative_patcher_arm64.h b/compiler/linker/arm64/relative_patcher_arm64.h
index b2a1da5..2d07e75 100644
--- a/compiler/linker/arm64/relative_patcher_arm64.h
+++ b/compiler/linker/arm64/relative_patcher_arm64.h
@@ -30,6 +30,7 @@
uint32_t ReserveSpace(uint32_t offset, const CompiledMethod* compiled_method,
MethodReference method_ref) OVERRIDE;
+ uint32_t ReserveSpaceEnd(uint32_t offset) OVERRIDE;
uint32_t WriteThunks(OutputStream* out, uint32_t offset) OVERRIDE;
void PatchCall(std::vector<uint8_t>* code, uint32_t literal_offset,
uint32_t patch_offset, uint32_t target_offset) OVERRIDE;
diff --git a/compiler/linker/relative_patcher.cc b/compiler/linker/relative_patcher.cc
index 71f38b4..8ee87aa 100644
--- a/compiler/linker/relative_patcher.cc
+++ b/compiler/linker/relative_patcher.cc
@@ -38,6 +38,10 @@
return offset; // No space reserved; no patches expected.
}
+ uint32_t ReserveSpaceEnd(uint32_t offset) OVERRIDE {
+ return offset; // No space reserved; no patches expected.
+ }
+
uint32_t WriteThunks(OutputStream* out ATTRIBUTE_UNUSED, uint32_t offset) OVERRIDE {
return offset; // No thunks added; no patches expected.
}
diff --git a/compiler/linker/relative_patcher.h b/compiler/linker/relative_patcher.h
index 7a78254..8a9f3f8 100644
--- a/compiler/linker/relative_patcher.h
+++ b/compiler/linker/relative_patcher.h
@@ -82,11 +82,13 @@
return size_misc_thunks_;
}
- // Reserve space for relative call thunks if needed, return adjusted offset. After all methods
- // of a class have been processed it's called one last time with compiled_method == nullptr.
+ // Reserve space for thunks if needed before a method, return adjusted offset.
virtual uint32_t ReserveSpace(uint32_t offset, const CompiledMethod* compiled_method,
MethodReference method_ref) = 0;
+ // Reserve space for thunks if needed after the last method, return adjusted offset.
+ virtual uint32_t ReserveSpaceEnd(uint32_t offset) = 0;
+
// Write relative call thunks if needed, return adjusted offset.
virtual uint32_t WriteThunks(OutputStream* out, uint32_t offset) = 0;
diff --git a/compiler/linker/relative_patcher_test.h b/compiler/linker/relative_patcher_test.h
index dede42e..08167b3 100644
--- a/compiler/linker/relative_patcher_test.h
+++ b/compiler/linker/relative_patcher_test.h
@@ -98,7 +98,7 @@
method_offset_map_.map.Put(compiled_method_refs_[idx], quick_code_offset);
++idx;
}
- offset = patcher_->ReserveSpace(offset, nullptr, MethodReference(nullptr, 0u));
+ offset = patcher_->ReserveSpaceEnd(offset);
uint32_t output_size = offset;
output_.reserve(output_size);
diff --git a/compiler/linker/x86/relative_patcher_x86_base.cc b/compiler/linker/x86/relative_patcher_x86_base.cc
index ea3472d..bc285a7 100644
--- a/compiler/linker/x86/relative_patcher_x86_base.cc
+++ b/compiler/linker/x86/relative_patcher_x86_base.cc
@@ -26,6 +26,10 @@
return offset; // No space reserved; no limit on relative call distance.
}
+uint32_t X86BaseRelativePatcher::ReserveSpaceEnd(uint32_t offset) {
+ return offset; // No space reserved; no limit on relative call distance.
+}
+
uint32_t X86BaseRelativePatcher::WriteThunks(OutputStream* out ATTRIBUTE_UNUSED, uint32_t offset) {
return offset; // No thunks added; no limit on relative call distance.
}
diff --git a/compiler/linker/x86/relative_patcher_x86_base.h b/compiler/linker/x86/relative_patcher_x86_base.h
index 1f38cf2..9200709 100644
--- a/compiler/linker/x86/relative_patcher_x86_base.h
+++ b/compiler/linker/x86/relative_patcher_x86_base.h
@@ -27,6 +27,7 @@
uint32_t ReserveSpace(uint32_t offset,
const CompiledMethod* compiled_method,
MethodReference method_ref) OVERRIDE;
+ uint32_t ReserveSpaceEnd(uint32_t offset) OVERRIDE;
uint32_t WriteThunks(OutputStream* out, uint32_t offset) OVERRIDE;
void PatchCall(std::vector<uint8_t>* code, uint32_t literal_offset,
uint32_t patch_offset, uint32_t target_offset) OVERRIDE;
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index e15890f..baa6210 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -357,8 +357,7 @@
bool EndClass() {
OatDexMethodVisitor::EndClass();
if (oat_class_index_ == writer_->oat_classes_.size()) {
- offset_ = writer_->relative_patcher_->ReserveSpace(offset_, nullptr,
- MethodReference(nullptr, 0u));
+ offset_ = writer_->relative_patcher_->ReserveSpaceEnd(offset_);
}
return true;
}