Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(266)

Side by Side Diff: runtime/vm/class_table.cc

Issue 51653006: Track live instance and allocation counts for classes (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 #include "vm/flags.h" 6 #include "vm/flags.h"
7 #include "vm/freelist.h" 7 #include "vm/freelist.h"
8 #include "vm/heap.h"
8 #include "vm/object.h" 9 #include "vm/object.h"
9 #include "vm/raw_object.h" 10 #include "vm/raw_object.h"
10 #include "vm/visitor.h" 11 #include "vm/visitor.h"
11 12
12 namespace dart { 13 namespace dart {
13 14
14 DEFINE_FLAG(bool, print_class_table, false, "Print initial class table."); 15 DEFINE_FLAG(bool, print_class_table, false, "Print initial class table.");
15 16
16 ClassTable::ClassTable() 17 ClassTable::ClassTable()
17 : top_(kNumPredefinedCids), capacity_(0), table_(NULL) { 18 : top_(kNumPredefinedCids), capacity_(0), table_(NULL),
19 class_heap_stats_table_(NULL),
20 predefined_class_heap_stats_table_(NULL) {
18 if (Dart::vm_isolate() == NULL) { 21 if (Dart::vm_isolate() == NULL) {
19 capacity_ = initial_capacity_; 22 capacity_ = initial_capacity_;
20 table_ = reinterpret_cast<RawClass**>( 23 table_ = reinterpret_cast<RawClass**>(
21 calloc(capacity_, sizeof(RawClass*))); // NOLINT 24 calloc(capacity_, sizeof(RawClass*))); // NOLINT
22 } else { 25 } else {
23 // Duplicate the class table from the VM isolate. 26 // Duplicate the class table from the VM isolate.
24 ClassTable* vm_class_table = Dart::vm_isolate()->class_table(); 27 ClassTable* vm_class_table = Dart::vm_isolate()->class_table();
25 capacity_ = vm_class_table->capacity_; 28 capacity_ = vm_class_table->capacity_;
26 table_ = reinterpret_cast<RawClass**>( 29 table_ = reinterpret_cast<RawClass**>(
27 calloc(capacity_, sizeof(RawClass*))); // NOLINT 30 calloc(capacity_, sizeof(RawClass*))); // NOLINT
28 for (intptr_t i = kObjectCid; i < kInstanceCid; i++) { 31 for (intptr_t i = kObjectCid; i < kInstanceCid; i++) {
29 table_[i] = vm_class_table->At(i); 32 table_[i] = vm_class_table->At(i);
30 } 33 }
31 table_[kFreeListElement] = vm_class_table->At(kFreeListElement); 34 table_[kFreeListElement] = vm_class_table->At(kFreeListElement);
32 table_[kDynamicCid] = vm_class_table->At(kDynamicCid); 35 table_[kDynamicCid] = vm_class_table->At(kDynamicCid);
33 table_[kVoidCid] = vm_class_table->At(kVoidCid); 36 table_[kVoidCid] = vm_class_table->At(kVoidCid);
37 class_heap_stats_table_ = reinterpret_cast<ClassHeapStats*>(
38 calloc(capacity_, sizeof(ClassHeapStats))); // NOLINT
39 for (intptr_t i = 0; i < capacity_; i++) {
40 class_heap_stats_table_[i].Initialize();
41 }
42 }
43 predefined_class_heap_stats_table_ = reinterpret_cast<ClassHeapStats*>(
44 calloc(kNumPredefinedCids, sizeof(ClassHeapStats))); // NOLINT
45 for (intptr_t i = 0; i < kNumPredefinedCids; i++) {
46 predefined_class_heap_stats_table_[i].Initialize();
34 } 47 }
35 } 48 }
36 49
37 50
38 ClassTable::~ClassTable() { 51 ClassTable::~ClassTable() {
39 free(table_); 52 free(table_);
53 free(predefined_class_heap_stats_table_);
54 free(class_heap_stats_table_);
40 } 55 }
41 56
42 57
43 void ClassTable::Register(const Class& cls) { 58 void ClassTable::Register(const Class& cls) {
44 intptr_t index = cls.id(); 59 intptr_t index = cls.id();
45 if (index != kIllegalCid) { 60 if (index != kIllegalCid) {
46 ASSERT(index > 0); 61 ASSERT(index > 0);
47 ASSERT(index < kNumPredefinedCids); 62 ASSERT(index < kNumPredefinedCids);
48 ASSERT(table_[index] == 0); 63 ASSERT(table_[index] == 0);
49 ASSERT(index < capacity_); 64 ASSERT(index < capacity_);
50 table_[index] = cls.raw(); 65 table_[index] = cls.raw();
51 // Add the vtable for this predefined class into the static vtable registry 66 // Add the vtable for this predefined class into the static vtable registry
52 // if it has not been setup yet. 67 // if it has not been setup yet.
53 cpp_vtable cls_vtable = cls.handle_vtable(); 68 cpp_vtable cls_vtable = cls.handle_vtable();
54 cpp_vtable table_entry = Object::builtin_vtables_[index]; 69 cpp_vtable table_entry = Object::builtin_vtables_[index];
55 ASSERT((table_entry == 0) || (table_entry == cls_vtable)); 70 ASSERT((table_entry == 0) || (table_entry == cls_vtable));
56 if (table_entry == 0) { 71 if (table_entry == 0) {
57 Object::builtin_vtables_[index] = cls_vtable; 72 Object::builtin_vtables_[index] = cls_vtable;
58 } 73 }
59 } else { 74 } else {
60 if (top_ == capacity_) { 75 if (top_ == capacity_) {
61 // Grow the capacity of the class table. 76 // Grow the capacity of the class table.
62 intptr_t new_capacity = capacity_ + capacity_increment_; 77 intptr_t new_capacity = capacity_ + capacity_increment_;
63 RawClass** new_table = reinterpret_cast<RawClass**>( 78 RawClass** new_table = reinterpret_cast<RawClass**>(
64 realloc(table_, new_capacity * sizeof(RawClass*))); // NOLINT 79 realloc(table_, new_capacity * sizeof(RawClass*))); // NOLINT
80 ClassHeapStats* new_stats_table = reinterpret_cast<ClassHeapStats*>(
81 realloc(class_heap_stats_table_,
82 new_capacity * sizeof(ClassHeapStats))); // NOLINT
65 for (intptr_t i = capacity_; i < new_capacity; i++) { 83 for (intptr_t i = capacity_; i < new_capacity; i++) {
66 new_table[i] = NULL; 84 new_table[i] = NULL;
85 new_stats_table[i].Initialize();
67 } 86 }
68 capacity_ = new_capacity; 87 capacity_ = new_capacity;
69 table_ = new_table; 88 table_ = new_table;
89 class_heap_stats_table_ = new_stats_table;
70 } 90 }
71 ASSERT(top_ < capacity_); 91 ASSERT(top_ < capacity_);
72 cls.set_id(top_); 92 cls.set_id(top_);
73 table_[top_] = cls.raw(); 93 table_[top_] = cls.raw();
74 top_++; // Increment next index. 94 top_++; // Increment next index.
75 } 95 }
76 } 96 }
77 97
78 98
79 void ClassTable::VisitObjectPointers(ObjectPointerVisitor* visitor) { 99 void ClassTable::VisitObjectPointers(ObjectPointerVisitor* visitor) {
(...skipping 24 matching lines...) Expand all
104 JSONArray members(&jsobj, "members"); 124 JSONArray members(&jsobj, "members");
105 for (intptr_t i = 1; i < top_; i++) { 125 for (intptr_t i = 1; i < top_; i++) {
106 if (HasValidClassAt(i)) { 126 if (HasValidClassAt(i)) {
107 cls = At(i); 127 cls = At(i);
108 members.AddValue(cls); 128 members.AddValue(cls);
109 } 129 }
110 } 130 }
111 } 131 }
112 } 132 }
113 133
134
135 void ClassHeapStats::Initialize() {
136 allocated_before_gc_old_space = 0;
137 allocated_before_gc_new_space = 0;
138 allocated_size_before_gc_old_space = 0;
139 allocated_size_before_gc_new_space = 0;
140 live_after_gc_old_space = 0;
141 live_after_gc_new_space = 0;
142 live_size_after_gc_old_space = 0;
143 live_size_after_gc_new_space = 0;
144 allocated_since_gc_new_space = 0;
145 allocated_since_gc_old_space = 0;
146 allocated_size_since_gc_new_space = 0;
147 allocated_size_since_gc_old_space = 0;
148 }
149
150
151 void ClassHeapStats::ResetAtNewGC() {
152 allocated_before_gc_new_space = live_after_gc_new_space +
153 allocated_since_gc_new_space;
154 allocated_size_before_gc_new_space = live_size_after_gc_new_space +
155 allocated_size_since_gc_new_space;
156 live_after_gc_new_space = 0;
157 live_size_after_gc_new_space = 0;
158 allocated_since_gc_new_space = 0;
159 allocated_size_since_gc_new_space = 0;
160 }
161
162
163 void ClassHeapStats::ResetAtOldGC() {
164 allocated_before_gc_old_space = live_after_gc_old_space +
165 allocated_since_gc_old_space;
166 allocated_size_before_gc_old_space = live_size_after_gc_old_space +
167 allocated_size_since_gc_old_space;
168 live_after_gc_old_space = 0;
169 live_size_after_gc_old_space = 0;
170 allocated_since_gc_old_space = 0;
171 allocated_size_since_gc_old_space = 0;
172 }
173
174
175 void ClassHeapStats::UpdateSize(intptr_t instance_size) {
176 ASSERT(instance_size > 0);
177 // For classes with fixed instance size we do not emit code to update
178 // the size statistics. Update them here.
179 allocated_size_before_gc_old_space =
180 allocated_before_gc_old_space * instance_size;
181 allocated_size_before_gc_new_space =
182 allocated_before_gc_new_space * instance_size;
183 live_size_after_gc_old_space =
184 live_after_gc_old_space * instance_size;
185 live_size_after_gc_new_space =
186 live_after_gc_new_space * instance_size;
187 allocated_size_since_gc_new_space =
188 allocated_since_gc_new_space * instance_size;
189 allocated_size_since_gc_old_space =
190 allocated_since_gc_old_space * instance_size;
191 }
192
193
194 void ClassHeapStats::PrintTOJSONArray(const Class& cls, JSONArray* array) {
195 JSONObject obj(array);
196 obj.AddProperty("type", "ClassHeapStats");
197 obj.AddProperty("class", cls);
198 {
199 JSONArray new_stats(&obj, "new");
200 new_stats.AddValue(allocated_before_gc_new_space);
201 new_stats.AddValue(allocated_size_before_gc_new_space);
202 new_stats.AddValue(live_after_gc_new_space);
203 new_stats.AddValue(live_size_after_gc_new_space);
204 new_stats.AddValue(allocated_since_gc_new_space);
205 new_stats.AddValue(allocated_size_since_gc_new_space);
206 }
207 {
208 JSONArray old_stats(&obj, "old");
209 old_stats.AddValue(allocated_before_gc_old_space);
210 old_stats.AddValue(allocated_size_before_gc_old_space);
211 old_stats.AddValue(live_after_gc_old_space);
212 old_stats.AddValue(live_size_after_gc_old_space);
213 old_stats.AddValue(allocated_since_gc_old_space);
214 old_stats.AddValue(allocated_size_since_gc_old_space);
215 }
216 }
217
218
219 void ClassTable::UpdateAllocatedNew(intptr_t cid, intptr_t size) {
220 ClassHeapStats* stats = StatsAt(cid);
221 ASSERT(stats != NULL);
222 ASSERT(size != 0);
223 stats->allocated_since_gc_new_space++;
224 stats->allocated_size_since_gc_new_space += size;
225 }
226
227
228 void ClassTable::UpdateAllocatedOld(intptr_t cid, intptr_t size) {
229 ClassHeapStats* stats = StatsAt(cid);
230 ASSERT(stats != NULL);
231 ASSERT(size != 0);
232 stats->allocated_since_gc_old_space++;
233 stats->allocated_size_since_gc_old_space += size;
234 }
235
236
237 // #define DEBUG_PRINT
Ivan Posva 2014/01/17 06:53:16 Debugging code should go.
Cutch 2014/01/17 18:37:59 Done.
238
239 #if defined(DEBUG_PRINT)
240 static void PrintClassHeapStats(intptr_t cid, const ClassHeapStats& stat) {
241 int new_new = static_cast<int>(stat.new_count_since_gc_new_space);
242 int new_old = static_cast<int>(stat.new_count_since_gc_old_space);
243 int b_new = static_cast<int>(stat.new_size_since_gc_new_space);
244 int b_old = static_cast<int>(stat.new_size_since_gc_old_space);
245 printf("%d (%d %d) [%d %d]\n", static_cast<int>(cid),
246 new_new, b_new, new_old, b_old);
247 }
248 #endif
249
250
251 bool ClassTable::CollectInstanceSizesForClass(intptr_t cid) {
Ivan Posva 2014/01/17 06:53:16 We have other lists of class ids in raw_object, fo
Cutch 2014/01/17 18:37:59 Done.
252 // We only collect size information for classes which do not have
253 // fixed lengths.
254 if ((cid == kArrayCid) ||
255 (cid == kImmutableArrayCid) ||
256 RawObject::IsOneByteStringClassId(cid) ||
257 RawObject::IsTwoByteStringClassId(cid) ||
258 RawObject::IsTypedDataClassId(cid) ||
259 (cid == kContextCid) ||
260 (cid == kTypeArgumentsCid) ||
261 (cid == kInstructionsCid) ||
262 (cid == kPcDescriptorsCid) ||
263 (cid == kStackmapCid) ||
264 (cid == kLocalVarDescriptorsCid) ||
265 (cid == kExceptionHandlersCid) ||
266 (cid == kDeoptInfoCid) ||
267 (cid == kCodeCid) ||
268 (cid == kContextScopeCid) ||
269 (cid == kInstanceCid) ||
270 (cid == kBigintCid) ||
271 (cid == kJSRegExpCid) ||
272 (cid == kSmiCid)) {
Ivan Posva 2014/01/17 06:53:16 SmiCid is definitely not variable in size.
273 return true;
274 }
275 return false;
276 }
277
278
279 ClassHeapStats* ClassTable::StatsAt(intptr_t cid) {
280 ASSERT(cid > 0);
281 if (cid < kNumPredefinedCids) {
282 return &predefined_class_heap_stats_table_[cid];
283 }
284 ASSERT(cid < top_);
285 return &class_heap_stats_table_[cid];
286 }
287
288
289 void ClassTable::ResetCountersOld() {
290 for (intptr_t i = 0; i < kNumPredefinedCids; i++) {
291 predefined_class_heap_stats_table_[i].ResetAtOldGC();
292 }
293 for (intptr_t i = kNumPredefinedCids; i < top_; i++) {
294 class_heap_stats_table_[i].ResetAtOldGC();
295 }
296 }
297
298
299 void ClassTable::ResetCountersNew() {
300 for (intptr_t i = 0; i < kNumPredefinedCids; i++) {
301 predefined_class_heap_stats_table_[i].ResetAtNewGC();
302 }
303 for (intptr_t i = kNumPredefinedCids; i < top_; i++) {
304 class_heap_stats_table_[i].ResetAtNewGC();
305 }
306 }
307
308
309 void ClassTable::HeapPrintToJSONStream(JSONStream* stream) {
310 Isolate* isolate = Isolate::Current();
311 ASSERT(isolate != NULL);
312 Heap* heap = isolate->heap();
313 ASSERT(heap != NULL);
314 JSONObject obj(stream);
315 obj.AddProperty("type", "HeapProfile");
316 {
317 JSONObject heaps(&obj, "heap");
Ivan Posva 2014/01/17 06:53:16 The heap should print itself here at least as a re
318 {
319 JSONObject space(&heaps, "new");
320 space.AddProperty("collections", heap->Collections(Heap::kNew));
321 space.AddProperty("used", heap->UsedInWords(Heap::kNew) * kWordSize);
322 space.AddProperty("capacity",
323 heap->CapacityInWords(Heap::kNew) * kWordSize);
324 space.AddProperty("time", heap->GCTimeInSeconds(Heap::kNew));
325 }
326 {
327 JSONObject space(&heaps, "old");
328 space.AddProperty("collections", heap->Collections(Heap::kOld));
329 space.AddProperty("used", heap->UsedInWords(Heap::kOld) * kWordSize);
330 space.AddProperty("capacity",
331 heap->CapacityInWords(Heap::kOld) * kWordSize);
332 space.AddProperty("time", heap->GCTimeInSeconds(Heap::kOld));
333 }
334 }
335 {
336 Class& cls = Class::Handle();
337 JSONArray arr(&obj, "members");
338 for (intptr_t i = 1; i < kNumPredefinedCids; i++) {
339 if (!HasValidClassAt(i) || (i == kFreeListElement)) {
340 continue;
341 }
342 cls = At(i);
343 if (!(cls.is_finalized() || cls.is_prefinalized())) {
344 // Not finalized.
345 continue;
346 }
347 if (!CollectInstanceSizesForClass(i)) {
348 predefined_class_heap_stats_table_[i].UpdateSize(cls.instance_size());
349 }
350 predefined_class_heap_stats_table_[i].PrintTOJSONArray(cls, &arr);
351 }
352 for (intptr_t i = kNumPredefinedCids; i < top_; i++) {
353 if (!HasValidClassAt(i)) {
354 continue;
355 }
356 cls = At(i);
357 if (!(cls.is_finalized() || cls.is_prefinalized())) {
358 // Not finalized.
359 continue;
360 }
361 if (!CollectInstanceSizesForClass(i)) {
362 class_heap_stats_table_[i].UpdateSize(cls.instance_size());
363 }
364 class_heap_stats_table_[i].PrintTOJSONArray(cls, &arr);
365 }
366 }
367 }
368
369
370 void ClassTable::UpdateLiveOld(intptr_t cid, intptr_t size) {
371 ClassHeapStats* stats = StatsAt(cid);
372 ASSERT(stats != NULL);
373 ASSERT(size > 0);
374 stats->live_after_gc_old_space++;
375 stats->live_size_after_gc_old_space += size;
376 }
377
378
379 void ClassTable::UpdateLiveNew(intptr_t cid, intptr_t size) {
380 ClassHeapStats* stats = StatsAt(cid);
381 ASSERT(stats != NULL);
382 ASSERT(size > 0);
383 stats->live_after_gc_new_space++;
384 stats->live_size_after_gc_new_space += size;
385 }
386
387
114 } // namespace dart 388 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/class_table.h ('k') | runtime/vm/gc_marker.cc » ('j') | runtime/vm/gc_marker.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698