| 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 |