| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/heap/object-stats.h" | 5 #include "src/heap/object-stats.h" |
| 6 | 6 |
| 7 #include "src/compilation-cache.h" |
| 7 #include "src/counters.h" | 8 #include "src/counters.h" |
| 8 #include "src/heap/heap-inl.h" | 9 #include "src/heap/heap-inl.h" |
| 9 #include "src/isolate.h" | 10 #include "src/isolate.h" |
| 10 #include "src/macro-assembler.h" | 11 #include "src/macro-assembler.h" |
| 11 #include "src/utils.h" | 12 #include "src/utils.h" |
| 12 | 13 |
| 13 namespace v8 { | 14 namespace v8 { |
| 14 namespace internal { | 15 namespace internal { |
| 15 | 16 |
| 16 static base::LazyMutex object_stats_mutex = LAZY_MUTEX_INITIALIZER; | 17 static base::LazyMutex object_stats_mutex = LAZY_MUTEX_INITIALIZER; |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 | 167 |
| 167 void ObjectStatsCollector::CollectStatistics(HeapObject* obj) { | 168 void ObjectStatsCollector::CollectStatistics(HeapObject* obj) { |
| 168 Map* map = obj->map(); | 169 Map* map = obj->map(); |
| 169 | 170 |
| 170 // Record for the InstanceType. | 171 // Record for the InstanceType. |
| 171 int object_size = obj->Size(); | 172 int object_size = obj->Size(); |
| 172 stats_->RecordObjectStats(map->instance_type(), object_size); | 173 stats_->RecordObjectStats(map->instance_type(), object_size); |
| 173 | 174 |
| 174 // Record specific sub types where possible. | 175 // Record specific sub types where possible. |
| 175 if (obj->IsMap()) RecordMapDetails(Map::cast(obj)); | 176 if (obj->IsMap()) RecordMapDetails(Map::cast(obj)); |
| 177 if (obj->IsObjectTemplateInfo() || obj->IsFunctionTemplateInfo()) { |
| 178 RecordTemplateInfoDetails(TemplateInfo::cast(obj)); |
| 179 } |
| 176 if (obj->IsBytecodeArray()) { | 180 if (obj->IsBytecodeArray()) { |
| 177 RecordBytecodeArrayDetails(BytecodeArray::cast(obj)); | 181 RecordBytecodeArrayDetails(BytecodeArray::cast(obj)); |
| 178 } | 182 } |
| 179 if (obj->IsCode()) RecordCodeDetails(Code::cast(obj)); | 183 if (obj->IsCode()) RecordCodeDetails(Code::cast(obj)); |
| 180 if (obj->IsSharedFunctionInfo()) { | 184 if (obj->IsSharedFunctionInfo()) { |
| 181 RecordSharedFunctionInfoDetails(SharedFunctionInfo::cast(obj)); | 185 RecordSharedFunctionInfoDetails(SharedFunctionInfo::cast(obj)); |
| 182 } | 186 } |
| 183 if (obj->IsFixedArray()) RecordFixedArrayDetails(FixedArray::cast(obj)); | 187 if (obj->IsFixedArray()) RecordFixedArrayDetails(FixedArray::cast(obj)); |
| 184 if (obj->IsJSObject()) RecordJSObjectDetails(JSObject::cast(obj)); | 188 if (obj->IsJSObject()) RecordJSObjectDetails(JSObject::cast(obj)); |
| 185 if (obj->IsJSWeakCollection()) { | 189 if (obj->IsJSWeakCollection()) { |
| 186 RecordJSWeakCollectionDetails(JSWeakCollection::cast(obj)); | 190 RecordJSWeakCollectionDetails(JSWeakCollection::cast(obj)); |
| 187 } | 191 } |
| 188 if (obj->IsJSCollection()) { | 192 if (obj->IsJSCollection()) { |
| 189 RecordJSCollectionDetails(JSObject::cast(obj)); | 193 RecordJSCollectionDetails(JSObject::cast(obj)); |
| 190 } | 194 } |
| 191 if (obj->IsJSFunction()) RecordJSFunctionDetails(JSFunction::cast(obj)); | 195 if (obj->IsJSFunction()) RecordJSFunctionDetails(JSFunction::cast(obj)); |
| 192 if (obj->IsScript()) RecordScriptDetails(Script::cast(obj)); | 196 if (obj->IsScript()) RecordScriptDetails(Script::cast(obj)); |
| 193 } | 197 } |
| 194 | 198 |
| 199 class ObjectStatsCollector::CompilationCacheTableVisitor |
| 200 : public ObjectVisitor { |
| 201 public: |
| 202 explicit CompilationCacheTableVisitor(ObjectStatsCollector* parent) |
| 203 : parent_(parent) {} |
| 204 |
| 205 void VisitPointers(Object** start, Object** end) override { |
| 206 for (Object** current = start; current < end; current++) { |
| 207 HeapObject* obj = HeapObject::cast(*current); |
| 208 if (obj->IsUndefined(parent_->heap_->isolate())) continue; |
| 209 CHECK(obj->IsCompilationCacheTable()); |
| 210 parent_->RecordHashTableHelper(nullptr, CompilationCacheTable::cast(obj), |
| 211 COMPILATION_CACHE_TABLE_SUB_TYPE); |
| 212 } |
| 213 } |
| 214 |
| 215 private: |
| 216 ObjectStatsCollector* parent_; |
| 217 }; |
| 218 |
| 195 void ObjectStatsCollector::CollectGlobalStatistics() { | 219 void ObjectStatsCollector::CollectGlobalStatistics() { |
| 196 // Global FixedArrays. | 220 // Global FixedArrays. |
| 197 RecordFixedArrayHelper(nullptr, heap_->weak_new_space_object_to_code_list(), | 221 RecordFixedArrayHelper(nullptr, heap_->weak_new_space_object_to_code_list(), |
| 198 WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE, 0); | 222 WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE, 0); |
| 199 RecordFixedArrayHelper(nullptr, heap_->serialized_templates(), | 223 RecordFixedArrayHelper(nullptr, heap_->serialized_templates(), |
| 200 SERIALIZED_TEMPLATES_SUB_TYPE, 0); | 224 SERIALIZED_TEMPLATES_SUB_TYPE, 0); |
| 201 RecordFixedArrayHelper(nullptr, heap_->number_string_cache(), | 225 RecordFixedArrayHelper(nullptr, heap_->number_string_cache(), |
| 202 NUMBER_STRING_CACHE_SUB_TYPE, 0); | 226 NUMBER_STRING_CACHE_SUB_TYPE, 0); |
| 203 RecordFixedArrayHelper(nullptr, heap_->single_character_string_cache(), | 227 RecordFixedArrayHelper(nullptr, heap_->single_character_string_cache(), |
| 204 SINGLE_CHARACTER_STRING_CACHE_SUB_TYPE, 0); | 228 SINGLE_CHARACTER_STRING_CACHE_SUB_TYPE, 0); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 219 // Global hash tables. | 243 // Global hash tables. |
| 220 RecordHashTableHelper(nullptr, heap_->string_table(), STRING_TABLE_SUB_TYPE); | 244 RecordHashTableHelper(nullptr, heap_->string_table(), STRING_TABLE_SUB_TYPE); |
| 221 RecordHashTableHelper(nullptr, heap_->weak_object_to_code_table(), | 245 RecordHashTableHelper(nullptr, heap_->weak_object_to_code_table(), |
| 222 OBJECT_TO_CODE_SUB_TYPE); | 246 OBJECT_TO_CODE_SUB_TYPE); |
| 223 RecordHashTableHelper(nullptr, heap_->code_stubs(), | 247 RecordHashTableHelper(nullptr, heap_->code_stubs(), |
| 224 CODE_STUBS_TABLE_SUB_TYPE); | 248 CODE_STUBS_TABLE_SUB_TYPE); |
| 225 RecordHashTableHelper(nullptr, heap_->intrinsic_function_names(), | 249 RecordHashTableHelper(nullptr, heap_->intrinsic_function_names(), |
| 226 INTRINSIC_FUNCTION_NAMES_SUB_TYPE); | 250 INTRINSIC_FUNCTION_NAMES_SUB_TYPE); |
| 227 RecordHashTableHelper(nullptr, heap_->empty_properties_dictionary(), | 251 RecordHashTableHelper(nullptr, heap_->empty_properties_dictionary(), |
| 228 EMPTY_PROPERTIES_DICTIONARY_SUB_TYPE); | 252 EMPTY_PROPERTIES_DICTIONARY_SUB_TYPE); |
| 253 CompilationCache* compilation_cache = heap_->isolate()->compilation_cache(); |
| 254 CompilationCacheTableVisitor v(this); |
| 255 compilation_cache->Iterate(&v); |
| 229 } | 256 } |
| 230 | 257 |
| 231 static bool CanRecordFixedArray(Heap* heap, FixedArrayBase* array) { | 258 static bool CanRecordFixedArray(Heap* heap, FixedArrayBase* array) { |
| 232 return array->map()->instance_type() == FIXED_ARRAY_TYPE && | 259 return array->map()->instance_type() == FIXED_ARRAY_TYPE && |
| 233 array->map() != heap->fixed_double_array_map() && | 260 array->map() != heap->fixed_double_array_map() && |
| 234 array != heap->empty_fixed_array() && | 261 array != heap->empty_fixed_array() && |
| 235 array != heap->empty_byte_array() && | 262 array != heap->empty_byte_array() && |
| 236 array != heap->empty_literals_array() && | 263 array != heap->empty_literals_array() && |
| 237 array != heap->empty_sloppy_arguments_elements() && | 264 array != heap->empty_sloppy_arguments_elements() && |
| 238 array != heap->empty_slow_element_dictionary() && | 265 array != heap->empty_slow_element_dictionary() && |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 RecordFixedArrayHelper(array, array->GetEnumCache(), ENUM_CACHE_SUB_TYPE, | 386 RecordFixedArrayHelper(array, array->GetEnumCache(), ENUM_CACHE_SUB_TYPE, |
| 360 0); | 387 0); |
| 361 } | 388 } |
| 362 if (array->HasEnumIndicesCache()) { | 389 if (array->HasEnumIndicesCache()) { |
| 363 RecordFixedArrayHelper(array, array->GetEnumIndicesCache(), | 390 RecordFixedArrayHelper(array, array->GetEnumIndicesCache(), |
| 364 ENUM_INDICES_CACHE_SUB_TYPE, 0); | 391 ENUM_INDICES_CACHE_SUB_TYPE, 0); |
| 365 } | 392 } |
| 366 } | 393 } |
| 367 | 394 |
| 368 if (map_obj->has_code_cache()) { | 395 if (map_obj->has_code_cache()) { |
| 369 RecordFixedArrayHelper(map_obj, map_obj->code_cache(), | 396 FixedArray* code_cache = map_obj->code_cache(); |
| 370 MAP_CODE_CACHE_SUB_TYPE, 0); | 397 if (code_cache->IsCodeCacheHashTable()) { |
| 398 RecordHashTableHelper(map_obj, CodeCacheHashTable::cast(code_cache), |
| 399 MAP_CODE_CACHE_SUB_TYPE); |
| 400 } else { |
| 401 RecordFixedArrayHelper(map_obj, code_cache, MAP_CODE_CACHE_SUB_TYPE, 0); |
| 402 } |
| 371 } | 403 } |
| 372 | 404 |
| 373 for (DependentCode* cur_dependent_code = map_obj->dependent_code(); | 405 for (DependentCode* cur_dependent_code = map_obj->dependent_code(); |
| 374 cur_dependent_code != heap_->empty_fixed_array(); | 406 cur_dependent_code != heap_->empty_fixed_array(); |
| 375 cur_dependent_code = DependentCode::cast( | 407 cur_dependent_code = DependentCode::cast( |
| 376 cur_dependent_code->get(DependentCode::kNextLinkIndex))) { | 408 cur_dependent_code->get(DependentCode::kNextLinkIndex))) { |
| 377 RecordFixedArrayHelper(map_obj, cur_dependent_code, DEPENDENT_CODE_SUB_TYPE, | 409 RecordFixedArrayHelper(map_obj, cur_dependent_code, DEPENDENT_CODE_SUB_TYPE, |
| 378 0); | 410 0); |
| 379 } | 411 } |
| 380 | 412 |
| 381 if (map_obj->is_prototype_map()) { | 413 if (map_obj->is_prototype_map()) { |
| 382 if (map_obj->prototype_info()->IsPrototypeInfo()) { | 414 if (map_obj->prototype_info()->IsPrototypeInfo()) { |
| 383 PrototypeInfo* info = PrototypeInfo::cast(map_obj->prototype_info()); | 415 PrototypeInfo* info = PrototypeInfo::cast(map_obj->prototype_info()); |
| 384 Object* users = info->prototype_users(); | 416 Object* users = info->prototype_users(); |
| 385 if (users->IsWeakFixedArray()) { | 417 if (users->IsWeakFixedArray()) { |
| 386 RecordFixedArrayHelper(map_obj, WeakFixedArray::cast(users), | 418 RecordFixedArrayHelper(map_obj, WeakFixedArray::cast(users), |
| 387 PROTOTYPE_USERS_SUB_TYPE, 0); | 419 PROTOTYPE_USERS_SUB_TYPE, 0); |
| 388 } | 420 } |
| 389 } | 421 } |
| 390 } | 422 } |
| 391 } | 423 } |
| 392 | 424 |
| 425 void ObjectStatsCollector::RecordTemplateInfoDetails(TemplateInfo* obj) { |
| 426 if (obj->property_accessors()->IsFixedArray()) { |
| 427 RecordFixedArrayHelper(obj, FixedArray::cast(obj->property_accessors()), |
| 428 TEMPLATE_INFO_SUB_TYPE, 0); |
| 429 } |
| 430 if (obj->property_list()->IsFixedArray()) { |
| 431 RecordFixedArrayHelper(obj, FixedArray::cast(obj->property_list()), |
| 432 TEMPLATE_INFO_SUB_TYPE, 0); |
| 433 } |
| 434 } |
| 435 |
| 393 void ObjectStatsCollector::RecordBytecodeArrayDetails(BytecodeArray* obj) { | 436 void ObjectStatsCollector::RecordBytecodeArrayDetails(BytecodeArray* obj) { |
| 394 RecordFixedArrayHelper(obj, obj->constant_pool(), | 437 RecordFixedArrayHelper(obj, obj->constant_pool(), |
| 395 BYTECODE_ARRAY_CONSTANT_POOL_SUB_TYPE, 0); | 438 BYTECODE_ARRAY_CONSTANT_POOL_SUB_TYPE, 0); |
| 396 RecordFixedArrayHelper(obj, obj->handler_table(), | 439 RecordFixedArrayHelper(obj, obj->handler_table(), |
| 397 BYTECODE_ARRAY_HANDLER_TABLE_SUB_TYPE, 0); | 440 BYTECODE_ARRAY_HANDLER_TABLE_SUB_TYPE, 0); |
| 398 } | 441 } |
| 399 | 442 |
| 400 void ObjectStatsCollector::RecordCodeDetails(Code* code) { | 443 void ObjectStatsCollector::RecordCodeDetails(Code* code) { |
| 401 stats_->RecordCodeSubTypeStats(code->kind(), code->GetAge(), code->Size()); | 444 stats_->RecordCodeSubTypeStats(code->kind(), code->GetAge(), code->Size()); |
| 402 RecordFixedArrayHelper(code, code->deoptimization_data(), | 445 RecordFixedArrayHelper(code, code->deoptimization_data(), |
| 403 DEOPTIMIZATION_DATA_SUB_TYPE, 0); | 446 DEOPTIMIZATION_DATA_SUB_TYPE, 0); |
| 447 if (code->kind() == Code::Kind::OPTIMIZED_FUNCTION) { |
| 448 DeoptimizationInputData* input_data = |
| 449 DeoptimizationInputData::cast(code->deoptimization_data()); |
| 450 RecordFixedArrayHelper(code->deoptimization_data(), |
| 451 input_data->LiteralArray(), |
| 452 OPTIMIZED_CODE_LITERALS_SUB_TYPE, 0); |
| 453 } |
| 404 RecordFixedArrayHelper(code, code->handler_table(), HANDLER_TABLE_SUB_TYPE, | 454 RecordFixedArrayHelper(code, code->handler_table(), HANDLER_TABLE_SUB_TYPE, |
| 405 0); | 455 0); |
| 406 int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 456 int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| 407 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { | 457 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { |
| 408 RelocInfo::Mode mode = it.rinfo()->rmode(); | 458 RelocInfo::Mode mode = it.rinfo()->rmode(); |
| 409 if (mode == RelocInfo::EMBEDDED_OBJECT) { | 459 if (mode == RelocInfo::EMBEDDED_OBJECT) { |
| 410 Object* target = it.rinfo()->target_object(); | 460 Object* target = it.rinfo()->target_object(); |
| 411 if (target->IsFixedArray()) { | 461 if (target->IsFixedArray()) { |
| 412 RecursivelyRecordFixedArrayHelper(code, FixedArray::cast(target), | 462 RecursivelyRecordFixedArrayHelper(code, FixedArray::cast(target), |
| 413 EMBEDDED_OBJECT_SUB_TYPE); | 463 EMBEDDED_OBJECT_SUB_TYPE); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 483 SLOW_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE); | 533 SLOW_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE); |
| 484 FixedArray* fast_cache = native_ctx->fast_template_instantiations_cache(); | 534 FixedArray* fast_cache = native_ctx->fast_template_instantiations_cache(); |
| 485 stats_->RecordFixedArraySubTypeStats( | 535 stats_->RecordFixedArraySubTypeStats( |
| 486 fast_cache, FAST_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE, | 536 fast_cache, FAST_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE, |
| 487 fast_cache->Size(), 0); | 537 fast_cache->Size(), 0); |
| 488 } | 538 } |
| 489 } | 539 } |
| 490 | 540 |
| 491 } // namespace internal | 541 } // namespace internal |
| 492 } // namespace v8 | 542 } // namespace v8 |
| OLD | NEW |