LCOV - code coverage report
Current view: top level - src/heap - object-stats.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 0 263 0.0 %
Date: 2017-10-20 Functions: 0 37 0.0 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/heap/object-stats.h"
       6             : 
       7             : #include "src/assembler-inl.h"
       8             : #include "src/compilation-cache.h"
       9             : #include "src/counters.h"
      10             : #include "src/heap/heap-inl.h"
      11             : #include "src/isolate.h"
      12             : #include "src/objects/compilation-cache-inl.h"
      13             : #include "src/utils.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : 
      18             : static base::LazyMutex object_stats_mutex = LAZY_MUTEX_INITIALIZER;
      19             : 
      20             : 
      21           0 : void ObjectStats::ClearObjectStats(bool clear_last_time_stats) {
      22           0 :   memset(object_counts_, 0, sizeof(object_counts_));
      23           0 :   memset(object_sizes_, 0, sizeof(object_sizes_));
      24           0 :   memset(over_allocated_, 0, sizeof(over_allocated_));
      25           0 :   memset(size_histogram_, 0, sizeof(size_histogram_));
      26           0 :   memset(over_allocated_histogram_, 0, sizeof(over_allocated_histogram_));
      27           0 :   if (clear_last_time_stats) {
      28           0 :     memset(object_counts_last_time_, 0, sizeof(object_counts_last_time_));
      29           0 :     memset(object_sizes_last_time_, 0, sizeof(object_sizes_last_time_));
      30             :   }
      31             :   visited_fixed_array_sub_types_.clear();
      32           0 : }
      33             : 
      34             : // Tell the compiler to never inline this: occasionally, the optimizer will
      35             : // decide to inline this and unroll the loop, making the compiled code more than
      36             : // 100KB larger.
      37           0 : V8_NOINLINE static void PrintJSONArray(size_t* array, const int len) {
      38           0 :   PrintF("[ ");
      39           0 :   for (int i = 0; i < len; i++) {
      40           0 :     PrintF("%zu", array[i]);
      41           0 :     if (i != (len - 1)) PrintF(", ");
      42             :   }
      43           0 :   PrintF(" ]");
      44           0 : }
      45             : 
      46           0 : V8_NOINLINE static void DumpJSONArray(std::stringstream& stream, size_t* array,
      47             :                                       const int len) {
      48           0 :   stream << "[";
      49           0 :   for (int i = 0; i < len; i++) {
      50           0 :     stream << array[i];
      51           0 :     if (i != (len - 1)) stream << ",";
      52             :   }
      53           0 :   stream << "]";
      54           0 : }
      55             : 
      56           0 : void ObjectStats::PrintKeyAndId(const char* key, int gc_count) {
      57             :   PrintF("\"isolate\": \"%p\", \"id\": %d, \"key\": \"%s\", ",
      58           0 :          reinterpret_cast<void*>(isolate()), gc_count, key);
      59           0 : }
      60             : 
      61           0 : void ObjectStats::PrintInstanceTypeJSON(const char* key, int gc_count,
      62             :                                         const char* name, int index) {
      63           0 :   PrintF("{ ");
      64             :   PrintKeyAndId(key, gc_count);
      65           0 :   PrintF("\"type\": \"instance_type_data\", ");
      66           0 :   PrintF("\"instance_type\": %d, ", index);
      67           0 :   PrintF("\"instance_type_name\": \"%s\", ", name);
      68           0 :   PrintF("\"overall\": %zu, ", object_sizes_[index]);
      69           0 :   PrintF("\"count\": %zu, ", object_counts_[index]);
      70           0 :   PrintF("\"over_allocated\": %zu, ", over_allocated_[index]);
      71           0 :   PrintF("\"histogram\": ");
      72           0 :   PrintJSONArray(size_histogram_[index], kNumberOfBuckets);
      73           0 :   PrintF(",");
      74           0 :   PrintF("\"over_allocated_histogram\": ");
      75           0 :   PrintJSONArray(over_allocated_histogram_[index], kNumberOfBuckets);
      76           0 :   PrintF(" }\n");
      77           0 : }
      78             : 
      79           0 : void ObjectStats::PrintJSON(const char* key) {
      80             :   double time = isolate()->time_millis_since_init();
      81           0 :   int gc_count = heap()->gc_count();
      82             : 
      83             :   // gc_descriptor
      84           0 :   PrintF("{ ");
      85             :   PrintKeyAndId(key, gc_count);
      86           0 :   PrintF("\"type\": \"gc_descriptor\", \"time\": %f }\n", time);
      87             :   // bucket_sizes
      88           0 :   PrintF("{ ");
      89             :   PrintKeyAndId(key, gc_count);
      90           0 :   PrintF("\"type\": \"bucket_sizes\", \"sizes\": [ ");
      91           0 :   for (int i = 0; i < kNumberOfBuckets; i++) {
      92           0 :     PrintF("%d", 1 << (kFirstBucketShift + i));
      93           0 :     if (i != (kNumberOfBuckets - 1)) PrintF(", ");
      94             :   }
      95           0 :   PrintF(" ] }\n");
      96             : 
      97             : #define INSTANCE_TYPE_WRAPPER(name) \
      98             :   PrintInstanceTypeJSON(key, gc_count, #name, name);
      99             : #define CODE_KIND_WRAPPER(name)                        \
     100             :   PrintInstanceTypeJSON(key, gc_count, "*CODE_" #name, \
     101             :                         FIRST_CODE_KIND_SUB_TYPE + Code::name);
     102             : #define FIXED_ARRAY_SUB_INSTANCE_TYPE_WRAPPER(name)           \
     103             :   PrintInstanceTypeJSON(key, gc_count, "*FIXED_ARRAY_" #name, \
     104             :                         FIRST_FIXED_ARRAY_SUB_TYPE + name);
     105             : 
     106           0 :   INSTANCE_TYPE_LIST(INSTANCE_TYPE_WRAPPER)
     107           0 :   CODE_KIND_LIST(CODE_KIND_WRAPPER)
     108           0 :   FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(FIXED_ARRAY_SUB_INSTANCE_TYPE_WRAPPER)
     109             : 
     110             : #undef INSTANCE_TYPE_WRAPPER
     111             : #undef CODE_KIND_WRAPPER
     112             : #undef FIXED_ARRAY_SUB_INSTANCE_TYPE_WRAPPER
     113             : #undef PRINT_INSTANCE_TYPE_DATA
     114             : #undef PRINT_KEY_AND_ID
     115           0 : }
     116             : 
     117           0 : void ObjectStats::DumpInstanceTypeData(std::stringstream& stream,
     118             :                                        const char* name, int index) {
     119           0 :   stream << "\"" << name << "\":{";
     120           0 :   stream << "\"type\":" << static_cast<int>(index) << ",";
     121           0 :   stream << "\"overall\":" << object_sizes_[index] << ",";
     122           0 :   stream << "\"count\":" << object_counts_[index] << ",";
     123           0 :   stream << "\"over_allocated\":" << over_allocated_[index] << ",";
     124           0 :   stream << "\"histogram\":";
     125           0 :   DumpJSONArray(stream, size_histogram_[index], kNumberOfBuckets);
     126           0 :   stream << ",\"over_allocated_histogram\":";
     127           0 :   DumpJSONArray(stream, over_allocated_histogram_[index], kNumberOfBuckets);
     128           0 :   stream << "},";
     129           0 : }
     130             : 
     131           0 : void ObjectStats::Dump(std::stringstream& stream) {
     132             :   double time = isolate()->time_millis_since_init();
     133           0 :   int gc_count = heap()->gc_count();
     134             : 
     135           0 :   stream << "{";
     136           0 :   stream << "\"isolate\":\"" << reinterpret_cast<void*>(isolate()) << "\",";
     137           0 :   stream << "\"id\":" << gc_count << ",";
     138           0 :   stream << "\"time\":" << time << ",";
     139           0 :   stream << "\"bucket_sizes\":[";
     140           0 :   for (int i = 0; i < kNumberOfBuckets; i++) {
     141           0 :     stream << (1 << (kFirstBucketShift + i));
     142           0 :     if (i != (kNumberOfBuckets - 1)) stream << ",";
     143             :   }
     144           0 :   stream << "],";
     145           0 :   stream << "\"type_data\":{";
     146             : 
     147             : #define INSTANCE_TYPE_WRAPPER(name) DumpInstanceTypeData(stream, #name, name);
     148             : #define CODE_KIND_WRAPPER(name)                \
     149             :   DumpInstanceTypeData(stream, "*CODE_" #name, \
     150             :                        FIRST_CODE_KIND_SUB_TYPE + Code::name);
     151             : 
     152             : #define FIXED_ARRAY_SUB_INSTANCE_TYPE_WRAPPER(name)   \
     153             :   DumpInstanceTypeData(stream, "*FIXED_ARRAY_" #name, \
     154             :                        FIRST_FIXED_ARRAY_SUB_TYPE + name);
     155             : 
     156           0 :   INSTANCE_TYPE_LIST(INSTANCE_TYPE_WRAPPER);
     157           0 :   CODE_KIND_LIST(CODE_KIND_WRAPPER);
     158           0 :   FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(FIXED_ARRAY_SUB_INSTANCE_TYPE_WRAPPER);
     159           0 :   stream << "\"END\":{}}}";
     160             : 
     161             : #undef INSTANCE_TYPE_WRAPPER
     162             : #undef CODE_KIND_WRAPPER
     163             : #undef FIXED_ARRAY_SUB_INSTANCE_TYPE_WRAPPER
     164             : #undef PRINT_INSTANCE_TYPE_DATA
     165           0 : }
     166             : 
     167           0 : void ObjectStats::CheckpointObjectStats() {
     168             :   base::LockGuard<base::Mutex> lock_guard(object_stats_mutex.Pointer());
     169             :   Counters* counters = isolate()->counters();
     170             : #define ADJUST_LAST_TIME_OBJECT_COUNT(name)              \
     171             :   counters->count_of_##name()->Increment(                \
     172             :       static_cast<int>(object_counts_[name]));           \
     173             :   counters->count_of_##name()->Decrement(                \
     174             :       static_cast<int>(object_counts_last_time_[name])); \
     175             :   counters->size_of_##name()->Increment(                 \
     176             :       static_cast<int>(object_sizes_[name]));            \
     177             :   counters->size_of_##name()->Decrement(                 \
     178             :       static_cast<int>(object_sizes_last_time_[name]));
     179           0 :   INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT)
     180             : #undef ADJUST_LAST_TIME_OBJECT_COUNT
     181             :   int index;
     182             : #define ADJUST_LAST_TIME_OBJECT_COUNT(name)               \
     183             :   index = FIRST_CODE_KIND_SUB_TYPE + Code::name;          \
     184             :   counters->count_of_CODE_TYPE_##name()->Increment(       \
     185             :       static_cast<int>(object_counts_[index]));           \
     186             :   counters->count_of_CODE_TYPE_##name()->Decrement(       \
     187             :       static_cast<int>(object_counts_last_time_[index])); \
     188             :   counters->size_of_CODE_TYPE_##name()->Increment(        \
     189             :       static_cast<int>(object_sizes_[index]));            \
     190             :   counters->size_of_CODE_TYPE_##name()->Decrement(        \
     191             :       static_cast<int>(object_sizes_last_time_[index]));
     192           0 :   CODE_KIND_LIST(ADJUST_LAST_TIME_OBJECT_COUNT)
     193             : #undef ADJUST_LAST_TIME_OBJECT_COUNT
     194             : #define ADJUST_LAST_TIME_OBJECT_COUNT(name)               \
     195             :   index = FIRST_FIXED_ARRAY_SUB_TYPE + name;              \
     196             :   counters->count_of_FIXED_ARRAY_##name()->Increment(     \
     197             :       static_cast<int>(object_counts_[index]));           \
     198             :   counters->count_of_FIXED_ARRAY_##name()->Decrement(     \
     199             :       static_cast<int>(object_counts_last_time_[index])); \
     200             :   counters->size_of_FIXED_ARRAY_##name()->Increment(      \
     201             :       static_cast<int>(object_sizes_[index]));            \
     202             :   counters->size_of_FIXED_ARRAY_##name()->Decrement(      \
     203             :       static_cast<int>(object_sizes_last_time_[index]));
     204           0 :   FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT)
     205             : #undef ADJUST_LAST_TIME_OBJECT_COUNT
     206             : 
     207           0 :   MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_));
     208           0 :   MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_));
     209           0 :   ClearObjectStats();
     210           0 : }
     211             : 
     212             : 
     213           0 : Isolate* ObjectStats::isolate() { return heap()->isolate(); }
     214             : 
     215           0 : ObjectStatsCollector::ObjectStatsCollector(Heap* heap, ObjectStats* stats)
     216             :     : heap_(heap),
     217             :       stats_(stats),
     218             :       marking_state_(
     219           0 :           heap->mark_compact_collector()->non_atomic_marking_state()) {}
     220             : 
     221           0 : void ObjectStatsCollector::CollectStatistics(HeapObject* obj) {
     222             :   Map* map = obj->map();
     223             : 
     224             :   // Record for the InstanceType.
     225           0 :   int object_size = obj->Size();
     226           0 :   stats_->RecordObjectStats(map->instance_type(), object_size);
     227             : 
     228             :   // Record specific sub types where possible.
     229           0 :   if (obj->IsMap()) RecordMapDetails(Map::cast(obj));
     230           0 :   if (obj->IsObjectTemplateInfo() || obj->IsFunctionTemplateInfo()) {
     231           0 :     RecordTemplateInfoDetails(TemplateInfo::cast(obj));
     232             :   }
     233           0 :   if (obj->IsBytecodeArray()) {
     234           0 :     RecordBytecodeArrayDetails(BytecodeArray::cast(obj));
     235             :   }
     236           0 :   if (obj->IsCode()) RecordCodeDetails(Code::cast(obj));
     237           0 :   if (obj->IsSharedFunctionInfo()) {
     238           0 :     RecordSharedFunctionInfoDetails(SharedFunctionInfo::cast(obj));
     239             :   }
     240           0 :   if (obj->IsFixedArray()) RecordFixedArrayDetails(FixedArray::cast(obj));
     241           0 :   if (obj->IsJSObject()) RecordJSObjectDetails(JSObject::cast(obj));
     242           0 :   if (obj->IsJSWeakCollection()) {
     243           0 :     RecordJSWeakCollectionDetails(JSWeakCollection::cast(obj));
     244             :   }
     245           0 :   if (obj->IsJSCollection()) {
     246           0 :     RecordJSCollectionDetails(JSObject::cast(obj));
     247             :   }
     248           0 :   if (obj->IsScript()) RecordScriptDetails(Script::cast(obj));
     249           0 : }
     250             : 
     251           0 : class ObjectStatsCollector::CompilationCacheTableVisitor : public RootVisitor {
     252             :  public:
     253             :   explicit CompilationCacheTableVisitor(ObjectStatsCollector* parent)
     254           0 :       : parent_(parent) {}
     255             : 
     256           0 :   void VisitRootPointers(Root root, Object** start, Object** end) override {
     257           0 :     for (Object** current = start; current < end; current++) {
     258           0 :       HeapObject* obj = HeapObject::cast(*current);
     259           0 :       if (obj->IsUndefined(parent_->heap_->isolate())) continue;
     260           0 :       CHECK(obj->IsCompilationCacheTable());
     261             :       parent_->RecordHashTableHelper(nullptr, CompilationCacheTable::cast(obj),
     262           0 :                                      COMPILATION_CACHE_TABLE_SUB_TYPE);
     263             :     }
     264           0 :   }
     265             : 
     266             :  private:
     267             :   ObjectStatsCollector* parent_;
     268             : };
     269             : 
     270           0 : void ObjectStatsCollector::CollectGlobalStatistics() {
     271             :   // Global FixedArrays.
     272           0 :   RecordFixedArrayHelper(nullptr, heap_->weak_new_space_object_to_code_list(),
     273           0 :                          WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE, 0);
     274             :   RecordFixedArrayHelper(nullptr, heap_->serialized_templates(),
     275           0 :                          SERIALIZED_TEMPLATES_SUB_TYPE, 0);
     276             :   RecordFixedArrayHelper(nullptr, heap_->number_string_cache(),
     277           0 :                          NUMBER_STRING_CACHE_SUB_TYPE, 0);
     278             :   RecordFixedArrayHelper(nullptr, heap_->single_character_string_cache(),
     279           0 :                          SINGLE_CHARACTER_STRING_CACHE_SUB_TYPE, 0);
     280             :   RecordFixedArrayHelper(nullptr, heap_->string_split_cache(),
     281           0 :                          STRING_SPLIT_CACHE_SUB_TYPE, 0);
     282             :   RecordFixedArrayHelper(nullptr, heap_->regexp_multiple_cache(),
     283           0 :                          REGEXP_MULTIPLE_CACHE_SUB_TYPE, 0);
     284           0 :   RecordFixedArrayHelper(nullptr, heap_->retained_maps(),
     285           0 :                          RETAINED_MAPS_SUB_TYPE, 0);
     286             : 
     287             :   // Global weak FixedArrays.
     288             :   RecordFixedArrayHelper(
     289           0 :       nullptr, WeakFixedArray::cast(heap_->noscript_shared_function_infos()),
     290           0 :       NOSCRIPT_SHARED_FUNCTION_INFOS_SUB_TYPE, 0);
     291           0 :   RecordFixedArrayHelper(nullptr, WeakFixedArray::cast(heap_->script_list()),
     292           0 :                          SCRIPT_LIST_SUB_TYPE, 0);
     293             : 
     294             :   // Global hash tables.
     295           0 :   RecordHashTableHelper(nullptr, heap_->string_table(), STRING_TABLE_SUB_TYPE);
     296             :   RecordHashTableHelper(nullptr, heap_->weak_object_to_code_table(),
     297           0 :                         OBJECT_TO_CODE_SUB_TYPE);
     298             :   RecordHashTableHelper(nullptr, heap_->code_stubs(),
     299           0 :                         CODE_STUBS_TABLE_SUB_TYPE);
     300             :   RecordHashTableHelper(nullptr, heap_->empty_property_dictionary(),
     301           0 :                         EMPTY_PROPERTIES_DICTIONARY_SUB_TYPE);
     302           0 :   CompilationCache* compilation_cache = heap_->isolate()->compilation_cache();
     303             :   CompilationCacheTableVisitor v(this);
     304           0 :   compilation_cache->Iterate(&v);
     305           0 : }
     306             : 
     307           0 : static bool CanRecordFixedArray(Heap* heap, FixedArrayBase* array) {
     308           0 :   return (array->map()->instance_type() == FIXED_ARRAY_TYPE ||
     309           0 :           array->map()->instance_type() == HASH_TABLE_TYPE) &&
     310           0 :          array->map() != heap->fixed_double_array_map() &&
     311           0 :          array != heap->empty_fixed_array() &&
     312           0 :          array != heap->empty_byte_array() &&
     313           0 :          array != heap->empty_sloppy_arguments_elements() &&
     314           0 :          array != heap->empty_slow_element_dictionary() &&
     315           0 :          array != heap->empty_descriptor_array() &&
     316           0 :          array != heap->empty_property_dictionary();
     317             : }
     318             : 
     319           0 : static bool IsCowArray(Heap* heap, FixedArrayBase* array) {
     320             :   return array->map() == heap->fixed_cow_array_map();
     321             : }
     322             : 
     323           0 : bool ObjectStatsCollector::SameLiveness(HeapObject* obj1, HeapObject* obj2) {
     324           0 :   return obj1 == nullptr || obj2 == nullptr ||
     325           0 :          marking_state_->Color(obj1) == marking_state_->Color(obj2);
     326             : }
     327             : 
     328           0 : bool ObjectStatsCollector::RecordFixedArrayHelper(HeapObject* parent,
     329             :                                                   FixedArray* array,
     330             :                                                   int subtype,
     331             :                                                   size_t overhead) {
     332           0 :   if (SameLiveness(parent, array) && CanRecordFixedArray(heap_, array) &&
     333           0 :       !IsCowArray(heap_, array)) {
     334           0 :     return stats_->RecordFixedArraySubTypeStats(array, subtype, array->Size(),
     335           0 :                                                 overhead);
     336             :   }
     337             :   return false;
     338             : }
     339             : 
     340           0 : void ObjectStatsCollector::RecursivelyRecordFixedArrayHelper(HeapObject* parent,
     341             :                                                              FixedArray* array,
     342             :                                                              int subtype) {
     343           0 :   if (RecordFixedArrayHelper(parent, array, subtype, 0)) {
     344           0 :     for (int i = 0; i < array->length(); i++) {
     345           0 :       if (array->get(i)->IsFixedArray()) {
     346             :         RecursivelyRecordFixedArrayHelper(
     347           0 :             parent, FixedArray::cast(array->get(i)), subtype);
     348             :       }
     349             :     }
     350             :   }
     351           0 : }
     352             : 
     353             : template <class HashTable>
     354           0 : void ObjectStatsCollector::RecordHashTableHelper(HeapObject* parent,
     355             :                                                  HashTable* array,
     356             :                                                  int subtype) {
     357           0 :   int used = array->NumberOfElements() * HashTable::kEntrySize * kPointerSize;
     358           0 :   CHECK_GE(array->Size(), used);
     359           0 :   size_t overhead = array->Size() - used -
     360             :                     HashTable::kElementsStartIndex * kPointerSize -
     361           0 :                     FixedArray::kHeaderSize;
     362           0 :   RecordFixedArrayHelper(parent, array, subtype, overhead);
     363           0 : }
     364             : 
     365           0 : void ObjectStatsCollector::RecordJSObjectDetails(JSObject* object) {
     366             :   size_t overhead = 0;
     367             :   FixedArrayBase* elements = object->elements();
     368           0 :   if (CanRecordFixedArray(heap_, elements) && !IsCowArray(heap_, elements)) {
     369           0 :     if (elements->IsDictionary() && SameLiveness(object, elements)) {
     370             :       SeededNumberDictionary* dict = SeededNumberDictionary::cast(elements);
     371           0 :       RecordHashTableHelper(object, dict, DICTIONARY_ELEMENTS_SUB_TYPE);
     372             :     } else {
     373           0 :       if (IsHoleyElementsKind(object->GetElementsKind())) {
     374           0 :         int used = object->GetFastElementsUsage() * kPointerSize;
     375           0 :         if (object->GetElementsKind() == HOLEY_DOUBLE_ELEMENTS) used *= 2;
     376           0 :         CHECK_GE(elements->Size(), used);
     377           0 :         overhead = elements->Size() - used - FixedArray::kHeaderSize;
     378             :       }
     379             :       stats_->RecordFixedArraySubTypeStats(elements, PACKED_ELEMENTS_SUB_TYPE,
     380           0 :                                            elements->Size(), overhead);
     381             :     }
     382             :   }
     383             : 
     384           0 :   if (object->IsJSGlobalObject()) {
     385             :     GlobalDictionary* properties =
     386             :         JSGlobalObject::cast(object)->global_dictionary();
     387           0 :     if (CanRecordFixedArray(heap_, properties) &&
     388           0 :         SameLiveness(object, properties)) {
     389           0 :       RecordHashTableHelper(object, properties, DICTIONARY_PROPERTIES_SUB_TYPE);
     390             :     }
     391           0 :   } else if (!object->HasFastProperties()) {
     392             :     NameDictionary* properties = object->property_dictionary();
     393           0 :     if (CanRecordFixedArray(heap_, properties) &&
     394           0 :         SameLiveness(object, properties)) {
     395           0 :       RecordHashTableHelper(object, properties, DICTIONARY_PROPERTIES_SUB_TYPE);
     396             :     }
     397             :   }
     398           0 : }
     399             : 
     400           0 : void ObjectStatsCollector::RecordJSWeakCollectionDetails(
     401             :     JSWeakCollection* obj) {
     402           0 :   if (obj->table()->IsHashTable()) {
     403             :     ObjectHashTable* table = ObjectHashTable::cast(obj->table());
     404           0 :     int used = table->NumberOfElements() * ObjectHashTable::kEntrySize;
     405           0 :     size_t overhead = table->Size() - used;
     406           0 :     RecordFixedArrayHelper(obj, table, JS_WEAK_COLLECTION_SUB_TYPE, overhead);
     407             :   }
     408           0 : }
     409             : 
     410           0 : void ObjectStatsCollector::RecordJSCollectionDetails(JSObject* obj) {
     411             :   // The JS versions use a different HashTable implementation that cannot use
     412             :   // the regular helper. Since overall impact is usually small just record
     413             :   // without overhead.
     414           0 :   if (obj->IsJSMap()) {
     415             :     RecordFixedArrayHelper(nullptr, FixedArray::cast(JSMap::cast(obj)->table()),
     416           0 :                            JS_COLLECTION_SUB_TYPE, 0);
     417             :   }
     418           0 :   if (obj->IsJSSet()) {
     419             :     RecordFixedArrayHelper(nullptr, FixedArray::cast(JSSet::cast(obj)->table()),
     420           0 :                            JS_COLLECTION_SUB_TYPE, 0);
     421             :   }
     422           0 : }
     423             : 
     424           0 : void ObjectStatsCollector::RecordScriptDetails(Script* obj) {
     425             :   FixedArray* infos = FixedArray::cast(obj->shared_function_infos());
     426           0 :   RecordFixedArrayHelper(obj, infos, SHARED_FUNCTION_INFOS_SUB_TYPE, 0);
     427           0 : }
     428             : 
     429           0 : void ObjectStatsCollector::RecordMapDetails(Map* map_obj) {
     430             :   DescriptorArray* array = map_obj->instance_descriptors();
     431           0 :   if (map_obj->owns_descriptors() && array != heap_->empty_descriptor_array() &&
     432           0 :       SameLiveness(map_obj, array)) {
     433           0 :     RecordFixedArrayHelper(map_obj, array, DESCRIPTOR_ARRAY_SUB_TYPE, 0);
     434             :     EnumCache* enum_cache = array->GetEnumCache();
     435           0 :     RecordFixedArrayHelper(array, enum_cache->keys(), ENUM_CACHE_SUB_TYPE, 0);
     436             :     RecordFixedArrayHelper(array, enum_cache->indices(),
     437           0 :                            ENUM_INDICES_CACHE_SUB_TYPE, 0);
     438             :   }
     439             : 
     440           0 :   for (DependentCode* cur_dependent_code = map_obj->dependent_code();
     441           0 :        cur_dependent_code != heap_->empty_fixed_array();
     442             :        cur_dependent_code = DependentCode::cast(
     443             :            cur_dependent_code->get(DependentCode::kNextLinkIndex))) {
     444             :     RecordFixedArrayHelper(map_obj, cur_dependent_code, DEPENDENT_CODE_SUB_TYPE,
     445           0 :                            0);
     446             :   }
     447             : 
     448           0 :   if (map_obj->is_prototype_map()) {
     449           0 :     if (map_obj->prototype_info()->IsPrototypeInfo()) {
     450             :       PrototypeInfo* info = PrototypeInfo::cast(map_obj->prototype_info());
     451             :       Object* users = info->prototype_users();
     452           0 :       if (users->IsWeakFixedArray()) {
     453             :         RecordFixedArrayHelper(map_obj, WeakFixedArray::cast(users),
     454           0 :                                PROTOTYPE_USERS_SUB_TYPE, 0);
     455             :       }
     456             :     }
     457             :   }
     458           0 : }
     459             : 
     460           0 : void ObjectStatsCollector::RecordTemplateInfoDetails(TemplateInfo* obj) {
     461           0 :   if (obj->property_accessors()->IsFixedArray()) {
     462             :     RecordFixedArrayHelper(obj, FixedArray::cast(obj->property_accessors()),
     463           0 :                            TEMPLATE_INFO_SUB_TYPE, 0);
     464             :   }
     465           0 :   if (obj->property_list()->IsFixedArray()) {
     466             :     RecordFixedArrayHelper(obj, FixedArray::cast(obj->property_list()),
     467           0 :                            TEMPLATE_INFO_SUB_TYPE, 0);
     468             :   }
     469           0 : }
     470             : 
     471           0 : void ObjectStatsCollector::RecordBytecodeArrayDetails(BytecodeArray* obj) {
     472             :   RecordFixedArrayHelper(obj, obj->constant_pool(),
     473           0 :                          BYTECODE_ARRAY_CONSTANT_POOL_SUB_TYPE, 0);
     474             :   RecordFixedArrayHelper(obj, obj->handler_table(),
     475           0 :                          BYTECODE_ARRAY_HANDLER_TABLE_SUB_TYPE, 0);
     476           0 : }
     477             : 
     478           0 : void ObjectStatsCollector::RecordCodeDetails(Code* code) {
     479           0 :   stats_->RecordCodeSubTypeStats(code->kind(), code->Size());
     480             :   RecordFixedArrayHelper(code, code->deoptimization_data(),
     481           0 :                          DEOPTIMIZATION_DATA_SUB_TYPE, 0);
     482           0 :   if (code->kind() == Code::Kind::OPTIMIZED_FUNCTION) {
     483             :     DeoptimizationData* input_data =
     484             :         DeoptimizationData::cast(code->deoptimization_data());
     485           0 :     if (input_data->length() > 0) {
     486             :       RecordFixedArrayHelper(code->deoptimization_data(),
     487             :                              input_data->LiteralArray(),
     488           0 :                              OPTIMIZED_CODE_LITERALS_SUB_TYPE, 0);
     489             :     }
     490             :   }
     491             :   RecordFixedArrayHelper(code, code->handler_table(), HANDLER_TABLE_SUB_TYPE,
     492           0 :                          0);
     493             :   int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
     494           0 :   for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
     495           0 :     RelocInfo::Mode mode = it.rinfo()->rmode();
     496           0 :     if (mode == RelocInfo::EMBEDDED_OBJECT) {
     497           0 :       Object* target = it.rinfo()->target_object();
     498           0 :       if (target->IsFixedArray()) {
     499             :         RecursivelyRecordFixedArrayHelper(code, FixedArray::cast(target),
     500           0 :                                           EMBEDDED_OBJECT_SUB_TYPE);
     501             :       }
     502             :     }
     503             :   }
     504           0 : }
     505             : 
     506           0 : void ObjectStatsCollector::RecordSharedFunctionInfoDetails(
     507             :     SharedFunctionInfo* sfi) {
     508             :   FixedArray* scope_info = sfi->scope_info();
     509           0 :   RecordFixedArrayHelper(sfi, scope_info, SCOPE_INFO_SUB_TYPE, 0);
     510             :   FeedbackMetadata* feedback_metadata = sfi->feedback_metadata();
     511           0 :   if (!feedback_metadata->is_empty()) {
     512             :     RecordFixedArrayHelper(sfi, feedback_metadata, FEEDBACK_METADATA_SUB_TYPE,
     513           0 :                            0);
     514             :   }
     515           0 : }
     516             : 
     517           0 : void ObjectStatsCollector::RecordFixedArrayDetails(FixedArray* array) {
     518           0 :   if (array->IsContext()) {
     519           0 :     RecordFixedArrayHelper(nullptr, array, CONTEXT_SUB_TYPE, 0);
     520             :   }
     521           0 :   if (IsCowArray(heap_, array) && CanRecordFixedArray(heap_, array)) {
     522             :     stats_->RecordFixedArraySubTypeStats(array, COPY_ON_WRITE_SUB_TYPE,
     523           0 :                                          array->Size(), 0);
     524             :   }
     525           0 :   if (array->IsNativeContext()) {
     526             :     Context* native_ctx = Context::cast(array);
     527             :     RecordHashTableHelper(array,
     528             :                           native_ctx->slow_template_instantiations_cache(),
     529           0 :                           SLOW_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE);
     530             :     FixedArray* fast_cache = native_ctx->fast_template_instantiations_cache();
     531             :     stats_->RecordFixedArraySubTypeStats(
     532             :         fast_cache, FAST_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE,
     533           0 :         fast_cache->Size(), 0);
     534             :   }
     535           0 : }
     536             : 
     537             : }  // namespace internal
     538             : }  // namespace v8

Generated by: LCOV version 1.10