| 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 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 Unmarker() {} | 142 Unmarker() {} |
| 143 | 143 |
| 144 void VisitObject(RawObject* obj) { | 144 void VisitObject(RawObject* obj) { |
| 145 if (obj->IsMarked()) { | 145 if (obj->IsMarked()) { |
| 146 obj->ClearMarkBit(); | 146 obj->ClearMarkBit(); |
| 147 } | 147 } |
| 148 } | 148 } |
| 149 | 149 |
| 150 static void UnmarkAll(Isolate* isolate) { | 150 static void UnmarkAll(Isolate* isolate) { |
| 151 Unmarker unmarker; | 151 Unmarker unmarker; |
| 152 isolate->heap()->IterateObjects(&unmarker); | 152 isolate->heap()->VisitObjects(&unmarker); |
| 153 } | 153 } |
| 154 | 154 |
| 155 private: | 155 private: |
| 156 DISALLOW_COPY_AND_ASSIGN(Unmarker); | 156 DISALLOW_COPY_AND_ASSIGN(Unmarker); |
| 157 }; | 157 }; |
| 158 | 158 |
| 159 | 159 |
| 160 ObjectGraph::ObjectGraph(Thread* thread) : StackResource(thread) { | 160 ObjectGraph::ObjectGraph(Thread* thread) : StackResource(thread) { |
| 161 // The VM isolate has all its objects pre-marked, so iterating over it | 161 // The VM isolate has all its objects pre-marked, so iterating over it |
| 162 // would be a no-op. | 162 // would be a no-op. |
| 163 ASSERT(thread->isolate() != Dart::vm_isolate()); | 163 ASSERT(thread->isolate() != Dart::vm_isolate()); |
| 164 thread->isolate()->heap()->WriteProtectCode(false); | |
| 165 } | 164 } |
| 166 | 165 |
| 167 | 166 |
| 168 ObjectGraph::~ObjectGraph() { | 167 ObjectGraph::~ObjectGraph() {} |
| 169 isolate()->heap()->WriteProtectCode(true); | |
| 170 } | |
| 171 | 168 |
| 172 | 169 |
| 173 void ObjectGraph::IterateObjects(ObjectGraph::Visitor* visitor) { | 170 void ObjectGraph::IterateObjects(ObjectGraph::Visitor* visitor) { |
| 174 NoSafepointScope no_safepoint_scope_; | 171 NoSafepointScope no_safepoint_scope_; |
| 175 Stack stack(isolate()); | 172 Stack stack(isolate()); |
| 176 isolate()->IterateObjectPointers(&stack, false); | 173 isolate()->VisitObjectPointers(&stack, false); |
| 177 stack.TraverseGraph(visitor); | 174 stack.TraverseGraph(visitor); |
| 178 Unmarker::UnmarkAll(isolate()); | 175 Unmarker::UnmarkAll(isolate()); |
| 179 } | 176 } |
| 180 | 177 |
| 181 | 178 |
| 182 void ObjectGraph::IterateObjectsFrom(const Object& root, | 179 void ObjectGraph::IterateObjectsFrom(const Object& root, |
| 183 ObjectGraph::Visitor* visitor) { | 180 ObjectGraph::Visitor* visitor) { |
| 184 NoSafepointScope no_safepoint_scope_; | 181 NoSafepointScope no_safepoint_scope_; |
| 185 Stack stack(isolate()); | 182 Stack stack(isolate()); |
| 186 RawObject* root_raw = root.raw(); | 183 RawObject* root_raw = root.raw(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 209 DISALLOW_COPY_AND_ASSIGN(InstanceAccumulator); | 206 DISALLOW_COPY_AND_ASSIGN(InstanceAccumulator); |
| 210 }; | 207 }; |
| 211 | 208 |
| 212 | 209 |
| 213 void ObjectGraph::IterateObjectsFrom(intptr_t class_id, | 210 void ObjectGraph::IterateObjectsFrom(intptr_t class_id, |
| 214 ObjectGraph::Visitor* visitor) { | 211 ObjectGraph::Visitor* visitor) { |
| 215 NoSafepointScope no_safepoint_scope_; | 212 NoSafepointScope no_safepoint_scope_; |
| 216 Stack stack(isolate()); | 213 Stack stack(isolate()); |
| 217 | 214 |
| 218 InstanceAccumulator accumulator(&stack, class_id); | 215 InstanceAccumulator accumulator(&stack, class_id); |
| 219 isolate()->heap()->IterateObjects(&accumulator); | 216 isolate()->heap()->VisitObjects(&accumulator); |
| 220 | 217 |
| 221 stack.TraverseGraph(visitor); | 218 stack.TraverseGraph(visitor); |
| 222 Unmarker::UnmarkAll(isolate()); | 219 Unmarker::UnmarkAll(isolate()); |
| 223 } | 220 } |
| 224 | 221 |
| 225 | 222 |
| 226 class SizeVisitor : public ObjectGraph::Visitor { | 223 class SizeVisitor : public ObjectGraph::Visitor { |
| 227 public: | 224 public: |
| 228 SizeVisitor() : size_(0) {} | 225 SizeVisitor() : size_(0) {} |
| 229 intptr_t size() const { return size_; } | 226 intptr_t size() const { return size_; } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 258 virtual bool ShouldSkip(RawObject* obj) const { | 255 virtual bool ShouldSkip(RawObject* obj) const { |
| 259 return obj->GetClassId() == skip_; | 256 return obj->GetClassId() == skip_; |
| 260 } | 257 } |
| 261 | 258 |
| 262 private: | 259 private: |
| 263 const intptr_t skip_; | 260 const intptr_t skip_; |
| 264 }; | 261 }; |
| 265 | 262 |
| 266 | 263 |
| 267 intptr_t ObjectGraph::SizeRetainedByInstance(const Object& obj) { | 264 intptr_t ObjectGraph::SizeRetainedByInstance(const Object& obj) { |
| 265 HeapIterationScope iteration_scope(true); |
| 268 SizeVisitor total; | 266 SizeVisitor total; |
| 269 IterateObjects(&total); | 267 IterateObjects(&total); |
| 270 intptr_t size_total = total.size(); | 268 intptr_t size_total = total.size(); |
| 271 SizeExcludingObjectVisitor excluding_obj(obj); | 269 SizeExcludingObjectVisitor excluding_obj(obj); |
| 272 IterateObjects(&excluding_obj); | 270 IterateObjects(&excluding_obj); |
| 273 intptr_t size_excluding_obj = excluding_obj.size(); | 271 intptr_t size_excluding_obj = excluding_obj.size(); |
| 274 return size_total - size_excluding_obj; | 272 return size_total - size_excluding_obj; |
| 275 } | 273 } |
| 276 | 274 |
| 277 | 275 |
| 278 intptr_t ObjectGraph::SizeReachableByInstance(const Object& obj) { | 276 intptr_t ObjectGraph::SizeReachableByInstance(const Object& obj) { |
| 277 HeapIterationScope iteration_scope(true); |
| 279 SizeVisitor total; | 278 SizeVisitor total; |
| 280 IterateObjectsFrom(obj, &total); | 279 IterateObjectsFrom(obj, &total); |
| 281 return total.size(); | 280 return total.size(); |
| 282 } | 281 } |
| 283 | 282 |
| 284 | 283 |
| 285 intptr_t ObjectGraph::SizeRetainedByClass(intptr_t class_id) { | 284 intptr_t ObjectGraph::SizeRetainedByClass(intptr_t class_id) { |
| 285 HeapIterationScope iteration_scope(true); |
| 286 SizeVisitor total; | 286 SizeVisitor total; |
| 287 IterateObjects(&total); | 287 IterateObjects(&total); |
| 288 intptr_t size_total = total.size(); | 288 intptr_t size_total = total.size(); |
| 289 SizeExcludingClassVisitor excluding_class(class_id); | 289 SizeExcludingClassVisitor excluding_class(class_id); |
| 290 IterateObjects(&excluding_class); | 290 IterateObjects(&excluding_class); |
| 291 intptr_t size_excluding_class = excluding_class.size(); | 291 intptr_t size_excluding_class = excluding_class.size(); |
| 292 return size_total - size_excluding_class; | 292 return size_total - size_excluding_class; |
| 293 } | 293 } |
| 294 | 294 |
| 295 | 295 |
| 296 intptr_t ObjectGraph::SizeReachableByClass(intptr_t class_id) { | 296 intptr_t ObjectGraph::SizeReachableByClass(intptr_t class_id) { |
| 297 HeapIterationScope iteration_scope(true); |
| 297 SizeVisitor total; | 298 SizeVisitor total; |
| 298 IterateObjectsFrom(class_id, &total); | 299 IterateObjectsFrom(class_id, &total); |
| 299 return total.size(); | 300 return total.size(); |
| 300 } | 301 } |
| 301 | 302 |
| 302 | 303 |
| 303 class RetainingPathVisitor : public ObjectGraph::Visitor { | 304 class RetainingPathVisitor : public ObjectGraph::Visitor { |
| 304 public: | 305 public: |
| 305 // We cannot use a GrowableObjectArray, since we must not trigger GC. | 306 // We cannot use a GrowableObjectArray, since we must not trigger GC. |
| 306 RetainingPathVisitor(RawObject* obj, const Array& path) | 307 RetainingPathVisitor(RawObject* obj, const Array& path) |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 Thread* thread_; | 384 Thread* thread_; |
| 384 RawObject* obj_; | 385 RawObject* obj_; |
| 385 const Array& path_; | 386 const Array& path_; |
| 386 intptr_t length_; | 387 intptr_t length_; |
| 387 bool was_last_array_; | 388 bool was_last_array_; |
| 388 }; | 389 }; |
| 389 | 390 |
| 390 | 391 |
| 391 intptr_t ObjectGraph::RetainingPath(Object* obj, const Array& path) { | 392 intptr_t ObjectGraph::RetainingPath(Object* obj, const Array& path) { |
| 392 NoSafepointScope no_safepoint_scope_; | 393 NoSafepointScope no_safepoint_scope_; |
| 394 HeapIterationScope iteration_scope(true); |
| 393 // To break the trivial path, the handle 'obj' is temporarily cleared during | 395 // To break the trivial path, the handle 'obj' is temporarily cleared during |
| 394 // the search, but restored before returning. | 396 // the search, but restored before returning. |
| 395 RawObject* raw = obj->raw(); | 397 RawObject* raw = obj->raw(); |
| 396 *obj = Object::null(); | 398 *obj = Object::null(); |
| 397 RetainingPathVisitor visitor(raw, path); | 399 RetainingPathVisitor visitor(raw, path); |
| 398 IterateObjects(&visitor); | 400 IterateObjects(&visitor); |
| 399 *obj = raw; | 401 *obj = raw; |
| 400 return visitor.length(); | 402 return visitor.length(); |
| 401 } | 403 } |
| 402 | 404 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 RawObject* source_; | 462 RawObject* source_; |
| 461 RawObject* target_; | 463 RawObject* target_; |
| 462 const Array& references_; | 464 const Array& references_; |
| 463 Object* scratch_; | 465 Object* scratch_; |
| 464 intptr_t length_; | 466 intptr_t length_; |
| 465 }; | 467 }; |
| 466 | 468 |
| 467 | 469 |
| 468 intptr_t ObjectGraph::InboundReferences(Object* obj, const Array& references) { | 470 intptr_t ObjectGraph::InboundReferences(Object* obj, const Array& references) { |
| 469 Object& scratch = Object::Handle(); | 471 Object& scratch = Object::Handle(); |
| 470 NoSafepointScope no_safepoint_scope_; | 472 NoSafepointScope no_safepoint_scope; |
| 471 InboundReferencesVisitor visitor(isolate(), obj->raw(), references, &scratch); | 473 InboundReferencesVisitor visitor(isolate(), obj->raw(), references, &scratch); |
| 472 isolate()->heap()->IterateObjects(&visitor); | 474 isolate()->heap()->IterateObjects(&visitor); |
| 473 return visitor.length(); | 475 return visitor.length(); |
| 474 } | 476 } |
| 475 | 477 |
| 476 | 478 |
| 477 static void WritePtr(RawObject* raw, WriteStream* stream) { | 479 static void WritePtr(RawObject* raw, WriteStream* stream) { |
| 478 ASSERT(raw->IsHeapObject()); | 480 ASSERT(raw->IsHeapObject()); |
| 479 ASSERT(raw->IsOldObject()); | 481 ASSERT(raw->IsOldObject()); |
| 480 uword addr = RawObject::ToAddr(raw); | 482 uword addr = RawObject::ToAddr(raw); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 | 606 |
| 605 | 607 |
| 606 intptr_t ObjectGraph::Serialize(WriteStream* stream, | 608 intptr_t ObjectGraph::Serialize(WriteStream* stream, |
| 607 SnapshotRoots roots, | 609 SnapshotRoots roots, |
| 608 bool collect_garbage) { | 610 bool collect_garbage) { |
| 609 if (collect_garbage) { | 611 if (collect_garbage) { |
| 610 isolate()->heap()->CollectAllGarbage(); | 612 isolate()->heap()->CollectAllGarbage(); |
| 611 } | 613 } |
| 612 // Current encoding assumes objects do not move, so promote everything to old. | 614 // Current encoding assumes objects do not move, so promote everything to old. |
| 613 isolate()->heap()->new_space()->Evacuate(); | 615 isolate()->heap()->new_space()->Evacuate(); |
| 616 HeapIterationScope iteration_scope(true); |
| 614 | 617 |
| 615 RawObject* kRootAddress = reinterpret_cast<RawObject*>(kHeapObjectTag); | 618 RawObject* kRootAddress = reinterpret_cast<RawObject*>(kHeapObjectTag); |
| 616 const intptr_t kRootCid = kIllegalCid; | 619 const intptr_t kRootCid = kIllegalCid; |
| 617 RawObject* kStackAddress = | 620 RawObject* kStackAddress = |
| 618 reinterpret_cast<RawObject*>(kObjectAlignment + kHeapObjectTag); | 621 reinterpret_cast<RawObject*>(kObjectAlignment + kHeapObjectTag); |
| 619 | 622 |
| 620 stream->WriteUnsigned(kObjectAlignment); | 623 stream->WriteUnsigned(kObjectAlignment); |
| 621 stream->WriteUnsigned(kStackCid); | 624 stream->WriteUnsigned(kStackCid); |
| 622 | 625 |
| 623 if (roots == kVM) { | 626 if (roots == kVM) { |
| 624 // Write root "object". | 627 // Write root "object". |
| 625 WriteHeader(kRootAddress, 0, kRootCid, stream); | 628 WriteHeader(kRootAddress, 0, kRootCid, stream); |
| 626 WritePointerVisitor ptr_writer(isolate(), stream, false); | 629 WritePointerVisitor ptr_writer(isolate(), stream, false); |
| 627 isolate()->IterateObjectPointers(&ptr_writer, false); | 630 isolate()->VisitObjectPointers(&ptr_writer, false); |
| 628 stream->WriteUnsigned(0); | 631 stream->WriteUnsigned(0); |
| 629 } else { | 632 } else { |
| 630 { | 633 { |
| 631 // Write root "object". | 634 // Write root "object". |
| 632 WriteHeader(kRootAddress, 0, kRootCid, stream); | 635 WriteHeader(kRootAddress, 0, kRootCid, stream); |
| 633 WritePointerVisitor ptr_writer(isolate(), stream, false); | 636 WritePointerVisitor ptr_writer(isolate(), stream, false); |
| 634 IterateUserFields(&ptr_writer); | 637 IterateUserFields(&ptr_writer); |
| 635 WritePtr(kStackAddress, stream); | 638 WritePtr(kStackAddress, stream); |
| 636 stream->WriteUnsigned(0); | 639 stream->WriteUnsigned(0); |
| 637 } | 640 } |
| 638 | 641 |
| 639 { | 642 { |
| 640 // Write stack "object". | 643 // Write stack "object". |
| 641 WriteHeader(kStackAddress, 0, kStackCid, stream); | 644 WriteHeader(kStackAddress, 0, kStackCid, stream); |
| 642 WritePointerVisitor ptr_writer(isolate(), stream, true); | 645 WritePointerVisitor ptr_writer(isolate(), stream, true); |
| 643 isolate()->IterateStackPointers(&ptr_writer, false); | 646 isolate()->VisitStackPointers(&ptr_writer, false); |
| 644 stream->WriteUnsigned(0); | 647 stream->WriteUnsigned(0); |
| 645 } | 648 } |
| 646 } | 649 } |
| 647 | 650 |
| 648 WriteGraphVisitor visitor(isolate(), stream, roots); | 651 WriteGraphVisitor visitor(isolate(), stream, roots); |
| 649 IterateObjects(&visitor); | 652 IterateObjects(&visitor); |
| 650 | 653 |
| 651 intptr_t object_count = visitor.count(); | 654 intptr_t object_count = visitor.count(); |
| 652 if (roots == kVM) { | 655 if (roots == kVM) { |
| 653 object_count += 1; // root | 656 object_count += 1; // root |
| 654 } else { | 657 } else { |
| 655 object_count += 2; // root and stack | 658 object_count += 2; // root and stack |
| 656 } | 659 } |
| 657 return object_count; | 660 return object_count; |
| 658 } | 661 } |
| 659 | 662 |
| 660 } // namespace dart | 663 } // namespace dart |
| OLD | NEW |