Remove mirror:: and ArtMethod deps in utils.{h,cc}
The latest chapter in the ongoing saga of attempting to dump a DEX
file without having to start a whole runtime instance. This episode
finds us removing references to ArtMethod/ArtField/mirror.
One aspect of this change that I would like to call out specfically
is that the utils versions of the "Pretty*" functions all were written
to accept nullptr as an argument. I have split these functions up as
follows:
1) an instance method, such as PrettyClass that obviously requires
this != nullptr.
2) a static method, that behaves the same way as the util method, but
calls the instance method if p != nullptr.
This requires using a full class qualifier for the static methods,
which isn't exactly beautiful. I have tried to remove as many cases
as possible where it was clear p != nullptr.
Bug: 22322814
Test: test-art-host
Change-Id: I21adee3614aa697aa580cd1b86b72d9206e1cb24
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index 3789081..b11dad8 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -168,7 +168,7 @@
// 32-bit.
if (UNLIKELY(size == 0)) {
self->ThrowOutOfMemoryError(StringPrintf("%s of length %d would overflow",
- PrettyDescriptor(array_class).c_str(),
+ array_class->PrettyDescriptor().c_str(),
component_count).c_str());
return nullptr;
}
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 14bd243..9992a9e 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -42,14 +42,14 @@
template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline uint32_t Class::GetObjectSize() {
// Note: Extra parentheses to avoid the comma being interpreted as macro parameter separator.
- DCHECK((!IsVariableSize<kVerifyFlags, kReadBarrierOption>())) << "class=" << PrettyTypeOf(this);
+ DCHECK((!IsVariableSize<kVerifyFlags, kReadBarrierOption>())) << "class=" << PrettyTypeOf();
return GetField32(ObjectSizeOffset());
}
template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline uint32_t Class::GetObjectSizeAllocFastPath() {
// Note: Extra parentheses to avoid the comma being interpreted as macro parameter separator.
- DCHECK((!IsVariableSize<kVerifyFlags, kReadBarrierOption>())) << "class=" << PrettyTypeOf(this);
+ DCHECK((!IsVariableSize<kVerifyFlags, kReadBarrierOption>())) << "class=" << PrettyTypeOf();
return GetField32(ObjectSizeAllocFastPathOffset());
}
@@ -218,7 +218,7 @@
inline ArtMethod* Class::GetVirtualMethod(size_t i, PointerSize pointer_size) {
CheckPointerSize(pointer_size);
DCHECK(IsResolved<kVerifyFlags>() || IsErroneous<kVerifyFlags>())
- << PrettyClass(this) << " status=" << GetStatus();
+ << Class::PrettyClass() << " status=" << GetStatus();
return GetVirtualMethodUnchecked(i, pointer_size);
}
@@ -308,7 +308,7 @@
inline bool Class::Implements(ObjPtr<Class> klass) {
DCHECK(klass != nullptr);
- DCHECK(klass->IsInterface()) << PrettyClass(this);
+ DCHECK(klass->IsInterface()) << PrettyClass();
// All interfaces implemented directly and by our superclass, and
// recursively all super-interfaces of those interfaces, are listed
// in iftable_, so we can just do a linear scan through that.
@@ -342,20 +342,20 @@
// Object[] = int[] --> false
//
inline bool Class::IsArrayAssignableFromArray(ObjPtr<Class> src) {
- DCHECK(IsArrayClass()) << PrettyClass(this);
- DCHECK(src->IsArrayClass()) << PrettyClass(src);
+ DCHECK(IsArrayClass()) << PrettyClass();
+ DCHECK(src->IsArrayClass()) << src->PrettyClass();
return GetComponentType()->IsAssignableFrom(src->GetComponentType());
}
inline bool Class::IsAssignableFromArray(ObjPtr<Class> src) {
- DCHECK(!IsInterface()) << PrettyClass(this); // handled first in IsAssignableFrom
- DCHECK(src->IsArrayClass()) << PrettyClass(src);
+ DCHECK(!IsInterface()) << PrettyClass(); // handled first in IsAssignableFrom
+ DCHECK(src->IsArrayClass()) << src->PrettyClass();
if (!IsArrayClass()) {
// If "this" is not also an array, it must be Object.
// src's super should be java_lang_Object, since it is an array.
ObjPtr<Class> java_lang_Object = src->GetSuperClass();
- DCHECK(java_lang_Object != nullptr) << PrettyClass(src);
- DCHECK(java_lang_Object->GetSuperClass() == nullptr) << PrettyClass(src);
+ DCHECK(java_lang_Object != nullptr) << src->PrettyClass();
+ DCHECK(java_lang_Object->GetSuperClass() == nullptr) << src->PrettyClass();
return this == java_lang_Object;
}
return IsArrayAssignableFromArray(src);
@@ -469,8 +469,8 @@
}
inline bool Class::IsSubClass(ObjPtr<Class> klass) {
- DCHECK(!IsInterface()) << PrettyClass(this);
- DCHECK(!IsArrayClass()) << PrettyClass(this);
+ DCHECK(!IsInterface()) << PrettyClass();
+ DCHECK(!IsArrayClass()) << PrettyClass();
ObjPtr<Class> current = this;
do {
if (current == klass) {
@@ -484,8 +484,8 @@
inline ArtMethod* Class::FindVirtualMethodForInterface(ArtMethod* method,
PointerSize pointer_size) {
ObjPtr<Class> declaring_class = method->GetDeclaringClass();
- DCHECK(declaring_class != nullptr) << PrettyClass(this);
- DCHECK(declaring_class->IsInterface()) << PrettyMethod(method);
+ DCHECK(declaring_class != nullptr) << PrettyClass();
+ DCHECK(declaring_class->IsInterface()) << method->PrettyMethod();
DCHECK(!method->IsCopied());
// TODO cache to improve lookup speed
const int32_t iftable_count = GetIfTableCount();
@@ -647,7 +647,7 @@
IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>()
<< " IsString=" << (this == String::GetJavaLangString())
<< " status= " << GetStatus<kVerifyFlags>()
- << " descriptor=" << PrettyDescriptor(this);
+ << " descriptor=" << PrettyDescriptor();
return GetField32<kVerifyFlags>(AccessFlagsOffset());
}
@@ -687,20 +687,20 @@
inline void Class::CheckObjectAlloc() {
DCHECK(!IsArrayClass())
- << PrettyClass(this)
+ << PrettyClass()
<< "A array shouldn't be allocated through this "
<< "as it requires a pre-fence visitor that sets the class size.";
DCHECK(!IsClassClass())
- << PrettyClass(this)
+ << PrettyClass()
<< "A class object shouldn't be allocated through this "
<< "as it requires a pre-fence visitor that sets the class size.";
DCHECK(!IsStringClass())
- << PrettyClass(this)
+ << PrettyClass()
<< "A string shouldn't be allocated through this "
<< "as it requires a pre-fence visitor that sets the class size.";
- DCHECK(IsInstantiable()) << PrettyClass(this);
+ DCHECK(IsInstantiable()) << PrettyClass();
// TODO: decide whether we want this check. It currently fails during bootstrap.
- // DCHECK(!Runtime::Current()->IsStarted() || IsInitializing()) << PrettyClass(this);
+ // DCHECK(!Runtime::Current()->IsStarted() || IsInitializing()) << PrettyClass();
DCHECK_GE(this->object_size_, sizeof(Object));
}
@@ -840,8 +840,8 @@
inline void Class::AssertInitializedOrInitializingInThread(Thread* self) {
if (kIsDebugBuild && !IsInitialized()) {
- CHECK(IsInitializing()) << PrettyClass(this) << " is not initializing: " << GetStatus();
- CHECK_EQ(GetClinitThreadId(), self->GetTid()) << PrettyClass(this)
+ CHECK(IsInitializing()) << PrettyClass() << " is not initializing: " << GetStatus();
+ CHECK_EQ(GetClinitThreadId(), self->GetTid()) << PrettyClass()
<< " is initializing in a different thread";
}
}
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index f93f72f..6a357b3 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -59,7 +59,7 @@
}
inline void Class::SetVerifyError(ObjPtr<Object> error) {
- CHECK(error != nullptr) << PrettyClass(this);
+ CHECK(error != nullptr) << PrettyClass();
if (Runtime::Current()->IsActiveTransaction()) {
SetFieldObject<true>(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_), error);
} else {
@@ -74,22 +74,22 @@
if (LIKELY(class_linker_initialized)) {
if (UNLIKELY(new_status <= old_status && new_status != kStatusError &&
new_status != kStatusRetired)) {
- LOG(FATAL) << "Unexpected change back of class status for " << PrettyClass(h_this.Get())
+ LOG(FATAL) << "Unexpected change back of class status for " << h_this->PrettyClass()
<< " " << old_status << " -> " << new_status;
}
if (new_status >= kStatusResolved || old_status >= kStatusResolved) {
// When classes are being resolved the resolution code should hold the lock.
CHECK_EQ(h_this->GetLockOwnerThreadId(), self->GetThreadId())
<< "Attempt to change status of class while not holding its lock: "
- << PrettyClass(h_this.Get()) << " " << old_status << " -> " << new_status;
+ << h_this->PrettyClass() << " " << old_status << " -> " << new_status;
}
}
if (UNLIKELY(new_status == kStatusError)) {
CHECK_NE(h_this->GetStatus(), kStatusError)
<< "Attempt to set as erroneous an already erroneous class "
- << PrettyClass(h_this.Get());
+ << h_this->PrettyClass();
if (VLOG_IS_ON(class_linker)) {
- LOG(ERROR) << "Setting " << PrettyDescriptor(h_this.Get()) << " to erroneous.";
+ LOG(ERROR) << "Setting " << h_this->PrettyDescriptor() << " to erroneous.";
if (self->IsExceptionPending()) {
LOG(ERROR) << "Exception: " << self->GetException()->Dump();
}
@@ -127,7 +127,7 @@
if (h_this->IsTemp()) {
// Class is a temporary one, ensure that waiters for resolution get notified of retirement
// so that they can grab the new version of the class from the class linker's table.
- CHECK_LT(new_status, kStatusResolved) << PrettyDescriptor(h_this.Get());
+ CHECK_LT(new_status, kStatusResolved) << h_this->PrettyDescriptor();
if (new_status == kStatusRetired || new_status == kStatusError) {
h_this->NotifyAll(self);
}
@@ -149,7 +149,7 @@
if (kIsDebugBuild && new_class_size < GetClassSize()) {
DumpClass(LOG_STREAM(FATAL_WITHOUT_ABORT), kDumpClassFullDetail);
LOG(FATAL_WITHOUT_ABORT) << new_class_size << " vs " << GetClassSize();
- LOG(FATAL) << "class=" << PrettyTypeOf(this);
+ LOG(FATAL) << "class=" << PrettyTypeOf();
}
// Not called within a transaction.
SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), new_class_size);
@@ -196,7 +196,7 @@
void Class::DumpClass(std::ostream& os, int flags) {
if ((flags & kDumpClassFullDetail) == 0) {
- os << PrettyClass(this);
+ os << PrettyClass();
if ((flags & kDumpClassClassLoader) != 0) {
os << ' ' << GetClassLoader();
}
@@ -221,7 +221,7 @@
os << StringPrintf(" access=0x%04x.%04x\n",
GetAccessFlags() >> 16, GetAccessFlags() & kAccJavaFlagsMask);
if (h_super.Get() != nullptr) {
- os << " super='" << PrettyClass(h_super.Get()) << "' (cl=" << h_super->GetClassLoader()
+ os << " super='" << h_super->PrettyClass() << "' (cl=" << h_super->GetClassLoader()
<< ")\n";
}
if (IsArrayClass()) {
@@ -247,19 +247,20 @@
os << " vtable (" << h_this->NumVirtualMethods() << " entries, "
<< (h_super.Get() != nullptr ? h_super->NumVirtualMethods() : 0) << " in super):\n";
for (size_t i = 0; i < NumVirtualMethods(); ++i) {
- os << StringPrintf(" %2zd: %s\n", i, PrettyMethod(
+ os << StringPrintf(" %2zd: %s\n", i, ArtMethod::PrettyMethod(
h_this->GetVirtualMethodDuringLinking(i, image_pointer_size)).c_str());
}
os << " direct methods (" << h_this->NumDirectMethods() << " entries):\n";
for (size_t i = 0; i < h_this->NumDirectMethods(); ++i) {
- os << StringPrintf(" %2zd: %s\n", i, PrettyMethod(
+ os << StringPrintf(" %2zd: %s\n", i, ArtMethod::PrettyMethod(
h_this->GetDirectMethod(i, image_pointer_size)).c_str());
}
if (h_this->NumStaticFields() > 0) {
os << " static fields (" << h_this->NumStaticFields() << " entries):\n";
if (h_this->IsResolved() || h_this->IsErroneous()) {
for (size_t i = 0; i < h_this->NumStaticFields(); ++i) {
- os << StringPrintf(" %2zd: %s\n", i, PrettyField(h_this->GetStaticField(i)).c_str());
+ os << StringPrintf(" %2zd: %s\n", i,
+ ArtField::PrettyField(h_this->GetStaticField(i)).c_str());
}
} else {
os << " <not yet available>";
@@ -269,7 +270,8 @@
os << " instance fields (" << h_this->NumInstanceFields() << " entries):\n";
if (h_this->IsResolved() || h_this->IsErroneous()) {
for (size_t i = 0; i < h_this->NumInstanceFields(); ++i) {
- os << StringPrintf(" %2zd: %s\n", i, PrettyField(h_this->GetInstanceField(i)).c_str());
+ os << StringPrintf(" %2zd: %s\n", i,
+ ArtField::PrettyField(h_this->GetInstanceField(i)).c_str());
}
} else {
os << " <not yet available>";
@@ -690,7 +692,7 @@
break;
}
}
- CHECK_EQ(found, ret) << "Found " << PrettyField(found) << " vs " << PrettyField(ret);
+ CHECK_EQ(found, ret) << "Found " << found->PrettyField() << " vs " << ret->PrettyField();
}
return ret;
}
@@ -919,7 +921,7 @@
while (!common_super_class->IsAssignableFrom(klass.Get())) {
ObjPtr<Class> old_common = common_super_class;
common_super_class = old_common->GetSuperClass();
- DCHECK(common_super_class != nullptr) << PrettyClass(old_common);
+ DCHECK(common_super_class != nullptr) << old_common->PrettyClass();
}
return common_super_class;
}
@@ -953,7 +955,7 @@
void Class::PopulateEmbeddedVTable(PointerSize pointer_size) {
PointerArray* table = GetVTableDuringLinking();
- CHECK(table != nullptr) << PrettyClass(this);
+ CHECK(table != nullptr) << PrettyClass();
const size_t table_length = table->GetLength();
SetEmbeddedVTableLength(table_length);
for (size_t i = 0; i < table_length; i++) {
@@ -1239,5 +1241,50 @@
}
}
+std::string Class::PrettyDescriptor(ObjPtr<mirror::Class> klass) {
+ if (klass == nullptr) {
+ return "null";
+ }
+ return klass->PrettyDescriptor();
+}
+
+std::string Class::PrettyDescriptor() {
+ std::string temp;
+ return art::PrettyDescriptor(GetDescriptor(&temp));
+}
+
+std::string Class::PrettyClass(ObjPtr<mirror::Class> c) {
+ if (c == nullptr) {
+ return "null";
+ }
+ return c->PrettyClass();
+}
+
+std::string Class::PrettyClass() {
+ std::string result;
+ result += "java.lang.Class<";
+ result += PrettyDescriptor();
+ result += ">";
+ return result;
+}
+
+std::string Class::PrettyClassAndClassLoader(ObjPtr<mirror::Class> c) {
+ if (c == nullptr) {
+ return "null";
+ }
+ return c->PrettyClassAndClassLoader();
+}
+
+std::string Class::PrettyClassAndClassLoader() {
+ std::string result;
+ result += "java.lang.Class<";
+ result += PrettyDescriptor();
+ result += ",";
+ result += mirror::Object::PrettyTypeOf(GetClassLoader());
+ // TODO: add an identifying hash value for the loader
+ result += ">";
+ return result;
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index a5b61fd..5793795 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -1120,7 +1120,7 @@
REQUIRES_SHARED(Locks::mutator_lock_);
pid_t GetClinitThreadId() REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK(IsIdxLoaded() || IsErroneous()) << PrettyClass(this);
+ DCHECK(IsIdxLoaded() || IsErroneous()) << PrettyClass();
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_));
}
@@ -1288,6 +1288,22 @@
ALWAYS_INLINE ArraySlice<ArtMethod> GetCopiedMethodsSliceUnchecked(PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
+ static std::string PrettyDescriptor(ObjPtr<mirror::Class> klass)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ std::string PrettyDescriptor()
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ // Returns a human-readable form of the name of the given class.
+ // Given String.class, the output would be "java.lang.Class<java.lang.String>".
+ static std::string PrettyClass(ObjPtr<mirror::Class> c)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ std::string PrettyClass()
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ // Returns a human-readable form of the name of the given class with its class loader.
+ static std::string PrettyClassAndClassLoader(ObjPtr<mirror::Class> c)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ std::string PrettyClassAndClassLoader()
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
// Fix up all of the native pointers in the class by running them through the visitor. Only sets
// the corresponding entry in dest if visitor(obj) != obj to prevent dirty memory. Dest should be
// initialized to a copy of *this to prevent issues. Does not visit the ArtMethod and ArtField
diff --git a/runtime/mirror/method.cc b/runtime/mirror/method.cc
index 7ddadda..25cbdc1 100644
--- a/runtime/mirror/method.cc
+++ b/runtime/mirror/method.cc
@@ -53,7 +53,7 @@
template <PointerSize kPointerSize, bool kTransactionActive>
Method* Method::CreateFromArtMethod(Thread* self, ArtMethod* method) {
- DCHECK(!method->IsConstructor()) << PrettyMethod(method);
+ DCHECK(!method->IsConstructor()) << method->PrettyMethod();
ObjPtr<Method> ret = ObjPtr<Method>::DownCast(StaticClass()->AllocObject(self));
if (LIKELY(ret != nullptr)) {
ObjPtr<Executable>(ret)->
@@ -105,7 +105,7 @@
template <PointerSize kPointerSize, bool kTransactionActive>
Constructor* Constructor::CreateFromArtMethod(Thread* self, ArtMethod* method) {
- DCHECK(method->IsConstructor()) << PrettyMethod(method);
+ DCHECK(method->IsConstructor()) << method->PrettyMethod();
ObjPtr<Constructor> ret = ObjPtr<Constructor>::DownCast(StaticClass()->AllocObject(self));
if (LIKELY(ret != nullptr)) {
ObjPtr<Executable>(ret)->
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index f555c80..2e70c9b 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -510,7 +510,7 @@
template GetObjectSize<kNewFlags, kReadBarrierOption>();
}
DCHECK_GE(result, sizeof(Object))
- << " class=" << PrettyClass(GetClass<kNewFlags, kReadBarrierOption>());
+ << " class=" << Class::PrettyClass(GetClass<kNewFlags, kReadBarrierOption>());
return result;
}
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index 7e92c53..8cfb60e 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -266,7 +266,7 @@
}
}
LOG(FATAL) << "Failed to find field for assignment to " << reinterpret_cast<void*>(this)
- << " of type " << PrettyDescriptor(c) << " at offset " << field_offset;
+ << " of type " << c->PrettyDescriptor() << " at offset " << field_offset;
UNREACHABLE();
}
@@ -275,5 +275,24 @@
: ArtField::FindInstanceFieldWithOffset(GetClass(), offset.Uint32Value());
}
+std::string Object::PrettyTypeOf(ObjPtr<mirror::Object> obj) {
+ if (obj == nullptr) {
+ return "null";
+ }
+ return obj->PrettyTypeOf();
+}
+
+std::string Object::PrettyTypeOf() {
+ if (GetClass() == nullptr) {
+ return "(raw)";
+ }
+ std::string temp;
+ std::string result(PrettyDescriptor(GetClass()->GetDescriptor(&temp)));
+ if (IsClass()) {
+ result += "<" + PrettyDescriptor(AsClass()->GetDescriptor(&temp)) + ">";
+ }
+ return result;
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 13f4028..f1ab72a 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -544,6 +544,15 @@
// Generate an identity hash code. Public for object test.
static uint32_t GenerateIdentityHashCode();
+ // Returns a human-readable form of the name of the *class* of the given object.
+ // So given an instance of java.lang.String, the output would
+ // be "java.lang.String". Given an array of int, the output would be "int[]".
+ // Given String.class, the output would be "java.lang.Class<java.lang.String>".
+ static std::string PrettyTypeOf(ObjPtr<mirror::Object> obj)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ std::string PrettyTypeOf()
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
protected:
// Accessors for non-Java type fields
template<class T, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kIsVolatile = false>
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index 3c2390b..5fb9459 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -238,8 +238,8 @@
}
Runtime::Current()->GetHeap()->WriteBarrierArray(this, dst_pos, count);
if (UNLIKELY(i != count)) {
- std::string actualSrcType(PrettyTypeOf(o));
- std::string dstType(PrettyTypeOf(this));
+ std::string actualSrcType(mirror::Object::PrettyTypeOf(o));
+ std::string dstType(PrettyTypeOf());
Thread* self = Thread::Current();
if (throw_exception) {
self->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 60e2bf8..5bf254d 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -337,7 +337,7 @@
dims->Set<false>(0, -1);
multi = Array::CreateMultiArray(soa.Self(), c, dims);
EXPECT_TRUE(soa.Self()->IsExceptionPending());
- EXPECT_EQ(PrettyDescriptor(soa.Self()->GetException()->GetClass()),
+ EXPECT_EQ(mirror::Class::PrettyDescriptor(soa.Self()->GetException()->GetClass()),
"java.lang.NegativeArraySizeException");
soa.Self()->ClearException();
diff --git a/runtime/mirror/string-inl.h b/runtime/mirror/string-inl.h
index cf902af..d42bb92 100644
--- a/runtime/mirror/string-inl.h
+++ b/runtime/mirror/string-inl.h
@@ -232,7 +232,7 @@
const size_t max_length = RoundDown(max_alloc_length, kObjectAlignment / block_size);
if (UNLIKELY(length > max_length)) {
self->ThrowOutOfMemoryError(StringPrintf("%s of length %d would overflow",
- PrettyDescriptor(string_class).c_str(),
+ Class::PrettyDescriptor(string_class).c_str(),
static_cast<int>(length)).c_str());
return nullptr;
}
diff --git a/runtime/mirror/string.cc b/runtime/mirror/string.cc
index ed1103f..ea2660b 100644
--- a/runtime/mirror/string.cc
+++ b/runtime/mirror/string.cc
@@ -365,5 +365,16 @@
return (IsCompressed()) ? (GetValueCompressed() == nullptr) : (GetValue() == nullptr);
}
+std::string String::PrettyStringDescriptor(ObjPtr<mirror::String> java_descriptor) {
+ if (java_descriptor == nullptr) {
+ return "null";
+ }
+ return java_descriptor->PrettyStringDescriptor();
+}
+
+std::string String::PrettyStringDescriptor() {
+ return PrettyDescriptor(ToModifiedUtf8().c_str());
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h
index cfb1153..a1b674a 100644
--- a/runtime/mirror/string.h
+++ b/runtime/mirror/string.h
@@ -204,6 +204,14 @@
static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
+ // Returns a human-readable equivalent of 'descriptor'. So "I" would be "int",
+ // "[[I" would be "int[][]", "[Ljava/lang/String;" would be
+ // "java.lang.String[]", and so forth.
+ static std::string PrettyStringDescriptor(ObjPtr<mirror::String> descriptor)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ std::string PrettyStringDescriptor()
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
private:
void SetHashCode(int32_t new_hash_code) REQUIRES_SHARED(Locks::mutator_lock_) {
// Hash code is invariant so use non-transactional mode. Also disable check as we may run inside
diff --git a/runtime/mirror/throwable.cc b/runtime/mirror/throwable.cc
index 7aff3de..b866a63 100644
--- a/runtime/mirror/throwable.cc
+++ b/runtime/mirror/throwable.cc
@@ -83,7 +83,7 @@
}
std::string Throwable::Dump() {
- std::string result(PrettyTypeOf(this));
+ std::string result(PrettyTypeOf());
result += ": ";
ObjPtr<String> msg = GetDetailMessage();
if (msg != nullptr) {
@@ -112,7 +112,7 @@
uintptr_t dex_pc = method_trace->GetElementPtrSize<uintptr_t>(i + depth, ptr_size);
int32_t line_number = method->GetLineNumFromDexPC(dex_pc);
const char* source_file = method->GetDeclaringClassSourceFile();
- result += StringPrintf(" at %s (%s:%d)\n", PrettyMethod(method, true).c_str(),
+ result += StringPrintf(" at %s (%s:%d)\n", method->PrettyMethod(true).c_str(),
source_file, line_number);
}
}