diff options
| -rw-r--r-- | compiler/jit/jit_compiler.cc | 2 | ||||
| -rw-r--r-- | libdexfile/dex/class_accessor.h | 11 | ||||
| -rw-r--r-- | openjdkjvmti/ti_redefine.cc | 11 | ||||
| -rw-r--r-- | runtime/gc/collector/concurrent_copying.cc | 6 | ||||
| -rw-r--r-- | runtime/gc/space/malloc_space.cc | 2 | ||||
| -rw-r--r-- | runtime/gc/space/region_space.cc | 46 | ||||
| -rw-r--r-- | runtime/gc/space/region_space.h | 5 | ||||
| -rw-r--r-- | tools/hiddenapi/hiddenapi.cc | 137 | ||||
| -rw-r--r-- | tools/hiddenapi/hiddenapi_test.cc | 73 | ||||
| -rw-r--r-- | tools/libcore_failures.txt | 10 |
10 files changed, 165 insertions, 138 deletions
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc index a881c5ec98..3fc559e13b 100644 --- a/compiler/jit/jit_compiler.cc +++ b/compiler/jit/jit_compiler.cc @@ -88,7 +88,7 @@ extern "C" void jit_types_loaded(void* handle, mirror::Class** types, size_t cou JitCompiler::JitCompiler() { compiler_options_.reset(new CompilerOptions()); // Special case max code units for inlining, whose default is "unset" (implictly - // meaning no limit). Do this before parsing the actuall passed options. + // meaning no limit). Do this before parsing the actual passed options. compiler_options_->SetInlineMaxCodeUnits(CompilerOptions::kDefaultInlineMaxCodeUnits); { std::string error_msg; diff --git a/libdexfile/dex/class_accessor.h b/libdexfile/dex/class_accessor.h index 8ffeee4f2f..d40577f31f 100644 --- a/libdexfile/dex/class_accessor.h +++ b/libdexfile/dex/class_accessor.h @@ -31,7 +31,7 @@ class ClassIteratorData; // Classes to access Dex data. class ClassAccessor { - private: + public: class BaseItem { public: explicit BaseItem(const DexFile& dex_file, @@ -65,6 +65,14 @@ class ClassAccessor { return ptr_pos_; } + bool MemberIsNative() const { + return GetRawAccessFlags() & kAccNative; + } + + bool MemberIsFinal() const { + return GetRawAccessFlags() & kAccFinal; + } + protected: // Internal data pointer for reading. const DexFile& dex_file_; @@ -73,7 +81,6 @@ class ClassAccessor { uint32_t access_flags_ = 0u; }; - public: // A decoded version of the method of a class_data_item. class Method : public BaseItem { public: diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc index 1476880f45..dd0428dfcf 100644 --- a/openjdkjvmti/ti_redefine.cc +++ b/openjdkjvmti/ti_redefine.cc @@ -368,17 +368,6 @@ jvmtiError Redefiner::RedefineClasses(ArtJvmTiEnv* env, if (res != OK) { return res; } - // We make a copy of the class_bytes to pass into the retransformation. - // This makes cleanup easier (since we unambiguously own the bytes) and also is useful since we - // will need to keep the original bytes around unaltered for subsequent RetransformClasses calls - // to get the passed in bytes. - unsigned char* class_bytes_copy = nullptr; - res = env->Allocate(definitions[i].class_byte_count, &class_bytes_copy); - if (res != OK) { - return res; - } - memcpy(class_bytes_copy, definitions[i].class_bytes, definitions[i].class_byte_count); - ArtClassDefinition def; res = def.Init(self, definitions[i]); if (res != OK) { diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc index edaa043ce6..b03f67152b 100644 --- a/runtime/gc/collector/concurrent_copying.cc +++ b/runtime/gc/collector/concurrent_copying.cc @@ -53,9 +53,9 @@ static constexpr size_t kDefaultGcMarkStackSize = 2 * MB; // If kFilterModUnionCards then we attempt to filter cards that don't need to be dirty in the mod // union table. Disabled since it does not seem to help the pause much. static constexpr bool kFilterModUnionCards = kIsDebugBuild; -// If kDisallowReadBarrierDuringScan is true then the GC aborts if there are any that occur during -// ConcurrentCopying::Scan. May be used to diagnose possibly unnecessary read barriers. -// Only enabled for kIsDebugBuild to avoid performance hit. +// If kDisallowReadBarrierDuringScan is true then the GC aborts if there are any read barrier that +// occur during ConcurrentCopying::Scan in GC thread. May be used to diagnose possibly unnecessary +// read barriers. Only enabled for kIsDebugBuild to avoid performance hit. static constexpr bool kDisallowReadBarrierDuringScan = kIsDebugBuild; // Slow path mark stack size, increase this if the stack is getting full and it is causing // performance problems. diff --git a/runtime/gc/space/malloc_space.cc b/runtime/gc/space/malloc_space.cc index 0965560e2c..6936fdc6d4 100644 --- a/runtime/gc/space/malloc_space.cc +++ b/runtime/gc/space/malloc_space.cc @@ -247,7 +247,7 @@ void MallocSpace::SweepCallback(size_t num_ptrs, mirror::Object** ptrs, void* ar } } // Use a bulk free, that merges consecutive objects before freeing or free per object? - // Documentation suggests better free performance with merging, but this may be at the expensive + // Documentation suggests better free performance with merging, but this may be at the expense // of allocation. context->freed.objects += num_ptrs; context->freed.bytes += space->FreeList(self, num_ptrs, ptrs); diff --git a/runtime/gc/space/region_space.cc b/runtime/gc/space/region_space.cc index 0701330e81..0569092bcd 100644 --- a/runtime/gc/space/region_space.cc +++ b/runtime/gc/space/region_space.cc @@ -16,6 +16,7 @@ #include "bump_pointer_space-inl.h" #include "bump_pointer_space.h" +#include "base/dumpable.h" #include "gc/accounting/read_barrier_table.h" #include "mirror/class-inl.h" #include "mirror/object-inl.h" @@ -42,6 +43,9 @@ static constexpr bool kPoisonDeadObjectsInUnevacuatedRegions = true; // points to a valid, non-protected memory area. static constexpr uint32_t kPoisonDeadObject = 0xBADDB01D; // "BADDROID" +// Whether we check a region's live bytes count against the region bitmap. +static constexpr bool kCheckLiveBytesAgainstRegionBitmap = kIsDebugBuild; + MemMap* RegionSpace::CreateMemMap(const std::string& name, size_t capacity, uint8_t* requested_begin) { CHECK_ALIGNED(capacity, kRegionSize); @@ -316,6 +320,9 @@ void RegionSpace::ClearFromSpace(/* out */ uint64_t* cleared_bytes, }; for (size_t i = 0; i < std::min(num_regions_, non_free_region_index_limit_); ++i) { Region* r = ®ions_[i]; + if (kCheckLiveBytesAgainstRegionBitmap) { + CheckLiveBytesAgainstRegionBitmap(r); + } if (r->IsInFromSpace()) { *cleared_bytes += r->BytesAllocated(); *cleared_objects += r->ObjectsAllocated(); @@ -404,6 +411,42 @@ void RegionSpace::ClearFromSpace(/* out */ uint64_t* cleared_bytes, num_evac_regions_ = 0; } +void RegionSpace::CheckLiveBytesAgainstRegionBitmap(Region* r) { + if (r->LiveBytes() == static_cast<size_t>(-1)) { + // Live bytes count is undefined for `r`; nothing to check here. + return; + } + + // Functor walking the region space bitmap for the range corresponding + // to region `r` and calculating the sum of live bytes. + size_t live_bytes_recount = 0u; + auto recount_live_bytes = + [&r, &live_bytes_recount](mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) { + DCHECK_ALIGNED(obj, kAlignment); + if (r->IsLarge()) { + // If `r` is a large region, then it contains at most one + // object, which must start at the beginning of the + // region. The live byte count in that case is equal to the + // allocated regions (large region + large tails regions). + DCHECK_EQ(reinterpret_cast<uint8_t*>(obj), r->Begin()); + DCHECK_EQ(live_bytes_recount, 0u); + live_bytes_recount = r->Top() - r->Begin(); + } else { + DCHECK(r->IsAllocated()) + << "r->State()=" << r->State() << " r->LiveBytes()=" << r->LiveBytes(); + size_t obj_size = obj->SizeOf<kDefaultVerifyFlags>(); + size_t alloc_size = RoundUp(obj_size, space::RegionSpace::kAlignment); + live_bytes_recount += alloc_size; + } + }; + // Visit live objects in `r` and recount the live bytes. + GetLiveBitmap()->VisitMarkedRange(reinterpret_cast<uintptr_t>(r->Begin()), + reinterpret_cast<uintptr_t>(r->Top()), + recount_live_bytes); + // Check that this recount matches the region's current live bytes count. + DCHECK_EQ(live_bytes_recount, r->LiveBytes()); +} + // Poison the memory area in range [`begin`, `end`) with value `kPoisonDeadObject`. static void PoisonUnevacuatedRange(uint8_t* begin, uint8_t* end) { static constexpr size_t kPoisonDeadObjectSize = sizeof(kPoisonDeadObject); @@ -423,7 +466,8 @@ void RegionSpace::PoisonDeadObjectsInUnevacuatedRegion(Region* r) { // The live byte count of `r` should be different from -1, as this // region should neither be a newly allocated region nor an // evacuated region. - DCHECK_NE(r->LiveBytes(), static_cast<size_t>(-1)); + DCHECK_NE(r->LiveBytes(), static_cast<size_t>(-1)) + << "Unexpected live bytes count of -1 in " << Dumpable<Region>(*r); // Past-the-end address of the previously visited (live) object (or // the beginning of the region, if `maybe_poison` has not run yet). diff --git a/runtime/gc/space/region_space.h b/runtime/gc/space/region_space.h index fa33a8a21b..90f1f1dd2a 100644 --- a/runtime/gc/space/region_space.h +++ b/runtime/gc/space/region_space.h @@ -602,6 +602,11 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace { /* out */ size_t* bytes_tl_bulk_allocated, /* out */ size_t* next_region = nullptr) REQUIRES(region_lock_); + // Check that the value of `r->LiveBytes()` matches the number of + // (allocated) bytes used by live objects according to the live bits + // in the region space bitmap range corresponding to region `r`. + void CheckLiveBytesAgainstRegionBitmap(Region* r); + // Poison memory areas used by dead objects within unevacuated // region `r`. This is meant to detect dangling references to dead // objects earlier in debug mode. diff --git a/tools/hiddenapi/hiddenapi.cc b/tools/hiddenapi/hiddenapi.cc index e4bec060f2..bf8a1b755e 100644 --- a/tools/hiddenapi/hiddenapi.cc +++ b/tools/hiddenapi/hiddenapi.cc @@ -26,6 +26,7 @@ #include "base/os.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-inl.h" #include "dex/hidden_api_access_flags.h" @@ -91,32 +92,23 @@ static bool Contains(const std::vector<E>& vec, const E& elem) { return std::find(vec.begin(), vec.end(), elem) != vec.end(); } -class DexClass { +class DexClass : public ClassAccessor { public: - DexClass(const DexFile& dex_file, uint32_t idx) - : dex_file_(dex_file), class_def_(dex_file.GetClassDef(idx)) {} + explicit DexClass(const ClassAccessor& accessor) : ClassAccessor(accessor) {} - const DexFile& GetDexFile() const { return dex_file_; } - const uint8_t* GetData() const { return dex_file_.GetClassData(class_def_); } + const uint8_t* GetData() const { return dex_file_.GetClassData(GetClassDef()); } - const dex::TypeIndex GetClassIndex() const { return class_def_.class_idx_; } - const dex::TypeIndex GetSuperclassIndex() const { return class_def_.superclass_idx_; } + const dex::TypeIndex GetSuperclassIndex() const { return GetClassDef().superclass_idx_; } bool HasSuperclass() const { return dex_file_.IsTypeIndexValid(GetSuperclassIndex()); } - std::string GetDescriptor() const { return dex_file_.GetClassDescriptor(class_def_); } - std::string GetSuperclassDescriptor() const { - if (HasSuperclass()) { - return dex_file_.StringByTypeIdx(GetSuperclassIndex()); - } else { - return ""; - } + return HasSuperclass() ? dex_file_.StringByTypeIdx(GetSuperclassIndex()) : ""; } std::set<std::string> GetInterfaceDescriptors() const { std::set<std::string> list; - const DexFile::TypeList* ifaces = dex_file_.GetInterfacesList(class_def_); + const DexFile::TypeList* ifaces = dex_file_.GetInterfacesList(GetClassDef()); for (uint32_t i = 0; ifaces != nullptr && i < ifaces->Size(); ++i) { list.insert(dex_file_.StringByTypeIdx(ifaces->GetTypeItem(i).type_idx_)); } @@ -126,7 +118,7 @@ class DexClass { inline bool IsPublic() const { return HasAccessFlags(kAccPublic); } inline bool Equals(const DexClass& other) const { - bool equals = GetDescriptor() == other.GetDescriptor(); + bool equals = strcmp(GetDescriptor(), other.GetDescriptor()) == 0; if (equals) { // TODO(dbrazdil): Check that methods/fields match as well once b/111116543 is fixed. CHECK_EQ(GetAccessFlags(), other.GetAccessFlags()); @@ -137,39 +129,40 @@ class DexClass { } private: - uint32_t GetAccessFlags() const { return class_def_.access_flags_; } + uint32_t GetAccessFlags() const { return GetClassDef().access_flags_; } bool HasAccessFlags(uint32_t mask) const { return (GetAccessFlags() & mask) == mask; } - - const DexFile& dex_file_; - const DexFile::ClassDef& class_def_; }; class DexMember { public: - DexMember(const DexClass& klass, const ClassDataItemIterator& it) - : klass_(klass), it_(it) { - DCHECK_EQ(IsMethod() ? GetMethodId().class_idx_ : GetFieldId().class_idx_, - klass_.GetClassIndex()); + DexMember(const DexClass& klass, const ClassAccessor::Field& item) + : klass_(klass), item_(item), is_method_(false) { + DCHECK_EQ(GetFieldId().class_idx_, klass.GetClassIdx()); + } + + DexMember(const DexClass& klass, const ClassAccessor::Method& item) + : klass_(klass), item_(item), is_method_(true) { + DCHECK_EQ(GetMethodId().class_idx_, klass.GetClassIdx()); } inline const DexClass& GetDeclaringClass() const { return klass_; } // Sets hidden bits in access flags and writes them back into the DEX in memory. - // Note that this will not update the cached data of ClassDataItemIterator + // Note that this will not update the cached data of the class accessor // until it iterates over this item again and therefore will fail a CHECK if // it is called multiple times on the same DexMember. - void SetHidden(HiddenApiAccessFlags::ApiList value) { - const uint32_t old_flags = it_.GetRawMemberAccessFlags(); + void SetHidden(HiddenApiAccessFlags::ApiList value) const { + const uint32_t old_flags = item_.GetRawAccessFlags(); const uint32_t new_flags = HiddenApiAccessFlags::EncodeForDex(old_flags, value); CHECK_EQ(UnsignedLeb128Size(new_flags), UnsignedLeb128Size(old_flags)); // Locate the LEB128-encoded access flags in class data. // `ptr` initially points to the next ClassData item. We iterate backwards // until we hit the terminating byte of the previous Leb128 value. - const uint8_t* ptr = it_.DataPointer(); + const uint8_t* ptr = item_.GetDataPointer(); if (IsMethod()) { ptr = ReverseSearchUnsignedLeb128(ptr); - DCHECK_EQ(DecodeUnsignedLeb128WithoutMovingCursor(ptr), it_.GetMethodCodeItemOffset()); + DCHECK_EQ(DecodeUnsignedLeb128WithoutMovingCursor(ptr), GetMethod().GetCodeItemOffset()); } ptr = ReverseSearchUnsignedLeb128(ptr); DCHECK_EQ(DecodeUnsignedLeb128WithoutMovingCursor(ptr), old_flags); @@ -178,8 +171,8 @@ class DexMember { UpdateUnsignedLeb128(const_cast<uint8_t*>(ptr), new_flags); } - inline bool IsMethod() const { return it_.IsAtMethod(); } - inline bool IsVirtualMethod() const { return it_.IsAtVirtualMethod(); } + inline bool IsMethod() const { return is_method_; } + inline bool IsVirtualMethod() const { return IsMethod() && !GetMethod().IsStaticOrDirect(); } inline bool IsConstructor() const { return IsMethod() && HasAccessFlags(kAccConstructor); } inline bool IsPublicOrProtected() const { @@ -189,11 +182,12 @@ class DexMember { // Constructs a string with a unique signature of this class member. std::string GetApiEntry() const { std::stringstream ss; - ss << klass_.GetDescriptor() << "->" << GetName() << (IsMethod() ? "" : ":") << GetSignature(); + ss << klass_.GetDescriptor() << "->" << GetName() << (IsMethod() ? "" : ":") + << GetSignature(); return ss.str(); } - inline bool operator==(const DexMember& other) { + inline bool operator==(const DexMember& other) const { // These need to match if they should resolve to one another. bool equals = IsMethod() == other.IsMethod() && GetName() == other.GetName() && @@ -208,31 +202,37 @@ class DexMember { } private: - inline uint32_t GetAccessFlags() const { return it_.GetMemberAccessFlags(); } + inline uint32_t GetAccessFlags() const { return item_.GetAccessFlags(); } inline uint32_t HasAccessFlags(uint32_t mask) const { return (GetAccessFlags() & mask) == mask; } inline std::string GetName() const { - return IsMethod() ? klass_.GetDexFile().GetMethodName(GetMethodId()) - : klass_.GetDexFile().GetFieldName(GetFieldId()); + return IsMethod() ? item_.GetDexFile().GetMethodName(GetMethodId()) + : item_.GetDexFile().GetFieldName(GetFieldId()); } inline std::string GetSignature() const { - return IsMethod() ? klass_.GetDexFile().GetMethodSignature(GetMethodId()).ToString() - : klass_.GetDexFile().GetFieldTypeDescriptor(GetFieldId()); + return IsMethod() ? item_.GetDexFile().GetMethodSignature(GetMethodId()).ToString() + : item_.GetDexFile().GetFieldTypeDescriptor(GetFieldId()); + } + + inline const ClassAccessor::Method& GetMethod() const { + DCHECK(IsMethod()); + return down_cast<const ClassAccessor::Method&>(item_); } inline const DexFile::MethodId& GetMethodId() const { DCHECK(IsMethod()); - return klass_.GetDexFile().GetMethodId(it_.GetMemberIndex()); + return item_.GetDexFile().GetMethodId(item_.GetIndex()); } inline const DexFile::FieldId& GetFieldId() const { DCHECK(!IsMethod()); - return klass_.GetDexFile().GetFieldId(it_.GetMemberIndex()); + return item_.GetDexFile().GetFieldId(item_.GetIndex()); } const DexClass& klass_; - const ClassDataItemIterator& it_; + const ClassAccessor::BaseItem& item_; + const bool is_method_; }; class ClassPath FINAL { @@ -244,22 +244,20 @@ class ClassPath FINAL { template<typename Fn> void ForEachDexClass(Fn fn) { for (auto& dex_file : dex_files_) { - for (uint32_t class_idx = 0; class_idx < dex_file->NumClassDefs(); ++class_idx) { - DexClass klass(*dex_file, class_idx); - fn(klass); + for (ClassAccessor accessor : dex_file->GetClasses()) { + fn(DexClass(accessor)); } } } template<typename Fn> void ForEachDexMember(Fn fn) { - ForEachDexClass([&fn](DexClass& klass) { - const uint8_t* klass_data = klass.GetData(); - if (klass_data != nullptr) { - for (ClassDataItemIterator it(klass.GetDexFile(), klass_data); it.HasNext(); it.Next()) { - DexMember member(klass, it); - fn(member); - } + ForEachDexClass([&fn](const DexClass& klass) { + for (const ClassAccessor::Field& field : klass.GetFields()) { + fn(DexMember(klass, field)); + } + for (const ClassAccessor::Method& method : klass.GetMethods()) { + fn(DexMember(klass, method)); } }); } @@ -416,16 +414,18 @@ class HierarchyClass FINAL { template<typename Fn> ResolutionResult ForEachMatchingMember(const DexMember& other, Fn fn) { ResolutionResult found = ResolutionResult::kNotFound; + auto compare_member = [&](const DexMember& member) { + if (member == other) { + found = Accumulate(found, fn(member) ? ResolutionResult::kFoundNew + : ResolutionResult::kFoundOld); + } + }; for (const DexClass& dex_class : dex_classes_) { - const uint8_t* data = dex_class.GetData(); - if (data != nullptr) { - for (ClassDataItemIterator it(dex_class.GetDexFile(), data); it.HasNext(); it.Next()) { - DexMember member(dex_class, it); - if (member == other) { - found = Accumulate(found, fn(member) ? ResolutionResult::kFoundNew - : ResolutionResult::kFoundOld); - } - } + for (const ClassAccessor::Field& field : dex_class.GetFields()) { + compare_member(DexMember(dex_class, field)); + } + for (const ClassAccessor::Method& method : dex_class.GetMethods()) { + compare_member(DexMember(dex_class, method)); } } return found; @@ -528,7 +528,7 @@ class Hierarchy FINAL { void BuildClassHierarchy() { // Create one HierarchyClass entry in `classes_` per class descriptor // and add all DexClass objects with the same descriptor to that entry. - classpath_.ForEachDexClass([this](DexClass& klass) { + classpath_.ForEachDexClass([this](const DexClass& klass) { classes_[klass.GetDescriptor()].AddDexClass(klass); }); @@ -643,13 +643,9 @@ class HiddenApi FINAL { ClassPath boot_classpath(boot_dex_paths_, /* open_writable */ true); // Set access flags of all members. - boot_classpath.ForEachDexMember([&api_list](DexMember& boot_member) { + boot_classpath.ForEachDexMember([&api_list](const DexMember& boot_member) { auto it = api_list.find(boot_member.GetApiEntry()); - if (it == api_list.end()) { - boot_member.SetHidden(HiddenApiAccessFlags::kWhitelist); - } else { - boot_member.SetHidden(it->second); - } + boot_member.SetHidden(it == api_list.end() ? HiddenApiAccessFlags::kWhitelist : it->second); }); boot_classpath.UpdateDexChecksums(); @@ -696,7 +692,7 @@ class HiddenApi FINAL { Hierarchy boot_hierarchy(boot_classpath); // Mark all boot dex members private. - boot_classpath.ForEachDexMember([&boot_members](DexMember& boot_member) { + boot_classpath.ForEachDexMember([&boot_members](const DexMember& boot_member) { boot_members[boot_member.GetApiEntry()] = false; }); @@ -705,14 +701,15 @@ class HiddenApi FINAL { ClassPath stub_classpath(stub_classpath_dex, /* open_writable */ false); Hierarchy stub_hierarchy(stub_classpath); stub_classpath.ForEachDexMember( - [&stub_hierarchy, &boot_hierarchy, &boot_members, &unresolved](DexMember& stub_member) { + [&stub_hierarchy, &boot_hierarchy, &boot_members, &unresolved]( + const DexMember& stub_member) { if (!stub_hierarchy.IsMemberVisible(stub_member)) { // Typically fake constructors and inner-class `this` fields. return; } bool resolved = boot_hierarchy.ForEachResolvableMember( stub_member, - [&boot_members](DexMember& boot_member) { + [&boot_members](const DexMember& boot_member) { std::string entry = boot_member.GetApiEntry(); auto it = boot_members.find(entry); CHECK(it != boot_members.end()); diff --git a/tools/hiddenapi/hiddenapi_test.cc b/tools/hiddenapi/hiddenapi_test.cc index aa87f21e7f..b50f684f09 100644 --- a/tools/hiddenapi/hiddenapi_test.cc +++ b/tools/hiddenapi/hiddenapi_test.cc @@ -20,6 +20,7 @@ #include "base/zip_archive.h" #include "common_runtime_test.h" #include "dex/art_dex_file_loader.h" +#include "dex/class_accessor-inl.h" #include "dex/dex_file-inl.h" #include "exec_utils.h" @@ -114,40 +115,27 @@ class HiddenApiTest : public CommonRuntimeTest { } const DexFile::ClassDef& FindClass(const char* desc, const DexFile& dex_file) { - for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) { - const DexFile::ClassDef& class_def = dex_file.GetClassDef(i); - if (strcmp(desc, dex_file.GetClassDescriptor(class_def)) == 0) { - return class_def; - } - } - LOG(FATAL) << "Could not find class " << desc; - UNREACHABLE(); + const DexFile::TypeId* type_id = dex_file.FindTypeId(desc); + CHECK(type_id != nullptr) << "Could not find class " << desc; + const DexFile::ClassDef* found = dex_file.FindClassDef(dex_file.GetIndexForTypeId(*type_id)); + CHECK(found != nullptr) << "Could not find class " << desc; + return *found; } HiddenApiAccessFlags::ApiList GetFieldHiddenFlags(const char* name, uint32_t expected_visibility, const DexFile::ClassDef& class_def, const DexFile& dex_file) { - const uint8_t* class_data = dex_file.GetClassData(class_def); - if (class_data == nullptr) { - LOG(FATAL) << "Class " << dex_file.GetClassDescriptor(class_def) << " has no data"; - UNREACHABLE(); - } + ClassAccessor accessor(dex_file, class_def); + CHECK(accessor.HasClassData()) << "Class " << accessor.GetDescriptor() << " has no data"; - for (ClassDataItemIterator it(dex_file, class_data); it.HasNext(); it.Next()) { - if (it.IsAtMethod()) { - break; - } - const DexFile::FieldId& fid = dex_file.GetFieldId(it.GetMemberIndex()); + for (const ClassAccessor::Field& field : accessor.GetFields()) { + const DexFile::FieldId& fid = dex_file.GetFieldId(field.GetIndex()); if (strcmp(name, dex_file.GetFieldName(fid)) == 0) { - uint32_t actual_visibility = it.GetFieldAccessFlags() & kAccVisibilityFlags; - if (actual_visibility != expected_visibility) { - LOG(FATAL) << "Field " << name << " in class " << dex_file.GetClassDescriptor(class_def) - << " does not have the expected visibility flags (" << expected_visibility - << " != " << actual_visibility << ")"; - UNREACHABLE(); - } - return it.DecodeHiddenAccessFlags(); + const uint32_t actual_visibility = field.GetAccessFlags() & kAccVisibilityFlags; + CHECK_EQ(actual_visibility, expected_visibility) + << "Field " << name << " in class " << accessor.GetDescriptor(); + return field.DecodeHiddenAccessFlags(); } } @@ -161,31 +149,18 @@ class HiddenApiTest : public CommonRuntimeTest { bool expected_native, const DexFile::ClassDef& class_def, const DexFile& dex_file) { - const uint8_t* class_data = dex_file.GetClassData(class_def); - if (class_data == nullptr) { - LOG(FATAL) << "Class " << dex_file.GetClassDescriptor(class_def) << " has no data"; - UNREACHABLE(); - } + ClassAccessor accessor(dex_file, class_def); + CHECK(accessor.HasClassData()) << "Class " << accessor.GetDescriptor() << " has no data"; - for (ClassDataItemIterator it(dex_file, class_data); it.HasNext(); it.Next()) { - if (!it.IsAtMethod()) { - continue; - } - const DexFile::MethodId& mid = dex_file.GetMethodId(it.GetMemberIndex()); + for (const ClassAccessor::Method& method : accessor.GetMethods()) { + const DexFile::MethodId& mid = dex_file.GetMethodId(method.GetIndex()); if (strcmp(name, dex_file.GetMethodName(mid)) == 0) { - if (expected_native != it.MemberIsNative()) { - LOG(FATAL) << "Expected native=" << expected_native << " for method " << name - << " in class " << dex_file.GetClassDescriptor(class_def); - UNREACHABLE(); - } - uint32_t actual_visibility = it.GetMethodAccessFlags() & kAccVisibilityFlags; - if (actual_visibility != expected_visibility) { - LOG(FATAL) << "Method " << name << " in class " << dex_file.GetClassDescriptor(class_def) - << " does not have the expected visibility flags (" << expected_visibility - << " != " << actual_visibility << ")"; - UNREACHABLE(); - } - return it.DecodeHiddenAccessFlags(); + CHECK_EQ(expected_native, method.MemberIsNative()) + << "Method " << name << " in class " << accessor.GetDescriptor(); + const uint32_t actual_visibility = method.GetAccessFlags() & kAccVisibilityFlags; + CHECK_EQ(actual_visibility, expected_visibility) + << "Method " << name << " in class " << accessor.GetDescriptor(); + return method.DecodeHiddenAccessFlags(); } } diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt index 60aac3cdb5..264217ead6 100644 --- a/tools/libcore_failures.txt +++ b/tools/libcore_failures.txt @@ -214,5 +214,15 @@ description: "java.io.IOException: Error writing ASN.1 encoding", result: EXEC_FAILED, names: ["libcore.javax.crypto.spec.AlgorithmParametersTestGCM#testEncoding"] +}, +{ + description: "Tests fail because mockito can not read android.os.Build$VERSION", + result: EXEC_FAILED, + bug: 111704422, + names: ["libcore.java.lang.ThreadTest#testUncaughtExceptionPreHandler_calledBeforeDefaultHandler", + "libcore.java.lang.ThreadTest#testUncaughtExceptionPreHandler_noDefaultHandler", + "libcore.javax.crypto.CipherInputStreamTest#testCloseTwice", + "libcore.libcore.io.BlockGuardOsTest#test_android_getaddrinfo_networkPolicy", + "libcore.libcore.io.BlockGuardOsTest#test_checkNewMethodsInPosix"] } ] |