Merge "De-duplicate inline info in stack maps."
diff --git a/adbconnection/adbconnection.cc b/adbconnection/adbconnection.cc
index 8cd0d8b..ad94148 100644
--- a/adbconnection/adbconnection.cc
+++ b/adbconnection/adbconnection.cc
@@ -489,7 +489,7 @@
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 @@
(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/dex/dex_to_dex_decompiler_test.cc b/compiler/dex/dex_to_dex_decompiler_test.cc
index 75de238..1fe42ad 100644
--- a/compiler/dex/dex_to_dex_decompiler_test.cc
+++ b/compiler/dex/dex_to_dex_decompiler_test.cc
@@ -67,7 +67,7 @@
class_loader = LoadDex(dex_name);
updated_dex_file = GetDexFiles(class_loader)[0];
Runtime::Current()->GetClassLinker()->RegisterDexFile(
- *updated_dex_file, soa.Decode<mirror::ClassLoader>(class_loader).Ptr());
+ *updated_dex_file, soa.Decode<mirror::ClassLoader>(class_loader));
}
// The dex files should be identical.
int cmp = memcmp(original_dex_file->Begin(),
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index 028de34..dc07090 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -1342,6 +1342,14 @@
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 4046dc1..9951668 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -4032,13 +4032,13 @@
// 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 @@
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/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc
index 0694c4f..d0a6eb9 100644
--- a/dex2oat/linker/oat_writer_test.cc
+++ b/dex2oat/linker/oat_writer_test.cc
@@ -545,8 +545,7 @@
ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
for (const DexFile* dex_file : dex_files) {
ScopedObjectAccess soa(Thread::Current());
- class_linker->RegisterDexFile(*dex_file,
- soa.Decode<mirror::ClassLoader>(class_loader).Ptr());
+ class_linker->RegisterDexFile(*dex_file, soa.Decode<mirror::ClassLoader>(class_loader));
}
compiler_driver_->SetDexFilesForOatFile(dex_files);
compiler_driver_->CompileAll(class_loader, dex_files, &timings);
diff --git a/libdexfile/dex/class_accessor-inl.h b/libdexfile/dex/class_accessor-inl.h
index 49ca98d..3bb9e93 100644
--- a/libdexfile/dex/class_accessor-inl.h
+++ b/libdexfile/dex/class_accessor-inl.h
@@ -37,30 +37,26 @@
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 @@
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 @@
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 dda6e1c..4f0fd32 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 @@
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 @@
}
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 @@
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 @@
}
}
+ // 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 @@
// 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_;
}
- private:
- const uint8_t* Read(const uint8_t* ptr);
+ bool IsStatic() const {
+ return is_static_;
+ }
+ // Unhide the hidden API access flags at the iterator position. TODO: Deprecate.
+ void UnHideAccessFlags() const;
+
+ private:
+ 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 @@
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 @@
if (position_ == partition_pos_) {
data_.NextSection();
}
- DCHECK(ptr_pos_ != nullptr);
- ptr_pos_ = data_.Read(ptr_pos_);
+ data_.Read();
}
}
@@ -217,8 +241,6 @@
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 @@
// 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 @@
return num_instance_fields_;
}
+ uint32_t NumFields() const {
+ return NumStaticFields() + NumInstanceFields();
+ }
+
uint32_t NumDirectMethods() const {
return num_direct_methods_;
}
@@ -285,14 +323,22 @@
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 95380d8..d0533c1 100644
--- a/libdexfile/dex/class_accessor_test.cc
+++ b/libdexfile/dex/class_accessor_test.cc
@@ -38,18 +38,27 @@
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 @@
});
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 9de260c..f570158 100644
--- a/libdexfile/dex/dex_file.cc
+++ b/libdexfile/dex/dex_file.cc
@@ -45,19 +45,18 @@
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 f1f8b50..ed21980 100644
--- a/libdexfile/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -1010,8 +1010,8 @@
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 ca5ec2f..00ec358 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();
}
-}
+ 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();
-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));
-}
-
-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 @@
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));
}
+
+ return TypeLookupTable(dex_file.DataBegin(), mask_bits, entries, std::move(owned_entries));
}
-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;
+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);
}
-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;
-}
-
-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();
- entry = &entries_[pos];
+ if (entry->IsEmpty()) {
+ return dex::kDexNoIndex;
}
- return pos;
+ // 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.
+ }
+ // 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 0ba2b75..7005d34 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 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;
+ /**
+ * 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);
+ }
- Entry() : str_offset(0), data(0), next_pos_delta(0) {}
+ 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;
}
+
+ uint32_t GetStringOffset() const {
+ return str_offset_;
+ }
+
+ uint32_t GetNextPosDelta(uint32_t mask_bits) const {
+ return data_ & GetMask(mask_bits);
+ }
+
+ uint32_t GetClassDefIdx(uint32_t mask_bits) const {
+ return (data_ >> mask_bits) & GetMask(mask_bits);
+ }
+
+ uint32_t GetHashBits(uint32_t mask_bits) const {
+ DCHECK_LE(mask_bits, 16u);
+ return data_ >> (2u * mask_bits);
+ }
+
+ static uint32_t GetMask(uint32_t mask_bits) {
+ DCHECK_LE(mask_bits, 16u);
+ return ~(std::numeric_limits<uint32_t>::max() << mask_bits);
+ }
+
+ private:
+ uint32_t str_offset_;
+ uint32_t data_;
};
- static uint32_t CalculateMask(uint32_t num_class_defs);
+ static uint32_t CalculateMaskBits(uint32_t num_class_defs);
static bool SupportedSize(uint32_t num_class_defs);
- // Construct from a dex file.
- explicit TypeLookupTable(const DexFile& dex_file, uint8_t* storage);
+ // Construct the TypeLookupTable.
+ TypeLookupTable(const uint8_t* dex_data_pointer,
+ uint32_t mask_bits,
+ const Entry* entries,
+ std::unique_ptr<Entry[]> owned_entries);
- // 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;
- }
-
- // 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 data) const {
- return data & mask_;
- }
-
- uint32_t GetSizeMask() const {
- return mask_;
- }
-
- // 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);
-
- // Insert an entry, probes until there is an empty slot.
- void Insert(const Entry& entry, uint32_t hash);
-
- // Find the last entry in a chain.
- uint32_t FindLastEntryInBucket(uint32_t cur_pos) const;
+ const char* GetStringData(const Entry& entry) const;
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_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(TypeLookupTable);
+ 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 6c3d291..4316be0 100644
--- a/libdexfile/dex/type_lookup_table_test.cc
+++ b/libdexfile/dex/type_lookup_table_test.cc
@@ -30,20 +30,20 @@
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 7ac9e98..7b72e18 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -105,6 +105,10 @@
const char* image_roots_descriptions_[] = {
"kDexCaches",
"kClassRoots",
+ "kOomeWhenThrowingException",
+ "kOomeWhenThrowingOome",
+ "kOomeWhenHandlingStackOverflow",
+ "kNoClassDefFoundError",
"kClassLoader",
};
@@ -1942,17 +1946,17 @@
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/openjdkjvm/OpenjdkJvm.cc b/openjdkjvm/OpenjdkJvm.cc
index be1ab78..765225a 100644
--- a/openjdkjvm/OpenjdkJvm.cc
+++ b/openjdkjvm/OpenjdkJvm.cc
@@ -401,7 +401,7 @@
art::ThrowNullPointerException("object == null");
return JNI_FALSE;
}
- return soa.Self()->HoldsLock(object.Ptr());
+ return soa.Self()->HoldsLock(object);
}
JNIEXPORT void JVM_SetNativeThreadName(JNIEnv* env, jobject jthread, jstring java_name) {
diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc
index fcbafe7..a660fb5 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 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/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index 73e3719..50d8dfe 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -526,7 +526,7 @@
return art::mirror::ByteArray::AllocateAndFill(
driver_->self_,
reinterpret_cast<const signed char*>(original_dex_file_.data()),
- original_dex_file_.size());
+ original_dex_file_.size()).Ptr();
}
// See if we already have one set.
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index a6d3903..3c0b3e4 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -973,7 +973,7 @@
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 baa5102..c5fb7d5 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 @@
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 b867621..6cbd9e4 100644
--- a/runtime/art_field.cc
+++ b/runtime/art_field.cc
@@ -52,13 +52,6 @@
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 784a862..123595c 100644
--- a/runtime/art_field.h
+++ b/runtime/art_field.h
@@ -201,8 +201,7 @@
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 @@
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 ec66966..18595cf 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -245,6 +245,12 @@
}
}
+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 151c36f..45bf664 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 @@
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 @@
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) {
+ 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();
}
- while (it.HasNextVirtualMethod()) {
- if (it.GetMemberIndex() == 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 012d706..09debb0 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -589,7 +589,7 @@
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 888f713..2536b23 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -35,20 +35,19 @@
namespace art {
inline ObjPtr<mirror::Class> ClassLinker::FindArrayClass(Thread* self,
- ObjPtr<mirror::Class>* element_class) {
+ ObjPtr<mirror::Class> element_class) {
for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
// Read the cached array class once to avoid races with other threads setting it.
ObjPtr<mirror::Class> array_class = find_array_class_cache_[i].Read();
- if (array_class != nullptr && array_class->GetComponentType() == *element_class) {
- return array_class.Ptr();
+ if (array_class != nullptr && array_class->GetComponentType() == element_class) {
+ return array_class;
}
}
std::string descriptor = "[";
std::string temp;
- descriptor += (*element_class)->GetDescriptor(&temp);
- StackHandleScope<2> hs(Thread::Current());
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle((*element_class)->GetClassLoader()));
- HandleWrapperObjPtr<mirror::Class> h_element_class(hs.NewHandleWrapper(element_class));
+ descriptor += element_class->GetDescriptor(&temp);
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::ClassLoader> class_loader(hs.NewHandle(element_class->GetClassLoader()));
ObjPtr<mirror::Class> array_class = FindClass(self, descriptor.c_str(), class_loader);
if (array_class != nullptr) {
// Benign races in storing array class and incrementing index.
@@ -59,7 +58,55 @@
// We should have a NoClassDefFoundError.
self->AssertPendingException();
}
- return array_class.Ptr();
+ 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,
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index dccdff0..6933174 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 @@
}
} 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 @@
: 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),
@@ -432,8 +431,8 @@
heap->IncrementDisableMovingGC(self);
StackHandleScope<64> hs(self); // 64 is picked arbitrarily.
auto class_class_size = mirror::Class::ClassClassSize(image_pointer_size_);
- Handle<mirror::Class> java_lang_Class(hs.NewHandle(down_cast<mirror::Class*>(
- heap->AllocNonMovableObject<true>(self, nullptr, class_class_size, VoidFunctor()))));
+ Handle<mirror::Class> java_lang_Class(hs.NewHandle(ObjPtr<mirror::Class>::DownCast(MakeObjPtr(
+ heap->AllocNonMovableObject<true>(self, nullptr, class_class_size, VoidFunctor())))));
CHECK(java_lang_Class != nullptr);
java_lang_Class->SetClassFlags(mirror::kClassFlagClass);
java_lang_Class->SetClass(java_lang_Class.Get());
@@ -512,6 +511,10 @@
// 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 @@
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 @@
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 @@
// 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
@@ -988,8 +988,8 @@
}
class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class>>(
- down_cast<mirror::ObjectArray<mirror::Class>*>(
- spaces[0]->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots)));
+ ObjPtr<mirror::ObjectArray<mirror::Class>>::DownCast(MakeObjPtr(
+ spaces[0]->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots))));
DCHECK_EQ(GetClassRoot(ClassRoot::kJavaLangClass, this)->GetClassFlags(),
mirror::kClassFlagClass);
@@ -1000,11 +1000,6 @@
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;
@@ -1094,7 +1089,7 @@
return false; // Stop the visit.
}
if (name != nullptr) {
- out_dex_file_names->push_front(name.Ptr());
+ out_dex_file_names->push_front(name);
}
return true; // Continue with the next Element.
};
@@ -1931,7 +1926,6 @@
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();
@@ -2114,16 +2108,16 @@
delete data.class_table;
}
-mirror::PointerArray* ClassLinker::AllocPointerArray(Thread* self, size_t length) {
- return down_cast<mirror::PointerArray*>(
+ObjPtr<mirror::PointerArray> ClassLinker::AllocPointerArray(Thread* self, size_t length) {
+ return ObjPtr<mirror::PointerArray>::DownCast(
image_pointer_size_ == PointerSize::k64
- ? static_cast<mirror::Array*>(mirror::LongArray::Alloc(self, length))
- : static_cast<mirror::Array*>(mirror::IntArray::Alloc(self, length)));
+ ? ObjPtr<mirror::Array>(mirror::LongArray::Alloc(self, length))
+ : ObjPtr<mirror::Array>(mirror::IntArray::Alloc(self, length)));
}
-mirror::DexCache* ClassLinker::AllocDexCache(ObjPtr<mirror::String>* out_location,
- Thread* self,
- const DexFile& dex_file) {
+ObjPtr<mirror::DexCache> ClassLinker::AllocDexCache(/*out*/ ObjPtr<mirror::String>* out_location,
+ Thread* self,
+ const DexFile& dex_file) {
StackHandleScope<1> hs(self);
DCHECK(out_location != nullptr);
auto dex_cache(hs.NewHandle(ObjPtr<mirror::DexCache>::DownCast(
@@ -2141,9 +2135,9 @@
return dex_cache.Get();
}
-mirror::DexCache* ClassLinker::AllocAndInitializeDexCache(Thread* self,
- const DexFile& dex_file,
- LinearAlloc* linear_alloc) {
+ObjPtr<mirror::DexCache> ClassLinker::AllocAndInitializeDexCache(Thread* self,
+ const DexFile& dex_file,
+ LinearAlloc* linear_alloc) {
ObjPtr<mirror::String> location = nullptr;
ObjPtr<mirror::DexCache> dex_cache = AllocDexCache(&location, self, dex_file);
if (dex_cache != nullptr) {
@@ -2156,7 +2150,7 @@
linear_alloc,
image_pointer_size_);
}
- return dex_cache.Ptr();
+ return dex_cache;
}
ObjPtr<mirror::Class> ClassLinker::AllocClass(Thread* self,
@@ -2179,7 +2173,7 @@
return AllocClass(self, GetClassRoot<mirror::Class>(this), class_size);
}
-mirror::ObjectArray<mirror::StackTraceElement>* ClassLinker::AllocStackTraceElementArray(
+ObjPtr<mirror::ObjectArray<mirror::StackTraceElement>> ClassLinker::AllocStackTraceElementArray(
Thread* self,
size_t length) {
return mirror::ObjectArray<mirror::StackTraceElement>::Alloc(
@@ -2260,7 +2254,7 @@
// Return the loaded class. No exceptions should be pending.
CHECK(klass->IsResolved()) << klass->PrettyClass();
self->AssertNoPendingException();
- return klass.Ptr();
+ return klass;
}
typedef std::pair<const DexFile*, const DexFile::ClassDef*> ClassPathEntry;
@@ -2282,7 +2276,7 @@
const char* descriptor,
size_t hash,
Handle<mirror::ClassLoader> class_loader,
- ObjPtr<mirror::Class>* result) {
+ /*out*/ ObjPtr<mirror::Class>* result) {
// Termination case: boot class loader.
if (IsBootClassLoader(soa, class_loader.Get())) {
*result = FindClassInBootClassLoaderClassPath(self, descriptor, hash);
@@ -2535,7 +2529,7 @@
if (old == nullptr) {
old = result_ptr; // For the comparison below, after releasing the lock.
if (descriptor_equals) {
- class_table->InsertWithHash(result_ptr.Ptr(), hash);
+ class_table->InsertWithHash(result_ptr, hash);
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader.Get());
} // else throw below, after releasing the lock.
}
@@ -2563,8 +2557,8 @@
DescriptorToDot(descriptor).c_str());
return nullptr;
}
- // success, return mirror::Class*
- return result_ptr.Ptr();
+ // Success.
+ return result_ptr;
}
ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self,
@@ -2730,52 +2724,50 @@
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 @@
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 @@
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 @@
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 @@
// 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;
- if (UNLIKELY(num_sfields != it.NumStaticFields()) ||
- UNLIKELY(num_ifields != it.NumInstanceFields())) {
+ // 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;
+
+ // 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 @@
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)) {
@@ -3553,6 +3533,10 @@
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;".
@@ -3612,7 +3596,7 @@
ObjPtr<mirror::Class> new_class =
LookupClass(self, descriptor, hash, component_type->GetClassLoader());
if (new_class != nullptr) {
- return new_class.Ptr();
+ return new_class;
}
}
@@ -3680,7 +3664,7 @@
// 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);
}
@@ -3713,7 +3697,7 @@
//
// (Yes, this happens.)
- return existing.Ptr();
+ return existing;
}
ObjPtr<mirror::Class> ClassLinker::FindPrimitiveClass(char type) {
@@ -3763,7 +3747,7 @@
ClassTable* const class_table = InsertClassTableForClassLoader(class_loader);
ObjPtr<mirror::Class> existing = class_table->Lookup(descriptor, hash);
if (existing != nullptr) {
- return existing.Ptr();
+ return existing;
}
VerifyObject(klass);
class_table->InsertWithHash(klass, hash);
@@ -3817,7 +3801,7 @@
if (class_table != nullptr) {
ObjPtr<mirror::Class> result = class_table->Lookup(descriptor, hash);
if (result != nullptr) {
- return result.Ptr();
+ return result;
}
}
return nullptr;
@@ -4772,24 +4756,29 @@
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());
}
}
@@ -5723,8 +5712,8 @@
klass->SetVTable(super_vtable);
return true;
}
- vtable = hs.NewHandle(down_cast<mirror::PointerArray*>(
- super_vtable->CopyOf(self, max_count)));
+ vtable = hs.NewHandle(
+ ObjPtr<mirror::PointerArray>::DownCast(super_vtable->CopyOf(self, max_count)));
if (UNLIKELY(vtable == nullptr)) {
self->AssertPendingOOMException();
return false;
@@ -5860,7 +5849,7 @@
// Shrink vtable if possible
CHECK_LE(actual_count, max_count);
if (actual_count < max_count) {
- vtable.Assign(down_cast<mirror::PointerArray*>(vtable->CopyOf(self, actual_count)));
+ vtable.Assign(ObjPtr<mirror::PointerArray>::DownCast(vtable->CopyOf(self, actual_count)));
if (UNLIKELY(vtable == nullptr)) {
self->AssertPendingOOMException();
return false;
@@ -5874,7 +5863,7 @@
static_cast<int>(num_virtual_methods));
return false;
}
- auto* vtable = AllocPointerArray(self, num_virtual_methods);
+ ObjPtr<mirror::PointerArray> vtable = AllocPointerArray(self, num_virtual_methods);
if (UNLIKELY(vtable == nullptr)) {
self->AssertPendingOOMException();
return false;
@@ -6118,7 +6107,8 @@
DCHECK(if_table != nullptr);
DCHECK(if_table->GetMethodArray(i) != nullptr);
// If we are working on a super interface, try extending the existing method array.
- method_array = down_cast<mirror::PointerArray*>(if_table->GetMethodArray(i)->Clone(self));
+ method_array = ObjPtr<mirror::PointerArray>::DownCast(MakeObjPtr(
+ if_table->GetMethodArray(i)->Clone(self)));
} else {
method_array = AllocPointerArray(self, num_methods);
}
@@ -6382,7 +6372,7 @@
// iftable must be large enough to hold all interfaces without changing its size.
static size_t FillIfTable(ObjPtr<mirror::IfTable> iftable,
size_t super_ifcount,
- std::vector<mirror::Class*> to_process)
+ std::vector<ObjPtr<mirror::Class>> to_process)
REQUIRES(Roles::uninterruptible_)
REQUIRES_SHARED(Locks::mutator_lock_) {
// This is the set of all class's already in the iftable. Used to make checking if a class has
@@ -6522,11 +6512,11 @@
size_t new_ifcount;
{
ScopedAssertNoThreadSuspension nts("Copying mirror::Class*'s for FillIfTable");
- std::vector<mirror::Class*> to_add;
+ std::vector<ObjPtr<mirror::Class>> to_add;
for (size_t i = 0; i < num_interfaces; i++) {
ObjPtr<mirror::Class> interface = have_interfaces ? interfaces->Get(i) :
mirror::Class::GetDirectInterface(self, klass.Get(), i);
- to_add.push_back(interface.Ptr());
+ to_add.push_back(interface);
}
new_ifcount = FillIfTable(iftable.Get(), super_ifcount, std::move(to_add));
@@ -6537,7 +6527,7 @@
// Shrink iftable in case duplicates were found
if (new_ifcount < ifcount) {
DCHECK_NE(num_interfaces, 0U);
- iftable.Assign(down_cast<mirror::IfTable*>(
+ iftable.Assign(ObjPtr<mirror::IfTable>::DownCast(
iftable->CopyOf(self, new_ifcount * mirror::IfTable::kMax)));
if (UNLIKELY(iftable == nullptr)) {
self->AssertPendingOOMException();
@@ -7051,7 +7041,7 @@
default_conflict_methods_.size();
ObjPtr<mirror::PointerArray> vtable =
- down_cast<mirror::PointerArray*>(old_vtable->CopyOf(self_, new_vtable_count));
+ ObjPtr<mirror::PointerArray>::DownCast(old_vtable->CopyOf(self_, new_vtable_count));
if (UNLIKELY(vtable == nullptr)) {
self_->AssertPendingOOMException();
return nullptr;
@@ -7664,14 +7654,15 @@
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);
@@ -7682,13 +7673,9 @@
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);
@@ -7721,7 +7708,7 @@
DCHECK(self != nullptr);
const size_t hash = ComputeModifiedUtf8Hash(descriptor);
// Find the class in the loaded classes table.
- type = LookupClass(self, descriptor, hash, class_loader.Ptr());
+ type = LookupClass(self, descriptor, hash, class_loader);
}
if (type != nullptr) {
if (type->IsResolved()) {
@@ -8104,7 +8091,7 @@
ObjPtr<mirror::MethodType> resolved = dex_cache->GetResolvedMethodType(proto_idx);
if (resolved != nullptr) {
- return resolved.Ptr();
+ return resolved;
}
StackHandleScope<4> hs(self);
@@ -8760,7 +8747,7 @@
DCHECK(dex_file != nullptr);
Thread* const self = Thread::Current();
WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
- ClassTable* const table = ClassTableForClassLoader(class_loader.Ptr());
+ ClassTable* const table = ClassTableForClassLoader(class_loader);
DCHECK(table != nullptr);
if (table->InsertStrongRoot(dex_file) && class_loader != nullptr) {
// It was not already inserted, perform the write barrier to let the GC know the class loader's
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 32016fa..30c2423 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"
@@ -163,7 +164,7 @@
}
// Finds the array class given for the element class.
- ObjPtr<mirror::Class> FindArrayClass(Thread* self, ObjPtr<mirror::Class>* element_class)
+ ObjPtr<mirror::Class> FindArrayClass(Thread* self, ObjPtr<mirror::Class> element_class)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_);
@@ -203,6 +204,16 @@
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,
@@ -451,7 +462,7 @@
LinearAlloc* allocator,
size_t length);
- mirror::PointerArray* AllocPointerArray(Thread* self, size_t length)
+ ObjPtr<mirror::PointerArray> AllocPointerArray(Thread* self, size_t length)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
@@ -459,8 +470,8 @@
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
- mirror::ObjectArray<mirror::StackTraceElement>* AllocStackTraceElementArray(Thread* self,
- size_t length)
+ ObjPtr<mirror::ObjectArray<mirror::StackTraceElement>> AllocStackTraceElementArray(Thread* self,
+ size_t length)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
@@ -543,8 +554,9 @@
REQUIRES_SHARED(Locks::mutator_lock_);
template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
- mirror::ObjectArray<mirror::Class>* GetClassRoots() REQUIRES_SHARED(Locks::mutator_lock_) {
- mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read<kReadBarrierOption>();
+ ObjPtr<mirror::ObjectArray<mirror::Class>> GetClassRoots() REQUIRES_SHARED(Locks::mutator_lock_) {
+ ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
+ class_roots_.Read<kReadBarrierOption>();
DCHECK(class_roots != nullptr);
return class_roots;
}
@@ -777,16 +789,16 @@
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
- mirror::DexCache* AllocDexCache(ObjPtr<mirror::String>* out_location,
- Thread* self,
- const DexFile& dex_file)
+ ObjPtr<mirror::DexCache> AllocDexCache(/*out*/ ObjPtr<mirror::String>* out_location,
+ Thread* self,
+ const DexFile& dex_file)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
// Used for tests and AppendToBootClassPath.
- mirror::DexCache* AllocAndInitializeDexCache(Thread* self,
- const DexFile& dex_file,
- LinearAlloc* linear_alloc)
+ ObjPtr<mirror::DexCache> AllocAndInitializeDexCache(Thread* self,
+ const DexFile& dex_file,
+ LinearAlloc* linear_alloc)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_)
REQUIRES(!Roles::uninterruptible_);
@@ -824,18 +836,14 @@
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_);
@@ -850,7 +858,7 @@
const char* descriptor,
size_t hash,
Handle<mirror::ClassLoader> class_loader,
- ObjPtr<mirror::Class>* result)
+ /*out*/ ObjPtr<mirror::Class>* result)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_);
@@ -884,6 +892,19 @@
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)
@@ -1251,6 +1272,8 @@
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_;
@@ -1280,9 +1303,6 @@
// 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/class_linker_test.cc b/runtime/class_linker_test.cc
index 5d420aa..e40f1db 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -233,8 +233,7 @@
ObjPtr<mirror::Class> direct_interface1 =
mirror::Class::GetDirectInterface(self, array.Get(), 1);
EXPECT_STREQ(direct_interface1->GetDescriptor(&temp), "Ljava/io/Serializable;");
- ObjPtr<mirror::Class> array_ptr = array->GetComponentType();
- EXPECT_OBJ_PTR_EQ(class_linker_->FindArrayClass(self, &array_ptr), array.Get());
+ EXPECT_OBJ_PTR_EQ(class_linker_->FindArrayClass(self, array->GetComponentType()), array.Get());
PointerSize pointer_size = class_linker_->GetImagePointerSize();
ObjPtr<mirror::Class> JavaLangObject =
diff --git a/runtime/class_root.h b/runtime/class_root.h
index 5c78198..4aa9801 100644
--- a/runtime/class_root.h
+++ b/runtime/class_root.h
@@ -127,7 +127,7 @@
ObjPtr<mirror::Class> klass =
class_roots->GetWithoutChecks<kDefaultVerifyFlags, kReadBarrierOption>(index);
DCHECK(klass != nullptr);
- return klass.Ptr();
+ return klass;
}
template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
diff --git a/runtime/debug_print.cc b/runtime/debug_print.cc
index c5bb4d5..cb334b5 100644
--- a/runtime/debug_print.cc
+++ b/runtime/debug_print.cc
@@ -37,7 +37,7 @@
std::ostringstream oss;
gc::Heap* heap = Runtime::Current()->GetHeap();
gc::space::ContinuousSpace* cs =
- heap->FindContinuousSpaceFromObject(klass.Ptr(), /* fail_ok */ true);
+ heap->FindContinuousSpaceFromObject(klass, /* fail_ok */ true);
if (cs != nullptr) {
if (cs->IsImageSpace()) {
gc::space::ImageSpace* ispace = cs->AsImageSpace();
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 88628bb..f75f47c 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -1388,7 +1388,7 @@
*new_object_id = 0;
return JDWP::ERR_OUT_OF_MEMORY;
}
- *new_object_id = gRegistry->Add(new_object.Ptr());
+ *new_object_id = gRegistry->Add(new_object);
return JDWP::ERR_NONE;
}
@@ -1404,10 +1404,9 @@
return error;
}
Thread* self = Thread::Current();
- gc::Heap* heap = Runtime::Current()->GetHeap();
- mirror::Array* new_array = mirror::Array::Alloc<true>(self, c, length,
- c->GetComponentSizeShift(),
- heap->GetCurrentAllocator());
+ gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
+ ObjPtr<mirror::Array> new_array =
+ mirror::Array::Alloc<true>(self, c, length, c->GetComponentSizeShift(), allocator_type);
if (new_array == nullptr) {
DCHECK(self->IsExceptionPending());
self->ClearException();
@@ -1849,7 +1848,7 @@
return field_value;
case Primitive::kPrimNot:
- field_value.SetL(f->GetObject(o).Ptr());
+ field_value.SetL(f->GetObject(o));
return field_value;
case Primitive::kPrimVoid:
diff --git a/runtime/dex/dex_file_annotations.cc b/runtime/dex/dex_file_annotations.cc
index 5cb08dc..9358cbe 100644
--- a/runtime/dex/dex_file_annotations.cc
+++ b/runtime/dex/dex_file_annotations.cc
@@ -359,7 +359,7 @@
ObjPtr<mirror::Class> annotation_member_class =
soa.Decode<mirror::Class>(WellKnownClasses::libcore_reflect_AnnotationMember);
ObjPtr<mirror::Class> annotation_member_array_class =
- class_linker->FindArrayClass(self, &annotation_member_class);
+ class_linker->FindArrayClass(self, annotation_member_class);
if (annotation_member_array_class == nullptr) {
return nullptr;
}
@@ -967,7 +967,7 @@
ObjPtr<mirror::Class> annotation_array_class =
soa.Decode<mirror::Class>(WellKnownClasses::java_lang_annotation_Annotation__array);
ObjPtr<mirror::Class> annotation_array_array_class =
- Runtime::Current()->GetClassLinker()->FindArrayClass(self, &annotation_array_class);
+ Runtime::Current()->GetClassLinker()->FindArrayClass(self, annotation_array_class);
if (annotation_array_array_class == nullptr) {
return nullptr;
}
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index f6b1c73..022857a 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -268,14 +268,14 @@
// check.
template <bool kAccessCheck, bool kInstrumented>
ALWAYS_INLINE
-inline mirror::Array* AllocArrayFromCode(dex::TypeIndex type_idx,
- int32_t component_count,
- ArtMethod* method,
- Thread* self,
- gc::AllocatorType allocator_type) {
+inline ObjPtr<mirror::Array> AllocArrayFromCode(dex::TypeIndex type_idx,
+ int32_t component_count,
+ ArtMethod* method,
+ Thread* self,
+ gc::AllocatorType allocator_type) {
bool slow_path = false;
- mirror::Class* klass = CheckArrayAlloc<kAccessCheck>(type_idx, component_count, method,
- &slow_path);
+ ObjPtr<mirror::Class> klass =
+ CheckArrayAlloc<kAccessCheck>(type_idx, component_count, method, &slow_path);
if (UNLIKELY(slow_path)) {
if (klass == nullptr) {
return nullptr;
@@ -306,7 +306,7 @@
// No need to retry a slow-path allocation as the above code won't cause a GC or thread
// suspension.
return mirror::Array::Alloc<kInstrumented>(self, klass, component_count,
- klass->GetComponentSizeShift(), allocator_type);
+ klass->GetComponentSizeShift(), allocator_type).Ptr();
}
template<FindFieldType type, bool access_check>
@@ -743,33 +743,6 @@
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.h b/runtime/entrypoints/entrypoint_utils.h
index e33de9c..9d70b03 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -87,11 +87,11 @@
// When verification/compiler hasn't been able to verify access, optionally perform an access
// check.
template <bool kAccessCheck, bool kInstrumented>
-ALWAYS_INLINE inline mirror::Array* AllocArrayFromCode(dex::TypeIndex type_idx,
- int32_t component_count,
- ArtMethod* method,
- Thread* self,
- gc::AllocatorType allocator_type)
+ALWAYS_INLINE inline ObjPtr<mirror::Array> AllocArrayFromCode(dex::TypeIndex type_idx,
+ int32_t component_count,
+ ArtMethod* method,
+ Thread* self,
+ gc::AllocatorType allocator_type)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
@@ -162,11 +162,6 @@
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 fa536c7..6275612 100644
--- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
@@ -210,7 +210,8 @@
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/gc/heap_verification_test.cc b/runtime/gc/heap_verification_test.cc
index 4f06ee6..3869533 100644
--- a/runtime/gc/heap_verification_test.cc
+++ b/runtime/gc/heap_verification_test.cc
@@ -35,7 +35,7 @@
VerificationTest() {}
template <class T>
- mirror::ObjectArray<T>* AllocObjectArray(Thread* self, size_t length)
+ ObjPtr<mirror::ObjectArray<T>> AllocObjectArray(Thread* self, size_t length)
REQUIRES_SHARED(Locks::mutator_lock_) {
return mirror::ObjectArray<T>::Alloc(
self,
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index dbe09e8..e754fbc 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -1287,7 +1287,7 @@
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 3a66a34..c527f6f 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 7ad2e7b..17fc664 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 8acd5bc..c6fc052 100644
--- a/runtime/image.h
+++ b/runtime/image.h
@@ -27,6 +27,7 @@
class ArtField;
class ArtMethod;
+template <class MirrorType> class ObjPtr;
namespace linker {
class ImageWriter;
@@ -206,7 +207,11 @@
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 @@
}
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/indirect_reference_table-inl.h b/runtime/indirect_reference_table-inl.h
index 9673bd9..2128f8c 100644
--- a/runtime/indirect_reference_table-inl.h
+++ b/runtime/indirect_reference_table-inl.h
@@ -111,12 +111,12 @@
if (serial_ == kIRTPrevCount) {
serial_ = 0;
}
- references_[serial_] = GcRoot<mirror::Object>(obj.Ptr());
+ references_[serial_] = GcRoot<mirror::Object>(obj);
}
inline void IrtEntry::SetReference(ObjPtr<mirror::Object> obj) {
DCHECK_LT(serial_, kIRTPrevCount);
- references_[serial_] = GcRoot<mirror::Object>(obj.Ptr());
+ references_[serial_] = GcRoot<mirror::Object>(obj);
}
} // namespace art
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 90e89cf..27f761a 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -945,11 +945,9 @@
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 0ee780d..60bf505 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -340,12 +340,8 @@
}
}
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/interpreter/mterp/mterp.cc b/runtime/interpreter/mterp/mterp.cc
index d62f511..e4cc6d3 100644
--- a/runtime/interpreter/mterp/mterp.cc
+++ b/runtime/interpreter/mterp/mterp.cc
@@ -559,7 +559,7 @@
REQUIRES_SHARED(Locks::mutator_lock_) {
const Instruction* inst = Instruction::At(dex_pc_ptr);
int32_t length = shadow_frame->GetVReg(inst->VRegB_22c(inst_data));
- mirror::Object* obj = AllocArrayFromCode<false, true>(
+ ObjPtr<mirror::Object> obj = AllocArrayFromCode<false, true>(
dex::TypeIndex(inst->VRegC_22c()), length, shadow_frame->GetMethod(), self,
Runtime::Current()->GetHeap()->GetCurrentAllocator());
if (UNLIKELY(obj == nullptr)) {
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 7abb007..667bd03 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -1691,7 +1691,7 @@
ObjPtr<mirror::Class> element_class = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
Runtime* runtime = Runtime::Current();
ObjPtr<mirror::Class> array_class =
- runtime->GetClassLinker()->FindArrayClass(self, &element_class);
+ runtime->GetClassLinker()->FindArrayClass(self, element_class);
DCHECK(array_class != nullptr);
gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
result->SetL(mirror::Array::Alloc<true, true>(self,
@@ -1818,13 +1818,13 @@
ObjPtr<mirror::Class> element_class = reinterpret_cast<mirror::Class*>(args[0])->AsClass();
Runtime* runtime = Runtime::Current();
ClassLinker* class_linker = runtime->GetClassLinker();
- ObjPtr<mirror::Class> array_class = class_linker->FindArrayClass(self, &element_class);
+ ObjPtr<mirror::Class> array_class = class_linker->FindArrayClass(self, element_class);
if (UNLIKELY(array_class == nullptr)) {
CHECK(self->IsExceptionPending());
return;
}
DCHECK(array_class->IsObjectArrayClass());
- mirror::Array* new_array = mirror::ObjectArray<mirror::Object*>::Alloc(
+ ObjPtr<mirror::Array> new_array = mirror::ObjectArray<mirror::Object>::Alloc(
self, array_class, length, runtime->GetHeap()->GetCurrentAllocator());
result->SetL(new_array);
}
diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc
index 449458c..655713e 100644
--- a/runtime/interpreter/unstarted_runtime_test.cc
+++ b/runtime/interpreter/unstarted_runtime_test.cc
@@ -91,7 +91,7 @@
REQUIRES_SHARED(Locks::mutator_lock_) {
Runtime* runtime = Runtime::Current();
ObjPtr<mirror::Class> array_type =
- runtime->GetClassLinker()->FindArrayClass(self, &component_type);
+ runtime->GetClassLinker()->FindArrayClass(self, component_type);
CHECK(array_type != nullptr);
ObjPtr<mirror::ObjectArray<mirror::Object>> result =
mirror::ObjectArray<mirror::Object>::Alloc(self, array_type, 3);
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index d8aa00c..b010650 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -471,7 +471,7 @@
if (kIsDebugBuild) {
// Ensure the string is strongly interned. b/32995596
if (object->IsString()) {
- ObjPtr<mirror::String> str = reinterpret_cast<mirror::String*>(object.Ptr());
+ ObjPtr<mirror::String> str = ObjPtr<mirror::String>::DownCast(object);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
CHECK(class_linker->GetInternTable()->LookupStrong(Thread::Current(), str) != nullptr);
}
diff --git a/runtime/jni/jni_internal.cc b/runtime/jni/jni_internal.cc
index 987c8e9..7290d63 100644
--- a/runtime/jni/jni_internal.cc
+++ b/runtime/jni/jni_internal.cc
@@ -2036,14 +2036,14 @@
return nullptr;
}
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- array_class = class_linker->FindArrayClass(soa.Self(), &element_class);
+ array_class = class_linker->FindArrayClass(soa.Self(), element_class);
if (UNLIKELY(array_class == nullptr)) {
return nullptr;
}
}
// Allocate and initialize if necessary.
- mirror::ObjectArray<mirror::Object>* result =
+ ObjPtr<mirror::ObjectArray<mirror::Object>> result =
mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), array_class, length);
if (result != nullptr && initial_element != nullptr) {
ObjPtr<mirror::Object> initial_object = soa.Decode<mirror::Object>(initial_element);
@@ -2548,7 +2548,7 @@
soa.Vm()->JniAbortF("NewPrimitiveArray", "negative array length: %d", length);
return nullptr;
}
- ArtT* result = ArtT::Alloc(soa.Self(), length);
+ ObjPtr<ArtT> result = ArtT::Alloc(soa.Self(), length);
return soa.AddLocalReference<JniT>(result);
}
diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc
index 28df174..01a32a2 100644
--- a/runtime/method_handles.cc
+++ b/runtime/method_handles.cc
@@ -268,7 +268,7 @@
// Then perform the actual boxing, and then set the reference.
ObjPtr<mirror::Object> boxed = BoxPrimitive(type, src_value);
- value->SetL(boxed.Ptr());
+ value->SetL(boxed);
return true;
} else {
// The source type is a reference and the target type is a primitive, so we must unbox.
@@ -323,7 +323,7 @@
// Note: As an optimization, non-moving collectors leave a stale reference value
// in the references array even after the original vreg was overwritten to a non-reference.
if (src_value == reinterpret_cast<uintptr_t>(o.Ptr())) {
- callee_frame->SetVRegReference(dst_reg, o.Ptr());
+ callee_frame->SetVRegReference(dst_reg, o);
} else {
callee_frame->SetVReg(dst_reg, src_value);
}
diff --git a/runtime/method_handles_test.cc b/runtime/method_handles_test.cc
index 0db9551..d123754 100644
--- a/runtime/method_handles_test.cc
+++ b/runtime/method_handles_test.cc
@@ -179,7 +179,7 @@
StackHandleScope<3> hs(soa.Self());
static const int32_t kInitialValue = 101;
JValue value = JValue::FromPrimitive(kInitialValue);
- Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr());
+ Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value));
Handle<mirror::Class> from = hs.NewHandle(boxed_value->GetClass());
Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Number;"));
value.SetL(boxed_value.Get());
@@ -195,8 +195,7 @@
ClassLinker* cl = Runtime::Current()->GetClassLinker();
StackHandleScope<3> hs(soa.Self());
JValue value = JValue::FromPrimitive(3.733e2);
- Handle<mirror::Object> boxed_value =
- hs.NewHandle(BoxPrimitive(Primitive::kPrimDouble, value).Ptr());
+ Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimDouble, value));
Handle<mirror::Class> from = hs.NewHandle(boxed_value->GetClass());
Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
value.SetL(boxed_value.Get());
@@ -293,7 +292,7 @@
StackHandleScope<3> hs(soa.Self());
const int32_t kInitialValue = 101;
JValue value = JValue::FromPrimitive(kInitialValue);
- Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr());
+ Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value));
Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('I'));
value.SetL(boxed_value.Get());
@@ -308,7 +307,7 @@
StackHandleScope<3> hs(soa.Self());
static const int32_t kInitialValue = 101;
JValue value = JValue::FromPrimitive(kInitialValue);
- Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr());
+ Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value));
Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('J'));
value.SetL(boxed_value.Get());
@@ -352,7 +351,7 @@
StackHandleScope<3> hs(soa.Self());
static const int32_t kInitialValue = 101;
JValue value = JValue::FromPrimitive(kInitialValue);
- Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr());
+ Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value));
Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('S'));
value.SetL(boxed_value.Get());
@@ -368,8 +367,7 @@
StackHandleScope<3> hs(soa.Self());
static const double kInitialValue = 1e77;
JValue value = JValue::FromPrimitive(kInitialValue);
- Handle<mirror::Object> boxed_value =
- hs.NewHandle(BoxPrimitive(Primitive::kPrimDouble, value).Ptr());
+ Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimDouble, value));
Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Number;"));
Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('F'));
value.SetL(boxed_value.Get());
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index d2adcb4..2e39530 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -151,11 +151,11 @@
};
template <bool kIsInstrumented, bool kFillUsable>
-inline Array* Array::Alloc(Thread* self,
- ObjPtr<Class> array_class,
- int32_t component_count,
- size_t component_size_shift,
- gc::AllocatorType allocator_type) {
+inline ObjPtr<Array> Array::Alloc(Thread* self,
+ ObjPtr<Class> array_class,
+ int32_t component_count,
+ size_t component_size_shift,
+ gc::AllocatorType allocator_type) {
DCHECK(allocator_type != gc::kAllocatorTypeLOS);
DCHECK(array_class != nullptr);
DCHECK(array_class->IsArrayClass());
@@ -175,19 +175,19 @@
}
#endif
gc::Heap* heap = Runtime::Current()->GetHeap();
- Array* result;
+ ObjPtr<Array> result;
if (!kFillUsable) {
SetLengthVisitor visitor(component_count);
- result = down_cast<Array*>(
+ result = ObjPtr<Array>::DownCast(MakeObjPtr(
heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, array_class, size,
- allocator_type, visitor));
+ allocator_type, visitor)));
} else {
SetLengthToUsableSizeVisitor visitor(component_count,
DataOffset(1U << component_size_shift).SizeValue(),
component_size_shift);
- result = down_cast<Array*>(
+ result = ObjPtr<Array>::DownCast(MakeObjPtr(
heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, array_class, size,
- allocator_type, visitor));
+ allocator_type, visitor)));
}
if (kIsDebugBuild && result != nullptr && Runtime::Current()->IsStarted()) {
array_class = result->GetClass(); // In case the array class moved.
@@ -202,9 +202,9 @@
}
template<typename T>
-inline PrimitiveArray<T>* PrimitiveArray<T>::AllocateAndFill(Thread* self,
- const T* data,
- size_t length) {
+inline ObjPtr<PrimitiveArray<T>> PrimitiveArray<T>::AllocateAndFill(Thread* self,
+ const T* data,
+ size_t length) {
StackHandleScope<1> hs(self);
Handle<PrimitiveArray<T>> arr(hs.NewHandle(PrimitiveArray<T>::Alloc(self, length)));
if (!arr.IsNull()) {
diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc
index 06ce0bb..66ec368 100644
--- a/runtime/mirror/array.cc
+++ b/runtime/mirror/array.cc
@@ -42,17 +42,18 @@
// piece and work our way in.
// Recursively create an array with multiple dimensions. Elements may be
// Objects or primitive types.
-static Array* RecursiveCreateMultiArray(Thread* self,
- Handle<Class> array_class, int current_dimension,
- Handle<mirror::IntArray> dimensions)
+static ObjPtr<Array> RecursiveCreateMultiArray(Thread* self,
+ Handle<Class> array_class,
+ int current_dimension,
+ Handle<mirror::IntArray> dimensions)
REQUIRES_SHARED(Locks::mutator_lock_) {
int32_t array_length = dimensions->Get(current_dimension);
- StackHandleScope<1> hs(self);
- Handle<Array> new_array(
- hs.NewHandle(
- Array::Alloc<true>(self, array_class.Get(), array_length,
- array_class->GetComponentSizeShift(),
- Runtime::Current()->GetHeap()->GetCurrentAllocator())));
+ StackHandleScope<2> hs(self);
+ Handle<mirror::Class> h_component_type(hs.NewHandle(array_class->GetComponentType()));
+ size_t component_size_shift = h_component_type->GetPrimitiveTypeSizeShift();
+ gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
+ Handle<Array> new_array(hs.NewHandle(Array::Alloc<true>(
+ self, array_class.Get(), array_length, component_size_shift, allocator_type)));
if (UNLIKELY(new_array == nullptr)) {
CHECK(self->IsExceptionPending());
return nullptr;
@@ -60,10 +61,8 @@
if (current_dimension + 1 < dimensions->GetLength()) {
// Create a new sub-array in every element of the array.
for (int32_t i = 0; i < array_length; i++) {
- StackHandleScope<1> hs2(self);
- Handle<mirror::Class> h_component_type(hs2.NewHandle(array_class->GetComponentType()));
- ObjPtr<Array> sub_array = RecursiveCreateMultiArray(self, h_component_type,
- current_dimension + 1, dimensions);
+ ObjPtr<Array> sub_array =
+ RecursiveCreateMultiArray(self, h_component_type, current_dimension + 1, dimensions);
if (UNLIKELY(sub_array == nullptr)) {
CHECK(self->IsExceptionPending());
return nullptr;
@@ -75,8 +74,9 @@
return new_array.Get();
}
-Array* Array::CreateMultiArray(Thread* self, Handle<Class> element_class,
- Handle<IntArray> dimensions) {
+ObjPtr<Array> Array::CreateMultiArray(Thread* self,
+ Handle<Class> element_class,
+ Handle<IntArray> dimensions) {
// Verify dimensions.
//
// The caller is responsible for verifying that "dimArray" is non-null
@@ -95,17 +95,15 @@
// Find/generate the array class.
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- ObjPtr<mirror::Class> element_class_ptr = element_class.Get();
StackHandleScope<1> hs(self);
MutableHandle<mirror::Class> array_class(
- hs.NewHandle(class_linker->FindArrayClass(self, &element_class_ptr)));
+ hs.NewHandle(class_linker->FindArrayClass(self, element_class.Get())));
if (UNLIKELY(array_class == nullptr)) {
CHECK(self->IsExceptionPending());
return nullptr;
}
for (int32_t i = 1; i < dimensions->GetLength(); ++i) {
- ObjPtr<mirror::Class> array_class_ptr = array_class.Get();
- array_class.Assign(class_linker->FindArrayClass(self, &array_class_ptr));
+ array_class.Assign(class_linker->FindArrayClass(self, array_class.Get()));
if (UNLIKELY(array_class == nullptr)) {
CHECK(self->IsExceptionPending());
return nullptr;
@@ -120,13 +118,14 @@
}
template<typename T>
-PrimitiveArray<T>* PrimitiveArray<T>::Alloc(Thread* self, size_t length) {
- Array* raw_array = Array::Alloc<true>(self,
- GetClassRoot<PrimitiveArray<T>>(),
- length,
- ComponentSizeShiftWidth(sizeof(T)),
- Runtime::Current()->GetHeap()->GetCurrentAllocator());
- return down_cast<PrimitiveArray<T>*>(raw_array);
+ObjPtr<PrimitiveArray<T>> PrimitiveArray<T>::Alloc(Thread* self, size_t length) {
+ gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
+ ObjPtr<Array> raw_array = Array::Alloc<true>(self,
+ GetClassRoot<PrimitiveArray<T>>(),
+ length,
+ ComponentSizeShiftWidth(sizeof(T)),
+ allocator_type);
+ return ObjPtr<PrimitiveArray<T>>::DownCast(raw_array);
}
void Array::ThrowArrayIndexOutOfBoundsException(int32_t index) {
@@ -137,7 +136,7 @@
art::ThrowArrayStoreException(object->GetClass(), this->GetClass());
}
-Array* Array::CopyOf(Thread* self, int32_t new_length) {
+ObjPtr<Array> Array::CopyOf(Thread* self, int32_t new_length) {
CHECK(GetClass()->GetComponentType()->IsPrimitive()) << "Will miss write barriers";
DCHECK_GE(new_length, 0);
// We may get copied by a compacting GC.
@@ -148,7 +147,8 @@
heap->GetCurrentNonMovingAllocator();
const auto component_size = GetClass()->GetComponentSize();
const auto component_shift = GetClass()->GetComponentSizeShift();
- ObjPtr<Array> new_array = Alloc<true>(self, GetClass(), new_length, component_shift, allocator_type);
+ ObjPtr<Array> new_array =
+ Alloc<true>(self, GetClass(), new_length, component_shift, allocator_type);
if (LIKELY(new_array != nullptr)) {
memcpy(new_array->GetRawData(component_size, 0),
h_this->GetRawData(component_size, 0),
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index aeaaf673..8bdd561 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -37,17 +37,17 @@
// least component_count size, however, if there's usable space at the end of the allocation the
// array will fill it.
template <bool kIsInstrumented, bool kFillUsable = false>
- ALWAYS_INLINE static Array* Alloc(Thread* self,
- ObjPtr<Class> array_class,
- int32_t component_count,
- size_t component_size_shift,
- gc::AllocatorType allocator_type)
+ ALWAYS_INLINE static ObjPtr<Array> Alloc(Thread* self,
+ ObjPtr<Class> array_class,
+ int32_t component_count,
+ size_t component_size_shift,
+ gc::AllocatorType allocator_type)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
- static Array* CreateMultiArray(Thread* self,
- Handle<Class> element_class,
- Handle<IntArray> dimensions)
+ static ObjPtr<Array> CreateMultiArray(Thread* self,
+ Handle<Class> element_class,
+ Handle<IntArray> dimensions)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
@@ -90,7 +90,7 @@
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE bool CheckIsValidIndex(int32_t index) REQUIRES_SHARED(Locks::mutator_lock_);
- Array* CopyOf(Thread* self, int32_t new_length) REQUIRES_SHARED(Locks::mutator_lock_)
+ ObjPtr<Array> CopyOf(Thread* self, int32_t new_length) REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
protected:
@@ -114,10 +114,10 @@
public:
typedef T ElementType;
- static PrimitiveArray<T>* Alloc(Thread* self, size_t length)
+ static ObjPtr<PrimitiveArray<T>> Alloc(Thread* self, size_t length)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
- static PrimitiveArray<T>* AllocateAndFill(Thread* self, const T* data, size_t length)
+ static ObjPtr<PrimitiveArray<T>> AllocateAndFill(Thread* self, const T* data, size_t length)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 5328ad9..fffd7f3 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -294,7 +294,7 @@
return GetFieldObject<PointerArray>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_));
}
-inline void Class::SetVTable(PointerArray* new_vtable) {
+inline void Class::SetVTable(ObjPtr<PointerArray> new_vtable) {
SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable);
}
@@ -486,7 +486,7 @@
if (UNLIKELY(!this->CanAccess(dex_access_to))) {
if (throw_on_failure) {
ThrowIllegalAccessErrorClassForMethodDispatch(this,
- dex_access_to.Ptr(),
+ dex_access_to,
method,
throw_invoke_type);
}
@@ -797,7 +797,7 @@
obj = nullptr;
}
}
- return obj.Ptr();
+ return obj;
}
inline ObjPtr<Object> Class::AllocObject(Thread* self) {
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 31a83f8..44b0c2b 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -419,7 +419,7 @@
}
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 @@
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 @@
}
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/class.h b/runtime/mirror/class.h
index 6feaa9c..c3e167c 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -781,7 +781,7 @@
ALWAYS_INLINE PointerArray* GetVTableDuringLinking() REQUIRES_SHARED(Locks::mutator_lock_);
- void SetVTable(PointerArray* new_vtable) REQUIRES_SHARED(Locks::mutator_lock_);
+ void SetVTable(ObjPtr<PointerArray> new_vtable) REQUIRES_SHARED(Locks::mutator_lock_);
static MemberOffset VTableOffset() {
return OFFSET_OF_OBJECT_MEMBER(Class, vtable_);
diff --git a/runtime/mirror/class_ext.cc b/runtime/mirror/class_ext.cc
index 7214620..44bf989 100644
--- a/runtime/mirror/class_ext.cc
+++ b/runtime/mirror/class_ext.cc
@@ -43,8 +43,8 @@
auto obsolete_dex_cache_off = OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_dex_caches_);
auto obsolete_methods_off = OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_methods_);
DCHECK(!Runtime::Current()->IsActiveTransaction());
- SetFieldObject<false>(obsolete_dex_cache_off, dex_caches.Ptr());
- SetFieldObject<false>(obsolete_methods_off, methods.Ptr());
+ SetFieldObject<false>(obsolete_dex_cache_off, dex_caches);
+ SetFieldObject<false>(obsolete_methods_off, methods);
}
// We really need to be careful how we update this. If we ever in the future make it so that
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index cd822c2..ee4f53b 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -114,10 +114,6 @@
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);
}
@@ -776,7 +772,7 @@
} else {
obj = GetFieldObject<Object>(field_offset);
}
- Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj.Ptr(), true);
+ Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj, true);
}
if (kVerifyFlags & kVerifyThis) {
VerifyObject(this);
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 8584b8a..a89d632 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -176,7 +176,6 @@
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/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index 086d2f4..ed3c567 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -37,14 +37,15 @@
namespace mirror {
template<class T>
-inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self,
- ObjPtr<Class> object_array_class,
- int32_t length, gc::AllocatorType allocator_type) {
- Array* array = Array::Alloc<true>(self,
- object_array_class.Ptr(),
- length,
- ComponentSizeShiftWidth(kHeapReferenceSize),
- allocator_type);
+inline ObjPtr<ObjectArray<T>> ObjectArray<T>::Alloc(Thread* self,
+ ObjPtr<Class> object_array_class,
+ int32_t length,
+ gc::AllocatorType allocator_type) {
+ ObjPtr<Array> array = Array::Alloc<true>(self,
+ object_array_class,
+ length,
+ ComponentSizeShiftWidth(kHeapReferenceSize),
+ allocator_type);
if (UNLIKELY(array == nullptr)) {
return nullptr;
}
@@ -54,9 +55,9 @@
}
template<class T>
-inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self,
- ObjPtr<Class> object_array_class,
- int32_t length) {
+inline ObjPtr<ObjectArray<T>> ObjectArray<T>::Alloc(Thread* self,
+ ObjPtr<Class> object_array_class,
+ int32_t length) {
return Alloc(self,
object_array_class,
length,
@@ -346,7 +347,7 @@
}
template<class T>
-inline ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) {
+inline ObjPtr<ObjectArray<T>> ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) {
DCHECK_GE(new_length, 0);
// We may get copied by a compacting GC.
StackHandleScope<1> hs(self);
@@ -354,7 +355,7 @@
gc::Heap* heap = Runtime::Current()->GetHeap();
gc::AllocatorType allocator_type = heap->IsMovableObject(this) ? heap->GetCurrentAllocator() :
heap->GetCurrentNonMovingAllocator();
- ObjectArray<T>* new_array = Alloc(self, GetClass(), new_length, allocator_type);
+ ObjPtr<ObjectArray<T>> new_array = Alloc(self, GetClass(), new_length, allocator_type);
if (LIKELY(new_array != nullptr)) {
new_array->AssignableMemcpy(0, h_this.Get(), 0, std::min(h_this->GetLength(), new_length));
}
diff --git a/runtime/mirror/object_array.h b/runtime/mirror/object_array.h
index b7a9561..6506f6e 100644
--- a/runtime/mirror/object_array.h
+++ b/runtime/mirror/object_array.h
@@ -31,15 +31,15 @@
return Array::ClassSize(pointer_size);
}
- static ObjectArray<T>* Alloc(Thread* self,
- ObjPtr<Class> object_array_class,
- int32_t length,
- gc::AllocatorType allocator_type)
+ static ObjPtr<ObjectArray<T>> Alloc(Thread* self,
+ ObjPtr<Class> object_array_class,
+ int32_t length,
+ gc::AllocatorType allocator_type)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
- static ObjectArray<T>* Alloc(Thread* self,
- ObjPtr<Class> object_array_class,
- int32_t length)
+ static ObjPtr<ObjectArray<T>> Alloc(Thread* self,
+ ObjPtr<Class> object_array_class,
+ int32_t length)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
@@ -99,7 +99,7 @@
bool throw_exception)
REQUIRES_SHARED(Locks::mutator_lock_);
- ObjectArray<T>* CopyOf(Thread* self, int32_t new_length)
+ ObjPtr<ObjectArray<T>> CopyOf(Thread* self, int32_t new_length)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 8b7a1b6..0b615a6 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -76,7 +76,7 @@
}
template <class T>
- mirror::ObjectArray<T>* AllocObjectArray(Thread* self, size_t length)
+ ObjPtr<mirror::ObjectArray<T>> AllocObjectArray(Thread* self, size_t length)
REQUIRES_SHARED(Locks::mutator_lock_) {
return mirror::ObjectArray<T>::Alloc(
self, GetClassRoot(ClassRoot::kObjectArrayClass, class_linker_), length);
@@ -206,7 +206,8 @@
ScopedObjectAccess soa(Thread::Current());
typedef typename ArrayT::ElementType T;
- ArrayT* a = ArrayT::Alloc(soa.Self(), 2);
+ StackHandleScope<2> hs(soa.Self());
+ Handle<ArrayT> a = hs.NewHandle(ArrayT::Alloc(soa.Self(), 2));
EXPECT_EQ(2, a->GetLength());
EXPECT_EQ(0, a->Get(0));
EXPECT_EQ(0, a->Get(1));
@@ -217,7 +218,6 @@
EXPECT_EQ(T(123), a->Get(0));
EXPECT_EQ(T(321), a->Get(1));
- StackHandleScope<1> hs(soa.Self());
Handle<Class> aioobe = hs.NewHandle(
cl->FindSystemClass(soa.Self(), "Ljava/lang/ArrayIndexOutOfBoundsException;"));
@@ -256,7 +256,8 @@
ScopedObjectAccess soa(Thread::Current());
typedef typename ArrayT::ElementType T;
- ArrayT* a = ArrayT::Alloc(soa.Self(), 2);
+ StackHandleScope<2> hs(soa.Self());
+ Handle<ArrayT> a = hs.NewHandle(ArrayT::Alloc(soa.Self(), 2));
EXPECT_EQ(2, a->GetLength());
EXPECT_DOUBLE_EQ(0, a->Get(0));
EXPECT_DOUBLE_EQ(0, a->Get(1));
@@ -267,7 +268,6 @@
EXPECT_DOUBLE_EQ(T(123), a->Get(0));
EXPECT_DOUBLE_EQ(T(321), a->Get(1));
- StackHandleScope<1> hs(soa.Self());
Handle<Class> aioobe = hs.NewHandle(
class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/ArrayIndexOutOfBoundsException;"));
@@ -287,7 +287,8 @@
ScopedObjectAccess soa(Thread::Current());
typedef typename ArrayT::ElementType T;
- ArrayT* a = ArrayT::Alloc(soa.Self(), 2);
+ StackHandleScope<2> hs(soa.Self());
+ Handle<ArrayT> a = hs.NewHandle(ArrayT::Alloc(soa.Self(), 2));
EXPECT_FLOAT_EQ(2, a->GetLength());
EXPECT_FLOAT_EQ(0, a->Get(0));
EXPECT_FLOAT_EQ(0, a->Get(1));
@@ -298,7 +299,6 @@
EXPECT_FLOAT_EQ(T(123), a->Get(0));
EXPECT_FLOAT_EQ(T(321), a->Get(1));
- StackHandleScope<1> hs(soa.Self());
Handle<Class> aioobe = hs.NewHandle(
class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/ArrayIndexOutOfBoundsException;"));
@@ -317,16 +317,17 @@
TEST_F(ObjectTest, CreateMultiArray) {
ScopedObjectAccess soa(Thread::Current());
- StackHandleScope<2> hs(soa.Self());
- Handle<Class> c(hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "I")));
+ StackHandleScope<4> hs(soa.Self());
+ Handle<Class> int_class(hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "I")));
+ Handle<Class> int_array_class = hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[I"));
MutableHandle<IntArray> dims(hs.NewHandle(IntArray::Alloc(soa.Self(), 1)));
dims->Set<false>(0, 1);
- Array* multi = Array::CreateMultiArray(soa.Self(), c, dims);
- EXPECT_TRUE(multi->GetClass() == class_linker_->FindSystemClass(soa.Self(), "[I"));
+ MutableHandle<Array> multi = hs.NewHandle(Array::CreateMultiArray(soa.Self(), int_class, dims));
+ EXPECT_OBJ_PTR_EQ(int_array_class.Get(), multi->GetClass());
EXPECT_EQ(1, multi->GetLength());
dims->Set<false>(0, -1);
- multi = Array::CreateMultiArray(soa.Self(), c, dims);
+ multi.Assign(Array::CreateMultiArray(soa.Self(), int_class, dims));
EXPECT_TRUE(soa.Self()->IsExceptionPending());
EXPECT_EQ(mirror::Class::PrettyDescriptor(soa.Self()->GetException()->GetClass()),
"java.lang.NegativeArraySizeException");
@@ -337,12 +338,12 @@
for (int j = 0; j < 20; ++j) {
dims->Set<false>(0, i);
dims->Set<false>(1, j);
- multi = Array::CreateMultiArray(soa.Self(), c, dims);
+ multi.Assign(Array::CreateMultiArray(soa.Self(), int_class, dims));
EXPECT_TRUE(multi->GetClass() == class_linker_->FindSystemClass(soa.Self(), "[[I"));
EXPECT_EQ(i, multi->GetLength());
for (int k = 0; k < i; ++k) {
- Array* outer = multi->AsObjectArray<Array>()->Get(k);
- EXPECT_TRUE(outer->GetClass() == class_linker_->FindSystemClass(soa.Self(), "[I"));
+ ObjPtr<Array> outer = multi->AsObjectArray<Array>()->Get(k);
+ EXPECT_OBJ_PTR_EQ(int_array_class.Get(), outer->GetClass());
EXPECT_EQ(j, outer->GetLength());
}
}
@@ -817,7 +818,7 @@
ObjPtr<mirror::Class> c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;");
ASSERT_TRUE(c != nullptr);
- mirror::Object* o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0);
+ ObjPtr<mirror::Object> o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0);
EXPECT_EQ("java.lang.String[]", mirror::Object::PrettyTypeOf(o));
EXPECT_EQ("java.lang.Class<java.lang.String[]>", mirror::Object::PrettyTypeOf(o->GetClass()));
}
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 6c82019..3227c69 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -32,6 +32,7 @@
#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"
@@ -111,7 +112,7 @@
}
Runtime* runtime = Runtime::Current();
ObjPtr<mirror::Class> array_class =
- runtime->GetClassLinker()->FindArrayClass(soa.Self(), &element_class);
+ runtime->GetClassLinker()->FindArrayClass(soa.Self(), element_class);
if (UNLIKELY(array_class == nullptr)) {
return nullptr;
}
@@ -138,7 +139,7 @@
}
Runtime* runtime = Runtime::Current();
ObjPtr<mirror::Class> array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(),
- &element_class);
+ element_class);
if (UNLIKELY(array_class == nullptr)) {
return nullptr;
}
@@ -573,30 +574,12 @@
}
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/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 38c65f5..5b47eac 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -100,7 +100,7 @@
}
void AddClass(ObjPtr<mirror::Class> klass) REQUIRES(Locks::mutator_lock_) {
- class_set_.insert(self_->GetJniEnv()->AddLocalReference<jclass>(klass.Ptr()));
+ class_set_.insert(self_->GetJniEnv()->AddLocalReference<jclass>(klass));
}
const std::unordered_set<jclass>& GetClasses() const {
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index c6bdfa1..82e54e2 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -646,8 +646,8 @@
soa.Decode<mirror::Class>(WellKnownClasses::java_lang_annotation_Annotation__array);
ObjPtr<mirror::ObjectArray<mirror::Object>> empty_array =
mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(),
- annotation_array_class.Ptr(),
- 0);
+ annotation_array_class,
+ /* length */ 0);
return soa.AddLocalReference<jobjectArray>(empty_array);
}
return soa.AddLocalReference<jobjectArray>(annotations::GetAnnotationsForClass(klass));
diff --git a/runtime/native/java_lang_Object.cc b/runtime/native/java_lang_Object.cc
index 208ccf6..48540f8 100644
--- a/runtime/native/java_lang_Object.cc
+++ b/runtime/native/java_lang_Object.cc
@@ -41,11 +41,6 @@
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 @@
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_Thread.cc b/runtime/native/java_lang_Thread.cc
index a37a76f..13871f7 100644
--- a/runtime/native/java_lang_Thread.cc
+++ b/runtime/native/java_lang_Thread.cc
@@ -119,7 +119,7 @@
return JNI_FALSE;
}
Thread* thread = soa.Self();
- return thread->HoldsLock(object.Ptr());
+ return thread->HoldsLock(object);
}
static void Thread_nativeInterrupt(JNIEnv* env, jobject java_thread) {
diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc
index 42c7ad5..1ad233a 100644
--- a/runtime/native/java_lang_VMClassLoader.cc
+++ b/runtime/native/java_lang_VMClassLoader.cc
@@ -86,7 +86,7 @@
}
// If class is erroneous, throw the earlier failure, wrapped in certain cases. See b/28787733.
if (c != nullptr && c->IsErroneous()) {
- cl->ThrowEarlierClassFailure(c.Ptr());
+ cl->ThrowEarlierClassFailure(c);
Thread* self = soa.Self();
ObjPtr<mirror::Class> iae_class =
self->DecodeJObject(WellKnownClasses::java_lang_IllegalAccessError)->AsClass();
diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc
index 8bcda10..452a66d 100644
--- a/runtime/native/java_lang_reflect_Array.cc
+++ b/runtime/native/java_lang_reflect_Array.cc
@@ -44,9 +44,8 @@
Primitive::kPrimInt);
Handle<mirror::IntArray> dimensions_array(
hs.NewHandle(ObjPtr<mirror::IntArray>::DownCast(dimensions_obj)));
- mirror::Array* new_array = mirror::Array::CreateMultiArray(soa.Self(),
- element_class,
- dimensions_array);
+ ObjPtr<mirror::Array> new_array =
+ mirror::Array::CreateMultiArray(soa.Self(), element_class, dimensions_array);
return soa.AddLocalReference<jobject>(new_array);
}
@@ -57,16 +56,16 @@
ThrowNegativeArraySizeException(length);
return nullptr;
}
- ObjPtr<mirror::Class> element_class = soa.Decode<mirror::Class>(javaElementClass);
Runtime* runtime = Runtime::Current();
ClassLinker* class_linker = runtime->GetClassLinker();
- ObjPtr<mirror::Class> array_class = class_linker->FindArrayClass(soa.Self(), &element_class);
+ ObjPtr<mirror::Class> array_class =
+ class_linker->FindArrayClass(soa.Self(), soa.Decode<mirror::Class>(javaElementClass));
if (UNLIKELY(array_class == nullptr)) {
CHECK(soa.Self()->IsExceptionPending());
return nullptr;
}
DCHECK(array_class->IsObjectArrayClass());
- ObjPtr<mirror::Array> new_array = mirror::ObjectArray<mirror::Object*>::Alloc(
+ ObjPtr<mirror::Array> new_array = mirror::ObjectArray<mirror::Object>::Alloc(
soa.Self(),
array_class,
length,
diff --git a/runtime/native/java_lang_reflect_Executable.cc b/runtime/native/java_lang_reflect_Executable.cc
index a40cb9b..a10db91 100644
--- a/runtime/native/java_lang_reflect_Executable.cc
+++ b/runtime/native/java_lang_reflect_Executable.cc
@@ -320,7 +320,7 @@
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 2559984..895b2f9 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -464,8 +464,7 @@
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) {
@@ -476,7 +475,7 @@
ObjPtr<mirror::Class> annotation_array_class =
soa.Decode<mirror::Class>(WellKnownClasses::java_lang_annotation_Annotation__array);
ObjPtr<mirror::ObjectArray<mirror::Object>> empty_array =
- mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class.Ptr(), 0);
+ mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0);
return soa.AddLocalReference<jobjectArray>(empty_array);
}
return soa.AddLocalReference<jobjectArray>(annotations::GetAnnotationsForField(field));
diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc
index 34455fe..87fda6b 100644
--- a/runtime/native/java_lang_reflect_Method.cc
+++ b/runtime/native/java_lang_reflect_Method.cc
@@ -69,7 +69,7 @@
// Return an empty array instead of a null pointer
ObjPtr<mirror::Class> class_array_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>();
DCHECK(class_array_class != nullptr);
- mirror::ObjectArray<mirror::Class>* empty_array =
+ ObjPtr<mirror::ObjectArray<mirror::Class>> empty_array =
mirror::ObjectArray<mirror::Class>::Alloc(soa.Self(), class_array_class, 0);
return soa.AddLocalReference<jobjectArray>(empty_array);
} else {
diff --git a/runtime/oat.h b/runtime/oat.h
index e7e5848..72eb27d 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,8 +32,8 @@
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 ffbc26c..2b05b0e 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -1687,6 +1687,7 @@
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(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 @@
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 @@
// 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 8e18cee..d72b6a8 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -514,14 +514,14 @@
// 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 @@
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/reference_table_test.cc b/runtime/reference_table_test.cc
index 06ea384..1d54d21 100644
--- a/runtime/reference_table_test.cc
+++ b/runtime/reference_table_test.cc
@@ -106,7 +106,7 @@
}
// Add a second object 10 times and check dumping is sane.
- mirror::Object* o2 = mirror::ShortArray::Alloc(soa.Self(), 0);
+ ObjPtr<mirror::Object> o2 = mirror::ShortArray::Alloc(soa.Self(), 0);
for (size_t i = 0; i < 10; ++i) {
rt.Add(o2);
EXPECT_EQ(i + 2, rt.Size());
@@ -276,23 +276,26 @@
ReferenceTable rt("test", 0, 20);
{
- mirror::Object* s1 = mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello");
- mirror::Object* s2 = mirror::String::AllocFromModifiedUtf8(soa.Self(), "world");
+ StackHandleScope<1> hs(soa.Self());
+ Handle<mirror::String> s1 =
+ hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello"));
+ ObjPtr<mirror::String> s2 = mirror::String::AllocFromModifiedUtf8(soa.Self(), "world");
// 3 copies of s1, 2 copies of s2, interleaved.
for (size_t i = 0; i != 2; ++i) {
- rt.Add(s1);
+ rt.Add(s1.Get());
rt.Add(s2);
}
- rt.Add(s1);
+ rt.Add(s1.Get());
}
{
- // Differently sized byte arrays. Should be sorted by identical (non-unique cound).
- mirror::Object* b1_1 = mirror::ByteArray::Alloc(soa.Self(), 1);
- rt.Add(b1_1);
+ // 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());
rt.Add(mirror::ByteArray::Alloc(soa.Self(), 2));
- rt.Add(b1_1);
+ rt.Add(b1_1.Get());
rt.Add(mirror::ByteArray::Alloc(soa.Self(), 2));
rt.Add(mirror::ByteArray::Alloc(soa.Self(), 1));
rt.Add(mirror::ByteArray::Alloc(soa.Self(), 2));
diff --git a/runtime/reflection-inl.h b/runtime/reflection-inl.h
index 26fb021..9fe4bca 100644
--- a/runtime/reflection-inl.h
+++ b/runtime/reflection-inl.h
@@ -121,7 +121,7 @@
if (UNLIKELY(o == nullptr)) {
ThrowNullPointerException("null receiver");
return false;
- } else if (UNLIKELY(!o->InstanceOf(c.Ptr()))) {
+ } else if (UNLIKELY(!o->InstanceOf(c))) {
InvalidReceiverError(o, c);
return false;
}
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 66eba1e..6aeedd4 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -243,7 +243,7 @@
// we've seen cases where it's not b/34440020.
ObjPtr<mirror::Class> dst_class(
m->ResolveClassFromTypeIndex(classes->GetTypeItem(args_offset).type_idx_));
- if (dst_class.Ptr() == nullptr) {
+ if (dst_class == nullptr) {
CHECK(self->IsExceptionPending());
return false;
}
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 0d9d16c..1e327fc 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1090,6 +1090,17 @@
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 @@
// 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");
+ 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,
- &Runtime::pre_allocated_NoClassDefFoundError_,
- "Ljava/lang/NoClassDefFoundError;",
- "Class not found using the boot class loader; "
- "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::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 @@
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 10f72e7..d85490c 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -774,11 +774,6 @@
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/thread.cc b/runtime/thread.cc
index b59606a..a8133a1 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -491,7 +491,7 @@
Thread* Thread::FromManagedThread(const ScopedObjectAccessAlreadyRunnable& soa,
jobject java_thread) {
- return FromManagedThread(soa, soa.Decode<mirror::Object>(java_thread).Ptr());
+ return FromManagedThread(soa, soa.Decode<mirror::Object>(java_thread));
}
static size_t FixStackSize(size_t stack_size) {
@@ -2728,7 +2728,7 @@
depth = std::min(depth, traces_length);
} else {
// Create java_trace array and place in local reference table
- mirror::ObjectArray<mirror::StackTraceElement>* java_traces =
+ ObjPtr<mirror::ObjectArray<mirror::StackTraceElement>> java_traces =
class_linker->AllocStackTraceElementArray(soa.Self(), depth);
if (java_traces == nullptr) {
return nullptr;
diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc
index 02e61d7..370a619 100644
--- a/runtime/transaction_test.cc
+++ b/runtime/transaction_test.cc
@@ -506,7 +506,7 @@
class_linker_->LookupString(string_idx, h_dex_cache.Get());
ASSERT_TRUE(s != nullptr);
EXPECT_STREQ(s->ToModifiedUtf8().c_str(), kResolvedString);
- EXPECT_EQ(s.Ptr(), h_dex_cache->GetResolvedString(string_idx));
+ EXPECT_OBJ_PTR_EQ(s, h_dex_cache->GetResolvedString(string_idx));
}
Runtime::Current()->RollbackAndExitTransactionMode();
// Check that the string did not stay resolved.
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc
index 838d7f1..32aa86d 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 @@
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 2e3a659..5961748 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 @@
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,80 +203,6 @@
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);
-
- MethodVerifier::FailureData failure_data;
-
- int64_t previous_method_idx = -1;
- while (HasNextMethod<kDirect>(it)) {
- self->AllowThreadSuspension();
- uint32_t method_idx = it->GetMemberIndex();
- if (method_idx == previous_method_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>(
- method_idx, dex_cache, class_loader, /* referrer */ nullptr, type);
- if (method == nullptr) {
- DCHECK(self->IsExceptionPending());
- // We couldn't resolve the method, but continue regardless.
- self->ClearException();
- } else {
- DCHECK(method->GetDeclaringClassUnchecked() != nullptr) << type;
- }
- StackHandleScope<1> hs(self);
- std::string hard_failure_msg;
- MethodVerifier::FailureData result = VerifyMethod(self,
- method_idx,
- dex_file,
- dex_cache,
- class_loader,
- class_def,
- it->GetMethodCodeItem(),
- method,
- it->GetMethodAccessFlags(),
- callbacks,
- allow_soft_failures,
- log_level,
- need_precise_constants,
- &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";
- } 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_string += " ";
- *error_string += 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,
@@ -300,52 +222,72 @@
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;
+ ClassAccessor accessor(*dex_file, class_def);
+
+ int64_t previous_method_idx[2] = { -1, -1 };
+ MethodVerifier::FailureData failure_data;
+ ClassLinker* const linker = Runtime::Current()->GetClassLinker();
+
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+ int64_t* previous_idx = &previous_method_idx[method.IsStaticOrDirect() ? 0u : 1u];
+ self->AllowThreadSuspension();
+ 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
+ continue;
+ }
+ *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 (resolved_method == nullptr) {
+ DCHECK(self->IsExceptionPending());
+ // We couldn't resolve the method, but continue regardless.
+ self->ClearException();
+ } else {
+ DCHECK(resolved_method->GetDeclaringClassUnchecked() != nullptr) << type;
+ }
+ std::string hard_failure_msg;
+ MethodVerifier::FailureData result = VerifyMethod(self,
+ method_idx,
+ dex_file,
+ dex_cache,
+ class_loader,
+ class_def,
+ method.GetCodeItem(),
+ resolved_method,
+ method.GetAccessFlags(),
+ callbacks,
+ allow_soft_failures,
+ log_level,
+ /*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 += "\n";
+ } else {
+ // If we didn't log a hard failure before, print the header of the message.
+ *error += "Verifier rejected class ";
+ *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+ *error += ":";
+ }
+ *error += " ";
+ *error += hard_failure_msg;
+ }
+ failure_data.Merge(result);
}
- 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 @@
}
LOG(WARNING) << tmp;
}
- return data1.kind;
+ return failure_data.kind;
}
}
@@ -1924,15 +1866,11 @@
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();
+ ClassAccessor accessor(dex_file, *class_def);
+ for (const ClassAccessor::Field& field : accessor.GetInstanceFields()) {
+ if (field.IsFinal()) {
+ return field.GetIndex();
}
- it.Next();
}
return dex::kDexNoIndex;
}
@@ -2932,7 +2870,7 @@
: called_method->LookupResolvedReturnType();
if (return_type_class != nullptr) {
return_type = &FromClass(return_type_descriptor,
- return_type_class.Ptr(),
+ return_type_class,
return_type_class->CannotBeAssignedFromOtherTypes());
} else {
DCHECK(!can_load_classes_ || self_->IsExceptionPending());
@@ -3685,7 +3623,7 @@
}
// Record result of class resolution attempt.
- VerifierDeps::MaybeRecordClassResolution(*dex_file_, class_idx, klass.Ptr());
+ VerifierDeps::MaybeRecordClassResolution(*dex_file_, class_idx, klass);
// If requested, check if access is allowed. Unresolved types are included in this check, as the
// interpreter only tests whether access is allowed when a class is not pre-verified and runs in
@@ -4628,9 +4566,7 @@
std::string temp;
ObjPtr<mirror::Class> klass = field->GetDeclaringClass();
const RegType& field_klass =
- FromClass(klass->GetDescriptor(&temp),
- klass.Ptr(),
- klass->CannotBeAssignedFromOtherTypes());
+ FromClass(klass->GetDescriptor(&temp), klass, klass->CannotBeAssignedFromOtherTypes());
if (obj_type.IsUninitializedTypes()) {
// Field accesses through uninitialized references are only allowable for constructors where
// the field is declared in this class.
@@ -4731,7 +4667,7 @@
can_load_classes_ ? field->ResolveType() : field->LookupResolvedType();
if (field_type_class != nullptr) {
field_type = &FromClass(field->GetTypeDescriptor(),
- field_type_class.Ptr(),
+ field_type_class,
field_type_class->CannotBeAssignedFromOtherTypes());
} else {
DCHECK(!can_load_classes_ || self_->IsExceptionPending());
@@ -4919,7 +4855,7 @@
: method_being_verified_->LookupResolvedReturnType();
if (return_type_class != nullptr) {
return_type_ = &FromClass(method_being_verified_->GetReturnTypeDescriptor(),
- return_type_class.Ptr(),
+ return_type_class,
return_type_class->CannotBeAssignedFromOtherTypes());
} else {
DCHECK(!can_load_classes_ || self_->IsExceptionPending());
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index ae7481c..9890af9 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -275,23 +275,6 @@
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/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index 73e516c..4a3f9e6 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -807,7 +807,7 @@
}
// Note: The following lookup invalidates existing ObjPtr<>s.
ObjPtr<mirror::Class> array_class =
- Runtime::Current()->GetClassLinker()->FindArrayClass(self, &common_elem);
+ Runtime::Current()->GetClassLinker()->FindArrayClass(self, common_elem);
if (UNLIKELY(array_class == nullptr)) {
self->AssertPendingException();
return nullptr;
diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc
index 500cc37..fb91976 100644
--- a/runtime/verifier/verifier_deps.cc
+++ b/runtime/verifier/verifier_deps.cc
@@ -384,7 +384,7 @@
// Find a boundary making `source` inherit from `destination`. We must find one.
for (const ObjPtr<mirror::Class>& boundary : boundaries) {
if (destination->IsAssignableFrom(boundary)) {
- return boundary.Ptr();
+ return boundary;
}
}
LOG(FATAL) << "Should have found a classpath boundary";
diff --git a/test/497-inlining-and-class-loader/clear_dex_cache.cc b/test/497-inlining-and-class-loader/clear_dex_cache.cc
index c113042..c6fd56f 100644
--- a/test/497-inlining-and-class-loader/clear_dex_cache.cc
+++ b/test/497-inlining-and-class-loader/clear_dex_cache.cc
@@ -52,11 +52,11 @@
uint32_t index = pair.index;
ArtMethod* method = pair.object;
if (sizeof(void*) == 4) {
- ObjPtr<mirror::IntArray> int_array = down_cast<mirror::IntArray*>(decoded_array.Ptr());
+ ObjPtr<mirror::IntArray> int_array = ObjPtr<mirror::IntArray>::DownCast(decoded_array);
int_array->Set(2u * i, index);
int_array->Set(2u * i + 1u, static_cast<jint>(reinterpret_cast<uintptr_t>(method)));
} else {
- ObjPtr<mirror::LongArray> long_array = down_cast<mirror::LongArray*>(decoded_array.Ptr());
+ ObjPtr<mirror::LongArray> long_array = ObjPtr<mirror::LongArray>::DownCast(decoded_array);
long_array->Set(2u * i, index);
long_array->Set(2u * i + 1u, reinterpret_cast64<jlong>(method));
}
diff --git a/test/911-get-stack-trace/check b/test/911-get-stack-trace/check
deleted file mode 100644
index ee00266..0000000
--- 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 8177f49..b0a400a 100644
--- a/test/911-get-stack-trace/expected.txt
+++ b/test/911-get-stack-trace/expected.txt
@@ -9,19 +9,19 @@
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 @@
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 @@
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 @@
---------
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 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 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 @@
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 @@
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 @@
<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 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 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 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 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 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 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 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 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 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 @@
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 @@
<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 @@
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 @@
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 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 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 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 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 @@
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 @@
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 @@
################################
### 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 @@
###########################
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 c12015a..0000000
--- 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 d73f78b..507925c 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 @@
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 675bff5..3f5ae59 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 @@
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 0de93de..9b27e72 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 @@
printList(list, 0);
- printList(list, 5);
+ printList(list, 7);
printList(list, 25);
diff --git a/tools/dexanalyze/dexanalyze.cc b/tools/dexanalyze/dexanalyze.cc
index 7d7e5f2..7a9b8fb 100644
--- a/tools/dexanalyze/dexanalyze.cc
+++ b/tools/dexanalyze/dexanalyze.cc
@@ -116,12 +116,14 @@
}
}
- 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 @@
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 1a3b89c..244f45b 100644
--- a/tools/dexanalyze/dexanalyze_experiments.cc
+++ b/tools/dexanalyze/dexanalyze_experiments.cc
@@ -75,86 +75,95 @@
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 a2621c8..2be53d6 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 @@
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 @@
// 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 @@
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);