diff options
author | Johanna Aijala <johanna.aijala@digia.com> | 2013-02-21 09:34:08 +0200 |
---|---|---|
committer | Johanna Aijala <johanna.aijala@digia.com> | 2013-02-21 09:34:53 +0200 |
commit | e6c484102e2e447f9171d9eb6799a0470910fd99 (patch) | |
tree | 7fbeb840709b78863b4ed3b4f0a66f479984caa0 /Source/JavaScriptCore | |
parent | 30400131a4c18e9a0e0895d517c620b599aaddee (diff) | |
parent | 08322b49d440e36a8c1a8b2f250a641ea1886ae3 (diff) | |
download | qtwebkit-e6c484102e2e447f9171d9eb6799a0470910fd99.tar.gz |
Merge branch 'stable' into release
Change-Id: I5f9488665e344d270d876075e4a78d472e12a66f
Diffstat (limited to 'Source/JavaScriptCore')
-rw-r--r-- | Source/JavaScriptCore/ChangeLog | 85 | ||||
-rw-r--r-- | Source/JavaScriptCore/heap/BlockAllocator.h | 8 | ||||
-rw-r--r-- | Source/JavaScriptCore/heap/CopiedBlock.h | 7 | ||||
-rw-r--r-- | Source/JavaScriptCore/heap/CopiedSpace.cpp | 8 | ||||
-rw-r--r-- | Source/JavaScriptCore/heap/CopiedSpace.h | 1 | ||||
-rw-r--r-- | Source/JavaScriptCore/heap/CopiedSpaceInlines.h | 12 | ||||
-rw-r--r-- | Source/JavaScriptCore/heap/CopyVisitor.h | 2 | ||||
-rw-r--r-- | Source/JavaScriptCore/heap/CopyVisitorInlines.h | 11 | ||||
-rw-r--r-- | Source/JavaScriptCore/heap/SlotVisitorInlines.h | 6 | ||||
-rw-r--r-- | Source/JavaScriptCore/runtime/Butterfly.h | 4 | ||||
-rw-r--r-- | Source/JavaScriptCore/runtime/ButterflyInlines.h | 7 | ||||
-rw-r--r-- | Source/JavaScriptCore/runtime/JSObject.cpp | 6 | ||||
-rw-r--r-- | Source/JavaScriptCore/runtime/MathObject.cpp | 16 |
13 files changed, 127 insertions, 46 deletions
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index 4e661d971..18927d19e 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,3 +1,88 @@ +2012-12-18 Mark Hahnenberg <mhahnenberg@apple.com> + + Restrictions on oversize CopiedBlock allocations should be relaxed + https://bugs.webkit.org/show_bug.cgi?id=105339 + + Reviewed by Filip Pizlo. + + Currently the DFG has a single branch in the inline allocation path for property/array storage where + it checks to see if the number of bytes requested will fit in the current block. This does not match + what the C++ allocation path does; it checks if the requested number of bytes is oversize, and then + if it's not, it tries to fit it in the current block. The garbage collector assumes that ALL allocations + that are greater than 16KB are in oversize blocks. Therefore, this mismatch can lead to crashes when + the collector tries to perform some operation on a CopiedBlock. + + To avoid adding an extra branch to the inline allocation path in the JIT, we should make it so that + oversize blocks are allocated on the same alignment boundaries so that there is a single mask to find + the block header of any CopiedBlock (rather than two, one for normal and one for oversize blocks), and + we should figure out if a block is oversize by some other method than just whatever the JSObject says + it is. One way we could record this info Region of the block, since we allocate a one-off Region for + oversize blocks. + + * heap/BlockAllocator.h: + (JSC::Region::isCustomSize): + (Region): + (JSC::Region::createCustomSize): + (JSC::Region::Region): + (JSC::BlockAllocator::deallocateCustomSize): + * heap/CopiedBlock.h: + (CopiedBlock): + (JSC::CopiedBlock::isOversize): + (JSC): + * heap/CopiedSpace.cpp: + (JSC::CopiedSpace::tryAllocateOversize): + (JSC::CopiedSpace::tryReallocate): + (JSC::CopiedSpace::tryReallocateOversize): + * heap/CopiedSpace.h: + (CopiedSpace): + * heap/CopiedSpaceInlines.h: + (JSC::CopiedSpace::contains): + (JSC::CopiedSpace::tryAllocate): + (JSC): + * heap/CopyVisitor.h: + (CopyVisitor): + * heap/CopyVisitorInlines.h: + (JSC::CopyVisitor::checkIfShouldCopy): + (JSC::CopyVisitor::didCopy): + * heap/SlotVisitorInlines.h: + (JSC::SlotVisitor::copyLater): + * runtime/JSObject.cpp: + (JSC::JSObject::copyButterfly): + +2012-12-17 Mark Hahnenberg <mhahnenberg@apple.com> + + Butterfly::growArrayRight shouldn't be called on null Butterfly objects + https://bugs.webkit.org/show_bug.cgi?id=105221 + + Reviewed by Filip Pizlo. + + Currently we depend upon the fact that Butterfly::growArrayRight works with null Butterfly + objects purely by coincidence. We should add a new static function that null checks the old + Butterfly object and creates a new one if it's null, or calls growArrayRight if it isn't for + use in the couple of places in JSObject that expect such behavior to work. + + * runtime/Butterfly.h: + (Butterfly): + * runtime/ButterflyInlines.h: + (JSC::Butterfly::createOrGrowArrayRight): + (JSC): + * runtime/JSObject.cpp: + (JSC::JSObject::createInitialIndexedStorage): + (JSC::JSObject::createArrayStorage): + +2013-01-02 Simon Hausmann <simon.hausmann@digia.com> + + [MinGW-w64] Centralize workaround for pow() implementation + https://bugs.webkit.org/show_bug.cgi?id=105925 + + Reviewed by Sam Weinig. + + As suggested by Sam, move the MinGW-w64 workaround into MathExtras.h + away from the JSC usage. + + * runtime/MathObject.cpp: + (JSC::mathPow): + 2012-12-17 Jonathan Liu <net147@gmail.com> Fix Math.pow implementation with MinGW-w64 diff --git a/Source/JavaScriptCore/heap/BlockAllocator.h b/Source/JavaScriptCore/heap/BlockAllocator.h index 417f81da0..90210c1fa 100644 --- a/Source/JavaScriptCore/heap/BlockAllocator.h +++ b/Source/JavaScriptCore/heap/BlockAllocator.h @@ -68,6 +68,7 @@ public: size_t blockSize() const { return m_blockSize; } bool isFull() const { return m_blocksInUse == m_totalBlocks; } bool isEmpty() const { return !m_blocksInUse; } + bool isCustomSize() const { return m_isCustomSize; } DeadBlock* allocate(); void deallocate(void*); @@ -81,6 +82,7 @@ private: size_t m_totalBlocks; size_t m_blocksInUse; size_t m_blockSize; + bool m_isCustomSize; Region* m_prev; Region* m_next; DoublyLinkedList<DeadBlock> m_deadBlocks; @@ -101,7 +103,9 @@ inline Region* Region::createCustomSize(size_t blockSize, size_t blockAlignment) PageAllocationAligned allocation = PageAllocationAligned::allocate(blockSize, blockAlignment, OSAllocator::JSGCHeapPages); if (!static_cast<bool>(allocation)) CRASH(); - return new Region(allocation, blockSize, 1); + Region* region = new Region(allocation, blockSize, 1); + region->m_isCustomSize = true; + return region; } inline Region::Region(PageAllocationAligned& allocation, size_t blockSize, size_t totalBlocks) @@ -110,6 +114,7 @@ inline Region::Region(PageAllocationAligned& allocation, size_t blockSize, size_ , m_totalBlocks(totalBlocks) , m_blocksInUse(0) , m_blockSize(blockSize) + , m_isCustomSize(false) , m_prev(0) , m_next(0) { @@ -300,6 +305,7 @@ template<typename T> inline void BlockAllocator::deallocateCustomSize(T* block) { Region* region = block->region(); + ASSERT(region->isCustomSize()); region->deallocate(block); delete region; } diff --git a/Source/JavaScriptCore/heap/CopiedBlock.h b/Source/JavaScriptCore/heap/CopiedBlock.h index 7f585585c..cc60a0103 100644 --- a/Source/JavaScriptCore/heap/CopiedBlock.h +++ b/Source/JavaScriptCore/heap/CopiedBlock.h @@ -50,6 +50,8 @@ public: void pin(); bool isPinned(); + bool isOversize(); + unsigned liveBytes(); void reportLiveBytes(JSCell*, unsigned); void didSurviveGC(); @@ -168,6 +170,11 @@ inline bool CopiedBlock::isPinned() return m_isPinned; } +inline bool CopiedBlock::isOversize() +{ + return region()->isCustomSize(); +} + inline unsigned CopiedBlock::liveBytes() { return m_liveBytes; diff --git a/Source/JavaScriptCore/heap/CopiedSpace.cpp b/Source/JavaScriptCore/heap/CopiedSpace.cpp index e4141c1d7..b235de1dd 100644 --- a/Source/JavaScriptCore/heap/CopiedSpace.cpp +++ b/Source/JavaScriptCore/heap/CopiedSpace.cpp @@ -81,7 +81,7 @@ CheckedBoolean CopiedSpace::tryAllocateOversize(size_t bytes, void** outPtr) { ASSERT(isOversize(bytes)); - CopiedBlock* block = CopiedBlock::create(m_heap->blockAllocator().allocateCustomSize(sizeof(CopiedBlock) + bytes, WTF::pageSize())); + CopiedBlock* block = CopiedBlock::create(m_heap->blockAllocator().allocateCustomSize(sizeof(CopiedBlock) + bytes, CopiedBlock::blockSize)); m_oversizeBlocks.push(block); m_blockFilter.add(reinterpret_cast<Bits>(block)); m_blockSet.add(block); @@ -104,7 +104,7 @@ CheckedBoolean CopiedSpace::tryReallocate(void** ptr, size_t oldSize, size_t new void* oldPtr = *ptr; ASSERT(!m_heap->globalData()->isInitializingObject()); - if (isOversize(oldSize) || isOversize(newSize)) + if (CopiedSpace::blockFor(oldPtr)->isOversize() || isOversize(newSize)) return tryReallocateOversize(ptr, oldSize, newSize); if (m_allocator.tryReallocate(oldPtr, oldSize, newSize)) @@ -135,8 +135,8 @@ CheckedBoolean CopiedSpace::tryReallocateOversize(void** ptr, size_t oldSize, si memcpy(newPtr, oldPtr, oldSize); - if (isOversize(oldSize)) { - CopiedBlock* oldBlock = oversizeBlockFor(oldPtr); + CopiedBlock* oldBlock = CopiedSpace::blockFor(oldPtr); + if (oldBlock->isOversize()) { m_oversizeBlocks.remove(oldBlock); m_blockSet.remove(oldBlock); m_heap->blockAllocator().deallocateCustomSize(CopiedBlock::destroy(oldBlock)); diff --git a/Source/JavaScriptCore/heap/CopiedSpace.h b/Source/JavaScriptCore/heap/CopiedSpace.h index e3727100e..65ca04ef6 100644 --- a/Source/JavaScriptCore/heap/CopiedSpace.h +++ b/Source/JavaScriptCore/heap/CopiedSpace.h @@ -82,7 +82,6 @@ public: private: static bool isOversize(size_t); - static CopiedBlock* oversizeBlockFor(void* ptr); JS_EXPORT_PRIVATE CheckedBoolean tryAllocateSlowCase(size_t, void**); CheckedBoolean tryAllocateOversize(size_t, void**); diff --git a/Source/JavaScriptCore/heap/CopiedSpaceInlines.h b/Source/JavaScriptCore/heap/CopiedSpaceInlines.h index 41f94dd74..6087cf4c2 100644 --- a/Source/JavaScriptCore/heap/CopiedSpaceInlines.h +++ b/Source/JavaScriptCore/heap/CopiedSpaceInlines.h @@ -47,9 +47,8 @@ inline bool CopiedSpace::contains(void* ptr, CopiedBlock*& result) result = block; return true; } - block = oversizeBlockFor(ptr); - result = block; - return contains(block); + result = 0; + return false; } inline void CopiedSpace::pin(CopiedBlock* block) @@ -153,7 +152,7 @@ inline CheckedBoolean CopiedSpace::tryAllocate(size_t bytes, void** outPtr) { ASSERT(!m_heap->globalData()->isInitializingObject()); - if (isOversize(bytes) || !m_allocator.tryAllocate(bytes, outPtr)) + if (!m_allocator.tryAllocate(bytes, outPtr)) return tryAllocateSlowCase(bytes, outPtr); ASSERT(*outPtr); @@ -170,11 +169,6 @@ inline bool CopiedSpace::isPinned(void* ptr) return blockFor(ptr)->m_isPinned; } -inline CopiedBlock* CopiedSpace::oversizeBlockFor(void* ptr) -{ - return reinterpret_cast<CopiedBlock*>(reinterpret_cast<size_t>(ptr) & WTF::pageMask()); -} - inline CopiedBlock* CopiedSpace::blockFor(void* ptr) { return reinterpret_cast<CopiedBlock*>(reinterpret_cast<size_t>(ptr) & s_blockMask); diff --git a/Source/JavaScriptCore/heap/CopyVisitor.h b/Source/JavaScriptCore/heap/CopyVisitor.h index c5f7272a9..da92ba5b5 100644 --- a/Source/JavaScriptCore/heap/CopyVisitor.h +++ b/Source/JavaScriptCore/heap/CopyVisitor.h @@ -45,7 +45,7 @@ public: // Low-level API for copying, appropriate for cases where the object's heap references // are discontiguous or if the object occurs frequently enough that you need to focus on // performance. Use this with care as it is easy to shoot yourself in the foot. - bool checkIfShouldCopy(void*, size_t); + bool checkIfShouldCopy(void*); void* allocateNewSpace(size_t); void didCopy(void*, size_t); diff --git a/Source/JavaScriptCore/heap/CopyVisitorInlines.h b/Source/JavaScriptCore/heap/CopyVisitorInlines.h index 1557af93d..4e087b8db 100644 --- a/Source/JavaScriptCore/heap/CopyVisitorInlines.h +++ b/Source/JavaScriptCore/heap/CopyVisitorInlines.h @@ -40,14 +40,11 @@ inline void CopyVisitor::visitCell(JSCell* cell) JSObject::copyBackingStore(cell, *this); } -inline bool CopyVisitor::checkIfShouldCopy(void* oldPtr, size_t bytes) +inline bool CopyVisitor::checkIfShouldCopy(void* oldPtr) { - if (CopiedSpace::isOversize(bytes)) + CopiedBlock* block = CopiedSpace::blockFor(oldPtr); + if (block->isOversize() || block->isPinned()) return false; - - if (CopiedSpace::blockFor(oldPtr)->isPinned()) - return false; - return true; } @@ -92,8 +89,8 @@ inline void CopyVisitor::doneCopying() inline void CopyVisitor::didCopy(void* ptr, size_t bytes) { - ASSERT(!CopiedSpace::isOversize(bytes)); CopiedBlock* block = CopiedSpace::blockFor(ptr); + ASSERT(!block->isOversize()); ASSERT(!block->isPinned()); block->didEvacuateBytes(bytes); diff --git a/Source/JavaScriptCore/heap/SlotVisitorInlines.h b/Source/JavaScriptCore/heap/SlotVisitorInlines.h index d76ac552a..3a7f2290c 100644 --- a/Source/JavaScriptCore/heap/SlotVisitorInlines.h +++ b/Source/JavaScriptCore/heap/SlotVisitorInlines.h @@ -163,12 +163,12 @@ inline void SlotVisitor::donateAndDrain() inline void SlotVisitor::copyLater(JSCell* owner, void* ptr, size_t bytes) { - if (CopiedSpace::isOversize(bytes)) { - m_shared.m_copiedSpace->pin(CopiedSpace::oversizeBlockFor(ptr)); + CopiedBlock* block = CopiedSpace::blockFor(ptr); + if (block->isOversize()) { + m_shared.m_copiedSpace->pin(block); return; } - CopiedBlock* block = CopiedSpace::blockFor(ptr); if (block->isPinned()) return; diff --git a/Source/JavaScriptCore/runtime/Butterfly.h b/Source/JavaScriptCore/runtime/Butterfly.h index 4b8d53f7e..bbbda9461 100644 --- a/Source/JavaScriptCore/runtime/Butterfly.h +++ b/Source/JavaScriptCore/runtime/Butterfly.h @@ -110,7 +110,9 @@ public: void* base(size_t preCapacity, size_t propertyCapacity) { return propertyStorage() - propertyCapacity - preCapacity; } void* base(Structure*); - + + static Butterfly* createOrGrowArrayRight(Butterfly*, JSGlobalData&, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes); + // The butterfly reallocation methods perform the reallocation itself but do not change any // of the meta-data to reflect that the reallocation occurred. Note that this set of // methods is not exhaustive and is not intended to encapsulate all possible allocation diff --git a/Source/JavaScriptCore/runtime/ButterflyInlines.h b/Source/JavaScriptCore/runtime/ButterflyInlines.h index 9167497a4..f01458950 100644 --- a/Source/JavaScriptCore/runtime/ButterflyInlines.h +++ b/Source/JavaScriptCore/runtime/ButterflyInlines.h @@ -99,6 +99,13 @@ inline Butterfly* Butterfly::growPropertyStorage(JSGlobalData& globalData, Struc globalData, oldStructure, oldStructure->outOfLineCapacity(), newPropertyCapacity); } +inline Butterfly* Butterfly::createOrGrowArrayRight(Butterfly* oldButterfly, JSGlobalData& globalData, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes) +{ + if (!oldButterfly) + return create(globalData, 0, propertyCapacity, true, IndexingHeader(), newIndexingPayloadSizeInBytes); + return oldButterfly->growArrayRight(globalData, oldStructure, propertyCapacity, hadIndexingHeader, oldIndexingPayloadSizeInBytes, newIndexingPayloadSizeInBytes); +} + inline Butterfly* Butterfly::growArrayRight(JSGlobalData& globalData, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes) { ASSERT_UNUSED(oldStructure, !indexingHeader()->preCapacity(oldStructure)); diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index dc73e04b0..32adefd2f 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -110,7 +110,7 @@ ALWAYS_INLINE void JSObject::copyButterfly(CopyVisitor& visitor, Butterfly* butt indexingPayloadSizeInBytes = 0; } size_t capacityInBytes = Butterfly::totalSize(preCapacity, propertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes); - if (visitor.checkIfShouldCopy(butterfly->base(preCapacity, propertyCapacity), capacityInBytes)) { + if (visitor.checkIfShouldCopy(butterfly->base(preCapacity, propertyCapacity))) { Butterfly* newButterfly = Butterfly::createUninitializedDuringCollection(visitor, preCapacity, propertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes); // Copy the properties. @@ -610,7 +610,7 @@ Butterfly* JSObject::createInitialIndexedStorage(JSGlobalData& globalData, unsig ASSERT(!structure()->needsSlowPutIndexing()); ASSERT(!indexingShouldBeSparse()); unsigned vectorLength = std::max(length, BASE_VECTOR_LEN); - Butterfly* newButterfly = m_butterfly->growArrayRight( + Butterfly* newButterfly = Butterfly::createOrGrowArrayRight(m_butterfly, globalData, structure(), structure()->outOfLineCapacity(), false, 0, elementSize * vectorLength); newButterfly->setPublicLength(length); @@ -656,7 +656,7 @@ ArrayStorage* JSObject::createArrayStorage(JSGlobalData& globalData, unsigned le { IndexingType oldType = structure()->indexingType(); ASSERT_UNUSED(oldType, !hasIndexedProperties(oldType)); - Butterfly* newButterfly = m_butterfly->growArrayRight( + Butterfly* newButterfly = Butterfly::createOrGrowArrayRight(m_butterfly, globalData, structure(), structure()->outOfLineCapacity(), false, 0, ArrayStorage::sizeFor(vectorLength)); if (!newButterfly) diff --git a/Source/JavaScriptCore/runtime/MathObject.cpp b/Source/JavaScriptCore/runtime/MathObject.cpp index f939b8dd4..7634487ad 100644 --- a/Source/JavaScriptCore/runtime/MathObject.cpp +++ b/Source/JavaScriptCore/runtime/MathObject.cpp @@ -232,22 +232,6 @@ static ALWAYS_INLINE double mathPow(double x, double y) ALWAYS_INLINE double mathPow(double x, double y) { -#if COMPILER(MINGW64) - // MinGW-w64 has a custom implementation for pow. - // This handles certain special cases that are different. - if ((x == 0.0 || isinf(x)) && isfinite(y)) { - double f; - if (modf(y, &f) != 0.0) - return ((x == 0.0) ^ (y > 0.0)) ? std::numeric_limits<double>::infinity() : 0.0; - } - - if (x == 2.0) { - int yInt = static_cast<int>(y); - if (y == yInt) - return ldexp(1.0, yInt); - } -#endif - return pow(x, y); } |