Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(586)

Side by Side Diff: runtime/vm/object_graph.cc

Issue 2502283003: Add a version of heap snapshots that use only fields and stack frames as roots and only include ins… (Closed)
Patch Set: . Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/object_graph.h ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "vm/object_store.h"
11 #include "vm/raw_object.h" 12 #include "vm/raw_object.h"
12 #include "vm/reusable_handles.h" 13 #include "vm/reusable_handles.h"
13 #include "vm/visitor.h" 14 #include "vm/visitor.h"
14 15
15 namespace dart { 16 namespace dart {
16 17
17 // The state of a pre-order, depth-first traversal of an object graph. 18 // The state of a pre-order, depth-first traversal of an object graph.
18 // When a node is visited, *all* its children are pushed to the stack at once. 19 // When a node is visited, *all* its children are pushed to the stack at once.
19 // We insert a sentinel between the node and its children on the stack, to 20 // We insert a sentinel between the node and its children on the stack, to
20 // remember that the node has been visited. The node is kept on the stack while 21 // remember that the node has been visited. The node is kept on the stack while
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 ASSERT(Utils::IsAligned(addr, kObjectAlignment)); 481 ASSERT(Utils::IsAligned(addr, kObjectAlignment));
481 // Using units of kObjectAlignment makes the ids fit into Smis when parsed 482 // Using units of kObjectAlignment makes the ids fit into Smis when parsed
482 // in the Dart code of the Observatory. 483 // in the Dart code of the Observatory.
483 // TODO(koda): Use delta-encoding/back-references to further compress this. 484 // TODO(koda): Use delta-encoding/back-references to further compress this.
484 stream->WriteUnsigned(addr / kObjectAlignment); 485 stream->WriteUnsigned(addr / kObjectAlignment);
485 } 486 }
486 487
487 488
488 class WritePointerVisitor : public ObjectPointerVisitor { 489 class WritePointerVisitor : public ObjectPointerVisitor {
489 public: 490 public:
490 WritePointerVisitor(Isolate* isolate, WriteStream* stream) 491 WritePointerVisitor(Isolate* isolate,
491 : ObjectPointerVisitor(isolate), stream_(stream), count_(0) {} 492 WriteStream* stream,
493 bool only_instances)
494 : ObjectPointerVisitor(isolate),
495 stream_(stream),
496 only_instances_(only_instances),
497 count_(0) {}
492 virtual void VisitPointers(RawObject** first, RawObject** last) { 498 virtual void VisitPointers(RawObject** first, RawObject** last) {
493 for (RawObject** current = first; current <= last; ++current) { 499 for (RawObject** current = first; current <= last; ++current) {
494 RawObject* object = *current; 500 RawObject* object = *current;
495 if (!object->IsHeapObject() || object->IsVMHeapObject()) { 501 if (!object->IsHeapObject() || object->IsVMHeapObject()) {
496 // Ignore smis and objects in the VM isolate for now. 502 // Ignore smis and objects in the VM isolate for now.
497 // TODO(koda): To track which field each pointer corresponds to, 503 // TODO(koda): To track which field each pointer corresponds to,
498 // we'll need to encode which fields were omitted here. 504 // we'll need to encode which fields were omitted here.
499 continue; 505 continue;
500 } 506 }
507 if (only_instances_ && (object->GetClassId() < kInstanceCid)) {
508 continue;
509 }
501 WritePtr(object, stream_); 510 WritePtr(object, stream_);
502 ++count_; 511 ++count_;
503 } 512 }
504 } 513 }
505 514
506 intptr_t count() const { return count_; } 515 intptr_t count() const { return count_; }
507 516
508 private: 517 private:
509 WriteStream* stream_; 518 WriteStream* stream_;
519 bool only_instances_;
510 intptr_t count_; 520 intptr_t count_;
511 }; 521 };
512 522
513 523
514 static void WriteHeader(RawObject* raw, 524 static void WriteHeader(RawObject* raw,
515 intptr_t size, 525 intptr_t size,
516 intptr_t cid, 526 intptr_t cid,
517 WriteStream* stream) { 527 WriteStream* stream) {
518 WritePtr(raw, stream); 528 WritePtr(raw, stream);
519 ASSERT(Utils::IsAligned(size, kObjectAlignment)); 529 ASSERT(Utils::IsAligned(size, kObjectAlignment));
520 stream->WriteUnsigned(size); 530 stream->WriteUnsigned(size);
521 stream->WriteUnsigned(cid); 531 stream->WriteUnsigned(cid);
522 } 532 }
523 533
524 534
525 class WriteGraphVisitor : public ObjectGraph::Visitor { 535 class WriteGraphVisitor : public ObjectGraph::Visitor {
526 public: 536 public:
527 WriteGraphVisitor(Isolate* isolate, WriteStream* stream) 537 WriteGraphVisitor(Isolate* isolate,
528 : stream_(stream), ptr_writer_(isolate, stream), count_(0) {} 538 WriteStream* stream,
539 ObjectGraph::SnapshotRoots roots)
540 : stream_(stream),
541 ptr_writer_(isolate, stream, roots == ObjectGraph::kUser),
542 roots_(roots),
543 count_(0) {}
529 544
530 virtual Direction VisitObject(ObjectGraph::StackIterator* it) { 545 virtual Direction VisitObject(ObjectGraph::StackIterator* it) {
531 RawObject* raw_obj = it->Get(); 546 RawObject* raw_obj = it->Get();
532 Thread* thread = Thread::Current(); 547 Thread* thread = Thread::Current();
533 REUSABLE_OBJECT_HANDLESCOPE(thread); 548 REUSABLE_OBJECT_HANDLESCOPE(thread);
534 Object& obj = thread->ObjectHandle(); 549 Object& obj = thread->ObjectHandle();
535 obj = raw_obj; 550 obj = raw_obj;
536 // Each object is a header + a zero-terminated list of its neighbors. 551 if ((roots_ == ObjectGraph::kVM) || obj.IsField() || obj.IsInstance()) {
537 WriteHeader(raw_obj, raw_obj->Size(), obj.GetClassId(), stream_); 552 // Each object is a header + a zero-terminated list of its neighbors.
538 raw_obj->VisitPointers(&ptr_writer_); 553 WriteHeader(raw_obj, raw_obj->Size(), obj.GetClassId(), stream_);
539 stream_->WriteUnsigned(0); 554 raw_obj->VisitPointers(&ptr_writer_);
540 ++count_; 555 stream_->WriteUnsigned(0);
556 ++count_;
557 }
541 return kProceed; 558 return kProceed;
542 } 559 }
543 560
544 intptr_t count() const { return count_; } 561 intptr_t count() const { return count_; }
545 562
546 private: 563 private:
547 WriteStream* stream_; 564 WriteStream* stream_;
548 WritePointerVisitor ptr_writer_; 565 WritePointerVisitor ptr_writer_;
566 ObjectGraph::SnapshotRoots roots_;
549 intptr_t count_; 567 intptr_t count_;
550 }; 568 };
551 569
552 570
553 intptr_t ObjectGraph::Serialize(WriteStream* stream, bool collect_garbage) { 571 static void IterateUserFields(ObjectPointerVisitor* visitor) {
572 Thread* thread = Thread::Current();
573 // Scope to prevent handles create here from appearing as stack references.
574 HANDLESCOPE(thread);
575 Zone* zone = thread->zone();
576 const GrowableObjectArray& libraries = GrowableObjectArray::Handle(
577 zone, thread->isolate()->object_store()->libraries());
578 Library& library = Library::Handle(zone);
579 Object& entry = Object::Handle(zone);
580 Class& cls = Class::Handle(zone);
581 Array& fields = Array::Handle(zone);
582 Field& field = Field::Handle(zone);
583 for (intptr_t i = 0; i < libraries.Length(); i++) {
584 library ^= libraries.At(i);
585 DictionaryIterator entries(library);
586 while (entries.HasNext()) {
587 entry = entries.GetNext();
588 if (entry.IsClass()) {
589 cls ^= entry.raw();
590 fields = cls.fields();
591 for (intptr_t j = 0; j < fields.Length(); j++) {
592 field ^= fields.At(j);
593 RawObject* ptr = field.raw();
594 visitor->VisitPointer(&ptr);
595 }
596 } else if (entry.IsField()) {
597 field ^= entry.raw();
598 RawObject* ptr = field.raw();
599 visitor->VisitPointer(&ptr);
600 }
601 }
602 }
603 }
604
605
606 intptr_t ObjectGraph::Serialize(WriteStream* stream,
607 SnapshotRoots roots,
608 bool collect_garbage) {
554 if (collect_garbage) { 609 if (collect_garbage) {
555 isolate()->heap()->CollectAllGarbage(); 610 isolate()->heap()->CollectAllGarbage();
556 } 611 }
557 // Current encoding assumes objects do not move, so promote everything to old. 612 // Current encoding assumes objects do not move, so promote everything to old.
558 isolate()->heap()->new_space()->Evacuate(); 613 isolate()->heap()->new_space()->Evacuate();
559 614
560 WriteGraphVisitor visitor(isolate(), stream); 615 RawObject* kRootAddress = reinterpret_cast<RawObject*>(kHeapObjectTag);
616 const intptr_t kRootCid = kIllegalCid;
617 RawObject* kStackAddress =
618 reinterpret_cast<RawObject*>(kObjectAlignment + kHeapObjectTag);
619
561 stream->WriteUnsigned(kObjectAlignment); 620 stream->WriteUnsigned(kObjectAlignment);
562 stream->WriteUnsigned(0); 621 stream->WriteUnsigned(kStackCid);
563 stream->WriteUnsigned(0); 622
564 stream->WriteUnsigned(0); 623 if (roots == kVM) {
565 { 624 // Write root "object".
566 WritePointerVisitor ptr_writer(isolate(), stream); 625 WriteHeader(kRootAddress, 0, kRootCid, stream);
626 WritePointerVisitor ptr_writer(isolate(), stream, false);
567 isolate()->IterateObjectPointers(&ptr_writer, false); 627 isolate()->IterateObjectPointers(&ptr_writer, false);
628 stream->WriteUnsigned(0);
629 } else {
630 {
631 // Write root "object".
632 WriteHeader(kRootAddress, 0, kRootCid, stream);
633 WritePointerVisitor ptr_writer(isolate(), stream, false);
634 IterateUserFields(&ptr_writer);
635 WritePtr(kStackAddress, stream);
636 stream->WriteUnsigned(0);
637 }
638
639 {
640 // Write stack "object".
641 WriteHeader(kStackAddress, 0, kStackCid, stream);
642 WritePointerVisitor ptr_writer(isolate(), stream, true);
643 isolate()->IterateStackPointers(&ptr_writer, false);
644 stream->WriteUnsigned(0);
645 }
568 } 646 }
569 stream->WriteUnsigned(0); 647
648 WriteGraphVisitor visitor(isolate(), stream, roots);
570 IterateObjects(&visitor); 649 IterateObjects(&visitor);
571 return visitor.count() + 1; // + root 650
651 intptr_t object_count = visitor.count();
652 if (roots == kVM) {
653 object_count += 1; // root
654 } else {
655 object_count += 2; // root and stack
656 }
657 return object_count;
572 } 658 }
573 659
574 } // namespace dart 660 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object_graph.h ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698