diff options
-rw-r--r-- | libdexfile/dex/descriptors_names.cc | 60 | ||||
-rw-r--r-- | perfetto_hprof/perfetto_hprof.cc | 23 |
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; |