From 1a0efd803ae80e4b6caa1e501a7fc3d955d2396d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Liz=C3=A9?= Date: Wed, 2 May 2018 14:46:45 +0200 Subject: [PATCH] Report the per-isolate total size of scripts source. As with other code size stats, this doesn't distinguish between live and dead objects, and doesn't scan the young generation. Also make ExternalString::is_short() const. Bug: chromium:837659 Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng Change-Id: I72815edb719ba61d9727e226ff1da0fc4af22a24 Reviewed-on: https://chromium-review.googlesource.com/1032994 Commit-Queue: Benoit L Reviewed-by: Leszek Swirski Reviewed-by: Michael Lippautz Reviewed-by: Yang Guo Cr-Commit-Position: refs/heads/master@{#52955} --- include/v8.h | 2 ++ src/api.cc | 6 +++++- src/heap/code-stats.cc | 45 ++++++++++++++++++++++++---------------- src/heap/heap.cc | 1 + src/heap/object-stats.cc | 5 +---- src/isolate.h | 1 + src/objects.cc | 5 +++++ src/objects/string-inl.h | 2 +- src/objects/string.h | 4 +++- 9 files changed, 46 insertions(+), 25 deletions(-) diff --git a/include/v8.h b/include/v8.h index 0a0fd0abdf..a00390f80b 100644 --- a/include/v8.h +++ b/include/v8.h @@ -6593,10 +6593,12 @@ class V8_EXPORT HeapCodeStatistics { HeapCodeStatistics(); size_t code_and_metadata_size() { return code_and_metadata_size_; } size_t bytecode_and_metadata_size() { return bytecode_and_metadata_size_; } + size_t external_script_source_size() { return external_script_source_size_; } private: size_t code_and_metadata_size_; size_t bytecode_and_metadata_size_; + size_t external_script_source_size_; friend class Isolate; }; diff --git a/src/api.cc b/src/api.cc index d48f7b128f..b9458c2b6b 100644 --- a/src/api.cc +++ b/src/api.cc @@ -6026,7 +6026,9 @@ HeapObjectStatistics::HeapObjectStatistics() object_size_(0) {} HeapCodeStatistics::HeapCodeStatistics() - : code_and_metadata_size_(0), bytecode_and_metadata_size_(0) {} + : code_and_metadata_size_(0), + bytecode_and_metadata_size_(0), + external_script_source_size_(0) {} bool v8::V8::InitializeICU(const char* icu_data_file) { return i::InitializeICU(icu_data_file); @@ -8461,6 +8463,8 @@ bool Isolate::GetHeapCodeAndMetadataStatistics( code_statistics->code_and_metadata_size_ = isolate->code_and_metadata_size(); code_statistics->bytecode_and_metadata_size_ = isolate->bytecode_and_metadata_size(); + code_statistics->external_script_source_size_ = + isolate->external_script_source_size(); return true; } diff --git a/src/heap/code-stats.cc b/src/heap/code-stats.cc index 4cdc674896..1753e29afd 100644 --- a/src/heap/code-stats.cc +++ b/src/heap/code-stats.cc @@ -11,32 +11,41 @@ namespace internal { // Record code statisitcs. void CodeStatistics::RecordCodeAndMetadataStatistics(HeapObject* object, Isolate* isolate) { - if (!object->IsAbstractCode()) { - return; - } - - // Record code+metadata statisitcs. - AbstractCode* abstract_code = AbstractCode::cast(object); - int size = abstract_code->SizeIncludingMetadata(); - if (abstract_code->IsCode()) { - size += isolate->code_and_metadata_size(); - isolate->set_code_and_metadata_size(size); - } else { - size += isolate->bytecode_and_metadata_size(); - isolate->set_bytecode_and_metadata_size(size); - } + if (object->IsScript()) { + Script* script = Script::cast(object); + // Log the size of external source code. + Object* source = script->source(); + if (source->IsExternalString()) { + ExternalString* external_source_string = ExternalString::cast(source); + int size = isolate->external_script_source_size(); + size += external_source_string->ExternalPayloadSize(); + isolate->set_external_script_source_size(size); + } + } else if (object->IsAbstractCode()) { + // Record code+metadata statisitcs. + AbstractCode* abstract_code = AbstractCode::cast(object); + int size = abstract_code->SizeIncludingMetadata(); + if (abstract_code->IsCode()) { + size += isolate->code_and_metadata_size(); + isolate->set_code_and_metadata_size(size); + } else { + size += isolate->bytecode_and_metadata_size(); + isolate->set_bytecode_and_metadata_size(size); + } #ifdef DEBUG - // Record code kind and code comment statistics. - isolate->code_kind_statistics()[abstract_code->kind()] += - abstract_code->Size(); - CodeStatistics::CollectCodeCommentStatistics(object, isolate); + // Record code kind and code comment statistics. + isolate->code_kind_statistics()[abstract_code->kind()] += + abstract_code->Size(); + CodeStatistics::CollectCodeCommentStatistics(object, isolate); #endif + } } void CodeStatistics::ResetCodeAndMetadataStatistics(Isolate* isolate) { isolate->set_code_and_metadata_size(0); isolate->set_bytecode_and_metadata_size(0); + isolate->set_external_script_source_size(0); #ifdef DEBUG ResetCodeStatistics(isolate); #endif diff --git a/src/heap/heap.cc b/src/heap/heap.cc index c5cf87ea3c..0d1038d7cb 100644 --- a/src/heap/heap.cc +++ b/src/heap/heap.cc @@ -3485,6 +3485,7 @@ bool Heap::InvokeNearHeapLimitCallback() { } void Heap::CollectCodeStatistics() { + TRACE_EVENT0("v8", "Heap::CollectCodeStatistics"); CodeStatistics::ResetCodeAndMetadataStatistics(isolate()); // We do not look for code in new space, or map space. If code // somehow ends up in those spaces, we would miss it here. diff --git a/src/heap/object-stats.cc b/src/heap/object-stats.cc index 679292b3f9..82b4363f57 100644 --- a/src/heap/object-stats.cc +++ b/src/heap/object-stats.cc @@ -644,10 +644,7 @@ void ObjectStatsCollectorImpl::RecordVirtualScriptDetails(Script* script) { // The contents of external strings aren't on the heap, so we have to record // them manually. ExternalString* external_source_string = ExternalString::cast(source); - size_t length_multiplier = external_source_string->IsTwoByteRepresentation() - ? kShortSize - : kCharSize; - size_t off_heap_size = external_source_string->length() * length_multiplier; + size_t off_heap_size = external_source_string->ExternalPayloadSize(); size_t on_heap_size = external_source_string->Size(); RecordVirtualObjectStats(script, external_source_string, ObjectStats::SCRIPT_SOURCE_EXTERNAL_TYPE, diff --git a/src/isolate.h b/src/isolate.h index ea9a7f69a9..446aaff42b 100644 --- a/src/isolate.h +++ b/src/isolate.h @@ -430,6 +430,7 @@ typedef std::vector DebugObjectCache; V(const v8::StartupData*, snapshot_blob, nullptr) \ V(int, code_and_metadata_size, 0) \ V(int, bytecode_and_metadata_size, 0) \ + V(int, external_script_source_size, 0) \ /* true if being profiled. Causes collection of extra compile info. */ \ V(bool, is_profiling, false) \ /* true if a trace is being formatted through Error.prepareStackTrace. */ \ diff --git a/src/objects.cc b/src/objects.cc index a6f8c2bffa..357b29b376 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -12089,6 +12089,11 @@ void SeqTwoByteString::clear_padding() { SizeFor(length()) - data_size); } +int ExternalString::ExternalPayloadSize() const { + int length_multiplier = IsTwoByteRepresentation() ? kShortSize : kCharSize; + return length() * length_multiplier; +} + uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) { // For array indexes mix the length into the hash as an array index could // be zero. diff --git a/src/objects/string-inl.h b/src/objects/string-inl.h index 1438934126..a5d02aec80 100644 --- a/src/objects/string-inl.h +++ b/src/objects/string-inl.h @@ -529,7 +529,7 @@ HeapObject* ThinString::unchecked_actual() const { return reinterpret_cast(READ_FIELD(this, kActualOffset)); } -bool ExternalString::is_short() { +bool ExternalString::is_short() const { InstanceType type = map()->instance_type(); return (type & kShortExternalStringMask) == kShortExternalStringTag; } diff --git a/src/objects/string.h b/src/objects/string.h index 07fe164957..e270e5a9b6 100644 --- a/src/objects/string.h +++ b/src/objects/string.h @@ -717,7 +717,9 @@ class ExternalString : public String { static const int kSize = kResourceDataOffset + kPointerSize; // Return whether external string is short (data pointer is not cached). - inline bool is_short(); + inline bool is_short() const; + // Size in bytes of the external payload. + int ExternalPayloadSize() const; // Used in the serializer/deserializer. inline Address resource_as_address();