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 #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 Loading... |
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 bool ClassTable::ShouldUpdateSizeForClassId(intptr_t cid) { |
| 238 return !RawObject::IsVariableSizeClassId(cid); |
| 239 } |
| 240 |
| 241 |
| 242 ClassHeapStats* ClassTable::StatsAt(intptr_t cid) { |
| 243 ASSERT(cid > 0); |
| 244 if (cid < kNumPredefinedCids) { |
| 245 return &predefined_class_heap_stats_table_[cid]; |
| 246 } |
| 247 ASSERT(cid < top_); |
| 248 return &class_heap_stats_table_[cid]; |
| 249 } |
| 250 |
| 251 |
| 252 void ClassTable::ResetCountersOld() { |
| 253 for (intptr_t i = 0; i < kNumPredefinedCids; i++) { |
| 254 predefined_class_heap_stats_table_[i].ResetAtOldGC(); |
| 255 } |
| 256 for (intptr_t i = kNumPredefinedCids; i < top_; i++) { |
| 257 class_heap_stats_table_[i].ResetAtOldGC(); |
| 258 } |
| 259 } |
| 260 |
| 261 |
| 262 void ClassTable::ResetCountersNew() { |
| 263 for (intptr_t i = 0; i < kNumPredefinedCids; i++) { |
| 264 predefined_class_heap_stats_table_[i].ResetAtNewGC(); |
| 265 } |
| 266 for (intptr_t i = kNumPredefinedCids; i < top_; i++) { |
| 267 class_heap_stats_table_[i].ResetAtNewGC(); |
| 268 } |
| 269 } |
| 270 |
| 271 |
| 272 void ClassTable::AllocationProfilePrintToJSONStream(JSONStream* stream) { |
| 273 Isolate* isolate = Isolate::Current(); |
| 274 ASSERT(isolate != NULL); |
| 275 Heap* heap = isolate->heap(); |
| 276 ASSERT(heap != NULL); |
| 277 JSONObject obj(stream); |
| 278 obj.AddProperty("type", "AllocationProfile"); |
| 279 { |
| 280 JSONObject heaps(&obj, "heaps"); |
| 281 { |
| 282 heap->PrintToJSONObject(Heap::kNew, &heaps); |
| 283 } |
| 284 { |
| 285 heap->PrintToJSONObject(Heap::kOld, &heaps); |
| 286 } |
| 287 } |
| 288 { |
| 289 Class& cls = Class::Handle(); |
| 290 JSONArray arr(&obj, "members"); |
| 291 for (intptr_t i = 1; i < kNumPredefinedCids; i++) { |
| 292 if (!HasValidClassAt(i) || (i == kFreeListElement) || (i == kSmiCid)) { |
| 293 continue; |
| 294 } |
| 295 cls = At(i); |
| 296 if (!(cls.is_finalized() || cls.is_prefinalized())) { |
| 297 // Not finalized. |
| 298 continue; |
| 299 } |
| 300 if (ShouldUpdateSizeForClassId(i)) { |
| 301 intptr_t instance_size = cls.instance_size(); |
| 302 predefined_class_heap_stats_table_[i].UpdateSize(instance_size); |
| 303 } |
| 304 predefined_class_heap_stats_table_[i].PrintTOJSONArray(cls, &arr); |
| 305 } |
| 306 for (intptr_t i = kNumPredefinedCids; i < top_; i++) { |
| 307 if (!HasValidClassAt(i)) { |
| 308 continue; |
| 309 } |
| 310 cls = At(i); |
| 311 if (!(cls.is_finalized() || cls.is_prefinalized())) { |
| 312 // Not finalized. |
| 313 continue; |
| 314 } |
| 315 if (ShouldUpdateSizeForClassId(i)) { |
| 316 intptr_t instance_size = cls.instance_size(); |
| 317 class_heap_stats_table_[i].UpdateSize(instance_size); |
| 318 } |
| 319 class_heap_stats_table_[i].PrintTOJSONArray(cls, &arr); |
| 320 } |
| 321 } |
| 322 } |
| 323 |
| 324 |
| 325 void ClassTable::UpdateLiveOld(intptr_t cid, intptr_t size) { |
| 326 ClassHeapStats* stats = StatsAt(cid); |
| 327 ASSERT(stats != NULL); |
| 328 ASSERT(size >= 0); |
| 329 stats->live_after_gc_old_space++; |
| 330 stats->live_size_after_gc_old_space += size; |
| 331 } |
| 332 |
| 333 |
| 334 void ClassTable::UpdateLiveNew(intptr_t cid, intptr_t size) { |
| 335 ClassHeapStats* stats = StatsAt(cid); |
| 336 ASSERT(stats != NULL); |
| 337 ASSERT(size >= 0); |
| 338 stats->live_after_gc_new_space++; |
| 339 stats->live_size_after_gc_new_space += size; |
| 340 } |
| 341 |
| 342 |
114 } // namespace dart | 343 } // namespace dart |
OLD | NEW |