Use ArtMethod* .bss entries for HInvokeStaticOrDirect.
Test: m test-art-host-gtest
Test: testrunner.py --host
Test: testrunner.py --target
Test: Nexus 6P boots.
Test: Build aosp_mips64-userdebug.
Bug: 30627598
Change-Id: I0e54fdd2e91e983d475b7a04d40815ba89ae3d4f
diff --git a/compiler/Android.bp b/compiler/Android.bp
index 307a42c..a1269dc 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -110,7 +110,6 @@
"optimizing/code_generator_vector_arm.cc",
"optimizing/code_generator_arm_vixl.cc",
"optimizing/code_generator_vector_arm_vixl.cc",
- "optimizing/dex_cache_array_fixups_arm.cc",
"optimizing/instruction_simplifier_arm.cc",
"optimizing/instruction_simplifier_shared.cc",
"optimizing/intrinsics_arm.cc",
@@ -145,7 +144,6 @@
"linker/mips/relative_patcher_mips.cc",
"optimizing/code_generator_mips.cc",
"optimizing/code_generator_vector_mips.cc",
- "optimizing/dex_cache_array_fixups_mips.cc",
"optimizing/intrinsics_mips.cc",
"optimizing/pc_relative_fixups_mips.cc",
"utils/mips/assembler_mips.cc",
@@ -342,6 +340,7 @@
"image_test.cc",
"image_write_read_test.cc",
"jni/jni_compiler_test.cc",
+ "linker/method_bss_mapping_encoder_test.cc",
"linker/multi_oat_relative_patcher_test.cc",
"linker/output_stream_test.cc",
"oat_test.cc",
diff --git a/compiler/compiled_method.h b/compiler/compiled_method.h
index 0ca23a5..761e9e1 100644
--- a/compiler/compiled_method.h
+++ b/compiler/compiled_method.h
@@ -120,13 +120,13 @@
// patch_type_ as an uintN_t and do explicit static_cast<>s.
enum class Type : uint8_t {
kMethodRelative, // NOTE: Actual patching is instruction_set-dependent.
+ kMethodBssEntry, // NOTE: Actual patching is instruction_set-dependent.
kCall,
kCallRelative, // NOTE: Actual patching is instruction_set-dependent.
kTypeRelative, // NOTE: Actual patching is instruction_set-dependent.
kTypeBssEntry, // NOTE: Actual patching is instruction_set-dependent.
kStringRelative, // NOTE: Actual patching is instruction_set-dependent.
kStringBssEntry, // NOTE: Actual patching is instruction_set-dependent.
- kDexCacheArray, // NOTE: Actual patching is instruction_set-dependent.
kBakerReadBarrierBranch, // NOTE: Actual patching is instruction_set-dependent.
};
@@ -140,6 +140,16 @@
return patch;
}
+ static LinkerPatch MethodBssEntryPatch(size_t literal_offset,
+ const DexFile* target_dex_file,
+ uint32_t pc_insn_offset,
+ uint32_t target_method_idx) {
+ LinkerPatch patch(literal_offset, Type::kMethodBssEntry, target_dex_file);
+ patch.method_idx_ = target_method_idx;
+ patch.pc_insn_offset_ = pc_insn_offset;
+ return patch;
+ }
+
static LinkerPatch CodePatch(size_t literal_offset,
const DexFile* target_dex_file,
uint32_t target_method_idx) {
@@ -196,16 +206,6 @@
return patch;
}
- static LinkerPatch DexCacheArrayPatch(size_t literal_offset,
- const DexFile* target_dex_file,
- uint32_t pc_insn_offset,
- uint32_t element_offset) {
- LinkerPatch patch(literal_offset, Type::kDexCacheArray, target_dex_file);
- patch.pc_insn_offset_ = pc_insn_offset;
- patch.element_offset_ = element_offset;
- return patch;
- }
-
static LinkerPatch BakerReadBarrierBranchPatch(size_t literal_offset,
uint32_t custom_value1 = 0u,
uint32_t custom_value2 = 0u) {
@@ -229,12 +229,12 @@
bool IsPcRelative() const {
switch (GetType()) {
case Type::kMethodRelative:
+ case Type::kMethodBssEntry:
case Type::kCallRelative:
case Type::kTypeRelative:
case Type::kTypeBssEntry:
case Type::kStringRelative:
case Type::kStringBssEntry:
- case Type::kDexCacheArray:
case Type::kBakerReadBarrierBranch:
return true;
default:
@@ -244,6 +244,7 @@
MethodReference TargetMethod() const {
DCHECK(patch_type_ == Type::kMethodRelative ||
+ patch_type_ == Type::kMethodBssEntry ||
patch_type_ == Type::kCall ||
patch_type_ == Type::kCallRelative);
return MethodReference(target_dex_file_, method_idx_);
@@ -273,23 +274,13 @@
return dex::StringIndex(string_idx_);
}
- const DexFile* TargetDexCacheDexFile() const {
- DCHECK(patch_type_ == Type::kDexCacheArray);
- return target_dex_file_;
- }
-
- size_t TargetDexCacheElementOffset() const {
- DCHECK(patch_type_ == Type::kDexCacheArray);
- return element_offset_;
- }
-
uint32_t PcInsnOffset() const {
DCHECK(patch_type_ == Type::kMethodRelative ||
+ patch_type_ == Type::kMethodBssEntry ||
patch_type_ == Type::kTypeRelative ||
patch_type_ == Type::kTypeBssEntry ||
patch_type_ == Type::kStringRelative ||
- patch_type_ == Type::kStringBssEntry ||
- patch_type_ == Type::kDexCacheArray);
+ patch_type_ == Type::kStringBssEntry);
return pc_insn_offset_;
}
@@ -324,12 +315,10 @@
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.
uint32_t baker_custom_value1_;
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");
static_assert(sizeof(baker_custom_value1_) == sizeof(cmp1_), "needed by relational operators");
};
union {
diff --git a/compiler/compiled_method_test.cc b/compiler/compiled_method_test.cc
index 72b2282..f4a72cf 100644
--- a/compiler/compiled_method_test.cc
+++ b/compiler/compiled_method_test.cc
@@ -58,6 +58,14 @@
LinkerPatch::RelativeMethodPatch(16u, dex_file2, 3001u, 1000u),
LinkerPatch::RelativeMethodPatch(16u, dex_file2, 3000u, 1001u),
LinkerPatch::RelativeMethodPatch(16u, dex_file2, 3001u, 1001u),
+ LinkerPatch::MethodBssEntryPatch(16u, dex_file1, 3000u, 1000u),
+ LinkerPatch::MethodBssEntryPatch(16u, dex_file1, 3001u, 1000u),
+ LinkerPatch::MethodBssEntryPatch(16u, dex_file1, 3000u, 1001u),
+ LinkerPatch::MethodBssEntryPatch(16u, dex_file1, 3001u, 1001u),
+ LinkerPatch::MethodBssEntryPatch(16u, dex_file2, 3000u, 1000u),
+ LinkerPatch::MethodBssEntryPatch(16u, dex_file2, 3001u, 1000u),
+ LinkerPatch::MethodBssEntryPatch(16u, dex_file2, 3000u, 1001u),
+ LinkerPatch::MethodBssEntryPatch(16u, dex_file2, 3001u, 1001u),
LinkerPatch::CodePatch(16u, dex_file1, 1000u),
LinkerPatch::CodePatch(16u, dex_file1, 1001u),
LinkerPatch::CodePatch(16u, dex_file2, 1000u),
@@ -98,14 +106,6 @@
LinkerPatch::StringBssEntryPatch(16u, dex_file2, 3001u, 1000u),
LinkerPatch::StringBssEntryPatch(16u, dex_file2, 3000u, 1001u),
LinkerPatch::StringBssEntryPatch(16u, dex_file2, 3001u, 1001u),
- LinkerPatch::DexCacheArrayPatch(16u, dex_file1, 3000u, 2000u),
- LinkerPatch::DexCacheArrayPatch(16u, dex_file1, 3001u, 2000u),
- LinkerPatch::DexCacheArrayPatch(16u, dex_file1, 3000u, 2001u),
- LinkerPatch::DexCacheArrayPatch(16u, dex_file1, 3001u, 2001u),
- LinkerPatch::DexCacheArrayPatch(16u, dex_file2, 3000u, 2000u),
- LinkerPatch::DexCacheArrayPatch(16u, dex_file2, 3001u, 2000u),
- LinkerPatch::DexCacheArrayPatch(16u, dex_file2, 3000u, 2001u),
- LinkerPatch::DexCacheArrayPatch(16u, dex_file2, 3001u, 2001u),
LinkerPatch::BakerReadBarrierBranchPatch(16u, 0u, 0u),
LinkerPatch::BakerReadBarrierBranchPatch(16u, 0u, 1u),
LinkerPatch::BakerReadBarrierBranchPatch(16u, 1u, 0u),
@@ -119,6 +119,14 @@
LinkerPatch::RelativeMethodPatch(32u, dex_file2, 3001u, 1000u),
LinkerPatch::RelativeMethodPatch(32u, dex_file2, 3000u, 1001u),
LinkerPatch::RelativeMethodPatch(32u, dex_file2, 3001u, 1001u),
+ LinkerPatch::MethodBssEntryPatch(32u, dex_file1, 3000u, 1000u),
+ LinkerPatch::MethodBssEntryPatch(32u, dex_file1, 3001u, 1000u),
+ LinkerPatch::MethodBssEntryPatch(32u, dex_file1, 3000u, 1001u),
+ LinkerPatch::MethodBssEntryPatch(32u, dex_file1, 3001u, 1001u),
+ LinkerPatch::MethodBssEntryPatch(32u, dex_file2, 3000u, 1000u),
+ LinkerPatch::MethodBssEntryPatch(32u, dex_file2, 3001u, 1000u),
+ LinkerPatch::MethodBssEntryPatch(32u, dex_file2, 3000u, 1001u),
+ LinkerPatch::MethodBssEntryPatch(32u, dex_file2, 3001u, 1001u),
LinkerPatch::CodePatch(32u, dex_file1, 1000u),
LinkerPatch::CodePatch(32u, dex_file1, 1001u),
LinkerPatch::CodePatch(32u, dex_file2, 1000u),
@@ -159,14 +167,6 @@
LinkerPatch::StringBssEntryPatch(32u, dex_file2, 3001u, 1000u),
LinkerPatch::StringBssEntryPatch(32u, dex_file2, 3000u, 1001u),
LinkerPatch::StringBssEntryPatch(32u, dex_file2, 3001u, 1001u),
- LinkerPatch::DexCacheArrayPatch(32u, dex_file1, 3000u, 2000u),
- LinkerPatch::DexCacheArrayPatch(32u, dex_file1, 3001u, 2000u),
- LinkerPatch::DexCacheArrayPatch(32u, dex_file1, 3000u, 2001u),
- LinkerPatch::DexCacheArrayPatch(32u, dex_file1, 3001u, 2001u),
- LinkerPatch::DexCacheArrayPatch(32u, dex_file2, 3000u, 2000u),
- LinkerPatch::DexCacheArrayPatch(32u, dex_file2, 3001u, 2000u),
- LinkerPatch::DexCacheArrayPatch(32u, dex_file2, 3000u, 2001u),
- LinkerPatch::DexCacheArrayPatch(32u, dex_file2, 3001u, 2001u),
LinkerPatch::BakerReadBarrierBranchPatch(32u, 0u, 0u),
LinkerPatch::BakerReadBarrierBranchPatch(32u, 0u, 1u),
LinkerPatch::BakerReadBarrierBranchPatch(32u, 1u, 0u),
diff --git a/compiler/elf_builder.h b/compiler/elf_builder.h
index 7c02384..2ef9fa1 100644
--- a/compiler/elf_builder.h
+++ b/compiler/elf_builder.h
@@ -670,6 +670,7 @@
Elf_Word rodata_size,
Elf_Word text_size,
Elf_Word bss_size,
+ Elf_Word bss_methods_offset,
Elf_Word bss_roots_offset) {
std::string soname(elf_file_path);
size_t directory_separator_pos = soname.rfind('/');
@@ -715,9 +716,18 @@
Elf_Word bss_index = rodata_index + 1u + (text_size != 0 ? 1u : 0u);
Elf_Word oatbss = dynstr_.Add("oatbss");
dynsym_.Add(oatbss, bss_index, bss_address, bss_roots_offset, STB_GLOBAL, STT_OBJECT);
+ DCHECK_LE(bss_methods_offset, bss_roots_offset);
+ DCHECK_LE(bss_roots_offset, bss_size);
+ // Add a symbol marking the start of the methods part of the .bss, if not empty.
+ if (bss_methods_offset != bss_roots_offset) {
+ Elf_Word bss_methods_address = bss_address + bss_methods_offset;
+ Elf_Word bss_methods_size = bss_roots_offset - bss_methods_offset;
+ Elf_Word oatbssroots = dynstr_.Add("oatbssmethods");
+ dynsym_.Add(
+ oatbssroots, bss_index, bss_methods_address, bss_methods_size, STB_GLOBAL, STT_OBJECT);
+ }
// Add a symbol marking the start of the GC roots part of the .bss, if not empty.
if (bss_roots_offset != bss_size) {
- DCHECK_LT(bss_roots_offset, bss_size);
Elf_Word bss_roots_address = bss_address + bss_roots_offset;
Elf_Word bss_roots_size = bss_size - bss_roots_offset;
Elf_Word oatbssroots = dynstr_.Add("oatbssroots");
diff --git a/compiler/elf_writer.h b/compiler/elf_writer.h
index 7baae52..a8a5bc3 100644
--- a/compiler/elf_writer.h
+++ b/compiler/elf_writer.h
@@ -55,6 +55,7 @@
virtual void PrepareDynamicSection(size_t rodata_size,
size_t text_size,
size_t bss_size,
+ size_t bss_methods_offset,
size_t bss_roots_offset) = 0;
virtual void PrepareDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) = 0;
virtual OutputStream* StartRoData() = 0;
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index 738f5a2..38bd9be 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -97,6 +97,7 @@
void PrepareDynamicSection(size_t rodata_size,
size_t text_size,
size_t bss_size,
+ size_t bss_methods_offset,
size_t bss_roots_offset) OVERRIDE;
void PrepareDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) OVERRIDE;
OutputStream* StartRoData() OVERRIDE;
@@ -178,6 +179,7 @@
void ElfWriterQuick<ElfTypes>::PrepareDynamicSection(size_t rodata_size,
size_t text_size,
size_t bss_size,
+ size_t bss_methods_offset,
size_t bss_roots_offset) {
DCHECK_EQ(rodata_size_, 0u);
rodata_size_ = rodata_size;
@@ -189,6 +191,7 @@
rodata_size_,
text_size_,
bss_size_,
+ bss_methods_offset,
bss_roots_offset);
}
diff --git a/compiler/image_test.h b/compiler/image_test.h
index 2f15ff4..394b7f1 100644
--- a/compiler/image_test.h
+++ b/compiler/image_test.h
@@ -311,6 +311,7 @@
elf_writer->PrepareDynamicSection(rodata_size,
text_size,
oat_writer->GetBssSize(),
+ oat_writer->GetBssMethodsOffset(),
oat_writer->GetBssRootsOffset());
writer->UpdateOatFileLayout(i,
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
index 2283b39..3db4fab 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -106,19 +106,6 @@
ArtMethod* GetImageMethodAddress(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
- template <typename PtrType>
- PtrType GetDexCacheArrayElementImageAddress(const DexFile* dex_file, uint32_t offset)
- const REQUIRES_SHARED(Locks::mutator_lock_) {
- auto oat_it = dex_file_oat_index_map_.find(dex_file);
- DCHECK(oat_it != dex_file_oat_index_map_.end());
- const ImageInfo& image_info = GetImageInfo(oat_it->second);
- auto it = image_info.dex_cache_array_starts_.find(dex_file);
- DCHECK(it != image_info.dex_cache_array_starts_.end());
- return reinterpret_cast<PtrType>(
- image_info.image_begin_ + image_info.bin_slot_offsets_[kBinDexCacheArray] +
- it->second + offset);
- }
-
size_t GetOatFileOffset(size_t oat_index) const {
return GetImageInfo(oat_index).oat_offset_;
}
diff --git a/compiler/linker/arm64/relative_patcher_arm64.cc b/compiler/linker/arm64/relative_patcher_arm64.cc
index 117684a..bc21607 100644
--- a/compiler/linker/arm64/relative_patcher_arm64.cc
+++ b/compiler/linker/arm64/relative_patcher_arm64.cc
@@ -59,11 +59,11 @@
case LinkerPatch::Type::kBakerReadBarrierBranch:
return false;
case LinkerPatch::Type::kMethodRelative:
+ case LinkerPatch::Type::kMethodBssEntry:
case LinkerPatch::Type::kTypeRelative:
case LinkerPatch::Type::kTypeBssEntry:
case LinkerPatch::Type::kStringRelative:
case LinkerPatch::Type::kStringBssEntry:
- case LinkerPatch::Type::kDexCacheArray:
return patch.LiteralOffset() == patch.PcInsnOffset();
}
}
@@ -251,20 +251,20 @@
// ADD immediate, 64-bit with imm12 == 0 (unset).
if (!kEmitCompilerReadBarrier) {
DCHECK(patch.GetType() == LinkerPatch::Type::kMethodRelative ||
- patch.GetType() == LinkerPatch::Type::kStringRelative ||
- patch.GetType() == LinkerPatch::Type::kTypeRelative) << patch.GetType();
+ patch.GetType() == LinkerPatch::Type::kTypeRelative ||
+ patch.GetType() == LinkerPatch::Type::kStringRelative) << patch.GetType();
} else {
// With the read barrier (non-Baker) enabled, it could be kStringBssEntry or kTypeBssEntry.
DCHECK(patch.GetType() == LinkerPatch::Type::kMethodRelative ||
- patch.GetType() == LinkerPatch::Type::kStringRelative ||
patch.GetType() == LinkerPatch::Type::kTypeRelative ||
- patch.GetType() == LinkerPatch::Type::kStringBssEntry ||
- patch.GetType() == LinkerPatch::Type::kTypeBssEntry) << patch.GetType();
+ patch.GetType() == LinkerPatch::Type::kStringRelative ||
+ patch.GetType() == LinkerPatch::Type::kTypeBssEntry ||
+ patch.GetType() == LinkerPatch::Type::kStringBssEntry) << patch.GetType();
}
shift = 0u; // No shift for ADD.
} else {
// LDR/STR 32-bit or 64-bit with imm12 == 0 (unset).
- DCHECK(patch.GetType() == LinkerPatch::Type::kDexCacheArray ||
+ DCHECK(patch.GetType() == LinkerPatch::Type::kMethodBssEntry ||
patch.GetType() == LinkerPatch::Type::kTypeBssEntry ||
patch.GetType() == LinkerPatch::Type::kStringBssEntry) << patch.GetType();
DCHECK_EQ(insn & 0xbfbffc00, 0xb9000000) << std::hex << insn;
diff --git a/compiler/linker/method_bss_mapping_encoder.h b/compiler/linker/method_bss_mapping_encoder.h
new file mode 100644
index 0000000..b2922ec
--- /dev/null
+++ b/compiler/linker/method_bss_mapping_encoder.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_LINKER_METHOD_BSS_MAPPING_ENCODER_H_
+#define ART_COMPILER_LINKER_METHOD_BSS_MAPPING_ENCODER_H_
+
+#include "base/enums.h"
+#include "base/logging.h"
+#include "dex_file.h"
+#include "method_bss_mapping.h"
+
+namespace art {
+namespace linker {
+
+// Helper class for encoding compressed MethodBssMapping.
+class MethodBssMappingEncoder {
+ public:
+ explicit MethodBssMappingEncoder(PointerSize pointer_size)
+ : pointer_size_(static_cast<size_t>(pointer_size)) {
+ entry_.method_index = DexFile::kDexNoIndex16;
+ entry_.index_mask = 0u;
+ entry_.bss_offset = static_cast<uint32_t>(-1);
+ }
+
+ // Try to merge the next method_index -> bss_offset mapping into the current entry.
+ // Return true on success, false on failure.
+ bool TryMerge(uint32_t method_index, uint32_t bss_offset) {
+ DCHECK_NE(method_index, entry_.method_index);
+ if (entry_.bss_offset + pointer_size_ != bss_offset) {
+ return false;
+ }
+ uint32_t diff = method_index - entry_.method_index;
+ if (diff > 16u) {
+ return false;
+ }
+ if ((entry_.index_mask & ~(static_cast<uint32_t>(-1) << diff)) != 0u) {
+ return false;
+ }
+ entry_.method_index = method_index;
+ // Insert the bit indicating the method index we've just overwritten
+ // and shift bits indicating method indexes before that.
+ entry_.index_mask = dchecked_integral_cast<uint16_t>(
+ (static_cast<uint32_t>(entry_.index_mask) | 0x10000u) >> diff);
+ entry_.bss_offset = bss_offset;
+ return true;
+ }
+
+ void Reset(uint32_t method_index, uint32_t bss_offset) {
+ entry_.method_index = method_index;
+ entry_.index_mask = 0u;
+ entry_.bss_offset = bss_offset;
+ }
+
+ MethodBssMappingEntry GetEntry() {
+ return entry_;
+ }
+
+ private:
+ size_t pointer_size_;
+ MethodBssMappingEntry entry_;
+};
+
+} // namespace linker
+} // namespace art
+
+#endif // ART_COMPILER_LINKER_METHOD_BSS_MAPPING_ENCODER_H_
diff --git a/compiler/linker/method_bss_mapping_encoder_test.cc b/compiler/linker/method_bss_mapping_encoder_test.cc
new file mode 100644
index 0000000..1240389
--- /dev/null
+++ b/compiler/linker/method_bss_mapping_encoder_test.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "method_bss_mapping_encoder.h"
+
+#include "gtest/gtest.h"
+
+namespace art {
+namespace linker {
+
+TEST(MethodBssMappingEncoder, TryMerge) {
+ for (PointerSize pointer_size : {PointerSize::k32, PointerSize::k64}) {
+ size_t raw_pointer_size = static_cast<size_t>(pointer_size);
+ MethodBssMappingEncoder encoder(pointer_size);
+ encoder.Reset(1u, 0u);
+ ASSERT_FALSE(encoder.TryMerge(5u, raw_pointer_size + 1)); // Wrong bss_offset difference.
+ ASSERT_FALSE(encoder.TryMerge(18u, raw_pointer_size)); // Method index out of range.
+ ASSERT_TRUE(encoder.TryMerge(5u, raw_pointer_size));
+ ASSERT_TRUE(encoder.GetEntry().CoversIndex(1u));
+ ASSERT_TRUE(encoder.GetEntry().CoversIndex(5u));
+ ASSERT_FALSE(encoder.GetEntry().CoversIndex(17u));
+ ASSERT_FALSE(encoder.TryMerge(17u, 2 * raw_pointer_size + 1)); // Wrong bss_offset difference.
+ ASSERT_FALSE(encoder.TryMerge(18u, 2 * raw_pointer_size)); // Method index out of range.
+ ASSERT_TRUE(encoder.TryMerge(17u, 2 * raw_pointer_size));
+ ASSERT_TRUE(encoder.GetEntry().CoversIndex(1u));
+ ASSERT_TRUE(encoder.GetEntry().CoversIndex(5u));
+ ASSERT_TRUE(encoder.GetEntry().CoversIndex(17u));
+ ASSERT_EQ(0u, encoder.GetEntry().GetBssOffset(1u, raw_pointer_size));
+ ASSERT_EQ(raw_pointer_size, encoder.GetEntry().GetBssOffset(5u, raw_pointer_size));
+ ASSERT_EQ(2 * raw_pointer_size, encoder.GetEntry().GetBssOffset(17u, raw_pointer_size));
+ ASSERT_EQ(0x0011u, encoder.GetEntry().index_mask);
+ ASSERT_FALSE(encoder.TryMerge(18u, 2 * raw_pointer_size)); // Method index out of range.
+ }
+}
+
+} // namespace linker
+} // namespace art
diff --git a/compiler/linker/mips/relative_patcher_mips.cc b/compiler/linker/mips/relative_patcher_mips.cc
index 8da530f..d99d237 100644
--- a/compiler/linker/mips/relative_patcher_mips.cc
+++ b/compiler/linker/mips/relative_patcher_mips.cc
@@ -50,7 +50,6 @@
uint32_t anchor_literal_offset = patch.PcInsnOffset();
uint32_t literal_offset = patch.LiteralOffset();
uint32_t literal_low_offset;
- bool dex_cache_array = (patch.GetType() == LinkerPatch::Type::kDexCacheArray);
// Perform basic sanity checks and initialize `literal_low_offset` to point
// to the instruction containing the 16 least significant bits of the
@@ -72,16 +71,8 @@
DCHECK_GE(code->size(), 16u);
DCHECK_LE(literal_offset, code->size() - 12u);
DCHECK_GE(literal_offset, 4u);
- // The NAL instruction may not precede immediately as the PC+0 value may
- // come from HMipsComputeBaseMethodAddress.
- if (dex_cache_array) {
- DCHECK_EQ(literal_offset + 4u, anchor_literal_offset);
- // NAL
- DCHECK_EQ((*code)[literal_offset - 4], 0x00);
- DCHECK_EQ((*code)[literal_offset - 3], 0x00);
- DCHECK_EQ((*code)[literal_offset - 2], 0x10);
- DCHECK_EQ((*code)[literal_offset - 1], 0x04);
- }
+ // The NAL instruction does not precede immediately as the PC+0
+ // comes from HMipsComputeBaseMethodAddress.
// LUI reg, offset_high
DCHECK_EQ((*code)[literal_offset + 0], 0x34);
DCHECK_EQ((*code)[literal_offset + 1], 0x12);
@@ -90,10 +81,6 @@
// ADDU reg, reg, reg2
DCHECK_EQ((*code)[literal_offset + 4], 0x21);
DCHECK_EQ(((*code)[literal_offset + 5] & 0x07), 0x00);
- if (dex_cache_array) {
- // reg2 is either RA or from HMipsComputeBaseMethodAddress.
- DCHECK_EQ(((*code)[literal_offset + 6] & 0x1F), 0x1F);
- }
DCHECK_EQ(((*code)[literal_offset + 7] & 0xFC), 0x00);
// instr reg(s), offset_low
DCHECK_EQ((*code)[literal_offset + 8], 0x78);
@@ -104,9 +91,6 @@
// Apply patch.
uint32_t anchor_offset = patch_offset - literal_offset + anchor_literal_offset;
uint32_t diff = target_offset - anchor_offset;
- if (dex_cache_array && !is_r6) {
- diff += kDexCacheArrayLwOffset;
- }
diff += (diff & 0x8000) << 1; // Account for sign extension in "instr reg(s), offset_low".
// LUI reg, offset_high / AUIPC reg, offset_high
diff --git a/compiler/linker/mips/relative_patcher_mips.h b/compiler/linker/mips/relative_patcher_mips.h
index 852a345..0b74bd3 100644
--- a/compiler/linker/mips/relative_patcher_mips.h
+++ b/compiler/linker/mips/relative_patcher_mips.h
@@ -46,9 +46,6 @@
uint32_t patch_offset) OVERRIDE;
private:
- // We'll maximize the range of a single load instruction for dex cache array accesses
- // by aligning offset -32768 with the offset of the first used element.
- static constexpr uint32_t kDexCacheArrayLwOffset = 0x8000;
bool is_r6;
DISALLOW_COPY_AND_ASSIGN(MipsRelativePatcher);
diff --git a/compiler/linker/mips/relative_patcher_mips_test.cc b/compiler/linker/mips/relative_patcher_mips_test.cc
index 961b312..49af7c6 100644
--- a/compiler/linker/mips/relative_patcher_mips_test.cc
+++ b/compiler/linker/mips/relative_patcher_mips_test.cc
@@ -61,7 +61,6 @@
ASSERT_TRUE(result.first);
uint32_t diff = target_offset - (result.second + kAnchorOffset);
- CHECK_NE(patches[0].GetType(), LinkerPatch::Type::kDexCacheArray);
diff += (diff & 0x8000) << 1; // Account for sign extension in addiu.
const uint8_t expected_code[] = {
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index 1578c0c..fdb21e4 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -220,6 +220,7 @@
elf_writer->PrepareDynamicSection(rodata_size,
text_size,
oat_writer.GetBssSize(),
+ oat_writer.GetBssMethodsOffset(),
oat_writer.GetBssRootsOffset());
if (kIsVdexEnabled) {
@@ -483,7 +484,7 @@
TEST_F(OatTest, OatHeaderSizeCheck) {
// If this test is failing and you have to update these constants,
// it is time to update OatHeader::kOatVersion
- EXPECT_EQ(72U, sizeof(OatHeader));
+ EXPECT_EQ(76U, sizeof(OatHeader));
EXPECT_EQ(4U, sizeof(OatMethodOffsets));
EXPECT_EQ(24U, sizeof(OatQuickMethodHeader));
EXPECT_EQ(161 * static_cast<size_t>(GetInstructionSetPointerSize(kRuntimeISA)),
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index fed2d34..581b1ee 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -22,7 +22,7 @@
#include "arch/arm64/instruction_set_features_arm64.h"
#include "art_method-inl.h"
#include "base/allocator.h"
-#include "base/bit_vector.h"
+#include "base/bit_vector-inl.h"
#include "base/enums.h"
#include "base/file_magic.h"
#include "base/stl_util.h"
@@ -41,6 +41,7 @@
#include "image_writer.h"
#include "linker/buffered_output_stream.h"
#include "linker/file_output_stream.h"
+#include "linker/method_bss_mapping_encoder.h"
#include "linker/multi_oat_relative_patcher.h"
#include "linker/output_stream.h"
#include "mirror/array.h"
@@ -230,12 +231,14 @@
return dex_file_location_data_;
}
- void ReserveClassOffsets(OatWriter* oat_writer);
-
size_t SizeOf() const;
bool Write(OatWriter* oat_writer, OutputStream* out) const;
bool WriteClassOffsets(OatWriter* oat_writer, OutputStream* out);
+ size_t GetClassOffsetsRawSize() const {
+ return class_offsets_.size() * sizeof(class_offsets_[0]);
+ }
+
// The source of the dex file.
DexFileSource source_;
@@ -256,15 +259,12 @@
uint32_t dex_file_offset_;
uint32_t class_offsets_offset_;
uint32_t lookup_table_offset_;
+ uint32_t method_bss_mapping_offset_;
// Data to write to a separate section.
dchecked_vector<uint32_t> class_offsets_;
private:
- size_t GetClassOffsetsRawSize() const {
- return class_offsets_.size() * sizeof(class_offsets_[0]);
- }
-
DISALLOW_COPY_AND_ASSIGN(OatDexFile);
};
@@ -294,7 +294,10 @@
oat_size_(0u),
bss_start_(0u),
bss_size_(0u),
+ bss_methods_offset_(0u),
bss_roots_offset_(0u),
+ bss_method_entry_references_(),
+ bss_method_entries_(),
bss_type_entries_(),
bss_string_entries_(),
oat_data_offset_(0u),
@@ -331,6 +334,7 @@
size_oat_dex_file_offset_(0),
size_oat_dex_file_class_offsets_offset_(0),
size_oat_dex_file_lookup_table_offset_(0),
+ size_oat_dex_file_method_bss_mapping_offset_(0),
size_oat_lookup_table_alignment_(0),
size_oat_lookup_table_(0),
size_oat_class_offsets_alignment_(0),
@@ -339,6 +343,7 @@
size_oat_class_status_(0),
size_oat_class_method_bitmaps_(0),
size_oat_class_method_offsets_(0),
+ size_method_bss_mappings_(0u),
relative_patcher_(nullptr),
absolute_patch_locations_(),
profile_compilation_info_(info) {
@@ -502,11 +507,10 @@
// Reserve space for Vdex header and checksums.
vdex_size_ = sizeof(VdexFile::Header) + oat_dex_files_.size() * sizeof(VdexFile::VdexChecksum);
}
- size_t oat_data_offset = InitOatHeader(instruction_set,
- instruction_set_features,
- dchecked_integral_cast<uint32_t>(oat_dex_files_.size()),
- key_value_store);
- oat_size_ = InitOatDexFiles(oat_data_offset);
+ oat_size_ = InitOatHeader(instruction_set,
+ instruction_set_features,
+ dchecked_integral_cast<uint32_t>(oat_dex_files_.size()),
+ key_value_store);
ChecksumUpdatingOutputStream checksum_updating_rodata(oat_rodata, oat_header_.get());
@@ -539,16 +543,6 @@
return false;
}
- // Reserve space for class offsets in OAT and update class_offsets_offset_.
- for (OatDexFile& oat_dex_file : oat_dex_files_) {
- oat_dex_file.ReserveClassOffsets(this);
- }
-
- // Write OatDexFiles into OAT. Needs to be done last, once offsets are collected.
- if (!WriteOatDexFiles(&checksum_updating_rodata)) {
- return false;
- }
-
*opened_dex_files_map = std::move(dex_files_map);
*opened_dex_files = std::move(dex_files);
write_state_ = WriteState::kPrepareLayout;
@@ -567,16 +561,34 @@
InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
CHECK_EQ(instruction_set, oat_header_->GetInstructionSet());
+ {
+ TimingLogger::ScopedTiming split("InitBssLayout", timings_);
+ InitBssLayout(instruction_set);
+ }
+
uint32_t offset = oat_size_;
{
+ TimingLogger::ScopedTiming split("InitClassOffsets", timings_);
+ offset = InitClassOffsets(offset);
+ }
+ {
TimingLogger::ScopedTiming split("InitOatClasses", timings_);
offset = InitOatClasses(offset);
}
{
+ TimingLogger::ScopedTiming split("InitMethodBssMappings", timings_);
+ offset = InitMethodBssMappings(offset);
+ }
+ {
TimingLogger::ScopedTiming split("InitOatMaps", timings_);
offset = InitOatMaps(offset);
}
{
+ TimingLogger::ScopedTiming split("InitOatDexFiles", timings_);
+ oat_header_->SetOatDexFilesOffset(offset);
+ offset = InitOatDexFiles(offset);
+ }
+ {
TimingLogger::ScopedTiming split("InitOatCode", timings_);
offset = InitOatCode(offset);
}
@@ -585,11 +597,7 @@
offset = InitOatCodeDexFiles(offset);
}
oat_size_ = offset;
-
- {
- TimingLogger::ScopedTiming split("InitBssLayout", timings_);
- InitBssLayout(instruction_set);
- }
+ bss_start_ = (bss_size_ != 0u) ? RoundUp(oat_size_, kPageSize) : 0u;
CHECK_EQ(dex_files_->size(), oat_dex_files_.size());
if (compiling_boot_image_) {
@@ -606,11 +614,10 @@
class OatWriter::DexMethodVisitor {
public:
DexMethodVisitor(OatWriter* writer, size_t offset)
- : writer_(writer),
- offset_(offset),
- dex_file_(nullptr),
- class_def_index_(DexFile::kDexNoIndex) {
- }
+ : writer_(writer),
+ offset_(offset),
+ dex_file_(nullptr),
+ class_def_index_(DexFile::kDexNoIndex) {}
virtual bool StartClass(const DexFile* dex_file, size_t class_def_index) {
DCHECK(dex_file_ == nullptr);
@@ -650,19 +657,18 @@
class OatWriter::OatDexMethodVisitor : public DexMethodVisitor {
public:
OatDexMethodVisitor(OatWriter* writer, size_t offset)
- : DexMethodVisitor(writer, offset),
- oat_class_index_(0u),
- method_offsets_index_(0u) {
- }
+ : DexMethodVisitor(writer, offset),
+ oat_class_index_(0u),
+ method_offsets_index_(0u) {}
- bool StartClass(const DexFile* dex_file, size_t class_def_index) {
+ bool StartClass(const DexFile* dex_file, size_t class_def_index) OVERRIDE {
DexMethodVisitor::StartClass(dex_file, class_def_index);
DCHECK_LT(oat_class_index_, writer_->oat_classes_.size());
method_offsets_index_ = 0u;
return true;
}
- bool EndClass() {
+ bool EndClass() OVERRIDE {
++oat_class_index_;
return DexMethodVisitor::EndClass();
}
@@ -672,21 +678,61 @@
size_t method_offsets_index_;
};
+class OatWriter::InitBssLayoutMethodVisitor : public DexMethodVisitor {
+ public:
+ explicit InitBssLayoutMethodVisitor(OatWriter* writer)
+ : DexMethodVisitor(writer, /* offset */ 0u) {}
+
+ bool VisitMethod(size_t class_def_method_index ATTRIBUTE_UNUSED,
+ const ClassDataItemIterator& it) OVERRIDE {
+ // Look for patches with .bss references and prepare maps with placeholders for their offsets.
+ CompiledMethod* compiled_method = writer_->compiler_driver_->GetCompiledMethod(
+ MethodReference(dex_file_, it.GetMemberIndex()));
+ if (compiled_method != nullptr) {
+ for (const LinkerPatch& patch : compiled_method->GetPatches()) {
+ if (patch.GetType() == LinkerPatch::Type::kMethodBssEntry) {
+ MethodReference target_method = patch.TargetMethod();
+ auto refs_it = writer_->bss_method_entry_references_.find(target_method.dex_file);
+ if (refs_it == writer_->bss_method_entry_references_.end()) {
+ refs_it = writer_->bss_method_entry_references_.Put(
+ target_method.dex_file,
+ BitVector(target_method.dex_file->NumMethodIds(),
+ /* expandable */ false,
+ Allocator::GetMallocAllocator()));
+ refs_it->second.ClearAllBits();
+ }
+ refs_it->second.SetBit(target_method.dex_method_index);
+ writer_->bss_method_entries_.Overwrite(target_method, /* placeholder */ 0u);
+ } else if (patch.GetType() == LinkerPatch::Type::kTypeBssEntry) {
+ TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
+ writer_->bss_type_entries_.Overwrite(ref, /* placeholder */ 0u);
+ } else if (patch.GetType() == LinkerPatch::Type::kStringBssEntry) {
+ StringReference ref(patch.TargetStringDexFile(), patch.TargetStringIndex());
+ writer_->bss_string_entries_.Overwrite(ref, /* placeholder */ 0u);
+ }
+ }
+ }
+ return true;
+ }
+};
+
class OatWriter::InitOatClassesMethodVisitor : public DexMethodVisitor {
public:
InitOatClassesMethodVisitor(OatWriter* writer, size_t offset)
- : DexMethodVisitor(writer, offset),
- compiled_methods_(),
- num_non_null_compiled_methods_(0u) {
+ : DexMethodVisitor(writer, offset),
+ compiled_methods_(),
+ num_non_null_compiled_methods_(0u) {
size_t num_classes = 0u;
for (const OatDexFile& oat_dex_file : writer_->oat_dex_files_) {
num_classes += oat_dex_file.class_offsets_.size();
}
writer_->oat_classes_.reserve(num_classes);
compiled_methods_.reserve(256u);
+ // If there are any classes, the class offsets allocation aligns the offset.
+ DCHECK(num_classes == 0u || IsAligned<4u>(offset));
}
- bool StartClass(const DexFile* dex_file, size_t class_def_index) {
+ bool StartClass(const DexFile* dex_file, size_t class_def_index) OVERRIDE {
DexMethodVisitor::StartClass(dex_file, class_def_index);
compiled_methods_.clear();
num_non_null_compiled_methods_ = 0u;
@@ -694,7 +740,7 @@
}
bool VisitMethod(size_t class_def_method_index ATTRIBUTE_UNUSED,
- const ClassDataItemIterator& it) {
+ const ClassDataItemIterator& it) OVERRIDE {
// Fill in the compiled_methods_ array for methods that have a
// CompiledMethod. We track the number of non-null entries in
// num_non_null_compiled_methods_ since we only want to allocate
@@ -704,12 +750,12 @@
writer_->compiler_driver_->GetCompiledMethod(MethodReference(dex_file_, method_idx));
compiled_methods_.push_back(compiled_method);
if (compiled_method != nullptr) {
- ++num_non_null_compiled_methods_;
+ ++num_non_null_compiled_methods_;
}
return true;
}
- bool EndClass() {
+ bool EndClass() OVERRIDE {
ClassReference class_ref(dex_file_, class_def_index_);
mirror::Class::Status status;
bool found = writer_->compiler_driver_->GetCompiledClass(class_ref, &status);
@@ -740,14 +786,14 @@
class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor {
public:
InitCodeMethodVisitor(OatWriter* writer, size_t offset, size_t quickening_info_offset)
- : OatDexMethodVisitor(writer, offset),
- debuggable_(writer->GetCompilerDriver()->GetCompilerOptions().GetDebuggable()),
- current_quickening_info_offset_(quickening_info_offset) {
+ : OatDexMethodVisitor(writer, offset),
+ debuggable_(writer->GetCompilerDriver()->GetCompilerOptions().GetDebuggable()),
+ current_quickening_info_offset_(quickening_info_offset) {
writer_->absolute_patch_locations_.reserve(
writer_->compiler_driver_->GetNonRelativeLinkerPatchCount());
}
- bool EndClass() {
+ bool EndClass() OVERRIDE {
OatDexMethodVisitor::EndClass();
if (oat_class_index_ == writer_->oat_classes_.size()) {
offset_ = writer_->relative_patcher_->ReserveSpaceEnd(offset_);
@@ -755,7 +801,7 @@
return true;
}
- bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it)
+ bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE
REQUIRES_SHARED(Locks::mutator_lock_) {
OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
@@ -858,14 +904,6 @@
if (!patch.IsPcRelative()) {
writer_->absolute_patch_locations_.push_back(base_loc + patch.LiteralOffset());
}
- if (patch.GetType() == LinkerPatch::Type::kTypeBssEntry) {
- TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
- writer_->bss_type_entries_.Overwrite(ref, /* placeholder */ 0u);
- }
- if (patch.GetType() == LinkerPatch::Type::kStringBssEntry) {
- StringReference ref(patch.TargetStringDexFile(), patch.TargetStringIndex());
- writer_->bss_string_entries_.Overwrite(ref, /* placeholder */ 0u);
- }
}
}
}
@@ -950,11 +988,10 @@
class OatWriter::InitMapMethodVisitor : public OatDexMethodVisitor {
public:
InitMapMethodVisitor(OatWriter* writer, size_t offset)
- : OatDexMethodVisitor(writer, offset) {
- }
+ : OatDexMethodVisitor(writer, offset) {}
bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it ATTRIBUTE_UNUSED)
- REQUIRES_SHARED(Locks::mutator_lock_) {
+ OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
@@ -997,7 +1034,7 @@
InitMethodInfoVisitor(OatWriter* writer, size_t offset) : OatDexMethodVisitor(writer, offset) {}
bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it ATTRIBUTE_UNUSED)
- REQUIRES_SHARED(Locks::mutator_lock_) {
+ OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
@@ -1035,18 +1072,17 @@
InitImageMethodVisitor(OatWriter* writer,
size_t offset,
const std::vector<const DexFile*>* dex_files)
- : OatDexMethodVisitor(writer, offset),
- pointer_size_(GetInstructionSetPointerSize(writer_->compiler_driver_->GetInstructionSet())),
- dex_files_(dex_files),
- class_linker_(Runtime::Current()->GetClassLinker()) {
- }
+ : OatDexMethodVisitor(writer, offset),
+ pointer_size_(GetInstructionSetPointerSize(writer_->compiler_driver_->GetInstructionSet())),
+ dex_files_(dex_files),
+ class_linker_(Runtime::Current()->GetClassLinker()) {}
// Handle copied methods here. Copy pointer to quick code from
// an origin method to a copied method only if they are
// in the same oat file. If the origin and the copied methods are
// in different oat files don't touch the copied method.
// References to other oat files are not supported yet.
- bool StartClass(const DexFile* dex_file, size_t class_def_index)
+ bool StartClass(const DexFile* dex_file, size_t class_def_index) OVERRIDE
REQUIRES_SHARED(Locks::mutator_lock_) {
OatDexMethodVisitor::StartClass(dex_file, class_def_index);
// Skip classes that are not in the image.
@@ -1085,7 +1121,7 @@
return true;
}
- bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it)
+ bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE
REQUIRES_SHARED(Locks::mutator_lock_) {
// Skip methods that are not in the image.
if (!IsImageClass()) {
@@ -1131,8 +1167,7 @@
// Should already have been resolved by the compiler, just peek into the dex cache.
// It may not be resolved if the class failed to verify, in this case, don't set the
// entrypoint. This is not fatal since the dex cache will contain a resolution method.
- method = dex_cache->GetResolvedMethod(it.GetMemberIndex(),
- class_linker_->GetImagePointerSize());
+ method = dex_cache->GetResolvedMethod(it.GetMemberIndex(), pointer_size_);
}
if (method != nullptr &&
compiled_method != nullptr &&
@@ -1171,7 +1206,7 @@
}
}
- protected:
+ private:
const PointerSize pointer_size_;
const std::vector<const DexFile*>* dex_files_;
ClassLinker* const class_linker_;
@@ -1182,14 +1217,15 @@
public:
WriteCodeMethodVisitor(OatWriter* writer, OutputStream* out, const size_t file_offset,
size_t relative_offset) SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
- : OatDexMethodVisitor(writer, relative_offset),
- class_loader_(writer->HasImage() ? writer->image_writer_->GetClassLoader() : nullptr),
- out_(out),
- file_offset_(file_offset),
- soa_(Thread::Current()),
- no_thread_suspension_("OatWriter patching"),
- class_linker_(Runtime::Current()->GetClassLinker()),
- dex_cache_(nullptr) {
+ : OatDexMethodVisitor(writer, relative_offset),
+ pointer_size_(GetInstructionSetPointerSize(writer_->compiler_driver_->GetInstructionSet())),
+ class_loader_(writer->HasImage() ? writer->image_writer_->GetClassLoader() : nullptr),
+ out_(out),
+ file_offset_(file_offset),
+ soa_(Thread::Current()),
+ no_thread_suspension_("OatWriter patching"),
+ class_linker_(Runtime::Current()->GetClassLinker()),
+ dex_cache_(nullptr) {
patched_code_.reserve(16 * KB);
if (writer_->HasBootImage()) {
// If we're creating the image, the address space must be ready so that we can apply patches.
@@ -1200,7 +1236,7 @@
~WriteCodeMethodVisitor() UNLOCK_FUNCTION(Locks::mutator_lock_) {
}
- bool StartClass(const DexFile* dex_file, size_t class_def_index)
+ bool StartClass(const DexFile* dex_file, size_t class_def_index) OVERRIDE
REQUIRES_SHARED(Locks::mutator_lock_) {
OatDexMethodVisitor::StartClass(dex_file, class_def_index);
if (dex_cache_ == nullptr || dex_cache_->GetDexFile() != dex_file) {
@@ -1210,7 +1246,7 @@
return true;
}
- bool EndClass() REQUIRES_SHARED(Locks::mutator_lock_) {
+ bool EndClass() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
bool result = OatDexMethodVisitor::EndClass();
if (oat_class_index_ == writer_->oat_classes_.size()) {
DCHECK(result); // OatDexMethodVisitor::EndClass() never fails.
@@ -1223,7 +1259,7 @@
return result;
}
- bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it)
+ bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE
REQUIRES_SHARED(Locks::mutator_lock_) {
OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
@@ -1275,6 +1311,15 @@
for (const LinkerPatch& patch : compiled_method->GetPatches()) {
uint32_t literal_offset = patch.LiteralOffset();
switch (patch.GetType()) {
+ case LinkerPatch::Type::kMethodBssEntry: {
+ uint32_t target_offset =
+ writer_->bss_start_ + writer_->bss_method_entries_.Get(patch.TargetMethod());
+ writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+ patch,
+ offset_ + literal_offset,
+ target_offset);
+ break;
+ }
case LinkerPatch::Type::kCallRelative: {
// NOTE: Relative calls across oat files are not supported.
uint32_t target_offset = GetTargetOffset(patch);
@@ -1284,14 +1329,6 @@
target_offset);
break;
}
- case LinkerPatch::Type::kDexCacheArray: {
- uint32_t target_offset = GetDexCacheOffset(patch);
- writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
- patch,
- offset_ + literal_offset,
- target_offset);
- break;
- }
case LinkerPatch::Type::kStringRelative: {
uint32_t target_offset = GetTargetObjectOffset(GetTargetString(patch));
writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
@@ -1302,7 +1339,8 @@
}
case LinkerPatch::Type::kStringBssEntry: {
StringReference ref(patch.TargetStringDexFile(), patch.TargetStringIndex());
- uint32_t target_offset = writer_->bss_string_entries_.Get(ref);
+ uint32_t target_offset =
+ writer_->bss_start_ + writer_->bss_string_entries_.Get(ref);
writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
patch,
offset_ + literal_offset,
@@ -1319,7 +1357,7 @@
}
case LinkerPatch::Type::kTypeBssEntry: {
TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
- uint32_t target_offset = writer_->bss_type_entries_.Get(ref);
+ uint32_t target_offset = writer_->bss_start_ + writer_->bss_type_entries_.Get(ref);
writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
patch,
offset_ + literal_offset,
@@ -1368,6 +1406,7 @@
}
private:
+ const PointerSize pointer_size_;
ObjPtr<mirror::ClassLoader> class_loader_;
OutputStream* const out_;
const size_t file_offset_;
@@ -1388,8 +1427,7 @@
ObjPtr<mirror::DexCache> dex_cache =
(dex_file_ == ref.dex_file) ? dex_cache_ : class_linker_->FindDexCache(
Thread::Current(), *ref.dex_file);
- ArtMethod* method = dex_cache->GetResolvedMethod(
- ref.dex_method_index, class_linker_->GetImagePointerSize());
+ ArtMethod* method = dex_cache->GetResolvedMethod(ref.dex_method_index, pointer_size_);
CHECK(method != nullptr);
return method;
}
@@ -1401,9 +1439,8 @@
if (UNLIKELY(target_offset == 0)) {
ArtMethod* target = GetTargetMethod(patch);
DCHECK(target != nullptr);
- PointerSize size =
- GetInstructionSetPointerSize(writer_->compiler_driver_->GetInstructionSet());
- const void* oat_code_offset = target->GetEntryPointFromQuickCompiledCodePtrSize(size);
+ const void* oat_code_offset =
+ target->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size_);
if (oat_code_offset != 0) {
DCHECK(!writer_->HasBootImage());
DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickResolutionStub(oat_code_offset));
@@ -1447,19 +1484,6 @@
return string;
}
- uint32_t GetDexCacheOffset(const LinkerPatch& patch) REQUIRES_SHARED(Locks::mutator_lock_) {
- if (writer_->HasBootImage()) {
- uintptr_t element = writer_->image_writer_->GetDexCacheArrayElementImageAddress<uintptr_t>(
- patch.TargetDexCacheDexFile(), patch.TargetDexCacheElementOffset());
- size_t oat_index = writer_->image_writer_->GetOatIndexForDexCache(dex_cache_);
- uintptr_t oat_data = writer_->image_writer_->GetOatDataBegin(oat_index);
- return element - oat_data;
- } else {
- size_t start = writer_->dex_cache_arrays_offsets_.Get(patch.TargetDexCacheDexFile());
- return start + patch.TargetDexCacheElementOffset();
- }
- }
-
uint32_t GetTargetMethodOffset(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(writer_->HasBootImage());
method = writer_->image_writer_->GetImageMethodAddress(method);
@@ -1525,12 +1549,11 @@
OutputStream* out,
const size_t file_offset,
size_t relative_offset)
- : OatDexMethodVisitor(writer, relative_offset),
- out_(out),
- file_offset_(file_offset) {
- }
+ : OatDexMethodVisitor(writer, relative_offset),
+ out_(out),
+ file_offset_(file_offset) {}
- bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) {
+ bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE {
OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
@@ -1589,11 +1612,11 @@
OutputStream* out,
const size_t file_offset,
size_t relative_offset)
- : OatDexMethodVisitor(writer, relative_offset),
- out_(out),
- file_offset_(file_offset) {}
+ : OatDexMethodVisitor(writer, relative_offset),
+ out_(out),
+ file_offset_(file_offset) {}
- bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) {
+ bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE {
OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
@@ -1698,12 +1721,17 @@
return oat_header_->GetHeaderSize();
}
-size_t OatWriter::InitOatDexFiles(size_t offset) {
- TimingLogger::ScopedTiming split("InitOatDexFiles", timings_);
- // Initialize offsets of dex files.
+size_t OatWriter::InitClassOffsets(size_t offset) {
+ // Reserve space for class offsets in OAT and update class_offsets_offset_.
for (OatDexFile& oat_dex_file : oat_dex_files_) {
- oat_dex_file.offset_ = offset;
- offset += oat_dex_file.SizeOf();
+ DCHECK_EQ(oat_dex_file.class_offsets_offset_, 0u);
+ if (!oat_dex_file.class_offsets_.empty()) {
+ // Class offsets are required to be 4 byte aligned.
+ offset = RoundUp(offset, 4u);
+ oat_dex_file.class_offsets_offset_ = offset;
+ offset += oat_dex_file.GetClassOffsetsRawSize();
+ DCHECK_ALIGNED(offset, 4u);
+ }
}
return offset;
}
@@ -1748,6 +1776,50 @@
return offset;
}
+size_t OatWriter::InitMethodBssMappings(size_t offset) {
+ size_t number_of_dex_files = 0u;
+ for (size_t i = 0, size = dex_files_->size(); i != size; ++i) {
+ const DexFile* dex_file = (*dex_files_)[i];
+ auto it = bss_method_entry_references_.find(dex_file);
+ if (it != bss_method_entry_references_.end()) {
+ const BitVector& method_indexes = it->second;
+ ++number_of_dex_files;
+ // If there are any classes, the class offsets allocation aligns the offset
+ // and we cannot have method bss mappings without class offsets.
+ static_assert(alignof(MethodBssMapping) == 4u, "MethodBssMapping alignment check.");
+ DCHECK_ALIGNED(offset, 4u);
+ oat_dex_files_[i].method_bss_mapping_offset_ = offset;
+
+ linker::MethodBssMappingEncoder encoder(
+ GetInstructionSetPointerSize(oat_header_->GetInstructionSet()));
+ size_t number_of_entries = 0u;
+ bool first_index = true;
+ for (uint32_t method_index : method_indexes.Indexes()) {
+ uint32_t bss_offset = bss_method_entries_.Get(MethodReference(dex_file, method_index));
+ if (first_index || !encoder.TryMerge(method_index, bss_offset)) {
+ encoder.Reset(method_index, bss_offset);
+ ++number_of_entries;
+ first_index = false;
+ }
+ }
+ DCHECK_NE(number_of_entries, 0u);
+ offset += MethodBssMapping::ComputeSize(number_of_entries);
+ }
+ }
+ // Check that all dex files targeted by method bss entries are in `*dex_files_`.
+ CHECK_EQ(number_of_dex_files, bss_method_entry_references_.size());
+ return offset;
+}
+
+size_t OatWriter::InitOatDexFiles(size_t offset) {
+ // Initialize offsets of oat dex files.
+ for (OatDexFile& oat_dex_file : oat_dex_files_) {
+ oat_dex_file.offset_ = offset;
+ offset += oat_dex_file.SizeOf();
+ }
+ return offset;
+}
+
size_t OatWriter::InitOatCode(size_t offset) {
// calculate the offsets within OatHeader to executable code
size_t old_offset = offset;
@@ -1806,38 +1878,51 @@
}
void OatWriter::InitBssLayout(InstructionSet instruction_set) {
+ {
+ InitBssLayoutMethodVisitor visitor(this);
+ bool success = VisitDexMethods(&visitor);
+ DCHECK(success);
+ }
+
+ DCHECK_EQ(bss_size_, 0u);
if (HasBootImage()) {
DCHECK(bss_string_entries_.empty());
- if (bss_type_entries_.empty()) {
+ if (bss_method_entries_.empty() && bss_type_entries_.empty()) {
// Nothing to put to the .bss section.
return;
}
}
// Allocate space for app dex cache arrays in the .bss section.
- bss_start_ = RoundUp(oat_size_, kPageSize);
- bss_size_ = 0u;
+ PointerSize pointer_size = GetInstructionSetPointerSize(instruction_set);
if (!HasBootImage()) {
- PointerSize pointer_size = GetInstructionSetPointerSize(instruction_set);
for (const DexFile* dex_file : *dex_files_) {
- dex_cache_arrays_offsets_.Put(dex_file, bss_start_ + bss_size_);
DexCacheArraysLayout layout(pointer_size, dex_file);
bss_size_ += layout.Size();
}
}
+ bss_methods_offset_ = bss_size_;
+
+ // Prepare offsets for .bss ArtMethod entries.
+ for (auto& entry : bss_method_entries_) {
+ DCHECK_EQ(entry.second, 0u);
+ entry.second = bss_size_;
+ bss_size_ += static_cast<size_t>(pointer_size);
+ }
+
bss_roots_offset_ = bss_size_;
// Prepare offsets for .bss Class entries.
for (auto& entry : bss_type_entries_) {
DCHECK_EQ(entry.second, 0u);
- entry.second = bss_start_ + bss_size_;
+ entry.second = bss_size_;
bss_size_ += sizeof(GcRoot<mirror::Class>);
}
// Prepare offsets for .bss String entries.
for (auto& entry : bss_string_entries_) {
DCHECK_EQ(entry.second, 0u);
- entry.second = bss_start_ + bss_size_;
+ entry.second = bss_size_;
bss_size_ += sizeof(GcRoot<mirror::String>);
}
}
@@ -1845,30 +1930,45 @@
bool OatWriter::WriteRodata(OutputStream* out) {
CHECK(write_state_ == WriteState::kWriteRoData);
+ size_t file_offset = oat_data_offset_;
+ off_t current_offset = out->Seek(0, kSeekCurrent);
+ if (current_offset == static_cast<off_t>(-1)) {
+ PLOG(ERROR) << "Failed to retrieve current position in " << out->GetLocation();
+ }
+ DCHECK_GE(static_cast<size_t>(current_offset), file_offset + oat_header_->GetHeaderSize());
+ size_t relative_offset = current_offset - file_offset;
+
// Wrap out to update checksum with each write.
ChecksumUpdatingOutputStream checksum_updating_out(out, oat_header_.get());
out = &checksum_updating_out;
- if (!WriteClassOffsets(out)) {
- LOG(ERROR) << "Failed to write class offsets to " << out->GetLocation();
+ relative_offset = WriteClassOffsets(out, file_offset, relative_offset);
+ if (relative_offset == 0) {
+ PLOG(ERROR) << "Failed to write class offsets to " << out->GetLocation();
return false;
}
- if (!WriteClasses(out)) {
- LOG(ERROR) << "Failed to write classes to " << out->GetLocation();
+ relative_offset = WriteClasses(out, file_offset, relative_offset);
+ if (relative_offset == 0) {
+ PLOG(ERROR) << "Failed to write classes to " << out->GetLocation();
return false;
}
- off_t tables_end_offset = out->Seek(0, kSeekCurrent);
- if (tables_end_offset == static_cast<off_t>(-1)) {
- LOG(ERROR) << "Failed to get oat code position in " << out->GetLocation();
+ relative_offset = WriteMethodBssMappings(out, file_offset, relative_offset);
+ if (relative_offset == 0) {
+ PLOG(ERROR) << "Failed to write method bss mappings to " << out->GetLocation();
return false;
}
- size_t file_offset = oat_data_offset_;
- size_t relative_offset = static_cast<size_t>(tables_end_offset) - file_offset;
+
relative_offset = WriteMaps(out, file_offset, relative_offset);
if (relative_offset == 0) {
- LOG(ERROR) << "Failed to write oat code to " << out->GetLocation();
+ PLOG(ERROR) << "Failed to write oat code to " << out->GetLocation();
+ return false;
+ }
+
+ relative_offset = WriteOatDexFiles(out, file_offset, relative_offset);
+ if (relative_offset == 0) {
+ PLOG(ERROR) << "Failed to write oat dex information to " << out->GetLocation();
return false;
}
@@ -1891,12 +1991,12 @@
class OatWriter::WriteQuickeningInfoMethodVisitor : public DexMethodVisitor {
public:
WriteQuickeningInfoMethodVisitor(OatWriter* writer, OutputStream* out, uint32_t offset)
- : DexMethodVisitor(writer, offset),
- out_(out),
- written_bytes_(0u) {}
+ : DexMethodVisitor(writer, offset),
+ out_(out),
+ written_bytes_(0u) {}
bool VisitMethod(size_t class_def_method_index ATTRIBUTE_UNUSED,
- const ClassDataItemIterator& it) {
+ const ClassDataItemIterator& it) OVERRIDE {
if (it.GetMethodCodeItem() == nullptr) {
// No CodeItem. Native or abstract method.
return true;
@@ -2092,6 +2192,7 @@
DO_STAT(size_oat_dex_file_offset_);
DO_STAT(size_oat_dex_file_class_offsets_offset_);
DO_STAT(size_oat_dex_file_lookup_table_offset_);
+ DO_STAT(size_oat_dex_file_method_bss_mapping_offset_);
DO_STAT(size_oat_lookup_table_alignment_);
DO_STAT(size_oat_lookup_table_);
DO_STAT(size_oat_class_offsets_alignment_);
@@ -2100,6 +2201,7 @@
DO_STAT(size_oat_class_status_);
DO_STAT(size_oat_class_method_bitmaps_);
DO_STAT(size_oat_class_method_offsets_);
+ DO_STAT(size_method_bss_mappings_);
#undef DO_STAT
VLOG(compiler) << "size_total=" << PrettySize(size_total) << " (" << size_total << "B)";
@@ -2172,35 +2274,41 @@
return true;
}
-bool OatWriter::WriteClassOffsets(OutputStream* out) {
+size_t OatWriter::WriteClassOffsets(OutputStream* out, size_t file_offset, size_t relative_offset) {
for (OatDexFile& oat_dex_file : oat_dex_files_) {
if (oat_dex_file.class_offsets_offset_ != 0u) {
- uint32_t expected_offset = oat_data_offset_ + oat_dex_file.class_offsets_offset_;
- off_t actual_offset = out->Seek(expected_offset, kSeekSet);
- if (static_cast<uint32_t>(actual_offset) != expected_offset) {
- PLOG(ERROR) << "Failed to seek to oat class offsets section. Actual: " << actual_offset
- << " Expected: " << expected_offset << " File: " << oat_dex_file.GetLocation();
- return false;
+ // Class offsets are required to be 4 byte aligned.
+ if (UNLIKELY(!IsAligned<4u>(relative_offset))) {
+ size_t padding_size = RoundUp(relative_offset, 4u) - relative_offset;
+ if (!WriteUpTo16BytesAlignment(out, padding_size, &size_oat_class_offsets_alignment_)) {
+ return 0u;
+ }
+ relative_offset += padding_size;
}
+ DCHECK_OFFSET();
if (!oat_dex_file.WriteClassOffsets(this, out)) {
- return false;
+ return 0u;
}
+ relative_offset += oat_dex_file.GetClassOffsetsRawSize();
}
}
- return true;
+ return relative_offset;
}
-bool OatWriter::WriteClasses(OutputStream* out) {
+size_t OatWriter::WriteClasses(OutputStream* out, size_t file_offset, size_t relative_offset) {
for (OatClass& oat_class : oat_classes_) {
+ // If there are any classes, the class offsets allocation aligns the offset.
+ DCHECK_ALIGNED(relative_offset, 4u);
+ DCHECK_OFFSET();
if (!oat_class.Write(this, out, oat_data_offset_)) {
- PLOG(ERROR) << "Failed to write oat methods information to " << out->GetLocation();
- return false;
+ return 0u;
}
+ relative_offset += oat_class.SizeOf();
}
- return true;
+ return relative_offset;
}
-size_t OatWriter::WriteMaps(OutputStream* out, const size_t file_offset, size_t relative_offset) {
+size_t OatWriter::WriteMaps(OutputStream* out, size_t file_offset, size_t relative_offset) {
{
size_t vmap_tables_offset = relative_offset;
WriteMapMethodVisitor visitor(this, out, file_offset, relative_offset);
@@ -2223,7 +2331,87 @@
return relative_offset;
}
-size_t OatWriter::WriteCode(OutputStream* out, const size_t file_offset, size_t relative_offset) {
+size_t OatWriter::WriteMethodBssMappings(OutputStream* out,
+ size_t file_offset,
+ size_t relative_offset) {
+ TimingLogger::ScopedTiming split("WriteMethodBssMappings", timings_);
+
+ for (size_t i = 0, size = dex_files_->size(); i != size; ++i) {
+ const DexFile* dex_file = (*dex_files_)[i];
+ OatDexFile* oat_dex_file = &oat_dex_files_[i];
+ auto it = bss_method_entry_references_.find(dex_file);
+ if (it != bss_method_entry_references_.end()) {
+ const BitVector& method_indexes = it->second;
+ // If there are any classes, the class offsets allocation aligns the offset
+ // and we cannot have method bss mappings without class offsets.
+ static_assert(alignof(MethodBssMapping) == sizeof(uint32_t),
+ "MethodBssMapping alignment check.");
+ DCHECK_ALIGNED(relative_offset, sizeof(uint32_t));
+
+ linker::MethodBssMappingEncoder encoder(
+ GetInstructionSetPointerSize(oat_header_->GetInstructionSet()));
+ // Allocate a sufficiently large MethodBssMapping.
+ size_t number_of_method_indexes = method_indexes.NumSetBits();
+ DCHECK_NE(number_of_method_indexes, 0u);
+ size_t max_mappings_size = MethodBssMapping::ComputeSize(number_of_method_indexes);
+ DCHECK_ALIGNED(max_mappings_size, sizeof(uint32_t));
+ std::unique_ptr<uint32_t[]> storage(new uint32_t[max_mappings_size / sizeof(uint32_t)]);
+ MethodBssMapping* mappings = new(storage.get()) MethodBssMapping(number_of_method_indexes);
+ mappings->ClearPadding();
+ // Encode the MethodBssMapping.
+ auto init_it = mappings->begin();
+ bool first_index = true;
+ for (uint32_t method_index : method_indexes.Indexes()) {
+ size_t bss_offset = bss_method_entries_.Get(MethodReference(dex_file, method_index));
+ if (first_index) {
+ first_index = false;
+ encoder.Reset(method_index, bss_offset);
+ } else if (!encoder.TryMerge(method_index, bss_offset)) {
+ *init_it = encoder.GetEntry();
+ ++init_it;
+ encoder.Reset(method_index, bss_offset);
+ }
+ }
+ // Store the last entry and shrink the mapping to the actual size.
+ *init_it = encoder.GetEntry();
+ ++init_it;
+ DCHECK(init_it <= mappings->end());
+ mappings->SetSize(std::distance(mappings->begin(), init_it));
+ size_t mappings_size = MethodBssMapping::ComputeSize(mappings->size());
+
+ DCHECK_EQ(relative_offset, oat_dex_file->method_bss_mapping_offset_);
+ DCHECK_OFFSET();
+ if (!out->WriteFully(storage.get(), mappings_size)) {
+ return 0u;
+ }
+ size_method_bss_mappings_ += mappings_size;
+ relative_offset += mappings_size;
+ } else {
+ DCHECK_EQ(0u, oat_dex_file->method_bss_mapping_offset_);
+ }
+ }
+ return relative_offset;
+}
+
+size_t OatWriter::WriteOatDexFiles(OutputStream* out, size_t file_offset, size_t relative_offset) {
+ TimingLogger::ScopedTiming split("WriteOatDexFiles", timings_);
+
+ for (size_t i = 0, size = oat_dex_files_.size(); i != size; ++i) {
+ OatDexFile* oat_dex_file = &oat_dex_files_[i];
+ DCHECK_EQ(relative_offset, oat_dex_file->offset_);
+ DCHECK_OFFSET();
+
+ // Write OatDexFile.
+ if (!oat_dex_file->Write(this, out)) {
+ return 0u;
+ }
+ relative_offset += oat_dex_file->SizeOf();
+ }
+
+ return relative_offset;
+}
+
+size_t OatWriter::WriteCode(OutputStream* out, size_t file_offset, size_t relative_offset) {
if (compiler_driver_->GetCompilerOptions().IsBootImage()) {
InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
@@ -2253,7 +2441,7 @@
}
size_t OatWriter::WriteCodeDexFiles(OutputStream* out,
- const size_t file_offset,
+ size_t file_offset,
size_t relative_offset) {
#define VISIT(VisitorType) \
do { \
@@ -2667,50 +2855,6 @@
return true;
}
-bool OatWriter::WriteOatDexFiles(OutputStream* rodata) {
- TimingLogger::ScopedTiming split("WriteOatDexFiles", timings_);
-
- off_t initial_offset = rodata->Seek(0, kSeekCurrent);
- if (initial_offset == static_cast<off_t>(-1)) {
- LOG(ERROR) << "Failed to get current position in " << rodata->GetLocation();
- return false;
- }
-
- // Seek to the start of OatDexFiles, i.e. to the end of the OatHeader. If there are
- // no OatDexFiles, no data is actually written to .rodata before WriteHeader() and
- // this Seek() ensures that we reserve the space for OatHeader in .rodata.
- DCHECK(oat_dex_files_.empty() || oat_dex_files_[0u].offset_ == oat_header_->GetHeaderSize());
- uint32_t expected_offset = oat_data_offset_ + oat_header_->GetHeaderSize();
- off_t actual_offset = rodata->Seek(expected_offset, kSeekSet);
- if (static_cast<uint32_t>(actual_offset) != expected_offset) {
- PLOG(ERROR) << "Failed to seek to OatDexFile table section. Actual: " << actual_offset
- << " Expected: " << expected_offset << " File: " << rodata->GetLocation();
- return false;
- }
-
- for (size_t i = 0, size = oat_dex_files_.size(); i != size; ++i) {
- OatDexFile* oat_dex_file = &oat_dex_files_[i];
-
- DCHECK_EQ(oat_data_offset_ + oat_dex_file->offset_,
- static_cast<size_t>(rodata->Seek(0, kSeekCurrent)));
-
- // Write OatDexFile.
- if (!oat_dex_file->Write(this, rodata)) {
- PLOG(ERROR) << "Failed to write oat dex information to " << rodata->GetLocation();
- return false;
- }
- }
-
- // Seek back to the initial position.
- if (rodata->Seek(initial_offset, kSeekSet) != initial_offset) {
- PLOG(ERROR) << "Failed to seek to initial position. Actual: " << actual_offset
- << " Expected: " << initial_offset << " File: " << rodata->GetLocation();
- return false;
- }
-
- return true;
-}
-
bool OatWriter::OpenDexFiles(
File* file,
bool verify,
@@ -2929,14 +3073,18 @@
}
bool OatWriter::WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delta) {
+ return WriteUpTo16BytesAlignment(out, aligned_code_delta, &size_code_alignment_);
+}
+
+bool OatWriter::WriteUpTo16BytesAlignment(OutputStream* out, uint32_t size, uint32_t* stat) {
static const uint8_t kPadding[] = {
0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u
};
- DCHECK_LE(aligned_code_delta, sizeof(kPadding));
- if (UNLIKELY(!out->WriteFully(kPadding, aligned_code_delta))) {
+ DCHECK_LE(size, sizeof(kPadding));
+ if (UNLIKELY(!out->WriteFully(kPadding, size))) {
return false;
}
- size_code_alignment_ += aligned_code_delta;
+ *stat += size;
return true;
}
@@ -2965,6 +3113,7 @@
dex_file_offset_(0u),
class_offsets_offset_(0u),
lookup_table_offset_(0u),
+ method_bss_mapping_offset_(0u),
class_offsets_() {
}
@@ -2974,19 +3123,8 @@
+ sizeof(dex_file_location_checksum_)
+ sizeof(dex_file_offset_)
+ sizeof(class_offsets_offset_)
- + sizeof(lookup_table_offset_);
-}
-
-void OatWriter::OatDexFile::ReserveClassOffsets(OatWriter* oat_writer) {
- DCHECK_EQ(class_offsets_offset_, 0u);
- if (!class_offsets_.empty()) {
- // Class offsets are required to be 4 byte aligned.
- size_t initial_offset = oat_writer->oat_size_;
- size_t offset = RoundUp(initial_offset, 4);
- oat_writer->size_oat_class_offsets_alignment_ += offset - initial_offset;
- class_offsets_offset_ = offset;
- oat_writer->oat_size_ = offset + GetClassOffsetsRawSize();
- }
+ + sizeof(lookup_table_offset_)
+ + sizeof(method_bss_mapping_offset_);
}
bool OatWriter::OatDexFile::Write(OatWriter* oat_writer, OutputStream* out) const {
@@ -3029,6 +3167,12 @@
}
oat_writer->size_oat_dex_file_lookup_table_offset_ += sizeof(lookup_table_offset_);
+ if (!out->WriteFully(&method_bss_mapping_offset_, sizeof(method_bss_mapping_offset_))) {
+ PLOG(ERROR) << "Failed to write method bss mapping offset to " << out->GetLocation();
+ return false;
+ }
+ oat_writer->size_oat_dex_file_method_bss_mapping_offset_ += sizeof(method_bss_mapping_offset_);
+
return true;
}
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index 66b70ad..9217701 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -60,11 +60,6 @@
// OatHeader variable length with count of D OatDexFiles
//
-// OatDexFile[0] one variable sized OatDexFile with offsets to Dex and OatClasses
-// OatDexFile[1]
-// ...
-// OatDexFile[D]
-//
// TypeLookupTable[0] one descriptor to class def index hash table for each OatDexFile.
// TypeLookupTable[1]
// ...
@@ -80,20 +75,25 @@
// ...
// OatClass[C]
//
-// GcMap one variable sized blob with GC map.
-// GcMap GC maps are deduplicated.
+// MethodBssMapping one variable sized MethodBssMapping for each dex file, optional.
+// MethodBssMapping
// ...
-// GcMap
+// MethodBssMapping
//
-// VmapTable one variable sized VmapTable blob (quick compiler only).
+// VmapTable one variable sized VmapTable blob (CodeInfo or QuickeningInfo).
// VmapTable VmapTables are deduplicated.
// ...
// VmapTable
//
-// MappingTable one variable sized blob with MappingTable (quick compiler only).
-// MappingTable MappingTables are deduplicated.
+// MethodInfo one variable sized blob with MethodInfo.
+// MethodInfo MethodInfos are deduplicated.
// ...
-// MappingTable
+// MethodInfo
+//
+// OatDexFile[0] one variable sized OatDexFile with offsets to Dex and OatClasses
+// OatDexFile[1]
+// ...
+// OatDexFile[D]
//
// padding if necessary so that the following code will be page aligned
//
@@ -217,6 +217,10 @@
return bss_size_;
}
+ size_t GetBssMethodsOffset() const {
+ return bss_methods_offset_;
+ }
+
size_t GetBssRootsOffset() const {
return bss_roots_offset_;
}
@@ -251,6 +255,7 @@
// to actually write it.
class DexMethodVisitor;
class OatDexMethodVisitor;
+ class InitBssLayoutMethodVisitor;
class InitOatClassesMethodVisitor;
class InitCodeMethodVisitor;
class InitMapMethodVisitor;
@@ -295,26 +300,30 @@
const InstructionSetFeatures* instruction_set_features,
uint32_t num_dex_files,
SafeMap<std::string, std::string>* key_value_store);
- size_t InitOatDexFiles(size_t offset);
+ size_t InitClassOffsets(size_t offset);
size_t InitOatClasses(size_t offset);
size_t InitOatMaps(size_t offset);
+ size_t InitMethodBssMappings(size_t offset);
+ size_t InitOatDexFiles(size_t offset);
size_t InitOatCode(size_t offset);
size_t InitOatCodeDexFiles(size_t offset);
void InitBssLayout(InstructionSet instruction_set);
- bool WriteClassOffsets(OutputStream* out);
- bool WriteClasses(OutputStream* out);
- size_t WriteMaps(OutputStream* out, const size_t file_offset, size_t relative_offset);
- size_t WriteCode(OutputStream* out, const size_t file_offset, size_t relative_offset);
- size_t WriteCodeDexFiles(OutputStream* out, const size_t file_offset, size_t relative_offset);
+ size_t WriteClassOffsets(OutputStream* out, size_t file_offset, size_t relative_offset);
+ size_t WriteClasses(OutputStream* out, size_t file_offset, size_t relative_offset);
+ size_t WriteMaps(OutputStream* out, size_t file_offset, size_t relative_offset);
+ size_t WriteMethodBssMappings(OutputStream* out, size_t file_offset, size_t relative_offset);
+ size_t WriteOatDexFiles(OutputStream* out, size_t file_offset, size_t relative_offset);
+ size_t WriteCode(OutputStream* out, size_t file_offset, size_t relative_offset);
+ size_t WriteCodeDexFiles(OutputStream* out, size_t file_offset, size_t relative_offset);
bool RecordOatDataOffset(OutputStream* out);
bool ReadDexFileHeader(File* oat_file, OatDexFile* oat_dex_file);
bool ValidateDexFileHeader(const uint8_t* raw_header, const char* location);
- bool WriteOatDexFiles(OutputStream* oat_rodata);
bool WriteTypeLookupTables(OutputStream* oat_rodata,
const std::vector<std::unique_ptr<const DexFile>>& opened_dex_files);
bool WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delta);
+ bool WriteUpTo16BytesAlignment(OutputStream* out, uint32_t size, uint32_t* stat);
void SetMultiOatRelativePatcherAdjustment();
void CloseSources();
@@ -368,9 +377,20 @@
// The size of the required .bss section holding the DexCache data and GC roots.
size_t bss_size_;
+ // The offset of the methods in .bss section.
+ size_t bss_methods_offset_;
+
// The offset of the GC roots in .bss section.
size_t bss_roots_offset_;
+ // Map for recording references to ArtMethod entries in .bss.
+ SafeMap<const DexFile*, BitVector> bss_method_entry_references_;
+
+ // Map for allocating ArtMethod entries in .bss. Indexed by MethodReference for the target
+ // method in the dex file with the "method reference value comparator" for deduplication.
+ // The value is the target offset for patching, starting at `bss_start_ + bss_methods_offset_`.
+ SafeMap<MethodReference, size_t, MethodReferenceValueComparator> bss_method_entries_;
+
// Map for allocating Class entries in .bss. Indexed by TypeReference for the source
// type in the dex file with the "type value comparator" for deduplication. The value
// is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`.
@@ -381,10 +401,6 @@
// is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`.
SafeMap<StringReference, size_t, StringReferenceValueComparator> bss_string_entries_;
- // Offsets of the dex cache arrays for each app dex file. For the
- // boot image, this information is provided by the ImageWriter.
- SafeMap<const DexFile*, size_t> dex_cache_arrays_offsets_; // DexFiles not owned.
-
// Offset of the oat data from the start of the mmapped region of the elf file.
size_t oat_data_offset_;
@@ -434,6 +450,7 @@
uint32_t size_oat_dex_file_offset_;
uint32_t size_oat_dex_file_class_offsets_offset_;
uint32_t size_oat_dex_file_lookup_table_offset_;
+ uint32_t size_oat_dex_file_method_bss_mapping_offset_;
uint32_t size_oat_lookup_table_alignment_;
uint32_t size_oat_lookup_table_;
uint32_t size_oat_class_offsets_alignment_;
@@ -442,6 +459,7 @@
uint32_t size_oat_class_status_;
uint32_t size_oat_class_method_bitmaps_;
uint32_t size_oat_class_method_offsets_;
+ uint32_t size_method_bss_mappings_;
// The helper for processing relative patches is external so that we can patch across oat files.
linker::MultiOatRelativePatcher* relative_patcher_;
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 8300f81..804bc0f 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -2395,8 +2395,8 @@
isa_features_(isa_features),
uint32_literals_(std::less<uint32_t>(),
graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
- pc_relative_dex_cache_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
pc_relative_method_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
+ method_bss_entry_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
pc_relative_type_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
type_bss_entry_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
pc_relative_string_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
@@ -3553,18 +3553,10 @@
IntrinsicLocationsBuilderARM intrinsic(codegen_);
if (intrinsic.TryDispatch(invoke)) {
- if (invoke->GetLocations()->CanCall() && invoke->HasPcRelativeDexCache()) {
- invoke->GetLocations()->SetInAt(invoke->GetSpecialInputIndex(), Location::Any());
- }
return;
}
HandleInvoke(invoke);
-
- // For PC-relative dex cache the invoke has an extra input, the PC-relative address base.
- if (invoke->HasPcRelativeDexCache()) {
- invoke->GetLocations()->SetInAt(invoke->GetSpecialInputIndex(), Location::RequiresRegister());
- }
}
static bool TryGenerateIntrinsicCode(HInvoke* invoke, CodeGeneratorARM* codegen) {
@@ -8981,13 +8973,17 @@
case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
__ LoadImmediate(temp.AsRegister<Register>(), invoke->GetMethodAddress());
break;
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative: {
- HArmDexCacheArraysBase* base =
- invoke->InputAt(invoke->GetSpecialInputIndex())->AsArmDexCacheArraysBase();
- Register base_reg = GetInvokeStaticOrDirectExtraParameter(invoke,
- temp.AsRegister<Register>());
- int32_t offset = invoke->GetDexCacheArrayOffset() - base->GetElementOffset();
- __ LoadFromOffset(kLoadWord, temp.AsRegister<Register>(), base_reg, offset);
+ case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry: {
+ Register temp_reg = temp.AsRegister<Register>();
+ PcRelativePatchInfo* labels = NewMethodBssEntryPatch(
+ MethodReference(&GetGraph()->GetDexFile(), invoke->GetDexMethodIndex()));
+ __ BindTrackedLabel(&labels->movw_label);
+ __ movw(temp_reg, /* placeholder */ 0u);
+ __ BindTrackedLabel(&labels->movt_label);
+ __ movt(temp_reg, /* placeholder */ 0u);
+ __ BindTrackedLabel(&labels->add_pc_label);
+ __ add(temp_reg, temp_reg, ShifterOperand(PC));
+ __ LoadFromOffset(kLoadWord, temp_reg, temp_reg, /* offset */ 0);
break;
}
case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
@@ -9056,6 +9052,13 @@
&pc_relative_method_patches_);
}
+CodeGeneratorARM::PcRelativePatchInfo* CodeGeneratorARM::NewMethodBssEntryPatch(
+ MethodReference target_method) {
+ return NewPcRelativePatch(*target_method.dex_file,
+ target_method.dex_method_index,
+ &method_bss_entry_patches_);
+}
+
CodeGeneratorARM::PcRelativePatchInfo* CodeGeneratorARM::NewPcRelativeTypePatch(
const DexFile& dex_file, dex::TypeIndex type_index) {
return NewPcRelativePatch(dex_file, type_index.index_, &pc_relative_type_patches_);
@@ -9071,11 +9074,6 @@
return NewPcRelativePatch(dex_file, string_index.index_, &pc_relative_string_patches_);
}
-CodeGeneratorARM::PcRelativePatchInfo* CodeGeneratorARM::NewPcRelativeDexCacheArrayPatch(
- const DexFile& dex_file, uint32_t element_offset) {
- return NewPcRelativePatch(dex_file, element_offset, &pc_relative_dex_cache_patches_);
-}
-
CodeGeneratorARM::PcRelativePatchInfo* CodeGeneratorARM::NewPcRelativePatch(
const DexFile& dex_file, uint32_t offset_or_index, ArenaDeque<PcRelativePatchInfo>* patches) {
patches->emplace_back(dex_file, offset_or_index);
@@ -9134,15 +9132,13 @@
void CodeGeneratorARM::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) {
DCHECK(linker_patches->empty());
size_t size =
- /* MOVW+MOVT for each entry */ 2u * pc_relative_dex_cache_patches_.size() +
/* MOVW+MOVT for each entry */ 2u * pc_relative_method_patches_.size() +
+ /* MOVW+MOVT for each entry */ 2u * method_bss_entry_patches_.size() +
/* MOVW+MOVT for each entry */ 2u * pc_relative_type_patches_.size() +
/* MOVW+MOVT for each entry */ 2u * type_bss_entry_patches_.size() +
/* MOVW+MOVT for each entry */ 2u * pc_relative_string_patches_.size() +
baker_read_barrier_patches_.size();
linker_patches->reserve(size);
- EmitPcRelativeLinkerPatches<LinkerPatch::DexCacheArrayPatch>(pc_relative_dex_cache_patches_,
- linker_patches);
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<LinkerPatch::RelativeMethodPatch>(pc_relative_method_patches_,
linker_patches);
@@ -9156,6 +9152,8 @@
EmitPcRelativeLinkerPatches<LinkerPatch::StringBssEntryPatch>(pc_relative_string_patches_,
linker_patches);
}
+ EmitPcRelativeLinkerPatches<LinkerPatch::MethodBssEntryPatch>(method_bss_entry_patches_,
+ linker_patches);
EmitPcRelativeLinkerPatches<LinkerPatch::TypeBssEntryPatch>(type_bss_entry_patches_,
linker_patches);
for (const BakerReadBarrierPatchInfo& info : baker_read_barrier_patches_) {
@@ -9292,23 +9290,6 @@
}
}
-void LocationsBuilderARM::VisitArmDexCacheArraysBase(HArmDexCacheArraysBase* base) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(base);
- locations->SetOut(Location::RequiresRegister());
-}
-
-void InstructionCodeGeneratorARM::VisitArmDexCacheArraysBase(HArmDexCacheArraysBase* base) {
- Register base_reg = base->GetLocations()->Out().AsRegister<Register>();
- CodeGeneratorARM::PcRelativePatchInfo* labels =
- codegen_->NewPcRelativeDexCacheArrayPatch(base->GetDexFile(), base->GetElementOffset());
- __ BindTrackedLabel(&labels->movw_label);
- __ movw(base_reg, /* placeholder */ 0u);
- __ BindTrackedLabel(&labels->movt_label);
- __ movt(base_reg, /* placeholder */ 0u);
- __ BindTrackedLabel(&labels->add_pc_label);
- __ add(base_reg, base_reg, ShifterOperand(PC));
-}
-
void CodeGeneratorARM::MoveFromReturnRegister(Location trg, Primitive::Type type) {
if (!trg.IsValid()) {
DCHECK_EQ(type, Primitive::kPrimVoid);
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index 398b6ed..9280e63 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -483,12 +483,11 @@
};
PcRelativePatchInfo* NewPcRelativeMethodPatch(MethodReference target_method);
+ PcRelativePatchInfo* NewMethodBssEntryPatch(MethodReference target_method);
PcRelativePatchInfo* NewPcRelativeTypePatch(const DexFile& dex_file, dex::TypeIndex type_index);
PcRelativePatchInfo* NewTypeBssEntryPatch(const DexFile& dex_file, dex::TypeIndex type_index);
PcRelativePatchInfo* NewPcRelativeStringPatch(const DexFile& dex_file,
dex::StringIndex string_index);
- PcRelativePatchInfo* NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file,
- uint32_t element_offset);
// Add a new baker read barrier patch and return the label to be bound
// before the BNE instruction.
@@ -669,10 +668,10 @@
// Deduplication map for 32-bit literals, used for non-patchable boot image addresses.
Uint32ToLiteralMap uint32_literals_;
- // PC-relative patch info for each HArmDexCacheArraysBase.
- ArenaDeque<PcRelativePatchInfo> pc_relative_dex_cache_patches_;
// PC-relative method patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> pc_relative_method_patches_;
+ // PC-relative method patch info for kBssEntry.
+ ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> pc_relative_type_patches_;
// PC-relative type patch info for kBssEntry.
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index a84f8f3..9ba38e5 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -1448,8 +1448,8 @@
graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
uint64_literals_(std::less<uint64_t>(),
graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
- pc_relative_dex_cache_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
pc_relative_method_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
+ method_bss_entry_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
pc_relative_type_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
type_bss_entry_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
pc_relative_string_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
@@ -4526,15 +4526,14 @@
// Load method address from literal pool.
__ Ldr(XRegisterFrom(temp), DeduplicateUint64Literal(invoke->GetMethodAddress()));
break;
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative: {
+ case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry: {
// Add ADRP with its PC-relative DexCache access patch.
- const DexFile& dex_file = invoke->GetDexFileForPcRelativeDexCache();
- uint32_t element_offset = invoke->GetDexCacheArrayOffset();
- vixl::aarch64::Label* adrp_label = NewPcRelativeDexCacheArrayPatch(dex_file, element_offset);
+ MethodReference target_method(&GetGraph()->GetDexFile(), invoke->GetDexMethodIndex());
+ vixl::aarch64::Label* adrp_label = NewMethodBssEntryPatch(target_method);
EmitAdrpPlaceholder(adrp_label, XRegisterFrom(temp));
// Add LDR with its PC-relative DexCache access patch.
vixl::aarch64::Label* ldr_label =
- NewPcRelativeDexCacheArrayPatch(dex_file, element_offset, adrp_label);
+ NewMethodBssEntryPatch(target_method, adrp_label);
EmitLdrOffsetPlaceholder(ldr_label, XRegisterFrom(temp), XRegisterFrom(temp));
break;
}
@@ -4635,6 +4634,15 @@
&pc_relative_method_patches_);
}
+vixl::aarch64::Label* CodeGeneratorARM64::NewMethodBssEntryPatch(
+ MethodReference target_method,
+ vixl::aarch64::Label* adrp_label) {
+ return NewPcRelativePatch(*target_method.dex_file,
+ target_method.dex_method_index,
+ adrp_label,
+ &method_bss_entry_patches_);
+}
+
vixl::aarch64::Label* CodeGeneratorARM64::NewPcRelativeTypePatch(
const DexFile& dex_file,
dex::TypeIndex type_index,
@@ -4657,13 +4665,6 @@
NewPcRelativePatch(dex_file, string_index.index_, adrp_label, &pc_relative_string_patches_);
}
-vixl::aarch64::Label* CodeGeneratorARM64::NewPcRelativeDexCacheArrayPatch(
- const DexFile& dex_file,
- uint32_t element_offset,
- vixl::aarch64::Label* adrp_label) {
- return NewPcRelativePatch(dex_file, element_offset, adrp_label, &pc_relative_dex_cache_patches_);
-}
-
vixl::aarch64::Label* CodeGeneratorARM64::NewBakerReadBarrierPatch(uint32_t custom_data) {
baker_read_barrier_patches_.emplace_back(custom_data);
return &baker_read_barrier_patches_.back().label;
@@ -4685,7 +4686,7 @@
vixl::aarch64::Literal<uint32_t>* CodeGeneratorARM64::DeduplicateBootImageAddressLiteral(
uint64_t address) {
- return DeduplicateUint32Literal(dchecked_integral_cast<uint32_t>(address), &uint32_literals_);
+ return DeduplicateUint32Literal(dchecked_integral_cast<uint32_t>(address));
}
vixl::aarch64::Literal<uint32_t>* CodeGeneratorARM64::DeduplicateJitStringLiteral(
@@ -4748,19 +4749,13 @@
void CodeGeneratorARM64::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) {
DCHECK(linker_patches->empty());
size_t size =
- pc_relative_dex_cache_patches_.size() +
pc_relative_method_patches_.size() +
+ method_bss_entry_patches_.size() +
pc_relative_type_patches_.size() +
type_bss_entry_patches_.size() +
pc_relative_string_patches_.size() +
baker_read_barrier_patches_.size();
linker_patches->reserve(size);
- for (const PcRelativePatchInfo& info : pc_relative_dex_cache_patches_) {
- linker_patches->push_back(LinkerPatch::DexCacheArrayPatch(info.label.GetLocation(),
- &info.target_dex_file,
- info.pc_insn_label->GetLocation(),
- info.offset_or_index));
- }
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<LinkerPatch::RelativeMethodPatch>(pc_relative_method_patches_,
linker_patches);
@@ -4774,6 +4769,8 @@
EmitPcRelativeLinkerPatches<LinkerPatch::StringBssEntryPatch>(pc_relative_string_patches_,
linker_patches);
}
+ EmitPcRelativeLinkerPatches<LinkerPatch::MethodBssEntryPatch>(method_bss_entry_patches_,
+ linker_patches);
EmitPcRelativeLinkerPatches<LinkerPatch::TypeBssEntryPatch>(type_bss_entry_patches_,
linker_patches);
for (const BakerReadBarrierPatchInfo& info : baker_read_barrier_patches_) {
@@ -4783,9 +4780,8 @@
DCHECK_EQ(size, linker_patches->size());
}
-vixl::aarch64::Literal<uint32_t>* CodeGeneratorARM64::DeduplicateUint32Literal(uint32_t value,
- Uint32ToLiteralMap* map) {
- return map->GetOrCreate(
+vixl::aarch64::Literal<uint32_t>* CodeGeneratorARM64::DeduplicateUint32Literal(uint32_t value) {
+ return uint32_literals_.GetOrCreate(
value,
[this, value]() { return __ CreateLiteralDestroyedWithPool<uint32_t>(value); });
}
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index 5bb2ab5..d9c49d1 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -557,6 +557,13 @@
vixl::aarch64::Label* NewPcRelativeMethodPatch(MethodReference target_method,
vixl::aarch64::Label* adrp_label = nullptr);
+ // Add a new .bss entry method patch for an instruction and return
+ // the label to be bound before the instruction. The instruction will be
+ // either the ADRP (pass `adrp_label = null`) or the LDR (pass `adrp_label`
+ // pointing to the associated ADRP patch label).
+ vixl::aarch64::Label* NewMethodBssEntryPatch(MethodReference target_method,
+ vixl::aarch64::Label* adrp_label = nullptr);
+
// Add a new PC-relative type patch for an instruction and return the label
// to be bound before the instruction. The instruction will be either the
// ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing
@@ -581,15 +588,6 @@
dex::StringIndex string_index,
vixl::aarch64::Label* adrp_label = nullptr);
- // Add a new PC-relative dex cache array patch for an instruction and return
- // the label to be bound before the instruction. The instruction will be
- // either the ADRP (pass `adrp_label = null`) or the LDR (pass `adrp_label`
- // pointing to the associated ADRP patch label).
- vixl::aarch64::Label* NewPcRelativeDexCacheArrayPatch(
- const DexFile& dex_file,
- uint32_t element_offset,
- vixl::aarch64::Label* adrp_label = nullptr);
-
// Add a new baker read barrier patch and return the label to be bound
// before the CBNZ instruction.
vixl::aarch64::Label* NewBakerReadBarrierPatch(uint32_t custom_data);
@@ -741,8 +739,7 @@
vixl::aarch64::Literal<uint32_t>*,
TypeReferenceValueComparator>;
- vixl::aarch64::Literal<uint32_t>* DeduplicateUint32Literal(uint32_t value,
- Uint32ToLiteralMap* map);
+ vixl::aarch64::Literal<uint32_t>* DeduplicateUint32Literal(uint32_t value);
vixl::aarch64::Literal<uint64_t>* DeduplicateUint64Literal(uint64_t value);
// The PcRelativePatchInfo is used for PC-relative addressing of dex cache arrays
@@ -793,10 +790,10 @@
Uint32ToLiteralMap uint32_literals_;
// Deduplication map for 64-bit literals, used for non-patchable method address or method code.
Uint64ToLiteralMap uint64_literals_;
- // PC-relative DexCache access info.
- ArenaDeque<PcRelativePatchInfo> pc_relative_dex_cache_patches_;
// PC-relative method patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> pc_relative_method_patches_;
+ // PC-relative method patch info for kBssEntry.
+ ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> pc_relative_type_patches_;
// PC-relative type patch info for kBssEntry.
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index d5e3723..9cd7761 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -2499,8 +2499,8 @@
isa_features_(isa_features),
uint32_literals_(std::less<uint32_t>(),
graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
- pc_relative_dex_cache_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
pc_relative_method_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
+ method_bss_entry_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
pc_relative_type_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
type_bss_entry_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
pc_relative_string_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
@@ -3642,18 +3642,10 @@
IntrinsicLocationsBuilderARMVIXL intrinsic(codegen_);
if (intrinsic.TryDispatch(invoke)) {
- if (invoke->GetLocations()->CanCall() && invoke->HasPcRelativeDexCache()) {
- invoke->GetLocations()->SetInAt(invoke->GetSpecialInputIndex(), Location::Any());
- }
return;
}
HandleInvoke(invoke);
-
- // For PC-relative dex cache the invoke has an extra input, the PC-relative address base.
- if (invoke->HasPcRelativeDexCache()) {
- invoke->GetLocations()->SetInAt(invoke->GetSpecialInputIndex(), Location::RequiresRegister());
- }
}
static bool TryGenerateIntrinsicCode(HInvoke* invoke, CodeGeneratorARMVIXL* codegen) {
@@ -9140,12 +9132,12 @@
case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
__ Mov(RegisterFrom(temp), Operand::From(invoke->GetMethodAddress()));
break;
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative: {
- HArmDexCacheArraysBase* base =
- invoke->InputAt(invoke->GetSpecialInputIndex())->AsArmDexCacheArraysBase();
- vixl32::Register base_reg = GetInvokeStaticOrDirectExtraParameter(invoke, RegisterFrom(temp));
- int32_t offset = invoke->GetDexCacheArrayOffset() - base->GetElementOffset();
- GetAssembler()->LoadFromOffset(kLoadWord, RegisterFrom(temp), base_reg, offset);
+ case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry: {
+ PcRelativePatchInfo* labels = NewMethodBssEntryPatch(
+ MethodReference(&GetGraph()->GetDexFile(), invoke->GetDexMethodIndex()));
+ vixl32::Register temp_reg = RegisterFrom(temp);
+ EmitMovwMovtPlaceholder(labels, temp_reg);
+ GetAssembler()->LoadFromOffset(kLoadWord, temp_reg, temp_reg, /* offset*/ 0);
break;
}
case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
@@ -9244,6 +9236,13 @@
&pc_relative_method_patches_);
}
+CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewMethodBssEntryPatch(
+ MethodReference target_method) {
+ return NewPcRelativePatch(*target_method.dex_file,
+ target_method.dex_method_index,
+ &method_bss_entry_patches_);
+}
+
CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewPcRelativeTypePatch(
const DexFile& dex_file, dex::TypeIndex type_index) {
return NewPcRelativePatch(dex_file, type_index.index_, &pc_relative_type_patches_);
@@ -9259,11 +9258,6 @@
return NewPcRelativePatch(dex_file, string_index.index_, &pc_relative_string_patches_);
}
-CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewPcRelativeDexCacheArrayPatch(
- const DexFile& dex_file, uint32_t element_offset) {
- return NewPcRelativePatch(dex_file, element_offset, &pc_relative_dex_cache_patches_);
-}
-
CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewPcRelativePatch(
const DexFile& dex_file, uint32_t offset_or_index, ArenaDeque<PcRelativePatchInfo>* patches) {
patches->emplace_back(dex_file, offset_or_index);
@@ -9327,15 +9321,13 @@
void CodeGeneratorARMVIXL::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) {
DCHECK(linker_patches->empty());
size_t size =
- /* MOVW+MOVT for each entry */ 2u * pc_relative_dex_cache_patches_.size() +
/* MOVW+MOVT for each entry */ 2u * pc_relative_method_patches_.size() +
+ /* MOVW+MOVT for each entry */ 2u * method_bss_entry_patches_.size() +
/* MOVW+MOVT for each entry */ 2u * pc_relative_type_patches_.size() +
/* MOVW+MOVT for each entry */ 2u * type_bss_entry_patches_.size() +
/* MOVW+MOVT for each entry */ 2u * pc_relative_string_patches_.size() +
baker_read_barrier_patches_.size();
linker_patches->reserve(size);
- EmitPcRelativeLinkerPatches<LinkerPatch::DexCacheArrayPatch>(pc_relative_dex_cache_patches_,
- linker_patches);
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<LinkerPatch::RelativeMethodPatch>(pc_relative_method_patches_,
linker_patches);
@@ -9349,6 +9341,8 @@
EmitPcRelativeLinkerPatches<LinkerPatch::StringBssEntryPatch>(pc_relative_string_patches_,
linker_patches);
}
+ EmitPcRelativeLinkerPatches<LinkerPatch::MethodBssEntryPatch>(method_bss_entry_patches_,
+ linker_patches);
EmitPcRelativeLinkerPatches<LinkerPatch::TypeBssEntryPatch>(type_bss_entry_patches_,
linker_patches);
for (const BakerReadBarrierPatchInfo& info : baker_read_barrier_patches_) {
@@ -9498,17 +9492,6 @@
}
}
}
-void LocationsBuilderARMVIXL::VisitArmDexCacheArraysBase(HArmDexCacheArraysBase* base) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(base);
- locations->SetOut(Location::RequiresRegister());
-}
-
-void InstructionCodeGeneratorARMVIXL::VisitArmDexCacheArraysBase(HArmDexCacheArraysBase* base) {
- vixl32::Register base_reg = OutputRegister(base);
- CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
- codegen_->NewPcRelativeDexCacheArrayPatch(base->GetDexFile(), base->GetElementOffset());
- codegen_->EmitMovwMovtPlaceholder(labels, base_reg);
-}
// Copy the result of a call into the given target.
void CodeGeneratorARMVIXL::MoveFromReturnRegister(Location trg, Primitive::Type type) {
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index 5320f71..805a3f4 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -566,12 +566,11 @@
};
PcRelativePatchInfo* NewPcRelativeMethodPatch(MethodReference target_method);
+ PcRelativePatchInfo* NewMethodBssEntryPatch(MethodReference target_method);
PcRelativePatchInfo* NewPcRelativeTypePatch(const DexFile& dex_file, dex::TypeIndex type_index);
PcRelativePatchInfo* NewTypeBssEntryPatch(const DexFile& dex_file, dex::TypeIndex type_index);
PcRelativePatchInfo* NewPcRelativeStringPatch(const DexFile& dex_file,
dex::StringIndex string_index);
- PcRelativePatchInfo* NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file,
- uint32_t element_offset);
// Add a new baker read barrier patch and return the label to be bound
// before the BNE instruction.
@@ -766,10 +765,10 @@
// Deduplication map for 32-bit literals, used for non-patchable boot image addresses.
Uint32ToLiteralMap uint32_literals_;
- // PC-relative patch info for each HArmDexCacheArraysBase.
- ArenaDeque<PcRelativePatchInfo> pc_relative_dex_cache_patches_;
// PC-relative method patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> pc_relative_method_patches_;
+ // PC-relative method patch info for kBssEntry.
+ ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> pc_relative_type_patches_;
// PC-relative type patch info for kBssEntry.
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 8560e3e..b39d412 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -40,10 +40,6 @@
static constexpr int kCurrentMethodStackOffset = 0;
static constexpr Register kMethodRegisterArgument = A0;
-// We'll maximize the range of a single load instruction for dex cache array accesses
-// by aligning offset -32768 with the offset of the first used element.
-static constexpr uint32_t kDexCacheArrayLwOffset = 0x8000;
-
Location MipsReturnLocation(Primitive::Type return_type) {
switch (return_type) {
case Primitive::kPrimBoolean:
@@ -1060,8 +1056,8 @@
isa_features_(isa_features),
uint32_literals_(std::less<uint32_t>(),
graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
- pc_relative_dex_cache_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
pc_relative_method_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
+ method_bss_entry_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
pc_relative_type_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
type_bss_entry_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
pc_relative_string_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
@@ -1602,14 +1598,12 @@
void CodeGeneratorMIPS::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) {
DCHECK(linker_patches->empty());
size_t size =
- pc_relative_dex_cache_patches_.size() +
pc_relative_method_patches_.size() +
+ method_bss_entry_patches_.size() +
pc_relative_type_patches_.size() +
type_bss_entry_patches_.size() +
pc_relative_string_patches_.size();
linker_patches->reserve(size);
- EmitPcRelativeLinkerPatches<LinkerPatch::DexCacheArrayPatch>(pc_relative_dex_cache_patches_,
- linker_patches);
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<LinkerPatch::RelativeMethodPatch>(pc_relative_method_patches_,
linker_patches);
@@ -1623,6 +1617,8 @@
EmitPcRelativeLinkerPatches<LinkerPatch::StringBssEntryPatch>(pc_relative_string_patches_,
linker_patches);
}
+ EmitPcRelativeLinkerPatches<LinkerPatch::MethodBssEntryPatch>(method_bss_entry_patches_,
+ linker_patches);
EmitPcRelativeLinkerPatches<LinkerPatch::TypeBssEntryPatch>(type_bss_entry_patches_,
linker_patches);
DCHECK_EQ(size, linker_patches->size());
@@ -1635,6 +1631,13 @@
&pc_relative_method_patches_);
}
+CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewMethodBssEntryPatch(
+ MethodReference target_method) {
+ return NewPcRelativePatch(*target_method.dex_file,
+ target_method.dex_method_index,
+ &method_bss_entry_patches_);
+}
+
CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewPcRelativeTypePatch(
const DexFile& dex_file, dex::TypeIndex type_index) {
return NewPcRelativePatch(dex_file, type_index.index_, &pc_relative_type_patches_);
@@ -1650,11 +1653,6 @@
return NewPcRelativePatch(dex_file, string_index.index_, &pc_relative_string_patches_);
}
-CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewPcRelativeDexCacheArrayPatch(
- const DexFile& dex_file, uint32_t element_offset) {
- return NewPcRelativePatch(dex_file, element_offset, &pc_relative_dex_cache_patches_);
-}
-
CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewPcRelativePatch(
const DexFile& dex_file, uint32_t offset_or_index, ArenaDeque<PcRelativePatchInfo>* patches) {
patches->emplace_back(dex_file, offset_or_index);
@@ -7000,7 +6998,7 @@
HLoadString::LoadKind desired_string_load_kind) {
// We disable PC-relative load on pre-R6 when there is an irreducible loop, as the optimization
// is incompatible with it.
- // TODO: Create as many MipsDexCacheArraysBase instructions as needed for methods
+ // TODO: Create as many HMipsComputeBaseMethodAddress instructions as needed for methods
// with irreducible loops.
bool has_irreducible_loops = GetGraph()->HasIrreducibleLoops();
bool is_r6 = GetInstructionSetFeatures().IsR6();
@@ -7030,6 +7028,8 @@
HLoadClass::LoadKind desired_class_load_kind) {
// We disable PC-relative load on pre-R6 when there is an irreducible loop, as the optimization
// is incompatible with it.
+ // TODO: Create as many HMipsComputeBaseMethodAddress instructions as needed for methods
+ // with irreducible loops.
bool has_irreducible_loops = GetGraph()->HasIrreducibleLoops();
bool is_r6 = GetInstructionSetFeatures().IsR6();
bool fallback_load = has_irreducible_loops && !is_r6;
@@ -7093,12 +7093,14 @@
HInvokeStaticOrDirect::DispatchInfo dispatch_info = desired_dispatch_info;
// We disable PC-relative load on pre-R6 when there is an irreducible loop, as the optimization
// is incompatible with it.
+ // TODO: Create as many HMipsComputeBaseMethodAddress instructions as needed for methods
+ // with irreducible loops.
bool has_irreducible_loops = GetGraph()->HasIrreducibleLoops();
bool is_r6 = GetInstructionSetFeatures().IsR6();
bool fallback_load = has_irreducible_loops && !is_r6;
switch (dispatch_info.method_load_kind) {
case HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative:
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative:
+ case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry:
break;
default:
fallback_load = false;
@@ -7149,23 +7151,16 @@
case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
__ LoadConst32(temp.AsRegister<Register>(), invoke->GetMethodAddress());
break;
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative:
- if (is_r6) {
- uint32_t offset = invoke->GetDexCacheArrayOffset();
- CodeGeneratorMIPS::PcRelativePatchInfo* info =
- NewPcRelativeDexCacheArrayPatch(invoke->GetDexFileForPcRelativeDexCache(), offset);
- bool reordering = __ SetReorder(false);
- EmitPcRelativeAddressPlaceholderHigh(info, TMP, ZERO);
- __ Lw(temp.AsRegister<Register>(), TMP, /* placeholder */ 0x5678);
- __ SetReorder(reordering);
- } else {
- HMipsDexCacheArraysBase* base =
- invoke->InputAt(invoke->GetSpecialInputIndex())->AsMipsDexCacheArraysBase();
- int32_t offset =
- invoke->GetDexCacheArrayOffset() - base->GetElementOffset() - kDexCacheArrayLwOffset;
- __ LoadFromOffset(kLoadWord, temp.AsRegister<Register>(), base_reg, offset);
- }
+ case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry: {
+ PcRelativePatchInfo* info = NewMethodBssEntryPatch(
+ MethodReference(&GetGraph()->GetDexFile(), invoke->GetDexMethodIndex()));
+ Register temp_reg = temp.AsRegister<Register>();
+ bool reordering = __ SetReorder(false);
+ EmitPcRelativeAddressPlaceholderHigh(info, TMP, base_reg);
+ __ Lw(temp_reg, TMP, /* placeholder */ 0x5678);
+ __ SetReorder(reordering);
break;
+ }
case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
return; // No code pointer retrieval; the runtime performs the call directly.
@@ -8711,29 +8706,11 @@
__ Nal();
// Grab the return address off RA.
__ Move(reg, RA);
- // TODO: Can we share this code with that of VisitMipsDexCacheArraysBase()?
// Remember this offset (the obtained PC value) for later use with constant area.
__ BindPcRelBaseLabel();
}
-void LocationsBuilderMIPS::VisitMipsDexCacheArraysBase(HMipsDexCacheArraysBase* base) {
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(base);
- locations->SetOut(Location::RequiresRegister());
-}
-
-void InstructionCodeGeneratorMIPS::VisitMipsDexCacheArraysBase(HMipsDexCacheArraysBase* base) {
- Register reg = base->GetLocations()->Out().AsRegister<Register>();
- CodeGeneratorMIPS::PcRelativePatchInfo* info =
- codegen_->NewPcRelativeDexCacheArrayPatch(base->GetDexFile(), base->GetElementOffset());
- CHECK(!codegen_->GetInstructionSetFeatures().IsR6());
- bool reordering = __ SetReorder(false);
- // TODO: Reuse MipsComputeBaseMethodAddress on R2 instead of passing ZERO to force emitting NAL.
- codegen_->EmitPcRelativeAddressPlaceholderHigh(info, reg, ZERO);
- __ Addiu(reg, reg, /* placeholder */ 0x5678);
- __ SetReorder(reordering);
-}
-
void LocationsBuilderMIPS::VisitInvokeUnresolved(HInvokeUnresolved* invoke) {
// The trampoline uses the same calling convention as dex calling conventions,
// except instead of loading arg0/r0 with the target Method*, arg0/r0 will contain
diff --git a/compiler/optimizing/code_generator_mips.h b/compiler/optimizing/code_generator_mips.h
index d774219..e72e838d 100644
--- a/compiler/optimizing/code_generator_mips.h
+++ b/compiler/optimizing/code_generator_mips.h
@@ -585,12 +585,11 @@
};
PcRelativePatchInfo* NewPcRelativeMethodPatch(MethodReference target_method);
+ PcRelativePatchInfo* NewMethodBssEntryPatch(MethodReference target_method);
PcRelativePatchInfo* NewPcRelativeTypePatch(const DexFile& dex_file, dex::TypeIndex type_index);
PcRelativePatchInfo* NewTypeBssEntryPatch(const DexFile& dex_file, dex::TypeIndex type_index);
PcRelativePatchInfo* NewPcRelativeStringPatch(const DexFile& dex_file,
dex::StringIndex string_index);
- PcRelativePatchInfo* NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file,
- uint32_t element_offset);
Literal* DeduplicateBootImageAddressLiteral(uint32_t address);
void EmitPcRelativeAddressPlaceholderHigh(PcRelativePatchInfo* info, Register out, Register base);
@@ -645,10 +644,10 @@
// Deduplication map for 32-bit literals, used for non-patchable boot image addresses.
Uint32ToLiteralMap uint32_literals_;
- // PC-relative patch info for each HMipsDexCacheArraysBase.
- ArenaDeque<PcRelativePatchInfo> pc_relative_dex_cache_patches_;
// PC-relative method patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> pc_relative_method_patches_;
+ // PC-relative method patch info for kBssEntry.
+ ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> pc_relative_type_patches_;
// PC-relative type patch info for kBssEntry.
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index da43c4e..e4f1cbd 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -957,8 +957,8 @@
graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
uint64_literals_(std::less<uint64_t>(),
graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
- pc_relative_dex_cache_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
pc_relative_method_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
+ method_bss_entry_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
pc_relative_type_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
type_bss_entry_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
pc_relative_string_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
@@ -1440,14 +1440,12 @@
void CodeGeneratorMIPS64::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) {
DCHECK(linker_patches->empty());
size_t size =
- pc_relative_dex_cache_patches_.size() +
pc_relative_method_patches_.size() +
+ method_bss_entry_patches_.size() +
pc_relative_type_patches_.size() +
type_bss_entry_patches_.size() +
pc_relative_string_patches_.size();
linker_patches->reserve(size);
- EmitPcRelativeLinkerPatches<LinkerPatch::DexCacheArrayPatch>(pc_relative_dex_cache_patches_,
- linker_patches);
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<LinkerPatch::RelativeMethodPatch>(pc_relative_method_patches_,
linker_patches);
@@ -1461,6 +1459,8 @@
EmitPcRelativeLinkerPatches<LinkerPatch::StringBssEntryPatch>(pc_relative_string_patches_,
linker_patches);
}
+ EmitPcRelativeLinkerPatches<LinkerPatch::MethodBssEntryPatch>(method_bss_entry_patches_,
+ linker_patches);
EmitPcRelativeLinkerPatches<LinkerPatch::TypeBssEntryPatch>(type_bss_entry_patches_,
linker_patches);
DCHECK_EQ(size, linker_patches->size());
@@ -1473,6 +1473,13 @@
&pc_relative_method_patches_);
}
+CodeGeneratorMIPS64::PcRelativePatchInfo* CodeGeneratorMIPS64::NewMethodBssEntryPatch(
+ MethodReference target_method) {
+ return NewPcRelativePatch(*target_method.dex_file,
+ target_method.dex_method_index,
+ &method_bss_entry_patches_);
+}
+
CodeGeneratorMIPS64::PcRelativePatchInfo* CodeGeneratorMIPS64::NewPcRelativeTypePatch(
const DexFile& dex_file, dex::TypeIndex type_index) {
return NewPcRelativePatch(dex_file, type_index.index_, &pc_relative_type_patches_);
@@ -1488,11 +1495,6 @@
return NewPcRelativePatch(dex_file, string_index.index_, &pc_relative_string_patches_);
}
-CodeGeneratorMIPS64::PcRelativePatchInfo* CodeGeneratorMIPS64::NewPcRelativeDexCacheArrayPatch(
- const DexFile& dex_file, uint32_t element_offset) {
- return NewPcRelativePatch(dex_file, element_offset, &pc_relative_dex_cache_patches_);
-}
-
CodeGeneratorMIPS64::PcRelativePatchInfo* CodeGeneratorMIPS64::NewPcRelativePatch(
const DexFile& dex_file, uint32_t offset_or_index, ArenaDeque<PcRelativePatchInfo>* patches) {
patches->emplace_back(dex_file, offset_or_index);
@@ -4949,10 +4951,9 @@
kLoadDoubleword,
DeduplicateUint64Literal(invoke->GetMethodAddress()));
break;
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative: {
- uint32_t offset = invoke->GetDexCacheArrayOffset();
- CodeGeneratorMIPS64::PcRelativePatchInfo* info =
- NewPcRelativeDexCacheArrayPatch(invoke->GetDexFileForPcRelativeDexCache(), offset);
+ case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry: {
+ PcRelativePatchInfo* info = NewMethodBssEntryPatch(
+ MethodReference(&GetGraph()->GetDexFile(), invoke->GetDexMethodIndex()));
EmitPcRelativeAddressPlaceholderHigh(info, AT);
__ Ld(temp.AsRegister<GpuRegister>(), AT, /* placeholder */ 0x5678);
break;
diff --git a/compiler/optimizing/code_generator_mips64.h b/compiler/optimizing/code_generator_mips64.h
index 2e8af21..6260c73 100644
--- a/compiler/optimizing/code_generator_mips64.h
+++ b/compiler/optimizing/code_generator_mips64.h
@@ -551,12 +551,11 @@
};
PcRelativePatchInfo* NewPcRelativeMethodPatch(MethodReference target_method);
+ PcRelativePatchInfo* NewMethodBssEntryPatch(MethodReference target_method);
PcRelativePatchInfo* NewPcRelativeTypePatch(const DexFile& dex_file, dex::TypeIndex type_index);
PcRelativePatchInfo* NewTypeBssEntryPatch(const DexFile& dex_file, dex::TypeIndex type_index);
PcRelativePatchInfo* NewPcRelativeStringPatch(const DexFile& dex_file,
dex::StringIndex string_index);
- PcRelativePatchInfo* NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file,
- uint32_t element_offset);
PcRelativePatchInfo* NewPcRelativeCallPatch(const DexFile& dex_file,
uint32_t method_index);
Literal* DeduplicateBootImageAddressLiteral(uint64_t address);
@@ -609,10 +608,10 @@
// Deduplication map for 64-bit literals, used for non-patchable method address or method code
// address.
Uint64ToLiteralMap uint64_literals_;
- // PC-relative patch info.
- ArenaDeque<PcRelativePatchInfo> pc_relative_dex_cache_patches_;
// PC-relative method patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> pc_relative_method_patches_;
+ // PC-relative method patch info for kBssEntry.
+ ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PcRelativePatchInfo> pc_relative_type_patches_;
// PC-relative type patch info for kBssEntry.
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index ca921b8..83a261d 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1032,8 +1032,8 @@
move_resolver_(graph->GetArena(), this),
assembler_(graph->GetArena()),
isa_features_(isa_features),
- pc_relative_dex_cache_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
boot_image_method_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
+ method_bss_entry_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
boot_image_type_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
type_bss_entry_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
string_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
@@ -4553,16 +4553,14 @@
case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
__ movl(temp.AsRegister<Register>(), Immediate(invoke->GetMethodAddress()));
break;
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative: {
+ case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry: {
Register base_reg = GetInvokeStaticOrDirectExtraParameter(invoke,
temp.AsRegister<Register>());
__ movl(temp.AsRegister<Register>(), Address(base_reg, kDummy32BitOffset));
// Bind a new fixup label at the end of the "movl" insn.
- uint32_t offset = invoke->GetDexCacheArrayOffset();
- __ Bind(NewPcRelativeDexCacheArrayPatch(
+ __ Bind(NewMethodBssEntryPatch(
invoke->InputAt(invoke->GetSpecialInputIndex())->AsX86ComputeBaseMethodAddress(),
- invoke->GetDexFileForPcRelativeDexCache(),
- offset));
+ MethodReference(&GetGraph()->GetDexFile(), invoke->GetDexMethodIndex())));
break;
}
case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
@@ -4629,6 +4627,16 @@
__ Bind(&boot_image_method_patches_.back().label);
}
+Label* CodeGeneratorX86::NewMethodBssEntryPatch(
+ HX86ComputeBaseMethodAddress* method_address,
+ MethodReference target_method) {
+ // Add the patch entry and bind its label at the end of the instruction.
+ method_bss_entry_patches_.emplace_back(method_address,
+ *target_method.dex_file,
+ target_method.dex_method_index);
+ return &method_bss_entry_patches_.back().label;
+}
+
void CodeGeneratorX86::RecordBootTypePatch(HLoadClass* load_class) {
HX86ComputeBaseMethodAddress* address = load_class->InputAt(0)->AsX86ComputeBaseMethodAddress();
boot_image_type_patches_.emplace_back(address,
@@ -4663,15 +4671,6 @@
return &string_patches_.back().label;
}
-Label* CodeGeneratorX86::NewPcRelativeDexCacheArrayPatch(
- HX86ComputeBaseMethodAddress* method_address,
- const DexFile& dex_file,
- uint32_t element_offset) {
- // Add the patch entry and bind its label at the end of the instruction.
- pc_relative_dex_cache_patches_.emplace_back(method_address, dex_file, element_offset);
- return &pc_relative_dex_cache_patches_.back().label;
-}
-
// The label points to the end of the "movl" or another instruction but the literal offset
// for method patch needs to point to the embedded constant which occupies the last 4 bytes.
constexpr uint32_t kLabelPositionToLiteralOffsetAdjustment = 4u;
@@ -4690,14 +4689,12 @@
void CodeGeneratorX86::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) {
DCHECK(linker_patches->empty());
size_t size =
- pc_relative_dex_cache_patches_.size() +
boot_image_method_patches_.size() +
+ method_bss_entry_patches_.size() +
boot_image_type_patches_.size() +
type_bss_entry_patches_.size() +
string_patches_.size();
linker_patches->reserve(size);
- EmitPcRelativeLinkerPatches<LinkerPatch::DexCacheArrayPatch>(pc_relative_dex_cache_patches_,
- linker_patches);
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<LinkerPatch::RelativeMethodPatch>(boot_image_method_patches_,
linker_patches);
@@ -4709,6 +4706,8 @@
DCHECK(boot_image_type_patches_.empty());
EmitPcRelativeLinkerPatches<LinkerPatch::StringBssEntryPatch>(string_patches_, linker_patches);
}
+ EmitPcRelativeLinkerPatches<LinkerPatch::MethodBssEntryPatch>(method_bss_entry_patches_,
+ linker_patches);
EmitPcRelativeLinkerPatches<LinkerPatch::TypeBssEntryPatch>(type_bss_entry_patches_,
linker_patches);
DCHECK_EQ(size, linker_patches->size());
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 689f93e..f48753b 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -415,13 +415,12 @@
HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
void RecordBootMethodPatch(HInvokeStaticOrDirect* invoke);
+ Label* NewMethodBssEntryPatch(HX86ComputeBaseMethodAddress* method_address,
+ MethodReference target_method);
void RecordBootTypePatch(HLoadClass* load_class);
Label* NewTypeBssEntryPatch(HLoadClass* load_class);
void RecordBootStringPatch(HLoadString* load_string);
Label* NewStringBssEntryPatch(HLoadString* load_string);
- Label* NewPcRelativeDexCacheArrayPatch(HX86ComputeBaseMethodAddress* method_address,
- const DexFile& dex_file,
- uint32_t element_offset);
Label* NewJitRootStringPatch(const DexFile& dex_file,
dex::StringIndex dex_index,
Handle<mirror::String> handle);
@@ -633,10 +632,10 @@
X86Assembler assembler_;
const X86InstructionSetFeatures& isa_features_;
- // PC-relative DexCache access info.
- ArenaDeque<X86PcRelativePatchInfo> pc_relative_dex_cache_patches_;
// PC-relative method patch info for kBootImageLinkTimePcRelative.
ArenaDeque<X86PcRelativePatchInfo> boot_image_method_patches_;
+ // PC-relative method patch info for kBssEntry.
+ ArenaDeque<X86PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
ArenaDeque<X86PcRelativePatchInfo> boot_image_type_patches_;
// Type patch locations for kBssEntry.
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 148f551..7331a9e 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1002,12 +1002,12 @@
case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
Load64BitValue(temp.AsRegister<CpuRegister>(), invoke->GetMethodAddress());
break;
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative: {
+ case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry: {
__ movq(temp.AsRegister<CpuRegister>(),
Address::Absolute(kDummy32BitOffset, /* no_rip */ false));
// Bind a new fixup label at the end of the "movl" insn.
- uint32_t offset = invoke->GetDexCacheArrayOffset();
- __ Bind(NewPcRelativeDexCacheArrayPatch(invoke->GetDexFileForPcRelativeDexCache(), offset));
+ __ Bind(NewMethodBssEntryPatch(
+ MethodReference(&GetGraph()->GetDexFile(), invoke->GetDexMethodIndex())));
break;
}
case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
@@ -1071,6 +1071,12 @@
__ Bind(&boot_image_method_patches_.back().label);
}
+Label* CodeGeneratorX86_64::NewMethodBssEntryPatch(MethodReference target_method) {
+ // Add a patch entry and return the label.
+ method_bss_entry_patches_.emplace_back(*target_method.dex_file, target_method.dex_method_index);
+ return &method_bss_entry_patches_.back().label;
+}
+
void CodeGeneratorX86_64::RecordBootTypePatch(HLoadClass* load_class) {
boot_image_type_patches_.emplace_back(load_class->GetDexFile(),
load_class->GetTypeIndex().index_);
@@ -1094,13 +1100,6 @@
return &string_patches_.back().label;
}
-Label* CodeGeneratorX86_64::NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file,
- uint32_t element_offset) {
- // Add a patch entry and return the label.
- pc_relative_dex_cache_patches_.emplace_back(dex_file, element_offset);
- return &pc_relative_dex_cache_patches_.back().label;
-}
-
// The label points to the end of the "movl" or another instruction but the literal offset
// for method patch needs to point to the embedded constant which occupies the last 4 bytes.
constexpr uint32_t kLabelPositionToLiteralOffsetAdjustment = 4u;
@@ -1119,14 +1118,12 @@
void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) {
DCHECK(linker_patches->empty());
size_t size =
- pc_relative_dex_cache_patches_.size() +
boot_image_method_patches_.size() +
+ method_bss_entry_patches_.size() +
boot_image_type_patches_.size() +
type_bss_entry_patches_.size() +
string_patches_.size();
linker_patches->reserve(size);
- EmitPcRelativeLinkerPatches<LinkerPatch::DexCacheArrayPatch>(pc_relative_dex_cache_patches_,
- linker_patches);
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<LinkerPatch::RelativeMethodPatch>(boot_image_method_patches_,
linker_patches);
@@ -1138,6 +1135,8 @@
DCHECK(boot_image_type_patches_.empty());
EmitPcRelativeLinkerPatches<LinkerPatch::StringBssEntryPatch>(string_patches_, linker_patches);
}
+ EmitPcRelativeLinkerPatches<LinkerPatch::MethodBssEntryPatch>(method_bss_entry_patches_,
+ linker_patches);
EmitPcRelativeLinkerPatches<LinkerPatch::TypeBssEntryPatch>(type_bss_entry_patches_,
linker_patches);
DCHECK_EQ(size, linker_patches->size());
@@ -1226,8 +1225,8 @@
assembler_(graph->GetArena()),
isa_features_(isa_features),
constant_area_start_(0),
- pc_relative_dex_cache_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
boot_image_method_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
+ method_bss_entry_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
boot_image_type_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
type_bss_entry_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
string_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index 31debde..33c6429 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -410,11 +410,11 @@
HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
void RecordBootMethodPatch(HInvokeStaticOrDirect* invoke);
+ Label* NewMethodBssEntryPatch(MethodReference target_method);
void RecordBootTypePatch(HLoadClass* load_class);
Label* NewTypeBssEntryPatch(HLoadClass* load_class);
void RecordBootStringPatch(HLoadString* load_string);
Label* NewStringBssEntryPatch(HLoadString* load_string);
- Label* NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file, uint32_t element_offset);
Label* NewJitRootStringPatch(const DexFile& dex_file,
dex::StringIndex dex_index,
Handle<mirror::String> handle);
@@ -603,10 +603,10 @@
// Used for fixups to the constant area.
int constant_area_start_;
- // PC-relative DexCache access info.
- ArenaDeque<PatchInfo<Label>> pc_relative_dex_cache_patches_;
// PC-relative method patch info for kBootImageLinkTimePcRelative.
ArenaDeque<PatchInfo<Label>> boot_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_;
// Type patch locations for kBssEntry.
diff --git a/compiler/optimizing/dex_cache_array_fixups_arm.cc b/compiler/optimizing/dex_cache_array_fixups_arm.cc
deleted file mode 100644
index 0c832a5..0000000
--- a/compiler/optimizing/dex_cache_array_fixups_arm.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "dex_cache_array_fixups_arm.h"
-
-#include "base/arena_containers.h"
-#ifdef ART_USE_OLD_ARM_BACKEND
-#include "code_generator_arm.h"
-#include "intrinsics_arm.h"
-#else
-#include "code_generator_arm_vixl.h"
-#include "intrinsics_arm_vixl.h"
-#endif
-#include "utils/dex_cache_arrays_layout-inl.h"
-
-namespace art {
-namespace arm {
-#ifdef ART_USE_OLD_ARM_BACKEND
-typedef CodeGeneratorARM CodeGeneratorARMType;
-typedef IntrinsicLocationsBuilderARM IntrinsicLocationsBuilderARMType;
-#else
-typedef CodeGeneratorARMVIXL CodeGeneratorARMType;
-typedef IntrinsicLocationsBuilderARMVIXL IntrinsicLocationsBuilderARMType;
-#endif
-
-/**
- * Finds instructions that need the dex cache arrays base as an input.
- */
-class DexCacheArrayFixupsVisitor : public HGraphVisitor {
- public:
- DexCacheArrayFixupsVisitor(HGraph* graph, CodeGenerator* codegen)
- : HGraphVisitor(graph),
- codegen_(down_cast<CodeGeneratorARMType*>(codegen)),
- dex_cache_array_bases_(std::less<const DexFile*>(),
- // Attribute memory use to code generator.
- graph->GetArena()->Adapter(kArenaAllocCodeGenerator)) {}
-
- void MoveBasesIfNeeded() {
- for (const auto& entry : dex_cache_array_bases_) {
- // Bring the base closer to the first use (previously, it was in the
- // entry block) and relieve some pressure on the register allocator
- // while avoiding recalculation of the base in a loop.
- HArmDexCacheArraysBase* base = entry.second;
- base->MoveBeforeFirstUserAndOutOfLoops();
- }
- }
-
- private:
- void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE {
- // If this is an invoke with PC-relative access to the dex cache methods array,
- // we need to add the dex cache arrays base as the special input.
- if (invoke->HasPcRelativeDexCache() &&
- !IsCallFreeIntrinsic<IntrinsicLocationsBuilderARMType>(invoke, codegen_)) {
- HArmDexCacheArraysBase* base =
- GetOrCreateDexCacheArrayBase(invoke, invoke->GetDexFileForPcRelativeDexCache());
- // Update the element offset in base.
- DexCacheArraysLayout layout(kArmPointerSize, &invoke->GetDexFileForPcRelativeDexCache());
- base->UpdateElementOffset(layout.MethodOffset(invoke->GetDexMethodIndex()));
- // Add the special argument base to the method.
- DCHECK(!invoke->HasCurrentMethodInput());
- invoke->AddSpecialInput(base);
- }
- }
-
- HArmDexCacheArraysBase* GetOrCreateDexCacheArrayBase(HInstruction* cursor,
- const DexFile& dex_file) {
- if (GetGraph()->HasIrreducibleLoops()) {
- HArmDexCacheArraysBase* base = new (GetGraph()->GetArena()) HArmDexCacheArraysBase(dex_file);
- cursor->GetBlock()->InsertInstructionBefore(base, cursor);
- return base;
- } else {
- // Ensure we only initialize the pointer once for each dex file.
- auto lb = dex_cache_array_bases_.lower_bound(&dex_file);
- if (lb != dex_cache_array_bases_.end() &&
- !dex_cache_array_bases_.key_comp()(&dex_file, lb->first)) {
- return lb->second;
- }
-
- // Insert the base at the start of the entry block, move it to a better
- // position later in MoveBaseIfNeeded().
- HArmDexCacheArraysBase* base = new (GetGraph()->GetArena()) HArmDexCacheArraysBase(dex_file);
- HBasicBlock* entry_block = GetGraph()->GetEntryBlock();
- entry_block->InsertInstructionBefore(base, entry_block->GetFirstInstruction());
- dex_cache_array_bases_.PutBefore(lb, &dex_file, base);
- return base;
- }
- }
-
- CodeGeneratorARMType* codegen_;
-
- using DexCacheArraysBaseMap =
- ArenaSafeMap<const DexFile*, HArmDexCacheArraysBase*, std::less<const DexFile*>>;
- DexCacheArraysBaseMap dex_cache_array_bases_;
-};
-
-void DexCacheArrayFixups::Run() {
- DexCacheArrayFixupsVisitor visitor(graph_, codegen_);
- visitor.VisitInsertionOrder();
- visitor.MoveBasesIfNeeded();
-}
-
-} // namespace arm
-} // namespace art
diff --git a/compiler/optimizing/dex_cache_array_fixups_arm.h b/compiler/optimizing/dex_cache_array_fixups_arm.h
deleted file mode 100644
index 9d67a31..0000000
--- a/compiler/optimizing/dex_cache_array_fixups_arm.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_COMPILER_OPTIMIZING_DEX_CACHE_ARRAY_FIXUPS_ARM_H_
-#define ART_COMPILER_OPTIMIZING_DEX_CACHE_ARRAY_FIXUPS_ARM_H_
-
-#include "nodes.h"
-#include "optimization.h"
-
-namespace art {
-
-class CodeGenerator;
-
-namespace arm {
-
-class DexCacheArrayFixups : public HOptimization {
- public:
- DexCacheArrayFixups(HGraph* graph, CodeGenerator* codegen, OptimizingCompilerStats* stats)
- : HOptimization(graph, kDexCacheArrayFixupsArmPassName, stats),
- codegen_(codegen) {}
-
- static constexpr const char* kDexCacheArrayFixupsArmPassName = "dex_cache_array_fixups_arm";
-
- void Run() OVERRIDE;
-
- private:
- CodeGenerator* codegen_;
-};
-
-} // namespace arm
-} // namespace art
-
-#endif // ART_COMPILER_OPTIMIZING_DEX_CACHE_ARRAY_FIXUPS_ARM_H_
diff --git a/compiler/optimizing/dex_cache_array_fixups_mips.cc b/compiler/optimizing/dex_cache_array_fixups_mips.cc
deleted file mode 100644
index 7734f91..0000000
--- a/compiler/optimizing/dex_cache_array_fixups_mips.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "code_generator_mips.h"
-#include "dex_cache_array_fixups_mips.h"
-
-#include "base/arena_containers.h"
-#include "intrinsics_mips.h"
-#include "utils/dex_cache_arrays_layout-inl.h"
-
-namespace art {
-namespace mips {
-
-/**
- * Finds instructions that need the dex cache arrays base as an input.
- */
-class DexCacheArrayFixupsVisitor : public HGraphVisitor {
- public:
- explicit DexCacheArrayFixupsVisitor(HGraph* graph, CodeGenerator* codegen)
- : HGraphVisitor(graph),
- codegen_(down_cast<CodeGeneratorMIPS*>(codegen)),
- dex_cache_array_bases_(std::less<const DexFile*>(),
- // Attribute memory use to code generator.
- graph->GetArena()->Adapter(kArenaAllocCodeGenerator)) {}
-
- void MoveBasesIfNeeded() {
- for (const auto& entry : dex_cache_array_bases_) {
- // Bring the base closer to the first use (previously, it was in the
- // entry block) and relieve some pressure on the register allocator
- // while avoiding recalculation of the base in a loop.
- HMipsDexCacheArraysBase* base = entry.second;
- base->MoveBeforeFirstUserAndOutOfLoops();
- }
- // Computing the dex cache base for PC-relative accesses will clobber RA with
- // the NAL instruction on R2. Take a note of this before generating the method
- // entry.
- if (!dex_cache_array_bases_.empty()) {
- codegen_->ClobberRA();
- }
- }
-
- private:
- void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE {
- // If this is an invoke with PC-relative access to the dex cache methods array,
- // we need to add the dex cache arrays base as the special input.
- if (invoke->HasPcRelativeDexCache() &&
- !IsCallFreeIntrinsic<IntrinsicLocationsBuilderMIPS>(invoke, codegen_)) {
- // Initialize base for target method dex file if needed.
- HMipsDexCacheArraysBase* base =
- GetOrCreateDexCacheArrayBase(invoke->GetDexFileForPcRelativeDexCache());
- // Update the element offset in base.
- DexCacheArraysLayout layout(kMipsPointerSize, &invoke->GetDexFileForPcRelativeDexCache());
- base->UpdateElementOffset(layout.MethodOffset(invoke->GetDexMethodIndex()));
- // Add the special argument base to the method.
- DCHECK(!invoke->HasCurrentMethodInput());
- invoke->AddSpecialInput(base);
- }
- }
-
- HMipsDexCacheArraysBase* GetOrCreateDexCacheArrayBase(const DexFile& dex_file) {
- return dex_cache_array_bases_.GetOrCreate(
- &dex_file,
- [this, &dex_file]() {
- HMipsDexCacheArraysBase* base =
- new (GetGraph()->GetArena()) HMipsDexCacheArraysBase(dex_file);
- HBasicBlock* entry_block = GetGraph()->GetEntryBlock();
- // Insert the base at the start of the entry block, move it to a better
- // position later in MoveBaseIfNeeded().
- entry_block->InsertInstructionBefore(base, entry_block->GetFirstInstruction());
- return base;
- });
- }
-
- CodeGeneratorMIPS* codegen_;
-
- using DexCacheArraysBaseMap =
- ArenaSafeMap<const DexFile*, HMipsDexCacheArraysBase*, std::less<const DexFile*>>;
- DexCacheArraysBaseMap dex_cache_array_bases_;
-};
-
-void DexCacheArrayFixups::Run() {
- CodeGeneratorMIPS* mips_codegen = down_cast<CodeGeneratorMIPS*>(codegen_);
- if (mips_codegen->GetInstructionSetFeatures().IsR6()) {
- // Do nothing for R6 because it has PC-relative addressing.
- return;
- }
- if (graph_->HasIrreducibleLoops()) {
- // Do not run this optimization, as irreducible loops do not work with an instruction
- // that can be live-in at the irreducible loop header.
- return;
- }
- DexCacheArrayFixupsVisitor visitor(graph_, codegen_);
- visitor.VisitInsertionOrder();
- visitor.MoveBasesIfNeeded();
-}
-
-} // namespace mips
-} // namespace art
diff --git a/compiler/optimizing/dex_cache_array_fixups_mips.h b/compiler/optimizing/dex_cache_array_fixups_mips.h
deleted file mode 100644
index 861a199..0000000
--- a/compiler/optimizing/dex_cache_array_fixups_mips.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_COMPILER_OPTIMIZING_DEX_CACHE_ARRAY_FIXUPS_MIPS_H_
-#define ART_COMPILER_OPTIMIZING_DEX_CACHE_ARRAY_FIXUPS_MIPS_H_
-
-#include "nodes.h"
-#include "optimization.h"
-
-namespace art {
-
-class CodeGenerator;
-
-namespace mips {
-
-class DexCacheArrayFixups : public HOptimization {
- public:
- DexCacheArrayFixups(HGraph* graph, CodeGenerator* codegen, OptimizingCompilerStats* stats)
- : HOptimization(graph, kDexCacheArrayFixupsMipsPassName, stats),
- codegen_(codegen) {}
-
- static constexpr const char* kDexCacheArrayFixupsMipsPassName = "dex_cache_array_fixups_mips";
-
- void Run() OVERRIDE;
-
- private:
- CodeGenerator* codegen_;
-};
-
-} // namespace mips
-} // namespace art
-
-#endif // ART_COMPILER_OPTIMIZING_DEX_CACHE_ARRAY_FIXUPS_MIPS_H_
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index e53209f..d0047c5 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -2643,8 +2643,8 @@
return os << "BootImageLinkTimePcRelative";
case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
return os << "DirectAddress";
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative:
- return os << "DexCachePcRelative";
+ case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry:
+ return os << "BssEntry";
case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall:
return os << "RuntimeCall";
default:
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 74bb2ab..2867797 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1410,12 +1410,7 @@
M(IntermediateAddressIndex, Instruction)
#endif
-#ifndef ART_ENABLE_CODEGEN_arm
#define FOR_EACH_CONCRETE_INSTRUCTION_ARM(M)
-#else
-#define FOR_EACH_CONCRETE_INSTRUCTION_ARM(M) \
- M(ArmDexCacheArraysBase, Instruction)
-#endif
#define FOR_EACH_CONCRETE_INSTRUCTION_ARM64(M)
@@ -1424,7 +1419,6 @@
#else
#define FOR_EACH_CONCRETE_INSTRUCTION_MIPS(M) \
M(MipsComputeBaseMethodAddress, Instruction) \
- M(MipsDexCacheArraysBase, Instruction) \
M(MipsPackedSwitch, Instruction)
#endif
@@ -4166,11 +4160,9 @@
// Used for app->boot calls with non-relocatable image and for JIT-compiled calls.
kDirectAddress,
- // Load from resolved methods array in the dex cache using a PC-relative load.
- // Used when we need to use the dex cache, for example for invoke-static that
- // may cause class initialization (the entry may point to a resolution method),
- // and we know that we can access the dex cache arrays using a PC-relative load.
- kDexCachePcRelative,
+ // Load from an entry in the .bss section using a PC-relative load.
+ // Used for classes outside boot image when .bss is accessible with a PC-relative load.
+ kBssEntry,
// Make a runtime call to resolve and call the method. This is the last-resort-kind
// used when other kinds are unimplemented on a particular architecture.
@@ -4195,7 +4187,6 @@
// - thread entrypoint offset for kStringInit method if this is a string init invoke.
// Note that there are multiple string init methods, each having its own offset.
// - the method address for kDirectAddress
- // - the dex cache arrays offset for kDexCachePcRel.
uint64_t method_load_data;
};
@@ -4296,12 +4287,9 @@
bool NeedsDexCacheOfDeclaringClass() const OVERRIDE;
bool IsStringInit() const { return GetMethodLoadKind() == MethodLoadKind::kStringInit; }
bool HasMethodAddress() const { return GetMethodLoadKind() == MethodLoadKind::kDirectAddress; }
- bool HasPcRelativeDexCache() const {
- return GetMethodLoadKind() == MethodLoadKind::kDexCachePcRelative;
- }
bool HasPcRelativeMethodLoadKind() const {
return GetMethodLoadKind() == MethodLoadKind::kBootImageLinkTimePcRelative ||
- GetMethodLoadKind() == MethodLoadKind::kDexCachePcRelative;
+ GetMethodLoadKind() == MethodLoadKind::kBssEntry;
}
bool HasCurrentMethodInput() const {
// This function can be called only after the invoke has been fully initialized by the builder.
@@ -4325,11 +4313,6 @@
return dispatch_info_.method_load_data;
}
- uint32_t GetDexCacheArrayOffset() const {
- DCHECK(HasPcRelativeDexCache());
- return dispatch_info_.method_load_data;
- }
-
const DexFile& GetDexFileForPcRelativeDexCache() const;
ClinitCheckRequirement GetClinitCheckRequirement() const {
@@ -6879,9 +6862,6 @@
#if defined(ART_ENABLE_CODEGEN_arm) || defined(ART_ENABLE_CODEGEN_arm64)
#include "nodes_shared.h"
#endif
-#ifdef ART_ENABLE_CODEGEN_arm
-#include "nodes_arm.h"
-#endif
#ifdef ART_ENABLE_CODEGEN_mips
#include "nodes_mips.h"
#endif
diff --git a/compiler/optimizing/nodes_arm.h b/compiler/optimizing/nodes_arm.h
deleted file mode 100644
index d9f9740e..0000000
--- a/compiler/optimizing/nodes_arm.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_COMPILER_OPTIMIZING_NODES_ARM_H_
-#define ART_COMPILER_OPTIMIZING_NODES_ARM_H_
-
-namespace art {
-
-class HArmDexCacheArraysBase FINAL : public HExpression<0> {
- public:
- explicit HArmDexCacheArraysBase(const DexFile& dex_file)
- : HExpression(Primitive::kPrimInt, SideEffects::None(), kNoDexPc),
- dex_file_(&dex_file),
- element_offset_(static_cast<size_t>(-1)) { }
-
- bool CanBeMoved() const OVERRIDE { return true; }
-
- void UpdateElementOffset(size_t element_offset) {
- // Use the lowest offset from the requested elements so that all offsets from
- // this base are non-negative because our assemblers emit negative-offset loads
- // as a sequence of two or more instructions. (However, positive offsets beyond
- // 4KiB also require two or more instructions, so this simple heuristic could
- // be improved for cases where there is a dense cluster of elements far from
- // the lowest offset. This is expected to be rare enough though, so we choose
- // not to spend compile time on elaborate calculations.)
- element_offset_ = std::min(element_offset_, element_offset);
- }
-
- const DexFile& GetDexFile() const {
- return *dex_file_;
- }
-
- size_t GetElementOffset() const {
- return element_offset_;
- }
-
- DECLARE_INSTRUCTION(ArmDexCacheArraysBase);
-
- private:
- const DexFile* dex_file_;
- size_t element_offset_;
-
- DISALLOW_COPY_AND_ASSIGN(HArmDexCacheArraysBase);
-};
-
-} // namespace art
-
-#endif // ART_COMPILER_OPTIMIZING_NODES_ARM_H_
diff --git a/compiler/optimizing/nodes_mips.h b/compiler/optimizing/nodes_mips.h
index 36431c1..8e439d9 100644
--- a/compiler/optimizing/nodes_mips.h
+++ b/compiler/optimizing/nodes_mips.h
@@ -34,38 +34,6 @@
DISALLOW_COPY_AND_ASSIGN(HMipsComputeBaseMethodAddress);
};
-class HMipsDexCacheArraysBase : public HExpression<0> {
- public:
- explicit HMipsDexCacheArraysBase(const DexFile& dex_file)
- : HExpression(Primitive::kPrimInt, SideEffects::None(), kNoDexPc),
- dex_file_(&dex_file),
- element_offset_(static_cast<size_t>(-1)) { }
-
- bool CanBeMoved() const OVERRIDE { return true; }
-
- void UpdateElementOffset(size_t element_offset) {
- // We'll maximize the range of a single load instruction for dex cache array accesses
- // by aligning offset -32768 with the offset of the first used element.
- element_offset_ = std::min(element_offset_, element_offset);
- }
-
- const DexFile& GetDexFile() const {
- return *dex_file_;
- }
-
- size_t GetElementOffset() const {
- return element_offset_;
- }
-
- DECLARE_INSTRUCTION(MipsDexCacheArraysBase);
-
- private:
- const DexFile* dex_file_;
- size_t element_offset_;
-
- DISALLOW_COPY_AND_ASSIGN(HMipsDexCacheArraysBase);
-};
-
// Mips version of HPackedSwitch that holds a pointer to the base method address.
class HMipsPackedSwitch FINAL : public HTemplateInstruction<2> {
public:
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index e5ab00b..890ba67 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -24,16 +24,11 @@
#include "android-base/strings.h"
-#ifdef ART_ENABLE_CODEGEN_arm
-#include "dex_cache_array_fixups_arm.h"
-#endif
-
#ifdef ART_ENABLE_CODEGEN_arm64
#include "instruction_simplifier_arm64.h"
#endif
#ifdef ART_ENABLE_CODEGEN_mips
-#include "dex_cache_array_fixups_mips.h"
#include "pc_relative_fixups_mips.h"
#endif
@@ -522,8 +517,6 @@
} else if (opt_name == CodeSinking::kCodeSinkingPassName) {
return new (arena) CodeSinking(graph, stats);
#ifdef ART_ENABLE_CODEGEN_arm
- } else if (opt_name == arm::DexCacheArrayFixups::kDexCacheArrayFixupsArmPassName) {
- return new (arena) arm::DexCacheArrayFixups(graph, codegen, stats);
} else if (opt_name == arm::InstructionSimplifierArm::kInstructionSimplifierArmPassName) {
return new (arena) arm::InstructionSimplifierArm(graph, stats);
#endif
@@ -532,8 +525,6 @@
return new (arena) arm64::InstructionSimplifierArm64(graph, stats);
#endif
#ifdef ART_ENABLE_CODEGEN_mips
- } else if (opt_name == mips::DexCacheArrayFixups::kDexCacheArrayFixupsMipsPassName) {
- return new (arena) mips::DexCacheArrayFixups(graph, codegen, stats);
} else if (opt_name == mips::PcRelativeFixups::kPcRelativeFixupsMipsPassName) {
return new (arena) mips::PcRelativeFixups(graph, codegen, stats);
#endif
@@ -641,8 +632,6 @@
#if defined(ART_ENABLE_CODEGEN_arm)
case kThumb2:
case kArm: {
- arm::DexCacheArrayFixups* fixups =
- new (arena) arm::DexCacheArrayFixups(graph, codegen, stats);
arm::InstructionSimplifierArm* simplifier =
new (arena) arm::InstructionSimplifierArm(graph, stats);
SideEffectsAnalysis* side_effects = new (arena) SideEffectsAnalysis(graph);
@@ -653,7 +642,6 @@
simplifier,
side_effects,
gvn,
- fixups,
scheduling,
};
RunOptimizations(arm_optimizations, arraysize(arm_optimizations), pass_observer);
@@ -682,11 +670,8 @@
case kMips: {
mips::PcRelativeFixups* pc_relative_fixups =
new (arena) mips::PcRelativeFixups(graph, codegen, stats);
- mips::DexCacheArrayFixups* dex_cache_array_fixups =
- new (arena) mips::DexCacheArrayFixups(graph, codegen, stats);
HOptimization* mips_optimizations[] = {
pc_relative_fixups,
- dex_cache_array_fixups
};
RunOptimizations(mips_optimizations, arraysize(mips_optimizations), pass_observer);
break;
diff --git a/compiler/optimizing/pc_relative_fixups_mips.cc b/compiler/optimizing/pc_relative_fixups_mips.cc
index bce54bf..21b6452 100644
--- a/compiler/optimizing/pc_relative_fixups_mips.cc
+++ b/compiler/optimizing/pc_relative_fixups_mips.cc
@@ -59,10 +59,9 @@
}
void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE {
- // If this is an invoke with PC-relative pointer to a method,
+ // If this is an invoke with PC-relative load kind,
// we need to add the base as the special input.
- if (invoke->GetMethodLoadKind() ==
- HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative &&
+ if (invoke->HasPcRelativeMethodLoadKind() &&
!IsCallFreeIntrinsic<IntrinsicLocationsBuilderMIPS>(invoke, codegen_)) {
InitializePCRelativeBasePointer();
// Add the special argument base to the method.
diff --git a/compiler/optimizing/scheduler_arm.cc b/compiler/optimizing/scheduler_arm.cc
index 832a7e1..e78cd78 100644
--- a/compiler/optimizing/scheduler_arm.cc
+++ b/compiler/optimizing/scheduler_arm.cc
@@ -818,10 +818,5 @@
}
}
-void SchedulingLatencyVisitorARM::VisitArmDexCacheArraysBase(art::HArmDexCacheArraysBase*) {
- last_visited_internal_latency_ = kArmIntegerOpLatency;
- last_visited_latency_ = kArmIntegerOpLatency;
-}
-
} // namespace arm
} // namespace art
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index 106b709..8bd568b 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -128,15 +128,8 @@
method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative;
code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
} else {
- // Use PC-relative access to the dex cache arrays.
- method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative;
- // Note: we use the invoke's graph instead of the codegen graph, which are
- // different when inlining (the codegen graph is the most outer graph). The
- // invoke's dex method index is relative to the dex file where the invoke's graph
- // was built from.
- DexCacheArraysLayout layout(GetInstructionSetPointerSize(codegen->GetInstructionSet()),
- &invoke->GetBlock()->GetGraph()->GetDexFile());
- method_load_data = layout.MethodOffset(invoke->GetDexMethodIndex());
+ // Use PC-relative access to the .bss methods arrays.
+ method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBssEntry;
code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
}