Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (163413 => 163414)
--- trunk/Source/_javascript_Core/ChangeLog 2014-02-04 23:57:22 UTC (rev 163413)
+++ trunk/Source/_javascript_Core/ChangeLog 2014-02-05 00:08:40 UTC (rev 163414)
@@ -1,3 +1,50 @@
+2014-02-04 Mark Hahnenberg <[email protected]>
+
+ Refactor MarkStackArray to allow more than JSCells to be stored
+ https://bugs.webkit.org/show_bug.cgi?id=128203
+
+ Reviewed by Geoffrey Garen.
+
+ This patch refactors MarkStackArray into a separate template class named GCSegmentedArray.
+ This class allows subclassing to add functionality that only MarkStackArray wants.
+ Since it uses the JSC BlockAllocator instead of FastMalloc, this class can be used during
+ conservative stack scanning, which disallows using FastMalloc.
+
+ * GNUmakefile.list.am:
+ * _javascript_Core.vcxproj/_javascript_Core.vcxproj:
+ * _javascript_Core.vcxproj/_javascript_Core.vcxproj.filters:
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * heap/BlockAllocator.h:
+ * heap/GCSegmentedArray.h: Added.
+ (JSC::GCArraySegment::GCArraySegment):
+ (JSC::GCArraySegment::data):
+ * heap/GCSegmentedArrayInlines.h: Added.
+ (JSC::GCSegmentedArray<T>::GCSegmentedArray):
+ (JSC::GCSegmentedArray<T>::~GCSegmentedArray):
+ (JSC::GCSegmentedArray<T>::clear):
+ (JSC::GCSegmentedArray<T>::expand):
+ (JSC::GCSegmentedArray<T>::refill):
+ (JSC::GCSegmentedArray<T>::fillVector):
+ (JSC::GCArraySegment<T>::create):
+ (JSC::GCSegmentedArray<T>::postIncTop):
+ (JSC::GCSegmentedArray<T>::preDecTop):
+ (JSC::GCSegmentedArray<T>::setTopForFullSegment):
+ (JSC::GCSegmentedArray<T>::setTopForEmptySegment):
+ (JSC::GCSegmentedArray<T>::top):
+ (JSC::GCSegmentedArray<T>::validatePrevious):
+ (JSC::GCSegmentedArray<T>::append):
+ (JSC::GCSegmentedArray<T>::canRemoveLast):
+ (JSC::GCSegmentedArray<T>::removeLast):
+ (JSC::GCSegmentedArray<T>::isEmpty):
+ (JSC::GCSegmentedArray<T>::size):
+ * heap/MarkStack.cpp:
+ (JSC::MarkStackArray::MarkStackArray):
+ (JSC::MarkStackArray::~MarkStackArray):
+ (JSC::MarkStackArray::donateSomeCellsTo):
+ (JSC::MarkStackArray::stealSomeCellsFrom):
+ * heap/MarkStack.h:
+ * heap/MarkStackInlines.h:
+
2014-02-04 Anders Carlsson <[email protected]>
Rename the substring sharing StringImpl::create variants to better indicate what they do
Modified: trunk/Source/_javascript_Core/GNUmakefile.list.am (163413 => 163414)
--- trunk/Source/_javascript_Core/GNUmakefile.list.am 2014-02-04 23:57:22 UTC (rev 163413)
+++ trunk/Source/_javascript_Core/GNUmakefile.list.am 2014-02-05 00:08:40 UTC (rev 163414)
@@ -514,6 +514,8 @@
Source/_javascript_Core/heap/DeferGC.cpp \
Source/_javascript_Core/heap/DeferGC.h \
Source/_javascript_Core/heap/DelayedReleaseScope.h \
+ Source/_javascript_Core/heap/GCSegmentedArray.h \
+ Source/_javascript_Core/heap/GCSegmentedArrayInlines.h \
Source/_javascript_Core/heap/GCAssertions.h \
Source/_javascript_Core/heap/GCIncomingRefCounted.h \
Source/_javascript_Core/heap/GCIncomingRefCountedInlines.h \
@@ -556,7 +558,6 @@
Source/_javascript_Core/heap/MachineStackMarker.h \
Source/_javascript_Core/heap/MarkStack.cpp \
Source/_javascript_Core/heap/MarkStack.h \
- Source/_javascript_Core/heap/MarkStackInlines.h \
Source/_javascript_Core/heap/HeapRootVisitor.h \
Source/_javascript_Core/heap/MarkedAllocator.cpp \
Source/_javascript_Core/heap/MarkedAllocator.h \
Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj (163413 => 163414)
--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj 2014-02-04 23:57:22 UTC (rev 163413)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj 2014-02-05 00:08:40 UTC (rev 163414)
@@ -1008,6 +1008,8 @@
<ClInclude Include="..\heap\CopyWriteBarrier.h" />
<ClInclude Include="..\heap\DeferGC.h" />
<ClInclude Include="..\heap\DelayedReleaseScope.h" />
+ <ClInclude Include="..\heap\GCSegmentedArray.h" />
+ <ClInclude Include="..\heap\GCSegmentedArrayInlines.h" />
<ClInclude Include="..\heap\GCAssertions.h" />
<ClInclude Include="..\heap\GCThread.h" />
<ClInclude Include="..\heap\GCThreadSharedData.h" />
@@ -1034,7 +1036,6 @@
<ClInclude Include="..\heap\MarkedBlockSet.h" />
<ClInclude Include="..\heap\MarkedSpace.h" />
<ClInclude Include="..\heap\MarkStack.h" />
- <ClInclude Include="..\heap\MarkStackInlines.h" />
<ClInclude Include="..\heap\RecursiveAllocationScope.h" />
<ClInclude Include="..\heap\Region.h" />
<ClInclude Include="..\heap\SlotVisitor.h" />
Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters (163413 => 163414)
--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters 2014-02-04 23:57:22 UTC (rev 163413)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters 2014-02-05 00:08:40 UTC (rev 163414)
@@ -1655,6 +1655,12 @@
<ClInclude Include="..\heap\DeferGC.h">
<Filter>heap</Filter>
</ClInclude>
+ <ClInclude Include="..\heap\GCSegmentedArray.h">
+ <Filter>heap</Filter>
+ </ClInclude>
+ <ClInclude Include="..\heap\GCSegmentedArrayInlines.h">
+ <Filter>heap</Filter>
+ </ClInclude>
<ClInclude Include="..\heap\GCAssertions.h">
<Filter>heap</Filter>
</ClInclude>
@@ -1733,9 +1739,6 @@
<ClInclude Include="..\heap\MarkStack.h">
<Filter>heap</Filter>
</ClInclude>
- <ClInclude Include="..\heap\MarkStackInlines.h">
- <Filter>heap</Filter>
- </ClInclude>
<ClInclude Include="..\heap\RecursiveAllocationScope.h">
<Filter>heap</Filter>
</ClInclude>
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (163413 => 163414)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2014-02-04 23:57:22 UTC (rev 163413)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2014-02-05 00:08:40 UTC (rev 163414)
@@ -740,6 +740,8 @@
2600B5A6152BAAA70091EE5F /* JSStringJoiner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */; };
2600B5A7152BAAA70091EE5F /* JSStringJoiner.h in Headers */ = {isa = PBXBuildFile; fileRef = 2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */; };
2A2825D018341F2D0087FBA9 /* DelayedReleaseScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */; };
+ 2A343F7618A1748B0039B085 /* GCSegmentedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A343F7418A1748B0039B085 /* GCSegmentedArray.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 2A343F7818A1749D0039B085 /* GCSegmentedArrayInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A343F7718A1749D0039B085 /* GCSegmentedArrayInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
2A48D1911772365B00C65A5F /* APICallbackFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = C211B574176A224D000E2A23 /* APICallbackFunction.h */; };
2A4EC90B1860D6C20094F782 /* WriteBarrierBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A4EC9091860D6C20094F782 /* WriteBarrierBuffer.cpp */; };
2A4EC90C1860D6C20094F782 /* WriteBarrierBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A4EC90A1860D6C20094F782 /* WriteBarrierBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -1307,7 +1309,6 @@
C20BA92D16BB1C1500B3AEA2 /* StructureRareDataInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = C20BA92C16BB1C1500B3AEA2 /* StructureRareDataInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
C21122E115DD9AB300790E3A /* GCThreadSharedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C21122DE15DD9AB300790E3A /* GCThreadSharedData.cpp */; };
C21122E215DD9AB300790E3A /* GCThreadSharedData.h in Headers */ = {isa = PBXBuildFile; fileRef = C21122DF15DD9AB300790E3A /* GCThreadSharedData.h */; settings = {ATTRIBUTES = (Private, ); }; };
- C21122E315DD9AB300790E3A /* MarkStackInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = C21122E015DD9AB300790E3A /* MarkStackInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
C2160FE715F7E95E00942DFC /* SlotVisitorInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCB408515C0A3C30048932B /* SlotVisitorInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
C218D1401655CFD50062BB81 /* CopyWorkList.h in Headers */ = {isa = PBXBuildFile; fileRef = C218D13F1655CFD50062BB81 /* CopyWorkList.h */; settings = {ATTRIBUTES = (Private, ); }; };
C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2239D1216262BDD005AC5FD /* CopyVisitor.cpp */; };
@@ -2127,6 +2128,8 @@
2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStringJoiner.cpp; sourceTree = "<group>"; };
2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringJoiner.h; sourceTree = "<group>"; };
2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DelayedReleaseScope.h; sourceTree = "<group>"; };
+ 2A343F7418A1748B0039B085 /* GCSegmentedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCSegmentedArray.h; sourceTree = "<group>"; };
+ 2A343F7718A1749D0039B085 /* GCSegmentedArrayInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCSegmentedArrayInlines.h; sourceTree = "<group>"; };
2A4EC9091860D6C20094F782 /* WriteBarrierBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WriteBarrierBuffer.cpp; sourceTree = "<group>"; };
2A4EC90A1860D6C20094F782 /* WriteBarrierBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WriteBarrierBuffer.h; sourceTree = "<group>"; };
2A68295A1875F80500B6C3E2 /* CopyWriteBarrier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopyWriteBarrier.h; sourceTree = "<group>"; };
@@ -2738,7 +2741,6 @@
C20BA92C16BB1C1500B3AEA2 /* StructureRareDataInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureRareDataInlines.h; sourceTree = "<group>"; };
C21122DE15DD9AB300790E3A /* GCThreadSharedData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCThreadSharedData.cpp; sourceTree = "<group>"; };
C21122DF15DD9AB300790E3A /* GCThreadSharedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCThreadSharedData.h; sourceTree = "<group>"; };
- C21122E015DD9AB300790E3A /* MarkStackInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkStackInlines.h; sourceTree = "<group>"; };
C211B574176A224D000E2A23 /* APICallbackFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APICallbackFunction.h; sourceTree = "<group>"; };
C218D13F1655CFD50062BB81 /* CopyWorkList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopyWorkList.h; sourceTree = "<group>"; };
C2239D1216262BDD005AC5FD /* CopyVisitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CopyVisitor.cpp; sourceTree = "<group>"; };
@@ -3366,7 +3368,6 @@
14D2F3D9139F4BE200491031 /* MarkedSpace.h */,
142D6F0E13539A4100B02E86 /* MarkStack.cpp */,
142D6F0F13539A4100B02E86 /* MarkStack.h */,
- C21122E015DD9AB300790E3A /* MarkStackInlines.h */,
C20B25981706536200C21F4E /* Region.h */,
C225494215F7DBAA0065E898 /* SlotVisitor.cpp */,
14BA78F013AAB88F005B7C2C /* SlotVisitor.h */,
@@ -3394,6 +3395,8 @@
2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */,
2AAD964918569417001F93BE /* RecursiveAllocationScope.h */,
2A68295A1875F80500B6C3E2 /* CopyWriteBarrier.h */,
+ 2A343F7418A1748B0039B085 /* GCSegmentedArray.h */,
+ 2A343F7718A1749D0039B085 /* GCSegmentedArrayInlines.h */,
);
path = heap;
sourceTree = "<group>";
@@ -4633,6 +4636,8 @@
86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */,
86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */,
A5CEEE15187F3BAD00E55C99 /* InspectorAgent.h in Headers */,
+ 2A343F7618A1748B0039B085 /* GCSegmentedArray.h in Headers */,
+ 2A343F7818A1749D0039B085 /* GCSegmentedArrayInlines.h in Headers */,
65C0285D1717966800351E35 /* ARMv7DOpcode.h in Headers */,
2A68295B1875F80500B6C3E2 /* CopyWriteBarrier.h in Headers */,
2A4EC90C1860D6C20094F782 /* WriteBarrierBuffer.h in Headers */,
@@ -5177,7 +5182,6 @@
141448CB13A176EC00F5BA1A /* MarkedBlockSet.h in Headers */,
14D2F3DB139F4BE200491031 /* MarkedSpace.h in Headers */,
142D6F1213539A4100B02E86 /* MarkStack.h in Headers */,
- C21122E315DD9AB300790E3A /* MarkStackInlines.h in Headers */,
A5945595182479EB00CC3843 /* InspectorFrontendChannel.h in Headers */,
8612E4CD152389EC00C836BE /* MatchResult.h in Headers */,
A5840E21187B7B8600843B10 /* InjectedScriptModule.h in Headers */,
Modified: trunk/Source/_javascript_Core/heap/BlockAllocator.h (163413 => 163414)
--- trunk/Source/_javascript_Core/heap/BlockAllocator.h 2014-02-04 23:57:22 UTC (rev 163413)
+++ trunk/Source/_javascript_Core/heap/BlockAllocator.h 2014-02-05 00:08:40 UTC (rev 163414)
@@ -41,9 +41,10 @@
class BlockAllocator;
class CopiedBlock;
class CopyWorkListSegment;
+template <typename T> class GCArraySegment;
class HandleBlock;
+class JSCell;
class VM;
-class MarkStackSegment;
class MarkedBlock;
class WeakBlock;
@@ -95,7 +96,7 @@
SuperRegion m_superRegion;
RegionSet m_copiedRegionSet;
RegionSet m_markedRegionSet;
- // WeakBlocks and MarkStackSegments use the same RegionSet since they're the same size.
+ // WeakBlocks and GCArraySegments use the same RegionSet since they're the same size.
RegionSet m_fourKBBlockRegionSet;
RegionSet m_workListRegionSet;
@@ -235,7 +236,7 @@
}
template <>
-inline BlockAllocator::RegionSet& BlockAllocator::regionSetFor<MarkStackSegment>()
+inline BlockAllocator::RegionSet& BlockAllocator::regionSetFor<GCArraySegment<const JSCell*>>()
{
return m_fourKBBlockRegionSet;
}
@@ -271,7 +272,7 @@
}
template <>
-inline BlockAllocator::RegionSet& BlockAllocator::regionSetFor<HeapBlock<MarkStackSegment>>()
+inline BlockAllocator::RegionSet& BlockAllocator::regionSetFor<HeapBlock<GCArraySegment<const JSCell*>>>()
{
return m_fourKBBlockRegionSet;
}
Added: trunk/Source/_javascript_Core/heap/GCSegmentedArray.h (0 => 163414)
--- trunk/Source/_javascript_Core/heap/GCSegmentedArray.h (rev 0)
+++ trunk/Source/_javascript_Core/heap/GCSegmentedArray.h 2014-02-05 00:08:40 UTC (rev 163414)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GCSegmentedArray_h
+#define GCSegmentedArray_h
+
+#include "HeapBlock.h"
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class BlockAllocator;
+class DeadBlock;
+
+template <typename T>
+class GCArraySegment : public HeapBlock<GCArraySegment<T>> {
+public:
+ GCArraySegment(Region* region)
+ : HeapBlock<GCArraySegment>(region)
+#if !ASSERT_DISABLED
+ , m_top(0)
+#endif
+ {
+ }
+
+ static GCArraySegment* create(DeadBlock*);
+
+ T* data()
+ {
+ return bitwise_cast<T*>(this + 1);
+ }
+
+ static const size_t blockSize = 4 * KB;
+
+#if !ASSERT_DISABLED
+ size_t m_top;
+#endif
+};
+
+template <typename T>
+class GCSegmentedArray {
+public:
+ GCSegmentedArray(BlockAllocator&);
+ ~GCSegmentedArray();
+
+ void append(T);
+
+ bool canRemoveLast();
+ const T removeLast();
+ bool refill();
+
+ size_t size();
+ bool isEmpty();
+
+ void fillVector(Vector<T>&);
+ void clear();
+
+protected:
+ template <size_t size> struct CapacityFromSize {
+ static const size_t value = (size - sizeof(GCArraySegment<T>)) / sizeof(T);
+ };
+
+ void expand();
+
+ size_t postIncTop();
+ size_t preDecTop();
+ void setTopForFullSegment();
+ void setTopForEmptySegment();
+ size_t top();
+
+ void validatePrevious();
+
+ DoublyLinkedList<GCArraySegment<T>> m_segments;
+ BlockAllocator& m_blockAllocator;
+
+ JS_EXPORT_PRIVATE static const size_t s_segmentCapacity = CapacityFromSize<GCArraySegment<T>::blockSize>::value;
+ size_t m_top;
+ size_t m_numberOfSegments;
+};
+
+} // namespace JSC
+
+#endif // GCSegmentedArray_h
Added: trunk/Source/_javascript_Core/heap/GCSegmentedArrayInlines.h (0 => 163414)
--- trunk/Source/_javascript_Core/heap/GCSegmentedArrayInlines.h (rev 0)
+++ trunk/Source/_javascript_Core/heap/GCSegmentedArrayInlines.h 2014-02-05 00:08:40 UTC (rev 163414)
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GCSegmentedArrayInlines_h
+#define GCSegmentedArrayInlines_h
+
+#include "BlockAllocator.h"
+#include "GCSegmentedArray.h"
+
+namespace JSC {
+
+template <typename T>
+GCSegmentedArray<T>::GCSegmentedArray(BlockAllocator& blockAllocator)
+ : m_blockAllocator(blockAllocator)
+ , m_top(0)
+ , m_numberOfSegments(0)
+{
+ m_segments.push(GCArraySegment<T>::create(m_blockAllocator.allocate<GCArraySegment<T>>()));
+ m_numberOfSegments++;
+}
+
+template <typename T>
+GCSegmentedArray<T>::~GCSegmentedArray()
+{
+ ASSERT(m_numberOfSegments == 1);
+ ASSERT(m_segments.size() == 1);
+ m_blockAllocator.deallocate(GCArraySegment<T>::destroy(m_segments.removeHead()));
+ m_numberOfSegments--;
+ ASSERT(!m_numberOfSegments);
+ ASSERT(!m_segments.size());
+}
+
+template <typename T>
+void GCSegmentedArray<T>::clear()
+{
+ if (!m_segments.head())
+ return;
+ GCArraySegment<T>* next;
+ for (GCArraySegment<T>* current = m_segments.head(); current->next(); current = next) {
+ next = current->next();
+ m_segments.remove(current);
+ m_blockAllocator.deallocate(GCArraySegment<T>::destroy(current));
+ }
+ m_top = 0;
+ m_numberOfSegments = 1;
+#if !ASSERT_DISABLED
+ m_segments.head()->m_top = 0;
+#endif
+}
+
+template <typename T>
+void GCSegmentedArray<T>::expand()
+{
+ ASSERT(m_segments.head()->m_top == s_segmentCapacity);
+
+ GCArraySegment<T>* nextSegment = GCArraySegment<T>::create(m_blockAllocator.allocate<GCArraySegment<T>>());
+ m_numberOfSegments++;
+
+#if !ASSERT_DISABLED
+ nextSegment->m_top = 0;
+#endif
+
+ m_segments.push(nextSegment);
+ setTopForEmptySegment();
+ validatePrevious();
+}
+
+template <typename T>
+bool GCSegmentedArray<T>::refill()
+{
+ validatePrevious();
+ if (top())
+ return true;
+ m_blockAllocator.deallocate(GCArraySegment<T>::destroy(m_segments.removeHead()));
+ ASSERT(m_numberOfSegments > 1);
+ m_numberOfSegments--;
+ setTopForFullSegment();
+ validatePrevious();
+ return true;
+}
+
+template <typename T>
+void GCSegmentedArray<T>::fillVector(Vector<T>& vector)
+{
+ ASSERT(vector.size() == size());
+
+ GCArraySegment<T>* currentSegment = m_segments.head();
+ if (!currentSegment)
+ return;
+
+ unsigned count = 0;
+ for (unsigned i = 0; i < m_top; ++i) {
+ ASSERT(currentSegment->data()[i]);
+ vector[count++] = currentSegment->data()[i];
+ }
+
+ currentSegment = currentSegment->next();
+ while (currentSegment) {
+ for (unsigned i = 0; i < s_segmentCapacity; ++i) {
+ ASSERT(currentSegment->data()[i]);
+ vector[count++] = currentSegment->data()[i];
+ }
+ currentSegment = currentSegment->next();
+ }
+}
+
+template <typename T>
+inline GCArraySegment<T>* GCArraySegment<T>::create(DeadBlock* block)
+{
+ return new (NotNull, block) GCArraySegment<T>(block->region());
+}
+
+template <typename T>
+inline size_t GCSegmentedArray<T>::postIncTop()
+{
+ size_t result = m_top++;
+ ASSERT(result == m_segments.head()->m_top++);
+ return result;
+}
+
+template <typename T>
+inline size_t GCSegmentedArray<T>::preDecTop()
+{
+ size_t result = --m_top;
+ ASSERT(result == --m_segments.head()->m_top);
+ return result;
+}
+
+template <typename T>
+inline void GCSegmentedArray<T>::setTopForFullSegment()
+{
+ ASSERT(m_segments.head()->m_top == s_segmentCapacity);
+ m_top = s_segmentCapacity;
+}
+
+template <typename T>
+inline void GCSegmentedArray<T>::setTopForEmptySegment()
+{
+ ASSERT(!m_segments.head()->m_top);
+ m_top = 0;
+}
+
+template <typename T>
+inline size_t GCSegmentedArray<T>::top()
+{
+ ASSERT(m_top == m_segments.head()->m_top);
+ return m_top;
+}
+
+template <typename T>
+#if ASSERT_DISABLED
+inline void GCSegmentedArray<T>::validatePrevious() { }
+#else
+inline void GCSegmentedArray<T>::validatePrevious()
+{
+ unsigned count = 0;
+ for (GCArraySegment<T>* current = m_segments.head(); current; current = current->next())
+ count++;
+ ASSERT(m_segments.size() == m_numberOfSegments);
+}
+#endif
+
+template <typename T>
+inline void GCSegmentedArray<T>::append(T value)
+{
+ if (m_top == s_segmentCapacity)
+ expand();
+ m_segments.head()->data()[postIncTop()] = value;
+}
+
+template <typename T>
+inline bool GCSegmentedArray<T>::canRemoveLast()
+{
+ return !!m_top;
+}
+
+template <typename T>
+inline const T GCSegmentedArray<T>::removeLast()
+{
+ return m_segments.head()->data()[preDecTop()];
+}
+
+template <typename T>
+inline bool GCSegmentedArray<T>::isEmpty()
+{
+ if (m_top)
+ return false;
+ if (m_segments.head()->next()) {
+ ASSERT(m_segments.head()->next()->m_top == s_segmentCapacity);
+ return false;
+ }
+ return true;
+}
+
+template <typename T>
+inline size_t GCSegmentedArray<T>::size()
+{
+ return m_top + s_segmentCapacity * (m_numberOfSegments - 1);
+}
+
+} // namespace JSC
+
+#endif // GCSegmentedArrayInlines_h
Modified: trunk/Source/_javascript_Core/heap/MarkStack.cpp (163413 => 163414)
--- trunk/Source/_javascript_Core/heap/MarkStack.cpp 2014-02-04 23:57:22 UTC (rev 163413)
+++ trunk/Source/_javascript_Core/heap/MarkStack.cpp 2014-02-05 00:08:40 UTC (rev 163414)
@@ -25,92 +25,14 @@
#include "config.h"
#include "MarkStack.h"
-#include "MarkStackInlines.h"
-#include "ConservativeRoots.h"
-#include "CopiedSpace.h"
-#include "CopiedSpaceInlines.h"
-#include "Heap.h"
-#include "JSArray.h"
-#include "JSCell.h"
-#include "JSObject.h"
-
-#include "SlotVisitorInlines.h"
-#include "Structure.h"
-#include "WriteBarrier.h"
-#include <wtf/Atomics.h>
-#include <wtf/DataLog.h>
-#include <wtf/MainThread.h>
-
namespace JSC {
-COMPILE_ASSERT(MarkStackSegment::blockSize == WeakBlock::blockSize, blockSizeMatch);
-
MarkStackArray::MarkStackArray(BlockAllocator& blockAllocator)
- : m_blockAllocator(blockAllocator)
- , m_top(0)
- , m_numberOfSegments(0)
+ : GCSegmentedArray<const JSCell*>(blockAllocator)
{
- m_segments.push(MarkStackSegment::create(m_blockAllocator.allocate<MarkStackSegment>()));
- m_numberOfSegments++;
}
-MarkStackArray::~MarkStackArray()
-{
- ASSERT(m_numberOfSegments == 1);
- ASSERT(m_segments.size() == 1);
- m_blockAllocator.deallocate(MarkStackSegment::destroy(m_segments.removeHead()));
- m_numberOfSegments--;
- ASSERT(!m_numberOfSegments);
- ASSERT(!m_segments.size());
-}
-
-void MarkStackArray::clear()
-{
- if (!m_segments.head())
- return;
- MarkStackSegment* next;
- for (MarkStackSegment* current = m_segments.head(); current->next(); current = next) {
- next = current->next();
- m_segments.remove(current);
- m_blockAllocator.deallocate(MarkStackSegment::destroy(current));
- }
- m_top = 0;
- m_numberOfSegments = 1;
-#if !ASSERT_DISABLED
- m_segments.head()->m_top = 0;
-#endif
-}
-
-void MarkStackArray::expand()
-{
- ASSERT(m_segments.head()->m_top == s_segmentCapacity);
-
- MarkStackSegment* nextSegment = MarkStackSegment::create(m_blockAllocator.allocate<MarkStackSegment>());
- m_numberOfSegments++;
-
-#if !ASSERT_DISABLED
- nextSegment->m_top = 0;
-#endif
-
- m_segments.push(nextSegment);
- setTopForEmptySegment();
- validatePrevious();
-}
-
-bool MarkStackArray::refill()
-{
- validatePrevious();
- if (top())
- return true;
- m_blockAllocator.deallocate(MarkStackSegment::destroy(m_segments.removeHead()));
- ASSERT(m_numberOfSegments > 1);
- m_numberOfSegments--;
- setTopForFullSegment();
- validatePrevious();
- return true;
-}
-
void MarkStackArray::donateSomeCellsTo(MarkStackArray& other)
{
// Try to donate about 1 / 2 of our cells. To reduce copying costs,
@@ -133,11 +55,11 @@
// Remove our head and the head of the other list before we start moving segments around.
// We'll add them back on once we're done donating.
- MarkStackSegment* myHead = m_segments.removeHead();
- MarkStackSegment* otherHead = other.m_segments.removeHead();
+ GCArraySegment<const JSCell*>* myHead = m_segments.removeHead();
+ GCArraySegment<const JSCell*>* otherHead = other.m_segments.removeHead();
while (segmentsToDonate--) {
- MarkStackSegment* current = m_segments.removeHead();
+ GCArraySegment<const JSCell*>* current = m_segments.removeHead();
ASSERT(current);
ASSERT(m_numberOfSegments > 1);
other.m_segments.push(current);
@@ -165,8 +87,8 @@
// If other has an entire segment, steal it and return.
if (other.m_numberOfSegments > 1) {
// Move the heads of the lists aside. We'll push them back on after.
- MarkStackSegment* otherHead = other.m_segments.removeHead();
- MarkStackSegment* myHead = m_segments.removeHead();
+ GCArraySegment<const JSCell*>* otherHead = other.m_segments.removeHead();
+ GCArraySegment<const JSCell*>* myHead = m_segments.removeHead();
ASSERT(other.m_segments.head()->m_top == s_segmentCapacity);
@@ -188,28 +110,4 @@
append(other.removeLast());
}
-void MarkStackArray::fillVector(Vector<const JSCell*>& vector)
-{
- ASSERT(vector.size() == size());
-
- MarkStackSegment* currentSegment = m_segments.head();
- if (!currentSegment)
- return;
-
- unsigned count = 0;
- for (unsigned i = 0; i < m_top; ++i) {
- ASSERT(currentSegment->data()[i]);
- vector[count++] = currentSegment->data()[i];
- }
-
- currentSegment = currentSegment->next();
- while (currentSegment) {
- for (unsigned i = 0; i < s_segmentCapacity; ++i) {
- ASSERT(currentSegment->data()[i]);
- vector[count++] = currentSegment->data()[i];
- }
- currentSegment = currentSegment->next();
- }
-}
-
} // namespace JSC
Modified: trunk/Source/_javascript_Core/heap/MarkStack.h (163413 => 163414)
--- trunk/Source/_javascript_Core/heap/MarkStack.h 2014-02-04 23:57:22 UTC (rev 163413)
+++ trunk/Source/_javascript_Core/heap/MarkStack.h 2014-02-05 00:08:40 UTC (rev 163414)
@@ -50,82 +50,18 @@
#define MARK_LOG_CHILD(visitor, child) do { } while (false)
#endif
-#include "HeapBlock.h"
-#include <wtf/StdLibExtras.h>
-#include <wtf/Vector.h>
+#include "GCSegmentedArrayInlines.h"
namespace JSC {
-class BlockAllocator;
-class DeadBlock;
class JSCell;
-class MarkStackSegment : public HeapBlock<MarkStackSegment> {
+class MarkStackArray : public GCSegmentedArray<const JSCell*> {
public:
- MarkStackSegment(Region* region)
- : HeapBlock<MarkStackSegment>(region)
-#if !ASSERT_DISABLED
- , m_top(0)
-#endif
- {
- }
-
- static MarkStackSegment* create(DeadBlock*);
-
- const JSCell** data()
- {
- return bitwise_cast<const JSCell**>(this + 1);
- }
-
- static const size_t blockSize = 4 * KB;
-
-#if !ASSERT_DISABLED
- size_t m_top;
-#endif
-};
-
-class MarkStackArray {
-public:
MarkStackArray(BlockAllocator&);
- ~MarkStackArray();
- void append(const JSCell*);
-
- bool canRemoveLast();
- const JSCell* removeLast();
- bool refill();
-
void donateSomeCellsTo(MarkStackArray& other);
void stealSomeCellsFrom(MarkStackArray& other, size_t idleThreadCount);
-
- size_t size();
- bool isEmpty();
-
- void fillVector(Vector<const JSCell*>&);
- void clear();
-
-private:
- template <size_t size> struct CapacityFromSize {
- static const size_t value = (size - sizeof(MarkStackSegment)) / sizeof(const JSCell*);
- };
-
- JS_EXPORT_PRIVATE void expand();
-
- size_t postIncTop();
- size_t preDecTop();
- void setTopForFullSegment();
- void setTopForEmptySegment();
- size_t top();
-
- void validatePrevious();
-
- DoublyLinkedList<MarkStackSegment> m_segments;
- BlockAllocator& m_blockAllocator;
-
- JS_EXPORT_PRIVATE static const size_t s_segmentCapacity = CapacityFromSize<MarkStackSegment::blockSize>::value;
- size_t m_top;
- size_t m_numberOfSegments;
-
};
} // namespace JSC
Deleted: trunk/Source/_javascript_Core/heap/MarkStackInlines.h (163413 => 163414)
--- trunk/Source/_javascript_Core/heap/MarkStackInlines.h 2014-02-04 23:57:22 UTC (rev 163413)
+++ trunk/Source/_javascript_Core/heap/MarkStackInlines.h 2014-02-05 00:08:40 UTC (rev 163414)
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2009, 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef MarkStackInlines_h
-#define MarkStackInlines_h
-
-#include "GCThreadSharedData.h"
-#include "MarkStack.h"
-
-namespace JSC {
-
-inline MarkStackSegment* MarkStackSegment::create(DeadBlock* block)
-{
- return new (NotNull, block) MarkStackSegment(block->region());
-}
-
-inline size_t MarkStackArray::postIncTop()
-{
- size_t result = m_top++;
- ASSERT(result == m_segments.head()->m_top++);
- return result;
-}
-
-inline size_t MarkStackArray::preDecTop()
-{
- size_t result = --m_top;
- ASSERT(result == --m_segments.head()->m_top);
- return result;
-}
-
-inline void MarkStackArray::setTopForFullSegment()
-{
- ASSERT(m_segments.head()->m_top == s_segmentCapacity);
- m_top = s_segmentCapacity;
-}
-
-inline void MarkStackArray::setTopForEmptySegment()
-{
- ASSERT(!m_segments.head()->m_top);
- m_top = 0;
-}
-
-inline size_t MarkStackArray::top()
-{
- ASSERT(m_top == m_segments.head()->m_top);
- return m_top;
-}
-
-#if ASSERT_DISABLED
-inline void MarkStackArray::validatePrevious() { }
-#else
-inline void MarkStackArray::validatePrevious()
-{
- unsigned count = 0;
- for (MarkStackSegment* current = m_segments.head(); current; current = current->next())
- count++;
- ASSERT(m_segments.size() == m_numberOfSegments);
-}
-#endif
-
-inline void MarkStackArray::append(const JSCell* cell)
-{
- if (m_top == s_segmentCapacity)
- expand();
- m_segments.head()->data()[postIncTop()] = cell;
-}
-
-inline bool MarkStackArray::canRemoveLast()
-{
- return !!m_top;
-}
-
-inline const JSCell* MarkStackArray::removeLast()
-{
- return m_segments.head()->data()[preDecTop()];
-}
-
-inline bool MarkStackArray::isEmpty()
-{
- if (m_top)
- return false;
- if (m_segments.head()->next()) {
- ASSERT(m_segments.head()->next()->m_top == s_segmentCapacity);
- return false;
- }
- return true;
-}
-
-inline size_t MarkStackArray::size()
-{
- return m_top + s_segmentCapacity * (m_numberOfSegments - 1);
-}
-
-} // namespace JSC
-
-#endif // MarkStackInlines_h
-
Modified: trunk/Source/_javascript_Core/heap/SlotVisitor.h (163413 => 163414)
--- trunk/Source/_javascript_Core/heap/SlotVisitor.h 2014-02-04 23:57:22 UTC (rev 163413)
+++ trunk/Source/_javascript_Core/heap/SlotVisitor.h 2014-02-05 00:08:40 UTC (rev 163414)
@@ -28,8 +28,9 @@
#include "CopyToken.h"
#include "HandleTypes.h"
-#include "MarkStackInlines.h"
+#include "MarkStack.h"
+#include <wtf/HashSet.h>
#include <wtf/text/StringHash.h>
namespace JSC {
@@ -37,9 +38,11 @@
class ConservativeRoots;
class GCThreadSharedData;
class Heap;
+template<typename T> class JITWriteBarrier;
+class UnconditionalFinalizer;
template<typename T> class Weak;
+class WeakReferenceHarvester;
template<typename T> class WriteBarrierBase;
-template<typename T> class JITWriteBarrier;
class SlotVisitor {
WTF_MAKE_NONCOPYABLE(SlotVisitor);