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/growable_array.h" | |
| 8 #include "vm/heap.h" | 9 #include "vm/heap.h" |
| 9 #include "vm/object.h" | 10 #include "vm/object.h" |
| 10 #include "vm/raw_object.h" | 11 #include "vm/raw_object.h" |
| 11 #include "vm/visitor.h" | 12 #include "vm/visitor.h" |
| 12 | 13 |
| 13 namespace dart { | 14 namespace dart { |
| 14 | 15 |
| 15 DEFINE_FLAG(bool, print_class_table, false, "Print initial class table."); | 16 DEFINE_FLAG(bool, print_class_table, false, "Print initial class table."); |
| 16 | 17 |
| 17 ClassTable::ClassTable() | 18 ClassTable::ClassTable() |
| 18 : top_(kNumPredefinedCids), capacity_(0), table_(NULL), | 19 : top_(kNumPredefinedCids), capacity_(0), table_(NULL), |
| 20 old_tables_(new MallocGrowableArray<RawClass**>()), | |
|
Ivan Posva
2015/01/20 22:46:45
Wondering why you decided on MallocGrowableArray v
koda
2015/01/21 14:36:09
1. To avoid yet another ad hoc linked list impleme
| |
| 19 class_heap_stats_table_(NULL), | 21 class_heap_stats_table_(NULL), |
| 20 predefined_class_heap_stats_table_(NULL) { | 22 predefined_class_heap_stats_table_(NULL) { |
| 21 if (Dart::vm_isolate() == NULL) { | 23 if (Dart::vm_isolate() == NULL) { |
| 22 capacity_ = initial_capacity_; | 24 capacity_ = initial_capacity_; |
| 23 table_ = reinterpret_cast<RawClass**>( | 25 table_ = reinterpret_cast<RawClass**>( |
| 24 calloc(capacity_, sizeof(RawClass*))); // NOLINT | 26 calloc(capacity_, sizeof(RawClass*))); // NOLINT |
| 25 } else { | 27 } else { |
| 26 // Duplicate the class table from the VM isolate. | 28 // Duplicate the class table from the VM isolate. |
| 27 ClassTable* vm_class_table = Dart::vm_isolate()->class_table(); | 29 ClassTable* vm_class_table = Dart::vm_isolate()->class_table(); |
| 28 capacity_ = vm_class_table->capacity_; | 30 capacity_ = vm_class_table->capacity_; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 44 calloc(kNumPredefinedCids, sizeof(ClassHeapStats))); // NOLINT | 46 calloc(kNumPredefinedCids, sizeof(ClassHeapStats))); // NOLINT |
| 45 for (intptr_t i = 0; i < kNumPredefinedCids; i++) { | 47 for (intptr_t i = 0; i < kNumPredefinedCids; i++) { |
| 46 predefined_class_heap_stats_table_[i].Initialize(); | 48 predefined_class_heap_stats_table_[i].Initialize(); |
| 47 } | 49 } |
| 48 } | 50 } |
| 49 | 51 |
| 50 | 52 |
| 51 ClassTable::ClassTable(ClassTable* original) | 53 ClassTable::ClassTable(ClassTable* original) |
| 52 : top_(original->top_), | 54 : top_(original->top_), |
| 53 capacity_(original->top_), | 55 capacity_(original->top_), |
| 54 table_(reinterpret_cast<RawClass**>( | 56 table_(original->table_), |
| 55 calloc(original->top_, sizeof(RawClass*)))), | 57 old_tables_(NULL), |
| 56 class_heap_stats_table_(NULL), | 58 class_heap_stats_table_(NULL), |
| 57 predefined_class_heap_stats_table_(NULL) { | 59 predefined_class_heap_stats_table_(NULL) { |
| 58 for (intptr_t i = 1; i < top_; i++) { | 60 } |
| 59 table_[i] = original->At(i); | 61 |
| 62 | |
| 63 ClassTable::~ClassTable() { | |
| 64 if (old_tables_ != NULL) { | |
| 65 FreeOldTables(); | |
| 66 delete old_tables_; | |
| 67 free(table_); | |
| 68 free(predefined_class_heap_stats_table_); | |
| 69 free(class_heap_stats_table_); | |
| 70 } else { | |
| 71 // This instance was a shallow copy. It doesn't own any memory. | |
| 72 ASSERT(predefined_class_heap_stats_table_ == NULL); | |
| 73 ASSERT(class_heap_stats_table_ == NULL); | |
| 60 } | 74 } |
| 61 } | 75 } |
| 62 | 76 |
| 63 | 77 |
| 64 ClassTable::~ClassTable() { | 78 void ClassTable::FreeOldTables() { |
| 65 free(table_); | 79 while (old_tables_->length() > 0) { |
| 66 free(predefined_class_heap_stats_table_); | 80 free(old_tables_->RemoveLast()); |
| 67 free(class_heap_stats_table_); | 81 } |
| 68 } | 82 } |
| 69 | 83 |
| 70 | 84 |
| 71 void ClassTable::Register(const Class& cls) { | 85 void ClassTable::Register(const Class& cls) { |
| 72 intptr_t index = cls.id(); | 86 intptr_t index = cls.id(); |
| 73 if (index != kIllegalCid) { | 87 if (index != kIllegalCid) { |
| 74 ASSERT(index > 0); | 88 ASSERT(index > 0); |
| 75 ASSERT(index < kNumPredefinedCids); | 89 ASSERT(index < kNumPredefinedCids); |
| 76 ASSERT(table_[index] == 0); | 90 ASSERT(table_[index] == 0); |
| 77 ASSERT(index < capacity_); | 91 ASSERT(index < capacity_); |
| 78 table_[index] = cls.raw(); | 92 table_[index] = cls.raw(); |
| 79 // Add the vtable for this predefined class into the static vtable registry | 93 // Add the vtable for this predefined class into the static vtable registry |
| 80 // if it has not been setup yet. | 94 // if it has not been setup yet. |
| 81 cpp_vtable cls_vtable = cls.handle_vtable(); | 95 cpp_vtable cls_vtable = cls.handle_vtable(); |
| 82 cpp_vtable table_entry = Object::builtin_vtables_[index]; | 96 cpp_vtable table_entry = Object::builtin_vtables_[index]; |
| 83 ASSERT((table_entry == 0) || (table_entry == cls_vtable)); | 97 ASSERT((table_entry == 0) || (table_entry == cls_vtable)); |
| 84 if (table_entry == 0) { | 98 if (table_entry == 0) { |
| 85 Object::builtin_vtables_[index] = cls_vtable; | 99 Object::builtin_vtables_[index] = cls_vtable; |
| 86 } | 100 } |
| 87 } else { | 101 } else { |
| 88 if (top_ == capacity_) { | 102 if (top_ == capacity_) { |
| 89 // Grow the capacity of the class table. | 103 // Grow the capacity of the class table. |
| 104 // TODO(koda): Add ClassTable::Grow to share code. | |
| 90 intptr_t new_capacity = capacity_ + capacity_increment_; | 105 intptr_t new_capacity = capacity_ + capacity_increment_; |
| 91 RawClass** new_table = reinterpret_cast<RawClass**>( | 106 RawClass** new_table = reinterpret_cast<RawClass**>( |
| 92 realloc(table_, new_capacity * sizeof(RawClass*))); // NOLINT | 107 malloc(new_capacity * sizeof(RawClass*))); // NOLINT |
| 108 memmove(new_table, table_, capacity_ * sizeof(RawClass*)); | |
| 93 ClassHeapStats* new_stats_table = reinterpret_cast<ClassHeapStats*>( | 109 ClassHeapStats* new_stats_table = reinterpret_cast<ClassHeapStats*>( |
| 94 realloc(class_heap_stats_table_, | 110 realloc(class_heap_stats_table_, |
| 95 new_capacity * sizeof(ClassHeapStats))); // NOLINT | 111 new_capacity * sizeof(ClassHeapStats))); // NOLINT |
| 96 for (intptr_t i = capacity_; i < new_capacity; i++) { | 112 for (intptr_t i = capacity_; i < new_capacity; i++) { |
| 97 new_table[i] = NULL; | 113 new_table[i] = NULL; |
| 98 new_stats_table[i].Initialize(); | 114 new_stats_table[i].Initialize(); |
| 99 } | 115 } |
| 100 capacity_ = new_capacity; | 116 capacity_ = new_capacity; |
| 101 table_ = new_table; | 117 old_tables_->Add(table_); |
| 118 table_ = new_table; // TODO(koda): This should use atomics. | |
| 102 class_heap_stats_table_ = new_stats_table; | 119 class_heap_stats_table_ = new_stats_table; |
| 103 } | 120 } |
| 104 ASSERT(top_ < capacity_); | 121 ASSERT(top_ < capacity_); |
| 105 if (!Class::is_valid_id(top_)) { | 122 if (!Class::is_valid_id(top_)) { |
| 106 FATAL1("Fatal error in ClassTable::Register: invalid index %" Pd "\n", | 123 FATAL1("Fatal error in ClassTable::Register: invalid index %" Pd "\n", |
| 107 top_); | 124 top_); |
| 108 } | 125 } |
| 109 cls.set_id(top_); | 126 cls.set_id(top_); |
| 110 table_[top_] = cls.raw(); | 127 table_[top_] = cls.raw(); |
| 111 top_++; // Increment next index. | 128 top_++; // Increment next index. |
| 112 } | 129 } |
| 113 } | 130 } |
| 114 | 131 |
| 115 | 132 |
| 116 void ClassTable::RegisterAt(intptr_t index, const Class& cls) { | 133 void ClassTable::RegisterAt(intptr_t index, const Class& cls) { |
| 117 ASSERT(index != kIllegalCid); | 134 ASSERT(index != kIllegalCid); |
| 118 ASSERT(index >= kNumPredefinedCids); | 135 ASSERT(index >= kNumPredefinedCids); |
| 119 if (index >= capacity_) { | 136 if (index >= capacity_) { |
| 120 // Grow the capacity of the class table. | 137 // Grow the capacity of the class table. |
| 138 // TODO(koda): Add ClassTable::Grow to share code. | |
| 121 intptr_t new_capacity = index + capacity_increment_; | 139 intptr_t new_capacity = index + capacity_increment_; |
| 122 if (!Class::is_valid_id(index) || new_capacity < capacity_) { | 140 if (!Class::is_valid_id(index) || new_capacity < capacity_) { |
| 123 FATAL1("Fatal error in ClassTable::Register: invalid index %" Pd "\n", | 141 FATAL1("Fatal error in ClassTable::Register: invalid index %" Pd "\n", |
| 124 index); | 142 index); |
| 125 } | 143 } |
| 126 RawClass** new_table = reinterpret_cast<RawClass**>( | 144 RawClass** new_table = reinterpret_cast<RawClass**>( |
| 127 realloc(table_, new_capacity * sizeof(RawClass*))); // NOLINT | 145 malloc(new_capacity * sizeof(RawClass*))); // NOLINT |
| 146 memmove(new_table, table_, capacity_ * sizeof(RawClass*)); | |
| 128 ClassHeapStats* new_stats_table = reinterpret_cast<ClassHeapStats*>( | 147 ClassHeapStats* new_stats_table = reinterpret_cast<ClassHeapStats*>( |
| 129 realloc(class_heap_stats_table_, | 148 realloc(class_heap_stats_table_, |
| 130 new_capacity * sizeof(ClassHeapStats))); // NOLINT | 149 new_capacity * sizeof(ClassHeapStats))); // NOLINT |
| 131 for (intptr_t i = capacity_; i < new_capacity; i++) { | 150 for (intptr_t i = capacity_; i < new_capacity; i++) { |
| 132 new_table[i] = NULL; | 151 new_table[i] = NULL; |
| 133 new_stats_table[i].Initialize(); | 152 new_stats_table[i].Initialize(); |
| 134 } | 153 } |
| 135 capacity_ = new_capacity; | 154 capacity_ = new_capacity; |
| 136 table_ = new_table; | 155 old_tables_->Add(table_); |
| 156 table_ = new_table; // TODO(koda): This should use atomics. | |
| 137 class_heap_stats_table_ = new_stats_table; | 157 class_heap_stats_table_ = new_stats_table; |
| 138 ASSERT(capacity_increment_ >= 1); | 158 ASSERT(capacity_increment_ >= 1); |
| 139 } | 159 } |
| 140 ASSERT(table_[index] == 0); | 160 ASSERT(table_[index] == 0); |
| 141 cls.set_id(index); | 161 cls.set_id(index); |
| 142 table_[index] = cls.raw(); | 162 table_[index] = cls.raw(); |
| 143 if (index >= top_) { | 163 if (index >= top_) { |
| 144 top_ = index + 1; | 164 top_ = index + 1; |
| 145 } | 165 } |
| 146 } | 166 } |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 452 | 472 |
| 453 void ClassTable::UpdateLiveNew(intptr_t cid, intptr_t size) { | 473 void ClassTable::UpdateLiveNew(intptr_t cid, intptr_t size) { |
| 454 ClassHeapStats* stats = PreliminaryStatsAt(cid); | 474 ClassHeapStats* stats = PreliminaryStatsAt(cid); |
| 455 ASSERT(stats != NULL); | 475 ASSERT(stats != NULL); |
| 456 ASSERT(size >= 0); | 476 ASSERT(size >= 0); |
| 457 stats->post_gc.AddNew(size); | 477 stats->post_gc.AddNew(size); |
| 458 } | 478 } |
| 459 | 479 |
| 460 | 480 |
| 461 } // namespace dart | 481 } // namespace dart |
| OLD | NEW |