Commit 3d4ddb30 authored by mlippautz's avatar mlippautz Committed by Commit bot

[heap] ObjectStats: Cleanup and more FIXED_ARRAY sub types

Reduces the dark matter of reported fixed arrays to < 5%.

BUG=chromium:631094
R=ulan@chromium.org

Review-Url: https://codereview.chromium.org/2181623002
Cr-Commit-Position: refs/heads/master@{#38032}
parent 258c2c35
......@@ -2243,25 +2243,28 @@ void MarkCompactCollector::RegisterExternallyReferencedObject(Object** object) {
class MarkCompactCollector::ObjectStatsVisitor
: public MarkCompactCollector::HeapObjectVisitor {
public:
ObjectStatsVisitor(ObjectStats* live_stats, ObjectStats* dead_stats)
: live_stats_(live_stats), dead_stats_(dead_stats) {
DCHECK_NOT_NULL(live_stats_);
DCHECK_NOT_NULL(dead_stats_);
ObjectStatsVisitor(Heap* heap, ObjectStats* live_stats,
ObjectStats* dead_stats)
: live_collector_(heap, live_stats), dead_collector_(heap, dead_stats) {
DCHECK_NOT_NULL(live_stats);
DCHECK_NOT_NULL(dead_stats);
// Global objects are roots and thus recorded as live.
live_collector_.CollectGlobalStatistics();
}
bool Visit(HeapObject* obj) override {
if (Marking::IsBlack(ObjectMarking::MarkBitFrom(obj))) {
ObjectStatsCollector::CollectStatistics(live_stats_, obj);
live_collector_.CollectStatistics(obj);
} else {
DCHECK(!Marking::IsGrey(ObjectMarking::MarkBitFrom(obj)));
ObjectStatsCollector::CollectStatistics(dead_stats_, obj);
dead_collector_.CollectStatistics(obj);
}
return true;
}
private:
ObjectStats* live_stats_;
ObjectStats* dead_stats_;
ObjectStatsCollector live_collector_;
ObjectStatsCollector dead_collector_;
};
void MarkCompactCollector::VisitAllObjects(HeapObjectVisitor* visitor) {
......@@ -2277,7 +2280,7 @@ void MarkCompactCollector::VisitAllObjects(HeapObjectVisitor* visitor) {
void MarkCompactCollector::RecordObjectStats() {
if (FLAG_track_gc_object_stats) {
ObjectStatsVisitor visitor(heap()->live_object_stats_,
ObjectStatsVisitor visitor(heap(), heap()->live_object_stats_,
heap()->dead_object_stats_);
VisitAllObjects(&visitor);
if (FLAG_trace_gc_object_stats) {
......
......@@ -161,42 +161,69 @@ void ObjectStats::CheckpointObjectStats() {
Isolate* ObjectStats::isolate() { return heap()->isolate(); }
void ObjectStatsCollector::CollectStatistics(ObjectStats* stats,
HeapObject* obj) {
void ObjectStatsCollector::CollectStatistics(HeapObject* obj) {
Map* map = obj->map();
Heap* heap = obj->GetHeap();
// Record for the InstanceType.
int object_size = obj->Size();
stats->RecordObjectStats(map->instance_type(), object_size);
stats_->RecordObjectStats(map->instance_type(), object_size);
// Record specific sub types where possible.
if (obj->IsMap()) {
RecordMapDetails(stats, heap, obj);
}
if (obj->IsCode()) {
RecordCodeDetails(stats, heap, obj);
}
if (obj->IsMap()) RecordMapDetails(Map::cast(obj));
if (obj->IsCode()) RecordCodeDetails(Code::cast(obj));
if (obj->IsSharedFunctionInfo()) {
RecordSharedFunctionInfoDetails(stats, heap, obj);
}
if (obj->IsFixedArray()) {
RecordFixedArrayDetails(stats, heap, obj);
}
if (obj->IsJSObject()) {
RecordJSObjectDetails(stats, heap, JSObject::cast(obj));
RecordSharedFunctionInfoDetails(SharedFunctionInfo::cast(obj));
}
if (obj->IsFixedArray()) RecordFixedArrayDetails(FixedArray::cast(obj));
if (obj->IsJSObject()) RecordJSObjectDetails(JSObject::cast(obj));
if (obj->IsJSWeakCollection()) {
RecordJSWeakCollectionDetails(stats, heap, JSWeakCollection::cast(obj));
RecordJSWeakCollectionDetails(JSWeakCollection::cast(obj));
}
if (obj->IsScript()) {
RecordScriptDetails(stats, heap, Script::cast(obj));
if (obj->IsJSCollection()) {
RecordJSCollectionDetails(JSObject::cast(obj));
}
if (obj->IsJSFunction()) RecordJSFunctionDetails(JSFunction::cast(obj));
if (obj->IsScript()) RecordScriptDetails(Script::cast(obj));
}
void ObjectStatsCollector::CollectGlobalStatistics() {
// Global FixedArrays.
RecordFixedArrayHelper(nullptr, heap_->weak_new_space_object_to_code_list(),
WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE, 0);
RecordFixedArrayHelper(nullptr, heap_->serialized_templates(),
SERIALIZED_TEMPLATES_SUB_TYPE, 0);
RecordFixedArrayHelper(nullptr, heap_->number_string_cache(),
NUMBER_STRING_CACHE_SUB_TYPE, 0);
RecordFixedArrayHelper(nullptr, heap_->single_character_string_cache(),
SINGLE_CHARACTER_STRING_CACHE_SUB_TYPE, 0);
RecordFixedArrayHelper(nullptr, heap_->string_split_cache(),
STRING_SPLIT_CACHE_SUB_TYPE, 0);
RecordFixedArrayHelper(nullptr, heap_->regexp_multiple_cache(),
REGEXP_MULTIPLE_CACHE_SUB_TYPE, 0);
RecordFixedArrayHelper(nullptr, heap_->retained_maps(),
RETAINED_MAPS_SUB_TYPE, 0);
// Global weak FixedArrays.
RecordFixedArrayHelper(
nullptr, WeakFixedArray::cast(heap_->noscript_shared_function_infos()),
NOSCRIPT_SHARED_FUNCTION_INFOS_SUB_TYPE, 0);
RecordFixedArrayHelper(nullptr, WeakFixedArray::cast(heap_->script_list()),
SCRIPT_LIST_SUB_TYPE, 0);
// Global hash tables.
RecordHashTableHelper(nullptr, heap_->string_table(), STRING_TABLE_SUB_TYPE);
RecordHashTableHelper(nullptr, heap_->weak_object_to_code_table(),
OBJECT_TO_CODE_SUB_TYPE);
RecordHashTableHelper(nullptr, heap_->code_stubs(),
CODE_STUBS_TABLE_SUB_TYPE);
RecordHashTableHelper(nullptr, heap_->intrinsic_function_names(),
INTRINSIC_FUNCTION_NAMES_SUB_TYPE);
RecordHashTableHelper(nullptr, heap_->empty_properties_dictionary(),
EMPTY_PROPERTIES_DICTIONARY_SUB_TYPE);
}
static bool CanRecordFixedArray(Heap* heap, FixedArrayBase* array) {
return array->map()->instance_type() == FIXED_ARRAY_TYPE &&
array->map() != heap->fixed_cow_array_map() &&
array->map() != heap->fixed_double_array_map() &&
array != heap->empty_fixed_array() &&
array != heap->empty_byte_array() &&
......@@ -207,33 +234,57 @@ static bool CanRecordFixedArray(Heap* heap, FixedArrayBase* array) {
array != heap->empty_properties_dictionary();
}
static bool IsCowArray(Heap* heap, FixedArrayBase* array) {
return array->map() == heap->fixed_cow_array_map();
}
static bool SameLiveness(HeapObject* obj1, HeapObject* obj2) {
return ObjectMarking::Color(obj1) == ObjectMarking::Color(obj2);
return obj1 == nullptr || obj2 == nullptr ||
ObjectMarking::Color(obj1) == ObjectMarking::Color(obj2);
}
void ObjectStatsCollector::RecordFixedArrayHelper(
ObjectStats* stats, Heap* heap, HeapObject* parent, FixedArray* array,
int subtype, size_t overhead) {
if (SameLiveness(parent, array) && CanRecordFixedArray(heap, array)) {
stats->RecordFixedArraySubTypeStats(array, subtype, array->Size(),
overhead);
bool ObjectStatsCollector::RecordFixedArrayHelper(HeapObject* parent,
FixedArray* array,
int subtype,
size_t overhead) {
if (SameLiveness(parent, array) && CanRecordFixedArray(heap_, array) &&
!IsCowArray(heap_, array)) {
return stats_->RecordFixedArraySubTypeStats(array, subtype, array->Size(),
overhead);
}
return false;
}
void ObjectStatsCollector::RecordJSObjectDetails(ObjectStats* stats, Heap* heap,
JSObject* object) {
DCHECK(object->IsJSObject());
void ObjectStatsCollector::RecursivelyRecordFixedArrayHelper(HeapObject* parent,
FixedArray* array,
int subtype) {
if (RecordFixedArrayHelper(parent, array, subtype, 0)) {
for (int i = 0; i < array->length(); i++) {
if (array->get(i)->IsFixedArray()) {
RecursivelyRecordFixedArrayHelper(
parent, FixedArray::cast(array->get(i)), subtype);
}
}
}
}
template <class HashTable>
void ObjectStatsCollector::RecordHashTableHelper(HeapObject* parent,
HashTable* array,
int subtype) {
int used = array->NumberOfElements() * HashTable::kEntrySize;
CHECK_GE(array->Size(), used);
size_t overhead = array->Size() - used;
RecordFixedArrayHelper(parent, array, subtype, overhead);
}
void ObjectStatsCollector::RecordJSObjectDetails(JSObject* object) {
size_t overhead = 0;
FixedArrayBase* elements = object->elements();
if (CanRecordFixedArray(heap, elements)) {
if (CanRecordFixedArray(heap_, elements) && !IsCowArray(heap_, elements)) {
if (elements->IsDictionary() && SameLiveness(object, elements)) {
SeededNumberDictionary* dict = SeededNumberDictionary::cast(elements);
int used = dict->NumberOfElements() * SeededNumberDictionary::kEntrySize;
CHECK_GE(elements->Size(), used);
overhead = elements->Size() - used;
stats->RecordFixedArraySubTypeStats(
elements, DICTIONARY_ELEMENTS_SUB_TYPE, elements->Size(), overhead);
RecordHashTableHelper(object, dict, DICTIONARY_ELEMENTS_SUB_TYPE);
} else {
if (IsFastHoleyElementsKind(object->GetElementsKind())) {
int used = object->GetFastElementsUsage() * kPointerSize;
......@@ -241,108 +292,131 @@ void ObjectStatsCollector::RecordJSObjectDetails(ObjectStats* stats, Heap* heap,
CHECK_GE(elements->Size(), used);
overhead = elements->Size() - used;
}
stats->RecordFixedArraySubTypeStats(elements, FAST_ELEMENTS_SUB_TYPE,
elements->Size(), overhead);
stats_->RecordFixedArraySubTypeStats(elements, FAST_ELEMENTS_SUB_TYPE,
elements->Size(), overhead);
}
}
overhead = 0;
FixedArrayBase* properties = object->properties();
if (CanRecordFixedArray(heap, properties) &&
SameLiveness(object, properties)) {
if (CanRecordFixedArray(heap_, properties) &&
SameLiveness(object, properties) && !IsCowArray(heap_, properties)) {
if (properties->IsDictionary()) {
NameDictionary* dict = NameDictionary::cast(properties);
int used = dict->NumberOfElements() * NameDictionary::kEntrySize;
CHECK_GE(properties->Size(), used);
overhead = properties->Size() - used;
stats->RecordFixedArraySubTypeStats(properties,
DICTIONARY_PROPERTIES_SUB_TYPE,
properties->Size(), overhead);
RecordHashTableHelper(object, dict, DICTIONARY_PROPERTIES_SUB_TYPE);
} else {
stats->RecordFixedArraySubTypeStats(properties, FAST_PROPERTIES_SUB_TYPE,
properties->Size(), overhead);
stats_->RecordFixedArraySubTypeStats(properties, FAST_PROPERTIES_SUB_TYPE,
properties->Size(), overhead);
}
}
}
void ObjectStatsCollector::RecordJSWeakCollectionDetails(
ObjectStats* stats, Heap* heap, JSWeakCollection* obj) {
JSWeakCollection* obj) {
if (obj->table()->IsHashTable()) {
ObjectHashTable* table = ObjectHashTable::cast(obj->table());
int used = table->NumberOfElements() * ObjectHashTable::kEntrySize;
size_t overhead = table->Size() - used;
RecordFixedArrayHelper(stats, heap, obj, table, WEAK_COLLECTION_SUB_TYPE,
overhead);
RecordFixedArrayHelper(obj, table, JS_WEAK_COLLECTION_SUB_TYPE, overhead);
}
}
void ObjectStatsCollector::RecordScriptDetails(ObjectStats* stats, Heap* heap,
Script* obj) {
void ObjectStatsCollector::RecordJSCollectionDetails(JSObject* obj) {
if (obj->IsJSMap()) {
RecordHashTableHelper(nullptr,
OrderedHashMap::cast(JSMap::cast(obj)->table()),
JS_COLLECTION_SUB_TYPE);
}
if (obj->IsJSSet()) {
RecordHashTableHelper(nullptr,
OrderedHashSet::cast(JSSet::cast(obj)->table()),
JS_COLLECTION_SUB_TYPE);
}
}
void ObjectStatsCollector::RecordScriptDetails(Script* obj) {
Object* infos = WeakFixedArray::cast(obj->shared_function_infos());
if (infos->IsWeakFixedArray())
RecordFixedArrayHelper(stats, heap, obj, WeakFixedArray::cast(infos),
RecordFixedArrayHelper(obj, WeakFixedArray::cast(infos),
SHARED_FUNCTION_INFOS_SUB_TYPE, 0);
}
void ObjectStatsCollector::RecordMapDetails(ObjectStats* stats, Heap* heap,
HeapObject* obj) {
Map* map_obj = Map::cast(obj);
DCHECK(obj->map()->instance_type() == MAP_TYPE);
void ObjectStatsCollector::RecordMapDetails(Map* map_obj) {
DescriptorArray* array = map_obj->instance_descriptors();
if (map_obj->owns_descriptors() && array != heap->empty_descriptor_array() &&
if (map_obj->owns_descriptors() && array != heap_->empty_descriptor_array() &&
SameLiveness(map_obj, array)) {
RecordFixedArrayHelper(stats, heap, map_obj, array,
DESCRIPTOR_ARRAY_SUB_TYPE, 0);
RecordFixedArrayHelper(map_obj, array, DESCRIPTOR_ARRAY_SUB_TYPE, 0);
if (array->HasEnumCache()) {
RecordFixedArrayHelper(stats, heap, array, array->GetEnumCache(),
ENUM_CACHE_SUB_TYPE, 0);
RecordFixedArrayHelper(array, array->GetEnumCache(), ENUM_CACHE_SUB_TYPE,
0);
}
if (array->HasEnumIndicesCache()) {
RecordFixedArrayHelper(stats, heap, array, array->GetEnumIndicesCache(),
RecordFixedArrayHelper(array, array->GetEnumIndicesCache(),
ENUM_INDICES_CACHE_SUB_TYPE, 0);
}
}
if (map_obj->has_code_cache()) {
RecordFixedArrayHelper(stats, heap, map_obj, map_obj->code_cache(),
RecordFixedArrayHelper(map_obj, map_obj->code_cache(),
MAP_CODE_CACHE_SUB_TYPE, 0);
}
for (DependentCode* cur_dependent_code = map_obj->dependent_code();
cur_dependent_code != heap_->empty_fixed_array();
cur_dependent_code = DependentCode::cast(
cur_dependent_code->get(DependentCode::kNextLinkIndex))) {
RecordFixedArrayHelper(map_obj, cur_dependent_code, DEPENDENT_CODE_SUB_TYPE,
0);
}
if (map_obj->is_prototype_map()) {
if (map_obj->prototype_info()->IsPrototypeInfo()) {
PrototypeInfo* info = PrototypeInfo::cast(map_obj->prototype_info());
Object* users = info->prototype_users();
if (users->IsWeakFixedArray()) {
RecordFixedArrayHelper(map_obj, WeakFixedArray::cast(users),
PROTOTYPE_USERS_SUB_TYPE, 0);
}
}
}
}
void ObjectStatsCollector::RecordCodeDetails(ObjectStats* stats, Heap* heap,
HeapObject* obj) {
int object_size = obj->Size();
DCHECK(obj->map()->instance_type() == CODE_TYPE);
Code* code_obj = Code::cast(obj);
stats->RecordCodeSubTypeStats(code_obj->kind(), code_obj->GetAge(),
object_size);
Code* code = Code::cast(obj);
RecordFixedArrayHelper(stats, heap, code, code->deoptimization_data(),
void ObjectStatsCollector::RecordCodeDetails(Code* code) {
stats_->RecordCodeSubTypeStats(code->kind(), code->GetAge(), code->Size());
RecordFixedArrayHelper(code, code->deoptimization_data(),
DEOPTIMIZATION_DATA_SUB_TYPE, 0);
for (RelocIterator it(code); !it.done(); it.next()) {
RecordFixedArrayHelper(code, code->handler_table(), HANDLER_TABLE_SUB_TYPE,
0);
int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
RelocInfo::Mode mode = it.rinfo()->rmode();
if (mode == RelocInfo::EMBEDDED_OBJECT) {
Object* target = it.rinfo()->target_object();
if (target->IsFixedArray()) {
RecordFixedArrayHelper(stats, heap, code, FixedArray::cast(target),
EMBEDDED_OBJECT_SUB_TYPE, 0);
RecursivelyRecordFixedArrayHelper(code, FixedArray::cast(target),
EMBEDDED_OBJECT_SUB_TYPE);
}
}
}
}
void ObjectStatsCollector::RecordSharedFunctionInfoDetails(ObjectStats* stats,
Heap* heap,
HeapObject* obj) {
SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj);
void ObjectStatsCollector::RecordSharedFunctionInfoDetails(
SharedFunctionInfo* sfi) {
FixedArray* scope_info = sfi->scope_info();
RecordFixedArrayHelper(stats, heap, sfi, scope_info, SCOPE_INFO_SUB_TYPE, 0);
FixedArray* feedback_metadata = sfi->feedback_metadata();
RecordFixedArrayHelper(stats, heap, sfi, feedback_metadata,
TYPE_FEEDBACK_METADATA_SUB_TYPE, 0);
RecordFixedArrayHelper(sfi, scope_info, SCOPE_INFO_SUB_TYPE, 0);
TypeFeedbackMetadata* feedback_metadata = sfi->feedback_metadata();
if (!feedback_metadata->is_empty()) {
RecordFixedArrayHelper(sfi, feedback_metadata,
TYPE_FEEDBACK_METADATA_SUB_TYPE, 0);
UnseededNumberDictionary* names = UnseededNumberDictionary::cast(
feedback_metadata->get(TypeFeedbackMetadata::kNamesTableIndex));
RecordHashTableHelper(sfi, names, TYPE_FEEDBACK_METADATA_SUB_TYPE);
}
if (!sfi->OptimizedCodeMapIsCleared()) {
FixedArray* optimized_code_map = sfi->optimized_code_map();
RecordFixedArrayHelper(sfi, optimized_code_map, OPTIMIZED_CODE_MAP_SUB_TYPE,
0);
// Optimized code map should be small, so skip accounting.
int len = optimized_code_map->length();
for (int i = SharedFunctionInfo::kEntriesStart; i < len;
......@@ -359,73 +433,33 @@ void ObjectStatsCollector::RecordSharedFunctionInfoDetails(ObjectStats* stats,
literals = LiteralsArray::cast(slot);
}
if (literals != nullptr) {
RecordFixedArrayHelper(stats, heap, sfi, literals,
LITERALS_ARRAY_SUB_TYPE, 0);
RecordFixedArrayHelper(stats, heap, sfi, literals->feedback_vector(),
RecordFixedArrayHelper(sfi, literals, LITERALS_ARRAY_SUB_TYPE, 0);
RecordFixedArrayHelper(sfi, literals->feedback_vector(),
TYPE_FEEDBACK_VECTOR_SUB_TYPE, 0);
}
}
}
}
void ObjectStatsCollector::RecordFixedArrayDetails(ObjectStats* stats,
Heap* heap,
HeapObject* obj) {
FixedArray* array = FixedArray::cast(obj);
// Special fixed arrays.
int subtype = -1;
if (array == heap->weak_new_space_object_to_code_list())
subtype = WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE;
if (array == heap->serialized_templates())
subtype = SERIALIZED_TEMPLATES_SUB_TYPE;
if (array == heap->string_table()) subtype = STRING_TABLE_SUB_TYPE;
if (array == heap->number_string_cache())
subtype = NUMBER_STRING_CACHE_SUB_TYPE;
if (array == heap->single_character_string_cache())
subtype = SINGLE_CHARACTER_STRING_CACHE_SUB_TYPE;
if (array == heap->string_split_cache())
subtype = STRING_SPLIT_CACHE_SUB_TYPE;
if (array == heap->regexp_multiple_cache())
subtype = REGEXP_MULTIPLE_CACHE_SUB_TYPE;
if (array->IsContext()) subtype = CONTEXT_SUB_TYPE;
if (array->map() == heap->fixed_cow_array_map())
subtype = COPY_ON_WRITE_SUB_TYPE;
if (subtype != -1) {
stats->RecordFixedArraySubTypeStats(array, subtype, array->Size(), 0);
}
void ObjectStatsCollector::RecordJSFunctionDetails(JSFunction* function) {
LiteralsArray* literals = function->literals();
RecordFixedArrayHelper(function, literals, LITERALS_ARRAY_SUB_TYPE, 0);
RecordFixedArrayHelper(function, literals->feedback_vector(),
TYPE_FEEDBACK_VECTOR_SUB_TYPE, 0);
}
// Special hash maps.
if (array == heap->weak_object_to_code_table()) {
WeakHashTable* table = reinterpret_cast<WeakHashTable*>(array);
int used = table->NumberOfElements() * WeakHashTable::kEntrySize;
CHECK_GE(array->Size(), used);
size_t overhead = array->Size() - used;
stats->RecordFixedArraySubTypeStats(table, OBJECT_TO_CODE_SUB_TYPE,
table->Size(), overhead);
void ObjectStatsCollector::RecordFixedArrayDetails(FixedArray* array) {
if (array->IsContext()) {
RecordFixedArrayHelper(nullptr, array, CONTEXT_SUB_TYPE, 0);
}
if (IsCowArray(heap_, array) && CanRecordFixedArray(heap_, array)) {
stats_->RecordFixedArraySubTypeStats(array, COPY_ON_WRITE_SUB_TYPE,
array->Size(), 0);
}
if (array->IsNativeContext()) {
Context* native_ctx = Context::cast(array);
UnseededNumberDictionary* dict =
native_ctx->template_instantiations_cache();
int used = dict->NumberOfElements() * UnseededNumberDictionary::kEntrySize;
size_t overhead = dict->Size() - used;
RecordFixedArrayHelper(stats, heap, array, dict,
TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE, overhead);
}
if (array == heap->code_stubs()) {
UnseededNumberDictionary* dict = UnseededNumberDictionary::cast(array);
int used = dict->NumberOfElements() * UnseededNumberDictionary::kEntrySize;
size_t overhead = dict->Size() - used;
stats->RecordFixedArraySubTypeStats(dict, CODE_STUBS_TABLE_SUB_TYPE,
dict->Size(), overhead);
}
if (array == heap->intrinsic_function_names()) {
NameDictionary* dict = NameDictionary::cast(array);
int used = dict->NumberOfElements() * NameDictionary::kEntrySize;
size_t overhead = dict->Size() - used;
stats->RecordFixedArraySubTypeStats(dict, INTRINSIC_FUNCTION_NAMES_SUB_TYPE,
dict->Size(), overhead);
RecordHashTableHelper(array, native_ctx->template_instantiations_cache(),
TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE);
}
}
......
......@@ -60,19 +60,22 @@ class ObjectStats {
size_histogram_[code_age_index][idx]++;
}
void RecordFixedArraySubTypeStats(FixedArrayBase* array, int array_sub_type,
bool RecordFixedArraySubTypeStats(FixedArrayBase* array, int array_sub_type,
size_t size, size_t over_allocated) {
auto it = visited_fixed_array_sub_types_.insert(array);
if (!it.second) return;
if (!it.second) return false;
DCHECK(array_sub_type <= LAST_FIXED_ARRAY_SUB_TYPE);
object_counts_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type]++;
object_sizes_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type] += size;
size_histogram_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type]
[HistogramIndexFromSize(size)]++;
over_allocated_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type] +=
over_allocated;
over_allocated_histogram_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type]
[HistogramIndexFromSize(over_allocated)]++;
if (over_allocated > 0) {
over_allocated_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type] +=
over_allocated;
over_allocated_histogram_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type]
[HistogramIndexFromSize(over_allocated)]++;
}
return true;
}
size_t object_count_last_gc(size_t index) {
......@@ -117,26 +120,31 @@ class ObjectStats {
class ObjectStatsCollector {
public:
static void CollectStatistics(ObjectStats* stats, HeapObject* obj);
ObjectStatsCollector(Heap* heap, ObjectStats* stats)
: heap_(heap), stats_(stats) {}
void CollectGlobalStatistics();
void CollectStatistics(HeapObject* obj);
private:
static void RecordMapDetails(ObjectStats* stats, Heap* heap, HeapObject* obj);
static void RecordCodeDetails(ObjectStats* stats, Heap* heap,
HeapObject* obj);
static void RecordSharedFunctionInfoDetails(ObjectStats* stats, Heap* heap,
HeapObject* obj);
static void RecordFixedArrayDetails(ObjectStats* stats, Heap* heap,
HeapObject* obj);
static void RecordJSObjectDetails(ObjectStats* stats, Heap* heap,
JSObject* object);
static void RecordJSWeakCollectionDetails(ObjectStats* stats, Heap* heap,
JSWeakCollection* obj);
static void RecordScriptDetails(ObjectStats* stats, Heap* heap, Script* obj);
static void RecordFixedArrayHelper(ObjectStats* stats, Heap* heap,
HeapObject* parent, FixedArray* array,
int subtype, size_t overhead);
void RecordCodeDetails(Code* code);
void RecordFixedArrayDetails(FixedArray* array);
void RecordJSCollectionDetails(JSObject* obj);
void RecordJSFunctionDetails(JSFunction* function);
void RecordJSObjectDetails(JSObject* object);
void RecordJSWeakCollectionDetails(JSWeakCollection* obj);
void RecordMapDetails(Map* map);
void RecordScriptDetails(Script* obj);
void RecordSharedFunctionInfoDetails(SharedFunctionInfo* sfi);
bool RecordFixedArrayHelper(HeapObject* parent, FixedArray* array,
int subtype, size_t overhead);
void RecursivelyRecordFixedArrayHelper(HeapObject* parent, FixedArray* array,
int subtype);
template <class HashTable>
void RecordHashTableHelper(HeapObject* parent, HashTable* array, int subtype);
Heap* heap_;
ObjectStats* stats_;
};
} // namespace internal
......
......@@ -705,6 +705,8 @@ bool HeapObject::IsJSWeakCollection() const {
return IsJSWeakMap() || IsJSWeakSet();
}
bool HeapObject::IsJSCollection() const { return IsJSMap() || IsJSSet(); }
bool HeapObject::IsDescriptorArray() const { return IsFixedArray(); }
bool HeapObject::IsArrayList() const { return IsFixedArray(); }
......
......@@ -776,17 +776,27 @@ std::ostream& operator<<(std::ostream& os, InstanceType instance_type);
V(EMBEDDED_OBJECT_SUB_TYPE) \
V(ENUM_CACHE_SUB_TYPE) \
V(ENUM_INDICES_CACHE_SUB_TYPE) \
V(DEPENDENT_CODE_SUB_TYPE) \
V(DICTIONARY_ELEMENTS_SUB_TYPE) \
V(DICTIONARY_PROPERTIES_SUB_TYPE) \
V(EMPTY_PROPERTIES_DICTIONARY_SUB_TYPE) \
V(FAST_ELEMENTS_SUB_TYPE) \
V(FAST_PROPERTIES_SUB_TYPE) \
V(HANDLER_TABLE_SUB_TYPE) \
V(INTRINSIC_FUNCTION_NAMES_SUB_TYPE) \
V(JS_COLLECTION_SUB_TYPE) \
V(JS_WEAK_COLLECTION_SUB_TYPE) \
V(LITERALS_ARRAY_SUB_TYPE) \
V(MAP_CODE_CACHE_SUB_TYPE) \
V(NOSCRIPT_SHARED_FUNCTION_INFOS_SUB_TYPE) \
V(NUMBER_STRING_CACHE_SUB_TYPE) \
V(OBJECT_TO_CODE_SUB_TYPE) \
V(OPTIMIZED_CODE_MAP_SUB_TYPE) \
V(PROTOTYPE_USERS_SUB_TYPE) \
V(REGEXP_MULTIPLE_CACHE_SUB_TYPE) \
V(RETAINED_MAPS_SUB_TYPE) \
V(SCOPE_INFO_SUB_TYPE) \
V(SCRIPT_LIST_SUB_TYPE) \
V(SERIALIZED_TEMPLATES_SUB_TYPE) \
V(SHARED_FUNCTION_INFOS_SUB_TYPE) \
V(SINGLE_CHARACTER_STRING_CACHE_SUB_TYPE) \
......@@ -795,7 +805,6 @@ std::ostream& operator<<(std::ostream& os, InstanceType instance_type);
V(TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \
V(TYPE_FEEDBACK_VECTOR_SUB_TYPE) \
V(TYPE_FEEDBACK_METADATA_SUB_TYPE) \
V(WEAK_COLLECTION_SUB_TYPE) \
V(WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE)
enum FixedArraySubInstanceType {
......@@ -975,6 +984,7 @@ template <class C> inline bool Is(Object* obj);
V(JSArray) \
V(JSArrayBuffer) \
V(JSArrayBufferView) \
V(JSCollection) \
V(JSTypedArray) \
V(JSDataView) \
V(JSProxy) \
......@@ -5598,6 +5608,9 @@ class DependentCode: public FixedArray {
};
static const int kGroupCount = kAllocationSiteTransitionChangedGroup + 1;
static const int kNextLinkIndex = 0;
static const int kFlagsIndex = 1;
static const int kCodesStartIndex = 2;
bool Contains(DependencyGroup group, WeakCell* code_cell);
bool IsEmpty(DependencyGroup group);
......@@ -5658,9 +5671,6 @@ class DependentCode: public FixedArray {
class GroupField : public BitField<int, 0, 3> {};
class CountField : public BitField<int, 3, 27> {};
STATIC_ASSERT(kGroupCount <= GroupField::kMax + 1);
static const int kNextLinkIndex = 0;
static const int kFlagsIndex = 1;
static const int kCodesStartIndex = 2;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment