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 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
716 virtual void prepareHeapForTermination() = 0; | 716 virtual void prepareHeapForTermination() = 0; |
717 }; | 717 }; |
718 | 718 |
719 template<typename Header> | 719 template<typename Header> |
720 class FreeList { | 720 class FreeList { |
721 public: | 721 public: |
722 FreeList(); | 722 FreeList(); |
723 | 723 |
724 void addToFreeList(Address, size_t); | 724 void addToFreeList(Address, size_t); |
725 void clear(); | 725 void clear(); |
726 FreeListEntry* takeEntry(size_t allocationSize); | |
727 | 726 |
728 // Returns a bucket number for inserting a FreeListEntry of a given size. | 727 // Returns a bucket number for inserting a FreeListEntry of a given size. |
729 // All FreeListEntries in the given bucket, n, have size >= 2^n. | 728 // All FreeListEntries in the given bucket, n, have size >= 2^n. |
730 static int bucketIndexForSize(size_t); | 729 static int bucketIndexForSize(size_t); |
731 | 730 |
732 private: | 731 private: |
733 int m_biggestFreeListIndex; | 732 int m_biggestFreeListIndex; |
734 | 733 |
735 // All FreeListEntries in the nth list have size >= 2^n. | 734 // All FreeListEntries in the nth list have size >= 2^n. |
736 FreeListEntry* m_freeLists[blinkPageSizeLog2]; | 735 FreeListEntry* m_freeLists[blinkPageSizeLog2]; |
737 | 736 |
738 #if ENABLE(ASSERT) | |
739 friend class ThreadHeap<Header>; | 737 friend class ThreadHeap<Header>; |
740 #endif | |
741 }; | 738 }; |
742 | 739 |
743 // Thread heaps represent a part of the per-thread Blink heap. | 740 // Thread heaps represent a part of the per-thread Blink heap. |
744 // | 741 // |
745 // Each Blink thread has a number of thread heaps: one general heap | 742 // Each Blink thread has a number of thread heaps: one general heap |
746 // that contains any type of object and a number of heaps specialized | 743 // that contains any type of object and a number of heaps specialized |
747 // for specific object types (such as Node). | 744 // for specific object types (such as Node). |
748 // | 745 // |
749 // Each thread heap contains the functionality to allocate new objects | 746 // Each thread heap contains the functionality to allocate new objects |
750 // (potentially adding new pages to the heap), to find and mark | 747 // (potentially adding new pages to the heap), to find and mark |
(...skipping 28 matching lines...) Expand all Loading... |
779 | 776 |
780 ThreadState* threadState() { return m_threadState; } | 777 ThreadState* threadState() { return m_threadState; } |
781 | 778 |
782 void addToFreeList(Address address, size_t size) | 779 void addToFreeList(Address address, size_t size) |
783 { | 780 { |
784 ASSERT(pageFromAddress(address)); | 781 ASSERT(pageFromAddress(address)); |
785 ASSERT(pageFromAddress(address + size - 1)); | 782 ASSERT(pageFromAddress(address + size - 1)); |
786 m_freeList.addToFreeList(address, size); | 783 m_freeList.addToFreeList(address, size); |
787 } | 784 } |
788 | 785 |
789 inline Address allocate(size_t, const GCInfo*); | 786 inline Address allocate(size_t payloadSize, const GCInfo*); |
790 inline static size_t roundedAllocationSize(size_t size) | 787 inline static size_t roundedAllocationSize(size_t size) |
791 { | 788 { |
792 return allocationSizeFromSize(size) - sizeof(Header); | 789 return allocationSizeFromSize(size) - sizeof(Header); |
793 } | 790 } |
794 | 791 |
795 virtual void prepareHeapForTermination() override; | 792 virtual void prepareHeapForTermination() override; |
796 | 793 |
797 void removePageFromHeap(HeapPage<Header>*); | 794 void removePageFromHeap(HeapPage<Header>*); |
798 | 795 |
799 PLATFORM_EXPORT void promptlyFreeObject(Header*); | 796 PLATFORM_EXPORT void promptlyFreeObject(Header*); |
800 PLATFORM_EXPORT bool expandObject(Header*, size_t); | 797 PLATFORM_EXPORT bool expandObject(Header*, size_t); |
801 void shrinkObject(Header*, size_t); | 798 void shrinkObject(Header*, size_t); |
802 | 799 |
803 private: | 800 private: |
804 void addPageToHeap(const GCInfo*); | 801 void addPageToHeap(const GCInfo*); |
805 PLATFORM_EXPORT Address outOfLineAllocate(size_t payloadSize, size_t allocat
ionSize, const GCInfo*); | 802 PLATFORM_EXPORT Address outOfLineAllocate(size_t allocationSize, const GCInf
o*); |
806 static size_t allocationSizeFromSize(size_t); | 803 static size_t allocationSizeFromSize(size_t); |
807 PLATFORM_EXPORT Address allocateLargeObject(size_t, const GCInfo*); | 804 PLATFORM_EXPORT Address allocateLargeObject(size_t, const GCInfo*); |
808 Address currentAllocationPoint() const { return m_currentAllocationPoint; } | 805 Address currentAllocationPoint() const { return m_currentAllocationPoint; } |
809 size_t remainingAllocationSize() const { return m_remainingAllocationSize; } | 806 size_t remainingAllocationSize() const { return m_remainingAllocationSize; } |
810 bool hasCurrentAllocationArea() const { return currentAllocationPoint() && r
emainingAllocationSize(); } | 807 bool hasCurrentAllocationArea() const { return currentAllocationPoint() && r
emainingAllocationSize(); } |
811 void setAllocationPoint(Address point, size_t size) | 808 void setAllocationPoint(Address point, size_t size) |
812 { | 809 { |
813 ASSERT(!point || pageFromAddress(point)); | 810 ASSERT(!point || pageFromAddress(point)); |
814 ASSERT(size <= HeapPage<Header>::payloadSize()); | 811 ASSERT(size <= HeapPage<Header>::payloadSize()); |
815 if (hasCurrentAllocationArea()) | 812 if (hasCurrentAllocationArea()) |
816 addToFreeList(currentAllocationPoint(), remainingAllocationSize()); | 813 addToFreeList(currentAllocationPoint(), remainingAllocationSize()); |
817 updateRemainingAllocationSize(); | 814 updateRemainingAllocationSize(); |
818 m_currentAllocationPoint = point; | 815 m_currentAllocationPoint = point; |
819 m_lastRemainingAllocationSize = m_remainingAllocationSize = size; | 816 m_lastRemainingAllocationSize = m_remainingAllocationSize = size; |
820 } | 817 } |
821 void updateRemainingAllocationSize(); | 818 void updateRemainingAllocationSize(); |
822 bool allocateFromFreeList(size_t); | 819 Address allocateFromFreeList(size_t, const GCInfo*); |
823 | 820 |
824 void freeLargeObject(LargeObject<Header>*, LargeObject<Header>**); | 821 void freeLargeObject(LargeObject<Header>*, LargeObject<Header>**); |
825 void allocatePage(const GCInfo*); | 822 void allocatePage(const GCInfo*); |
826 | 823 |
| 824 inline Address allocateSize(size_t allocationSize, const GCInfo*); |
| 825 inline Address allocateAtAddress(Address, size_t allocationSize, const GCInf
o*); |
| 826 |
827 #if ENABLE(ASSERT) | 827 #if ENABLE(ASSERT) |
828 bool pagesToBeSweptContains(Address); | 828 bool pagesToBeSweptContains(Address); |
829 bool pagesAllocatedDuringSweepingContains(Address); | 829 bool pagesAllocatedDuringSweepingContains(Address); |
830 #endif | 830 #endif |
831 | 831 |
832 void sweepNormalPages(); | 832 void sweepNormalPages(); |
833 void sweepLargePages(); | 833 void sweepLargePages(); |
834 bool coalesce(size_t); | 834 bool coalesce(size_t); |
835 | 835 |
836 Address m_currentAllocationPoint; | 836 Address m_currentAllocationPoint; |
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1275 // therefore has to happen before any calculation on the size. | 1275 // therefore has to happen before any calculation on the size. |
1276 RELEASE_ASSERT(size < maxHeapObjectSize); | 1276 RELEASE_ASSERT(size < maxHeapObjectSize); |
1277 | 1277 |
1278 // Add space for header. | 1278 // Add space for header. |
1279 size_t allocationSize = size + sizeof(Header); | 1279 size_t allocationSize = size + sizeof(Header); |
1280 // Align size with allocation granularity. | 1280 // Align size with allocation granularity. |
1281 allocationSize = (allocationSize + allocationMask) & ~allocationMask; | 1281 allocationSize = (allocationSize + allocationMask) & ~allocationMask; |
1282 return allocationSize; | 1282 return allocationSize; |
1283 } | 1283 } |
1284 | 1284 |
| 1285 |
| 1286 template<typename Header> |
| 1287 inline Address ThreadHeap<Header>::allocateAtAddress(Address headerAddress, size
_t allocationSize, const GCInfo* gcInfo) |
| 1288 { |
| 1289 new (NotNull, headerAddress) Header(allocationSize, gcInfo); |
| 1290 Address result = headerAddress + sizeof(Header); |
| 1291 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask)); |
| 1292 |
| 1293 // Unpoison the memory used for the object (payload). |
| 1294 ASAN_UNPOISON_MEMORY_REGION(result, allocationSize - sizeof(Header)); |
| 1295 FILL_ZERO_IF_NOT_PRODUCTION(result, allocationSize - sizeof(Header)); |
| 1296 ASSERT(pageFromAddress(headerAddress + allocationSize - 1)); |
| 1297 return result; |
| 1298 } |
| 1299 |
| 1300 template<typename Header> |
| 1301 Address ThreadHeap<Header>::allocateSize(size_t allocationSize, const GCInfo* gc
Info) |
| 1302 { |
| 1303 if (LIKELY(allocationSize <= m_remainingAllocationSize)) { |
| 1304 Address headerAddress = m_currentAllocationPoint; |
| 1305 m_currentAllocationPoint += allocationSize; |
| 1306 m_remainingAllocationSize -= allocationSize; |
| 1307 return allocateAtAddress(headerAddress, allocationSize, gcInfo); |
| 1308 } |
| 1309 return outOfLineAllocate(allocationSize, gcInfo); |
| 1310 } |
| 1311 |
1285 template<typename Header> | 1312 template<typename Header> |
1286 Address ThreadHeap<Header>::allocate(size_t size, const GCInfo* gcInfo) | 1313 Address ThreadHeap<Header>::allocate(size_t size, const GCInfo* gcInfo) |
1287 { | 1314 { |
1288 size_t allocationSize = allocationSizeFromSize(size); | 1315 return allocateSize(allocationSizeFromSize(size), gcInfo); |
1289 if (LIKELY(allocationSize <= m_remainingAllocationSize)) { | |
1290 Address headerAddress = m_currentAllocationPoint; | |
1291 m_currentAllocationPoint += allocationSize; | |
1292 m_remainingAllocationSize -= allocationSize; | |
1293 new (NotNull, headerAddress) Header(allocationSize, gcInfo); | |
1294 Address result = headerAddress + sizeof(Header); | |
1295 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask)); | |
1296 | |
1297 // Unpoison the memory used for the object (payload). | |
1298 ASAN_UNPOISON_MEMORY_REGION(result, allocationSize - sizeof(Header)); | |
1299 FILL_ZERO_IF_NOT_PRODUCTION(result, allocationSize - sizeof(Header)); | |
1300 ASSERT(pageFromAddress(headerAddress + allocationSize - 1)); | |
1301 return result; | |
1302 } | |
1303 return outOfLineAllocate(size, allocationSize, gcInfo); | |
1304 } | 1316 } |
1305 | 1317 |
1306 template<typename T, typename HeapTraits> | 1318 template<typename T, typename HeapTraits> |
1307 Address Heap::allocate(size_t size) | 1319 Address Heap::allocate(size_t size) |
1308 { | 1320 { |
1309 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(); | 1321 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(); |
1310 ASSERT(state->isAllocationAllowed()); | 1322 ASSERT(state->isAllocationAllowed()); |
1311 const GCInfo* gcInfo = GCInfoTrait<T>::get(); | 1323 const GCInfo* gcInfo = GCInfoTrait<T>::get(); |
1312 int heapIndex = HeapTraits::index(gcInfo->hasFinalizer(), size); | 1324 int heapIndex = HeapTraits::index(gcInfo->hasFinalizer(), size); |
1313 BaseHeap* heap = state->heap(heapIndex); | 1325 BaseHeap* heap = state->heap(heapIndex); |
(...skipping 1022 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2336 template<typename T, size_t inlineCapacity> | 2348 template<typename T, size_t inlineCapacity> |
2337 struct GCInfoTrait<HeapVector<T, inlineCapacity>> : public GCInfoTrait<Vector<T,
inlineCapacity, HeapAllocator>> { }; | 2349 struct GCInfoTrait<HeapVector<T, inlineCapacity>> : public GCInfoTrait<Vector<T,
inlineCapacity, HeapAllocator>> { }; |
2338 template<typename T, size_t inlineCapacity> | 2350 template<typename T, size_t inlineCapacity> |
2339 struct GCInfoTrait<HeapDeque<T, inlineCapacity>> : public GCInfoTrait<Deque<T, i
nlineCapacity, HeapAllocator>> { }; | 2351 struct GCInfoTrait<HeapDeque<T, inlineCapacity>> : public GCInfoTrait<Deque<T, i
nlineCapacity, HeapAllocator>> { }; |
2340 template<typename T, typename U, typename V> | 2352 template<typename T, typename U, typename V> |
2341 struct GCInfoTrait<HeapHashCountedSet<T, U, V>> : public GCInfoTrait<HashCounted
Set<T, U, V, HeapAllocator>> { }; | 2353 struct GCInfoTrait<HeapHashCountedSet<T, U, V>> : public GCInfoTrait<HashCounted
Set<T, U, V, HeapAllocator>> { }; |
2342 | 2354 |
2343 } // namespace blink | 2355 } // namespace blink |
2344 | 2356 |
2345 #endif // Heap_h | 2357 #endif // Heap_h |
OLD | NEW |