| 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 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 intptr_t padding() const { return m_padding; } | 566 intptr_t padding() const { return m_padding; } |
| 567 | 567 |
| 568 HeapPage<Header>* m_next; | 568 HeapPage<Header>* m_next; |
| 569 intptr_t m_padding; // Preserve 8-byte alignment on 32-bit systems. | 569 intptr_t m_padding; // Preserve 8-byte alignment on 32-bit systems. |
| 570 bool m_objectStartBitMapComputed; | 570 bool m_objectStartBitMapComputed; |
| 571 uint8_t m_objectStartBitMap[reservedForObjectBitMap]; | 571 uint8_t m_objectStartBitMap[reservedForObjectBitMap]; |
| 572 | 572 |
| 573 friend class ThreadHeap<Header>; | 573 friend class ThreadHeap<Header>; |
| 574 }; | 574 }; |
| 575 | 575 |
| 576 class AddressEntry { | 576 // A HeapDoesNotContainCache provides a fast way of taking an arbitrary |
| 577 // pointer-sized word, and determining whether it cannot be interpreted |
| 578 // as a pointer to an area that is managed by the garbage collected |
| 579 // Blink heap. This is a cache of 'pages' that have previously been |
| 580 // determined to be wholly outside of the heap. The size of these pages must be |
| 581 // smaller than the allocation alignment of the heap pages. We determine |
| 582 // off-heap-ness by rounding down the pointer to the nearest page and looking up |
| 583 // the page in the cache. If there is a miss in the cache we can determine the |
| 584 // status of the pointer precisely using the heap RegionTree. |
| 585 // |
| 586 // The HeapDoesNotContainCache is a negative cache, so it must be |
| 587 // flushed when memory is added to the heap. |
| 588 class HeapDoesNotContainCache { |
| 577 public: | 589 public: |
| 578 AddressEntry() : m_address(0) { } | 590 HeapDoesNotContainCache() |
| 579 | 591 : m_entries(adoptArrayPtr(new Address[HeapDoesNotContainCache::numberOfE
ntries])) |
| 580 explicit AddressEntry(Address address) : m_address(address) { } | 592 , m_hasEntries(true) |
| 581 | |
| 582 Address address() const { return m_address; } | |
| 583 | |
| 584 private: | |
| 585 Address m_address; | |
| 586 }; | |
| 587 | |
| 588 class PositiveEntry : public AddressEntry { | |
| 589 public: | |
| 590 PositiveEntry() | |
| 591 : AddressEntry() | |
| 592 , m_containingPage(0) | |
| 593 { | 593 { |
| 594 } | 594 // Start by flushing the cache in a non-empty state to initialize all th
e cache entries. |
| 595 | 595 flush(); |
| 596 PositiveEntry(Address address, BaseHeapPage* containingPage) | |
| 597 : AddressEntry(address) | |
| 598 , m_containingPage(containingPage) | |
| 599 { | |
| 600 } | |
| 601 | |
| 602 BaseHeapPage* result() const { return m_containingPage; } | |
| 603 | |
| 604 typedef BaseHeapPage* LookupResult; | |
| 605 | |
| 606 private: | |
| 607 BaseHeapPage* m_containingPage; | |
| 608 }; | |
| 609 | |
| 610 class NegativeEntry : public AddressEntry { | |
| 611 public: | |
| 612 NegativeEntry() : AddressEntry() { } | |
| 613 | |
| 614 NegativeEntry(Address address, bool) : AddressEntry(address) { } | |
| 615 | |
| 616 bool result() const { return true; } | |
| 617 | |
| 618 typedef bool LookupResult; | |
| 619 }; | |
| 620 | |
| 621 // A HeapExtentCache provides a fast way of taking an arbitrary | |
| 622 // pointer-sized word, and determining whether it can be interpreted | |
| 623 // as a pointer to an area that is managed by the garbage collected | |
| 624 // Blink heap. There is a cache of 'pages' that have previously been | |
| 625 // determined to be wholly inside the heap. The size of these pages must be | |
| 626 // smaller than the allocation alignment of the heap pages. We determine | |
| 627 // on-heap-ness by rounding down the pointer to the nearest page and looking up | |
| 628 // the page in the cache. If there is a miss in the cache we can ask the heap | |
| 629 // to determine the status of the pointer by iterating over all of the heap. | |
| 630 // The result is then cached in the two-way associative page cache. | |
| 631 // | |
| 632 // A HeapContainsCache is a positive cache. Therefore, it must be flushed when | |
| 633 // memory is removed from the Blink heap. The HeapDoesNotContainCache is a | |
| 634 // negative cache, so it must be flushed when memory is added to the heap. | |
| 635 template<typename Entry> | |
| 636 class HeapExtentCache { | |
| 637 public: | |
| 638 HeapExtentCache() | |
| 639 : m_entries(adoptArrayPtr(new Entry[HeapExtentCache::numberOfEntries])) | |
| 640 , m_hasEntries(false) | |
| 641 { | |
| 642 } | 596 } |
| 643 | 597 |
| 644 void flush(); | 598 void flush(); |
| 645 bool contains(Address); | |
| 646 bool isEmpty() { return !m_hasEntries; } | 599 bool isEmpty() { return !m_hasEntries; } |
| 647 | 600 |
| 648 // Perform a lookup in the cache. | 601 // Perform a lookup in the cache. |
| 649 // | 602 // |
| 650 // If lookup returns null/false the argument address was not found in | 603 // If lookup returns false, the argument address was not found in |
| 651 // the cache and it is unknown if the address is in the Blink | 604 // the cache and it is unknown if the address is in the Blink |
| 652 // heap. | 605 // heap. |
| 653 // | 606 // |
| 654 // If lookup returns true/a page, the argument address was found in the | 607 // If lookup returns true, the argument address was found in the |
| 655 // cache. For the HeapContainsCache this means the address is in the heap. | 608 // cache which means the address is not in the heap. |
| 656 // For the HeapDoesNotContainCache this means the address is not in the | 609 PLATFORM_EXPORT bool lookup(Address); |
| 657 // heap. | |
| 658 PLATFORM_EXPORT typename Entry::LookupResult lookup(Address); | |
| 659 | 610 |
| 660 // Add an entry to the cache. | 611 // Add an entry to the cache. |
| 661 PLATFORM_EXPORT void addEntry(Address, typename Entry::LookupResult); | 612 PLATFORM_EXPORT void addEntry(Address); |
| 662 | 613 |
| 663 private: | 614 private: |
| 664 static const int numberOfEntriesLog2 = 12; | 615 static const int numberOfEntriesLog2 = 12; |
| 665 static const int numberOfEntries = 1 << numberOfEntriesLog2; | 616 static const int numberOfEntries = 1 << numberOfEntriesLog2; |
| 666 | 617 |
| 667 static size_t hash(Address); | 618 static size_t hash(Address); |
| 668 | 619 |
| 669 WTF::OwnPtr<Entry[]> m_entries; | 620 WTF::OwnPtr<Address[]> m_entries; |
| 670 bool m_hasEntries; | 621 bool m_hasEntries; |
| 671 | |
| 672 friend class ThreadState; | |
| 673 }; | 622 }; |
| 674 | 623 |
| 675 // Normally these would be typedefs instead of subclasses, but that makes them | |
| 676 // very hard to forward declare. | |
| 677 class HeapContainsCache : public HeapExtentCache<PositiveEntry> { | |
| 678 public: | |
| 679 BaseHeapPage* lookup(Address); | |
| 680 void addEntry(Address, BaseHeapPage*); | |
| 681 }; | |
| 682 | |
| 683 class HeapDoesNotContainCache : public HeapExtentCache<NegativeEntry> { }; | |
| 684 | |
| 685 // FIXME: This is currently used by the WebAudio code. | 624 // FIXME: This is currently used by the WebAudio code. |
| 686 // We should attempt to restructure the WebAudio code so that the main thread | 625 // We should attempt to restructure the WebAudio code so that the main thread |
| 687 // alone determines life-time and receives messages about life-time from the | 626 // alone determines life-time and receives messages about life-time from the |
| 688 // audio thread. | 627 // audio thread. |
| 689 template<typename T> | 628 template<typename T> |
| 690 class ThreadSafeRefCountedGarbageCollected : public GarbageCollectedFinalized<T>
, public WTF::ThreadSafeRefCountedBase { | 629 class ThreadSafeRefCountedGarbageCollected : public GarbageCollectedFinalized<T>
, public WTF::ThreadSafeRefCountedBase { |
| 691 WTF_MAKE_NONCOPYABLE(ThreadSafeRefCountedGarbageCollected); | 630 WTF_MAKE_NONCOPYABLE(ThreadSafeRefCountedGarbageCollected); |
| 692 | 631 |
| 693 public: | 632 public: |
| 694 ThreadSafeRefCountedGarbageCollected() | 633 ThreadSafeRefCountedGarbageCollected() |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 868 virtual void makeConsistentForSweeping(); | 807 virtual void makeConsistentForSweeping(); |
| 869 | 808 |
| 870 #if ENABLE(ASSERT) | 809 #if ENABLE(ASSERT) |
| 871 virtual bool isConsistentForSweeping(); | 810 virtual bool isConsistentForSweeping(); |
| 872 | 811 |
| 873 virtual void getScannedStats(HeapStats&); | 812 virtual void getScannedStats(HeapStats&); |
| 874 #endif | 813 #endif |
| 875 | 814 |
| 876 ThreadState* threadState() { return m_threadState; } | 815 ThreadState* threadState() { return m_threadState; } |
| 877 HeapStats& stats() { return m_threadState->stats(); } | 816 HeapStats& stats() { return m_threadState->stats(); } |
| 878 void flushHeapContainsCache() | |
| 879 { | |
| 880 m_threadState->heapContainsCache()->flush(); | |
| 881 } | |
| 882 | 817 |
| 883 inline Address allocate(size_t, const GCInfo*); | 818 inline Address allocate(size_t, const GCInfo*); |
| 884 void addToFreeList(Address, size_t); | 819 void addToFreeList(Address, size_t); |
| 885 inline static size_t roundedAllocationSize(size_t size) | 820 inline static size_t roundedAllocationSize(size_t size) |
| 886 { | 821 { |
| 887 return allocationSizeFromSize(size) - sizeof(Header); | 822 return allocationSizeFromSize(size) - sizeof(Header); |
| 888 } | 823 } |
| 889 | 824 |
| 890 virtual void prepareHeapForTermination(); | 825 virtual void prepareHeapForTermination(); |
| 891 | 826 |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1065 static void flushHeapDoesNotContainCache(); | 1000 static void flushHeapDoesNotContainCache(); |
| 1066 static bool heapDoesNotContainCacheIsEmpty() { return s_heapDoesNotContainCa
che->isEmpty(); } | 1001 static bool heapDoesNotContainCacheIsEmpty() { return s_heapDoesNotContainCa
che->isEmpty(); } |
| 1067 | 1002 |
| 1068 // Return true if the last GC found a pointer into a heap page | 1003 // Return true if the last GC found a pointer into a heap page |
| 1069 // during conservative scanning. | 1004 // during conservative scanning. |
| 1070 static bool lastGCWasConservative() { return s_lastGCWasConservative; } | 1005 static bool lastGCWasConservative() { return s_lastGCWasConservative; } |
| 1071 | 1006 |
| 1072 static FreePagePool* freePagePool() { return s_freePagePool; } | 1007 static FreePagePool* freePagePool() { return s_freePagePool; } |
| 1073 static OrphanedPagePool* orphanedPagePool() { return s_orphanedPagePool; } | 1008 static OrphanedPagePool* orphanedPagePool() { return s_orphanedPagePool; } |
| 1074 | 1009 |
| 1010 // This look-up uses the region search tree and a negative contains cache to |
| 1011 // provide an efficient mapping from arbitrary addresses to the containing |
| 1012 // heap-page if one exists. |
| 1013 static BaseHeapPage* lookup(Address); |
| 1014 static void addPageMemoryRegion(PageMemoryRegion*); |
| 1015 static void removePageMemoryRegion(PageMemoryRegion*); |
| 1016 |
| 1075 private: | 1017 private: |
| 1018 // A RegionTree is a simple binary search tree of PageMemoryRegions sorted |
| 1019 // by base addresses. |
| 1020 class RegionTree { |
| 1021 public: |
| 1022 explicit RegionTree(PageMemoryRegion* region) : m_region(region), m_left
(0), m_right(0) { } |
| 1023 ~RegionTree() |
| 1024 { |
| 1025 delete m_left; |
| 1026 delete m_right; |
| 1027 } |
| 1028 PageMemoryRegion* lookup(Address); |
| 1029 static void add(RegionTree*, RegionTree**); |
| 1030 static void remove(PageMemoryRegion*, RegionTree**); |
| 1031 private: |
| 1032 PageMemoryRegion* m_region; |
| 1033 RegionTree* m_left; |
| 1034 RegionTree* m_right; |
| 1035 }; |
| 1036 |
| 1076 static Visitor* s_markingVisitor; | 1037 static Visitor* s_markingVisitor; |
| 1077 static Vector<OwnPtr<blink::WebThread> >* s_markingThreads; | 1038 static Vector<OwnPtr<blink::WebThread> >* s_markingThreads; |
| 1078 static CallbackStack* s_markingStack; | 1039 static CallbackStack* s_markingStack; |
| 1079 static CallbackStack* s_postMarkingCallbackStack; | 1040 static CallbackStack* s_postMarkingCallbackStack; |
| 1080 static CallbackStack* s_weakCallbackStack; | 1041 static CallbackStack* s_weakCallbackStack; |
| 1081 static CallbackStack* s_ephemeronStack; | 1042 static CallbackStack* s_ephemeronStack; |
| 1082 static HeapDoesNotContainCache* s_heapDoesNotContainCache; | 1043 static HeapDoesNotContainCache* s_heapDoesNotContainCache; |
| 1083 static bool s_shutdownCalled; | 1044 static bool s_shutdownCalled; |
| 1084 static bool s_lastGCWasConservative; | 1045 static bool s_lastGCWasConservative; |
| 1085 static FreePagePool* s_freePagePool; | 1046 static FreePagePool* s_freePagePool; |
| 1086 static OrphanedPagePool* s_orphanedPagePool; | 1047 static OrphanedPagePool* s_orphanedPagePool; |
| 1048 static RegionTree* s_regionTree; |
| 1087 friend class ThreadState; | 1049 friend class ThreadState; |
| 1088 }; | 1050 }; |
| 1089 | 1051 |
| 1090 // The NoAllocationScope class is used in debug mode to catch unwanted | 1052 // The NoAllocationScope class is used in debug mode to catch unwanted |
| 1091 // allocations. E.g. allocations during GC. | 1053 // allocations. E.g. allocations during GC. |
| 1092 template<ThreadAffinity Affinity> | 1054 template<ThreadAffinity Affinity> |
| 1093 class NoAllocationScope { | 1055 class NoAllocationScope { |
| 1094 public: | 1056 public: |
| 1095 NoAllocationScope() : m_active(true) { enter(); } | 1057 NoAllocationScope() : m_active(true) { enter(); } |
| 1096 | 1058 |
| (...skipping 1391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2488 }; | 2450 }; |
| 2489 | 2451 |
| 2490 template<typename T> | 2452 template<typename T> |
| 2491 struct IfWeakMember<WeakMember<T> > { | 2453 struct IfWeakMember<WeakMember<T> > { |
| 2492 static bool isDead(Visitor* visitor, const WeakMember<T>& t) { return !visit
or->isAlive(t.get()); } | 2454 static bool isDead(Visitor* visitor, const WeakMember<T>& t) { return !visit
or->isAlive(t.get()); } |
| 2493 }; | 2455 }; |
| 2494 | 2456 |
| 2495 } | 2457 } |
| 2496 | 2458 |
| 2497 #endif // Heap_h | 2459 #endif // Heap_h |
| OLD | NEW |