diff options
97 files changed, 1416 insertions, 1789 deletions
diff --git a/adbconnection/adbconnection.cc b/adbconnection/adbconnection.cc index 8cd0d8bc9f..ad941481fd 100644 --- a/adbconnection/adbconnection.cc +++ b/adbconnection/adbconnection.cc @@ -489,7 +489,7 @@ bool AdbConnectionState::SetupAdbConnection() { int sleep_ms = 500; const int sleep_max_ms = 2*1000; - android::base::unique_fd sock(socket(AF_UNIX, SOCK_SEQPACKET, 0)); + android::base::unique_fd sock(socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0)); if (sock < 0) { PLOG(ERROR) << "Could not create ADB control socket"; return false; @@ -872,7 +872,7 @@ std::string AdbConnectionState::MakeAgentArg() { (ContainsArgument(opts, "server=y") ? "" : "server=y,") + // See the comment above for why we need to be suspend=n. Since the agent defaults to // suspend=y we will add it if it wasn't already present. - (ContainsArgument(opts, "suspend=n") ? "" : "suspend=n") + + (ContainsArgument(opts, "suspend=n") ? "" : "suspend=n,") + "transport=dt_fd_forward,address=" + std::to_string(remote_agent_control_sock_); } diff --git a/compiler/dex/dex_to_dex_decompiler_test.cc b/compiler/dex/dex_to_dex_decompiler_test.cc index 75de238211..1fe42ad531 100644 --- a/compiler/dex/dex_to_dex_decompiler_test.cc +++ b/compiler/dex/dex_to_dex_decompiler_test.cc @@ -67,7 +67,7 @@ class DexToDexDecompilerTest : public CommonCompilerTest { 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 028de34e96..dc0709013c 100644 --- a/dex2oat/linker/image_writer.cc +++ b/dex2oat/linker/image_writer.cc @@ -1342,6 +1342,14 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots(size_t oat_index) const { ObjectArray<Object>::Alloc(self, object_array_class.Get(), image_roots_size))); image_roots->Set<false>(ImageHeader::kDexCaches, dex_caches.Get()); image_roots->Set<false>(ImageHeader::kClassRoots, class_linker->GetClassRoots()); + image_roots->Set<false>(ImageHeader::kOomeWhenThrowingException, + runtime->GetPreAllocatedOutOfMemoryErrorWhenThrowingException()); + image_roots->Set<false>(ImageHeader::kOomeWhenThrowingOome, + runtime->GetPreAllocatedOutOfMemoryErrorWhenThrowingOOME()); + image_roots->Set<false>(ImageHeader::kOomeWhenHandlingStackOverflow, + runtime->GetPreAllocatedOutOfMemoryErrorWhenHandlingStackOverflow()); + image_roots->Set<false>(ImageHeader::kNoClassDefFoundError, + runtime->GetPreAllocatedNoClassDefFoundError()); // image_roots[ImageHeader::kClassLoader] will be set later for app image. static_assert(ImageHeader::kClassLoader + 1u == ImageHeader::kImageRootsMax, "Class loader should be the last image root."); diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc index 4046dc101f..99516684e8 100644 --- a/dex2oat/linker/oat_writer.cc +++ b/dex2oat/linker/oat_writer.cc @@ -4032,13 +4032,13 @@ bool OatWriter::WriteTypeLookupTables( // TypeLookupTable allocates its own and OatDexFile takes ownership. const DexFile& dex_file = *opened_dex_files[i]; { - std::unique_ptr<TypeLookupTable> type_lookup_table = - TypeLookupTable::Create(dex_file, /* storage */ nullptr); + TypeLookupTable type_lookup_table = TypeLookupTable::Create(dex_file); type_lookup_table_oat_dex_files_.push_back( std::make_unique<art::OatDexFile>(std::move(type_lookup_table))); dex_file.SetOatDexFile(type_lookup_table_oat_dex_files_.back().get()); } - TypeLookupTable* const table = type_lookup_table_oat_dex_files_.back()->GetTypeLookupTable(); + const TypeLookupTable& table = type_lookup_table_oat_dex_files_.back()->GetTypeLookupTable(); + DCHECK(table.Valid()); // Type tables are required to be 4 byte aligned. size_t initial_offset = oat_size_; @@ -4057,9 +4057,9 @@ bool OatWriter::WriteTypeLookupTables( DCHECK_EQ(oat_data_offset_ + rodata_offset, static_cast<size_t>(oat_rodata->Seek(0u, kSeekCurrent))); - DCHECK_EQ(table_size, table->RawDataLength()); + DCHECK_EQ(table_size, table.RawDataLength()); - if (!oat_rodata->WriteFully(table->RawData(), table_size)) { + if (!oat_rodata->WriteFully(table.RawData(), table_size)) { PLOG(ERROR) << "Failed to write lookup table." << " File: " << oat_dex_file->GetLocation() << " Output: " << oat_rodata->GetLocation(); diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc index 0694c4ff9f..d0a6eb9ff2 100644 --- a/dex2oat/linker/oat_writer_test.cc +++ b/dex2oat/linker/oat_writer_test.cc @@ -545,8 +545,7 @@ TEST_F(OatTest, EmptyTextSection) { 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 49ca98d47f..3bb9e93e5a 100644 --- a/libdexfile/dex/class_accessor-inl.h +++ b/libdexfile/dex/class_accessor-inl.h @@ -37,30 +37,26 @@ inline ClassAccessor::ClassAccessor(const DexFile& dex_file, const DexFile::Clas num_direct_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u), num_virtual_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u) {} -inline const uint8_t* ClassAccessor::Method::Read(const uint8_t* ptr) { - index_ += DecodeUnsignedLeb128(&ptr); - access_flags_ = DecodeUnsignedLeb128(&ptr); - code_off_ = DecodeUnsignedLeb128(&ptr); - return ptr; +inline void ClassAccessor::Method::Read() { + index_ += DecodeUnsignedLeb128(&ptr_pos_); + access_flags_ = DecodeUnsignedLeb128(&ptr_pos_); + code_off_ = DecodeUnsignedLeb128(&ptr_pos_); } -inline const uint8_t* ClassAccessor::Field::Read(const uint8_t* ptr) { - index_ += DecodeUnsignedLeb128(&ptr); - access_flags_ = DecodeUnsignedLeb128(&ptr); - return ptr; +inline void ClassAccessor::Field::Read() { + index_ += DecodeUnsignedLeb128(&ptr_pos_); + access_flags_ = DecodeUnsignedLeb128(&ptr_pos_); } template <typename DataType, typename Visitor> -inline const uint8_t* ClassAccessor::VisitMembers(size_t count, - const Visitor& visitor, - const uint8_t* ptr, - DataType* data) const { +inline void ClassAccessor::VisitMembers(size_t count, + const Visitor& visitor, + DataType* data) const { DCHECK(data != nullptr); for ( ; count != 0; --count) { - ptr = data->Read(ptr); + data->Read(); visitor(*data); } - return ptr; } template <typename StaticFieldVisitor, @@ -72,15 +68,15 @@ inline void ClassAccessor::VisitFieldsAndMethods( const InstanceFieldVisitor& instance_field_visitor, const DirectMethodVisitor& direct_method_visitor, const VirtualMethodVisitor& virtual_method_visitor) const { - Field field(dex_file_); - const uint8_t* ptr = VisitMembers(num_static_fields_, static_field_visitor, ptr_pos_, &field); + Field field(dex_file_, ptr_pos_); + VisitMembers(num_static_fields_, static_field_visitor, &field); field.NextSection(); - ptr = VisitMembers(num_instance_fields_, instance_field_visitor, ptr, &field); + VisitMembers(num_instance_fields_, instance_field_visitor, &field); - Method method(dex_file_, /*is_static_or_direct*/ true); - ptr = VisitMembers(num_direct_methods_, direct_method_visitor, ptr, &method); + Method method(dex_file_, field.ptr_pos_, /*is_static_or_direct*/ true); + VisitMembers(num_direct_methods_, direct_method_visitor, &method); method.NextSection(); - ptr = VisitMembers(num_virtual_methods_, virtual_method_visitor, ptr, &method); + VisitMembers(num_virtual_methods_, virtual_method_visitor, &method); } template <typename DirectMethodVisitor, @@ -119,23 +115,64 @@ inline const DexFile::CodeItem* ClassAccessor::Method::GetCodeItem() const { return dex_file_.GetCodeItem(code_off_); } +inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> + ClassAccessor::GetFieldsInternal(size_t count) const { + return { DataIterator<Field>(dex_file_, 0u, num_static_fields_, count, ptr_pos_), + DataIterator<Field>(dex_file_, count, num_static_fields_, count, ptr_pos_) }; +} + +// Return an iteration range for the first <count> methods. +inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>> + ClassAccessor::GetMethodsInternal(size_t count) const { + // Skip over the fields. + Field field(dex_file_, ptr_pos_); + VisitMembers(NumFields(), VoidFunctor(), &field); + // Return the iterator pair. + return { DataIterator<Method>(dex_file_, 0u, num_direct_methods_, count, field.ptr_pos_), + DataIterator<Method>(dex_file_, count, num_direct_methods_, count, field.ptr_pos_) }; +} + inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> ClassAccessor::GetFields() const { - const uint32_t limit = num_static_fields_ + num_instance_fields_; - return { DataIterator<Field>(dex_file_, 0u, num_static_fields_, limit, ptr_pos_), - DataIterator<Field>(dex_file_, limit, num_static_fields_, limit, ptr_pos_) }; + return GetFieldsInternal(num_static_fields_ + num_instance_fields_); +} + +inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> + ClassAccessor::GetStaticFields() const { + return GetFieldsInternal(num_static_fields_); +} + + +inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> + ClassAccessor::GetInstanceFields() const { + IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> fields = GetFields(); + // Skip the static fields. + return { std::next(fields.begin(), NumStaticFields()), fields.end() }; } inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>> ClassAccessor::GetMethods() const { - // Skip over the fields. - Field field(dex_file_); - const size_t skip_count = num_static_fields_ + num_instance_fields_; - const uint8_t* ptr_pos = VisitMembers(skip_count, VoidFunctor(), ptr_pos_, &field); - // Return the iterator pair for all the methods. - const uint32_t limit = num_direct_methods_ + num_virtual_methods_; - return { DataIterator<Method>(dex_file_, 0u, num_direct_methods_, limit, ptr_pos), - DataIterator<Method>(dex_file_, limit, num_direct_methods_, limit, ptr_pos) }; + return GetMethodsInternal(NumMethods()); +} + +inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>> + ClassAccessor::GetDirectMethods() const { + return GetMethodsInternal(NumDirectMethods()); +} + +inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>> + ClassAccessor::GetVirtualMethods() const { + IterationRange<DataIterator<Method>> methods = GetMethods(); + // Skip the direct fields. + return { std::next(methods.begin(), NumDirectMethods()), methods.end() }; +} + +inline void ClassAccessor::Field::UnHideAccessFlags() const { + DexFile::UnHideAccessFlags(const_cast<uint8_t*>(ptr_pos_), GetAccessFlags(), /*is_method*/ false); +} + +inline void ClassAccessor::Method::UnHideAccessFlags() const { + DexFile::UnHideAccessFlags(const_cast<uint8_t*>(ptr_pos_), GetAccessFlags(), /*is_method*/ true); } } // namespace art diff --git a/libdexfile/dex/class_accessor.h b/libdexfile/dex/class_accessor.h index dda6e1c1a6..4f0fd32e31 100644 --- a/libdexfile/dex/class_accessor.h +++ b/libdexfile/dex/class_accessor.h @@ -20,6 +20,7 @@ #include "base/utils.h" #include "code_item_accessors.h" #include "dex_file.h" +#include "hidden_api_access_flags.h" #include "invoke_type.h" #include "method_reference.h" #include "modifiers.h" @@ -33,12 +34,18 @@ class ClassAccessor { private: class BaseItem { public: + explicit BaseItem(const uint8_t* ptr_pos) : ptr_pos_(ptr_pos) {} + uint32_t GetIndex() const { return index_; } uint32_t GetAccessFlags() const { - return access_flags_; + return HiddenApiAccessFlags::RemoveFromDex(access_flags_); + } + + HiddenApiAccessFlags::ApiList DecodeHiddenAccessFlags() const { + return HiddenApiAccessFlags::DecodeFromDex(access_flags_); } bool IsFinal() const { @@ -46,6 +53,8 @@ class ClassAccessor { } protected: + // Internal data pointer for reading. + const uint8_t* ptr_pos_ = nullptr; uint32_t index_ = 0u; uint32_t access_flags_ = 0u; }; @@ -76,13 +85,18 @@ class ClassAccessor { return is_static_or_direct_; } + // Unhide the hidden API access flags at the iterator position. TODO: Deprecate. + void UnHideAccessFlags() const; + private: explicit Method(const DexFile& dex_file, + const uint8_t* ptr_pos, bool is_static_or_direct = true) - : dex_file_(dex_file), + : BaseItem(ptr_pos), + dex_file_(dex_file), is_static_or_direct_(is_static_or_direct) {} - const uint8_t* Read(const uint8_t* ptr); + void Read(); InvokeType GetDirectMethodInvokeType() const { return (GetAccessFlags() & kAccStatic) != 0 ? kStatic : kDirect; @@ -99,6 +113,7 @@ class ClassAccessor { } } + // Move to virtual method section. void NextSection() { DCHECK(is_static_or_direct_) << "Already in the virtual methods section"; is_static_or_direct_ = false; @@ -115,20 +130,31 @@ class ClassAccessor { // A decoded version of the field of a class_data_item. class Field : public BaseItem { public: - explicit Field(const DexFile& dex_file) : dex_file_(dex_file) {} + explicit Field(const DexFile& dex_file, + const uint8_t* ptr_pos) : BaseItem(ptr_pos), dex_file_(dex_file) {} const DexFile& GetDexFile() const { return dex_file_; } + bool IsStatic() const { + return is_static_; + } + + // Unhide the hidden API access flags at the iterator position. TODO: Deprecate. + void UnHideAccessFlags() const; + private: - const uint8_t* Read(const uint8_t* ptr); + void Read(); + // Move to instance fields section. void NextSection() { index_ = 0u; + is_static_ = false; } const DexFile& dex_file_; + bool is_static_ = true; friend class ClassAccessor; }; @@ -144,11 +170,10 @@ class ClassAccessor { uint32_t partition_pos, uint32_t iterator_end, const uint8_t* ptr_pos) - : data_(dex_file), + : data_(dex_file, ptr_pos), position_(position), partition_pos_(partition_pos), - iterator_end_(iterator_end), - ptr_pos_(ptr_pos) { + iterator_end_(iterator_end) { ReadData(); } @@ -205,8 +230,7 @@ class ClassAccessor { if (position_ == partition_pos_) { data_.NextSection(); } - DCHECK(ptr_pos_ != nullptr); - ptr_pos_ = data_.Read(ptr_pos_); + data_.Read(); } } @@ -217,8 +241,6 @@ class ClassAccessor { const uint32_t partition_pos_; // At iterator_end_, the iterator is no longer valid. const uint32_t iterator_end_; - // Internal data pointer. - const uint8_t* ptr_pos_; }; // Not explicit specifically for range-based loops. @@ -252,9 +274,21 @@ class ClassAccessor { // Return the iteration range for all the fields. IterationRange<DataIterator<Field>> GetFields() const; + // Return the iteration range for all the static fields. + IterationRange<DataIterator<Field>> GetStaticFields() const; + + // Return the iteration range for all the instance fields. + IterationRange<DataIterator<Field>> GetInstanceFields() const; + // Return the iteration range for all the methods. IterationRange<DataIterator<Method>> GetMethods() const; + // Return the iteration range for the direct methods. + IterationRange<DataIterator<Method>> GetDirectMethods() const; + + // Return the iteration range for the virtual methods. + IterationRange<DataIterator<Method>> GetVirtualMethods() const; + uint32_t NumStaticFields() const { return num_static_fields_; } @@ -263,6 +297,10 @@ class ClassAccessor { return num_instance_fields_; } + uint32_t NumFields() const { + return NumStaticFields() + NumInstanceFields(); + } + uint32_t NumDirectMethods() const { return num_direct_methods_; } @@ -285,14 +323,22 @@ class ClassAccessor { return dex_file_; } + bool HasClassData() const { + return ptr_pos_ != nullptr; + } + protected: // Template visitor to reduce copy paste for visiting elements. // No thread safety analysis since the visitor may require capabilities. template <typename DataType, typename Visitor> - const uint8_t* VisitMembers(size_t count, - const Visitor& visitor, - const uint8_t* ptr, - DataType* data) const NO_THREAD_SAFETY_ANALYSIS; + void VisitMembers(size_t count, const Visitor& visitor, DataType* data) const + NO_THREAD_SAFETY_ANALYSIS; + + // Return an iteration range for the first <count> fields. + IterationRange<DataIterator<Field>> GetFieldsInternal(size_t count) const; + + // Return an iteration range for the first <count> methods. + IterationRange<DataIterator<Method>> GetMethodsInternal(size_t count) const; const DexFile& dex_file_; const dex::TypeIndex descriptor_index_ = {}; diff --git a/libdexfile/dex/class_accessor_test.cc b/libdexfile/dex/class_accessor_test.cc index 95380d8140..d0533c1811 100644 --- a/libdexfile/dex/class_accessor_test.cc +++ b/libdexfile/dex/class_accessor_test.cc @@ -38,18 +38,27 @@ TEST_F(ClassAccessorTest, TestVisiting) { auto fields = accessor.GetFields(); auto method_it = methods.begin(); auto field_it = fields.begin(); + auto instance_fields = accessor.GetInstanceFields(); + auto instance_field_it = instance_fields.begin(); accessor.VisitFieldsAndMethods( // Static fields. [&](const ClassAccessor::Field& field) { + EXPECT_TRUE(field.IsStatic()); + EXPECT_TRUE(field_it->IsStatic()); EXPECT_EQ(field.GetIndex(), field_it->GetIndex()); EXPECT_EQ(field.GetAccessFlags(), field_it->GetAccessFlags()); ++field_it; }, // Instance fields. [&](const ClassAccessor::Field& field) { + EXPECT_FALSE(field.IsStatic()); + EXPECT_FALSE(field_it->IsStatic()); EXPECT_EQ(field.GetIndex(), field_it->GetIndex()); EXPECT_EQ(field.GetAccessFlags(), field_it->GetAccessFlags()); + EXPECT_EQ(field.GetIndex(), instance_field_it->GetIndex()); + EXPECT_EQ(field.GetAccessFlags(), instance_field_it->GetAccessFlags()); ++field_it; + ++instance_field_it; }, // Direct methods. [&](const ClassAccessor::Method& method) { @@ -71,6 +80,7 @@ TEST_F(ClassAccessorTest, TestVisiting) { }); ASSERT_TRUE(field_it == fields.end()); ASSERT_TRUE(method_it == methods.end()); + ASSERT_TRUE(instance_field_it == instance_fields.end()); } EXPECT_EQ(class_def_idx, dex_file->NumClassDefs()); } diff --git a/libdexfile/dex/dex_file.cc b/libdexfile/dex/dex_file.cc index 9de260c862..f570158dfb 100644 --- a/libdexfile/dex/dex_file.cc +++ b/libdexfile/dex/dex_file.cc @@ -45,19 +45,18 @@ static_assert(std::is_trivially_copyable<dex::StringIndex>::value, "StringIndex static_assert(sizeof(dex::TypeIndex) == sizeof(uint16_t), "TypeIndex size is wrong"); static_assert(std::is_trivially_copyable<dex::TypeIndex>::value, "TypeIndex not trivial"); -void DexFile::UnHideAccessFlags(ClassDataItemIterator& class_it) { - uint8_t* data = const_cast<uint8_t*>(class_it.DataPointer()); - uint32_t new_flag = class_it.GetMemberAccessFlags(); - bool is_method = class_it.IsAtMethod(); +void DexFile::UnHideAccessFlags(uint8_t* data_ptr, + uint32_t new_access_flags, + bool is_method) { // Go back 1 uleb to start. - data = ReverseSearchUnsignedLeb128(data); + data_ptr = ReverseSearchUnsignedLeb128(data_ptr); if (is_method) { // Methods have another uleb field before the access flags - data = ReverseSearchUnsignedLeb128(data); + data_ptr = ReverseSearchUnsignedLeb128(data_ptr); } - DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data)), - new_flag); - UpdateUnsignedLeb128(data, new_flag); + DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data_ptr)), + new_access_flags); + UpdateUnsignedLeb128(data_ptr, new_access_flags); } uint32_t DexFile::CalculateChecksum() const { diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h index f1f8b505bd..ed219808d2 100644 --- a/libdexfile/dex/dex_file.h +++ b/libdexfile/dex/dex_file.h @@ -1010,8 +1010,8 @@ class DexFile { return container_.get(); } - // Changes the dex file pointed to by class_it to not have any hiddenapi flags. - static void UnHideAccessFlags(ClassDataItemIterator& class_it); + // Changes the dex class data pointed to by data_ptr it to not have any hiddenapi flags. + static void UnHideAccessFlags(uint8_t* data_ptr, uint32_t new_access_flags, bool is_method); inline IterationRange<ClassIterator> GetClasses() const; diff --git a/libdexfile/dex/type_lookup_table.cc b/libdexfile/dex/type_lookup_table.cc index ca5ec2f798..00ec358b02 100644 --- a/libdexfile/dex/type_lookup_table.cc +++ b/libdexfile/dex/type_lookup_table.cc @@ -20,72 +20,43 @@ #include <memory> #include "base/bit_utils.h" +#include "base/leb128.h" #include "dex/dex_file-inl.h" #include "dex/utf-inl.h" namespace art { -static uint16_t MakeData(uint16_t class_def_idx, uint32_t hash, uint32_t mask) { - uint16_t hash_mask = static_cast<uint16_t>(~mask); - return (static_cast<uint16_t>(hash) & hash_mask) | class_def_idx; +static inline bool ModifiedUtf8StringEquals(const char* lhs, const char* rhs) { + return CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(lhs, rhs) == 0; } -TypeLookupTable::~TypeLookupTable() { - if (!owns_entries_) { - // We don't actually own the entries, don't let the unique_ptr release them. - entries_.release(); +TypeLookupTable TypeLookupTable::Create(const DexFile& dex_file) { + uint32_t num_class_defs = dex_file.NumClassDefs(); + if (UNLIKELY(!SupportedSize(num_class_defs))) { + return TypeLookupTable(); } -} - -uint32_t TypeLookupTable::RawDataLength(uint32_t num_class_defs) { - return SupportedSize(num_class_defs) ? RoundUpToPowerOfTwo(num_class_defs) * sizeof(Entry) : 0u; -} - -uint32_t TypeLookupTable::CalculateMask(uint32_t num_class_defs) { - return SupportedSize(num_class_defs) ? RoundUpToPowerOfTwo(num_class_defs) - 1u : 0u; -} - -bool TypeLookupTable::SupportedSize(uint32_t num_class_defs) { - return num_class_defs != 0u && num_class_defs <= std::numeric_limits<uint16_t>::max(); -} - -std::unique_ptr<TypeLookupTable> TypeLookupTable::Create(const DexFile& dex_file, - uint8_t* storage) { - const uint32_t num_class_defs = dex_file.NumClassDefs(); - return std::unique_ptr<TypeLookupTable>(SupportedSize(num_class_defs) - ? new TypeLookupTable(dex_file, storage) - : nullptr); -} - -std::unique_ptr<TypeLookupTable> TypeLookupTable::Open(const uint8_t* dex_file_pointer, - const uint8_t* raw_data, - uint32_t num_class_defs) { - return std::unique_ptr<TypeLookupTable>( - new TypeLookupTable(dex_file_pointer, raw_data, num_class_defs)); -} + size_t mask_bits = CalculateMaskBits(num_class_defs); + size_t size = 1u << mask_bits; + std::unique_ptr<Entry[]> owned_entries(new Entry[size]); + Entry* entries = owned_entries.get(); -TypeLookupTable::TypeLookupTable(const DexFile& dex_file, uint8_t* storage) - : dex_data_begin_(dex_file.DataBegin()), - raw_data_length_(RawDataLength(dex_file.NumClassDefs())), - mask_(CalculateMask(dex_file.NumClassDefs())), - entries_(storage != nullptr ? reinterpret_cast<Entry*>(storage) : new Entry[mask_ + 1]), - owns_entries_(storage == nullptr) { static_assert(alignof(Entry) == 4u, "Expecting Entry to be 4-byte aligned."); - DCHECK_ALIGNED(storage, alignof(Entry)); + const uint32_t mask = Entry::GetMask(mask_bits); std::vector<uint16_t> conflict_class_defs; // The first stage. Put elements on their initial positions. If an initial position is already // occupied then delay the insertion of the element to the second stage to reduce probing // distance. - for (size_t i = 0; i < dex_file.NumClassDefs(); ++i) { - const DexFile::ClassDef& class_def = dex_file.GetClassDef(i); + for (size_t class_def_idx = 0; class_def_idx < dex_file.NumClassDefs(); ++class_def_idx) { + const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_idx); const DexFile::TypeId& type_id = dex_file.GetTypeId(class_def.class_idx_); const DexFile::StringId& str_id = dex_file.GetStringId(type_id.descriptor_idx_); const uint32_t hash = ComputeModifiedUtf8Hash(dex_file.GetStringData(str_id)); - Entry entry; - entry.str_offset = str_id.string_data_off_; - entry.data = MakeData(i, hash, GetSizeMask()); - if (!SetOnInitialPos(entry, hash)) { - conflict_class_defs.push_back(i); + const uint32_t pos = hash & mask; + if (entries[pos].IsEmpty()) { + entries[pos] = Entry(str_id.string_data_off_, hash, class_def_idx, mask_bits); + DCHECK(entries[pos].IsLast(mask_bits)); + } else { + conflict_class_defs.push_back(class_def_idx); } } // The second stage. The initial position of these elements had a collision. Put these elements @@ -95,51 +66,111 @@ TypeLookupTable::TypeLookupTable(const DexFile& dex_file, uint8_t* storage) const DexFile::TypeId& type_id = dex_file.GetTypeId(class_def.class_idx_); const DexFile::StringId& str_id = dex_file.GetStringId(type_id.descriptor_idx_); const uint32_t hash = ComputeModifiedUtf8Hash(dex_file.GetStringData(str_id)); - Entry entry; - entry.str_offset = str_id.string_data_off_; - entry.data = MakeData(class_def_idx, hash, GetSizeMask()); - Insert(entry, hash); + // Find the last entry in the chain. + uint32_t tail_pos = hash & mask; + DCHECK(!entries[tail_pos].IsEmpty()); + while (!entries[tail_pos].IsLast(mask_bits)) { + tail_pos = (tail_pos + entries[tail_pos].GetNextPosDelta(mask_bits)) & mask; + DCHECK(!entries[tail_pos].IsEmpty()); + } + // Find an empty entry for insertion. + uint32_t insert_pos = tail_pos; + do { + insert_pos = (insert_pos + 1) & mask; + } while (!entries[insert_pos].IsEmpty()); + // Insert and chain the new entry. + entries[insert_pos] = Entry(str_id.string_data_off_, hash, class_def_idx, mask_bits); + entries[tail_pos].SetNextPosDelta((insert_pos - tail_pos) & mask, mask_bits); + DCHECK(entries[insert_pos].IsLast(mask_bits)); + DCHECK(!entries[tail_pos].IsLast(mask_bits)); } -} -TypeLookupTable::TypeLookupTable(const uint8_t* dex_file_pointer, - const uint8_t* raw_data, - uint32_t num_class_defs) - : dex_data_begin_(dex_file_pointer), - raw_data_length_(RawDataLength(num_class_defs)), - mask_(CalculateMask(num_class_defs)), - entries_(reinterpret_cast<Entry*>(const_cast<uint8_t*>(raw_data))), - owns_entries_(false) {} - -bool TypeLookupTable::SetOnInitialPos(const Entry& entry, uint32_t hash) { - const uint32_t pos = hash & GetSizeMask(); - if (!entries_[pos].IsEmpty()) { - return false; - } - entries_[pos] = entry; - entries_[pos].next_pos_delta = 0; - return true; + return TypeLookupTable(dex_file.DataBegin(), mask_bits, entries, std::move(owned_entries)); } -void TypeLookupTable::Insert(const Entry& entry, uint32_t hash) { - uint32_t pos = FindLastEntryInBucket(hash & GetSizeMask()); - uint32_t next_pos = (pos + 1) & GetSizeMask(); - while (!entries_[next_pos].IsEmpty()) { - next_pos = (next_pos + 1) & GetSizeMask(); - } - const uint32_t delta = (next_pos >= pos) ? (next_pos - pos) : (next_pos + Size() - pos); - entries_[pos].next_pos_delta = delta; - entries_[next_pos] = entry; - entries_[next_pos].next_pos_delta = 0; +TypeLookupTable TypeLookupTable::Open(const uint8_t* dex_data_pointer, + const uint8_t* raw_data, + uint32_t num_class_defs) { + DCHECK_ALIGNED(raw_data, alignof(Entry)); + const Entry* entries = reinterpret_cast<const Entry*>(raw_data); + size_t mask_bits = CalculateMaskBits(num_class_defs); + return TypeLookupTable(dex_data_pointer, mask_bits, entries, /* owned_entries */ nullptr); } -uint32_t TypeLookupTable::FindLastEntryInBucket(uint32_t pos) const { +uint32_t TypeLookupTable::Lookup(const char* str, uint32_t hash) const { + uint32_t mask = Entry::GetMask(mask_bits_); + uint32_t pos = hash & mask; + // Thanks to special insertion algorithm, the element at position pos can be empty + // or start of the right bucket, or anywhere in the wrong bucket's chain. const Entry* entry = &entries_[pos]; - while (!entry->IsLast()) { - pos = (pos + entry->next_pos_delta) & GetSizeMask(); + if (entry->IsEmpty()) { + return dex::kDexNoIndex; + } + // Look for the partial hash match first, even if traversing the wrong bucket's chain. + uint32_t compared_hash_bits = (hash << mask_bits_) >> (2 * mask_bits_); + while (compared_hash_bits != entry->GetHashBits(mask_bits_)) { + if (entry->IsLast(mask_bits_)) { + return dex::kDexNoIndex; + } + pos = (pos + entry->GetNextPosDelta(mask_bits_)) & mask; entry = &entries_[pos]; + DCHECK(!entry->IsEmpty()); + } + // Found partial hash match, compare strings (expecting this to succeed). + const char* first_checked_str = GetStringData(*entry); + if (ModifiedUtf8StringEquals(str, first_checked_str)) { + return entry->GetClassDefIdx(mask_bits_); + } + // If we're at the end of the chain, return before doing further expensive work. + if (entry->IsLast(mask_bits_)) { + return dex::kDexNoIndex; + } + // Check if we're traversing the right bucket. This is important if the compared + // partial hash has only a few bits (i.e. it can match frequently). + if (((ComputeModifiedUtf8Hash(first_checked_str) ^ hash) & mask) != 0u) { + return dex::kDexNoIndex; // Low hash bits mismatch. } - return pos; + // Continue looking for the string in the rest of the chain. + do { + pos = (pos + entry->GetNextPosDelta(mask_bits_)) & mask; + entry = &entries_[pos]; + DCHECK(!entry->IsEmpty()); + if (compared_hash_bits == entry->GetHashBits(mask_bits_) && + ModifiedUtf8StringEquals(str, GetStringData(*entry))) { + return entry->GetClassDefIdx(mask_bits_); + } + } while (!entry->IsLast(mask_bits_)); + // Not found. + return dex::kDexNoIndex; +} + +uint32_t TypeLookupTable::RawDataLength(uint32_t num_class_defs) { + return SupportedSize(num_class_defs) ? RoundUpToPowerOfTwo(num_class_defs) * sizeof(Entry) : 0u; +} + +uint32_t TypeLookupTable::CalculateMaskBits(uint32_t num_class_defs) { + return SupportedSize(num_class_defs) ? MinimumBitsToStore(num_class_defs - 1u) : 0u; +} + +bool TypeLookupTable::SupportedSize(uint32_t num_class_defs) { + return num_class_defs != 0u && num_class_defs <= std::numeric_limits<uint16_t>::max(); +} + +TypeLookupTable::TypeLookupTable(const uint8_t* dex_data_pointer, + uint32_t mask_bits, + const Entry* entries, + std::unique_ptr<Entry[]> owned_entries) + : dex_data_begin_(dex_data_pointer), + mask_bits_(mask_bits), + entries_(entries), + owned_entries_(std::move(owned_entries)) {} + +const char* TypeLookupTable::GetStringData(const Entry& entry) const { + DCHECK(dex_data_begin_ != nullptr); + const uint8_t* ptr = dex_data_begin_ + entry.GetStringOffset(); + // Skip string length. + DecodeUnsignedLeb128(&ptr); + return reinterpret_cast<const char*>(ptr); } } // namespace art diff --git a/libdexfile/dex/type_lookup_table.h b/libdexfile/dex/type_lookup_table.h index 0ba2b75dc6..7005d34b88 100644 --- a/libdexfile/dex/type_lookup_table.h +++ b/libdexfile/dex/type_lookup_table.h @@ -17,9 +17,8 @@ #ifndef ART_LIBDEXFILE_DEX_TYPE_LOOKUP_TABLE_H_ #define ART_LIBDEXFILE_DEX_TYPE_LOOKUP_TABLE_H_ -#include "base/leb128.h" +#include "base/logging.h" #include "dex/dex_file_types.h" -#include "dex/utf.h" namespace art { @@ -34,140 +33,146 @@ class DexFile; */ class TypeLookupTable { public: - ~TypeLookupTable(); + // Method creates lookup table for dex file. + static TypeLookupTable Create(const DexFile& dex_file); + + // Method opens lookup table from binary data. Lookups will traverse strings and other + // data contained in dex_file as well. Lookup table does not own raw_data or dex_file. + static TypeLookupTable Open(const uint8_t* dex_data_pointer, + const uint8_t* raw_data, + uint32_t num_class_defs); + + // Create an invalid lookup table. + TypeLookupTable() + : dex_data_begin_(nullptr), + mask_bits_(0u), + entries_(nullptr), + owned_entries_(nullptr) {} + + TypeLookupTable(TypeLookupTable&& src) noexcept = default; + TypeLookupTable& operator=(TypeLookupTable&& src) noexcept = default; + + ~TypeLookupTable() { + // Implicit deallocation by std::unique_ptr<> destructor. + } + + // Returns whether the TypeLookupTable is valid. + bool Valid() const { + return entries_ != nullptr; + } // Return the number of buckets in the lookup table. uint32_t Size() const { - return mask_ + 1; + DCHECK(Valid()); + return 1u << mask_bits_; } // Method search class_def_idx by class descriptor and it's hash. // If no data found then the method returns dex::kDexNoIndex. - uint32_t Lookup(const char* str, uint32_t hash) const { - uint32_t pos = hash & GetSizeMask(); - // Thanks to special insertion algorithm, the element at position pos can be empty or start of - // bucket. - const Entry* entry = &entries_[pos]; - while (!entry->IsEmpty()) { - if (CmpHashBits(entry->data, hash) && IsStringsEquals(str, entry->str_offset)) { - return GetClassDefIdx(entry->data); - } - if (entry->IsLast()) { - return dex::kDexNoIndex; - } - pos = (pos + entry->next_pos_delta) & GetSizeMask(); - entry = &entries_[pos]; - } - return dex::kDexNoIndex; - } - - // Method creates lookup table for dex file - static std::unique_ptr<TypeLookupTable> Create(const DexFile& dex_file, - uint8_t* storage = nullptr); - - // Method opens lookup table from binary data. Lookups will traverse strings and other - // data contained in dex_file as well. Lookup table does not own raw_data or dex_file. - static std::unique_ptr<TypeLookupTable> Open(const uint8_t* dex_file_pointer, - const uint8_t* raw_data, - uint32_t num_class_defs); + uint32_t Lookup(const char* str, uint32_t hash) const; // Method returns pointer to binary data of lookup table. Used by the oat writer. const uint8_t* RawData() const { - return reinterpret_cast<const uint8_t*>(entries_.get()); + DCHECK(Valid()); + return reinterpret_cast<const uint8_t*>(entries_); } // Method returns length of binary data. Used by the oat writer. - uint32_t RawDataLength() const { return raw_data_length_; } + uint32_t RawDataLength() const { + DCHECK(Valid()); + return Size() * sizeof(Entry); + } // Method returns length of binary data for the specified number of class definitions. static uint32_t RawDataLength(uint32_t num_class_defs); private: - /** - * To find element we need to compare strings. - * It is faster to compare first hashes and then strings itself. - * But we have no full hash of element of table. But we can use 2 ideas. - * 1. All minor bits of hash inside one bucket are equals. - * 2. If dex file contains N classes and size of hash table is 2^n (where N <= 2^n) - * then 16-n bits are free. So we can encode part of element's hash into these bits. - * So hash of element can be divided on three parts: - * XXXX XXXX XXXX YYYY YZZZ ZZZZ ZZZZZ - * Z - a part of hash encoded in bucket (these bits of has are same for all elements in bucket) - - * n bits - * Y - a part of hash that we can write into free 16-n bits (because only n bits used to store - * class_def_idx) - * X - a part of has that we can't use without increasing increase - * So the data element of Entry used to store class_def_idx and part of hash of the entry. - */ - struct Entry { - uint32_t str_offset; - uint16_t data; - uint16_t next_pos_delta; - - Entry() : str_offset(0), data(0), next_pos_delta(0) {} + /** + * To find element we need to compare strings. + * It is faster to compare first hashes and then strings itself. + * But we have no full hash of element of table. But we can use 2 ideas. + * 1. All minor bits of hash inside one bucket are equal. + * (TODO: We're not actually using this, are we?) + * 2. If the dex file contains N classes and the size of the hash table is 2^n (where N <= 2^n) + * then we need n bits for the class def index and n bits for the next position delta. + * So we can encode part of element's hash into the remaining 32-2*n (n <= 16) bits which + * would be otherwise wasted as a padding. + * So hash of element can be divided on three parts: + * XXXX XXXX XXXY YYYY YYYY YZZZ ZZZZ ZZZZ (example with n=11) + * Z - a part of hash encoded implicitly in the bucket index + * (these bits are same for all elements in bucket) + * Y - a part of hash that we can write into free 32-2*n bits + * X - a part of hash that we can't use without increasing the size of the entry + * So the `data` element of Entry is used to store the next position delta, class_def_index + * and a part of hash of the entry. + */ + class Entry { + public: + Entry() : str_offset_(0u), data_(0u) {} + Entry(uint32_t str_offset, uint32_t hash, uint32_t class_def_index, uint32_t mask_bits) + : str_offset_(str_offset), + data_(((hash & ~GetMask(mask_bits)) | class_def_index) << mask_bits) { + DCHECK_EQ(class_def_index & ~GetMask(mask_bits), 0u); + } + + void SetNextPosDelta(uint32_t next_pos_delta, uint32_t mask_bits) { + DCHECK_EQ(GetNextPosDelta(mask_bits), 0u); + DCHECK_EQ(next_pos_delta & ~GetMask(mask_bits), 0u); + DCHECK_NE(next_pos_delta, 0u); + data_ |= next_pos_delta; + } bool IsEmpty() const { - return str_offset == 0; + return str_offset_ == 0u; } - bool IsLast() const { - return next_pos_delta == 0; + bool IsLast(uint32_t mask_bits) const { + return GetNextPosDelta(mask_bits) == 0u; } - }; - static uint32_t CalculateMask(uint32_t num_class_defs); - static bool SupportedSize(uint32_t num_class_defs); + uint32_t GetStringOffset() const { + return str_offset_; + } - // Construct from a dex file. - explicit TypeLookupTable(const DexFile& dex_file, uint8_t* storage); - - // Construct from a dex file with existing data. - TypeLookupTable(const uint8_t* dex_file_pointer, - const uint8_t* raw_data, - uint32_t num_class_defs); - - bool IsStringsEquals(const char* str, uint32_t str_offset) const { - const uint8_t* ptr = dex_data_begin_ + str_offset; - CHECK(dex_data_begin_ != nullptr); - // Skip string length. - DecodeUnsignedLeb128(&ptr); - return CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues( - str, reinterpret_cast<const char*>(ptr)) == 0; - } + uint32_t GetNextPosDelta(uint32_t mask_bits) const { + return data_ & GetMask(mask_bits); + } - // Method extracts hash bits from element's data and compare them with - // the corresponding bits of the specified hash - bool CmpHashBits(uint32_t data, uint32_t hash) const { - uint32_t mask = static_cast<uint16_t>(~GetSizeMask()); - return (hash & mask) == (data & mask); - } + uint32_t GetClassDefIdx(uint32_t mask_bits) const { + return (data_ >> mask_bits) & GetMask(mask_bits); + } - uint32_t GetClassDefIdx(uint32_t data) const { - return data & mask_; - } + uint32_t GetHashBits(uint32_t mask_bits) const { + DCHECK_LE(mask_bits, 16u); + return data_ >> (2u * mask_bits); + } - uint32_t GetSizeMask() const { - return mask_; - } + static uint32_t GetMask(uint32_t mask_bits) { + DCHECK_LE(mask_bits, 16u); + return ~(std::numeric_limits<uint32_t>::max() << mask_bits); + } - // Attempt to set an entry on its hash's slot. If there is already something there, return false. - // Otherwise return true. - bool SetOnInitialPos(const Entry& entry, uint32_t hash); + private: + uint32_t str_offset_; + uint32_t data_; + }; - // Insert an entry, probes until there is an empty slot. - void Insert(const Entry& entry, uint32_t hash); + static uint32_t CalculateMaskBits(uint32_t num_class_defs); + static bool SupportedSize(uint32_t num_class_defs); - // Find the last entry in a chain. - uint32_t FindLastEntryInBucket(uint32_t cur_pos) const; + // Construct the TypeLookupTable. + TypeLookupTable(const uint8_t* dex_data_pointer, + uint32_t mask_bits, + const Entry* entries, + std::unique_ptr<Entry[]> owned_entries); - const uint8_t* dex_data_begin_; - const uint32_t raw_data_length_; - const uint32_t mask_; - std::unique_ptr<Entry[]> entries_; - // owns_entries_ specifies if the lookup table owns the entries_ array. - const bool owns_entries_; + const char* GetStringData(const Entry& entry) const; - DISALLOW_IMPLICIT_CONSTRUCTORS(TypeLookupTable); + const uint8_t* dex_data_begin_; + uint32_t mask_bits_; + const Entry* entries_; + // `owned_entries_` is either null (not owning `entries_`) or same pointer as `entries_`. + std::unique_ptr<Entry[]> owned_entries_; }; } // namespace art diff --git a/libdexfile/dex/type_lookup_table_test.cc b/libdexfile/dex/type_lookup_table_test.cc index 6c3d291332..4316be0bd6 100644 --- a/libdexfile/dex/type_lookup_table_test.cc +++ b/libdexfile/dex/type_lookup_table_test.cc @@ -30,20 +30,20 @@ class TypeLookupTableTest : public CommonArtTestWithParam<DescriptorClassDefIdxP TEST_F(TypeLookupTableTest, CreateLookupTable) { std::unique_ptr<const DexFile> dex_file(OpenTestDexFile("Lookup")); - std::unique_ptr<TypeLookupTable> table(TypeLookupTable::Create(*dex_file)); - ASSERT_NE(nullptr, table.get()); - ASSERT_NE(nullptr, table->RawData()); - ASSERT_EQ(32U, table->RawDataLength()); + TypeLookupTable table = TypeLookupTable::Create(*dex_file); + ASSERT_TRUE(table.Valid()); + ASSERT_NE(nullptr, table.RawData()); + ASSERT_EQ(32U, table.RawDataLength()); } TEST_P(TypeLookupTableTest, Find) { std::unique_ptr<const DexFile> dex_file(OpenTestDexFile("Lookup")); - std::unique_ptr<TypeLookupTable> table(TypeLookupTable::Create(*dex_file)); - ASSERT_NE(nullptr, table.get()); + TypeLookupTable table(TypeLookupTable::Create(*dex_file)); + ASSERT_TRUE(table.Valid()); auto pair = GetParam(); const char* descriptor = pair.first; size_t hash = ComputeModifiedUtf8Hash(descriptor); - uint32_t class_def_idx = table->Lookup(descriptor, hash); + uint32_t class_def_idx = table.Lookup(descriptor, hash); ASSERT_EQ(pair.second, class_def_idx); } diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 7ac9e984ff..7b72e189b9 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -105,6 +105,10 @@ const char* image_methods_descriptions_[] = { const char* image_roots_descriptions_[] = { "kDexCaches", "kClassRoots", + "kOomeWhenThrowingException", + "kOomeWhenThrowingOome", + "kOomeWhenHandlingStackOverflow", + "kNoClassDefFoundError", "kClassLoader", }; @@ -1942,17 +1946,17 @@ class ImageDumper { os << "COMPILE PIC: " << (image_header_.CompilePic() ? "yes" : "no") << "\n\n"; { - os << "ROOTS: " << reinterpret_cast<void*>(image_header_.GetImageRoots()) << "\n"; + os << "ROOTS: " << reinterpret_cast<void*>(image_header_.GetImageRoots().Ptr()) << "\n"; static_assert(arraysize(image_roots_descriptions_) == static_cast<size_t>(ImageHeader::kImageRootsMax), "sizes must match"); DCHECK_LE(image_header_.GetImageRoots()->GetLength(), ImageHeader::kImageRootsMax); for (int32_t i = 0, size = image_header_.GetImageRoots()->GetLength(); i != size; ++i) { ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i); const char* image_root_description = image_roots_descriptions_[i]; - mirror::Object* image_root_object = image_header_.GetImageRoot(image_root); - indent_os << StringPrintf("%s: %p\n", image_root_description, image_root_object); + ObjPtr<mirror::Object> image_root_object = image_header_.GetImageRoot(image_root); + indent_os << StringPrintf("%s: %p\n", image_root_description, image_root_object.Ptr()); if (image_root_object != nullptr && image_root_object->IsObjectArray()) { - mirror::ObjectArray<mirror::Object>* image_root_object_array + ObjPtr<mirror::ObjectArray<mirror::Object>> image_root_object_array = image_root_object->AsObjectArray<mirror::Object>(); ScopedIndentation indent2(&vios_); for (int j = 0; j < image_root_object_array->GetLength(); j++) { diff --git a/openjdkjvm/OpenjdkJvm.cc b/openjdkjvm/OpenjdkJvm.cc index be1ab7812a..765225ae95 100644 --- a/openjdkjvm/OpenjdkJvm.cc +++ b/openjdkjvm/OpenjdkJvm.cc @@ -401,7 +401,7 @@ JNIEXPORT jboolean JVM_HoldsLock(JNIEnv* env, jclass unused ATTRIBUTE_UNUSED, jo 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 fcbafe7e71..a660fb56c4 100644 --- a/openjdkjvmti/fixed_up_dex_file.cc +++ b/openjdkjvmti/fixed_up_dex_file.cc @@ -31,6 +31,7 @@ #include "base/leb128.h" #include "fixed_up_dex_file.h" +#include "dex/class_accessor-inl.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_loader.h" #include "dex/dex_file_verifier.h" @@ -51,14 +52,12 @@ static void RecomputeDexChecksum(art::DexFile* dex_file) { } static void UnhideApis(const art::DexFile& target_dex_file) { - for (uint32_t i = 0; i < target_dex_file.NumClassDefs(); ++i) { - const uint8_t* class_data = target_dex_file.GetClassData(target_dex_file.GetClassDef(i)); - if (class_data != nullptr) { - for (art::ClassDataItemIterator class_it(target_dex_file, class_data); - class_it.HasNext(); - class_it.Next()) { - art::DexFile::UnHideAccessFlags(class_it); - } + for (art::ClassAccessor accessor : target_dex_file.GetClasses()) { + for (const art::ClassAccessor::Field& field : accessor.GetFields()) { + field.UnHideAccessFlags(); + } + for (const art::ClassAccessor::Method& method : accessor.GetMethods()) { + method.UnHideAccessFlags(); } } } diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc index 73e37199ed..50d8dfeb70 100644 --- a/openjdkjvmti/ti_redefine.cc +++ b/openjdkjvmti/ti_redefine.cc @@ -526,7 +526,7 @@ art::mirror::Object* Redefiner::ClassRedefinition::AllocateOrGetOriginalDexFile( 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 a6d3903f19..3c0b3e42c9 100644 --- a/patchoat/patchoat.cc +++ b/patchoat/patchoat.cc @@ -973,7 +973,7 @@ bool PatchOat::PatchImage(bool primary_image) { ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin()); CHECK_GT(image_->Size(), sizeof(ImageHeader)); // These are the roots from the original file. - auto* img_roots = image_header->GetImageRoots(); + mirror::ObjectArray<mirror::Object>* img_roots = image_header->GetImageRoots().Ptr(); image_header->RelocateImage(delta_); PatchArtFields(image_header); diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h index baa5102f5d..c5fb7d5f40 100644 --- a/runtime/art_field-inl.h +++ b/runtime/art_field-inl.h @@ -21,7 +21,7 @@ #include <android-base/logging.h> -#include "class_linker.h" +#include "class_linker-inl.h" #include "dex/dex_file-inl.h" #include "dex/primitive.h" #include "gc/accounting/card_table-inl.h" @@ -339,16 +339,11 @@ inline const DexFile* ArtField::GetDexFile() REQUIRES_SHARED(Locks::mutator_lock return GetDexCache<kWithoutReadBarrier>()->GetDexFile(); } -inline ObjPtr<mirror::String> ArtField::GetStringName(Thread* self, bool resolve) { - auto dex_field_index = GetDexFieldIndex(); +inline ObjPtr<mirror::String> ArtField::ResolveNameString() { + uint32_t dex_field_index = GetDexFieldIndex(); CHECK_NE(dex_field_index, dex::kDexNoIndex); - ObjPtr<mirror::DexCache> dex_cache = GetDexCache(); - const DexFile::FieldId& field_id = dex_cache->GetDexFile()->GetFieldId(dex_field_index); - ObjPtr<mirror::String> name = dex_cache->GetResolvedString(field_id.name_idx_); - if (resolve && name == nullptr) { - name = ResolveGetStringName(self, field_id.name_idx_, dex_cache); - } - return name; + const DexFile::FieldId& field_id = GetDexFile()->GetFieldId(dex_field_index); + return Runtime::Current()->GetClassLinker()->ResolveString(field_id.name_idx_, this); } template <typename Visitor> diff --git a/runtime/art_field.cc b/runtime/art_field.cc index b867621f02..6cbd9e4cfc 100644 --- a/runtime/art_field.cc +++ b/runtime/art_field.cc @@ -52,13 +52,6 @@ ObjPtr<mirror::Class> ArtField::ProxyFindSystemClass(const char* descriptor) { return klass; } -ObjPtr<mirror::String> ArtField::ResolveGetStringName(Thread* self, - dex::StringIndex string_idx, - ObjPtr<mirror::DexCache> dex_cache) { - StackHandleScope<1> hs(self); - return Runtime::Current()->GetClassLinker()->ResolveString(string_idx, hs.NewHandle(dex_cache)); -} - std::string ArtField::PrettyField(ArtField* f, bool with_type) { if (f == nullptr) { return "null"; diff --git a/runtime/art_field.h b/runtime/art_field.h index 784a862425..123595c6fe 100644 --- a/runtime/art_field.h +++ b/runtime/art_field.h @@ -201,8 +201,7 @@ class ArtField FINAL { const char* GetName() REQUIRES_SHARED(Locks::mutator_lock_); // Resolves / returns the name from the dex cache. - ObjPtr<mirror::String> GetStringName(Thread* self, bool resolve) - REQUIRES_SHARED(Locks::mutator_lock_); + ObjPtr<mirror::String> ResolveNameString() REQUIRES_SHARED(Locks::mutator_lock_); const char* GetTypeDescriptor() REQUIRES_SHARED(Locks::mutator_lock_); @@ -241,10 +240,6 @@ class ArtField FINAL { ObjPtr<mirror::Class> ProxyFindSystemClass(const char* descriptor) REQUIRES_SHARED(Locks::mutator_lock_); - ObjPtr<mirror::String> ResolveGetStringName(Thread* self, - dex::StringIndex string_idx, - ObjPtr<mirror::DexCache> dex_cache) - REQUIRES_SHARED(Locks::mutator_lock_); void GetAccessFlagsDCheck() REQUIRES_SHARED(Locks::mutator_lock_); void GetOffsetDCheck() REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h index ec66966869..18595cf17a 100644 --- a/runtime/art_method-inl.h +++ b/runtime/art_method-inl.h @@ -245,6 +245,12 @@ inline const char* ArtMethod::GetName() { } } +inline ObjPtr<mirror::String> ArtMethod::ResolveNameString() { + DCHECK(!IsProxyMethod()); + const DexFile::MethodId& method_id = GetDexFile()->GetMethodId(GetDexMethodIndex()); + return Runtime::Current()->GetClassLinker()->ResolveString(method_id.name_idx_, this); +} + inline const DexFile::CodeItem* ArtMethod::GetCodeItem() { return GetDexFile()->GetCodeItem(GetCodeItemOffset()); } diff --git a/runtime/art_method.cc b/runtime/art_method.cc index 151c36f3bc..45bf66446a 100644 --- a/runtime/art_method.cc +++ b/runtime/art_method.cc @@ -26,6 +26,7 @@ #include "class_linker-inl.h" #include "class_root.h" #include "debugger.h" +#include "dex/class_accessor-inl.h" #include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_exception_helpers.h" @@ -142,16 +143,6 @@ uint16_t ArtMethod::FindObsoleteDexClassDefIndex() { return dex_file->GetIndexForClassDef(*class_def); } -ObjPtr<mirror::String> ArtMethod::GetNameAsString(Thread* self) { - CHECK(!IsProxyMethod()); - StackHandleScope<1> hs(self); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(GetDexCache())); - auto* dex_file = dex_cache->GetDexFile(); - uint32_t dex_method_idx = GetDexMethodIndex(); - const DexFile::MethodId& method_id = dex_file->GetMethodId(dex_method_idx); - return Runtime::Current()->GetClassLinker()->ResolveString(method_id.name_idx_, dex_cache); -} - void ArtMethod::ThrowInvocationTimeError() { DCHECK(!IsInvokable()); // NOTE: IsDefaultConflicting must be first since the actual method might or might not be abstract @@ -434,28 +425,14 @@ bool ArtMethod::IsPolymorphicSignature() { static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file, uint16_t class_def_idx, uint32_t method_idx) { - const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_idx); - const uint8_t* class_data = dex_file.GetClassData(class_def); - CHECK(class_data != nullptr); - ClassDataItemIterator it(dex_file, class_data); - it.SkipAllFields(); - // Process methods - size_t class_def_method_index = 0; - while (it.HasNextDirectMethod()) { - if (it.GetMemberIndex() == method_idx) { - return class_def_method_index; - } - class_def_method_index++; - it.Next(); - } - while (it.HasNextVirtualMethod()) { - if (it.GetMemberIndex() == method_idx) { + ClassAccessor accessor(dex_file, dex_file.GetClassDef(class_def_idx)); + uint32_t class_def_method_index = 0u; + for (const ClassAccessor::Method& method : accessor.GetMethods()) { + if (method.GetIndex() == method_idx) { return class_def_method_index; } class_def_method_index++; - it.Next(); } - DCHECK(!it.HasNext()); LOG(FATAL) << "Failed to find method index " << method_idx << " in " << dex_file.GetLocation(); UNREACHABLE(); } diff --git a/runtime/art_method.h b/runtime/art_method.h index 012d706756..09debb0c50 100644 --- a/runtime/art_method.h +++ b/runtime/art_method.h @@ -589,7 +589,7 @@ class ArtMethod FINAL { ALWAYS_INLINE const char* GetName() REQUIRES_SHARED(Locks::mutator_lock_); - ObjPtr<mirror::String> GetNameAsString(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_); + ObjPtr<mirror::String> ResolveNameString() REQUIRES_SHARED(Locks::mutator_lock_); const DexFile::CodeItem* GetCodeItem() REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h index 888f713d8f..2536b23416 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 @@ inline ObjPtr<mirror::Class> ClassLinker::FindArrayClass(Thread* self, // 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 dccdff0a5d..6933174d8b 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -56,6 +56,7 @@ #include "compiler_callbacks.h" #include "debug_print.h" #include "debugger.h" +#include "dex/class_accessor-inl.h" #include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_exception_helpers.h" @@ -197,8 +198,7 @@ static void HandleEarlierVerifyError(Thread* self, } } else { // Previous error has been stored as an instance. Just rethrow. - ObjPtr<mirror::Class> throwable_class = - self->DecodeJObject(WellKnownClasses::java_lang_Throwable)->AsClass(); + ObjPtr<mirror::Class> throwable_class = GetClassRoot<mirror::Throwable>(class_linker); ObjPtr<mirror::Class> error_class = obj->GetClass(); CHECK(throwable_class->IsAssignableFrom(error_class)); self->SetException(obj->AsThrowable()); @@ -376,7 +376,6 @@ ClassLinker::ClassLinker(InternTable* intern_table) : boot_class_table_(new ClassTable()), failed_dex_cache_class_lookups_(0), class_roots_(nullptr), - array_iftable_(nullptr), find_array_class_cache_next_victim_(0), init_done_(false), log_new_roots_(false), @@ -432,8 +431,8 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b 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 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b // Fill in the empty iftable. Needs to be done after the kObjectArrayClass root is set. java_lang_Object->SetIfTable(AllocIfTable(self, 0)); + // Create array interface entries to populate once we can load system classes. + object_array_class->SetIfTable(AllocIfTable(self, 2)); + DCHECK_EQ(GetArrayIfTable(), object_array_class->GetIfTable()); + // Setup the primitive type classes. SetClassRoot(ClassRoot::kPrimitiveBoolean, CreatePrimitiveClass(self, Primitive::kPrimBoolean)); SetClassRoot(ClassRoot::kPrimitiveByte, CreatePrimitiveClass(self, Primitive::kPrimByte)); @@ -523,9 +526,6 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b SetClassRoot(ClassRoot::kPrimitiveDouble, CreatePrimitiveClass(self, Primitive::kPrimDouble)); SetClassRoot(ClassRoot::kPrimitiveVoid, CreatePrimitiveClass(self, Primitive::kPrimVoid)); - // Create array interface entries to populate once we can load system classes. - array_iftable_ = GcRoot<mirror::IfTable>(AllocIfTable(self, 2)); - // Create int array type for native pointer arrays (for example vtables) on 32-bit archs. Handle<mirror::Class> int_array_class(hs.NewHandle( AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_)))); @@ -639,8 +639,8 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b CHECK(java_io_Serializable != nullptr); // We assume that Cloneable/Serializable don't have superinterfaces -- normally we'd have to // crawl up and explicitly list all of the supers as well. - array_iftable_.Read()->SetInterface(0, java_lang_Cloneable.Get()); - array_iftable_.Read()->SetInterface(1, java_io_Serializable.Get()); + object_array_class->GetIfTable()->SetInterface(0, java_lang_Cloneable.Get()); + object_array_class->GetIfTable()->SetInterface(1, java_io_Serializable.Get()); // Sanity check Class[] and Object[]'s interfaces. GetDirectInterface may cause thread // suspension. @@ -841,7 +841,7 @@ void ClassLinker::FinishInit(Thread* self) { // if possible add new checks there to catch errors early } - CHECK(!array_iftable_.IsNull()); + CHECK(GetArrayIfTable() != nullptr); // disable the slow paths in FindClass and CreatePrimitiveClass now // that Object, Class, and Object[] are setup @@ -988,8 +988,8 @@ bool ClassLinker::InitFromBootImage(std::string* error_msg) { } 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 @@ bool ClassLinker::InitFromBootImage(std::string* error_msg) { runtime->SetSentinel(heap->AllocNonMovableObject<true>( self, java_lang_Object, java_lang_Object->GetObjectSize(), VoidFunctor())); - // reinit array_iftable_ from any array class instance, they should be == - array_iftable_ = - GcRoot<mirror::IfTable>(GetClassRoot(ClassRoot::kObjectArrayClass, this)->GetIfTable()); - DCHECK_EQ(array_iftable_.Read(), GetClassRoot(ClassRoot::kBooleanArrayClass, this)->GetIfTable()); - for (gc::space::ImageSpace* image_space : spaces) { // Boot class loader, use a null handle. std::vector<std::unique_ptr<const DexFile>> dex_files; @@ -1094,7 +1089,7 @@ static bool FlattenPathClassLoader(ObjPtr<mirror::ClassLoader> class_loader, 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::VisitClassRoots(RootVisitor* visitor, VisitRootFlags flags) { void ClassLinker::VisitRoots(RootVisitor* visitor, VisitRootFlags flags) { class_roots_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal)); VisitClassRoots(visitor, flags); - array_iftable_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal)); // Instead of visiting the find_array_class_cache_ drop it so that it doesn't prevent class // unloading if we are marking roots. DropFindArrayClassCache(); @@ -2114,16 +2108,16 @@ void ClassLinker::DeleteClassLoader(Thread* self, const ClassLoaderData& data, b 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 @@ mirror::DexCache* ClassLinker::AllocDexCache(ObjPtr<mirror::String>* out_locatio 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 @@ mirror::DexCache* ClassLinker::AllocAndInitializeDexCache(Thread* self, linear_alloc, image_pointer_size_); } - return dex_cache.Ptr(); + return dex_cache; } ObjPtr<mirror::Class> ClassLinker::AllocClass(Thread* self, @@ -2179,7 +2173,7 @@ ObjPtr<mirror::Class> ClassLinker::AllocClass(Thread* self, uint32_t class_size) 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 @@ ObjPtr<mirror::Class> ClassLinker::EnsureResolved(Thread* self, // 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 @@ bool ClassLinker::FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnabl 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 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, 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 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, 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 @@ ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, uint32_t ClassLinker::SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def) { - const uint8_t* class_data = dex_file.GetClassData(dex_class_def); size_t num_ref = 0; size_t num_8 = 0; size_t num_16 = 0; size_t num_32 = 0; size_t num_64 = 0; - if (class_data != nullptr) { - // We allow duplicate definitions of the same field in a class_data_item - // but ignore the repeated indexes here, b/21868015. - uint32_t last_field_idx = dex::kDexNoIndex; - for (ClassDataItemIterator it(dex_file, class_data); it.HasNextStaticField(); it.Next()) { - uint32_t field_idx = it.GetMemberIndex(); - // Ordering enforced by DexFileVerifier. - DCHECK(last_field_idx == dex::kDexNoIndex || last_field_idx <= field_idx); - if (UNLIKELY(field_idx == last_field_idx)) { - continue; - } - last_field_idx = field_idx; - const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); - const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id); - char c = descriptor[0]; - switch (c) { - case 'L': - case '[': - num_ref++; - break; - case 'J': - case 'D': - num_64++; - break; - case 'I': - case 'F': - num_32++; - break; - case 'S': - case 'C': - num_16++; - break; - case 'B': - case 'Z': - num_8++; - break; - default: - LOG(FATAL) << "Unknown descriptor: " << c; - UNREACHABLE(); - } + ClassAccessor accessor(dex_file, dex_class_def); + // We allow duplicate definitions of the same field in a class_data_item + // but ignore the repeated indexes here, b/21868015. + uint32_t last_field_idx = dex::kDexNoIndex; + for (const ClassAccessor::Field& field : accessor.GetStaticFields()) { + uint32_t field_idx = field.GetIndex(); + // Ordering enforced by DexFileVerifier. + DCHECK(last_field_idx == dex::kDexNoIndex || last_field_idx <= field_idx); + if (UNLIKELY(field_idx == last_field_idx)) { + continue; + } + last_field_idx = field_idx; + const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); + const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id); + char c = descriptor[0]; + switch (c) { + case 'L': + case '[': + num_ref++; + break; + case 'J': + case 'D': + num_64++; + break; + case 'I': + case 'F': + num_32++; + break; + case 'S': + case 'C': + num_16++; + break; + case 'B': + case 'Z': + num_8++; + break; + default: + LOG(FATAL) << "Unknown descriptor: " << c; + UNREACHABLE(); } } return mirror::Class::ComputeClassSize(false, @@ -2873,17 +2865,15 @@ void ClassLinker::FixupStaticTrampolines(ObjPtr<mirror::Class> klass) { const DexFile& dex_file = klass->GetDexFile(); const DexFile::ClassDef* dex_class_def = klass->GetClassDef(); CHECK(dex_class_def != nullptr); - const uint8_t* class_data = dex_file.GetClassData(*dex_class_def); + ClassAccessor accessor(dex_file, *dex_class_def); // There should always be class data if there were direct methods. - CHECK(class_data != nullptr) << klass->PrettyDescriptor(); - ClassDataItemIterator it(dex_file, class_data); - it.SkipAllFields(); + CHECK(accessor.HasClassData()) << klass->PrettyDescriptor(); bool has_oat_class; OatFile::OatClass oat_class = OatFile::FindOatClass(dex_file, klass->GetDexClassDefIndex(), &has_oat_class); // Link the code of methods skipped by LinkCode. - for (size_t method_index = 0; it.HasNextDirectMethod(); ++method_index, it.Next()) { + for (size_t method_index = 0; method_index < accessor.NumDirectMethods(); ++method_index) { ArtMethod* method = klass->GetDirectMethod(method_index, image_pointer_size_); if (!method->IsStatic()) { // Only update static methods. @@ -2992,17 +2982,6 @@ void ClassLinker::SetupClass(const DexFile& dex_file, klass->SetDexTypeIndex(dex_class_def.class_idx_); } -void ClassLinker::LoadClass(Thread* self, - const DexFile& dex_file, - const DexFile::ClassDef& dex_class_def, - Handle<mirror::Class> klass) { - const uint8_t* class_data = dex_file.GetClassData(dex_class_def); - if (class_data == nullptr) { - return; // no fields or methods - for example a marker interface - } - LoadClassMembers(self, dex_file, class_data, klass); -} - LengthPrefixedArray<ArtField>* ClassLinker::AllocArtFieldArray(Thread* self, LinearAlloc* allocator, size_t length) { @@ -3061,10 +3040,15 @@ LinearAlloc* ClassLinker::GetOrCreateAllocatorForClassLoader(ObjPtr<mirror::Clas return allocator; } -void ClassLinker::LoadClassMembers(Thread* self, - const DexFile& dex_file, - const uint8_t* class_data, - Handle<mirror::Class> klass) { +void ClassLinker::LoadClass(Thread* self, + const DexFile& dex_file, + const DexFile::ClassDef& dex_class_def, + Handle<mirror::Class> klass) { + ClassAccessor accessor(dex_file, dex_class_def); + if (!accessor.HasClassData()) { + return; + } + Runtime* const runtime = Runtime::Current(); { // Note: We cannot have thread suspension until the field and method arrays are setup or else // Class::VisitFieldRoots may miss some fields or methods. @@ -3073,45 +3057,79 @@ void ClassLinker::LoadClassMembers(Thread* self, // We allow duplicate definitions of the same field in a class_data_item // but ignore the repeated indexes here, b/21868015. LinearAlloc* const allocator = GetAllocatorForClassLoader(klass->GetClassLoader()); - ClassDataItemIterator it(dex_file, class_data); LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self, allocator, - it.NumStaticFields()); - size_t num_sfields = 0; - uint32_t last_field_idx = 0u; - for (; it.HasNextStaticField(); it.Next()) { - uint32_t field_idx = it.GetMemberIndex(); - DCHECK_GE(field_idx, last_field_idx); // Ordering enforced by DexFileVerifier. - if (num_sfields == 0 || LIKELY(field_idx > last_field_idx)) { - DCHECK_LT(num_sfields, it.NumStaticFields()); - LoadField(it, klass, &sfields->At(num_sfields)); - ++num_sfields; - last_field_idx = field_idx; - } - } - - // Load instance fields. + accessor.NumStaticFields()); LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self, allocator, - it.NumInstanceFields()); + accessor.NumInstanceFields()); + size_t num_sfields = 0u; size_t num_ifields = 0u; - last_field_idx = 0u; - for (; it.HasNextInstanceField(); it.Next()) { - uint32_t field_idx = it.GetMemberIndex(); - DCHECK_GE(field_idx, last_field_idx); // Ordering enforced by DexFileVerifier. - if (num_ifields == 0 || LIKELY(field_idx > last_field_idx)) { - DCHECK_LT(num_ifields, it.NumInstanceFields()); - LoadField(it, klass, &ifields->At(num_ifields)); - ++num_ifields; - last_field_idx = field_idx; - } - } + uint32_t last_static_field_idx = 0u; + uint32_t last_instance_field_idx = 0u; - 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 @@ void ClassLinker::LoadClassMembers(Thread* self, DCHECK_EQ(klass->NumStaticFields(), num_sfields); klass->SetIFieldsPtr(ifields); DCHECK_EQ(klass->NumInstanceFields(), num_ifields); - // Load methods. - bool has_oat_class = false; - const OatFile::OatClass oat_class = - (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler()) - ? OatFile::FindOatClass(dex_file, klass->GetDexClassDefIndex(), &has_oat_class) - : OatFile::OatClass::Invalid(); - const OatFile::OatClass* oat_class_ptr = has_oat_class ? &oat_class : nullptr; - klass->SetMethodsPtr( - AllocArtMethodArray(self, allocator, it.NumDirectMethods() + it.NumVirtualMethods()), - it.NumDirectMethods(), - it.NumVirtualMethods()); - size_t class_def_method_index = 0; - uint32_t last_dex_method_index = dex::kDexNoIndex; - size_t last_class_def_method_index = 0; - // TODO These should really use the iterators. - for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) { - ArtMethod* method = klass->GetDirectMethodUnchecked(i, image_pointer_size_); - LoadMethod(dex_file, it, klass, method); - LinkCode(this, method, oat_class_ptr, class_def_method_index); - uint32_t it_method_index = it.GetMemberIndex(); - if (last_dex_method_index == it_method_index) { - // duplicate case - method->SetMethodIndex(last_class_def_method_index); - } else { - method->SetMethodIndex(class_def_method_index); - last_dex_method_index = it_method_index; - last_class_def_method_index = class_def_method_index; - } - class_def_method_index++; - } - for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) { - ArtMethod* method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_); - LoadMethod(dex_file, it, klass, method); - DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i); - LinkCode(this, method, oat_class_ptr, class_def_method_index); - class_def_method_index++; - } - DCHECK(!it.HasNext()); } // Ensure that the card is marked so that remembered sets pick up native roots. Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(klass.Get()); self->AllowThreadSuspension(); } -void ClassLinker::LoadField(const ClassDataItemIterator& it, +void ClassLinker::LoadField(const ClassAccessor::Field& field, Handle<mirror::Class> klass, ArtField* dst) { - const uint32_t field_idx = it.GetMemberIndex(); + const uint32_t field_idx = field.GetIndex(); dst->SetDexFieldIndex(field_idx); dst->SetDeclaringClass(klass.Get()); // Get access flags from the DexFile. If this is a boot class path class, // also set its runtime hidden API access flags. - uint32_t access_flags = it.GetFieldAccessFlags(); + uint32_t access_flags = field.GetAccessFlags(); if (klass->IsBootStrapClassLoaded()) { access_flags = - HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags()); + HiddenApiAccessFlags::EncodeForRuntime(access_flags, field.DecodeHiddenAccessFlags()); } dst->SetAccessFlags(access_flags); } void ClassLinker::LoadMethod(const DexFile& dex_file, - const ClassDataItemIterator& it, + const ClassAccessor::Method& method, Handle<mirror::Class> klass, ArtMethod* dst) { - uint32_t dex_method_idx = it.GetMemberIndex(); + const uint32_t dex_method_idx = method.GetIndex(); const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx); const char* method_name = dex_file.StringDataByIdx(method_id.name_idx_); ScopedAssertNoThreadSuspension ants("LoadMethod"); dst->SetDexMethodIndex(dex_method_idx); dst->SetDeclaringClass(klass.Get()); - dst->SetCodeItemOffset(it.GetMethodCodeItemOffset()); + dst->SetCodeItemOffset(method.GetCodeItemOffset()); // Get access flags from the DexFile. If this is a boot class path class, // also set its runtime hidden API access flags. - uint32_t access_flags = it.GetMethodAccessFlags(); + uint32_t access_flags = method.GetAccessFlags(); if (klass->IsBootStrapClassLoaded()) { access_flags = - HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags()); + HiddenApiAccessFlags::EncodeForRuntime(access_flags, method.DecodeHiddenAccessFlags()); } if (UNLIKELY(strcmp("finalize", method_name) == 0)) { @@ -3553,6 +3533,10 @@ ObjPtr<mirror::Class> ClassLinker::CreatePrimitiveClass(Thread* self, Primitive: return h_class.Get(); } +inline ObjPtr<mirror::IfTable> ClassLinker::GetArrayIfTable() { + return GetClassRoot<mirror::ObjectArray<mirror::Object>>(this)->GetIfTable(); +} + // Create an array class (i.e. the class object for the array, not the // array itself). "descriptor" looks like "[C" or "[[[[B" or // "[Ljava/lang/String;". @@ -3612,7 +3596,7 @@ ObjPtr<mirror::Class> ClassLinker::CreateArrayClass(Thread* self, 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 @@ ObjPtr<mirror::Class> ClassLinker::CreateArrayClass(Thread* self, // Use the single, global copies of "interfaces" and "iftable" // (remember not to free them for arrays). { - ObjPtr<mirror::IfTable> array_iftable = array_iftable_.Read(); + ObjPtr<mirror::IfTable> array_iftable = GetArrayIfTable(); CHECK(array_iftable != nullptr); new_class->SetIfTable(array_iftable); } @@ -3713,7 +3697,7 @@ ObjPtr<mirror::Class> ClassLinker::CreateArrayClass(Thread* self, // // (Yes, this happens.) - return existing.Ptr(); + return existing; } ObjPtr<mirror::Class> ClassLinker::FindPrimitiveClass(char type) { @@ -3763,7 +3747,7 @@ ObjPtr<mirror::Class> ClassLinker::InsertClass(const char* descriptor, 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 @@ ObjPtr<mirror::Class> ClassLinker::LookupClass(Thread* self, 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 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass, this, *dex_class_def); const DexFile& dex_file = *dex_cache->GetDexFile(); - const uint8_t* class_data = dex_file.GetClassData(*dex_class_def); - ClassDataItemIterator field_it(dex_file, class_data); + if (value_it.HasNext()) { - DCHECK(field_it.HasNextStaticField()); + ClassAccessor accessor(dex_file, *dex_class_def); CHECK(can_init_statics); - for ( ; value_it.HasNext(); value_it.Next(), field_it.Next()) { - ArtField* field = ResolveField( - field_it.GetMemberIndex(), dex_cache, class_loader, /* is_static */ true); + for (const ClassAccessor::Field& field : accessor.GetStaticFields()) { + if (!value_it.HasNext()) { + break; + } + ArtField* art_field = ResolveField(field.GetIndex(), + dex_cache, + class_loader, + /* is_static */ true); if (Runtime::Current()->IsActiveTransaction()) { - value_it.ReadValueToField<true>(field); + value_it.ReadValueToField<true>(art_field); } else { - value_it.ReadValueToField<false>(field); + value_it.ReadValueToField<false>(art_field); } if (self->IsExceptionPending()) { break; } - DCHECK(!value_it.HasNext() || field_it.HasNextStaticField()); + value_it.Next(); } + DCHECK(self->IsExceptionPending() || !value_it.HasNext()); } } @@ -5723,8 +5712,8 @@ bool ClassLinker::LinkVirtualMethods( 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 @@ bool ClassLinker::LinkVirtualMethods( // 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 @@ bool ClassLinker::LinkVirtualMethods( 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 @@ bool ClassLinker::AllocateIfTableMethodArrays(Thread* self, 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 @@ static bool NotSubinterfaceOfAny( // 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 @@ bool ClassLinker::SetupInterfaceLookupTable(Thread* self, Handle<mirror::Class> 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 @@ bool ClassLinker::SetupInterfaceLookupTable(Thread* self, Handle<mirror::Class> // 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 @@ ObjPtr<mirror::PointerArray> ClassLinker::LinkInterfaceMethodsHelper::UpdateVtab 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 @@ void ClassLinker::CreateReferenceInstanceOffsets(Handle<mirror::Class> klass) { klass->SetReferenceInstanceOffsets(reference_offsets); } -ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx, - Handle<mirror::DexCache> dex_cache) { - DCHECK(dex_cache != nullptr); - Thread::PoisonObjectPointersIfDebug(); - ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx); - if (resolved != nullptr) { - return resolved; - } +ObjPtr<mirror::String> ClassLinker::DoResolveString(dex::StringIndex string_idx, + ObjPtr<mirror::DexCache> dex_cache) { + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(dex_cache)); + return DoResolveString(string_idx, h_dex_cache); +} + +ObjPtr<mirror::String> ClassLinker::DoResolveString(dex::StringIndex string_idx, + Handle<mirror::DexCache> dex_cache) { const DexFile& dex_file = *dex_cache->GetDexFile(); uint32_t utf16_length; const char* utf8_data = dex_file.StringDataAndUtf16LengthByIdx(string_idx, &utf16_length); @@ -7682,13 +7673,9 @@ ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx, return string; } -ObjPtr<mirror::String> ClassLinker::LookupString(dex::StringIndex string_idx, - ObjPtr<mirror::DexCache> dex_cache) { +ObjPtr<mirror::String> ClassLinker::DoLookupString(dex::StringIndex string_idx, + ObjPtr<mirror::DexCache> dex_cache) { DCHECK(dex_cache != nullptr); - ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx); - if (resolved != nullptr) { - return resolved; - } const DexFile& dex_file = *dex_cache->GetDexFile(); uint32_t utf16_length; const char* utf8_data = dex_file.StringDataAndUtf16LengthByIdx(string_idx, &utf16_length); @@ -7721,7 +7708,7 @@ ObjPtr<mirror::Class> ClassLinker::DoLookupResolvedType(dex::TypeIndex type_idx, 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> ClassLinker::ResolveMethodType( 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 @@ void ClassLinker::InsertDexFileInToClassLoader(ObjPtr<mirror::Object> dex_file, 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 32016fa12a..30c242399d 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -27,6 +27,7 @@ #include "base/enums.h" #include "base/macros.h" #include "base/mutex.h" +#include "dex/class_accessor.h" #include "dex/dex_cache_resolved_classes.h" #include "dex/dex_file.h" #include "dex/dex_file_types.h" @@ -163,7 +164,7 @@ class ClassLinker { } // 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 @@ class ClassLinker { REQUIRES(!Locks::classlinker_classes_lock_) REQUIRES_SHARED(Locks::mutator_lock_); + // Resolve a String with the given index from the DexFile associated with the given `referrer`, + // storing the result in the DexCache. The `referrer` is used to identify the target DexCache + // to use for resolution. + ObjPtr<mirror::String> ResolveString(dex::StringIndex string_idx, + ArtField* referrer) + REQUIRES_SHARED(Locks::mutator_lock_); + ObjPtr<mirror::String> ResolveString(dex::StringIndex string_idx, + ArtMethod* referrer) + REQUIRES_SHARED(Locks::mutator_lock_); + // Resolve a String with the given index from the DexFile associated with the given DexCache, // storing the result in the DexCache. ObjPtr<mirror::String> ResolveString(dex::StringIndex string_idx, @@ -451,7 +462,7 @@ class ClassLinker { 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 @@ class ClassLinker { 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 @@ class ClassLinker { 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 @@ class ClassLinker { 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 @@ class ClassLinker { const DexFile::ClassDef& dex_class_def, Handle<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); - void LoadClassMembers(Thread* self, - const DexFile& dex_file, - const uint8_t* class_data, - Handle<mirror::Class> klass) - REQUIRES_SHARED(Locks::mutator_lock_); - void LoadField(const ClassDataItemIterator& it, Handle<mirror::Class> klass, ArtField* dst) + void LoadField(const ClassAccessor::Field& field, Handle<mirror::Class> klass, ArtField* dst) REQUIRES_SHARED(Locks::mutator_lock_); void LoadMethod(const DexFile& dex_file, - const ClassDataItemIterator& it, - Handle<mirror::Class> klass, ArtMethod* dst) + const ClassAccessor::Method& method, + Handle<mirror::Class> klass, + ArtMethod* dst) REQUIRES_SHARED(Locks::mutator_lock_); void FixupStaticTrampolines(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); @@ -850,7 +858,7 @@ class ClassLinker { 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 @@ class ClassLinker { ObjPtr<mirror::ClassLoader> class_loader) REQUIRES_SHARED(Locks::mutator_lock_); + // Implementation of ResolveString() called when the string was not found in the dex cache. + ObjPtr<mirror::String> DoResolveString(dex::StringIndex string_idx, + ObjPtr<mirror::DexCache> dex_cache) + REQUIRES_SHARED(Locks::mutator_lock_); + ObjPtr<mirror::String> DoResolveString(dex::StringIndex string_idx, + Handle<mirror::DexCache> dex_cache) + REQUIRES_SHARED(Locks::mutator_lock_); + + // Implementation of LookupString() called when the string was not found in the dex cache. + ObjPtr<mirror::String> DoLookupString(dex::StringIndex string_idx, + ObjPtr<mirror::DexCache> dex_cache) + REQUIRES_SHARED(Locks::mutator_lock_); + // Implementation of ResolveType() called when the type was not found in the dex cache. ObjPtr<mirror::Class> DoResolveType(dex::TypeIndex type_idx, ObjPtr<mirror::Class> referrer) @@ -1251,6 +1272,8 @@ class ClassLinker { ObjPtr<mirror::ClassLoader> class_loader) REQUIRES_SHARED(Locks::mutator_lock_); + ObjPtr<mirror::IfTable> GetArrayIfTable() REQUIRES_SHARED(Locks::mutator_lock_); + std::vector<const DexFile*> boot_class_path_; std::vector<std::unique_ptr<const DexFile>> boot_dex_files_; @@ -1280,9 +1303,6 @@ class ClassLinker { // Well known mirror::Class roots. GcRoot<mirror::ObjectArray<mirror::Class>> class_roots_; - // The interface table used by all arrays. - GcRoot<mirror::IfTable> array_iftable_; - // A cache of the last FindArrayClass results. The cache serves to avoid creating array class // descriptors for the sake of performing FindClass. static constexpr size_t kFindArrayCacheSize = 16; diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 5d420aae04..e40f1dbcdf 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -233,8 +233,7 @@ class ClassLinkerTest : public CommonRuntimeTest { 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 5c7819841b..4aa9801ab4 100644 --- a/runtime/class_root.h +++ b/runtime/class_root.h @@ -127,7 +127,7 @@ inline ObjPtr<mirror::Class> GetClassRoot( 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 c5bb4d57e6..cb334b569f 100644 --- a/runtime/debug_print.cc +++ b/runtime/debug_print.cc @@ -37,7 +37,7 @@ std::string DescribeSpace(ObjPtr<mirror::Class> klass) { 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 88628bbc50..f75f47c075 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -1388,7 +1388,7 @@ JDWP::JdwpError Dbg::CreateObject(JDWP::RefTypeId class_id, JDWP::ObjectId* new_ *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 @@ JDWP::JdwpError Dbg::CreateArrayObject(JDWP::RefTypeId array_class_id, uint32_t 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 @@ static JValue GetArtFieldValue(ArtField* f, mirror::Object* o) 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 5cb08dc278..9358cbe5a9 100644 --- a/runtime/dex/dex_file_annotations.cc +++ b/runtime/dex/dex_file_annotations.cc @@ -359,7 +359,7 @@ ObjPtr<mirror::Object> ProcessEncodedAnnotation(const ClassData& klass, const ui 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::ObjectArray<mirror::Object>> ProcessAnnotationSetRefList( 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 f6b1c73230..022857a4d5 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -268,14 +268,14 @@ inline mirror::Class* CheckArrayAlloc(dex::TypeIndex type_idx, // 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 @@ inline mirror::Array* AllocArrayFromCodeResolved(mirror::Class* klass, // 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 @@ inline ObjPtr<mirror::Class> ResolveVerifyAndClinit(dex::TypeIndex type_idx, return h_class.Get(); } -static inline ObjPtr<mirror::String> ResolveString(ClassLinker* class_linker, - dex::StringIndex string_idx, - ArtMethod* referrer) - REQUIRES_SHARED(Locks::mutator_lock_) { - Thread::PoisonObjectPointersIfDebug(); - ObjPtr<mirror::String> string = referrer->GetDexCache()->GetResolvedString(string_idx); - if (UNLIKELY(string == nullptr)) { - StackHandleScope<1> hs(Thread::Current()); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache())); - string = class_linker->ResolveString(string_idx, dex_cache); - } - return string; -} - -inline ObjPtr<mirror::String> ResolveStringFromCode(ArtMethod* referrer, - dex::StringIndex string_idx) { - Thread::PoisonObjectPointersIfDebug(); - ObjPtr<mirror::String> string = referrer->GetDexCache()->GetResolvedString(string_idx); - if (UNLIKELY(string == nullptr)) { - StackHandleScope<1> hs(Thread::Current()); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache())); - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - string = class_linker->ResolveString(string_idx, dex_cache); - } - return string; -} - inline void UnlockJniSynchronizedMethod(jobject locked, Thread* self) { // Save any pending exception over monitor exit call. mirror::Throwable* saved_exception = nullptr; diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h index e33de9c45a..9d70b03dfa 100644 --- a/runtime/entrypoints/entrypoint_utils.h +++ b/runtime/entrypoints/entrypoint_utils.h @@ -87,11 +87,11 @@ ALWAYS_INLINE inline mirror::Class* CheckArrayAlloc(dex::TypeIndex type_idx, // 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 @@ ObjPtr<mirror::MethodType> ResolveMethodTypeFromCode(ArtMethod* referrer, dex::P REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); -inline ObjPtr<mirror::String> ResolveStringFromCode(ArtMethod* referrer, - dex::StringIndex string_idx) - REQUIRES_SHARED(Locks::mutator_lock_) - REQUIRES(!Roles::uninterruptible_); - // TODO: annotalysis disabled as monitor semantics are maintained in Java code. inline void UnlockJniSynchronizedMethod(jobject locked, Thread* self) NO_THREAD_SAFETY_ANALYSIS REQUIRES(!Roles::uninterruptible_); diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc index fa536c77a9..62756123e1 100644 --- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc @@ -210,7 +210,8 @@ extern "C" mirror::String* artResolveStringFromCode(int32_t string_idx, Thread* auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self, CalleeSaveType::kSaveEverything); ArtMethod* caller = caller_and_outer.caller; - ObjPtr<mirror::String> result = ResolveStringFromCode(caller, dex::StringIndex(string_idx)); + ObjPtr<mirror::String> result = + Runtime::Current()->GetClassLinker()->ResolveString(dex::StringIndex(string_idx), caller); if (LIKELY(result != nullptr) && CanReferenceBss(caller_and_outer.outer_method, caller)) { StoreStringInBss(caller_and_outer.outer_method, dex::StringIndex(string_idx), result); } diff --git a/runtime/gc/heap_verification_test.cc b/runtime/gc/heap_verification_test.cc index 4f06ee6910..38695332bb 100644 --- a/runtime/gc/heap_verification_test.cc +++ b/runtime/gc/heap_verification_test.cc @@ -35,7 +35,7 @@ class VerificationTest : public CommonRuntimeTest { 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 dbe09e8c5b..e754fbcbae 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -1287,7 +1287,7 @@ class ImageSpaceLoader { bitmap->VisitMarkedRange(objects_begin, objects_end, fixup_object_visitor); // Fixup image roots. CHECK(app_image.InSource(reinterpret_cast<uintptr_t>( - image_header.GetImageRoots<kWithoutReadBarrier>()))); + image_header.GetImageRoots<kWithoutReadBarrier>().Ptr()))); image_header.RelocateImageObjects(app_image.Delta()); CHECK_EQ(image_header.GetImageBegin(), target_base); // Fix up dex cache DexFile pointers. diff --git a/runtime/image-inl.h b/runtime/image-inl.h index 3a66a34cb3..c527f6fbcc 100644 --- a/runtime/image-inl.h +++ b/runtime/image-inl.h @@ -23,18 +23,19 @@ #include "imt_conflict_table.h" #include "imtable.h" #include "mirror/object_array-inl.h" +#include "obj_ptr-inl.h" #include "read_barrier-inl.h" namespace art { template <ReadBarrierOption kReadBarrierOption> -inline mirror::Object* ImageHeader::GetImageRoot(ImageRoot image_root) const { - mirror::ObjectArray<mirror::Object>* image_roots = GetImageRoots<kReadBarrierOption>(); +inline ObjPtr<mirror::Object> ImageHeader::GetImageRoot(ImageRoot image_root) const { + ObjPtr<mirror::ObjectArray<mirror::Object>> image_roots = GetImageRoots<kReadBarrierOption>(); return image_roots->Get<kVerifyNone, kReadBarrierOption>(static_cast<int32_t>(image_root)); } template <ReadBarrierOption kReadBarrierOption> -inline mirror::ObjectArray<mirror::Object>* ImageHeader::GetImageRoots() const { +inline ObjPtr<mirror::ObjectArray<mirror::Object>> ImageHeader::GetImageRoots() const { // Need a read barrier as it's not visited during root scan. // Pass in the address of the local variable to the read barrier // rather than image_roots_ because it won't move (asserted below) diff --git a/runtime/image.cc b/runtime/image.cc index 7ad2e7bf95..17fc664bd7 100644 --- a/runtime/image.cc +++ b/runtime/image.cc @@ -26,7 +26,7 @@ namespace art { const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' }; -const uint8_t ImageHeader::kImageVersion[] = { '0', '6', '0', '\0' }; // ClassRoot::MethodHandle. +const uint8_t ImageHeader::kImageVersion[] = { '0', '6', '1', '\0' }; // Pre-allocated Throwables. ImageHeader::ImageHeader(uint32_t image_begin, uint32_t image_size, diff --git a/runtime/image.h b/runtime/image.h index 8acd5bc4c4..c6fc052a60 100644 --- a/runtime/image.h +++ b/runtime/image.h @@ -27,6 +27,7 @@ namespace art { class ArtField; class ArtMethod; +template <class MirrorType> class ObjPtr; namespace linker { class ImageWriter; @@ -206,7 +207,11 @@ class PACKED(4) ImageHeader { enum ImageRoot { kDexCaches, kClassRoots, - kClassLoader, // App image only. + kOomeWhenThrowingException, // Pre-allocated OOME when throwing exception. + kOomeWhenThrowingOome, // Pre-allocated OOME when throwing OOME. + kOomeWhenHandlingStackOverflow, // Pre-allocated OOME when handling StackOverflowError. + kNoClassDefFoundError, // Pre-allocated NoClassDefFoundError. + kClassLoader, // App image only. kImageRootsMax, }; @@ -277,11 +282,11 @@ class PACKED(4) ImageHeader { } template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier> - mirror::Object* GetImageRoot(ImageRoot image_root) const + ObjPtr<mirror::Object> GetImageRoot(ImageRoot image_root) const REQUIRES_SHARED(Locks::mutator_lock_); template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier> - mirror::ObjectArray<mirror::Object>* GetImageRoots() const + ObjPtr<mirror::ObjectArray<mirror::Object>> GetImageRoots() const REQUIRES_SHARED(Locks::mutator_lock_); void RelocateImage(off_t delta); diff --git a/runtime/indirect_reference_table-inl.h b/runtime/indirect_reference_table-inl.h index 9673bd9728..2128f8cde8 100644 --- a/runtime/indirect_reference_table-inl.h +++ b/runtime/indirect_reference_table-inl.h @@ -111,12 +111,12 @@ inline void IrtEntry::Add(ObjPtr<mirror::Object> obj) { 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 90e89cf3db..27f761a144 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -945,11 +945,9 @@ static bool GetArgumentForBootstrapMethod(Thread* self, return true; } case EncodedArrayValueIterator::ValueType::kString: { - StackHandleScope<1> hs(self); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache())); dex::StringIndex index(static_cast<uint32_t>(encoded_value->GetI())); ClassLinker* cl = Runtime::Current()->GetClassLinker(); - ObjPtr<mirror::String> o = cl->ResolveString(index, dex_cache); + ObjPtr<mirror::String> o = cl->ResolveString(index, referrer); if (UNLIKELY(o.IsNull())) { DCHECK(self->IsExceptionPending()); return false; diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h index 0ee780d32d..60bf50546f 100644 --- a/runtime/interpreter/interpreter_common.h +++ b/runtime/interpreter/interpreter_common.h @@ -340,12 +340,8 @@ static inline ObjPtr<mirror::String> ResolveString(Thread* self, } } ArtMethod* method = shadow_frame.GetMethod(); - ObjPtr<mirror::String> string_ptr = method->GetDexCache()->GetResolvedString(string_idx); - if (UNLIKELY(string_ptr == nullptr)) { - StackHandleScope<1> hs(self); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache())); - string_ptr = Runtime::Current()->GetClassLinker()->ResolveString(string_idx, dex_cache); - } + ObjPtr<mirror::String> string_ptr = + Runtime::Current()->GetClassLinker()->ResolveString(string_idx, method); return string_ptr; } diff --git a/runtime/interpreter/mterp/mterp.cc b/runtime/interpreter/mterp/mterp.cc index d62f511ad5..e4cc6d3f9f 100644 --- a/runtime/interpreter/mterp/mterp.cc +++ b/runtime/interpreter/mterp/mterp.cc @@ -559,7 +559,7 @@ extern "C" size_t MterpNewArray(ShadowFrame* shadow_frame, 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 7abb007838..667bd03c18 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -1691,7 +1691,7 @@ void UnstartedRuntime::UnstartedJNIVMRuntimeNewUnpaddedArray( 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 @@ void UnstartedRuntime::UnstartedJNIArrayCreateObjectArray( 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 449458ce6f..655713e8c6 100644 --- a/runtime/interpreter/unstarted_runtime_test.cc +++ b/runtime/interpreter/unstarted_runtime_test.cc @@ -91,7 +91,7 @@ class UnstartedRuntimeTest : public CommonRuntimeTest { 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 d8aa00c45e..b010650345 100644 --- a/runtime/jit/jit_code_cache.cc +++ b/runtime/jit/jit_code_cache.cc @@ -471,7 +471,7 @@ static void FillRootTable(uint8_t* roots_data, Handle<mirror::ObjectArray<mirror 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 987c8e974f..7290d638f3 100644 --- a/runtime/jni/jni_internal.cc +++ b/runtime/jni/jni_internal.cc @@ -2036,14 +2036,14 @@ class JNI { 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 @@ class JNI { 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 28df1749a4..01a32a2288 100644 --- a/runtime/method_handles.cc +++ b/runtime/method_handles.cc @@ -268,7 +268,7 @@ bool ConvertJValueCommon( // 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 @@ inline void CopyArgumentsFromCallerFrame(const ShadowFrame& caller_frame, // 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 0db9551265..d123754e47 100644 --- a/runtime/method_handles_test.cc +++ b/runtime/method_handles_test.cc @@ -179,7 +179,7 @@ TEST_F(MethodHandlesTest, SupportedReferenceCast) { 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 @@ TEST_F(MethodHandlesTest, UnsupportedReferenceCast) { 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 @@ TEST_F(MethodHandlesTest, SupportedBoxedToPrimitiveConversion) { 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 @@ TEST_F(MethodHandlesTest, SupportedBoxedToWiderPrimitiveConversion) { 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 @@ TEST_F(MethodHandlesTest, UnsupportedBoxedToNarrowerPrimitiveConversionNoCast) { 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 @@ TEST_F(MethodHandlesTest, UnsupportedBoxedToNarrowerPrimitiveConversionWithCast) 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 d2adcb4766..2e395302af 100644 --- a/runtime/mirror/array-inl.h +++ b/runtime/mirror/array-inl.h @@ -151,11 +151,11 @@ class SetLengthToUsableSizeVisitor { }; 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 @@ inline Array* Array::Alloc(Thread* self, } #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 @@ inline Array* Array::Alloc(Thread* self, } 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 06ce0bb5dd..66ec368935 100644 --- a/runtime/mirror/array.cc +++ b/runtime/mirror/array.cc @@ -42,17 +42,18 @@ using android::base::StringPrintf; // 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 @@ static Array* RecursiveCreateMultiArray(Thread* self, 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 @@ static Array* RecursiveCreateMultiArray(Thread* self, 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 @@ Array* Array::CreateMultiArray(Thread* self, Handle<Class> element_class, // 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 @@ Array* Array::CreateMultiArray(Thread* self, Handle<Class> element_class, } 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 @@ void Array::ThrowArrayStoreException(ObjPtr<Object> object) { 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 @@ Array* Array::CopyOf(Thread* self, int32_t new_length) { 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 aeaaf67310..8bdd561ec4 100644 --- a/runtime/mirror/array.h +++ b/runtime/mirror/array.h @@ -37,17 +37,17 @@ class MANAGED Array : public Object { // 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 @@ class MANAGED Array : public Object { 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 @@ class MANAGED PrimitiveArray : public Array { 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 5328ad979f..fffd7f3062 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -294,7 +294,7 @@ inline PointerArray* Class::GetVTableDuringLinking() { 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 @@ inline bool Class::ResolvedMethodAccessTest(ObjPtr<Class> access_to, 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 @@ inline ObjPtr<Object> Class::Alloc(Thread* self, gc::AllocatorType allocator_typ 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 31a83f8e48..44b0c2b007 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -419,7 +419,7 @@ bool Class::IsInSamePackage(ObjPtr<Class> that) { } bool Class::IsThrowableClass() { - return WellKnownClasses::ToClass(WellKnownClasses::java_lang_Throwable)->IsAssignableFrom(this); + return GetClassRoot<mirror::Throwable>()->IsAssignableFrom(this); } void Class::SetClassLoader(ObjPtr<ClassLoader> new_class_loader) { @@ -1269,7 +1269,7 @@ ObjPtr<Method> Class::GetDeclaredMethodInternal( for (auto& m : h_klass->GetDeclaredVirtualMethods(kPointerSize)) { auto* np_method = m.GetInterfaceMethodIfProxy(kPointerSize); // May cause thread suspension. - ObjPtr<String> np_name = np_method->GetNameAsString(self); + ObjPtr<String> np_name = np_method->ResolveNameString(); if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) { if (UNLIKELY(self->IsExceptionPending())) { return nullptr; @@ -1291,7 +1291,7 @@ ObjPtr<Method> Class::GetDeclaredMethodInternal( } auto* np_method = m.GetInterfaceMethodIfProxy(kPointerSize); // May cause thread suspension. - ObjPtr<String> np_name = np_method->GetNameAsString(self); + ObjPtr<String> np_name = np_method->ResolveNameString(); if (np_name == nullptr) { self->AssertPendingException(); return nullptr; diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 6feaa9cd74..c3e167c306 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -781,7 +781,7 @@ class MANAGED Class FINAL : public Object { 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 7214620c93..44bf9891cd 100644 --- a/runtime/mirror/class_ext.cc +++ b/runtime/mirror/class_ext.cc @@ -43,8 +43,8 @@ void ClassExt::SetObsoleteArrays(ObjPtr<PointerArray> methods, 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 cd822c244e..ee4f53b695 100644 --- a/runtime/mirror/object-inl.h +++ b/runtime/mirror/object-inl.h @@ -114,10 +114,6 @@ inline void Object::NotifyAll(Thread* self) { Monitor::NotifyAll(self, this); } -inline void Object::Wait(Thread* self) { - Monitor::Wait(self, this, 0, 0, true, kWaiting); -} - inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) { Monitor::Wait(self, this, ms, ns, true, kTimedWaiting); } @@ -776,7 +772,7 @@ inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, } 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 8584b8a56f..a89d6323a5 100644 --- a/runtime/mirror/object.h +++ b/runtime/mirror/object.h @@ -176,7 +176,6 @@ class MANAGED LOCKABLE Object { UNLOCK_FUNCTION(); void Notify(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_); void NotifyAll(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_); - void Wait(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_); void Wait(Thread* self, int64_t timeout, int32_t nanos) REQUIRES_SHARED(Locks::mutator_lock_); template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h index 086d2f4672..ed3c567464 100644 --- a/runtime/mirror/object_array-inl.h +++ b/runtime/mirror/object_array-inl.h @@ -37,14 +37,15 @@ namespace art { 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 @@ inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, } 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 @@ inline void ObjectArray<T>::AssignableCheckingMemcpy(int32_t dst_pos, } 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 @@ inline ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) 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 b7a956176f..6506f6ea9a 100644 --- a/runtime/mirror/object_array.h +++ b/runtime/mirror/object_array.h @@ -31,15 +31,15 @@ class MANAGED ObjectArray: public Array { 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 @@ class MANAGED ObjectArray: public Array { 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 8b7a1b6876..0b615a6b9a 100644 --- a/runtime/mirror/object_test.cc +++ b/runtime/mirror/object_test.cc @@ -76,7 +76,7 @@ class ObjectTest : public CommonRuntimeTest { } 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 @@ void TestPrimitiveArray(ClassLinker* cl) { 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 @@ void TestPrimitiveArray(ClassLinker* cl) { 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 @@ TEST_F(ObjectTest, PrimitiveArray_Double_Alloc) { 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 @@ TEST_F(ObjectTest, PrimitiveArray_Double_Alloc) { 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 @@ TEST_F(ObjectTest, PrimitiveArray_Float_Alloc) { 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 @@ TEST_F(ObjectTest, PrimitiveArray_Float_Alloc) { 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, PrimitiveArray_Float_Alloc) { 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 @@ TEST_F(ObjectTest, CreateMultiArray) { 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 @@ TEST_F(ObjectTest, PrettyTypeOf) { 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 6c820190b4..3227c69305 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -32,6 +32,7 @@ extern "C" void android_set_application_target_sdk_version(uint32_t version); #include "class_linker-inl.h" #include "common_throws.h" #include "debugger.h" +#include "dex/class_accessor-inl.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_types.h" #include "gc/accounting/card_table-inl.h" @@ -111,7 +112,7 @@ static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaEle } 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 @@ static jobject VMRuntime_newUnpaddedArray(JNIEnv* env, jobject, jclass javaEleme } 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 @@ static void VMRuntime_preloadDexCaches(JNIEnv* env, jobject) { } if (kPreloadDexCachesFieldsAndMethods) { - for (size_t class_def_index = 0; - class_def_index < dex_file->NumClassDefs(); - class_def_index++) { - const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index); - const uint8_t* class_data = dex_file->GetClassData(class_def); - if (class_data == nullptr) { - continue; + for (ClassAccessor accessor : dex_file->GetClasses()) { + for (const ClassAccessor::Field& field : accessor.GetFields()) { + PreloadDexCachesResolveField(dex_cache, field.GetIndex(), field.IsStatic()); } - ClassDataItemIterator it(*dex_file, class_data); - for (; it.HasNextStaticField(); it.Next()) { - uint32_t field_idx = it.GetMemberIndex(); - PreloadDexCachesResolveField(dex_cache, field_idx, true); - } - for (; it.HasNextInstanceField(); it.Next()) { - uint32_t field_idx = it.GetMemberIndex(); - PreloadDexCachesResolveField(dex_cache, field_idx, false); - } - for (; it.HasNextDirectMethod(); it.Next()) { - uint32_t method_idx = it.GetMemberIndex(); - PreloadDexCachesResolveMethod(dex_cache, method_idx); - } - for (; it.HasNextVirtualMethod(); it.Next()) { - uint32_t method_idx = it.GetMemberIndex(); - PreloadDexCachesResolveMethod(dex_cache, method_idx); + for (const ClassAccessor::Method& method : accessor.GetMethods()) { + PreloadDexCachesResolveMethod(dex_cache, method.GetIndex()); } } } diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc index 38c65f5deb..5b47eaca86 100644 --- a/runtime/native/dalvik_system_ZygoteHooks.cc +++ b/runtime/native/dalvik_system_ZygoteHooks.cc @@ -100,7 +100,7 @@ class ClassSet { } 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 c6bdfa10c6..82e54e2f4c 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -646,8 +646,8 @@ static jobjectArray Class_getDeclaredAnnotations(JNIEnv* env, jobject javaThis) 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 208ccf6a82..48540f877d 100644 --- a/runtime/native/java_lang_Object.cc +++ b/runtime/native/java_lang_Object.cc @@ -41,11 +41,6 @@ static void Object_notifyAll(JNIEnv* env, jobject java_this) { soa.Decode<mirror::Object>(java_this)->NotifyAll(soa.Self()); } -static void Object_wait(JNIEnv* env, jobject java_this) { - ScopedFastNativeObjectAccess soa(env); - soa.Decode<mirror::Object>(java_this)->Wait(soa.Self()); -} - static void Object_waitJI(JNIEnv* env, jobject java_this, jlong ms, jint ns) { ScopedFastNativeObjectAccess soa(env); soa.Decode<mirror::Object>(java_this)->Wait(soa.Self(), ms, ns); @@ -61,7 +56,6 @@ static JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(Object, internalClone, "()Ljava/lang/Object;"), FAST_NATIVE_METHOD(Object, notify, "()V"), FAST_NATIVE_METHOD(Object, notifyAll, "()V"), - OVERLOADED_FAST_NATIVE_METHOD(Object, wait, "()V", wait), OVERLOADED_FAST_NATIVE_METHOD(Object, wait, "(JI)V", waitJI), FAST_NATIVE_METHOD(Object, identityHashCodeNative, "(Ljava/lang/Object;)I"), }; diff --git a/runtime/native/java_lang_Thread.cc b/runtime/native/java_lang_Thread.cc index a37a76f809..13871f7be7 100644 --- a/runtime/native/java_lang_Thread.cc +++ b/runtime/native/java_lang_Thread.cc @@ -119,7 +119,7 @@ static jboolean Thread_holdsLock(JNIEnv* env, jclass, jobject java_object) { 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 42c7ad5650..1ad233a6b2 100644 --- a/runtime/native/java_lang_VMClassLoader.cc +++ b/runtime/native/java_lang_VMClassLoader.cc @@ -86,7 +86,7 @@ static jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoa } // 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 8bcda10f2a..452a66dca2 100644 --- a/runtime/native/java_lang_reflect_Array.cc +++ b/runtime/native/java_lang_reflect_Array.cc @@ -44,9 +44,8 @@ static jobject Array_createMultiArray( 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 @@ static jobject Array_createObjectArray(JNIEnv* env, jclass, jclass javaElementCl 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 a40cb9b2e6..a10db9115f 100644 --- a/runtime/native/java_lang_reflect_Executable.cc +++ b/runtime/native/java_lang_reflect_Executable.cc @@ -320,7 +320,7 @@ static jstring Executable_getMethodNameInternal(JNIEnv* env, jobject javaMethod) ScopedFastNativeObjectAccess soa(env); ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod); method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize); - return soa.AddLocalReference<jstring>(method->GetNameAsString(soa.Self())); + return soa.AddLocalReference<jstring>(method->ResolveNameString()); } static jclass Executable_getMethodReturnTypeInternal(JNIEnv* env, jobject javaMethod) { diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc index 25599843e9..895b2f9fd7 100644 --- a/runtime/native/java_lang_reflect_Field.cc +++ b/runtime/native/java_lang_reflect_Field.cc @@ -464,8 +464,7 @@ static jlong Field_getArtField(JNIEnv* env, jobject javaField) { static jstring Field_getNameInternal(JNIEnv* env, jobject javaField) { ScopedFastNativeObjectAccess soa(env); ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField(); - return soa.AddLocalReference<jstring>( - field->GetStringName(soa.Self(), true /* resolve */)); + return soa.AddLocalReference<jstring>(field->ResolveNameString()); } static jobjectArray Field_getDeclaredAnnotations(JNIEnv* env, jobject javaField) { @@ -476,7 +475,7 @@ static jobjectArray Field_getDeclaredAnnotations(JNIEnv* env, jobject javaField) 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 34455fe00f..87fda6bf5d 100644 --- a/runtime/native/java_lang_reflect_Method.cc +++ b/runtime/native/java_lang_reflect_Method.cc @@ -69,7 +69,7 @@ static jobjectArray Method_getExceptionTypes(JNIEnv* env, jobject javaMethod) { // 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 e7e5848dd6..72eb27d69e 100644 --- a/runtime/oat.h +++ b/runtime/oat.h @@ -32,8 +32,8 @@ class InstructionSetFeatures; class PACKED(4) OatHeader { public: static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' }; - // Last oat version changed reason: Rewrite dex register map encoding. - static constexpr uint8_t kOatVersion[] = { '1', '4', '6', '\0' }; + // Last oat version changed reason: Rewrite TypeLookupTable. + static constexpr uint8_t kOatVersion[] = { '1', '4', '7', '\0' }; static constexpr const char* kImageLocationKey = "image-location"; static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline"; diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index ffbc26c647..2b05b0e3dd 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -1687,6 +1687,7 @@ OatFile::OatDexFile::OatDexFile(const OatFile* oat_file, type_bss_mapping_(type_bss_mapping_data), string_bss_mapping_(string_bss_mapping_data), oat_class_offsets_pointer_(oat_class_offsets_pointer), + lookup_table_(), dex_layout_sections_(dex_layout_sections) { // Initialize TypeLookupTable. if (lookup_table_data_ != nullptr) { @@ -1706,7 +1707,7 @@ OatFile::OatDexFile::OatDexFile(const OatFile* oat_file, } } -OatFile::OatDexFile::OatDexFile(std::unique_ptr<TypeLookupTable>&& lookup_table) +OatFile::OatDexFile::OatDexFile(TypeLookupTable&& lookup_table) : lookup_table_(std::move(lookup_table)) {} OatFile::OatDexFile::~OatDexFile() {} @@ -1783,9 +1784,9 @@ const DexFile::ClassDef* OatFile::OatDexFile::FindClassDef(const DexFile& dex_fi DCHECK_EQ(ComputeModifiedUtf8Hash(descriptor), hash); bool used_lookup_table = false; const DexFile::ClassDef* lookup_table_classdef = nullptr; - if (LIKELY((oat_dex_file != nullptr) && (oat_dex_file->GetTypeLookupTable() != nullptr))) { + if (LIKELY((oat_dex_file != nullptr) && oat_dex_file->GetTypeLookupTable().Valid())) { used_lookup_table = true; - const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable()->Lookup(descriptor, hash); + const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable().Lookup(descriptor, hash); lookup_table_classdef = (class_def_idx != dex::kDexNoIndex) ? &dex_file.GetClassDef(class_def_idx) : nullptr; @@ -1796,6 +1797,7 @@ const DexFile::ClassDef* OatFile::OatDexFile::FindClassDef(const DexFile& dex_fi // Fast path for rare no class defs case. const uint32_t num_class_defs = dex_file.NumClassDefs(); if (num_class_defs == 0) { + DCHECK(!used_lookup_table); return nullptr; } const DexFile::TypeId* type_id = dex_file.FindTypeId(descriptor); diff --git a/runtime/oat_file.h b/runtime/oat_file.h index 8e18cee729..d72b6a8971 100644 --- a/runtime/oat_file.h +++ b/runtime/oat_file.h @@ -514,14 +514,14 @@ class OatDexFile FINAL { // Madvise the dex file based on the state we are moving to. static void MadviseDexFile(const DexFile& dex_file, MadviseState state); - TypeLookupTable* GetTypeLookupTable() const { - return lookup_table_.get(); + const TypeLookupTable& GetTypeLookupTable() const { + return lookup_table_; } ~OatDexFile(); // Create only with a type lookup table, used by the compiler to speed up compilation. - explicit OatDexFile(std::unique_ptr<TypeLookupTable>&& lookup_table); + explicit OatDexFile(TypeLookupTable&& lookup_table); // Return the dex layout sections. const DexLayoutSections* GetDexLayoutSections() const { @@ -553,7 +553,7 @@ class OatDexFile FINAL { const IndexBssMapping* const type_bss_mapping_ = nullptr; const IndexBssMapping* const string_bss_mapping_ = nullptr; const uint32_t* const oat_class_offsets_pointer_ = 0u; - mutable std::unique_ptr<TypeLookupTable> lookup_table_; + TypeLookupTable lookup_table_; const DexLayoutSections* const dex_layout_sections_ = nullptr; friend class OatFile; diff --git a/runtime/reference_table_test.cc b/runtime/reference_table_test.cc index 06ea384aa3..1d54d21187 100644 --- a/runtime/reference_table_test.cc +++ b/runtime/reference_table_test.cc @@ -106,7 +106,7 @@ TEST_F(ReferenceTableTest, Basics) { } // 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 @@ TEST_F(ReferenceTableTest, SummaryOrder) { 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 26fb021903..9fe4bca9dd 100644 --- a/runtime/reflection-inl.h +++ b/runtime/reflection-inl.h @@ -121,7 +121,7 @@ inline bool VerifyObjectIsClass(ObjPtr<mirror::Object> o, ObjPtr<mirror::Class> 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 66eba1e1d4..6aeedd4f02 100644 --- a/runtime/reflection.cc +++ b/runtime/reflection.cc @@ -243,7 +243,7 @@ class ArgArray { // 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 0d9d16cd01..1e327fc8ed 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -1090,6 +1090,17 @@ void Runtime::SetSentinel(mirror::Object* sentinel) { sentinel_ = GcRoot<mirror::Object>(sentinel); } +static inline void InitPreAllocatedException(Thread* self, + GcRoot<mirror::Throwable>* exception, + const char* exception_class_descriptor, + const char* msg) + REQUIRES_SHARED(Locks::mutator_lock_) { + DCHECK_EQ(self, Thread::Current()); + self->ThrowNewException(exception_class_descriptor, msg); + *exception = GcRoot<mirror::Throwable>(self->GetException()); + self->ClearException(); +} + bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { // (b/30160149): protect subprocesses from modifications to LD_LIBRARY_PATH, etc. // Take a snapshot of the environment at the time the runtime was created, for use by Exec, etc. @@ -1505,34 +1516,54 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { // TODO: move this to just be an Trace::Start argument Trace::SetDefaultClockSource(runtime_options.GetOrDefault(Opt::ProfileClock)); - // Pre-allocate an OutOfMemoryError for the case when we fail to - // allocate the exception to be thrown. - InitPreAllocatedException(self, - &Runtime::pre_allocated_OutOfMemoryError_when_throwing_exception_, - "Ljava/lang/OutOfMemoryError;", - "OutOfMemoryError thrown while trying to throw an exception; " - "no stack trace available"); - // Pre-allocate an OutOfMemoryError for the double-OOME case. - InitPreAllocatedException(self, - &Runtime::pre_allocated_OutOfMemoryError_when_throwing_oome_, - "Ljava/lang/OutOfMemoryError;", - "OutOfMemoryError thrown while trying to throw OutOfMemoryError; " - "no stack trace available"); - // Pre-allocate an OutOfMemoryError for the case when we fail to - // allocate while handling a stack overflow. - InitPreAllocatedException(self, - &Runtime::pre_allocated_OutOfMemoryError_when_handling_stack_overflow_, - "Ljava/lang/OutOfMemoryError;", - "OutOfMemoryError thrown while trying to handle a stack overflow; " - "no stack trace available"); - - // Pre-allocate a NoClassDefFoundError for the common case of failing to find a system class - // ahead of checking the application's class loader. - InitPreAllocatedException(self, - &Runtime::pre_allocated_NoClassDefFoundError_, - "Ljava/lang/NoClassDefFoundError;", - "Class not found using the boot class loader; " - "no stack trace available"); + if (GetHeap()->HasBootImageSpace()) { + const ImageHeader& image_header = GetHeap()->GetBootImageSpaces()[0]->GetImageHeader(); + pre_allocated_OutOfMemoryError_when_throwing_exception_ = GcRoot<mirror::Throwable>( + image_header.GetImageRoot(ImageHeader::kOomeWhenThrowingException)->AsThrowable()); + DCHECK(pre_allocated_OutOfMemoryError_when_throwing_exception_.Read()->GetClass() + ->DescriptorEquals("Ljava/lang/OutOfMemoryError;")); + pre_allocated_OutOfMemoryError_when_throwing_oome_ = GcRoot<mirror::Throwable>( + image_header.GetImageRoot(ImageHeader::kOomeWhenThrowingOome)->AsThrowable()); + DCHECK(pre_allocated_OutOfMemoryError_when_throwing_oome_.Read()->GetClass() + ->DescriptorEquals("Ljava/lang/OutOfMemoryError;")); + pre_allocated_OutOfMemoryError_when_handling_stack_overflow_ = GcRoot<mirror::Throwable>( + image_header.GetImageRoot(ImageHeader::kOomeWhenHandlingStackOverflow)->AsThrowable()); + DCHECK(pre_allocated_OutOfMemoryError_when_handling_stack_overflow_.Read()->GetClass() + ->DescriptorEquals("Ljava/lang/OutOfMemoryError;")); + pre_allocated_NoClassDefFoundError_ = GcRoot<mirror::Throwable>( + image_header.GetImageRoot(ImageHeader::kNoClassDefFoundError)->AsThrowable()); + DCHECK(pre_allocated_NoClassDefFoundError_.Read()->GetClass() + ->DescriptorEquals("Ljava/lang/NoClassDefFoundError;")); + } else { + // Pre-allocate an OutOfMemoryError for the case when we fail to + // allocate the exception to be thrown. + InitPreAllocatedException(self, + &pre_allocated_OutOfMemoryError_when_throwing_exception_, + "Ljava/lang/OutOfMemoryError;", + "OutOfMemoryError thrown while trying to throw an exception; " + "no stack trace available"); + // Pre-allocate an OutOfMemoryError for the double-OOME case. + InitPreAllocatedException(self, + &pre_allocated_OutOfMemoryError_when_throwing_oome_, + "Ljava/lang/OutOfMemoryError;", + "OutOfMemoryError thrown while trying to throw OutOfMemoryError; " + "no stack trace available"); + // Pre-allocate an OutOfMemoryError for the case when we fail to + // allocate while handling a stack overflow. + InitPreAllocatedException(self, + &pre_allocated_OutOfMemoryError_when_handling_stack_overflow_, + "Ljava/lang/OutOfMemoryError;", + "OutOfMemoryError thrown while trying to handle a stack overflow; " + "no stack trace available"); + + // Pre-allocate a NoClassDefFoundError for the common case of failing to find a system class + // ahead of checking the application's class loader. + InitPreAllocatedException(self, + &pre_allocated_NoClassDefFoundError_, + "Ljava/lang/NoClassDefFoundError;", + "Class not found using the boot class loader; " + "no stack trace available"); + } // Runtime initialization is largely done now. // We load plugins first since that can modify the runtime state slightly. @@ -1682,16 +1713,6 @@ void Runtime::AttachAgent(JNIEnv* env, const std::string& agent_arg, jobject cla } } -void Runtime::InitPreAllocatedException(Thread* self, - GcRoot<mirror::Throwable> Runtime::* exception, - const char* exception_class_descriptor, - const char* msg) { - DCHECK_EQ(self, Thread::Current()); - self->ThrowNewException(exception_class_descriptor, msg); - this->*exception = GcRoot<mirror::Throwable>(self->GetException()); - self->ClearException(); -} - void Runtime::InitNativeMethods() { VLOG(startup) << "Runtime::InitNativeMethods entering"; Thread* self = Thread::Current(); @@ -2048,9 +2069,10 @@ void Runtime::VisitImageRoots(RootVisitor* visitor) { auto* image_space = space->AsImageSpace(); const auto& image_header = image_space->GetImageHeader(); for (int32_t i = 0, size = image_header.GetImageRoots()->GetLength(); i != size; ++i) { - auto* obj = image_header.GetImageRoot(static_cast<ImageHeader::ImageRoot>(i)); + mirror::Object* obj = + image_header.GetImageRoot(static_cast<ImageHeader::ImageRoot>(i)).Ptr(); if (obj != nullptr) { - auto* after_obj = obj; + mirror::Object* after_obj = obj; visitor->VisitRoot(&after_obj, RootInfo(kRootStickyClass)); CHECK_EQ(after_obj, obj); } diff --git a/runtime/runtime.h b/runtime/runtime.h index 10f72e7c5b..d85490c0a6 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -774,11 +774,6 @@ class Runtime { bool Init(RuntimeArgumentMap&& runtime_options) SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_); - void InitPreAllocatedException(Thread* self, - GcRoot<mirror::Throwable> Runtime::* exception, - const char* exception_class_descriptor, - const char* msg) - REQUIRES_SHARED(Locks::mutator_lock_); void InitNativeMethods() REQUIRES(!Locks::mutator_lock_); void RegisterRuntimeNativeMethods(JNIEnv* env); diff --git a/runtime/thread.cc b/runtime/thread.cc index b59606a06b..a8133a1fda 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -491,7 +491,7 @@ Thread* Thread::FromManagedThread(const ScopedObjectAccessAlreadyRunnable& soa, 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 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray( 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 02e61d76a1..370a619820 100644 --- a/runtime/transaction_test.cc +++ b/runtime/transaction_test.cc @@ -506,7 +506,7 @@ TEST_F(TransactionTest, ResolveString) { 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 838d7f14bc..32aa86dc93 100644 --- a/runtime/vdex_file.cc +++ b/runtime/vdex_file.cc @@ -28,6 +28,7 @@ #include "base/stl_util.h" #include "base/unix_file/fd_file.h" #include "dex/art_dex_file_loader.h" +#include "dex/class_accessor-inl.h" #include "dex/dex_file.h" #include "dex/dex_file_loader.h" #include "dex/hidden_api_access_flags.h" @@ -283,30 +284,25 @@ void VdexFile::UnquickenDexFile(const DexFile& target_dex_file, std::unordered_set<const DexFile::CodeItem*> unquickened_code_item; CompactOffsetTable::Accessor accessor(GetQuickenInfoOffsetTable(source_dex_begin, quickening_info)); - for (uint32_t i = 0; i < target_dex_file.NumClassDefs(); ++i) { - const DexFile::ClassDef& class_def = target_dex_file.GetClassDef(i); - const uint8_t* class_data = target_dex_file.GetClassData(class_def); - if (class_data != nullptr) { - for (ClassDataItemIterator class_it(target_dex_file, class_data); - class_it.HasNext(); - class_it.Next()) { - if (class_it.IsAtMethod()) { - const DexFile::CodeItem* code_item = class_it.GetMethodCodeItem(); - if (code_item != nullptr && unquickened_code_item.emplace(code_item).second) { - const uint32_t offset = accessor.GetOffset(class_it.GetMemberIndex()); - // Offset being 0 means not quickened. - if (offset != 0u) { - ArrayRef<const uint8_t> quicken_data = GetQuickeningInfoAt(quickening_info, offset); - optimizer::ArtDecompileDEX( - target_dex_file, - *code_item, - quicken_data, - decompile_return_instruction); - } - } + for (ClassAccessor class_accessor : target_dex_file.GetClasses()) { + for (const ClassAccessor::Method& method : class_accessor.GetMethods()) { + const DexFile::CodeItem* code_item = method.GetCodeItem(); + if (code_item != nullptr && unquickened_code_item.emplace(code_item).second) { + const uint32_t offset = accessor.GetOffset(method.GetIndex()); + // Offset being 0 means not quickened. + if (offset != 0u) { + ArrayRef<const uint8_t> quicken_data = GetQuickeningInfoAt(quickening_info, offset); + optimizer::ArtDecompileDEX( + target_dex_file, + *code_item, + quicken_data, + decompile_return_instruction); } - DexFile::UnHideAccessFlags(class_it); } + method.UnHideAccessFlags(); + } + for (const ClassAccessor::Field& field : class_accessor.GetFields()) { + field.UnHideAccessFlags(); } } } diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 2e3a6590e4..59617481eb 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -35,6 +35,7 @@ #include "class_linker.h" #include "class_root.h" #include "compiler_callbacks.h" +#include "dex/class_accessor-inl.h" #include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_exception_helpers.h" @@ -190,11 +191,6 @@ FailureKind MethodVerifier::VerifyClass(Thread* self, error); } -template <bool kDirect> -static bool HasNextMethod(ClassDataItemIterator* it) { - return kDirect ? it->HasNextDirectMethod() : it->HasNextVirtualMethod(); -} - static FailureKind FailureKindMax(FailureKind fk1, FailureKind fk2) { static_assert(FailureKind::kNoFailure < FailureKind::kSoftFailure && FailureKind::kSoftFailure < FailureKind::kHardFailure, @@ -207,45 +203,51 @@ void MethodVerifier::FailureData::Merge(const MethodVerifier::FailureData& fd) { types |= fd.types; } -template <bool kDirect> -MethodVerifier::FailureData MethodVerifier::VerifyMethods(Thread* self, - ClassLinker* linker, - const DexFile* dex_file, - const DexFile::ClassDef& class_def, - ClassDataItemIterator* it, - Handle<mirror::DexCache> dex_cache, - Handle<mirror::ClassLoader> class_loader, - CompilerCallbacks* callbacks, - bool allow_soft_failures, - HardFailLogMode log_level, - bool need_precise_constants, - std::string* error_string) { - DCHECK(it != nullptr); +FailureKind MethodVerifier::VerifyClass(Thread* self, + const DexFile* dex_file, + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> class_loader, + const DexFile::ClassDef& class_def, + CompilerCallbacks* callbacks, + bool allow_soft_failures, + HardFailLogMode log_level, + std::string* error) { + SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(dex_file->GetClassDescriptor(class_def)); + // A class must not be abstract and final. + if ((class_def.access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) { + *error = "Verifier rejected class "; + *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def)); + *error += ": class is abstract and final."; + return FailureKind::kHardFailure; + } + + ClassAccessor accessor(*dex_file, class_def); + + int64_t previous_method_idx[2] = { -1, -1 }; MethodVerifier::FailureData failure_data; + ClassLinker* const linker = Runtime::Current()->GetClassLinker(); - int64_t previous_method_idx = -1; - while (HasNextMethod<kDirect>(it)) { + for (const ClassAccessor::Method& method : accessor.GetMethods()) { + int64_t* previous_idx = &previous_method_idx[method.IsStaticOrDirect() ? 0u : 1u]; self->AllowThreadSuspension(); - uint32_t method_idx = it->GetMemberIndex(); - if (method_idx == previous_method_idx) { + const uint32_t method_idx = method.GetIndex(); + if (method_idx == *previous_idx) { // smali can create dex files with two encoded_methods sharing the same method_idx // http://code.google.com/p/smali/issues/detail?id=119 - it->Next(); continue; } - previous_method_idx = method_idx; - InvokeType type = it->GetMethodInvokeType(class_def); - ArtMethod* method = linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>( + *previous_idx = method_idx; + const InvokeType type = method.GetInvokeType(class_def.access_flags_); + ArtMethod* resolved_method = linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>( method_idx, dex_cache, class_loader, /* referrer */ nullptr, type); - if (method == nullptr) { + if (resolved_method == nullptr) { DCHECK(self->IsExceptionPending()); // We couldn't resolve the method, but continue regardless. self->ClearException(); } else { - DCHECK(method->GetDeclaringClassUnchecked() != nullptr) << type; + DCHECK(resolved_method->GetDeclaringClassUnchecked() != nullptr) << type; } - StackHandleScope<1> hs(self); std::string hard_failure_msg; MethodVerifier::FailureData result = VerifyMethod(self, method_idx, @@ -253,99 +255,39 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethods(Thread* self, dex_cache, class_loader, class_def, - it->GetMethodCodeItem(), - method, - it->GetMethodAccessFlags(), + method.GetCodeItem(), + resolved_method, + method.GetAccessFlags(), callbacks, allow_soft_failures, log_level, - need_precise_constants, + /*need_precise_constants*/ false, &hard_failure_msg); if (result.kind == FailureKind::kHardFailure) { if (failure_data.kind == FailureKind::kHardFailure) { // If we logged an error before, we need a newline. - *error_string += "\n"; + *error += "\n"; } else { // If we didn't log a hard failure before, print the header of the message. - *error_string += "Verifier rejected class "; - *error_string += PrettyDescriptor(dex_file->GetClassDescriptor(class_def)); - *error_string += ":"; + *error += "Verifier rejected class "; + *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def)); + *error += ":"; } - *error_string += " "; - *error_string += hard_failure_msg; + *error += " "; + *error += hard_failure_msg; } failure_data.Merge(result); - it->Next(); - } - - return failure_data; -} - -FailureKind MethodVerifier::VerifyClass(Thread* self, - const DexFile* dex_file, - Handle<mirror::DexCache> dex_cache, - Handle<mirror::ClassLoader> class_loader, - const DexFile::ClassDef& class_def, - CompilerCallbacks* callbacks, - bool allow_soft_failures, - HardFailLogMode log_level, - std::string* error) { - SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(dex_file->GetClassDescriptor(class_def)); - - // A class must not be abstract and final. - if ((class_def.access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) { - *error = "Verifier rejected class "; - *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def)); - *error += ": class is abstract and final."; - return FailureKind::kHardFailure; } - const uint8_t* class_data = dex_file->GetClassData(class_def); - if (class_data == nullptr) { - // empty class, probably a marker interface - return FailureKind::kNoFailure; - } - ClassDataItemIterator it(*dex_file, class_data); - it.SkipAllFields(); - ClassLinker* linker = Runtime::Current()->GetClassLinker(); - // Direct methods. - MethodVerifier::FailureData data1 = VerifyMethods<true>(self, - linker, - dex_file, - class_def, - &it, - dex_cache, - class_loader, - callbacks, - allow_soft_failures, - log_level, - false /* need precise constants */, - error); - // Virtual methods. - MethodVerifier::FailureData data2 = VerifyMethods<false>(self, - linker, - dex_file, - class_def, - &it, - dex_cache, - class_loader, - callbacks, - allow_soft_failures, - log_level, - false /* need precise constants */, - error); - - data1.Merge(data2); - - if (data1.kind == FailureKind::kNoFailure) { + if (failure_data.kind == FailureKind::kNoFailure) { return FailureKind::kNoFailure; } else { - if ((data1.types & VERIFY_ERROR_LOCKING) != 0) { + if ((failure_data.types & VERIFY_ERROR_LOCKING) != 0) { // Print a warning about expected slow-down. Use a string temporary to print one contiguous // warning. std::string tmp = StringPrintf("Class %s failed lock verification and will run slower.", - PrettyDescriptor(dex_file->GetClassDescriptor(class_def)).c_str()); + PrettyDescriptor(accessor.GetDescriptor()).c_str()); if (!gPrintedDxMonitorText) { tmp = tmp + "\nCommon causes for lock verification issues are non-optimized dex code\n" "and incorrect proguard optimizations."; @@ -353,7 +295,7 @@ FailureKind MethodVerifier::VerifyClass(Thread* self, } LOG(WARNING) << tmp; } - return data1.kind; + return failure_data.kind; } } @@ -1924,15 +1866,11 @@ bool MethodVerifier::CodeFlowVerifyMethod() { static uint32_t GetFirstFinalInstanceFieldIndex(const DexFile& dex_file, dex::TypeIndex type_idx) { const DexFile::ClassDef* class_def = dex_file.FindClassDef(type_idx); DCHECK(class_def != nullptr); - const uint8_t* class_data = dex_file.GetClassData(*class_def); - DCHECK(class_data != nullptr); - ClassDataItemIterator it(dex_file, class_data); - it.SkipStaticFields(); - while (it.HasNextInstanceField()) { - if ((it.GetFieldAccessFlags() & kAccFinal) != 0) { - return it.GetMemberIndex(); + 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 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { : 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 @@ const RegType& MethodVerifier::ResolveClass(dex::TypeIndex class_idx) { } // 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 @@ ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_id 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 @@ void MethodVerifier::VerifyISFieldAccess(const Instruction* inst, const RegType& 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 @@ const RegType& MethodVerifier::GetMethodReturnType() { : 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 ae7481c6b1..9890af9d95 100644 --- a/runtime/verifier/method_verifier.h +++ b/runtime/verifier/method_verifier.h @@ -275,23 +275,6 @@ class MethodVerifier { void Merge(const FailureData& src); }; - // Verify all direct or virtual methods of a class. The method assumes that the iterator is - // positioned correctly, and the iterator will be updated. - template <bool kDirect> - static FailureData VerifyMethods(Thread* self, - ClassLinker* linker, - const DexFile* dex_file, - const DexFile::ClassDef& class_def, - ClassDataItemIterator* it, - Handle<mirror::DexCache> dex_cache, - Handle<mirror::ClassLoader> class_loader, - CompilerCallbacks* callbacks, - bool allow_soft_failures, - HardFailLogMode log_level, - bool need_precise_constants, - std::string* error_string) - REQUIRES_SHARED(Locks::mutator_lock_); - /* * Perform verification on a single method. * diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc index 73e516c7bf..4a3f9e6365 100644 --- a/runtime/verifier/reg_type.cc +++ b/runtime/verifier/reg_type.cc @@ -807,7 +807,7 @@ ObjPtr<mirror::Class> RegType::ClassJoin(ObjPtr<mirror::Class> s, ObjPtr<mirror: } // 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 500cc37af4..fb91976781 100644 --- a/runtime/verifier/verifier_deps.cc +++ b/runtime/verifier/verifier_deps.cc @@ -384,7 +384,7 @@ ObjPtr<mirror::Class> VerifierDeps::FindOneClassPathBoundaryForInterface( // 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 c113042c9c..c6fd56f20d 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 @@ extern "C" JNIEXPORT jobject JNICALL Java_Main_cloneResolvedMethods(JNIEnv* env, 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 ee00266b36..0000000000 --- a/test/911-get-stack-trace/check +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -if [[ "$DX" == 'd8' ]]; then - patch -p0 expected.txt < expected_d8.diff -fi - -./default-check "$@" -if [[ "$?" == "0" ]]; then - exit 0; -fi - -# We cannot always correctly determine if D8 was used because of (b/68406220). -# So we are just going to try to see it matches the expect output of D8 no -# matter what. -patch -p0 expected.txt < expected_d8.diff - -./default-check "$@" diff --git a/test/911-get-stack-trace/expected.txt b/test/911-get-stack-trace/expected.txt index 8177f494ac..b0a400ab75 100644 --- a/test/911-get-stack-trace/expected.txt +++ b/test/911-get-stack-trace/expected.txt @@ -9,19 +9,19 @@ From top baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - doTest ()V 34 25 + doTest ()V 33 25 run ()V 0 25 --------- print (Ljava/lang/Thread;II)V 0 38 @@ -29,19 +29,19 @@ From top baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - doTest ()V 38 26 + doTest ()V 37 26 run ()V 0 25 --------- getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 -2 @@ -54,12 +54,12 @@ From top baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 From bottom --------- run ()V 0 25 --------- - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 doTest ()V 60 32 @@ -67,7 +67,7 @@ From bottom --------- bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 @@ -76,68 +76,76 @@ From bottom ################################ From top --------- - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 28 --------- + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 28 --------- - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 --------- + wait ()V 2 568 + printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 From bottom --------- run ()V 4 28 --------- foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 28 --------- - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 ########################### @@ -145,20 +153,20 @@ From bottom ########################### From top --------- - printOrWait (IILart/ControlData;)V 44 54 + printOrWait (IILart/ControlData;)V 45 54 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 61 @@ -166,29 +174,29 @@ From top baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 61 --------- - printOrWait (IILart/ControlData;)V 44 54 + printOrWait (IILart/ControlData;)V 45 54 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 --------- bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 From bottom @@ -196,15 +204,15 @@ From bottom run ()V 4 61 --------- foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 61 --------- - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 ################################ @@ -263,7 +271,9 @@ main <not printed> --------- AllTraces Thread 0 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 @@ -271,7 +281,9 @@ AllTraces Thread 0 --------- AllTraces Thread 1 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 @@ -279,7 +291,9 @@ AllTraces Thread 1 --------- AllTraces Thread 2 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 @@ -287,7 +301,9 @@ AllTraces Thread 2 --------- AllTraces Thread 3 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 @@ -295,7 +311,9 @@ AllTraces Thread 3 --------- AllTraces Thread 4 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 @@ -303,7 +321,9 @@ AllTraces Thread 4 --------- AllTraces Thread 5 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 @@ -311,7 +331,9 @@ AllTraces Thread 5 --------- AllTraces Thread 6 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 @@ -319,7 +341,9 @@ AllTraces Thread 6 --------- AllTraces Thread 7 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 @@ -327,7 +351,9 @@ AllTraces Thread 7 --------- AllTraces Thread 8 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 @@ -335,7 +361,9 @@ AllTraces Thread 8 --------- AllTraces Thread 9 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 @@ -360,7 +388,7 @@ Signal Catcher Test911 getAllStackTraces (I)[[Ljava/lang/Object; -1 -2 printAll (I)V 0 75 - doTest ()V 122 59 + doTest ()V 120 59 run ()V 24 37 --------- @@ -368,210 +396,230 @@ main <not printed> --------- AllTraces Thread 0 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 47 --------- AllTraces Thread 1 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 47 --------- AllTraces Thread 2 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 47 --------- AllTraces Thread 3 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 47 --------- AllTraces Thread 4 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 47 --------- AllTraces Thread 5 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 47 --------- AllTraces Thread 6 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 47 --------- AllTraces Thread 7 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 47 --------- AllTraces Thread 8 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 47 --------- AllTraces Thread 9 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 47 @@ -595,7 +643,7 @@ Signal Catcher Test911 getAllStackTraces (I)[[Ljava/lang/Object; -1 -2 printAll (I)V 0 75 - doTest ()V 127 61 + doTest ()V 125 61 run ()V 24 37 --------- @@ -627,12 +675,14 @@ ThreadListTraces Thread 8 Test911 getThreadListStackTraces ([Ljava/lang/Thread;I)[[Ljava/lang/Object; -1 -2 printList ([Ljava/lang/Thread;I)V 0 68 - doTest ()V 112 54 + doTest ()V 110 54 run ()V 32 41 --------- ThreadListTraces Thread 0 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 @@ -640,7 +690,9 @@ ThreadListTraces Thread 0 --------- ThreadListTraces Thread 2 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 @@ -648,7 +700,9 @@ ThreadListTraces Thread 2 --------- ThreadListTraces Thread 4 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 @@ -656,7 +710,9 @@ ThreadListTraces Thread 4 --------- ThreadListTraces Thread 6 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 @@ -664,7 +720,9 @@ ThreadListTraces Thread 6 --------- ThreadListTraces Thread 8 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 @@ -674,110 +732,120 @@ ThreadListTraces Thread 8 Test911 getThreadListStackTraces ([Ljava/lang/Thread;I)[[Ljava/lang/Object; -1 -2 printList ([Ljava/lang/Thread;I)V 0 68 - doTest ()V 117 56 + doTest ()V 115 56 run ()V 32 41 --------- ThreadListTraces Thread 0 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 37 --------- ThreadListTraces Thread 2 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 37 --------- ThreadListTraces Thread 4 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 37 --------- ThreadListTraces Thread 6 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 37 --------- ThreadListTraces Thread 8 - wait ()V -1 -2 + wait (JI)V -1 -2 + wait (J)V 1 442 + wait ()V 2 568 printOrWait (IILart/ControlData;)V 24 47 baz (IIILart/ControlData;)Ljava/lang/Object; 2 32 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 - baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 + baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 bar (IIILart/ControlData;)J 0 26 foo (IIILart/ControlData;)I 0 21 run ()V 4 37 @@ -789,7 +857,7 @@ ThreadListTraces Thread 8 4 JVMTI_ERROR_ILLEGAL_ARGUMENT [public static native java.lang.Object[] art.Frames.getFrameLocation(java.lang.Thread,int), ffffffff] -[public static void art.Frames.doTestSameThread(), 35] +[public static void art.Frames.doTestSameThread(), 40] [public static void art.Frames.doTest() throws java.lang.Exception, 0] [public void art.Test911$1.run(), 28] JVMTI_ERROR_NO_MORE_FRAMES @@ -797,23 +865,25 @@ JVMTI_ERROR_NO_MORE_FRAMES ################################ ### Other thread (suspended) ### ################################ -18 +20 JVMTI_ERROR_ILLEGAL_ARGUMENT -[public final native void java.lang.Object.wait() throws java.lang.InterruptedException, ffffffff] +[public final native void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, ffffffff] +[public final void java.lang.Object.wait(long) throws java.lang.InterruptedException, 1] +[public final void java.lang.Object.wait() throws java.lang.InterruptedException, 2] [private static void art.Recurse.printOrWait(int,int,art.ControlData), 18] [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 2] [private static long art.Recurse.bar(int,int,int,art.ControlData), 0] [public static int art.Recurse.foo(int,int,int,art.ControlData), 0] -[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9] +[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8] [private static long art.Recurse.bar(int,int,int,art.ControlData), 0] [public static int art.Recurse.foo(int,int,int,art.ControlData), 0] -[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9] +[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8] [private static long art.Recurse.bar(int,int,int,art.ControlData), 0] [public static int art.Recurse.foo(int,int,int,art.ControlData), 0] -[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9] +[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8] [private static long art.Recurse.bar(int,int,int,art.ControlData), 0] [public static int art.Recurse.foo(int,int,int,art.ControlData), 0] -[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9] +[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8] [private static long art.Recurse.bar(int,int,int,art.ControlData), 0] [public static int art.Recurse.foo(int,int,int,art.ControlData), 0] [public void art.Frames$1.run(), 4] @@ -824,20 +894,20 @@ JVMTI_ERROR_NO_MORE_FRAMES ########################### 17 JVMTI_ERROR_ILLEGAL_ARGUMENT -[private static void art.Recurse.printOrWait(int,int,art.ControlData), 2c] +[private static void art.Recurse.printOrWait(int,int,art.ControlData), 2d] [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 2] [private static long art.Recurse.bar(int,int,int,art.ControlData), 0] [public static int art.Recurse.foo(int,int,int,art.ControlData), 0] -[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9] +[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8] [private static long art.Recurse.bar(int,int,int,art.ControlData), 0] [public static int art.Recurse.foo(int,int,int,art.ControlData), 0] -[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9] +[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8] [private static long art.Recurse.bar(int,int,int,art.ControlData), 0] [public static int art.Recurse.foo(int,int,int,art.ControlData), 0] -[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9] +[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8] [private static long art.Recurse.bar(int,int,int,art.ControlData), 0] [public static int art.Recurse.foo(int,int,int,art.ControlData), 0] -[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9] +[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8] [private static long art.Recurse.bar(int,int,int,art.ControlData), 0] [public static int art.Recurse.foo(int,int,int,art.ControlData), 0] [public void art.Frames$2.run(), 4] diff --git a/test/911-get-stack-trace/expected_d8.diff b/test/911-get-stack-trace/expected_d8.diff deleted file mode 100644 index c12015a832..0000000000 --- a/test/911-get-stack-trace/expected_d8.diff +++ /dev/null @@ -1,456 +0,0 @@ -12c12 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -15c15 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -18c18 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -21c21 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -24c24 -< doTest ()V 34 25 ---- -> doTest ()V 33 25 -32c32 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -35c35 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -38c38 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -41c41 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -44c44 -< doTest ()V 38 26 ---- -> doTest ()V 37 26 -57c57 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -62c62 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -70c70 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -84c84 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -87c87 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -90c90 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -93c93 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -102c102 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -105c105 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -108c108 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -111c111 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -125c125 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -132c132 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -137c137 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -140c140 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -148c148 -< printOrWait (IILart/ControlData;)V 44 54 ---- -> printOrWait (IILart/ControlData;)V 45 54 -152c152 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -155c155 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -158c158 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -161c161 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -169c169 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -172c172 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -175c175 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -178c178 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -183c183 -< printOrWait (IILart/ControlData;)V 44 54 ---- -> printOrWait (IILart/ControlData;)V 45 54 -187c187 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -191c191 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -199c199 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -204c204 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -207c207 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -363c363 -< doTest ()V 122 59 ---- -> doTest ()V 120 59 -376c376 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -379c379 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -382c382 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -385c385 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -397c397 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -400c400 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -403c403 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -406c406 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -418c418 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -421c421 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -424c424 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -427c427 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -439c439 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -442c442 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -445c445 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -448c448 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -460c460 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -463c463 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -466c466 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -469c469 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -481c481 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -484c484 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -487c487 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -490c490 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -502c502 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -505c505 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -508c508 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -511c511 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -523c523 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -526c526 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -529c529 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -532c532 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -544c544 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -547c547 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -550c550 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -553c553 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -565c565 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -568c568 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -571c571 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -574c574 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -598c598 -< doTest ()V 127 61 ---- -> doTest ()V 125 61 -630c630 -< doTest ()V 112 54 ---- -> doTest ()V 110 54 -677c677 -< doTest ()V 117 56 ---- -> doTest ()V 115 56 -687c687 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -690c690 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -693c693 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -696c696 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -708c708 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -711c711 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -714c714 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -717c717 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -729c729 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -732c732 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -735c735 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -738c738 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -750c750 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -753c753 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -756c756 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -759c759 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -771c771 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -774c774 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -777c777 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -780c780 -< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34 ---- -> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34 -792c792 -< [public static void art.Frames.doTestSameThread(), 35] ---- -> [public static void art.Frames.doTestSameThread(), 40] -807c807 -< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9] ---- -> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8] -810c810 -< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9] ---- -> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8] -813c813 -< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9] ---- -> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8] -816c816 -< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9] ---- -> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8] -827c827 -< [private static void art.Recurse.printOrWait(int,int,art.ControlData), 2c] ---- -> [private static void art.Recurse.printOrWait(int,int,art.ControlData), 2d] -831c831 -< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9] ---- -> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8] -834c834 -< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9] ---- -> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8] -837c837 -< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9] ---- -> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8] -840c840 -< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9] ---- -> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8] diff --git a/test/911-get-stack-trace/src/art/AllTraces.java b/test/911-get-stack-trace/src/art/AllTraces.java index d73f78bba1..507925c29e 100644 --- a/test/911-get-stack-trace/src/art/AllTraces.java +++ b/test/911-get-stack-trace/src/art/AllTraces.java @@ -56,7 +56,7 @@ public class AllTraces { printAll(0); - printAll(5); + printAll(7); printAll(25); diff --git a/test/911-get-stack-trace/src/art/OtherThread.java b/test/911-get-stack-trace/src/art/OtherThread.java index 675bff55a6..3f5ae59e18 100644 --- a/test/911-get-stack-trace/src/art/OtherThread.java +++ b/test/911-get-stack-trace/src/art/OtherThread.java @@ -36,8 +36,8 @@ public class OtherThread { System.out.println("From top"); PrintThread.print(t, 0, 25); PrintThread.print(t, 1, 25); - PrintThread.print(t, 0, 5); - PrintThread.print(t, 2, 5); + PrintThread.print(t, 0, 7); + PrintThread.print(t, 2, 7); System.out.println("From bottom"); PrintThread.print(t, -1, 25); diff --git a/test/911-get-stack-trace/src/art/ThreadListTraces.java b/test/911-get-stack-trace/src/art/ThreadListTraces.java index 0de93de706..9b27e72f22 100644 --- a/test/911-get-stack-trace/src/art/ThreadListTraces.java +++ b/test/911-get-stack-trace/src/art/ThreadListTraces.java @@ -51,7 +51,7 @@ public class ThreadListTraces { printList(list, 0); - printList(list, 5); + printList(list, 7); printList(list, 25); diff --git a/tools/dexanalyze/dexanalyze.cc b/tools/dexanalyze/dexanalyze.cc index 7d7e5f28b3..7a9b8fb018 100644 --- a/tools/dexanalyze/dexanalyze.cc +++ b/tools/dexanalyze/dexanalyze.cc @@ -116,12 +116,14 @@ class DexAnalyze { } } - bool ProcessDexFile(const DexFile& dex_file) { + bool ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files) { for (std::unique_ptr<Experiment>& experiment : experiments_) { - experiment->ProcessDexFile(dex_file); + experiment->ProcessDexFiles(dex_files); } - total_size_ += dex_file.Size(); - ++dex_count_; + for (const std::unique_ptr<const DexFile>& dex_file : dex_files) { + total_size_ += dex_file->Size(); + } + dex_count_ += dex_files.size(); return true; } @@ -169,18 +171,16 @@ class DexAnalyze { LOG(ERROR) << "OpenAll failed for " + filename << " with " << error_msg << std::endl; return kExitCodeFailedToOpenDex; } - for (std::unique_ptr<const DexFile>& dex_file : dex_files) { - if (options.dump_per_input_dex_) { - Analysis current(&options); - if (!current.ProcessDexFile(*dex_file)) { - LOG(ERROR) << "Failed to process " << filename << " with error " << error_msg; - return kExitCodeFailedToProcessDex; - } - LOG(INFO) << "Analysis for " << dex_file->GetLocation() << std::endl; - current.Dump(LOG_STREAM(INFO)); + if (options.dump_per_input_dex_) { + Analysis current(&options); + if (!current.ProcessDexFiles(dex_files)) { + LOG(ERROR) << "Failed to process " << filename << " with error " << error_msg; + return kExitCodeFailedToProcessDex; } - cumulative.ProcessDexFile(*dex_file); + LOG(INFO) << "Analysis for " << filename << std::endl; + current.Dump(LOG_STREAM(INFO)); } + cumulative.ProcessDexFiles(dex_files); } LOG(INFO) << "Cumulative analysis for " << cumulative.dex_count_ << " DEX files" << std::endl; cumulative.Dump(LOG_STREAM(INFO)); diff --git a/tools/dexanalyze/dexanalyze_experiments.cc b/tools/dexanalyze/dexanalyze_experiments.cc index 1a3b89cbc7..244f45bbe6 100644 --- a/tools/dexanalyze/dexanalyze_experiments.cc +++ b/tools/dexanalyze/dexanalyze_experiments.cc @@ -75,86 +75,95 @@ static size_t PrefixLen(const std::string& a, const std::string& b) { return len; } -void AnalyzeDebugInfo::ProcessDexFile(const DexFile& dex_file) { +void Experiment::ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files) { + for (const std::unique_ptr<const DexFile>& dex_file : dex_files) { + ProcessDexFile(*dex_file); + } +} + +void AnalyzeDebugInfo::ProcessDexFiles( + const std::vector<std::unique_ptr<const DexFile>>& dex_files) { std::set<const uint8_t*> seen; std::vector<size_t> counts(256, 0u); std::vector<size_t> opcode_counts(256, 0u); std::set<std::vector<uint8_t>> unique_non_header; - for (ClassAccessor accessor : dex_file.GetClasses()) { - for (const ClassAccessor::Method& method : accessor.GetMethods()) { - CodeItemDebugInfoAccessor code_item(dex_file, method.GetCodeItem(), method.GetIndex()); - const uint8_t* debug_info = dex_file.GetDebugInfoStream(code_item.DebugInfoOffset()); - if (debug_info != nullptr && seen.insert(debug_info).second) { - const uint8_t* stream = debug_info; - DecodeUnsignedLeb128(&stream); // line_start - uint32_t parameters_size = DecodeUnsignedLeb128(&stream); - for (uint32_t i = 0; i < parameters_size; ++i) { - DecodeUnsignedLeb128P1(&stream); // Parameter name. - } - bool done = false; - const uint8_t* after_header_start = stream; - while (!done) { - const uint8_t* const op_start = stream; - uint8_t opcode = *stream++; - ++opcode_counts[opcode]; - ++total_opcode_bytes_; - switch (opcode) { - case DexFile::DBG_END_SEQUENCE: - ++total_end_seq_bytes_; - done = true; - break; - case DexFile::DBG_ADVANCE_PC: - DecodeUnsignedLeb128(&stream); // addr_diff - total_advance_pc_bytes_ += stream - op_start; - break; - case DexFile::DBG_ADVANCE_LINE: - DecodeSignedLeb128(&stream); // line_diff - total_advance_line_bytes_ += stream - op_start; - break; - case DexFile::DBG_START_LOCAL: - DecodeUnsignedLeb128(&stream); // register_num - DecodeUnsignedLeb128P1(&stream); // name_idx - DecodeUnsignedLeb128P1(&stream); // type_idx - total_start_local_bytes_ += stream - op_start; - break; - case DexFile::DBG_START_LOCAL_EXTENDED: - DecodeUnsignedLeb128(&stream); // register_num - DecodeUnsignedLeb128P1(&stream); // name_idx - DecodeUnsignedLeb128P1(&stream); // type_idx - DecodeUnsignedLeb128P1(&stream); // sig_idx - total_start_local_extended_bytes_ += stream - op_start; - break; - case DexFile::DBG_END_LOCAL: - DecodeUnsignedLeb128(&stream); // register_num - total_end_local_bytes_ += stream - op_start; - break; - case DexFile::DBG_RESTART_LOCAL: - DecodeUnsignedLeb128(&stream); // register_num - total_restart_local_bytes_ += stream - op_start; - break; - case DexFile::DBG_SET_PROLOGUE_END: - case DexFile::DBG_SET_EPILOGUE_BEGIN: - total_epilogue_bytes_ += stream - op_start; - break; - case DexFile::DBG_SET_FILE: { - DecodeUnsignedLeb128P1(&stream); // name_idx - total_set_file_bytes_ += stream - op_start; - break; - } - default: { - total_other_bytes_ += stream - op_start; - break; + for (const std::unique_ptr<const DexFile>& dex_file : dex_files) { + for (ClassAccessor accessor : dex_file->GetClasses()) { + for (const ClassAccessor::Method& method : accessor.GetMethods()) { + CodeItemDebugInfoAccessor code_item(*dex_file, method.GetCodeItem(), method.GetIndex()); + const uint8_t* debug_info = dex_file->GetDebugInfoStream(code_item.DebugInfoOffset()); + if (debug_info != nullptr && seen.insert(debug_info).second) { + const uint8_t* stream = debug_info; + DecodeUnsignedLeb128(&stream); // line_start + uint32_t parameters_size = DecodeUnsignedLeb128(&stream); + for (uint32_t i = 0; i < parameters_size; ++i) { + DecodeUnsignedLeb128P1(&stream); // Parameter name. + } + bool done = false; + const uint8_t* after_header_start = stream; + while (!done) { + const uint8_t* const op_start = stream; + uint8_t opcode = *stream++; + ++opcode_counts[opcode]; + ++total_opcode_bytes_; + switch (opcode) { + case DexFile::DBG_END_SEQUENCE: + ++total_end_seq_bytes_; + done = true; + break; + case DexFile::DBG_ADVANCE_PC: + DecodeUnsignedLeb128(&stream); // addr_diff + total_advance_pc_bytes_ += stream - op_start; + break; + case DexFile::DBG_ADVANCE_LINE: + DecodeSignedLeb128(&stream); // line_diff + total_advance_line_bytes_ += stream - op_start; + break; + case DexFile::DBG_START_LOCAL: + DecodeUnsignedLeb128(&stream); // register_num + DecodeUnsignedLeb128P1(&stream); // name_idx + DecodeUnsignedLeb128P1(&stream); // type_idx + total_start_local_bytes_ += stream - op_start; + break; + case DexFile::DBG_START_LOCAL_EXTENDED: + DecodeUnsignedLeb128(&stream); // register_num + DecodeUnsignedLeb128P1(&stream); // name_idx + DecodeUnsignedLeb128P1(&stream); // type_idx + DecodeUnsignedLeb128P1(&stream); // sig_idx + total_start_local_extended_bytes_ += stream - op_start; + break; + case DexFile::DBG_END_LOCAL: + DecodeUnsignedLeb128(&stream); // register_num + total_end_local_bytes_ += stream - op_start; + break; + case DexFile::DBG_RESTART_LOCAL: + DecodeUnsignedLeb128(&stream); // register_num + total_restart_local_bytes_ += stream - op_start; + break; + case DexFile::DBG_SET_PROLOGUE_END: + case DexFile::DBG_SET_EPILOGUE_BEGIN: + total_epilogue_bytes_ += stream - op_start; + break; + case DexFile::DBG_SET_FILE: { + DecodeUnsignedLeb128P1(&stream); // name_idx + total_set_file_bytes_ += stream - op_start; + break; + } + default: { + total_other_bytes_ += stream - op_start; + break; + } } } - } - const size_t bytes = stream - debug_info; - total_bytes_ += bytes; - total_non_header_bytes_ += stream - after_header_start; - if (unique_non_header.insert(std::vector<uint8_t>(after_header_start, stream)).second) { - total_unique_non_header_bytes_ += stream - after_header_start; - } - for (size_t i = 0; i < bytes; ++i) { - ++counts[debug_info[i]]; + const size_t bytes = stream - debug_info; + total_bytes_ += bytes; + total_non_header_bytes_ += stream - after_header_start; + if (unique_non_header.insert(std::vector<uint8_t>(after_header_start, stream)).second) { + total_unique_non_header_bytes_ += stream - after_header_start; + } + for (size_t i = 0; i < bytes; ++i) { + ++counts[debug_info[i]]; + } } } } diff --git a/tools/dexanalyze/dexanalyze_experiments.h b/tools/dexanalyze/dexanalyze_experiments.h index a2621c85ca..2be53d6216 100644 --- a/tools/dexanalyze/dexanalyze_experiments.h +++ b/tools/dexanalyze/dexanalyze_experiments.h @@ -18,7 +18,9 @@ #define ART_TOOLS_DEXANALYZE_DEXANALYZE_EXPERIMENTS_H_ #include <iosfwd> +#include <memory> #include <set> +#include <vector> namespace art { @@ -30,7 +32,8 @@ std::string Percent(uint64_t value, uint64_t max); class Experiment { public: virtual ~Experiment() {} - virtual void ProcessDexFile(const DexFile& dex_file) = 0; + virtual void ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files); + virtual void ProcessDexFile(const DexFile&) {} virtual void Dump(std::ostream& os, uint64_t total_size) const = 0; }; @@ -54,7 +57,7 @@ class AnalyzeStrings : public Experiment { // Analyze debug info sizes. class AnalyzeDebugInfo : public Experiment { public: - void ProcessDexFile(const DexFile& dex_file); + void ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files); void Dump(std::ostream& os, uint64_t total_size) const; private: @@ -112,7 +115,7 @@ class CountDexIndices : public Experiment { size_t total_super_ = 0; }; -// Measure various code metrics including args per invoke-virtual, fill/spill move paterns. +// Measure various code metrics including args per invoke-virtual, fill/spill move patterns. class CodeMetrics : public Experiment { public: void ProcessDexFile(const DexFile& dex_file); |