WebKit Bugzilla
Attachment 341338 Details for
Bug 185967
: Rope string sweeping should avoid touching unresolved ropes
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
maybe it'll work
blah.patch (text/plain), 53.65 KB, created by
Filip Pizlo
on 2018-05-25 15:27:45 PDT
(
hide
)
Description:
maybe it'll work
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2018-05-25 15:27:45 PDT
Size:
53.65 KB
patch
obsolete
>Index: Source/JavaScriptCore/ChangeLog >=================================================================== >--- Source/JavaScriptCore/ChangeLog (revision 232209) >+++ Source/JavaScriptCore/ChangeLog (working copy) >@@ -1,3 +1,80 @@ >+2018-05-25 Filip Pizlo <fpizlo@apple.com> >+ >+ Rope string sweeping should avoid touching unresolved ropes >+ https://bugs.webkit.org/show_bug.cgi?id=185967 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Especially when ropes are being used in anger, a lot of JSRopeString objects are never resolved. >+ Thus they don't need destruction. Since destruction is expensive, that would be useful to know. >+ >+ Ropes are usually unresolved because people do something like this: >+ >+ var result = ""; >+ for (things) >+ result += stuff >+ use result >+ >+ In that case, we will create a JSRopeString for each iteration of the loop, but we will only >+ resolve the last one. This comes up over and over again. For example, this: >+ >+ "foo" + bar + "baz" + fuzz + "buzz" + thingy + "stuff" >+ >+ will create three JSRopeStrings, but only the last one will get resolved. >+ >+ This change uses an IsoCellSet to track which JSRopeStrings have been resolved, so that we can >+ skip destructing those that haven't been resolved. To do that, this change puts JSString and >+ JSRopeString into their own IsoSubspaces. >+ >+ This also removes some unnecessary barriers in the construction of JSRopeStrings. >+ >+ * JavaScriptCore.xcodeproj/project.pbxproj: >+ * Sources.txt: >+ * heap/AtomIndices.h: >+ (JSC::AtomIndices::AtomIndices): >+ * heap/IsoCellSet.h: >+ * heap/IsoCellSetInlines.h: >+ (JSC::IsoCellSet::add): >+ (JSC::IsoCellSet::remove): >+ (JSC::IsoCellSet::contains const): >+ (JSC::IsoCellSet::bits const): >+ * heap/IsoSubspace.cpp: >+ (JSC::IsoSubspace::didSweepToFreeList): >+ (JSC::IsoSubspace::didBeginSweepingToFreeList): Deleted. >+ * heap/IsoSubspace.h: >+ * heap/MarkedBlock.cpp: >+ (JSC::MarkedBlock::Handle::sweep): >+ * heap/MarkedBlock.h: >+ (JSC::MarkedBlock::Handle::HasNoDestructor::operator() const): >+ * heap/MarkedBlockInlines.h: >+ (JSC::MarkedBlock::Handle::specializedSweep): >+ (JSC::MarkedBlock::Handle::finishSweepKnowingHeapCellType): >+ * heap/Subspace.cpp: >+ (JSC::Subspace::didSweepToFreeList): >+ (JSC::Subspace::didBeginSweepingToFreeList): Deleted. >+ * heap/Subspace.h: >+ * runtime/JSCellInlines.h: >+ (JSC::allocateCell): >+ * runtime/JSRopeStringHeapCellType.cpp: Added. >+ (JSC::JSRopeStringHasDestructorFunc::JSRopeStringHasDestructorFunc): >+ (JSC::JSRopeStringHasDestructorFunc::operator() const): >+ (JSC::JSRopeStringDestroyFunc::operator() const): >+ (JSC::JSRopeStringHeapCellType::JSRopeStringHeapCellType): >+ (JSC::JSRopeStringHeapCellType::~JSRopeStringHeapCellType): >+ (JSC::JSRopeStringHeapCellType::finishSweep): >+ (JSC::JSRopeStringHeapCellType::destroy): >+ * runtime/JSRopeStringHeapCellType.h: Added. >+ * runtime/JSString.cpp: >+ (JSC::JSRopeString::resolveRopeToAtomicString const): >+ (JSC::JSRopeString::resolveRopeToExistingAtomicString const): >+ (JSC::JSRopeString::resolveRope const): >+ (JSC::JSRopeString::didBecomeDestructible const): >+ * runtime/JSString.h: >+ (JSC::JSString::subspaceFor): >+ * runtime/VM.cpp: >+ (JSC::VM::VM): >+ * runtime/VM.h: >+ > 2018-05-25 Saam Barati <sbarati@apple.com> > > Have a memory test where we can validate JSCs mini memory mode >Index: Source/JavaScriptCore/Sources.txt >=================================================================== >--- Source/JavaScriptCore/Sources.txt (revision 232209) >+++ Source/JavaScriptCore/Sources.txt (working copy) >@@ -827,6 +827,7 @@ runtime/JSPromiseDeferred.cpp > runtime/JSPromisePrototype.cpp > runtime/JSPropertyNameEnumerator.cpp > runtime/JSProxy.cpp >+runtime/JSRopeStringHeapCellType.cpp > runtime/JSRunLoopTimer.cpp > runtime/JSScope.cpp > runtime/JSScriptFetcher.cpp >Index: Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >=================================================================== >--- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (revision 232209) >+++ Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (working copy) >@@ -348,6 +348,7 @@ > 0F5CF9891E9ED65200C18692 /* AirStackAllocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5CF9871E9ED64E00C18692 /* AirStackAllocation.h */; }; > 0F5E0FD8207C72730097F0DE /* DFGAbstractInterpreterClobberState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5E0FD6207C72710097F0DE /* DFGAbstractInterpreterClobberState.h */; }; > 0F5E0FE72086AD480097F0DE /* IsoSubspacePerVM.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5E0FE52086AD460097F0DE /* IsoSubspacePerVM.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0F5E790D20B8C18B00B809B8 /* JSRopeStringHeapCellType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5E790B20B8C14800B809B8 /* JSRopeStringHeapCellType.h */; }; > 0F5EF91F16878F7D003E5C25 /* JITThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5EF91C16878F78003E5C25 /* JITThunks.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F60FE901FFC37020003320A /* ExecutableToCodeBlockEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F60FE8E1FFC36FD0003320A /* ExecutableToCodeBlockEdge.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F61832A1C45BF070072450B /* AirCCallingConvention.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183211C45BF070072450B /* AirCCallingConvention.h */; }; >@@ -2375,6 +2376,8 @@ > 0F5E0FD7207C72710097F0DE /* DFGAbstractInterpreterClobberState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAbstractInterpreterClobberState.cpp; path = dfg/DFGAbstractInterpreterClobberState.cpp; sourceTree = "<group>"; }; > 0F5E0FE52086AD460097F0DE /* IsoSubspacePerVM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IsoSubspacePerVM.h; sourceTree = "<group>"; }; > 0F5E0FE62086AD470097F0DE /* IsoSubspacePerVM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IsoSubspacePerVM.cpp; sourceTree = "<group>"; }; >+ 0F5E790B20B8C14800B809B8 /* JSRopeStringHeapCellType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSRopeStringHeapCellType.h; sourceTree = "<group>"; }; >+ 0F5E790C20B8C14900B809B8 /* JSRopeStringHeapCellType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSRopeStringHeapCellType.cpp; sourceTree = "<group>"; }; > 0F5EF91B16878F78003E5C25 /* JITThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITThunks.cpp; sourceTree = "<group>"; }; > 0F5EF91C16878F78003E5C25 /* JITThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITThunks.h; sourceTree = "<group>"; }; > 0F60FE8D1FFC36FC0003320A /* ExecutableToCodeBlockEdge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableToCodeBlockEdge.cpp; sourceTree = "<group>"; }; >@@ -6645,9 +6648,9 @@ > E178633F0D9BEC0000D74E75 /* InitializeThreading.h */, > E35E035D1B7AB43E0073AD2A /* InspectorInstrumentationObject.cpp */, > E35E035E1B7AB43E0073AD2A /* InspectorInstrumentationObject.h */, >+ A7A8AF2B17ADB5F3005AB174 /* Int8Array.h */, > A7A8AF2C17ADB5F3005AB174 /* Int16Array.h */, > A7A8AF2D17ADB5F3005AB174 /* Int32Array.h */, >- A7A8AF2B17ADB5F3005AB174 /* Int8Array.h */, > BC9BB95B0E19680600DF8855 /* InternalFunction.cpp */, > BC11667A0E199C05008066DD /* InternalFunction.h */, > A1B9E2331B4E0D6700BC7FED /* IntlCollator.cpp */, >@@ -6757,9 +6760,9 @@ > 79B819921DD25CF500DDC714 /* JSGlobalObjectInlines.h */, > 53F11F422091749800E411A7 /* JSImmutableButterfly.cpp */, > 53F11F40209138D700E411A7 /* JSImmutableButterfly.h */, >+ 0F2B66C917B6B5AB00A7AE3F /* JSInt8Array.h */, > 0F2B66CA17B6B5AB00A7AE3F /* JSInt16Array.h */, > 0F2B66CB17B6B5AB00A7AE3F /* JSInt32Array.h */, >- 0F2B66C917B6B5AB00A7AE3F /* JSInt8Array.h */, > E33F507E1B8429A400413856 /* JSInternalPromise.cpp */, > E33F507F1B8429A400413856 /* JSInternalPromise.h */, > E33F50761B84225700413856 /* JSInternalPromiseConstructor.cpp */, >@@ -6805,6 +6808,8 @@ > 2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */, > 862553CE16136AA5009F17D0 /* JSProxy.cpp */, > 862553CF16136AA5009F17D0 /* JSProxy.h */, >+ 0F5E790C20B8C14900B809B8 /* JSRopeStringHeapCellType.cpp */, >+ 0F5E790B20B8C14800B809B8 /* JSRopeStringHeapCellType.h */, > 534638721E70D01500F12AC1 /* JSRunLoopTimer.cpp */, > 534638701E70CF3D00F12AC1 /* JSRunLoopTimer.h */, > 14874AE115EBDE4A002E3587 /* JSScope.cpp */, >@@ -6848,10 +6853,10 @@ > 53F256E11B87E28000B4B768 /* JSTypedArrayViewPrototype.cpp */, > 53917E7C1B791106000EBD33 /* JSTypedArrayViewPrototype.h */, > 6507D2970E871E4A00D7D896 /* JSTypeInfo.h */, >- 0F2B66D417B6B5AB00A7AE3F /* JSUint16Array.h */, >- 0F2B66D517B6B5AB00A7AE3F /* JSUint32Array.h */, > 0F2B66D217B6B5AB00A7AE3F /* JSUint8Array.h */, > 0F2B66D317B6B5AB00A7AE3F /* JSUint8ClampedArray.h */, >+ 0F2B66D417B6B5AB00A7AE3F /* JSUint16Array.h */, >+ 0F2B66D517B6B5AB00A7AE3F /* JSUint32Array.h */, > A7CA3AE117DA41AE006538AF /* JSWeakMap.cpp */, > A7CA3AE217DA41AE006538AF /* JSWeakMap.h */, > 709FB8611AE335C60039D069 /* JSWeakSet.cpp */, >@@ -7060,11 +7065,11 @@ > 0F2D4DE019832D91007D4B19 /* TypeProfilerLog.h */, > 0F2D4DE319832D91007D4B19 /* TypeSet.cpp */, > 0F2D4DE419832D91007D4B19 /* TypeSet.h */, >+ A7A8AF3017ADB5F3005AB174 /* Uint8Array.h */, >+ A7A8AF3117ADB5F3005AB174 /* Uint8ClampedArray.h */, > A7A8AF3217ADB5F3005AB174 /* Uint16Array.h */, > 866739D113BFDE710023D87C /* Uint16WithFraction.h */, > A7A8AF3317ADB5F3005AB174 /* Uint32Array.h */, >- A7A8AF3017ADB5F3005AB174 /* Uint8Array.h */, >- A7A8AF3117ADB5F3005AB174 /* Uint8ClampedArray.h */, > 0FE050231AA9095600D33B33 /* VarOffset.cpp */, > 0FE050241AA9095600D33B33 /* VarOffset.h */, > E18E3A570DF9278C00D90B34 /* VM.cpp */, >@@ -8708,6 +8713,7 @@ > 0FD8A32A17D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.h in Headers */, > 0FD8A32C17D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.h in Headers */, > 0FE7211E193B9C590031F6ED /* DFGTransition.h in Headers */, >+ 0F5E790D20B8C18B00B809B8 /* JSRopeStringHeapCellType.h in Headers */, > 0F63943F15C75F19006A597C /* DFGTypeCheckHoistingPhase.h in Headers */, > 0FBE0F7716C1DB120082C5E8 /* DFGUnificationPhase.h in Headers */, > 0F34B14A16D42013001CDA5A /* DFGUseKind.h in Headers */, >Index: Source/JavaScriptCore/heap/AtomIndices.h >=================================================================== >--- Source/JavaScriptCore/heap/AtomIndices.h (revision 232209) >+++ Source/JavaScriptCore/heap/AtomIndices.h (working copy) >@@ -32,7 +32,7 @@ namespace JSC { > struct AtomIndices { > AtomIndices() { } > >- AtomIndices(HeapCell* cell) >+ AtomIndices(const HeapCell* cell) > : block(MarkedBlock::blockFor(cell)) > , blockIndex(block->handle().index()) > , atomNumber(block->atomNumber(cell)) >Index: Source/JavaScriptCore/heap/IsoCellSet.h >=================================================================== >--- Source/JavaScriptCore/heap/IsoCellSet.h (revision 232209) >+++ Source/JavaScriptCore/heap/IsoCellSet.h (working copy) >@@ -45,11 +45,14 @@ public: > IsoCellSet(IsoSubspace& subspace); > ~IsoCellSet(); > >- bool add(HeapCell* cell); // Returns true if the cell was newly added. >+ bool add(const HeapCell*); // Returns true if the cell was newly added. > >- bool remove(HeapCell* cell); // Returns true if the cell was previously present and got removed. >+ bool remove(const HeapCell*); // Returns true if the cell was previously present and got removed. > >- bool contains(HeapCell* cell) const; >+ bool contains(const HeapCell*) const; >+ >+ bool contains(MarkedBlock::Handle*) const; >+ Bitmap<MarkedBlock::atomsPerBlock>* bits(MarkedBlock::Handle*) const; > > JS_EXPORT_PRIVATE RefPtr<SharedTask<MarkedBlock::Handle*()>> parallelNotEmptyMarkedBlockSource(); > >Index: Source/JavaScriptCore/heap/IsoCellSetInlines.h >=================================================================== >--- Source/JavaScriptCore/heap/IsoCellSetInlines.h (revision 232209) >+++ Source/JavaScriptCore/heap/IsoCellSetInlines.h (working copy) >@@ -31,7 +31,7 @@ > > namespace JSC { > >-inline bool IsoCellSet::add(HeapCell* cell) >+inline bool IsoCellSet::add(const HeapCell* cell) > { > AtomIndices atomIndices(cell); > auto& bitsPtrRef = m_bits[atomIndices.blockIndex]; >@@ -41,7 +41,7 @@ inline bool IsoCellSet::add(HeapCell* ce > return !bits->concurrentTestAndSet(atomIndices.atomNumber); > } > >-inline bool IsoCellSet::remove(HeapCell* cell) >+inline bool IsoCellSet::remove(const HeapCell* cell) > { > AtomIndices atomIndices(cell); > auto& bitsPtrRef = m_bits[atomIndices.blockIndex]; >@@ -51,7 +51,7 @@ inline bool IsoCellSet::remove(HeapCell* > return bits->concurrentTestAndClear(atomIndices.atomNumber); > } > >-inline bool IsoCellSet::contains(HeapCell* cell) const >+inline bool IsoCellSet::contains(const HeapCell* cell) const > { > AtomIndices atomIndices(cell); > auto* bits = m_bits[atomIndices.blockIndex].get(); >@@ -60,6 +60,16 @@ inline bool IsoCellSet::contains(HeapCel > return false; > } > >+inline bool IsoCellSet::contains(MarkedBlock::Handle* handle) const >+{ >+ return m_blocksWithBits[handle->index()]; >+} >+ >+inline Bitmap<MarkedBlock::atomsPerBlock>* IsoCellSet::bits(MarkedBlock::Handle* handle) const >+{ >+ return m_bits[handle->index()].get(); >+} >+ > template<typename Func> > void IsoCellSet::forEachMarkedCell(const Func& func) > { >Index: Source/JavaScriptCore/heap/IsoSubspace.cpp >=================================================================== >--- Source/JavaScriptCore/heap/IsoSubspace.cpp (revision 232209) >+++ Source/JavaScriptCore/heap/IsoSubspace.cpp (working copy) >@@ -79,7 +79,7 @@ void IsoSubspace::didRemoveBlock(size_t > }); > } > >-void IsoSubspace::didBeginSweepingToFreeList(MarkedBlock::Handle* block) >+void IsoSubspace::didSweepToFreeList(MarkedBlock::Handle* block) > { > m_cellSets.forEach( > [&] (IsoCellSet* set) { >Index: Source/JavaScriptCore/heap/IsoSubspace.h >=================================================================== >--- Source/JavaScriptCore/heap/IsoSubspace.h (revision 232209) >+++ Source/JavaScriptCore/heap/IsoSubspace.h (working copy) >@@ -52,7 +52,7 @@ private: > > void didResizeBits(size_t newSize) override; > void didRemoveBlock(size_t blockIndex) override; >- void didBeginSweepingToFreeList(MarkedBlock::Handle*) override; >+ void didSweepToFreeList(MarkedBlock::Handle*) override; > > size_t m_size; > BlockDirectory m_directory; >Index: Source/JavaScriptCore/heap/MarkedBlock.cpp >=================================================================== >--- Source/JavaScriptCore/heap/MarkedBlock.cpp (revision 232209) >+++ Source/JavaScriptCore/heap/MarkedBlock.cpp (working copy) >@@ -426,60 +426,59 @@ void MarkedBlock::Handle::sweep(FreeList > if (space()->isMarking()) > blockFooter().m_lock.lock(); > >- subspace()->didBeginSweepingToFreeList(this); >- >- if (needsDestruction) { >+ if (needsDestruction) > subspace()->finishSweep(*this, freeList); >- return; >- } >- >- // Handle the no-destructor specializations here, since we have the most of those. This >- // ensures that they don't get re-specialized for every destructor space. >- >- EmptyMode emptyMode = this->emptyMode(); >- ScribbleMode scribbleMode = this->scribbleMode(); >- NewlyAllocatedMode newlyAllocatedMode = this->newlyAllocatedMode(); >- MarksMode marksMode = this->marksMode(); >- >- auto trySpecialized = [&] () -> bool { >- if (sweepMode != SweepToFreeList) >- return false; >- if (scribbleMode != DontScribble) >- return false; >- if (newlyAllocatedMode != DoesNotHaveNewlyAllocated) >- return false; >+ else { >+ // Handle the no-destructor specializations here, since we have the most of those. This >+ // ensures that they don't get re-specialized for every destructor space. >+ >+ EmptyMode emptyMode = this->emptyMode(); >+ ScribbleMode scribbleMode = this->scribbleMode(); >+ NewlyAllocatedMode newlyAllocatedMode = this->newlyAllocatedMode(); >+ MarksMode marksMode = this->marksMode(); >+ >+ auto trySpecialized = [&] () -> bool { >+ if (sweepMode != SweepToFreeList) >+ return false; >+ if (scribbleMode != DontScribble) >+ return false; >+ if (newlyAllocatedMode != DoesNotHaveNewlyAllocated) >+ return false; > >- switch (emptyMode) { >- case IsEmpty: >- switch (marksMode) { >- case MarksNotStale: >- specializedSweep<true, IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale>(freeList, IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale, [] (VM&, JSCell*) { }); >- return true; >- case MarksStale: >- specializedSweep<true, IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale>(freeList, IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale, [] (VM&, JSCell*) { }); >- return true; >+ switch (emptyMode) { >+ case IsEmpty: >+ switch (marksMode) { >+ case MarksNotStale: >+ specializedSweep<true, IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale>(freeList, IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale, HasNoDestructor(), [] (VM&, JSCell*) { }); >+ return true; >+ case MarksStale: >+ specializedSweep<true, IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale>(freeList, IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale, HasNoDestructor(), [] (VM&, JSCell*) { }); >+ return true; >+ } >+ break; >+ case NotEmpty: >+ switch (marksMode) { >+ case MarksNotStale: >+ specializedSweep<true, NotEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale>(freeList, IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale, HasNoDestructor(), [] (VM&, JSCell*) { }); >+ return true; >+ case MarksStale: >+ specializedSweep<true, NotEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale>(freeList, IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale, HasNoDestructor(), [] (VM&, JSCell*) { }); >+ return true; >+ } >+ break; > } >- break; >- case NotEmpty: >- switch (marksMode) { >- case MarksNotStale: >- specializedSweep<true, NotEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale>(freeList, IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale, [] (VM&, JSCell*) { }); >- return true; >- case MarksStale: >- specializedSweep<true, NotEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale>(freeList, IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale, [] (VM&, JSCell*) { }); >- return true; >- } >- break; >- } > >- return false; >- }; >+ return false; >+ }; > >- if (trySpecialized()) >- return; >- >- // The template arguments don't matter because the first one is false. >- specializedSweep<false, IsEmpty, SweepOnly, BlockHasNoDestructors, DontScribble, HasNewlyAllocated, MarksStale>(freeList, emptyMode, sweepMode, BlockHasNoDestructors, scribbleMode, newlyAllocatedMode, marksMode, [] (VM&, JSCell*) { }); >+ if (!trySpecialized()) { >+ // The template arguments don't matter because the first one is false. >+ specializedSweep<false, IsEmpty, SweepOnly, BlockHasNoDestructors, DontScribble, HasNewlyAllocated, MarksStale>(freeList, emptyMode, sweepMode, BlockHasNoDestructors, scribbleMode, newlyAllocatedMode, marksMode, HasNoDestructor(), [] (VM&, JSCell*) { }); >+ } >+ } >+ >+ if (sweepMode == SweepToFreeList) >+ subspace()->didSweepToFreeList(this); > } > > bool MarkedBlock::Handle::isFreeListedCell(const void* target) const >Index: Source/JavaScriptCore/heap/MarkedBlock.h >=================================================================== >--- Source/JavaScriptCore/heap/MarkedBlock.h (revision 232209) >+++ Source/JavaScriptCore/heap/MarkedBlock.h (working copy) >@@ -133,10 +133,20 @@ public: > // mistake of making a pop freelist rather than a bump freelist. > void sweep(FreeList*); > >- // This is to be called by Subspace. > template<typename DestroyFunc> > void finishSweepKnowingHeapCellType(FreeList*, const DestroyFunc&); > >+ struct HasNoDestructor { >+ ALWAYS_INLINE bool operator()(size_t) const { return false; } >+ }; >+ >+ struct AlwaysHasDestructor { >+ ALWAYS_INLINE bool operator()(size_t) const { return true; } >+ }; >+ >+ template<typename HasDestructorFunc, typename DestroyFunc> >+ void finishSweepKnowingHeapCellType(FreeList*, const HasDestructorFunc&, const DestroyFunc&); >+ > void unsweepWithNoNewlyAllocated(); > > void zap(const FreeList&); >@@ -209,8 +219,8 @@ public: > NewlyAllocatedMode newlyAllocatedMode(); > MarksMode marksMode(); > >- template<bool, EmptyMode, SweepMode, SweepDestructionMode, ScribbleMode, NewlyAllocatedMode, MarksMode, typename DestroyFunc> >- void specializedSweep(FreeList*, EmptyMode, SweepMode, SweepDestructionMode, ScribbleMode, NewlyAllocatedMode, MarksMode, const DestroyFunc&); >+ template<bool, EmptyMode, SweepMode, SweepDestructionMode, ScribbleMode, NewlyAllocatedMode, MarksMode, typename HasDestructorFunc, typename DestroyFunc> >+ void specializedSweep(FreeList*, EmptyMode, SweepMode, SweepDestructionMode, ScribbleMode, NewlyAllocatedMode, MarksMode, const HasDestructorFunc&, const DestroyFunc&); > > void setIsFreeListed(); > >Index: Source/JavaScriptCore/heap/MarkedBlockInlines.h >=================================================================== >--- Source/JavaScriptCore/heap/MarkedBlockInlines.h (revision 232209) >+++ Source/JavaScriptCore/heap/MarkedBlockInlines.h (working copy) >@@ -224,8 +224,8 @@ inline bool MarkedBlock::Handle::isLiveC > // > // Only the DoesNotNeedDestruction one should be specialized by MarkedBlock. > >-template<bool specialize, MarkedBlock::Handle::EmptyMode specializedEmptyMode, MarkedBlock::Handle::SweepMode specializedSweepMode, MarkedBlock::Handle::SweepDestructionMode specializedDestructionMode, MarkedBlock::Handle::ScribbleMode specializedScribbleMode, MarkedBlock::Handle::NewlyAllocatedMode specializedNewlyAllocatedMode, MarkedBlock::Handle::MarksMode specializedMarksMode, typename DestroyFunc> >-void MarkedBlock::Handle::specializedSweep(FreeList* freeList, MarkedBlock::Handle::EmptyMode emptyMode, MarkedBlock::Handle::SweepMode sweepMode, MarkedBlock::Handle::SweepDestructionMode destructionMode, MarkedBlock::Handle::ScribbleMode scribbleMode, MarkedBlock::Handle::NewlyAllocatedMode newlyAllocatedMode, MarkedBlock::Handle::MarksMode marksMode, const DestroyFunc& destroyFunc) >+template<bool specialize, MarkedBlock::Handle::EmptyMode specializedEmptyMode, MarkedBlock::Handle::SweepMode specializedSweepMode, MarkedBlock::Handle::SweepDestructionMode specializedDestructionMode, MarkedBlock::Handle::ScribbleMode specializedScribbleMode, MarkedBlock::Handle::NewlyAllocatedMode specializedNewlyAllocatedMode, MarkedBlock::Handle::MarksMode specializedMarksMode, typename HasDestructorFunc, typename DestroyFunc> >+void MarkedBlock::Handle::specializedSweep(FreeList* freeList, MarkedBlock::Handle::EmptyMode emptyMode, MarkedBlock::Handle::SweepMode sweepMode, MarkedBlock::Handle::SweepDestructionMode destructionMode, MarkedBlock::Handle::ScribbleMode scribbleMode, MarkedBlock::Handle::NewlyAllocatedMode newlyAllocatedMode, MarkedBlock::Handle::MarksMode marksMode, const HasDestructorFunc& hasDestructor, const DestroyFunc& destroyFunc) > { > if (specialize) { > emptyMode = specializedEmptyMode; >@@ -259,6 +259,9 @@ void MarkedBlock::Handle::specializedSwe > > m_directory->setIsDestructible(NoLockingNecessary, this, false); > >+ unsigned endAtom = m_endAtom; >+ unsigned atomsPerCell = m_atomsPerCell; >+ > if (Options::useBumpAllocator() > && emptyMode == IsEmpty > && newlyAllocatedMode == DoesNotHaveNewlyAllocated) { >@@ -285,8 +288,11 @@ void MarkedBlock::Handle::specializedSwe > if (space()->isMarking()) > footer.m_lock.unlock(); > if (destructionMode != BlockHasNoDestructors) { >- for (char* cell = payloadBegin; cell < payloadEnd; cell += cellSize) >- destroy(cell); >+ for (size_t i = 0; i < endAtom; i += atomsPerCell) { >+ HeapCell* cell = reinterpret_cast_ptr<HeapCell*>(&block.atoms()[i]); >+ if (hasDestructor(i)) >+ destroy(cell); >+ } > } > if (sweepMode == SweepToFreeList) { > if (scribbleMode == Scribble) >@@ -322,7 +328,7 @@ void MarkedBlock::Handle::specializedSwe > ++count; > } > }; >- for (size_t i = 0; i < m_endAtom; i += m_atomsPerCell) { >+ for (size_t i = 0; i < endAtom; i += atomsPerCell) { > if (emptyMode == NotEmpty > && ((marksMode == MarksNotStale && footer.m_marks.get(i)) > || (newlyAllocatedMode == HasNewlyAllocated && footer.m_newlyAllocated.get(i)))) { >@@ -330,6 +336,9 @@ void MarkedBlock::Handle::specializedSwe > continue; > } > >+ if (!hasDestructor(i)) >+ continue; >+ > if (destructionMode == BlockHasDestructorsAndCollectorIsRunning) > deadCells.append(i); > else >@@ -358,8 +367,8 @@ void MarkedBlock::Handle::specializedSwe > dataLog("Slowly swept block ", RawPointer(&block), " with cell size ", cellSize, " and attributes ", m_attributes, ": ", pointerDump(freeList), "\n"); > } > >-template<typename DestroyFunc> >-void MarkedBlock::Handle::finishSweepKnowingHeapCellType(FreeList* freeList, const DestroyFunc& destroyFunc) >+template<typename HasDestructorFunc, typename DestroyFunc> >+void MarkedBlock::Handle::finishSweepKnowingHeapCellType(FreeList* freeList, const HasDestructorFunc& hasDestructor, const DestroyFunc& destroyFunc) > { > SweepMode sweepMode = freeList ? SweepToFreeList : SweepOnly; > SweepDestructionMode destructionMode = this->sweepDestructionMode(); >@@ -382,20 +391,20 @@ void MarkedBlock::Handle::finishSweepKno > case SweepOnly: > switch (marksMode) { > case MarksNotStale: >- specializedSweep<true, IsEmpty, SweepOnly, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale>(freeList, IsEmpty, SweepOnly, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale, destroyFunc); >+ specializedSweep<true, IsEmpty, SweepOnly, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale>(freeList, IsEmpty, SweepOnly, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale, hasDestructor, destroyFunc); > return true; > case MarksStale: >- specializedSweep<true, IsEmpty, SweepOnly, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale>(freeList, IsEmpty, SweepOnly, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale, destroyFunc); >+ specializedSweep<true, IsEmpty, SweepOnly, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale>(freeList, IsEmpty, SweepOnly, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale, hasDestructor, destroyFunc); > return true; > } > RELEASE_ASSERT_NOT_REACHED(); > case SweepToFreeList: > switch (marksMode) { > case MarksNotStale: >- specializedSweep<true, IsEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale>(freeList, IsEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale, destroyFunc); >+ specializedSweep<true, IsEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale>(freeList, IsEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale, hasDestructor, destroyFunc); > return true; > case MarksStale: >- specializedSweep<true, IsEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale>(freeList, IsEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale, destroyFunc); >+ specializedSweep<true, IsEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale>(freeList, IsEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale, hasDestructor, destroyFunc); > return true; > } > } >@@ -405,20 +414,20 @@ void MarkedBlock::Handle::finishSweepKno > case SweepOnly: > switch (marksMode) { > case MarksNotStale: >- specializedSweep<true, NotEmpty, SweepOnly, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale>(freeList, NotEmpty, SweepOnly, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale, destroyFunc); >+ specializedSweep<true, NotEmpty, SweepOnly, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale>(freeList, NotEmpty, SweepOnly, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale, hasDestructor, destroyFunc); > return true; > case MarksStale: >- specializedSweep<true, NotEmpty, SweepOnly, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale>(freeList, NotEmpty, SweepOnly, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale, destroyFunc); >+ specializedSweep<true, NotEmpty, SweepOnly, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale>(freeList, NotEmpty, SweepOnly, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale, hasDestructor, destroyFunc); > return true; > } > RELEASE_ASSERT_NOT_REACHED(); > case SweepToFreeList: > switch (marksMode) { > case MarksNotStale: >- specializedSweep<true, NotEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale>(freeList, NotEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale, destroyFunc); >+ specializedSweep<true, NotEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale>(freeList, NotEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale, hasDestructor, destroyFunc); > return true; > case MarksStale: >- specializedSweep<true, NotEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale>(freeList, NotEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale, destroyFunc); >+ specializedSweep<true, NotEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale>(freeList, NotEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale, hasDestructor, destroyFunc); > return true; > } > } >@@ -431,7 +440,13 @@ void MarkedBlock::Handle::finishSweepKno > return; > > // The template arguments don't matter because the first one is false. >- specializedSweep<false, IsEmpty, SweepOnly, BlockHasNoDestructors, DontScribble, HasNewlyAllocated, MarksStale>(freeList, emptyMode, sweepMode, destructionMode, scribbleMode, newlyAllocatedMode, marksMode, destroyFunc); >+ specializedSweep<false, IsEmpty, SweepOnly, BlockHasNoDestructors, DontScribble, HasNewlyAllocated, MarksStale>(freeList, emptyMode, sweepMode, destructionMode, scribbleMode, newlyAllocatedMode, marksMode, hasDestructor, destroyFunc); >+} >+ >+template<typename DestroyFunc> >+void MarkedBlock::Handle::finishSweepKnowingHeapCellType(FreeList* freeList, const DestroyFunc& destroyFunc) >+{ >+ finishSweepKnowingHeapCellType(freeList, AlwaysHasDestructor(), destroyFunc); > } > > inline MarkedBlock::Handle::SweepDestructionMode MarkedBlock::Handle::sweepDestructionMode() >Index: Source/JavaScriptCore/heap/Subspace.cpp >=================================================================== >--- Source/JavaScriptCore/heap/Subspace.cpp (revision 232209) >+++ Source/JavaScriptCore/heap/Subspace.cpp (working copy) >@@ -142,7 +142,7 @@ void Subspace::didRemoveBlock(size_t) > { > } > >-void Subspace::didBeginSweepingToFreeList(MarkedBlock::Handle*) >+void Subspace::didSweepToFreeList(MarkedBlock::Handle*) > { > } > >Index: Source/JavaScriptCore/heap/Subspace.h >=================================================================== >--- Source/JavaScriptCore/heap/Subspace.h (revision 232209) >+++ Source/JavaScriptCore/heap/Subspace.h (working copy) >@@ -99,7 +99,7 @@ public: > > virtual void didResizeBits(size_t newSize); > virtual void didRemoveBlock(size_t blockIndex); >- virtual void didBeginSweepingToFreeList(MarkedBlock::Handle*); >+ virtual void didSweepToFreeList(MarkedBlock::Handle*); // This is the last thing that sweep does. > > protected: > void initialize(HeapCellType*, AlignedMemoryAllocator*); >Index: Source/JavaScriptCore/runtime/JSCellInlines.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSCellInlines.h (revision 232209) >+++ Source/JavaScriptCore/runtime/JSCellInlines.h (working copy) >@@ -170,7 +170,7 @@ ALWAYS_INLINE void* tryAllocateCellHelpe > } > > template<typename T> >-void* allocateCell(Heap& heap, size_t size) >+ALWAYS_INLINE void* allocateCell(Heap& heap, size_t size) > { > return tryAllocateCellHelper<T>(heap, size, nullptr, AllocationFailureMode::Assert); > } >Index: Source/JavaScriptCore/runtime/JSRopeStringHeapCellType.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSRopeStringHeapCellType.cpp (nonexistent) >+++ Source/JavaScriptCore/runtime/JSRopeStringHeapCellType.cpp (working copy) >@@ -0,0 +1,88 @@ >+/* >+ * Copyright (C) 2018 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. >+ */ >+ >+#include "config.h" >+#include "JSRopeStringHeapCellType.h" >+ >+#include "IsoCellSetInlines.h" >+#include "MarkedBlockInlines.h" >+#include "JSCInlines.h" >+ >+namespace JSC { >+ >+class JSRopeStringHasDestructorFunc { >+public: >+ JSRopeStringHasDestructorFunc(Bitmap<MarkedBlock::atomsPerBlock>* bits) >+ : m_bits(bits) >+ { >+ } >+ >+ ALWAYS_INLINE bool operator()(size_t i) const >+ { >+ return m_bits->get(i); >+ } >+ >+private: >+ Bitmap<MarkedBlock::atomsPerBlock>* m_bits; >+}; >+ >+struct JSRopeStringDestroyFunc { >+ ALWAYS_INLINE void operator()(VM&, JSCell* cell) const >+ { >+ static_cast<JSRopeString*>(cell)->JSRopeString::~JSRopeString(); >+ } >+}; >+ >+JSRopeStringHeapCellType::JSRopeStringHeapCellType() >+ : HeapCellType(CellAttributes(NeedsDestruction, HeapCell::JSCell)) >+{ >+} >+ >+JSRopeStringHeapCellType::~JSRopeStringHeapCellType() >+{ >+} >+ >+void JSRopeStringHeapCellType::finishSweep(MarkedBlock::Handle& handle, FreeList* freeList) >+{ >+ VM& vm = *handle.vm(); >+ >+ if (vm.ropeStringsWithDestructors.contains(&handle)) { >+ handle.finishSweepKnowingHeapCellType( >+ freeList, >+ JSRopeStringHasDestructorFunc(vm.ropeStringsWithDestructors.bits(&handle)), >+ JSRopeStringDestroyFunc()); >+ return; >+ } >+ >+ handle.finishSweepKnowingHeapCellType(freeList, JSRopeStringDestroyFunc()); >+} >+ >+void JSRopeStringHeapCellType::destroy(VM& vm, JSCell* cell) >+{ >+ JSRopeStringDestroyFunc()(vm, cell); >+} >+ >+} // namespace JSC >+ >Index: Source/JavaScriptCore/runtime/JSRopeStringHeapCellType.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSRopeStringHeapCellType.h (nonexistent) >+++ Source/JavaScriptCore/runtime/JSRopeStringHeapCellType.h (working copy) >@@ -0,0 +1,42 @@ >+/* >+ * Copyright (C) 2018 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. >+ */ >+ >+#pragma once >+ >+#include "HeapCellType.h" >+ >+namespace JSC { >+ >+class JSRopeStringHeapCellType : public HeapCellType { >+public: >+ JS_EXPORT_PRIVATE JSRopeStringHeapCellType(); >+ JS_EXPORT_PRIVATE virtual ~JSRopeStringHeapCellType(); >+ >+ void finishSweep(MarkedBlock::Handle&, FreeList*) override; >+ void destroy(VM&, JSCell*) override; >+}; >+ >+} // namespace JSC >+ >Index: Source/JavaScriptCore/runtime/JSString.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSString.cpp (revision 232209) >+++ Source/JavaScriptCore/runtime/JSString.cpp (working copy) >@@ -23,6 +23,7 @@ > #include "config.h" > #include "JSString.h" > >+#include "IsoCellSetInlines.h" > #include "JSGlobalObject.h" > #include "JSGlobalObjectFunctions.h" > #include "JSObject.h" >@@ -181,6 +182,7 @@ void JSRopeString::resolveRopeToAtomicSt > if (length() > maxLengthForOnStackResolve) { > resolveRope(exec); > m_value = AtomicString(m_value); >+ didBecomeDestructible(exec->vm()); > setIs8Bit(m_value.impl()->is8Bit()); > return; > } >@@ -189,11 +191,13 @@ void JSRopeString::resolveRopeToAtomicSt > LChar buffer[maxLengthForOnStackResolve]; > resolveRopeInternal8(buffer); > m_value = AtomicString(buffer, length()); >+ didBecomeDestructible(exec->vm()); > setIs8Bit(m_value.impl()->is8Bit()); > } else { > UChar buffer[maxLengthForOnStackResolve]; > resolveRopeInternal16(buffer); > m_value = AtomicString(buffer, length()); >+ didBecomeDestructible(exec->vm()); > setIs8Bit(m_value.impl()->is8Bit()); > } > >@@ -216,6 +220,7 @@ RefPtr<AtomicStringImpl> JSRopeString::r > resolveRope(exec); > if (RefPtr<AtomicStringImpl> existingAtomicString = AtomicStringImpl::lookUp(m_value.impl())) { > m_value = *existingAtomicString; >+ didBecomeDestructible(exec->vm()); > setIs8Bit(m_value.impl()->is8Bit()); > clearFibers(); > return existingAtomicString; >@@ -228,6 +233,7 @@ RefPtr<AtomicStringImpl> JSRopeString::r > resolveRopeInternal8(buffer); > if (RefPtr<AtomicStringImpl> existingAtomicString = AtomicStringImpl::lookUp(buffer, length())) { > m_value = *existingAtomicString; >+ didBecomeDestructible(exec->vm()); > setIs8Bit(m_value.impl()->is8Bit()); > clearFibers(); > return existingAtomicString; >@@ -237,6 +243,7 @@ RefPtr<AtomicStringImpl> JSRopeString::r > resolveRopeInternal16(buffer); > if (RefPtr<AtomicStringImpl> existingAtomicString = AtomicStringImpl::lookUp(buffer, length())) { > m_value = *existingAtomicString; >+ didBecomeDestructible(exec->vm()); > setIs8Bit(m_value.impl()->is8Bit()); > clearFibers(); > return existingAtomicString; >@@ -253,6 +260,7 @@ void JSRopeString::resolveRope(ExecState > if (isSubstring()) { > ASSERT(!substringBase()->isRope()); > m_value = substringBase()->m_value.substringSharingImpl(substringOffset(), length()); >+ didBecomeDestructible(exec->vm()); > substringBase().clear(); > return; > } >@@ -262,6 +270,7 @@ void JSRopeString::resolveRope(ExecState > if (auto newImpl = StringImpl::tryCreateUninitialized(length(), buffer)) { > Heap::heap(this)->reportExtraMemoryAllocated(newImpl->cost()); > m_value = WTFMove(newImpl); >+ didBecomeDestructible(exec->vm()); > } else { > outOfMemory(exec); > return; >@@ -276,6 +285,7 @@ void JSRopeString::resolveRope(ExecState > if (auto newImpl = StringImpl::tryCreateUninitialized(length(), buffer)) { > Heap::heap(this)->reportExtraMemoryAllocated(newImpl->cost()); > m_value = WTFMove(newImpl); >+ didBecomeDestructible(exec->vm()); > } else { > outOfMemory(exec); > return; >@@ -376,6 +386,11 @@ void JSRopeString::resolveRopeSlowCase(U > ASSERT(buffer == position); > } > >+void JSRopeString::didBecomeDestructible(VM& vm) const >+{ >+ vm.ropeStringsWithDestructors.add(this); >+} >+ > void JSRopeString::outOfMemory(ExecState* exec) const > { > VM& vm = exec->vm(); >Index: Source/JavaScriptCore/runtime/JSString.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSString.h (revision 232209) >+++ Source/JavaScriptCore/runtime/JSString.h (working copy) >@@ -87,10 +87,8 @@ public: > static const bool needsDestruction = true; > static void destroy(JSCell*); > >- // We specialize the string subspace to get the fastest possible sweep. This wouldn't be >- // necessary if JSString didn't have a destructor. > template<typename> >- static CompleteSubspace* subspaceFor(VM& vm) >+ static IsoSubspace* subspaceFor(VM& vm) > { > return &vm.stringSpace; > } >@@ -240,6 +238,12 @@ class JSRopeString final : public JSStri > friend JSRopeString* jsStringBuilder(VM*); > > public: >+ template<typename> >+ static IsoSubspace* subspaceFor(VM& vm) >+ { >+ return &vm.ropeStringSpace; >+ } >+ > template <class OverflowHandler = CrashOnOverflow> > class RopeBuilder : public OverflowHandler { > public: >@@ -292,28 +296,28 @@ private: > { > } > >- void finishCreation(VM& vm, JSString* s1, JSString* s2) >+ ALWAYS_INLINE void finishCreation(VM& vm, JSString* s1, JSString* s2) > { > Base::finishCreation(vm); > ASSERT(!sumOverflows<int32_t>(s1->length(), s2->length())); > setLength(s1->length() + s2->length()); > setIs8Bit(s1->is8Bit() && s2->is8Bit()); > setIsSubstring(false); >- fiber(0).set(vm, this, s1); >- fiber(1).set(vm, this, s2); >+ fiber(0).setWithoutWriteBarrier(s1); >+ fiber(1).setWithoutWriteBarrier(s2); > fiber(2).clear(); > } > >- void finishCreation(VM& vm, JSString* s1, JSString* s2, JSString* s3) >+ ALWAYS_INLINE void finishCreation(VM& vm, JSString* s1, JSString* s2, JSString* s3) > { > Base::finishCreation(vm); > ASSERT(!sumOverflows<int32_t>(s1->length(), s2->length(), s3->length())); > setLength(s1->length() + s2->length() + s3->length()); > setIs8Bit(s1->is8Bit() && s2->is8Bit() && s3->is8Bit()); > setIsSubstring(false); >- fiber(0).set(vm, this, s1); >- fiber(1).set(vm, this, s2); >- fiber(2).set(vm, this, s3); >+ fiber(0).setWithoutWriteBarrier(s1); >+ fiber(1).setWithoutWriteBarrier(s2); >+ fiber(2).setWithoutWriteBarrier(s3); > } > > void finishCreation(VM& vm, ExecState* exec, JSString* base, unsigned offset, unsigned length) >@@ -402,13 +406,13 @@ public: > static const unsigned s_maxInternalRopeLength = 3; > > private: >- static JSString* create(VM& vm, JSString* s1, JSString* s2) >+ ALWAYS_INLINE static JSString* create(VM& vm, JSString* s1, JSString* s2) > { > JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(vm.heap)) JSRopeString(vm); > newString->finishCreation(vm, s1, s2); > return newString; > } >- static JSString* create(VM& vm, JSString* s1, JSString* s2, JSString* s3) >+ ALWAYS_INLINE static JSString* create(VM& vm, JSString* s1, JSString* s2, JSString* s3) > { > JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(vm.heap)) JSRopeString(vm); > newString->finishCreation(vm, s1, s2, s3); >@@ -431,7 +435,9 @@ private: > void clearFibers() const; > StringView unsafeView(ExecState*) const; > StringViewWithUnderlyingString viewWithUnderlyingString(ExecState*) const; >- >+ >+ void didBecomeDestructible(VM&) const; >+ > WriteBarrierBase<JSString>& fiber(unsigned i) const > { > ASSERT(!isSubstring()); >Index: Source/JavaScriptCore/runtime/VM.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/VM.cpp (revision 232209) >+++ Source/JavaScriptCore/runtime/VM.cpp (working copy) >@@ -92,6 +92,7 @@ > #include "JSMapIterator.h" > #include "JSPromiseDeferred.h" > #include "JSPropertyNameEnumerator.h" >+#include "JSRopeStringHeapCellType.h" > #include "JSSegmentedVariableObjectHeapCellType.h" > #include "JSScriptFetchParameters.h" > #include "JSScriptFetcher.h" >@@ -252,6 +253,7 @@ VM::VM(VMType vmType, HeapType heapType) > , cellDangerousBitsHeapCellType(std::make_unique<HeapCellType>(CellAttributes(DoesNotNeedDestruction, HeapCell::JSCell))) > , destructibleCellHeapCellType(std::make_unique<HeapCellType>(CellAttributes(NeedsDestruction, HeapCell::JSCell))) > , stringHeapCellType(std::make_unique<JSStringHeapCellType>()) >+ , ropeStringHeapCellType(std::make_unique<JSRopeStringHeapCellType>()) > , destructibleObjectHeapCellType(std::make_unique<JSDestructibleObjectHeapCellType>()) > , segmentedVariableObjectHeapCellType(std::make_unique<JSSegmentedVariableObjectHeapCellType>()) > #if ENABLE(WEBASSEMBLY) >@@ -263,7 +265,6 @@ VM::VM(VMType vmType, HeapType heapType) > , cellDangerousBitsSpace("JSCell DangerousBits", heap, cellDangerousBitsHeapCellType.get(), fastMallocAllocator.get()) > , jsValueGigacageCellSpace("JSValue Gigacage JSCell", heap, cellJSValueOOBHeapCellType.get(), jsValueGigacageAllocator.get()) > , destructibleCellSpace("Destructible JSCell", heap, destructibleCellHeapCellType.get(), fastMallocAllocator.get()) >- , stringSpace("JSString", heap, stringHeapCellType.get(), fastMallocAllocator.get()) > , destructibleObjectSpace("JSDestructibleObject", heap, destructibleObjectHeapCellType.get(), fastMallocAllocator.get()) > , eagerlySweptDestructibleObjectSpace("Eagerly Swept JSDestructibleObject", heap, destructibleObjectHeapCellType.get(), fastMallocAllocator.get()) > , segmentedVariableObjectSpace("JSSegmentedVariableObjectSpace", heap, segmentedVariableObjectHeapCellType.get(), fastMallocAllocator.get()) >@@ -300,7 +301,9 @@ VM::VM(VMType vmType, HeapType heapType) > , propertyTableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), PropertyTable) > , proxyRevokeSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), ProxyRevoke) > , regExpConstructorSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), RegExpConstructor) >+ , ropeStringSpace ISO_SUBSPACE_INIT(heap, ropeStringHeapCellType.get(), JSRopeString) > , strictModeTypeErrorFunctionSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), StrictModeTypeErrorFunction) >+ , stringSpace ISO_SUBSPACE_INIT(heap, stringHeapCellType.get(), JSString) > , structureRareDataSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), StructureRareData) > , structureSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), Structure) > , weakSetSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), JSWeakSet) >@@ -314,6 +317,7 @@ VM::VM(VMType vmType, HeapType heapType) > , executableToCodeBlockEdgesWithFinalizers(executableToCodeBlockEdgeSpace) > , inferredTypesWithFinalizers(inferredTypeSpace) > , inferredValuesWithFinalizers(inferredValueSpace) >+ , ropeStringsWithDestructors(ropeStringSpace) > , evalCodeBlockSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), EvalCodeBlock) > , functionCodeBlockSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), FunctionCodeBlock) > , moduleProgramCodeBlockSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), ModuleProgramCodeBlock) >Index: Source/JavaScriptCore/runtime/VM.h >=================================================================== >--- Source/JavaScriptCore/runtime/VM.h (revision 232209) >+++ Source/JavaScriptCore/runtime/VM.h (working copy) >@@ -120,6 +120,7 @@ class JSCustomGetterSetterFunction; > class JSDestructibleObjectHeapCellType; > class JSGlobalObject; > class JSObject; >+class JSRopeStringHeapCellType; > class JSRunLoopTimer; > class JSSegmentedVariableObjectHeapCellType; > class JSStringHeapCellType; >@@ -309,6 +310,7 @@ public: > std::unique_ptr<HeapCellType> cellDangerousBitsHeapCellType; > std::unique_ptr<HeapCellType> destructibleCellHeapCellType; > std::unique_ptr<JSStringHeapCellType> stringHeapCellType; >+ std::unique_ptr<JSRopeStringHeapCellType> ropeStringHeapCellType; > std::unique_ptr<JSDestructibleObjectHeapCellType> destructibleObjectHeapCellType; > std::unique_ptr<JSSegmentedVariableObjectHeapCellType> segmentedVariableObjectHeapCellType; > #if ENABLE(WEBASSEMBLY) >@@ -341,7 +343,6 @@ public: > CompleteSubspace cellDangerousBitsSpace; > CompleteSubspace jsValueGigacageCellSpace; // FIXME: This space is problematic because we have things in here like DirectArguments and ScopedArguments; those should be split into JSValueOOB cells and JSValueStrict auxiliaries. https://bugs.webkit.org/show_bug.cgi?id=182858 > CompleteSubspace destructibleCellSpace; >- CompleteSubspace stringSpace; > CompleteSubspace destructibleObjectSpace; > CompleteSubspace eagerlySweptDestructibleObjectSpace; > CompleteSubspace segmentedVariableObjectSpace; >@@ -379,7 +380,9 @@ public: > IsoSubspace propertyTableSpace; > IsoSubspace proxyRevokeSpace; > IsoSubspace regExpConstructorSpace; >+ IsoSubspace ropeStringSpace; > IsoSubspace strictModeTypeErrorFunctionSpace; >+ IsoSubspace stringSpace; > IsoSubspace structureRareDataSpace; > IsoSubspace structureSpace; > IsoSubspace weakSetSpace; >@@ -394,6 +397,7 @@ public: > IsoCellSet executableToCodeBlockEdgesWithFinalizers; > IsoCellSet inferredTypesWithFinalizers; > IsoCellSet inferredValuesWithFinalizers; >+ IsoCellSet ropeStringsWithDestructors; > > struct SpaceAndFinalizerSet { > IsoSubspace space;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 185967
:
341234
|
341338
|
341361
|
341413