Clean up OatQuickMethodHeader after Quick removal.
This reduces the size of the pre-header by 8 bytes, reducing
oat file size and mmapped .text section size. The memory
needed to store a CompiledMethod by dex2oat is also reduced,
for 32-bit dex2oat by 8B and for 64-bit dex2oat by 16B. The
aosp_flounder-userdebug 32-bit and 64-bit boot.oat are each
about 1.1MiB smaller.
Disable the broken StubTest.IMT, b/27991555 .
Change-Id: I05fe45c28c8ffb7a0fa8b1117b969786748b1039
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index 6483ef6..0001b67 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -59,36 +59,20 @@
ArrayRef<const uint8_t> vmap_table = compiled_method->GetVmapTable();
uint32_t vmap_table_offset = vmap_table.empty() ? 0u
: sizeof(OatQuickMethodHeader) + vmap_table.size();
- ArrayRef<const uint8_t> mapping_table = compiled_method->GetMappingTable();
- bool mapping_table_used = !mapping_table.empty();
- size_t mapping_table_size = mapping_table.size();
- uint32_t mapping_table_offset = !mapping_table_used ? 0u
- : sizeof(OatQuickMethodHeader) + vmap_table.size() + mapping_table_size;
- ArrayRef<const uint8_t> gc_map = compiled_method->GetGcMap();
- bool gc_map_used = !gc_map.empty();
- size_t gc_map_size = gc_map.size();
- uint32_t gc_map_offset = !gc_map_used ? 0u
- : sizeof(OatQuickMethodHeader) + vmap_table.size() + mapping_table_size + gc_map_size;
- OatQuickMethodHeader method_header(mapping_table_offset, vmap_table_offset, gc_map_offset,
+ OatQuickMethodHeader method_header(vmap_table_offset,
compiled_method->GetFrameSizeInBytes(),
compiled_method->GetCoreSpillMask(),
- compiled_method->GetFpSpillMask(), code_size);
+ compiled_method->GetFpSpillMask(),
+ code_size);
header_code_and_maps_chunks_.push_back(std::vector<uint8_t>());
std::vector<uint8_t>* chunk = &header_code_and_maps_chunks_.back();
const size_t max_padding = GetInstructionSetAlignment(compiled_method->GetInstructionSet());
- const size_t size =
- gc_map_size + mapping_table_size + vmap_table.size() + sizeof(method_header) + code_size;
+ const size_t size = vmap_table.size() + sizeof(method_header) + code_size;
chunk->reserve(size + max_padding);
chunk->resize(sizeof(method_header));
memcpy(&(*chunk)[0], &method_header, sizeof(method_header));
chunk->insert(chunk->begin(), vmap_table.begin(), vmap_table.end());
- if (mapping_table_used) {
- chunk->insert(chunk->begin(), mapping_table.begin(), mapping_table.end());
- }
- if (gc_map_used) {
- chunk->insert(chunk->begin(), gc_map.begin(), gc_map.end());
- }
chunk->insert(chunk->end(), code.begin(), code.end());
CHECK_EQ(chunk->size(), size);
const void* unaligned_code_ptr = chunk->data() + (size - code_size);
diff --git a/compiler/compiled_method.cc b/compiler/compiled_method.cc
index 9551d22..f06d90c 100644
--- a/compiler/compiled_method.cc
+++ b/compiler/compiled_method.cc
@@ -106,9 +106,7 @@
const uint32_t core_spill_mask,
const uint32_t fp_spill_mask,
const ArrayRef<const SrcMapElem>& src_mapping_table,
- const ArrayRef<const uint8_t>& mapping_table,
const ArrayRef<const uint8_t>& vmap_table,
- const ArrayRef<const uint8_t>& native_gc_map,
const ArrayRef<const uint8_t>& cfi_info,
const ArrayRef<const LinkerPatch>& patches)
: CompiledCode(driver, instruction_set, quick_code),
@@ -116,9 +114,7 @@
fp_spill_mask_(fp_spill_mask),
src_mapping_table_(
driver->GetCompiledMethodStorage()->DeduplicateSrcMappingTable(src_mapping_table)),
- mapping_table_(driver->GetCompiledMethodStorage()->DeduplicateMappingTable(mapping_table)),
vmap_table_(driver->GetCompiledMethodStorage()->DeduplicateVMapTable(vmap_table)),
- gc_map_(driver->GetCompiledMethodStorage()->DeduplicateGCMap(native_gc_map)),
cfi_info_(driver->GetCompiledMethodStorage()->DeduplicateCFIInfo(cfi_info)),
patches_(driver->GetCompiledMethodStorage()->DeduplicateLinkerPatches(patches)) {
}
@@ -131,15 +127,20 @@
const uint32_t core_spill_mask,
const uint32_t fp_spill_mask,
const ArrayRef<const SrcMapElem>& src_mapping_table,
- const ArrayRef<const uint8_t>& mapping_table,
const ArrayRef<const uint8_t>& vmap_table,
- const ArrayRef<const uint8_t>& native_gc_map,
const ArrayRef<const uint8_t>& cfi_info,
const ArrayRef<const LinkerPatch>& patches) {
SwapAllocator<CompiledMethod> alloc(driver->GetCompiledMethodStorage()->GetSwapSpaceAllocator());
CompiledMethod* ret = alloc.allocate(1);
- alloc.construct(ret, driver, instruction_set, quick_code, frame_size_in_bytes, core_spill_mask,
- fp_spill_mask, src_mapping_table, mapping_table, vmap_table, native_gc_map,
+ alloc.construct(ret,
+ driver,
+ instruction_set,
+ quick_code,
+ frame_size_in_bytes,
+ core_spill_mask,
+ fp_spill_mask,
+ src_mapping_table,
+ vmap_table,
cfi_info, patches);
return ret;
}
@@ -154,9 +155,7 @@
CompiledMethodStorage* storage = GetCompilerDriver()->GetCompiledMethodStorage();
storage->ReleaseLinkerPatches(patches_);
storage->ReleaseCFIInfo(cfi_info_);
- storage->ReleaseGCMap(gc_map_);
storage->ReleaseVMapTable(vmap_table_);
- storage->ReleaseMappingTable(mapping_table_);
storage->ReleaseSrcMappingTable(src_mapping_table_);
}
diff --git a/compiler/compiled_method.h b/compiler/compiled_method.h
index 70161eb..9479ff3 100644
--- a/compiler/compiled_method.h
+++ b/compiler/compiled_method.h
@@ -377,9 +377,7 @@
const uint32_t core_spill_mask,
const uint32_t fp_spill_mask,
const ArrayRef<const SrcMapElem>& src_mapping_table,
- const ArrayRef<const uint8_t>& mapping_table,
const ArrayRef<const uint8_t>& vmap_table,
- const ArrayRef<const uint8_t>& native_gc_map,
const ArrayRef<const uint8_t>& cfi_info,
const ArrayRef<const LinkerPatch>& patches);
@@ -393,9 +391,7 @@
const uint32_t core_spill_mask,
const uint32_t fp_spill_mask,
const ArrayRef<const SrcMapElem>& src_mapping_table,
- const ArrayRef<const uint8_t>& mapping_table,
const ArrayRef<const uint8_t>& vmap_table,
- const ArrayRef<const uint8_t>& native_gc_map,
const ArrayRef<const uint8_t>& cfi_info,
const ArrayRef<const LinkerPatch>& patches);
@@ -417,18 +413,10 @@
return GetArray(src_mapping_table_);
}
- ArrayRef<const uint8_t> GetMappingTable() const {
- return GetArray(mapping_table_);
- }
-
ArrayRef<const uint8_t> GetVmapTable() const {
return GetArray(vmap_table_);
}
- ArrayRef<const uint8_t> GetGcMap() const {
- return GetArray(gc_map_);
- }
-
ArrayRef<const uint8_t> GetCFIInfo() const {
return GetArray(cfi_info_);
}
@@ -446,14 +434,8 @@
const uint32_t fp_spill_mask_;
// For quick code, a set of pairs (PC, DEX) mapping from native PC offset to DEX offset.
const LengthPrefixedArray<SrcMapElem>* const src_mapping_table_;
- // For quick code, a uleb128 encoded map from native PC offset to dex PC aswell as dex PC to
- // native PC offset. Size prefixed.
- const LengthPrefixedArray<uint8_t>* const mapping_table_;
// For quick code, a uleb128 encoded map from GPR/FPR register to dex register. Size prefixed.
const LengthPrefixedArray<uint8_t>* const vmap_table_;
- // For quick code, a map keyed by native PC indices to bitmaps describing what dalvik registers
- // are live.
- const LengthPrefixedArray<uint8_t>* const gc_map_;
// For quick code, a FDE entry for the debug_frame section.
const LengthPrefixedArray<uint8_t>* const cfi_info_;
// For quick code, linker patches needed by the method.
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index efddeba..3ce786e 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -363,9 +363,7 @@
0,
0,
ArrayRef<const SrcMapElem>(), // src_mapping_table
- ArrayRef<const uint8_t>(), // mapping_table
ArrayRef<const uint8_t>(builder.GetData()), // vmap_table
- ArrayRef<const uint8_t>(), // gc_map
ArrayRef<const uint8_t>(), // cfi data
ArrayRef<const LinkerPatch>());
}
diff --git a/compiler/driver/compiled_method_storage.cc b/compiler/driver/compiled_method_storage.cc
index 510613e..a0a8f81 100644
--- a/compiler/driver/compiled_method_storage.cc
+++ b/compiler/driver/compiled_method_storage.cc
@@ -174,11 +174,8 @@
dedupe_code_("dedupe code", LengthPrefixedArrayAlloc<uint8_t>(swap_space_.get())),
dedupe_src_mapping_table_("dedupe source mapping table",
LengthPrefixedArrayAlloc<SrcMapElem>(swap_space_.get())),
- dedupe_mapping_table_("dedupe mapping table",
- LengthPrefixedArrayAlloc<uint8_t>(swap_space_.get())),
dedupe_vmap_table_("dedupe vmap table",
LengthPrefixedArrayAlloc<uint8_t>(swap_space_.get())),
- dedupe_gc_map_("dedupe gc map", LengthPrefixedArrayAlloc<uint8_t>(swap_space_.get())),
dedupe_cfi_info_("dedupe cfi info", LengthPrefixedArrayAlloc<uint8_t>(swap_space_.get())),
dedupe_linker_patches_("dedupe cfi info",
LengthPrefixedArrayAlloc<LinkerPatch>(swap_space_.get())) {
@@ -196,9 +193,7 @@
if (extended) {
Thread* self = Thread::Current();
os << "\nCode dedupe: " << dedupe_code_.DumpStats(self);
- os << "\nMapping table dedupe: " << dedupe_mapping_table_.DumpStats(self);
os << "\nVmap table dedupe: " << dedupe_vmap_table_.DumpStats(self);
- os << "\nGC map dedupe: " << dedupe_gc_map_.DumpStats(self);
os << "\nCFI info dedupe: " << dedupe_cfi_info_.DumpStats(self);
}
}
@@ -221,15 +216,6 @@
ReleaseArrayIfNotDeduplicated(src_map);
}
-const LengthPrefixedArray<uint8_t>* CompiledMethodStorage::DeduplicateMappingTable(
- const ArrayRef<const uint8_t>& table) {
- return AllocateOrDeduplicateArray(table, &dedupe_mapping_table_);
-}
-
-void CompiledMethodStorage::ReleaseMappingTable(const LengthPrefixedArray<uint8_t>* table) {
- ReleaseArrayIfNotDeduplicated(table);
-}
-
const LengthPrefixedArray<uint8_t>* CompiledMethodStorage::DeduplicateVMapTable(
const ArrayRef<const uint8_t>& table) {
return AllocateOrDeduplicateArray(table, &dedupe_vmap_table_);
@@ -239,15 +225,6 @@
ReleaseArrayIfNotDeduplicated(table);
}
-const LengthPrefixedArray<uint8_t>* CompiledMethodStorage::DeduplicateGCMap(
- const ArrayRef<const uint8_t>& gc_map) {
- return AllocateOrDeduplicateArray(gc_map, &dedupe_gc_map_);
-}
-
-void CompiledMethodStorage::ReleaseGCMap(const LengthPrefixedArray<uint8_t>* gc_map) {
- ReleaseArrayIfNotDeduplicated(gc_map);
-}
-
const LengthPrefixedArray<uint8_t>* CompiledMethodStorage::DeduplicateCFIInfo(
const ArrayRef<const uint8_t>& cfi_info) {
return AllocateOrDeduplicateArray(cfi_info, &dedupe_cfi_info_);
diff --git a/compiler/driver/compiled_method_storage.h b/compiler/driver/compiled_method_storage.h
index d6961a0..8674abf 100644
--- a/compiler/driver/compiled_method_storage.h
+++ b/compiler/driver/compiled_method_storage.h
@@ -56,15 +56,9 @@
const ArrayRef<const SrcMapElem>& src_map);
void ReleaseSrcMappingTable(const LengthPrefixedArray<SrcMapElem>* src_map);
- const LengthPrefixedArray<uint8_t>* DeduplicateMappingTable(const ArrayRef<const uint8_t>& table);
- void ReleaseMappingTable(const LengthPrefixedArray<uint8_t>* table);
-
const LengthPrefixedArray<uint8_t>* DeduplicateVMapTable(const ArrayRef<const uint8_t>& table);
void ReleaseVMapTable(const LengthPrefixedArray<uint8_t>* table);
- const LengthPrefixedArray<uint8_t>* DeduplicateGCMap(const ArrayRef<const uint8_t>& gc_map);
- void ReleaseGCMap(const LengthPrefixedArray<uint8_t>* gc_map);
-
const LengthPrefixedArray<uint8_t>* DeduplicateCFIInfo(const ArrayRef<const uint8_t>& cfi_info);
void ReleaseCFIInfo(const LengthPrefixedArray<uint8_t>* cfi_info);
@@ -103,9 +97,7 @@
ArrayDedupeSet<uint8_t> dedupe_code_;
ArrayDedupeSet<SrcMapElem> dedupe_src_mapping_table_;
- ArrayDedupeSet<uint8_t> dedupe_mapping_table_;
ArrayDedupeSet<uint8_t> dedupe_vmap_table_;
- ArrayDedupeSet<uint8_t> dedupe_gc_map_;
ArrayDedupeSet<uint8_t> dedupe_cfi_info_;
ArrayDedupeSet<LinkerPatch> dedupe_linker_patches_;
diff --git a/compiler/driver/compiled_method_storage_test.cc b/compiler/driver/compiled_method_storage_test.cc
index 0695cb5..9e0c22c 100644
--- a/compiler/driver/compiled_method_storage_test.cc
+++ b/compiler/driver/compiled_method_storage_test.cc
@@ -61,24 +61,12 @@
ArrayRef<const SrcMapElem>(raw_src_map1),
ArrayRef<const SrcMapElem>(raw_src_map2),
};
- const uint8_t raw_mapping_table1[] = { 5, 6, 7 };
- const uint8_t raw_mapping_table2[] = { 7, 6, 5, 4 };
- ArrayRef<const uint8_t> mapping_table[] = {
- ArrayRef<const uint8_t>(raw_mapping_table1),
- ArrayRef<const uint8_t>(raw_mapping_table2),
- };
const uint8_t raw_vmap_table1[] = { 2, 4, 6 };
const uint8_t raw_vmap_table2[] = { 7, 5, 3, 1 };
ArrayRef<const uint8_t> vmap_table[] = {
ArrayRef<const uint8_t>(raw_vmap_table1),
ArrayRef<const uint8_t>(raw_vmap_table2),
};
- const uint8_t raw_gc_map1[] = { 9, 8, 7 };
- const uint8_t raw_gc_map2[] = { 6, 7, 8, 9 };
- ArrayRef<const uint8_t> gc_map[] = {
- ArrayRef<const uint8_t>(raw_gc_map1),
- ArrayRef<const uint8_t>(raw_gc_map2),
- };
const uint8_t raw_cfi_info1[] = { 1, 3, 5 };
const uint8_t raw_cfi_info2[] = { 8, 6, 4, 2 };
ArrayRef<const uint8_t> cfi_info[] = {
@@ -102,49 +90,37 @@
compiled_methods.reserve(1u << 7);
for (auto&& c : code) {
for (auto&& s : src_map) {
- for (auto&& m : mapping_table) {
- for (auto&& v : vmap_table) {
- for (auto&& g : gc_map) {
- for (auto&& f : cfi_info) {
- for (auto&& p : patches) {
- compiled_methods.push_back(CompiledMethod::SwapAllocCompiledMethod(
- &driver, kNone, c, 0u, 0u, 0u, s, m, v, g, f, p));
- }
- }
+ for (auto&& v : vmap_table) {
+ for (auto&& f : cfi_info) {
+ for (auto&& p : patches) {
+ compiled_methods.push_back(CompiledMethod::SwapAllocCompiledMethod(
+ &driver, kNone, c, 0u, 0u, 0u, s, v, f, p));
}
}
}
}
}
- constexpr size_t code_bit = 1u << 6;
- constexpr size_t src_map_bit = 1u << 5;
- constexpr size_t mapping_table_bit = 1u << 4;
- constexpr size_t vmap_table_bit = 1u << 3;
- constexpr size_t gc_map_bit = 1u << 2;
+ constexpr size_t code_bit = 1u << 4;
+ constexpr size_t src_map_bit = 1u << 3;
+ constexpr size_t vmap_table_bit = 1u << 2;
constexpr size_t cfi_info_bit = 1u << 1;
constexpr size_t patches_bit = 1u << 0;
- CHECK_EQ(compiled_methods.size(), 1u << 7);
+ CHECK_EQ(compiled_methods.size(), 1u << 5);
for (size_t i = 0; i != compiled_methods.size(); ++i) {
for (size_t j = 0; j != compiled_methods.size(); ++j) {
CompiledMethod* lhs = compiled_methods[i];
CompiledMethod* rhs = compiled_methods[j];
bool same_code = ((i ^ j) & code_bit) == 0u;
bool same_src_map = ((i ^ j) & src_map_bit) == 0u;
- bool same_mapping_table = ((i ^ j) & mapping_table_bit) == 0u;
bool same_vmap_table = ((i ^ j) & vmap_table_bit) == 0u;
- bool same_gc_map = ((i ^ j) & gc_map_bit) == 0u;
bool same_cfi_info = ((i ^ j) & cfi_info_bit) == 0u;
bool same_patches = ((i ^ j) & patches_bit) == 0u;
ASSERT_EQ(same_code, lhs->GetQuickCode().data() == rhs->GetQuickCode().data())
<< i << " " << j;
ASSERT_EQ(same_src_map, lhs->GetSrcMappingTable().data() == rhs->GetSrcMappingTable().data())
<< i << " " << j;
- ASSERT_EQ(same_mapping_table, lhs->GetMappingTable().data() == rhs->GetMappingTable().data())
- << i << " " << j;
ASSERT_EQ(same_vmap_table, lhs->GetVmapTable().data() == rhs->GetVmapTable().data())
<< i << " " << j;
- ASSERT_EQ(same_gc_map, lhs->GetGcMap().data() == rhs->GetGcMap().data())
- << i << " " << j;
ASSERT_EQ(same_cfi_info, lhs->GetCFIInfo().data() == rhs->GetCFIInfo().data())
<< i << " " << j;
ASSERT_EQ(same_patches, lhs->GetPatches().data() == rhs->GetPatches().data())
diff --git a/compiler/exception_test.cc b/compiler/exception_test.cc
new file mode 100644
index 0000000..38ac052
--- /dev/null
+++ b/compiler/exception_test.cc
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2011 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 <memory>
+
+#include "base/arena_allocator.h"
+#include "class_linker.h"
+#include "common_runtime_test.h"
+#include "dex_file.h"
+#include "dex_file-inl.h"
+#include "gtest/gtest.h"
+#include "leb128.h"
+#include "mirror/class-inl.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/object-inl.h"
+#include "mirror/stack_trace_element.h"
+#include "oat_quick_method_header.h"
+#include "optimizing/stack_map_stream.h"
+#include "runtime.h"
+#include "scoped_thread_state_change.h"
+#include "handle_scope-inl.h"
+#include "thread.h"
+
+namespace art {
+
+class ExceptionTest : public CommonRuntimeTest {
+ protected:
+ virtual void SetUp() {
+ CommonRuntimeTest::SetUp();
+
+ ScopedObjectAccess soa(Thread::Current());
+ StackHandleScope<2> hs(soa.Self());
+ Handle<mirror::ClassLoader> class_loader(
+ hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("ExceptionHandle"))));
+ my_klass_ = class_linker_->FindClass(soa.Self(), "LExceptionHandle;", class_loader);
+ ASSERT_TRUE(my_klass_ != nullptr);
+ Handle<mirror::Class> klass(hs.NewHandle(my_klass_));
+ class_linker_->EnsureInitialized(soa.Self(), klass, true, true);
+ my_klass_ = klass.Get();
+
+ dex_ = my_klass_->GetDexCache()->GetDexFile();
+
+ uint32_t code_size = 12;
+ for (size_t i = 0 ; i < code_size; i++) {
+ fake_code_.push_back(0x70 | i);
+ }
+
+ ArenaPool pool;
+ ArenaAllocator allocator(&pool);
+ StackMapStream stack_maps(&allocator);
+ stack_maps.BeginStackMapEntry(/* dex_pc */ 3u,
+ /* native_pc_offset */ 3u,
+ /* register_mask */ 0u,
+ /* sp_mask */ nullptr,
+ /* num_dex_registers */ 0u,
+ /* inlining_depth */ 0u);
+ stack_maps.EndStackMapEntry();
+ size_t stack_maps_size = stack_maps.PrepareForFillIn();
+ size_t stack_maps_offset = stack_maps_size + sizeof(OatQuickMethodHeader);
+
+ fake_header_code_and_maps_.resize(stack_maps_offset + fake_code_.size());
+ MemoryRegion stack_maps_region(&fake_header_code_and_maps_[0], stack_maps_size);
+ stack_maps.FillIn(stack_maps_region);
+ OatQuickMethodHeader method_header(stack_maps_offset, 4 * sizeof(void*), 0u, 0u, code_size);
+ memcpy(&fake_header_code_and_maps_[stack_maps_size], &method_header, sizeof(method_header));
+ std::copy(fake_code_.begin(),
+ fake_code_.end(),
+ fake_header_code_and_maps_.begin() + stack_maps_offset);
+
+ // Align the code.
+ const size_t alignment = GetInstructionSetAlignment(kRuntimeISA);
+ fake_header_code_and_maps_.reserve(fake_header_code_and_maps_.size() + alignment);
+ const void* unaligned_code_ptr =
+ fake_header_code_and_maps_.data() + (fake_header_code_and_maps_.size() - code_size);
+ size_t offset = dchecked_integral_cast<size_t>(reinterpret_cast<uintptr_t>(unaligned_code_ptr));
+ size_t padding = RoundUp(offset, alignment) - offset;
+ // Make sure no resizing takes place.
+ CHECK_GE(fake_header_code_and_maps_.capacity(), fake_header_code_and_maps_.size() + padding);
+ fake_header_code_and_maps_.insert(fake_header_code_and_maps_.begin(), padding, 0);
+ const void* code_ptr = reinterpret_cast<const uint8_t*>(unaligned_code_ptr) + padding;
+ CHECK_EQ(code_ptr,
+ static_cast<const void*>(fake_header_code_and_maps_.data() +
+ (fake_header_code_and_maps_.size() - code_size)));
+
+ if (kRuntimeISA == kArm) {
+ // Check that the Thumb2 adjustment will be a NOP, see EntryPointToCodePointer().
+ CHECK_ALIGNED(stack_maps_offset, 2);
+ }
+
+ method_f_ = my_klass_->FindVirtualMethod("f", "()I", sizeof(void*));
+ ASSERT_TRUE(method_f_ != nullptr);
+ method_f_->SetEntryPointFromQuickCompiledCode(code_ptr);
+
+ method_g_ = my_klass_->FindVirtualMethod("g", "(I)V", sizeof(void*));
+ ASSERT_TRUE(method_g_ != nullptr);
+ method_g_->SetEntryPointFromQuickCompiledCode(code_ptr);
+ }
+
+ const DexFile* dex_;
+
+ std::vector<uint8_t> fake_code_;
+ std::vector<uint8_t> fake_header_code_and_maps_;
+
+ ArtMethod* method_f_;
+ ArtMethod* method_g_;
+
+ private:
+ mirror::Class* my_klass_;
+};
+
+TEST_F(ExceptionTest, FindCatchHandler) {
+ ScopedObjectAccess soa(Thread::Current());
+ const DexFile::CodeItem* code_item = dex_->GetCodeItem(method_f_->GetCodeItemOffset());
+
+ ASSERT_TRUE(code_item != nullptr);
+
+ ASSERT_EQ(2u, code_item->tries_size_);
+ ASSERT_NE(0u, code_item->insns_size_in_code_units_);
+
+ const DexFile::TryItem *t0, *t1;
+ t0 = dex_->GetTryItems(*code_item, 0);
+ t1 = dex_->GetTryItems(*code_item, 1);
+ EXPECT_LE(t0->start_addr_, t1->start_addr_);
+ {
+ CatchHandlerIterator iter(*code_item, 4 /* Dex PC in the first try block */);
+ EXPECT_STREQ("Ljava/io/IOException;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex()));
+ ASSERT_TRUE(iter.HasNext());
+ iter.Next();
+ EXPECT_STREQ("Ljava/lang/Exception;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex()));
+ ASSERT_TRUE(iter.HasNext());
+ iter.Next();
+ EXPECT_FALSE(iter.HasNext());
+ }
+ {
+ CatchHandlerIterator iter(*code_item, 8 /* Dex PC in the second try block */);
+ EXPECT_STREQ("Ljava/io/IOException;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex()));
+ ASSERT_TRUE(iter.HasNext());
+ iter.Next();
+ EXPECT_FALSE(iter.HasNext());
+ }
+ {
+ CatchHandlerIterator iter(*code_item, 11 /* Dex PC not in any try block */);
+ EXPECT_FALSE(iter.HasNext());
+ }
+}
+
+TEST_F(ExceptionTest, StackTraceElement) {
+ Thread* thread = Thread::Current();
+ thread->TransitionFromSuspendedToRunnable();
+ bool started = runtime_->Start();
+ CHECK(started);
+ JNIEnv* env = thread->GetJniEnv();
+ ScopedObjectAccess soa(env);
+
+ std::vector<uintptr_t> fake_stack;
+ Runtime* r = Runtime::Current();
+ r->SetInstructionSet(kRuntimeISA);
+ ArtMethod* save_method = r->CreateCalleeSaveMethod();
+ r->SetCalleeSaveMethod(save_method, Runtime::kSaveAll);
+ QuickMethodFrameInfo frame_info = r->GetRuntimeMethodFrameInfo(save_method);
+
+ ASSERT_EQ(kStackAlignment, 16U);
+ // ASSERT_EQ(sizeof(uintptr_t), sizeof(uint32_t));
+
+
+ // Create three fake stack frames with mapping data created in SetUp. We map offset 3 in the
+ // code to dex pc 3.
+ const uint32_t dex_pc = 3;
+
+ // Create the stack frame for the callee save method, expected by the runtime.
+ fake_stack.push_back(reinterpret_cast<uintptr_t>(save_method));
+ for (size_t i = 0; i < frame_info.FrameSizeInBytes() - 2 * sizeof(uintptr_t);
+ i += sizeof(uintptr_t)) {
+ fake_stack.push_back(0);
+ }
+
+ fake_stack.push_back(method_g_->GetOatQuickMethodHeader(0)->ToNativeQuickPc(
+ method_g_, dex_pc, /* is_catch_handler */ false)); // return pc
+
+ // Create/push fake 16byte stack frame for method g
+ fake_stack.push_back(reinterpret_cast<uintptr_t>(method_g_));
+ fake_stack.push_back(0);
+ fake_stack.push_back(0);
+ fake_stack.push_back(method_g_->GetOatQuickMethodHeader(0)->ToNativeQuickPc(
+ method_g_, dex_pc, /* is_catch_handler */ false)); // return pc
+
+ // Create/push fake 16byte stack frame for method f
+ fake_stack.push_back(reinterpret_cast<uintptr_t>(method_f_));
+ fake_stack.push_back(0);
+ fake_stack.push_back(0);
+ fake_stack.push_back(0xEBAD6070); // return pc
+
+ // Push Method* of null to terminate the trace
+ fake_stack.push_back(0);
+
+ // Push null values which will become null incoming arguments.
+ fake_stack.push_back(0);
+ fake_stack.push_back(0);
+ fake_stack.push_back(0);
+
+ // Set up thread to appear as if we called out of method_g_ at pc dex 3
+ thread->SetTopOfStack(reinterpret_cast<ArtMethod**>(&fake_stack[0]));
+
+ jobject internal = thread->CreateInternalStackTrace<false>(soa);
+ ASSERT_TRUE(internal != nullptr);
+ jobjectArray ste_array = Thread::InternalStackTraceToStackTraceElementArray(soa, internal);
+ ASSERT_TRUE(ste_array != nullptr);
+ auto* trace_array = soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>*>(ste_array);
+
+ ASSERT_TRUE(trace_array != nullptr);
+ ASSERT_TRUE(trace_array->Get(0) != nullptr);
+ EXPECT_STREQ("ExceptionHandle",
+ trace_array->Get(0)->GetDeclaringClass()->ToModifiedUtf8().c_str());
+ EXPECT_STREQ("ExceptionHandle.java",
+ trace_array->Get(0)->GetFileName()->ToModifiedUtf8().c_str());
+ EXPECT_STREQ("g", trace_array->Get(0)->GetMethodName()->ToModifiedUtf8().c_str());
+ EXPECT_EQ(37, trace_array->Get(0)->GetLineNumber());
+
+ ASSERT_TRUE(trace_array->Get(1) != nullptr);
+ EXPECT_STREQ("ExceptionHandle",
+ trace_array->Get(1)->GetDeclaringClass()->ToModifiedUtf8().c_str());
+ EXPECT_STREQ("ExceptionHandle.java",
+ trace_array->Get(1)->GetFileName()->ToModifiedUtf8().c_str());
+ EXPECT_STREQ("f", trace_array->Get(1)->GetMethodName()->ToModifiedUtf8().c_str());
+ EXPECT_EQ(22, trace_array->Get(1)->GetLineNumber());
+
+ thread->SetTopOfStack(nullptr); // Disarm the assertion that no code is running when we detach.
+}
+
+} // namespace art
diff --git a/compiler/gc_map_builder.h b/compiler/gc_map_builder.h
deleted file mode 100644
index 2ef7f1a..0000000
--- a/compiler/gc_map_builder.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2014 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_GC_MAP_BUILDER_H_
-#define ART_COMPILER_GC_MAP_BUILDER_H_
-
-#include <vector>
-
-#include "base/bit_utils.h"
-#include "gc_map.h"
-
-namespace art {
-
-class GcMapBuilder {
- public:
- template <typename Vector>
- GcMapBuilder(Vector* table, size_t entries, uint32_t max_native_offset,
- size_t references_width)
- : entries_(entries), references_width_(entries != 0u ? references_width : 0u),
- native_offset_width_(entries != 0 && max_native_offset != 0
- ? sizeof(max_native_offset) - CLZ(max_native_offset) / 8u
- : 0u),
- in_use_(entries) {
- static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
-
- // Resize table and set up header.
- table->resize((EntryWidth() * entries) + sizeof(uint32_t));
- table_ = table->data();
- CHECK_LT(native_offset_width_, 1U << 3);
- (*table)[0] = native_offset_width_ & 7;
- CHECK_LT(references_width_, 1U << 13);
- (*table)[0] |= (references_width_ << 3) & 0xFF;
- (*table)[1] = (references_width_ >> 5) & 0xFF;
- CHECK_LT(entries, 1U << 16);
- (*table)[2] = entries & 0xFF;
- (*table)[3] = (entries >> 8) & 0xFF;
- }
-
- void AddEntry(uint32_t native_offset, const uint8_t* references) {
- size_t table_index = TableIndex(native_offset);
- while (in_use_[table_index]) {
- table_index = (table_index + 1) % entries_;
- }
- in_use_[table_index] = true;
- SetCodeOffset(table_index, native_offset);
- DCHECK_EQ(native_offset, GetCodeOffset(table_index));
- SetReferences(table_index, references);
- }
-
- private:
- size_t TableIndex(uint32_t native_offset) {
- return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_;
- }
-
- uint32_t GetCodeOffset(size_t table_index) {
- uint32_t native_offset = 0;
- size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
- for (size_t i = 0; i < native_offset_width_; i++) {
- native_offset |= table_[table_offset + i] << (i * 8);
- }
- return native_offset;
- }
-
- void SetCodeOffset(size_t table_index, uint32_t native_offset) {
- size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
- for (size_t i = 0; i < native_offset_width_; i++) {
- table_[table_offset + i] = (native_offset >> (i * 8)) & 0xFF;
- }
- }
-
- void SetReferences(size_t table_index, const uint8_t* references) {
- size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
- memcpy(&table_[table_offset + native_offset_width_], references, references_width_);
- }
-
- size_t EntryWidth() const {
- return native_offset_width_ + references_width_;
- }
-
- // Number of entries in the table.
- const size_t entries_;
- // Number of bytes used to encode the reference bitmap.
- const size_t references_width_;
- // Number of bytes used to encode a native offset.
- const size_t native_offset_width_;
- // Entries that are in use.
- std::vector<bool> in_use_;
- // The table we're building.
- uint8_t* table_;
-};
-
-} // namespace art
-
-#endif // ART_COMPILER_GC_MAP_BUILDER_H_
diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc
index e920460..b8cda24 100644
--- a/compiler/jni/quick/jni_compiler.cc
+++ b/compiler/jni/quick/jni_compiler.cc
@@ -488,9 +488,7 @@
main_jni_conv->CoreSpillMask(),
main_jni_conv->FpSpillMask(),
ArrayRef<const SrcMapElem>(),
- ArrayRef<const uint8_t>(), // mapping_table.
ArrayRef<const uint8_t>(), // vmap_table.
- ArrayRef<const uint8_t>(), // native_gc_map.
ArrayRef<const uint8_t>(*jni_asm->cfi().data()),
ArrayRef<const LinkerPatch>());
}
diff --git a/compiler/linker/relative_patcher_test.h b/compiler/linker/relative_patcher_test.h
index bf61ea0..c07de79 100644
--- a/compiler/linker/relative_patcher_test.h
+++ b/compiler/linker/relative_patcher_test.h
@@ -85,9 +85,15 @@
const ArrayRef<const LinkerPatch>& patches) {
compiled_method_refs_.push_back(method_ref);
compiled_methods_.emplace_back(new CompiledMethod(
- &driver_, instruction_set_, code,
- 0u, 0u, 0u, ArrayRef<const SrcMapElem>(), ArrayRef<const uint8_t>(),
- ArrayRef<const uint8_t>(), ArrayRef<const uint8_t>(), ArrayRef<const uint8_t>(),
+ &driver_,
+ instruction_set_,
+ code,
+ /* frame_size_in_bytes */ 0u,
+ /* core_spill_mask */ 0u,
+ /* fp_spill_mask */ 0u,
+ /* src_mapping_table */ ArrayRef<const SrcMapElem>(),
+ /* vmap_table */ ArrayRef<const uint8_t>(),
+ /* cfi_info */ ArrayRef<const uint8_t>(),
patches));
}
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index eaf0e17..73b16d5 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -442,7 +442,7 @@
// it is time to update OatHeader::kOatVersion
EXPECT_EQ(72U, sizeof(OatHeader));
EXPECT_EQ(4U, sizeof(OatMethodOffsets));
- EXPECT_EQ(28U, sizeof(OatQuickMethodHeader));
+ EXPECT_EQ(20U, sizeof(OatQuickMethodHeader));
EXPECT_EQ(132 * GetInstructionSetPointerSize(kRuntimeISA), sizeof(QuickEntryPoints));
}
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 3a67b1e..cf1c114 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -275,9 +275,7 @@
size_code_alignment_(0),
size_relative_call_thunks_(0),
size_misc_thunks_(0),
- size_mapping_table_(0),
size_vmap_table_(0),
- size_gc_map_(0),
size_oat_dex_file_location_size_(0),
size_oat_dex_file_location_data_(0),
size_oat_dex_file_location_checksum_(0),
@@ -498,72 +496,6 @@
OatWriter::~OatWriter() {
}
-struct OatWriter::GcMapDataAccess {
- static ArrayRef<const uint8_t> GetData(const CompiledMethod* compiled_method) ALWAYS_INLINE {
- return compiled_method->GetGcMap();
- }
-
- static uint32_t GetOffset(OatClass* oat_class, size_t method_offsets_index) ALWAYS_INLINE {
- uint32_t offset = oat_class->method_headers_[method_offsets_index].gc_map_offset_;
- return offset == 0u ? 0u :
- (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
- }
-
- static void SetOffset(OatClass* oat_class, size_t method_offsets_index, uint32_t offset)
- ALWAYS_INLINE {
- oat_class->method_headers_[method_offsets_index].gc_map_offset_ =
- (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
- }
-
- static const char* Name() {
- return "GC map";
- }
-};
-
-struct OatWriter::MappingTableDataAccess {
- static ArrayRef<const uint8_t> GetData(const CompiledMethod* compiled_method) ALWAYS_INLINE {
- return compiled_method->GetMappingTable();
- }
-
- static uint32_t GetOffset(OatClass* oat_class, size_t method_offsets_index) ALWAYS_INLINE {
- uint32_t offset = oat_class->method_headers_[method_offsets_index].mapping_table_offset_;
- return offset == 0u ? 0u :
- (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
- }
-
- static void SetOffset(OatClass* oat_class, size_t method_offsets_index, uint32_t offset)
- ALWAYS_INLINE {
- oat_class->method_headers_[method_offsets_index].mapping_table_offset_ =
- (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
- }
-
- static const char* Name() {
- return "mapping table";
- }
-};
-
-struct OatWriter::VmapTableDataAccess {
- static ArrayRef<const uint8_t> GetData(const CompiledMethod* compiled_method) ALWAYS_INLINE {
- return compiled_method->GetVmapTable();
- }
-
- static uint32_t GetOffset(OatClass* oat_class, size_t method_offsets_index) ALWAYS_INLINE {
- uint32_t offset = oat_class->method_headers_[method_offsets_index].vmap_table_offset_;
- return offset == 0u ? 0u :
- (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
- }
-
- static void SetOffset(OatClass* oat_class, size_t method_offsets_index, uint32_t offset)
- ALWAYS_INLINE {
- oat_class->method_headers_[method_offsets_index].vmap_table_offset_ =
- (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
- }
-
- static const char* Name() {
- return "vmap table";
- }
-};
-
class OatWriter::DexMethodVisitor {
public:
DexMethodVisitor(OatWriter* writer, size_t offset)
@@ -726,26 +658,24 @@
uint32_t thumb_offset = compiled_method->CodeDelta();
// Deduplicate code arrays if we are not producing debuggable code.
- bool deduped = false;
+ bool deduped = true;
MethodReference method_ref(dex_file_, it.GetMemberIndex());
if (debuggable_) {
quick_code_offset = writer_->relative_patcher_->GetOffset(method_ref);
if (quick_code_offset != 0u) {
// Duplicate methods, we want the same code for both of them so that the oat writer puts
// the same code in both ArtMethods so that we do not get different oat code at runtime.
- deduped = true;
} else {
quick_code_offset = NewQuickCodeOffset(compiled_method, it, thumb_offset);
+ deduped = false;
}
} else {
- auto lb = dedupe_map_.lower_bound(compiled_method);
- if (lb != dedupe_map_.end() && !dedupe_map_.key_comp()(compiled_method, lb->first)) {
- quick_code_offset = lb->second;
- deduped = true;
- } else {
- quick_code_offset = NewQuickCodeOffset(compiled_method, it, thumb_offset);
- dedupe_map_.PutBefore(lb, compiled_method, quick_code_offset);
- }
+ quick_code_offset = dedupe_map_.GetOrCreate(
+ compiled_method,
+ [this, &deduped, compiled_method, &it, thumb_offset]() {
+ deduped = false;
+ return NewQuickCodeOffset(compiled_method, it, thumb_offset);
+ });
}
if (code_size != 0) {
@@ -763,33 +693,25 @@
// Update quick method header.
DCHECK_LT(method_offsets_index_, oat_class->method_headers_.size());
OatQuickMethodHeader* method_header = &oat_class->method_headers_[method_offsets_index_];
- uint32_t mapping_table_offset = method_header->mapping_table_offset_;
uint32_t vmap_table_offset = method_header->vmap_table_offset_;
// If we don't have quick code, then we must have a vmap, as that is how the dex2dex
// compiler records its transformations.
DCHECK(!quick_code.empty() || vmap_table_offset != 0);
- uint32_t gc_map_offset = method_header->gc_map_offset_;
// The code offset was 0 when the mapping/vmap table offset was set, so it's set
// to 0-offset and we need to adjust it by code_offset.
uint32_t code_offset = quick_code_offset - thumb_offset;
- if (mapping_table_offset != 0u && code_offset != 0u) {
- mapping_table_offset += code_offset;
- DCHECK_LT(mapping_table_offset, code_offset) << "Overflow in oat offsets";
- }
if (vmap_table_offset != 0u && code_offset != 0u) {
vmap_table_offset += code_offset;
DCHECK_LT(vmap_table_offset, code_offset) << "Overflow in oat offsets";
}
- if (gc_map_offset != 0u && code_offset != 0u) {
- gc_map_offset += code_offset;
- DCHECK_LT(gc_map_offset, code_offset) << "Overflow in oat offsets";
- }
uint32_t frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
uint32_t core_spill_mask = compiled_method->GetCoreSpillMask();
uint32_t fp_spill_mask = compiled_method->GetFpSpillMask();
- *method_header = OatQuickMethodHeader(mapping_table_offset, vmap_table_offset,
- gc_map_offset, frame_size_in_bytes, core_spill_mask,
- fp_spill_mask, code_size);
+ *method_header = OatQuickMethodHeader(vmap_table_offset,
+ frame_size_in_bytes,
+ core_spill_mask,
+ fp_spill_mask,
+ code_size);
if (!deduped) {
// Update offsets. (Checksum is updated when writing.)
@@ -844,15 +766,6 @@
} else {
status = mirror::Class::kStatusNotReady;
}
- ArrayRef<const uint8_t> gc_map = compiled_method->GetGcMap();
- if (!gc_map.empty()) {
- size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]);
- bool is_native = it.MemberIsNative();
- CHECK(gc_map_size != 0 || is_native || status < mirror::Class::kStatusVerified)
- << gc_map_size << " " << (is_native ? "true" : "false") << " "
- << (status < mirror::Class::kStatusVerified) << " " << status << " "
- << PrettyMethod(it.GetMemberIndex(), *dex_file_);
- }
}
DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
@@ -872,15 +785,9 @@
return lhs->GetQuickCode().data() < rhs->GetQuickCode().data();
}
// If the code is the same, all other fields are likely to be the same as well.
- if (UNLIKELY(lhs->GetMappingTable().data() != rhs->GetMappingTable().data())) {
- return lhs->GetMappingTable().data() < rhs->GetMappingTable().data();
- }
if (UNLIKELY(lhs->GetVmapTable().data() != rhs->GetVmapTable().data())) {
return lhs->GetVmapTable().data() < rhs->GetVmapTable().data();
}
- if (UNLIKELY(lhs->GetGcMap().data() != rhs->GetGcMap().data())) {
- return lhs->GetGcMap().data() < rhs->GetGcMap().data();
- }
if (UNLIKELY(lhs->GetPatches().data() != rhs->GetPatches().data())) {
return lhs->GetPatches().data() < rhs->GetPatches().data();
}
@@ -907,7 +814,6 @@
const bool debuggable_;
};
-template <typename DataAccess>
class OatWriter::InitMapMethodVisitor : public OatDexMethodVisitor {
public:
InitMapMethodVisitor(OatWriter* writer, size_t offset)
@@ -921,19 +827,21 @@
if (compiled_method != nullptr) {
DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
- DCHECK_EQ(DataAccess::GetOffset(oat_class, method_offsets_index_), 0u);
+ DCHECK_EQ(oat_class->method_headers_[method_offsets_index_].vmap_table_offset_, 0u);
- ArrayRef<const uint8_t> map = DataAccess::GetData(compiled_method);
+ ArrayRef<const uint8_t> map = compiled_method->GetVmapTable();
uint32_t map_size = map.size() * sizeof(map[0]);
if (map_size != 0u) {
- auto lb = dedupe_map_.lower_bound(map.data());
- if (lb != dedupe_map_.end() && !dedupe_map_.key_comp()(map.data(), lb->first)) {
- DataAccess::SetOffset(oat_class, method_offsets_index_, lb->second);
- } else {
- DataAccess::SetOffset(oat_class, method_offsets_index_, offset_);
- dedupe_map_.PutBefore(lb, map.data(), offset_);
- offset_ += map_size;
- }
+ size_t offset = dedupe_map_.GetOrCreate(
+ map.data(),
+ [this, map_size]() {
+ uint32_t new_offset = offset_;
+ offset_ += map_size;
+ return new_offset;
+ });
+ // Code offset is not initialized yet, so set the map offset to 0u-offset.
+ DCHECK_EQ(oat_class->method_offsets_[method_offsets_index_].code_offset_, 0u);
+ oat_class->method_headers_[method_offsets_index_].vmap_table_offset_ = 0u - offset;
}
++method_offsets_index_;
}
@@ -1342,10 +1250,11 @@
}
};
-template <typename DataAccess>
class OatWriter::WriteMapMethodVisitor : public OatDexMethodVisitor {
public:
- WriteMapMethodVisitor(OatWriter* writer, OutputStream* out, const size_t file_offset,
+ WriteMapMethodVisitor(OatWriter* writer,
+ OutputStream* out,
+ const size_t file_offset,
size_t relative_offset)
: OatDexMethodVisitor(writer, relative_offset),
out_(out),
@@ -1360,22 +1269,31 @@
size_t file_offset = file_offset_;
OutputStream* out = out_;
- uint32_t map_offset = DataAccess::GetOffset(oat_class, method_offsets_index_);
+ uint32_t map_offset = oat_class->method_headers_[method_offsets_index_].vmap_table_offset_;
+ uint32_t code_offset = oat_class->method_offsets_[method_offsets_index_].code_offset_;
++method_offsets_index_;
- // Write deduplicated map.
- ArrayRef<const uint8_t> map = DataAccess::GetData(compiled_method);
- size_t map_size = map.size() * sizeof(map[0]);
- DCHECK((map_size == 0u && map_offset == 0u) ||
- (map_size != 0u && map_offset != 0u && map_offset <= offset_))
- << map_size << " " << map_offset << " " << offset_ << " "
- << PrettyMethod(it.GetMemberIndex(), *dex_file_) << " for " << DataAccess::Name();
- if (map_size != 0u && map_offset == offset_) {
- if (UNLIKELY(!writer_->WriteData(out, map.data(), map_size))) {
- ReportWriteFailure(it);
- return false;
+ DCHECK((compiled_method->GetVmapTable().size() == 0u && map_offset == 0u) ||
+ (compiled_method->GetVmapTable().size() != 0u && map_offset != 0u))
+ << compiled_method->GetVmapTable().size() << " " << map_offset << " "
+ << PrettyMethod(it.GetMemberIndex(), *dex_file_);
+
+ if (map_offset != 0u) {
+ // Transform map_offset to actual oat data offset.
+ map_offset = (code_offset - compiled_method->CodeDelta()) - map_offset;
+ DCHECK_NE(map_offset, 0u);
+ DCHECK_LE(map_offset, offset_) << PrettyMethod(it.GetMemberIndex(), *dex_file_);
+
+ ArrayRef<const uint8_t> map = compiled_method->GetVmapTable();
+ size_t map_size = map.size() * sizeof(map[0]);
+ if (map_offset == offset_) {
+ // Write deduplicated map (code info for Optimizing or transformation info for dex2dex).
+ if (UNLIKELY(!writer_->WriteData(out, map.data(), map_size))) {
+ ReportWriteFailure(it);
+ return false;
+ }
+ offset_ += map_size;
}
- offset_ += map_size;
}
DCHECK_OFFSET_();
}
@@ -1388,7 +1306,7 @@
size_t const file_offset_;
void ReportWriteFailure(const ClassDataItemIterator& it) {
- PLOG(ERROR) << "Failed to write " << DataAccess::Name() << " for "
+ PLOG(ERROR) << "Failed to write map for "
<< PrettyMethod(it.GetMemberIndex(), *dex_file_) << " to " << out_->GetLocation();
}
};
@@ -1481,19 +1399,10 @@
}
size_t OatWriter::InitOatMaps(size_t offset) {
- #define VISIT(VisitorType) \
- do { \
- VisitorType visitor(this, offset); \
- bool success = VisitDexMethods(&visitor); \
- DCHECK(success); \
- offset = visitor.GetOffset(); \
- } while (false)
-
- VISIT(InitMapMethodVisitor<GcMapDataAccess>);
- VISIT(InitMapMethodVisitor<MappingTableDataAccess>);
- VISIT(InitMapMethodVisitor<VmapTableDataAccess>);
-
- #undef VISIT
+ InitMapMethodVisitor visitor(this, offset);
+ bool success = VisitDexMethods(&visitor);
+ DCHECK(success);
+ offset = visitor.GetOffset();
return offset;
}
@@ -1647,9 +1556,7 @@
DO_STAT(size_code_alignment_);
DO_STAT(size_relative_call_thunks_);
DO_STAT(size_misc_thunks_);
- DO_STAT(size_mapping_table_);
DO_STAT(size_vmap_table_);
- DO_STAT(size_gc_map_);
DO_STAT(size_oat_dex_file_location_size_);
DO_STAT(size_oat_dex_file_location_data_);
DO_STAT(size_oat_dex_file_location_checksum_);
@@ -1764,29 +1671,14 @@
}
size_t OatWriter::WriteMaps(OutputStream* out, const size_t file_offset, size_t relative_offset) {
- #define VISIT(VisitorType) \
- do { \
- VisitorType visitor(this, out, file_offset, relative_offset); \
- if (UNLIKELY(!VisitDexMethods(&visitor))) { \
- return 0; \
- } \
- relative_offset = visitor.GetOffset(); \
- } while (false)
-
- size_t gc_maps_offset = relative_offset;
- VISIT(WriteMapMethodVisitor<GcMapDataAccess>);
- size_gc_map_ = relative_offset - gc_maps_offset;
-
- size_t mapping_tables_offset = relative_offset;
- VISIT(WriteMapMethodVisitor<MappingTableDataAccess>);
- size_mapping_table_ = relative_offset - mapping_tables_offset;
-
size_t vmap_tables_offset = relative_offset;
- VISIT(WriteMapMethodVisitor<VmapTableDataAccess>);
+ WriteMapMethodVisitor visitor(this, out, file_offset, relative_offset);
+ if (UNLIKELY(!VisitDexMethods(&visitor))) {
+ return 0;
+ }
+ relative_offset = visitor.GetOffset();
size_vmap_table_ = relative_offset - vmap_tables_offset;
- #undef VISIT
-
return relative_offset;
}
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index 5e7a4a3..3862798 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -219,13 +219,6 @@
class OatClass;
class OatDexFile;
- // The DataAccess classes are helper classes that provide access to members related to
- // a given map, i.e. GC map, mapping table or vmap table. By abstracting these away
- // we can share a lot of code for processing the maps with template classes below.
- struct GcMapDataAccess;
- struct MappingTableDataAccess;
- struct VmapTableDataAccess;
-
// The function VisitDexMethods() below iterates through all the methods in all
// the compiled dex files in order of their definitions. The method visitor
// classes provide individual bits of processing for each of the passes we need to
@@ -235,11 +228,9 @@
class OatDexMethodVisitor;
class InitOatClassesMethodVisitor;
class InitCodeMethodVisitor;
- template <typename DataAccess>
class InitMapMethodVisitor;
class InitImageMethodVisitor;
class WriteCodeMethodVisitor;
- template <typename DataAccess>
class WriteMapMethodVisitor;
// Visit all the methods in all the compiled dex files in their definition order
@@ -354,9 +345,7 @@
uint32_t size_code_alignment_;
uint32_t size_relative_call_thunks_;
uint32_t size_misc_thunks_;
- uint32_t size_mapping_table_;
uint32_t size_vmap_table_;
- uint32_t size_gc_map_;
uint32_t size_oat_dex_file_location_size_;
uint32_t size_oat_dex_file_location_data_;
uint32_t size_oat_dex_file_location_checksum_;
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 65e5c3a..953c0ae 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -44,18 +44,15 @@
#include "compiled_method.h"
#include "dex/verified_method.h"
#include "driver/compiler_driver.h"
-#include "gc_map_builder.h"
#include "graph_visualizer.h"
#include "intrinsics.h"
#include "leb128.h"
-#include "mapping_table.h"
#include "mirror/array-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/object_reference.h"
#include "parallel_move_resolver.h"
#include "ssa_liveness_analysis.h"
#include "utils/assembler.h"
-#include "vmap_table.h"
namespace art {
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 3d6bf62..cad94c7 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -597,9 +597,7 @@
codegen->GetCoreSpillMask(),
codegen->GetFpuSpillMask(),
ArrayRef<const SrcMapElem>(),
- ArrayRef<const uint8_t>(), // mapping_table.
ArrayRef<const uint8_t>(stack_map),
- ArrayRef<const uint8_t>(), // native_gc_map.
ArrayRef<const uint8_t>(*codegen->GetAssembler()->cfi().data()),
ArrayRef<const LinkerPatch>(linker_patches));
@@ -916,9 +914,7 @@
const void* code = code_cache->CommitCode(
self,
method,
- nullptr,
stack_map_data,
- nullptr,
codegen->HasEmptyFrame() ? 0 : codegen->GetFrameSize(),
codegen->GetCoreSpillMask(),
codegen->GetFpuSpillMask(),