| 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 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 699 // invariant that memory on the free list is zero filled. | 699 // invariant that memory on the free list is zero filled. |
| 700 // The rest of the memory is already on the free list and is | 700 // The rest of the memory is already on the free list and is |
| 701 // therefore already zero filled. | 701 // therefore already zero filled. |
| 702 SET_MEMORY_INACCESSIBLE(headerAddress, size < sizeof(FreeListEntry) | 702 SET_MEMORY_INACCESSIBLE(headerAddress, size < sizeof(FreeListEntry) |
| 703 ? size | 703 ? size |
| 704 : sizeof(FreeListEntry)); | 704 : sizeof(FreeListEntry)); |
| 705 CHECK_MEMORY_INACCESSIBLE(headerAddress, size); | 705 CHECK_MEMORY_INACCESSIBLE(headerAddress, size); |
| 706 headerAddress += size; | 706 headerAddress += size; |
| 707 continue; | 707 continue; |
| 708 } | 708 } |
| 709 header->checkHeader(); | |
| 710 if (startOfGap != headerAddress) | 709 if (startOfGap != headerAddress) |
| 711 addToFreeList(startOfGap, headerAddress - startOfGap); | 710 addToFreeList(startOfGap, headerAddress - startOfGap); |
| 712 | 711 |
| 713 headerAddress += size; | 712 headerAddress += size; |
| 714 startOfGap = headerAddress; | 713 startOfGap = headerAddress; |
| 715 } | 714 } |
| 716 | 715 |
| 717 if (startOfGap != page->payloadEnd()) | 716 if (startOfGap != page->payloadEnd()) |
| 718 addToFreeList(startOfGap, page->payloadEnd() - startOfGap); | 717 addToFreeList(startOfGap, page->payloadEnd() - startOfGap); |
| 719 } | 718 } |
| 720 getThreadState()->decreaseAllocatedObjectSize(freedSize); | 719 getThreadState()->decreaseAllocatedObjectSize(freedSize); |
| 721 ASSERT(m_promptlyFreedSize == freedSize); | 720 ASSERT(m_promptlyFreedSize == freedSize); |
| 722 m_promptlyFreedSize = 0; | 721 m_promptlyFreedSize = 0; |
| 723 return true; | 722 return true; |
| 724 } | 723 } |
| 725 | 724 |
| 726 void NormalPageArena::promptlyFreeObject(HeapObjectHeader* header) { | 725 void NormalPageArena::promptlyFreeObject(HeapObjectHeader* header) { |
| 727 ASSERT(!getThreadState()->sweepForbidden()); | 726 ASSERT(!getThreadState()->sweepForbidden()); |
| 728 header->checkHeader(); | |
| 729 Address address = reinterpret_cast<Address>(header); | 727 Address address = reinterpret_cast<Address>(header); |
| 730 Address payload = header->payload(); | 728 Address payload = header->payload(); |
| 731 size_t size = header->size(); | 729 size_t size = header->size(); |
| 732 size_t payloadSize = header->payloadSize(); | 730 size_t payloadSize = header->payloadSize(); |
| 733 ASSERT(size > 0); | 731 ASSERT(size > 0); |
| 734 ASSERT(pageFromObject(address) == findPageFromAddress(address)); | 732 ASSERT(pageFromObject(address) == findPageFromAddress(address)); |
| 735 | 733 |
| 736 { | 734 { |
| 737 ThreadState::SweepForbiddenScope forbiddenScope(getThreadState()); | 735 ThreadState::SweepForbiddenScope forbiddenScope(getThreadState()); |
| 738 header->finalize(payload, payloadSize); | 736 header->finalize(payload, payloadSize); |
| 739 if (address + size == m_currentAllocationPoint) { | 737 if (address + size == m_currentAllocationPoint) { |
| 740 m_currentAllocationPoint = address; | 738 m_currentAllocationPoint = address; |
| 741 setRemainingAllocationSize(m_remainingAllocationSize + size); | 739 setRemainingAllocationSize(m_remainingAllocationSize + size); |
| 742 SET_MEMORY_INACCESSIBLE(address, size); | 740 SET_MEMORY_INACCESSIBLE(address, size); |
| 743 return; | 741 return; |
| 744 } | 742 } |
| 745 SET_MEMORY_INACCESSIBLE(payload, payloadSize); | 743 SET_MEMORY_INACCESSIBLE(payload, payloadSize); |
| 746 header->markPromptlyFreed(); | 744 header->markPromptlyFreed(); |
| 747 } | 745 } |
| 748 | 746 |
| 749 m_promptlyFreedSize += size; | 747 m_promptlyFreedSize += size; |
| 750 } | 748 } |
| 751 | 749 |
| 752 bool NormalPageArena::expandObject(HeapObjectHeader* header, size_t newSize) { | 750 bool NormalPageArena::expandObject(HeapObjectHeader* header, size_t newSize) { |
| 753 // It's possible that Vector requests a smaller expanded size because | 751 // It's possible that Vector requests a smaller expanded size because |
| 754 // Vector::shrinkCapacity can set a capacity smaller than the actual payload | 752 // Vector::shrinkCapacity can set a capacity smaller than the actual payload |
| 755 // size. | 753 // size. |
| 756 header->checkHeader(); | |
| 757 if (header->payloadSize() >= newSize) | 754 if (header->payloadSize() >= newSize) |
| 758 return true; | 755 return true; |
| 759 size_t allocationSize = ThreadHeap::allocationSizeFromSize(newSize); | 756 size_t allocationSize = ThreadHeap::allocationSizeFromSize(newSize); |
| 760 ASSERT(allocationSize > header->size()); | 757 ASSERT(allocationSize > header->size()); |
| 761 size_t expandSize = allocationSize - header->size(); | 758 size_t expandSize = allocationSize - header->size(); |
| 762 if (isObjectAllocatedAtAllocationPoint(header) && | 759 if (isObjectAllocatedAtAllocationPoint(header) && |
| 763 expandSize <= m_remainingAllocationSize) { | 760 expandSize <= m_remainingAllocationSize) { |
| 764 m_currentAllocationPoint += expandSize; | 761 m_currentAllocationPoint += expandSize; |
| 765 ASSERT(m_remainingAllocationSize >= expandSize); | 762 ASSERT(m_remainingAllocationSize >= expandSize); |
| 766 setRemainingAllocationSize(m_remainingAllocationSize - expandSize); | 763 setRemainingAllocationSize(m_remainingAllocationSize - expandSize); |
| 767 // Unpoison the memory used for the object (payload). | 764 // Unpoison the memory used for the object (payload). |
| 768 SET_MEMORY_ACCESSIBLE(header->payloadEnd(), expandSize); | 765 SET_MEMORY_ACCESSIBLE(header->payloadEnd(), expandSize); |
| 769 header->setSize(allocationSize); | 766 header->setSize(allocationSize); |
| 770 ASSERT(findPageFromAddress(header->payloadEnd() - 1)); | 767 ASSERT(findPageFromAddress(header->payloadEnd() - 1)); |
| 771 return true; | 768 return true; |
| 772 } | 769 } |
| 773 return false; | 770 return false; |
| 774 } | 771 } |
| 775 | 772 |
| 776 bool NormalPageArena::shrinkObject(HeapObjectHeader* header, size_t newSize) { | 773 bool NormalPageArena::shrinkObject(HeapObjectHeader* header, size_t newSize) { |
| 777 header->checkHeader(); | |
| 778 ASSERT(header->payloadSize() > newSize); | 774 ASSERT(header->payloadSize() > newSize); |
| 779 size_t allocationSize = ThreadHeap::allocationSizeFromSize(newSize); | 775 size_t allocationSize = ThreadHeap::allocationSizeFromSize(newSize); |
| 780 ASSERT(header->size() > allocationSize); | 776 ASSERT(header->size() > allocationSize); |
| 781 size_t shrinkSize = header->size() - allocationSize; | 777 size_t shrinkSize = header->size() - allocationSize; |
| 782 if (isObjectAllocatedAtAllocationPoint(header)) { | 778 if (isObjectAllocatedAtAllocationPoint(header)) { |
| 783 m_currentAllocationPoint -= shrinkSize; | 779 m_currentAllocationPoint -= shrinkSize; |
| 784 setRemainingAllocationSize(m_remainingAllocationSize + shrinkSize); | 780 setRemainingAllocationSize(m_remainingAllocationSize + shrinkSize); |
| 785 SET_MEMORY_INACCESSIBLE(m_currentAllocationPoint, shrinkSize); | 781 SET_MEMORY_INACCESSIBLE(m_currentAllocationPoint, shrinkSize); |
| 786 header->setSize(allocationSize); | 782 header->setSize(allocationSize); |
| 787 return true; | 783 return true; |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 996 for (size_t i = 0; i < largeObjectSize; ++i) | 992 for (size_t i = 0; i < largeObjectSize; ++i) |
| 997 ASSERT(!largeObjectAddress[i]); | 993 ASSERT(!largeObjectAddress[i]); |
| 998 #endif | 994 #endif |
| 999 ASSERT(gcInfoIndex > 0); | 995 ASSERT(gcInfoIndex > 0); |
| 1000 HeapObjectHeader* header = new (NotNull, headerAddress) | 996 HeapObjectHeader* header = new (NotNull, headerAddress) |
| 1001 HeapObjectHeader(largeObjectSizeInHeader, gcInfoIndex); | 997 HeapObjectHeader(largeObjectSizeInHeader, gcInfoIndex); |
| 1002 Address result = headerAddress + sizeof(*header); | 998 Address result = headerAddress + sizeof(*header); |
| 1003 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask)); | 999 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask)); |
| 1004 LargeObjectPage* largeObject = new (largeObjectAddress) | 1000 LargeObjectPage* largeObject = new (largeObjectAddress) |
| 1005 LargeObjectPage(pageMemory, this, allocationSize); | 1001 LargeObjectPage(pageMemory, this, allocationSize); |
| 1006 header->checkHeader(); | |
| 1007 | 1002 |
| 1008 // Poison the object header and allocationGranularity bytes after the object | 1003 // Poison the object header and allocationGranularity bytes after the object |
| 1009 ASAN_POISON_MEMORY_REGION(header, sizeof(*header)); | 1004 ASAN_POISON_MEMORY_REGION(header, sizeof(*header)); |
| 1010 ASAN_POISON_MEMORY_REGION(largeObject->getAddress() + largeObject->size(), | 1005 ASAN_POISON_MEMORY_REGION(largeObject->getAddress() + largeObject->size(), |
| 1011 allocationGranularity); | 1006 allocationGranularity); |
| 1012 | 1007 |
| 1013 largeObject->link(&m_firstPage); | 1008 largeObject->link(&m_firstPage); |
| 1014 | 1009 |
| 1015 getThreadState()->heap().heapStats().increaseAllocatedSpace( | 1010 getThreadState()->heap().heapStats().increaseAllocatedSpace( |
| 1016 largeObject->size()); | 1011 largeObject->size()); |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1254 | 1249 |
| 1255 size_t NormalPage::objectPayloadSizeForTesting() { | 1250 size_t NormalPage::objectPayloadSizeForTesting() { |
| 1256 size_t objectPayloadSize = 0; | 1251 size_t objectPayloadSize = 0; |
| 1257 Address headerAddress = payload(); | 1252 Address headerAddress = payload(); |
| 1258 markAsSwept(); | 1253 markAsSwept(); |
| 1259 ASSERT(headerAddress != payloadEnd()); | 1254 ASSERT(headerAddress != payloadEnd()); |
| 1260 do { | 1255 do { |
| 1261 HeapObjectHeader* header = | 1256 HeapObjectHeader* header = |
| 1262 reinterpret_cast<HeapObjectHeader*>(headerAddress); | 1257 reinterpret_cast<HeapObjectHeader*>(headerAddress); |
| 1263 if (!header->isFree()) { | 1258 if (!header->isFree()) { |
| 1264 header->checkHeader(); | |
| 1265 objectPayloadSize += header->payloadSize(); | 1259 objectPayloadSize += header->payloadSize(); |
| 1266 } | 1260 } |
| 1267 ASSERT(header->size() < blinkPagePayloadSize()); | 1261 ASSERT(header->size() < blinkPagePayloadSize()); |
| 1268 headerAddress += header->size(); | 1262 headerAddress += header->size(); |
| 1269 ASSERT(headerAddress <= payloadEnd()); | 1263 ASSERT(headerAddress <= payloadEnd()); |
| 1270 } while (headerAddress < payloadEnd()); | 1264 } while (headerAddress < payloadEnd()); |
| 1271 return objectPayloadSize; | 1265 return objectPayloadSize; |
| 1272 } | 1266 } |
| 1273 | 1267 |
| 1274 bool NormalPage::isEmpty() { | 1268 bool NormalPage::isEmpty() { |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1570 ASSERT(mapIndex > 0); | 1564 ASSERT(mapIndex > 0); |
| 1571 byte = m_objectStartBitMap[--mapIndex]; | 1565 byte = m_objectStartBitMap[--mapIndex]; |
| 1572 } | 1566 } |
| 1573 int leadingZeroes = numberOfLeadingZeroes(byte); | 1567 int leadingZeroes = numberOfLeadingZeroes(byte); |
| 1574 objectStartNumber = (mapIndex * 8) + 7 - leadingZeroes; | 1568 objectStartNumber = (mapIndex * 8) + 7 - leadingZeroes; |
| 1575 objectOffset = objectStartNumber * allocationGranularity; | 1569 objectOffset = objectStartNumber * allocationGranularity; |
| 1576 Address objectAddress = objectOffset + payload(); | 1570 Address objectAddress = objectOffset + payload(); |
| 1577 HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(objectAddress); | 1571 HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(objectAddress); |
| 1578 if (header->isFree()) | 1572 if (header->isFree()) |
| 1579 return nullptr; | 1573 return nullptr; |
| 1580 header->checkHeader(); | |
| 1581 return header; | 1574 return header; |
| 1582 } | 1575 } |
| 1583 | 1576 |
| 1584 #if DCHECK_IS_ON() | 1577 #if DCHECK_IS_ON() |
| 1585 static bool isUninitializedMemory(void* objectPointer, size_t objectSize) { | 1578 static bool isUninitializedMemory(void* objectPointer, size_t objectSize) { |
| 1586 // Scan through the object's fields and check that they are all zero. | 1579 // Scan through the object's fields and check that they are all zero. |
| 1587 Address* objectFields = reinterpret_cast<Address*>(objectPointer); | 1580 Address* objectFields = reinterpret_cast<Address*>(objectPointer); |
| 1588 for (size_t i = 0; i < objectSize / sizeof(Address); ++i) { | 1581 for (size_t i = 0; i < objectSize / sizeof(Address); ++i) { |
| 1589 if (objectFields[i] != 0) | 1582 if (objectFields[i] != 0) |
| 1590 return false; | 1583 return false; |
| 1591 } | 1584 } |
| 1592 return true; | 1585 return true; |
| 1593 } | 1586 } |
| 1594 #endif | 1587 #endif |
| 1595 | 1588 |
| 1596 static void markPointer(Visitor* visitor, HeapObjectHeader* header) { | 1589 static void markPointer(Visitor* visitor, HeapObjectHeader* header) { |
| 1597 header->checkHeader(); | |
| 1598 const GCInfo* gcInfo = ThreadHeap::gcInfo(header->gcInfoIndex()); | 1590 const GCInfo* gcInfo = ThreadHeap::gcInfo(header->gcInfoIndex()); |
| 1599 if (gcInfo->hasVTable() && !vTableInitialized(header->payload())) { | 1591 if (gcInfo->hasVTable() && !vTableInitialized(header->payload())) { |
| 1600 // We hit this branch when a GC strikes before GarbageCollected<>'s | 1592 // We hit this branch when a GC strikes before GarbageCollected<>'s |
| 1601 // constructor runs. | 1593 // constructor runs. |
| 1602 // | 1594 // |
| 1603 // class A : public GarbageCollected<A> { virtual void f() = 0; }; | 1595 // class A : public GarbageCollected<A> { virtual void f() = 0; }; |
| 1604 // class B : public A { | 1596 // class B : public A { |
| 1605 // B() : A(foo()) { }; | 1597 // B() : A(foo()) { }; |
| 1606 // }; | 1598 // }; |
| 1607 // | 1599 // |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1826 | 1818 |
| 1827 m_hasEntries = true; | 1819 m_hasEntries = true; |
| 1828 size_t index = hash(address); | 1820 size_t index = hash(address); |
| 1829 ASSERT(!(index & 1)); | 1821 ASSERT(!(index & 1)); |
| 1830 Address cachePage = roundToBlinkPageStart(address); | 1822 Address cachePage = roundToBlinkPageStart(address); |
| 1831 m_entries[index + 1] = m_entries[index]; | 1823 m_entries[index + 1] = m_entries[index]; |
| 1832 m_entries[index] = cachePage; | 1824 m_entries[index] = cachePage; |
| 1833 } | 1825 } |
| 1834 | 1826 |
| 1835 } // namespace blink | 1827 } // namespace blink |
| OLD | NEW |