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/counters.h" | 7 #include "src/counters.h" |
8 #include "src/heap/heap-inl.h" | 8 #include "src/heap/heap-inl.h" |
9 #include "src/isolate.h" | 9 #include "src/isolate.h" |
10 #include "src/utils.h" | 10 #include "src/utils.h" |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 127 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
128 | 128 |
129 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 129 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
130 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 130 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
131 ClearObjectStats(); | 131 ClearObjectStats(); |
132 } | 132 } |
133 | 133 |
134 | 134 |
135 Isolate* ObjectStats::isolate() { return heap()->isolate(); } | 135 Isolate* ObjectStats::isolate() { return heap()->isolate(); } |
136 | 136 |
137 | 137 void ObjectStatsCollector::CountFixedArray( |
138 void ObjectStatsVisitor::CountFixedArray( | |
139 FixedArrayBase* fixed_array, FixedArraySubInstanceType fast_type, | 138 FixedArrayBase* fixed_array, FixedArraySubInstanceType fast_type, |
140 FixedArraySubInstanceType dictionary_type) { | 139 FixedArraySubInstanceType dictionary_type) { |
141 Heap* heap = fixed_array->map()->GetHeap(); | 140 Heap* heap = fixed_array->map()->GetHeap(); |
142 if (fixed_array->map() != heap->fixed_cow_array_map() && | 141 if (fixed_array->map() != heap->fixed_cow_array_map() && |
143 fixed_array->map() != heap->fixed_double_array_map() && | 142 fixed_array->map() != heap->fixed_double_array_map() && |
144 fixed_array != heap->empty_fixed_array()) { | 143 fixed_array != heap->empty_fixed_array()) { |
145 if (fixed_array->IsDictionary()) { | 144 if (fixed_array->IsDictionary()) { |
146 heap->object_stats_->RecordFixedArraySubTypeStats(dictionary_type, | 145 heap->object_stats_->RecordFixedArraySubTypeStats(dictionary_type, |
147 fixed_array->Size()); | 146 fixed_array->Size()); |
148 } else { | 147 } else { |
149 heap->object_stats_->RecordFixedArraySubTypeStats(fast_type, | 148 heap->object_stats_->RecordFixedArraySubTypeStats(fast_type, |
150 fixed_array->Size()); | 149 fixed_array->Size()); |
151 } | 150 } |
152 } | 151 } |
153 } | 152 } |
154 | 153 |
| 154 void ObjectStatsCollector::CollectStatistics(StaticVisitorBase::VisitorId id, |
| 155 Map* map, HeapObject* obj) { |
| 156 // Record any type specific statistics here. |
| 157 switch (id) { |
| 158 case StaticVisitorBase::kVisitMap: |
| 159 RecordMapStats(map, obj); |
| 160 break; |
| 161 case StaticVisitorBase::kVisitCode: |
| 162 RecordCodeStats(map, obj); |
| 163 break; |
| 164 case StaticVisitorBase::kVisitSharedFunctionInfo: |
| 165 RecordSharedFunctionInfoStats(map, obj); |
| 166 break; |
| 167 case StaticVisitorBase::kVisitFixedArray: |
| 168 RecordFixedArrayStats(map, obj); |
| 169 break; |
| 170 default: |
| 171 break; |
| 172 } |
155 | 173 |
156 void ObjectStatsVisitor::VisitBase(VisitorId id, Map* map, HeapObject* obj) { | |
157 Heap* heap = map->GetHeap(); | 174 Heap* heap = map->GetHeap(); |
158 int object_size = obj->Size(); | 175 int object_size = obj->Size(); |
159 heap->object_stats_->RecordObjectStats(map->instance_type(), object_size); | 176 heap->object_stats_->RecordObjectStats(map->instance_type(), object_size); |
160 table_.GetVisitorById(id)(map, obj); | 177 } |
| 178 |
| 179 void ObjectStatsCollector::CollectFixedArrayStatistics(HeapObject* obj) { |
161 if (obj->IsJSObject()) { | 180 if (obj->IsJSObject()) { |
162 JSObject* object = JSObject::cast(obj); | 181 JSObject* object = JSObject::cast(obj); |
163 CountFixedArray(object->elements(), DICTIONARY_ELEMENTS_SUB_TYPE, | 182 CountFixedArray(object->elements(), DICTIONARY_ELEMENTS_SUB_TYPE, |
164 FAST_ELEMENTS_SUB_TYPE); | 183 FAST_ELEMENTS_SUB_TYPE); |
165 CountFixedArray(object->properties(), DICTIONARY_PROPERTIES_SUB_TYPE, | 184 CountFixedArray(object->properties(), DICTIONARY_PROPERTIES_SUB_TYPE, |
166 FAST_PROPERTIES_SUB_TYPE); | 185 FAST_PROPERTIES_SUB_TYPE); |
167 } | 186 } |
168 } | 187 } |
169 | 188 |
170 | 189 void ObjectStatsCollector::RecordMapStats(Map* map, HeapObject* obj) { |
171 template <ObjectStatsVisitor::VisitorId id> | |
172 void ObjectStatsVisitor::Visit(Map* map, HeapObject* obj) { | |
173 VisitBase(id, map, obj); | |
174 } | |
175 | |
176 | |
177 template <> | |
178 void ObjectStatsVisitor::Visit<ObjectStatsVisitor::kVisitMap>(Map* map, | |
179 HeapObject* obj) { | |
180 Heap* heap = map->GetHeap(); | 190 Heap* heap = map->GetHeap(); |
181 Map* map_obj = Map::cast(obj); | 191 Map* map_obj = Map::cast(obj); |
182 DCHECK(map->instance_type() == MAP_TYPE); | 192 DCHECK(map->instance_type() == MAP_TYPE); |
183 DescriptorArray* array = map_obj->instance_descriptors(); | 193 DescriptorArray* array = map_obj->instance_descriptors(); |
184 if (map_obj->owns_descriptors() && array != heap->empty_descriptor_array()) { | 194 if (map_obj->owns_descriptors() && array != heap->empty_descriptor_array()) { |
185 int fixed_array_size = array->Size(); | 195 int fixed_array_size = array->Size(); |
186 heap->object_stats_->RecordFixedArraySubTypeStats(DESCRIPTOR_ARRAY_SUB_TYPE, | 196 heap->object_stats_->RecordFixedArraySubTypeStats(DESCRIPTOR_ARRAY_SUB_TYPE, |
187 fixed_array_size); | 197 fixed_array_size); |
188 } | 198 } |
189 if (map_obj->has_code_cache()) { | 199 if (map_obj->has_code_cache()) { |
190 FixedArray* cache = FixedArray::cast(map_obj->code_cache()); | 200 FixedArray* cache = FixedArray::cast(map_obj->code_cache()); |
191 heap->object_stats_->RecordFixedArraySubTypeStats(MAP_CODE_CACHE_SUB_TYPE, | 201 heap->object_stats_->RecordFixedArraySubTypeStats(MAP_CODE_CACHE_SUB_TYPE, |
192 cache->Size()); | 202 cache->Size()); |
193 } | 203 } |
194 VisitBase(kVisitMap, map, obj); | |
195 } | 204 } |
196 | 205 |
197 | 206 void ObjectStatsCollector::RecordCodeStats(Map* map, HeapObject* obj) { |
198 template <> | |
199 void ObjectStatsVisitor::Visit<ObjectStatsVisitor::kVisitCode>( | |
200 Map* map, HeapObject* obj) { | |
201 Heap* heap = map->GetHeap(); | 207 Heap* heap = map->GetHeap(); |
202 int object_size = obj->Size(); | 208 int object_size = obj->Size(); |
203 DCHECK(map->instance_type() == CODE_TYPE); | 209 DCHECK(map->instance_type() == CODE_TYPE); |
204 Code* code_obj = Code::cast(obj); | 210 Code* code_obj = Code::cast(obj); |
205 heap->object_stats_->RecordCodeSubTypeStats(code_obj->kind(), | 211 heap->object_stats_->RecordCodeSubTypeStats(code_obj->kind(), |
206 code_obj->GetAge(), object_size); | 212 code_obj->GetAge(), object_size); |
207 VisitBase(kVisitCode, map, obj); | |
208 } | 213 } |
209 | 214 |
210 | 215 void ObjectStatsCollector::RecordSharedFunctionInfoStats(Map* map, |
211 template <> | 216 HeapObject* obj) { |
212 void ObjectStatsVisitor::Visit<ObjectStatsVisitor::kVisitSharedFunctionInfo>( | |
213 Map* map, HeapObject* obj) { | |
214 Heap* heap = map->GetHeap(); | 217 Heap* heap = map->GetHeap(); |
215 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj); | 218 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj); |
216 if (sfi->scope_info() != heap->empty_fixed_array()) { | 219 if (sfi->scope_info() != heap->empty_fixed_array()) { |
217 heap->object_stats_->RecordFixedArraySubTypeStats( | 220 heap->object_stats_->RecordFixedArraySubTypeStats( |
218 SCOPE_INFO_SUB_TYPE, FixedArray::cast(sfi->scope_info())->Size()); | 221 SCOPE_INFO_SUB_TYPE, FixedArray::cast(sfi->scope_info())->Size()); |
219 } | 222 } |
220 VisitBase(kVisitSharedFunctionInfo, map, obj); | |
221 } | 223 } |
222 | 224 |
223 | 225 void ObjectStatsCollector::RecordFixedArrayStats(Map* map, HeapObject* obj) { |
224 template <> | |
225 void ObjectStatsVisitor::Visit<ObjectStatsVisitor::kVisitFixedArray>( | |
226 Map* map, HeapObject* obj) { | |
227 Heap* heap = map->GetHeap(); | 226 Heap* heap = map->GetHeap(); |
228 FixedArray* fixed_array = FixedArray::cast(obj); | 227 FixedArray* fixed_array = FixedArray::cast(obj); |
229 if (fixed_array == heap->string_table()) { | 228 if (fixed_array == heap->string_table()) { |
230 heap->object_stats_->RecordFixedArraySubTypeStats(STRING_TABLE_SUB_TYPE, | 229 heap->object_stats_->RecordFixedArraySubTypeStats(STRING_TABLE_SUB_TYPE, |
231 fixed_array->Size()); | 230 fixed_array->Size()); |
232 } | 231 } |
233 VisitBase(kVisitFixedArray, map, obj); | |
234 } | 232 } |
235 | 233 |
236 | 234 void MarkCompactObjectStatsVisitor::Initialize( |
237 void ObjectStatsVisitor::Initialize(VisitorDispatchTable<Callback>* original) { | 235 VisitorDispatchTable<Callback>* original) { |
238 // Copy the original visitor table to make call-through possible. After we | 236 // Copy the original visitor table to make call-through possible. After we |
239 // preserved a copy locally, we patch the original table to call us. | 237 // preserved a copy locally, we patch the original table to call us. |
240 table_.CopyFrom(original); | 238 table_.CopyFrom(original); |
| 239 #define COUNT_FUNCTION(id) original->Register(kVisit##id, Visit<kVisit##id>); |
| 240 VISITOR_ID_LIST(COUNT_FUNCTION) |
| 241 #undef COUNT_FUNCTION |
| 242 } |
| 243 |
| 244 template <MarkCompactObjectStatsVisitor::VisitorId id> |
| 245 void MarkCompactObjectStatsVisitor::Visit(Map* map, HeapObject* obj) { |
| 246 ObjectStatsCollector::CollectStatistics(id, map, obj); |
| 247 table_.GetVisitorById(id)(map, obj); |
| 248 ObjectStatsCollector::CollectFixedArrayStatistics(obj); |
| 249 } |
| 250 |
| 251 void IncrementalMarkingObjectStatsVisitor::Initialize( |
| 252 VisitorDispatchTable<Callback>* original) { |
| 253 // Copy the original visitor table to make call-through possible. After we |
| 254 // preserved a copy locally, we patch the original table to call us. |
| 255 table_.CopyFrom(original); |
241 #define COUNT_FUNCTION(id) original->Register(kVisit##id, Visit<kVisit##id>); | 256 #define COUNT_FUNCTION(id) original->Register(kVisit##id, Visit<kVisit##id>); |
242 VISITOR_ID_LIST(COUNT_FUNCTION) | 257 VISITOR_ID_LIST(COUNT_FUNCTION) |
243 #undef COUNT_FUNCTION | 258 #undef COUNT_FUNCTION |
244 } | 259 } |
245 | 260 |
| 261 template <IncrementalMarkingObjectStatsVisitor::VisitorId id> |
| 262 void IncrementalMarkingObjectStatsVisitor::Visit(Map* map, HeapObject* obj) { |
| 263 ObjectStatsCollector::CollectStatistics(id, map, obj); |
| 264 table_.GetVisitorById(id)(map, obj); |
| 265 ObjectStatsCollector::CollectFixedArrayStatistics(obj); |
| 266 } |
| 267 |
246 } // namespace internal | 268 } // namespace internal |
247 } // namespace v8 | 269 } // namespace v8 |
OLD | NEW |