Merge "Add a HCurrentMethod node."
diff --git a/Android.mk b/Android.mk
index 3467f1d..98d5fb1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -119,6 +119,10 @@
# Sync test files to the target, depends upon all things that must be pushed to the target.
.PHONY: test-art-target-sync
+# Check if we need to sync. In case ART_TEST_ANDROID_ROOT is not empty,
+# the code below uses 'adb push' instead of 'adb sync', which does not
+# check if the files on the device have changed.
+ifneq ($(ART_TEST_NO_SYNC),true)
ifeq ($(ART_TEST_ANDROID_ROOT),)
test-art-target-sync: $(TEST_ART_TARGET_SYNC_DEPS)
adb root
@@ -130,9 +134,7 @@
adb wait-for-device push $(ANDROID_PRODUCT_OUT)/system $(ART_TEST_ANDROID_ROOT)
adb push $(ANDROID_PRODUCT_OUT)/data /data
endif
-
-# Undefine variable now its served its purpose.
-TEST_ART_TARGET_SYNC_DEPS :=
+endif
# "mm test-art" to build and run all tests on host and device
.PHONY: test-art
@@ -377,6 +379,15 @@
build-art-target: $(TARGET_OUT_EXECUTABLES)/art $(ART_TARGET_DEPENDENCIES) $(TARGET_CORE_IMG_OUTS)
########################################################################
+# Rules for building all dependencies for tests.
+
+.PHONY: build-art-host-tests
+build-art-host-tests: build-art-host $(ART_TEST_HOST_RUN_TEST_DEPENDENCIES) $(ART_TEST_HOST_GTEST_DEPENDENCIES)
+
+.PHONY: build-art-target-tests
+build-art-target-tests: build-art-target $(TEST_ART_TARGET_SYNC_DEPS)
+
+########################################################################
# targets to switch back and forth from libdvm to libart
.PHONY: use-art
@@ -467,3 +478,4 @@
# Clear locally used variables.
art_dont_bother :=
art_test_bother :=
+TEST_ART_TARGET_SYNC_DEPS :=
diff --git a/build/Android.common_build.mk b/build/Android.common_build.mk
index 3e427a3..b84154b 100644
--- a/build/Android.common_build.mk
+++ b/build/Android.common_build.mk
@@ -177,8 +177,8 @@
ART_C_INCLUDES := \
external/gtest/include \
external/icu/icu4c/source/common \
- external/valgrind/main/include \
- external/valgrind/main \
+ external/valgrind/include \
+ external/valgrind \
external/vixl/src \
external/zlib \
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 69472b7..0876cc0 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -313,6 +313,7 @@
ART_TEST_TARGET_GTEST$(ART_PHONY_TEST_TARGET_SUFFIX)_RULES :=
ART_TEST_TARGET_GTEST$(2ND_ART_PHONY_TEST_TARGET_SUFFIX)_RULES :=
ART_TEST_TARGET_GTEST_RULES :=
+ART_TEST_HOST_GTEST_DEPENDENCIES :=
ART_GTEST_TARGET_ANDROID_ROOT := '/system'
ifneq ($(ART_TEST_ANDROID_ROOT),)
@@ -374,11 +375,15 @@
gtest_exe := $$(HOST_OUT_EXECUTABLES)/$(1)$$($(2)ART_PHONY_TEST_HOST_SUFFIX)
# Dependencies for all host gtests.
gtest_deps := $$(HOST_CORE_DEX_LOCATIONS) \
- $$($(2)ART_HOST_OUT_SHARED_LIBRARIES)/libjavacore$$(ART_HOST_SHLIB_EXTENSION)
+ $$($(2)ART_HOST_OUT_SHARED_LIBRARIES)/libjavacore$$(ART_HOST_SHLIB_EXTENSION) \
+ $$(gtest_exe) \
+ $$(ART_GTEST_$(1)_HOST_DEPS) \
+ $(foreach file,$(ART_GTEST_$(1)_DEX_DEPS),$(ART_TEST_HOST_GTEST_$(file)_DEX))
+ ART_TEST_HOST_GTEST_DEPENDENCIES += $$(gtest_deps)
.PHONY: $$(gtest_rule)
-$$(gtest_rule): $$(gtest_exe) $$(ART_GTEST_$(1)_HOST_DEPS) $(foreach file,$(ART_GTEST_$(1)_DEX_DEPS),$(ART_TEST_HOST_GTEST_$(file)_DEX)) $$(gtest_deps)
+$$(gtest_rule): $$(gtest_exe) $$(gtest_deps)
$(hide) ($$(call ART_TEST_SKIP,$$@) && $$< && $$(call ART_TEST_PASSED,$$@)) \
|| $$(call ART_TEST_FAILED,$$@)
@@ -388,7 +393,7 @@
.PHONY: valgrind-$$(gtest_rule)
-valgrind-$$(gtest_rule): $$(gtest_exe) $$(ART_GTEST_$(1)_HOST_DEPS) $(foreach file,$(ART_GTEST_$(1)_DEX_DEPS),$(ART_TEST_HOST_GTEST_$(file)_DEX)) $$(gtest_deps) $(ART_VALGRIND_DEPENDENCIES)
+valgrind-$$(gtest_rule): $$(gtest_deps) $(ART_VALGRIND_DEPENDENCIES)
$(hide) $$(call ART_TEST_SKIP,$$@) && \
VALGRIND_LIB=$(HOST_OUT)/lib64/valgrind \
$(HOST_OUT_EXECUTABLES)/valgrind --leak-check=full --error-exitcode=1 $$< && \
diff --git a/compiler/elf_builder.h b/compiler/elf_builder.h
index 8a63a48..5b74c94 100644
--- a/compiler/elf_builder.h
+++ b/compiler/elf_builder.h
@@ -57,12 +57,12 @@
public:
Section(const std::string& name, Elf_Word type, Elf_Word flags,
const Section* link, Elf_Word info, Elf_Word align, Elf_Word entsize)
- : header_(new Elf_Shdr()), section_index_(0), name_(name), link_(link) {
- header_->sh_type = type;
- header_->sh_flags = flags;
- header_->sh_info = info;
- header_->sh_addralign = align;
- header_->sh_entsize = entsize;
+ : header_(), section_index_(0), name_(name), link_(link) {
+ header_.sh_type = type;
+ header_.sh_flags = flags;
+ header_.sh_info = info;
+ header_.sh_addralign = align;
+ header_.sh_entsize = entsize;
}
virtual ~Section() {}
@@ -80,11 +80,11 @@
}
const Elf_Shdr* GetHeader() const {
- return header_.get();
+ return &header_;
}
Elf_Shdr* GetHeader() {
- return header_.get();
+ return &header_;
}
Elf_Word GetSectionIndex() const {
@@ -101,9 +101,7 @@
}
private:
- // Elf_Shdr is somewhat large so allocate it on the heap.
- // Otherwise we get in trouble with stack frame sizes.
- std::unique_ptr<Elf_Shdr> header_;
+ Elf_Shdr header_;
Elf_Word section_index_;
const std::string name_;
const Section* const link_;
@@ -168,6 +166,10 @@
patched_(false), patch_(patch), patch_base_section_(patch_base_section) {
}
+ RawSection(const std::string& name, Elf_Word type)
+ : RawSection(name, type, 0, nullptr, 0, 1, 0, nullptr, nullptr) {
+ }
+
Elf_Word GetSize() const OVERRIDE {
return buffer_.size();
}
@@ -779,10 +781,12 @@
template<typename T>
static bool WriteArray(File* elf_file, const T* data, size_t count) {
- DCHECK(data != nullptr);
- if (!elf_file->WriteFully(data, count * sizeof(T))) {
- PLOG(ERROR) << "Failed to write to file " << elf_file->GetPath();
- return false;
+ if (count != 0) {
+ DCHECK(data != nullptr);
+ if (!elf_file->WriteFully(data, count * sizeof(T))) {
+ PLOG(ERROR) << "Failed to write to file " << elf_file->GetPath();
+ return false;
+ }
}
return true;
}
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index 05b5c68..3f0a80b 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -19,6 +19,7 @@
#include <unordered_map>
#include <unordered_set>
+#include "base/casts.h"
#include "base/logging.h"
#include "base/unix_file/fd_file.h"
#include "compiled_method.h"
@@ -69,36 +70,17 @@
template <typename ElfTypes>
static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, OatWriter* oat_writer);
-// Encode patch locations in .oat_patches format.
+// Encode patch locations as LEB128 list of deltas between consecutive addresses.
template <typename ElfTypes>
-void ElfWriterQuick<ElfTypes>::EncodeOatPatches(
- const OatWriter::PatchLocationsMap& sections,
- std::vector<uint8_t>* buffer) {
- for (const auto& section : sections) {
- const std::string& name = section.first;
- std::vector<uintptr_t>* locations = section.second.get();
- DCHECK(!name.empty());
- std::sort(locations->begin(), locations->end());
- // Reserve buffer space - guess 2 bytes per ULEB128.
- buffer->reserve(buffer->size() + name.size() + locations->size() * 2);
- // Write null-terminated section name.
- const uint8_t* name_data = reinterpret_cast<const uint8_t*>(name.c_str());
- buffer->insert(buffer->end(), name_data, name_data + name.size() + 1);
- // Write placeholder for data length.
- size_t length_pos = buffer->size();
- EncodeUnsignedLeb128(buffer, UINT32_MAX);
- // Write LEB128 encoded list of advances (deltas between consequtive addresses).
- size_t data_pos = buffer->size();
- uintptr_t address = 0; // relative to start of section.
- for (uintptr_t location : *locations) {
- DCHECK_LT(location - address, UINT32_MAX) << "Large gap between patch locations";
- EncodeUnsignedLeb128(buffer, location - address);
- address = location;
- }
- // Update length.
- UpdateUnsignedLeb128(buffer->data() + length_pos, buffer->size() - data_pos);
+void ElfWriterQuick<ElfTypes>::EncodeOatPatches(const std::vector<uintptr_t>& locations,
+ std::vector<uint8_t>* buffer) {
+ buffer->reserve(buffer->size() + locations.size() * 2); // guess 2 bytes per ULEB128.
+ uintptr_t address = 0; // relative to start of section.
+ for (uintptr_t location : locations) {
+ DCHECK_GE(location, address) << "Patch locations are not in sorted order";
+ EncodeUnsignedLeb128(buffer, dchecked_integral_cast<uint32_t>(location - address));
+ address = location;
}
- buffer->push_back(0); // End of sections.
}
class RodataWriter FINAL : public CodeOutput {
@@ -174,48 +156,62 @@
isa, rodata_size, &rodata_writer, text_size, &text_writer, bss_size));
// Add debug sections.
- // They are stack allocated here (in the same scope as the builder),
- // but they are registred with the builder only if they are used.
+ // They are allocated here (in the same scope as the builder),
+ // but they are registered with the builder only if they are used.
using RawSection = typename ElfBuilder<ElfTypes>::RawSection;
const auto* text = builder->GetText();
const bool is64bit = Is64BitInstructionSet(isa);
const int pointer_size = GetInstructionSetPointerSize(isa);
- RawSection eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0,
- is64bit ? Patch<Elf_Addr, uint64_t, kPointerRelativeAddress> :
- Patch<Elf_Addr, uint32_t, kPointerRelativeAddress>,
- text);
- RawSection eh_frame_hdr(".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0,
- Patch<Elf_Addr, uint32_t, kSectionRelativeAddress>, text);
- RawSection debug_frame(".debug_frame", SHT_PROGBITS, 0, nullptr, 0, pointer_size, 0,
- is64bit ? Patch<Elf_Addr, uint64_t, kAbsoluteAddress> :
- Patch<Elf_Addr, uint32_t, kAbsoluteAddress>,
- text);
- RawSection debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0,
- Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text);
- RawSection debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
- RawSection debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
- RawSection debug_line(".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0,
- Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text);
+ std::unique_ptr<RawSection> eh_frame(new RawSection(
+ ".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0,
+ is64bit ? Patch<Elf_Addr, uint64_t, kPointerRelativeAddress> :
+ Patch<Elf_Addr, uint32_t, kPointerRelativeAddress>,
+ text));
+ std::unique_ptr<RawSection> eh_frame_hdr(new RawSection(
+ ".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0,
+ Patch<Elf_Addr, uint32_t, kSectionRelativeAddress>, text));
+ std::unique_ptr<RawSection> debug_frame(new RawSection(
+ ".debug_frame", SHT_PROGBITS, 0, nullptr, 0, pointer_size, 0,
+ is64bit ? Patch<Elf_Addr, uint64_t, kAbsoluteAddress> :
+ Patch<Elf_Addr, uint32_t, kAbsoluteAddress>,
+ text));
+ std::unique_ptr<RawSection> debug_frame_oat_patches(new RawSection(
+ ".debug_frame.oat_patches", SHT_OAT_PATCH));
+ std::unique_ptr<RawSection> debug_info(new RawSection(
+ ".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0,
+ Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text));
+ std::unique_ptr<RawSection> debug_info_oat_patches(new RawSection(
+ ".debug_info.oat_patches", SHT_OAT_PATCH));
+ std::unique_ptr<RawSection> debug_abbrev(new RawSection(
+ ".debug_abbrev", SHT_PROGBITS));
+ std::unique_ptr<RawSection> debug_str(new RawSection(
+ ".debug_str", SHT_PROGBITS));
+ std::unique_ptr<RawSection> debug_line(new RawSection(
+ ".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0,
+ Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text));
+ std::unique_ptr<RawSection> debug_line_oat_patches(new RawSection(
+ ".debug_line.oat_patches", SHT_OAT_PATCH));
if (!oat_writer->GetMethodDebugInfo().empty()) {
if (compiler_driver_->GetCompilerOptions().GetIncludeCFI()) {
if (kCFIFormat == dwarf::DW_EH_FRAME_FORMAT) {
dwarf::WriteCFISection(
compiler_driver_, oat_writer,
dwarf::DW_EH_PE_pcrel, kCFIFormat,
- eh_frame.GetBuffer(), eh_frame.GetPatchLocations(),
- eh_frame_hdr.GetBuffer(), eh_frame_hdr.GetPatchLocations());
- builder->RegisterSection(&eh_frame);
- builder->RegisterSection(&eh_frame_hdr);
+ eh_frame->GetBuffer(), eh_frame->GetPatchLocations(),
+ eh_frame_hdr->GetBuffer(), eh_frame_hdr->GetPatchLocations());
+ builder->RegisterSection(eh_frame.get());
+ builder->RegisterSection(eh_frame_hdr.get());
} else {
DCHECK(kCFIFormat == dwarf::DW_DEBUG_FRAME_FORMAT);
dwarf::WriteCFISection(
compiler_driver_, oat_writer,
dwarf::DW_EH_PE_absptr, kCFIFormat,
- debug_frame.GetBuffer(), debug_frame.GetPatchLocations(),
+ debug_frame->GetBuffer(), debug_frame->GetPatchLocations(),
nullptr, nullptr);
- builder->RegisterSection(&debug_frame);
- *oat_writer->GetAbsolutePatchLocationsFor(".debug_frame") =
- *debug_frame.GetPatchLocations();
+ builder->RegisterSection(debug_frame.get());
+ EncodeOatPatches(*debug_frame->GetPatchLocations(),
+ debug_frame_oat_patches->GetBuffer());
+ builder->RegisterSection(debug_frame_oat_patches.get());
}
}
if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
@@ -224,29 +220,32 @@
// Generate DWARF .debug_* sections.
dwarf::WriteDebugSections(
compiler_driver_, oat_writer,
- debug_info.GetBuffer(), debug_info.GetPatchLocations(),
- debug_abbrev.GetBuffer(),
- debug_str.GetBuffer(),
- debug_line.GetBuffer(), debug_line.GetPatchLocations());
- builder->RegisterSection(&debug_info);
- builder->RegisterSection(&debug_abbrev);
- builder->RegisterSection(&debug_str);
- builder->RegisterSection(&debug_line);
- *oat_writer->GetAbsolutePatchLocationsFor(".debug_info") =
- *debug_info.GetPatchLocations();
- *oat_writer->GetAbsolutePatchLocationsFor(".debug_line") =
- *debug_line.GetPatchLocations();
+ debug_info->GetBuffer(), debug_info->GetPatchLocations(),
+ debug_abbrev->GetBuffer(),
+ debug_str->GetBuffer(),
+ debug_line->GetBuffer(), debug_line->GetPatchLocations());
+ builder->RegisterSection(debug_info.get());
+ EncodeOatPatches(*debug_info->GetPatchLocations(),
+ debug_info_oat_patches->GetBuffer());
+ builder->RegisterSection(debug_info_oat_patches.get());
+ builder->RegisterSection(debug_abbrev.get());
+ builder->RegisterSection(debug_str.get());
+ builder->RegisterSection(debug_line.get());
+ EncodeOatPatches(*debug_line->GetPatchLocations(),
+ debug_line_oat_patches->GetBuffer());
+ builder->RegisterSection(debug_line_oat_patches.get());
}
}
- // Add relocation section.
- RawSection oat_patches(".oat_patches", SHT_OAT_PATCH, 0, nullptr, 0, 1, 0);
- if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation() ||
- // ElfWriter::Fixup will be called regardless and it needs to be able
- // to patch debug sections so we have to include patches for them.
- compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
- EncodeOatPatches(oat_writer->GetAbsolutePatchLocations(), oat_patches.GetBuffer());
- builder->RegisterSection(&oat_patches);
+ // Add relocation section for .text.
+ std::unique_ptr<RawSection> text_oat_patches(new RawSection(
+ ".text.oat_patches", SHT_OAT_PATCH));
+ if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) {
+ // Note that ElfWriter::Fixup will be called regardless and therefore
+ // we need to include oat_patches for debug sections unconditionally.
+ EncodeOatPatches(oat_writer->GetAbsolutePatchLocations(),
+ text_oat_patches->GetBuffer());
+ builder->RegisterSection(text_oat_patches.get());
}
return builder->Write(elf_file_);
diff --git a/compiler/elf_writer_quick.h b/compiler/elf_writer_quick.h
index 955b568..fd202ee 100644
--- a/compiler/elf_writer_quick.h
+++ b/compiler/elf_writer_quick.h
@@ -35,7 +35,7 @@
const CompilerDriver& driver)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static void EncodeOatPatches(const OatWriter::PatchLocationsMap& sections,
+ static void EncodeOatPatches(const std::vector<uintptr_t>& locations,
std::vector<uint8_t>* buffer);
protected:
diff --git a/compiler/elf_writer_test.cc b/compiler/elf_writer_test.cc
index 08523d8..ccf34b8 100644
--- a/compiler/elf_writer_test.cc
+++ b/compiler/elf_writer_test.cc
@@ -88,73 +88,41 @@
}
}
-// Run only on host since we do unaligned memory accesses.
-#ifndef HAVE_ANDROID_OS
-
-static void PatchSection(const std::vector<uintptr_t>& patch_locations,
- std::vector<uint8_t>* section, int32_t delta) {
- for (uintptr_t location : patch_locations) {
- *reinterpret_cast<int32_t*>(section->data() + location) += delta;
- }
-}
-
TEST_F(ElfWriterTest, EncodeDecodeOatPatches) {
- std::vector<uint8_t> oat_patches; // Encoded patches.
+ const std::vector<std::vector<uintptr_t>> test_data {
+ { 0, 4, 8, 15, 128, 200 },
+ { 8, 8 + 127 },
+ { 8, 8 + 128 },
+ { },
+ };
+ for (const auto& patch_locations : test_data) {
+ constexpr int32_t delta = 0x11235813;
- // Encode patch locations for a few sections.
- OatWriter::PatchLocationsMap sections;
- std::vector<uintptr_t> patches0 { 0, 4, 8, 15, 128, 200 }; // NOLINT
- sections.emplace(".section0", std::unique_ptr<std::vector<uintptr_t>>(
- new std::vector<uintptr_t> { patches0 }));
- std::vector<uintptr_t> patches1 { 8, 127 }; // NOLINT
- sections.emplace(".section1", std::unique_ptr<std::vector<uintptr_t>>(
- new std::vector<uintptr_t> { patches1 }));
- std::vector<uintptr_t> patches2 { }; // NOLINT
- sections.emplace(".section2", std::unique_ptr<std::vector<uintptr_t>>(
- new std::vector<uintptr_t> { patches2 }));
- ElfWriterQuick32::EncodeOatPatches(sections, &oat_patches);
+ // Encode patch locations.
+ std::vector<uint8_t> oat_patches;
+ ElfWriterQuick32::EncodeOatPatches(patch_locations, &oat_patches);
- // Create buffers to be patched.
- std::vector<uint8_t> initial_data(256);
- for (size_t i = 0; i < initial_data.size(); i++) {
- initial_data[i] = i;
+ // Create buffer to be patched.
+ std::vector<uint8_t> initial_data(256);
+ for (size_t i = 0; i < initial_data.size(); i++) {
+ initial_data[i] = i;
+ }
+
+ // Patch manually.
+ std::vector<uint8_t> expected = initial_data;
+ for (uintptr_t location : patch_locations) {
+ typedef __attribute__((__aligned__(1))) uint32_t UnalignedAddress;
+ *reinterpret_cast<UnalignedAddress*>(expected.data() + location) += delta;
+ }
+
+ // Decode and apply patch locations.
+ std::vector<uint8_t> actual = initial_data;
+ ElfFileImpl32::ApplyOatPatches(
+ oat_patches.data(), oat_patches.data() + oat_patches.size(), delta,
+ actual.data(), actual.data() + actual.size());
+
+ EXPECT_EQ(expected, actual);
}
- std::vector<uint8_t> section0_expected = initial_data;
- std::vector<uint8_t> section1_expected = initial_data;
- std::vector<uint8_t> section2_expected = initial_data;
- std::vector<uint8_t> section0_actual = initial_data;
- std::vector<uint8_t> section1_actual = initial_data;
- std::vector<uint8_t> section2_actual = initial_data;
-
- // Patch manually.
- constexpr int32_t delta = 0x11235813;
- PatchSection(patches0, §ion0_expected, delta);
- PatchSection(patches1, §ion1_expected, delta);
- PatchSection(patches2, §ion2_expected, delta);
-
- // Decode and apply patch locations.
- bool section0_successful = ElfFileImpl32::ApplyOatPatches(
- oat_patches.data(), oat_patches.data() + oat_patches.size(),
- ".section0", delta,
- section0_actual.data(), section0_actual.data() + section0_actual.size());
- EXPECT_TRUE(section0_successful);
- EXPECT_EQ(section0_expected, section0_actual);
-
- bool section1_successful = ElfFileImpl32::ApplyOatPatches(
- oat_patches.data(), oat_patches.data() + oat_patches.size(),
- ".section1", delta,
- section1_actual.data(), section1_actual.data() + section1_actual.size());
- EXPECT_TRUE(section1_successful);
- EXPECT_EQ(section1_expected, section1_actual);
-
- bool section2_successful = ElfFileImpl32::ApplyOatPatches(
- oat_patches.data(), oat_patches.data() + oat_patches.size(),
- ".section2", delta,
- section2_actual.data(), section2_actual.data() + section2_actual.size());
- EXPECT_TRUE(section2_successful);
- EXPECT_EQ(section2_expected, section2_actual);
}
-#endif
-
} // namespace art
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index bf32feb..02a2588 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -972,8 +972,8 @@
// Fix up the object previously had hash codes.
for (const std::pair<mirror::Object*, uint32_t>& hash_pair : saved_hashes_) {
Object* obj = hash_pair.first;
- DCHECK_EQ(obj->GetLockWord(false).ReadBarrierState(), 0U);
- obj->SetLockWord(LockWord::FromHashCode(hash_pair.second, 0U), false);
+ DCHECK_EQ(obj->GetLockWord<kVerifyNone>(false).ReadBarrierState(), 0U);
+ obj->SetLockWord<kVerifyNone>(LockWord::FromHashCode(hash_pair.second, 0U), false);
}
saved_hashes_.clear();
}
@@ -1008,11 +1008,11 @@
const size_t num_elements = arr->GetLength();
if (target_ptr_size_ == 4u) {
// Will get fixed up by fixup object.
- dst->SetClass(down_cast<mirror::Class*>(
+ dst->SetClass<kVerifyNone>(down_cast<mirror::Class*>(
GetImageAddress(mirror::IntArray::GetArrayClass())));
} else {
DCHECK_EQ(target_ptr_size_, 8u);
- dst->SetClass(down_cast<mirror::Class*>(
+ dst->SetClass<kVerifyNone>(down_cast<mirror::Class*>(
GetImageAddress(mirror::LongArray::GetArrayClass())));
}
mirror::Array* dest_array = down_cast<mirror::Array*>(dst);
@@ -1027,15 +1027,15 @@
fixup_location = image_begin_ + it2->second;
}
if (target_ptr_size_ == 4u) {
- down_cast<mirror::IntArray*>(dest_array)->SetWithoutChecks<kVerifyNone>(
+ down_cast<mirror::IntArray*>(dest_array)->SetWithoutChecks<false, false, kVerifyNone>(
i, static_cast<uint32_t>(reinterpret_cast<uint64_t>(fixup_location)));
} else {
DCHECK_EQ(target_ptr_size_, 8u);
- down_cast<mirror::LongArray*>(dest_array)->SetWithoutChecks<kVerifyNone>(
+ down_cast<mirror::LongArray*>(dest_array)->SetWithoutChecks<false, false, kVerifyNone>(
i, reinterpret_cast<uint64_t>(fixup_location));
}
}
- dst->SetLockWord(LockWord::Default(), false);
+ dst->SetLockWord<kVerifyNone>(LockWord::Default(), false);
return true;
}
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 15b4017..745cdcf 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -351,9 +351,8 @@
public:
InitCodeMethodVisitor(OatWriter* writer, size_t offset)
: OatDexMethodVisitor(writer, offset),
- text_absolute_patch_locations_(writer->GetAbsolutePatchLocationsFor(".text")),
debuggable_(writer->GetCompilerDriver()->GetCompilerOptions().GetDebuggable()) {
- text_absolute_patch_locations_->reserve(
+ writer_->absolute_patch_locations_.reserve(
writer_->compiler_driver_->GetNonRelativeLinkerPatchCount());
}
@@ -444,7 +443,7 @@
uintptr_t base_loc = offset_ - code_size - writer_->oat_header_->GetExecutableOffset();
for (const LinkerPatch& patch : compiled_method->GetPatches()) {
if (!patch.IsPcRelative()) {
- text_absolute_patch_locations_->push_back(base_loc + patch.LiteralOffset());
+ writer_->absolute_patch_locations_.push_back(base_loc + patch.LiteralOffset());
}
}
}
@@ -547,9 +546,6 @@
// so we can simply compare the pointers to find out if things are duplicated.
SafeMap<const CompiledMethod*, uint32_t, CodeOffsetsKeyComparator> dedupe_map_;
- // Patch locations for the .text section.
- std::vector<uintptr_t>* const text_absolute_patch_locations_;
-
// Cache of compiler's --debuggable option.
const bool debuggable_;
};
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index 6f1b4ec..82b9377 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -19,7 +19,6 @@
#include <stdint.h>
#include <cstddef>
-#include <map>
#include <memory>
#include "linker/relative_patcher.h" // For linker::RelativePatcherTargetProvider.
@@ -82,8 +81,6 @@
//
class OatWriter {
public:
- typedef std::map<std::string, std::unique_ptr<std::vector<uintptr_t>>> PatchLocationsMap;
-
OatWriter(const std::vector<const DexFile*>& dex_files,
uint32_t image_file_location_oat_checksum,
uintptr_t image_file_location_oat_begin,
@@ -105,19 +102,10 @@
return bss_size_;
}
- const PatchLocationsMap& GetAbsolutePatchLocations() const {
+ const std::vector<uintptr_t>& GetAbsolutePatchLocations() const {
return absolute_patch_locations_;
}
- std::vector<uintptr_t>* GetAbsolutePatchLocationsFor(const char* section_name) {
- auto it = absolute_patch_locations_.emplace(
- std::string(section_name), std::unique_ptr<std::vector<uintptr_t>>());
- if (it.second) { // Inserted new item.
- it.first->second.reset(new std::vector<uintptr_t>());
- }
- return it.first->second.get();
- }
-
bool WriteRodata(OutputStream* out);
bool WriteCode(OutputStream* out);
@@ -339,9 +327,8 @@
std::unique_ptr<linker::RelativePatcher> relative_patcher_;
- // The locations of absolute patches relative to the start of section.
- // The map's key is the ELF's section name (including the dot).
- PatchLocationsMap absolute_patch_locations_;
+ // The locations of absolute patches relative to the start of the executable section.
+ std::vector<uintptr_t> absolute_patch_locations_;
// Map method reference to assigned offset.
// Wrap the map in a class implementing linker::RelativePatcherTargetProvider.
diff --git a/compiler/optimizing/bounds_check_elimination_test.cc b/compiler/optimizing/bounds_check_elimination_test.cc
index 163458f..48090a3 100644
--- a/compiler/optimizing/bounds_check_elimination_test.cc
+++ b/compiler/optimizing/bounds_check_elimination_test.cc
@@ -647,7 +647,7 @@
graph->AddBlock(block);
entry->AddSuccessor(block);
HInstruction* new_array = new (allocator)
- HNewArray(constant_10, 0, Primitive::kPrimInt, kQuickAllocArray);
+ HNewArray(constant_10, 0, Primitive::kPrimInt, graph->GetDexFile(), kQuickAllocArray);
block->AddInstruction(new_array);
block->AddInstruction(new (allocator) HGoto());
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index c142e4d..41c1d2c 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -1034,7 +1034,11 @@
QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
? kQuickAllocArrayWithAccessCheck
: kQuickAllocArray;
- HInstruction* object = new (arena_) HNewArray(length, dex_pc, type_index, entrypoint);
+ HInstruction* object = new (arena_) HNewArray(length,
+ dex_pc,
+ type_index,
+ *dex_compilation_unit_->GetDexFile(),
+ entrypoint);
current_block_->AddInstruction(object);
const char* descriptor = dex_file_->StringByTypeIdx(type_index);
@@ -2001,8 +2005,8 @@
QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
? kQuickAllocArrayWithAccessCheck
: kQuickAllocArray;
- current_block_->AddInstruction(
- new (arena_) HNewArray(length, dex_pc, type_index, entrypoint));
+ current_block_->AddInstruction(new (arena_) HNewArray(
+ length, dex_pc, type_index, *dex_compilation_unit_->GetDexFile(), entrypoint));
UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction());
break;
}
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 1cca522..ab3b6b0 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -1029,19 +1029,19 @@
GenerateTestAndBranch(deoptimize, slow_path_entry, nullptr, slow_path_entry);
}
-void LocationsBuilderARM::VisitCondition(HCondition* comp) {
+void LocationsBuilderARM::VisitCondition(HCondition* cond) {
LocationSummary* locations =
- new (GetGraph()->GetArena()) LocationSummary(comp, LocationSummary::kNoCall);
+ new (GetGraph()->GetArena()) LocationSummary(cond, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
- locations->SetInAt(1, Location::RegisterOrConstant(comp->InputAt(1)));
- if (comp->NeedsMaterialization()) {
+ locations->SetInAt(1, Location::RegisterOrConstant(cond->InputAt(1)));
+ if (cond->NeedsMaterialization()) {
locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
}
}
-void InstructionCodeGeneratorARM::VisitCondition(HCondition* comp) {
- if (!comp->NeedsMaterialization()) return;
- LocationSummary* locations = comp->GetLocations();
+void InstructionCodeGeneratorARM::VisitCondition(HCondition* cond) {
+ if (!cond->NeedsMaterialization()) return;
+ LocationSummary* locations = cond->GetLocations();
Register left = locations->InAt(0).AsRegister<Register>();
if (locations->InAt(1).IsRegister()) {
@@ -1058,11 +1058,11 @@
__ cmp(left, ShifterOperand(temp));
}
}
- __ it(ARMCondition(comp->GetCondition()), kItElse);
+ __ it(ARMCondition(cond->GetCondition()), kItElse);
__ mov(locations->Out().AsRegister<Register>(), ShifterOperand(1),
- ARMCondition(comp->GetCondition()));
+ ARMCondition(cond->GetCondition()));
__ mov(locations->Out().AsRegister<Register>(), ShifterOperand(0),
- ARMOppositeCondition(comp->GetCondition()));
+ ARMOppositeCondition(cond->GetCondition()));
}
void LocationsBuilderARM::VisitEqual(HEqual* comp) {
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 3c5efa4..1688efc 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -984,20 +984,20 @@
UNUSED(store);
}
-void LocationsBuilderX86::VisitCondition(HCondition* comp) {
+void LocationsBuilderX86::VisitCondition(HCondition* cond) {
LocationSummary* locations =
- new (GetGraph()->GetArena()) LocationSummary(comp, LocationSummary::kNoCall);
+ new (GetGraph()->GetArena()) LocationSummary(cond, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::Any());
- if (comp->NeedsMaterialization()) {
+ if (cond->NeedsMaterialization()) {
// We need a byte register.
locations->SetOut(Location::RegisterLocation(ECX));
}
}
-void InstructionCodeGeneratorX86::VisitCondition(HCondition* comp) {
- if (comp->NeedsMaterialization()) {
- LocationSummary* locations = comp->GetLocations();
+void InstructionCodeGeneratorX86::VisitCondition(HCondition* cond) {
+ if (cond->NeedsMaterialization()) {
+ LocationSummary* locations = cond->GetLocations();
Register reg = locations->Out().AsRegister<Register>();
// Clear register: setcc only sets the low byte.
__ xorl(reg, reg);
@@ -1015,7 +1015,7 @@
} else {
__ cmpl(lhs.AsRegister<Register>(), Address(ESP, rhs.GetStackIndex()));
}
- __ setb(X86Condition(comp->GetCondition()), reg);
+ __ setb(X86Condition(cond->GetCondition()), reg);
}
}
@@ -1960,6 +1960,8 @@
if (second.IsRegister()) {
if (out.AsRegister<Register>() == first.AsRegister<Register>()) {
__ addl(out.AsRegister<Register>(), second.AsRegister<Register>());
+ } else if (out.AsRegister<Register>() == second.AsRegister<Register>()) {
+ __ addl(out.AsRegister<Register>(), first.AsRegister<Register>());
} else {
__ leal(out.AsRegister<Register>(), Address(
first.AsRegister<Register>(), second.AsRegister<Register>(), TIMES_1, 0));
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 7b08c89..7847701 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -945,19 +945,19 @@
UNUSED(store);
}
-void LocationsBuilderX86_64::VisitCondition(HCondition* comp) {
+void LocationsBuilderX86_64::VisitCondition(HCondition* cond) {
LocationSummary* locations =
- new (GetGraph()->GetArena()) LocationSummary(comp, LocationSummary::kNoCall);
+ new (GetGraph()->GetArena()) LocationSummary(cond, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::Any());
- if (comp->NeedsMaterialization()) {
+ if (cond->NeedsMaterialization()) {
locations->SetOut(Location::RequiresRegister());
}
}
-void InstructionCodeGeneratorX86_64::VisitCondition(HCondition* comp) {
- if (comp->NeedsMaterialization()) {
- LocationSummary* locations = comp->GetLocations();
+void InstructionCodeGeneratorX86_64::VisitCondition(HCondition* cond) {
+ if (cond->NeedsMaterialization()) {
+ LocationSummary* locations = cond->GetLocations();
CpuRegister reg = locations->Out().AsRegister<CpuRegister>();
// Clear register: setcc only sets the low byte.
__ xorl(reg, reg);
@@ -975,7 +975,7 @@
} else {
__ cmpl(lhs.AsRegister<CpuRegister>(), Address(CpuRegister(RSP), rhs.GetStackIndex()));
}
- __ setcc(X86_64Condition(comp->GetCondition()), reg);
+ __ setcc(X86_64Condition(cond->GetCondition()), reg);
}
}
@@ -2118,6 +2118,8 @@
if (second.IsRegister()) {
if (out.AsRegister<Register>() == first.AsRegister<Register>()) {
__ addl(out.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
+ } else if (out.AsRegister<Register>() == second.AsRegister<Register>()) {
+ __ addl(out.AsRegister<CpuRegister>(), first.AsRegister<CpuRegister>());
} else {
__ leal(out.AsRegister<CpuRegister>(), Address(
first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>(), TIMES_1, 0));
@@ -2141,6 +2143,8 @@
if (second.IsRegister()) {
if (out.AsRegister<Register>() == first.AsRegister<Register>()) {
__ addq(out.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
+ } else if (out.AsRegister<Register>() == second.AsRegister<Register>()) {
+ __ addq(out.AsRegister<CpuRegister>(), first.AsRegister<CpuRegister>());
} else {
__ leaq(out.AsRegister<CpuRegister>(), Address(
first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>(), TIMES_1, 0));
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index d542e59..869809d 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -2676,16 +2676,19 @@
HNewArray(HInstruction* length,
uint32_t dex_pc,
uint16_t type_index,
+ const DexFile& dex_file,
QuickEntrypointEnum entrypoint)
: HExpression(Primitive::kPrimNot, SideEffects::None()),
dex_pc_(dex_pc),
type_index_(type_index),
+ dex_file_(dex_file),
entrypoint_(entrypoint) {
SetRawInputAt(0, length);
}
uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
uint16_t GetTypeIndex() const { return type_index_; }
+ const DexFile& GetDexFile() const { return dex_file_; }
// Calls runtime so needs an environment.
bool NeedsEnvironment() const OVERRIDE { return true; }
@@ -2702,6 +2705,7 @@
private:
const uint32_t dex_pc_;
const uint16_t type_index_;
+ const DexFile& dex_file_;
const QuickEntrypointEnum entrypoint_;
DISALLOW_COPY_AND_ASSIGN(HNewArray);
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 601b48a..91b2e6f 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -35,7 +35,7 @@
void ReferenceTypePropagation::VisitBasicBlock(HBasicBlock* block) {
// TODO: handle other instructions that give type info
- // (NewArray/Call/Field accesses/array accesses)
+ // (Call/Field accesses/array accesses)
// Initialize exact types first for faster convergence.
for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
@@ -44,6 +44,8 @@
VisitNewInstance(instr->AsNewInstance());
} else if (instr->IsLoadClass()) {
VisitLoadClass(instr->AsLoadClass());
+ } else if (instr->IsNewArray()) {
+ VisitNewArray(instr->AsNewArray());
}
}
@@ -159,18 +161,29 @@
}
}
-void ReferenceTypePropagation::VisitNewInstance(HNewInstance* instr) {
+void ReferenceTypePropagation::UpdateReferenceTypeInfo(HInstruction* instr,
+ uint16_t type_idx,
+ const DexFile& dex_file) {
+ DCHECK_EQ(instr->GetType(), Primitive::kPrimNot);
+
ScopedObjectAccess soa(Thread::Current());
- mirror::DexCache* dex_cache =
- Runtime::Current()->GetClassLinker()->FindDexCache(instr->GetDexFile());
+ mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file);
// Get type from dex cache assuming it was populated by the verifier.
- mirror::Class* resolved_class = dex_cache->GetResolvedType(instr->GetTypeIndex());
+ mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx);
if (resolved_class != nullptr) {
MutableHandle<mirror::Class> handle = handles_->NewHandle(resolved_class);
instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(handle, true));
}
}
+void ReferenceTypePropagation::VisitNewInstance(HNewInstance* instr) {
+ UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile());
+}
+
+void ReferenceTypePropagation::VisitNewArray(HNewArray* instr) {
+ UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile());
+}
+
void ReferenceTypePropagation::VisitLoadClass(HLoadClass* instr) {
ScopedObjectAccess soa(Thread::Current());
mirror::DexCache* dex_cache =
diff --git a/compiler/optimizing/reference_type_propagation.h b/compiler/optimizing/reference_type_propagation.h
index b68fc67..12c3362 100644
--- a/compiler/optimizing/reference_type_propagation.h
+++ b/compiler/optimizing/reference_type_propagation.h
@@ -42,6 +42,7 @@
private:
void VisitNewInstance(HNewInstance* new_instance);
void VisitLoadClass(HLoadClass* load_class);
+ void VisitNewArray(HNewArray* instr);
void VisitPhi(HPhi* phi);
void VisitBasicBlock(HBasicBlock* block);
@@ -50,6 +51,7 @@
void BoundTypeForIfNotNull(HBasicBlock* block);
void BoundTypeForIfInstanceOf(HBasicBlock* block);
+ void UpdateReferenceTypeInfo(HInstruction* instr, uint16_t type_idx, const DexFile& dex_file);
void ProcessWorklist();
void AddToWorklist(HInstruction* instr);
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index a67ef8f..04f5a6a 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -1035,7 +1035,7 @@
void DumpCodeInfo(std::ostream& os,
const CodeInfo& code_info,
const DexFile::CodeItem& code_item) {
- code_info.Dump(os, code_item.registers_size_);
+ code_info.Dump(os, code_item.registers_size_, true);
}
// Display a vmap table.
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index ef84a17..8db1d23 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -563,21 +563,21 @@
uintptr_t quick= reinterpret_cast<uintptr_t>(
object->GetEntryPointFromQuickCompiledCodePtrSize<kVerifyNone>(pointer_size));
if (quick != 0) {
- copy->SetEntryPointFromQuickCompiledCodePtrSize(reinterpret_cast<void*>(quick + delta_),
- pointer_size);
+ copy->SetEntryPointFromQuickCompiledCodePtrSize<kVerifyNone>(
+ reinterpret_cast<void*>(quick + delta_), pointer_size);
}
uintptr_t interpreter = reinterpret_cast<uintptr_t>(
object->GetEntryPointFromInterpreterPtrSize<kVerifyNone>(pointer_size));
if (interpreter != 0) {
- copy->SetEntryPointFromInterpreterPtrSize(
+ copy->SetEntryPointFromInterpreterPtrSize<kVerifyNone>(
reinterpret_cast<mirror::EntryPointFromInterpreter*>(interpreter + delta_), pointer_size);
}
uintptr_t native_method = reinterpret_cast<uintptr_t>(
object->GetEntryPointFromJniPtrSize(pointer_size));
if (native_method != 0) {
- copy->SetEntryPointFromJniPtrSize(reinterpret_cast<void*>(native_method + delta_),
- pointer_size);
+ copy->SetEntryPointFromJniPtrSize<kVerifyNone>(
+ reinterpret_cast<void*>(native_method + delta_), pointer_size);
}
}
diff --git a/runtime/arch/arm64/context_arm64.cc b/runtime/arch/arm64/context_arm64.cc
index af2f661..5488f9d 100644
--- a/runtime/arch/arm64/context_arm64.cc
+++ b/runtime/arch/arm64/context_arm64.cc
@@ -134,7 +134,7 @@
gprs[i] = gprs_[i] != nullptr ? *gprs_[i] : Arm64Context::kBadGprBase + i;
}
for (size_t i = 0; i < kNumberOfDRegisters; ++i) {
- fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : Arm64Context::kBadGprBase + i;
+ fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : Arm64Context::kBadFprBase + i;
}
DCHECK_EQ(reinterpret_cast<uintptr_t>(Thread::Current()), gprs[TR]);
art_quick_do_long_jump(gprs, fprs);
diff --git a/runtime/arch/mips/context_mips.cc b/runtime/arch/mips/context_mips.cc
index f0c893a..24892e9 100644
--- a/runtime/arch/mips/context_mips.cc
+++ b/runtime/arch/mips/context_mips.cc
@@ -87,7 +87,7 @@
gprs[i] = gprs_[i] != nullptr ? *gprs_[i] : MipsContext::kBadGprBase + i;
}
for (size_t i = 0; i < kNumberOfFRegisters; ++i) {
- fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : MipsContext::kBadGprBase + i;
+ fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : MipsContext::kBadFprBase + i;
}
art_quick_do_long_jump(gprs, fprs);
}
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 0752c59..728e8e3 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -3703,7 +3703,9 @@
mirror::ArtMethod* m = single_step_control->GetMethod();
const int32_t line_number = visitor.line_number;
- if (!m->IsNative()) {
+ // Note: if the thread is not running Java code (pure native thread), there is no "current"
+ // method on the stack (and no line number either).
+ if (m != nullptr && !m->IsNative()) {
const DexFile::CodeItem* const code_item = m->GetCodeItem();
DebugCallbackContext context(single_step_control, line_number, code_item);
m->GetDexFile()->DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(),
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index b1d933d..9fd8c87 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -1401,86 +1401,53 @@
}
template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::FixupDebugSections(typename std::make_signed<Elf_Off>::type base_address_delta) {
+bool ElfFileImpl<ElfTypes>::FixupDebugSections(Elf_Addr base_address_delta) {
if (base_address_delta == 0) {
return true;
}
- if (FindSectionByName(".debug_frame") != nullptr) {
- if (!ApplyOatPatchesTo(".debug_frame", base_address_delta)) {
- return false;
- }
- }
- if (FindSectionByName(".debug_info") != nullptr) {
- if (!ApplyOatPatchesTo(".debug_info", base_address_delta)) {
- return false;
- }
- }
- if (FindSectionByName(".debug_line") != nullptr) {
- if (!ApplyOatPatchesTo(".debug_line", base_address_delta)) {
- return false;
- }
- }
- return true;
+ return ApplyOatPatchesTo(".debug_frame", base_address_delta) &&
+ ApplyOatPatchesTo(".debug_info", base_address_delta) &&
+ ApplyOatPatchesTo(".debug_line", base_address_delta);
}
template <typename ElfTypes>
bool ElfFileImpl<ElfTypes>::ApplyOatPatchesTo(
- const char* target_section_name,
- typename std::make_signed<Elf_Off>::type delta) {
- auto patches_section = FindSectionByName(".oat_patches");
+ const char* target_section_name, Elf_Addr delta) {
+ auto target_section = FindSectionByName(target_section_name);
+ if (target_section == nullptr) {
+ return true;
+ }
+ std::string patches_name = target_section_name + std::string(".oat_patches");
+ auto patches_section = FindSectionByName(patches_name.c_str());
if (patches_section == nullptr) {
- LOG(ERROR) << ".oat_patches section not found.";
+ LOG(ERROR) << patches_name << " section not found.";
return false;
}
if (patches_section->sh_type != SHT_OAT_PATCH) {
- LOG(ERROR) << "Unexpected type of .oat_patches.";
+ LOG(ERROR) << "Unexpected type of " << patches_name;
return false;
}
- auto target_section = FindSectionByName(target_section_name);
- if (target_section == nullptr) {
- LOG(ERROR) << target_section_name << " section not found.";
- return false;
- }
- if (!ApplyOatPatches(
+ ApplyOatPatches(
Begin() + patches_section->sh_offset,
Begin() + patches_section->sh_offset + patches_section->sh_size,
- target_section_name, delta,
+ delta,
Begin() + target_section->sh_offset,
- Begin() + target_section->sh_offset + target_section->sh_size)) {
- LOG(ERROR) << target_section_name << " section not found in .oat_patches.";
- }
+ Begin() + target_section->sh_offset + target_section->sh_size);
return true;
}
-// Apply .oat_patches to given section.
+// Apply LEB128 encoded patches to given section.
template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::ApplyOatPatches(
- const uint8_t* patches, const uint8_t* patches_end,
- const char* target_section_name,
- typename std::make_signed<Elf_Off>::type delta,
+void ElfFileImpl<ElfTypes>::ApplyOatPatches(
+ const uint8_t* patches, const uint8_t* patches_end, Elf_Addr delta,
uint8_t* to_patch, const uint8_t* to_patch_end) {
- // Read null-terminated section name.
- const char* section_name;
- while ((section_name = reinterpret_cast<const char*>(patches))[0] != '\0') {
- patches += strlen(section_name) + 1;
- uint32_t length = DecodeUnsignedLeb128(&patches);
- const uint8_t* next_section = patches + length;
- // Is it the section we want to patch?
- if (strcmp(section_name, target_section_name) == 0) {
- // Read LEB128 encoded list of advances.
- while (patches < next_section) {
- DCHECK_LT(patches, patches_end) << "Unexpected end of .oat_patches.";
- to_patch += DecodeUnsignedLeb128(&patches);
- DCHECK_LT(to_patch, to_patch_end) << "Patch past the end of " << section_name;
- // TODO: 32-bit vs 64-bit. What is the right type to use here?
- auto* patch_loc = reinterpret_cast<typename std::make_signed<Elf_Off>::type*>(to_patch);
- *patch_loc += delta;
- }
- return true;
- }
- patches = next_section;
+ typedef __attribute__((__aligned__(1))) Elf_Addr UnalignedAddress;
+ while (patches < patches_end) {
+ to_patch += DecodeUnsignedLeb128(&patches);
+ DCHECK_LE(patches, patches_end) << "Unexpected end of patch list.";
+ DCHECK_LT(to_patch, to_patch_end) << "Patch past the end of section.";
+ *reinterpret_cast<UnalignedAddress*>(to_patch) += delta;
}
- return false;
}
template <typename ElfTypes>
diff --git a/runtime/elf_file_impl.h b/runtime/elf_file_impl.h
index 3ad096f..0f466bd 100644
--- a/runtime/elf_file_impl.h
+++ b/runtime/elf_file_impl.h
@@ -119,12 +119,9 @@
bool FixupProgramHeaders(Elf_Addr base_address);
bool FixupSymbols(Elf_Addr base_address, bool dynamic);
bool FixupRelocations(Elf_Addr base_address);
- bool FixupDebugSections(typename std::make_signed<Elf_Off>::type base_address_delta);
- bool ApplyOatPatchesTo(const char* target_section_name,
- typename std::make_signed<Elf_Off>::type base_address_delta);
- static bool ApplyOatPatches(const uint8_t* patches, const uint8_t* patches_end,
- const char* target_section_name,
- typename std::make_signed<Elf_Off>::type delta,
+ bool FixupDebugSections(Elf_Addr base_address_delta);
+ bool ApplyOatPatchesTo(const char* target_section_name, Elf_Addr base_address_delta);
+ static void ApplyOatPatches(const uint8_t* patches, const uint8_t* patches_end, Elf_Addr delta,
uint8_t* to_patch, const uint8_t* to_patch_end);
bool Strip(std::string* error_msg);
diff --git a/runtime/entrypoints/quick/callee_save_frame.h b/runtime/entrypoints/quick/callee_save_frame.h
index 8cd6ca6..3bcaf93 100644
--- a/runtime/entrypoints/quick/callee_save_frame.h
+++ b/runtime/entrypoints/quick/callee_save_frame.h
@@ -38,22 +38,24 @@
class ScopedQuickEntrypointChecks {
public:
- explicit ScopedQuickEntrypointChecks(Thread *self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : self_(self) {
- if (kIsDebugBuild) {
+ explicit ScopedQuickEntrypointChecks(Thread *self,
+ bool entry_check = kIsDebugBuild,
+ bool exit_check = kIsDebugBuild)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : self_(self), exit_check_(exit_check) {
+ if (entry_check) {
TestsOnEntry();
}
}
- explicit ScopedQuickEntrypointChecks() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : self_(kIsDebugBuild ? Thread::Current() : nullptr) {
+ ScopedQuickEntrypointChecks() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : self_(kIsDebugBuild ? Thread::Current() : nullptr), exit_check_(kIsDebugBuild) {
if (kIsDebugBuild) {
TestsOnEntry();
}
}
~ScopedQuickEntrypointChecks() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (kIsDebugBuild) {
+ if (exit_check_) {
TestsOnExit();
}
}
@@ -70,6 +72,7 @@
}
Thread* const self_;
+ bool exit_check_;
};
static constexpr size_t GetCalleeSaveFrameSize(InstructionSet isa, Runtime::CalleeSaveType type) {
diff --git a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
index eb1b105..2bb73ef 100644
--- a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
@@ -29,7 +29,9 @@
Thread* self,
uintptr_t lr)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ScopedQuickEntrypointChecks sqec(self);
+ // Instrumentation changes the stack. Thus, when exiting, the stack cannot be verified, so skip
+ // that part.
+ ScopedQuickEntrypointChecks sqec(self, kIsDebugBuild, false);
instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
const void* result;
if (instrumentation->IsDeoptimized(method)) {
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index f5bc080..c029eeb 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -823,7 +823,10 @@
Thread* self,
StackReference<mirror::ArtMethod>* sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ScopedQuickEntrypointChecks sqec(self);
+ // The resolution trampoline stashes the resolved method into the callee-save frame to transport
+ // it. Thus, when exiting, the stack cannot be verified (as the resolved method most likely
+ // does not have the same stack layout as the callee-save method).
+ ScopedQuickEntrypointChecks sqec(self, kIsDebugBuild, false);
// Start new JNI local reference state
JNIEnvExt* env = self->GetJniEnv();
ScopedObjectAccessUnchecked soa(env);
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index e93717e..f3546b1 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -239,7 +239,7 @@
}
template<typename T>
-template<bool kTransactionActive, bool kCheckTransaction>
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline void PrimitiveArray<T>::SetWithoutChecks(int32_t i, T value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
@@ -247,7 +247,7 @@
if (kTransactionActive) {
Runtime::Current()->RecordWriteArray(this, i, GetWithoutChecks(i));
}
- DCHECK(CheckIsValidIndex(i));
+ DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
GetData()[i] = value;
}
// Backward copy where elements are of aligned appropriately for T. Count is in T sized units.
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 832ad68..167f824 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -131,7 +131,9 @@
// TODO fix thread safety analysis broken by the use of template. This should be
// SHARED_LOCKS_REQUIRED(Locks::mutator_lock_).
- template<bool kTransactionActive, bool kCheckTransaction = true>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void SetWithoutChecks(int32_t i, T value) ALWAYS_INLINE NO_THREAD_SAFETY_ANALYSIS;
/*
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 39d0f56..7760ea2 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -59,19 +59,23 @@
OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass);
}
+template<VerifyObjectFlags kVerifyFlags>
inline LockWord Object::GetLockWord(bool as_volatile) {
if (as_volatile) {
- return LockWord(GetField32Volatile(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
+ return LockWord(GetField32Volatile<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
}
- return LockWord(GetField32(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
+ return LockWord(GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
}
+template<VerifyObjectFlags kVerifyFlags>
inline void Object::SetLockWord(LockWord new_val, bool as_volatile) {
// Force use of non-transactional mode and do not check.
if (as_volatile) {
- SetField32Volatile<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
+ SetField32Volatile<false, false, kVerifyFlags>(
+ OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
} else {
- SetField32<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
+ SetField32<false, false, kVerifyFlags>(
+ OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
}
}
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 5afe99f..2c0e626 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -125,7 +125,9 @@
// As_volatile can be false if the mutators are suspended. This is an optimization since it
// avoids the barriers.
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
LockWord GetLockWord(bool as_volatile) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void SetLockWord(LockWord new_val, bool as_volatile) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool CasLockWordWeakSequentiallyConsistent(LockWord old_val, LockWord new_val)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 9736e15..a172197 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -16,6 +16,9 @@
#include "dalvik_system_VMRuntime.h"
+#ifdef HAVE_ANDROID_OS
+extern "C" void android_set_application_target_sdk_version(uint32_t version);
+#endif
#include <limits.h>
#include <ScopedUtfChars.h>
@@ -192,6 +195,12 @@
// Note that targetSdkVersion may be CUR_DEVELOPMENT (10000).
// Note that targetSdkVersion may be 0, meaning "current".
Runtime::Current()->SetTargetSdkVersion(target_sdk_version);
+
+#ifdef HAVE_ANDROID_OS
+ // This part is letting libc/dynamic linker know about current app's
+ // target sdk version to enable compatibility workarounds.
+ android_set_application_target_sdk_version(static_cast<uint32_t>(target_sdk_version));
+#endif
}
static void VMRuntime_registerNativeAllocation(JNIEnv* env, jobject, jint bytes) {
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index 6a0c07d..c36ee05 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -18,6 +18,8 @@
#include <stdint.h>
+#include "indenter.h"
+
namespace art {
constexpr size_t DexRegisterLocationCatalog::kNoLocationEntryIndex;
@@ -203,72 +205,95 @@
DexRegisterLocation location,
const std::string& prefix = "v",
const std::string& suffix = "") {
- os << " " << prefix << dex_register_num << ": "
- << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
- << " (" << location.GetValue() << ")" << suffix << '\n';
+ Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+ std::ostream indented_os(&indent_filter);
+ indented_os << prefix << dex_register_num << ": "
+ << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
+ << " (" << location.GetValue() << ")" << suffix << '\n';
+}
+
+void CodeInfo::DumpStackMap(std::ostream& os,
+ size_t stack_map_num,
+ uint16_t number_of_dex_registers) const {
+ StackMap stack_map = GetStackMapAt(stack_map_num);
+ DumpStackMapHeader(os, stack_map_num);
+ if (stack_map.HasDexRegisterMap(*this)) {
+ DexRegisterMap dex_register_map = GetDexRegisterMapOf(stack_map, number_of_dex_registers);
+ dex_register_map.Dump(os, *this, number_of_dex_registers);
+ }
}
void CodeInfo::DumpStackMapHeader(std::ostream& os, size_t stack_map_num) const {
StackMap stack_map = GetStackMapAt(stack_map_num);
- os << " StackMap " << stack_map_num
- << std::hex
- << " (dex_pc=0x" << stack_map.GetDexPc(*this)
- << ", native_pc_offset=0x" << stack_map.GetNativePcOffset(*this)
- << ", dex_register_map_offset=0x" << stack_map.GetDexRegisterMapOffset(*this)
- << ", inline_info_offset=0x" << stack_map.GetInlineDescriptorOffset(*this)
- << ", register_mask=0x" << stack_map.GetRegisterMask(*this)
- << std::dec
- << ", stack_mask=0b";
+ Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+ std::ostream indented_os(&indent_filter);
+ indented_os << "StackMap " << stack_map_num
+ << std::hex
+ << " (dex_pc=0x" << stack_map.GetDexPc(*this)
+ << ", native_pc_offset=0x" << stack_map.GetNativePcOffset(*this)
+ << ", dex_register_map_offset=0x" << stack_map.GetDexRegisterMapOffset(*this)
+ << ", inline_info_offset=0x" << stack_map.GetInlineDescriptorOffset(*this)
+ << ", register_mask=0x" << stack_map.GetRegisterMask(*this)
+ << std::dec
+ << ", stack_mask=0b";
MemoryRegion stack_mask = stack_map.GetStackMask(*this);
for (size_t i = 0, e = stack_mask.size_in_bits(); i < e; ++i) {
- os << stack_mask.LoadBit(e - i - 1);
+ indented_os << stack_mask.LoadBit(e - i - 1);
}
- os << ")\n";
+ indented_os << ")\n";
};
-void CodeInfo::Dump(std::ostream& os, uint16_t number_of_dex_registers) const {
+void CodeInfo::Dump(std::ostream& os,
+ uint16_t number_of_dex_registers,
+ bool dump_stack_maps) const {
uint32_t code_info_size = GetOverallSize();
size_t number_of_stack_maps = GetNumberOfStackMaps();
- os << " Optimized CodeInfo (size=" << code_info_size
- << ", number_of_dex_registers=" << number_of_dex_registers
- << ", number_of_stack_maps=" << number_of_stack_maps
- << ", has_inline_info=" << HasInlineInfo()
- << ", number_of_bytes_for_inline_info=" << NumberOfBytesForInlineInfo()
- << ", number_of_bytes_for_dex_register_map=" << NumberOfBytesForDexRegisterMap()
- << ", number_of_bytes_for_dex_pc=" << NumberOfBytesForDexPc()
- << ", number_of_bytes_for_native_pc=" << NumberOfBytesForNativePc()
- << ", number_of_bytes_for_register_mask=" << NumberOfBytesForRegisterMask()
- << ")\n";
-
+ Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+ std::ostream indented_os(&indent_filter);
+ indented_os << "Optimized CodeInfo (size=" << code_info_size
+ << ", number_of_dex_registers=" << number_of_dex_registers
+ << ", number_of_stack_maps=" << number_of_stack_maps
+ << ", has_inline_info=" << HasInlineInfo()
+ << ", number_of_bytes_for_inline_info=" << NumberOfBytesForInlineInfo()
+ << ", number_of_bytes_for_dex_register_map=" << NumberOfBytesForDexRegisterMap()
+ << ", number_of_bytes_for_dex_pc=" << NumberOfBytesForDexPc()
+ << ", number_of_bytes_for_native_pc=" << NumberOfBytesForNativePc()
+ << ", number_of_bytes_for_register_mask=" << NumberOfBytesForRegisterMask()
+ << ")\n";
// Display the Dex register location catalog.
- size_t number_of_location_catalog_entries = GetNumberOfDexRegisterLocationCatalogEntries();
- size_t location_catalog_size_in_bytes = GetDexRegisterLocationCatalogSize();
- os << " DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
- << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
- DexRegisterLocationCatalog dex_register_location_catalog = GetDexRegisterLocationCatalog();
- for (size_t i = 0; i < number_of_location_catalog_entries; ++i) {
- DexRegisterLocation location = dex_register_location_catalog.GetDexRegisterLocation(i);
- DumpRegisterMapping(os, i, location, "entry ");
- }
-
+ GetDexRegisterLocationCatalog().Dump(indented_os, *this);
// Display stack maps along with (live) Dex register maps.
- for (size_t i = 0; i < number_of_stack_maps; ++i) {
- StackMap stack_map = GetStackMapAt(i);
- DumpStackMapHeader(os, i);
- if (stack_map.HasDexRegisterMap(*this)) {
- DexRegisterMap dex_register_map = GetDexRegisterMapOf(stack_map, number_of_dex_registers);
- dex_register_map.Dump(os, *this, number_of_dex_registers);
+ if (dump_stack_maps) {
+ for (size_t i = 0; i < number_of_stack_maps; ++i) {
+ DumpStackMap(indented_os, i, number_of_dex_registers);
}
}
// TODO: Dump the stack map's inline information? We need to know more from the caller:
// we need to know the number of dex registers for each inlined method.
}
+void DexRegisterLocationCatalog::Dump(std::ostream& os, const CodeInfo& code_info) {
+ size_t number_of_location_catalog_entries =
+ code_info.GetNumberOfDexRegisterLocationCatalogEntries();
+ size_t location_catalog_size_in_bytes = code_info.GetDexRegisterLocationCatalogSize();
+ Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+ std::ostream indented_os(&indent_filter);
+ indented_os
+ << "DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
+ << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
+ for (size_t i = 0; i < number_of_location_catalog_entries; ++i) {
+ DexRegisterLocation location = GetDexRegisterLocation(i);
+ DumpRegisterMapping(indented_os, i, location, "entry ");
+ }
+}
+
void DexRegisterMap::Dump(std::ostream& os,
const CodeInfo& code_info,
uint16_t number_of_dex_registers) const {
size_t number_of_location_catalog_entries =
code_info.GetNumberOfDexRegisterLocationCatalogEntries();
+ Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+ std::ostream indented_os(&indent_filter);
// TODO: Display the bit mask of live Dex registers.
for (size_t j = 0; j < number_of_dex_registers; ++j) {
if (IsDexRegisterLive(j)) {
@@ -276,7 +301,7 @@
j, number_of_dex_registers, number_of_location_catalog_entries);
DexRegisterLocation location = GetDexRegisterLocation(j, number_of_dex_registers, code_info);
DumpRegisterMapping(
- os, j, location, "v",
+ indented_os, j, location, "v",
"\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]");
}
}
@@ -285,18 +310,20 @@
void InlineInfo::Dump(std::ostream& os,
const CodeInfo& code_info,
uint16_t number_of_dex_registers[]) const {
- os << "InlineInfo with depth " << static_cast<uint32_t>(GetDepth()) << "\n";
+ Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+ std::ostream indented_os(&indent_filter);
+ indented_os << "InlineInfo with depth " << static_cast<uint32_t>(GetDepth()) << "\n";
for (size_t i = 0; i < GetDepth(); ++i) {
- os << " At depth " << i
- << std::hex
- << " (dex_pc=0x" << GetDexPcAtDepth(i)
- << ", method_index=0x" << GetMethodIndexAtDepth(i)
- << ")\n";
+ indented_os << " At depth " << i
+ << std::hex
+ << " (dex_pc=0x" << GetDexPcAtDepth(i)
+ << ", method_index=0x" << GetMethodIndexAtDepth(i)
+ << ")\n";
if (HasDexRegisterMapAtDepth(i)) {
DexRegisterMap dex_register_map =
code_info.GetDexRegisterMapAtDepth(i, *this, number_of_dex_registers[i]);
- dex_register_map.Dump(os, code_info, number_of_dex_registers[i]);
+ dex_register_map.Dump(indented_os, code_info, number_of_dex_registers[i]);
}
}
}
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index 69e57ff..eefdaa7 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -356,6 +356,8 @@
return region_.size();
}
+ void Dump(std::ostream& os, const CodeInfo& code_info);
+
// Special (invalid) Dex register location catalog entry index meaning
// that there is no location for a given Dex register (i.e., it is
// mapped to a DexRegisterLocation::Kind::kNone location).
@@ -1046,7 +1048,15 @@
return StackMap();
}
- void Dump(std::ostream& os, uint16_t number_of_dex_registers) const;
+ // Dump this CodeInfo object on `os`. If `dump_stack_maps` is true,
+ // also dump the stack maps and the associated Dex register maps.
+ void Dump(std::ostream& os, uint16_t number_of_dex_registers, bool dump_stack_maps) const;
+
+ // Dump stack map number `stack_map_num` as well as associated data on `os`,
+ // such as Dex register locations.
+ void DumpStackMap(std::ostream& os, size_t stack_map_num, uint16_t number_of_dex_registers) const;
+ // Dump the header of stack map number `stack_map_num` on `os`, without
+ // associated data.
void DumpStackMapHeader(std::ostream& os, size_t stack_map_num) const;
private: