summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libdexfile/dex/descriptors_names.cc60
-rw-r--r--perfetto_hprof/perfetto_hprof.cc23
2 files changed, 53 insertions, 30 deletions
diff --git a/libdexfile/dex/descriptors_names.cc b/libdexfile/dex/descriptors_names.cc
index 44cb7cb588..4f73469e1c 100644
--- a/libdexfile/dex/descriptors_names.cc
+++ b/libdexfile/dex/descriptors_names.cc
@@ -36,38 +36,58 @@ void AppendPrettyDescriptor(const char* descriptor, std::string* result) {
}
// Reference or primitive?
+ bool primitive = false;
if (*c == 'L') {
// "[[La/b/C;" -> "a.b.C[][]".
c++; // Skip the 'L'.
} else {
+ primitive = true;
// "[[B" -> "byte[][]".
- // To make life easier, we make primitives look like unqualified
- // reference types.
switch (*c) {
- case 'B': c = "byte;"; break;
- case 'C': c = "char;"; break;
- case 'D': c = "double;"; break;
- case 'F': c = "float;"; break;
- case 'I': c = "int;"; break;
- case 'J': c = "long;"; break;
- case 'S': c = "short;"; break;
- case 'Z': c = "boolean;"; break;
- case 'V': c = "void;"; break; // Used when decoding return types.
+ case 'B':
+ c = "byte";
+ break;
+ case 'C':
+ c = "char";
+ break;
+ case 'D':
+ c = "double";
+ break;
+ case 'F':
+ c = "float";
+ break;
+ case 'I':
+ c = "int";
+ break;
+ case 'J':
+ c = "long";
+ break;
+ case 'S':
+ c = "short";
+ break;
+ case 'Z':
+ c = "boolean";
+ break;
+ case 'V':
+ c = "void";
+ break; // Used when decoding return types.
default: result->append(descriptor); return;
}
}
- // At this point, 'c' is a string of the form "fully/qualified/Type;"
- // or "primitive;". Rewrite the type with '.' instead of '/':
- const char* p = c;
- while (*p != ';') {
- char ch = *p++;
- if (ch == '/') {
- ch = '.';
+ // At this point, 'c' is a string of the form "fully/qualified/Type;" or
+ // "primitive". In the former case, rewrite the type with '.' instead of '/':
+ std::string temp(c);
+ if (!primitive) {
+ std::replace(temp.begin(), temp.end(), '/', '.');
+ // ...and remove the semicolon:
+ if (temp.back() == ';') {
+ temp.pop_back();
}
- result->push_back(ch);
}
- // ...and replace the semicolon with 'dim' "[]" pairs:
+ result->append(temp);
+
+ // Finally, add 'dim' "[]" pairs:
for (size_t i = 0; i < dim; ++i) {
result->append("[]");
}
diff --git a/perfetto_hprof/perfetto_hprof.cc b/perfetto_hprof/perfetto_hprof.cc
index ba4c6f259e..d7aa3bd935 100644
--- a/perfetto_hprof/perfetto_hprof.cc
+++ b/perfetto_hprof/perfetto_hprof.cc
@@ -412,8 +412,9 @@ class Writer {
class ReferredObjectsFinder {
public:
explicit ReferredObjectsFinder(
- std::vector<std::pair<std::string, art::mirror::Object*>>* referred_objects)
- : referred_objects_(referred_objects) {}
+ std::vector<std::pair<std::string, art::mirror::Object*>>* referred_objects,
+ bool emit_field_ids)
+ : referred_objects_(referred_objects), emit_field_ids_(emit_field_ids) {}
// For art::mirror::Object::VisitReferences.
void operator()(art::ObjPtr<art::mirror::Object> obj, art::MemberOffset offset,
@@ -431,7 +432,7 @@ class ReferredObjectsFinder {
field = art::ArtField::FindInstanceFieldWithOffset(obj->GetClass(), offset.Uint32Value());
}
std::string field_name = "";
- if (field != nullptr) {
+ if (field != nullptr && emit_field_ids_) {
field_name = field->PrettyField(/*with_type=*/true);
}
referred_objects_->emplace_back(std::move(field_name), ref);
@@ -446,6 +447,8 @@ class ReferredObjectsFinder {
// We can use a raw Object* pointer here, because there are no concurrent GC threads after the
// fork.
std::vector<std::pair<std::string, art::mirror::Object*>>* referred_objects_;
+ // Prettifying field names is expensive; avoid if field name will not be used.
+ bool emit_field_ids_;
};
class RootFinder : public art::SingleRootVisitor {
@@ -583,10 +586,11 @@ size_t EncodedSize(uint64_t n) {
// Returns all the references that `*obj` (an object of type `*klass`) is holding.
std::vector<std::pair<std::string, art::mirror::Object*>> GetReferences(art::mirror::Object* obj,
- art::mirror::Class* klass)
+ art::mirror::Class* klass,
+ bool emit_field_ids)
REQUIRES_SHARED(art::Locks::mutator_lock_) {
std::vector<std::pair<std::string, art::mirror::Object*>> referred_objects;
- ReferredObjectsFinder objf(&referred_objects);
+ ReferredObjectsFinder objf(&referred_objects, emit_field_ids);
if (klass->GetClassFlags() != art::mirror::kClassFlagNormal &&
klass->GetClassFlags() != art::mirror::kClassFlagPhantomReference) {
@@ -797,17 +801,16 @@ class HeapGraphDumper {
art::mirror::Class* klass,
perfetto::protos::pbzero::HeapGraphObject* object_proto)
REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ const bool emit_field_ids = klass->GetClassFlags() != art::mirror::kClassFlagObjectArray &&
+ klass->GetClassFlags() != art::mirror::kClassFlagNormal &&
+ klass->GetClassFlags() != art::mirror::kClassFlagPhantomReference;
std::vector<std::pair<std::string, art::mirror::Object*>> referred_objects =
- GetReferences(obj, klass);
+ GetReferences(obj, klass, emit_field_ids);
art::mirror::Object* min_nonnull_ptr = FilterIgnoredReferencesAndFindMin(referred_objects);
uint64_t base_obj_id = EncodeBaseObjId(referred_objects, min_nonnull_ptr);
- const bool emit_field_ids = klass->GetClassFlags() != art::mirror::kClassFlagObjectArray &&
- klass->GetClassFlags() != art::mirror::kClassFlagNormal &&
- klass->GetClassFlags() != art::mirror::kClassFlagPhantomReference;
-
for (const auto& p : referred_objects) {
const std::string& field_name = p.first;
art::mirror::Object* referred_obj = p.second;