OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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/object_graph.h" | 5 #include "vm/object_graph.h" |
6 | 6 |
7 #include "vm/dart.h" | 7 #include "vm/dart.h" |
8 #include "vm/growable_array.h" | 8 #include "vm/growable_array.h" |
9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
10 #include "vm/object.h" | 10 #include "vm/object.h" |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 } | 87 } |
88 } | 88 } |
89 return kNoParent; | 89 return kNoParent; |
90 } | 90 } |
91 | 91 |
92 GrowableArray<Node> data_; | 92 GrowableArray<Node> data_; |
93 friend class StackIterator; | 93 friend class StackIterator; |
94 DISALLOW_COPY_AND_ASSIGN(Stack); | 94 DISALLOW_COPY_AND_ASSIGN(Stack); |
95 }; | 95 }; |
96 | 96 |
97 | |
98 RawObject** const ObjectGraph::Stack::kSentinel = NULL; | 97 RawObject** const ObjectGraph::Stack::kSentinel = NULL; |
99 | 98 |
100 | |
101 RawObject* ObjectGraph::StackIterator::Get() const { | 99 RawObject* ObjectGraph::StackIterator::Get() const { |
102 return stack_->data_[index_].obj; | 100 return stack_->data_[index_].obj; |
103 } | 101 } |
104 | 102 |
105 | |
106 bool ObjectGraph::StackIterator::MoveToParent() { | 103 bool ObjectGraph::StackIterator::MoveToParent() { |
107 intptr_t parent = stack_->Parent(index_); | 104 intptr_t parent = stack_->Parent(index_); |
108 if (parent == Stack::kNoParent) { | 105 if (parent == Stack::kNoParent) { |
109 return false; | 106 return false; |
110 } else { | 107 } else { |
111 index_ = parent; | 108 index_ = parent; |
112 return true; | 109 return true; |
113 } | 110 } |
114 } | 111 } |
115 | 112 |
116 | |
117 intptr_t ObjectGraph::StackIterator::OffsetFromParentInWords() const { | 113 intptr_t ObjectGraph::StackIterator::OffsetFromParentInWords() const { |
118 intptr_t parent_index = stack_->Parent(index_); | 114 intptr_t parent_index = stack_->Parent(index_); |
119 if (parent_index == Stack::kNoParent) { | 115 if (parent_index == Stack::kNoParent) { |
120 return -1; | 116 return -1; |
121 } | 117 } |
122 Stack::Node parent = stack_->data_[parent_index]; | 118 Stack::Node parent = stack_->data_[parent_index]; |
123 uword parent_start = RawObject::ToAddr(parent.obj); | 119 uword parent_start = RawObject::ToAddr(parent.obj); |
124 Stack::Node child = stack_->data_[index_]; | 120 Stack::Node child = stack_->data_[index_]; |
125 ASSERT(child.obj == *child.ptr); | 121 ASSERT(child.obj == *child.ptr); |
126 uword child_ptr_addr = reinterpret_cast<uword>(child.ptr); | 122 uword child_ptr_addr = reinterpret_cast<uword>(child.ptr); |
127 intptr_t offset = child_ptr_addr - parent_start; | 123 intptr_t offset = child_ptr_addr - parent_start; |
128 if (offset > 0 && offset < parent.obj->Size()) { | 124 if (offset > 0 && offset < parent.obj->Size()) { |
129 ASSERT(Utils::IsAligned(offset, kWordSize)); | 125 ASSERT(Utils::IsAligned(offset, kWordSize)); |
130 return offset >> kWordSizeLog2; | 126 return offset >> kWordSizeLog2; |
131 } else { | 127 } else { |
132 // Some internal VM objects visit pointers not contained within the parent. | 128 // Some internal VM objects visit pointers not contained within the parent. |
133 // For instance, RawCode::VisitCodePointers visits pointers in instructions. | 129 // For instance, RawCode::VisitCodePointers visits pointers in instructions. |
134 ASSERT(!parent.obj->IsDartInstance()); | 130 ASSERT(!parent.obj->IsDartInstance()); |
135 return -1; | 131 return -1; |
136 } | 132 } |
137 } | 133 } |
138 | 134 |
139 | |
140 class Unmarker : public ObjectVisitor { | 135 class Unmarker : public ObjectVisitor { |
141 public: | 136 public: |
142 Unmarker() {} | 137 Unmarker() {} |
143 | 138 |
144 void VisitObject(RawObject* obj) { | 139 void VisitObject(RawObject* obj) { |
145 if (obj->IsMarked()) { | 140 if (obj->IsMarked()) { |
146 obj->ClearMarkBit(); | 141 obj->ClearMarkBit(); |
147 } | 142 } |
148 } | 143 } |
149 | 144 |
150 static void UnmarkAll(Isolate* isolate) { | 145 static void UnmarkAll(Isolate* isolate) { |
151 Unmarker unmarker; | 146 Unmarker unmarker; |
152 isolate->heap()->VisitObjectsNoImagePages(&unmarker); | 147 isolate->heap()->VisitObjectsNoImagePages(&unmarker); |
153 } | 148 } |
154 | 149 |
155 private: | 150 private: |
156 DISALLOW_COPY_AND_ASSIGN(Unmarker); | 151 DISALLOW_COPY_AND_ASSIGN(Unmarker); |
157 }; | 152 }; |
158 | 153 |
159 | |
160 ObjectGraph::ObjectGraph(Thread* thread) : StackResource(thread) { | 154 ObjectGraph::ObjectGraph(Thread* thread) : StackResource(thread) { |
161 // The VM isolate has all its objects pre-marked, so iterating over it | 155 // The VM isolate has all its objects pre-marked, so iterating over it |
162 // would be a no-op. | 156 // would be a no-op. |
163 ASSERT(thread->isolate() != Dart::vm_isolate()); | 157 ASSERT(thread->isolate() != Dart::vm_isolate()); |
164 } | 158 } |
165 | 159 |
166 | |
167 ObjectGraph::~ObjectGraph() {} | 160 ObjectGraph::~ObjectGraph() {} |
168 | 161 |
169 | |
170 void ObjectGraph::IterateObjects(ObjectGraph::Visitor* visitor) { | 162 void ObjectGraph::IterateObjects(ObjectGraph::Visitor* visitor) { |
171 NoSafepointScope no_safepoint_scope_; | 163 NoSafepointScope no_safepoint_scope_; |
172 Stack stack(isolate()); | 164 Stack stack(isolate()); |
173 isolate()->VisitObjectPointers(&stack, false); | 165 isolate()->VisitObjectPointers(&stack, false); |
174 stack.TraverseGraph(visitor); | 166 stack.TraverseGraph(visitor); |
175 Unmarker::UnmarkAll(isolate()); | 167 Unmarker::UnmarkAll(isolate()); |
176 } | 168 } |
177 | 169 |
178 | |
179 void ObjectGraph::IterateObjectsFrom(const Object& root, | 170 void ObjectGraph::IterateObjectsFrom(const Object& root, |
180 ObjectGraph::Visitor* visitor) { | 171 ObjectGraph::Visitor* visitor) { |
181 NoSafepointScope no_safepoint_scope_; | 172 NoSafepointScope no_safepoint_scope_; |
182 Stack stack(isolate()); | 173 Stack stack(isolate()); |
183 RawObject* root_raw = root.raw(); | 174 RawObject* root_raw = root.raw(); |
184 stack.VisitPointer(&root_raw); | 175 stack.VisitPointer(&root_raw); |
185 stack.TraverseGraph(visitor); | 176 stack.TraverseGraph(visitor); |
186 Unmarker::UnmarkAll(isolate()); | 177 Unmarker::UnmarkAll(isolate()); |
187 } | 178 } |
188 | 179 |
189 | |
190 class InstanceAccumulator : public ObjectVisitor { | 180 class InstanceAccumulator : public ObjectVisitor { |
191 public: | 181 public: |
192 InstanceAccumulator(ObjectGraph::Stack* stack, intptr_t class_id) | 182 InstanceAccumulator(ObjectGraph::Stack* stack, intptr_t class_id) |
193 : stack_(stack), class_id_(class_id) {} | 183 : stack_(stack), class_id_(class_id) {} |
194 | 184 |
195 void VisitObject(RawObject* obj) { | 185 void VisitObject(RawObject* obj) { |
196 if (obj->GetClassId() == class_id_) { | 186 if (obj->GetClassId() == class_id_) { |
197 RawObject* rawobj = obj; | 187 RawObject* rawobj = obj; |
198 stack_->VisitPointer(&rawobj); | 188 stack_->VisitPointer(&rawobj); |
199 } | 189 } |
200 } | 190 } |
201 | 191 |
202 private: | 192 private: |
203 ObjectGraph::Stack* stack_; | 193 ObjectGraph::Stack* stack_; |
204 const intptr_t class_id_; | 194 const intptr_t class_id_; |
205 | 195 |
206 DISALLOW_COPY_AND_ASSIGN(InstanceAccumulator); | 196 DISALLOW_COPY_AND_ASSIGN(InstanceAccumulator); |
207 }; | 197 }; |
208 | 198 |
209 | |
210 void ObjectGraph::IterateObjectsFrom(intptr_t class_id, | 199 void ObjectGraph::IterateObjectsFrom(intptr_t class_id, |
211 ObjectGraph::Visitor* visitor) { | 200 ObjectGraph::Visitor* visitor) { |
212 NoSafepointScope no_safepoint_scope_; | 201 NoSafepointScope no_safepoint_scope_; |
213 Stack stack(isolate()); | 202 Stack stack(isolate()); |
214 | 203 |
215 InstanceAccumulator accumulator(&stack, class_id); | 204 InstanceAccumulator accumulator(&stack, class_id); |
216 isolate()->heap()->VisitObjectsNoImagePages(&accumulator); | 205 isolate()->heap()->VisitObjectsNoImagePages(&accumulator); |
217 | 206 |
218 stack.TraverseGraph(visitor); | 207 stack.TraverseGraph(visitor); |
219 Unmarker::UnmarkAll(isolate()); | 208 Unmarker::UnmarkAll(isolate()); |
220 } | 209 } |
221 | 210 |
222 | |
223 class SizeVisitor : public ObjectGraph::Visitor { | 211 class SizeVisitor : public ObjectGraph::Visitor { |
224 public: | 212 public: |
225 SizeVisitor() : size_(0) {} | 213 SizeVisitor() : size_(0) {} |
226 intptr_t size() const { return size_; } | 214 intptr_t size() const { return size_; } |
227 virtual bool ShouldSkip(RawObject* obj) const { return false; } | 215 virtual bool ShouldSkip(RawObject* obj) const { return false; } |
228 virtual Direction VisitObject(ObjectGraph::StackIterator* it) { | 216 virtual Direction VisitObject(ObjectGraph::StackIterator* it) { |
229 RawObject* obj = it->Get(); | 217 RawObject* obj = it->Get(); |
230 if (ShouldSkip(obj)) { | 218 if (ShouldSkip(obj)) { |
231 return kBacktrack; | 219 return kBacktrack; |
232 } | 220 } |
233 size_ += obj->Size(); | 221 size_ += obj->Size(); |
234 return kProceed; | 222 return kProceed; |
235 } | 223 } |
236 | 224 |
237 private: | 225 private: |
238 intptr_t size_; | 226 intptr_t size_; |
239 }; | 227 }; |
240 | 228 |
241 | |
242 class SizeExcludingObjectVisitor : public SizeVisitor { | 229 class SizeExcludingObjectVisitor : public SizeVisitor { |
243 public: | 230 public: |
244 explicit SizeExcludingObjectVisitor(const Object& skip) : skip_(skip) {} | 231 explicit SizeExcludingObjectVisitor(const Object& skip) : skip_(skip) {} |
245 virtual bool ShouldSkip(RawObject* obj) const { return obj == skip_.raw(); } | 232 virtual bool ShouldSkip(RawObject* obj) const { return obj == skip_.raw(); } |
246 | 233 |
247 private: | 234 private: |
248 const Object& skip_; | 235 const Object& skip_; |
249 }; | 236 }; |
250 | 237 |
251 | |
252 class SizeExcludingClassVisitor : public SizeVisitor { | 238 class SizeExcludingClassVisitor : public SizeVisitor { |
253 public: | 239 public: |
254 explicit SizeExcludingClassVisitor(intptr_t skip) : skip_(skip) {} | 240 explicit SizeExcludingClassVisitor(intptr_t skip) : skip_(skip) {} |
255 virtual bool ShouldSkip(RawObject* obj) const { | 241 virtual bool ShouldSkip(RawObject* obj) const { |
256 return obj->GetClassId() == skip_; | 242 return obj->GetClassId() == skip_; |
257 } | 243 } |
258 | 244 |
259 private: | 245 private: |
260 const intptr_t skip_; | 246 const intptr_t skip_; |
261 }; | 247 }; |
262 | 248 |
263 | |
264 intptr_t ObjectGraph::SizeRetainedByInstance(const Object& obj) { | 249 intptr_t ObjectGraph::SizeRetainedByInstance(const Object& obj) { |
265 HeapIterationScope iteration_scope(true); | 250 HeapIterationScope iteration_scope(true); |
266 SizeVisitor total; | 251 SizeVisitor total; |
267 IterateObjects(&total); | 252 IterateObjects(&total); |
268 intptr_t size_total = total.size(); | 253 intptr_t size_total = total.size(); |
269 SizeExcludingObjectVisitor excluding_obj(obj); | 254 SizeExcludingObjectVisitor excluding_obj(obj); |
270 IterateObjects(&excluding_obj); | 255 IterateObjects(&excluding_obj); |
271 intptr_t size_excluding_obj = excluding_obj.size(); | 256 intptr_t size_excluding_obj = excluding_obj.size(); |
272 return size_total - size_excluding_obj; | 257 return size_total - size_excluding_obj; |
273 } | 258 } |
274 | 259 |
275 | |
276 intptr_t ObjectGraph::SizeReachableByInstance(const Object& obj) { | 260 intptr_t ObjectGraph::SizeReachableByInstance(const Object& obj) { |
277 HeapIterationScope iteration_scope(true); | 261 HeapIterationScope iteration_scope(true); |
278 SizeVisitor total; | 262 SizeVisitor total; |
279 IterateObjectsFrom(obj, &total); | 263 IterateObjectsFrom(obj, &total); |
280 return total.size(); | 264 return total.size(); |
281 } | 265 } |
282 | 266 |
283 | |
284 intptr_t ObjectGraph::SizeRetainedByClass(intptr_t class_id) { | 267 intptr_t ObjectGraph::SizeRetainedByClass(intptr_t class_id) { |
285 HeapIterationScope iteration_scope(true); | 268 HeapIterationScope iteration_scope(true); |
286 SizeVisitor total; | 269 SizeVisitor total; |
287 IterateObjects(&total); | 270 IterateObjects(&total); |
288 intptr_t size_total = total.size(); | 271 intptr_t size_total = total.size(); |
289 SizeExcludingClassVisitor excluding_class(class_id); | 272 SizeExcludingClassVisitor excluding_class(class_id); |
290 IterateObjects(&excluding_class); | 273 IterateObjects(&excluding_class); |
291 intptr_t size_excluding_class = excluding_class.size(); | 274 intptr_t size_excluding_class = excluding_class.size(); |
292 return size_total - size_excluding_class; | 275 return size_total - size_excluding_class; |
293 } | 276 } |
294 | 277 |
295 | |
296 intptr_t ObjectGraph::SizeReachableByClass(intptr_t class_id) { | 278 intptr_t ObjectGraph::SizeReachableByClass(intptr_t class_id) { |
297 HeapIterationScope iteration_scope(true); | 279 HeapIterationScope iteration_scope(true); |
298 SizeVisitor total; | 280 SizeVisitor total; |
299 IterateObjectsFrom(class_id, &total); | 281 IterateObjectsFrom(class_id, &total); |
300 return total.size(); | 282 return total.size(); |
301 } | 283 } |
302 | 284 |
303 | |
304 class RetainingPathVisitor : public ObjectGraph::Visitor { | 285 class RetainingPathVisitor : public ObjectGraph::Visitor { |
305 public: | 286 public: |
306 // We cannot use a GrowableObjectArray, since we must not trigger GC. | 287 // We cannot use a GrowableObjectArray, since we must not trigger GC. |
307 RetainingPathVisitor(RawObject* obj, const Array& path) | 288 RetainingPathVisitor(RawObject* obj, const Array& path) |
308 : thread_(Thread::Current()), obj_(obj), path_(path), length_(0) { | 289 : thread_(Thread::Current()), obj_(obj), path_(path), length_(0) { |
309 ASSERT(Thread::Current()->no_safepoint_scope_depth() != 0); | 290 ASSERT(Thread::Current()->no_safepoint_scope_depth() != 0); |
310 } | 291 } |
311 | 292 |
312 intptr_t length() const { return length_; } | 293 intptr_t length() const { return length_; } |
313 | 294 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 } | 362 } |
382 | 363 |
383 private: | 364 private: |
384 Thread* thread_; | 365 Thread* thread_; |
385 RawObject* obj_; | 366 RawObject* obj_; |
386 const Array& path_; | 367 const Array& path_; |
387 intptr_t length_; | 368 intptr_t length_; |
388 bool was_last_array_; | 369 bool was_last_array_; |
389 }; | 370 }; |
390 | 371 |
391 | |
392 intptr_t ObjectGraph::RetainingPath(Object* obj, const Array& path) { | 372 intptr_t ObjectGraph::RetainingPath(Object* obj, const Array& path) { |
393 NoSafepointScope no_safepoint_scope_; | 373 NoSafepointScope no_safepoint_scope_; |
394 HeapIterationScope iteration_scope(true); | 374 HeapIterationScope iteration_scope(true); |
395 // To break the trivial path, the handle 'obj' is temporarily cleared during | 375 // To break the trivial path, the handle 'obj' is temporarily cleared during |
396 // the search, but restored before returning. | 376 // the search, but restored before returning. |
397 RawObject* raw = obj->raw(); | 377 RawObject* raw = obj->raw(); |
398 *obj = Object::null(); | 378 *obj = Object::null(); |
399 RetainingPathVisitor visitor(raw, path); | 379 RetainingPathVisitor visitor(raw, path); |
400 IterateObjects(&visitor); | 380 IterateObjects(&visitor); |
401 *obj = raw; | 381 *obj = raw; |
402 return visitor.length(); | 382 return visitor.length(); |
403 } | 383 } |
404 | 384 |
405 | |
406 class InboundReferencesVisitor : public ObjectVisitor, | 385 class InboundReferencesVisitor : public ObjectVisitor, |
407 public ObjectPointerVisitor { | 386 public ObjectPointerVisitor { |
408 public: | 387 public: |
409 // We cannot use a GrowableObjectArray, since we must not trigger GC. | 388 // We cannot use a GrowableObjectArray, since we must not trigger GC. |
410 InboundReferencesVisitor(Isolate* isolate, | 389 InboundReferencesVisitor(Isolate* isolate, |
411 RawObject* target, | 390 RawObject* target, |
412 const Array& references, | 391 const Array& references, |
413 Object* scratch) | 392 Object* scratch) |
414 : ObjectPointerVisitor(isolate), | 393 : ObjectPointerVisitor(isolate), |
415 source_(NULL), | 394 source_(NULL), |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 } | 438 } |
460 | 439 |
461 private: | 440 private: |
462 RawObject* source_; | 441 RawObject* source_; |
463 RawObject* target_; | 442 RawObject* target_; |
464 const Array& references_; | 443 const Array& references_; |
465 Object* scratch_; | 444 Object* scratch_; |
466 intptr_t length_; | 445 intptr_t length_; |
467 }; | 446 }; |
468 | 447 |
469 | |
470 intptr_t ObjectGraph::InboundReferences(Object* obj, const Array& references) { | 448 intptr_t ObjectGraph::InboundReferences(Object* obj, const Array& references) { |
471 Object& scratch = Object::Handle(); | 449 Object& scratch = Object::Handle(); |
472 NoSafepointScope no_safepoint_scope; | 450 NoSafepointScope no_safepoint_scope; |
473 InboundReferencesVisitor visitor(isolate(), obj->raw(), references, &scratch); | 451 InboundReferencesVisitor visitor(isolate(), obj->raw(), references, &scratch); |
474 isolate()->heap()->IterateObjects(&visitor); | 452 isolate()->heap()->IterateObjects(&visitor); |
475 return visitor.length(); | 453 return visitor.length(); |
476 } | 454 } |
477 | 455 |
478 | |
479 static void WritePtr(RawObject* raw, WriteStream* stream) { | 456 static void WritePtr(RawObject* raw, WriteStream* stream) { |
480 ASSERT(raw->IsHeapObject()); | 457 ASSERT(raw->IsHeapObject()); |
481 ASSERT(raw->IsOldObject()); | 458 ASSERT(raw->IsOldObject()); |
482 uword addr = RawObject::ToAddr(raw); | 459 uword addr = RawObject::ToAddr(raw); |
483 ASSERT(Utils::IsAligned(addr, kObjectAlignment)); | 460 ASSERT(Utils::IsAligned(addr, kObjectAlignment)); |
484 // Using units of kObjectAlignment makes the ids fit into Smis when parsed | 461 // Using units of kObjectAlignment makes the ids fit into Smis when parsed |
485 // in the Dart code of the Observatory. | 462 // in the Dart code of the Observatory. |
486 // TODO(koda): Use delta-encoding/back-references to further compress this. | 463 // TODO(koda): Use delta-encoding/back-references to further compress this. |
487 stream->WriteUnsigned(addr / kObjectAlignment); | 464 stream->WriteUnsigned(addr / kObjectAlignment); |
488 } | 465 } |
489 | 466 |
490 | |
491 class WritePointerVisitor : public ObjectPointerVisitor { | 467 class WritePointerVisitor : public ObjectPointerVisitor { |
492 public: | 468 public: |
493 WritePointerVisitor(Isolate* isolate, | 469 WritePointerVisitor(Isolate* isolate, |
494 WriteStream* stream, | 470 WriteStream* stream, |
495 bool only_instances) | 471 bool only_instances) |
496 : ObjectPointerVisitor(isolate), | 472 : ObjectPointerVisitor(isolate), |
497 stream_(stream), | 473 stream_(stream), |
498 only_instances_(only_instances), | 474 only_instances_(only_instances), |
499 count_(0) {} | 475 count_(0) {} |
500 virtual void VisitPointers(RawObject** first, RawObject** last) { | 476 virtual void VisitPointers(RawObject** first, RawObject** last) { |
(...skipping 14 matching lines...) Expand all Loading... |
515 } | 491 } |
516 | 492 |
517 intptr_t count() const { return count_; } | 493 intptr_t count() const { return count_; } |
518 | 494 |
519 private: | 495 private: |
520 WriteStream* stream_; | 496 WriteStream* stream_; |
521 bool only_instances_; | 497 bool only_instances_; |
522 intptr_t count_; | 498 intptr_t count_; |
523 }; | 499 }; |
524 | 500 |
525 | |
526 static void WriteHeader(RawObject* raw, | 501 static void WriteHeader(RawObject* raw, |
527 intptr_t size, | 502 intptr_t size, |
528 intptr_t cid, | 503 intptr_t cid, |
529 WriteStream* stream) { | 504 WriteStream* stream) { |
530 WritePtr(raw, stream); | 505 WritePtr(raw, stream); |
531 ASSERT(Utils::IsAligned(size, kObjectAlignment)); | 506 ASSERT(Utils::IsAligned(size, kObjectAlignment)); |
532 stream->WriteUnsigned(size); | 507 stream->WriteUnsigned(size); |
533 stream->WriteUnsigned(cid); | 508 stream->WriteUnsigned(cid); |
534 } | 509 } |
535 | 510 |
536 | |
537 class WriteGraphVisitor : public ObjectGraph::Visitor { | 511 class WriteGraphVisitor : public ObjectGraph::Visitor { |
538 public: | 512 public: |
539 WriteGraphVisitor(Isolate* isolate, | 513 WriteGraphVisitor(Isolate* isolate, |
540 WriteStream* stream, | 514 WriteStream* stream, |
541 ObjectGraph::SnapshotRoots roots) | 515 ObjectGraph::SnapshotRoots roots) |
542 : stream_(stream), | 516 : stream_(stream), |
543 ptr_writer_(isolate, stream, roots == ObjectGraph::kUser), | 517 ptr_writer_(isolate, stream, roots == ObjectGraph::kUser), |
544 roots_(roots), | 518 roots_(roots), |
545 count_(0) {} | 519 count_(0) {} |
546 | 520 |
(...skipping 16 matching lines...) Expand all Loading... |
563 | 537 |
564 intptr_t count() const { return count_; } | 538 intptr_t count() const { return count_; } |
565 | 539 |
566 private: | 540 private: |
567 WriteStream* stream_; | 541 WriteStream* stream_; |
568 WritePointerVisitor ptr_writer_; | 542 WritePointerVisitor ptr_writer_; |
569 ObjectGraph::SnapshotRoots roots_; | 543 ObjectGraph::SnapshotRoots roots_; |
570 intptr_t count_; | 544 intptr_t count_; |
571 }; | 545 }; |
572 | 546 |
573 | |
574 static void IterateUserFields(ObjectPointerVisitor* visitor) { | 547 static void IterateUserFields(ObjectPointerVisitor* visitor) { |
575 Thread* thread = Thread::Current(); | 548 Thread* thread = Thread::Current(); |
576 // Scope to prevent handles create here from appearing as stack references. | 549 // Scope to prevent handles create here from appearing as stack references. |
577 HANDLESCOPE(thread); | 550 HANDLESCOPE(thread); |
578 Zone* zone = thread->zone(); | 551 Zone* zone = thread->zone(); |
579 const GrowableObjectArray& libraries = GrowableObjectArray::Handle( | 552 const GrowableObjectArray& libraries = GrowableObjectArray::Handle( |
580 zone, thread->isolate()->object_store()->libraries()); | 553 zone, thread->isolate()->object_store()->libraries()); |
581 Library& library = Library::Handle(zone); | 554 Library& library = Library::Handle(zone); |
582 Object& entry = Object::Handle(zone); | 555 Object& entry = Object::Handle(zone); |
583 Class& cls = Class::Handle(zone); | 556 Class& cls = Class::Handle(zone); |
(...skipping 14 matching lines...) Expand all Loading... |
598 } | 571 } |
599 } else if (entry.IsField()) { | 572 } else if (entry.IsField()) { |
600 field ^= entry.raw(); | 573 field ^= entry.raw(); |
601 RawObject* ptr = field.raw(); | 574 RawObject* ptr = field.raw(); |
602 visitor->VisitPointer(&ptr); | 575 visitor->VisitPointer(&ptr); |
603 } | 576 } |
604 } | 577 } |
605 } | 578 } |
606 } | 579 } |
607 | 580 |
608 | |
609 intptr_t ObjectGraph::Serialize(WriteStream* stream, | 581 intptr_t ObjectGraph::Serialize(WriteStream* stream, |
610 SnapshotRoots roots, | 582 SnapshotRoots roots, |
611 bool collect_garbage) { | 583 bool collect_garbage) { |
612 if (collect_garbage) { | 584 if (collect_garbage) { |
613 isolate()->heap()->CollectAllGarbage(); | 585 isolate()->heap()->CollectAllGarbage(); |
614 } | 586 } |
615 // Current encoding assumes objects do not move, so promote everything to old. | 587 // Current encoding assumes objects do not move, so promote everything to old. |
616 isolate()->heap()->new_space()->Evacuate(); | 588 isolate()->heap()->new_space()->Evacuate(); |
617 HeapIterationScope iteration_scope(true); | 589 HeapIterationScope iteration_scope(true); |
618 | 590 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 intptr_t object_count = visitor.count(); | 627 intptr_t object_count = visitor.count(); |
656 if (roots == kVM) { | 628 if (roots == kVM) { |
657 object_count += 1; // root | 629 object_count += 1; // root |
658 } else { | 630 } else { |
659 object_count += 2; // root and stack | 631 object_count += 2; // root and stack |
660 } | 632 } |
661 return object_count; | 633 return object_count; |
662 } | 634 } |
663 | 635 |
664 } // namespace dart | 636 } // namespace dart |
OLD | NEW |