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 |