Merge "Cleanup BitMemoryReader/Writer api."
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index a881c5e..3fc559e 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -88,7 +88,7 @@
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 8ffeee4..d40577f 100644
--- a/libdexfile/dex/class_accessor.h
+++ b/libdexfile/dex/class_accessor.h
@@ -31,7 +31,7 @@
// Classes to access Dex data.
class ClassAccessor {
- private:
+ public:
class BaseItem {
public:
explicit BaseItem(const DexFile& dex_file,
@@ -65,6 +65,14 @@
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 @@
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 1476880..dd0428d 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -368,17 +368,6 @@
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 edaa043..b03f671 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -53,9 +53,9 @@
// 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 0965560..6936fdc 100644
--- a/runtime/gc/space/malloc_space.cc
+++ b/runtime/gc/space/malloc_space.cc
@@ -247,7 +247,7 @@
}
}
// 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 0701330..0569092 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 @@
// 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 @@
};
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 @@
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 @@
// 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 fa33a8a..90f1f1d 100644
--- a/runtime/gc/space/region_space.h
+++ b/runtime/gc/space/region_space.h
@@ -602,6 +602,11 @@
/* 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 e4bec06..bf8a1b7 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 @@
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 @@
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 @@
}
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 @@
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 @@
// 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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 aa87f21..b50f684 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 @@
}
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 @@
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 60aac3c..264217e 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"]
}
]