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
2014/01/14 22:54:23
Duplicate allocation here.
Cutch
2014/01/15 19:49:49
Done.
| |
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 allocated_before_gc_old_space = 0; | |
138 allocated_before_gc_new_space = 0; | |
139 allocated_size_before_gc_old_space = 0; | |
140 allocated_size_before_gc_new_space = 0; | |
141 live_after_gc_old_space = 0; | |
142 live_after_gc_new_space = 0; | |
143 live_size_after_gc_old_space = 0; | |
144 live_size_after_gc_new_space = 0; | |
145 allocated_since_gc_new_space = 0; | |
146 allocated_since_gc_old_space = 0; | |
147 allocated_size_since_gc_new_space = 0; | |
148 allocated_size_since_gc_old_space = 0; | |
149 } | |
150 | |
151 | |
152 void ClassHeapStats::ResetAtNewGC() { | |
153 allocated_before_gc_new_space = live_after_gc_new_space + | |
154 allocated_since_gc_new_space; | |
155 allocated_size_before_gc_new_space = live_size_after_gc_new_space + | |
156 allocated_size_since_gc_new_space; | |
157 live_after_gc_new_space = 0; | |
158 live_size_after_gc_new_space = 0; | |
159 allocated_since_gc_new_space = 0; | |
160 allocated_size_since_gc_new_space = 0; | |
161 } | |
162 | |
163 | |
164 void ClassHeapStats::ResetAtOldGC() { | |
165 allocated_before_gc_old_space = live_after_gc_old_space + | |
166 allocated_since_gc_old_space; | |
167 allocated_size_before_gc_old_space = live_size_after_gc_old_space + | |
168 allocated_size_since_gc_old_space; | |
169 live_after_gc_old_space = 0; | |
170 live_size_after_gc_old_space = 0; | |
171 allocated_since_gc_old_space = 0; | |
172 allocated_size_since_gc_old_space = 0; | |
173 } | |
174 | |
175 | |
176 void ClassTable::UpdateAllocatedNew(intptr_t cid, intptr_t size) { | |
177 ClassHeapStats* stats = StatsAt(cid); | |
178 ASSERT(stats != NULL); | |
179 ASSERT(size != 0); | |
180 stats->allocated_since_gc_new_space++; | |
181 stats->allocated_size_since_gc_new_space += size; | |
182 } | |
183 | |
184 | |
185 void ClassTable::UpdateAllocatedOld(intptr_t cid, intptr_t size) { | |
186 ClassHeapStats* stats = StatsAt(cid); | |
187 ASSERT(stats != NULL); | |
188 ASSERT(size != 0); | |
189 stats->allocated_since_gc_old_space++; | |
190 stats->allocated_size_since_gc_old_space += size; | |
191 } | |
192 | |
193 | |
194 // #define DEBUG_PRINT | |
195 | |
196 #if defined(DEBUG_PRINT) | |
197 static void PrintClassHeapStats(intptr_t cid, const ClassHeapStats& stat) { | |
198 int new_new = static_cast<int>(stat.new_count_since_gc_new_space); | |
199 int new_old = static_cast<int>(stat.new_count_since_gc_old_space); | |
200 int b_new = static_cast<int>(stat.new_size_since_gc_new_space); | |
201 int b_old = static_cast<int>(stat.new_size_since_gc_old_space); | |
202 printf("%d (%d %d) [%d %d]\n", static_cast<int>(cid), | |
203 new_new, b_new, new_old, b_old); | |
204 } | |
205 #endif | |
206 | |
207 | |
208 bool ClassTable::CollectInstanceSizesForClass(intptr_t cid) { | |
209 // We only collect size information for classes which do not have | |
210 // fixed lengths. | |
211 if ((cid == kArrayCid) || | |
212 RawObject::IsOneByteStringClassId(cid) || | |
213 RawObject::IsTwoByteStringClassId(cid) || | |
214 RawObject::IsTypedDataClassId(cid) || | |
215 (cid == kContextCid)) { | |
216 return true; | |
217 } | |
218 return false; | |
219 } | |
220 | |
221 | |
222 ClassHeapStats* ClassTable::StatsAt(intptr_t cid) { | |
223 ASSERT(cid > 0); | |
224 if (cid < kNumPredefinedCids) { | |
225 return &predefined_class_heap_stats_table_[cid]; | |
226 } | |
227 ASSERT(cid < top_); | |
228 return &class_heap_stats_table_[cid]; | |
229 } | |
230 | |
231 | |
232 void ClassTable::ResetCountersOld() { | |
233 for (intptr_t i = 0; i < kNumPredefinedCids; i++) { | |
234 predefined_class_heap_stats_table_[i].ResetAtOldGC(); | |
235 } | |
236 for (intptr_t i = kNumPredefinedCids; i < top_; i++) { | |
237 class_heap_stats_table_[i].ResetAtOldGC(); | |
238 } | |
239 } | |
240 | |
241 | |
242 void ClassTable::ResetCountersNew() { | |
243 for (intptr_t i = 0; i < kNumPredefinedCids; i++) { | |
244 predefined_class_heap_stats_table_[i].ResetAtNewGC(); | |
245 } | |
246 for (intptr_t i = kNumPredefinedCids; i < top_; i++) { | |
247 class_heap_stats_table_[i].ResetAtNewGC(); | |
248 } | |
249 } | |
250 | |
251 | |
252 void ClassTable::UpdateLiveOld(intptr_t cid, intptr_t size) { | |
253 ClassHeapStats* stats = StatsAt(cid); | |
254 ASSERT(stats != NULL); | |
255 ASSERT(size != 0); | |
256 stats->live_after_gc_old_space++; | |
257 stats->live_size_after_gc_old_space += size; | |
258 } | |
259 | |
260 | |
261 void ClassTable::UpdateLiveNew(intptr_t cid, intptr_t size) { | |
262 ClassHeapStats* stats = StatsAt(cid); | |
263 ASSERT(stats != NULL); | |
264 ASSERT(size != 0); | |
265 stats->live_after_gc_new_space++; | |
266 stats->live_size_after_gc_new_space += size; | |
267 } | |
268 | |
269 | |
114 } // namespace dart | 270 } // namespace dart |
OLD | NEW |