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

Side by Side Diff: Source/platform/heap/Heap.cpp

Issue 921493003: Revert of Oilpan: Remove duplicated code between HeapPage and LargeObject (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 10 months 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 | Annotate | Revision Log
« no previous file with comments | « Source/platform/heap/Heap.h ('k') | Source/platform/heap/ThreadState.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 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 525
526 void LargeObject::markUnmarkedObjectsDead() 526 void LargeObject::markUnmarkedObjectsDead()
527 { 527 {
528 HeapObjectHeader* header = heapObjectHeader(); 528 HeapObjectHeader* header = heapObjectHeader();
529 if (header->isMarked()) 529 if (header->isMarked())
530 header->unmark(); 530 header->unmark();
531 else 531 else
532 header->markDead(); 532 header->markDead();
533 } 533 }
534 534
535 void LargeObject::removeFromHeap() 535 void LargeObject::removeFromHeap(ThreadHeap* heap)
536 { 536 {
537 static_cast<ThreadHeapForLargeObject*>(heap())->freeLargeObject(this); 537 heap->freeLargeObject(this);
538 }
539
540 ThreadHeap::ThreadHeap(ThreadState* state, int index)
541 : m_currentAllocationPoint(nullptr)
542 , m_remainingAllocationSize(0)
543 , m_lastRemainingAllocationSize(0)
544 , m_firstPage(nullptr)
545 , m_firstLargeObject(nullptr)
546 , m_firstUnsweptPage(nullptr)
547 , m_firstUnsweptLargeObject(nullptr)
548 , m_threadState(state)
549 , m_index(index)
550 , m_promptlyFreedSize(0)
551 #if ENABLE(GC_PROFILING)
552 , m_cumulativeAllocationSize(0)
553 , m_allocationCount(0)
554 , m_inlineAllocationCount(0)
555 #endif
556 {
557 clearFreeLists();
538 } 558 }
539 559
540 FreeList::FreeList() 560 FreeList::FreeList()
541 : m_biggestFreeListIndex(0) 561 : m_biggestFreeListIndex(0)
542 { 562 {
543 } 563 }
544 564
545 ThreadHeap::ThreadHeap(ThreadState* state, int index)
546 : m_firstPage(nullptr)
547 , m_firstUnsweptPage(nullptr)
548 , m_threadState(state)
549 , m_index(index)
550 #if ENABLE(GC_PROFILING)
551 , m_cumulativeAllocationSize(0)
552 , m_allocationCount(0)
553 , m_inlineAllocationCount(0)
554 #endif
555 {
556 }
557
558 ThreadHeapForHeapPage::ThreadHeapForHeapPage(ThreadState* state, int index)
559 : ThreadHeap(state, index)
560 , m_currentAllocationPoint(nullptr)
561 , m_remainingAllocationSize(0)
562 , m_lastRemainingAllocationSize(0)
563 , m_promptlyFreedSize(0)
564 {
565 clearFreeLists();
566 }
567
568 ThreadHeapForLargeObject::ThreadHeapForLargeObject(ThreadState* state, int index )
569 : ThreadHeap(state, index)
570 {
571 }
572
573 ThreadHeap::~ThreadHeap() 565 ThreadHeap::~ThreadHeap()
574 { 566 {
575 ASSERT(!m_firstPage); 567 ASSERT(!m_firstPage);
568 ASSERT(!m_firstLargeObject);
576 ASSERT(!m_firstUnsweptPage); 569 ASSERT(!m_firstUnsweptPage);
570 ASSERT(!m_firstUnsweptLargeObject);
577 } 571 }
578 572
579 void ThreadHeap::cleanupPages() 573 void ThreadHeap::cleanupPages()
580 { 574 {
581 clearFreeLists(); 575 clearFreeLists();
582 576
583 ASSERT(!m_firstUnsweptPage); 577 ASSERT(!m_firstUnsweptPage);
578 ASSERT(!m_firstUnsweptLargeObject);
584 // Add the ThreadHeap's pages to the orphanedPagePool. 579 // Add the ThreadHeap's pages to the orphanedPagePool.
585 for (BaseHeapPage* page = m_firstPage; page; page = page->next()) { 580 for (HeapPage* page = m_firstPage; page; page = page->m_next) {
586 Heap::decreaseAllocatedSpace(page->size()); 581 Heap::decreaseAllocatedSpace(blinkPageSize);
587 Heap::orphanedPagePool()->addOrphanedPage(heapIndex(), page); 582 Heap::orphanedPagePool()->addOrphanedPage(m_index, page);
588 } 583 }
589 m_firstPage = nullptr; 584 m_firstPage = nullptr;
585
586 for (LargeObject* largeObject = m_firstLargeObject; largeObject; largeObject = largeObject->m_next) {
587 Heap::decreaseAllocatedSpace(largeObject->size());
588 Heap::orphanedPagePool()->addOrphanedPage(m_index, largeObject);
589 }
590 m_firstLargeObject = nullptr;
590 } 591 }
591 592
592 void ThreadHeapForHeapPage::updateRemainingAllocationSize() 593 void ThreadHeap::updateRemainingAllocationSize()
593 { 594 {
594 if (m_lastRemainingAllocationSize > remainingAllocationSize()) { 595 if (m_lastRemainingAllocationSize > remainingAllocationSize()) {
595 Heap::increaseAllocatedObjectSize(m_lastRemainingAllocationSize - remain ingAllocationSize()); 596 Heap::increaseAllocatedObjectSize(m_lastRemainingAllocationSize - remain ingAllocationSize());
596 m_lastRemainingAllocationSize = remainingAllocationSize(); 597 m_lastRemainingAllocationSize = remainingAllocationSize();
597 } 598 }
598 ASSERT(m_lastRemainingAllocationSize == remainingAllocationSize()); 599 ASSERT(m_lastRemainingAllocationSize == remainingAllocationSize());
599 } 600 }
600 601
601 void ThreadHeapForHeapPage::setAllocationPoint(Address point, size_t size) 602 void ThreadHeap::setAllocationPoint(Address point, size_t size)
602 { 603 {
603 #if ENABLE(ASSERT) 604 #if ENABLE(ASSERT)
604 if (point) { 605 if (point) {
605 ASSERT(size); 606 ASSERT(size);
606 BaseHeapPage* page = pageFromObject(point); 607 BaseHeapPage* page = pageFromObject(point);
607 ASSERT(!page->isLargeObject()); 608 ASSERT(!page->isLargeObject());
608 ASSERT(size <= static_cast<HeapPage*>(page)->payloadSize()); 609 ASSERT(size <= static_cast<HeapPage*>(page)->payloadSize());
609 } 610 }
610 #endif 611 #endif
611 if (hasCurrentAllocationArea()) { 612 if (hasCurrentAllocationArea())
612 addToFreeList(currentAllocationPoint(), remainingAllocationSize()); 613 addToFreeList(currentAllocationPoint(), remainingAllocationSize());
613 }
614 updateRemainingAllocationSize(); 614 updateRemainingAllocationSize();
615 m_currentAllocationPoint = point; 615 m_currentAllocationPoint = point;
616 m_lastRemainingAllocationSize = m_remainingAllocationSize = size; 616 m_lastRemainingAllocationSize = m_remainingAllocationSize = size;
617 } 617 }
618 618
619 Address ThreadHeapForHeapPage::outOfLineAllocate(size_t allocationSize, size_t g cInfoIndex) 619 Address ThreadHeap::outOfLineAllocate(size_t allocationSize, size_t gcInfoIndex)
620 { 620 {
621 ASSERT(allocationSize > remainingAllocationSize()); 621 ASSERT(allocationSize > remainingAllocationSize());
622 ASSERT(allocationSize >= allocationGranularity); 622 ASSERT(allocationSize >= allocationGranularity);
623 623
624 #if ENABLE(GC_PROFILING) 624 #if ENABLE(GC_PROFILING)
625 m_threadState->snapshotFreeListIfNecessary(); 625 m_threadState->snapshotFreeListIfNecessary();
626 #endif 626 #endif
627 627
628 // 1. If this allocation is big enough, allocate a large object. 628 // 1. If this allocation is big enough, allocate a large object.
629 if (allocationSize >= largeObjectSizeThreshold) 629 if (allocationSize >= largeObjectSizeThreshold)
630 return static_cast<ThreadHeapForLargeObject*>(threadState()->heap(LargeO bjectHeap))->allocateLargeObject(allocationSize, gcInfoIndex); 630 return allocateLargeObject(allocationSize, gcInfoIndex);
631 631
632 // 2. Check if we should trigger a GC. 632 // 2. Check if we should trigger a GC.
633 updateRemainingAllocationSize(); 633 updateRemainingAllocationSize();
634 threadState()->scheduleGCIfNeeded(); 634 threadState()->scheduleGCIfNeeded();
635 635
636 // 3. Try to allocate from a free list. 636 // 3. Try to allocate from a free list.
637 Address result = allocateFromFreeList(allocationSize, gcInfoIndex); 637 Address result = allocateFromFreeList(allocationSize, gcInfoIndex);
638 if (result) 638 if (result)
639 return result; 639 return result;
640 640
641 // 4. Reset the allocation point. 641 // 4. Reset the allocation point.
642 setAllocationPoint(nullptr, 0); 642 setAllocationPoint(nullptr, 0);
643 643
644 // 5. Lazily sweep pages of this heap until we find a freed area for 644 // 5. Lazily sweep pages of this heap until we find a freed area for
645 // this allocation or we finish sweeping all pages of this heap. 645 // this allocation or we finish sweeping all pages of this heap.
646 result = lazySweep(allocationSize, gcInfoIndex); 646 result = lazySweepPages(allocationSize, gcInfoIndex);
647 if (result) 647 if (result)
648 return result; 648 return result;
649 649
650 // 6. Coalesce promptly freed areas and then try to allocate from a free 650 // 6. Coalesce promptly freed areas and then try to allocate from a free
651 // list. 651 // list.
652 if (coalesce()) { 652 if (coalesce()) {
653 result = allocateFromFreeList(allocationSize, gcInfoIndex); 653 result = allocateFromFreeList(allocationSize, gcInfoIndex);
654 if (result) 654 if (result)
655 return result; 655 return result;
656 } 656 }
657 657
658 // 7. Complete sweeping. 658 // 7. Complete sweeping.
659 threadState()->completeSweep(); 659 threadState()->completeSweep();
660 660
661 // 8. Add a new page to this heap. 661 // 8. Add a new page to this heap.
662 allocatePage(); 662 allocatePage();
663 663
664 // 9. Try to allocate from a free list. This allocation must succeed. 664 // 9. Try to allocate from a free list. This allocation must succeed.
665 result = allocateFromFreeList(allocationSize, gcInfoIndex); 665 result = allocateFromFreeList(allocationSize, gcInfoIndex);
666 RELEASE_ASSERT(result); 666 RELEASE_ASSERT(result);
667 return result; 667 return result;
668 } 668 }
669 669
670 Address ThreadHeapForHeapPage::allocateFromFreeList(size_t allocationSize, size_ t gcInfoIndex) 670 Address ThreadHeap::allocateFromFreeList(size_t allocationSize, size_t gcInfoInd ex)
671 { 671 {
672 // Try reusing a block from the largest bin. The underlying reasoning 672 // Try reusing a block from the largest bin. The underlying reasoning
673 // being that we want to amortize this slow allocation call by carving 673 // being that we want to amortize this slow allocation call by carving
674 // off as a large a free block as possible in one go; a block that will 674 // off as a large a free block as possible in one go; a block that will
675 // service this block and let following allocations be serviced quickly 675 // service this block and let following allocations be serviced quickly
676 // by bump allocation. 676 // by bump allocation.
677 size_t bucketSize = 1 << m_freeList.m_biggestFreeListIndex; 677 size_t bucketSize = 1 << m_freeList.m_biggestFreeListIndex;
678 int index = m_freeList.m_biggestFreeListIndex; 678 int index = m_freeList.m_biggestFreeListIndex;
679 for (; index > 0; --index, bucketSize >>= 1) { 679 for (; index > 0; --index, bucketSize >>= 1) {
680 FreeListEntry* entry = m_freeList.m_freeLists[index]; 680 FreeListEntry* entry = m_freeList.m_freeLists[index];
(...skipping 14 matching lines...) Expand all
695 } 695 }
696 } 696 }
697 m_freeList.m_biggestFreeListIndex = index; 697 m_freeList.m_biggestFreeListIndex = index;
698 return nullptr; 698 return nullptr;
699 } 699 }
700 700
701 void ThreadHeap::prepareForSweep() 701 void ThreadHeap::prepareForSweep()
702 { 702 {
703 ASSERT(!threadState()->isInGC()); 703 ASSERT(!threadState()->isInGC());
704 ASSERT(!m_firstUnsweptPage); 704 ASSERT(!m_firstUnsweptPage);
705 ASSERT(!m_firstUnsweptLargeObject);
705 706
706 // Move all pages to a list of unswept pages. 707 // Move all pages to a list of unswept pages.
707 m_firstUnsweptPage = m_firstPage; 708 m_firstUnsweptPage = m_firstPage;
709 m_firstUnsweptLargeObject = m_firstLargeObject;
708 m_firstPage = nullptr; 710 m_firstPage = nullptr;
711 m_firstLargeObject = nullptr;
709 } 712 }
710 713
711 Address ThreadHeap::lazySweep(size_t allocationSize, size_t gcInfoIndex) 714 Address ThreadHeap::lazySweepPages(size_t allocationSize, size_t gcInfoIndex)
712 { 715 {
716 ASSERT(!hasCurrentAllocationArea());
717 ASSERT(allocationSize < largeObjectSizeThreshold);
718
713 // If there are no pages to be swept, return immediately. 719 // If there are no pages to be swept, return immediately.
714 if (!m_firstUnsweptPage) 720 if (!m_firstUnsweptPage)
715 return nullptr; 721 return nullptr;
716 722
717 RELEASE_ASSERT(threadState()->isSweepingInProgress()); 723 RELEASE_ASSERT(threadState()->isSweepingInProgress());
718 724
719 // lazySweepPages() can be called recursively if finalizers invoked in 725 // lazySweepPages() can be called recursively if finalizers invoked in
720 // page->sweep() allocate memory and the allocation triggers 726 // page->sweep() allocate memory and the allocation triggers
721 // lazySweepPages(). This check prevents the sweeping from being executed 727 // lazySweepPages(). This check prevents the sweeping from being executed
722 // recursively. 728 // recursively.
723 if (threadState()->sweepForbidden()) 729 if (threadState()->sweepForbidden())
724 return nullptr; 730 return nullptr;
725 731
726 TRACE_EVENT0("blink_gc", "ThreadHeap::lazySweepPages"); 732 TRACE_EVENT0("blink_gc", "ThreadHeap::lazySweepPages");
727 ThreadState::SweepForbiddenScope scope(threadState()); 733 ThreadState::SweepForbiddenScope scope(m_threadState);
728 734
729 if (threadState()->isMainThread()) 735 if (threadState()->isMainThread())
730 ScriptForbiddenScope::enter(); 736 ScriptForbiddenScope::enter();
731 737
732 Address result = lazySweepPages(allocationSize, gcInfoIndex);
733
734 if (threadState()->isMainThread())
735 ScriptForbiddenScope::exit();
736 return result;
737 }
738
739 Address ThreadHeapForHeapPage::lazySweepPages(size_t allocationSize, size_t gcIn foIndex)
740 {
741 ASSERT(!hasCurrentAllocationArea());
742 Address result = nullptr; 738 Address result = nullptr;
743 while (m_firstUnsweptPage) { 739 while (m_firstUnsweptPage) {
744 BaseHeapPage* page = m_firstUnsweptPage; 740 HeapPage* page = m_firstUnsweptPage;
745 if (page->isEmpty()) { 741 if (page->isEmpty()) {
746 page->unlink(&m_firstUnsweptPage); 742 page->unlink(&m_firstUnsweptPage);
747 page->removeFromHeap(); 743 page->removeFromHeap(this);
748 } else { 744 } else {
749 // Sweep a page and move the page from m_firstUnsweptPages to 745 // Sweep a page and move the page from m_firstUnsweptPages to
750 // m_firstPages. 746 // m_firstPages.
751 page->sweep(); 747 page->sweep();
752 page->unlink(&m_firstUnsweptPage); 748 page->unlink(&m_firstUnsweptPage);
753 page->link(&m_firstPage); 749 page->link(&m_firstPage);
754 page->markAsSwept(); 750 page->markAsSwept();
755 751
756 // For HeapPage, stop lazy sweeping once we find a slot to
757 // allocate a new object.
758 result = allocateFromFreeList(allocationSize, gcInfoIndex); 752 result = allocateFromFreeList(allocationSize, gcInfoIndex);
759 if (result) 753 if (result)
760 break; 754 break;
761 } 755 }
762 } 756 }
757
758 if (threadState()->isMainThread())
759 ScriptForbiddenScope::exit();
763 return result; 760 return result;
764 } 761 }
765 762
766 Address ThreadHeapForLargeObject::lazySweepPages(size_t allocationSize, size_t g cInfoIndex) 763 bool ThreadHeap::lazySweepLargeObjects(size_t allocationSize)
767 { 764 {
768 Address result = nullptr; 765 ASSERT(allocationSize >= largeObjectSizeThreshold);
766
767 // If there are no large objects to be swept, return immediately.
768 if (!m_firstUnsweptLargeObject)
769 return false;
770
771 RELEASE_ASSERT(threadState()->isSweepingInProgress());
772
773 // lazySweepLargeObjects() can be called recursively if finalizers invoked
774 // in page->sweep() allocate memory and the allocation triggers
775 // lazySweepLargeObjects(). This check prevents the sweeping from being
776 // executed recursively.
777 if (threadState()->sweepForbidden())
778 return false;
779
780 TRACE_EVENT0("blink_gc", "ThreadHeap::lazySweepLargeObjects");
781 ThreadState::SweepForbiddenScope scope(m_threadState);
782
783 if (threadState()->isMainThread())
784 ScriptForbiddenScope::enter();
785
786 bool result = false;
769 size_t sweptSize = 0; 787 size_t sweptSize = 0;
770 while (m_firstUnsweptPage) { 788 while (m_firstUnsweptLargeObject) {
771 BaseHeapPage* page = m_firstUnsweptPage; 789 LargeObject* largeObject = m_firstUnsweptLargeObject;
772 if (page->isEmpty()) { 790 if (largeObject->isEmpty()) {
773 sweptSize += static_cast<LargeObject*>(page)->payloadSize() + sizeof (HeapObjectHeader); 791 sweptSize += largeObject->size();
774 page->unlink(&m_firstUnsweptPage); 792 largeObject->unlink(&m_firstUnsweptLargeObject);
775 page->removeFromHeap(); 793 largeObject->removeFromHeap(this);
776 // For LargeObject, stop lazy sweeping once we have swept 794
777 // more than allocationSize bytes. 795 // If we have swept large objects more than allocationSize,
796 // we stop the lazy sweeping.
778 if (sweptSize >= allocationSize) { 797 if (sweptSize >= allocationSize) {
779 result = doAllocateLargeObject(allocationSize, gcInfoIndex); 798 result = true;
780 ASSERT(result);
781 break; 799 break;
782 } 800 }
783 } else { 801 } else {
802 // Sweep a large object and move the large object from
803 // m_firstUnsweptLargeObjects to m_firstLargeObjects.
804 largeObject->sweep();
805 largeObject->unlink(&m_firstUnsweptLargeObject);
806 largeObject->link(&m_firstLargeObject);
807 largeObject->markAsSwept();
808 }
809 }
810
811 if (threadState()->isMainThread())
812 ScriptForbiddenScope::exit();
813 return result;
814 }
815
816 void ThreadHeap::completeSweep()
817 {
818 RELEASE_ASSERT(threadState()->isSweepingInProgress());
819 ASSERT(threadState()->sweepForbidden());
820
821 if (threadState()->isMainThread())
822 ScriptForbiddenScope::enter();
823
824 // Sweep normal pages.
825 while (m_firstUnsweptPage) {
826 HeapPage* page = m_firstUnsweptPage;
827 if (page->isEmpty()) {
828 page->unlink(&m_firstUnsweptPage);
829 page->removeFromHeap(this);
830 } else {
784 // Sweep a page and move the page from m_firstUnsweptPages to 831 // Sweep a page and move the page from m_firstUnsweptPages to
785 // m_firstPages. 832 // m_firstPages.
786 page->sweep(); 833 page->sweep();
787 page->unlink(&m_firstUnsweptPage); 834 page->unlink(&m_firstUnsweptPage);
788 page->link(&m_firstPage); 835 page->link(&m_firstPage);
789 page->markAsSwept(); 836 page->markAsSwept();
790 } 837 }
791 } 838 }
792 return result;
793 }
794
795 void ThreadHeap::completeSweep()
796 {
797 RELEASE_ASSERT(threadState()->isSweepingInProgress());
798 ASSERT(threadState()->sweepForbidden());
799
800 if (threadState()->isMainThread())
801 ScriptForbiddenScope::enter();
802
803 while (m_firstUnsweptPage) {
804 BaseHeapPage* page = m_firstUnsweptPage;
805 if (page->isEmpty()) {
806 page->unlink(&m_firstUnsweptPage);
807 page->removeFromHeap();
808 } else {
809 // Sweep a page and move the page from m_firstUnsweptPages to
810 // m_firstPages.
811 page->sweep();
812 page->unlink(&m_firstUnsweptPage);
813 page->link(&m_firstPage);
814 page->markAsSwept();
815 }
816 }
817 839
840 // Sweep large objects.
841 while (m_firstUnsweptLargeObject) {
842 LargeObject* largeObject = m_firstUnsweptLargeObject;
843 if (largeObject->isEmpty()) {
844 largeObject->unlink(&m_firstUnsweptLargeObject);
845 largeObject->removeFromHeap(this);
846 } else {
847 // Sweep a large object and move the large object from
848 // m_firstUnsweptLargeObjects to m_firstLargeObjects.
849 largeObject->sweep();
850 largeObject->unlink(&m_firstUnsweptLargeObject);
851 largeObject->link(&m_firstLargeObject);
852 largeObject->markAsSwept();
853 }
854 }
855
818 if (threadState()->isMainThread()) 856 if (threadState()->isMainThread())
819 ScriptForbiddenScope::exit(); 857 ScriptForbiddenScope::exit();
820 } 858 }
821 859
822 #if ENABLE(ASSERT) 860 #if ENABLE(ASSERT)
861 static bool isLargeObjectAligned(LargeObject* largeObject, Address address)
862 {
863 // Check that a large object is blinkPageSize aligned (modulo the osPageSize
864 // for the guard page).
865 return reinterpret_cast<Address>(largeObject) - WTF::kSystemPageSize == roun dToBlinkPageStart(reinterpret_cast<Address>(largeObject));
866 }
867 #endif
868
869 #if ENABLE(ASSERT) || ENABLE(GC_PROFILING)
823 BaseHeapPage* ThreadHeap::findPageFromAddress(Address address) 870 BaseHeapPage* ThreadHeap::findPageFromAddress(Address address)
824 { 871 {
825 for (BaseHeapPage* page = m_firstPage; page; page = page->next()) { 872 for (HeapPage* page = m_firstPage; page; page = page->next()) {
826 if (page->contains(address)) 873 if (page->contains(address))
827 return page; 874 return page;
828 } 875 }
829 for (BaseHeapPage* page = m_firstUnsweptPage; page; page = page->next()) { 876 for (HeapPage* page = m_firstUnsweptPage; page; page = page->next()) {
830 if (page->contains(address)) 877 if (page->contains(address))
831 return page; 878 return page;
832 } 879 }
880 for (LargeObject* largeObject = m_firstLargeObject; largeObject; largeObject = largeObject->next()) {
881 ASSERT(isLargeObjectAligned(largeObject, address));
882 if (largeObject->contains(address))
883 return largeObject;
884 }
885 for (LargeObject* largeObject = m_firstUnsweptLargeObject; largeObject; larg eObject = largeObject->next()) {
886 ASSERT(isLargeObjectAligned(largeObject, address));
887 if (largeObject->contains(address))
888 return largeObject;
889 }
833 return nullptr; 890 return nullptr;
834 } 891 }
835 #endif 892 #endif
836 893
837 #if ENABLE(GC_PROFILING) 894 #if ENABLE(GC_PROFILING)
838 #define GC_PROFILE_HEAP_PAGE_SNAPSHOT_THRESHOLD 0 895 #define GC_PROFILE_HEAP_PAGE_SNAPSHOT_THRESHOLD 0
839 void ThreadHeap::snapshot(TracedValue* json, ThreadState::SnapshotInfo* info) 896 void ThreadHeap::snapshot(TracedValue* json, ThreadState::SnapshotInfo* info)
840 { 897 {
841 ASSERT(isConsistentForSweeping()); 898 ASSERT(isConsistentForSweeping());
842 size_t previousPageCount = info->pageCount; 899 size_t previousPageCount = info->pageCount;
843 900
844 json->beginArray("pages"); 901 json->beginArray("pages");
845 for (BaseHeapPage* page = m_firstPage; page; page = page->next(), ++info->pa geCount) { 902 for (HeapPage* page = m_firstPage; page; page = page->next(), ++info->pageCo unt) {
846 // FIXME: To limit the size of the snapshot we only output "threshold" m any page snapshots. 903 // FIXME: To limit the size of the snapshot we only output "threshold" m any page snapshots.
847 if (info->pageCount < GC_PROFILE_HEAP_PAGE_SNAPSHOT_THRESHOLD) { 904 if (info->pageCount < GC_PROFILE_HEAP_PAGE_SNAPSHOT_THRESHOLD) {
848 json->beginArray(); 905 json->beginArray();
849 json->pushInteger(reinterpret_cast<intptr_t>(page)); 906 json->pushInteger(reinterpret_cast<intptr_t>(page));
850 page->snapshot(json, info); 907 page->snapshot(json, info);
851 json->endArray(); 908 json->endArray();
852 } else { 909 } else {
853 page->snapshot(0, info); 910 page->snapshot(0, info);
854 } 911 }
855 } 912 }
856 json->endArray(); 913 json->endArray();
857 914
915 json->beginArray("largeObjects");
916 for (LargeObject* largeObject = m_firstLargeObject; largeObject; largeObject = largeObject->next()) {
917 json->beginDictionary();
918 largeObject->snapshot(json, info);
919 json->endDictionary();
920 }
921 json->endArray();
922
858 json->setInteger("pageCount", info->pageCount - previousPageCount); 923 json->setInteger("pageCount", info->pageCount - previousPageCount);
859 } 924 }
860 925
861 void ThreadHeap::incrementMarkedObjectsAge() 926 void ThreadHeap::incrementMarkedObjectsAge()
862 { 927 {
863 for (HeapPage* page = m_firstPage; page; page = page->next()) 928 for (HeapPage* page = m_firstPage; page; page = page->next())
864 page->incrementMarkedObjectsAge(); 929 page->incrementMarkedObjectsAge();
865 for (LargeObject* largeObject = m_firstLargeObject; largeObject; largeObject = largeObject->next()) 930 for (LargeObject* largeObject = m_firstLargeObject; largeObject; largeObject = largeObject->next())
866 largeObject->incrementMarkedObjectsAge(); 931 largeObject->incrementMarkedObjectsAge();
867 } 932 }
(...skipping 26 matching lines...) Expand all
894 // space. 959 // space.
895 if (static_cast<HeapPage*>(page)->payloadSize() != size && !entry->shouldAdd ToFreeList()) 960 if (static_cast<HeapPage*>(page)->payloadSize() != size && !entry->shouldAdd ToFreeList())
896 return; 961 return;
897 #endif 962 #endif
898 int index = bucketIndexForSize(size); 963 int index = bucketIndexForSize(size);
899 entry->link(&m_freeLists[index]); 964 entry->link(&m_freeLists[index]);
900 if (index > m_biggestFreeListIndex) 965 if (index > m_biggestFreeListIndex)
901 m_biggestFreeListIndex = index; 966 m_biggestFreeListIndex = index;
902 } 967 }
903 968
904 bool ThreadHeapForHeapPage::expandObject(HeapObjectHeader* header, size_t newSiz e) 969 bool ThreadHeap::expandObject(HeapObjectHeader* header, size_t newSize)
905 { 970 {
906 // It's possible that Vector requests a smaller expanded size because 971 // It's possible that Vector requests a smaller expanded size because
907 // Vector::shrinkCapacity can set a capacity smaller than the actual payload 972 // Vector::shrinkCapacity can set a capacity smaller than the actual payload
908 // size. 973 // size.
909 if (header->payloadSize() >= newSize) 974 if (header->payloadSize() >= newSize)
910 return true; 975 return true;
911 size_t allocationSize = allocationSizeFromSize(newSize); 976 size_t allocationSize = allocationSizeFromSize(newSize);
912 ASSERT(allocationSize > header->size()); 977 ASSERT(allocationSize > header->size());
913 size_t expandSize = allocationSize - header->size(); 978 size_t expandSize = allocationSize - header->size();
914 if (header->payloadEnd() == m_currentAllocationPoint && expandSize <= m_rema iningAllocationSize) { 979 if (header->payloadEnd() == m_currentAllocationPoint && expandSize <= m_rema iningAllocationSize) {
915 m_currentAllocationPoint += expandSize; 980 m_currentAllocationPoint += expandSize;
916 m_remainingAllocationSize -= expandSize; 981 m_remainingAllocationSize -= expandSize;
917 982
918 // Unpoison the memory used for the object (payload). 983 // Unpoison the memory used for the object (payload).
919 ASAN_UNPOISON_MEMORY_REGION(header->payloadEnd(), expandSize); 984 ASAN_UNPOISON_MEMORY_REGION(header->payloadEnd(), expandSize);
920 FILL_ZERO_IF_NOT_PRODUCTION(header->payloadEnd(), expandSize); 985 FILL_ZERO_IF_NOT_PRODUCTION(header->payloadEnd(), expandSize);
921 header->setSize(allocationSize); 986 header->setSize(allocationSize);
922 ASSERT(findPageFromAddress(header->payloadEnd() - 1)); 987 ASSERT(findPageFromAddress(header->payloadEnd() - 1));
923 return true; 988 return true;
924 } 989 }
925 return false; 990 return false;
926 } 991 }
927 992
928 void ThreadHeapForHeapPage::shrinkObject(HeapObjectHeader* header, size_t newSiz e) 993 void ThreadHeap::shrinkObject(HeapObjectHeader* header, size_t newSize)
929 { 994 {
930 ASSERT(header->payloadSize() > newSize); 995 ASSERT(header->payloadSize() > newSize);
931 size_t allocationSize = allocationSizeFromSize(newSize); 996 size_t allocationSize = allocationSizeFromSize(newSize);
932 ASSERT(header->size() > allocationSize); 997 ASSERT(header->size() > allocationSize);
933 size_t shrinkSize = header->size() - allocationSize; 998 size_t shrinkSize = header->size() - allocationSize;
934 if (header->payloadEnd() == m_currentAllocationPoint) { 999 if (header->payloadEnd() == m_currentAllocationPoint) {
935 m_currentAllocationPoint -= shrinkSize; 1000 m_currentAllocationPoint -= shrinkSize;
936 m_remainingAllocationSize += shrinkSize; 1001 m_remainingAllocationSize += shrinkSize;
937 FILL_ZERO_IF_PRODUCTION(m_currentAllocationPoint, shrinkSize); 1002 FILL_ZERO_IF_PRODUCTION(m_currentAllocationPoint, shrinkSize);
938 ASAN_POISON_MEMORY_REGION(m_currentAllocationPoint, shrinkSize); 1003 ASAN_POISON_MEMORY_REGION(m_currentAllocationPoint, shrinkSize);
939 header->setSize(allocationSize); 1004 header->setSize(allocationSize);
940 } else { 1005 } else {
941 ASSERT(shrinkSize >= sizeof(HeapObjectHeader)); 1006 ASSERT(shrinkSize >= sizeof(HeapObjectHeader));
942 ASSERT(header->gcInfoIndex() > 0); 1007 ASSERT(header->gcInfoIndex() > 0);
943 HeapObjectHeader* freedHeader = new (NotNull, header->payloadEnd() - shr inkSize) HeapObjectHeader(shrinkSize, header->gcInfoIndex()); 1008 HeapObjectHeader* freedHeader = new (NotNull, header->payloadEnd() - shr inkSize) HeapObjectHeader(shrinkSize, header->gcInfoIndex());
944 freedHeader->markPromptlyFreed(); 1009 freedHeader->markPromptlyFreed();
945 ASSERT(pageFromObject(reinterpret_cast<Address>(header)) == findPageFrom Address(reinterpret_cast<Address>(header))); 1010 ASSERT(pageFromObject(reinterpret_cast<Address>(header)) == findPageFrom Address(reinterpret_cast<Address>(header)));
946 m_promptlyFreedSize += shrinkSize; 1011 m_promptlyFreedSize += shrinkSize;
947 header->setSize(allocationSize); 1012 header->setSize(allocationSize);
948 } 1013 }
949 } 1014 }
950 1015
951 void ThreadHeapForHeapPage::promptlyFreeObject(HeapObjectHeader* header) 1016 void ThreadHeap::promptlyFreeObject(HeapObjectHeader* header)
952 { 1017 {
953 ASSERT(!threadState()->sweepForbidden()); 1018 ASSERT(!m_threadState->sweepForbidden());
954 header->checkHeader(); 1019 header->checkHeader();
955 Address address = reinterpret_cast<Address>(header); 1020 Address address = reinterpret_cast<Address>(header);
956 Address payload = header->payload(); 1021 Address payload = header->payload();
957 size_t size = header->size(); 1022 size_t size = header->size();
958 size_t payloadSize = header->payloadSize(); 1023 size_t payloadSize = header->payloadSize();
959 ASSERT(size > 0); 1024 ASSERT(size > 0);
960 ASSERT(pageFromObject(address) == findPageFromAddress(address)); 1025 ASSERT(pageFromObject(address) == findPageFromAddress(address));
961 1026
962 { 1027 {
963 ThreadState::SweepForbiddenScope forbiddenScope(threadState()); 1028 ThreadState::SweepForbiddenScope forbiddenScope(m_threadState);
964 header->finalize(payload, payloadSize); 1029 header->finalize(payload, payloadSize);
965 if (address + size == m_currentAllocationPoint) { 1030 if (address + size == m_currentAllocationPoint) {
966 m_currentAllocationPoint = address; 1031 m_currentAllocationPoint = address;
967 if (m_lastRemainingAllocationSize == m_remainingAllocationSize) { 1032 if (m_lastRemainingAllocationSize == m_remainingAllocationSize) {
968 Heap::decreaseAllocatedObjectSize(size); 1033 Heap::decreaseAllocatedObjectSize(size);
969 m_lastRemainingAllocationSize += size; 1034 m_lastRemainingAllocationSize += size;
970 } 1035 }
971 m_remainingAllocationSize += size; 1036 m_remainingAllocationSize += size;
972 FILL_ZERO_IF_PRODUCTION(address, size); 1037 FILL_ZERO_IF_PRODUCTION(address, size);
973 ASAN_POISON_MEMORY_REGION(address, size); 1038 ASAN_POISON_MEMORY_REGION(address, size);
974 return; 1039 return;
975 } 1040 }
976 FILL_ZERO_IF_PRODUCTION(payload, payloadSize); 1041 FILL_ZERO_IF_PRODUCTION(payload, payloadSize);
977 header->markPromptlyFreed(); 1042 header->markPromptlyFreed();
978 } 1043 }
979 1044
980 m_promptlyFreedSize += size; 1045 m_promptlyFreedSize += size;
981 } 1046 }
982 1047
983 bool ThreadHeapForHeapPage::coalesce() 1048 bool ThreadHeap::coalesce()
984 { 1049 {
985 // Don't coalesce heaps if there are not enough promptly freed entries 1050 // Don't coalesce heaps if there are not enough promptly freed entries
986 // to be coalesced. 1051 // to be coalesced.
987 // 1052 //
988 // FIXME: This threshold is determined just to optimize blink_perf 1053 // FIXME: This threshold is determined just to optimize blink_perf
989 // benchmarks. Coalescing is very sensitive to the threashold and 1054 // benchmarks. Coalescing is very sensitive to the threashold and
990 // we need further investigations on the coalescing scheme. 1055 // we need further investigations on the coalescing scheme.
991 if (m_promptlyFreedSize < 1024 * 1024) 1056 if (m_promptlyFreedSize < 1024 * 1024)
992 return false; 1057 return false;
993 1058
994 if (threadState()->sweepForbidden()) 1059 if (m_threadState->sweepForbidden())
995 return false; 1060 return false;
996 1061
997 ASSERT(!hasCurrentAllocationArea()); 1062 ASSERT(!hasCurrentAllocationArea());
998 TRACE_EVENT0("blink_gc", "ThreadHeap::coalesce"); 1063 TRACE_EVENT0("blink_gc", "ThreadHeap::coalesce");
999 1064
1000 // Rebuild free lists. 1065 // Rebuild free lists.
1001 m_freeList.clear(); 1066 m_freeList.clear();
1002 size_t freedSize = 0; 1067 size_t freedSize = 0;
1003 for (HeapPage* page = static_cast<HeapPage*>(m_firstPage); page; page = stat ic_cast<HeapPage*>(page->next())) { 1068 for (HeapPage* page = m_firstPage; page; page = page->next()) {
1004 page->clearObjectStartBitMap(); 1069 page->clearObjectStartBitMap();
1005 Address startOfGap = page->payload(); 1070 Address startOfGap = page->payload();
1006 for (Address headerAddress = startOfGap; headerAddress < page->payloadEn d(); ) { 1071 for (Address headerAddress = startOfGap; headerAddress < page->payloadEn d(); ) {
1007 HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(heade rAddress); 1072 HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(heade rAddress);
1008 size_t size = header->size(); 1073 size_t size = header->size();
1009 ASSERT(size > 0); 1074 ASSERT(size > 0);
1010 ASSERT(size < blinkPagePayloadSize()); 1075 ASSERT(size < blinkPagePayloadSize());
1011 1076
1012 if (header->isPromptlyFreed()) { 1077 if (header->isPromptlyFreed()) {
1013 ASSERT(size >= sizeof(HeapObjectHeader)); 1078 ASSERT(size >= sizeof(HeapObjectHeader));
(...skipping 20 matching lines...) Expand all
1034 1099
1035 if (startOfGap != page->payloadEnd()) 1100 if (startOfGap != page->payloadEnd())
1036 addToFreeList(startOfGap, page->payloadEnd() - startOfGap); 1101 addToFreeList(startOfGap, page->payloadEnd() - startOfGap);
1037 } 1102 }
1038 Heap::decreaseAllocatedObjectSize(freedSize); 1103 Heap::decreaseAllocatedObjectSize(freedSize);
1039 ASSERT(m_promptlyFreedSize == freedSize); 1104 ASSERT(m_promptlyFreedSize == freedSize);
1040 m_promptlyFreedSize = 0; 1105 m_promptlyFreedSize = 0;
1041 return true; 1106 return true;
1042 } 1107 }
1043 1108
1044 Address ThreadHeapForLargeObject::allocateLargeObject(size_t allocationSize, siz e_t gcInfoIndex) 1109 Address ThreadHeap::allocateLargeObject(size_t size, size_t gcInfoIndex)
1045 { 1110 {
1046 // Caller already added space for object header and rounded up to allocation 1111 // Caller already added space for object header and rounded up to allocation
1047 // alignment 1112 // alignment
1048 ASSERT(!(allocationSize & allocationMask)); 1113 ASSERT(!(size & allocationMask));
1114
1115 size_t allocationSize = sizeof(LargeObject) + size;
1116
1117 // Ensure that there is enough space for alignment. If the header
1118 // is not a multiple of 8 bytes we will allocate an extra
1119 // headerPadding bytes to ensure it 8 byte aligned.
1120 allocationSize += headerPadding();
1121
1122 // If ASan is supported we add allocationGranularity bytes to the allocated
1123 // space and poison that to detect overflows
1124 #if defined(ADDRESS_SANITIZER)
1125 allocationSize += allocationGranularity;
1126 #endif
1049 1127
1050 // 1. Check if we should trigger a GC. 1128 // 1. Check if we should trigger a GC.
1051 threadState()->scheduleGCIfNeeded(); 1129 updateRemainingAllocationSize();
1130 m_threadState->scheduleGCIfNeeded();
1052 1131
1053 // 2. Try to sweep large objects more than allocationSize bytes 1132 // 2. Try to sweep large objects more than allocationSize bytes
1054 // before allocating a new large object. 1133 // before allocating a new large object.
1055 Address result = lazySweep(allocationSize, gcInfoIndex); 1134 if (!lazySweepLargeObjects(allocationSize)) {
1056 if (result) 1135 // 3. If we have failed in sweeping allocationSize bytes,
1057 return result; 1136 // we complete sweeping before allocating this large object.
1137 m_threadState->completeSweep();
1138 }
1058 1139
1059 // 3. If we have failed in sweeping allocationSize bytes, 1140 m_threadState->shouldFlushHeapDoesNotContainCache();
1060 // we complete sweeping before allocating this large object. 1141 PageMemory* pageMemory = PageMemory::allocate(allocationSize);
1061 threadState()->completeSweep(); 1142 m_threadState->allocatedRegionsSinceLastGC().append(pageMemory->region());
1062 return doAllocateLargeObject(allocationSize, gcInfoIndex);
1063 }
1064
1065 Address ThreadHeapForLargeObject::doAllocateLargeObject(size_t allocationSize, s ize_t gcInfoIndex)
1066 {
1067 size_t largeObjectSize = sizeof(LargeObject) + LargeObject::headerPadding() + allocationSize;
1068 // If ASan is supported we add allocationGranularity bytes to the allocated
1069 // space and poison that to detect overflows
1070 #if defined(ADDRESS_SANITIZER)
1071 largeObjectSize += allocationGranularity;
1072 #endif
1073
1074 threadState()->shouldFlushHeapDoesNotContainCache();
1075 PageMemory* pageMemory = PageMemory::allocate(largeObjectSize);
1076 threadState()->allocatedRegionsSinceLastGC().append(pageMemory->region());
1077 Address largeObjectAddress = pageMemory->writableStart(); 1143 Address largeObjectAddress = pageMemory->writableStart();
1078 Address headerAddress = largeObjectAddress + sizeof(LargeObject) + LargeObje ct::headerPadding(); 1144 Address headerAddress = largeObjectAddress + sizeof(LargeObject) + headerPad ding();
1079 #if ENABLE(ASSERT) 1145 #if ENABLE(ASSERT)
1080 // Verify that the allocated PageMemory is expectedly zeroed. 1146 // Verify that the allocated PageMemory is expectedly zeroed.
1081 for (size_t i = 0; i < largeObjectSize; ++i) 1147 for (size_t i = 0; i < size; ++i)
1082 ASSERT(!headerAddress[i]); 1148 ASSERT(!headerAddress[i]);
1083 #endif 1149 #endif
1084 ASSERT(gcInfoIndex > 0); 1150 ASSERT(gcInfoIndex > 0);
1085 HeapObjectHeader* header = new (NotNull, headerAddress) HeapObjectHeader(lar geObjectSizeInHeader, gcInfoIndex); 1151 HeapObjectHeader* header = new (NotNull, headerAddress) HeapObjectHeader(lar geObjectSizeInHeader, gcInfoIndex);
1086 Address result = headerAddress + sizeof(*header); 1152 Address result = headerAddress + sizeof(*header);
1087 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask)); 1153 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask));
1088 LargeObject* largeObject = new (largeObjectAddress) LargeObject(pageMemory, this, allocationSize); 1154 LargeObject* largeObject = new (largeObjectAddress) LargeObject(pageMemory, this, size);
1089 header->checkHeader(); 1155 header->checkHeader();
1090 1156
1091 // Poison the object header and allocationGranularity bytes after the object 1157 // Poison the object header and allocationGranularity bytes after the object
1092 ASAN_POISON_MEMORY_REGION(header, sizeof(*header)); 1158 ASAN_POISON_MEMORY_REGION(header, sizeof(*header));
1093 ASAN_POISON_MEMORY_REGION(largeObject->address() + largeObject->size(), allo cationGranularity); 1159 ASAN_POISON_MEMORY_REGION(largeObject->address() + largeObject->size(), allo cationGranularity);
1094 1160
1095 largeObject->link(&m_firstPage); 1161 largeObject->link(&m_firstLargeObject);
1096 1162
1097 Heap::increaseAllocatedSpace(largeObject->size()); 1163 Heap::increaseAllocatedSpace(largeObject->size());
1098 Heap::increaseAllocatedObjectSize(largeObject->size()); 1164 Heap::increaseAllocatedObjectSize(largeObject->size());
1099 return result; 1165 return result;
1100 } 1166 }
1101 1167
1102 void ThreadHeapForLargeObject::freeLargeObject(LargeObject* object) 1168 void ThreadHeap::freeLargeObject(LargeObject* object)
1103 { 1169 {
1104 object->heapObjectHeader()->finalize(object->payload(), object->payloadSize( )); 1170 object->heapObjectHeader()->finalize(object->payload(), object->payloadSize( ));
1105 Heap::decreaseAllocatedSpace(object->size()); 1171 Heap::decreaseAllocatedSpace(object->size());
1106 1172
1107 // Unpoison the object header and allocationGranularity bytes after the 1173 // Unpoison the object header and allocationGranularity bytes after the
1108 // object before freeing. 1174 // object before freeing.
1109 ASAN_UNPOISON_MEMORY_REGION(object->heapObjectHeader(), sizeof(HeapObjectHea der)); 1175 ASAN_UNPOISON_MEMORY_REGION(object->heapObjectHeader(), sizeof(HeapObjectHea der));
1110 ASAN_UNPOISON_MEMORY_REGION(object->address() + object->size(), allocationGr anularity); 1176 ASAN_UNPOISON_MEMORY_REGION(object->address() + object->size(), allocationGr anularity);
1111 1177
1112 if (object->terminating()) { 1178 if (object->terminating()) {
1113 ASSERT(ThreadState::current()->isTerminating()); 1179 ASSERT(ThreadState::current()->isTerminating());
1114 // The thread is shutting down and this page is being removed as a part 1180 // The thread is shutting down and this page is being removed as a part
1115 // of the thread local GC. In that case the object could be traced in 1181 // of the thread local GC. In that case the object could be traced in
1116 // the next global GC if there is a dangling pointer from a live thread 1182 // the next global GC if there is a dangling pointer from a live thread
1117 // heap to this dead thread heap. To guard against this, we put the 1183 // heap to this dead thread heap. To guard against this, we put the
1118 // page into the orphaned page pool and zap the page memory. This 1184 // page into the orphaned page pool and zap the page memory. This
1119 // ensures that tracing the dangling pointer in the next global GC just 1185 // ensures that tracing the dangling pointer in the next global GC just
1120 // crashes instead of causing use-after-frees. After the next global 1186 // crashes instead of causing use-after-frees. After the next global
1121 // GC, the orphaned pages are removed. 1187 // GC, the orphaned pages are removed.
1122 Heap::orphanedPagePool()->addOrphanedPage(heapIndex(), object); 1188 Heap::orphanedPagePool()->addOrphanedPage(m_index, object);
1123 } else { 1189 } else {
1124 ASSERT(!ThreadState::current()->isTerminating()); 1190 ASSERT(!ThreadState::current()->isTerminating());
1125 PageMemory* memory = object->storage(); 1191 PageMemory* memory = object->storage();
1126 object->~LargeObject(); 1192 object->~LargeObject();
1127 delete memory; 1193 delete memory;
1128 } 1194 }
1129 } 1195 }
1130 1196
1131 template<typename DataType> 1197 template<typename DataType>
1132 PagePool<DataType>::PagePool() 1198 PagePool<DataType>::PagePool()
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1173 1239
1174 // We got some memory, but failed to commit it, try again. 1240 // We got some memory, but failed to commit it, try again.
1175 delete memory; 1241 delete memory;
1176 } 1242 }
1177 return nullptr; 1243 return nullptr;
1178 } 1244 }
1179 1245
1180 BaseHeapPage::BaseHeapPage(PageMemory* storage, ThreadHeap* heap) 1246 BaseHeapPage::BaseHeapPage(PageMemory* storage, ThreadHeap* heap)
1181 : m_storage(storage) 1247 : m_storage(storage)
1182 , m_heap(heap) 1248 , m_heap(heap)
1183 , m_next(nullptr)
1184 , m_terminating(false) 1249 , m_terminating(false)
1185 , m_swept(true) 1250 , m_swept(true)
1186 { 1251 {
1187 ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this))); 1252 ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this)));
1188 } 1253 }
1189 1254
1190 void BaseHeapPage::markOrphaned() 1255 void BaseHeapPage::markOrphaned()
1191 { 1256 {
1192 m_heap = nullptr; 1257 m_heap = nullptr;
1193 m_terminating = false; 1258 m_terminating = false;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1279 for (PoolEntry* entry = m_pool[index]; entry; entry = entry->next) { 1344 for (PoolEntry* entry = m_pool[index]; entry; entry = entry->next) {
1280 BaseHeapPage* page = entry->data; 1345 BaseHeapPage* page = entry->data;
1281 if (page->contains(reinterpret_cast<Address>(object))) 1346 if (page->contains(reinterpret_cast<Address>(object)))
1282 return true; 1347 return true;
1283 } 1348 }
1284 } 1349 }
1285 return false; 1350 return false;
1286 } 1351 }
1287 #endif 1352 #endif
1288 1353
1289 void ThreadHeapForHeapPage::freePage(HeapPage* page) 1354 void ThreadHeap::freePage(HeapPage* page)
1290 { 1355 {
1291 Heap::decreaseAllocatedSpace(page->size()); 1356 Heap::decreaseAllocatedSpace(blinkPageSize);
1292 1357
1293 if (page->terminating()) { 1358 if (page->terminating()) {
1294 // The thread is shutting down and this page is being removed as a part 1359 // The thread is shutting down and this page is being removed as a part
1295 // of the thread local GC. In that case the object could be traced in 1360 // of the thread local GC. In that case the object could be traced in
1296 // the next global GC if there is a dangling pointer from a live thread 1361 // the next global GC if there is a dangling pointer from a live thread
1297 // heap to this dead thread heap. To guard against this, we put the 1362 // heap to this dead thread heap. To guard against this, we put the
1298 // page into the orphaned page pool and zap the page memory. This 1363 // page into the orphaned page pool and zap the page memory. This
1299 // ensures that tracing the dangling pointer in the next global GC just 1364 // ensures that tracing the dangling pointer in the next global GC just
1300 // crashes instead of causing use-after-frees. After the next global 1365 // crashes instead of causing use-after-frees. After the next global
1301 // GC, the orphaned pages are removed. 1366 // GC, the orphaned pages are removed.
1302 Heap::orphanedPagePool()->addOrphanedPage(heapIndex(), page); 1367 Heap::orphanedPagePool()->addOrphanedPage(m_index, page);
1303 } else { 1368 } else {
1304 PageMemory* memory = page->storage(); 1369 PageMemory* memory = page->storage();
1305 page->~HeapPage(); 1370 page->~HeapPage();
1306 Heap::freePagePool()->addFreePage(heapIndex(), memory); 1371 Heap::freePagePool()->addFreePage(m_index, memory);
1307 } 1372 }
1308 } 1373 }
1309 1374
1310 void ThreadHeapForHeapPage::allocatePage() 1375 void ThreadHeap::allocatePage()
1311 { 1376 {
1312 threadState()->shouldFlushHeapDoesNotContainCache(); 1377 m_threadState->shouldFlushHeapDoesNotContainCache();
1313 PageMemory* pageMemory = Heap::freePagePool()->takeFreePage(heapIndex()); 1378 PageMemory* pageMemory = Heap::freePagePool()->takeFreePage(m_index);
1314 // We continue allocating page memory until we succeed in committing one. 1379 // We continue allocating page memory until we succeed in committing one.
1315 while (!pageMemory) { 1380 while (!pageMemory) {
1316 // Allocate a memory region for blinkPagesPerRegion pages that 1381 // Allocate a memory region for blinkPagesPerRegion pages that
1317 // will each have the following layout. 1382 // will each have the following layout.
1318 // 1383 //
1319 // [ guard os page | ... payload ... | guard os page ] 1384 // [ guard os page | ... payload ... | guard os page ]
1320 // ^---{ aligned to blink page size } 1385 // ^---{ aligned to blink page size }
1321 PageMemoryRegion* region = PageMemoryRegion::allocateNormalPages(); 1386 PageMemoryRegion* region = PageMemoryRegion::allocateNormalPages();
1322 threadState()->allocatedRegionsSinceLastGC().append(region); 1387 m_threadState->allocatedRegionsSinceLastGC().append(region);
1323 1388
1324 // Setup the PageMemory object for each of the pages in the region. 1389 // Setup the PageMemory object for each of the pages in the region.
1325 size_t offset = 0; 1390 size_t offset = 0;
1326 for (size_t i = 0; i < blinkPagesPerRegion; ++i) { 1391 for (size_t i = 0; i < blinkPagesPerRegion; ++i) {
1327 PageMemory* memory = PageMemory::setupPageMemoryInRegion(region, off set, blinkPagePayloadSize()); 1392 PageMemory* memory = PageMemory::setupPageMemoryInRegion(region, off set, blinkPagePayloadSize());
1328 // Take the first possible page ensuring that this thread actually 1393 // Take the first possible page ensuring that this thread actually
1329 // gets a page and add the rest to the page pool. 1394 // gets a page and add the rest to the page pool.
1330 if (!pageMemory) { 1395 if (!pageMemory) {
1331 if (memory->commit()) 1396 if (memory->commit())
1332 pageMemory = memory; 1397 pageMemory = memory;
1333 else 1398 else
1334 delete memory; 1399 delete memory;
1335 } else { 1400 } else {
1336 Heap::freePagePool()->addFreePage(heapIndex(), memory); 1401 Heap::freePagePool()->addFreePage(m_index, memory);
1337 } 1402 }
1338 offset += blinkPageSize; 1403 offset += blinkPageSize;
1339 } 1404 }
1340 } 1405 }
1341 HeapPage* page = new (pageMemory->writableStart()) HeapPage(pageMemory, this ); 1406 HeapPage* page = new (pageMemory->writableStart()) HeapPage(pageMemory, this );
1407
1342 page->link(&m_firstPage); 1408 page->link(&m_firstPage);
1343 1409
1344 Heap::increaseAllocatedSpace(page->size()); 1410 Heap::increaseAllocatedSpace(blinkPageSize);
1345 addToFreeList(page->payload(), page->payloadSize()); 1411 addToFreeList(page->payload(), page->payloadSize());
1346 } 1412 }
1347 1413
1348 #if ENABLE(ASSERT) 1414 #if ENABLE(ASSERT)
1349 bool ThreadHeapForHeapPage::pagesToBeSweptContains(Address address) 1415 bool ThreadHeap::pagesToBeSweptContains(Address address)
1350 { 1416 {
1351 for (BaseHeapPage* page = m_firstUnsweptPage; page; page = page->next()) { 1417 for (HeapPage* page = m_firstUnsweptPage; page; page = page->next()) {
1352 if (page->contains(address)) 1418 if (page->contains(address))
1353 return true; 1419 return true;
1354 } 1420 }
1355 return false; 1421 return false;
1356 } 1422 }
1357 #endif 1423 #endif
1358 1424
1359 size_t ThreadHeap::objectPayloadSizeForTesting() 1425 size_t ThreadHeap::objectPayloadSizeForTesting()
1360 { 1426 {
1361 ASSERT(isConsistentForSweeping()); 1427 ASSERT(isConsistentForSweeping());
1362 ASSERT(!m_firstUnsweptPage); 1428 ASSERT(!m_firstUnsweptPage);
1429 ASSERT(!m_firstUnsweptLargeObject);
1363 1430
1364 size_t objectPayloadSize = 0; 1431 size_t objectPayloadSize = 0;
1365 for (BaseHeapPage* page = m_firstPage; page; page = page->next()) 1432 for (HeapPage* page = m_firstPage; page; page = page->next())
1366 objectPayloadSize += page->objectPayloadSizeForTesting(); 1433 objectPayloadSize += page->objectPayloadSizeForTesting();
1434 for (LargeObject* largeObject = m_firstLargeObject; largeObject; largeObject = largeObject->next())
1435 objectPayloadSize += largeObject->objectPayloadSizeForTesting();
1367 return objectPayloadSize; 1436 return objectPayloadSize;
1368 } 1437 }
1369 1438
1370 #if ENABLE(ASSERT) 1439 #if ENABLE(ASSERT)
1371 bool ThreadHeapForHeapPage::isConsistentForSweeping() 1440 bool ThreadHeap::isConsistentForSweeping()
1372 { 1441 {
1373 // A thread heap is consistent for sweeping if none of the pages to be swept 1442 // A thread heap is consistent for sweeping if none of the pages to be swept
1374 // contain a freelist block or the current allocation point. 1443 // contain a freelist block or the current allocation point.
1375 for (size_t i = 0; i < blinkPageSizeLog2; ++i) { 1444 for (size_t i = 0; i < blinkPageSizeLog2; ++i) {
1376 for (FreeListEntry* freeListEntry = m_freeList.m_freeLists[i]; freeListE ntry; freeListEntry = freeListEntry->next()) { 1445 for (FreeListEntry* freeListEntry = m_freeList.m_freeLists[i]; freeListE ntry; freeListEntry = freeListEntry->next()) {
1377 if (pagesToBeSweptContains(freeListEntry->address())) 1446 if (pagesToBeSweptContains(freeListEntry->address()))
1378 return false; 1447 return false;
1379 } 1448 }
1380 } 1449 }
1381 if (hasCurrentAllocationArea()) { 1450 if (hasCurrentAllocationArea()) {
1382 if (pagesToBeSweptContains(currentAllocationPoint())) 1451 if (pagesToBeSweptContains(currentAllocationPoint()))
1383 return false; 1452 return false;
1384 } 1453 }
1385 return true; 1454 return true;
1386 } 1455 }
1387 #endif 1456 #endif
1388 1457
1389 void ThreadHeap::makeConsistentForSweeping() 1458 void ThreadHeap::makeConsistentForSweeping()
1390 { 1459 {
1460 preparePagesForSweeping();
1461 setAllocationPoint(nullptr, 0);
1391 clearFreeLists(); 1462 clearFreeLists();
1463 }
1464
1465 void ThreadHeap::preparePagesForSweeping()
1466 {
1392 ASSERT(isConsistentForSweeping()); 1467 ASSERT(isConsistentForSweeping());
1393 for (BaseHeapPage* page = m_firstPage; page; page = page->next()) 1468 for (HeapPage* page = m_firstPage; page; page = page->next())
1394 page->markAsUnswept(); 1469 page->markAsUnswept();
1395 1470
1396 // If a new GC is requested before this thread got around to sweep, 1471 // If a new GC is requested before this thread got around to sweep,
1397 // ie. due to the thread doing a long running operation, we clear 1472 // ie. due to the thread doing a long running operation, we clear
1398 // the mark bits and mark any of the dead objects as dead. The latter 1473 // the mark bits and mark any of the dead objects as dead. The latter
1399 // is used to ensure the next GC marking does not trace already dead 1474 // is used to ensure the next GC marking does not trace already dead
1400 // objects. If we trace a dead object we could end up tracing into 1475 // objects. If we trace a dead object we could end up tracing into
1401 // garbage or the middle of another object via the newly conservatively 1476 // garbage or the middle of another object via the newly conservatively
1402 // found object. 1477 // found object.
1403 BaseHeapPage* previousPage = nullptr; 1478 HeapPage* previousPage = nullptr;
1404 for (BaseHeapPage* page = m_firstUnsweptPage; page; previousPage = page, pag e = page->next()) { 1479 for (HeapPage* page = m_firstUnsweptPage; page; previousPage = page, page = page->next()) {
1405 page->markUnmarkedObjectsDead(); 1480 page->markUnmarkedObjectsDead();
1406 ASSERT(!page->hasBeenSwept()); 1481 ASSERT(!page->hasBeenSwept());
1407 } 1482 }
1408 if (previousPage) { 1483 if (previousPage) {
1409 ASSERT(m_firstUnsweptPage); 1484 ASSERT(m_firstUnsweptPage);
1410 previousPage->m_next = m_firstPage; 1485 previousPage->m_next = m_firstPage;
1411 m_firstPage = m_firstUnsweptPage; 1486 m_firstPage = m_firstUnsweptPage;
1412 m_firstUnsweptPage = nullptr; 1487 m_firstUnsweptPage = nullptr;
1413 } 1488 }
1414 ASSERT(!m_firstUnsweptPage); 1489 ASSERT(!m_firstUnsweptPage);
1490
1491 for (LargeObject* largeObject = m_firstLargeObject; largeObject; largeObject = largeObject->next())
1492 largeObject->markAsUnswept();
1493
1494 LargeObject* previousLargeObject = nullptr;
1495 for (LargeObject* largeObject = m_firstUnsweptLargeObject; largeObject; prev iousLargeObject = largeObject, largeObject = largeObject->next()) {
1496 largeObject->markUnmarkedObjectsDead();
1497 ASSERT(!largeObject->hasBeenSwept());
1498 }
1499 if (previousLargeObject) {
1500 ASSERT(m_firstUnsweptLargeObject);
1501 previousLargeObject->m_next = m_firstLargeObject;
1502 m_firstLargeObject = m_firstUnsweptLargeObject;
1503 m_firstUnsweptLargeObject = nullptr;
1504 }
1505 ASSERT(!m_firstUnsweptLargeObject);
1415 } 1506 }
1416 1507
1417 void ThreadHeapForHeapPage::clearFreeLists() 1508 void ThreadHeap::clearFreeLists()
1418 { 1509 {
1419 setAllocationPoint(nullptr, 0);
1420 m_freeList.clear(); 1510 m_freeList.clear();
1421 } 1511 }
1422 1512
1423 #if ENABLE(GC_PROFILING) 1513 #if ENABLE(GC_PROFILING)
1424 void ThreadHeap::snapshotFreeList(TracedValue& json) 1514 void ThreadHeap::snapshotFreeList(TracedValue& json)
1425 { 1515 {
1426 json.setInteger("cumulativeAllocationSize", m_cumulativeAllocationSize); 1516 json.setInteger("cumulativeAllocationSize", m_cumulativeAllocationSize);
1427 json.setDouble("inlineAllocationRate", static_cast<double>(m_inlineAllocatio nCount) / m_allocationCount); 1517 json.setDouble("inlineAllocationRate", static_cast<double>(m_inlineAllocatio nCount) / m_allocationCount);
1428 json.setInteger("inlineAllocationCount", m_inlineAllocationCount); 1518 json.setInteger("inlineAllocationCount", m_inlineAllocationCount);
1429 json.setInteger("allocationCount", m_allocationCount); 1519 json.setInteger("allocationCount", m_allocationCount);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1498 ++entryCount; 1588 ++entryCount;
1499 freeSize += entry->size(); 1589 freeSize += entry->size();
1500 } 1590 }
1501 totalFreeSize += freeSize; 1591 totalFreeSize += freeSize;
1502 } 1592 }
1503 } 1593 }
1504 #endif 1594 #endif
1505 1595
1506 HeapPage::HeapPage(PageMemory* storage, ThreadHeap* heap) 1596 HeapPage::HeapPage(PageMemory* storage, ThreadHeap* heap)
1507 : BaseHeapPage(storage, heap) 1597 : BaseHeapPage(storage, heap)
1598 , m_next(nullptr)
1508 { 1599 {
1509 m_objectStartBitMapComputed = false; 1600 m_objectStartBitMapComputed = false;
1510 ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this))); 1601 ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this)));
1511 } 1602 }
1512 1603
1513 size_t HeapPage::objectPayloadSizeForTesting() 1604 size_t HeapPage::objectPayloadSizeForTesting()
1514 { 1605 {
1515 size_t objectPayloadSize = 0; 1606 size_t objectPayloadSize = 0;
1516 Address headerAddress = payload(); 1607 Address headerAddress = payload();
1517 markAsSwept(); 1608 markAsSwept();
(...skipping 22 matching lines...) Expand all
1540 clearObjectStartBitMap(); 1631 clearObjectStartBitMap();
1541 1632
1542 size_t markedObjectSize = 0; 1633 size_t markedObjectSize = 0;
1543 Address startOfGap = payload(); 1634 Address startOfGap = payload();
1544 for (Address headerAddress = startOfGap; headerAddress < payloadEnd(); ) { 1635 for (Address headerAddress = startOfGap; headerAddress < payloadEnd(); ) {
1545 HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(headerAdd ress); 1636 HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(headerAdd ress);
1546 ASSERT(header->size() > 0); 1637 ASSERT(header->size() > 0);
1547 ASSERT(header->size() < blinkPagePayloadSize()); 1638 ASSERT(header->size() < blinkPagePayloadSize());
1548 1639
1549 if (header->isPromptlyFreed()) 1640 if (header->isPromptlyFreed())
1550 heapForHeapPage()->decreasePromptlyFreedSize(header->size()); 1641 heap()->decreasePromptlyFreedSize(header->size());
1551 if (header->isFree()) { 1642 if (header->isFree()) {
1552 size_t size = header->size(); 1643 size_t size = header->size();
1553 // Zero the memory in the free list header to maintain the 1644 // Zero the memory in the free list header to maintain the
1554 // invariant that memory on the free list is zero filled. 1645 // invariant that memory on the free list is zero filled.
1555 // The rest of the memory is already on the free list and is 1646 // The rest of the memory is already on the free list and is
1556 // therefore already zero filled. 1647 // therefore already zero filled.
1557 FILL_ZERO_IF_PRODUCTION(headerAddress, size < sizeof(FreeListEntry) ? size : sizeof(FreeListEntry)); 1648 FILL_ZERO_IF_PRODUCTION(headerAddress, size < sizeof(FreeListEntry) ? size : sizeof(FreeListEntry));
1558 headerAddress += size; 1649 headerAddress += size;
1559 continue; 1650 continue;
1560 } 1651 }
(...skipping 12 matching lines...) Expand all
1573 header->finalize(payload, payloadSize); 1664 header->finalize(payload, payloadSize);
1574 // This memory will be added to the freelist. Maintain the invariant 1665 // This memory will be added to the freelist. Maintain the invariant
1575 // that memory on the freelist is zero filled. 1666 // that memory on the freelist is zero filled.
1576 FILL_ZERO_IF_PRODUCTION(headerAddress, size); 1667 FILL_ZERO_IF_PRODUCTION(headerAddress, size);
1577 ASAN_POISON_MEMORY_REGION(payload, payloadSize); 1668 ASAN_POISON_MEMORY_REGION(payload, payloadSize);
1578 headerAddress += size; 1669 headerAddress += size;
1579 continue; 1670 continue;
1580 } 1671 }
1581 1672
1582 if (startOfGap != headerAddress) 1673 if (startOfGap != headerAddress)
1583 heapForHeapPage()->addToFreeList(startOfGap, headerAddress - startOf Gap); 1674 heap()->addToFreeList(startOfGap, headerAddress - startOfGap);
1584 header->unmark(); 1675 header->unmark();
1585 headerAddress += header->size(); 1676 headerAddress += header->size();
1586 markedObjectSize += header->size(); 1677 markedObjectSize += header->size();
1587 startOfGap = headerAddress; 1678 startOfGap = headerAddress;
1588 } 1679 }
1589 if (startOfGap != payloadEnd()) 1680 if (startOfGap != payloadEnd())
1590 heapForHeapPage()->addToFreeList(startOfGap, payloadEnd() - startOfGap); 1681 heap()->addToFreeList(startOfGap, payloadEnd() - startOfGap);
1591 1682
1592 if (markedObjectSize) 1683 if (markedObjectSize)
1593 Heap::increaseMarkedObjectSize(markedObjectSize); 1684 Heap::increaseMarkedObjectSize(markedObjectSize);
1594 } 1685 }
1595 1686
1596 void HeapPage::markUnmarkedObjectsDead() 1687 void HeapPage::markUnmarkedObjectsDead()
1597 { 1688 {
1598 for (Address headerAddress = payload(); headerAddress < payloadEnd();) { 1689 for (Address headerAddress = payload(); headerAddress < payloadEnd();) {
1599 HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(headerAdd ress); 1690 HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(headerAdd ress);
1600 ASSERT(header->size() < blinkPagePayloadSize()); 1691 ASSERT(header->size() < blinkPagePayloadSize());
1601 // Check if a free list entry first since we cannot call 1692 // Check if a free list entry first since we cannot call
1602 // isMarked on a free list entry. 1693 // isMarked on a free list entry.
1603 if (header->isFree()) { 1694 if (header->isFree()) {
1604 headerAddress += header->size(); 1695 headerAddress += header->size();
1605 continue; 1696 continue;
1606 } 1697 }
1607 header->checkHeader(); 1698 header->checkHeader();
1608 if (header->isMarked()) 1699 if (header->isMarked())
1609 header->unmark(); 1700 header->unmark();
1610 else 1701 else
1611 header->markDead(); 1702 header->markDead();
1612 headerAddress += header->size(); 1703 headerAddress += header->size();
1613 } 1704 }
1614 } 1705 }
1615 1706
1616 void HeapPage::removeFromHeap() 1707 void HeapPage::removeFromHeap(ThreadHeap* heap)
1617 { 1708 {
1618 heapForHeapPage()->freePage(this); 1709 heap->freePage(this);
1619 }
1620
1621 ThreadHeapForHeapPage* HeapPage::heapForHeapPage()
1622 {
1623 return static_cast<ThreadHeapForHeapPage*>(heap());
1624 } 1710 }
1625 1711
1626 void HeapPage::populateObjectStartBitMap() 1712 void HeapPage::populateObjectStartBitMap()
1627 { 1713 {
1628 memset(&m_objectStartBitMap, 0, objectStartBitMapSize); 1714 memset(&m_objectStartBitMap, 0, objectStartBitMapSize);
1629 Address start = payload(); 1715 Address start = payload();
1630 for (Address headerAddress = start; headerAddress < payloadEnd();) { 1716 for (Address headerAddress = start; headerAddress < payloadEnd();) {
1631 HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(headerAdd ress); 1717 HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(headerAdd ress);
1632 size_t objectOffset = headerAddress - start; 1718 size_t objectOffset = headerAddress - start;
1633 ASSERT(!(objectOffset & allocationMask)); 1719 ASSERT(!(objectOffset & allocationMask));
(...skipping 898 matching lines...) Expand 10 before | Expand all | Expand 10 after
2532 2618
2533 double Heap::estimatedMarkingTime() 2619 double Heap::estimatedMarkingTime()
2534 { 2620 {
2535 // FIXME: Implement heuristics 2621 // FIXME: Implement heuristics
2536 return 0.0; 2622 return 0.0;
2537 } 2623 }
2538 2624
2539 void ThreadHeap::prepareHeapForTermination() 2625 void ThreadHeap::prepareHeapForTermination()
2540 { 2626 {
2541 ASSERT(!m_firstUnsweptPage); 2627 ASSERT(!m_firstUnsweptPage);
2542 for (BaseHeapPage* page = m_firstPage; page; page = page->next()) { 2628 ASSERT(!m_firstUnsweptLargeObject);
2629 for (HeapPage* page = m_firstPage; page; page = page->next()) {
2543 page->setTerminating(); 2630 page->setTerminating();
2544 } 2631 }
2632 for (LargeObject* largeObject = m_firstLargeObject; largeObject; largeObject = largeObject->next()) {
2633 largeObject->setTerminating();
2634 }
2545 } 2635 }
2546 2636
2547 size_t Heap::objectPayloadSizeForTesting() 2637 size_t Heap::objectPayloadSizeForTesting()
2548 { 2638 {
2549 size_t objectPayloadSize = 0; 2639 size_t objectPayloadSize = 0;
2550 for (ThreadState* state : ThreadState::attachedThreads()) { 2640 for (ThreadState* state : ThreadState::attachedThreads()) {
2551 state->setGCState(ThreadState::GCRunning); 2641 state->setGCState(ThreadState::GCRunning);
2552 state->makeConsistentForSweeping(); 2642 state->makeConsistentForSweeping();
2553 objectPayloadSize += state->objectPayloadSizeForTesting(); 2643 objectPayloadSize += state->objectPayloadSizeForTesting();
2554 state->setGCState(ThreadState::EagerSweepScheduled); 2644 state->setGCState(ThreadState::EagerSweepScheduled);
(...skipping 14 matching lines...) Expand all
2569 ASSERT(!state->isInGC()); 2659 ASSERT(!state->isInGC());
2570 2660
2571 // Don't promptly free large objects because their page is never reused. 2661 // Don't promptly free large objects because their page is never reused.
2572 // Don't free backings allocated on other threads. 2662 // Don't free backings allocated on other threads.
2573 BaseHeapPage* page = pageFromObject(address); 2663 BaseHeapPage* page = pageFromObject(address);
2574 if (page->isLargeObject() || page->heap()->threadState() != state) 2664 if (page->isLargeObject() || page->heap()->threadState() != state)
2575 return; 2665 return;
2576 2666
2577 HeapObjectHeader* header = HeapObjectHeader::fromPayload(address); 2667 HeapObjectHeader* header = HeapObjectHeader::fromPayload(address);
2578 header->checkHeader(); 2668 header->checkHeader();
2579 static_cast<HeapPage*>(page)->heapForHeapPage()->promptlyFreeObject(header); 2669 static_cast<HeapPage*>(page)->heap()->promptlyFreeObject(header);
2580 } 2670 }
2581 2671
2582 void HeapAllocator::freeVectorBacking(void* address) 2672 void HeapAllocator::freeVectorBacking(void* address)
2583 { 2673 {
2584 backingFree(address); 2674 backingFree(address);
2585 } 2675 }
2586 2676
2587 void HeapAllocator::freeInlineVectorBacking(void* address) 2677 void HeapAllocator::freeInlineVectorBacking(void* address)
2588 { 2678 {
2589 backingFree(address); 2679 backingFree(address);
(...skipping 16 matching lines...) Expand all
2606 ASSERT(state->isAllocationAllowed()); 2696 ASSERT(state->isAllocationAllowed());
2607 2697
2608 // FIXME: Support expand for large objects. 2698 // FIXME: Support expand for large objects.
2609 // Don't expand backings allocated on other threads. 2699 // Don't expand backings allocated on other threads.
2610 BaseHeapPage* page = pageFromObject(address); 2700 BaseHeapPage* page = pageFromObject(address);
2611 if (page->isLargeObject() || page->heap()->threadState() != state) 2701 if (page->isLargeObject() || page->heap()->threadState() != state)
2612 return false; 2702 return false;
2613 2703
2614 HeapObjectHeader* header = HeapObjectHeader::fromPayload(address); 2704 HeapObjectHeader* header = HeapObjectHeader::fromPayload(address);
2615 header->checkHeader(); 2705 header->checkHeader();
2616 return static_cast<HeapPage*>(page)->heapForHeapPage()->expandObject(header, newSize); 2706 return static_cast<HeapPage*>(page)->heap()->expandObject(header, newSize);
2617 } 2707 }
2618 2708
2619 bool HeapAllocator::expandVectorBacking(void* address, size_t newSize) 2709 bool HeapAllocator::expandVectorBacking(void* address, size_t newSize)
2620 { 2710 {
2621 return backingExpand(address, newSize); 2711 return backingExpand(address, newSize);
2622 } 2712 }
2623 2713
2624 bool HeapAllocator::expandInlineVectorBacking(void* address, size_t newSize) 2714 bool HeapAllocator::expandInlineVectorBacking(void* address, size_t newSize)
2625 { 2715 {
2626 return backingExpand(address, newSize); 2716 return backingExpand(address, newSize);
(...skipping 22 matching lines...) Expand all
2649 ASSERT(state->isAllocationAllowed()); 2739 ASSERT(state->isAllocationAllowed());
2650 2740
2651 // FIXME: Support shrink for large objects. 2741 // FIXME: Support shrink for large objects.
2652 // Don't shrink backings allocated on other threads. 2742 // Don't shrink backings allocated on other threads.
2653 BaseHeapPage* page = pageFromObject(address); 2743 BaseHeapPage* page = pageFromObject(address);
2654 if (page->isLargeObject() || page->heap()->threadState() != state) 2744 if (page->isLargeObject() || page->heap()->threadState() != state)
2655 return; 2745 return;
2656 2746
2657 HeapObjectHeader* header = HeapObjectHeader::fromPayload(address); 2747 HeapObjectHeader* header = HeapObjectHeader::fromPayload(address);
2658 header->checkHeader(); 2748 header->checkHeader();
2659 static_cast<HeapPage*>(page)->heapForHeapPage()->shrinkObject(header, quanti zedShrunkSize); 2749 static_cast<HeapPage*>(page)->heap()->shrinkObject(header, quantizedShrunkSi ze);
2660 } 2750 }
2661 2751
2662 void HeapAllocator::shrinkVectorBackingInternal(void* address, size_t quantizedC urrentSize, size_t quantizedShrunkSize) 2752 void HeapAllocator::shrinkVectorBackingInternal(void* address, size_t quantizedC urrentSize, size_t quantizedShrunkSize)
2663 { 2753 {
2664 backingShrink(address, quantizedCurrentSize, quantizedShrunkSize); 2754 backingShrink(address, quantizedCurrentSize, quantizedShrunkSize);
2665 } 2755 }
2666 2756
2667 void HeapAllocator::shrinkInlineVectorBackingInternal(void* address, size_t quan tizedCurrentSize, size_t quantizedShrunkSize) 2757 void HeapAllocator::shrinkInlineVectorBackingInternal(void* address, size_t quan tizedCurrentSize, size_t quantizedShrunkSize)
2668 { 2758 {
2669 backingShrink(address, quantizedCurrentSize, quantizedShrunkSize); 2759 backingShrink(address, quantizedCurrentSize, quantizedShrunkSize);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
2769 bool Heap::s_shutdownCalled = false; 2859 bool Heap::s_shutdownCalled = false;
2770 bool Heap::s_lastGCWasConservative = false; 2860 bool Heap::s_lastGCWasConservative = false;
2771 FreePagePool* Heap::s_freePagePool; 2861 FreePagePool* Heap::s_freePagePool;
2772 OrphanedPagePool* Heap::s_orphanedPagePool; 2862 OrphanedPagePool* Heap::s_orphanedPagePool;
2773 Heap::RegionTree* Heap::s_regionTree = nullptr; 2863 Heap::RegionTree* Heap::s_regionTree = nullptr;
2774 size_t Heap::s_allocatedObjectSize = 0; 2864 size_t Heap::s_allocatedObjectSize = 0;
2775 size_t Heap::s_allocatedSpace = 0; 2865 size_t Heap::s_allocatedSpace = 0;
2776 size_t Heap::s_markedObjectSize = 0; 2866 size_t Heap::s_markedObjectSize = 0;
2777 2867
2778 } // namespace blink 2868 } // namespace blink
OLDNEW
« no previous file with comments | « Source/platform/heap/Heap.h ('k') | Source/platform/heap/ThreadState.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698