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

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 7 years, 1 month 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/object.h" 8 #include "vm/object.h"
9 #include "vm/raw_object.h" 9 #include "vm/raw_object.h"
10 #include "vm/visitor.h" 10 #include "vm/visitor.h"
11 11
12 namespace dart { 12 namespace dart {
13 13
14 DEFINE_FLAG(bool, print_class_table, false, "Print initial class table."); 14 DEFINE_FLAG(bool, print_class_table, false, "Print initial class table.");
15 15
16 ClassTable::ClassTable() 16 ClassTable::ClassTable()
17 : top_(kNumPredefinedCids), capacity_(0), table_(NULL) { 17 : top_(kNumPredefinedCids), capacity_(0), table_(NULL),
18 class_heap_stats_table_(NULL),
19 predefined_class_heap_stats_table_(NULL) {
18 if (Dart::vm_isolate() == NULL) { 20 if (Dart::vm_isolate() == NULL) {
19 capacity_ = initial_capacity_; 21 capacity_ = initial_capacity_;
20 table_ = reinterpret_cast<RawClass**>( 22 table_ = reinterpret_cast<RawClass**>(
21 calloc(capacity_, sizeof(RawClass*))); // NOLINT 23 calloc(capacity_, sizeof(RawClass*))); // NOLINT
22 } else { 24 } else {
23 // Duplicate the class table from the VM isolate. 25 // Duplicate the class table from the VM isolate.
24 ClassTable* vm_class_table = Dart::vm_isolate()->class_table(); 26 ClassTable* vm_class_table = Dart::vm_isolate()->class_table();
25 capacity_ = vm_class_table->capacity_; 27 capacity_ = vm_class_table->capacity_;
26 table_ = reinterpret_cast<RawClass**>( 28 table_ = reinterpret_cast<RawClass**>(
27 calloc(capacity_, sizeof(RawClass*))); // NOLINT 29 calloc(capacity_, sizeof(RawClass*))); // NOLINT
28 for (intptr_t i = kObjectCid; i < kInstanceCid; i++) { 30 for (intptr_t i = kObjectCid; i < kInstanceCid; i++) {
29 table_[i] = vm_class_table->At(i); 31 table_[i] = vm_class_table->At(i);
30 } 32 }
31 table_[kFreeListElement] = vm_class_table->At(kFreeListElement); 33 table_[kFreeListElement] = vm_class_table->At(kFreeListElement);
32 table_[kDynamicCid] = vm_class_table->At(kDynamicCid); 34 table_[kDynamicCid] = vm_class_table->At(kDynamicCid);
33 table_[kVoidCid] = vm_class_table->At(kVoidCid); 35 table_[kVoidCid] = vm_class_table->At(kVoidCid);
36 predefined_class_heap_stats_table_ = reinterpret_cast<ClassHeapStats*>(
Ivan Posva 2013/12/12 13:53:24 Why is this allocated twice?
Cutch 2013/12/13 01:31:09 The predefined class stats table is allocated once
37 calloc(kNumPredefinedCids, sizeof(ClassHeapStats))); // NOLINT
38 class_heap_stats_table_ = reinterpret_cast<ClassHeapStats*>(
39 calloc(capacity_, sizeof(ClassHeapStats))); // NOLINT
40 for (intptr_t i = 0; i < capacity_; i++) {
41 class_heap_stats_table_[i].Initialize();
42 }
43 }
44 predefined_class_heap_stats_table_ = reinterpret_cast<ClassHeapStats*>(
45 calloc(kNumPredefinedCids, sizeof(ClassHeapStats))); // NOLINT
46 for (intptr_t i = 0; i < kNumPredefinedCids; i++) {
47 predefined_class_heap_stats_table_[i].Initialize();
34 } 48 }
35 } 49 }
36 50
37 51
38 ClassTable::~ClassTable() { 52 ClassTable::~ClassTable() {
39 free(table_); 53 free(table_);
54 free(predefined_class_heap_stats_table_);
55 free(class_heap_stats_table_);
40 } 56 }
41 57
42 58
43 void ClassTable::Register(const Class& cls) { 59 void ClassTable::Register(const Class& cls) {
44 intptr_t index = cls.id(); 60 intptr_t index = cls.id();
45 if (index != kIllegalCid) { 61 if (index != kIllegalCid) {
46 ASSERT(index > 0); 62 ASSERT(index > 0);
47 ASSERT(index < kNumPredefinedCids); 63 ASSERT(index < kNumPredefinedCids);
48 ASSERT(table_[index] == 0); 64 ASSERT(table_[index] == 0);
49 ASSERT(index < capacity_); 65 ASSERT(index < capacity_);
50 table_[index] = cls.raw(); 66 table_[index] = cls.raw();
51 // Add the vtable for this predefined class into the static vtable registry 67 // Add the vtable for this predefined class into the static vtable registry
52 // if it has not been setup yet. 68 // if it has not been setup yet.
53 cpp_vtable cls_vtable = cls.handle_vtable(); 69 cpp_vtable cls_vtable = cls.handle_vtable();
54 cpp_vtable table_entry = Object::builtin_vtables_[index]; 70 cpp_vtable table_entry = Object::builtin_vtables_[index];
55 ASSERT((table_entry == 0) || (table_entry == cls_vtable)); 71 ASSERT((table_entry == 0) || (table_entry == cls_vtable));
56 if (table_entry == 0) { 72 if (table_entry == 0) {
57 Object::builtin_vtables_[index] = cls_vtable; 73 Object::builtin_vtables_[index] = cls_vtable;
58 } 74 }
59 } else { 75 } else {
60 if (top_ == capacity_) { 76 if (top_ == capacity_) {
61 // Grow the capacity of the class table. 77 // Grow the capacity of the class table.
62 intptr_t new_capacity = capacity_ + capacity_increment_; 78 intptr_t new_capacity = capacity_ + capacity_increment_;
63 RawClass** new_table = reinterpret_cast<RawClass**>( 79 RawClass** new_table = reinterpret_cast<RawClass**>(
64 realloc(table_, new_capacity * sizeof(RawClass*))); // NOLINT 80 realloc(table_, new_capacity * sizeof(RawClass*))); // NOLINT
81 ClassHeapStats* new_stats_table = reinterpret_cast<ClassHeapStats*>(
82 realloc(class_heap_stats_table_,
83 new_capacity * sizeof(ClassHeapStats))); // NOLINT
65 for (intptr_t i = capacity_; i < new_capacity; i++) { 84 for (intptr_t i = capacity_; i < new_capacity; i++) {
66 new_table[i] = NULL; 85 new_table[i] = NULL;
86 new_stats_table[i].Initialize();
67 } 87 }
68 capacity_ = new_capacity; 88 capacity_ = new_capacity;
69 table_ = new_table; 89 table_ = new_table;
90 class_heap_stats_table_ = new_stats_table;
70 } 91 }
71 ASSERT(top_ < capacity_); 92 ASSERT(top_ < capacity_);
72 cls.set_id(top_); 93 cls.set_id(top_);
73 table_[top_] = cls.raw(); 94 table_[top_] = cls.raw();
74 top_++; // Increment next index. 95 top_++; // Increment next index.
75 } 96 }
76 } 97 }
77 98
78 99
79 void ClassTable::VisitObjectPointers(ObjectPointerVisitor* visitor) { 100 void ClassTable::VisitObjectPointers(ObjectPointerVisitor* visitor) {
(...skipping 24 matching lines...) Expand all
104 JSONArray members(&jsobj, "members"); 125 JSONArray members(&jsobj, "members");
105 for (intptr_t i = 1; i < top_; i++) { 126 for (intptr_t i = 1; i < top_; i++) {
106 if (HasValidClassAt(i)) { 127 if (HasValidClassAt(i)) {
107 cls = At(i); 128 cls = At(i);
108 members.AddValue(cls); 129 members.AddValue(cls);
109 } 130 }
110 } 131 }
111 } 132 }
112 } 133 }
113 134
135
136 void ClassHeapStats::Initialize() {
137 live_count_old_space = 0;
138 live_count_new_space = 0;
139 live_size_old_space = 0;
140 live_size_new_space = 0;
141 new_count_since_gc_new_space = 0;
142 new_count_since_gc_old_space = 0;
143 new_size_since_gc_new_space = 0;
144 new_size_since_gc_old_space = 0;
145 }
146
147
148 void ClassHeapStats::ResetAtGC() {
149 live_count_old_space = 0;
150 live_count_new_space = 0;
151 live_size_old_space = 0;
152 live_size_new_space = 0;
153 new_count_since_gc_new_space = 0;
154 new_count_since_gc_old_space = 0;
155 new_size_since_gc_new_space = 0;
156 new_size_since_gc_old_space = 0;
157 }
158
159
160 void ClassTable::ReportAllocationNewSpace(intptr_t cid, intptr_t size) {
161 ClassHeapStats* stats = FindClassHeapStats(cid);
162 ASSERT(stats != NULL);
163 ASSERT(size != 0);
164 stats->new_count_since_gc_new_space++;
165 if (CollectInstanceSizesForClass(cid)) {
Ivan Posva 2013/12/12 13:53:24 How about avoiding the check and just updating the
Cutch 2013/12/13 01:31:09 Done.
166 stats->new_size_since_gc_new_space += size;
167 }
168 }
169
170
171 void ClassTable::ReportAllocationOldSpace(intptr_t cid, intptr_t size) {
172 ClassHeapStats* stats = FindClassHeapStats(cid);
173 ASSERT(stats != NULL);
174 ASSERT(size != 0);
175 stats->new_count_since_gc_old_space++;
176 if (CollectInstanceSizesForClass(cid)) {
Ivan Posva 2013/12/12 13:53:24 ditto
Cutch 2013/12/13 01:31:09 Done.
177 stats->new_size_since_gc_old_space += size;
178 }
179 }
180
181
182 // #define DEBUG_PRINT
Ivan Posva 2013/12/12 13:53:24 Please make this a command line flag or remove the
Cutch 2013/12/13 01:31:09 This will be removed before committing. It's just
183
184 #if defined(DEBUG_PRINT)
185 static void PrintClassHeapStats(intptr_t cid, const ClassHeapStats& stat) {
186 int new_new = static_cast<int>(stat.new_count_since_gc_new_space);
187 int new_old = static_cast<int>(stat.new_count_since_gc_old_space);
188 int b_new = static_cast<int>(stat.new_size_since_gc_new_space);
189 int b_old = static_cast<int>(stat.new_size_since_gc_old_space);
190 printf("%d (%d %d) [%d %d]\n", static_cast<int>(cid),
191 new_new, b_new, new_old, b_old);
192 }
193 #endif
194
195
196 void ClassTable::Collect() {
Ivan Posva 2013/12/12 13:53:24 How about only exposing ResetCounters()?
Cutch 2013/12/13 01:31:09 Done.
197 Isolate* isolate = Isolate::Current();
198 ASSERT(isolate != NULL);
199 #if defined(DEBUG_PRINT)
200 for (intptr_t i = 0; i < kNumPredefinedCids; i++) {
201 const ClassHeapStats& stat = predefined_class_heap_stats_table_[i];
202 if ((stat.new_count_since_gc_new_space > 0) ||
203 (stat.new_count_since_gc_old_space > 0)) {
204 PrintClassHeapStats(i, stat);
205 }
206 }
207 for (intptr_t i = kNumPredefinedCids; i < top_; i++) {
208 const ClassHeapStats& stat = class_heap_stats_table_[i];
209 if ((stat.new_count_since_gc_new_space > 0) ||
210 (stat.new_count_since_gc_old_space > 0)) {
211 PrintClassHeapStats(i, stat);
212 }
213 }
214 #endif
215 ResetCounters();
216 }
217
218
219 bool ClassTable::CollectInstanceSizesForClass(intptr_t cid) {
220 // We only collect size information for classes which do not have
221 // fixed lengths.
222 if ((cid == kArrayCid) ||
223 RawObject::IsOneByteStringClassId(cid) ||
224 RawObject::IsTwoByteStringClassId(cid) ||
225 RawObject::IsTypedDataClassId(cid) ||
226 (cid == kContextCid)) {
227 return true;
228 }
229 return false;
230 }
231
232
233 ClassHeapStats* ClassTable::FindClassHeapStats(intptr_t cid) {
Ivan Posva 2013/12/12 13:53:24 StatsAt(intptr_t cid)
Cutch 2013/12/13 01:31:09 Done.
234 ASSERT(cid > 0);
235 if (cid < kNumPredefinedCids) {
236 return &predefined_class_heap_stats_table_[cid];
237 }
238 ASSERT(cid < top_);
239 return &class_heap_stats_table_[cid];
240 }
241
242
243 void ClassTable::ResetCounters() {
244 for (intptr_t i = 0; i < kNumPredefinedCids; i++) {
245 predefined_class_heap_stats_table_[i].ResetAtGC();
246 }
247 for (intptr_t i = kNumPredefinedCids; i < top_; i++) {
248 class_heap_stats_table_[i].ResetAtGC();
249 }
250 }
251
252
253 void ClassTable::ReportLiveOldSpace(intptr_t cid, intptr_t size) {
254 ClassHeapStats* stats = FindClassHeapStats(cid);
255 ASSERT(stats != NULL);
256 ASSERT(size != 0);
257 stats->live_count_old_space++;
258 stats->live_size_old_space += size;
259 }
260
261
262 void ClassTable::ReportLiveNewSpace(intptr_t cid, intptr_t size) {
263 ClassHeapStats* stats = FindClassHeapStats(cid);
264 ASSERT(stats != NULL);
265 ASSERT(size != 0);
266 stats->live_count_new_space++;
267 stats->live_size_new_space += size;
268 }
269
270
114 } // namespace dart 271 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698