| OLD | NEW |
| 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 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 // | 345 // |
| 346 // - LargeObjectPage is a page that contains only one object. The object size | 346 // - LargeObjectPage is a page that contains only one object. The object size |
| 347 // is arbitrary. An object whose size is larger than |blinkPageSize| is stored | 347 // is arbitrary. An object whose size is larger than |blinkPageSize| is stored |
| 348 // as a single project in LargeObjectPage. | 348 // as a single project in LargeObjectPage. |
| 349 // | 349 // |
| 350 // Note: An object whose size is between |largeObjectSizeThreshold| and | 350 // Note: An object whose size is between |largeObjectSizeThreshold| and |
| 351 // |blinkPageSize| can go to either of NormalPage or LargeObjectPage. | 351 // |blinkPageSize| can go to either of NormalPage or LargeObjectPage. |
| 352 class BasePage { | 352 class BasePage { |
| 353 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); | 353 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); |
| 354 public: | 354 public: |
| 355 BasePage(PageMemory*, BaseHeap*); | 355 BasePage(PageMemory*, BaseArena*); |
| 356 virtual ~BasePage() { } | 356 virtual ~BasePage() { } |
| 357 | 357 |
| 358 void link(BasePage** previousNext) | 358 void link(BasePage** previousNext) |
| 359 { | 359 { |
| 360 m_next = *previousNext; | 360 m_next = *previousNext; |
| 361 *previousNext = this; | 361 *previousNext = this; |
| 362 } | 362 } |
| 363 void unlink(BasePage** previousNext) | 363 void unlink(BasePage** previousNext) |
| 364 { | 364 { |
| 365 *previousNext = m_next; | 365 *previousNext = m_next; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 | 401 |
| 402 virtual void takeSnapshot(WebMemoryAllocatorDump*, ThreadState::GCSnapshotIn
fo&, HeapSnapshotInfo&) = 0; | 402 virtual void takeSnapshot(WebMemoryAllocatorDump*, ThreadState::GCSnapshotIn
fo&, HeapSnapshotInfo&) = 0; |
| 403 #if ENABLE(ASSERT) | 403 #if ENABLE(ASSERT) |
| 404 virtual bool contains(Address) = 0; | 404 virtual bool contains(Address) = 0; |
| 405 #endif | 405 #endif |
| 406 virtual size_t size() = 0; | 406 virtual size_t size() = 0; |
| 407 virtual bool isLargeObjectPage() { return false; } | 407 virtual bool isLargeObjectPage() { return false; } |
| 408 | 408 |
| 409 Address getAddress() { return reinterpret_cast<Address>(this); } | 409 Address getAddress() { return reinterpret_cast<Address>(this); } |
| 410 PageMemory* storage() const { return m_storage; } | 410 PageMemory* storage() const { return m_storage; } |
| 411 BaseHeap* heap() const { return m_heap; } | 411 BaseArena* arena() const { return m_arena; } |
| 412 bool orphaned() { return !m_heap; } | 412 bool orphaned() { return !m_arena; } |
| 413 bool terminating() { return m_terminating; } | 413 bool terminating() { return m_terminating; } |
| 414 void setTerminating() { m_terminating = true; } | 414 void setTerminating() { m_terminating = true; } |
| 415 | 415 |
| 416 // Returns true if this page has been swept by the ongoing lazy sweep. | 416 // Returns true if this page has been swept by the ongoing lazy sweep. |
| 417 bool hasBeenSwept() const { return m_swept; } | 417 bool hasBeenSwept() const { return m_swept; } |
| 418 | 418 |
| 419 void markAsSwept() | 419 void markAsSwept() |
| 420 { | 420 { |
| 421 ASSERT(!m_swept); | 421 ASSERT(!m_swept); |
| 422 m_swept = true; | 422 m_swept = true; |
| 423 } | 423 } |
| 424 | 424 |
| 425 void markAsUnswept() | 425 void markAsUnswept() |
| 426 { | 426 { |
| 427 ASSERT(m_swept); | 427 ASSERT(m_swept); |
| 428 m_swept = false; | 428 m_swept = false; |
| 429 } | 429 } |
| 430 | 430 |
| 431 private: | 431 private: |
| 432 PageMemory* m_storage; | 432 PageMemory* m_storage; |
| 433 BaseHeap* m_heap; | 433 BaseArena* m_arena; |
| 434 BasePage* m_next; | 434 BasePage* m_next; |
| 435 // Whether the page is part of a terminating thread or not. | 435 // Whether the page is part of a terminating thread or not. |
| 436 bool m_terminating; | 436 bool m_terminating; |
| 437 | 437 |
| 438 // Track the sweeping state of a page. Set to true once | 438 // Track the sweeping state of a page. Set to true once |
| 439 // the lazy sweep completes has processed it. | 439 // the lazy sweep completes has processed it. |
| 440 // | 440 // |
| 441 // Set to false at the start of a sweep, true upon completion | 441 // Set to false at the start of a sweep, true upon completion |
| 442 // of lazy sweeping. | 442 // of lazy sweeping. |
| 443 bool m_swept; | 443 bool m_swept; |
| 444 friend class BaseHeap; | 444 friend class BaseArena; |
| 445 }; | 445 }; |
| 446 | 446 |
| 447 class NormalPage final : public BasePage { | 447 class NormalPage final : public BasePage { |
| 448 public: | 448 public: |
| 449 NormalPage(PageMemory*, BaseHeap*); | 449 NormalPage(PageMemory*, BaseArena*); |
| 450 | 450 |
| 451 Address payload() | 451 Address payload() |
| 452 { | 452 { |
| 453 return getAddress() + pageHeaderSize(); | 453 return getAddress() + pageHeaderSize(); |
| 454 } | 454 } |
| 455 size_t payloadSize() | 455 size_t payloadSize() |
| 456 { | 456 { |
| 457 return (blinkPagePayloadSize() - pageHeaderSize()) & ~allocationMask; | 457 return (blinkPagePayloadSize() - pageHeaderSize()) & ~allocationMask; |
| 458 } | 458 } |
| 459 Address payloadEnd() { return payload() + payloadSize(); } | 459 Address payloadEnd() { return payload() + payloadSize(); } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 485 size_t size() override { return blinkPageSize; } | 485 size_t size() override { return blinkPageSize; } |
| 486 static size_t pageHeaderSize() | 486 static size_t pageHeaderSize() |
| 487 { | 487 { |
| 488 // Compute the amount of padding we have to add to a header to make | 488 // Compute the amount of padding we have to add to a header to make |
| 489 // the size of the header plus the padding a multiple of 8 bytes. | 489 // the size of the header plus the padding a multiple of 8 bytes. |
| 490 size_t paddingSize = (sizeof(NormalPage) + allocationGranularity - (size
of(HeapObjectHeader) % allocationGranularity)) % allocationGranularity; | 490 size_t paddingSize = (sizeof(NormalPage) + allocationGranularity - (size
of(HeapObjectHeader) % allocationGranularity)) % allocationGranularity; |
| 491 return sizeof(NormalPage) + paddingSize; | 491 return sizeof(NormalPage) + paddingSize; |
| 492 } | 492 } |
| 493 | 493 |
| 494 | 494 |
| 495 NormalPageHeap* heapForNormalPage(); | 495 NormalPageHeap* arenaForNormalPage(); |
| 496 | 496 |
| 497 private: | 497 private: |
| 498 HeapObjectHeader* findHeaderFromAddress(Address); | 498 HeapObjectHeader* findHeaderFromAddress(Address); |
| 499 void populateObjectStartBitMap(); | 499 void populateObjectStartBitMap(); |
| 500 | 500 |
| 501 bool m_objectStartBitMapComputed; | 501 bool m_objectStartBitMapComputed; |
| 502 uint8_t m_objectStartBitMap[reservedForObjectBitMap]; | 502 uint8_t m_objectStartBitMap[reservedForObjectBitMap]; |
| 503 }; | 503 }; |
| 504 | 504 |
| 505 // Large allocations are allocated as separate objects and linked in a list. | 505 // Large allocations are allocated as separate objects and linked in a list. |
| 506 // | 506 // |
| 507 // In order to use the same memory allocation routines for everything allocated | 507 // In order to use the same memory allocation routines for everything allocated |
| 508 // in the heap, large objects are considered heap pages containing only one | 508 // in the heap, large objects are considered heap pages containing only one |
| 509 // object. | 509 // object. |
| 510 class LargeObjectPage final : public BasePage { | 510 class LargeObjectPage final : public BasePage { |
| 511 public: | 511 public: |
| 512 LargeObjectPage(PageMemory*, BaseHeap*, size_t); | 512 LargeObjectPage(PageMemory*, BaseArena*, size_t); |
| 513 | 513 |
| 514 Address payload() { return heapObjectHeader()->payload(); } | 514 Address payload() { return heapObjectHeader()->payload(); } |
| 515 size_t payloadSize() { return m_payloadSize; } | 515 size_t payloadSize() { return m_payloadSize; } |
| 516 Address payloadEnd() { return payload() + payloadSize(); } | 516 Address payloadEnd() { return payload() + payloadSize(); } |
| 517 bool containedInObjectPayload(Address address) | 517 bool containedInObjectPayload(Address address) |
| 518 { | 518 { |
| 519 return payload() <= address && address < payloadEnd(); | 519 return payload() <= address && address < payloadEnd(); |
| 520 } | 520 } |
| 521 | 521 |
| 522 size_t objectPayloadSizeForTesting() override; | 522 size_t objectPayloadSizeForTesting() override; |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 | 642 |
| 643 private: | 643 private: |
| 644 int m_biggestFreeListIndex; | 644 int m_biggestFreeListIndex; |
| 645 | 645 |
| 646 // All FreeListEntries in the nth list have size >= 2^n. | 646 // All FreeListEntries in the nth list have size >= 2^n. |
| 647 FreeListEntry* m_freeLists[blinkPageSizeLog2]; | 647 FreeListEntry* m_freeLists[blinkPageSizeLog2]; |
| 648 | 648 |
| 649 friend class NormalPageHeap; | 649 friend class NormalPageHeap; |
| 650 }; | 650 }; |
| 651 | 651 |
| 652 // Each thread has a number of thread heaps (e.g., Generic heaps, | 652 // Each thread has a number of thread arenas (e.g., Generic arenas, |
| 653 // typed heaps for Node, heaps for collection backings etc) | 653 // typed arenas for Node, arenas for collection backings etc) |
| 654 // and BaseHeap represents each thread heap. | 654 // and BaseArena represents each thread heap. |
| 655 // | 655 // |
| 656 // BaseHeap is a parent class of NormalPageHeap and LargeObjectHeap. | 656 // BaseArena is a parent class of NormalPageHeap and LargeObjectHeap. |
| 657 // NormalPageHeap represents a heap that contains NormalPages | 657 // NormalPageHeap represents a heap that contains NormalPages |
| 658 // and LargeObjectHeap represents a heap that contains LargeObjectPages. | 658 // and LargeObjectHeap represents a heap that contains LargeObjectPages. |
| 659 class PLATFORM_EXPORT BaseHeap { | 659 class PLATFORM_EXPORT BaseArena { |
| 660 USING_FAST_MALLOC(BaseHeap); | 660 USING_FAST_MALLOC(BaseArena); |
| 661 public: | 661 public: |
| 662 BaseHeap(ThreadState*, int); | 662 BaseArena(ThreadState*, int); |
| 663 virtual ~BaseHeap(); | 663 virtual ~BaseArena(); |
| 664 void cleanupPages(); | 664 void cleanupPages(); |
| 665 | 665 |
| 666 void takeSnapshot(const String& dumpBaseName, ThreadState::GCSnapshotInfo&); | 666 void takeSnapshot(const String& dumpBaseName, ThreadState::GCSnapshotInfo&); |
| 667 #if ENABLE(ASSERT) | 667 #if ENABLE(ASSERT) |
| 668 BasePage* findPageFromAddress(Address); | 668 BasePage* findPageFromAddress(Address); |
| 669 #endif | 669 #endif |
| 670 virtual void takeFreelistSnapshot(const String& dumpBaseName) { } | 670 virtual void takeFreelistSnapshot(const String& dumpBaseName) { } |
| 671 virtual void clearFreeLists() { } | 671 virtual void clearFreeLists() { } |
| 672 void makeConsistentForGC(); | 672 void makeConsistentForGC(); |
| 673 void makeConsistentForMutator(); | 673 void makeConsistentForMutator(); |
| 674 #if ENABLE(ASSERT) | 674 #if ENABLE(ASSERT) |
| 675 virtual bool isConsistentForGC() = 0; | 675 virtual bool isConsistentForGC() = 0; |
| 676 #endif | 676 #endif |
| 677 size_t objectPayloadSizeForTesting(); | 677 size_t objectPayloadSizeForTesting(); |
| 678 void prepareHeapForTermination(); | 678 void prepareHeapForTermination(); |
| 679 void prepareForSweep(); | 679 void prepareForSweep(); |
| 680 #if defined(ADDRESS_SANITIZER) | 680 #if defined(ADDRESS_SANITIZER) |
| 681 void poisonHeap(BlinkGC::ObjectsToPoison, BlinkGC::Poisoning); | 681 void poisonHeap(BlinkGC::ObjectsToPoison, BlinkGC::Poisoning); |
| 682 #endif | 682 #endif |
| 683 Address lazySweep(size_t, size_t gcInfoIndex); | 683 Address lazySweep(size_t, size_t gcInfoIndex); |
| 684 void sweepUnsweptPage(); | 684 void sweepUnsweptPage(); |
| 685 // Returns true if we have swept all pages within the deadline. | 685 // Returns true if we have swept all pages within the deadline. |
| 686 // Returns false otherwise. | 686 // Returns false otherwise. |
| 687 bool lazySweepWithDeadline(double deadlineSeconds); | 687 bool lazySweepWithDeadline(double deadlineSeconds); |
| 688 void completeSweep(); | 688 void completeSweep(); |
| 689 | 689 |
| 690 ThreadState* threadState() { return m_threadState; } | 690 ThreadState* threadState() { return m_threadState; } |
| 691 int heapIndex() const { return m_index; } | 691 int arenaIndex() const { return m_index; } |
| 692 | 692 |
| 693 protected: | 693 protected: |
| 694 BasePage* m_firstPage; | 694 BasePage* m_firstPage; |
| 695 BasePage* m_firstUnsweptPage; | 695 BasePage* m_firstUnsweptPage; |
| 696 | 696 |
| 697 private: | 697 private: |
| 698 virtual Address lazySweepPages(size_t, size_t gcInfoIndex) = 0; | 698 virtual Address lazySweepPages(size_t, size_t gcInfoIndex) = 0; |
| 699 | 699 |
| 700 ThreadState* m_threadState; | 700 ThreadState* m_threadState; |
| 701 | 701 |
| 702 // Index into the page pools. This is used to ensure that the pages of the | 702 // Index into the page pools. This is used to ensure that the pages of the |
| 703 // same type go into the correct page pool and thus avoid type confusion. | 703 // same type go into the correct page pool and thus avoid type confusion. |
| 704 int m_index; | 704 int m_index; |
| 705 }; | 705 }; |
| 706 | 706 |
| 707 class PLATFORM_EXPORT NormalPageHeap final : public BaseHeap { | 707 class PLATFORM_EXPORT NormalPageHeap final : public BaseArena { |
| 708 public: | 708 public: |
| 709 NormalPageHeap(ThreadState*, int); | 709 NormalPageHeap(ThreadState*, int); |
| 710 void addToFreeList(Address address, size_t size) | 710 void addToFreeList(Address address, size_t size) |
| 711 { | 711 { |
| 712 ASSERT(findPageFromAddress(address)); | 712 ASSERT(findPageFromAddress(address)); |
| 713 ASSERT(findPageFromAddress(address + size - 1)); | 713 ASSERT(findPageFromAddress(address + size - 1)); |
| 714 m_freeList.addToFreeList(address, size); | 714 m_freeList.addToFreeList(address, size); |
| 715 } | 715 } |
| 716 void clearFreeLists() override; | 716 void clearFreeLists() override; |
| 717 #if ENABLE(ASSERT) | 717 #if ENABLE(ASSERT) |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 752 | 752 |
| 753 FreeList m_freeList; | 753 FreeList m_freeList; |
| 754 Address m_currentAllocationPoint; | 754 Address m_currentAllocationPoint; |
| 755 size_t m_remainingAllocationSize; | 755 size_t m_remainingAllocationSize; |
| 756 size_t m_lastRemainingAllocationSize; | 756 size_t m_lastRemainingAllocationSize; |
| 757 | 757 |
| 758 // The size of promptly freed objects in the heap. | 758 // The size of promptly freed objects in the heap. |
| 759 size_t m_promptlyFreedSize; | 759 size_t m_promptlyFreedSize; |
| 760 }; | 760 }; |
| 761 | 761 |
| 762 class LargeObjectHeap final : public BaseHeap { | 762 class LargeObjectHeap final : public BaseArena { |
| 763 public: | 763 public: |
| 764 LargeObjectHeap(ThreadState*, int); | 764 LargeObjectHeap(ThreadState*, int); |
| 765 Address allocateLargeObjectPage(size_t, size_t gcInfoIndex); | 765 Address allocateLargeObjectPage(size_t, size_t gcInfoIndex); |
| 766 void freeLargeObjectPage(LargeObjectPage*); | 766 void freeLargeObjectPage(LargeObjectPage*); |
| 767 #if ENABLE(ASSERT) | 767 #if ENABLE(ASSERT) |
| 768 bool isConsistentForGC() override { return true; } | 768 bool isConsistentForGC() override { return true; } |
| 769 #endif | 769 #endif |
| 770 private: | 770 private: |
| 771 Address doAllocateLargeObjectPage(size_t, size_t gcInfoIndex); | 771 Address doAllocateLargeObjectPage(size_t, size_t gcInfoIndex); |
| 772 Address lazySweepPages(size_t, size_t gcInfoIndex) override; | 772 Address lazySweepPages(size_t, size_t gcInfoIndex) override; |
| 773 }; | 773 }; |
| 774 | 774 |
| 775 // Mask an address down to the enclosing oilpan heap base page. All oilpan heap | 775 // Mask an address down to the enclosing oilpan heap base page. All oilpan heap |
| 776 // pages are aligned at blinkPageBase plus the size of a guard size. | 776 // pages are aligned at blinkPageBase plus the size of a guard size. |
| 777 // FIXME: Remove PLATFORM_EXPORT once we get a proper public interface to our | 777 // FIXME: Remove PLATFORM_EXPORT once we get a proper public interface to our |
| 778 // typed heaps. This is only exported to enable tests in HeapTest.cpp. | 778 // typed arenas. This is only exported to enable tests in HeapTest.cpp. |
| 779 PLATFORM_EXPORT inline BasePage* pageFromObject(const void* object) | 779 PLATFORM_EXPORT inline BasePage* pageFromObject(const void* object) |
| 780 { | 780 { |
| 781 Address address = reinterpret_cast<Address>(const_cast<void*>(object)); | 781 Address address = reinterpret_cast<Address>(const_cast<void*>(object)); |
| 782 BasePage* page = reinterpret_cast<BasePage*>(blinkPageAddress(address) + bli
nkGuardPageSize); | 782 BasePage* page = reinterpret_cast<BasePage*>(blinkPageAddress(address) + bli
nkGuardPageSize); |
| 783 ASSERT(page->contains(address)); | 783 ASSERT(page->contains(address)); |
| 784 return page; | 784 return page; |
| 785 } | 785 } |
| 786 | 786 |
| 787 NO_SANITIZE_ADDRESS inline | 787 NO_SANITIZE_ADDRESS inline |
| 788 size_t HeapObjectHeader::size() const | 788 size_t HeapObjectHeader::size() const |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 886 SET_MEMORY_ACCESSIBLE(result, allocationSize - sizeof(HeapObjectHeader))
; | 886 SET_MEMORY_ACCESSIBLE(result, allocationSize - sizeof(HeapObjectHeader))
; |
| 887 ASSERT(findPageFromAddress(headerAddress + allocationSize - 1)); | 887 ASSERT(findPageFromAddress(headerAddress + allocationSize - 1)); |
| 888 return result; | 888 return result; |
| 889 } | 889 } |
| 890 return outOfLineAllocate(allocationSize, gcInfoIndex); | 890 return outOfLineAllocate(allocationSize, gcInfoIndex); |
| 891 } | 891 } |
| 892 | 892 |
| 893 } // namespace blink | 893 } // namespace blink |
| 894 | 894 |
| 895 #endif // HeapPage_h | 895 #endif // HeapPage_h |
| OLD | NEW |