| 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 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 Address addr = reinterpret_cast<Address>(const_cast<void*>(payload)); | 577 Address addr = reinterpret_cast<Address>(const_cast<void*>(payload)); |
| 578 FinalizedHeapObjectHeader* header = | 578 FinalizedHeapObjectHeader* header = |
| 579 reinterpret_cast<FinalizedHeapObjectHeader*>(addr - finalizedHeaderSize)
; | 579 reinterpret_cast<FinalizedHeapObjectHeader*>(addr - finalizedHeaderSize)
; |
| 580 return header; | 580 return header; |
| 581 } | 581 } |
| 582 | 582 |
| 583 template<typename Header> | 583 template<typename Header> |
| 584 ThreadHeap<Header>::ThreadHeap(ThreadState* state, int index) | 584 ThreadHeap<Header>::ThreadHeap(ThreadState* state, int index) |
| 585 : m_currentAllocationPoint(0) | 585 : m_currentAllocationPoint(0) |
| 586 , m_remainingAllocationSize(0) | 586 , m_remainingAllocationSize(0) |
| 587 , m_lastRemainingAllocationSize(0) |
| 587 , m_firstPage(0) | 588 , m_firstPage(0) |
| 588 , m_firstLargeHeapObject(0) | 589 , m_firstLargeHeapObject(0) |
| 589 , m_firstPageAllocatedDuringSweeping(0) | 590 , m_firstPageAllocatedDuringSweeping(0) |
| 590 , m_lastPageAllocatedDuringSweeping(0) | 591 , m_lastPageAllocatedDuringSweeping(0) |
| 591 , m_mergePoint(0) | 592 , m_mergePoint(0) |
| 592 , m_biggestFreeListIndex(0) | 593 , m_biggestFreeListIndex(0) |
| 593 , m_threadState(state) | 594 , m_threadState(state) |
| 594 , m_index(index) | 595 , m_index(index) |
| 595 , m_numberOfNormalPages(0) | 596 , m_numberOfNormalPages(0) |
| 596 , m_promptlyFreedCount(0) | 597 , m_promptlyFreedCount(0) |
| (...skipping 21 matching lines...) Expand all Loading... |
| 618 | 619 |
| 619 for (LargeHeapObject<Header>* largeObject = m_firstLargeHeapObject; largeObj
ect; largeObject = largeObject->m_next) | 620 for (LargeHeapObject<Header>* largeObject = m_firstLargeHeapObject; largeObj
ect; largeObject = largeObject->m_next) |
| 620 Heap::orphanedPagePool()->addOrphanedPage(m_index, largeObject); | 621 Heap::orphanedPagePool()->addOrphanedPage(m_index, largeObject); |
| 621 m_firstLargeHeapObject = 0; | 622 m_firstLargeHeapObject = 0; |
| 622 } | 623 } |
| 623 | 624 |
| 624 template<typename Header> | 625 template<typename Header> |
| 625 Address ThreadHeap<Header>::outOfLineAllocate(size_t size, const GCInfo* gcInfo) | 626 Address ThreadHeap<Header>::outOfLineAllocate(size_t size, const GCInfo* gcInfo) |
| 626 { | 627 { |
| 627 size_t allocationSize = allocationSizeFromSize(size); | 628 size_t allocationSize = allocationSizeFromSize(size); |
| 629 ASSERT(allocationSize > remainingAllocationSize()); |
| 630 if (allocationSize > HeapPage<Header>::payloadSize() / 2) |
| 631 return allocateLargeObject(allocationSize, gcInfo); |
| 632 |
| 633 if (remainingAllocationSize() > 0) |
| 634 addToFreeList(currentAllocationPoint(), remainingAllocationSize()); |
| 635 // This also updates the stats. |
| 636 setAllocationPoint(0, 0); |
| 628 if (threadState()->shouldGC()) { | 637 if (threadState()->shouldGC()) { |
| 629 if (threadState()->shouldForceConservativeGC()) | 638 if (threadState()->shouldForceConservativeGC()) |
| 630 Heap::collectGarbage(ThreadState::HeapPointersOnStack); | 639 Heap::collectGarbage(ThreadState::HeapPointersOnStack); |
| 631 else | 640 else |
| 632 threadState()->setGCRequested(); | 641 threadState()->setGCRequested(); |
| 633 } | 642 } |
| 634 ensureCurrentAllocation(allocationSize, gcInfo); | 643 ensureCurrentAllocation(allocationSize, gcInfo); |
| 635 return allocate(size, gcInfo); | 644 return allocate(size, gcInfo); |
| 636 } | 645 } |
| 637 | 646 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 653 } | 662 } |
| 654 } | 663 } |
| 655 m_biggestFreeListIndex = i; | 664 m_biggestFreeListIndex = i; |
| 656 return false; | 665 return false; |
| 657 } | 666 } |
| 658 | 667 |
| 659 template<typename Header> | 668 template<typename Header> |
| 660 void ThreadHeap<Header>::ensureCurrentAllocation(size_t minSize, const GCInfo* g
cInfo) | 669 void ThreadHeap<Header>::ensureCurrentAllocation(size_t minSize, const GCInfo* g
cInfo) |
| 661 { | 670 { |
| 662 ASSERT(minSize >= allocationGranularity); | 671 ASSERT(minSize >= allocationGranularity); |
| 663 if (remainingAllocationSize() >= minSize) | |
| 664 return; | |
| 665 | |
| 666 if (remainingAllocationSize() > 0) { | |
| 667 addToFreeList(currentAllocationPoint(), remainingAllocationSize()); | |
| 668 setAllocationPoint(0, 0); | |
| 669 } | |
| 670 if (allocateFromFreeList(minSize)) | 672 if (allocateFromFreeList(minSize)) |
| 671 return; | 673 return; |
| 672 if (coalesce(minSize) && allocateFromFreeList(minSize)) | 674 if (coalesce(minSize) && allocateFromFreeList(minSize)) |
| 673 return; | 675 return; |
| 674 addPageToHeap(gcInfo); | 676 addPageToHeap(gcInfo); |
| 675 bool success = allocateFromFreeList(minSize); | 677 bool success = allocateFromFreeList(minSize); |
| 676 RELEASE_ASSERT(success); | 678 RELEASE_ASSERT(success); |
| 677 } | 679 } |
| 678 | 680 |
| 679 template<typename Header> | 681 template<typename Header> |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 849 page->clearObjectStartBitMap(); | 851 page->clearObjectStartBitMap(); |
| 850 page->resetPromptlyFreedSize(); | 852 page->resetPromptlyFreedSize(); |
| 851 size_t freedCount = 0; | 853 size_t freedCount = 0; |
| 852 Address startOfGap = page->payload(); | 854 Address startOfGap = page->payload(); |
| 853 for (Address headerAddress = startOfGap; headerAddress < page->end(); )
{ | 855 for (Address headerAddress = startOfGap; headerAddress < page->end(); )
{ |
| 854 BasicObjectHeader* basicHeader = reinterpret_cast<BasicObjectHeader*
>(headerAddress); | 856 BasicObjectHeader* basicHeader = reinterpret_cast<BasicObjectHeader*
>(headerAddress); |
| 855 ASSERT(basicHeader->size() > 0); | 857 ASSERT(basicHeader->size() > 0); |
| 856 ASSERT(basicHeader->size() < blinkPagePayloadSize()); | 858 ASSERT(basicHeader->size() < blinkPagePayloadSize()); |
| 857 | 859 |
| 858 if (basicHeader->isPromptlyFreed()) { | 860 if (basicHeader->isPromptlyFreed()) { |
| 859 stats().decreaseObjectSpace(reinterpret_cast<Header*>(basicHeade
r)->payloadSize()); | 861 stats().decreaseObjectSpace(reinterpret_cast<Header*>(basicHeade
r)->size()); |
| 860 size_t size = basicHeader->size(); | 862 size_t size = basicHeader->size(); |
| 861 ASSERT(size >= sizeof(Header)); | 863 ASSERT(size >= sizeof(Header)); |
| 862 #if !ENABLE(ASSERT) && !defined(LEAK_SANITIZER) && !defined(ADDRESS_SANITIZER) | 864 #if !ENABLE(ASSERT) && !defined(LEAK_SANITIZER) && !defined(ADDRESS_SANITIZER) |
| 863 memset(headerAddress, 0, sizeof(Header)); | 865 memset(headerAddress, 0, sizeof(Header)); |
| 864 #endif | 866 #endif |
| 865 ++freedCount; | 867 ++freedCount; |
| 866 headerAddress += size; | 868 headerAddress += size; |
| 867 continue; | 869 continue; |
| 868 } | 870 } |
| 869 | 871 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 914 // Ensure that there is enough space for alignment. If the header | 916 // Ensure that there is enough space for alignment. If the header |
| 915 // is not a multiple of 8 bytes we will allocate an extra | 917 // is not a multiple of 8 bytes we will allocate an extra |
| 916 // headerPadding<Header> bytes to ensure it 8 byte aligned. | 918 // headerPadding<Header> bytes to ensure it 8 byte aligned. |
| 917 allocationSize += headerPadding<Header>(); | 919 allocationSize += headerPadding<Header>(); |
| 918 | 920 |
| 919 // If ASan is supported we add allocationGranularity bytes to the allocated
space and | 921 // If ASan is supported we add allocationGranularity bytes to the allocated
space and |
| 920 // poison that to detect overflows | 922 // poison that to detect overflows |
| 921 #if defined(ADDRESS_SANITIZER) | 923 #if defined(ADDRESS_SANITIZER) |
| 922 allocationSize += allocationGranularity; | 924 allocationSize += allocationGranularity; |
| 923 #endif | 925 #endif |
| 926 |
| 927 // Update stats before checking if we should GC. |
| 928 if (m_lastRemainingAllocationSize != m_remainingAllocationSize) { |
| 929 stats().increaseObjectSpace(m_lastRemainingAllocationSize-m_remainingAll
ocationSize); |
| 930 m_lastRemainingAllocationSize = m_remainingAllocationSize; |
| 931 } |
| 924 if (threadState()->shouldGC()) | 932 if (threadState()->shouldGC()) |
| 925 threadState()->setGCRequested(); | 933 threadState()->setGCRequested(); |
| 926 Heap::flushHeapDoesNotContainCache(); | 934 Heap::flushHeapDoesNotContainCache(); |
| 927 PageMemory* pageMemory = PageMemory::allocate(allocationSize); | 935 PageMemory* pageMemory = PageMemory::allocate(allocationSize); |
| 928 Address largeObjectAddress = pageMemory->writableStart(); | 936 Address largeObjectAddress = pageMemory->writableStart(); |
| 929 Address headerAddress = largeObjectAddress + sizeof(LargeHeapObject<Header>)
+ headerPadding<Header>(); | 937 Address headerAddress = largeObjectAddress + sizeof(LargeHeapObject<Header>)
+ headerPadding<Header>(); |
| 930 memset(headerAddress, 0, size); | 938 memset(headerAddress, 0, size); |
| 931 Header* header = new (NotNull, headerAddress) Header(size, gcInfo); | 939 Header* header = new (NotNull, headerAddress) Header(size, gcInfo); |
| 932 Address result = headerAddress + sizeof(*header); | 940 Address result = headerAddress + sizeof(*header); |
| 933 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask)); | 941 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask)); |
| 934 LargeHeapObject<Header>* largeObject = new (largeObjectAddress) LargeHeapObj
ect<Header>(pageMemory, gcInfo, threadState()); | 942 LargeHeapObject<Header>* largeObject = new (largeObjectAddress) LargeHeapObj
ect<Header>(pageMemory, gcInfo, threadState()); |
| 935 | 943 |
| 936 // Poison the object header and allocationGranularity bytes after the object | 944 // Poison the object header and allocationGranularity bytes after the object |
| 937 ASAN_POISON_MEMORY_REGION(header, sizeof(*header)); | 945 ASAN_POISON_MEMORY_REGION(header, sizeof(*header)); |
| 938 ASAN_POISON_MEMORY_REGION(largeObject->address() + largeObject->size(), allo
cationGranularity); | 946 ASAN_POISON_MEMORY_REGION(largeObject->address() + largeObject->size(), allo
cationGranularity); |
| 939 largeObject->link(&m_firstLargeHeapObject); | 947 largeObject->link(&m_firstLargeHeapObject); |
| 940 stats().increaseAllocatedSpace(largeObject->size()); | 948 stats().increaseAllocatedSpace(largeObject->size()); |
| 941 stats().increaseObjectSpace(largeObject->payloadSize()); | 949 stats().increaseObjectSpace(largeObject->size()); |
| 942 return result; | 950 return result; |
| 943 } | 951 } |
| 944 | 952 |
| 945 template<typename Header> | 953 template<typename Header> |
| 946 void ThreadHeap<Header>::freeLargeObject(LargeHeapObject<Header>* object, LargeH
eapObject<Header>** previousNext) | 954 void ThreadHeap<Header>::freeLargeObject(LargeHeapObject<Header>* object, LargeH
eapObject<Header>** previousNext) |
| 947 { | 955 { |
| 948 flushHeapContainsCache(); | 956 flushHeapContainsCache(); |
| 949 object->unlink(previousNext); | 957 object->unlink(previousNext); |
| 950 object->finalize(); | 958 object->finalize(); |
| 951 | 959 |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1265 } | 1273 } |
| 1266 | 1274 |
| 1267 template<typename Header> | 1275 template<typename Header> |
| 1268 void ThreadHeap<Header>::sweepLargePages(HeapStats* stats) | 1276 void ThreadHeap<Header>::sweepLargePages(HeapStats* stats) |
| 1269 { | 1277 { |
| 1270 TRACE_EVENT0("blink_gc", "ThreadHeap::sweepLargePages"); | 1278 TRACE_EVENT0("blink_gc", "ThreadHeap::sweepLargePages"); |
| 1271 LargeHeapObject<Header>** previousNext = &m_firstLargeHeapObject; | 1279 LargeHeapObject<Header>** previousNext = &m_firstLargeHeapObject; |
| 1272 for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current;) { | 1280 for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current;) { |
| 1273 if (current->isMarked()) { | 1281 if (current->isMarked()) { |
| 1274 stats->increaseAllocatedSpace(current->size()); | 1282 stats->increaseAllocatedSpace(current->size()); |
| 1275 stats->increaseObjectSpace(current->payloadSize()); | 1283 stats->increaseObjectSpace(current->size()); |
| 1276 current->unmark(); | 1284 current->unmark(); |
| 1277 previousNext = ¤t->m_next; | 1285 previousNext = ¤t->m_next; |
| 1278 current = current->next(); | 1286 current = current->next(); |
| 1279 } else { | 1287 } else { |
| 1280 LargeHeapObject<Header>* next = current->next(); | 1288 LargeHeapObject<Header>* next = current->next(); |
| 1281 freeLargeObject(current, previousNext); | 1289 freeLargeObject(current, previousNext); |
| 1282 current = next; | 1290 current = next; |
| 1283 } | 1291 } |
| 1284 } | 1292 } |
| 1285 } | 1293 } |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1416 | 1424 |
| 1417 template<typename Header> | 1425 template<typename Header> |
| 1418 void HeapPage<Header>::getStats(HeapStats& stats) | 1426 void HeapPage<Header>::getStats(HeapStats& stats) |
| 1419 { | 1427 { |
| 1420 stats.increaseAllocatedSpace(blinkPageSize); | 1428 stats.increaseAllocatedSpace(blinkPageSize); |
| 1421 Address headerAddress = payload(); | 1429 Address headerAddress = payload(); |
| 1422 ASSERT(headerAddress != end()); | 1430 ASSERT(headerAddress != end()); |
| 1423 do { | 1431 do { |
| 1424 Header* header = reinterpret_cast<Header*>(headerAddress); | 1432 Header* header = reinterpret_cast<Header*>(headerAddress); |
| 1425 if (!header->isFree()) | 1433 if (!header->isFree()) |
| 1426 stats.increaseObjectSpace(header->payloadSize()); | 1434 stats.increaseObjectSpace(header->size()); |
| 1427 ASSERT(header->size() < blinkPagePayloadSize()); | 1435 ASSERT(header->size() < blinkPagePayloadSize()); |
| 1428 headerAddress += header->size(); | 1436 headerAddress += header->size(); |
| 1429 ASSERT(headerAddress <= end()); | 1437 ASSERT(headerAddress <= end()); |
| 1430 } while (headerAddress < end()); | 1438 } while (headerAddress < end()); |
| 1431 } | 1439 } |
| 1432 | 1440 |
| 1433 template<typename Header> | 1441 template<typename Header> |
| 1434 bool HeapPage<Header>::isEmpty() | 1442 bool HeapPage<Header>::isEmpty() |
| 1435 { | 1443 { |
| 1436 BasicObjectHeader* header = reinterpret_cast<BasicObjectHeader*>(payload()); | 1444 BasicObjectHeader* header = reinterpret_cast<BasicObjectHeader*>(payload()); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1480 #endif | 1488 #endif |
| 1481 ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize()); | 1489 ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize()); |
| 1482 headerAddress += size; | 1490 headerAddress += size; |
| 1483 continue; | 1491 continue; |
| 1484 } | 1492 } |
| 1485 | 1493 |
| 1486 if (startOfGap != headerAddress) | 1494 if (startOfGap != headerAddress) |
| 1487 heap->addToFreeList(startOfGap, headerAddress - startOfGap); | 1495 heap->addToFreeList(startOfGap, headerAddress - startOfGap); |
| 1488 header->unmark(); | 1496 header->unmark(); |
| 1489 headerAddress += header->size(); | 1497 headerAddress += header->size(); |
| 1490 stats->increaseObjectSpace(header->payloadSize()); | 1498 stats->increaseObjectSpace(header->size()); |
| 1491 startOfGap = headerAddress; | 1499 startOfGap = headerAddress; |
| 1492 } | 1500 } |
| 1493 if (startOfGap != end()) | 1501 if (startOfGap != end()) |
| 1494 heap->addToFreeList(startOfGap, end() - startOfGap); | 1502 heap->addToFreeList(startOfGap, end() - startOfGap); |
| 1495 } | 1503 } |
| 1496 | 1504 |
| 1497 template<typename Header> | 1505 template<typename Header> |
| 1498 void HeapPage<Header>::clearLiveAndMarkDead() | 1506 void HeapPage<Header>::clearLiveAndMarkDead() |
| 1499 { | 1507 { |
| 1500 for (Address headerAddress = payload(); headerAddress < end();) { | 1508 for (Address headerAddress = payload(); headerAddress < end();) { |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1709 template<> | 1717 template<> |
| 1710 inline bool HeapPage<FinalizedHeapObjectHeader>::hasVTable(FinalizedHeapObjectHe
ader* header) | 1718 inline bool HeapPage<FinalizedHeapObjectHeader>::hasVTable(FinalizedHeapObjectHe
ader* header) |
| 1711 { | 1719 { |
| 1712 return header->hasVTable(); | 1720 return header->hasVTable(); |
| 1713 } | 1721 } |
| 1714 | 1722 |
| 1715 template<typename Header> | 1723 template<typename Header> |
| 1716 void LargeHeapObject<Header>::getStats(HeapStats& stats) | 1724 void LargeHeapObject<Header>::getStats(HeapStats& stats) |
| 1717 { | 1725 { |
| 1718 stats.increaseAllocatedSpace(size()); | 1726 stats.increaseAllocatedSpace(size()); |
| 1719 stats.increaseObjectSpace(payloadSize()); | 1727 stats.increaseObjectSpace(size()); |
| 1720 } | 1728 } |
| 1721 | 1729 |
| 1722 #if ENABLE(GC_PROFILE_HEAP) | 1730 #if ENABLE(GC_PROFILE_HEAP) |
| 1723 template<typename Header> | 1731 template<typename Header> |
| 1724 void LargeHeapObject<Header>::snapshot(TracedValue* json, ThreadState::SnapshotI
nfo* info) | 1732 void LargeHeapObject<Header>::snapshot(TracedValue* json, ThreadState::SnapshotI
nfo* info) |
| 1725 { | 1733 { |
| 1726 Header* header = heapObjectHeader(); | 1734 Header* header = heapObjectHeader(); |
| 1727 size_t tag = info->getClassTag(header->gcInfo()); | 1735 size_t tag = info->getClassTag(header->gcInfo()); |
| 1728 size_t age = header->age(); | 1736 size_t age = header->age(); |
| 1729 if (isMarked()) { | 1737 if (isMarked()) { |
| (...skipping 991 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2721 CallbackStack* Heap::s_markingStack; | 2729 CallbackStack* Heap::s_markingStack; |
| 2722 CallbackStack* Heap::s_postMarkingCallbackStack; | 2730 CallbackStack* Heap::s_postMarkingCallbackStack; |
| 2723 CallbackStack* Heap::s_weakCallbackStack; | 2731 CallbackStack* Heap::s_weakCallbackStack; |
| 2724 CallbackStack* Heap::s_ephemeronStack; | 2732 CallbackStack* Heap::s_ephemeronStack; |
| 2725 HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache; | 2733 HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache; |
| 2726 bool Heap::s_shutdownCalled = false; | 2734 bool Heap::s_shutdownCalled = false; |
| 2727 bool Heap::s_lastGCWasConservative = false; | 2735 bool Heap::s_lastGCWasConservative = false; |
| 2728 FreePagePool* Heap::s_freePagePool; | 2736 FreePagePool* Heap::s_freePagePool; |
| 2729 OrphanedPagePool* Heap::s_orphanedPagePool; | 2737 OrphanedPagePool* Heap::s_orphanedPagePool; |
| 2730 } | 2738 } |
| OLD | NEW |