OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/class_table.h" | 5 #include "vm/class_table.h" |
6 | 6 |
7 #include "vm/atomic.h" | 7 #include "vm/atomic.h" |
8 #include "vm/flags.h" | 8 #include "vm/flags.h" |
9 #include "vm/freelist.h" | 9 #include "vm/freelist.h" |
10 #include "vm/growable_array.h" | 10 #include "vm/growable_array.h" |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 } | 52 } |
53 #ifndef PRODUCT | 53 #ifndef PRODUCT |
54 predefined_class_heap_stats_table_ = reinterpret_cast<ClassHeapStats*>( | 54 predefined_class_heap_stats_table_ = reinterpret_cast<ClassHeapStats*>( |
55 calloc(kNumPredefinedCids, sizeof(ClassHeapStats))); // NOLINT | 55 calloc(kNumPredefinedCids, sizeof(ClassHeapStats))); // NOLINT |
56 for (intptr_t i = 0; i < kNumPredefinedCids; i++) { | 56 for (intptr_t i = 0; i < kNumPredefinedCids; i++) { |
57 predefined_class_heap_stats_table_[i].Initialize(); | 57 predefined_class_heap_stats_table_[i].Initialize(); |
58 } | 58 } |
59 #endif // !PRODUCT | 59 #endif // !PRODUCT |
60 } | 60 } |
61 | 61 |
62 | |
63 ClassTable::ClassTable(ClassTable* original) | 62 ClassTable::ClassTable(ClassTable* original) |
64 : top_(original->top_), | 63 : top_(original->top_), |
65 capacity_(original->top_), | 64 capacity_(original->top_), |
66 table_(original->table_), | 65 table_(original->table_), |
67 old_tables_(NULL) { | 66 old_tables_(NULL) { |
68 NOT_IN_PRODUCT(class_heap_stats_table_ = NULL); | 67 NOT_IN_PRODUCT(class_heap_stats_table_ = NULL); |
69 NOT_IN_PRODUCT(predefined_class_heap_stats_table_ = NULL); | 68 NOT_IN_PRODUCT(predefined_class_heap_stats_table_ = NULL); |
70 } | 69 } |
71 | 70 |
72 | |
73 ClassTable::~ClassTable() { | 71 ClassTable::~ClassTable() { |
74 if (old_tables_ != NULL) { | 72 if (old_tables_ != NULL) { |
75 FreeOldTables(); | 73 FreeOldTables(); |
76 delete old_tables_; | 74 delete old_tables_; |
77 free(table_); | 75 free(table_); |
78 NOT_IN_PRODUCT(free(predefined_class_heap_stats_table_)); | 76 NOT_IN_PRODUCT(free(predefined_class_heap_stats_table_)); |
79 NOT_IN_PRODUCT(free(class_heap_stats_table_)); | 77 NOT_IN_PRODUCT(free(class_heap_stats_table_)); |
80 } else { | 78 } else { |
81 // This instance was a shallow copy. It doesn't own any memory. | 79 // This instance was a shallow copy. It doesn't own any memory. |
82 NOT_IN_PRODUCT(ASSERT(predefined_class_heap_stats_table_ == NULL)); | 80 NOT_IN_PRODUCT(ASSERT(predefined_class_heap_stats_table_ == NULL)); |
83 NOT_IN_PRODUCT(ASSERT(class_heap_stats_table_ == NULL)); | 81 NOT_IN_PRODUCT(ASSERT(class_heap_stats_table_ == NULL)); |
84 } | 82 } |
85 } | 83 } |
86 | 84 |
87 | |
88 void ClassTable::AddOldTable(RawClass** old_table) { | 85 void ClassTable::AddOldTable(RawClass** old_table) { |
89 ASSERT(Thread::Current()->IsMutatorThread()); | 86 ASSERT(Thread::Current()->IsMutatorThread()); |
90 old_tables_->Add(old_table); | 87 old_tables_->Add(old_table); |
91 } | 88 } |
92 | 89 |
93 | |
94 void ClassTable::FreeOldTables() { | 90 void ClassTable::FreeOldTables() { |
95 while (old_tables_->length() > 0) { | 91 while (old_tables_->length() > 0) { |
96 free(old_tables_->RemoveLast()); | 92 free(old_tables_->RemoveLast()); |
97 } | 93 } |
98 } | 94 } |
99 | 95 |
100 | |
101 #ifndef PRODUCT | 96 #ifndef PRODUCT |
102 void ClassTable::SetTraceAllocationFor(intptr_t cid, bool trace) { | 97 void ClassTable::SetTraceAllocationFor(intptr_t cid, bool trace) { |
103 ClassHeapStats* stats = PreliminaryStatsAt(cid); | 98 ClassHeapStats* stats = PreliminaryStatsAt(cid); |
104 stats->set_trace_allocation(trace); | 99 stats->set_trace_allocation(trace); |
105 } | 100 } |
106 | 101 |
107 | |
108 bool ClassTable::TraceAllocationFor(intptr_t cid) { | 102 bool ClassTable::TraceAllocationFor(intptr_t cid) { |
109 ClassHeapStats* stats = PreliminaryStatsAt(cid); | 103 ClassHeapStats* stats = PreliminaryStatsAt(cid); |
110 return stats->trace_allocation(); | 104 return stats->trace_allocation(); |
111 } | 105 } |
112 #endif // !PRODUCT | 106 #endif // !PRODUCT |
113 | 107 |
114 | |
115 void ClassTable::Register(const Class& cls) { | 108 void ClassTable::Register(const Class& cls) { |
116 ASSERT(Thread::Current()->IsMutatorThread()); | 109 ASSERT(Thread::Current()->IsMutatorThread()); |
117 intptr_t index = cls.id(); | 110 intptr_t index = cls.id(); |
118 if (index != kIllegalCid) { | 111 if (index != kIllegalCid) { |
119 ASSERT(index > 0); | 112 ASSERT(index > 0); |
120 ASSERT(index < kNumPredefinedCids); | 113 ASSERT(index < kNumPredefinedCids); |
121 ASSERT(table_[index] == 0); | 114 ASSERT(table_[index] == 0); |
122 ASSERT(index < capacity_); | 115 ASSERT(index < capacity_); |
123 table_[index] = cls.raw(); | 116 table_[index] = cls.raw(); |
124 // Add the vtable for this predefined class into the static vtable registry | 117 // Add the vtable for this predefined class into the static vtable registry |
(...skipping 30 matching lines...) Expand all Loading... |
155 if (!Class::is_valid_id(top_)) { | 148 if (!Class::is_valid_id(top_)) { |
156 FATAL1("Fatal error in ClassTable::Register: invalid index %" Pd "\n", | 149 FATAL1("Fatal error in ClassTable::Register: invalid index %" Pd "\n", |
157 top_); | 150 top_); |
158 } | 151 } |
159 cls.set_id(top_); | 152 cls.set_id(top_); |
160 table_[top_] = cls.raw(); | 153 table_[top_] = cls.raw(); |
161 top_++; // Increment next index. | 154 top_++; // Increment next index. |
162 } | 155 } |
163 } | 156 } |
164 | 157 |
165 | |
166 void ClassTable::AllocateIndex(intptr_t index) { | 158 void ClassTable::AllocateIndex(intptr_t index) { |
167 if (index >= capacity_) { | 159 if (index >= capacity_) { |
168 // Grow the capacity of the class table. | 160 // Grow the capacity of the class table. |
169 // TODO(koda): Add ClassTable::Grow to share code. | 161 // TODO(koda): Add ClassTable::Grow to share code. |
170 intptr_t new_capacity = index + capacity_increment_; | 162 intptr_t new_capacity = index + capacity_increment_; |
171 if (!Class::is_valid_id(index) || new_capacity < capacity_) { | 163 if (!Class::is_valid_id(index) || new_capacity < capacity_) { |
172 FATAL1("Fatal error in ClassTable::Register: invalid index %" Pd "\n", | 164 FATAL1("Fatal error in ClassTable::Register: invalid index %" Pd "\n", |
173 index); | 165 index); |
174 } | 166 } |
175 RawClass** new_table = reinterpret_cast<RawClass**>( | 167 RawClass** new_table = reinterpret_cast<RawClass**>( |
(...skipping 14 matching lines...) Expand all Loading... |
190 NOT_IN_PRODUCT(class_heap_stats_table_ = new_stats_table); | 182 NOT_IN_PRODUCT(class_heap_stats_table_ = new_stats_table); |
191 ASSERT(capacity_increment_ >= 1); | 183 ASSERT(capacity_increment_ >= 1); |
192 } | 184 } |
193 | 185 |
194 ASSERT(table_[index] == 0); | 186 ASSERT(table_[index] == 0); |
195 if (index >= top_) { | 187 if (index >= top_) { |
196 top_ = index + 1; | 188 top_ = index + 1; |
197 } | 189 } |
198 } | 190 } |
199 | 191 |
200 | |
201 void ClassTable::RegisterAt(intptr_t index, const Class& cls) { | 192 void ClassTable::RegisterAt(intptr_t index, const Class& cls) { |
202 ASSERT(Thread::Current()->IsMutatorThread()); | 193 ASSERT(Thread::Current()->IsMutatorThread()); |
203 ASSERT(index != kIllegalCid); | 194 ASSERT(index != kIllegalCid); |
204 ASSERT(index >= kNumPredefinedCids); | 195 ASSERT(index >= kNumPredefinedCids); |
205 AllocateIndex(index); | 196 AllocateIndex(index); |
206 cls.set_id(index); | 197 cls.set_id(index); |
207 table_[index] = cls.raw(); | 198 table_[index] = cls.raw(); |
208 } | 199 } |
209 | 200 |
210 | |
211 #if defined(DEBUG) | 201 #if defined(DEBUG) |
212 void ClassTable::Unregister(intptr_t index) { | 202 void ClassTable::Unregister(intptr_t index) { |
213 table_[index] = 0; | 203 table_[index] = 0; |
214 } | 204 } |
215 #endif | 205 #endif |
216 | 206 |
217 | |
218 void ClassTable::Remap(intptr_t* old_to_new_cid) { | 207 void ClassTable::Remap(intptr_t* old_to_new_cid) { |
219 ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0); | 208 ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0); |
220 intptr_t num_cids = NumCids(); | 209 intptr_t num_cids = NumCids(); |
221 RawClass** cls_by_old_cid = new RawClass*[num_cids]; | 210 RawClass** cls_by_old_cid = new RawClass*[num_cids]; |
222 for (intptr_t i = 0; i < num_cids; i++) { | 211 for (intptr_t i = 0; i < num_cids; i++) { |
223 cls_by_old_cid[i] = table_[i]; | 212 cls_by_old_cid[i] = table_[i]; |
224 } | 213 } |
225 for (intptr_t i = 0; i < num_cids; i++) { | 214 for (intptr_t i = 0; i < num_cids; i++) { |
226 table_[old_to_new_cid[i]] = cls_by_old_cid[i]; | 215 table_[old_to_new_cid[i]] = cls_by_old_cid[i]; |
227 } | 216 } |
228 delete[] cls_by_old_cid; | 217 delete[] cls_by_old_cid; |
229 } | 218 } |
230 | 219 |
231 | |
232 void ClassTable::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 220 void ClassTable::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
233 ASSERT(visitor != NULL); | 221 ASSERT(visitor != NULL); |
234 visitor->VisitPointers(reinterpret_cast<RawObject**>(&table_[0]), top_); | 222 visitor->VisitPointers(reinterpret_cast<RawObject**>(&table_[0]), top_); |
235 } | 223 } |
236 | 224 |
237 | |
238 void ClassTable::Validate() { | 225 void ClassTable::Validate() { |
239 Class& cls = Class::Handle(); | 226 Class& cls = Class::Handle(); |
240 for (intptr_t cid = kNumPredefinedCids; cid < top_; cid++) { | 227 for (intptr_t cid = kNumPredefinedCids; cid < top_; cid++) { |
241 // Some of the class table entries maybe NULL as we create some | 228 // Some of the class table entries maybe NULL as we create some |
242 // top level classes but do not add them to the list of anonymous | 229 // top level classes but do not add them to the list of anonymous |
243 // classes in a library if there are no top level fields or functions. | 230 // classes in a library if there are no top level fields or functions. |
244 // Since there are no references to these top level classes they are | 231 // Since there are no references to these top level classes they are |
245 // not written into a full snapshot and will not be recreated when | 232 // not written into a full snapshot and will not be recreated when |
246 // we read back the full snapshot. These class slots end up with NULL | 233 // we read back the full snapshot. These class slots end up with NULL |
247 // entries. | 234 // entries. |
248 if (HasValidClassAt(cid)) { | 235 if (HasValidClassAt(cid)) { |
249 cls = At(cid); | 236 cls = At(cid); |
250 ASSERT(cls.IsClass()); | 237 ASSERT(cls.IsClass()); |
251 ASSERT(cls.id() == cid); | 238 ASSERT(cls.id() == cid); |
252 } | 239 } |
253 } | 240 } |
254 } | 241 } |
255 | 242 |
256 | |
257 void ClassTable::Print() { | 243 void ClassTable::Print() { |
258 Class& cls = Class::Handle(); | 244 Class& cls = Class::Handle(); |
259 String& name = String::Handle(); | 245 String& name = String::Handle(); |
260 | 246 |
261 for (intptr_t i = 1; i < top_; i++) { | 247 for (intptr_t i = 1; i < top_; i++) { |
262 if (!HasValidClassAt(i)) { | 248 if (!HasValidClassAt(i)) { |
263 continue; | 249 continue; |
264 } | 250 } |
265 cls = At(i); | 251 cls = At(i); |
266 if (cls.raw() != reinterpret_cast<RawClass*>(0)) { | 252 if (cls.raw() != reinterpret_cast<RawClass*>(0)) { |
267 name = cls.Name(); | 253 name = cls.Name(); |
268 OS::Print("%" Pd ": %s\n", i, name.ToCString()); | 254 OS::Print("%" Pd ": %s\n", i, name.ToCString()); |
269 } | 255 } |
270 } | 256 } |
271 } | 257 } |
272 | 258 |
273 | |
274 #ifndef PRODUCT | 259 #ifndef PRODUCT |
275 void ClassTable::PrintToJSONObject(JSONObject* object) { | 260 void ClassTable::PrintToJSONObject(JSONObject* object) { |
276 if (!FLAG_support_service) { | 261 if (!FLAG_support_service) { |
277 return; | 262 return; |
278 } | 263 } |
279 Class& cls = Class::Handle(); | 264 Class& cls = Class::Handle(); |
280 object->AddProperty("type", "ClassList"); | 265 object->AddProperty("type", "ClassList"); |
281 { | 266 { |
282 JSONArray members(object, "classes"); | 267 JSONArray members(object, "classes"); |
283 for (intptr_t i = 1; i < top_; i++) { | 268 for (intptr_t i = 1; i < top_; i++) { |
284 if (HasValidClassAt(i)) { | 269 if (HasValidClassAt(i)) { |
285 cls = At(i); | 270 cls = At(i); |
286 members.AddValue(cls); | 271 members.AddValue(cls); |
287 } | 272 } |
288 } | 273 } |
289 } | 274 } |
290 } | 275 } |
291 | 276 |
292 | |
293 void ClassHeapStats::Initialize() { | 277 void ClassHeapStats::Initialize() { |
294 pre_gc.Reset(); | 278 pre_gc.Reset(); |
295 post_gc.Reset(); | 279 post_gc.Reset(); |
296 recent.Reset(); | 280 recent.Reset(); |
297 accumulated.Reset(); | 281 accumulated.Reset(); |
298 last_reset.Reset(); | 282 last_reset.Reset(); |
299 promoted_count = 0; | 283 promoted_count = 0; |
300 promoted_size = 0; | 284 promoted_size = 0; |
301 state_ = 0; | 285 state_ = 0; |
302 USE(align_); | 286 USE(align_); |
303 } | 287 } |
304 | 288 |
305 | |
306 void ClassHeapStats::ResetAtNewGC() { | 289 void ClassHeapStats::ResetAtNewGC() { |
307 Verify(); | 290 Verify(); |
308 pre_gc.new_count = post_gc.new_count + recent.new_count; | 291 pre_gc.new_count = post_gc.new_count + recent.new_count; |
309 pre_gc.new_size = post_gc.new_size + recent.new_size; | 292 pre_gc.new_size = post_gc.new_size + recent.new_size; |
310 // Accumulate allocations. | 293 // Accumulate allocations. |
311 accumulated.new_count += recent.new_count - last_reset.new_count; | 294 accumulated.new_count += recent.new_count - last_reset.new_count; |
312 accumulated.new_size += recent.new_size - last_reset.new_size; | 295 accumulated.new_size += recent.new_size - last_reset.new_size; |
313 last_reset.ResetNew(); | 296 last_reset.ResetNew(); |
314 post_gc.ResetNew(); | 297 post_gc.ResetNew(); |
315 recent.ResetNew(); | 298 recent.ResetNew(); |
316 old_pre_new_gc_count_ = recent.old_count; | 299 old_pre_new_gc_count_ = recent.old_count; |
317 old_pre_new_gc_size_ = recent.old_size; | 300 old_pre_new_gc_size_ = recent.old_size; |
318 } | 301 } |
319 | 302 |
320 | |
321 void ClassHeapStats::ResetAtOldGC() { | 303 void ClassHeapStats::ResetAtOldGC() { |
322 Verify(); | 304 Verify(); |
323 pre_gc.old_count = post_gc.old_count + recent.old_count; | 305 pre_gc.old_count = post_gc.old_count + recent.old_count; |
324 pre_gc.old_size = post_gc.old_size + recent.old_size; | 306 pre_gc.old_size = post_gc.old_size + recent.old_size; |
325 // Accumulate allocations. | 307 // Accumulate allocations. |
326 accumulated.old_count += recent.old_count - last_reset.old_count; | 308 accumulated.old_count += recent.old_count - last_reset.old_count; |
327 accumulated.old_size += recent.old_size - last_reset.old_size; | 309 accumulated.old_size += recent.old_size - last_reset.old_size; |
328 last_reset.ResetOld(); | 310 last_reset.ResetOld(); |
329 post_gc.ResetOld(); | 311 post_gc.ResetOld(); |
330 recent.ResetOld(); | 312 recent.ResetOld(); |
331 } | 313 } |
332 | 314 |
333 | |
334 void ClassHeapStats::Verify() { | 315 void ClassHeapStats::Verify() { |
335 pre_gc.Verify(); | 316 pre_gc.Verify(); |
336 post_gc.Verify(); | 317 post_gc.Verify(); |
337 recent.Verify(); | 318 recent.Verify(); |
338 accumulated.Verify(); | 319 accumulated.Verify(); |
339 last_reset.Verify(); | 320 last_reset.Verify(); |
340 } | 321 } |
341 | 322 |
342 | |
343 void ClassHeapStats::UpdateSize(intptr_t instance_size) { | 323 void ClassHeapStats::UpdateSize(intptr_t instance_size) { |
344 pre_gc.UpdateSize(instance_size); | 324 pre_gc.UpdateSize(instance_size); |
345 post_gc.UpdateSize(instance_size); | 325 post_gc.UpdateSize(instance_size); |
346 recent.UpdateSize(instance_size); | 326 recent.UpdateSize(instance_size); |
347 accumulated.UpdateSize(instance_size); | 327 accumulated.UpdateSize(instance_size); |
348 last_reset.UpdateSize(instance_size); | 328 last_reset.UpdateSize(instance_size); |
349 promoted_size = promoted_count * instance_size; | 329 promoted_size = promoted_count * instance_size; |
350 old_pre_new_gc_size_ = old_pre_new_gc_count_ * instance_size; | 330 old_pre_new_gc_size_ = old_pre_new_gc_count_ * instance_size; |
351 } | 331 } |
352 | 332 |
353 | |
354 void ClassHeapStats::ResetAccumulator() { | 333 void ClassHeapStats::ResetAccumulator() { |
355 // Remember how much was allocated so we can subtract this from the result | 334 // Remember how much was allocated so we can subtract this from the result |
356 // when printing. | 335 // when printing. |
357 last_reset.new_count = recent.new_count; | 336 last_reset.new_count = recent.new_count; |
358 last_reset.new_size = recent.new_size; | 337 last_reset.new_size = recent.new_size; |
359 last_reset.old_count = recent.old_count; | 338 last_reset.old_count = recent.old_count; |
360 last_reset.old_size = recent.old_size; | 339 last_reset.old_size = recent.old_size; |
361 accumulated.Reset(); | 340 accumulated.Reset(); |
362 } | 341 } |
363 | 342 |
364 | |
365 void ClassHeapStats::UpdatePromotedAfterNewGC() { | 343 void ClassHeapStats::UpdatePromotedAfterNewGC() { |
366 promoted_count = recent.old_count - old_pre_new_gc_count_; | 344 promoted_count = recent.old_count - old_pre_new_gc_count_; |
367 promoted_size = recent.old_size - old_pre_new_gc_size_; | 345 promoted_size = recent.old_size - old_pre_new_gc_size_; |
368 } | 346 } |
369 | 347 |
370 | |
371 void ClassHeapStats::PrintToJSONObject(const Class& cls, | 348 void ClassHeapStats::PrintToJSONObject(const Class& cls, |
372 JSONObject* obj) const { | 349 JSONObject* obj) const { |
373 if (!FLAG_support_service) { | 350 if (!FLAG_support_service) { |
374 return; | 351 return; |
375 } | 352 } |
376 obj->AddProperty("type", "ClassHeapStats"); | 353 obj->AddProperty("type", "ClassHeapStats"); |
377 obj->AddProperty("class", cls); | 354 obj->AddProperty("class", cls); |
378 { | 355 { |
379 JSONArray new_stats(obj, "new"); | 356 JSONArray new_stats(obj, "new"); |
380 new_stats.AddValue(pre_gc.new_count); | 357 new_stats.AddValue(pre_gc.new_count); |
(...skipping 17 matching lines...) Expand all Loading... |
398 old_stats.AddValue(recent.old_size); | 375 old_stats.AddValue(recent.old_size); |
399 old_stats.AddValue64(accumulated.old_count + recent.old_count - | 376 old_stats.AddValue64(accumulated.old_count + recent.old_count - |
400 last_reset.old_count); | 377 last_reset.old_count); |
401 old_stats.AddValue64(accumulated.old_size + recent.old_size - | 378 old_stats.AddValue64(accumulated.old_size + recent.old_size - |
402 last_reset.old_size); | 379 last_reset.old_size); |
403 } | 380 } |
404 obj->AddProperty("promotedInstances", promoted_count); | 381 obj->AddProperty("promotedInstances", promoted_count); |
405 obj->AddProperty("promotedBytes", promoted_size); | 382 obj->AddProperty("promotedBytes", promoted_size); |
406 } | 383 } |
407 | 384 |
408 | |
409 void ClassTable::UpdateAllocatedNew(intptr_t cid, intptr_t size) { | 385 void ClassTable::UpdateAllocatedNew(intptr_t cid, intptr_t size) { |
410 ClassHeapStats* stats = PreliminaryStatsAt(cid); | 386 ClassHeapStats* stats = PreliminaryStatsAt(cid); |
411 ASSERT(stats != NULL); | 387 ASSERT(stats != NULL); |
412 ASSERT(size != 0); | 388 ASSERT(size != 0); |
413 stats->recent.AddNew(size); | 389 stats->recent.AddNew(size); |
414 } | 390 } |
415 | 391 |
416 | |
417 void ClassTable::UpdateAllocatedOld(intptr_t cid, intptr_t size) { | 392 void ClassTable::UpdateAllocatedOld(intptr_t cid, intptr_t size) { |
418 ClassHeapStats* stats = PreliminaryStatsAt(cid); | 393 ClassHeapStats* stats = PreliminaryStatsAt(cid); |
419 ASSERT(stats != NULL); | 394 ASSERT(stats != NULL); |
420 ASSERT(size != 0); | 395 ASSERT(size != 0); |
421 stats->recent.AddOld(size); | 396 stats->recent.AddOld(size); |
422 } | 397 } |
423 | 398 |
424 | |
425 bool ClassTable::ShouldUpdateSizeForClassId(intptr_t cid) { | 399 bool ClassTable::ShouldUpdateSizeForClassId(intptr_t cid) { |
426 return !RawObject::IsVariableSizeClassId(cid); | 400 return !RawObject::IsVariableSizeClassId(cid); |
427 } | 401 } |
428 | 402 |
429 | |
430 ClassHeapStats* ClassTable::PreliminaryStatsAt(intptr_t cid) { | 403 ClassHeapStats* ClassTable::PreliminaryStatsAt(intptr_t cid) { |
431 ASSERT(cid > 0); | 404 ASSERT(cid > 0); |
432 if (cid < kNumPredefinedCids) { | 405 if (cid < kNumPredefinedCids) { |
433 return &predefined_class_heap_stats_table_[cid]; | 406 return &predefined_class_heap_stats_table_[cid]; |
434 } | 407 } |
435 ASSERT(cid < top_); | 408 ASSERT(cid < top_); |
436 return &class_heap_stats_table_[cid]; | 409 return &class_heap_stats_table_[cid]; |
437 } | 410 } |
438 | 411 |
439 | |
440 ClassHeapStats* ClassTable::StatsWithUpdatedSize(intptr_t cid) { | 412 ClassHeapStats* ClassTable::StatsWithUpdatedSize(intptr_t cid) { |
441 if (!HasValidClassAt(cid) || (cid == kFreeListElement) || | 413 if (!HasValidClassAt(cid) || (cid == kFreeListElement) || |
442 (cid == kForwardingCorpse) || (cid == kSmiCid)) { | 414 (cid == kForwardingCorpse) || (cid == kSmiCid)) { |
443 return NULL; | 415 return NULL; |
444 } | 416 } |
445 Class& cls = Class::Handle(At(cid)); | 417 Class& cls = Class::Handle(At(cid)); |
446 if (!(cls.is_finalized() || cls.is_prefinalized())) { | 418 if (!(cls.is_finalized() || cls.is_prefinalized())) { |
447 // Not finalized. | 419 // Not finalized. |
448 return NULL; | 420 return NULL; |
449 } | 421 } |
450 ClassHeapStats* stats = PreliminaryStatsAt(cid); | 422 ClassHeapStats* stats = PreliminaryStatsAt(cid); |
451 if (ShouldUpdateSizeForClassId(cid)) { | 423 if (ShouldUpdateSizeForClassId(cid)) { |
452 stats->UpdateSize(cls.instance_size()); | 424 stats->UpdateSize(cls.instance_size()); |
453 } | 425 } |
454 stats->Verify(); | 426 stats->Verify(); |
455 return stats; | 427 return stats; |
456 } | 428 } |
457 | 429 |
458 | |
459 void ClassTable::ResetCountersOld() { | 430 void ClassTable::ResetCountersOld() { |
460 for (intptr_t i = 0; i < kNumPredefinedCids; i++) { | 431 for (intptr_t i = 0; i < kNumPredefinedCids; i++) { |
461 predefined_class_heap_stats_table_[i].ResetAtOldGC(); | 432 predefined_class_heap_stats_table_[i].ResetAtOldGC(); |
462 } | 433 } |
463 for (intptr_t i = kNumPredefinedCids; i < top_; i++) { | 434 for (intptr_t i = kNumPredefinedCids; i < top_; i++) { |
464 class_heap_stats_table_[i].ResetAtOldGC(); | 435 class_heap_stats_table_[i].ResetAtOldGC(); |
465 } | 436 } |
466 } | 437 } |
467 | 438 |
468 | |
469 void ClassTable::ResetCountersNew() { | 439 void ClassTable::ResetCountersNew() { |
470 for (intptr_t i = 0; i < kNumPredefinedCids; i++) { | 440 for (intptr_t i = 0; i < kNumPredefinedCids; i++) { |
471 predefined_class_heap_stats_table_[i].ResetAtNewGC(); | 441 predefined_class_heap_stats_table_[i].ResetAtNewGC(); |
472 } | 442 } |
473 for (intptr_t i = kNumPredefinedCids; i < top_; i++) { | 443 for (intptr_t i = kNumPredefinedCids; i < top_; i++) { |
474 class_heap_stats_table_[i].ResetAtNewGC(); | 444 class_heap_stats_table_[i].ResetAtNewGC(); |
475 } | 445 } |
476 } | 446 } |
477 | 447 |
478 | |
479 void ClassTable::UpdatePromoted() { | 448 void ClassTable::UpdatePromoted() { |
480 for (intptr_t i = 0; i < kNumPredefinedCids; i++) { | 449 for (intptr_t i = 0; i < kNumPredefinedCids; i++) { |
481 predefined_class_heap_stats_table_[i].UpdatePromotedAfterNewGC(); | 450 predefined_class_heap_stats_table_[i].UpdatePromotedAfterNewGC(); |
482 } | 451 } |
483 for (intptr_t i = kNumPredefinedCids; i < top_; i++) { | 452 for (intptr_t i = kNumPredefinedCids; i < top_; i++) { |
484 class_heap_stats_table_[i].UpdatePromotedAfterNewGC(); | 453 class_heap_stats_table_[i].UpdatePromotedAfterNewGC(); |
485 } | 454 } |
486 } | 455 } |
487 | 456 |
488 | |
489 ClassHeapStats** ClassTable::TableAddressFor(intptr_t cid) { | 457 ClassHeapStats** ClassTable::TableAddressFor(intptr_t cid) { |
490 return (cid < kNumPredefinedCids) ? &predefined_class_heap_stats_table_ | 458 return (cid < kNumPredefinedCids) ? &predefined_class_heap_stats_table_ |
491 : &class_heap_stats_table_; | 459 : &class_heap_stats_table_; |
492 } | 460 } |
493 | 461 |
494 | |
495 intptr_t ClassTable::TableOffsetFor(intptr_t cid) { | 462 intptr_t ClassTable::TableOffsetFor(intptr_t cid) { |
496 return (cid < kNumPredefinedCids) | 463 return (cid < kNumPredefinedCids) |
497 ? OFFSET_OF(ClassTable, predefined_class_heap_stats_table_) | 464 ? OFFSET_OF(ClassTable, predefined_class_heap_stats_table_) |
498 : OFFSET_OF(ClassTable, class_heap_stats_table_); | 465 : OFFSET_OF(ClassTable, class_heap_stats_table_); |
499 } | 466 } |
500 | 467 |
501 | |
502 intptr_t ClassTable::ClassOffsetFor(intptr_t cid) { | 468 intptr_t ClassTable::ClassOffsetFor(intptr_t cid) { |
503 return cid * sizeof(ClassHeapStats); // NOLINT | 469 return cid * sizeof(ClassHeapStats); // NOLINT |
504 } | 470 } |
505 | 471 |
506 | |
507 intptr_t ClassTable::CounterOffsetFor(intptr_t cid, bool is_new_space) { | 472 intptr_t ClassTable::CounterOffsetFor(intptr_t cid, bool is_new_space) { |
508 const intptr_t class_offset = ClassOffsetFor(cid); | 473 const intptr_t class_offset = ClassOffsetFor(cid); |
509 const intptr_t count_field_offset = | 474 const intptr_t count_field_offset = |
510 is_new_space ? ClassHeapStats::allocated_since_gc_new_space_offset() | 475 is_new_space ? ClassHeapStats::allocated_since_gc_new_space_offset() |
511 : ClassHeapStats::allocated_since_gc_old_space_offset(); | 476 : ClassHeapStats::allocated_since_gc_old_space_offset(); |
512 return class_offset + count_field_offset; | 477 return class_offset + count_field_offset; |
513 } | 478 } |
514 | 479 |
515 | |
516 intptr_t ClassTable::StateOffsetFor(intptr_t cid) { | 480 intptr_t ClassTable::StateOffsetFor(intptr_t cid) { |
517 return ClassOffsetFor(cid) + ClassHeapStats::state_offset(); | 481 return ClassOffsetFor(cid) + ClassHeapStats::state_offset(); |
518 } | 482 } |
519 | 483 |
520 | |
521 intptr_t ClassTable::SizeOffsetFor(intptr_t cid, bool is_new_space) { | 484 intptr_t ClassTable::SizeOffsetFor(intptr_t cid, bool is_new_space) { |
522 const uword class_offset = ClassOffsetFor(cid); | 485 const uword class_offset = ClassOffsetFor(cid); |
523 const uword size_field_offset = | 486 const uword size_field_offset = |
524 is_new_space ? ClassHeapStats::allocated_size_since_gc_new_space_offset() | 487 is_new_space ? ClassHeapStats::allocated_size_since_gc_new_space_offset() |
525 : ClassHeapStats::allocated_size_since_gc_old_space_offset(); | 488 : ClassHeapStats::allocated_size_since_gc_old_space_offset(); |
526 return class_offset + size_field_offset; | 489 return class_offset + size_field_offset; |
527 } | 490 } |
528 | 491 |
529 | |
530 void ClassTable::AllocationProfilePrintJSON(JSONStream* stream) { | 492 void ClassTable::AllocationProfilePrintJSON(JSONStream* stream) { |
531 if (!FLAG_support_service) { | 493 if (!FLAG_support_service) { |
532 return; | 494 return; |
533 } | 495 } |
534 Isolate* isolate = Isolate::Current(); | 496 Isolate* isolate = Isolate::Current(); |
535 ASSERT(isolate != NULL); | 497 ASSERT(isolate != NULL); |
536 Heap* heap = isolate->heap(); | 498 Heap* heap = isolate->heap(); |
537 ASSERT(heap != NULL); | 499 ASSERT(heap != NULL); |
538 JSONObject obj(stream); | 500 JSONObject obj(stream); |
539 obj.AddProperty("type", "AllocationProfile"); | 501 obj.AddProperty("type", "AllocationProfile"); |
(...skipping 19 matching lines...) Expand all Loading... |
559 const ClassHeapStats* stats = StatsWithUpdatedSize(i); | 521 const ClassHeapStats* stats = StatsWithUpdatedSize(i); |
560 if (stats != NULL) { | 522 if (stats != NULL) { |
561 JSONObject obj(&arr); | 523 JSONObject obj(&arr); |
562 cls = At(i); | 524 cls = At(i); |
563 stats->PrintToJSONObject(cls, &obj); | 525 stats->PrintToJSONObject(cls, &obj); |
564 } | 526 } |
565 } | 527 } |
566 } | 528 } |
567 } | 529 } |
568 | 530 |
569 | |
570 void ClassTable::ResetAllocationAccumulators() { | 531 void ClassTable::ResetAllocationAccumulators() { |
571 for (intptr_t i = 1; i < top_; i++) { | 532 for (intptr_t i = 1; i < top_; i++) { |
572 ClassHeapStats* stats = StatsWithUpdatedSize(i); | 533 ClassHeapStats* stats = StatsWithUpdatedSize(i); |
573 if (stats != NULL) { | 534 if (stats != NULL) { |
574 stats->ResetAccumulator(); | 535 stats->ResetAccumulator(); |
575 } | 536 } |
576 } | 537 } |
577 } | 538 } |
578 | 539 |
579 | |
580 void ClassTable::UpdateLiveOld(intptr_t cid, intptr_t size, intptr_t count) { | 540 void ClassTable::UpdateLiveOld(intptr_t cid, intptr_t size, intptr_t count) { |
581 ClassHeapStats* stats = PreliminaryStatsAt(cid); | 541 ClassHeapStats* stats = PreliminaryStatsAt(cid); |
582 ASSERT(stats != NULL); | 542 ASSERT(stats != NULL); |
583 ASSERT(size >= 0); | 543 ASSERT(size >= 0); |
584 ASSERT(count >= 0); | 544 ASSERT(count >= 0); |
585 stats->post_gc.AddOld(size, count); | 545 stats->post_gc.AddOld(size, count); |
586 } | 546 } |
587 | 547 |
588 | |
589 void ClassTable::UpdateLiveNew(intptr_t cid, intptr_t size) { | 548 void ClassTable::UpdateLiveNew(intptr_t cid, intptr_t size) { |
590 ClassHeapStats* stats = PreliminaryStatsAt(cid); | 549 ClassHeapStats* stats = PreliminaryStatsAt(cid); |
591 ASSERT(stats != NULL); | 550 ASSERT(stats != NULL); |
592 ASSERT(size >= 0); | 551 ASSERT(size >= 0); |
593 stats->post_gc.AddNew(size); | 552 stats->post_gc.AddNew(size); |
594 } | 553 } |
595 #endif // !PRODUCT | 554 #endif // !PRODUCT |
596 | 555 |
597 | |
598 } // namespace dart | 556 } // namespace dart |
OLD | NEW |