summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--adbconnection/adbconnection.cc4
-rw-r--r--compiler/optimizing/stack_map_stream.cc45
-rw-r--r--compiler/optimizing/stack_map_stream.h4
-rw-r--r--compiler/optimizing/stack_map_test.cc84
-rw-r--r--dex2oat/linker/image_writer.cc8
-rw-r--r--dex2oat/linker/oat_writer.cc10
-rw-r--r--libdexfile/dex/class_accessor-inl.h101
-rw-r--r--libdexfile/dex/class_accessor.h78
-rw-r--r--libdexfile/dex/class_accessor_test.cc10
-rw-r--r--libdexfile/dex/dex_file.cc17
-rw-r--r--libdexfile/dex/dex_file.h4
-rw-r--r--libdexfile/dex/type_lookup_table.cc201
-rw-r--r--libdexfile/dex/type_lookup_table.h211
-rw-r--r--libdexfile/dex/type_lookup_table_test.cc14
-rw-r--r--oatdump/oatdump.cc12
-rw-r--r--openjdkjvmti/fixed_up_dex_file.cc15
-rw-r--r--patchoat/patchoat.cc2
-rw-r--r--runtime/art_field-inl.h15
-rw-r--r--runtime/art_field.cc7
-rw-r--r--runtime/art_field.h7
-rw-r--r--runtime/art_method-inl.h6
-rw-r--r--runtime/art_method.cc33
-rw-r--r--runtime/art_method.h2
-rw-r--r--runtime/class_linker-inl.h48
-rw-r--r--runtime/class_linker.cc354
-rw-r--r--runtime/class_linker.h41
-rw-r--r--runtime/entrypoints/entrypoint_utils-inl.h46
-rw-r--r--runtime/entrypoints/entrypoint_utils.cc9
-rw-r--r--runtime/entrypoints/entrypoint_utils.h5
-rw-r--r--runtime/entrypoints/quick/quick_dexcache_entrypoints.cc3
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc21
-rw-r--r--runtime/gc/space/image_space.cc2
-rw-r--r--runtime/image-inl.h7
-rw-r--r--runtime/image.cc2
-rw-r--r--runtime/image.h11
-rw-r--r--runtime/interpreter/interpreter_common.cc4
-rw-r--r--runtime/interpreter/interpreter_common.h8
-rw-r--r--runtime/mirror/class.cc6
-rw-r--r--runtime/mirror/object-inl.h4
-rw-r--r--runtime/mirror/object.h1
-rw-r--r--runtime/native/dalvik_system_VMRuntime.cc29
-rw-r--r--runtime/native/java_lang_Object.cc6
-rw-r--r--runtime/native/java_lang_reflect_Executable.cc2
-rw-r--r--runtime/native/java_lang_reflect_Field.cc3
-rw-r--r--runtime/oat.h4
-rw-r--r--runtime/oat_file.cc8
-rw-r--r--runtime/oat_file.h8
-rw-r--r--runtime/quick_exception_handler.cc2
-rw-r--r--runtime/reference_table_test.cc2
-rw-r--r--runtime/runtime.cc102
-rw-r--r--runtime/runtime.h5
-rw-r--r--runtime/stack.cc26
-rw-r--r--runtime/stack_map.cc45
-rw-r--r--runtime/stack_map.h72
-rw-r--r--runtime/vdex_file.cc40
-rw-r--r--runtime/verifier/method_verifier.cc164
-rw-r--r--runtime/verifier/method_verifier.h17
-rw-r--r--test/911-get-stack-trace/check31
-rw-r--r--test/911-get-stack-trace/expected.txt366
-rw-r--r--test/911-get-stack-trace/expected_d8.diff456
-rw-r--r--test/911-get-stack-trace/src/art/AllTraces.java2
-rw-r--r--test/911-get-stack-trace/src/art/OtherThread.java4
-rw-r--r--test/911-get-stack-trace/src/art/ThreadListTraces.java2
-rw-r--r--test/knownfailures.json6
-rw-r--r--test/testrunner/target_config.py2
-rw-r--r--tools/dexanalyze/dexanalyze.cc28
-rw-r--r--tools/dexanalyze/dexanalyze_experiments.cc157
-rw-r--r--tools/dexanalyze/dexanalyze_experiments.h9
68 files changed, 1353 insertions, 1707 deletions
diff --git a/adbconnection/adbconnection.cc b/adbconnection/adbconnection.cc
index 8cd0d8bc9f..ad941481fd 100644
--- a/adbconnection/adbconnection.cc
+++ b/adbconnection/adbconnection.cc
@@ -489,7 +489,7 @@ bool AdbConnectionState::SetupAdbConnection() {
int sleep_ms = 500;
const int sleep_max_ms = 2*1000;
- android::base::unique_fd sock(socket(AF_UNIX, SOCK_SEQPACKET, 0));
+ android::base::unique_fd sock(socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0));
if (sock < 0) {
PLOG(ERROR) << "Could not create ADB control socket";
return false;
@@ -872,7 +872,7 @@ std::string AdbConnectionState::MakeAgentArg() {
(ContainsArgument(opts, "server=y") ? "" : "server=y,") +
// See the comment above for why we need to be suspend=n. Since the agent defaults to
// suspend=y we will add it if it wasn't already present.
- (ContainsArgument(opts, "suspend=n") ? "" : "suspend=n") +
+ (ContainsArgument(opts, "suspend=n") ? "" : "suspend=n,") +
"transport=dt_fd_forward,address=" + std::to_string(remote_agent_control_sock_);
}
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc
index d99beac59f..d80e2fc0e3 100644
--- a/compiler/optimizing/stack_map_stream.cc
+++ b/compiler/optimizing/stack_map_stream.cc
@@ -65,7 +65,7 @@ void StackMapStream::BeginStackMapEntry(uint32_t dex_pc,
// and it might modify the data before that. Therefore, just store the pointer.
// See ClearSpillSlotsFromLoopPhisInStackMap in code_generator.h.
lazy_stack_masks_.push_back(stack_mask);
- current_inline_infos_ = 0;
+ current_inline_infos_.clear();
current_dex_registers_.clear();
expected_num_dex_registers_ = num_dex_registers;
@@ -84,9 +84,7 @@ void StackMapStream::BeginStackMapEntry(uint32_t dex_pc,
CHECK_EQ(seen_stack_mask.LoadBit(b), stack_mask != nullptr && stack_mask->IsBitSet(b));
}
CHECK_EQ(stack_map.HasInlineInfo(), (inlining_depth != 0));
- if (inlining_depth != 0) {
- CHECK_EQ(code_info.GetInlineInfoOf(stack_map).GetDepth(), inlining_depth);
- }
+ CHECK_EQ(code_info.GetInlineDepthOf(stack_map), inlining_depth);
CHECK_EQ(stack_map.HasDexRegisterMap(), (num_dex_registers != 0));
});
}
@@ -97,9 +95,11 @@ void StackMapStream::EndStackMapEntry() {
in_stack_map_ = false;
DCHECK_EQ(expected_num_dex_registers_, current_dex_registers_.size());
- // Mark the last inline info as last in the list for the stack map.
- if (current_inline_infos_ > 0) {
- inline_infos_[inline_infos_.size() - 1].is_last = InlineInfo::kLast;
+ // Generate index into the InlineInfo table.
+ if (!current_inline_infos_.empty()) {
+ current_inline_infos_.back().is_last = InlineInfo::kLast;
+ current_stack_map_.inline_info_index =
+ inline_infos_.Dedup(current_inline_infos_.data(), current_inline_infos_.size());
}
stack_maps_.Add(current_stack_map_);
@@ -162,30 +162,27 @@ void StackMapStream::BeginInlineInfoEntry(ArtMethod* method,
uint32_t dex_method_index = method->GetDexMethodIndexUnchecked();
entry.method_info_index = method_infos_.Dedup(&dex_method_index);
}
- if (current_inline_infos_++ == 0) {
- current_stack_map_.inline_info_index = inline_infos_.size();
- }
- inline_infos_.Add(entry);
+ current_inline_infos_.push_back(entry);
current_dex_registers_.clear();
expected_num_dex_registers_ = num_dex_registers;
if (kVerifyStackMaps) {
size_t stack_map_index = stack_maps_.size();
- size_t depth = current_inline_infos_ - 1;
+ size_t depth = current_inline_infos_.size() - 1;
dchecks_.emplace_back([=](const CodeInfo& code_info) {
StackMap stack_map = code_info.GetStackMapAt(stack_map_index);
- InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
- CHECK_EQ(inline_info.GetDexPcAtDepth(depth), dex_pc);
+ InlineInfo inline_info = code_info.GetInlineInfoAtDepth(stack_map, depth);
+ CHECK_EQ(inline_info.GetDexPc(), dex_pc);
bool encode_art_method = EncodeArtMethodInInlineInfo(method);
- CHECK_EQ(inline_info.EncodesArtMethodAtDepth(depth), encode_art_method);
+ CHECK_EQ(inline_info.EncodesArtMethod(), encode_art_method);
if (encode_art_method) {
- CHECK_EQ(inline_info.GetArtMethodAtDepth(depth), method);
+ CHECK_EQ(inline_info.GetArtMethod(), method);
} else {
- CHECK_EQ(method_infos_[inline_info.GetMethodIndexIdxAtDepth(depth)],
+ CHECK_EQ(method_infos_[inline_info.GetMethodIndexIdx()],
method->GetDexMethodIndexUnchecked());
}
- CHECK_EQ(inline_info.HasDexRegisterMapAtDepth(depth), (num_dex_registers != 0));
+ CHECK_EQ(inline_info.HasDexRegisterMap(), (num_dex_registers != 0));
});
}
}
@@ -222,9 +219,9 @@ void StackMapStream::CreateDexRegisterMap() {
}
uint32_t map_index = dex_register_maps_.Dedup(temp_dex_register_map_.data(),
temp_dex_register_map_.size());
- if (current_inline_infos_ > 0) {
- inline_infos_[inline_infos_.size() - 1].dex_register_mask_index = mask_index;
- inline_infos_[inline_infos_.size() - 1].dex_register_map_index = map_index;
+ if (!current_inline_infos_.empty()) {
+ current_inline_infos_.back().dex_register_mask_index = mask_index;
+ current_inline_infos_.back().dex_register_map_index = map_index;
} else {
current_stack_map_.dex_register_mask_index = mask_index;
current_stack_map_.dex_register_map_index = map_index;
@@ -232,7 +229,7 @@ void StackMapStream::CreateDexRegisterMap() {
if (kVerifyStackMaps) {
size_t stack_map_index = stack_maps_.size();
- int32_t depth = current_inline_infos_ - 1;
+ int32_t depth = current_inline_infos_.size() - 1;
// We need to make copy of the current registers for later (when the check is run).
auto expected_dex_registers = std::make_shared<std::vector<DexRegisterLocation>>(
current_dex_registers_.begin(), current_dex_registers_.end());
@@ -241,9 +238,7 @@ void StackMapStream::CreateDexRegisterMap() {
size_t num_dex_registers = expected_dex_registers->size();
DexRegisterMap map = (depth == -1)
? code_info.GetDexRegisterMapOf(stack_map, num_dex_registers)
- : code_info.GetDexRegisterMapAtDepth(depth,
- code_info.GetInlineInfoOf(stack_map),
- num_dex_registers);
+ : code_info.GetDexRegisterMapAtDepth(depth, stack_map, num_dex_registers);
CHECK_EQ(map.size(), num_dex_registers);
for (size_t r = 0; r < num_dex_registers; r++) {
CHECK_EQ(expected_dex_registers->at(r), map.Get(r));
diff --git a/compiler/optimizing/stack_map_stream.h b/compiler/optimizing/stack_map_stream.h
index c758bca951..d634c703ff 100644
--- a/compiler/optimizing/stack_map_stream.h
+++ b/compiler/optimizing/stack_map_stream.h
@@ -53,7 +53,7 @@ class StackMapStream : public ValueObject {
lazy_stack_masks_(allocator->Adapter(kArenaAllocStackMapStream)),
in_stack_map_(false),
in_inline_info_(false),
- current_inline_infos_(0),
+ current_inline_infos_(allocator->Adapter(kArenaAllocStackMapStream)),
current_dex_registers_(allocator->Adapter(kArenaAllocStackMapStream)),
temp_dex_register_mask_(allocator, 32, true, kArenaAllocStackMapStream),
temp_dex_register_map_(allocator->Adapter(kArenaAllocStackMapStream)) {
@@ -157,7 +157,7 @@ class StackMapStream : public ValueObject {
bool in_stack_map_;
bool in_inline_info_;
StackMapEntry current_stack_map_;
- uint32_t current_inline_infos_;
+ ScopedArenaVector<InlineInfoEntry> current_inline_infos_;
ScopedArenaVector<DexRegisterLocation> current_dex_registers_;
size_t expected_num_dex_registers_;
diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc
index 262c240bc7..77aa3ef965 100644
--- a/compiler/optimizing/stack_map_test.cc
+++ b/compiler/optimizing/stack_map_test.cc
@@ -189,12 +189,13 @@ TEST(StackMapTest, Test2) {
ASSERT_EQ(-2, location1.GetValue());
ASSERT_TRUE(stack_map.HasInlineInfo());
- InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
- ASSERT_EQ(2u, inline_info.GetDepth());
- ASSERT_EQ(3u, inline_info.GetDexPcAtDepth(0));
- ASSERT_EQ(2u, inline_info.GetDexPcAtDepth(1));
- ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(0));
- ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(1));
+ InlineInfo inline_info0 = code_info.GetInlineInfoAtDepth(stack_map, 0);
+ InlineInfo inline_info1 = code_info.GetInlineInfoAtDepth(stack_map, 1);
+ ASSERT_EQ(2u, code_info.GetInlineDepthOf(stack_map));
+ ASSERT_EQ(3u, inline_info0.GetDexPc());
+ ASSERT_EQ(2u, inline_info1.GetDexPc());
+ ASSERT_TRUE(inline_info0.EncodesArtMethod());
+ ASSERT_TRUE(inline_info1.EncodesArtMethod());
}
// Second stack map.
@@ -361,8 +362,8 @@ TEST(StackMapTest, TestDeduplicateInlineInfoDexRegisterMap) {
// Test that the inline info dex register map deduplicated to the same offset as the stack map
// one.
ASSERT_TRUE(stack_map.HasInlineInfo());
- InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
- EXPECT_EQ(inline_info.GetDexRegisterMapIndexAtDepth(0),
+ InlineInfo inline_info = code_info.GetInlineInfoAtDepth(stack_map, 0);
+ EXPECT_EQ(inline_info.GetDexRegisterMapIndex(),
stack_map.GetDexRegisterMapIndex());
}
}
@@ -605,17 +606,18 @@ TEST(StackMapTest, InlineTest) {
ASSERT_EQ(0, dex_registers0.GetStackOffsetInBytes(0));
ASSERT_EQ(4, dex_registers0.GetConstant(1));
- InlineInfo if0 = ci.GetInlineInfoOf(sm0);
- ASSERT_EQ(2u, if0.GetDepth());
- ASSERT_EQ(2u, if0.GetDexPcAtDepth(0));
- ASSERT_TRUE(if0.EncodesArtMethodAtDepth(0));
- ASSERT_EQ(3u, if0.GetDexPcAtDepth(1));
- ASSERT_TRUE(if0.EncodesArtMethodAtDepth(1));
+ InlineInfo if0_0 = ci.GetInlineInfoAtDepth(sm0, 0);
+ InlineInfo if0_1 = ci.GetInlineInfoAtDepth(sm0, 1);
+ ASSERT_EQ(2u, ci.GetInlineDepthOf(sm0));
+ ASSERT_EQ(2u, if0_0.GetDexPc());
+ ASSERT_TRUE(if0_0.EncodesArtMethod());
+ ASSERT_EQ(3u, if0_1.GetDexPc());
+ ASSERT_TRUE(if0_1.EncodesArtMethod());
- DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if0, 1);
+ DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, sm0, 1);
ASSERT_EQ(8, dex_registers1.GetStackOffsetInBytes(0));
- DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if0, 3);
+ DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, sm0, 3);
ASSERT_EQ(16, dex_registers2.GetStackOffsetInBytes(0));
ASSERT_EQ(20, dex_registers2.GetConstant(1));
ASSERT_EQ(15, dex_registers2.GetMachineRegister(2));
@@ -629,24 +631,26 @@ TEST(StackMapTest, InlineTest) {
ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0));
ASSERT_EQ(0, dex_registers0.GetConstant(1));
- InlineInfo if1 = ci.GetInlineInfoOf(sm1);
- ASSERT_EQ(3u, if1.GetDepth());
- ASSERT_EQ(2u, if1.GetDexPcAtDepth(0));
- ASSERT_TRUE(if1.EncodesArtMethodAtDepth(0));
- ASSERT_EQ(3u, if1.GetDexPcAtDepth(1));
- ASSERT_TRUE(if1.EncodesArtMethodAtDepth(1));
- ASSERT_EQ(5u, if1.GetDexPcAtDepth(2));
- ASSERT_TRUE(if1.EncodesArtMethodAtDepth(2));
-
- DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if1, 1);
+ InlineInfo if1_0 = ci.GetInlineInfoAtDepth(sm1, 0);
+ InlineInfo if1_1 = ci.GetInlineInfoAtDepth(sm1, 1);
+ InlineInfo if1_2 = ci.GetInlineInfoAtDepth(sm1, 2);
+ ASSERT_EQ(3u, ci.GetInlineDepthOf(sm1));
+ ASSERT_EQ(2u, if1_0.GetDexPc());
+ ASSERT_TRUE(if1_0.EncodesArtMethod());
+ ASSERT_EQ(3u, if1_1.GetDexPc());
+ ASSERT_TRUE(if1_1.EncodesArtMethod());
+ ASSERT_EQ(5u, if1_2.GetDexPc());
+ ASSERT_TRUE(if1_2.EncodesArtMethod());
+
+ DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, sm1, 1);
ASSERT_EQ(12, dex_registers1.GetStackOffsetInBytes(0));
- DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if1, 3);
+ DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, sm1, 3);
ASSERT_EQ(80, dex_registers2.GetStackOffsetInBytes(0));
ASSERT_EQ(10, dex_registers2.GetConstant(1));
ASSERT_EQ(5, dex_registers2.GetMachineRegister(2));
- ASSERT_FALSE(if1.HasDexRegisterMapAtDepth(2));
+ ASSERT_FALSE(if1_2.HasDexRegisterMap());
}
{
@@ -667,21 +671,23 @@ TEST(StackMapTest, InlineTest) {
ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0));
ASSERT_EQ(0, dex_registers0.GetConstant(1));
- InlineInfo if2 = ci.GetInlineInfoOf(sm3);
- ASSERT_EQ(3u, if2.GetDepth());
- ASSERT_EQ(2u, if2.GetDexPcAtDepth(0));
- ASSERT_TRUE(if2.EncodesArtMethodAtDepth(0));
- ASSERT_EQ(5u, if2.GetDexPcAtDepth(1));
- ASSERT_TRUE(if2.EncodesArtMethodAtDepth(1));
- ASSERT_EQ(10u, if2.GetDexPcAtDepth(2));
- ASSERT_TRUE(if2.EncodesArtMethodAtDepth(2));
+ InlineInfo if2_0 = ci.GetInlineInfoAtDepth(sm3, 0);
+ InlineInfo if2_1 = ci.GetInlineInfoAtDepth(sm3, 1);
+ InlineInfo if2_2 = ci.GetInlineInfoAtDepth(sm3, 2);
+ ASSERT_EQ(3u, ci.GetInlineDepthOf(sm3));
+ ASSERT_EQ(2u, if2_0.GetDexPc());
+ ASSERT_TRUE(if2_0.EncodesArtMethod());
+ ASSERT_EQ(5u, if2_1.GetDexPc());
+ ASSERT_TRUE(if2_1.EncodesArtMethod());
+ ASSERT_EQ(10u, if2_2.GetDexPc());
+ ASSERT_TRUE(if2_2.EncodesArtMethod());
- ASSERT_FALSE(if2.HasDexRegisterMapAtDepth(0));
+ ASSERT_FALSE(if2_0.HasDexRegisterMap());
- DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(1, if2, 1);
+ DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(1, sm3, 1);
ASSERT_EQ(2, dex_registers1.GetMachineRegister(0));
- DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(2, if2, 2);
+ DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(2, sm3, 2);
ASSERT_FALSE(dex_registers2.IsDexRegisterLive(0));
ASSERT_EQ(3, dex_registers2.GetMachineRegister(1));
}
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index 028de34e96..dc0709013c 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -1342,6 +1342,14 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots(size_t oat_index) const {
ObjectArray<Object>::Alloc(self, object_array_class.Get(), image_roots_size)));
image_roots->Set<false>(ImageHeader::kDexCaches, dex_caches.Get());
image_roots->Set<false>(ImageHeader::kClassRoots, class_linker->GetClassRoots());
+ image_roots->Set<false>(ImageHeader::kOomeWhenThrowingException,
+ runtime->GetPreAllocatedOutOfMemoryErrorWhenThrowingException());
+ image_roots->Set<false>(ImageHeader::kOomeWhenThrowingOome,
+ runtime->GetPreAllocatedOutOfMemoryErrorWhenThrowingOOME());
+ image_roots->Set<false>(ImageHeader::kOomeWhenHandlingStackOverflow,
+ runtime->GetPreAllocatedOutOfMemoryErrorWhenHandlingStackOverflow());
+ image_roots->Set<false>(ImageHeader::kNoClassDefFoundError,
+ runtime->GetPreAllocatedNoClassDefFoundError());
// image_roots[ImageHeader::kClassLoader] will be set later for app image.
static_assert(ImageHeader::kClassLoader + 1u == ImageHeader::kImageRootsMax,
"Class loader should be the last image root.");
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index 4046dc101f..99516684e8 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -4032,13 +4032,13 @@ bool OatWriter::WriteTypeLookupTables(
// TypeLookupTable allocates its own and OatDexFile takes ownership.
const DexFile& dex_file = *opened_dex_files[i];
{
- std::unique_ptr<TypeLookupTable> type_lookup_table =
- TypeLookupTable::Create(dex_file, /* storage */ nullptr);
+ TypeLookupTable type_lookup_table = TypeLookupTable::Create(dex_file);
type_lookup_table_oat_dex_files_.push_back(
std::make_unique<art::OatDexFile>(std::move(type_lookup_table)));
dex_file.SetOatDexFile(type_lookup_table_oat_dex_files_.back().get());
}
- TypeLookupTable* const table = type_lookup_table_oat_dex_files_.back()->GetTypeLookupTable();
+ const TypeLookupTable& table = type_lookup_table_oat_dex_files_.back()->GetTypeLookupTable();
+ DCHECK(table.Valid());
// Type tables are required to be 4 byte aligned.
size_t initial_offset = oat_size_;
@@ -4057,9 +4057,9 @@ bool OatWriter::WriteTypeLookupTables(
DCHECK_EQ(oat_data_offset_ + rodata_offset,
static_cast<size_t>(oat_rodata->Seek(0u, kSeekCurrent)));
- DCHECK_EQ(table_size, table->RawDataLength());
+ DCHECK_EQ(table_size, table.RawDataLength());
- if (!oat_rodata->WriteFully(table->RawData(), table_size)) {
+ if (!oat_rodata->WriteFully(table.RawData(), table_size)) {
PLOG(ERROR) << "Failed to write lookup table."
<< " File: " << oat_dex_file->GetLocation()
<< " Output: " << oat_rodata->GetLocation();
diff --git a/libdexfile/dex/class_accessor-inl.h b/libdexfile/dex/class_accessor-inl.h
index 49ca98d47f..3bb9e93e5a 100644
--- a/libdexfile/dex/class_accessor-inl.h
+++ b/libdexfile/dex/class_accessor-inl.h
@@ -37,30 +37,26 @@ inline ClassAccessor::ClassAccessor(const DexFile& dex_file, const DexFile::Clas
num_direct_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
num_virtual_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u) {}
-inline const uint8_t* ClassAccessor::Method::Read(const uint8_t* ptr) {
- index_ += DecodeUnsignedLeb128(&ptr);
- access_flags_ = DecodeUnsignedLeb128(&ptr);
- code_off_ = DecodeUnsignedLeb128(&ptr);
- return ptr;
+inline void ClassAccessor::Method::Read() {
+ index_ += DecodeUnsignedLeb128(&ptr_pos_);
+ access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
+ code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
}
-inline const uint8_t* ClassAccessor::Field::Read(const uint8_t* ptr) {
- index_ += DecodeUnsignedLeb128(&ptr);
- access_flags_ = DecodeUnsignedLeb128(&ptr);
- return ptr;
+inline void ClassAccessor::Field::Read() {
+ index_ += DecodeUnsignedLeb128(&ptr_pos_);
+ access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
}
template <typename DataType, typename Visitor>
-inline const uint8_t* ClassAccessor::VisitMembers(size_t count,
- const Visitor& visitor,
- const uint8_t* ptr,
- DataType* data) const {
+inline void ClassAccessor::VisitMembers(size_t count,
+ const Visitor& visitor,
+ DataType* data) const {
DCHECK(data != nullptr);
for ( ; count != 0; --count) {
- ptr = data->Read(ptr);
+ data->Read();
visitor(*data);
}
- return ptr;
}
template <typename StaticFieldVisitor,
@@ -72,15 +68,15 @@ inline void ClassAccessor::VisitFieldsAndMethods(
const InstanceFieldVisitor& instance_field_visitor,
const DirectMethodVisitor& direct_method_visitor,
const VirtualMethodVisitor& virtual_method_visitor) const {
- Field field(dex_file_);
- const uint8_t* ptr = VisitMembers(num_static_fields_, static_field_visitor, ptr_pos_, &field);
+ Field field(dex_file_, ptr_pos_);
+ VisitMembers(num_static_fields_, static_field_visitor, &field);
field.NextSection();
- ptr = VisitMembers(num_instance_fields_, instance_field_visitor, ptr, &field);
+ VisitMembers(num_instance_fields_, instance_field_visitor, &field);
- Method method(dex_file_, /*is_static_or_direct*/ true);
- ptr = VisitMembers(num_direct_methods_, direct_method_visitor, ptr, &method);
+ Method method(dex_file_, field.ptr_pos_, /*is_static_or_direct*/ true);
+ VisitMembers(num_direct_methods_, direct_method_visitor, &method);
method.NextSection();
- ptr = VisitMembers(num_virtual_methods_, virtual_method_visitor, ptr, &method);
+ VisitMembers(num_virtual_methods_, virtual_method_visitor, &method);
}
template <typename DirectMethodVisitor,
@@ -119,23 +115,64 @@ inline const DexFile::CodeItem* ClassAccessor::Method::GetCodeItem() const {
return dex_file_.GetCodeItem(code_off_);
}
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
+ ClassAccessor::GetFieldsInternal(size_t count) const {
+ return { DataIterator<Field>(dex_file_, 0u, num_static_fields_, count, ptr_pos_),
+ DataIterator<Field>(dex_file_, count, num_static_fields_, count, ptr_pos_) };
+}
+
+// Return an iteration range for the first <count> methods.
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
+ ClassAccessor::GetMethodsInternal(size_t count) const {
+ // Skip over the fields.
+ Field field(dex_file_, ptr_pos_);
+ VisitMembers(NumFields(), VoidFunctor(), &field);
+ // Return the iterator pair.
+ return { DataIterator<Method>(dex_file_, 0u, num_direct_methods_, count, field.ptr_pos_),
+ DataIterator<Method>(dex_file_, count, num_direct_methods_, count, field.ptr_pos_) };
+}
+
inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> ClassAccessor::GetFields()
const {
- const uint32_t limit = num_static_fields_ + num_instance_fields_;
- return { DataIterator<Field>(dex_file_, 0u, num_static_fields_, limit, ptr_pos_),
- DataIterator<Field>(dex_file_, limit, num_static_fields_, limit, ptr_pos_) };
+ return GetFieldsInternal(num_static_fields_ + num_instance_fields_);
+}
+
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
+ ClassAccessor::GetStaticFields() const {
+ return GetFieldsInternal(num_static_fields_);
+}
+
+
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
+ ClassAccessor::GetInstanceFields() const {
+ IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> fields = GetFields();
+ // Skip the static fields.
+ return { std::next(fields.begin(), NumStaticFields()), fields.end() };
}
inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
ClassAccessor::GetMethods() const {
- // Skip over the fields.
- Field field(dex_file_);
- const size_t skip_count = num_static_fields_ + num_instance_fields_;
- const uint8_t* ptr_pos = VisitMembers(skip_count, VoidFunctor(), ptr_pos_, &field);
- // Return the iterator pair for all the methods.
- const uint32_t limit = num_direct_methods_ + num_virtual_methods_;
- return { DataIterator<Method>(dex_file_, 0u, num_direct_methods_, limit, ptr_pos),
- DataIterator<Method>(dex_file_, limit, num_direct_methods_, limit, ptr_pos) };
+ return GetMethodsInternal(NumMethods());
+}
+
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
+ ClassAccessor::GetDirectMethods() const {
+ return GetMethodsInternal(NumDirectMethods());
+}
+
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
+ ClassAccessor::GetVirtualMethods() const {
+ IterationRange<DataIterator<Method>> methods = GetMethods();
+ // Skip the direct fields.
+ return { std::next(methods.begin(), NumDirectMethods()), methods.end() };
+}
+
+inline void ClassAccessor::Field::UnHideAccessFlags() const {
+ DexFile::UnHideAccessFlags(const_cast<uint8_t*>(ptr_pos_), GetAccessFlags(), /*is_method*/ false);
+}
+
+inline void ClassAccessor::Method::UnHideAccessFlags() const {
+ DexFile::UnHideAccessFlags(const_cast<uint8_t*>(ptr_pos_), GetAccessFlags(), /*is_method*/ true);
}
} // namespace art
diff --git a/libdexfile/dex/class_accessor.h b/libdexfile/dex/class_accessor.h
index dda6e1c1a6..4f0fd32e31 100644
--- a/libdexfile/dex/class_accessor.h
+++ b/libdexfile/dex/class_accessor.h
@@ -20,6 +20,7 @@
#include "base/utils.h"
#include "code_item_accessors.h"
#include "dex_file.h"
+#include "hidden_api_access_flags.h"
#include "invoke_type.h"
#include "method_reference.h"
#include "modifiers.h"
@@ -33,12 +34,18 @@ class ClassAccessor {
private:
class BaseItem {
public:
+ explicit BaseItem(const uint8_t* ptr_pos) : ptr_pos_(ptr_pos) {}
+
uint32_t GetIndex() const {
return index_;
}
uint32_t GetAccessFlags() const {
- return access_flags_;
+ return HiddenApiAccessFlags::RemoveFromDex(access_flags_);
+ }
+
+ HiddenApiAccessFlags::ApiList DecodeHiddenAccessFlags() const {
+ return HiddenApiAccessFlags::DecodeFromDex(access_flags_);
}
bool IsFinal() const {
@@ -46,6 +53,8 @@ class ClassAccessor {
}
protected:
+ // Internal data pointer for reading.
+ const uint8_t* ptr_pos_ = nullptr;
uint32_t index_ = 0u;
uint32_t access_flags_ = 0u;
};
@@ -76,13 +85,18 @@ class ClassAccessor {
return is_static_or_direct_;
}
+ // Unhide the hidden API access flags at the iterator position. TODO: Deprecate.
+ void UnHideAccessFlags() const;
+
private:
explicit Method(const DexFile& dex_file,
+ const uint8_t* ptr_pos,
bool is_static_or_direct = true)
- : dex_file_(dex_file),
+ : BaseItem(ptr_pos),
+ dex_file_(dex_file),
is_static_or_direct_(is_static_or_direct) {}
- const uint8_t* Read(const uint8_t* ptr);
+ void Read();
InvokeType GetDirectMethodInvokeType() const {
return (GetAccessFlags() & kAccStatic) != 0 ? kStatic : kDirect;
@@ -99,6 +113,7 @@ class ClassAccessor {
}
}
+ // Move to virtual method section.
void NextSection() {
DCHECK(is_static_or_direct_) << "Already in the virtual methods section";
is_static_or_direct_ = false;
@@ -115,20 +130,31 @@ class ClassAccessor {
// A decoded version of the field of a class_data_item.
class Field : public BaseItem {
public:
- explicit Field(const DexFile& dex_file) : dex_file_(dex_file) {}
+ explicit Field(const DexFile& dex_file,
+ const uint8_t* ptr_pos) : BaseItem(ptr_pos), dex_file_(dex_file) {}
const DexFile& GetDexFile() const {
return dex_file_;
}
+ bool IsStatic() const {
+ return is_static_;
+ }
+
+ // Unhide the hidden API access flags at the iterator position. TODO: Deprecate.
+ void UnHideAccessFlags() const;
+
private:
- const uint8_t* Read(const uint8_t* ptr);
+ void Read();
+ // Move to instance fields section.
void NextSection() {
index_ = 0u;
+ is_static_ = false;
}
const DexFile& dex_file_;
+ bool is_static_ = true;
friend class ClassAccessor;
};
@@ -144,11 +170,10 @@ class ClassAccessor {
uint32_t partition_pos,
uint32_t iterator_end,
const uint8_t* ptr_pos)
- : data_(dex_file),
+ : data_(dex_file, ptr_pos),
position_(position),
partition_pos_(partition_pos),
- iterator_end_(iterator_end),
- ptr_pos_(ptr_pos) {
+ iterator_end_(iterator_end) {
ReadData();
}
@@ -205,8 +230,7 @@ class ClassAccessor {
if (position_ == partition_pos_) {
data_.NextSection();
}
- DCHECK(ptr_pos_ != nullptr);
- ptr_pos_ = data_.Read(ptr_pos_);
+ data_.Read();
}
}
@@ -217,8 +241,6 @@ class ClassAccessor {
const uint32_t partition_pos_;
// At iterator_end_, the iterator is no longer valid.
const uint32_t iterator_end_;
- // Internal data pointer.
- const uint8_t* ptr_pos_;
};
// Not explicit specifically for range-based loops.
@@ -252,9 +274,21 @@ class ClassAccessor {
// Return the iteration range for all the fields.
IterationRange<DataIterator<Field>> GetFields() const;
+ // Return the iteration range for all the static fields.
+ IterationRange<DataIterator<Field>> GetStaticFields() const;
+
+ // Return the iteration range for all the instance fields.
+ IterationRange<DataIterator<Field>> GetInstanceFields() const;
+
// Return the iteration range for all the methods.
IterationRange<DataIterator<Method>> GetMethods() const;
+ // Return the iteration range for the direct methods.
+ IterationRange<DataIterator<Method>> GetDirectMethods() const;
+
+ // Return the iteration range for the virtual methods.
+ IterationRange<DataIterator<Method>> GetVirtualMethods() const;
+
uint32_t NumStaticFields() const {
return num_static_fields_;
}
@@ -263,6 +297,10 @@ class ClassAccessor {
return num_instance_fields_;
}
+ uint32_t NumFields() const {
+ return NumStaticFields() + NumInstanceFields();
+ }
+
uint32_t NumDirectMethods() const {
return num_direct_methods_;
}
@@ -285,14 +323,22 @@ class ClassAccessor {
return dex_file_;
}
+ bool HasClassData() const {
+ return ptr_pos_ != nullptr;
+ }
+
protected:
// Template visitor to reduce copy paste for visiting elements.
// No thread safety analysis since the visitor may require capabilities.
template <typename DataType, typename Visitor>
- const uint8_t* VisitMembers(size_t count,
- const Visitor& visitor,
- const uint8_t* ptr,
- DataType* data) const NO_THREAD_SAFETY_ANALYSIS;
+ void VisitMembers(size_t count, const Visitor& visitor, DataType* data) const
+ NO_THREAD_SAFETY_ANALYSIS;
+
+ // Return an iteration range for the first <count> fields.
+ IterationRange<DataIterator<Field>> GetFieldsInternal(size_t count) const;
+
+ // Return an iteration range for the first <count> methods.
+ IterationRange<DataIterator<Method>> GetMethodsInternal(size_t count) const;
const DexFile& dex_file_;
const dex::TypeIndex descriptor_index_ = {};
diff --git a/libdexfile/dex/class_accessor_test.cc b/libdexfile/dex/class_accessor_test.cc
index 95380d8140..d0533c1811 100644
--- a/libdexfile/dex/class_accessor_test.cc
+++ b/libdexfile/dex/class_accessor_test.cc
@@ -38,18 +38,27 @@ TEST_F(ClassAccessorTest, TestVisiting) {
auto fields = accessor.GetFields();
auto method_it = methods.begin();
auto field_it = fields.begin();
+ auto instance_fields = accessor.GetInstanceFields();
+ auto instance_field_it = instance_fields.begin();
accessor.VisitFieldsAndMethods(
// Static fields.
[&](const ClassAccessor::Field& field) {
+ EXPECT_TRUE(field.IsStatic());
+ EXPECT_TRUE(field_it->IsStatic());
EXPECT_EQ(field.GetIndex(), field_it->GetIndex());
EXPECT_EQ(field.GetAccessFlags(), field_it->GetAccessFlags());
++field_it;
},
// Instance fields.
[&](const ClassAccessor::Field& field) {
+ EXPECT_FALSE(field.IsStatic());
+ EXPECT_FALSE(field_it->IsStatic());
EXPECT_EQ(field.GetIndex(), field_it->GetIndex());
EXPECT_EQ(field.GetAccessFlags(), field_it->GetAccessFlags());
+ EXPECT_EQ(field.GetIndex(), instance_field_it->GetIndex());
+ EXPECT_EQ(field.GetAccessFlags(), instance_field_it->GetAccessFlags());
++field_it;
+ ++instance_field_it;
},
// Direct methods.
[&](const ClassAccessor::Method& method) {
@@ -71,6 +80,7 @@ TEST_F(ClassAccessorTest, TestVisiting) {
});
ASSERT_TRUE(field_it == fields.end());
ASSERT_TRUE(method_it == methods.end());
+ ASSERT_TRUE(instance_field_it == instance_fields.end());
}
EXPECT_EQ(class_def_idx, dex_file->NumClassDefs());
}
diff --git a/libdexfile/dex/dex_file.cc b/libdexfile/dex/dex_file.cc
index 9de260c862..f570158dfb 100644
--- a/libdexfile/dex/dex_file.cc
+++ b/libdexfile/dex/dex_file.cc
@@ -45,19 +45,18 @@ static_assert(std::is_trivially_copyable<dex::StringIndex>::value, "StringIndex
static_assert(sizeof(dex::TypeIndex) == sizeof(uint16_t), "TypeIndex size is wrong");
static_assert(std::is_trivially_copyable<dex::TypeIndex>::value, "TypeIndex not trivial");
-void DexFile::UnHideAccessFlags(ClassDataItemIterator& class_it) {
- uint8_t* data = const_cast<uint8_t*>(class_it.DataPointer());
- uint32_t new_flag = class_it.GetMemberAccessFlags();
- bool is_method = class_it.IsAtMethod();
+void DexFile::UnHideAccessFlags(uint8_t* data_ptr,
+ uint32_t new_access_flags,
+ bool is_method) {
// Go back 1 uleb to start.
- data = ReverseSearchUnsignedLeb128(data);
+ data_ptr = ReverseSearchUnsignedLeb128(data_ptr);
if (is_method) {
// Methods have another uleb field before the access flags
- data = ReverseSearchUnsignedLeb128(data);
+ data_ptr = ReverseSearchUnsignedLeb128(data_ptr);
}
- DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data)),
- new_flag);
- UpdateUnsignedLeb128(data, new_flag);
+ DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data_ptr)),
+ new_access_flags);
+ UpdateUnsignedLeb128(data_ptr, new_access_flags);
}
uint32_t DexFile::CalculateChecksum() const {
diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h
index f1f8b505bd..ed219808d2 100644
--- a/libdexfile/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -1010,8 +1010,8 @@ class DexFile {
return container_.get();
}
- // Changes the dex file pointed to by class_it to not have any hiddenapi flags.
- static void UnHideAccessFlags(ClassDataItemIterator& class_it);
+ // Changes the dex class data pointed to by data_ptr it to not have any hiddenapi flags.
+ static void UnHideAccessFlags(uint8_t* data_ptr, uint32_t new_access_flags, bool is_method);
inline IterationRange<ClassIterator> GetClasses() const;
diff --git a/libdexfile/dex/type_lookup_table.cc b/libdexfile/dex/type_lookup_table.cc
index ca5ec2f798..00ec358b02 100644
--- a/libdexfile/dex/type_lookup_table.cc
+++ b/libdexfile/dex/type_lookup_table.cc
@@ -20,72 +20,43 @@
#include <memory>
#include "base/bit_utils.h"
+#include "base/leb128.h"
#include "dex/dex_file-inl.h"
#include "dex/utf-inl.h"
namespace art {
-static uint16_t MakeData(uint16_t class_def_idx, uint32_t hash, uint32_t mask) {
- uint16_t hash_mask = static_cast<uint16_t>(~mask);
- return (static_cast<uint16_t>(hash) & hash_mask) | class_def_idx;
+static inline bool ModifiedUtf8StringEquals(const char* lhs, const char* rhs) {
+ return CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(lhs, rhs) == 0;
}
-TypeLookupTable::~TypeLookupTable() {
- if (!owns_entries_) {
- // We don't actually own the entries, don't let the unique_ptr release them.
- entries_.release();
+TypeLookupTable TypeLookupTable::Create(const DexFile& dex_file) {
+ uint32_t num_class_defs = dex_file.NumClassDefs();
+ if (UNLIKELY(!SupportedSize(num_class_defs))) {
+ return TypeLookupTable();
}
-}
-
-uint32_t TypeLookupTable::RawDataLength(uint32_t num_class_defs) {
- return SupportedSize(num_class_defs) ? RoundUpToPowerOfTwo(num_class_defs) * sizeof(Entry) : 0u;
-}
-
-uint32_t TypeLookupTable::CalculateMask(uint32_t num_class_defs) {
- return SupportedSize(num_class_defs) ? RoundUpToPowerOfTwo(num_class_defs) - 1u : 0u;
-}
-
-bool TypeLookupTable::SupportedSize(uint32_t num_class_defs) {
- return num_class_defs != 0u && num_class_defs <= std::numeric_limits<uint16_t>::max();
-}
-
-std::unique_ptr<TypeLookupTable> TypeLookupTable::Create(const DexFile& dex_file,
- uint8_t* storage) {
- const uint32_t num_class_defs = dex_file.NumClassDefs();
- return std::unique_ptr<TypeLookupTable>(SupportedSize(num_class_defs)
- ? new TypeLookupTable(dex_file, storage)
- : nullptr);
-}
-
-std::unique_ptr<TypeLookupTable> TypeLookupTable::Open(const uint8_t* dex_file_pointer,
- const uint8_t* raw_data,
- uint32_t num_class_defs) {
- return std::unique_ptr<TypeLookupTable>(
- new TypeLookupTable(dex_file_pointer, raw_data, num_class_defs));
-}
+ size_t mask_bits = CalculateMaskBits(num_class_defs);
+ size_t size = 1u << mask_bits;
+ std::unique_ptr<Entry[]> owned_entries(new Entry[size]);
+ Entry* entries = owned_entries.get();
-TypeLookupTable::TypeLookupTable(const DexFile& dex_file, uint8_t* storage)
- : dex_data_begin_(dex_file.DataBegin()),
- raw_data_length_(RawDataLength(dex_file.NumClassDefs())),
- mask_(CalculateMask(dex_file.NumClassDefs())),
- entries_(storage != nullptr ? reinterpret_cast<Entry*>(storage) : new Entry[mask_ + 1]),
- owns_entries_(storage == nullptr) {
static_assert(alignof(Entry) == 4u, "Expecting Entry to be 4-byte aligned.");
- DCHECK_ALIGNED(storage, alignof(Entry));
+ const uint32_t mask = Entry::GetMask(mask_bits);
std::vector<uint16_t> conflict_class_defs;
// The first stage. Put elements on their initial positions. If an initial position is already
// occupied then delay the insertion of the element to the second stage to reduce probing
// distance.
- for (size_t i = 0; i < dex_file.NumClassDefs(); ++i) {
- const DexFile::ClassDef& class_def = dex_file.GetClassDef(i);
+ for (size_t class_def_idx = 0; class_def_idx < dex_file.NumClassDefs(); ++class_def_idx) {
+ const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_idx);
const DexFile::TypeId& type_id = dex_file.GetTypeId(class_def.class_idx_);
const DexFile::StringId& str_id = dex_file.GetStringId(type_id.descriptor_idx_);
const uint32_t hash = ComputeModifiedUtf8Hash(dex_file.GetStringData(str_id));
- Entry entry;
- entry.str_offset = str_id.string_data_off_;
- entry.data = MakeData(i, hash, GetSizeMask());
- if (!SetOnInitialPos(entry, hash)) {
- conflict_class_defs.push_back(i);
+ const uint32_t pos = hash & mask;
+ if (entries[pos].IsEmpty()) {
+ entries[pos] = Entry(str_id.string_data_off_, hash, class_def_idx, mask_bits);
+ DCHECK(entries[pos].IsLast(mask_bits));
+ } else {
+ conflict_class_defs.push_back(class_def_idx);
}
}
// The second stage. The initial position of these elements had a collision. Put these elements
@@ -95,51 +66,111 @@ TypeLookupTable::TypeLookupTable(const DexFile& dex_file, uint8_t* storage)
const DexFile::TypeId& type_id = dex_file.GetTypeId(class_def.class_idx_);
const DexFile::StringId& str_id = dex_file.GetStringId(type_id.descriptor_idx_);
const uint32_t hash = ComputeModifiedUtf8Hash(dex_file.GetStringData(str_id));
- Entry entry;
- entry.str_offset = str_id.string_data_off_;
- entry.data = MakeData(class_def_idx, hash, GetSizeMask());
- Insert(entry, hash);
+ // Find the last entry in the chain.
+ uint32_t tail_pos = hash & mask;
+ DCHECK(!entries[tail_pos].IsEmpty());
+ while (!entries[tail_pos].IsLast(mask_bits)) {
+ tail_pos = (tail_pos + entries[tail_pos].GetNextPosDelta(mask_bits)) & mask;
+ DCHECK(!entries[tail_pos].IsEmpty());
+ }
+ // Find an empty entry for insertion.
+ uint32_t insert_pos = tail_pos;
+ do {
+ insert_pos = (insert_pos + 1) & mask;
+ } while (!entries[insert_pos].IsEmpty());
+ // Insert and chain the new entry.
+ entries[insert_pos] = Entry(str_id.string_data_off_, hash, class_def_idx, mask_bits);
+ entries[tail_pos].SetNextPosDelta((insert_pos - tail_pos) & mask, mask_bits);
+ DCHECK(entries[insert_pos].IsLast(mask_bits));
+ DCHECK(!entries[tail_pos].IsLast(mask_bits));
}
-}
-TypeLookupTable::TypeLookupTable(const uint8_t* dex_file_pointer,
- const uint8_t* raw_data,
- uint32_t num_class_defs)
- : dex_data_begin_(dex_file_pointer),
- raw_data_length_(RawDataLength(num_class_defs)),
- mask_(CalculateMask(num_class_defs)),
- entries_(reinterpret_cast<Entry*>(const_cast<uint8_t*>(raw_data))),
- owns_entries_(false) {}
-
-bool TypeLookupTable::SetOnInitialPos(const Entry& entry, uint32_t hash) {
- const uint32_t pos = hash & GetSizeMask();
- if (!entries_[pos].IsEmpty()) {
- return false;
- }
- entries_[pos] = entry;
- entries_[pos].next_pos_delta = 0;
- return true;
+ return TypeLookupTable(dex_file.DataBegin(), mask_bits, entries, std::move(owned_entries));
}
-void TypeLookupTable::Insert(const Entry& entry, uint32_t hash) {
- uint32_t pos = FindLastEntryInBucket(hash & GetSizeMask());
- uint32_t next_pos = (pos + 1) & GetSizeMask();
- while (!entries_[next_pos].IsEmpty()) {
- next_pos = (next_pos + 1) & GetSizeMask();
- }
- const uint32_t delta = (next_pos >= pos) ? (next_pos - pos) : (next_pos + Size() - pos);
- entries_[pos].next_pos_delta = delta;
- entries_[next_pos] = entry;
- entries_[next_pos].next_pos_delta = 0;
+TypeLookupTable TypeLookupTable::Open(const uint8_t* dex_data_pointer,
+ const uint8_t* raw_data,
+ uint32_t num_class_defs) {
+ DCHECK_ALIGNED(raw_data, alignof(Entry));
+ const Entry* entries = reinterpret_cast<const Entry*>(raw_data);
+ size_t mask_bits = CalculateMaskBits(num_class_defs);
+ return TypeLookupTable(dex_data_pointer, mask_bits, entries, /* owned_entries */ nullptr);
}
-uint32_t TypeLookupTable::FindLastEntryInBucket(uint32_t pos) const {
+uint32_t TypeLookupTable::Lookup(const char* str, uint32_t hash) const {
+ uint32_t mask = Entry::GetMask(mask_bits_);
+ uint32_t pos = hash & mask;
+ // Thanks to special insertion algorithm, the element at position pos can be empty
+ // or start of the right bucket, or anywhere in the wrong bucket's chain.
const Entry* entry = &entries_[pos];
- while (!entry->IsLast()) {
- pos = (pos + entry->next_pos_delta) & GetSizeMask();
+ if (entry->IsEmpty()) {
+ return dex::kDexNoIndex;
+ }
+ // Look for the partial hash match first, even if traversing the wrong bucket's chain.
+ uint32_t compared_hash_bits = (hash << mask_bits_) >> (2 * mask_bits_);
+ while (compared_hash_bits != entry->GetHashBits(mask_bits_)) {
+ if (entry->IsLast(mask_bits_)) {
+ return dex::kDexNoIndex;
+ }
+ pos = (pos + entry->GetNextPosDelta(mask_bits_)) & mask;
entry = &entries_[pos];
+ DCHECK(!entry->IsEmpty());
+ }
+ // Found partial hash match, compare strings (expecting this to succeed).
+ const char* first_checked_str = GetStringData(*entry);
+ if (ModifiedUtf8StringEquals(str, first_checked_str)) {
+ return entry->GetClassDefIdx(mask_bits_);
+ }
+ // If we're at the end of the chain, return before doing further expensive work.
+ if (entry->IsLast(mask_bits_)) {
+ return dex::kDexNoIndex;
+ }
+ // Check if we're traversing the right bucket. This is important if the compared
+ // partial hash has only a few bits (i.e. it can match frequently).
+ if (((ComputeModifiedUtf8Hash(first_checked_str) ^ hash) & mask) != 0u) {
+ return dex::kDexNoIndex; // Low hash bits mismatch.
}
- return pos;
+ // Continue looking for the string in the rest of the chain.
+ do {
+ pos = (pos + entry->GetNextPosDelta(mask_bits_)) & mask;
+ entry = &entries_[pos];
+ DCHECK(!entry->IsEmpty());
+ if (compared_hash_bits == entry->GetHashBits(mask_bits_) &&
+ ModifiedUtf8StringEquals(str, GetStringData(*entry))) {
+ return entry->GetClassDefIdx(mask_bits_);
+ }
+ } while (!entry->IsLast(mask_bits_));
+ // Not found.
+ return dex::kDexNoIndex;
+}
+
+uint32_t TypeLookupTable::RawDataLength(uint32_t num_class_defs) {
+ return SupportedSize(num_class_defs) ? RoundUpToPowerOfTwo(num_class_defs) * sizeof(Entry) : 0u;
+}
+
+uint32_t TypeLookupTable::CalculateMaskBits(uint32_t num_class_defs) {
+ return SupportedSize(num_class_defs) ? MinimumBitsToStore(num_class_defs - 1u) : 0u;
+}
+
+bool TypeLookupTable::SupportedSize(uint32_t num_class_defs) {
+ return num_class_defs != 0u && num_class_defs <= std::numeric_limits<uint16_t>::max();
+}
+
+TypeLookupTable::TypeLookupTable(const uint8_t* dex_data_pointer,
+ uint32_t mask_bits,
+ const Entry* entries,
+ std::unique_ptr<Entry[]> owned_entries)
+ : dex_data_begin_(dex_data_pointer),
+ mask_bits_(mask_bits),
+ entries_(entries),
+ owned_entries_(std::move(owned_entries)) {}
+
+const char* TypeLookupTable::GetStringData(const Entry& entry) const {
+ DCHECK(dex_data_begin_ != nullptr);
+ const uint8_t* ptr = dex_data_begin_ + entry.GetStringOffset();
+ // Skip string length.
+ DecodeUnsignedLeb128(&ptr);
+ return reinterpret_cast<const char*>(ptr);
}
} // namespace art
diff --git a/libdexfile/dex/type_lookup_table.h b/libdexfile/dex/type_lookup_table.h
index 0ba2b75dc6..7005d34b88 100644
--- a/libdexfile/dex/type_lookup_table.h
+++ b/libdexfile/dex/type_lookup_table.h
@@ -17,9 +17,8 @@
#ifndef ART_LIBDEXFILE_DEX_TYPE_LOOKUP_TABLE_H_
#define ART_LIBDEXFILE_DEX_TYPE_LOOKUP_TABLE_H_
-#include "base/leb128.h"
+#include "base/logging.h"
#include "dex/dex_file_types.h"
-#include "dex/utf.h"
namespace art {
@@ -34,140 +33,146 @@ class DexFile;
*/
class TypeLookupTable {
public:
- ~TypeLookupTable();
+ // Method creates lookup table for dex file.
+ static TypeLookupTable Create(const DexFile& dex_file);
+
+ // Method opens lookup table from binary data. Lookups will traverse strings and other
+ // data contained in dex_file as well. Lookup table does not own raw_data or dex_file.
+ static TypeLookupTable Open(const uint8_t* dex_data_pointer,
+ const uint8_t* raw_data,
+ uint32_t num_class_defs);
+
+ // Create an invalid lookup table.
+ TypeLookupTable()
+ : dex_data_begin_(nullptr),
+ mask_bits_(0u),
+ entries_(nullptr),
+ owned_entries_(nullptr) {}
+
+ TypeLookupTable(TypeLookupTable&& src) noexcept = default;
+ TypeLookupTable& operator=(TypeLookupTable&& src) noexcept = default;
+
+ ~TypeLookupTable() {
+ // Implicit deallocation by std::unique_ptr<> destructor.
+ }
+
+ // Returns whether the TypeLookupTable is valid.
+ bool Valid() const {
+ return entries_ != nullptr;
+ }
// Return the number of buckets in the lookup table.
uint32_t Size() const {
- return mask_ + 1;
+ DCHECK(Valid());
+ return 1u << mask_bits_;
}
// Method search class_def_idx by class descriptor and it's hash.
// If no data found then the method returns dex::kDexNoIndex.
- uint32_t Lookup(const char* str, uint32_t hash) const {
- uint32_t pos = hash & GetSizeMask();
- // Thanks to special insertion algorithm, the element at position pos can be empty or start of
- // bucket.
- const Entry* entry = &entries_[pos];
- while (!entry->IsEmpty()) {
- if (CmpHashBits(entry->data, hash) && IsStringsEquals(str, entry->str_offset)) {
- return GetClassDefIdx(entry->data);
- }
- if (entry->IsLast()) {
- return dex::kDexNoIndex;
- }
- pos = (pos + entry->next_pos_delta) & GetSizeMask();
- entry = &entries_[pos];
- }
- return dex::kDexNoIndex;
- }
-
- // Method creates lookup table for dex file
- static std::unique_ptr<TypeLookupTable> Create(const DexFile& dex_file,
- uint8_t* storage = nullptr);
-
- // Method opens lookup table from binary data. Lookups will traverse strings and other
- // data contained in dex_file as well. Lookup table does not own raw_data or dex_file.
- static std::unique_ptr<TypeLookupTable> Open(const uint8_t* dex_file_pointer,
- const uint8_t* raw_data,
- uint32_t num_class_defs);
+ uint32_t Lookup(const char* str, uint32_t hash) const;
// Method returns pointer to binary data of lookup table. Used by the oat writer.
const uint8_t* RawData() const {
- return reinterpret_cast<const uint8_t*>(entries_.get());
+ DCHECK(Valid());
+ return reinterpret_cast<const uint8_t*>(entries_);
}
// Method returns length of binary data. Used by the oat writer.
- uint32_t RawDataLength() const { return raw_data_length_; }
+ uint32_t RawDataLength() const {
+ DCHECK(Valid());
+ return Size() * sizeof(Entry);
+ }
// Method returns length of binary data for the specified number of class definitions.
static uint32_t RawDataLength(uint32_t num_class_defs);
private:
- /**
- * To find element we need to compare strings.
- * It is faster to compare first hashes and then strings itself.
- * But we have no full hash of element of table. But we can use 2 ideas.
- * 1. All minor bits of hash inside one bucket are equals.
- * 2. If dex file contains N classes and size of hash table is 2^n (where N <= 2^n)
- * then 16-n bits are free. So we can encode part of element's hash into these bits.
- * So hash of element can be divided on three parts:
- * XXXX XXXX XXXX YYYY YZZZ ZZZZ ZZZZZ
- * Z - a part of hash encoded in bucket (these bits of has are same for all elements in bucket) -
- * n bits
- * Y - a part of hash that we can write into free 16-n bits (because only n bits used to store
- * class_def_idx)
- * X - a part of has that we can't use without increasing increase
- * So the data element of Entry used to store class_def_idx and part of hash of the entry.
- */
- struct Entry {
- uint32_t str_offset;
- uint16_t data;
- uint16_t next_pos_delta;
-
- Entry() : str_offset(0), data(0), next_pos_delta(0) {}
+ /**
+ * To find element we need to compare strings.
+ * It is faster to compare first hashes and then strings itself.
+ * But we have no full hash of element of table. But we can use 2 ideas.
+ * 1. All minor bits of hash inside one bucket are equal.
+ * (TODO: We're not actually using this, are we?)
+ * 2. If the dex file contains N classes and the size of the hash table is 2^n (where N <= 2^n)
+ * then we need n bits for the class def index and n bits for the next position delta.
+ * So we can encode part of element's hash into the remaining 32-2*n (n <= 16) bits which
+ * would be otherwise wasted as a padding.
+ * So hash of element can be divided on three parts:
+ * XXXX XXXX XXXY YYYY YYYY YZZZ ZZZZ ZZZZ (example with n=11)
+ * Z - a part of hash encoded implicitly in the bucket index
+ * (these bits are same for all elements in bucket)
+ * Y - a part of hash that we can write into free 32-2*n bits
+ * X - a part of hash that we can't use without increasing the size of the entry
+ * So the `data` element of Entry is used to store the next position delta, class_def_index
+ * and a part of hash of the entry.
+ */
+ class Entry {
+ public:
+ Entry() : str_offset_(0u), data_(0u) {}
+ Entry(uint32_t str_offset, uint32_t hash, uint32_t class_def_index, uint32_t mask_bits)
+ : str_offset_(str_offset),
+ data_(((hash & ~GetMask(mask_bits)) | class_def_index) << mask_bits) {
+ DCHECK_EQ(class_def_index & ~GetMask(mask_bits), 0u);
+ }
+
+ void SetNextPosDelta(uint32_t next_pos_delta, uint32_t mask_bits) {
+ DCHECK_EQ(GetNextPosDelta(mask_bits), 0u);
+ DCHECK_EQ(next_pos_delta & ~GetMask(mask_bits), 0u);
+ DCHECK_NE(next_pos_delta, 0u);
+ data_ |= next_pos_delta;
+ }
bool IsEmpty() const {
- return str_offset == 0;
+ return str_offset_ == 0u;
}
- bool IsLast() const {
- return next_pos_delta == 0;
+ bool IsLast(uint32_t mask_bits) const {
+ return GetNextPosDelta(mask_bits) == 0u;
}
- };
- static uint32_t CalculateMask(uint32_t num_class_defs);
- static bool SupportedSize(uint32_t num_class_defs);
+ uint32_t GetStringOffset() const {
+ return str_offset_;
+ }
- // Construct from a dex file.
- explicit TypeLookupTable(const DexFile& dex_file, uint8_t* storage);
-
- // Construct from a dex file with existing data.
- TypeLookupTable(const uint8_t* dex_file_pointer,
- const uint8_t* raw_data,
- uint32_t num_class_defs);
-
- bool IsStringsEquals(const char* str, uint32_t str_offset) const {
- const uint8_t* ptr = dex_data_begin_ + str_offset;
- CHECK(dex_data_begin_ != nullptr);
- // Skip string length.
- DecodeUnsignedLeb128(&ptr);
- return CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(
- str, reinterpret_cast<const char*>(ptr)) == 0;
- }
+ uint32_t GetNextPosDelta(uint32_t mask_bits) const {
+ return data_ & GetMask(mask_bits);
+ }
- // Method extracts hash bits from element's data and compare them with
- // the corresponding bits of the specified hash
- bool CmpHashBits(uint32_t data, uint32_t hash) const {
- uint32_t mask = static_cast<uint16_t>(~GetSizeMask());
- return (hash & mask) == (data & mask);
- }
+ uint32_t GetClassDefIdx(uint32_t mask_bits) const {
+ return (data_ >> mask_bits) & GetMask(mask_bits);
+ }
- uint32_t GetClassDefIdx(uint32_t data) const {
- return data & mask_;
- }
+ uint32_t GetHashBits(uint32_t mask_bits) const {
+ DCHECK_LE(mask_bits, 16u);
+ return data_ >> (2u * mask_bits);
+ }
- uint32_t GetSizeMask() const {
- return mask_;
- }
+ static uint32_t GetMask(uint32_t mask_bits) {
+ DCHECK_LE(mask_bits, 16u);
+ return ~(std::numeric_limits<uint32_t>::max() << mask_bits);
+ }
- // Attempt to set an entry on its hash's slot. If there is already something there, return false.
- // Otherwise return true.
- bool SetOnInitialPos(const Entry& entry, uint32_t hash);
+ private:
+ uint32_t str_offset_;
+ uint32_t data_;
+ };
- // Insert an entry, probes until there is an empty slot.
- void Insert(const Entry& entry, uint32_t hash);
+ static uint32_t CalculateMaskBits(uint32_t num_class_defs);
+ static bool SupportedSize(uint32_t num_class_defs);
- // Find the last entry in a chain.
- uint32_t FindLastEntryInBucket(uint32_t cur_pos) const;
+ // Construct the TypeLookupTable.
+ TypeLookupTable(const uint8_t* dex_data_pointer,
+ uint32_t mask_bits,
+ const Entry* entries,
+ std::unique_ptr<Entry[]> owned_entries);
- const uint8_t* dex_data_begin_;
- const uint32_t raw_data_length_;
- const uint32_t mask_;
- std::unique_ptr<Entry[]> entries_;
- // owns_entries_ specifies if the lookup table owns the entries_ array.
- const bool owns_entries_;
+ const char* GetStringData(const Entry& entry) const;
- DISALLOW_IMPLICIT_CONSTRUCTORS(TypeLookupTable);
+ const uint8_t* dex_data_begin_;
+ uint32_t mask_bits_;
+ const Entry* entries_;
+ // `owned_entries_` is either null (not owning `entries_`) or same pointer as `entries_`.
+ std::unique_ptr<Entry[]> owned_entries_;
};
} // namespace art
diff --git a/libdexfile/dex/type_lookup_table_test.cc b/libdexfile/dex/type_lookup_table_test.cc
index 6c3d291332..4316be0bd6 100644
--- a/libdexfile/dex/type_lookup_table_test.cc
+++ b/libdexfile/dex/type_lookup_table_test.cc
@@ -30,20 +30,20 @@ class TypeLookupTableTest : public CommonArtTestWithParam<DescriptorClassDefIdxP
TEST_F(TypeLookupTableTest, CreateLookupTable) {
std::unique_ptr<const DexFile> dex_file(OpenTestDexFile("Lookup"));
- std::unique_ptr<TypeLookupTable> table(TypeLookupTable::Create(*dex_file));
- ASSERT_NE(nullptr, table.get());
- ASSERT_NE(nullptr, table->RawData());
- ASSERT_EQ(32U, table->RawDataLength());
+ TypeLookupTable table = TypeLookupTable::Create(*dex_file);
+ ASSERT_TRUE(table.Valid());
+ ASSERT_NE(nullptr, table.RawData());
+ ASSERT_EQ(32U, table.RawDataLength());
}
TEST_P(TypeLookupTableTest, Find) {
std::unique_ptr<const DexFile> dex_file(OpenTestDexFile("Lookup"));
- std::unique_ptr<TypeLookupTable> table(TypeLookupTable::Create(*dex_file));
- ASSERT_NE(nullptr, table.get());
+ TypeLookupTable table(TypeLookupTable::Create(*dex_file));
+ ASSERT_TRUE(table.Valid());
auto pair = GetParam();
const char* descriptor = pair.first;
size_t hash = ComputeModifiedUtf8Hash(descriptor);
- uint32_t class_def_idx = table->Lookup(descriptor, hash);
+ uint32_t class_def_idx = table.Lookup(descriptor, hash);
ASSERT_EQ(pair.second, class_def_idx);
}
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 7ac9e984ff..7b72e189b9 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -105,6 +105,10 @@ const char* image_methods_descriptions_[] = {
const char* image_roots_descriptions_[] = {
"kDexCaches",
"kClassRoots",
+ "kOomeWhenThrowingException",
+ "kOomeWhenThrowingOome",
+ "kOomeWhenHandlingStackOverflow",
+ "kNoClassDefFoundError",
"kClassLoader",
};
@@ -1942,17 +1946,17 @@ class ImageDumper {
os << "COMPILE PIC: " << (image_header_.CompilePic() ? "yes" : "no") << "\n\n";
{
- os << "ROOTS: " << reinterpret_cast<void*>(image_header_.GetImageRoots()) << "\n";
+ os << "ROOTS: " << reinterpret_cast<void*>(image_header_.GetImageRoots().Ptr()) << "\n";
static_assert(arraysize(image_roots_descriptions_) ==
static_cast<size_t>(ImageHeader::kImageRootsMax), "sizes must match");
DCHECK_LE(image_header_.GetImageRoots()->GetLength(), ImageHeader::kImageRootsMax);
for (int32_t i = 0, size = image_header_.GetImageRoots()->GetLength(); i != size; ++i) {
ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i);
const char* image_root_description = image_roots_descriptions_[i];
- mirror::Object* image_root_object = image_header_.GetImageRoot(image_root);
- indent_os << StringPrintf("%s: %p\n", image_root_description, image_root_object);
+ ObjPtr<mirror::Object> image_root_object = image_header_.GetImageRoot(image_root);
+ indent_os << StringPrintf("%s: %p\n", image_root_description, image_root_object.Ptr());
if (image_root_object != nullptr && image_root_object->IsObjectArray()) {
- mirror::ObjectArray<mirror::Object>* image_root_object_array
+ ObjPtr<mirror::ObjectArray<mirror::Object>> image_root_object_array
= image_root_object->AsObjectArray<mirror::Object>();
ScopedIndentation indent2(&vios_);
for (int j = 0; j < image_root_object_array->GetLength(); j++) {
diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc
index fcbafe7e71..a660fb56c4 100644
--- a/openjdkjvmti/fixed_up_dex_file.cc
+++ b/openjdkjvmti/fixed_up_dex_file.cc
@@ -31,6 +31,7 @@
#include "base/leb128.h"
#include "fixed_up_dex_file.h"
+#include "dex/class_accessor-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_loader.h"
#include "dex/dex_file_verifier.h"
@@ -51,14 +52,12 @@ static void RecomputeDexChecksum(art::DexFile* dex_file) {
}
static void UnhideApis(const art::DexFile& target_dex_file) {
- for (uint32_t i = 0; i < target_dex_file.NumClassDefs(); ++i) {
- const uint8_t* class_data = target_dex_file.GetClassData(target_dex_file.GetClassDef(i));
- if (class_data != nullptr) {
- for (art::ClassDataItemIterator class_it(target_dex_file, class_data);
- class_it.HasNext();
- class_it.Next()) {
- art::DexFile::UnHideAccessFlags(class_it);
- }
+ for (art::ClassAccessor accessor : target_dex_file.GetClasses()) {
+ for (const art::ClassAccessor::Field& field : accessor.GetFields()) {
+ field.UnHideAccessFlags();
+ }
+ for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
+ method.UnHideAccessFlags();
}
}
}
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index a6d3903f19..3c0b3e42c9 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -973,7 +973,7 @@ bool PatchOat::PatchImage(bool primary_image) {
ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin());
CHECK_GT(image_->Size(), sizeof(ImageHeader));
// These are the roots from the original file.
- auto* img_roots = image_header->GetImageRoots();
+ mirror::ObjectArray<mirror::Object>* img_roots = image_header->GetImageRoots().Ptr();
image_header->RelocateImage(delta_);
PatchArtFields(image_header);
diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h
index baa5102f5d..c5fb7d5f40 100644
--- a/runtime/art_field-inl.h
+++ b/runtime/art_field-inl.h
@@ -21,7 +21,7 @@
#include <android-base/logging.h>
-#include "class_linker.h"
+#include "class_linker-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/primitive.h"
#include "gc/accounting/card_table-inl.h"
@@ -339,16 +339,11 @@ inline const DexFile* ArtField::GetDexFile() REQUIRES_SHARED(Locks::mutator_lock
return GetDexCache<kWithoutReadBarrier>()->GetDexFile();
}
-inline ObjPtr<mirror::String> ArtField::GetStringName(Thread* self, bool resolve) {
- auto dex_field_index = GetDexFieldIndex();
+inline ObjPtr<mirror::String> ArtField::ResolveNameString() {
+ uint32_t dex_field_index = GetDexFieldIndex();
CHECK_NE(dex_field_index, dex::kDexNoIndex);
- ObjPtr<mirror::DexCache> dex_cache = GetDexCache();
- const DexFile::FieldId& field_id = dex_cache->GetDexFile()->GetFieldId(dex_field_index);
- ObjPtr<mirror::String> name = dex_cache->GetResolvedString(field_id.name_idx_);
- if (resolve && name == nullptr) {
- name = ResolveGetStringName(self, field_id.name_idx_, dex_cache);
- }
- return name;
+ const DexFile::FieldId& field_id = GetDexFile()->GetFieldId(dex_field_index);
+ return Runtime::Current()->GetClassLinker()->ResolveString(field_id.name_idx_, this);
}
template <typename Visitor>
diff --git a/runtime/art_field.cc b/runtime/art_field.cc
index b867621f02..6cbd9e4cfc 100644
--- a/runtime/art_field.cc
+++ b/runtime/art_field.cc
@@ -52,13 +52,6 @@ ObjPtr<mirror::Class> ArtField::ProxyFindSystemClass(const char* descriptor) {
return klass;
}
-ObjPtr<mirror::String> ArtField::ResolveGetStringName(Thread* self,
- dex::StringIndex string_idx,
- ObjPtr<mirror::DexCache> dex_cache) {
- StackHandleScope<1> hs(self);
- return Runtime::Current()->GetClassLinker()->ResolveString(string_idx, hs.NewHandle(dex_cache));
-}
-
std::string ArtField::PrettyField(ArtField* f, bool with_type) {
if (f == nullptr) {
return "null";
diff --git a/runtime/art_field.h b/runtime/art_field.h
index 784a862425..123595c6fe 100644
--- a/runtime/art_field.h
+++ b/runtime/art_field.h
@@ -201,8 +201,7 @@ class ArtField FINAL {
const char* GetName() REQUIRES_SHARED(Locks::mutator_lock_);
// Resolves / returns the name from the dex cache.
- ObjPtr<mirror::String> GetStringName(Thread* self, bool resolve)
- REQUIRES_SHARED(Locks::mutator_lock_);
+ ObjPtr<mirror::String> ResolveNameString() REQUIRES_SHARED(Locks::mutator_lock_);
const char* GetTypeDescriptor() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -241,10 +240,6 @@ class ArtField FINAL {
ObjPtr<mirror::Class> ProxyFindSystemClass(const char* descriptor)
REQUIRES_SHARED(Locks::mutator_lock_);
- ObjPtr<mirror::String> ResolveGetStringName(Thread* self,
- dex::StringIndex string_idx,
- ObjPtr<mirror::DexCache> dex_cache)
- REQUIRES_SHARED(Locks::mutator_lock_);
void GetAccessFlagsDCheck() REQUIRES_SHARED(Locks::mutator_lock_);
void GetOffsetDCheck() REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index ec66966869..18595cf17a 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -245,6 +245,12 @@ inline const char* ArtMethod::GetName() {
}
}
+inline ObjPtr<mirror::String> ArtMethod::ResolveNameString() {
+ DCHECK(!IsProxyMethod());
+ const DexFile::MethodId& method_id = GetDexFile()->GetMethodId(GetDexMethodIndex());
+ return Runtime::Current()->GetClassLinker()->ResolveString(method_id.name_idx_, this);
+}
+
inline const DexFile::CodeItem* ArtMethod::GetCodeItem() {
return GetDexFile()->GetCodeItem(GetCodeItemOffset());
}
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 151c36f3bc..45bf66446a 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -26,6 +26,7 @@
#include "class_linker-inl.h"
#include "class_root.h"
#include "debugger.h"
+#include "dex/class_accessor-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_exception_helpers.h"
@@ -142,16 +143,6 @@ uint16_t ArtMethod::FindObsoleteDexClassDefIndex() {
return dex_file->GetIndexForClassDef(*class_def);
}
-ObjPtr<mirror::String> ArtMethod::GetNameAsString(Thread* self) {
- CHECK(!IsProxyMethod());
- StackHandleScope<1> hs(self);
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(GetDexCache()));
- auto* dex_file = dex_cache->GetDexFile();
- uint32_t dex_method_idx = GetDexMethodIndex();
- const DexFile::MethodId& method_id = dex_file->GetMethodId(dex_method_idx);
- return Runtime::Current()->GetClassLinker()->ResolveString(method_id.name_idx_, dex_cache);
-}
-
void ArtMethod::ThrowInvocationTimeError() {
DCHECK(!IsInvokable());
// NOTE: IsDefaultConflicting must be first since the actual method might or might not be abstract
@@ -434,28 +425,14 @@ bool ArtMethod::IsPolymorphicSignature() {
static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file,
uint16_t class_def_idx,
uint32_t method_idx) {
- const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_idx);
- const uint8_t* class_data = dex_file.GetClassData(class_def);
- CHECK(class_data != nullptr);
- ClassDataItemIterator it(dex_file, class_data);
- it.SkipAllFields();
- // Process methods
- size_t class_def_method_index = 0;
- while (it.HasNextDirectMethod()) {
- if (it.GetMemberIndex() == method_idx) {
- return class_def_method_index;
- }
- class_def_method_index++;
- it.Next();
- }
- while (it.HasNextVirtualMethod()) {
- if (it.GetMemberIndex() == method_idx) {
+ ClassAccessor accessor(dex_file, dex_file.GetClassDef(class_def_idx));
+ uint32_t class_def_method_index = 0u;
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+ if (method.GetIndex() == method_idx) {
return class_def_method_index;
}
class_def_method_index++;
- it.Next();
}
- DCHECK(!it.HasNext());
LOG(FATAL) << "Failed to find method index " << method_idx << " in " << dex_file.GetLocation();
UNREACHABLE();
}
diff --git a/runtime/art_method.h b/runtime/art_method.h
index 012d706756..09debb0c50 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -589,7 +589,7 @@ class ArtMethod FINAL {
ALWAYS_INLINE const char* GetName() REQUIRES_SHARED(Locks::mutator_lock_);
- ObjPtr<mirror::String> GetNameAsString(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
+ ObjPtr<mirror::String> ResolveNameString() REQUIRES_SHARED(Locks::mutator_lock_);
const DexFile::CodeItem* GetCodeItem() REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 664b917543..2536b23416 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -61,6 +61,54 @@ inline ObjPtr<mirror::Class> ClassLinker::FindArrayClass(Thread* self,
return array_class;
}
+inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
+ ArtField* referrer) {
+ Thread::PoisonObjectPointersIfDebug();
+ DCHECK(!Thread::Current()->IsExceptionPending());
+ // We do not need the read barrier for getting the DexCache for the initial resolved type
+ // lookup as both from-space and to-space copies point to the same native resolved types array.
+ ObjPtr<mirror::String> resolved =
+ referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedString(string_idx);
+ if (resolved == nullptr) {
+ resolved = DoResolveString(string_idx, referrer->GetDexCache());
+ }
+ return resolved;
+}
+
+inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
+ ArtMethod* referrer) {
+ Thread::PoisonObjectPointersIfDebug();
+ DCHECK(!Thread::Current()->IsExceptionPending());
+ // We do not need the read barrier for getting the DexCache for the initial resolved type
+ // lookup as both from-space and to-space copies point to the same native resolved types array.
+ ObjPtr<mirror::String> resolved =
+ referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedString(string_idx);
+ if (resolved == nullptr) {
+ resolved = DoResolveString(string_idx, referrer->GetDexCache());
+ }
+ return resolved;
+}
+
+inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
+ Handle<mirror::DexCache> dex_cache) {
+ Thread::PoisonObjectPointersIfDebug();
+ DCHECK(!Thread::Current()->IsExceptionPending());
+ ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
+ if (resolved == nullptr) {
+ resolved = DoResolveString(string_idx, dex_cache);
+ }
+ return resolved;
+}
+
+inline ObjPtr<mirror::String> ClassLinker::LookupString(dex::StringIndex string_idx,
+ ObjPtr<mirror::DexCache> dex_cache) {
+ ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
+ if (resolved == nullptr) {
+ resolved = DoLookupString(string_idx, dex_cache);
+ }
+ return resolved;
+}
+
inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
ObjPtr<mirror::Class> referrer) {
if (kObjPtrPoisoning) {
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 67987963e1..be636d80a8 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -56,6 +56,7 @@
#include "compiler_callbacks.h"
#include "debug_print.h"
#include "debugger.h"
+#include "dex/class_accessor-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_exception_helpers.h"
@@ -197,8 +198,7 @@ static void HandleEarlierVerifyError(Thread* self,
}
} else {
// Previous error has been stored as an instance. Just rethrow.
- ObjPtr<mirror::Class> throwable_class =
- self->DecodeJObject(WellKnownClasses::java_lang_Throwable)->AsClass();
+ ObjPtr<mirror::Class> throwable_class = GetClassRoot<mirror::Throwable>(class_linker);
ObjPtr<mirror::Class> error_class = obj->GetClass();
CHECK(throwable_class->IsAssignableFrom(error_class));
self->SetException(obj->AsThrowable());
@@ -376,7 +376,6 @@ ClassLinker::ClassLinker(InternTable* intern_table)
: boot_class_table_(new ClassTable()),
failed_dex_cache_class_lookups_(0),
class_roots_(nullptr),
- array_iftable_(nullptr),
find_array_class_cache_next_victim_(0),
init_done_(false),
log_new_roots_(false),
@@ -512,6 +511,10 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
// Fill in the empty iftable. Needs to be done after the kObjectArrayClass root is set.
java_lang_Object->SetIfTable(AllocIfTable(self, 0));
+ // Create array interface entries to populate once we can load system classes.
+ object_array_class->SetIfTable(AllocIfTable(self, 2));
+ DCHECK_EQ(GetArrayIfTable(), object_array_class->GetIfTable());
+
// Setup the primitive type classes.
SetClassRoot(ClassRoot::kPrimitiveBoolean, CreatePrimitiveClass(self, Primitive::kPrimBoolean));
SetClassRoot(ClassRoot::kPrimitiveByte, CreatePrimitiveClass(self, Primitive::kPrimByte));
@@ -523,9 +526,6 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
SetClassRoot(ClassRoot::kPrimitiveDouble, CreatePrimitiveClass(self, Primitive::kPrimDouble));
SetClassRoot(ClassRoot::kPrimitiveVoid, CreatePrimitiveClass(self, Primitive::kPrimVoid));
- // Create array interface entries to populate once we can load system classes.
- array_iftable_ = GcRoot<mirror::IfTable>(AllocIfTable(self, 2));
-
// Create int array type for native pointer arrays (for example vtables) on 32-bit archs.
Handle<mirror::Class> int_array_class(hs.NewHandle(
AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_))));
@@ -639,8 +639,8 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
CHECK(java_io_Serializable != nullptr);
// We assume that Cloneable/Serializable don't have superinterfaces -- normally we'd have to
// crawl up and explicitly list all of the supers as well.
- array_iftable_.Read()->SetInterface(0, java_lang_Cloneable.Get());
- array_iftable_.Read()->SetInterface(1, java_io_Serializable.Get());
+ object_array_class->GetIfTable()->SetInterface(0, java_lang_Cloneable.Get());
+ object_array_class->GetIfTable()->SetInterface(1, java_io_Serializable.Get());
// Sanity check Class[] and Object[]'s interfaces. GetDirectInterface may cause thread
// suspension.
@@ -841,7 +841,7 @@ void ClassLinker::FinishInit(Thread* self) {
// if possible add new checks there to catch errors early
}
- CHECK(!array_iftable_.IsNull());
+ CHECK(GetArrayIfTable() != nullptr);
// disable the slow paths in FindClass and CreatePrimitiveClass now
// that Object, Class, and Object[] are setup
@@ -1000,11 +1000,6 @@ bool ClassLinker::InitFromBootImage(std::string* error_msg) {
runtime->SetSentinel(heap->AllocNonMovableObject<true>(
self, java_lang_Object, java_lang_Object->GetObjectSize(), VoidFunctor()));
- // reinit array_iftable_ from any array class instance, they should be ==
- array_iftable_ =
- GcRoot<mirror::IfTable>(GetClassRoot(ClassRoot::kObjectArrayClass, this)->GetIfTable());
- DCHECK_EQ(array_iftable_.Read(), GetClassRoot(ClassRoot::kBooleanArrayClass, this)->GetIfTable());
-
for (gc::space::ImageSpace* image_space : spaces) {
// Boot class loader, use a null handle.
std::vector<std::unique_ptr<const DexFile>> dex_files;
@@ -1931,7 +1926,6 @@ void ClassLinker::VisitClassRoots(RootVisitor* visitor, VisitRootFlags flags) {
void ClassLinker::VisitRoots(RootVisitor* visitor, VisitRootFlags flags) {
class_roots_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
VisitClassRoots(visitor, flags);
- array_iftable_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
// Instead of visiting the find_array_class_cache_ drop it so that it doesn't prevent class
// unloading if we are marking roots.
DropFindArrayClassCache();
@@ -2730,52 +2724,50 @@ ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self,
uint32_t ClassLinker::SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def) {
- const uint8_t* class_data = dex_file.GetClassData(dex_class_def);
size_t num_ref = 0;
size_t num_8 = 0;
size_t num_16 = 0;
size_t num_32 = 0;
size_t num_64 = 0;
- if (class_data != nullptr) {
- // We allow duplicate definitions of the same field in a class_data_item
- // but ignore the repeated indexes here, b/21868015.
- uint32_t last_field_idx = dex::kDexNoIndex;
- for (ClassDataItemIterator it(dex_file, class_data); it.HasNextStaticField(); it.Next()) {
- uint32_t field_idx = it.GetMemberIndex();
- // Ordering enforced by DexFileVerifier.
- DCHECK(last_field_idx == dex::kDexNoIndex || last_field_idx <= field_idx);
- if (UNLIKELY(field_idx == last_field_idx)) {
- continue;
- }
- last_field_idx = field_idx;
- const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
- const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
- char c = descriptor[0];
- switch (c) {
- case 'L':
- case '[':
- num_ref++;
- break;
- case 'J':
- case 'D':
- num_64++;
- break;
- case 'I':
- case 'F':
- num_32++;
- break;
- case 'S':
- case 'C':
- num_16++;
- break;
- case 'B':
- case 'Z':
- num_8++;
- break;
- default:
- LOG(FATAL) << "Unknown descriptor: " << c;
- UNREACHABLE();
- }
+ ClassAccessor accessor(dex_file, dex_class_def);
+ // We allow duplicate definitions of the same field in a class_data_item
+ // but ignore the repeated indexes here, b/21868015.
+ uint32_t last_field_idx = dex::kDexNoIndex;
+ for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
+ uint32_t field_idx = field.GetIndex();
+ // Ordering enforced by DexFileVerifier.
+ DCHECK(last_field_idx == dex::kDexNoIndex || last_field_idx <= field_idx);
+ if (UNLIKELY(field_idx == last_field_idx)) {
+ continue;
+ }
+ last_field_idx = field_idx;
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
+ const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
+ char c = descriptor[0];
+ switch (c) {
+ case 'L':
+ case '[':
+ num_ref++;
+ break;
+ case 'J':
+ case 'D':
+ num_64++;
+ break;
+ case 'I':
+ case 'F':
+ num_32++;
+ break;
+ case 'S':
+ case 'C':
+ num_16++;
+ break;
+ case 'B':
+ case 'Z':
+ num_8++;
+ break;
+ default:
+ LOG(FATAL) << "Unknown descriptor: " << c;
+ UNREACHABLE();
}
}
return mirror::Class::ComputeClassSize(false,
@@ -2873,17 +2865,15 @@ void ClassLinker::FixupStaticTrampolines(ObjPtr<mirror::Class> klass) {
const DexFile& dex_file = klass->GetDexFile();
const DexFile::ClassDef* dex_class_def = klass->GetClassDef();
CHECK(dex_class_def != nullptr);
- const uint8_t* class_data = dex_file.GetClassData(*dex_class_def);
+ ClassAccessor accessor(dex_file, *dex_class_def);
// There should always be class data if there were direct methods.
- CHECK(class_data != nullptr) << klass->PrettyDescriptor();
- ClassDataItemIterator it(dex_file, class_data);
- it.SkipAllFields();
+ CHECK(accessor.HasClassData()) << klass->PrettyDescriptor();
bool has_oat_class;
OatFile::OatClass oat_class = OatFile::FindOatClass(dex_file,
klass->GetDexClassDefIndex(),
&has_oat_class);
// Link the code of methods skipped by LinkCode.
- for (size_t method_index = 0; it.HasNextDirectMethod(); ++method_index, it.Next()) {
+ for (size_t method_index = 0; method_index < accessor.NumDirectMethods(); ++method_index) {
ArtMethod* method = klass->GetDirectMethod(method_index, image_pointer_size_);
if (!method->IsStatic()) {
// Only update static methods.
@@ -2992,17 +2982,6 @@ void ClassLinker::SetupClass(const DexFile& dex_file,
klass->SetDexTypeIndex(dex_class_def.class_idx_);
}
-void ClassLinker::LoadClass(Thread* self,
- const DexFile& dex_file,
- const DexFile::ClassDef& dex_class_def,
- Handle<mirror::Class> klass) {
- const uint8_t* class_data = dex_file.GetClassData(dex_class_def);
- if (class_data == nullptr) {
- return; // no fields or methods - for example a marker interface
- }
- LoadClassMembers(self, dex_file, class_data, klass);
-}
-
LengthPrefixedArray<ArtField>* ClassLinker::AllocArtFieldArray(Thread* self,
LinearAlloc* allocator,
size_t length) {
@@ -3061,10 +3040,15 @@ LinearAlloc* ClassLinker::GetOrCreateAllocatorForClassLoader(ObjPtr<mirror::Clas
return allocator;
}
-void ClassLinker::LoadClassMembers(Thread* self,
- const DexFile& dex_file,
- const uint8_t* class_data,
- Handle<mirror::Class> klass) {
+void ClassLinker::LoadClass(Thread* self,
+ const DexFile& dex_file,
+ const DexFile::ClassDef& dex_class_def,
+ Handle<mirror::Class> klass) {
+ ClassAccessor accessor(dex_file, dex_class_def);
+ if (!accessor.HasClassData()) {
+ return;
+ }
+ Runtime* const runtime = Runtime::Current();
{
// Note: We cannot have thread suspension until the field and method arrays are setup or else
// Class::VisitFieldRoots may miss some fields or methods.
@@ -3073,45 +3057,79 @@ void ClassLinker::LoadClassMembers(Thread* self,
// We allow duplicate definitions of the same field in a class_data_item
// but ignore the repeated indexes here, b/21868015.
LinearAlloc* const allocator = GetAllocatorForClassLoader(klass->GetClassLoader());
- ClassDataItemIterator it(dex_file, class_data);
LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self,
allocator,
- it.NumStaticFields());
- size_t num_sfields = 0;
- uint32_t last_field_idx = 0u;
- for (; it.HasNextStaticField(); it.Next()) {
- uint32_t field_idx = it.GetMemberIndex();
- DCHECK_GE(field_idx, last_field_idx); // Ordering enforced by DexFileVerifier.
- if (num_sfields == 0 || LIKELY(field_idx > last_field_idx)) {
- DCHECK_LT(num_sfields, it.NumStaticFields());
- LoadField(it, klass, &sfields->At(num_sfields));
- ++num_sfields;
- last_field_idx = field_idx;
- }
- }
-
- // Load instance fields.
+ accessor.NumStaticFields());
LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self,
allocator,
- it.NumInstanceFields());
+ accessor.NumInstanceFields());
+ size_t num_sfields = 0u;
size_t num_ifields = 0u;
- last_field_idx = 0u;
- for (; it.HasNextInstanceField(); it.Next()) {
- uint32_t field_idx = it.GetMemberIndex();
- DCHECK_GE(field_idx, last_field_idx); // Ordering enforced by DexFileVerifier.
- if (num_ifields == 0 || LIKELY(field_idx > last_field_idx)) {
- DCHECK_LT(num_ifields, it.NumInstanceFields());
- LoadField(it, klass, &ifields->At(num_ifields));
- ++num_ifields;
- last_field_idx = field_idx;
- }
- }
+ uint32_t last_static_field_idx = 0u;
+ uint32_t last_instance_field_idx = 0u;
+
+ // Methods
+ bool has_oat_class = false;
+ const OatFile::OatClass oat_class = (runtime->IsStarted() && !runtime->IsAotCompiler())
+ ? OatFile::FindOatClass(dex_file, klass->GetDexClassDefIndex(), &has_oat_class)
+ : OatFile::OatClass::Invalid();
+ const OatFile::OatClass* oat_class_ptr = has_oat_class ? &oat_class : nullptr;
+ klass->SetMethodsPtr(
+ AllocArtMethodArray(self, allocator, accessor.NumMethods()),
+ accessor.NumDirectMethods(),
+ accessor.NumVirtualMethods());
+ size_t class_def_method_index = 0;
+ uint32_t last_dex_method_index = dex::kDexNoIndex;
+ size_t last_class_def_method_index = 0;
- if (UNLIKELY(num_sfields != it.NumStaticFields()) ||
- UNLIKELY(num_ifields != it.NumInstanceFields())) {
+ // Use the visitor since the ranged based loops are bit slower from seeking. Seeking to the
+ // methods needs to decode all of the fields.
+ accessor.VisitFieldsAndMethods([&](
+ const ClassAccessor::Field& field) REQUIRES_SHARED(Locks::mutator_lock_) {
+ uint32_t field_idx = field.GetIndex();
+ DCHECK_GE(field_idx, last_static_field_idx); // Ordering enforced by DexFileVerifier.
+ if (num_sfields == 0 || LIKELY(field_idx > last_static_field_idx)) {
+ LoadField(field, klass, &sfields->At(num_sfields));
+ ++num_sfields;
+ last_static_field_idx = field_idx;
+ }
+ }, [&](const ClassAccessor::Field& field) REQUIRES_SHARED(Locks::mutator_lock_) {
+ uint32_t field_idx = field.GetIndex();
+ DCHECK_GE(field_idx, last_instance_field_idx); // Ordering enforced by DexFileVerifier.
+ if (num_ifields == 0 || LIKELY(field_idx > last_instance_field_idx)) {
+ LoadField(field, klass, &ifields->At(num_ifields));
+ ++num_ifields;
+ last_instance_field_idx = field_idx;
+ }
+ }, [&](const ClassAccessor::Method& method) REQUIRES_SHARED(Locks::mutator_lock_) {
+ ArtMethod* art_method = klass->GetDirectMethodUnchecked(class_def_method_index,
+ image_pointer_size_);
+ LoadMethod(dex_file, method, klass, art_method);
+ LinkCode(this, art_method, oat_class_ptr, class_def_method_index);
+ uint32_t it_method_index = method.GetIndex();
+ if (last_dex_method_index == it_method_index) {
+ // duplicate case
+ art_method->SetMethodIndex(last_class_def_method_index);
+ } else {
+ art_method->SetMethodIndex(class_def_method_index);
+ last_dex_method_index = it_method_index;
+ last_class_def_method_index = class_def_method_index;
+ }
+ ++class_def_method_index;
+ }, [&](const ClassAccessor::Method& method) REQUIRES_SHARED(Locks::mutator_lock_) {
+ ArtMethod* art_method = klass->GetVirtualMethodUnchecked(
+ class_def_method_index - accessor.NumDirectMethods(),
+ image_pointer_size_);
+ LoadMethod(dex_file, method, klass, art_method);
+ LinkCode(this, art_method, oat_class_ptr, class_def_method_index);
+ ++class_def_method_index;
+ });
+
+ if (UNLIKELY(num_ifields + num_sfields != accessor.NumFields())) {
LOG(WARNING) << "Duplicate fields in class " << klass->PrettyDescriptor()
- << " (unique static fields: " << num_sfields << "/" << it.NumStaticFields()
- << ", unique instance fields: " << num_ifields << "/" << it.NumInstanceFields() << ")";
+ << " (unique static fields: " << num_sfields << "/" << accessor.NumStaticFields()
+ << ", unique instance fields: " << num_ifields << "/" << accessor.NumInstanceFields()
+ << ")";
// NOTE: Not shrinking the over-allocated sfields/ifields, just setting size.
if (sfields != nullptr) {
sfields->SetSize(num_sfields);
@@ -3125,87 +3143,49 @@ void ClassLinker::LoadClassMembers(Thread* self,
DCHECK_EQ(klass->NumStaticFields(), num_sfields);
klass->SetIFieldsPtr(ifields);
DCHECK_EQ(klass->NumInstanceFields(), num_ifields);
- // Load methods.
- bool has_oat_class = false;
- const OatFile::OatClass oat_class =
- (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler())
- ? OatFile::FindOatClass(dex_file, klass->GetDexClassDefIndex(), &has_oat_class)
- : OatFile::OatClass::Invalid();
- const OatFile::OatClass* oat_class_ptr = has_oat_class ? &oat_class : nullptr;
- klass->SetMethodsPtr(
- AllocArtMethodArray(self, allocator, it.NumDirectMethods() + it.NumVirtualMethods()),
- it.NumDirectMethods(),
- it.NumVirtualMethods());
- size_t class_def_method_index = 0;
- uint32_t last_dex_method_index = dex::kDexNoIndex;
- size_t last_class_def_method_index = 0;
- // TODO These should really use the iterators.
- for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
- ArtMethod* method = klass->GetDirectMethodUnchecked(i, image_pointer_size_);
- LoadMethod(dex_file, it, klass, method);
- LinkCode(this, method, oat_class_ptr, class_def_method_index);
- uint32_t it_method_index = it.GetMemberIndex();
- if (last_dex_method_index == it_method_index) {
- // duplicate case
- method->SetMethodIndex(last_class_def_method_index);
- } else {
- method->SetMethodIndex(class_def_method_index);
- last_dex_method_index = it_method_index;
- last_class_def_method_index = class_def_method_index;
- }
- class_def_method_index++;
- }
- for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
- ArtMethod* method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
- LoadMethod(dex_file, it, klass, method);
- DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
- LinkCode(this, method, oat_class_ptr, class_def_method_index);
- class_def_method_index++;
- }
- DCHECK(!it.HasNext());
}
// Ensure that the card is marked so that remembered sets pick up native roots.
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(klass.Get());
self->AllowThreadSuspension();
}
-void ClassLinker::LoadField(const ClassDataItemIterator& it,
+void ClassLinker::LoadField(const ClassAccessor::Field& field,
Handle<mirror::Class> klass,
ArtField* dst) {
- const uint32_t field_idx = it.GetMemberIndex();
+ const uint32_t field_idx = field.GetIndex();
dst->SetDexFieldIndex(field_idx);
dst->SetDeclaringClass(klass.Get());
// Get access flags from the DexFile. If this is a boot class path class,
// also set its runtime hidden API access flags.
- uint32_t access_flags = it.GetFieldAccessFlags();
+ uint32_t access_flags = field.GetAccessFlags();
if (klass->IsBootStrapClassLoaded()) {
access_flags =
- HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags());
+ HiddenApiAccessFlags::EncodeForRuntime(access_flags, field.DecodeHiddenAccessFlags());
}
dst->SetAccessFlags(access_flags);
}
void ClassLinker::LoadMethod(const DexFile& dex_file,
- const ClassDataItemIterator& it,
+ const ClassAccessor::Method& method,
Handle<mirror::Class> klass,
ArtMethod* dst) {
- uint32_t dex_method_idx = it.GetMemberIndex();
+ const uint32_t dex_method_idx = method.GetIndex();
const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
const char* method_name = dex_file.StringDataByIdx(method_id.name_idx_);
ScopedAssertNoThreadSuspension ants("LoadMethod");
dst->SetDexMethodIndex(dex_method_idx);
dst->SetDeclaringClass(klass.Get());
- dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());
+ dst->SetCodeItemOffset(method.GetCodeItemOffset());
// Get access flags from the DexFile. If this is a boot class path class,
// also set its runtime hidden API access flags.
- uint32_t access_flags = it.GetMethodAccessFlags();
+ uint32_t access_flags = method.GetAccessFlags();
if (klass->IsBootStrapClassLoaded()) {
access_flags =
- HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags());
+ HiddenApiAccessFlags::EncodeForRuntime(access_flags, method.DecodeHiddenAccessFlags());
}
if (UNLIKELY(strcmp("finalize", method_name) == 0)) {
@@ -3380,6 +3360,7 @@ ObjPtr<mirror::DexCache> ClassLinker::EnsureSameClassLoader(
void ClassLinker::RegisterExistingDexCache(ObjPtr<mirror::DexCache> dex_cache,
ObjPtr<mirror::ClassLoader> class_loader) {
+ SCOPED_TRACE << __FUNCTION__ << " " << dex_cache->GetDexFile()->GetLocation();
Thread* self = Thread::Current();
StackHandleScope<2> hs(self);
Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(dex_cache));
@@ -3401,6 +3382,10 @@ void ClassLinker::RegisterExistingDexCache(ObjPtr<mirror::DexCache> dex_cache,
WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
table = InsertClassTableForClassLoader(h_class_loader.Get());
}
+ // Avoid a deadlock between a garbage collecting thread running a checkpoint,
+ // a thread holding the dex lock and blocking on a condition variable regarding
+ // weak references access, and a thread blocking on the dex lock.
+ gc::ScopedGCCriticalSection gcs(self, gc::kGcCauseClassLinker, gc::kCollectorTypeClassLinker);
WriterMutexLock mu(self, *Locks::dex_lock_);
RegisterDexFileLocked(*dex_file, h_dex_cache.Get(), h_class_loader.Get());
table->InsertStrongRoot(h_dex_cache.Get());
@@ -3423,6 +3408,7 @@ ObjPtr<mirror::DexCache> ClassLinker::RegisterDexFile(const DexFile& dex_file,
if (old_dex_cache != nullptr) {
return EnsureSameClassLoader(self, old_dex_cache, old_data, class_loader);
}
+ SCOPED_TRACE << __FUNCTION__ << " " << dex_file.GetLocation();
LinearAlloc* const linear_alloc = GetOrCreateAllocatorForClassLoader(class_loader);
DCHECK(linear_alloc != nullptr);
ClassTable* table;
@@ -3441,6 +3427,10 @@ ObjPtr<mirror::DexCache> ClassLinker::RegisterDexFile(const DexFile& dex_file,
dex_file)));
Handle<mirror::String> h_location(hs.NewHandle(location));
{
+ // Avoid a deadlock between a garbage collecting thread running a checkpoint,
+ // a thread holding the dex lock and blocking on a condition variable regarding
+ // weak references access, and a thread blocking on the dex lock.
+ gc::ScopedGCCriticalSection gcs(self, gc::kGcCauseClassLinker, gc::kCollectorTypeClassLinker);
WriterMutexLock mu(self, *Locks::dex_lock_);
old_data = FindDexCacheDataLocked(dex_file);
old_dex_cache = DecodeDexCache(self, old_data);
@@ -3553,6 +3543,10 @@ ObjPtr<mirror::Class> ClassLinker::CreatePrimitiveClass(Thread* self, Primitive:
return h_class.Get();
}
+inline ObjPtr<mirror::IfTable> ClassLinker::GetArrayIfTable() {
+ return GetClassRoot<mirror::ObjectArray<mirror::Object>>(this)->GetIfTable();
+}
+
// Create an array class (i.e. the class object for the array, not the
// array itself). "descriptor" looks like "[C" or "[[[[B" or
// "[Ljava/lang/String;".
@@ -3680,7 +3674,7 @@ ObjPtr<mirror::Class> ClassLinker::CreateArrayClass(Thread* self,
// Use the single, global copies of "interfaces" and "iftable"
// (remember not to free them for arrays).
{
- ObjPtr<mirror::IfTable> array_iftable = array_iftable_.Read();
+ ObjPtr<mirror::IfTable> array_iftable = GetArrayIfTable();
CHECK(array_iftable != nullptr);
new_class->SetIfTable(array_iftable);
}
@@ -4772,24 +4766,29 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
this,
*dex_class_def);
const DexFile& dex_file = *dex_cache->GetDexFile();
- const uint8_t* class_data = dex_file.GetClassData(*dex_class_def);
- ClassDataItemIterator field_it(dex_file, class_data);
+
if (value_it.HasNext()) {
- DCHECK(field_it.HasNextStaticField());
+ ClassAccessor accessor(dex_file, *dex_class_def);
CHECK(can_init_statics);
- for ( ; value_it.HasNext(); value_it.Next(), field_it.Next()) {
- ArtField* field = ResolveField(
- field_it.GetMemberIndex(), dex_cache, class_loader, /* is_static */ true);
+ for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
+ if (!value_it.HasNext()) {
+ break;
+ }
+ ArtField* art_field = ResolveField(field.GetIndex(),
+ dex_cache,
+ class_loader,
+ /* is_static */ true);
if (Runtime::Current()->IsActiveTransaction()) {
- value_it.ReadValueToField<true>(field);
+ value_it.ReadValueToField<true>(art_field);
} else {
- value_it.ReadValueToField<false>(field);
+ value_it.ReadValueToField<false>(art_field);
}
if (self->IsExceptionPending()) {
break;
}
- DCHECK(!value_it.HasNext() || field_it.HasNextStaticField());
+ value_it.Next();
}
+ DCHECK(self->IsExceptionPending() || !value_it.HasNext());
}
}
@@ -7665,14 +7664,15 @@ void ClassLinker::CreateReferenceInstanceOffsets(Handle<mirror::Class> klass) {
klass->SetReferenceInstanceOffsets(reference_offsets);
}
-ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
- Handle<mirror::DexCache> dex_cache) {
- DCHECK(dex_cache != nullptr);
- Thread::PoisonObjectPointersIfDebug();
- ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
- if (resolved != nullptr) {
- return resolved;
- }
+ObjPtr<mirror::String> ClassLinker::DoResolveString(dex::StringIndex string_idx,
+ ObjPtr<mirror::DexCache> dex_cache) {
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(dex_cache));
+ return DoResolveString(string_idx, h_dex_cache);
+}
+
+ObjPtr<mirror::String> ClassLinker::DoResolveString(dex::StringIndex string_idx,
+ Handle<mirror::DexCache> dex_cache) {
const DexFile& dex_file = *dex_cache->GetDexFile();
uint32_t utf16_length;
const char* utf8_data = dex_file.StringDataAndUtf16LengthByIdx(string_idx, &utf16_length);
@@ -7683,13 +7683,9 @@ ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
return string;
}
-ObjPtr<mirror::String> ClassLinker::LookupString(dex::StringIndex string_idx,
- ObjPtr<mirror::DexCache> dex_cache) {
+ObjPtr<mirror::String> ClassLinker::DoLookupString(dex::StringIndex string_idx,
+ ObjPtr<mirror::DexCache> dex_cache) {
DCHECK(dex_cache != nullptr);
- ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
- if (resolved != nullptr) {
- return resolved;
- }
const DexFile& dex_file = *dex_cache->GetDexFile();
uint32_t utf16_length;
const char* utf8_data = dex_file.StringDataAndUtf16LengthByIdx(string_idx, &utf16_length);
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 58ce6eb25c..30c242399d 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -27,6 +27,7 @@
#include "base/enums.h"
#include "base/macros.h"
#include "base/mutex.h"
+#include "dex/class_accessor.h"
#include "dex/dex_cache_resolved_classes.h"
#include "dex/dex_file.h"
#include "dex/dex_file_types.h"
@@ -203,6 +204,16 @@ class ClassLinker {
REQUIRES(!Locks::classlinker_classes_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
+ // Resolve a String with the given index from the DexFile associated with the given `referrer`,
+ // storing the result in the DexCache. The `referrer` is used to identify the target DexCache
+ // to use for resolution.
+ ObjPtr<mirror::String> ResolveString(dex::StringIndex string_idx,
+ ArtField* referrer)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ ObjPtr<mirror::String> ResolveString(dex::StringIndex string_idx,
+ ArtMethod* referrer)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
// Resolve a String with the given index from the DexFile associated with the given DexCache,
// storing the result in the DexCache.
ObjPtr<mirror::String> ResolveString(dex::StringIndex string_idx,
@@ -825,18 +836,14 @@ class ClassLinker {
const DexFile::ClassDef& dex_class_def,
Handle<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_);
- void LoadClassMembers(Thread* self,
- const DexFile& dex_file,
- const uint8_t* class_data,
- Handle<mirror::Class> klass)
- REQUIRES_SHARED(Locks::mutator_lock_);
- void LoadField(const ClassDataItemIterator& it, Handle<mirror::Class> klass, ArtField* dst)
+ void LoadField(const ClassAccessor::Field& field, Handle<mirror::Class> klass, ArtField* dst)
REQUIRES_SHARED(Locks::mutator_lock_);
void LoadMethod(const DexFile& dex_file,
- const ClassDataItemIterator& it,
- Handle<mirror::Class> klass, ArtMethod* dst)
+ const ClassAccessor::Method& method,
+ Handle<mirror::Class> klass,
+ ArtMethod* dst)
REQUIRES_SHARED(Locks::mutator_lock_);
void FixupStaticTrampolines(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
@@ -885,6 +892,19 @@ class ClassLinker {
ObjPtr<mirror::ClassLoader> class_loader)
REQUIRES_SHARED(Locks::mutator_lock_);
+ // Implementation of ResolveString() called when the string was not found in the dex cache.
+ ObjPtr<mirror::String> DoResolveString(dex::StringIndex string_idx,
+ ObjPtr<mirror::DexCache> dex_cache)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ ObjPtr<mirror::String> DoResolveString(dex::StringIndex string_idx,
+ Handle<mirror::DexCache> dex_cache)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ // Implementation of LookupString() called when the string was not found in the dex cache.
+ ObjPtr<mirror::String> DoLookupString(dex::StringIndex string_idx,
+ ObjPtr<mirror::DexCache> dex_cache)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
// Implementation of ResolveType() called when the type was not found in the dex cache.
ObjPtr<mirror::Class> DoResolveType(dex::TypeIndex type_idx,
ObjPtr<mirror::Class> referrer)
@@ -1252,6 +1272,8 @@ class ClassLinker {
ObjPtr<mirror::ClassLoader> class_loader)
REQUIRES_SHARED(Locks::mutator_lock_);
+ ObjPtr<mirror::IfTable> GetArrayIfTable() REQUIRES_SHARED(Locks::mutator_lock_);
+
std::vector<const DexFile*> boot_class_path_;
std::vector<std::unique_ptr<const DexFile>> boot_dex_files_;
@@ -1281,9 +1303,6 @@ class ClassLinker {
// Well known mirror::Class roots.
GcRoot<mirror::ObjectArray<mirror::Class>> class_roots_;
- // The interface table used by all arrays.
- GcRoot<mirror::IfTable> array_iftable_;
-
// A cache of the last FindArrayClass results. The cache serves to avoid creating array class
// descriptors for the sake of performing FindClass.
static constexpr size_t kFindArrayCacheSize = 16;
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index c533f9ca66..4a3d3b0da6 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -46,22 +46,24 @@ namespace art {
inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method,
const MethodInfo& method_info,
- const InlineInfo& inline_info,
+ const CodeInfo& code_info,
+ const StackMap& stack_map,
uint8_t inlining_depth)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(!outer_method->IsObsolete());
+ InlineInfo inline_info = code_info.GetInlineInfoAtDepth(stack_map, inlining_depth);
// This method is being used by artQuickResolutionTrampoline, before it sets up
// the passed parameters in a GC friendly way. Therefore we must never be
// suspended while executing it.
ScopedAssertNoThreadSuspension sants(__FUNCTION__);
- if (inline_info.EncodesArtMethodAtDepth(inlining_depth)) {
- return inline_info.GetArtMethodAtDepth(inlining_depth);
+ if (inline_info.EncodesArtMethod()) {
+ return inline_info.GetArtMethod();
}
- uint32_t method_index = inline_info.GetMethodIndexAtDepth(method_info, inlining_depth);
- if (inline_info.GetDexPcAtDepth(inlining_depth) == static_cast<uint32_t>(-1)) {
+ uint32_t method_index = inline_info.GetMethodIndex(method_info);
+ if (inline_info.GetDexPc() == static_cast<uint32_t>(-1)) {
// "charAt" special case. It is the only non-leaf method we inline across dex files.
ArtMethod* inlined_method = jni::DecodeArtMethod(WellKnownClasses::java_lang_String_charAt);
DCHECK_EQ(inlined_method->GetDexMethodIndex(), method_index);
@@ -72,9 +74,10 @@ inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method,
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
ArtMethod* method = outer_method;
for (uint32_t depth = 0, end = inlining_depth + 1u; depth != end; ++depth) {
- DCHECK(!inline_info.EncodesArtMethodAtDepth(depth));
- DCHECK_NE(inline_info.GetDexPcAtDepth(depth), static_cast<uint32_t>(-1));
- method_index = inline_info.GetMethodIndexAtDepth(method_info, depth);
+ inline_info = code_info.GetInlineInfoAtDepth(stack_map, depth);
+ DCHECK(!inline_info.EncodesArtMethod());
+ DCHECK_NE(inline_info.GetDexPc(), static_cast<uint32_t>(-1));
+ method_index = inline_info.GetMethodIndex(method_info);
ArtMethod* inlined_method = class_linker->LookupResolvedMethod(method_index,
method->GetDexCache(),
method->GetClassLoader());
@@ -743,33 +746,6 @@ inline ObjPtr<mirror::Class> ResolveVerifyAndClinit(dex::TypeIndex type_idx,
return h_class.Get();
}
-static inline ObjPtr<mirror::String> ResolveString(ClassLinker* class_linker,
- dex::StringIndex string_idx,
- ArtMethod* referrer)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- Thread::PoisonObjectPointersIfDebug();
- ObjPtr<mirror::String> string = referrer->GetDexCache()->GetResolvedString(string_idx);
- if (UNLIKELY(string == nullptr)) {
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
- string = class_linker->ResolveString(string_idx, dex_cache);
- }
- return string;
-}
-
-inline ObjPtr<mirror::String> ResolveStringFromCode(ArtMethod* referrer,
- dex::StringIndex string_idx) {
- Thread::PoisonObjectPointersIfDebug();
- ObjPtr<mirror::String> string = referrer->GetDexCache()->GetResolvedString(string_idx);
- if (UNLIKELY(string == nullptr)) {
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- string = class_linker->ResolveString(string_idx, dex_cache);
- }
- return string;
-}
-
inline void UnlockJniSynchronizedMethod(jobject locked, Thread* self) {
// Save any pending exception over monitor exit call.
mirror::Throwable* saved_exception = nullptr;
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 7f9b385a0a..e71d1fa38a 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -205,12 +205,9 @@ static inline ArtMethod* DoGetCalleeSaveMethodCaller(ArtMethod* outer_method,
MethodInfo method_info = current_code->GetOptimizedMethodInfo();
StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
DCHECK(stack_map.IsValid());
- if (stack_map.HasInlineInfo()) {
- InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
- caller = GetResolvedMethod(outer_method,
- method_info,
- inline_info,
- inline_info.GetDepth() - 1);
+ uint32_t depth = code_info.GetInlineDepthOf(stack_map);
+ if (depth != 0) {
+ caller = GetResolvedMethod(outer_method, method_info, code_info, stack_map, depth - 1);
}
}
if (kIsDebugBuild && do_caller_check) {
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 1f4475f6ff..9d70b03dfa 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -162,11 +162,6 @@ ObjPtr<mirror::MethodType> ResolveMethodTypeFromCode(ArtMethod* referrer, dex::P
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
-inline ObjPtr<mirror::String> ResolveStringFromCode(ArtMethod* referrer,
- dex::StringIndex string_idx)
- REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!Roles::uninterruptible_);
-
// TODO: annotalysis disabled as monitor semantics are maintained in Java code.
inline void UnlockJniSynchronizedMethod(jobject locked, Thread* self)
NO_THREAD_SAFETY_ANALYSIS REQUIRES(!Roles::uninterruptible_);
diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
index fa536c77a9..62756123e1 100644
--- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
@@ -210,7 +210,8 @@ extern "C" mirror::String* artResolveStringFromCode(int32_t string_idx, Thread*
auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self,
CalleeSaveType::kSaveEverything);
ArtMethod* caller = caller_and_outer.caller;
- ObjPtr<mirror::String> result = ResolveStringFromCode(caller, dex::StringIndex(string_idx));
+ ObjPtr<mirror::String> result =
+ Runtime::Current()->GetClassLinker()->ResolveString(dex::StringIndex(string_idx), caller);
if (LIKELY(result != nullptr) && CanReferenceBss(caller_and_outer.outer_method, caller)) {
StoreStringInBss(caller_and_outer.outer_method, dex::StringIndex(string_idx), result);
}
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index a59faeae9b..af6a936d40 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -344,9 +344,10 @@ class QuickArgumentVisitor {
CodeInfo code_info(current_code);
StackMap stack_map = code_info.GetStackMapForNativePcOffset(outer_pc_offset);
DCHECK(stack_map.IsValid());
- if (stack_map.HasInlineInfo()) {
- InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
- return inline_info.GetDexPcAtDepth(inline_info.GetDepth()-1);
+ uint32_t depth = code_info.GetInlineDepthOf(stack_map);
+ if (depth != 0) {
+ InlineInfo inline_info = code_info.GetInlineInfoAtDepth(stack_map, depth - 1);
+ return inline_info.GetDexPc();
} else {
return stack_map.GetDexPc();
}
@@ -1231,17 +1232,17 @@ static void DumpB74410240DebugData(ArtMethod** sp) REQUIRES_SHARED(Locks::mutato
LOG(FATAL_WITHOUT_ABORT) << " instruction: " << DumpInstruction(outer_method, dex_pc);
ArtMethod* caller = outer_method;
- if (stack_map.HasInlineInfo()) {
- InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
- size_t depth = inline_info.GetDepth();
+ uint32_t depth = code_info.GetInlineDepthOf(stack_map);
+ if (depth != 0) {
for (size_t d = 0; d < depth; ++d) {
+ InlineInfo inline_info = code_info.GetInlineInfoAtDepth(stack_map, d);
const char* tag = "";
- dex_pc = inline_info.GetDexPcAtDepth(d);
- if (inline_info.EncodesArtMethodAtDepth(d)) {
+ dex_pc = inline_info.GetDexPc();
+ if (inline_info.EncodesArtMethod()) {
tag = "encoded ";
- caller = inline_info.GetArtMethodAtDepth(d);
+ caller = inline_info.GetArtMethod();
} else {
- uint32_t method_index = inline_info.GetMethodIndexAtDepth(method_info, d);
+ uint32_t method_index = inline_info.GetMethodIndex(method_info);
if (dex_pc == static_cast<uint32_t>(-1)) {
tag = "special ";
CHECK_EQ(d + 1u, depth);
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index dbe09e8c5b..e754fbcbae 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -1287,7 +1287,7 @@ class ImageSpaceLoader {
bitmap->VisitMarkedRange(objects_begin, objects_end, fixup_object_visitor);
// Fixup image roots.
CHECK(app_image.InSource(reinterpret_cast<uintptr_t>(
- image_header.GetImageRoots<kWithoutReadBarrier>())));
+ image_header.GetImageRoots<kWithoutReadBarrier>().Ptr())));
image_header.RelocateImageObjects(app_image.Delta());
CHECK_EQ(image_header.GetImageBegin(), target_base);
// Fix up dex cache DexFile pointers.
diff --git a/runtime/image-inl.h b/runtime/image-inl.h
index 3a66a34cb3..c527f6fbcc 100644
--- a/runtime/image-inl.h
+++ b/runtime/image-inl.h
@@ -23,18 +23,19 @@
#include "imt_conflict_table.h"
#include "imtable.h"
#include "mirror/object_array-inl.h"
+#include "obj_ptr-inl.h"
#include "read_barrier-inl.h"
namespace art {
template <ReadBarrierOption kReadBarrierOption>
-inline mirror::Object* ImageHeader::GetImageRoot(ImageRoot image_root) const {
- mirror::ObjectArray<mirror::Object>* image_roots = GetImageRoots<kReadBarrierOption>();
+inline ObjPtr<mirror::Object> ImageHeader::GetImageRoot(ImageRoot image_root) const {
+ ObjPtr<mirror::ObjectArray<mirror::Object>> image_roots = GetImageRoots<kReadBarrierOption>();
return image_roots->Get<kVerifyNone, kReadBarrierOption>(static_cast<int32_t>(image_root));
}
template <ReadBarrierOption kReadBarrierOption>
-inline mirror::ObjectArray<mirror::Object>* ImageHeader::GetImageRoots() const {
+inline ObjPtr<mirror::ObjectArray<mirror::Object>> ImageHeader::GetImageRoots() const {
// Need a read barrier as it's not visited during root scan.
// Pass in the address of the local variable to the read barrier
// rather than image_roots_ because it won't move (asserted below)
diff --git a/runtime/image.cc b/runtime/image.cc
index 7ad2e7bf95..17fc664bd7 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -26,7 +26,7 @@
namespace art {
const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const uint8_t ImageHeader::kImageVersion[] = { '0', '6', '0', '\0' }; // ClassRoot::MethodHandle.
+const uint8_t ImageHeader::kImageVersion[] = { '0', '6', '1', '\0' }; // Pre-allocated Throwables.
ImageHeader::ImageHeader(uint32_t image_begin,
uint32_t image_size,
diff --git a/runtime/image.h b/runtime/image.h
index 8acd5bc4c4..c6fc052a60 100644
--- a/runtime/image.h
+++ b/runtime/image.h
@@ -27,6 +27,7 @@ namespace art {
class ArtField;
class ArtMethod;
+template <class MirrorType> class ObjPtr;
namespace linker {
class ImageWriter;
@@ -206,7 +207,11 @@ class PACKED(4) ImageHeader {
enum ImageRoot {
kDexCaches,
kClassRoots,
- kClassLoader, // App image only.
+ kOomeWhenThrowingException, // Pre-allocated OOME when throwing exception.
+ kOomeWhenThrowingOome, // Pre-allocated OOME when throwing OOME.
+ kOomeWhenHandlingStackOverflow, // Pre-allocated OOME when handling StackOverflowError.
+ kNoClassDefFoundError, // Pre-allocated NoClassDefFoundError.
+ kClassLoader, // App image only.
kImageRootsMax,
};
@@ -277,11 +282,11 @@ class PACKED(4) ImageHeader {
}
template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
- mirror::Object* GetImageRoot(ImageRoot image_root) const
+ ObjPtr<mirror::Object> GetImageRoot(ImageRoot image_root) const
REQUIRES_SHARED(Locks::mutator_lock_);
template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
- mirror::ObjectArray<mirror::Object>* GetImageRoots() const
+ ObjPtr<mirror::ObjectArray<mirror::Object>> GetImageRoots() const
REQUIRES_SHARED(Locks::mutator_lock_);
void RelocateImage(off_t delta);
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 90e89cf3db..27f761a144 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -945,11 +945,9 @@ static bool GetArgumentForBootstrapMethod(Thread* self,
return true;
}
case EncodedArrayValueIterator::ValueType::kString: {
- StackHandleScope<1> hs(self);
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
dex::StringIndex index(static_cast<uint32_t>(encoded_value->GetI()));
ClassLinker* cl = Runtime::Current()->GetClassLinker();
- ObjPtr<mirror::String> o = cl->ResolveString(index, dex_cache);
+ ObjPtr<mirror::String> o = cl->ResolveString(index, referrer);
if (UNLIKELY(o.IsNull())) {
DCHECK(self->IsExceptionPending());
return false;
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 0ee780d32d..60bf50546f 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -340,12 +340,8 @@ static inline ObjPtr<mirror::String> ResolveString(Thread* self,
}
}
ArtMethod* method = shadow_frame.GetMethod();
- ObjPtr<mirror::String> string_ptr = method->GetDexCache()->GetResolvedString(string_idx);
- if (UNLIKELY(string_ptr == nullptr)) {
- StackHandleScope<1> hs(self);
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
- string_ptr = Runtime::Current()->GetClassLinker()->ResolveString(string_idx, dex_cache);
- }
+ ObjPtr<mirror::String> string_ptr =
+ Runtime::Current()->GetClassLinker()->ResolveString(string_idx, method);
return string_ptr;
}
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 31a83f8e48..44b0c2b007 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -419,7 +419,7 @@ bool Class::IsInSamePackage(ObjPtr<Class> that) {
}
bool Class::IsThrowableClass() {
- return WellKnownClasses::ToClass(WellKnownClasses::java_lang_Throwable)->IsAssignableFrom(this);
+ return GetClassRoot<mirror::Throwable>()->IsAssignableFrom(this);
}
void Class::SetClassLoader(ObjPtr<ClassLoader> new_class_loader) {
@@ -1269,7 +1269,7 @@ ObjPtr<Method> Class::GetDeclaredMethodInternal(
for (auto& m : h_klass->GetDeclaredVirtualMethods(kPointerSize)) {
auto* np_method = m.GetInterfaceMethodIfProxy(kPointerSize);
// May cause thread suspension.
- ObjPtr<String> np_name = np_method->GetNameAsString(self);
+ ObjPtr<String> np_name = np_method->ResolveNameString();
if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {
if (UNLIKELY(self->IsExceptionPending())) {
return nullptr;
@@ -1291,7 +1291,7 @@ ObjPtr<Method> Class::GetDeclaredMethodInternal(
}
auto* np_method = m.GetInterfaceMethodIfProxy(kPointerSize);
// May cause thread suspension.
- ObjPtr<String> np_name = np_method->GetNameAsString(self);
+ ObjPtr<String> np_name = np_method->ResolveNameString();
if (np_name == nullptr) {
self->AssertPendingException();
return nullptr;
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index e022db86fd..ee4f53b695 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -114,10 +114,6 @@ inline void Object::NotifyAll(Thread* self) {
Monitor::NotifyAll(self, this);
}
-inline void Object::Wait(Thread* self) {
- Monitor::Wait(self, this, 0, 0, true, kWaiting);
-}
-
inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) {
Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
}
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 8584b8a56f..a89d6323a5 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -176,7 +176,6 @@ class MANAGED LOCKABLE Object {
UNLOCK_FUNCTION();
void Notify(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
void NotifyAll(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
- void Wait(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
void Wait(Thread* self, int64_t timeout, int32_t nanos) REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 8aed4a806c..3227c69305 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -32,6 +32,7 @@ extern "C" void android_set_application_target_sdk_version(uint32_t version);
#include "class_linker-inl.h"
#include "common_throws.h"
#include "debugger.h"
+#include "dex/class_accessor-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_types.h"
#include "gc/accounting/card_table-inl.h"
@@ -573,30 +574,12 @@ static void VMRuntime_preloadDexCaches(JNIEnv* env, jobject) {
}
if (kPreloadDexCachesFieldsAndMethods) {
- for (size_t class_def_index = 0;
- class_def_index < dex_file->NumClassDefs();
- class_def_index++) {
- const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
- const uint8_t* class_data = dex_file->GetClassData(class_def);
- if (class_data == nullptr) {
- continue;
+ for (ClassAccessor accessor : dex_file->GetClasses()) {
+ for (const ClassAccessor::Field& field : accessor.GetFields()) {
+ PreloadDexCachesResolveField(dex_cache, field.GetIndex(), field.IsStatic());
}
- ClassDataItemIterator it(*dex_file, class_data);
- for (; it.HasNextStaticField(); it.Next()) {
- uint32_t field_idx = it.GetMemberIndex();
- PreloadDexCachesResolveField(dex_cache, field_idx, true);
- }
- for (; it.HasNextInstanceField(); it.Next()) {
- uint32_t field_idx = it.GetMemberIndex();
- PreloadDexCachesResolveField(dex_cache, field_idx, false);
- }
- for (; it.HasNextDirectMethod(); it.Next()) {
- uint32_t method_idx = it.GetMemberIndex();
- PreloadDexCachesResolveMethod(dex_cache, method_idx);
- }
- for (; it.HasNextVirtualMethod(); it.Next()) {
- uint32_t method_idx = it.GetMemberIndex();
- PreloadDexCachesResolveMethod(dex_cache, method_idx);
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+ PreloadDexCachesResolveMethod(dex_cache, method.GetIndex());
}
}
}
diff --git a/runtime/native/java_lang_Object.cc b/runtime/native/java_lang_Object.cc
index 208ccf6a82..48540f877d 100644
--- a/runtime/native/java_lang_Object.cc
+++ b/runtime/native/java_lang_Object.cc
@@ -41,11 +41,6 @@ static void Object_notifyAll(JNIEnv* env, jobject java_this) {
soa.Decode<mirror::Object>(java_this)->NotifyAll(soa.Self());
}
-static void Object_wait(JNIEnv* env, jobject java_this) {
- ScopedFastNativeObjectAccess soa(env);
- soa.Decode<mirror::Object>(java_this)->Wait(soa.Self());
-}
-
static void Object_waitJI(JNIEnv* env, jobject java_this, jlong ms, jint ns) {
ScopedFastNativeObjectAccess soa(env);
soa.Decode<mirror::Object>(java_this)->Wait(soa.Self(), ms, ns);
@@ -61,7 +56,6 @@ static JNINativeMethod gMethods[] = {
FAST_NATIVE_METHOD(Object, internalClone, "()Ljava/lang/Object;"),
FAST_NATIVE_METHOD(Object, notify, "()V"),
FAST_NATIVE_METHOD(Object, notifyAll, "()V"),
- OVERLOADED_FAST_NATIVE_METHOD(Object, wait, "()V", wait),
OVERLOADED_FAST_NATIVE_METHOD(Object, wait, "(JI)V", waitJI),
FAST_NATIVE_METHOD(Object, identityHashCodeNative, "(Ljava/lang/Object;)I"),
};
diff --git a/runtime/native/java_lang_reflect_Executable.cc b/runtime/native/java_lang_reflect_Executable.cc
index a40cb9b2e6..a10db9115f 100644
--- a/runtime/native/java_lang_reflect_Executable.cc
+++ b/runtime/native/java_lang_reflect_Executable.cc
@@ -320,7 +320,7 @@ static jstring Executable_getMethodNameInternal(JNIEnv* env, jobject javaMethod)
ScopedFastNativeObjectAccess soa(env);
ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
- return soa.AddLocalReference<jstring>(method->GetNameAsString(soa.Self()));
+ return soa.AddLocalReference<jstring>(method->ResolveNameString());
}
static jclass Executable_getMethodReturnTypeInternal(JNIEnv* env, jobject javaMethod) {
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 8766692a8c..895b2f9fd7 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -464,8 +464,7 @@ static jlong Field_getArtField(JNIEnv* env, jobject javaField) {
static jstring Field_getNameInternal(JNIEnv* env, jobject javaField) {
ScopedFastNativeObjectAccess soa(env);
ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
- return soa.AddLocalReference<jstring>(
- field->GetStringName(soa.Self(), true /* resolve */));
+ return soa.AddLocalReference<jstring>(field->ResolveNameString());
}
static jobjectArray Field_getDeclaredAnnotations(JNIEnv* env, jobject javaField) {
diff --git a/runtime/oat.h b/runtime/oat.h
index e7e5848dd6..72eb27d69e 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,8 +32,8 @@ class InstructionSetFeatures;
class PACKED(4) OatHeader {
public:
static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
- // Last oat version changed reason: Rewrite dex register map encoding.
- static constexpr uint8_t kOatVersion[] = { '1', '4', '6', '\0' };
+ // Last oat version changed reason: Rewrite TypeLookupTable.
+ static constexpr uint8_t kOatVersion[] = { '1', '4', '7', '\0' };
static constexpr const char* kImageLocationKey = "image-location";
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index ffbc26c647..2b05b0e3dd 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -1687,6 +1687,7 @@ OatFile::OatDexFile::OatDexFile(const OatFile* oat_file,
type_bss_mapping_(type_bss_mapping_data),
string_bss_mapping_(string_bss_mapping_data),
oat_class_offsets_pointer_(oat_class_offsets_pointer),
+ lookup_table_(),
dex_layout_sections_(dex_layout_sections) {
// Initialize TypeLookupTable.
if (lookup_table_data_ != nullptr) {
@@ -1706,7 +1707,7 @@ OatFile::OatDexFile::OatDexFile(const OatFile* oat_file,
}
}
-OatFile::OatDexFile::OatDexFile(std::unique_ptr<TypeLookupTable>&& lookup_table)
+OatFile::OatDexFile::OatDexFile(TypeLookupTable&& lookup_table)
: lookup_table_(std::move(lookup_table)) {}
OatFile::OatDexFile::~OatDexFile() {}
@@ -1783,9 +1784,9 @@ const DexFile::ClassDef* OatFile::OatDexFile::FindClassDef(const DexFile& dex_fi
DCHECK_EQ(ComputeModifiedUtf8Hash(descriptor), hash);
bool used_lookup_table = false;
const DexFile::ClassDef* lookup_table_classdef = nullptr;
- if (LIKELY((oat_dex_file != nullptr) && (oat_dex_file->GetTypeLookupTable() != nullptr))) {
+ if (LIKELY((oat_dex_file != nullptr) && oat_dex_file->GetTypeLookupTable().Valid())) {
used_lookup_table = true;
- const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable()->Lookup(descriptor, hash);
+ const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable().Lookup(descriptor, hash);
lookup_table_classdef = (class_def_idx != dex::kDexNoIndex)
? &dex_file.GetClassDef(class_def_idx)
: nullptr;
@@ -1796,6 +1797,7 @@ const DexFile::ClassDef* OatFile::OatDexFile::FindClassDef(const DexFile& dex_fi
// Fast path for rare no class defs case.
const uint32_t num_class_defs = dex_file.NumClassDefs();
if (num_class_defs == 0) {
+ DCHECK(!used_lookup_table);
return nullptr;
}
const DexFile::TypeId* type_id = dex_file.FindTypeId(descriptor);
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 8e18cee729..d72b6a8971 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -514,14 +514,14 @@ class OatDexFile FINAL {
// Madvise the dex file based on the state we are moving to.
static void MadviseDexFile(const DexFile& dex_file, MadviseState state);
- TypeLookupTable* GetTypeLookupTable() const {
- return lookup_table_.get();
+ const TypeLookupTable& GetTypeLookupTable() const {
+ return lookup_table_;
}
~OatDexFile();
// Create only with a type lookup table, used by the compiler to speed up compilation.
- explicit OatDexFile(std::unique_ptr<TypeLookupTable>&& lookup_table);
+ explicit OatDexFile(TypeLookupTable&& lookup_table);
// Return the dex layout sections.
const DexLayoutSections* GetDexLayoutSections() const {
@@ -553,7 +553,7 @@ class OatDexFile FINAL {
const IndexBssMapping* const type_bss_mapping_ = nullptr;
const IndexBssMapping* const string_bss_mapping_ = nullptr;
const uint32_t* const oat_class_offsets_pointer_ = 0u;
- mutable std::unique_ptr<TypeLookupTable> lookup_table_;
+ TypeLookupTable lookup_table_;
const DexLayoutSections* const dex_layout_sections_ = nullptr;
friend class OatFile;
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 4f4abf7f7f..23ccf6ad58 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -406,7 +406,7 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor {
BitMemoryRegion stack_mask = code_info.GetStackMaskOf(stack_map);
DexRegisterMap vreg_map = IsInInlinedFrame()
? code_info.GetDexRegisterMapAtDepth(GetCurrentInliningDepth() - 1,
- code_info.GetInlineInfoOf(stack_map),
+ stack_map,
number_of_vregs)
: code_info.GetDexRegisterMapOf(stack_map, number_of_vregs);
diff --git a/runtime/reference_table_test.cc b/runtime/reference_table_test.cc
index 0cb5e565e9..1d54d21187 100644
--- a/runtime/reference_table_test.cc
+++ b/runtime/reference_table_test.cc
@@ -290,7 +290,7 @@ TEST_F(ReferenceTableTest, SummaryOrder) {
}
{
- // Differently sized byte arrays. Should be sorted by identical (non-unique cound).
+ // Differently sized byte arrays. Should be sorted by identical (non-unique count).
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ByteArray> b1_1 = hs.NewHandle(mirror::ByteArray::Alloc(soa.Self(), 1));
rt.Add(b1_1.Get());
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 0d9d16cd01..1e327fc8ed 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1090,6 +1090,17 @@ void Runtime::SetSentinel(mirror::Object* sentinel) {
sentinel_ = GcRoot<mirror::Object>(sentinel);
}
+static inline void InitPreAllocatedException(Thread* self,
+ GcRoot<mirror::Throwable>* exception,
+ const char* exception_class_descriptor,
+ const char* msg)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ DCHECK_EQ(self, Thread::Current());
+ self->ThrowNewException(exception_class_descriptor, msg);
+ *exception = GcRoot<mirror::Throwable>(self->GetException());
+ self->ClearException();
+}
+
bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
// (b/30160149): protect subprocesses from modifications to LD_LIBRARY_PATH, etc.
// Take a snapshot of the environment at the time the runtime was created, for use by Exec, etc.
@@ -1505,34 +1516,54 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
// TODO: move this to just be an Trace::Start argument
Trace::SetDefaultClockSource(runtime_options.GetOrDefault(Opt::ProfileClock));
- // Pre-allocate an OutOfMemoryError for the case when we fail to
- // allocate the exception to be thrown.
- InitPreAllocatedException(self,
- &Runtime::pre_allocated_OutOfMemoryError_when_throwing_exception_,
- "Ljava/lang/OutOfMemoryError;",
- "OutOfMemoryError thrown while trying to throw an exception; "
- "no stack trace available");
- // Pre-allocate an OutOfMemoryError for the double-OOME case.
- InitPreAllocatedException(self,
- &Runtime::pre_allocated_OutOfMemoryError_when_throwing_oome_,
- "Ljava/lang/OutOfMemoryError;",
- "OutOfMemoryError thrown while trying to throw OutOfMemoryError; "
- "no stack trace available");
- // Pre-allocate an OutOfMemoryError for the case when we fail to
- // allocate while handling a stack overflow.
- InitPreAllocatedException(self,
- &Runtime::pre_allocated_OutOfMemoryError_when_handling_stack_overflow_,
- "Ljava/lang/OutOfMemoryError;",
- "OutOfMemoryError thrown while trying to handle a stack overflow; "
- "no stack trace available");
-
- // Pre-allocate a NoClassDefFoundError for the common case of failing to find a system class
- // ahead of checking the application's class loader.
- InitPreAllocatedException(self,
- &Runtime::pre_allocated_NoClassDefFoundError_,
- "Ljava/lang/NoClassDefFoundError;",
- "Class not found using the boot class loader; "
- "no stack trace available");
+ if (GetHeap()->HasBootImageSpace()) {
+ const ImageHeader& image_header = GetHeap()->GetBootImageSpaces()[0]->GetImageHeader();
+ pre_allocated_OutOfMemoryError_when_throwing_exception_ = GcRoot<mirror::Throwable>(
+ image_header.GetImageRoot(ImageHeader::kOomeWhenThrowingException)->AsThrowable());
+ DCHECK(pre_allocated_OutOfMemoryError_when_throwing_exception_.Read()->GetClass()
+ ->DescriptorEquals("Ljava/lang/OutOfMemoryError;"));
+ pre_allocated_OutOfMemoryError_when_throwing_oome_ = GcRoot<mirror::Throwable>(
+ image_header.GetImageRoot(ImageHeader::kOomeWhenThrowingOome)->AsThrowable());
+ DCHECK(pre_allocated_OutOfMemoryError_when_throwing_oome_.Read()->GetClass()
+ ->DescriptorEquals("Ljava/lang/OutOfMemoryError;"));
+ pre_allocated_OutOfMemoryError_when_handling_stack_overflow_ = GcRoot<mirror::Throwable>(
+ image_header.GetImageRoot(ImageHeader::kOomeWhenHandlingStackOverflow)->AsThrowable());
+ DCHECK(pre_allocated_OutOfMemoryError_when_handling_stack_overflow_.Read()->GetClass()
+ ->DescriptorEquals("Ljava/lang/OutOfMemoryError;"));
+ pre_allocated_NoClassDefFoundError_ = GcRoot<mirror::Throwable>(
+ image_header.GetImageRoot(ImageHeader::kNoClassDefFoundError)->AsThrowable());
+ DCHECK(pre_allocated_NoClassDefFoundError_.Read()->GetClass()
+ ->DescriptorEquals("Ljava/lang/NoClassDefFoundError;"));
+ } else {
+ // Pre-allocate an OutOfMemoryError for the case when we fail to
+ // allocate the exception to be thrown.
+ InitPreAllocatedException(self,
+ &pre_allocated_OutOfMemoryError_when_throwing_exception_,
+ "Ljava/lang/OutOfMemoryError;",
+ "OutOfMemoryError thrown while trying to throw an exception; "
+ "no stack trace available");
+ // Pre-allocate an OutOfMemoryError for the double-OOME case.
+ InitPreAllocatedException(self,
+ &pre_allocated_OutOfMemoryError_when_throwing_oome_,
+ "Ljava/lang/OutOfMemoryError;",
+ "OutOfMemoryError thrown while trying to throw OutOfMemoryError; "
+ "no stack trace available");
+ // Pre-allocate an OutOfMemoryError for the case when we fail to
+ // allocate while handling a stack overflow.
+ InitPreAllocatedException(self,
+ &pre_allocated_OutOfMemoryError_when_handling_stack_overflow_,
+ "Ljava/lang/OutOfMemoryError;",
+ "OutOfMemoryError thrown while trying to handle a stack overflow; "
+ "no stack trace available");
+
+ // Pre-allocate a NoClassDefFoundError for the common case of failing to find a system class
+ // ahead of checking the application's class loader.
+ InitPreAllocatedException(self,
+ &pre_allocated_NoClassDefFoundError_,
+ "Ljava/lang/NoClassDefFoundError;",
+ "Class not found using the boot class loader; "
+ "no stack trace available");
+ }
// Runtime initialization is largely done now.
// We load plugins first since that can modify the runtime state slightly.
@@ -1682,16 +1713,6 @@ void Runtime::AttachAgent(JNIEnv* env, const std::string& agent_arg, jobject cla
}
}
-void Runtime::InitPreAllocatedException(Thread* self,
- GcRoot<mirror::Throwable> Runtime::* exception,
- const char* exception_class_descriptor,
- const char* msg) {
- DCHECK_EQ(self, Thread::Current());
- self->ThrowNewException(exception_class_descriptor, msg);
- this->*exception = GcRoot<mirror::Throwable>(self->GetException());
- self->ClearException();
-}
-
void Runtime::InitNativeMethods() {
VLOG(startup) << "Runtime::InitNativeMethods entering";
Thread* self = Thread::Current();
@@ -2048,9 +2069,10 @@ void Runtime::VisitImageRoots(RootVisitor* visitor) {
auto* image_space = space->AsImageSpace();
const auto& image_header = image_space->GetImageHeader();
for (int32_t i = 0, size = image_header.GetImageRoots()->GetLength(); i != size; ++i) {
- auto* obj = image_header.GetImageRoot(static_cast<ImageHeader::ImageRoot>(i));
+ mirror::Object* obj =
+ image_header.GetImageRoot(static_cast<ImageHeader::ImageRoot>(i)).Ptr();
if (obj != nullptr) {
- auto* after_obj = obj;
+ mirror::Object* after_obj = obj;
visitor->VisitRoot(&after_obj, RootInfo(kRootStickyClass));
CHECK_EQ(after_obj, obj);
}
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 10f72e7c5b..d85490c0a6 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -774,11 +774,6 @@ class Runtime {
bool Init(RuntimeArgumentMap&& runtime_options)
SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_);
- void InitPreAllocatedException(Thread* self,
- GcRoot<mirror::Throwable> Runtime::* exception,
- const char* exception_class_descriptor,
- const char* msg)
- REQUIRES_SHARED(Locks::mutator_lock_);
void InitNativeMethods() REQUIRES(!Locks::mutator_lock_);
void RegisterRuntimeNativeMethods(JNIEnv* env);
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 6da7dcb697..bd0d5d680e 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -76,14 +76,14 @@ StackVisitor::StackVisitor(Thread* thread,
}
}
-static InlineInfo GetCurrentInlineInfo(CodeInfo& code_info,
- const OatQuickMethodHeader* method_header,
- uintptr_t cur_quick_frame_pc)
+static StackMap GetCurrentStackMap(CodeInfo& code_info,
+ const OatQuickMethodHeader* method_header,
+ uintptr_t cur_quick_frame_pc)
REQUIRES_SHARED(Locks::mutator_lock_) {
uint32_t native_pc_offset = method_header->NativeQuickPcOffset(cur_quick_frame_pc);
StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
DCHECK(stack_map.IsValid());
- return code_info.GetInlineInfoOf(stack_map);
+ return stack_map;
}
ArtMethod* StackVisitor::GetMethod() const {
@@ -94,14 +94,13 @@ ArtMethod* StackVisitor::GetMethod() const {
size_t depth_in_stack_map = current_inlining_depth_ - 1;
const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
CodeInfo code_info(method_header);
- InlineInfo inline_info = GetCurrentInlineInfo(code_info,
- method_header,
- cur_quick_frame_pc_);
+ StackMap stack_map = GetCurrentStackMap(code_info, method_header, cur_quick_frame_pc_);
MethodInfo method_info = method_header->GetOptimizedMethodInfo();
DCHECK(walk_kind_ != StackWalkKind::kSkipInlinedFrames);
return GetResolvedMethod(*GetCurrentQuickFrame(),
method_info,
- inline_info,
+ code_info,
+ stack_map,
depth_in_stack_map);
} else {
return *cur_quick_frame_;
@@ -118,8 +117,8 @@ uint32_t StackVisitor::GetDexPc(bool abort_on_failure) const {
const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
CodeInfo code_info(method_header);
size_t depth_in_stack_map = current_inlining_depth_ - 1;
- return GetCurrentInlineInfo(code_info, method_header, cur_quick_frame_pc_).
- GetDexPcAtDepth(depth_in_stack_map);
+ StackMap stack_map = GetCurrentStackMap(code_info, method_header, cur_quick_frame_pc_);
+ return code_info.GetInlineInfoAtDepth(stack_map, depth_in_stack_map).GetDexPc();
} else if (cur_oat_quick_method_header_ == nullptr) {
return dex::kDexNoIndex;
} else {
@@ -237,9 +236,7 @@ bool StackVisitor::GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKin
size_t depth_in_stack_map = current_inlining_depth_ - 1;
DexRegisterMap dex_register_map = IsInInlinedFrame()
- ? code_info.GetDexRegisterMapAtDepth(depth_in_stack_map,
- code_info.GetInlineInfoOf(stack_map),
- number_of_dex_registers)
+ ? code_info.GetDexRegisterMapAtDepth(depth_in_stack_map, stack_map, number_of_dex_registers)
: code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
if (!dex_register_map.IsValid()) {
@@ -825,9 +822,8 @@ void StackVisitor::WalkStack(bool include_transitions) {
cur_oat_quick_method_header_->NativeQuickPcOffset(cur_quick_frame_pc_);
StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
if (stack_map.IsValid() && stack_map.HasInlineInfo()) {
- InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
DCHECK_EQ(current_inlining_depth_, 0u);
- for (current_inlining_depth_ = inline_info.GetDepth();
+ for (current_inlining_depth_ = code_info.GetInlineDepthOf(stack_map);
current_inlining_depth_ != 0;
--current_inlining_depth_) {
bool should_continue = VisitFrame();
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index 923bb3559a..a5749b84a7 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -146,38 +146,39 @@ void StackMap::Dump(VariableIndentationOutputStream* vios,
}
vios->Stream() << ")\n";
DumpDexRegisterMap(vios, code_info.GetDexRegisterMapOf(*this, number_of_dex_registers));
- if (HasInlineInfo()) {
- InlineInfo inline_info = code_info.GetInlineInfoOf(*this);
+ uint32_t depth = code_info.GetInlineDepthOf(*this);
+ for (size_t d = 0; d < depth; d++) {
+ InlineInfo inline_info = code_info.GetInlineInfoAtDepth(*this, d);
// We do not know the length of the dex register maps of inlined frames
// at this level, so we just pass null to `InlineInfo::Dump` to tell
// it not to look at these maps.
- inline_info.Dump(vios, code_info, method_info, nullptr);
+ inline_info.Dump(vios, code_info, *this, method_info, 0);
}
}
void InlineInfo::Dump(VariableIndentationOutputStream* vios,
const CodeInfo& code_info,
+ const StackMap& stack_map,
const MethodInfo& method_info,
- uint16_t number_of_dex_registers[]) const {
- for (size_t i = 0; i < GetDepth(); ++i) {
+ uint16_t number_of_dex_registers) const {
+ uint32_t depth = Row() - stack_map.GetInlineInfoIndex();
+ vios->Stream()
+ << "InlineInfo[" << Row() << "]"
+ << " (depth=" << depth
+ << std::hex
+ << ", dex_pc=0x" << GetDexPc();
+ if (EncodesArtMethod()) {
+ ScopedObjectAccess soa(Thread::Current());
+ vios->Stream() << ", method=" << GetArtMethod()->PrettyMethod();
+ } else {
vios->Stream()
- << "InlineInfo[" << Row() + i << "]"
- << " (depth=" << i
- << std::hex
- << ", dex_pc=0x" << GetDexPcAtDepth(i);
- if (EncodesArtMethodAtDepth(i)) {
- ScopedObjectAccess soa(Thread::Current());
- vios->Stream() << ", method=" << GetArtMethodAtDepth(i)->PrettyMethod();
- } else {
- vios->Stream()
- << std::dec
- << ", method_index=" << GetMethodIndexAtDepth(method_info, i);
- }
- vios->Stream() << ")\n";
- if (number_of_dex_registers != nullptr) {
- uint16_t vregs = number_of_dex_registers[i];
- DumpDexRegisterMap(vios, code_info.GetDexRegisterMapAtDepth(i, *this, vregs));
- }
+ << std::dec
+ << ", method_index=" << GetMethodIndex(method_info);
+ }
+ vios->Stream() << ")\n";
+ if (number_of_dex_registers != 0) {
+ uint16_t vregs = number_of_dex_registers;
+ DumpDexRegisterMap(vios, code_info.GetDexRegisterMapAtDepth(depth, stack_map, vregs));
}
}
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index 9aac204e70..b04197e160 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -222,54 +222,47 @@ class InlineInfo : public BitTable<7>::Accessor {
InlineInfo(const BitTable<kCount>* table, uint32_t row)
: BitTable<kCount>::Accessor(table, row) {}
- ALWAYS_INLINE InlineInfo AtDepth(uint32_t depth) const {
- return InlineInfo(table_, this->row_ + depth);
- }
-
- uint32_t GetDepth() const {
- size_t depth = 0;
- while (AtDepth(depth++).Get<kIsLast>() == kMore) { }
- return depth;
- }
+ uint32_t GetIsLast() const { return Get<kIsLast>(); }
- uint32_t GetMethodIndexIdxAtDepth(uint32_t depth) const {
- DCHECK(!EncodesArtMethodAtDepth(depth));
- return AtDepth(depth).Get<kMethodIndexIdx>();
+ uint32_t GetMethodIndexIdx() const {
+ DCHECK(!EncodesArtMethod());
+ return Get<kMethodIndexIdx>();
}
- uint32_t GetMethodIndexAtDepth(const MethodInfo& method_info, uint32_t depth) const {
- return method_info.GetMethodIndex(GetMethodIndexIdxAtDepth(depth));
+ uint32_t GetMethodIndex(const MethodInfo& method_info) const {
+ return method_info.GetMethodIndex(GetMethodIndexIdx());
}
- uint32_t GetDexPcAtDepth(uint32_t depth) const {
- return AtDepth(depth).Get<kDexPc>();
+ uint32_t GetDexPc() const {
+ return Get<kDexPc>();
}
- bool EncodesArtMethodAtDepth(uint32_t depth) const {
- return AtDepth(depth).Get<kArtMethodLo>() != kNoValue;
+ bool EncodesArtMethod() const {
+ return Get<kArtMethodLo>() != kNoValue;
}
- ArtMethod* GetArtMethodAtDepth(uint32_t depth) const {
- uint64_t lo = AtDepth(depth).Get<kArtMethodLo>();
- uint64_t hi = AtDepth(depth).Get<kArtMethodHi>();
+ ArtMethod* GetArtMethod() const {
+ uint64_t lo = Get<kArtMethodLo>();
+ uint64_t hi = Get<kArtMethodHi>();
return reinterpret_cast<ArtMethod*>((hi << 32) | lo);
}
- uint32_t GetDexRegisterMaskIndexAtDepth(uint32_t depth) const {
- return AtDepth(depth).Get<kDexRegisterMaskIndex>();
+ uint32_t GetDexRegisterMaskIndex() const {
+ return Get<kDexRegisterMaskIndex>();
}
- uint32_t GetDexRegisterMapIndexAtDepth(uint32_t depth) const {
- return AtDepth(depth).Get<kDexRegisterMapIndex>();
+ uint32_t GetDexRegisterMapIndex() const {
+ return Get<kDexRegisterMapIndex>();
}
- bool HasDexRegisterMapAtDepth(uint32_t depth) const {
- return GetDexRegisterMapIndexAtDepth(depth) != kNoValue;
+ bool HasDexRegisterMap() const {
+ return GetDexRegisterMapIndex() != kNoValue;
}
void Dump(VariableIndentationOutputStream* vios,
const CodeInfo& info,
+ const StackMap& stack_map,
const MethodInfo& method_info,
- uint16_t* number_of_dex_registers) const;
+ uint16_t number_of_dex_registers) const;
};
class InvokeInfo : public BitTable<3>::Accessor {
@@ -417,10 +410,11 @@ class CodeInfo {
}
ALWAYS_INLINE DexRegisterMap GetDexRegisterMapAtDepth(uint8_t depth,
- InlineInfo inline_info,
+ StackMap stack_map,
size_t num_dex_registers) const {
- return DecodeDexRegisterMap(inline_info.GetDexRegisterMaskIndexAtDepth(depth),
- inline_info.GetDexRegisterMapIndexAtDepth(depth),
+ InlineInfo inline_info = GetInlineInfoAtDepth(stack_map, depth);
+ return DecodeDexRegisterMap(inline_info.GetDexRegisterMaskIndex(),
+ inline_info.GetDexRegisterMapIndex(),
num_dex_registers);
}
@@ -428,10 +422,19 @@ class CodeInfo {
return InlineInfo(&inline_infos_, index);
}
- InlineInfo GetInlineInfoOf(StackMap stack_map) const {
- DCHECK(stack_map.HasInlineInfo());
+ uint32_t GetInlineDepthOf(StackMap stack_map) const {
+ uint32_t depth = 0;
uint32_t index = stack_map.GetInlineInfoIndex();
- return GetInlineInfo(index);
+ if (index != StackMap::kNoValue) {
+ while (GetInlineInfo(index + depth++).GetIsLast() == InlineInfo::kMore) { }
+ }
+ return depth;
+ }
+
+ InlineInfo GetInlineInfoAtDepth(StackMap stack_map, uint32_t depth) const {
+ DCHECK(stack_map.HasInlineInfo());
+ DCHECK_LT(depth, GetInlineDepthOf(stack_map));
+ return GetInlineInfo(stack_map.GetInlineInfoIndex() + depth);
}
StackMap GetStackMapForDexPc(uint32_t dex_pc) const {
@@ -473,7 +476,6 @@ class CodeInfo {
stack_map.GetNativePcOffset(kRuntimeISA)) {
DCHECK_EQ(other.GetDexRegisterMapIndex(),
stack_map.GetDexRegisterMapIndex());
- DCHECK(!stack_map.HasInlineInfo());
if (i < e - 2) {
// Make sure there are not three identical stack maps following each other.
DCHECK_NE(
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc
index 838d7f14bc..32aa86dc93 100644
--- a/runtime/vdex_file.cc
+++ b/runtime/vdex_file.cc
@@ -28,6 +28,7 @@
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "dex/art_dex_file_loader.h"
+#include "dex/class_accessor-inl.h"
#include "dex/dex_file.h"
#include "dex/dex_file_loader.h"
#include "dex/hidden_api_access_flags.h"
@@ -283,30 +284,25 @@ void VdexFile::UnquickenDexFile(const DexFile& target_dex_file,
std::unordered_set<const DexFile::CodeItem*> unquickened_code_item;
CompactOffsetTable::Accessor accessor(GetQuickenInfoOffsetTable(source_dex_begin,
quickening_info));
- for (uint32_t i = 0; i < target_dex_file.NumClassDefs(); ++i) {
- const DexFile::ClassDef& class_def = target_dex_file.GetClassDef(i);
- const uint8_t* class_data = target_dex_file.GetClassData(class_def);
- if (class_data != nullptr) {
- for (ClassDataItemIterator class_it(target_dex_file, class_data);
- class_it.HasNext();
- class_it.Next()) {
- if (class_it.IsAtMethod()) {
- const DexFile::CodeItem* code_item = class_it.GetMethodCodeItem();
- if (code_item != nullptr && unquickened_code_item.emplace(code_item).second) {
- const uint32_t offset = accessor.GetOffset(class_it.GetMemberIndex());
- // Offset being 0 means not quickened.
- if (offset != 0u) {
- ArrayRef<const uint8_t> quicken_data = GetQuickeningInfoAt(quickening_info, offset);
- optimizer::ArtDecompileDEX(
- target_dex_file,
- *code_item,
- quicken_data,
- decompile_return_instruction);
- }
- }
+ for (ClassAccessor class_accessor : target_dex_file.GetClasses()) {
+ for (const ClassAccessor::Method& method : class_accessor.GetMethods()) {
+ const DexFile::CodeItem* code_item = method.GetCodeItem();
+ if (code_item != nullptr && unquickened_code_item.emplace(code_item).second) {
+ const uint32_t offset = accessor.GetOffset(method.GetIndex());
+ // Offset being 0 means not quickened.
+ if (offset != 0u) {
+ ArrayRef<const uint8_t> quicken_data = GetQuickeningInfoAt(quickening_info, offset);
+ optimizer::ArtDecompileDEX(
+ target_dex_file,
+ *code_item,
+ quicken_data,
+ decompile_return_instruction);
}
- DexFile::UnHideAccessFlags(class_it);
}
+ method.UnHideAccessFlags();
+ }
+ for (const ClassAccessor::Field& field : class_accessor.GetFields()) {
+ field.UnHideAccessFlags();
}
}
}
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index f57f757f0b..59617481eb 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -35,6 +35,7 @@
#include "class_linker.h"
#include "class_root.h"
#include "compiler_callbacks.h"
+#include "dex/class_accessor-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_exception_helpers.h"
@@ -190,11 +191,6 @@ FailureKind MethodVerifier::VerifyClass(Thread* self,
error);
}
-template <bool kDirect>
-static bool HasNextMethod(ClassDataItemIterator* it) {
- return kDirect ? it->HasNextDirectMethod() : it->HasNextVirtualMethod();
-}
-
static FailureKind FailureKindMax(FailureKind fk1, FailureKind fk2) {
static_assert(FailureKind::kNoFailure < FailureKind::kSoftFailure
&& FailureKind::kSoftFailure < FailureKind::kHardFailure,
@@ -207,45 +203,51 @@ void MethodVerifier::FailureData::Merge(const MethodVerifier::FailureData& fd) {
types |= fd.types;
}
-template <bool kDirect>
-MethodVerifier::FailureData MethodVerifier::VerifyMethods(Thread* self,
- ClassLinker* linker,
- const DexFile* dex_file,
- const DexFile::ClassDef& class_def,
- ClassDataItemIterator* it,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- CompilerCallbacks* callbacks,
- bool allow_soft_failures,
- HardFailLogMode log_level,
- bool need_precise_constants,
- std::string* error_string) {
- DCHECK(it != nullptr);
+FailureKind MethodVerifier::VerifyClass(Thread* self,
+ const DexFile* dex_file,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader,
+ const DexFile::ClassDef& class_def,
+ CompilerCallbacks* callbacks,
+ bool allow_soft_failures,
+ HardFailLogMode log_level,
+ std::string* error) {
+ SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+ // A class must not be abstract and final.
+ if ((class_def.access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) {
+ *error = "Verifier rejected class ";
+ *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+ *error += ": class is abstract and final.";
+ return FailureKind::kHardFailure;
+ }
+
+ ClassAccessor accessor(*dex_file, class_def);
+
+ int64_t previous_method_idx[2] = { -1, -1 };
MethodVerifier::FailureData failure_data;
+ ClassLinker* const linker = Runtime::Current()->GetClassLinker();
- int64_t previous_method_idx = -1;
- while (HasNextMethod<kDirect>(it)) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+ int64_t* previous_idx = &previous_method_idx[method.IsStaticOrDirect() ? 0u : 1u];
self->AllowThreadSuspension();
- uint32_t method_idx = it->GetMemberIndex();
- if (method_idx == previous_method_idx) {
+ const uint32_t method_idx = method.GetIndex();
+ if (method_idx == *previous_idx) {
// smali can create dex files with two encoded_methods sharing the same method_idx
// http://code.google.com/p/smali/issues/detail?id=119
- it->Next();
continue;
}
- previous_method_idx = method_idx;
- InvokeType type = it->GetMethodInvokeType(class_def);
- ArtMethod* method = linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
+ *previous_idx = method_idx;
+ const InvokeType type = method.GetInvokeType(class_def.access_flags_);
+ ArtMethod* resolved_method = linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
method_idx, dex_cache, class_loader, /* referrer */ nullptr, type);
- if (method == nullptr) {
+ if (resolved_method == nullptr) {
DCHECK(self->IsExceptionPending());
// We couldn't resolve the method, but continue regardless.
self->ClearException();
} else {
- DCHECK(method->GetDeclaringClassUnchecked() != nullptr) << type;
+ DCHECK(resolved_method->GetDeclaringClassUnchecked() != nullptr) << type;
}
- StackHandleScope<1> hs(self);
std::string hard_failure_msg;
MethodVerifier::FailureData result = VerifyMethod(self,
method_idx,
@@ -253,99 +255,39 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethods(Thread* self,
dex_cache,
class_loader,
class_def,
- it->GetMethodCodeItem(),
- method,
- it->GetMethodAccessFlags(),
+ method.GetCodeItem(),
+ resolved_method,
+ method.GetAccessFlags(),
callbacks,
allow_soft_failures,
log_level,
- need_precise_constants,
+ /*need_precise_constants*/ false,
&hard_failure_msg);
if (result.kind == FailureKind::kHardFailure) {
if (failure_data.kind == FailureKind::kHardFailure) {
// If we logged an error before, we need a newline.
- *error_string += "\n";
+ *error += "\n";
} else {
// If we didn't log a hard failure before, print the header of the message.
- *error_string += "Verifier rejected class ";
- *error_string += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
- *error_string += ":";
+ *error += "Verifier rejected class ";
+ *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+ *error += ":";
}
- *error_string += " ";
- *error_string += hard_failure_msg;
+ *error += " ";
+ *error += hard_failure_msg;
}
failure_data.Merge(result);
- it->Next();
- }
-
- return failure_data;
-}
-
-FailureKind MethodVerifier::VerifyClass(Thread* self,
- const DexFile* dex_file,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- const DexFile::ClassDef& class_def,
- CompilerCallbacks* callbacks,
- bool allow_soft_failures,
- HardFailLogMode log_level,
- std::string* error) {
- SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
-
- // A class must not be abstract and final.
- if ((class_def.access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) {
- *error = "Verifier rejected class ";
- *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
- *error += ": class is abstract and final.";
- return FailureKind::kHardFailure;
}
- const uint8_t* class_data = dex_file->GetClassData(class_def);
- if (class_data == nullptr) {
- // empty class, probably a marker interface
- return FailureKind::kNoFailure;
- }
- ClassDataItemIterator it(*dex_file, class_data);
- it.SkipAllFields();
- ClassLinker* linker = Runtime::Current()->GetClassLinker();
- // Direct methods.
- MethodVerifier::FailureData data1 = VerifyMethods<true>(self,
- linker,
- dex_file,
- class_def,
- &it,
- dex_cache,
- class_loader,
- callbacks,
- allow_soft_failures,
- log_level,
- false /* need precise constants */,
- error);
- // Virtual methods.
- MethodVerifier::FailureData data2 = VerifyMethods<false>(self,
- linker,
- dex_file,
- class_def,
- &it,
- dex_cache,
- class_loader,
- callbacks,
- allow_soft_failures,
- log_level,
- false /* need precise constants */,
- error);
-
- data1.Merge(data2);
-
- if (data1.kind == FailureKind::kNoFailure) {
+ if (failure_data.kind == FailureKind::kNoFailure) {
return FailureKind::kNoFailure;
} else {
- if ((data1.types & VERIFY_ERROR_LOCKING) != 0) {
+ if ((failure_data.types & VERIFY_ERROR_LOCKING) != 0) {
// Print a warning about expected slow-down. Use a string temporary to print one contiguous
// warning.
std::string tmp =
StringPrintf("Class %s failed lock verification and will run slower.",
- PrettyDescriptor(dex_file->GetClassDescriptor(class_def)).c_str());
+ PrettyDescriptor(accessor.GetDescriptor()).c_str());
if (!gPrintedDxMonitorText) {
tmp = tmp + "\nCommon causes for lock verification issues are non-optimized dex code\n"
"and incorrect proguard optimizations.";
@@ -353,7 +295,7 @@ FailureKind MethodVerifier::VerifyClass(Thread* self,
}
LOG(WARNING) << tmp;
}
- return data1.kind;
+ return failure_data.kind;
}
}
@@ -1924,15 +1866,11 @@ bool MethodVerifier::CodeFlowVerifyMethod() {
static uint32_t GetFirstFinalInstanceFieldIndex(const DexFile& dex_file, dex::TypeIndex type_idx) {
const DexFile::ClassDef* class_def = dex_file.FindClassDef(type_idx);
DCHECK(class_def != nullptr);
- const uint8_t* class_data = dex_file.GetClassData(*class_def);
- DCHECK(class_data != nullptr);
- ClassDataItemIterator it(dex_file, class_data);
- it.SkipStaticFields();
- while (it.HasNextInstanceField()) {
- if ((it.GetFieldAccessFlags() & kAccFinal) != 0) {
- return it.GetMemberIndex();
- }
- it.Next();
+ ClassAccessor accessor(dex_file, *class_def);
+ for (const ClassAccessor::Field& field : accessor.GetInstanceFields()) {
+ if (field.IsFinal()) {
+ return field.GetIndex();
+ }
}
return dex::kDexNoIndex;
}
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index ae7481c6b1..9890af9d95 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -275,23 +275,6 @@ class MethodVerifier {
void Merge(const FailureData& src);
};
- // Verify all direct or virtual methods of a class. The method assumes that the iterator is
- // positioned correctly, and the iterator will be updated.
- template <bool kDirect>
- static FailureData VerifyMethods(Thread* self,
- ClassLinker* linker,
- const DexFile* dex_file,
- const DexFile::ClassDef& class_def,
- ClassDataItemIterator* it,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- CompilerCallbacks* callbacks,
- bool allow_soft_failures,
- HardFailLogMode log_level,
- bool need_precise_constants,
- std::string* error_string)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
/*
* Perform verification on a single method.
*
diff --git a/test/911-get-stack-trace/check b/test/911-get-stack-trace/check
deleted file mode 100644
index ee00266b36..0000000000
--- a/test/911-get-stack-trace/check
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-if [[ "$DX" == 'd8' ]]; then
- patch -p0 expected.txt < expected_d8.diff
-fi
-
-./default-check "$@"
-if [[ "$?" == "0" ]]; then
- exit 0;
-fi
-
-# We cannot always correctly determine if D8 was used because of (b/68406220).
-# So we are just going to try to see it matches the expect output of D8 no
-# matter what.
-patch -p0 expected.txt < expected_d8.diff
-
-./default-check "$@"
diff --git a/test/911-get-stack-trace/expected.txt b/test/911-get-stack-trace/expected.txt
index 8177f494ac..b0a400ab75 100644
--- a/test/911-get-stack-trace/expected.txt
+++ b/test/911-get-stack-trace/expected.txt
@@ -9,19 +9,19 @@ From top
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- doTest ()V 34 25
+ doTest ()V 33 25
run ()V 0 25
---------
print (Ljava/lang/Thread;II)V 0 38
@@ -29,19 +29,19 @@ From top
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- doTest ()V 38 26
+ doTest ()V 37 26
run ()V 0 25
---------
getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 -2
@@ -54,12 +54,12 @@ From top
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
From bottom
---------
run ()V 0 25
---------
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
doTest ()V 60 32
@@ -67,7 +67,7 @@ From bottom
---------
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
@@ -76,68 +76,76 @@ From bottom
################################
From top
---------
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 28
---------
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 28
---------
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
---------
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
From bottom
---------
run ()V 4 28
---------
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 28
---------
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
###########################
@@ -145,20 +153,20 @@ From bottom
###########################
From top
---------
- printOrWait (IILart/ControlData;)V 44 54
+ printOrWait (IILart/ControlData;)V 45 54
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 61
@@ -166,29 +174,29 @@ From top
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 61
---------
- printOrWait (IILart/ControlData;)V 44 54
+ printOrWait (IILart/ControlData;)V 45 54
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
---------
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
From bottom
@@ -196,15 +204,15 @@ From bottom
run ()V 4 61
---------
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 61
---------
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
################################
@@ -263,7 +271,9 @@ main
<not printed>
---------
AllTraces Thread 0
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -271,7 +281,9 @@ AllTraces Thread 0
---------
AllTraces Thread 1
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -279,7 +291,9 @@ AllTraces Thread 1
---------
AllTraces Thread 2
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -287,7 +301,9 @@ AllTraces Thread 2
---------
AllTraces Thread 3
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -295,7 +311,9 @@ AllTraces Thread 3
---------
AllTraces Thread 4
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -303,7 +321,9 @@ AllTraces Thread 4
---------
AllTraces Thread 5
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -311,7 +331,9 @@ AllTraces Thread 5
---------
AllTraces Thread 6
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -319,7 +341,9 @@ AllTraces Thread 6
---------
AllTraces Thread 7
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -327,7 +351,9 @@ AllTraces Thread 7
---------
AllTraces Thread 8
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -335,7 +361,9 @@ AllTraces Thread 8
---------
AllTraces Thread 9
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -360,7 +388,7 @@ Signal Catcher
Test911
getAllStackTraces (I)[[Ljava/lang/Object; -1 -2
printAll (I)V 0 75
- doTest ()V 122 59
+ doTest ()V 120 59
run ()V 24 37
---------
@@ -368,210 +396,230 @@ main
<not printed>
---------
AllTraces Thread 0
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 1
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 2
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 3
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 4
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 5
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 6
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 7
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 8
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 9
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
@@ -595,7 +643,7 @@ Signal Catcher
Test911
getAllStackTraces (I)[[Ljava/lang/Object; -1 -2
printAll (I)V 0 75
- doTest ()V 127 61
+ doTest ()V 125 61
run ()V 24 37
---------
@@ -627,12 +675,14 @@ ThreadListTraces Thread 8
Test911
getThreadListStackTraces ([Ljava/lang/Thread;I)[[Ljava/lang/Object; -1 -2
printList ([Ljava/lang/Thread;I)V 0 68
- doTest ()V 112 54
+ doTest ()V 110 54
run ()V 32 41
---------
ThreadListTraces Thread 0
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -640,7 +690,9 @@ ThreadListTraces Thread 0
---------
ThreadListTraces Thread 2
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -648,7 +700,9 @@ ThreadListTraces Thread 2
---------
ThreadListTraces Thread 4
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -656,7 +710,9 @@ ThreadListTraces Thread 4
---------
ThreadListTraces Thread 6
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -664,7 +720,9 @@ ThreadListTraces Thread 6
---------
ThreadListTraces Thread 8
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -674,110 +732,120 @@ ThreadListTraces Thread 8
Test911
getThreadListStackTraces ([Ljava/lang/Thread;I)[[Ljava/lang/Object; -1 -2
printList ([Ljava/lang/Thread;I)V 0 68
- doTest ()V 117 56
+ doTest ()V 115 56
run ()V 32 41
---------
ThreadListTraces Thread 0
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 37
---------
ThreadListTraces Thread 2
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 37
---------
ThreadListTraces Thread 4
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 37
---------
ThreadListTraces Thread 6
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 37
---------
ThreadListTraces Thread 8
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 37
@@ -789,7 +857,7 @@ ThreadListTraces Thread 8
4
JVMTI_ERROR_ILLEGAL_ARGUMENT
[public static native java.lang.Object[] art.Frames.getFrameLocation(java.lang.Thread,int), ffffffff]
-[public static void art.Frames.doTestSameThread(), 35]
+[public static void art.Frames.doTestSameThread(), 40]
[public static void art.Frames.doTest() throws java.lang.Exception, 0]
[public void art.Test911$1.run(), 28]
JVMTI_ERROR_NO_MORE_FRAMES
@@ -797,23 +865,25 @@ JVMTI_ERROR_NO_MORE_FRAMES
################################
### Other thread (suspended) ###
################################
-18
+20
JVMTI_ERROR_ILLEGAL_ARGUMENT
-[public final native void java.lang.Object.wait() throws java.lang.InterruptedException, ffffffff]
+[public final native void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, ffffffff]
+[public final void java.lang.Object.wait(long) throws java.lang.InterruptedException, 1]
+[public final void java.lang.Object.wait() throws java.lang.InterruptedException, 2]
[private static void art.Recurse.printOrWait(int,int,art.ControlData), 18]
[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 2]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
[public void art.Frames$1.run(), 4]
@@ -824,20 +894,20 @@ JVMTI_ERROR_NO_MORE_FRAMES
###########################
17
JVMTI_ERROR_ILLEGAL_ARGUMENT
-[private static void art.Recurse.printOrWait(int,int,art.ControlData), 2c]
+[private static void art.Recurse.printOrWait(int,int,art.ControlData), 2d]
[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 2]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
[public void art.Frames$2.run(), 4]
diff --git a/test/911-get-stack-trace/expected_d8.diff b/test/911-get-stack-trace/expected_d8.diff
deleted file mode 100644
index c12015a832..0000000000
--- a/test/911-get-stack-trace/expected_d8.diff
+++ /dev/null
@@ -1,456 +0,0 @@
-12c12
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-15c15
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-18c18
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-21c21
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-24c24
-< doTest ()V 34 25
----
-> doTest ()V 33 25
-32c32
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-35c35
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-38c38
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-41c41
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-44c44
-< doTest ()V 38 26
----
-> doTest ()V 37 26
-57c57
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-62c62
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-70c70
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-84c84
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-87c87
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-90c90
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-93c93
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-102c102
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-105c105
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-108c108
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-111c111
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-125c125
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-132c132
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-137c137
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-140c140
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-148c148
-< printOrWait (IILart/ControlData;)V 44 54
----
-> printOrWait (IILart/ControlData;)V 45 54
-152c152
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-155c155
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-158c158
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-161c161
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-169c169
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-172c172
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-175c175
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-178c178
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-183c183
-< printOrWait (IILart/ControlData;)V 44 54
----
-> printOrWait (IILart/ControlData;)V 45 54
-187c187
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-191c191
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-199c199
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-204c204
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-207c207
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-363c363
-< doTest ()V 122 59
----
-> doTest ()V 120 59
-376c376
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-379c379
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-382c382
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-385c385
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-397c397
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-400c400
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-403c403
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-406c406
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-418c418
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-421c421
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-424c424
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-427c427
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-439c439
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-442c442
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-445c445
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-448c448
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-460c460
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-463c463
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-466c466
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-469c469
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-481c481
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-484c484
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-487c487
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-490c490
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-502c502
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-505c505
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-508c508
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-511c511
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-523c523
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-526c526
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-529c529
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-532c532
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-544c544
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-547c547
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-550c550
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-553c553
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-565c565
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-568c568
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-571c571
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-574c574
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-598c598
-< doTest ()V 127 61
----
-> doTest ()V 125 61
-630c630
-< doTest ()V 112 54
----
-> doTest ()V 110 54
-677c677
-< doTest ()V 117 56
----
-> doTest ()V 115 56
-687c687
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-690c690
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-693c693
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-696c696
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-708c708
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-711c711
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-714c714
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-717c717
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-729c729
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-732c732
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-735c735
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-738c738
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-750c750
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-753c753
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-756c756
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-759c759
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-771c771
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-774c774
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-777c777
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-780c780
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-792c792
-< [public static void art.Frames.doTestSameThread(), 35]
----
-> [public static void art.Frames.doTestSameThread(), 40]
-807c807
-< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
----
-> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-810c810
-< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
----
-> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-813c813
-< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
----
-> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-816c816
-< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
----
-> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-827c827
-< [private static void art.Recurse.printOrWait(int,int,art.ControlData), 2c]
----
-> [private static void art.Recurse.printOrWait(int,int,art.ControlData), 2d]
-831c831
-< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
----
-> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-834c834
-< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
----
-> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-837c837
-< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
----
-> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-840c840
-< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
----
-> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
diff --git a/test/911-get-stack-trace/src/art/AllTraces.java b/test/911-get-stack-trace/src/art/AllTraces.java
index d73f78bba1..507925c29e 100644
--- a/test/911-get-stack-trace/src/art/AllTraces.java
+++ b/test/911-get-stack-trace/src/art/AllTraces.java
@@ -56,7 +56,7 @@ public class AllTraces {
printAll(0);
- printAll(5);
+ printAll(7);
printAll(25);
diff --git a/test/911-get-stack-trace/src/art/OtherThread.java b/test/911-get-stack-trace/src/art/OtherThread.java
index 675bff55a6..3f5ae59e18 100644
--- a/test/911-get-stack-trace/src/art/OtherThread.java
+++ b/test/911-get-stack-trace/src/art/OtherThread.java
@@ -36,8 +36,8 @@ public class OtherThread {
System.out.println("From top");
PrintThread.print(t, 0, 25);
PrintThread.print(t, 1, 25);
- PrintThread.print(t, 0, 5);
- PrintThread.print(t, 2, 5);
+ PrintThread.print(t, 0, 7);
+ PrintThread.print(t, 2, 7);
System.out.println("From bottom");
PrintThread.print(t, -1, 25);
diff --git a/test/911-get-stack-trace/src/art/ThreadListTraces.java b/test/911-get-stack-trace/src/art/ThreadListTraces.java
index 0de93de706..9b27e72f22 100644
--- a/test/911-get-stack-trace/src/art/ThreadListTraces.java
+++ b/test/911-get-stack-trace/src/art/ThreadListTraces.java
@@ -51,7 +51,7 @@ public class ThreadListTraces {
printList(list, 0);
- printList(list, 5);
+ printList(list, 7);
printList(list, 25);
diff --git a/test/knownfailures.json b/test/knownfailures.json
index 493582fa48..ed98d233c3 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -362,6 +362,12 @@
},
{
"test_patterns": ["616-cha.*"],
+ "description": ["cha tests rely on knowing the exact set of optimizations available. ",
+ "Debuggable runtimes change the set of optimizations."],
+ "variant": "debuggable"
+ },
+ {
+ "test_patterns": ["616-cha.*"],
"description": ["cha tests rely on knowing more about the state of the JIT then is possible with jvmti-stress"],
"variant": "jvmti-stress & jit | redefine-stress & jit"
},
diff --git a/test/testrunner/target_config.py b/test/testrunner/target_config.py
index e0757abbe0..71f4cc0731 100644
--- a/test/testrunner/target_config.py
+++ b/test/testrunner/target_config.py
@@ -44,7 +44,7 @@ target_config = {
'run-test' : ['--interp-ac']
},
'art-jit' : {
- 'run-test' : ['--jit']
+ 'run-test' : ['--jit', '--debuggable', '--ndebuggable']
},
'art-jit-on-first-use' : {
'run-test' : ['--jit',
diff --git a/tools/dexanalyze/dexanalyze.cc b/tools/dexanalyze/dexanalyze.cc
index 7d7e5f28b3..7a9b8fb018 100644
--- a/tools/dexanalyze/dexanalyze.cc
+++ b/tools/dexanalyze/dexanalyze.cc
@@ -116,12 +116,14 @@ class DexAnalyze {
}
}
- bool ProcessDexFile(const DexFile& dex_file) {
+ bool ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files) {
for (std::unique_ptr<Experiment>& experiment : experiments_) {
- experiment->ProcessDexFile(dex_file);
+ experiment->ProcessDexFiles(dex_files);
}
- total_size_ += dex_file.Size();
- ++dex_count_;
+ for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
+ total_size_ += dex_file->Size();
+ }
+ dex_count_ += dex_files.size();
return true;
}
@@ -169,18 +171,16 @@ class DexAnalyze {
LOG(ERROR) << "OpenAll failed for " + filename << " with " << error_msg << std::endl;
return kExitCodeFailedToOpenDex;
}
- for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
- if (options.dump_per_input_dex_) {
- Analysis current(&options);
- if (!current.ProcessDexFile(*dex_file)) {
- LOG(ERROR) << "Failed to process " << filename << " with error " << error_msg;
- return kExitCodeFailedToProcessDex;
- }
- LOG(INFO) << "Analysis for " << dex_file->GetLocation() << std::endl;
- current.Dump(LOG_STREAM(INFO));
+ if (options.dump_per_input_dex_) {
+ Analysis current(&options);
+ if (!current.ProcessDexFiles(dex_files)) {
+ LOG(ERROR) << "Failed to process " << filename << " with error " << error_msg;
+ return kExitCodeFailedToProcessDex;
}
- cumulative.ProcessDexFile(*dex_file);
+ LOG(INFO) << "Analysis for " << filename << std::endl;
+ current.Dump(LOG_STREAM(INFO));
}
+ cumulative.ProcessDexFiles(dex_files);
}
LOG(INFO) << "Cumulative analysis for " << cumulative.dex_count_ << " DEX files" << std::endl;
cumulative.Dump(LOG_STREAM(INFO));
diff --git a/tools/dexanalyze/dexanalyze_experiments.cc b/tools/dexanalyze/dexanalyze_experiments.cc
index 1a3b89cbc7..244f45bbe6 100644
--- a/tools/dexanalyze/dexanalyze_experiments.cc
+++ b/tools/dexanalyze/dexanalyze_experiments.cc
@@ -75,86 +75,95 @@ static size_t PrefixLen(const std::string& a, const std::string& b) {
return len;
}
-void AnalyzeDebugInfo::ProcessDexFile(const DexFile& dex_file) {
+void Experiment::ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files) {
+ for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
+ ProcessDexFile(*dex_file);
+ }
+}
+
+void AnalyzeDebugInfo::ProcessDexFiles(
+ const std::vector<std::unique_ptr<const DexFile>>& dex_files) {
std::set<const uint8_t*> seen;
std::vector<size_t> counts(256, 0u);
std::vector<size_t> opcode_counts(256, 0u);
std::set<std::vector<uint8_t>> unique_non_header;
- for (ClassAccessor accessor : dex_file.GetClasses()) {
- for (const ClassAccessor::Method& method : accessor.GetMethods()) {
- CodeItemDebugInfoAccessor code_item(dex_file, method.GetCodeItem(), method.GetIndex());
- const uint8_t* debug_info = dex_file.GetDebugInfoStream(code_item.DebugInfoOffset());
- if (debug_info != nullptr && seen.insert(debug_info).second) {
- const uint8_t* stream = debug_info;
- DecodeUnsignedLeb128(&stream); // line_start
- uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
- for (uint32_t i = 0; i < parameters_size; ++i) {
- DecodeUnsignedLeb128P1(&stream); // Parameter name.
- }
- bool done = false;
- const uint8_t* after_header_start = stream;
- while (!done) {
- const uint8_t* const op_start = stream;
- uint8_t opcode = *stream++;
- ++opcode_counts[opcode];
- ++total_opcode_bytes_;
- switch (opcode) {
- case DexFile::DBG_END_SEQUENCE:
- ++total_end_seq_bytes_;
- done = true;
- break;
- case DexFile::DBG_ADVANCE_PC:
- DecodeUnsignedLeb128(&stream); // addr_diff
- total_advance_pc_bytes_ += stream - op_start;
- break;
- case DexFile::DBG_ADVANCE_LINE:
- DecodeSignedLeb128(&stream); // line_diff
- total_advance_line_bytes_ += stream - op_start;
- break;
- case DexFile::DBG_START_LOCAL:
- DecodeUnsignedLeb128(&stream); // register_num
- DecodeUnsignedLeb128P1(&stream); // name_idx
- DecodeUnsignedLeb128P1(&stream); // type_idx
- total_start_local_bytes_ += stream - op_start;
- break;
- case DexFile::DBG_START_LOCAL_EXTENDED:
- DecodeUnsignedLeb128(&stream); // register_num
- DecodeUnsignedLeb128P1(&stream); // name_idx
- DecodeUnsignedLeb128P1(&stream); // type_idx
- DecodeUnsignedLeb128P1(&stream); // sig_idx
- total_start_local_extended_bytes_ += stream - op_start;
- break;
- case DexFile::DBG_END_LOCAL:
- DecodeUnsignedLeb128(&stream); // register_num
- total_end_local_bytes_ += stream - op_start;
- break;
- case DexFile::DBG_RESTART_LOCAL:
- DecodeUnsignedLeb128(&stream); // register_num
- total_restart_local_bytes_ += stream - op_start;
- break;
- case DexFile::DBG_SET_PROLOGUE_END:
- case DexFile::DBG_SET_EPILOGUE_BEGIN:
- total_epilogue_bytes_ += stream - op_start;
- break;
- case DexFile::DBG_SET_FILE: {
- DecodeUnsignedLeb128P1(&stream); // name_idx
- total_set_file_bytes_ += stream - op_start;
- break;
- }
- default: {
- total_other_bytes_ += stream - op_start;
- break;
+ for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
+ for (ClassAccessor accessor : dex_file->GetClasses()) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+ CodeItemDebugInfoAccessor code_item(*dex_file, method.GetCodeItem(), method.GetIndex());
+ const uint8_t* debug_info = dex_file->GetDebugInfoStream(code_item.DebugInfoOffset());
+ if (debug_info != nullptr && seen.insert(debug_info).second) {
+ const uint8_t* stream = debug_info;
+ DecodeUnsignedLeb128(&stream); // line_start
+ uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
+ for (uint32_t i = 0; i < parameters_size; ++i) {
+ DecodeUnsignedLeb128P1(&stream); // Parameter name.
+ }
+ bool done = false;
+ const uint8_t* after_header_start = stream;
+ while (!done) {
+ const uint8_t* const op_start = stream;
+ uint8_t opcode = *stream++;
+ ++opcode_counts[opcode];
+ ++total_opcode_bytes_;
+ switch (opcode) {
+ case DexFile::DBG_END_SEQUENCE:
+ ++total_end_seq_bytes_;
+ done = true;
+ break;
+ case DexFile::DBG_ADVANCE_PC:
+ DecodeUnsignedLeb128(&stream); // addr_diff
+ total_advance_pc_bytes_ += stream - op_start;
+ break;
+ case DexFile::DBG_ADVANCE_LINE:
+ DecodeSignedLeb128(&stream); // line_diff
+ total_advance_line_bytes_ += stream - op_start;
+ break;
+ case DexFile::DBG_START_LOCAL:
+ DecodeUnsignedLeb128(&stream); // register_num
+ DecodeUnsignedLeb128P1(&stream); // name_idx
+ DecodeUnsignedLeb128P1(&stream); // type_idx
+ total_start_local_bytes_ += stream - op_start;
+ break;
+ case DexFile::DBG_START_LOCAL_EXTENDED:
+ DecodeUnsignedLeb128(&stream); // register_num
+ DecodeUnsignedLeb128P1(&stream); // name_idx
+ DecodeUnsignedLeb128P1(&stream); // type_idx
+ DecodeUnsignedLeb128P1(&stream); // sig_idx
+ total_start_local_extended_bytes_ += stream - op_start;
+ break;
+ case DexFile::DBG_END_LOCAL:
+ DecodeUnsignedLeb128(&stream); // register_num
+ total_end_local_bytes_ += stream - op_start;
+ break;
+ case DexFile::DBG_RESTART_LOCAL:
+ DecodeUnsignedLeb128(&stream); // register_num
+ total_restart_local_bytes_ += stream - op_start;
+ break;
+ case DexFile::DBG_SET_PROLOGUE_END:
+ case DexFile::DBG_SET_EPILOGUE_BEGIN:
+ total_epilogue_bytes_ += stream - op_start;
+ break;
+ case DexFile::DBG_SET_FILE: {
+ DecodeUnsignedLeb128P1(&stream); // name_idx
+ total_set_file_bytes_ += stream - op_start;
+ break;
+ }
+ default: {
+ total_other_bytes_ += stream - op_start;
+ break;
+ }
}
}
- }
- const size_t bytes = stream - debug_info;
- total_bytes_ += bytes;
- total_non_header_bytes_ += stream - after_header_start;
- if (unique_non_header.insert(std::vector<uint8_t>(after_header_start, stream)).second) {
- total_unique_non_header_bytes_ += stream - after_header_start;
- }
- for (size_t i = 0; i < bytes; ++i) {
- ++counts[debug_info[i]];
+ const size_t bytes = stream - debug_info;
+ total_bytes_ += bytes;
+ total_non_header_bytes_ += stream - after_header_start;
+ if (unique_non_header.insert(std::vector<uint8_t>(after_header_start, stream)).second) {
+ total_unique_non_header_bytes_ += stream - after_header_start;
+ }
+ for (size_t i = 0; i < bytes; ++i) {
+ ++counts[debug_info[i]];
+ }
}
}
}
diff --git a/tools/dexanalyze/dexanalyze_experiments.h b/tools/dexanalyze/dexanalyze_experiments.h
index a2621c85ca..2be53d6216 100644
--- a/tools/dexanalyze/dexanalyze_experiments.h
+++ b/tools/dexanalyze/dexanalyze_experiments.h
@@ -18,7 +18,9 @@
#define ART_TOOLS_DEXANALYZE_DEXANALYZE_EXPERIMENTS_H_
#include <iosfwd>
+#include <memory>
#include <set>
+#include <vector>
namespace art {
@@ -30,7 +32,8 @@ std::string Percent(uint64_t value, uint64_t max);
class Experiment {
public:
virtual ~Experiment() {}
- virtual void ProcessDexFile(const DexFile& dex_file) = 0;
+ virtual void ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files);
+ virtual void ProcessDexFile(const DexFile&) {}
virtual void Dump(std::ostream& os, uint64_t total_size) const = 0;
};
@@ -54,7 +57,7 @@ class AnalyzeStrings : public Experiment {
// Analyze debug info sizes.
class AnalyzeDebugInfo : public Experiment {
public:
- void ProcessDexFile(const DexFile& dex_file);
+ void ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files);
void Dump(std::ostream& os, uint64_t total_size) const;
private:
@@ -112,7 +115,7 @@ class CountDexIndices : public Experiment {
size_t total_super_ = 0;
};
-// Measure various code metrics including args per invoke-virtual, fill/spill move paterns.
+// Measure various code metrics including args per invoke-virtual, fill/spill move patterns.
class CodeMetrics : public Experiment {
public:
void ProcessDexFile(const DexFile& dex_file);