Chromium Code Reviews| 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/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 Loading... | |
| 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 |
| OLD | NEW |