<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[210844] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/210844">210844</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2017-01-17 20:22:45 -0800 (Tue, 17 Jan 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Make opaque root scanning truly constraint-based
https://bugs.webkit.org/show_bug.cgi?id=165760

Reviewed by Geoffrey Garen.
JSTests:

        
Added this test, which demonstrates the benefit of having a dedicated string subspace.

* microbenchmarks/stringalloc.js: Added.

Source/JavaScriptCore:


We have bugs when visitChildren() changes its mind about what opaque root to add, since
we don't have barriers on opaque roots. This supposedly once worked for generational GC,
and I started adding more barriers to support concurrent GC. But I think that the real
bug here is that we want the JSObject-&gt;OpaqueRoot to be evaluated as a constraint that
participates in the fixpoint. I like to think of this as an *output* constraint, because it
is concerned with outgoing edges in the heap from the object that registered the constraint.
An *input* constraint is like what Weak&lt;&gt; does when deciding whether the thing it points to
should be live.

Whether or not an object has output constraints depends on its type. So, we want the GC to
have a feature where we rapidly call some function on all marked objects of some type.
        
It's easy to rapidly scan all marked objects in a MarkedBlock. So, we want to allocate all
objects that have output constraints in their own MarkedBlocks and we want to track the set
of MarkedBlocks with output constraints.
        
This patch makes it easy to have clients of JSC's internal C++ APIs create a Subspace - like
what we used to call MarkedSpace::Subspace but now it's in the JSC namespace - which is
a collection of objects that you can easily scan during GC from a MarkingConstraint. It's
now possible for internal C++ API clients to register their own MarkingConstraints. The DOM
now uses this to create two Subspaces (more on why two below) and it calls
JSCell::visitOutputConstraints() on all of the marked objects in those subspaces using a new
MarkingConstraint. That MarkingConstraint uses a new style of volatility, called
SeldomGreyed, which is like GreyedByExecution except it is opportunistically not executed
as roots in the hopes that their sole execution will be the snapshot-at-the-end. I also
converted the CodeBlock rescan constraint to SeldomGreyed, since that's also an output
constraint.
        
This patch also uses Subspace for something pretty obvious: knowing how to call the
destructor. Subspaces can specialize the sweep for their way of invoking destructors. We
have the following subspaces:
        
- auxiliary
- cell
- destructibleCell - for JSCell subclasses that have destructors and StructureIsImmortal
- stringSpace - inlines ~JSString into the sweep, making string allocation 7% faster
- destructibleObjectSpace - for JSDestructibleObject subclasses
        
And WebCore adds:
        
- outputConstraint - for JSDOMObjects that have a visitAdditionalChildren
- globalObjectOutputConstraint - for JSDOMGlobalObjects that have a visitAdditionalChildren,
  since JSDOMGlobalObjects are not JSDestructibleObjects
        
The Subspace for a type is selected by saying JSC::subspaceFor&lt;Type&gt;(vm). This calls
Type::subspaceFor&lt;Type&gt;(vm). This allows cell classes to override subspaceFor&lt;&gt; and it
allows any subspaceFor&lt;&gt; implementation to query static flags in the type. This is how
JSCell::subspaceFor&lt;&gt; can select either cellSpace or destructibleCellSpace.
        
This patch is mostly about:
        
- Moving MarkedSpace::Subspace out of MarkedSpace and making it a nice class with a nice
  API. Almost all of its functionality is just taken out of MarkedSpace.
- Converting users of the old API for allocating objects and getting MarkedAllocators, like
  heap.allocatorForObjectWithoutDestructor() and its friends. That would now say
  vm.cellSpace.allocatorFor().
        
Altogether, this means that we only have a small regression on Dromaeo. The regression is
due to the fact that we scan output constraints. Before the Subspace optimizations (see
<a href="http://trac.webkit.org/projects/webkit/changeset/209766">r209766</a>, which was rolled out in <a href="http://trac.webkit.org/projects/webkit/changeset/209812">r209812</a>), this regression on Dromaeo/jslib was 2x but after
the optimizations in this patch it's only 1.12x. Note that Dromaeo/jslib creats gigabytes of
DOM nodes. Compared to web pages, this is a very extreme synthetic microbenchmark. Still, we
like optimizing these because we don't want to presume what web pages will look like.
        
The use of Subspaces to specialize destructors happened not because it's super necessary but
because I wanted to introduce a single unified way of communicating to the GC how to treat
different types. Any Subspace feature that allowed us to collect some types together would
have to be mindful of the destructorness of objects. I could have turned this into a
liability where each Subspace has two subsubspaces - one for destructor objects and one for
non-destructor objects, which would have allowed me to keep the old sweep specialization
code. Just days prior, mlam wanted to do something that was hard because of that old sweep
specializer, so I decided to take the opportunity to fix the sweep specializer while also
making Subspace be the one true way of teaching the GC about types. To validate that this
actually does things, I added a JSStringSubspace and a test that shows that this is a 7%
string allocation progression.
        
In bug 167066, I'm getting rid of the rest of the code in JSC that would special-case for
JSDestructibleObject vs StructureIsImmortal by using the GC's DestructionMode. After that,
Subspace will be only mechanism by which JSC uses the GC to encode types.
        
Prior to this change, having multiple MarkedSpace::Subspaces would have been expensive
because they create a bunch of MarkedAllocators upfront. We now have the ability to create
MarkedAllocators lazily. We create them on the first allocation from that size class or when
a JIT asks for the MarkedAllocator. The concurrent JITs can ask for MarkedAllocators because
their creation is under a lock.
        
On my machine, this might be a 1.1% JetStream speed-up with 87% confidence and it might be
a 0.4% PLT3 slow-down with 92% confidence. Note that 0.4% on PLT3 is the level of systematic
error on PLT3 on my computer: I've seen definite 0.4% speed-ups and slow-downs that were not
confirmed by any bot. Let's see what the bots say.
        
* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/ObjectAllocationProfile.h:
(JSC::ObjectAllocationProfile::initialize):
* bytecode/PolymorphicAccess.cpp:
(JSC::AccessCase::generateImpl):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::emitAllocateRawObject):
(JSC::DFG::SpeculativeJIT::compileMakeRope):
(JSC::DFG::SpeculativeJIT::compileAllocatePropertyStorage):
(JSC::DFG::SpeculativeJIT::compileReallocatePropertyStorage):
(JSC::DFG::SpeculativeJIT::compileNewTypedArray):
(JSC::DFG::SpeculativeJIT::emitAllocateButterfly):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLAbstractHeapRepository.h:
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNewTypedArray):
(JSC::FTL::DFG::LowerDFGToB3::compileMakeRope):
(JSC::FTL::DFG::LowerDFGToB3::compileMaterializeNewObject):
(JSC::FTL::DFG::LowerDFGToB3::allocatePropertyStorageWithSizeImpl):
(JSC::FTL::DFG::LowerDFGToB3::allocateObject):
(JSC::FTL::DFG::LowerDFGToB3::allocatorForSize):
(JSC::FTL::DFG::LowerDFGToB3::allocateVariableSizedObject):
(JSC::FTL::DFG::LowerDFGToB3::allocateVariableSizedCell):
(JSC::FTL::DFG::LowerDFGToB3::allocateJSArray):
* heap/AllocatorAttributes.h:
(JSC::AllocatorAttributes::AllocatorAttributes):
* heap/ConstraintVolatility.h: Added.
(WTF::printInternal):
* heap/GCActivityCallback.cpp:
* heap/Heap.cpp:
(JSC::Heap::Heap):
(JSC::Heap::lastChanceToFinalize):
(JSC::Heap::markToFixpoint):
(JSC::Heap::updateObjectCounts):
(JSC::Heap::collectAllGarbage):
(JSC::Heap::collectInThread):
(JSC::Heap::stopTheWorld):
(JSC::Heap::updateAllocationLimits):
(JSC::Heap::bytesVisited):
(JSC::Heap::addCoreConstraints):
(JSC::Heap::addMarkingConstraint):
(JSC::Heap::notifyIsSafeToCollect):
(JSC::Heap::preventCollection):
(JSC::Heap::allowCollection):
(JSC::Heap::setMutatorShouldBeFenced):
(JSC::Heap::buildConstraintSet): Deleted.
(JSC::Heap::writeBarrierOpaqueRootSlow): Deleted.
(JSC::Heap::addMutatorShouldBeFencedCache): Deleted.
* heap/Heap.h:
(JSC::Heap::mutatorExecutionVersion):
(JSC::Heap::numOpaqueRoots):
(JSC::Heap::vm): Deleted.
(JSC::Heap::subspaceForObjectWithoutDestructor): Deleted.
(JSC::Heap::subspaceForObjectDestructor): Deleted.
(JSC::Heap::subspaceForAuxiliaryData): Deleted.
(JSC::Heap::allocatorForObjectWithoutDestructor): Deleted.
(JSC::Heap::allocatorForObjectWithDestructor): Deleted.
(JSC::Heap::allocatorForAuxiliaryData): Deleted.
* heap/HeapInlines.h:
(JSC::Heap::vm):
(JSC::Heap::allocateWithDestructor): Deleted.
(JSC::Heap::allocateWithoutDestructor): Deleted.
(JSC::Heap::allocateObjectOfType): Deleted.
(JSC::Heap::subspaceForObjectOfType): Deleted.
(JSC::Heap::allocatorForObjectOfType): Deleted.
(JSC::Heap::allocateAuxiliary): Deleted.
(JSC::Heap::tryAllocateAuxiliary): Deleted.
(JSC::Heap::tryReallocateAuxiliary): Deleted.
(JSC::Heap::ascribeOwner): Deleted.
(JSC::Heap::writeBarrierOpaqueRoot): Deleted.
* heap/LargeAllocation.cpp:
(JSC::LargeAllocation::tryCreate):
(JSC::LargeAllocation::LargeAllocation):
(JSC::LargeAllocation::~LargeAllocation):
(JSC::LargeAllocation::sweep):
* heap/LargeAllocation.h:
* heap/MarkedAllocator.cpp:
(JSC::MarkedAllocator::MarkedAllocator):
(JSC::MarkedAllocator::tryAllocateWithoutCollecting):
(JSC::MarkedAllocator::tryAllocateIn):
(JSC::MarkedAllocator::allocateSlowCaseImpl):
(JSC::MarkedAllocator::tryAllocateBlock):
(JSC::MarkedAllocator::shrink):
(JSC::MarkedAllocator::markedSpace):
* heap/MarkedAllocator.h:
(JSC::MarkedAllocator::nextAllocatorInSubspace):
(JSC::MarkedAllocator::setNextAllocatorInSubspace):
(JSC::MarkedAllocator::subspace):
(JSC::MarkedAllocator::tryAllocate): Deleted.
(JSC::MarkedAllocator::allocate): Deleted.
(JSC::MarkedAllocator::forEachBlock): Deleted.
* heap/MarkedAllocatorInlines.h: Added.
(JSC::MarkedAllocator::tryAllocate):
(JSC::MarkedAllocator::allocate):
(JSC::MarkedAllocator::forEachBlock):
(JSC::MarkedAllocator::forEachNotEmptyBlock):
* heap/MarkedBlock.cpp:
(JSC::MarkedBlock::Handle::subspace):
(JSC::MarkedBlock::Handle::sweep):
(JSC::MarkedBlock::Handle::specializedSweep): Deleted.
(JSC::MarkedBlock::Handle::sweepHelperSelectScribbleMode): Deleted.
(JSC::MarkedBlock::Handle::sweepHelperSelectEmptyMode): Deleted.
(JSC::MarkedBlock::Handle::sweepHelperSelectHasNewlyAllocated): Deleted.
(JSC::MarkedBlock::Handle::sweepHelperSelectSweepMode): Deleted.
(JSC::MarkedBlock::Handle::sweepHelperSelectMarksMode): Deleted.
* heap/MarkedBlock.h:
(JSC::MarkedBlock::Handle::visitWeakSet):
* heap/MarkedBlockInlines.h:
(JSC::MarkedBlock::Handle::isNewlyAllocatedStale):
(JSC::MarkedBlock::Handle::hasAnyNewlyAllocated):
(JSC::MarkedBlock::heap):
(JSC::MarkedBlock::space):
(JSC::MarkedBlock::Handle::space):
(JSC::MarkedBlock::Handle::specializedSweep):
(JSC::MarkedBlock::Handle::finishSweepKnowingSubspace):
(JSC::MarkedBlock::Handle::sweepDestructionMode):
(JSC::MarkedBlock::Handle::emptyMode):
(JSC::MarkedBlock::Handle::scribbleMode):
(JSC::MarkedBlock::Handle::newlyAllocatedMode):
(JSC::MarkedBlock::Handle::marksMode):
(JSC::MarkedBlock::Handle::forEachMarkedCell):
* heap/MarkedSpace.cpp:
(JSC::MarkedSpace::initializeSizeClassForStepSize):
(JSC::MarkedSpace::MarkedSpace):
(JSC::MarkedSpace::lastChanceToFinalize):
(JSC::MarkedSpace::addMarkedAllocator):
(JSC::MarkedSpace::allocate): Deleted.
(JSC::MarkedSpace::tryAllocate): Deleted.
(JSC::MarkedSpace::allocateLarge): Deleted.
(JSC::MarkedSpace::tryAllocateLarge): Deleted.
* heap/MarkedSpace.h:
(JSC::MarkedSpace::heap):
(JSC::MarkedSpace::allocatorLock):
(JSC::MarkedSpace::subspaceForObjectsWithDestructor): Deleted.
(JSC::MarkedSpace::subspaceForObjectsWithoutDestructor): Deleted.
(JSC::MarkedSpace::subspaceForAuxiliaryData): Deleted.
(JSC::MarkedSpace::allocatorFor): Deleted.
(JSC::MarkedSpace::destructorAllocatorFor): Deleted.
(JSC::MarkedSpace::auxiliaryAllocatorFor): Deleted.
(JSC::MarkedSpace::allocateWithoutDestructor): Deleted.
(JSC::MarkedSpace::allocateWithDestructor): Deleted.
(JSC::MarkedSpace::allocateAuxiliary): Deleted.
(JSC::MarkedSpace::tryAllocateAuxiliary): Deleted.
(JSC::MarkedSpace::forEachSubspace): Deleted.
* heap/MarkingConstraint.cpp:
(JSC::MarkingConstraint::MarkingConstraint):
* heap/MarkingConstraint.h:
(JSC::MarkingConstraint::volatility):
* heap/MarkingConstraintSet.cpp:
(JSC::MarkingConstraintSet::resetStats):
(JSC::MarkingConstraintSet::add):
(JSC::MarkingConstraintSet::executeConvergenceImpl):
* heap/MarkingConstraintSet.h:
* heap/SlotVisitor.cpp:
(JSC::SlotVisitor::visitChildren):
(JSC::SlotVisitor::visitAsConstraint):
(JSC::SlotVisitor::drain):
(JSC::SlotVisitor::addOpaqueRoot):
(JSC::SlotVisitor::mergeIfNecessary):
(JSC::SlotVisitor::mergeOpaqueRootsIfNecessary): Deleted.
* heap/SlotVisitor.h:
(JSC::SlotVisitor::setIgnoreNewOpaqueRoots):
* heap/SlotVisitorInlines.h:
(JSC::SlotVisitor::reportExtraMemoryVisited):
(JSC::SlotVisitor::reportExternalMemoryVisited):
* heap/Subspace.cpp: Added.
(JSC::Subspace::Subspace):
(JSC::Subspace::~Subspace):
(JSC::Subspace::finishSweep):
(JSC::Subspace::destroy):
(JSC::Subspace::allocate):
(JSC::Subspace::tryAllocate):
(JSC::Subspace::allocatorForSlow):
(JSC::Subspace::allocateSlow):
(JSC::Subspace::tryAllocateSlow):
* heap/Subspace.h: Added.
(JSC::Subspace::tryAllocatorFor):
(JSC::Subspace::allocatorFor):
* heap/SubspaceInlines.h: Added.
(JSC::Subspace::forEachMarkedBlock):
(JSC::Subspace::forEachNotEmptyMarkedBlock):
(JSC::Subspace::forEachLargeAllocation):
(JSC::Subspace::forEachMarkedCell):
* heap/WeakBlock.cpp:
(JSC::WeakBlock::specializedVisit):
* heap/WeakBlock.h:
* heap/WeakSet.h:
(JSC::WeakSet::visit):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::emitAllocateJSObjectWithKnownSize):
(JSC::AssemblyHelpers::emitAllocateVariableSized):
(JSC::AssemblyHelpers::emitAllocateVariableSizedCell):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_new_object):
* jsc.cpp:
* runtime/ButterflyInlines.h:
(JSC::Butterfly::createUninitialized):
(JSC::Butterfly::growArrayRight):
* runtime/ClassInfo.h:
* runtime/ClonedArguments.cpp:
(JSC::ClonedArguments::createEmpty):
* runtime/DirectArguments.cpp:
(JSC::DirectArguments::overrideThings):
* runtime/GenericArgumentsInlines.h:
(JSC::GenericArguments&lt;Type&gt;::initModifiedArgumentsDescriptor):
* runtime/HashMapImpl.h:
(JSC::HashMapBuffer::create):
* runtime/JSArray.cpp:
(JSC::JSArray::tryCreateUninitialized):
(JSC::JSArray::unshiftCountSlowCase):
* runtime/JSArrayBufferView.cpp:
(JSC::JSArrayBufferView::ConstructionContext::ConstructionContext):
* runtime/JSCell.h:
(JSC::subspaceFor):
* runtime/JSCellInlines.h:
(JSC::JSCell::visitOutputConstraints):
(JSC::JSCell::subspaceFor):
(JSC::allocateCell):
* runtime/JSDestructibleObject.h:
(JSC::JSDestructibleObject::subspaceFor):
* runtime/JSDestructibleObjectSubspace.cpp: Added.
(JSC::JSDestructibleObjectSubspace::JSDestructibleObjectSubspace):
(JSC::JSDestructibleObjectSubspace::~JSDestructibleObjectSubspace):
(JSC::JSDestructibleObjectSubspace::finishSweep):
(JSC::JSDestructibleObjectSubspace::destroy):
* runtime/JSDestructibleObjectSubspace.h: Added.
* runtime/JSObject.h:
(JSC::JSObject::JSObject):
* runtime/JSObjectInlines.h:
* runtime/JSSegmentedVariableObject.h:
* runtime/JSString.h:
(JSC::JSString::subspaceFor):
* runtime/JSStringSubspace.cpp: Added.
(JSC::JSStringSubspace::JSStringSubspace):
(JSC::JSStringSubspace::~JSStringSubspace):
(JSC::JSStringSubspace::finishSweep):
(JSC::JSStringSubspace::destroy):
* runtime/JSStringSubspace.h: Added.
* runtime/RegExpMatchesArray.h:
(JSC::tryCreateUninitializedRegExpMatchesArray):
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:

Source/WebCore:


No new tests yet. I think that writing tests for this is a big investigation:
https://bugs.webkit.org/show_bug.cgi?id=165808
        
Remove the previous advancing wavefront DOM write barrier. I don't think this will scale
very well. It's super confusing.
        
This change makes it so that visitAdditionalChildren can become a GC constraint that
executes as part of the fixpoint. This changes all WebCore visitAdditionalChildren into
output constraints by using new JSC API for Subspaces and MarkingConstraints.

* ForwardingHeaders/heap/MarkedAllocatorInlines.h: Added.
* ForwardingHeaders/heap/MarkedBlockInlines.h: Added.
* ForwardingHeaders/heap/MarkingConstraint.h: Added.
* ForwardingHeaders/heap/SubspaceInlines.h: Added.
* ForwardingHeaders/heap/VisitingTimeout.h: Added.
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/CommonVM.cpp:
(WebCore::commonVMSlow):
(WebCore::writeBarrierOpaqueRootSlow): Deleted.
* bindings/js/CommonVM.h:
(WebCore::writeBarrierOpaqueRoot): Deleted.
* bindings/js/JSDOMGlobalObject.cpp:
(WebCore::JSDOMGlobalObject::finishCreation):
(WebCore::JSDOMGlobalObject::scriptExecutionContext):
* bindings/js/JSDOMWrapper.cpp:
(WebCore::outputConstraintSubspaceFor):
(WebCore::globalObjectOutputConstraintSubspaceFor):
* bindings/js/JSDOMWrapper.h:
* bindings/js/WebCoreJSClientData.cpp: Added.
(WebCore::JSVMClientData::JSVMClientData):
(WebCore::JSVMClientData::~JSVMClientData):
(WebCore::JSVMClientData::getAllWorlds):
(WebCore::initNormalWorldClientData):
* bindings/js/WebCoreJSClientData.h:
(WebCore::JSVMClientData::outputConstraintSpace):
(WebCore::JSVMClientData::globalObjectOutputConstraintSpace):
(WebCore::JSVMClientData::forEachOutputConstraintSpace):
(WebCore::JSVMClientData::JSVMClientData): Deleted.
(WebCore::JSVMClientData::~JSVMClientData): Deleted.
(WebCore::JSVMClientData::getAllWorlds): Deleted.
(WebCore::initNormalWorldClientData): Deleted.
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateHeader):
(GenerateImplementation):
* dom/ContainerNodeAlgorithms.cpp:
(WebCore::notifyChildNodeInserted):
(WebCore::notifyChildNodeRemoved):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeObjectAllocationProfileh">trunk/Source/JavaScriptCore/bytecode/ObjectAllocationProfile.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePolymorphicAccesscpp">trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh">trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapAllocatorAttributesh">trunk/Source/JavaScriptCore/heap/AllocatorAttributes.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapGCActivityCallbackcpp">trunk/Source/JavaScriptCore/heap/GCActivityCallback.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapcpp">trunk/Source/JavaScriptCore/heap/Heap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeaph">trunk/Source/JavaScriptCore/heap/Heap.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapInlinesh">trunk/Source/JavaScriptCore/heap/HeapInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapLargeAllocationcpp">trunk/Source/JavaScriptCore/heap/LargeAllocation.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapLargeAllocationh">trunk/Source/JavaScriptCore/heap/LargeAllocation.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedAllocatorcpp">trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedAllocatorh">trunk/Source/JavaScriptCore/heap/MarkedAllocator.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedBlockcpp">trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedBlockh">trunk/Source/JavaScriptCore/heap/MarkedBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedBlockInlinesh">trunk/Source/JavaScriptCore/heap/MarkedBlockInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedSpacecpp">trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedSpaceh">trunk/Source/JavaScriptCore/heap/MarkedSpace.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkingConstraintcpp">trunk/Source/JavaScriptCore/heap/MarkingConstraint.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkingConstrainth">trunk/Source/JavaScriptCore/heap/MarkingConstraint.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkingConstraintSetcpp">trunk/Source/JavaScriptCore/heap/MarkingConstraintSet.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkingConstraintSeth">trunk/Source/JavaScriptCore/heap/MarkingConstraintSet.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSlotVisitorcpp">trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSlotVisitorh">trunk/Source/JavaScriptCore/heap/SlotVisitor.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSlotVisitorInlinesh">trunk/Source/JavaScriptCore/heap/SlotVisitorInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapWeakBlockcpp">trunk/Source/JavaScriptCore/heap/WeakBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapWeakBlockh">trunk/Source/JavaScriptCore/heap/WeakBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapWeakSeth">trunk/Source/JavaScriptCore/heap/WeakSet.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAssemblyHelpersh">trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodescpp">trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodes32_64cpp">trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeButterflyInlinesh">trunk/Source/JavaScriptCore/runtime/ButterflyInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeClassInfoh">trunk/Source/JavaScriptCore/runtime/ClassInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeClonedArgumentscpp">trunk/Source/JavaScriptCore/runtime/ClonedArguments.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeDirectArgumentscpp">trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeGenericArgumentsInlinesh">trunk/Source/JavaScriptCore/runtime/GenericArgumentsInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeHashMapImplh">trunk/Source/JavaScriptCore/runtime/HashMapImpl.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSArraycpp">trunk/Source/JavaScriptCore/runtime/JSArray.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSArrayBufferViewcpp">trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCellh">trunk/Source/JavaScriptCore/runtime/JSCell.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCellInlinesh">trunk/Source/JavaScriptCore/runtime/JSCellInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSDestructibleObjecth">trunk/Source/JavaScriptCore/runtime/JSDestructibleObject.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSObjecth">trunk/Source/JavaScriptCore/runtime/JSObject.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSObjectInlinesh">trunk/Source/JavaScriptCore/runtime/JSObjectInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSSegmentedVariableObjecth">trunk/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSStringh">trunk/Source/JavaScriptCore/runtime/JSString.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpMatchesArrayh">trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMcpp">trunk/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorebindingsjsCommonVMcpp">trunk/Source/WebCore/bindings/js/CommonVM.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsCommonVMh">trunk/Source/WebCore/bindings/js/CommonVM.h</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMGlobalObjectcpp">trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMWrappercpp">trunk/Source/WebCore/bindings/js/JSDOMWrapper.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMWrapperh">trunk/Source/WebCore/bindings/js/JSDOMWrapper.h</a></li>
<li><a href="#trunkSourceWebCorebindingsjsWebCoreJSClientDatah">trunk/Source/WebCore/bindings/js/WebCoreJSClientData.h</a></li>
<li><a href="#trunkSourceWebCorebindingsjsWorkerScriptControllercpp">trunk/Source/WebCore/bindings/js/WorkerScriptController.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptsCodeGeneratorJSpm">trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm</a></li>
<li><a href="#trunkSourceWebCoredomContainerNodeAlgorithmscpp">trunk/Source/WebCore/dom/ContainerNodeAlgorithms.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsmicrobenchmarksstringallocjs">trunk/JSTests/microbenchmarks/stringalloc.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapConstraintVolatilityh">trunk/Source/JavaScriptCore/heap/ConstraintVolatility.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedAllocatorInlinesh">trunk/Source/JavaScriptCore/heap/MarkedAllocatorInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSubspacecpp">trunk/Source/JavaScriptCore/heap/Subspace.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSubspaceh">trunk/Source/JavaScriptCore/heap/Subspace.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSubspaceInlinesh">trunk/Source/JavaScriptCore/heap/SubspaceInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSDestructibleObjectSubspacecpp">trunk/Source/JavaScriptCore/runtime/JSDestructibleObjectSubspace.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSDestructibleObjectSubspaceh">trunk/Source/JavaScriptCore/runtime/JSDestructibleObjectSubspace.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSStringSubspacecpp">trunk/Source/JavaScriptCore/runtime/JSStringSubspace.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSStringSubspaceh">trunk/Source/JavaScriptCore/runtime/JSStringSubspace.h</a></li>
<li><a href="#trunkSourceWebCoreForwardingHeadersheapMarkedAllocatorInlinesh">trunk/Source/WebCore/ForwardingHeaders/heap/MarkedAllocatorInlines.h</a></li>
<li><a href="#trunkSourceWebCoreForwardingHeadersheapMarkedBlockInlinesh">trunk/Source/WebCore/ForwardingHeaders/heap/MarkedBlockInlines.h</a></li>
<li><a href="#trunkSourceWebCoreForwardingHeadersheapMarkingConstrainth">trunk/Source/WebCore/ForwardingHeaders/heap/MarkingConstraint.h</a></li>
<li><a href="#trunkSourceWebCoreForwardingHeadersheapSubspaceInlinesh">trunk/Source/WebCore/ForwardingHeaders/heap/SubspaceInlines.h</a></li>
<li><a href="#trunkSourceWebCoreForwardingHeadersheapVisitingTimeouth">trunk/Source/WebCore/ForwardingHeaders/heap/VisitingTimeout.h</a></li>
<li><a href="#trunkSourceWebCorebindingsjsWebCoreJSClientDatacpp">trunk/Source/WebCore/bindings/js/WebCoreJSClientData.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/JSTests/ChangeLog        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2017-01-16  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Make opaque root scanning truly constraint-based
+        https://bugs.webkit.org/show_bug.cgi?id=165760
+
+        Reviewed by Geoffrey Garen.
+        
+        Added this test, which demonstrates the benefit of having a dedicated string subspace.
+
+        * microbenchmarks/stringalloc.js: Added.
+
</ins><span class="cx"> 2017-01-17  Michael Saboff  &lt;msaboff@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Nested parenthesized regular expressions with non-zero minimum counts appear to hang and use lots of memory
</span></span></pre></div>
<a id="trunkJSTestsmicrobenchmarksstringallocjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/stringalloc.js (0 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/stringalloc.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/stringalloc.js        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+var global;
+var array = [&quot;a&quot;, &quot;b&quot;];
+for (var i = 0; i &lt; 10000000; ++i)
+    global = array[i &amp; 1] + &quot;c&quot;;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -504,6 +504,7 @@
</span><span class="cx">     heap/SlotVisitor.cpp
</span><span class="cx">     heap/SpaceTimeMutatorScheduler.cpp
</span><span class="cx">     heap/StopIfNecessaryTimer.cpp
</span><ins>+    heap/Subspace.cpp
</ins><span class="cx">     heap/SynchronousStopTheWorldMutatorScheduler.cpp
</span><span class="cx">     heap/VisitRaceKey.cpp
</span><span class="cx">     heap/Weak.cpp
</span><span class="lines">@@ -752,6 +753,7 @@
</span><span class="cx">     runtime/JSDataView.cpp
</span><span class="cx">     runtime/JSDataViewPrototype.cpp
</span><span class="cx">     runtime/JSDateMath.cpp
</span><ins>+    runtime/JSDestructibleObjectSubspace.cpp
</ins><span class="cx">     runtime/JSEnvironmentRecord.cpp
</span><span class="cx">     runtime/JSFixedArray.cpp
</span><span class="cx">     runtime/JSFunction.cpp
</span><span class="lines">@@ -792,6 +794,7 @@
</span><span class="cx">     runtime/JSString.cpp
</span><span class="cx">     runtime/JSStringIterator.cpp
</span><span class="cx">     runtime/JSStringJoiner.cpp
</span><ins>+    runtime/JSStringSubspace.cpp
</ins><span class="cx">     runtime/JSSymbolTableObject.cpp
</span><span class="cx">     runtime/JSTemplateRegistryKey.cpp
</span><span class="cx">     runtime/JSTypedArrayConstructors.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,3 +1,347 @@
</span><ins>+2017-01-16  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Make opaque root scanning truly constraint-based
+        https://bugs.webkit.org/show_bug.cgi?id=165760
+
+        Reviewed by Geoffrey Garen.
+
+        We have bugs when visitChildren() changes its mind about what opaque root to add, since
+        we don't have barriers on opaque roots. This supposedly once worked for generational GC,
+        and I started adding more barriers to support concurrent GC. But I think that the real
+        bug here is that we want the JSObject-&gt;OpaqueRoot to be evaluated as a constraint that
+        participates in the fixpoint. I like to think of this as an *output* constraint, because it
+        is concerned with outgoing edges in the heap from the object that registered the constraint.
+        An *input* constraint is like what Weak&lt;&gt; does when deciding whether the thing it points to
+        should be live.
+
+        Whether or not an object has output constraints depends on its type. So, we want the GC to
+        have a feature where we rapidly call some function on all marked objects of some type.
+        
+        It's easy to rapidly scan all marked objects in a MarkedBlock. So, we want to allocate all
+        objects that have output constraints in their own MarkedBlocks and we want to track the set
+        of MarkedBlocks with output constraints.
+        
+        This patch makes it easy to have clients of JSC's internal C++ APIs create a Subspace - like
+        what we used to call MarkedSpace::Subspace but now it's in the JSC namespace - which is
+        a collection of objects that you can easily scan during GC from a MarkingConstraint. It's
+        now possible for internal C++ API clients to register their own MarkingConstraints. The DOM
+        now uses this to create two Subspaces (more on why two below) and it calls
+        JSCell::visitOutputConstraints() on all of the marked objects in those subspaces using a new
+        MarkingConstraint. That MarkingConstraint uses a new style of volatility, called
+        SeldomGreyed, which is like GreyedByExecution except it is opportunistically not executed
+        as roots in the hopes that their sole execution will be the snapshot-at-the-end. I also
+        converted the CodeBlock rescan constraint to SeldomGreyed, since that's also an output
+        constraint.
+        
+        This patch also uses Subspace for something pretty obvious: knowing how to call the
+        destructor. Subspaces can specialize the sweep for their way of invoking destructors. We
+        have the following subspaces:
+        
+        - auxiliary
+        - cell
+        - destructibleCell - for JSCell subclasses that have destructors and StructureIsImmortal
+        - stringSpace - inlines ~JSString into the sweep, making string allocation 7% faster
+        - destructibleObjectSpace - for JSDestructibleObject subclasses
+        
+        And WebCore adds:
+        
+        - outputConstraint - for JSDOMObjects that have a visitAdditionalChildren
+        - globalObjectOutputConstraint - for JSDOMGlobalObjects that have a visitAdditionalChildren,
+          since JSDOMGlobalObjects are not JSDestructibleObjects
+        
+        The Subspace for a type is selected by saying JSC::subspaceFor&lt;Type&gt;(vm). This calls
+        Type::subspaceFor&lt;Type&gt;(vm). This allows cell classes to override subspaceFor&lt;&gt; and it
+        allows any subspaceFor&lt;&gt; implementation to query static flags in the type. This is how
+        JSCell::subspaceFor&lt;&gt; can select either cellSpace or destructibleCellSpace.
+        
+        This patch is mostly about:
+        
+        - Moving MarkedSpace::Subspace out of MarkedSpace and making it a nice class with a nice
+          API. Almost all of its functionality is just taken out of MarkedSpace.
+        - Converting users of the old API for allocating objects and getting MarkedAllocators, like
+          heap.allocatorForObjectWithoutDestructor() and its friends. That would now say
+          vm.cellSpace.allocatorFor().
+        
+        Altogether, this means that we only have a small regression on Dromaeo. The regression is
+        due to the fact that we scan output constraints. Before the Subspace optimizations (see
+        r209766, which was rolled out in r209812), this regression on Dromaeo/jslib was 2x but after
+        the optimizations in this patch it's only 1.12x. Note that Dromaeo/jslib creats gigabytes of
+        DOM nodes. Compared to web pages, this is a very extreme synthetic microbenchmark. Still, we
+        like optimizing these because we don't want to presume what web pages will look like.
+        
+        The use of Subspaces to specialize destructors happened not because it's super necessary but
+        because I wanted to introduce a single unified way of communicating to the GC how to treat
+        different types. Any Subspace feature that allowed us to collect some types together would
+        have to be mindful of the destructorness of objects. I could have turned this into a
+        liability where each Subspace has two subsubspaces - one for destructor objects and one for
+        non-destructor objects, which would have allowed me to keep the old sweep specialization
+        code. Just days prior, mlam wanted to do something that was hard because of that old sweep
+        specializer, so I decided to take the opportunity to fix the sweep specializer while also
+        making Subspace be the one true way of teaching the GC about types. To validate that this
+        actually does things, I added a JSStringSubspace and a test that shows that this is a 7%
+        string allocation progression.
+        
+        In bug 167066, I'm getting rid of the rest of the code in JSC that would special-case for
+        JSDestructibleObject vs StructureIsImmortal by using the GC's DestructionMode. After that,
+        Subspace will be only mechanism by which JSC uses the GC to encode types.
+        
+        Prior to this change, having multiple MarkedSpace::Subspaces would have been expensive
+        because they create a bunch of MarkedAllocators upfront. We now have the ability to create
+        MarkedAllocators lazily. We create them on the first allocation from that size class or when
+        a JIT asks for the MarkedAllocator. The concurrent JITs can ask for MarkedAllocators because
+        their creation is under a lock.
+        
+        On my machine, this might be a 1.1% JetStream speed-up with 87% confidence and it might be
+        a 0.4% PLT3 slow-down with 92% confidence. Note that 0.4% on PLT3 is the level of systematic
+        error on PLT3 on my computer: I've seen definite 0.4% speed-ups and slow-downs that were not
+        confirmed by any bot. Let's see what the bots say.
+        
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/ObjectAllocationProfile.h:
+        (JSC::ObjectAllocationProfile::initialize):
+        * bytecode/PolymorphicAccess.cpp:
+        (JSC::AccessCase::generateImpl):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::emitAllocateRawObject):
+        (JSC::DFG::SpeculativeJIT::compileMakeRope):
+        (JSC::DFG::SpeculativeJIT::compileAllocatePropertyStorage):
+        (JSC::DFG::SpeculativeJIT::compileReallocatePropertyStorage):
+        (JSC::DFG::SpeculativeJIT::compileNewTypedArray):
+        (JSC::DFG::SpeculativeJIT::emitAllocateButterfly):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLAbstractHeapRepository.h:
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewTypedArray):
+        (JSC::FTL::DFG::LowerDFGToB3::compileMakeRope):
+        (JSC::FTL::DFG::LowerDFGToB3::compileMaterializeNewObject):
+        (JSC::FTL::DFG::LowerDFGToB3::allocatePropertyStorageWithSizeImpl):
+        (JSC::FTL::DFG::LowerDFGToB3::allocateObject):
+        (JSC::FTL::DFG::LowerDFGToB3::allocatorForSize):
+        (JSC::FTL::DFG::LowerDFGToB3::allocateVariableSizedObject):
+        (JSC::FTL::DFG::LowerDFGToB3::allocateVariableSizedCell):
+        (JSC::FTL::DFG::LowerDFGToB3::allocateJSArray):
+        * heap/AllocatorAttributes.h:
+        (JSC::AllocatorAttributes::AllocatorAttributes):
+        * heap/ConstraintVolatility.h: Added.
+        (WTF::printInternal):
+        * heap/GCActivityCallback.cpp:
+        * heap/Heap.cpp:
+        (JSC::Heap::Heap):
+        (JSC::Heap::lastChanceToFinalize):
+        (JSC::Heap::markToFixpoint):
+        (JSC::Heap::updateObjectCounts):
+        (JSC::Heap::collectAllGarbage):
+        (JSC::Heap::collectInThread):
+        (JSC::Heap::stopTheWorld):
+        (JSC::Heap::updateAllocationLimits):
+        (JSC::Heap::bytesVisited):
+        (JSC::Heap::addCoreConstraints):
+        (JSC::Heap::addMarkingConstraint):
+        (JSC::Heap::notifyIsSafeToCollect):
+        (JSC::Heap::preventCollection):
+        (JSC::Heap::allowCollection):
+        (JSC::Heap::setMutatorShouldBeFenced):
+        (JSC::Heap::buildConstraintSet): Deleted.
+        (JSC::Heap::writeBarrierOpaqueRootSlow): Deleted.
+        (JSC::Heap::addMutatorShouldBeFencedCache): Deleted.
+        * heap/Heap.h:
+        (JSC::Heap::mutatorExecutionVersion):
+        (JSC::Heap::numOpaqueRoots):
+        (JSC::Heap::vm): Deleted.
+        (JSC::Heap::subspaceForObjectWithoutDestructor): Deleted.
+        (JSC::Heap::subspaceForObjectDestructor): Deleted.
+        (JSC::Heap::subspaceForAuxiliaryData): Deleted.
+        (JSC::Heap::allocatorForObjectWithoutDestructor): Deleted.
+        (JSC::Heap::allocatorForObjectWithDestructor): Deleted.
+        (JSC::Heap::allocatorForAuxiliaryData): Deleted.
+        * heap/HeapInlines.h:
+        (JSC::Heap::vm):
+        (JSC::Heap::allocateWithDestructor): Deleted.
+        (JSC::Heap::allocateWithoutDestructor): Deleted.
+        (JSC::Heap::allocateObjectOfType): Deleted.
+        (JSC::Heap::subspaceForObjectOfType): Deleted.
+        (JSC::Heap::allocatorForObjectOfType): Deleted.
+        (JSC::Heap::allocateAuxiliary): Deleted.
+        (JSC::Heap::tryAllocateAuxiliary): Deleted.
+        (JSC::Heap::tryReallocateAuxiliary): Deleted.
+        (JSC::Heap::ascribeOwner): Deleted.
+        (JSC::Heap::writeBarrierOpaqueRoot): Deleted.
+        * heap/LargeAllocation.cpp:
+        (JSC::LargeAllocation::tryCreate):
+        (JSC::LargeAllocation::LargeAllocation):
+        (JSC::LargeAllocation::~LargeAllocation):
+        (JSC::LargeAllocation::sweep):
+        * heap/LargeAllocation.h:
+        * heap/MarkedAllocator.cpp:
+        (JSC::MarkedAllocator::MarkedAllocator):
+        (JSC::MarkedAllocator::tryAllocateWithoutCollecting):
+        (JSC::MarkedAllocator::tryAllocateIn):
+        (JSC::MarkedAllocator::allocateSlowCaseImpl):
+        (JSC::MarkedAllocator::tryAllocateBlock):
+        (JSC::MarkedAllocator::shrink):
+        (JSC::MarkedAllocator::markedSpace):
+        * heap/MarkedAllocator.h:
+        (JSC::MarkedAllocator::nextAllocatorInSubspace):
+        (JSC::MarkedAllocator::setNextAllocatorInSubspace):
+        (JSC::MarkedAllocator::subspace):
+        (JSC::MarkedAllocator::tryAllocate): Deleted.
+        (JSC::MarkedAllocator::allocate): Deleted.
+        (JSC::MarkedAllocator::forEachBlock): Deleted.
+        * heap/MarkedAllocatorInlines.h: Added.
+        (JSC::MarkedAllocator::tryAllocate):
+        (JSC::MarkedAllocator::allocate):
+        (JSC::MarkedAllocator::forEachBlock):
+        (JSC::MarkedAllocator::forEachNotEmptyBlock):
+        * heap/MarkedBlock.cpp:
+        (JSC::MarkedBlock::Handle::subspace):
+        (JSC::MarkedBlock::Handle::sweep):
+        (JSC::MarkedBlock::Handle::specializedSweep): Deleted.
+        (JSC::MarkedBlock::Handle::sweepHelperSelectScribbleMode): Deleted.
+        (JSC::MarkedBlock::Handle::sweepHelperSelectEmptyMode): Deleted.
+        (JSC::MarkedBlock::Handle::sweepHelperSelectHasNewlyAllocated): Deleted.
+        (JSC::MarkedBlock::Handle::sweepHelperSelectSweepMode): Deleted.
+        (JSC::MarkedBlock::Handle::sweepHelperSelectMarksMode): Deleted.
+        * heap/MarkedBlock.h:
+        (JSC::MarkedBlock::Handle::visitWeakSet):
+        * heap/MarkedBlockInlines.h:
+        (JSC::MarkedBlock::Handle::isNewlyAllocatedStale):
+        (JSC::MarkedBlock::Handle::hasAnyNewlyAllocated):
+        (JSC::MarkedBlock::heap):
+        (JSC::MarkedBlock::space):
+        (JSC::MarkedBlock::Handle::space):
+        (JSC::MarkedBlock::Handle::specializedSweep):
+        (JSC::MarkedBlock::Handle::finishSweepKnowingSubspace):
+        (JSC::MarkedBlock::Handle::sweepDestructionMode):
+        (JSC::MarkedBlock::Handle::emptyMode):
+        (JSC::MarkedBlock::Handle::scribbleMode):
+        (JSC::MarkedBlock::Handle::newlyAllocatedMode):
+        (JSC::MarkedBlock::Handle::marksMode):
+        (JSC::MarkedBlock::Handle::forEachMarkedCell):
+        * heap/MarkedSpace.cpp:
+        (JSC::MarkedSpace::initializeSizeClassForStepSize):
+        (JSC::MarkedSpace::MarkedSpace):
+        (JSC::MarkedSpace::lastChanceToFinalize):
+        (JSC::MarkedSpace::addMarkedAllocator):
+        (JSC::MarkedSpace::allocate): Deleted.
+        (JSC::MarkedSpace::tryAllocate): Deleted.
+        (JSC::MarkedSpace::allocateLarge): Deleted.
+        (JSC::MarkedSpace::tryAllocateLarge): Deleted.
+        * heap/MarkedSpace.h:
+        (JSC::MarkedSpace::heap):
+        (JSC::MarkedSpace::allocatorLock):
+        (JSC::MarkedSpace::subspaceForObjectsWithDestructor): Deleted.
+        (JSC::MarkedSpace::subspaceForObjectsWithoutDestructor): Deleted.
+        (JSC::MarkedSpace::subspaceForAuxiliaryData): Deleted.
+        (JSC::MarkedSpace::allocatorFor): Deleted.
+        (JSC::MarkedSpace::destructorAllocatorFor): Deleted.
+        (JSC::MarkedSpace::auxiliaryAllocatorFor): Deleted.
+        (JSC::MarkedSpace::allocateWithoutDestructor): Deleted.
+        (JSC::MarkedSpace::allocateWithDestructor): Deleted.
+        (JSC::MarkedSpace::allocateAuxiliary): Deleted.
+        (JSC::MarkedSpace::tryAllocateAuxiliary): Deleted.
+        (JSC::MarkedSpace::forEachSubspace): Deleted.
+        * heap/MarkingConstraint.cpp:
+        (JSC::MarkingConstraint::MarkingConstraint):
+        * heap/MarkingConstraint.h:
+        (JSC::MarkingConstraint::volatility):
+        * heap/MarkingConstraintSet.cpp:
+        (JSC::MarkingConstraintSet::resetStats):
+        (JSC::MarkingConstraintSet::add):
+        (JSC::MarkingConstraintSet::executeConvergenceImpl):
+        * heap/MarkingConstraintSet.h:
+        * heap/SlotVisitor.cpp:
+        (JSC::SlotVisitor::visitChildren):
+        (JSC::SlotVisitor::visitAsConstraint):
+        (JSC::SlotVisitor::drain):
+        (JSC::SlotVisitor::addOpaqueRoot):
+        (JSC::SlotVisitor::mergeIfNecessary):
+        (JSC::SlotVisitor::mergeOpaqueRootsIfNecessary): Deleted.
+        * heap/SlotVisitor.h:
+        (JSC::SlotVisitor::setIgnoreNewOpaqueRoots):
+        * heap/SlotVisitorInlines.h:
+        (JSC::SlotVisitor::reportExtraMemoryVisited):
+        (JSC::SlotVisitor::reportExternalMemoryVisited):
+        * heap/Subspace.cpp: Added.
+        (JSC::Subspace::Subspace):
+        (JSC::Subspace::~Subspace):
+        (JSC::Subspace::finishSweep):
+        (JSC::Subspace::destroy):
+        (JSC::Subspace::allocate):
+        (JSC::Subspace::tryAllocate):
+        (JSC::Subspace::allocatorForSlow):
+        (JSC::Subspace::allocateSlow):
+        (JSC::Subspace::tryAllocateSlow):
+        * heap/Subspace.h: Added.
+        (JSC::Subspace::tryAllocatorFor):
+        (JSC::Subspace::allocatorFor):
+        * heap/SubspaceInlines.h: Added.
+        (JSC::Subspace::forEachMarkedBlock):
+        (JSC::Subspace::forEachNotEmptyMarkedBlock):
+        (JSC::Subspace::forEachLargeAllocation):
+        (JSC::Subspace::forEachMarkedCell):
+        * heap/WeakBlock.cpp:
+        (JSC::WeakBlock::specializedVisit):
+        * heap/WeakBlock.h:
+        * heap/WeakSet.h:
+        (JSC::WeakSet::visit):
+        * jit/AssemblyHelpers.h:
+        (JSC::AssemblyHelpers::emitAllocateJSObjectWithKnownSize):
+        (JSC::AssemblyHelpers::emitAllocateVariableSized):
+        (JSC::AssemblyHelpers::emitAllocateVariableSizedCell):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_new_object):
+        * jsc.cpp:
+        * runtime/ButterflyInlines.h:
+        (JSC::Butterfly::createUninitialized):
+        (JSC::Butterfly::growArrayRight):
+        * runtime/ClassInfo.h:
+        * runtime/ClonedArguments.cpp:
+        (JSC::ClonedArguments::createEmpty):
+        * runtime/DirectArguments.cpp:
+        (JSC::DirectArguments::overrideThings):
+        * runtime/GenericArgumentsInlines.h:
+        (JSC::GenericArguments&lt;Type&gt;::initModifiedArgumentsDescriptor):
+        * runtime/HashMapImpl.h:
+        (JSC::HashMapBuffer::create):
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::tryCreateUninitialized):
+        (JSC::JSArray::unshiftCountSlowCase):
+        * runtime/JSArrayBufferView.cpp:
+        (JSC::JSArrayBufferView::ConstructionContext::ConstructionContext):
+        * runtime/JSCell.h:
+        (JSC::subspaceFor):
+        * runtime/JSCellInlines.h:
+        (JSC::JSCell::visitOutputConstraints):
+        (JSC::JSCell::subspaceFor):
+        (JSC::allocateCell):
+        * runtime/JSDestructibleObject.h:
+        (JSC::JSDestructibleObject::subspaceFor):
+        * runtime/JSDestructibleObjectSubspace.cpp: Added.
+        (JSC::JSDestructibleObjectSubspace::JSDestructibleObjectSubspace):
+        (JSC::JSDestructibleObjectSubspace::~JSDestructibleObjectSubspace):
+        (JSC::JSDestructibleObjectSubspace::finishSweep):
+        (JSC::JSDestructibleObjectSubspace::destroy):
+        * runtime/JSDestructibleObjectSubspace.h: Added.
+        * runtime/JSObject.h:
+        (JSC::JSObject::JSObject):
+        * runtime/JSObjectInlines.h:
+        * runtime/JSSegmentedVariableObject.h:
+        * runtime/JSString.h:
+        (JSC::JSString::subspaceFor):
+        * runtime/JSStringSubspace.cpp: Added.
+        (JSC::JSStringSubspace::JSStringSubspace):
+        (JSC::JSStringSubspace::~JSStringSubspace):
+        (JSC::JSStringSubspace::finishSweep):
+        (JSC::JSStringSubspace::destroy):
+        * runtime/JSStringSubspace.h: Added.
+        * runtime/RegExpMatchesArray.h:
+        (JSC::tryCreateUninitializedRegExpMatchesArray):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+
</ins><span class="cx"> 2017-01-17  Michael Saboff  &lt;msaboff@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Nested parenthesized regular expressions with non-zero minimum counts appear to hang and use lots of memory
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -130,7 +130,7 @@
</span><span class="cx">                 0F1FB38E1E173A6500A9BE50 /* SynchronousStopTheWorldMutatorScheduler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F1FB38A1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.cpp */; };
</span><span class="cx">                 0F1FB38F1E173A6700A9BE50 /* SynchronousStopTheWorldMutatorScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1FB38B1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.h */; };
</span><span class="cx">                 0F1FB3901E173A6B00A9BE50 /* MutatorScheduler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F1FB38C1E173A6200A9BE50 /* MutatorScheduler.cpp */; };
</span><del>-                0F1FB3931E177A7200A9BE50 /* VisitingTimeout.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1FB3921E177A6F00A9BE50 /* VisitingTimeout.h */; };
</del><ins>+                0F1FB3931E177A7200A9BE50 /* VisitingTimeout.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1FB3921E177A6F00A9BE50 /* VisitingTimeout.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F1FB3961E1AF7E100A9BE50 /* DFGPlanInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1FB3941E1AF7DF00A9BE50 /* DFGPlanInlines.h */; };
</span><span class="cx">                 0F1FB3971E1AF7E300A9BE50 /* DFGWorklistInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1FB3951E1AF7DF00A9BE50 /* DFGWorklistInlines.h */; };
</span><span class="cx">                 0F1FB3991E1F65FB00A9BE50 /* MutatorScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1FB3981E1F65F900A9BE50 /* MutatorScheduler.h */; };
</span><span class="lines">@@ -463,7 +463,7 @@
</span><span class="cx">                 0F64B27A1A7957B2006E4E66 /* CallEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F64B2781A7957B2006E4E66 /* CallEdge.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F64EAF31C4ECD0600621E9B /* AirArgInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F64EAF21C4ECD0600621E9B /* AirArgInlines.h */; };
</span><span class="cx">                 0F660E371E0517B90031462C /* MarkingConstraint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F660E331E0517B70031462C /* MarkingConstraint.cpp */; };
</span><del>-                0F660E381E0517BB0031462C /* MarkingConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F660E341E0517B70031462C /* MarkingConstraint.h */; };
</del><ins>+                0F660E381E0517BB0031462C /* MarkingConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F660E341E0517B70031462C /* MarkingConstraint.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F660E391E0517BF0031462C /* MarkingConstraintSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F660E351E0517B70031462C /* MarkingConstraintSet.cpp */; };
</span><span class="cx">                 0F660E3A1E0517C10031462C /* MarkingConstraintSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F660E361E0517B80031462C /* MarkingConstraintSet.h */; };
</span><span class="cx">                 0F664CE81DA304EF00B00A11 /* CodeBlockSetInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F664CE71DA304ED00B00A11 /* CodeBlockSetInlines.h */; };
</span><span class="lines">@@ -523,13 +523,22 @@
</span><span class="cx">                 0F7C39FB1C8F629300480151 /* RegExpInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C39FA1C8F629300480151 /* RegExpInlines.h */; };
</span><span class="cx">                 0F7C39FD1C8F659500480151 /* RegExpObjectInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C39FC1C8F659500480151 /* RegExpObjectInlines.h */; };
</span><span class="cx">                 0F7C39FF1C90C55B00480151 /* DFGOpInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C39FE1C90C55B00480151 /* DFGOpInfo.h */; };
</span><del>-                0F7C5FB81D888A0C0044F5E2 /* MarkedBlockInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C5FB71D888A010044F5E2 /* MarkedBlockInlines.h */; };
-                0F7C5FBA1D8895070044F5E2 /* MarkedSpaceInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C5FB91D8895050044F5E2 /* MarkedSpaceInlines.h */; };
</del><ins>+                0F7C5FB81D888A0C0044F5E2 /* MarkedBlockInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C5FB71D888A010044F5E2 /* MarkedBlockInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F7CF94F1DBEEE880098CC12 /* ReleaseHeapAccessScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7CF94E1DBEEE860098CC12 /* ReleaseHeapAccessScope.h */; };
</span><span class="cx">                 0F7CF9521DC027D90098CC12 /* StopIfNecessaryTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7CF9511DC027D70098CC12 /* StopIfNecessaryTimer.h */; };
</span><span class="cx">                 0F7CF9531DC027DB0098CC12 /* StopIfNecessaryTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7CF9501DC027D70098CC12 /* StopIfNecessaryTimer.cpp */; };
</span><span class="cx">                 0F7CF9561DC1258D0098CC12 /* AtomicsObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7CF9541DC1258B0098CC12 /* AtomicsObject.cpp */; };
</span><span class="cx">                 0F7CF9571DC125900098CC12 /* AtomicsObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7CF9551DC1258B0098CC12 /* AtomicsObject.h */; };
</span><ins>+                0F7DF1341E2970D70095951B /* ConstraintVolatility.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7DF12F1E2970D50095951B /* ConstraintVolatility.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F7DF1351E2970DC0095951B /* MarkedSpaceInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7DF1301E2970D50095951B /* MarkedSpaceInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F7DF1361E2970DF0095951B /* Subspace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7DF1311E2970D50095951B /* Subspace.cpp */; };
+                0F7DF1371E2970E10095951B /* Subspace.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7DF1321E2970D50095951B /* Subspace.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F7DF1381E2970E40095951B /* SubspaceInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7DF1331E2970D50095951B /* SubspaceInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F7DF13B1E2971110095951B /* JSDestructibleObjectSubspace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7DF1391E29710E0095951B /* JSDestructibleObjectSubspace.cpp */; };
+                0F7DF13C1E2971130095951B /* JSDestructibleObjectSubspace.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7DF13A1E29710E0095951B /* JSDestructibleObjectSubspace.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F7DF13F1E2AFC4D0095951B /* JSStringSubspace.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7DF13E1E2AFC4B0095951B /* JSStringSubspace.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F7DF1401E2AFC500095951B /* JSStringSubspace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7DF13D1E2AFC4B0095951B /* JSStringSubspace.cpp */; };
+                0F7DF1461E2BEF6A0095951B /* MarkedAllocatorInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7DF1451E2BEF680095951B /* MarkedAllocatorInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F7F988B1D9596C500F4F12E /* DFGStoreBarrierClusteringPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7F98891D9596C300F4F12E /* DFGStoreBarrierClusteringPhase.cpp */; };
</span><span class="cx">                 0F7F988C1D9596C800F4F12E /* DFGStoreBarrierClusteringPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7F988A1D9596C300F4F12E /* DFGStoreBarrierClusteringPhase.h */; };
</span><span class="cx">                 0F8023EA1613832B00A0BA45 /* ByValInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8023E91613832300A0BA45 /* ByValInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -2965,12 +2974,21 @@
</span><span class="cx">                 0F7C39FC1C8F659500480151 /* RegExpObjectInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpObjectInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F7C39FE1C90C55B00480151 /* DFGOpInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOpInfo.h; path = dfg/DFGOpInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F7C5FB71D888A010044F5E2 /* MarkedBlockInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkedBlockInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                0F7C5FB91D8895050044F5E2 /* MarkedSpaceInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkedSpaceInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 0F7CF94E1DBEEE860098CC12 /* ReleaseHeapAccessScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReleaseHeapAccessScope.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F7CF9501DC027D70098CC12 /* StopIfNecessaryTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StopIfNecessaryTimer.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F7CF9511DC027D70098CC12 /* StopIfNecessaryTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StopIfNecessaryTimer.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F7CF9541DC1258B0098CC12 /* AtomicsObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AtomicsObject.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F7CF9551DC1258B0098CC12 /* AtomicsObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtomicsObject.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F7DF12F1E2970D50095951B /* ConstraintVolatility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstraintVolatility.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F7DF1301E2970D50095951B /* MarkedSpaceInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkedSpaceInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F7DF1311E2970D50095951B /* Subspace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Subspace.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F7DF1321E2970D50095951B /* Subspace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Subspace.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F7DF1331E2970D50095951B /* SubspaceInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubspaceInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F7DF1391E29710E0095951B /* JSDestructibleObjectSubspace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDestructibleObjectSubspace.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F7DF13A1E29710E0095951B /* JSDestructibleObjectSubspace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDestructibleObjectSubspace.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F7DF13D1E2AFC4B0095951B /* JSStringSubspace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStringSubspace.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F7DF13E1E2AFC4B0095951B /* JSStringSubspace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringSubspace.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F7DF1451E2BEF680095951B /* MarkedAllocatorInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkedAllocatorInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F7F98891D9596C300F4F12E /* DFGStoreBarrierClusteringPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStoreBarrierClusteringPhase.cpp; path = dfg/DFGStoreBarrierClusteringPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F7F988A1D9596C300F4F12E /* DFGStoreBarrierClusteringPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStoreBarrierClusteringPhase.h; path = dfg/DFGStoreBarrierClusteringPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F8023E91613832300A0BA45 /* ByValInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ByValInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5698,6 +5716,7 @@
</span><span class="cx">                                 0FA762011DB9242300B7A2FD /* CollectionScope.h */,
</span><span class="cx">                                 146B14DB12EB5B12001BEC1B /* ConservativeRoots.cpp */,
</span><span class="cx">                                 149DAAF212EB559D0083B12B /* ConservativeRoots.h */,
</span><ins>+                                0F7DF12F1E2970D50095951B /* ConstraintVolatility.h */,
</ins><span class="cx">                                 2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */,
</span><span class="cx">                                 0F136D4B174AD69B0075B354 /* DeferGC.h */,
</span><span class="cx">                                 0FBB73BA1DEF8644002C009E /* DeleteAllCodeEffort.h */,
</span><span class="lines">@@ -5772,6 +5791,7 @@
</span><span class="cx">                                 14B7234012D7D0DA003BD5ED /* MachineStackMarker.h */,
</span><span class="cx">                                 C2B916C414DA040C00CBAC86 /* MarkedAllocator.cpp */,
</span><span class="cx">                                 C2B916C114DA014E00CBAC86 /* MarkedAllocator.h */,
</span><ins>+                                0F7DF1451E2BEF680095951B /* MarkedAllocatorInlines.h */,
</ins><span class="cx">                                 142D6F0613539A2800B02E86 /* MarkedBlock.cpp */,
</span><span class="cx">                                 142D6F0713539A2800B02E86 /* MarkedBlock.h */,
</span><span class="cx">                                 0F7C5FB71D888A010044F5E2 /* MarkedBlockInlines.h */,
</span><span class="lines">@@ -5778,7 +5798,7 @@
</span><span class="cx">                                 141448CA13A176EC00F5BA1A /* MarkedBlockSet.h */,
</span><span class="cx">                                 14D2F3D8139F4BE200491031 /* MarkedSpace.cpp */,
</span><span class="cx">                                 14D2F3D9139F4BE200491031 /* MarkedSpace.h */,
</span><del>-                                0F7C5FB91D8895050044F5E2 /* MarkedSpaceInlines.h */,
</del><ins>+                                0F7DF1301E2970D50095951B /* MarkedSpaceInlines.h */,
</ins><span class="cx">                                 0F660E331E0517B70031462C /* MarkingConstraint.cpp */,
</span><span class="cx">                                 0F660E341E0517B70031462C /* MarkingConstraint.h */,
</span><span class="cx">                                 0F660E351E0517B70031462C /* MarkingConstraintSet.cpp */,
</span><span class="lines">@@ -5801,6 +5821,9 @@
</span><span class="cx">                                 0F7CF9511DC027D70098CC12 /* StopIfNecessaryTimer.h */,
</span><span class="cx">                                 142E3132134FF0A600AFADB5 /* Strong.h */,
</span><span class="cx">                                 145722851437E140005FDE26 /* StrongInlines.h */,
</span><ins>+                                0F7DF1311E2970D50095951B /* Subspace.cpp */,
+                                0F7DF1321E2970D50095951B /* Subspace.h */,
+                                0F7DF1331E2970D50095951B /* SubspaceInlines.h */,
</ins><span class="cx">                                 0F1FB38A1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.cpp */,
</span><span class="cx">                                 0F1FB38B1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.h */,
</span><span class="cx">                                 141448CC13A1783700F5BA1A /* TinyBloomFilter.h */,
</span><span class="lines">@@ -6330,9 +6353,9 @@
</span><span class="cx">                                 E178633F0D9BEC0000D74E75 /* InitializeThreading.h */,
</span><span class="cx">                                 E35E035D1B7AB43E0073AD2A /* InspectorInstrumentationObject.cpp */,
</span><span class="cx">                                 E35E035E1B7AB43E0073AD2A /* InspectorInstrumentationObject.h */,
</span><ins>+                                A7A8AF2B17ADB5F3005AB174 /* Int8Array.h */,
</ins><span class="cx">                                 A7A8AF2C17ADB5F3005AB174 /* Int16Array.h */,
</span><span class="cx">                                 A7A8AF2D17ADB5F3005AB174 /* Int32Array.h */,
</span><del>-                                A7A8AF2B17ADB5F3005AB174 /* Int8Array.h */,
</del><span class="cx">                                 BC9BB95B0E19680600DF8855 /* InternalFunction.cpp */,
</span><span class="cx">                                 BC11667A0E199C05008066DD /* InternalFunction.h */,
</span><span class="cx">                                 A1B9E2331B4E0D6700BC7FED /* IntlCollator.cpp */,
</span><span class="lines">@@ -6397,6 +6420,8 @@
</span><span class="cx">                                 9788FC221471AD0C0068CE2D /* JSDateMath.cpp */,
</span><span class="cx">                                 9788FC231471AD0C0068CE2D /* JSDateMath.h */,
</span><span class="cx">                                 C2A7F687160432D400F76B98 /* JSDestructibleObject.h */,
</span><ins>+                                0F7DF1391E29710E0095951B /* JSDestructibleObjectSubspace.cpp */,
+                                0F7DF13A1E29710E0095951B /* JSDestructibleObjectSubspace.h */,
</ins><span class="cx">                                 BC22A39A0E16E14800AF21C8 /* JSEnvironmentRecord.cpp */,
</span><span class="cx">                                 14F252560D08DD8D004ECFFF /* JSEnvironmentRecord.h */,
</span><span class="cx">                                 A7B4ACAE1484C9CE00B38A36 /* JSExportMacros.h */,
</span><span class="lines">@@ -6425,9 +6450,9 @@
</span><span class="cx">                                 BC756FC60E2031B200DE7D12 /* JSGlobalObjectFunctions.cpp */,
</span><span class="cx">                                 BC756FC70E2031B200DE7D12 /* JSGlobalObjectFunctions.h */,
</span><span class="cx">                                 79B819921DD25CF500DDC714 /* JSGlobalObjectInlines.h */,
</span><ins>+                                0F2B66C917B6B5AB00A7AE3F /* JSInt8Array.h */,
</ins><span class="cx">                                 0F2B66CA17B6B5AB00A7AE3F /* JSInt16Array.h */,
</span><span class="cx">                                 0F2B66CB17B6B5AB00A7AE3F /* JSInt32Array.h */,
</span><del>-                                0F2B66C917B6B5AB00A7AE3F /* JSInt8Array.h */,
</del><span class="cx">                                 E33F507E1B8429A400413856 /* JSInternalPromise.cpp */,
</span><span class="cx">                                 E33F507F1B8429A400413856 /* JSInternalPromise.h */,
</span><span class="cx">                                 E33F50761B84225700413856 /* JSInternalPromiseConstructor.cpp */,
</span><span class="lines">@@ -6491,6 +6516,8 @@
</span><span class="cx">                                 70EC0EBD1AA0D7DA00B6AAFA /* JSStringIterator.h */,
</span><span class="cx">                                 2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */,
</span><span class="cx">                                 2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */,
</span><ins>+                                0F7DF13D1E2AFC4B0095951B /* JSStringSubspace.cpp */,
+                                0F7DF13E1E2AFC4B0095951B /* JSStringSubspace.h */,
</ins><span class="cx">                                 0F919D09157EE09D004A4E7D /* JSSymbolTableObject.cpp */,
</span><span class="cx">                                 0F919D0A157EE09D004A4E7D /* JSSymbolTableObject.h */,
</span><span class="cx">                                 70ECA6001AFDBEA200449739 /* JSTemplateRegistryKey.cpp */,
</span><span class="lines">@@ -6507,10 +6534,10 @@
</span><span class="cx">                                 53F256E11B87E28000B4B768 /* JSTypedArrayViewPrototype.cpp */,
</span><span class="cx">                                 53917E7C1B791106000EBD33 /* JSTypedArrayViewPrototype.h */,
</span><span class="cx">                                 6507D2970E871E4A00D7D896 /* JSTypeInfo.h */,
</span><ins>+                                0F2B66D217B6B5AB00A7AE3F /* JSUint8Array.h */,
+                                0F2B66D317B6B5AB00A7AE3F /* JSUint8ClampedArray.h */,
</ins><span class="cx">                                 0F2B66D417B6B5AB00A7AE3F /* JSUint16Array.h */,
</span><span class="cx">                                 0F2B66D517B6B5AB00A7AE3F /* JSUint32Array.h */,
</span><del>-                                0F2B66D217B6B5AB00A7AE3F /* JSUint8Array.h */,
-                                0F2B66D317B6B5AB00A7AE3F /* JSUint8ClampedArray.h */,
</del><span class="cx">                                 A7CA3AE117DA41AE006538AF /* JSWeakMap.cpp */,
</span><span class="cx">                                 A7CA3AE217DA41AE006538AF /* JSWeakMap.h */,
</span><span class="cx">                                 709FB8611AE335C60039D069 /* JSWeakSet.cpp */,
</span><span class="lines">@@ -6647,6 +6674,7 @@
</span><span class="cx">                                 0F5B4A321C84F0D600F1B17E /* SlowPathReturnType.h */,
</span><span class="cx">                                 93303FE80E6A72B500786E6A /* SmallStrings.cpp */,
</span><span class="cx">                                 93303FEA0E6A72C000786E6A /* SmallStrings.h */,
</span><ins>+                                425BA1337E4344E1B269A671 /* SourceOrigin.h */,
</ins><span class="cx">                                 0F0CD4C315F6B6B50032F1C0 /* SparseArrayValueMap.cpp */,
</span><span class="cx">                                 0FB7F39215ED8E3800F167B2 /* SparseArrayValueMap.h */,
</span><span class="cx">                                 0F3AC751183EA1040032029F /* StackAlignment.h */,
</span><span class="lines">@@ -6715,11 +6743,11 @@
</span><span class="cx">                                 0F2D4DE019832D91007D4B19 /* TypeProfilerLog.h */,
</span><span class="cx">                                 0F2D4DE319832D91007D4B19 /* TypeSet.cpp */,
</span><span class="cx">                                 0F2D4DE419832D91007D4B19 /* TypeSet.h */,
</span><ins>+                                A7A8AF3017ADB5F3005AB174 /* Uint8Array.h */,
+                                A7A8AF3117ADB5F3005AB174 /* Uint8ClampedArray.h */,
</ins><span class="cx">                                 A7A8AF3217ADB5F3005AB174 /* Uint16Array.h */,
</span><span class="cx">                                 866739D113BFDE710023D87C /* Uint16WithFraction.h */,
</span><span class="cx">                                 A7A8AF3317ADB5F3005AB174 /* Uint32Array.h */,
</span><del>-                                A7A8AF3017ADB5F3005AB174 /* Uint8Array.h */,
-                                A7A8AF3117ADB5F3005AB174 /* Uint8ClampedArray.h */,
</del><span class="cx">                                 0FE050231AA9095600D33B33 /* VarOffset.cpp */,
</span><span class="cx">                                 0FE050241AA9095600D33B33 /* VarOffset.h */,
</span><span class="cx">                                 E18E3A570DF9278C00D90B34 /* VM.cpp */,
</span><span class="lines">@@ -6743,7 +6771,6 @@
</span><span class="cx">                                 709FB8661AE335C60039D069 /* WeakSetPrototype.h */,
</span><span class="cx">                                 A7DCB77912E3D90500911940 /* WriteBarrier.h */,
</span><span class="cx">                                 C2B6D75218A33793004A9301 /* WriteBarrierInlines.h */,
</span><del>-                                425BA1337E4344E1B269A671 /* SourceOrigin.h */,
</del><span class="cx">                                 F73926918DC64330AFCDF0D7 /* JSSourceCode.cpp */,
</span><span class="cx">                                 3032175DF1AD47D8998B34E1 /* JSSourceCode.h */,
</span><span class="cx">                                 11C197C2624848EDA84CED7F /* JSScriptFetcher.cpp */,
</span><span class="lines">@@ -8071,6 +8098,7 @@
</span><span class="cx">                                 BCD203E80E1718F4002C7E82 /* DatePrototype.lut.h in Headers */,
</span><span class="cx">                                 BC18C3FA0E16F5CD00B34460 /* Debugger.h in Headers */,
</span><span class="cx">                                 BC18C3FB0E16F5CD00B34460 /* DebuggerCallFrame.h in Headers */,
</span><ins>+                                0F7DF1351E2970DC0095951B /* MarkedSpaceInlines.h in Headers */,
</ins><span class="cx">                                 6AD2CB4D19B9140100065719 /* DebuggerEvalEnabler.h in Headers */,
</span><span class="cx">                                 A5FC84B21D1DDAD6006B5C46 /* DebuggerLocation.h in Headers */,
</span><span class="cx">                                 A5A1A0941D8CB33E004C2EB8 /* DebuggerParseData.h in Headers */,
</span><span class="lines">@@ -8212,6 +8240,7 @@
</span><span class="cx">                                 0FC0977114693AF500CF2442 /* DFGOSRExitCompiler.h in Headers */,
</span><span class="cx">                                 0F7025AA1714B0FC00382C0E /* DFGOSRExitCompilerCommon.h in Headers */,
</span><span class="cx">                                 0F392C8A1B46188400844728 /* DFGOSRExitFuzz.h in Headers */,
</span><ins>+                                0F7DF13F1E2AFC4D0095951B /* JSStringSubspace.h in Headers */,
</ins><span class="cx">                                 0FEFC9AB1681A3B600567F53 /* DFGOSRExitJumpPlaceholder.h in Headers */,
</span><span class="cx">                                 0F235BEE17178E7300690C7F /* DFGOSRExitPreparation.h in Headers */,
</span><span class="cx">                                 0F6237981AE45CA700D402EA /* DFGPhantomInsertionPhase.h in Headers */,
</span><span class="lines">@@ -8388,8 +8417,10 @@
</span><span class="cx">                                 A54E8EB018BFFBBB00556D28 /* GCSegmentedArray.h in Headers */,
</span><span class="cx">                                 A54E8EB118BFFBBE00556D28 /* GCSegmentedArrayInlines.h in Headers */,
</span><span class="cx">                                 0F86A26F1D6F7B3300CB0C92 /* GCTypeMap.h in Headers */,
</span><ins>+                                0F7DF1381E2970E40095951B /* SubspaceInlines.h in Headers */,
</ins><span class="cx">                                 9959E9311BD18272001AA413 /* generate-combined-inspector-json.py in Headers */,
</span><span class="cx">                                 C4703CC0192844960013FBEA /* generate-inspector-protocol-bindings.py in Headers */,
</span><ins>+                                0F7DF1461E2BEF6A0095951B /* MarkedAllocatorInlines.h in Headers */,
</ins><span class="cx">                                 99DA00AF1BD5994E00F4575C /* generate-js-builtins.py in Headers */,
</span><span class="cx">                                 A5EA70EC19F5B3EA0098F5EC /* generate_cpp_alternate_backend_dispatcher_header.py in Headers */,
</span><span class="cx">                                 A5EF9B141A1D43F600702E90 /* generate_cpp_backend_dispatcher_header.py in Headers */,
</span><span class="lines">@@ -8552,6 +8583,7 @@
</span><span class="cx">                                 FE187A021BFBE5610038BBCA /* JITMulGenerator.h in Headers */,
</span><span class="cx">                                 FE99B2491C24C3D300C82159 /* JITNegGenerator.h in Headers */,
</span><span class="cx">                                 0F24E54D17EE274900ABB217 /* JITOperations.h in Headers */,
</span><ins>+                                0F7DF1371E2970E10095951B /* Subspace.h in Headers */,
</ins><span class="cx">                                 FE3A06C01C11041A00390FDD /* JITRightShiftGenerator.h in Headers */,
</span><span class="cx">                                 0F766D3115AA8112008F363E /* JITStubRoutine.h in Headers */,
</span><span class="cx">                                 0F766D2C15A8CC3A008F363E /* JITStubRoutineSet.h in Headers */,
</span><span class="lines">@@ -8668,6 +8700,7 @@
</span><span class="cx">                                 7C184E1F17BEE22E007CB63A /* JSPromisePrototype.h in Headers */,
</span><span class="cx">                                 996B731F1BDA08EF00331B84 /* JSPromisePrototype.lut.h in Headers */,
</span><span class="cx">                                 2A05ABD61961DF2400341750 /* JSPropertyNameEnumerator.h in Headers */,
</span><ins>+                                0F7DF13C1E2971130095951B /* JSDestructibleObjectSubspace.h in Headers */,
</ins><span class="cx">                                 E3EF88751B66DF23003F26CB /* JSPropertyNameIterator.h in Headers */,
</span><span class="cx">                                 862553D216136E1A009F17D0 /* JSProxy.h in Headers */,
</span><span class="cx">                                 A552C3801ADDB8FE00139726 /* JSRemoteInspector.h in Headers */,
</span><span class="lines">@@ -8677,6 +8710,7 @@
</span><span class="cx">                                 A7C0C4AC168103020017011D /* JSScriptRefPrivate.h in Headers */,
</span><span class="cx">                                 0F919D11157F332C004A4E7D /* JSSegmentedVariableObject.h in Headers */,
</span><span class="cx">                                 A7299D9E17D12837005F5FF9 /* JSSet.h in Headers */,
</span><ins>+                                0F7DF1341E2970D70095951B /* ConstraintVolatility.h in Headers */,
</ins><span class="cx">                                 A790DD70182F499700588807 /* JSSetIterator.h in Headers */,
</span><span class="cx">                                 BC18C4270E16F5CD00B34460 /* JSString.h in Headers */,
</span><span class="cx">                                 86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */,
</span><span class="lines">@@ -8780,7 +8814,6 @@
</span><span class="cx">                                 0F7C5FB81D888A0C0044F5E2 /* MarkedBlockInlines.h in Headers */,
</span><span class="cx">                                 141448CB13A176EC00F5BA1A /* MarkedBlockSet.h in Headers */,
</span><span class="cx">                                 14D2F3DB139F4BE200491031 /* MarkedSpace.h in Headers */,
</span><del>-                                0F7C5FBA1D8895070044F5E2 /* MarkedSpaceInlines.h in Headers */,
</del><span class="cx">                                 142D6F1213539A4100B02E86 /* MarkStack.h in Headers */,
</span><span class="cx">                                 8612E4CD152389EC00C836BE /* MatchResult.h in Headers */,
</span><span class="cx">                                 4340A4851A9051AF00D73CCA /* MathCommon.h in Headers */,
</span><span class="lines">@@ -9943,6 +9976,7 @@
</span><span class="cx">                                 0F7F988B1D9596C500F4F12E /* DFGStoreBarrierClusteringPhase.cpp in Sources */,
</span><span class="cx">                                 0F9E32631B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.cpp in Sources */,
</span><span class="cx">                                 0FC20CB51852E2C600C9E954 /* DFGStrengthReductionPhase.cpp in Sources */,
</span><ins>+                                0F7DF13B1E2971110095951B /* JSDestructibleObjectSubspace.cpp in Sources */,
</ins><span class="cx">                                 0F893BDB1936E23C001211F4 /* DFGStructureAbstractValue.cpp in Sources */,
</span><span class="cx">                                 0F79085519A290B200F6310C /* DFGStructureRegistrationPhase.cpp in Sources */,
</span><span class="cx">                                 0F2FCCFE18A60070001A27F8 /* DFGThreadData.cpp in Sources */,
</span><span class="lines">@@ -10153,6 +10187,7 @@
</span><span class="cx">                                 5B70CFDF1DB69E6600EC23F9 /* JSAsyncFunction.cpp in Sources */,
</span><span class="cx">                                 1421359B0A677F4F00A8195E /* JSBase.cpp in Sources */,
</span><span class="cx">                                 86FA9E91142BBB2E001773B7 /* JSBoundFunction.cpp in Sources */,
</span><ins>+                                0F7DF1401E2AFC500095951B /* JSStringSubspace.cpp in Sources */,
</ins><span class="cx">                                 1440F8AF0A508D200005F061 /* JSCallbackConstructor.cpp in Sources */,
</span><span class="cx">                                 1440F8920A508B100005F061 /* JSCallbackFunction.cpp in Sources */,
</span><span class="cx">                                 14ABDF600A437FEF00ECCA01 /* JSCallbackObject.cpp in Sources */,
</span><span class="lines">@@ -10180,6 +10215,7 @@
</span><span class="cx">                                 A5C3A1A518C0490200C9593A /* JSGlobalObjectConsoleClient.cpp in Sources */,
</span><span class="cx">                                 A59455921824744700CC3843 /* JSGlobalObjectDebuggable.cpp in Sources */,
</span><span class="cx">                                 A57D23E91891B0770031C7FA /* JSGlobalObjectDebuggerAgent.cpp in Sources */,
</span><ins>+                                0F7DF1361E2970DF0095951B /* Subspace.cpp in Sources */,
</ins><span class="cx">                                 ADE8029B1E08F1DE0058DE78 /* WebAssemblyLinkErrorPrototype.cpp in Sources */,
</span><span class="cx">                                 14E9D17B107EC469004DDA21 /* JSGlobalObjectFunctions.cpp in Sources */,
</span><span class="cx">                                 A51007C0187CC3C600B38879 /* JSGlobalObjectInspectorController.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeObjectAllocationProfileh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ObjectAllocationProfile.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ObjectAllocationProfile.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/bytecode/ObjectAllocationProfile.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -82,7 +82,7 @@
</span><span class="cx">         ASSERT(inlineCapacity &lt;= JSFinalObject::maxInlineCapacity());
</span><span class="cx"> 
</span><span class="cx">         size_t allocationSize = JSFinalObject::allocationSize(inlineCapacity);
</span><del>-        MarkedAllocator* allocator = vm.heap.allocatorForObjectWithoutDestructor(allocationSize);
</del><ins>+        MarkedAllocator* allocator = vm.cellSpace.allocatorFor(allocationSize);
</ins><span class="cx">         
</span><span class="cx">         // Take advantage of extra inline capacity available in the size class.
</span><span class="cx">         if (allocator) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePolymorphicAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -1264,7 +1264,7 @@
</span><span class="cx">             size_t newSize = newStructure()-&gt;outOfLineCapacity() * sizeof(JSValue);
</span><span class="cx">             
</span><span class="cx">             if (allocatingInline) {
</span><del>-                MarkedAllocator* allocator = vm.heap.allocatorForAuxiliaryData(newSize);
</del><ins>+                MarkedAllocator* allocator = vm.auxiliarySpace.allocatorFor(newSize);
</ins><span class="cx">                 
</span><span class="cx">                 if (!allocator) {
</span><span class="cx">                     // Yuck, this case would suck!
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -110,7 +110,7 @@
</span><span class="cx">     m_jit.move(TrustedImmPtr(0), storageGPR);
</span><span class="cx">     
</span><span class="cx">     if (size) {
</span><del>-        if (MarkedAllocator* allocator = m_jit.vm()-&gt;heap.allocatorForAuxiliaryData(size)) {
</del><ins>+        if (MarkedAllocator* allocator = m_jit.vm()-&gt;auxiliarySpace.allocatorFor(size)) {
</ins><span class="cx">             m_jit.move(TrustedImmPtr(allocator), scratchGPR);
</span><span class="cx">             m_jit.emitAllocate(storageGPR, allocator, scratchGPR, scratch2GPR, slowCases);
</span><span class="cx">             
</span><span class="lines">@@ -125,7 +125,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     size_t allocationSize = JSFinalObject::allocationSize(inlineCapacity);
</span><del>-    MarkedAllocator* allocatorPtr = m_jit.vm()-&gt;heap.allocatorForObjectWithoutDestructor(allocationSize);
</del><ins>+    MarkedAllocator* allocatorPtr = subspaceFor&lt;JSFinalObject&gt;(*m_jit.vm())-&gt;allocatorFor(allocationSize);
</ins><span class="cx">     if (allocatorPtr) {
</span><span class="cx">         m_jit.move(TrustedImmPtr(allocatorPtr), scratchGPR);
</span><span class="cx">         emitAllocateJSObject(resultGPR, allocatorPtr, scratchGPR, TrustedImmPtr(structure), storageGPR, scratch2GPR, slowCases);
</span><span class="lines">@@ -3897,7 +3897,7 @@
</span><span class="cx">     GPRReg scratchGPR = scratch.gpr();
</span><span class="cx">     
</span><span class="cx">     JITCompiler::JumpList slowPath;
</span><del>-    MarkedAllocator* markedAllocator = m_jit.vm()-&gt;heap.allocatorForObjectWithDestructor(sizeof(JSRopeString));
</del><ins>+    MarkedAllocator* markedAllocator = subspaceFor&lt;JSString&gt;(*m_jit.vm())-&gt;allocatorFor(sizeof(JSRopeString));
</ins><span class="cx">     RELEASE_ASSERT(markedAllocator);
</span><span class="cx">     m_jit.move(TrustedImmPtr(markedAllocator), allocatorGPR);
</span><span class="cx">     emitAllocateJSCell(resultGPR, markedAllocator, allocatorGPR, TrustedImmPtr(m_jit.vm()-&gt;stringStructure.get()), scratchGPR, slowPath);
</span><span class="lines">@@ -7555,7 +7555,7 @@
</span><span class="cx">     
</span><span class="cx">     size_t size = initialOutOfLineCapacity * sizeof(JSValue);
</span><span class="cx"> 
</span><del>-    MarkedAllocator* allocator = m_jit.vm()-&gt;heap.allocatorForAuxiliaryData(size);
</del><ins>+    MarkedAllocator* allocator = m_jit.vm()-&gt;auxiliarySpace.allocatorFor(size);
</ins><span class="cx"> 
</span><span class="cx">     if (!allocator || node-&gt;transition()-&gt;previous-&gt;couldHaveIndexingHeader()) {
</span><span class="cx">         SpeculateCellOperand base(this, node-&gt;child1());
</span><span class="lines">@@ -7600,7 +7600,7 @@
</span><span class="cx">     size_t newSize = oldSize * outOfLineGrowthFactor;
</span><span class="cx">     ASSERT(newSize == node-&gt;transition()-&gt;next-&gt;outOfLineCapacity() * sizeof(JSValue));
</span><span class="cx">     
</span><del>-    MarkedAllocator* allocator = m_jit.vm()-&gt;heap.allocatorForAuxiliaryData(newSize);
</del><ins>+    MarkedAllocator* allocator = m_jit.vm()-&gt;auxiliarySpace.allocatorFor(newSize);
</ins><span class="cx"> 
</span><span class="cx">     if (!allocator || node-&gt;transition()-&gt;previous-&gt;couldHaveIndexingHeader()) {
</span><span class="cx">         SpeculateCellOperand base(this, node-&gt;child1());
</span><span class="lines">@@ -7986,7 +7986,7 @@
</span><span class="cx">         m_jit.and32(TrustedImm32(~7), scratchGPR);
</span><span class="cx">     }
</span><span class="cx">     m_jit.emitAllocateVariableSized(
</span><del>-        storageGPR, m_jit.vm()-&gt;heap.subspaceForAuxiliaryData(), scratchGPR, scratchGPR,
</del><ins>+        storageGPR, m_jit.vm()-&gt;auxiliarySpace, scratchGPR, scratchGPR,
</ins><span class="cx">         scratchGPR2, slowCases);
</span><span class="cx">     
</span><span class="cx">     MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, sizeGPR);
</span><span class="lines">@@ -9564,7 +9564,7 @@
</span><span class="cx">     m_jit.lshift32(TrustedImm32(3), scratch1);
</span><span class="cx">     m_jit.add32(TrustedImm32(sizeof(IndexingHeader)), scratch1, scratch2);
</span><span class="cx">     m_jit.emitAllocateVariableSized(
</span><del>-        storageResultGPR, m_jit.vm()-&gt;heap.subspaceForAuxiliaryData(), scratch2, scratch1, scratch3, slowCases);
</del><ins>+        storageResultGPR, m_jit.vm()-&gt;auxiliarySpace, scratch2, scratch1, scratch3, slowCases);
</ins><span class="cx">     m_jit.addPtr(TrustedImm32(sizeof(IndexingHeader)), storageResultGPR);
</span><span class="cx"> 
</span><span class="cx">     m_jit.store32(sizeGPR, MacroAssembler::Address(storageResultGPR, Butterfly::offsetOfPublicLength()));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -4173,7 +4173,7 @@
</span><span class="cx">         
</span><span class="cx">         Structure* structure = node-&gt;structure();
</span><span class="cx">         size_t allocationSize = JSFinalObject::allocationSize(structure-&gt;inlineCapacity());
</span><del>-        MarkedAllocator* allocatorPtr = m_jit.vm()-&gt;heap.allocatorForObjectWithoutDestructor(allocationSize);
</del><ins>+        MarkedAllocator* allocatorPtr = subspaceFor&lt;JSFinalObject&gt;(*m_jit.vm())-&gt;allocatorFor(allocationSize);
</ins><span class="cx"> 
</span><span class="cx">         m_jit.move(TrustedImmPtr(allocatorPtr), allocatorGPR);
</span><span class="cx">         emitAllocateJSObject(resultGPR, allocatorPtr, allocatorGPR, TrustedImmPtr(structure), TrustedImmPtr(0), scratchGPR, slowPath);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -4145,7 +4145,7 @@
</span><span class="cx"> 
</span><span class="cx">         Structure* structure = node-&gt;structure();
</span><span class="cx">         size_t allocationSize = JSFinalObject::allocationSize(structure-&gt;inlineCapacity());
</span><del>-        MarkedAllocator* allocatorPtr = m_jit.vm()-&gt;heap.allocatorForObjectWithoutDestructor(allocationSize);
</del><ins>+        MarkedAllocator* allocatorPtr = subspaceFor&lt;JSFinalObject&gt;(*m_jit.vm())-&gt;allocatorFor(allocationSize);
</ins><span class="cx"> 
</span><span class="cx">         m_jit.move(TrustedImmPtr(allocatorPtr), allocatorGPR);
</span><span class="cx">         emitAllocateJSObject(resultGPR, allocatorPtr, allocatorGPR, TrustedImmPtr(structure), TrustedImmPtr(0), scratchGPR, slowPath);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -124,8 +124,8 @@
</span><span class="cx">     macro(JSEnvironmentRecord_variables, JSEnvironmentRecord::offsetOfVariables(), sizeof(EncodedJSValue)) \
</span><span class="cx">     macro(JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, 0, sizeof(WriteBarrier&lt;JSString&gt;)) \
</span><span class="cx">     macro(JSRopeString_fibers, JSRopeString::offsetOfFibers(), sizeof(WriteBarrier&lt;JSString&gt;)) \
</span><del>-    macro(MarkedSpace_Subspace_allocatorForSizeStep, OBJECT_OFFSETOF(MarkedSpace::Subspace, allocatorForSizeStep), sizeof(MarkedAllocator*)) \
</del><span class="cx">     macro(ScopedArguments_overflowStorage, ScopedArguments::overflowStorageOffset(), sizeof(EncodedJSValue)) \
</span><ins>+    macro(Subspace_allocatorForSizeStep, Subspace::offsetOfAllocatorForSizeStep(), sizeof(MarkedAllocator*)) \
</ins><span class="cx">     macro(WriteBarrierBuffer_bufferContents, 0, sizeof(JSCell*)) \
</span><span class="cx">     macro(characters8, 0, sizeof(LChar)) \
</span><span class="cx">     macro(characters16, 0, sizeof(UChar)) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -4751,8 +4751,7 @@
</span><span class="cx">                     m_out.constIntPtr(~static_cast&lt;intptr_t&gt;(7)));
</span><span class="cx">             }
</span><span class="cx">         
</span><del>-            LValue allocator = allocatorForSize(
-                vm().heap.subspaceForAuxiliaryData(), byteSize, slowCase);
</del><ins>+            LValue allocator = allocatorForSize(vm().auxiliarySpace, byteSize, slowCase);
</ins><span class="cx">             LValue storage = allocateHeapCell(allocator, slowCase);
</span><span class="cx">             
</span><span class="cx">             splatWords(
</span><span class="lines">@@ -4993,8 +4992,7 @@
</span><span class="cx">         
</span><span class="cx">         LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
</span><span class="cx">         
</span><del>-        MarkedAllocator* allocator =
-            vm().heap.allocatorForObjectWithDestructor(sizeof(JSRopeString));
</del><ins>+        MarkedAllocator* allocator = subspaceFor&lt;JSRopeString&gt;(vm())-&gt;allocatorFor(sizeof(JSRopeString));
</ins><span class="cx">         DFG_ASSERT(m_graph, m_node, allocator);
</span><span class="cx">         
</span><span class="cx">         LValue result = allocateCell(
</span><span class="lines">@@ -8636,7 +8634,7 @@
</span><span class="cx">             
</span><span class="cx">             if (structure-&gt;outOfLineCapacity() || hasIndexedProperties(structure-&gt;indexingType())) {
</span><span class="cx">                 size_t allocationSize = JSFinalObject::allocationSize(structure-&gt;inlineCapacity());
</span><del>-                MarkedAllocator* cellAllocator = vm().heap.allocatorForObjectWithoutDestructor(allocationSize);
</del><ins>+                MarkedAllocator* cellAllocator = subspaceFor&lt;JSFinalObject&gt;(vm())-&gt;allocatorFor(allocationSize);
</ins><span class="cx">                 DFG_ASSERT(m_graph, m_node, cellAllocator);
</span><span class="cx"> 
</span><span class="cx">                 bool hasIndexingHeader = hasIndexedProperties(structure-&gt;indexingType());
</span><span class="lines">@@ -8676,7 +8674,7 @@
</span><span class="cx">                 ValueFromBlock noButterfly = m_out.anchor(m_out.intPtrZero);
</span><span class="cx">                 
</span><span class="cx">                 LValue startOfStorage = allocateHeapCell(
</span><del>-                    allocatorForSize(vm().heap.subspaceForAuxiliaryData(), butterflySize, slowPath),
</del><ins>+                    allocatorForSize(vm().auxiliarySpace, butterflySize, slowPath),
</ins><span class="cx">                     slowPath);
</span><span class="cx"> 
</span><span class="cx">                 LValue fastButterflyValue = m_out.add(
</span><span class="lines">@@ -9622,7 +9620,7 @@
</span><span class="cx">         LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
</span><span class="cx"> 
</span><span class="cx">         size_t sizeInBytes = sizeInValues * sizeof(JSValue);
</span><del>-        MarkedAllocator* allocator = vm().heap.allocatorForAuxiliaryData(sizeInBytes);
</del><ins>+        MarkedAllocator* allocator = vm().auxiliarySpace.allocatorFor(sizeInBytes);
</ins><span class="cx">         LValue startOfStorage = allocateHeapCell(m_out.constIntPtr(allocator), slowPath);
</span><span class="cx">         ValueFromBlock fastButterfly = m_out.anchor(
</span><span class="cx">             m_out.add(m_out.constIntPtr(sizeInBytes + sizeof(IndexingHeader)), startOfStorage));
</span><span class="lines">@@ -10530,7 +10528,7 @@
</span><span class="cx">     LValue allocateObject(
</span><span class="cx">         size_t size, StructureType structure, LValue butterfly, LBasicBlock slowPath)
</span><span class="cx">     {
</span><del>-        MarkedAllocator* allocator = vm().heap.allocatorForObjectOfType&lt;ClassType&gt;(size);
</del><ins>+        MarkedAllocator* allocator = subspaceFor&lt;ClassType&gt;(vm())-&gt;allocatorFor(size);
</ins><span class="cx">         return allocateObject(m_out.constIntPtr(allocator), structure, butterfly, slowPath);
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -10547,10 +10545,10 @@
</span><span class="cx">         
</span><span class="cx">         // Try to do some constant-folding here.
</span><span class="cx">         if (subspace-&gt;hasIntPtr() &amp;&amp; size-&gt;hasIntPtr()) {
</span><del>-            MarkedSpace::Subspace* actualSubspace = bitwise_cast&lt;MarkedSpace::Subspace*&gt;(subspace-&gt;asIntPtr());
</del><ins>+            Subspace* actualSubspace = bitwise_cast&lt;Subspace*&gt;(subspace-&gt;asIntPtr());
</ins><span class="cx">             size_t actualSize = size-&gt;asIntPtr();
</span><span class="cx">             
</span><del>-            MarkedAllocator* actualAllocator = MarkedSpace::allocatorFor(*actualSubspace, actualSize);
</del><ins>+            MarkedAllocator* actualAllocator = actualSubspace-&gt;allocatorFor(actualSize);
</ins><span class="cx">             if (!actualAllocator) {
</span><span class="cx">                 LBasicBlock continuation = m_out.newBlock();
</span><span class="cx">                 LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation);
</span><span class="lines">@@ -10580,11 +10578,11 @@
</span><span class="cx">         
</span><span class="cx">         return m_out.loadPtr(
</span><span class="cx">             m_out.baseIndex(
</span><del>-                m_heaps.MarkedSpace_Subspace_allocatorForSizeStep,
</del><ins>+                m_heaps.Subspace_allocatorForSizeStep,
</ins><span class="cx">                 subspace, m_out.sub(sizeClassIndex, m_out.intPtrOne)));
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    LValue allocatorForSize(MarkedSpace::Subspace&amp; subspace, LValue size, LBasicBlock slowPath)
</del><ins>+    LValue allocatorForSize(Subspace&amp; subspace, LValue size, LBasicBlock slowPath)
</ins><span class="cx">     {
</span><span class="cx">         return allocatorForSize(m_out.constIntPtr(&amp;subspace), size, slowPath);
</span><span class="cx">     }
</span><span class="lines">@@ -10594,7 +10592,7 @@
</span><span class="cx">         LValue size, Structure* structure, LValue butterfly, LBasicBlock slowPath)
</span><span class="cx">     {
</span><span class="cx">         LValue allocator = allocatorForSize(
</span><del>-            vm().heap.subspaceForObjectOfType&lt;ClassType&gt;(), size, slowPath);
</del><ins>+            *subspaceFor&lt;ClassType&gt;(vm()), size, slowPath);
</ins><span class="cx">         return allocateObject(allocator, structure, butterfly, slowPath);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -10603,7 +10601,7 @@
</span><span class="cx">         LValue size, Structure* structure, LBasicBlock slowPath)
</span><span class="cx">     {
</span><span class="cx">         LValue allocator = allocatorForSize(
</span><del>-            vm().heap.subspaceForObjectOfType&lt;ClassType&gt;(), size, slowPath);
</del><ins>+            *subspaceFor&lt;ClassType&gt;(vm()), size, slowPath);
</ins><span class="cx">         return allocateCell(allocator, structure, slowPath);
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -10610,7 +10608,7 @@
</span><span class="cx">     LValue allocateObject(Structure* structure)
</span><span class="cx">     {
</span><span class="cx">         size_t allocationSize = JSFinalObject::allocationSize(structure-&gt;inlineCapacity());
</span><del>-        MarkedAllocator* allocator = vm().heap.allocatorForObjectWithoutDestructor(allocationSize);
</del><ins>+        MarkedAllocator* allocator = subspaceFor&lt;JSFinalObject&gt;(vm())-&gt;allocatorFor(allocationSize);
</ins><span class="cx">         
</span><span class="cx">         // FIXME: If the allocator is null, we could simply emit a normal C call to the allocator
</span><span class="cx">         // instead of putting it on the slow path.
</span><span class="lines">@@ -10712,8 +10710,7 @@
</span><span class="cx">         LValue butterflySize = m_out.add(
</span><span class="cx">             payloadSize, m_out.constIntPtr(sizeof(IndexingHeader)));
</span><span class="cx">             
</span><del>-        LValue allocator = allocatorForSize(
-            vm().heap.subspaceForAuxiliaryData(), butterflySize, failCase);
</del><ins>+        LValue allocator = allocatorForSize(vm().auxiliarySpace, butterflySize, failCase);
</ins><span class="cx">         LValue startOfStorage = allocateHeapCell(allocator, failCase);
</span><span class="cx">             
</span><span class="cx">         LValue butterfly = m_out.add(startOfStorage, m_out.constIntPtr(sizeof(IndexingHeader)));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapAllocatorAttributesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/AllocatorAttributes.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/AllocatorAttributes.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/AllocatorAttributes.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -25,6 +25,7 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><ins>+#include &quot;ConstraintVolatility.h&quot;
</ins><span class="cx"> #include &quot;DestructionMode.h&quot;
</span><span class="cx"> #include &quot;HeapCell.h&quot;
</span><span class="cx"> #include &lt;wtf/PrintStream.h&gt;
</span><span class="lines">@@ -34,6 +35,12 @@
</span><span class="cx"> struct AllocatorAttributes {
</span><span class="cx">     AllocatorAttributes() { }
</span><span class="cx">     
</span><ins>+    AllocatorAttributes(DestructionMode destruction, HeapCell::Kind cellKind)
+        : destruction(destruction)
+        , cellKind(cellKind)
+    {
+    }
+    
</ins><span class="cx">     void dump(PrintStream&amp; out) const;
</span><span class="cx">     
</span><span class="cx">     DestructionMode destruction { DoesNotNeedDestruction };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapConstraintVolatilityh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/ConstraintVolatility.h (0 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/ConstraintVolatility.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/heap/ConstraintVolatility.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -0,0 +1,73 @@
</span><ins>+/*
+ * Copyright (C) 2017 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.
+ */
+
+#pragma once
+
+#include &lt;wtf/PrintStream.h&gt;
+
+namespace JSC {
+
+enum class ConstraintVolatility : uint8_t {
+    // The constraint needs to be validated, but it is unlikely to ever produce information.
+    // It's best to run it at the bitter end.
+    SeldomGreyed,
+    
+    // FIXME: We could introduce a new kind of volatility called GreyedByResumption, which
+    // would mean running all of the times that GreyedByExecution runs except as a root in a
+    // full GC.
+    // https://bugs.webkit.org/show_bug.cgi?id=166830
+    
+    // The constraint needs to be reevaluated anytime the mutator runs: so at GC start and
+    // whenever the GC resuspends after a resumption. This is almost always something that
+    // you'd call a &quot;root&quot; in a traditional GC.
+    GreyedByExecution,
+    
+    // The constraint needs to be reevaluated any time any object is marked and anytime the
+    // mutator resumes.
+    GreyedByMarking
+};
+    
+} // namespace JSC
+
+namespace WTF {
+
+inline void printInternal(PrintStream&amp; out, JSC::ConstraintVolatility volatility)
+{
+    switch (volatility) {
+    case JSC::ConstraintVolatility::SeldomGreyed:
+        out.print(&quot;SeldomGreyed&quot;);
+        return;
+    case JSC::ConstraintVolatility::GreyedByExecution:
+        out.print(&quot;GreyedByExecuction&quot;);
+        return;
+    case JSC::ConstraintVolatility::GreyedByMarking:
+        out.print(&quot;GreyedByMarking&quot;);
+        return;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+} // namespace WTF
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapGCActivityCallbackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/GCActivityCallback.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/GCActivityCallback.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/GCActivityCallback.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2010 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2010-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -29,7 +29,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;GCActivityCallback.h&quot;
</span><span class="cx"> 
</span><del>-#include &quot;Heap.h&quot;
</del><ins>+#include &quot;HeapInlines.h&quot;
</ins><span class="cx"> #include &quot;JSLock.h&quot;
</span><span class="cx"> #include &quot;JSObject.h&quot;
</span><span class="cx"> #include &quot;VM.h&quot;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -192,7 +192,7 @@
</span><span class="cx">             double timing = after - m_before;
</span><span class="cx">             SimpleStats&amp; stats = timingStats(m_name, *m_scope);
</span><span class="cx">             stats.add(timing);
</span><del>-            dataLog(&quot;[GC:&quot;, *m_scope, &quot;] &quot;, m_name, &quot; took: &quot;, timing, &quot; ms (average &quot;, stats.mean(), &quot; ms).\n&quot;);
</del><ins>+            dataLog(&quot;[GC:&quot;, *m_scope, &quot;] &quot;, m_name, &quot; took: &quot;, timing, &quot;ms (average &quot;, stats.mean(), &quot;ms).\n&quot;);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> private:
</span><span class="lines">@@ -260,6 +260,7 @@
</span><span class="cx">     , m_collectorSlotVisitor(std::make_unique&lt;SlotVisitor&gt;(*this))
</span><span class="cx">     , m_mutatorMarkStack(std::make_unique&lt;MarkStackArray&gt;())
</span><span class="cx">     , m_raceMarkStack(std::make_unique&lt;MarkStackArray&gt;())
</span><ins>+    , m_constraintSet(std::make_unique&lt;MarkingConstraintSet&gt;())
</ins><span class="cx">     , m_handleSet(vm)
</span><span class="cx">     , m_codeBlocks(std::make_unique&lt;CodeBlockSet&gt;())
</span><span class="cx">     , m_jitStubRoutines(std::make_unique&lt;JITStubRoutineSet&gt;())
</span><span class="lines">@@ -361,6 +362,7 @@
</span><span class="cx">     
</span><span class="cx">     m_arrayBuffers.lastChanceToFinalize();
</span><span class="cx">     m_codeBlocks-&gt;lastChanceToFinalize();
</span><ins>+    m_objectSpace.stopAllocating();
</ins><span class="cx">     m_objectSpace.lastChanceToFinalize();
</span><span class="cx">     releaseDelayedReleasedObjects();
</span><span class="cx"> 
</span><span class="lines">@@ -585,13 +587,21 @@
</span><span class="cx">     // checks because bootstrap would have put things into the visitor. So, we should fall
</span><span class="cx">     // through to draining.
</span><span class="cx">     
</span><del>-    for (unsigned iteration = 1; ; ++iteration) {
</del><ins>+    unsigned iteration = 1;
+    for (;;) {
</ins><span class="cx">         if (Options::logGC())
</span><del>-            dataLog(&quot;i#&quot;, iteration, &quot; b=&quot;, m_barriersExecuted, &quot; &quot;);
</del><ins>+            dataLog(&quot;v=&quot;, bytesVisited() / 1024, &quot;kb o=&quot;, m_opaqueRoots.size(), &quot; b=&quot;, m_barriersExecuted, &quot; &quot;);
</ins><span class="cx">         
</span><span class="cx">         if (slotVisitor.didReachTermination()) {
</span><ins>+            if (Options::logGC())
+                dataLog(&quot;i#&quot;, iteration, &quot; &quot;);
+        
</ins><span class="cx">             assertSharedMarkStacksEmpty();
</span><span class="cx">             
</span><ins>+            slotVisitor.mergeIfNecessary();
+            for (auto&amp; parallelVisitor : m_parallelSlotVisitors)
+                parallelVisitor-&gt;mergeIfNecessary();
+            
</ins><span class="cx">             // FIXME: Take m_mutatorDidRun into account when scheduling constraints. Most likely,
</span><span class="cx">             // we don't have to execute root constraints again unless the mutator did run. At a
</span><span class="cx">             // minimum, we could use this for work estimates - but it's probably more than just an
</span><span class="lines">@@ -603,14 +613,15 @@
</span><span class="cx">             // when we have deep stacks or a lot of DOM stuff.
</span><span class="cx">             // https://bugs.webkit.org/show_bug.cgi?id=166831
</span><span class="cx">             
</span><del>-            bool executedEverything =
</del><ins>+            bool converged =
</ins><span class="cx">                 m_constraintSet-&gt;executeConvergence(slotVisitor, MonotonicTime::infinity());
</span><del>-            if (executedEverything &amp;&amp; slotVisitor.isEmpty()) {
</del><ins>+            if (converged &amp;&amp; slotVisitor.isEmpty()) {
</ins><span class="cx">                 assertSharedMarkStacksEmpty();
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             
</span><span class="cx">             m_scheduler-&gt;didExecuteConstraints();
</span><ins>+            iteration++;
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         if (Options::logGC())
</span><span class="lines">@@ -628,7 +639,7 @@
</span><span class="cx">         
</span><span class="cx">         if (Options::logGC()) {
</span><span class="cx">             double thisPauseMS = (MonotonicTime::now() - m_stopTime).milliseconds();
</span><del>-            dataLog(&quot;p=&quot;, thisPauseMS, &quot; ms (max &quot;, maxPauseMS(thisPauseMS), &quot;)...]\n&quot;);
</del><ins>+            dataLog(&quot;p=&quot;, thisPauseMS, &quot;ms (max &quot;, maxPauseMS(thisPauseMS), &quot;)...]\n&quot;);
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         resumeTheWorld();
</span><span class="lines">@@ -780,9 +791,7 @@
</span><span class="cx">     if (m_collectionScope == CollectionScope::Full)
</span><span class="cx">         m_totalBytesVisited = 0;
</span><span class="cx"> 
</span><del>-    m_totalBytesVisitedThisCycle =
-        m_collectorSlotVisitor-&gt;bytesVisited() +
-        threadBytesVisited();
</del><ins>+    m_totalBytesVisitedThisCycle = bytesVisited();
</ins><span class="cx">     
</span><span class="cx">     m_totalBytesVisited += m_totalBytesVisitedThisCycle;
</span><span class="cx"> }
</span><span class="lines">@@ -1011,7 +1020,7 @@
</span><span class="cx">     else {
</span><span class="cx">         double before = 0;
</span><span class="cx">         if (Options::logGC()) {
</span><del>-            dataLog(&quot;[Full sweep: &quot;, capacity() / 1024, &quot; kb &quot;);
</del><ins>+            dataLog(&quot;[Full sweep: &quot;, capacity() / 1024, &quot;kb &quot;);
</ins><span class="cx">             before = currentTimeMS();
</span><span class="cx">         }
</span><span class="cx">         m_objectSpace.sweep();
</span><span class="lines">@@ -1018,7 +1027,7 @@
</span><span class="cx">         m_objectSpace.shrink();
</span><span class="cx">         if (Options::logGC()) {
</span><span class="cx">             double after = currentTimeMS();
</span><del>-            dataLog(&quot;=&gt; &quot;, capacity() / 1024, &quot; kb, &quot;, after - before, &quot; ms]\n&quot;);
</del><ins>+            dataLog(&quot;=&gt; &quot;, capacity() / 1024, &quot;kb, &quot;, after - before, &quot;ms]\n&quot;);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     m_objectSpace.assertNoUnswept();
</span><span class="lines">@@ -1101,7 +1110,7 @@
</span><span class="cx"> 
</span><span class="cx">     MonotonicTime before;
</span><span class="cx">     if (Options::logGC()) {
</span><del>-        dataLog(&quot;[GC: START &quot;, capacity() / 1024, &quot; kb &quot;);
</del><ins>+        dataLog(&quot;[GC: START &quot;, capacity() / 1024, &quot;kb &quot;);
</ins><span class="cx">         before = MonotonicTime::now();
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -1170,7 +1179,7 @@
</span><span class="cx">     if (Options::logGC()) {
</span><span class="cx">         MonotonicTime after = MonotonicTime::now();
</span><span class="cx">         double thisPauseMS = (after - m_stopTime).milliseconds();
</span><del>-        dataLog(&quot;p=&quot;, thisPauseMS, &quot; ms (max &quot;, maxPauseMS(thisPauseMS), &quot;), cycle &quot;, (after - before).milliseconds(), &quot; ms END]\n&quot;);
</del><ins>+        dataLog(&quot;p=&quot;, thisPauseMS, &quot;ms (max &quot;, maxPauseMS(thisPauseMS), &quot;), cycle &quot;, (after - before).milliseconds(), &quot;ms END]\n&quot;);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     {
</span><span class="lines">@@ -1196,6 +1205,12 @@
</span><span class="cx">     RELEASE_ASSERT(!m_collectorBelievesThatTheWorldIsStopped);
</span><span class="cx">     waitWhileNeedFinalize();
</span><span class="cx">     stopTheMutator();
</span><ins>+    
+    if (m_mutatorDidRun)
+        m_mutatorExecutionVersion++;
+    
+    m_mutatorDidRun = false;
+    
</ins><span class="cx">     suspendCompilerThreads();
</span><span class="cx">     m_collectorBelievesThatTheWorldIsStopped = true;
</span><span class="cx"> 
</span><span class="lines">@@ -1769,7 +1784,7 @@
</span><span class="cx">     m_bytesAllocatedThisCycle = 0;
</span><span class="cx"> 
</span><span class="cx">     if (Options::logGC())
</span><del>-        dataLog(&quot;=&gt; &quot;, currentHeapSize / 1024, &quot; kb, &quot;);
</del><ins>+        dataLog(&quot;=&gt; &quot;, currentHeapSize / 1024, &quot;kb, &quot;);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Heap::didFinishCollection(double gcStartTime)
</span><span class="lines">@@ -1976,6 +1991,11 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+size_t Heap::bytesVisited()
+{
+    return m_collectorSlotVisitor-&gt;bytesVisited() + threadBytesVisited();
+}
+
</ins><span class="cx"> size_t Heap::threadBytesVisited()
</span><span class="cx"> {       
</span><span class="cx">     size_t result = 0;
</span><span class="lines">@@ -2125,10 +2145,8 @@
</span><span class="cx"> }
</span><span class="cx"> #endif // USE(CF)
</span><span class="cx"> 
</span><del>-void Heap::buildConstraintSet()
</del><ins>+void Heap::addCoreConstraints()
</ins><span class="cx"> {
</span><del>-    m_constraintSet = std::make_unique&lt;MarkingConstraintSet&gt;();
-    
</del><span class="cx">     m_constraintSet-&gt;add(
</span><span class="cx">         &quot;Cs&quot;, &quot;Conservative Scan&quot;,
</span><span class="cx">         [this] (SlotVisitor&amp; slotVisitor, const VisitingTimeout&amp;) {
</span><span class="lines">@@ -2141,7 +2159,7 @@
</span><span class="cx">             gatherScratchBufferRoots(conservativeRoots);
</span><span class="cx">             slotVisitor.append(conservativeRoots);
</span><span class="cx">         },
</span><del>-        MarkingConstraint::GreyedByExecution);
</del><ins>+        ConstraintVolatility::GreyedByExecution);
</ins><span class="cx">     
</span><span class="cx">     m_constraintSet-&gt;add(
</span><span class="cx">         &quot;Msr&quot;, &quot;Misc Small Roots&quot;,
</span><span class="lines">@@ -2162,7 +2180,7 @@
</span><span class="cx">             slotVisitor.appendUnbarriered(m_vm-&gt;exception());
</span><span class="cx">             slotVisitor.appendUnbarriered(m_vm-&gt;lastException());
</span><span class="cx">         },
</span><del>-        MarkingConstraint::GreyedByExecution);
</del><ins>+        ConstraintVolatility::GreyedByExecution);
</ins><span class="cx">     
</span><span class="cx">     m_constraintSet-&gt;add(
</span><span class="cx">         &quot;Sh&quot;, &quot;Strong Handles&quot;,
</span><span class="lines">@@ -2170,7 +2188,7 @@
</span><span class="cx">             m_handleSet.visitStrongHandles(slotVisitor);
</span><span class="cx">             m_handleStack.visit(slotVisitor);
</span><span class="cx">         },
</span><del>-        MarkingConstraint::GreyedByExecution);
</del><ins>+        ConstraintVolatility::GreyedByExecution);
</ins><span class="cx">     
</span><span class="cx">     m_constraintSet-&gt;add(
</span><span class="cx">         &quot;D&quot;, &quot;Debugger&quot;,
</span><span class="lines">@@ -2190,7 +2208,7 @@
</span><span class="cx">             
</span><span class="cx">             m_vm-&gt;shadowChicken().visitChildren(slotVisitor);
</span><span class="cx">         },
</span><del>-        MarkingConstraint::GreyedByExecution);
</del><ins>+        ConstraintVolatility::GreyedByExecution);
</ins><span class="cx">     
</span><span class="cx">     m_constraintSet-&gt;add(
</span><span class="cx">         &quot;Jsr&quot;, &quot;JIT Stub Routines&quot;,
</span><span class="lines">@@ -2197,18 +2215,14 @@
</span><span class="cx">         [this] (SlotVisitor&amp; slotVisitor, const VisitingTimeout&amp;) {
</span><span class="cx">             m_jitStubRoutines-&gt;traceMarkedStubRoutines(slotVisitor);
</span><span class="cx">         },
</span><del>-        MarkingConstraint::GreyedByExecution);
</del><ins>+        ConstraintVolatility::GreyedByExecution);
</ins><span class="cx">     
</span><span class="cx">     m_constraintSet-&gt;add(
</span><span class="cx">         &quot;Ws&quot;, &quot;Weak Sets&quot;,
</span><span class="cx">         [this] (SlotVisitor&amp; slotVisitor, const VisitingTimeout&amp;) {
</span><del>-            slotVisitor.mergeOpaqueRootsIfNecessary();
-            for (auto&amp; parallelVisitor : m_parallelSlotVisitors)
-                parallelVisitor-&gt;mergeOpaqueRootsIfNecessary();
-            
</del><span class="cx">             m_objectSpace.visitWeakSets(slotVisitor);
</span><span class="cx">         },
</span><del>-        MarkingConstraint::GreyedByMarking);
</del><ins>+        ConstraintVolatility::GreyedByMarking);
</ins><span class="cx">     
</span><span class="cx">     m_constraintSet-&gt;add(
</span><span class="cx">         &quot;Wrh&quot;, &quot;Weak Reference Harvesters&quot;,
</span><span class="lines">@@ -2216,7 +2230,7 @@
</span><span class="cx">             for (WeakReferenceHarvester* current = m_weakReferenceHarvesters.head(); current; current = current-&gt;next())
</span><span class="cx">                 current-&gt;visitWeakReferences(slotVisitor);
</span><span class="cx">         },
</span><del>-        MarkingConstraint::GreyedByMarking);
</del><ins>+        ConstraintVolatility::GreyedByMarking);
</ins><span class="cx">     
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     m_constraintSet-&gt;add(
</span><span class="lines">@@ -2236,7 +2250,7 @@
</span><span class="cx">             if (Options::logGC() == GCLogging::Verbose)
</span><span class="cx">                 dataLog(&quot;DFG Worklists:\n&quot;, slotVisitor);
</span><span class="cx">         },
</span><del>-        MarkingConstraint::GreyedByMarking);
</del><ins>+        ConstraintVolatility::GreyedByMarking);
</ins><span class="cx"> #endif
</span><span class="cx">     
</span><span class="cx">     m_constraintSet-&gt;add(
</span><span class="lines">@@ -2250,7 +2264,7 @@
</span><span class="cx">                         slotVisitor.visitAsConstraint(codeBlock);
</span><span class="cx">                 });
</span><span class="cx">         },
</span><del>-        MarkingConstraint::GreyedByExecution);
</del><ins>+        ConstraintVolatility::SeldomGreyed);
</ins><span class="cx">     
</span><span class="cx">     m_constraintSet-&gt;add(
</span><span class="cx">         &quot;Mrms&quot;, &quot;Mutator+Race Mark Stack&quot;,
</span><span class="lines">@@ -2268,12 +2282,18 @@
</span><span class="cx">         [this] (SlotVisitor&amp;) -&gt; double {
</span><span class="cx">             return m_mutatorMarkStack-&gt;size() + m_raceMarkStack-&gt;size();
</span><span class="cx">         },
</span><del>-        MarkingConstraint::GreyedByExecution);
</del><ins>+        ConstraintVolatility::GreyedByExecution);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Heap::addMarkingConstraint(std::unique_ptr&lt;MarkingConstraint&gt; constraint)
+{
+    PreventCollectionScope preventCollectionScope(*this);
+    m_constraintSet-&gt;add(WTFMove(constraint));
+}
+
</ins><span class="cx"> void Heap::notifyIsSafeToCollect()
</span><span class="cx"> {
</span><del>-    buildConstraintSet();
</del><ins>+    addCoreConstraints();
</ins><span class="cx">     
</span><span class="cx">     m_isSafeToCollect = true;
</span><span class="cx">     
</span><span class="lines">@@ -2311,6 +2331,9 @@
</span><span class="cx"> 
</span><span class="cx"> void Heap::preventCollection()
</span><span class="cx"> {
</span><ins>+    if (!m_isSafeToCollect)
+        return;
+    
</ins><span class="cx">     // This prevents the collectContinuously thread from starting a collection.
</span><span class="cx">     m_collectContinuouslyLock.lock();
</span><span class="cx">     
</span><span class="lines">@@ -2327,6 +2350,9 @@
</span><span class="cx"> 
</span><span class="cx"> void Heap::allowCollection()
</span><span class="cx"> {
</span><ins>+    if (!m_isSafeToCollect)
+        return;
+    
</ins><span class="cx">     m_collectContinuouslyLock.unlock();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2339,27 +2365,10 @@
</span><span class="cx">         func(*slotVisitor);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::writeBarrierOpaqueRootSlow(void* root)
-{
-    ASSERT(mutatorShouldBeFenced());
-    
-    auto locker = holdLock(m_opaqueRootsMutex);
-    m_opaqueRoots.add(root);
-}
-
-void Heap::addMutatorShouldBeFencedCache(bool&amp; cache)
-{
-    ASSERT(hasHeapAccess());
-    cache = m_mutatorShouldBeFenced;
-    m_mutatorShouldBeFencedCaches.append(&amp;cache);
-}
-
</del><span class="cx"> void Heap::setMutatorShouldBeFenced(bool value)
</span><span class="cx"> {
</span><span class="cx">     m_mutatorShouldBeFenced = value;
</span><span class="cx">     m_barrierThreshold = value ? tautologicalThreshold : blackThreshold;
</span><del>-    for (bool* cache : m_mutatorShouldBeFencedCaches)
-        *cache = value;
</del><span class="cx"> }
</span><span class="cx">     
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/Heap.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -31,7 +31,6 @@
</span><span class="cx"> #include &quot;HeapObserver.h&quot;
</span><span class="cx"> #include &quot;ListableHandler.h&quot;
</span><span class="cx"> #include &quot;MachineStackMarker.h&quot;
</span><del>-#include &quot;MarkedAllocator.h&quot;
</del><span class="cx"> #include &quot;MarkedBlock.h&quot;
</span><span class="cx"> #include &quot;MarkedBlockSet.h&quot;
</span><span class="cx"> #include &quot;MarkedSpace.h&quot;
</span><span class="lines">@@ -71,7 +70,9 @@
</span><span class="cx"> class JSValue;
</span><span class="cx"> class LLIntOffsetsExtractor;
</span><span class="cx"> class MarkStackArray;
</span><ins>+class MarkedAllocator;
</ins><span class="cx"> class MarkedArgumentBuffer;
</span><ins>+class MarkingConstraint;
</ins><span class="cx"> class MarkingConstraintSet;
</span><span class="cx"> class MutatorScheduler;
</span><span class="cx"> class SlotVisitor;
</span><span class="lines">@@ -124,17 +125,16 @@
</span><span class="cx">     // Take this if you know that from-&gt;cellState() &lt; barrierThreshold.
</span><span class="cx">     JS_EXPORT_PRIVATE void writeBarrierSlowPath(const JSCell* from);
</span><span class="cx"> 
</span><del>-    void writeBarrierOpaqueRoot(void*);
-
</del><span class="cx">     Heap(VM*, HeapType);
</span><span class="cx">     ~Heap();
</span><span class="cx">     void lastChanceToFinalize();
</span><span class="cx">     void releaseDelayedReleasedObjects();
</span><span class="cx"> 
</span><ins>+    VM* vm() const;
+
</ins><span class="cx">     // Set a hard limit where JSC will crash if live heap size exceeds it.
</span><span class="cx">     void setMaxLiveSize(size_t size) { m_maxLiveSize = size; }
</span><span class="cx"> 
</span><del>-    VM* vm() const { return m_vm; }
</del><span class="cx">     MarkedSpace&amp; objectSpace() { return m_objectSpace; }
</span><span class="cx">     MachineThreads&amp; machineThreads() { return m_machineThreads; }
</span><span class="cx"> 
</span><span class="lines">@@ -159,20 +159,6 @@
</span><span class="cx">     // helping heap.
</span><span class="cx">     JS_EXPORT_PRIVATE bool isCurrentThreadBusy();
</span><span class="cx">     
</span><del>-    MarkedSpace::Subspace&amp; subspaceForObjectWithoutDestructor() { return m_objectSpace.subspaceForObjectsWithoutDestructor(); }
-    MarkedSpace::Subspace&amp; subspaceForObjectDestructor() { return m_objectSpace.subspaceForObjectsWithDestructor(); }
-    MarkedSpace::Subspace&amp; subspaceForAuxiliaryData() { return m_objectSpace.subspaceForAuxiliaryData(); }
-    template&lt;typename ClassType&gt; MarkedSpace::Subspace&amp; subspaceForObjectOfType();
-    MarkedAllocator* allocatorForObjectWithoutDestructor(size_t bytes) { return m_objectSpace.allocatorFor(bytes); }
-    MarkedAllocator* allocatorForObjectWithDestructor(size_t bytes) { return m_objectSpace.destructorAllocatorFor(bytes); }
-    template&lt;typename ClassType&gt; MarkedAllocator* allocatorForObjectOfType(size_t bytes);
-    MarkedAllocator* allocatorForAuxiliaryData(size_t bytes) { return m_objectSpace.auxiliaryAllocatorFor(bytes); }
-    void* allocateAuxiliary(JSCell* intendedOwner, size_t);
-    void* tryAllocateAuxiliary(JSCell* intendedOwner, size_t);
-    void* tryAllocateAuxiliary(GCDeferralContext*, JSCell* intendedOwner, size_t);
-    void* tryReallocateAuxiliary(JSCell* intendedOwner, void* oldBase, size_t oldSize, size_t newSize);
-    void ascribeOwner(JSCell* intendedOwner, void*);
-
</del><span class="cx">     typedef void (*Finalizer)(JSCell*);
</span><span class="cx">     JS_EXPORT_PRIVATE void addFinalizer(JSCell*, Finalizer);
</span><span class="cx">     void addExecutable(ExecutableBase*);
</span><span class="lines">@@ -350,8 +336,14 @@
</span><span class="cx">     void preventCollection();
</span><span class="cx">     void allowCollection();
</span><span class="cx">     
</span><del>-    JS_EXPORT_PRIVATE void addMutatorShouldBeFencedCache(bool&amp;);
</del><ins>+    size_t bytesVisited();
</ins><span class="cx">     
</span><ins>+    uint64_t mutatorExecutionVersion() const { return m_mutatorExecutionVersion; }
+    
+    JS_EXPORT_PRIVATE void addMarkingConstraint(std::unique_ptr&lt;MarkingConstraint&gt;);
+    
+    size_t numOpaqueRoots() const { return m_opaqueRoots.size(); }
+
</ins><span class="cx"> #if USE(CF)
</span><span class="cx">     CFRunLoopRef runLoop() const { return m_runLoop.get(); }
</span><span class="cx">     JS_EXPORT_PRIVATE void setRunLoop(CFRunLoopRef);
</span><span class="lines">@@ -384,18 +376,6 @@
</span><span class="cx">     class Thread;
</span><span class="cx">     friend class Thread;
</span><span class="cx"> 
</span><del>-    template&lt;typename T&gt; friend void* allocateCell(Heap&amp;);
-    template&lt;typename T&gt; friend void* allocateCell(Heap&amp;, size_t);
-    template&lt;typename T&gt; friend void* allocateCell(Heap&amp;, GCDeferralContext*);
-    template&lt;typename T&gt; friend void* allocateCell(Heap&amp;, GCDeferralContext*, size_t);
-
-    void* allocateWithDestructor(size_t); // For use with objects with destructors.
-    void* allocateWithoutDestructor(size_t); // For use with objects without destructors.
-    void* allocateWithDestructor(GCDeferralContext*, size_t);
-    void* allocateWithoutDestructor(GCDeferralContext*, size_t);
-    template&lt;typename ClassType&gt; void* allocateObjectOfType(size_t); // Chooses one of the methods above based on type.
-    template&lt;typename ClassType&gt; void* allocateObjectOfType(GCDeferralContext*, size_t);
-
</del><span class="cx">     static const size_t minExtraMemory = 256;
</span><span class="cx">     
</span><span class="cx">     class FinalizerOwner : public WeakHandleOwner {
</span><span class="lines">@@ -490,11 +470,9 @@
</span><span class="cx">     
</span><span class="cx">     void forEachCodeBlockImpl(const ScopedLambda&lt;bool(CodeBlock*)&gt;&amp;);
</span><span class="cx">     
</span><del>-    JS_EXPORT_PRIVATE void writeBarrierOpaqueRootSlow(void*);
-    
</del><span class="cx">     void setMutatorShouldBeFenced(bool value);
</span><span class="cx">     
</span><del>-    void buildConstraintSet();
</del><ins>+    void addCoreConstraints();
</ins><span class="cx">     
</span><span class="cx">     template&lt;typename Func&gt;
</span><span class="cx">     void iterateExecutingAndCompilingCodeBlocks(const Func&amp;);
</span><span class="lines">@@ -566,7 +544,6 @@
</span><span class="cx"> 
</span><span class="cx">     bool m_mutatorShouldBeFenced { Options::forceFencedBarrier() };
</span><span class="cx">     unsigned m_barrierThreshold { Options::forceFencedBarrier() ? tautologicalThreshold : blackThreshold };
</span><del>-    Vector&lt;bool*&gt; m_mutatorShouldBeFencedCaches;
</del><span class="cx"> 
</span><span class="cx">     VM* m_vm;
</span><span class="cx">     double m_lastFullGCLength;
</span><span class="lines">@@ -610,7 +587,7 @@
</span><span class="cx">     bool m_parallelMarkersShouldExit { false };
</span><span class="cx"> 
</span><span class="cx">     Lock m_opaqueRootsMutex;
</span><del>-    HashSet&lt;void*&gt; m_opaqueRoots;
</del><ins>+    HashSet&lt;const void*&gt; m_opaqueRoots;
</ins><span class="cx"> 
</span><span class="cx">     static const size_t s_blockFragmentLength = 32;
</span><span class="cx"> 
</span><span class="lines">@@ -645,6 +622,7 @@
</span><span class="cx">     bool m_threadShouldStop { false };
</span><span class="cx">     bool m_threadIsStopping { false };
</span><span class="cx">     bool m_mutatorDidRun { true };
</span><ins>+    uint64_t m_mutatorExecutionVersion { 0 };
</ins><span class="cx">     Box&lt;Lock&gt; m_threadLock;
</span><span class="cx">     RefPtr&lt;AutomaticThreadCondition&gt; m_threadCondition; // The mutator must not wait on this. It would cause a deadlock.
</span><span class="cx">     RefPtr&lt;AutomaticThread&gt; m_thread;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/HeapInlines.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapInlines.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/HeapInlines.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -39,6 +39,11 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE VM* Heap::vm() const
+{
+    return bitwise_cast&lt;VM*&gt;(bitwise_cast&lt;uintptr_t&gt;(this) - OBJECT_OFFSETOF(VM, heap));
+}
+
</ins><span class="cx"> ALWAYS_INLINE Heap* Heap::heap(const HeapCell* cell)
</span><span class="cx"> {
</span><span class="cx">     return cell-&gt;heap();
</span><span class="lines">@@ -175,136 +180,6 @@
</span><span class="cx">     m_handleSet.forEachStrongHandle(functor, m_protectedValues);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void* Heap::allocateWithDestructor(size_t bytes)
-{
-#if ENABLE(ALLOCATION_LOGGING)
-    dataLogF(&quot;JSC GC allocating %lu bytes with normal destructor.\n&quot;, bytes);
-#endif
-    ASSERT(isValidAllocation(bytes));
-    return m_objectSpace.allocateWithDestructor(bytes);
-}
-
-inline void* Heap::allocateWithoutDestructor(size_t bytes)
-{
-#if ENABLE(ALLOCATION_LOGGING)
-    dataLogF(&quot;JSC GC allocating %lu bytes without destructor.\n&quot;, bytes);
-#endif
-    ASSERT(isValidAllocation(bytes));
-    return m_objectSpace.allocateWithoutDestructor(bytes);
-}
-
-inline void* Heap::allocateWithDestructor(GCDeferralContext* deferralContext, size_t bytes)
-{
-    ASSERT(isValidAllocation(bytes));
-    return m_objectSpace.allocateWithDestructor(deferralContext, bytes);
-}
-
-inline void* Heap::allocateWithoutDestructor(GCDeferralContext* deferralContext, size_t bytes)
-{
-    ASSERT(isValidAllocation(bytes));
-    return m_objectSpace.allocateWithoutDestructor(deferralContext, bytes);
-}
-
-template&lt;typename ClassType&gt;
-inline void* Heap::allocateObjectOfType(size_t bytes)
-{
-    // JSCell::classInfo() expects objects allocated with normal destructor to derive from JSDestructibleObject.
-    ASSERT((!ClassType::needsDestruction || (ClassType::StructureFlags &amp; StructureIsImmortal) || std::is_convertible&lt;ClassType, JSDestructibleObject&gt;::value));
-
-    if (ClassType::needsDestruction)
-        return allocateWithDestructor(bytes);
-    return allocateWithoutDestructor(bytes);
-}
-
-template&lt;typename ClassType&gt;
-inline void* Heap::allocateObjectOfType(GCDeferralContext* deferralContext, size_t bytes)
-{
-    ASSERT((!ClassType::needsDestruction || (ClassType::StructureFlags &amp; StructureIsImmortal) || std::is_convertible&lt;ClassType, JSDestructibleObject&gt;::value));
-
-    if (ClassType::needsDestruction)
-        return allocateWithDestructor(deferralContext, bytes);
-    return allocateWithoutDestructor(deferralContext, bytes);
-}
-
-template&lt;typename ClassType&gt;
-inline MarkedSpace::Subspace&amp; Heap::subspaceForObjectOfType()
-{
-    // JSCell::classInfo() expects objects allocated with normal destructor to derive from JSDestructibleObject.
-    ASSERT((!ClassType::needsDestruction || (ClassType::StructureFlags &amp; StructureIsImmortal) || std::is_convertible&lt;ClassType, JSDestructibleObject&gt;::value));
-    
-    if (ClassType::needsDestruction)
-        return subspaceForObjectDestructor();
-    return subspaceForObjectWithoutDestructor();
-}
-
-template&lt;typename ClassType&gt;
-inline MarkedAllocator* Heap::allocatorForObjectOfType(size_t bytes)
-{
-    // JSCell::classInfo() expects objects allocated with normal destructor to derive from JSDestructibleObject.
-    ASSERT((!ClassType::needsDestruction || (ClassType::StructureFlags &amp; StructureIsImmortal) || std::is_convertible&lt;ClassType, JSDestructibleObject&gt;::value));
-
-    MarkedAllocator* result;
-    if (ClassType::needsDestruction)
-        result = allocatorForObjectWithDestructor(bytes);
-    else
-        result = allocatorForObjectWithoutDestructor(bytes);
-    
-    ASSERT(result || !ClassType::info()-&gt;isSubClassOf(JSCallee::info()));
-    return result;
-}
-
-inline void* Heap::allocateAuxiliary(JSCell* intendedOwner, size_t bytes)
-{
-    void* result = m_objectSpace.allocateAuxiliary(bytes);
-#if ENABLE(ALLOCATION_LOGGING)
-    dataLogF(&quot;JSC GC allocating %lu bytes of auxiliary for %p: %p.\n&quot;, bytes, intendedOwner, result);
-#else
-    UNUSED_PARAM(intendedOwner);
-#endif
-    return result;
-}
-
-inline void* Heap::tryAllocateAuxiliary(JSCell* intendedOwner, size_t bytes)
-{
-    void* result = m_objectSpace.tryAllocateAuxiliary(bytes);
-#if ENABLE(ALLOCATION_LOGGING)
-    dataLogF(&quot;JSC GC allocating %lu bytes of auxiliary for %p: %p.\n&quot;, bytes, intendedOwner, result);
-#else
-    UNUSED_PARAM(intendedOwner);
-#endif
-    return result;
-}
-
-inline void* Heap::tryAllocateAuxiliary(GCDeferralContext* deferralContext, JSCell* intendedOwner, size_t bytes)
-{
-    void* result = m_objectSpace.tryAllocateAuxiliary(deferralContext, bytes);
-#if ENABLE(ALLOCATION_LOGGING)
-    dataLogF(&quot;JSC GC allocating %lu bytes of auxiliary for %p: %p.\n&quot;, bytes, intendedOwner, result);
-#else
-    UNUSED_PARAM(intendedOwner);
-#endif
-    return result;
-}
-
-inline void* Heap::tryReallocateAuxiliary(JSCell* intendedOwner, void* oldBase, size_t oldSize, size_t newSize)
-{
-    void* newBase = tryAllocateAuxiliary(intendedOwner, newSize);
-    if (!newBase)
-        return nullptr;
-    memcpy(newBase, oldBase, oldSize);
-    return newBase;
-}
-
-inline void Heap::ascribeOwner(JSCell* intendedOwner, void* storage)
-{
-#if ENABLE(ALLOCATION_LOGGING)
-    dataLogF(&quot;JSC GC ascribing %p as owner of storage %p.\n&quot;, intendedOwner, storage);
-#else
-    UNUSED_PARAM(intendedOwner);
-    UNUSED_PARAM(storage);
-#endif
-}
-
</del><span class="cx"> #if USE(FOUNDATION)
</span><span class="cx"> template &lt;typename T&gt;
</span><span class="cx"> inline void Heap::releaseSoon(RetainPtr&lt;T&gt;&amp;&amp; object)
</span><span class="lines">@@ -405,10 +280,4 @@
</span><span class="cx">         stopIfNecessarySlow();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void Heap::writeBarrierOpaqueRoot(void* root)
-{
-    if (mutatorShouldBeFenced())
-        writeBarrierOpaqueRootSlow(root);
-}
-
</del><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapLargeAllocationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/LargeAllocation.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/LargeAllocation.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/LargeAllocation.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -32,7 +32,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-LargeAllocation* LargeAllocation::tryCreate(Heap&amp; heap, size_t size, const AllocatorAttributes&amp; attributes)
</del><ins>+LargeAllocation* LargeAllocation::tryCreate(Heap&amp; heap, size_t size, Subspace* subspace)
</ins><span class="cx"> {
</span><span class="cx">     void* space = tryFastAlignedMalloc(alignment, headerSize() + size);
</span><span class="cx">     if (!space)
</span><span class="lines">@@ -39,19 +39,26 @@
</span><span class="cx">         return nullptr;
</span><span class="cx">     if (scribbleFreeCells())
</span><span class="cx">         scribble(space, size);
</span><del>-    return new (NotNull, space) LargeAllocation(heap, size, attributes);
</del><ins>+    return new (NotNull, space) LargeAllocation(heap, size, subspace);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-LargeAllocation::LargeAllocation(Heap&amp; heap, size_t size, const AllocatorAttributes&amp; attributes)
</del><ins>+LargeAllocation::LargeAllocation(Heap&amp; heap, size_t size, Subspace* subspace)
</ins><span class="cx">     : m_cellSize(size)
</span><span class="cx">     , m_isNewlyAllocated(true)
</span><span class="cx">     , m_hasValidCell(true)
</span><del>-    , m_attributes(attributes)
</del><ins>+    , m_attributes(subspace-&gt;attributes())
+    , m_subspace(subspace)
</ins><span class="cx">     , m_weakSet(heap.vm(), *this)
</span><span class="cx"> {
</span><span class="cx">     m_isMarked.store(0);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+LargeAllocation::~LargeAllocation()
+{
+    if (isOnList())
+        remove();
+}
+
</ins><span class="cx"> void LargeAllocation::lastChanceToFinalize()
</span><span class="cx"> {
</span><span class="cx">     m_weakSet.lastChanceToFinalize();
</span><span class="lines">@@ -92,7 +99,7 @@
</span><span class="cx">     
</span><span class="cx">     if (m_hasValidCell &amp;&amp; !isLive()) {
</span><span class="cx">         if (m_attributes.destruction == NeedsDestruction)
</span><del>-            static_cast&lt;JSCell*&gt;(cell())-&gt;callDestructor(*vm());
</del><ins>+            m_subspace-&gt;destroy(*vm(), static_cast&lt;JSCell*&gt;(cell()));
</ins><span class="cx">         m_hasValidCell = false;
</span><span class="cx">     }
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapLargeAllocationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/LargeAllocation.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/LargeAllocation.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/LargeAllocation.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -37,10 +37,12 @@
</span><span class="cx"> // objects directly using malloc, and put the LargeAllocation header just before them. We can detect
</span><span class="cx"> // when a HeapCell* is a LargeAllocation because it will have the MarkedBlock::atomSize / 2 bit set.
</span><span class="cx"> 
</span><del>-class LargeAllocation {
</del><ins>+class LargeAllocation : public BasicRawSentinelNode&lt;LargeAllocation&gt; {
</ins><span class="cx"> public:
</span><del>-    static LargeAllocation* tryCreate(Heap&amp;, size_t, const AllocatorAttributes&amp;);
</del><ins>+    static LargeAllocation* tryCreate(Heap&amp;, size_t, Subspace*);
</ins><span class="cx">     
</span><ins>+    ~LargeAllocation();
+    
</ins><span class="cx">     static LargeAllocation* fromCell(const void* cell)
</span><span class="cx">     {
</span><span class="cx">         return bitwise_cast&lt;LargeAllocation*&gt;(bitwise_cast&lt;char*&gt;(cell) - headerSize());
</span><span class="lines">@@ -136,7 +138,7 @@
</span><span class="cx">     void dump(PrintStream&amp;) const;
</span><span class="cx">     
</span><span class="cx"> private:
</span><del>-    LargeAllocation(Heap&amp;, size_t, const AllocatorAttributes&amp;);
</del><ins>+    LargeAllocation(Heap&amp;, size_t, Subspace*);
</ins><span class="cx">     
</span><span class="cx">     static const unsigned alignment = MarkedBlock::atomSize;
</span><span class="cx">     static const unsigned halfAlignment = alignment / 2;
</span><span class="lines">@@ -148,6 +150,7 @@
</span><span class="cx">     bool m_hasValidCell;
</span><span class="cx">     Atomic&lt;bool&gt; m_isMarked;
</span><span class="cx">     AllocatorAttributes m_attributes;
</span><ins>+    Subspace* m_subspace;
</ins><span class="cx">     WeakSet m_weakSet;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedAllocatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012, 2013, 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include &quot;Heap.h&quot;
</span><span class="cx"> #include &quot;IncrementalSweeper.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;MarkedAllocatorInlines.h&quot;
</ins><span class="cx"> #include &quot;MarkedBlockInlines.h&quot;
</span><span class="cx"> #include &quot;SuperSampler.h&quot;
</span><span class="cx"> #include &quot;VM.h&quot;
</span><span class="lines">@@ -38,13 +39,13 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-MarkedAllocator::MarkedAllocator(Heap* heap, MarkedSpace* markedSpace, size_t cellSize, const AllocatorAttributes&amp; attributes)
</del><ins>+MarkedAllocator::MarkedAllocator(Heap* heap, Subspace* subspace, size_t cellSize)
</ins><span class="cx">     : m_currentBlock(0)
</span><span class="cx">     , m_lastActiveBlock(0)
</span><span class="cx">     , m_cellSize(static_cast&lt;unsigned&gt;(cellSize))
</span><del>-    , m_attributes(attributes)
</del><ins>+    , m_attributes(subspace-&gt;attributes())
</ins><span class="cx">     , m_heap(heap)
</span><del>-    , m_markedSpace(markedSpace)
</del><ins>+    , m_subspace(subspace)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -111,7 +112,7 @@
</span><span class="cx">     
</span><span class="cx">     if (Options::stealEmptyBlocksFromOtherAllocators()
</span><span class="cx">         &amp;&amp; shouldStealEmptyBlocksFromOtherAllocators()) {
</span><del>-        if (MarkedBlock::Handle* block = m_markedSpace-&gt;findEmptyBlockToSteal()) {
</del><ins>+        if (MarkedBlock::Handle* block = markedSpace().findEmptyBlockToSteal()) {
</ins><span class="cx">             block-&gt;sweep();
</span><span class="cx">             
</span><span class="cx">             // It's good that this clears canAllocateButNotEmpty as well as all other bits,
</span><span class="lines">@@ -166,7 +167,7 @@
</span><span class="cx">     }
</span><span class="cx">     RELEASE_ASSERT(result);
</span><span class="cx">     setIsEden(NoLockingNecessary, m_currentBlock, true);
</span><del>-    m_markedSpace-&gt;didAllocateInBlock(m_currentBlock);
</del><ins>+    markedSpace().didAllocateInBlock(m_currentBlock);
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -206,7 +207,7 @@
</span><span class="cx">     ASSERT(m_heap-&gt;vm()-&gt;currentThreadIsHoldingAPILock());
</span><span class="cx">     doTestCollectionsIfNeeded(deferralContext);
</span><span class="cx"> 
</span><del>-    ASSERT(!m_markedSpace-&gt;isIterating());
</del><ins>+    ASSERT(!markedSpace().isIterating());
</ins><span class="cx">     m_heap-&gt;didAllocate(m_freeList.originalSize);
</span><span class="cx">     
</span><span class="cx">     didConsumeFreeList();
</span><span class="lines">@@ -254,7 +255,7 @@
</span><span class="cx">     if (!handle)
</span><span class="cx">         return nullptr;
</span><span class="cx">     
</span><del>-    m_markedSpace-&gt;didAddBlock(handle);
</del><ins>+    markedSpace().didAddBlock(handle);
</ins><span class="cx">     
</span><span class="cx">     return handle;
</span><span class="cx"> }
</span><span class="lines">@@ -444,7 +445,7 @@
</span><span class="cx"> {
</span><span class="cx">     m_empty.forEachSetBit(
</span><span class="cx">         [&amp;] (size_t index) {
</span><del>-            m_markedSpace-&gt;freeBlock(m_blocks[index]);
</del><ins>+            markedSpace().freeBlock(m_blocks[index]);
</ins><span class="cx">         });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -486,5 +487,10 @@
</span><span class="cx">         });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+MarkedSpace&amp; MarkedAllocator::markedSpace() const
+{
+    return m_subspace-&gt;space();
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedAllocatorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedAllocator.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedAllocator.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/MarkedAllocator.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012, 2013, 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -135,7 +135,7 @@
</span><span class="cx">     static ptrdiff_t offsetOfFreeList();
</span><span class="cx">     static ptrdiff_t offsetOfCellSize();
</span><span class="cx"> 
</span><del>-    MarkedAllocator(Heap*, MarkedSpace*, size_t cellSize, const AllocatorAttributes&amp;);
</del><ins>+    MarkedAllocator(Heap*, Subspace*, size_t cellSize);
</ins><span class="cx">     void lastChanceToFinalize();
</span><span class="cx">     void prepareForAllocation();
</span><span class="cx">     void stopAllocating();
</span><span class="lines">@@ -163,6 +163,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     template&lt;typename Functor&gt; void forEachBlock(const Functor&amp;);
</span><ins>+    template&lt;typename Functor&gt; void forEachNotEmptyBlock(const Functor&amp;);
</ins><span class="cx">     
</span><span class="cx">     void addBlock(MarkedBlock::Handle*);
</span><span class="cx">     void removeBlock(MarkedBlock::Handle*);
</span><span class="lines">@@ -200,14 +201,18 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     MarkedAllocator* nextAllocator() const { return m_nextAllocator; }
</span><ins>+    MarkedAllocator* nextAllocatorInSubspace() const { return m_nextAllocatorInSubspace; }
</ins><span class="cx">     
</span><del>-    // MarkedSpace calls this during init.
</del><span class="cx">     void setNextAllocator(MarkedAllocator* allocator) { m_nextAllocator = allocator; }
</span><ins>+    void setNextAllocatorInSubspace(MarkedAllocator* allocator) { m_nextAllocatorInSubspace = allocator; }
</ins><span class="cx">     
</span><span class="cx">     MarkedBlock::Handle* findEmptyBlockToSteal();
</span><span class="cx">     
</span><span class="cx">     MarkedBlock::Handle* findBlockToSweep();
</span><span class="cx">     
</span><ins>+    Subspace* subspace() const { return m_subspace; }
+    MarkedSpace&amp; markedSpace() const;
+    
</ins><span class="cx">     void dump(PrintStream&amp;) const;
</span><span class="cx">     void dumpBits(PrintStream&amp; = WTF::dataFile());
</span><span class="cx">     
</span><span class="lines">@@ -253,9 +258,12 @@
</span><span class="cx">     Lock m_lock;
</span><span class="cx">     unsigned m_cellSize;
</span><span class="cx">     AllocatorAttributes m_attributes;
</span><ins>+    // FIXME: All of these should probably be references.
+    // https://bugs.webkit.org/show_bug.cgi?id=166988
</ins><span class="cx">     Heap* m_heap;
</span><del>-    MarkedSpace* m_markedSpace;
-    MarkedAllocator* m_nextAllocator;
</del><ins>+    Subspace* m_subspace;
+    MarkedAllocator* m_nextAllocator { nullptr };
+    MarkedAllocator* m_nextAllocatorInSubspace { nullptr };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> inline ptrdiff_t MarkedAllocator::offsetOfFreeList()
</span><span class="lines">@@ -268,48 +276,4 @@
</span><span class="cx">     return OBJECT_OFFSETOF(MarkedAllocator, m_cellSize);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE void* MarkedAllocator::tryAllocate(GCDeferralContext* deferralContext)
-{
-    unsigned remaining = m_freeList.remaining;
-    if (remaining) {
-        unsigned cellSize = m_cellSize;
-        remaining -= cellSize;
-        m_freeList.remaining = remaining;
-        return m_freeList.payloadEnd - remaining - cellSize;
-    }
-    
-    FreeCell* head = m_freeList.head;
-    if (UNLIKELY(!head))
-        return tryAllocateSlowCase(deferralContext);
-    
-    m_freeList.head = head-&gt;next;
-    return head;
-}
-
-ALWAYS_INLINE void* MarkedAllocator::allocate(GCDeferralContext* deferralContext)
-{
-    unsigned remaining = m_freeList.remaining;
-    if (remaining) {
-        unsigned cellSize = m_cellSize;
-        remaining -= cellSize;
-        m_freeList.remaining = remaining;
-        return m_freeList.payloadEnd - remaining - cellSize;
-    }
-    
-    FreeCell* head = m_freeList.head;
-    if (UNLIKELY(!head))
-        return allocateSlowCase(deferralContext);
-    
-    m_freeList.head = head-&gt;next;
-    return head;
-}
-
-template &lt;typename Functor&gt; inline void MarkedAllocator::forEachBlock(const Functor&amp; functor)
-{
-    m_live.forEachSetBit(
-        [&amp;] (size_t index) {
-            functor(m_blocks[index]);
-        });
-}
-
</del><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedAllocatorInlinesh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/MarkedAllocatorInlines.h (0 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedAllocatorInlines.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/heap/MarkedAllocatorInlines.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -0,0 +1,85 @@
</span><ins>+/*
+ * Copyright (C) 2017 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 &quot;MarkedAllocator.h&quot;
+
+namespace JSC {
+
+ALWAYS_INLINE void* MarkedAllocator::tryAllocate(GCDeferralContext* deferralContext)
+{
+    unsigned remaining = m_freeList.remaining;
+    if (remaining) {
+        unsigned cellSize = m_cellSize;
+        remaining -= cellSize;
+        m_freeList.remaining = remaining;
+        return m_freeList.payloadEnd - remaining - cellSize;
+    }
+    
+    FreeCell* head = m_freeList.head;
+    if (UNLIKELY(!head))
+        return tryAllocateSlowCase(deferralContext);
+    
+    m_freeList.head = head-&gt;next;
+    return head;
+}
+
+ALWAYS_INLINE void* MarkedAllocator::allocate(GCDeferralContext* deferralContext)
+{
+    unsigned remaining = m_freeList.remaining;
+    if (remaining) {
+        unsigned cellSize = m_cellSize;
+        remaining -= cellSize;
+        m_freeList.remaining = remaining;
+        return m_freeList.payloadEnd - remaining - cellSize;
+    }
+    
+    FreeCell* head = m_freeList.head;
+    if (UNLIKELY(!head))
+        return allocateSlowCase(deferralContext);
+    
+    m_freeList.head = head-&gt;next;
+    return head;
+}
+
+template &lt;typename Functor&gt; inline void MarkedAllocator::forEachBlock(const Functor&amp; functor)
+{
+    m_live.forEachSetBit(
+        [&amp;] (size_t index) {
+            functor(m_blocks[index]);
+        });
+}
+
+template &lt;typename Functor&gt; inline void MarkedAllocator::forEachNotEmptyBlock(const Functor&amp; functor)
+{
+    m_markingNotEmpty.forEachSetBit(
+        [&amp;] (size_t index) {
+            functor(m_blocks[index]);
+        });
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011, 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -89,194 +89,6 @@
</span><span class="cx">         dataLog(RawPointer(this), &quot;: Allocated.\n&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;MarkedBlock::Handle::EmptyMode emptyMode, MarkedBlock::Handle::SweepMode sweepMode, MarkedBlock::Handle::SweepDestructionMode destructionMode, MarkedBlock::Handle::ScribbleMode scribbleMode, MarkedBlock::Handle::NewlyAllocatedMode newlyAllocatedMode, MarkedBlock::Handle::MarksMode marksMode&gt;
-FreeList MarkedBlock::Handle::specializedSweep()
-{
-    RELEASE_ASSERT(!(destructionMode == BlockHasNoDestructors &amp;&amp; sweepMode == SweepOnly));
-    
-    SuperSamplerScope superSamplerScope(false);
-
-    MarkedBlock&amp; block = this-&gt;block();
-    
-    if (false)
-        dataLog(RawPointer(this), &quot;/&quot;, RawPointer(&amp;block), &quot;: MarkedBlock::Handle::specializedSweep!\n&quot;);
-    
-    if (Options::useBumpAllocator()
-        &amp;&amp; emptyMode == IsEmpty
-        &amp;&amp; newlyAllocatedMode == DoesNotHaveNewlyAllocated) {
-        
-        // This is an incredibly powerful assertion that checks the sanity of our block bits.
-        if (marksMode == MarksNotStale &amp;&amp; !block.m_marks.isEmpty()) {
-            WTF::dataFile().atomically(
-                [&amp;] (PrintStream&amp; out) {
-                    out.print(&quot;Block &quot;, RawPointer(&amp;block), &quot;: marks not empty!\n&quot;);
-                    out.print(&quot;Block lock is held: &quot;, block.m_lock.isHeld(), &quot;\n&quot;);
-                    out.print(&quot;Marking version of block: &quot;, block.m_markingVersion, &quot;\n&quot;);
-                    out.print(&quot;Marking version of heap: &quot;, space()-&gt;markingVersion(), &quot;\n&quot;);
-                    UNREACHABLE_FOR_PLATFORM();
-                });
-        }
-        
-        char* startOfLastCell = static_cast&lt;char*&gt;(cellAlign(block.atoms() + m_endAtom - 1));
-        char* payloadEnd = startOfLastCell + cellSize();
-        RELEASE_ASSERT(payloadEnd - MarkedBlock::blockSize &lt;= bitwise_cast&lt;char*&gt;(&amp;block));
-        char* payloadBegin = bitwise_cast&lt;char*&gt;(block.atoms() + firstAtom());
-        if (scribbleMode == Scribble)
-            scribble(payloadBegin, payloadEnd - payloadBegin);
-        if (sweepMode == SweepToFreeList)
-            setIsFreeListed();
-        else
-            m_allocator-&gt;setIsEmpty(NoLockingNecessary, this, true);
-        if (space()-&gt;isMarking())
-            block.m_lock.unlock();
-        FreeList result = FreeList::bump(payloadEnd, payloadEnd - payloadBegin);
-        if (false)
-            dataLog(&quot;Quickly swept block &quot;, RawPointer(this), &quot; with cell size &quot;, cellSize(), &quot; and attributes &quot;, m_attributes, &quot;: &quot;, result, &quot;\n&quot;);
-        return result;
-    }
-
-    // This produces a free list that is ordered in reverse through the block.
-    // This is fine, since the allocation code makes no assumptions about the
-    // order of the free list.
-    FreeCell* head = 0;
-    size_t count = 0;
-    bool isEmpty = true;
-    Vector&lt;size_t&gt; deadCells;
-    auto handleDeadCell = [&amp;] (size_t i) {
-        HeapCell* cell = reinterpret_cast_ptr&lt;HeapCell*&gt;(&amp;block.atoms()[i]);
-
-        if (destructionMode != BlockHasNoDestructors &amp;&amp; emptyMode == NotEmpty)
-            static_cast&lt;JSCell*&gt;(cell)-&gt;callDestructor(*vm());
-
-        if (sweepMode == SweepToFreeList) {
-            FreeCell* freeCell = reinterpret_cast_ptr&lt;FreeCell*&gt;(cell);
-            if (scribbleMode == Scribble)
-                scribble(freeCell, cellSize());
-            freeCell-&gt;next = head;
-            head = freeCell;
-            ++count;
-        }
-    };
-    for (size_t i = firstAtom(); i &lt; m_endAtom; i += m_atomsPerCell) {
-        if (emptyMode == NotEmpty
-            &amp;&amp; ((marksMode == MarksNotStale &amp;&amp; block.m_marks.get(i))
-                || (newlyAllocatedMode == HasNewlyAllocated &amp;&amp; m_newlyAllocated.get(i)))) {
-            isEmpty = false;
-            continue;
-        }
-        
-        if (destructionMode == BlockHasDestructorsAndCollectorIsRunning)
-            deadCells.append(i);
-        else
-            handleDeadCell(i);
-    }
-    
-    // We only want to discard the newlyAllocated bits if we're creating a FreeList,
-    // otherwise we would lose information on what's currently alive.
-    if (sweepMode == SweepToFreeList &amp;&amp; newlyAllocatedMode == HasNewlyAllocated)
-        m_newlyAllocatedVersion = MarkedSpace::nullVersion;
-    
-    if (space()-&gt;isMarking())
-        block.m_lock.unlock();
-    
-    if (destructionMode == BlockHasDestructorsAndCollectorIsRunning) {
-        for (size_t i : deadCells)
-            handleDeadCell(i);
-    }
-
-    FreeList result = FreeList::list(head, count * cellSize());
-    if (sweepMode == SweepToFreeList)
-        setIsFreeListed();
-    else if (isEmpty)
-        m_allocator-&gt;setIsEmpty(NoLockingNecessary, this, true);
-    if (false)
-        dataLog(&quot;Slowly swept block &quot;, RawPointer(&amp;block), &quot; with cell size &quot;, cellSize(), &quot; and attributes &quot;, m_attributes, &quot;: &quot;, result, &quot;\n&quot;);
-    return result;
-}
-
-FreeList MarkedBlock::Handle::sweep(SweepMode sweepMode)
-{
-    // FIXME: Maybe HelpingGCScope should just be called SweepScope?
-    HelpingGCScope helpingGCScope(*heap());
-    
-    m_allocator-&gt;setIsUnswept(NoLockingNecessary, this, false);
-    
-    m_weakSet.sweep();
-
-    if (sweepMode == SweepOnly &amp;&amp; m_attributes.destruction == DoesNotNeedDestruction)
-        return FreeList();
-
-    if (UNLIKELY(m_isFreeListed)) {
-        RELEASE_ASSERT(sweepMode == SweepToFreeList);
-        return FreeList();
-    }
-    
-    ASSERT(!m_allocator-&gt;isAllocated(NoLockingNecessary, this));
-    
-    if (space()-&gt;isMarking())
-        block().m_lock.lock();
-    
-    if (m_attributes.destruction == NeedsDestruction) {
-        if (space()-&gt;isMarking())
-            return sweepHelperSelectScribbleMode&lt;BlockHasDestructorsAndCollectorIsRunning&gt;(sweepMode);
-        return sweepHelperSelectScribbleMode&lt;BlockHasDestructors&gt;(sweepMode);
-    }
-    return sweepHelperSelectScribbleMode&lt;BlockHasNoDestructors&gt;(sweepMode);
-}
-
-template&lt;MarkedBlock::Handle::SweepDestructionMode destructionMode&gt;
-FreeList MarkedBlock::Handle::sweepHelperSelectScribbleMode(SweepMode sweepMode)
-{
-    if (scribbleFreeCells())
-        return sweepHelperSelectEmptyMode&lt;destructionMode, Scribble&gt;(sweepMode);
-    return sweepHelperSelectEmptyMode&lt;destructionMode, DontScribble&gt;(sweepMode);
-}
-
-template&lt;MarkedBlock::Handle::SweepDestructionMode destructionMode, MarkedBlock::Handle::ScribbleMode scribbleMode&gt;
-FreeList MarkedBlock::Handle::sweepHelperSelectEmptyMode(SweepMode sweepMode)
-{
-    // It's not obvious, but this is the only way to know if the block is empty. It's the only
-    // bit that captures these caveats:
-    // - It's true when the block is freshly allocated.
-    // - It's true if the block had been swept in the past, all destructors were called, and that
-    //   sweep proved that the block is empty.
-    // - It's false if there are any destructors that need to be called, even if the block has no
-    //   live objects.
-    if (m_allocator-&gt;isEmpty(NoLockingNecessary, this))
-        return sweepHelperSelectHasNewlyAllocated&lt;IsEmpty, destructionMode, scribbleMode&gt;(sweepMode);
-    return sweepHelperSelectHasNewlyAllocated&lt;NotEmpty, destructionMode, scribbleMode&gt;(sweepMode);
-}
-
-template&lt;MarkedBlock::Handle::EmptyMode emptyMode, MarkedBlock::Handle::SweepDestructionMode destructionMode, MarkedBlock::Handle::ScribbleMode scribbleMode&gt;
-FreeList MarkedBlock::Handle::sweepHelperSelectHasNewlyAllocated(SweepMode sweepMode)
-{
-    if (hasAnyNewlyAllocated())
-        return sweepHelperSelectSweepMode&lt;emptyMode, destructionMode, scribbleMode, HasNewlyAllocated&gt;(sweepMode);
-    return sweepHelperSelectSweepMode&lt;emptyMode, destructionMode, scribbleMode, DoesNotHaveNewlyAllocated&gt;(sweepMode);
-}
-
-template&lt;MarkedBlock::Handle::EmptyMode emptyMode, MarkedBlock::Handle::SweepDestructionMode destructionMode, MarkedBlock::Handle::ScribbleMode scribbleMode, MarkedBlock::Handle::NewlyAllocatedMode newlyAllocatedMode&gt;
-FreeList MarkedBlock::Handle::sweepHelperSelectSweepMode(SweepMode sweepMode)
-{
-    if (sweepMode == SweepToFreeList)
-        return sweepHelperSelectMarksMode&lt;emptyMode, SweepToFreeList, destructionMode, scribbleMode, newlyAllocatedMode&gt;();
-    return sweepHelperSelectMarksMode&lt;emptyMode, SweepOnly, destructionMode, scribbleMode, newlyAllocatedMode&gt;();
-}
-
-template&lt;MarkedBlock::Handle::EmptyMode emptyMode, MarkedBlock::Handle::SweepMode sweepMode, MarkedBlock::Handle::SweepDestructionMode destructionMode, MarkedBlock::Handle::ScribbleMode scribbleMode, MarkedBlock::Handle::NewlyAllocatedMode newlyAllocatedMode&gt;
-FreeList MarkedBlock::Handle::sweepHelperSelectMarksMode()
-{
-    HeapVersion markingVersion = space()-&gt;markingVersion();
-    bool marksAreUseful = !block().areMarksStale(markingVersion);
-    
-    if (space()-&gt;isMarking())
-        marksAreUseful |= block().marksConveyLivenessDuringMarking(markingVersion);
-    
-    if (!marksAreUseful)
-        return specializedSweep&lt;emptyMode, sweepMode, destructionMode, scribbleMode, newlyAllocatedMode, MarksStale&gt;();
-    return specializedSweep&lt;emptyMode, sweepMode, destructionMode, scribbleMode, newlyAllocatedMode, MarksNotStale&gt;();
-}
-
</del><span class="cx"> void MarkedBlock::Handle::unsweepWithNoNewlyAllocated()
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(m_isFreeListed);
</span><span class="lines">@@ -590,6 +402,86 @@
</span><span class="cx">         });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Subspace* MarkedBlock::Handle::subspace() const
+{
+    return allocator()-&gt;subspace();
+}
+
+FreeList MarkedBlock::Handle::sweep(SweepMode sweepMode)
+{
+    // FIXME: Maybe HelpingGCScope should just be called SweepScope?
+    HelpingGCScope helpingGCScope(*heap());
+    
+    m_allocator-&gt;setIsUnswept(NoLockingNecessary, this, false);
+    
+    m_weakSet.sweep();
+
+    if (sweepMode == SweepOnly &amp;&amp; m_attributes.destruction == DoesNotNeedDestruction)
+        return FreeList();
+
+    if (UNLIKELY(m_isFreeListed)) {
+        RELEASE_ASSERT(sweepMode == SweepToFreeList);
+        return FreeList();
+    }
+    
+    ASSERT(!m_allocator-&gt;isAllocated(NoLockingNecessary, this));
+    
+    if (space()-&gt;isMarking())
+        block().m_lock.lock();
+    
+    if (m_attributes.destruction == NeedsDestruction)
+        return subspace()-&gt;finishSweep(*this, sweepMode);
+    
+    // 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-&gt;emptyMode();
+    ScribbleMode scribbleMode = this-&gt;scribbleMode();
+    NewlyAllocatedMode newlyAllocatedMode = this-&gt;newlyAllocatedMode();
+    MarksMode marksMode = this-&gt;marksMode();
+    
+    FreeList result;
+    auto trySpecialized = [&amp;] () -&gt; bool {
+        if (sweepMode != SweepToFreeList)
+            return false;
+        if (scribbleMode != DontScribble)
+            return false;
+        if (newlyAllocatedMode != DoesNotHaveNewlyAllocated)
+            return false;
+        
+        switch (emptyMode) {
+        case IsEmpty:
+            switch (marksMode) {
+            case MarksNotStale:
+                result = specializedSweep&lt;true, IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale&gt;(IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale, [] (VM&amp;, JSCell*) { });
+                return true;
+            case MarksStale:
+                result = specializedSweep&lt;true, IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale&gt;(IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale, [] (VM&amp;, JSCell*) { });
+                return true;
+            }
+            break;
+        case NotEmpty:
+            switch (marksMode) {
+            case MarksNotStale:
+                result = specializedSweep&lt;true, NotEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale&gt;(IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale, [] (VM&amp;, JSCell*) { });
+                return true;
+            case MarksStale:
+                result = specializedSweep&lt;true, NotEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale&gt;(IsEmpty, SweepToFreeList, BlockHasNoDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale, [] (VM&amp;, JSCell*) { });
+                return true;
+            }
+            break;
+        }
+        
+        return false;
+    };
+    
+    if (trySpecialized())
+        return result;
+
+    // The template arguments don't matter because the first one is false.
+    return specializedSweep&lt;false, IsEmpty, SweepOnly, BlockHasNoDestructors, DontScribble, HasNewlyAllocated, MarksStale&gt;(emptyMode, sweepMode, BlockHasNoDestructors, scribbleMode, newlyAllocatedMode, marksMode, [] (VM&amp;, JSCell*) { });
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedBlock.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedBlock.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/MarkedBlock.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
</span><span class="cx">  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
</span><del>- *  Copyright (C) 2003-2009, 2011, 2016 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Lesser General Public
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx"> class MarkedAllocator;
</span><span class="cx"> class MarkedSpace;
</span><span class="cx"> class SlotVisitor;
</span><ins>+class Subspace;
</ins><span class="cx"> 
</span><span class="cx"> typedef uintptr_t Bits;
</span><span class="cx"> typedef uint32_t HeapVersion;
</span><span class="lines">@@ -110,6 +111,7 @@
</span><span class="cx">         void lastChanceToFinalize();
</span><span class="cx"> 
</span><span class="cx">         MarkedAllocator* allocator() const;
</span><ins>+        Subspace* subspace() const;
</ins><span class="cx">         Heap* heap() const;
</span><span class="cx">         inline MarkedSpace* space() const;
</span><span class="cx">         VM* vm() const;
</span><span class="lines">@@ -127,6 +129,10 @@
</span><span class="cx">         enum SweepMode { SweepOnly, SweepToFreeList };
</span><span class="cx">         FreeList sweep(SweepMode = SweepOnly);
</span><span class="cx">         
</span><ins>+        // This is to be called by Subspace.
+        template&lt;typename DestroyFunc&gt;
+        FreeList finishSweepKnowingSubspace(SweepMode, const DestroyFunc&amp;);
+        
</ins><span class="cx">         void unsweepWithNoNewlyAllocated();
</span><span class="cx">         
</span><span class="cx">         void zap(const FreeList&amp;);
</span><span class="lines">@@ -133,7 +139,7 @@
</span><span class="cx">         
</span><span class="cx">         void shrink();
</span><span class="cx">             
</span><del>-        unsigned visitWeakSet(SlotVisitor&amp;);
</del><ins>+        void visitWeakSet(SlotVisitor&amp;);
</ins><span class="cx">         void reapWeakSet();
</span><span class="cx">             
</span><span class="cx">         // While allocating from a free list, MarkedBlock temporarily has bogus
</span><span class="lines">@@ -174,8 +180,9 @@
</span><span class="cx">         template &lt;typename Functor&gt; IterationStatus forEachCell(const Functor&amp;);
</span><span class="cx">         template &lt;typename Functor&gt; inline IterationStatus forEachLiveCell(const Functor&amp;);
</span><span class="cx">         template &lt;typename Functor&gt; inline IterationStatus forEachDeadCell(const Functor&amp;);
</span><ins>+        template &lt;typename Functor&gt; inline IterationStatus forEachMarkedCell(const Functor&amp;);
</ins><span class="cx">             
</span><del>-        bool areMarksStale();
</del><ins>+        JS_EXPORT_PRIVATE bool areMarksStale();
</ins><span class="cx">         
</span><span class="cx">         void assertMarksNotStale();
</span><span class="cx">             
</span><span class="lines">@@ -194,33 +201,20 @@
</span><span class="cx">         Handle(Heap&amp;, void*);
</span><span class="cx">         
</span><span class="cx">         enum SweepDestructionMode { BlockHasNoDestructors, BlockHasDestructors, BlockHasDestructorsAndCollectorIsRunning };
</span><del>-        
-        template&lt;SweepDestructionMode&gt;
-        FreeList sweepHelperSelectScribbleMode(SweepMode = SweepOnly);
-            
</del><span class="cx">         enum ScribbleMode { DontScribble, Scribble };
</span><del>-            
-        template&lt;SweepDestructionMode, ScribbleMode&gt;
-        FreeList sweepHelperSelectEmptyMode(SweepMode = SweepOnly);
-            
</del><span class="cx">         enum EmptyMode { IsEmpty, NotEmpty };
</span><del>-        
-        template&lt;EmptyMode, SweepDestructionMode, ScribbleMode&gt;
-        FreeList sweepHelperSelectHasNewlyAllocated(SweepMode = SweepOnly);
-        
</del><span class="cx">         enum NewlyAllocatedMode { HasNewlyAllocated, DoesNotHaveNewlyAllocated };
</span><ins>+        enum MarksMode { MarksStale, MarksNotStale };
</ins><span class="cx">         
</span><del>-        template&lt;EmptyMode, SweepDestructionMode, ScribbleMode, NewlyAllocatedMode&gt;
-        FreeList sweepHelperSelectSweepMode(SweepMode = SweepOnly);
</del><ins>+        SweepDestructionMode sweepDestructionMode();
+        EmptyMode emptyMode();
+        ScribbleMode scribbleMode();
+        NewlyAllocatedMode newlyAllocatedMode();
+        MarksMode marksMode();
</ins><span class="cx">         
</span><del>-        template&lt;EmptyMode, SweepMode, SweepDestructionMode, ScribbleMode, NewlyAllocatedMode&gt;
-        FreeList sweepHelperSelectMarksMode();
</del><ins>+        template&lt;bool, EmptyMode, SweepMode, SweepDestructionMode, ScribbleMode, NewlyAllocatedMode, MarksMode, typename DestroyFunc&gt;
+        FreeList specializedSweep(EmptyMode, SweepMode, SweepDestructionMode, ScribbleMode, NewlyAllocatedMode, MarksMode, const DestroyFunc&amp;);
</ins><span class="cx">         
</span><del>-        enum MarksMode { MarksStale, MarksNotStale };
-        
-        template&lt;EmptyMode, SweepMode, SweepDestructionMode, ScribbleMode, NewlyAllocatedMode, MarksMode&gt;
-        FreeList specializedSweep();
-            
</del><span class="cx">         template&lt;typename Func&gt;
</span><span class="cx">         void forEachFreeCell(const FreeList&amp;, const Func&amp;);
</span><span class="cx">         
</span><span class="lines">@@ -282,7 +276,7 @@
</span><span class="cx">         
</span><span class="cx">     WeakSet&amp; weakSet();
</span><span class="cx"> 
</span><del>-    bool areMarksStale();
</del><ins>+    JS_EXPORT_PRIVATE bool areMarksStale();
</ins><span class="cx">     bool areMarksStale(HeapVersion markingVersion);
</span><span class="cx">     struct MarksWithDependency {
</span><span class="cx">         bool areStale;
</span><span class="lines">@@ -432,7 +426,7 @@
</span><span class="cx">     m_weakSet.shrink();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline unsigned MarkedBlock::Handle::visitWeakSet(SlotVisitor&amp; visitor)
</del><ins>+inline void MarkedBlock::Handle::visitWeakSet(SlotVisitor&amp; visitor)
</ins><span class="cx"> {
</span><span class="cx">     return m_weakSet.visit(visitor);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedBlockInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedBlockInlines.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedBlockInlines.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/MarkedBlockInlines.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -25,9 +25,12 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><ins>+#include &quot;JSCell.h&quot;
</ins><span class="cx"> #include &quot;MarkedAllocator.h&quot;
</span><span class="cx"> #include &quot;MarkedBlock.h&quot;
</span><span class="cx"> #include &quot;MarkedSpace.h&quot;
</span><ins>+#include &quot;Operations.h&quot;
+#include &quot;SuperSampler.h&quot;
</ins><span class="cx"> #include &quot;VM.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -37,6 +40,31 @@
</span><span class="cx">     return MarkedSpace::blockPayload / cellSize();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool MarkedBlock::Handle::isNewlyAllocatedStale() const
+{
+    return m_newlyAllocatedVersion != space()-&gt;newlyAllocatedVersion();
+}
+
+inline bool MarkedBlock::Handle::hasAnyNewlyAllocated()
+{
+    return !isNewlyAllocatedStale();
+}
+
+inline Heap* MarkedBlock::heap() const
+{
+    return &amp;vm()-&gt;heap;
+}
+
+inline MarkedSpace* MarkedBlock::space() const
+{
+    return &amp;heap()-&gt;objectSpace();
+}
+
+inline MarkedSpace* MarkedBlock::Handle::space() const
+{
+    return &amp;heap()-&gt;objectSpace();
+}
+
</ins><span class="cx"> inline bool MarkedBlock::marksConveyLivenessDuringMarking(HeapVersion markingVersion)
</span><span class="cx"> {
</span><span class="cx">     // This returns true if any of these is true:
</span><span class="lines">@@ -89,16 +117,229 @@
</span><span class="cx">     return isLive(markingVersion, isMarking, static_cast&lt;const HeapCell*&gt;(p));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline bool MarkedBlock::Handle::isNewlyAllocatedStale() const
</del><ins>+// The following has to be true for specialization to kick in:
+//
+// sweepMode == SweepToFreeList
+// scribbleMode == DontScribble
+// newlyAllocatedMode == DoesNotHaveNewlyAllocated
+// destructionMode != BlockHasDestrictorsAndCollectorIsRunning
+//
+// emptyMode = IsEmpty
+//     destructionMode = DoesNotNeedDestruction
+//         marksMode = MarksNotStale (1)
+//         marksMode = MarksStale (2)
+// emptyMode = NotEmpty
+//     destructionMode = DoesNotNeedDestruction
+//         marksMode = MarksNotStale (3)
+//         marksMode = MarksStale (4)
+//     destructionMode = NeedsDestruction
+//         marksMode = MarksNotStale (5)
+//         marksMode = MarksStale (6)
+//
+// Only the DoesNotNeedDestruction one should be specialized by MarkedBlock.
+
+template&lt;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&gt;
+FreeList MarkedBlock::Handle::specializedSweep(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&amp; destroyFunc)
</ins><span class="cx"> {
</span><del>-    return m_newlyAllocatedVersion != space()-&gt;newlyAllocatedVersion();
</del><ins>+    if (specialize) {
+        emptyMode = specializedEmptyMode;
+        sweepMode = specializedSweepMode;
+        destructionMode = specializedDestructionMode;
+        scribbleMode = specializedScribbleMode;
+        newlyAllocatedMode = specializedNewlyAllocatedMode;
+        marksMode = specializedMarksMode;
+    }
+    
+    RELEASE_ASSERT(!(destructionMode == BlockHasNoDestructors &amp;&amp; sweepMode == SweepOnly));
+    
+    SuperSamplerScope superSamplerScope(false);
+
+    MarkedBlock&amp; block = this-&gt;block();
+    
+    if (false)
+        dataLog(RawPointer(this), &quot;/&quot;, RawPointer(&amp;block), &quot;: MarkedBlock::Handle::specializedSweep!\n&quot;);
+    
+    if (Options::useBumpAllocator()
+        &amp;&amp; emptyMode == IsEmpty
+        &amp;&amp; newlyAllocatedMode == DoesNotHaveNewlyAllocated) {
+        
+        // This is an incredibly powerful assertion that checks the sanity of our block bits.
+        if (marksMode == MarksNotStale &amp;&amp; !block.m_marks.isEmpty()) {
+            WTF::dataFile().atomically(
+                [&amp;] (PrintStream&amp; out) {
+                    out.print(&quot;Block &quot;, RawPointer(&amp;block), &quot;: marks not empty!\n&quot;);
+                    out.print(&quot;Block lock is held: &quot;, block.m_lock.isHeld(), &quot;\n&quot;);
+                    out.print(&quot;Marking version of block: &quot;, block.m_markingVersion, &quot;\n&quot;);
+                    out.print(&quot;Marking version of heap: &quot;, space()-&gt;markingVersion(), &quot;\n&quot;);
+                    UNREACHABLE_FOR_PLATFORM();
+                });
+        }
+        
+        char* startOfLastCell = static_cast&lt;char*&gt;(cellAlign(block.atoms() + m_endAtom - 1));
+        char* payloadEnd = startOfLastCell + cellSize();
+        RELEASE_ASSERT(payloadEnd - MarkedBlock::blockSize &lt;= bitwise_cast&lt;char*&gt;(&amp;block));
+        char* payloadBegin = bitwise_cast&lt;char*&gt;(block.atoms() + firstAtom());
+        if (scribbleMode == Scribble)
+            scribble(payloadBegin, payloadEnd - payloadBegin);
+        if (sweepMode == SweepToFreeList)
+            setIsFreeListed();
+        else
+            m_allocator-&gt;setIsEmpty(NoLockingNecessary, this, true);
+        if (space()-&gt;isMarking())
+            block.m_lock.unlock();
+        FreeList result = FreeList::bump(payloadEnd, payloadEnd - payloadBegin);
+        if (false)
+            dataLog(&quot;Quickly swept block &quot;, RawPointer(this), &quot; with cell size &quot;, cellSize(), &quot; and attributes &quot;, m_attributes, &quot;: &quot;, result, &quot;\n&quot;);
+        return result;
+    }
+
+    // This produces a free list that is ordered in reverse through the block.
+    // This is fine, since the allocation code makes no assumptions about the
+    // order of the free list.
+    FreeCell* head = 0;
+    size_t count = 0;
+    bool isEmpty = true;
+    Vector&lt;size_t&gt; deadCells;
+    VM&amp; vm = *this-&gt;vm();
+    auto handleDeadCell = [&amp;] (size_t i) {
+        HeapCell* cell = reinterpret_cast_ptr&lt;HeapCell*&gt;(&amp;block.atoms()[i]);
+
+        if (destructionMode != BlockHasNoDestructors &amp;&amp; emptyMode == NotEmpty) {
+            JSCell* jsCell = static_cast&lt;JSCell*&gt;(cell);
+            if (!jsCell-&gt;isZapped()) {
+                destroyFunc(vm, jsCell);
+                jsCell-&gt;zap();
+            }
+        }
+
+        if (sweepMode == SweepToFreeList) {
+            FreeCell* freeCell = reinterpret_cast_ptr&lt;FreeCell*&gt;(cell);
+            if (scribbleMode == Scribble)
+                scribble(freeCell, cellSize());
+            freeCell-&gt;next = head;
+            head = freeCell;
+            ++count;
+        }
+    };
+    for (size_t i = firstAtom(); i &lt; m_endAtom; i += m_atomsPerCell) {
+        if (emptyMode == NotEmpty
+            &amp;&amp; ((marksMode == MarksNotStale &amp;&amp; block.m_marks.get(i))
+                || (newlyAllocatedMode == HasNewlyAllocated &amp;&amp; m_newlyAllocated.get(i)))) {
+            isEmpty = false;
+            continue;
+        }
+        
+        if (destructionMode == BlockHasDestructorsAndCollectorIsRunning)
+            deadCells.append(i);
+        else
+            handleDeadCell(i);
+    }
+    
+    // We only want to discard the newlyAllocated bits if we're creating a FreeList,
+    // otherwise we would lose information on what's currently alive.
+    if (sweepMode == SweepToFreeList &amp;&amp; newlyAllocatedMode == HasNewlyAllocated)
+        m_newlyAllocatedVersion = MarkedSpace::nullVersion;
+    
+    if (space()-&gt;isMarking())
+        block.m_lock.unlock();
+    
+    if (destructionMode == BlockHasDestructorsAndCollectorIsRunning) {
+        for (size_t i : deadCells)
+            handleDeadCell(i);
+    }
+
+    FreeList result = FreeList::list(head, count * cellSize());
+    if (sweepMode == SweepToFreeList)
+        setIsFreeListed();
+    else if (isEmpty)
+        m_allocator-&gt;setIsEmpty(NoLockingNecessary, this, true);
+    if (false)
+        dataLog(&quot;Slowly swept block &quot;, RawPointer(&amp;block), &quot; with cell size &quot;, cellSize(), &quot; and attributes &quot;, m_attributes, &quot;: &quot;, result, &quot;\n&quot;);
+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline bool MarkedBlock::Handle::hasAnyNewlyAllocated()
</del><ins>+template&lt;typename DestroyFunc&gt;
+FreeList MarkedBlock::Handle::finishSweepKnowingSubspace(SweepMode sweepMode, const DestroyFunc&amp; destroyFunc)
</ins><span class="cx"> {
</span><del>-    return !isNewlyAllocatedStale();
</del><ins>+    SweepDestructionMode destructionMode = this-&gt;sweepDestructionMode();
+    EmptyMode emptyMode = this-&gt;emptyMode();
+    ScribbleMode scribbleMode = this-&gt;scribbleMode();
+    NewlyAllocatedMode newlyAllocatedMode = this-&gt;newlyAllocatedMode();
+    MarksMode marksMode = this-&gt;marksMode();
+
+    FreeList result;
+    auto trySpecialized = [&amp;] () -&gt; bool {
+        if (sweepMode != SweepToFreeList)
+            return false;
+        if (scribbleMode != DontScribble)
+            return false;
+        if (newlyAllocatedMode != DoesNotHaveNewlyAllocated)
+            return false;
+        if (destructionMode != BlockHasDestructors)
+            return false;
+        if (emptyMode == IsEmpty)
+            return false;
+        
+        switch (marksMode) {
+        case MarksNotStale:
+            result = specializedSweep&lt;true, NotEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale&gt;(IsEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksNotStale, destroyFunc);
+            return true;
+        case MarksStale:
+            result = specializedSweep&lt;true, NotEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale&gt;(IsEmpty, SweepToFreeList, BlockHasDestructors, DontScribble, DoesNotHaveNewlyAllocated, MarksStale, destroyFunc);
+            return true;
+        }
+        
+        return false;
+    };
+    
+    if (trySpecialized())
+        return result;
+    
+    // The template arguments don't matter because the first one is false.
+    return specializedSweep&lt;false, IsEmpty, SweepOnly, BlockHasNoDestructors, DontScribble, HasNewlyAllocated, MarksStale&gt;(emptyMode, sweepMode, destructionMode, scribbleMode, newlyAllocatedMode, marksMode, destroyFunc);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline MarkedBlock::Handle::SweepDestructionMode MarkedBlock::Handle::sweepDestructionMode()
+{
+    if (m_attributes.destruction == NeedsDestruction) {
+        if (space()-&gt;isMarking())
+            return BlockHasDestructorsAndCollectorIsRunning;
+        return BlockHasDestructors;
+    }
+    return BlockHasNoDestructors;
+}
+
+inline MarkedBlock::Handle::EmptyMode MarkedBlock::Handle::emptyMode()
+{
+    // It's not obvious, but this is the only way to know if the block is empty. It's the only
+    // bit that captures these caveats:
+    // - It's true when the block is freshly allocated.
+    // - It's true if the block had been swept in the past, all destructors were called, and that
+    //   sweep proved that the block is empty.
+    // - It's false if there are any destructors that need to be called, even if the block has no
+    //   live objects.
+    return m_allocator-&gt;isEmpty(NoLockingNecessary, this) ? IsEmpty : NotEmpty;
+}
+
+inline MarkedBlock::Handle::ScribbleMode MarkedBlock::Handle::scribbleMode()
+{
+    return scribbleFreeCells() ? Scribble : DontScribble;
+}
+
+inline MarkedBlock::Handle::NewlyAllocatedMode MarkedBlock::Handle::newlyAllocatedMode()
+{
+    return hasAnyNewlyAllocated() ? HasNewlyAllocated : DoesNotHaveNewlyAllocated;
+}
+
+inline MarkedBlock::Handle::MarksMode MarkedBlock::Handle::marksMode()
+{
+    HeapVersion markingVersion = space()-&gt;markingVersion();
+    bool marksAreUseful = !block().areMarksStale(markingVersion);
+    if (space()-&gt;isMarking())
+        marksAreUseful |= block().marksConveyLivenessDuringMarking(markingVersion);
+    return marksAreUseful ? MarksNotStale : MarksStale;
+}
+
</ins><span class="cx"> template &lt;typename Functor&gt;
</span><span class="cx"> inline IterationStatus MarkedBlock::Handle::forEachLiveCell(const Functor&amp; functor)
</span><span class="cx"> {
</span><span class="lines">@@ -129,20 +370,25 @@
</span><span class="cx">     return IterationStatus::Continue;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline Heap* MarkedBlock::heap() const
</del><ins>+template &lt;typename Functor&gt;
+inline IterationStatus MarkedBlock::Handle::forEachMarkedCell(const Functor&amp; functor)
</ins><span class="cx"> {
</span><del>-    return &amp;vm()-&gt;heap;
-}
</del><ins>+    HeapCell::Kind kind = m_attributes.cellKind;
+    MarkedBlock&amp; block = this-&gt;block();
+    bool areMarksStale = block.areMarksStale();
+    WTF::loadLoadFence();
+    if (areMarksStale)
+        return IterationStatus::Continue;
+    for (size_t i = firstAtom(); i &lt; m_endAtom; i += m_atomsPerCell) {
+        HeapCell* cell = reinterpret_cast_ptr&lt;HeapCell*&gt;(&amp;m_block-&gt;atoms()[i]);
+        if (!block.isMarkedRaw(cell))
+            continue;
</ins><span class="cx"> 
</span><del>-inline MarkedSpace* MarkedBlock::space() const
-{
-    return &amp;heap()-&gt;objectSpace();
</del><ins>+        if (functor(cell, kind) == IterationStatus::Done)
+            return IterationStatus::Done;
+    }
+    return IterationStatus::Continue;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline MarkedSpace* MarkedBlock::Handle::space() const
-{
-    return &amp;heap()-&gt;objectSpace();
-}
-
</del><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedSpacecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2016 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *  Copyright (C) 2007 Eric Seidel &lt;eric@webkit.org&gt;
</span><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="lines">@@ -25,6 +25,7 @@
</span><span class="cx"> #include &quot;IncrementalSweeper.h&quot;
</span><span class="cx"> #include &quot;JSObject.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;MarkedAllocatorInlines.h&quot;
</ins><span class="cx"> #include &quot;MarkedBlockInlines.h&quot;
</span><span class="cx"> #include &lt;wtf/ListDump.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -177,16 +178,18 @@
</span><span class="cx"> 
</span><span class="cx"> void MarkedSpace::initializeSizeClassForStepSize()
</span><span class="cx"> {
</span><del>-    // We call this multiple times and we may call it simultaneously from multiple threads. That's
-    // OK, since it always stores the same values into the table.
-    
-    buildSizeClassTable(
-        s_sizeClassForSizeStep,
-        [&amp;] (size_t sizeClass) -&gt; size_t {
-            return sizeClass;
-        },
-        [&amp;] (size_t sizeClass) -&gt; size_t {
-            return sizeClass;
</del><ins>+    static std::once_flag flag;
+    std::call_once(
+        flag,
+        [] {
+            buildSizeClassTable(
+                s_sizeClassForSizeStep,
+                [&amp;] (size_t sizeClass) -&gt; size_t {
+                    return sizeClass;
+                },
+                [&amp;] (size_t sizeClass) -&gt; size_t {
+                    return sizeClass;
+                });
</ins><span class="cx">         });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -196,35 +199,6 @@
</span><span class="cx">     , m_isIterating(false)
</span><span class="cx"> {
</span><span class="cx">     initializeSizeClassForStepSize();
</span><del>-    
-    forEachSubspace(
-        [&amp;] (Subspace&amp; subspace, AllocatorAttributes attributes) -&gt; IterationStatus {
-            subspace.attributes = attributes;
-            
-            buildSizeClassTable(
-                subspace.allocatorForSizeStep,
-                [&amp;] (size_t sizeClass) -&gt; MarkedAllocator* {
-                    return subspace.bagOfAllocators.add(heap, this, sizeClass, attributes);
-                },
-                [&amp;] (size_t) -&gt; MarkedAllocator* {
-                    return nullptr;
-                });
-            
-            return IterationStatus::Continue;
-        });
-    
-    MarkedAllocator* previous = nullptr;
-    forEachSubspace(
-        [&amp;] (Subspace&amp; subspace, AllocatorAttributes) -&gt; IterationStatus {
-            for (MarkedAllocator* allocator : subspace.bagOfAllocators) {
-                allocator-&gt;setNextAllocator(previous);
-                previous = allocator;
-            }
-            
-            return IterationStatus::Continue;
-        });
-    m_firstAllocator = previous;
-    m_allocatorForEmptyAllocation = previous;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MarkedSpace::~MarkedSpace()
</span><span class="lines">@@ -240,7 +214,6 @@
</span><span class="cx"> 
</span><span class="cx"> void MarkedSpace::lastChanceToFinalize()
</span><span class="cx"> {
</span><del>-    stopAllocating();
</del><span class="cx">     forEachAllocator(
</span><span class="cx">         [&amp;] (MarkedAllocator&amp; allocator) -&gt; IterationStatus {
</span><span class="cx">             allocator.lastChanceToFinalize();
</span><span class="lines">@@ -250,72 +223,6 @@
</span><span class="cx">         allocation-&gt;lastChanceToFinalize();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void* MarkedSpace::allocate(Subspace&amp; subspace, size_t bytes)
-{
-    if (false)
-        dataLog(&quot;Allocating &quot;, bytes, &quot; bytes in &quot;, subspace.attributes, &quot;.\n&quot;);
-    if (MarkedAllocator* allocator = allocatorFor(subspace, bytes)) {
-        void* result = allocator-&gt;allocate();
-        return result;
-    }
-    return allocateLarge(subspace, nullptr, bytes);
-}
-
-void* MarkedSpace::allocate(Subspace&amp; subspace, GCDeferralContext* deferralContext, size_t bytes)
-{
-    if (false)
-        dataLog(&quot;Allocating &quot;, bytes, &quot; deferred bytes in &quot;, subspace.attributes, &quot;.\n&quot;);
-    if (MarkedAllocator* allocator = allocatorFor(subspace, bytes)) {
-        void* result = allocator-&gt;allocate(deferralContext);
-        return result;
-    }
-    return allocateLarge(subspace, deferralContext, bytes);
-}
-
-void* MarkedSpace::tryAllocate(Subspace&amp; subspace, size_t bytes)
-{
-    if (false)
-        dataLog(&quot;Try-allocating &quot;, bytes, &quot; bytes in &quot;, subspace.attributes, &quot;.\n&quot;);
-    if (MarkedAllocator* allocator = allocatorFor(subspace, bytes)) {
-        void* result = allocator-&gt;tryAllocate();
-        return result;
-    }
-    return tryAllocateLarge(subspace, nullptr, bytes);
-}
-
-void* MarkedSpace::tryAllocate(Subspace&amp; subspace, GCDeferralContext* deferralContext, size_t bytes)
-{
-    if (false)
-        dataLog(&quot;Try-allocating &quot;, bytes, &quot; deferred bytes in &quot;, subspace.attributes, &quot;.\n&quot;);
-    if (MarkedAllocator* allocator = allocatorFor(subspace, bytes)) {
-        void* result = allocator-&gt;tryAllocate(deferralContext);
-        return result;
-    }
-    return tryAllocateLarge(subspace, deferralContext, bytes);
-}
-
-void* MarkedSpace::allocateLarge(Subspace&amp; subspace, GCDeferralContext* deferralContext, size_t size)
-{
-    void* result = tryAllocateLarge(subspace, deferralContext, size);
-    RELEASE_ASSERT(result);
-    return result;
-}
-
-void* MarkedSpace::tryAllocateLarge(Subspace&amp; subspace, GCDeferralContext* deferralContext, size_t size)
-{
-    m_heap-&gt;collectIfNecessaryOrDefer(deferralContext);
-    
-    size = WTF::roundUpToMultipleOf&lt;sizeStep&gt;(size);
-    LargeAllocation* allocation = LargeAllocation::tryCreate(*m_heap, size, subspace.attributes);
-    if (!allocation)
-        return nullptr;
-    
-    m_largeAllocations.append(allocation);
-    m_heap-&gt;didAllocate(size);
-    m_capacity += size;
-    return allocation-&gt;cell();
-}
-
</del><span class="cx"> void MarkedSpace::sweep()
</span><span class="cx"> {
</span><span class="cx">     m_heap-&gt;sweeper()-&gt;willFinishSweeping();
</span><span class="lines">@@ -654,4 +561,24 @@
</span><span class="cx">         });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+MarkedAllocator* MarkedSpace::addMarkedAllocator(
+    const AbstractLocker&amp;, Subspace* subspace, size_t sizeClass)
+{
+    MarkedAllocator* allocator = m_bagOfAllocators.add(heap(), subspace, sizeClass);
+    allocator-&gt;setNextAllocator(nullptr);
+    
+    WTF::storeStoreFence();
+
+    if (!m_firstAllocator) {
+        m_firstAllocator = allocator;
+        m_lastAllocator = allocator;
+        m_allocatorForEmptyAllocation = allocator;
+    } else {
+        m_lastAllocator-&gt;setNextAllocator(allocator);
+        m_lastAllocator = allocator;
+    }
+    
+    return allocator;
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedSpaceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedSpace.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedSpace.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/MarkedSpace.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
</span><span class="cx">  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
</span><del>- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2016 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Lesser General Public
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx"> class Heap;
</span><span class="cx"> class HeapIterationScope;
</span><span class="cx"> class LLIntOffsetsExtractor;
</span><ins>+class Subspace;
</ins><span class="cx"> class WeakSet;
</span><span class="cx"> 
</span><span class="cx"> typedef uint32_t HeapVersion;
</span><span class="lines">@@ -86,47 +87,15 @@
</span><span class="cx">         return (index + 1) * sizeStep;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    // Each Subspace corresponds to all of the blocks for all of the sizes for some &quot;class&quot; of
-    // objects. There are three classes: non-destructor JSCells, destructor JSCells, and auxiliary.
-    // MarkedSpace is set up to make it relatively easy to add new Subspaces.
-    struct Subspace {
-        std::array&lt;MarkedAllocator*, numSizeClasses&gt; allocatorForSizeStep;
-        
-        // Each MarkedAllocator is a size class.
-        Bag&lt;MarkedAllocator&gt; bagOfAllocators;
-        
-        AllocatorAttributes attributes;
-    };
-    
</del><span class="cx">     MarkedSpace(Heap*);
</span><span class="cx">     ~MarkedSpace();
</span><del>-    void lastChanceToFinalize();
</del><ins>+    
+    Heap* heap() const { return m_heap; }
+    
+    void lastChanceToFinalize(); // You must call stopAllocating before you call this.
</ins><span class="cx"> 
</span><span class="cx">     static size_t optimalSizeFor(size_t);
</span><span class="cx">     
</span><del>-    static MarkedAllocator* allocatorFor(Subspace&amp;, size_t);
-
-    MarkedAllocator* allocatorFor(size_t);
-    MarkedAllocator* destructorAllocatorFor(size_t);
-    MarkedAllocator* auxiliaryAllocatorFor(size_t);
-
-    JS_EXPORT_PRIVATE void* allocate(Subspace&amp;, size_t);
-    JS_EXPORT_PRIVATE void* allocate(Subspace&amp;, GCDeferralContext*, size_t);
-    JS_EXPORT_PRIVATE void* tryAllocate(Subspace&amp;, size_t);
-    JS_EXPORT_PRIVATE void* tryAllocate(Subspace&amp;, GCDeferralContext*, size_t);
-    
-    void* allocateWithDestructor(size_t);
-    void* allocateWithoutDestructor(size_t);
-    void* allocateWithDestructor(GCDeferralContext*, size_t);
-    void* allocateWithoutDestructor(GCDeferralContext*, size_t);
-    void* allocateAuxiliary(size_t);
-    void* tryAllocateAuxiliary(size_t);
-    void* tryAllocateAuxiliary(GCDeferralContext*, size_t);
-    
-    Subspace&amp; subspaceForObjectsWithDestructor() { return m_destructorSpace; }
-    Subspace&amp; subspaceForObjectsWithoutDestructor() { return m_normalSpace; }
-    Subspace&amp; subspaceForAuxiliaryData() { return m_auxiliarySpace; }
-    
</del><span class="cx">     void prepareForAllocation();
</span><span class="cx"> 
</span><span class="cx">     void visitWeakSets(SlotVisitor&amp;);
</span><span class="lines">@@ -190,20 +159,24 @@
</span><span class="cx">     
</span><span class="cx">     MarkedBlock::Handle* findEmptyBlockToSteal();
</span><span class="cx">     
</span><ins>+    Lock&amp; allocatorLock() { return m_allocatorLock; }
+    MarkedAllocator* addMarkedAllocator(const AbstractLocker&amp;, Subspace*, size_t cellSize);
+    
</ins><span class="cx">     // When this is true it means that we have flipped but the mark bits haven't converged yet.
</span><span class="cx">     bool isMarking() const { return m_isMarking; }
</span><span class="cx">     
</span><span class="cx">     void dumpBits(PrintStream&amp; = WTF::dataFile());
</span><span class="cx">     
</span><ins>+    JS_EXPORT_PRIVATE static std::array&lt;size_t, numSizeClasses&gt; s_sizeClassForSizeStep;
+    
</ins><span class="cx"> private:
</span><span class="cx">     friend class LLIntOffsetsExtractor;
</span><span class="cx">     friend class JIT;
</span><span class="cx">     friend class WeakSet;
</span><ins>+    friend class Subspace;
</ins><span class="cx">     
</span><del>-    JS_EXPORT_PRIVATE static std::array&lt;size_t, numSizeClasses&gt; s_sizeClassForSizeStep;
-    
-    void* allocateLarge(Subspace&amp;, GCDeferralContext*, size_t);
-    void* tryAllocateLarge(Subspace&amp;, GCDeferralContext*, size_t);
</del><ins>+    void* allocateSlow(Subspace&amp;, GCDeferralContext*, size_t);
+    void* tryAllocateSlow(Subspace&amp;, GCDeferralContext*, size_t);
</ins><span class="cx"> 
</span><span class="cx">     static void initializeSizeClassForStepSize();
</span><span class="cx">     
</span><span class="lines">@@ -210,14 +183,19 @@
</span><span class="cx">     void initializeSubspace(Subspace&amp;);
</span><span class="cx"> 
</span><span class="cx">     template&lt;typename Functor&gt; inline void forEachAllocator(const Functor&amp;);
</span><del>-    template&lt;typename Functor&gt; inline void forEachSubspace(const Functor&amp;);
</del><span class="cx">     
</span><span class="cx">     void addActiveWeakSet(WeakSet*);
</span><span class="cx"> 
</span><del>-    Subspace m_destructorSpace;
-    Subspace m_normalSpace;
-    Subspace m_auxiliarySpace;
</del><ins>+    Vector&lt;Subspace*&gt; m_subspaces;
</ins><span class="cx"> 
</span><ins>+    Vector&lt;LargeAllocation*&gt; m_largeAllocations;
+    unsigned m_largeAllocationsNurseryOffset { 0 };
+    unsigned m_largeAllocationsOffsetForThisCollection { 0 };
+    unsigned m_largeAllocationsNurseryOffsetForSweep { 0 };
+    LargeAllocation** m_largeAllocationsForThisCollectionBegin { nullptr };
+    LargeAllocation** m_largeAllocationsForThisCollectionEnd { nullptr };
+    unsigned m_largeAllocationsForThisCollectionSize { 0 };
+
</ins><span class="cx">     Heap* m_heap;
</span><span class="cx">     HeapVersion m_markingVersion { initialVersion };
</span><span class="cx">     HeapVersion m_newlyAllocatedVersion { initialVersion };
</span><span class="lines">@@ -226,79 +204,16 @@
</span><span class="cx">     bool m_isMarking { false };
</span><span class="cx">     MarkedBlockSet m_blocks;
</span><span class="cx">     
</span><del>-    Vector&lt;LargeAllocation*&gt; m_largeAllocations;
-    unsigned m_largeAllocationsNurseryOffset { 0 };
-    unsigned m_largeAllocationsOffsetForThisCollection { 0 };
-    unsigned m_largeAllocationsNurseryOffsetForSweep { 0 };
-    LargeAllocation** m_largeAllocationsForThisCollectionBegin { nullptr };
-    LargeAllocation** m_largeAllocationsForThisCollectionEnd { nullptr };
-    unsigned m_largeAllocationsForThisCollectionSize { 0 };
-    
</del><span class="cx">     SentinelLinkedList&lt;WeakSet, BasicRawSentinelNode&lt;WeakSet&gt;&gt; m_activeWeakSets;
</span><span class="cx">     SentinelLinkedList&lt;WeakSet, BasicRawSentinelNode&lt;WeakSet&gt;&gt; m_newActiveWeakSets;
</span><del>-    
</del><ins>+
+    Lock m_allocatorLock;
+    Bag&lt;MarkedAllocator&gt; m_bagOfAllocators;
</ins><span class="cx">     MarkedAllocator* m_firstAllocator { nullptr };
</span><ins>+    MarkedAllocator* m_lastAllocator { nullptr };
</ins><span class="cx">     MarkedAllocator* m_allocatorForEmptyAllocation { nullptr };
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-inline MarkedAllocator* MarkedSpace::allocatorFor(Subspace&amp; space, size_t bytes)
-{
-    ASSERT(bytes);
-    if (bytes &lt;= largeCutoff)
-        return space.allocatorForSizeStep[sizeClassToIndex(bytes)];
-    return nullptr;
-}
-
-inline MarkedAllocator* MarkedSpace::allocatorFor(size_t bytes)
-{
-    return allocatorFor(m_normalSpace, bytes);
-}
-
-inline MarkedAllocator* MarkedSpace::destructorAllocatorFor(size_t bytes)
-{
-    return allocatorFor(m_destructorSpace, bytes);
-}
-
-inline MarkedAllocator* MarkedSpace::auxiliaryAllocatorFor(size_t bytes)
-{
-    return allocatorFor(m_auxiliarySpace, bytes);
-}
-
-inline void* MarkedSpace::allocateWithoutDestructor(size_t bytes)
-{
-    return allocate(m_normalSpace, bytes);
-}
-
-inline void* MarkedSpace::allocateWithDestructor(size_t bytes)
-{
-    return allocate(m_destructorSpace, bytes);
-}
-
-inline void* MarkedSpace::allocateWithoutDestructor(GCDeferralContext* deferralContext, size_t bytes)
-{
-    return allocate(m_normalSpace, deferralContext, bytes);
-}
-
-inline void* MarkedSpace::allocateWithDestructor(GCDeferralContext* deferralContext, size_t bytes)
-{
-    return allocate(m_destructorSpace, deferralContext, bytes);
-}
-
-inline void* MarkedSpace::allocateAuxiliary(size_t bytes)
-{
-    return allocate(m_auxiliarySpace, bytes);
-}
-
-inline void* MarkedSpace::tryAllocateAuxiliary(size_t bytes)
-{
-    return tryAllocate(m_auxiliarySpace, bytes);
-}
-
-inline void* MarkedSpace::tryAllocateAuxiliary(GCDeferralContext* deferralContext, size_t bytes)
-{
-    return tryAllocate(m_auxiliarySpace, deferralContext, bytes);
-}
-
</del><span class="cx"> template &lt;typename Functor&gt; inline void MarkedSpace::forEachBlock(const Functor&amp; functor)
</span><span class="cx"> {
</span><span class="cx">     forEachAllocator(
</span><span class="lines">@@ -317,26 +232,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename Functor&gt;
-inline void MarkedSpace::forEachSubspace(const Functor&amp; func)
-{
-    AllocatorAttributes attributes;
-    
-    attributes.destruction = NeedsDestruction;
-    attributes.cellKind = HeapCell::JSCell;
-    if (func(m_destructorSpace, attributes) == IterationStatus::Done)
-        return;
-    
-    attributes.destruction = DoesNotNeedDestruction;
-    attributes.cellKind = HeapCell::JSCell;
-    if (func(m_normalSpace, attributes) == IterationStatus::Done)
-        return;
-
-    attributes.destruction = DoesNotNeedDestruction;
-    attributes.cellKind = HeapCell::Auxiliary;
-    func(m_auxiliarySpace, attributes);
-}
-
</del><span class="cx"> ALWAYS_INLINE size_t MarkedSpace::optimalSizeFor(size_t bytes)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(bytes);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkingConstraintcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkingConstraint.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkingConstraint.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/MarkingConstraint.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -33,7 +33,7 @@
</span><span class="cx"> MarkingConstraint::MarkingConstraint(
</span><span class="cx">     CString abbreviatedName, CString name,
</span><span class="cx">     ::Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp;)&gt; executeFunction,
</span><del>-    Volatility volatility)
</del><ins>+    ConstraintVolatility volatility)
</ins><span class="cx">     : m_abbreviatedName(abbreviatedName)
</span><span class="cx">     , m_name(WTFMove(name))
</span><span class="cx">     , m_executeFunction(WTFMove(executeFunction))
</span><span class="lines">@@ -45,7 +45,7 @@
</span><span class="cx">     CString abbreviatedName, CString name,
</span><span class="cx">     ::Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp;)&gt; executeFunction,
</span><span class="cx">     ::Function&lt;double(SlotVisitor&amp;)&gt; quickWorkEstimateFunction,
</span><del>-    Volatility volatility)
</del><ins>+    ConstraintVolatility volatility)
</ins><span class="cx">     : m_abbreviatedName(abbreviatedName)
</span><span class="cx">     , m_name(WTFMove(name))
</span><span class="cx">     , m_executeFunction(WTFMove(executeFunction))
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkingConstrainth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkingConstraint.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkingConstraint.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/MarkingConstraint.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -25,6 +25,7 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><ins>+#include &quot;ConstraintVolatility.h&quot;
</ins><span class="cx"> #include &quot;VisitingTimeout.h&quot;
</span><span class="cx"> #include &lt;wtf/FastMalloc.h&gt;
</span><span class="cx"> #include &lt;wtf/Function.h&gt;
</span><span class="lines">@@ -41,34 +42,18 @@
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(MarkingConstraint);
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>-    enum Volatility {
-        // FIXME: We could introduce a new kind of volatility called GreyedByResumption, which
-        // would mean running all of the times that GreyedByExecution runs except as a root in a
-        // full GC.
-        // https://bugs.webkit.org/show_bug.cgi?id=166830
-        
-        // The constraint needs to be reevaluated anytime the mutator runs: so at GC start and
-        // whenever the GC resuspends after a resumption. This is almost always something that
-        // you'd call a &quot;root&quot; in a traditional GC.
-        GreyedByExecution,
-        
-        // The constraint needs to be reevaluated any time any object is marked and anytime the
-        // mutator resumes.
-        GreyedByMarking
-    };
-    
-    MarkingConstraint(
</del><ins>+    JS_EXPORT_PRIVATE MarkingConstraint(
</ins><span class="cx">         CString abbreviatedName, CString name,
</span><span class="cx">         ::Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp;)&gt;,
</span><del>-        Volatility);
</del><ins>+        ConstraintVolatility);
</ins><span class="cx">     
</span><del>-    MarkingConstraint(
</del><ins>+    JS_EXPORT_PRIVATE MarkingConstraint(
</ins><span class="cx">         CString abbreviatedName, CString name,
</span><span class="cx">         ::Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp;)&gt;,
</span><span class="cx">         ::Function&lt;double(SlotVisitor&amp;)&gt;,
</span><del>-        Volatility);
</del><ins>+        ConstraintVolatility);
</ins><span class="cx">     
</span><del>-    ~MarkingConstraint();
</del><ins>+    JS_EXPORT_PRIVATE ~MarkingConstraint();
</ins><span class="cx">     
</span><span class="cx">     unsigned index() const { return m_index; }
</span><span class="cx">     
</span><span class="lines">@@ -93,7 +78,7 @@
</span><span class="cx">         return lastVisitCount() + quickWorkEstimate(visitor);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    Volatility volatility() const { return m_volatility; }
</del><ins>+    ConstraintVolatility volatility() const { return m_volatility; }
</ins><span class="cx">     
</span><span class="cx"> private:
</span><span class="cx">     friend class MarkingConstraintSet; // So it can set m_index.
</span><span class="lines">@@ -103,7 +88,7 @@
</span><span class="cx">     CString m_name;
</span><span class="cx">     ::Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp; timeout)&gt; m_executeFunction;
</span><span class="cx">     ::Function&lt;double(SlotVisitor&amp;)&gt; m_quickWorkEstimateFunction;
</span><del>-    Volatility m_volatility;
</del><ins>+    ConstraintVolatility m_volatility;
</ins><span class="cx">     size_t m_lastVisitCount { 0 };
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkingConstraintSetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkingConstraintSet.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkingConstraintSet.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/MarkingConstraintSet.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -93,17 +93,19 @@
</span><span class="cx">     for (auto&amp; constraint : m_set) {
</span><span class="cx">         constraint-&gt;resetStats();
</span><span class="cx">         switch (constraint-&gt;volatility()) {
</span><del>-        case MarkingConstraint::GreyedByExecution:
</del><ins>+        case ConstraintVolatility::GreyedByExecution:
</ins><span class="cx">             m_unexecutedRoots.set(constraint-&gt;index());
</span><span class="cx">             break;
</span><del>-        case MarkingConstraint::GreyedByMarking:
</del><ins>+        case ConstraintVolatility::GreyedByMarking:
</ins><span class="cx">             m_unexecutedOutgrowths.set(constraint-&gt;index());
</span><span class="cx">             break;
</span><ins>+        case ConstraintVolatility::SeldomGreyed:
+            break;
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MarkingConstraintSet::add(CString abbreviatedName, CString name, Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp;)&gt; function, MarkingConstraint::Volatility volatility)
</del><ins>+void MarkingConstraintSet::add(CString abbreviatedName, CString name, Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp;)&gt; function, ConstraintVolatility volatility)
</ins><span class="cx"> {
</span><span class="cx">     add(std::make_unique&lt;MarkingConstraint&gt;(WTFMove(abbreviatedName), WTFMove(name), WTFMove(function), volatility));
</span><span class="cx"> }
</span><span class="lines">@@ -112,7 +114,7 @@
</span><span class="cx">     CString abbreviatedName, CString name,
</span><span class="cx">     Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp;)&gt; executeFunction,
</span><span class="cx">     Function&lt;double(SlotVisitor&amp;)&gt; quickWorkEstimateFunction,
</span><del>-    MarkingConstraint::Volatility volatility)
</del><ins>+    ConstraintVolatility volatility)
</ins><span class="cx"> {
</span><span class="cx">     add(std::make_unique&lt;MarkingConstraint&gt;(WTFMove(abbreviatedName), WTFMove(name), WTFMove(executeFunction), WTFMove(quickWorkEstimateFunction), volatility));
</span><span class="cx"> }
</span><span class="lines">@@ -122,7 +124,7 @@
</span><span class="cx"> {
</span><span class="cx">     constraint-&gt;m_index = m_set.size();
</span><span class="cx">     m_ordered.append(constraint.get());
</span><del>-    if (constraint-&gt;volatility() == MarkingConstraint::GreyedByMarking)
</del><ins>+    if (constraint-&gt;volatility() == ConstraintVolatility::GreyedByMarking)
</ins><span class="cx">         m_outgrowths.append(constraint.get());
</span><span class="cx">     m_set.append(WTFMove(constraint));
</span><span class="cx"> }
</span><span class="lines">@@ -194,14 +196,29 @@
</span><span class="cx">         m_ordered.begin(), m_ordered.end(),
</span><span class="cx">         [&amp;] (MarkingConstraint* a, MarkingConstraint* b) -&gt; bool {
</span><span class="cx">             // Remember: return true if a should come before b.
</span><del>-            if (a-&gt;volatility() != b-&gt;volatility()) {
</del><ins>+            
+            auto volatilityScore = [] (MarkingConstraint* constraint) -&gt; unsigned {
+                return constraint-&gt;volatility() == ConstraintVolatility::GreyedByMarking ? 1 : 0;
+            };
+            
+            unsigned aVolatilityScore = volatilityScore(a);
+            unsigned bVolatilityScore = volatilityScore(b);
+            
+            if (aVolatilityScore != bVolatilityScore) {
</ins><span class="cx">                 if (isWavefrontAdvancing)
</span><del>-                    return a-&gt;volatility() &gt; b-&gt;volatility(); // GreyedByMarking should come before GreyedByExecution.
</del><ins>+                    return aVolatilityScore &gt; bVolatilityScore;
</ins><span class="cx">                 else
</span><del>-                    return a-&gt;volatility() &lt; b-&gt;volatility(); // GreyedByExecution should come before GreyedByMarking.
</del><ins>+                    return aVolatilityScore &lt; bVolatilityScore;
</ins><span class="cx">             }
</span><span class="cx">             
</span><del>-            return a-&gt;workEstimate(visitor) &gt; b-&gt;workEstimate(visitor);
</del><ins>+            double aWorkEstimate = a-&gt;workEstimate(visitor);
+            double bWorkEstimate = b-&gt;workEstimate(visitor);
+            
+            if (aWorkEstimate != bWorkEstimate)
+                return aWorkEstimate &gt; bWorkEstimate;
+            
+            // This causes us to use SeldomGreyed vs GreyedByExecution as a final tie-breaker.
+            return a-&gt;volatility() &gt; b-&gt;volatility();
</ins><span class="cx">         });
</span><span class="cx">     
</span><span class="cx">     for (MarkingConstraint* constraint : m_ordered) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkingConstraintSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkingConstraintSet.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkingConstraintSet.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/MarkingConstraintSet.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -42,7 +42,7 @@
</span><span class="cx">         CString abbreviatedName,
</span><span class="cx">         CString name,
</span><span class="cx">         ::Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp;)&gt;,
</span><del>-        MarkingConstraint::Volatility);
</del><ins>+        ConstraintVolatility);
</ins><span class="cx">     
</span><span class="cx">     void add(
</span><span class="cx">         CString abbreviatedName,
</span><span class="lines">@@ -49,7 +49,7 @@
</span><span class="cx">         CString name,
</span><span class="cx">         ::Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp;)&gt;,
</span><span class="cx">         ::Function&lt;double(SlotVisitor&amp;)&gt;,
</span><del>-        MarkingConstraint::Volatility);
</del><ins>+        ConstraintVolatility);
</ins><span class="cx">     
</span><span class="cx">     void add(std::unique_ptr&lt;MarkingConstraint&gt;);
</span><span class="cx">     
</span><span class="lines">@@ -62,8 +62,8 @@
</span><span class="cx">     // that you'll do some draining after this and then use executeConvergence().
</span><span class="cx">     bool executeBootstrap(SlotVisitor&amp;, MonotonicTime timeout = MonotonicTime::infinity());
</span><span class="cx">     
</span><del>-    // Returns true if all constraints were executed. This assumes that you've alraedy
-    // visited roots and drained from there.
</del><ins>+    // Returns true if this executed all constraints and none of them produced new work. This
+    // assumes that you've alraedy visited roots and drained from there.
</ins><span class="cx">     bool executeConvergence(
</span><span class="cx">         SlotVisitor&amp;,
</span><span class="cx">         MonotonicTime timeout = MonotonicTime::infinity());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -346,12 +346,6 @@
</span><span class="cx">     SlotVisitor&amp; m_visitor;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-void SlotVisitor::visitAsConstraint(const JSCell* cell)
-{
-    m_isVisitingMutatorStack = true;
-    visitChildren(cell);
-}
-
</del><span class="cx"> ALWAYS_INLINE void SlotVisitor::visitChildren(const JSCell* cell)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(Heap::isMarkedConcurrently(cell));
</span><span class="lines">@@ -360,8 +354,8 @@
</span><span class="cx">     
</span><span class="cx">     if (false) {
</span><span class="cx">         dataLog(&quot;Visiting &quot;, RawPointer(cell));
</span><del>-        if (m_isVisitingMutatorStack)
-            dataLog(&quot; (mutator)&quot;);
</del><ins>+        if (!m_isFirstVisit)
+            dataLog(&quot; (subsequent)&quot;);
</ins><span class="cx">         dataLog(&quot;\n&quot;);
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -395,11 +389,17 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (UNLIKELY(m_heapSnapshotBuilder)) {
</span><del>-        if (!m_isVisitingMutatorStack)
</del><ins>+        if (m_isFirstVisit)
</ins><span class="cx">             m_heapSnapshotBuilder-&gt;appendNode(const_cast&lt;JSCell*&gt;(cell));
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SlotVisitor::visitAsConstraint(const JSCell* cell)
+{
+    m_isFirstVisit = false;
+    visitChildren(cell);
+}
+
</ins><span class="cx"> void SlotVisitor::donateKnownParallel(MarkStackArray&amp; from, MarkStackArray&amp; to)
</span><span class="cx"> {
</span><span class="cx">     // NOTE: Because we re-try often, we can afford to be conservative, and
</span><span class="lines">@@ -469,7 +469,7 @@
</span><span class="cx">         updateMutatorIsStopped(locker);
</span><span class="cx">         if (!m_collectorStack.isEmpty()) {
</span><span class="cx">             m_collectorStack.refill();
</span><del>-            m_isVisitingMutatorStack = false;
</del><ins>+            m_isFirstVisit = true;
</ins><span class="cx">             for (unsigned countdown = Options::minimumNumberOfScansBetweenRebalance(); m_collectorStack.canRemoveLast() &amp;&amp; countdown--;)
</span><span class="cx">                 visitChildren(m_collectorStack.removeLast());
</span><span class="cx">         } else if (!m_mutatorStack.isEmpty()) {
</span><span class="lines">@@ -477,7 +477,7 @@
</span><span class="cx">             // We know for sure that we are visiting objects because of the barrier, not because of
</span><span class="cx">             // marking. Marking will visit an object exactly once. The barrier will visit it
</span><span class="cx">             // possibly many times, and always after it was already marked.
</span><del>-            m_isVisitingMutatorStack = true;
</del><ins>+            m_isFirstVisit = false;
</ins><span class="cx">             for (unsigned countdown = Options::minimumNumberOfScansBetweenRebalance(); m_mutatorStack.canRemoveLast() &amp;&amp; countdown--;)
</span><span class="cx">                 visitChildren(m_mutatorStack.removeLast());
</span><span class="cx">         } else
</span><span class="lines">@@ -486,7 +486,7 @@
</span><span class="cx">         donateKnownParallel();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    mergeOpaqueRootsIfNecessary();
</del><ins>+    mergeIfNecessary();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool SlotVisitor::didReachTermination()
</span><span class="lines">@@ -614,15 +614,18 @@
</span><span class="cx">     if (!root)
</span><span class="cx">         return;
</span><span class="cx">     
</span><ins>+    if (m_ignoreNewOpaqueRoots)
+        return;
+    
</ins><span class="cx">     if (Options::numberOfGCMarkers() == 1) {
</span><span class="cx">         // Put directly into the shared HashSet.
</span><del>-        m_visitCount += m_heap.m_opaqueRoots.add(root).isNewEntry;
</del><ins>+        m_heap.m_opaqueRoots.add(root);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     // Put into the local set, but merge with the shared one every once in
</span><span class="cx">     // a while to make sure that the local sets don't grow too large.
</span><span class="cx">     mergeOpaqueRootsIfProfitable();
</span><del>-    m_visitCount += m_opaqueRoots.add(root);
</del><ins>+    m_opaqueRoots.add(root);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool SlotVisitor::containsOpaqueRoot(void* root) const
</span><span class="lines">@@ -647,13 +650,13 @@
</span><span class="cx">     return MixedTriState;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SlotVisitor::mergeOpaqueRootsIfNecessary()
</del><ins>+void SlotVisitor::mergeIfNecessary()
</ins><span class="cx"> {
</span><span class="cx">     if (m_opaqueRoots.isEmpty())
</span><span class="cx">         return;
</span><span class="cx">     mergeOpaqueRoots();
</span><span class="cx"> }
</span><del>-    
</del><ins>+
</ins><span class="cx"> void SlotVisitor::mergeOpaqueRootsIfProfitable()
</span><span class="cx"> {
</span><span class="cx">     if (static_cast&lt;unsigned&gt;(m_opaqueRoots.size()) &lt; Options::opaqueRootMergeThreshold())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitor.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitor.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitor.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -92,6 +92,7 @@
</span><span class="cx">     void append(const Weak&lt;T&gt;&amp; weak);
</span><span class="cx">     
</span><span class="cx">     JS_EXPORT_PRIVATE void addOpaqueRoot(void*);
</span><ins>+    
</ins><span class="cx">     JS_EXPORT_PRIVATE bool containsOpaqueRoot(void*) const;
</span><span class="cx">     TriState containsOpaqueRootTriState(void*) const;
</span><span class="cx"> 
</span><span class="lines">@@ -116,6 +117,8 @@
</span><span class="cx"> 
</span><span class="cx">     SharedDrainResult drainInParallel(MonotonicTime timeout = MonotonicTime::infinity());
</span><span class="cx">     SharedDrainResult drainInParallelPassively(MonotonicTime timeout = MonotonicTime::infinity());
</span><ins>+    
+    JS_EXPORT_PRIVATE void mergeIfNecessary();
</ins><span class="cx"> 
</span><span class="cx">     // This informs the GC about auxiliary of some size that we are keeping alive. If you don't do
</span><span class="cx">     // this then the space will be freed at end of GC.
</span><span class="lines">@@ -135,8 +138,6 @@
</span><span class="cx">     
</span><span class="cx">     HeapVersion markingVersion() const { return m_markingVersion; }
</span><span class="cx"> 
</span><del>-    void mergeOpaqueRootsIfNecessary();
-    
</del><span class="cx">     bool mutatorIsStopped() const { return m_mutatorIsStopped; }
</span><span class="cx">     
</span><span class="cx">     Lock&amp; rightToRun() { return m_rightToRun; }
</span><span class="lines">@@ -155,6 +156,8 @@
</span><span class="cx">     void visitAsConstraint(const JSCell*);
</span><span class="cx">     
</span><span class="cx">     bool didReachTermination();
</span><ins>+    
+    void setIgnoreNewOpaqueRoots(bool value) { m_ignoreNewOpaqueRoots = value; }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class ParallelModeEnabler;
</span><span class="lines">@@ -176,7 +179,8 @@
</span><span class="cx">     
</span><span class="cx">     void noteLiveAuxiliaryCell(HeapCell*);
</span><span class="cx">     
</span><del>-    JS_EXPORT_PRIVATE void mergeOpaqueRoots();
</del><ins>+    void mergeOpaqueRoots();
+
</ins><span class="cx">     void mergeOpaqueRootsIfProfitable();
</span><span class="cx"> 
</span><span class="cx">     void visitChildren(const JSCell*);
</span><span class="lines">@@ -190,6 +194,7 @@
</span><span class="cx">     MarkStackArray m_collectorStack;
</span><span class="cx">     MarkStackArray m_mutatorStack;
</span><span class="cx">     OpaqueRootSet m_opaqueRoots; // Handle-owning data structures not visible to the garbage collector.
</span><ins>+    bool m_ignoreNewOpaqueRoots { false }; // Useful as a debugging mode.
</ins><span class="cx">     
</span><span class="cx">     size_t m_bytesVisited;
</span><span class="cx">     size_t m_visitCount;
</span><span class="lines">@@ -201,7 +206,7 @@
</span><span class="cx"> 
</span><span class="cx">     HeapSnapshotBuilder* m_heapSnapshotBuilder { nullptr };
</span><span class="cx">     JSCell* m_currentCell { nullptr };
</span><del>-    bool m_isVisitingMutatorStack { false };
</del><ins>+    bool m_isFirstVisit { false };
</ins><span class="cx">     bool m_mutatorIsStopped { false };
</span><span class="cx">     bool m_canOptimizeForStoppedMutator { false };
</span><span class="cx">     Lock m_rightToRun;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitorInlines.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitorInlines.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitorInlines.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -81,7 +81,7 @@
</span><span class="cx"> 
</span><span class="cx"> inline void SlotVisitor::reportExtraMemoryVisited(size_t size)
</span><span class="cx"> {
</span><del>-    if (!m_isVisitingMutatorStack)
</del><ins>+    if (m_isFirstVisit)
</ins><span class="cx">         heap()-&gt;reportExtraMemoryVisited(size);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -88,7 +88,7 @@
</span><span class="cx"> #if ENABLE(RESOURCE_USAGE)
</span><span class="cx"> inline void SlotVisitor::reportExternalMemoryVisited(size_t size)
</span><span class="cx"> {
</span><del>-    if (!m_isVisitingMutatorStack)
</del><ins>+    if (m_isFirstVisit)
</ins><span class="cx">         heap()-&gt;reportExternalMemoryVisited(size);
</span><span class="cx"> }
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSubspacecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/Subspace.cpp (0 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Subspace.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/heap/Subspace.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -0,0 +1,196 @@
</span><ins>+/*
+ * Copyright (C) 2017 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 &quot;config.h&quot;
+#include &quot;Subspace.h&quot;
+
+#include &quot;JSCInlines.h&quot;
+#include &quot;MarkedAllocatorInlines.h&quot;
+#include &quot;MarkedBlockInlines.h&quot;
+#include &quot;PreventCollectionScope.h&quot;
+#include &quot;SubspaceInlines.h&quot;
+
+namespace JSC {
+
+namespace {
+
+// Writing it this way ensures that when you pass this as a functor, the callee is specialized for
+// this callback. If you wrote this as a normal function then the callee would be specialized for
+// the function's type and it would have indirect calls to that function. And unlike a lambda, it's
+// possible to mark this ALWAYS_INLINE.
+struct DestroyFunc {
+    ALWAYS_INLINE void operator()(VM&amp; vm, JSCell* cell) const
+    {
+        ASSERT(cell-&gt;structureID());
+        ASSERT(cell-&gt;inlineTypeFlags() &amp; StructureIsImmortal);
+        Structure* structure = cell-&gt;structure(vm);
+        const ClassInfo* classInfo = structure-&gt;classInfo();
+        MethodTable::DestroyFunctionPtr destroy = classInfo-&gt;methodTable.destroy;
+        destroy(cell);
+    }
+};
+
+} // anonymous namespace
+
+Subspace::Subspace(CString name, Heap&amp; heap, AllocatorAttributes attributes)
+    : m_space(heap.objectSpace())
+    , m_name(name)
+    , m_attributes(attributes)
+{
+    // It's remotely possible that we're GCing right now even if the client is careful to only
+    // create subspaces right after VM creation, since collectContinuously (and probably other
+    // things) could cause a GC to be launched at pretty much any time and it's not 100% obvious
+    // that all clients would be able to ensure that there are zero safepoints between when they
+    // create VM and when they do this. Preventing GC while we're creating the Subspace ensures
+    // that we don't have to worry about whether it's OK for the GC to ever see a brand new
+    // subspace.
+    PreventCollectionScope preventCollectionScope(heap);
+    heap.objectSpace().m_subspaces.append(this);
+    
+    for (size_t i = MarkedSpace::numSizeClasses; i--;)
+        m_allocatorForSizeStep[i] = nullptr;
+}
+
+Subspace::~Subspace()
+{
+}
+
+FreeList Subspace::finishSweep(MarkedBlock::Handle&amp; block, MarkedBlock::Handle::SweepMode sweepMode)
+{
+    return block.finishSweepKnowingSubspace(sweepMode, DestroyFunc());
+}
+
+void Subspace::destroy(VM&amp; vm, JSCell* cell)
+{
+    DestroyFunc()(vm, cell);
+}
+
+// The reason why we distinguish between allocate and tryAllocate is to minimize the number of
+// checks on the allocation path in both cases. Likewise, the reason why we have overloads with and
+// without deferralContext is to minimize the amount of code for calling allocate when you don't
+// need the deferralContext.
+void* Subspace::allocate(size_t size)
+{
+    if (MarkedAllocator* allocator = tryAllocatorFor(size))
+        return allocator-&gt;allocate();
+    return allocateSlow(nullptr, size);
+}
+
+void* Subspace::allocate(GCDeferralContext* deferralContext, size_t size)
+{
+    if (MarkedAllocator* allocator = tryAllocatorFor(size))
+        return allocator-&gt;allocate(deferralContext);
+    return allocateSlow(deferralContext, size);
+}
+
+void* Subspace::tryAllocate(size_t size)
+{
+    if (MarkedAllocator* allocator = tryAllocatorFor(size))
+        return allocator-&gt;tryAllocate();
+    return tryAllocateSlow(nullptr, size);
+}
+
+void* Subspace::tryAllocate(GCDeferralContext* deferralContext, size_t size)
+{
+    if (MarkedAllocator* allocator = tryAllocatorFor(size))
+        return allocator-&gt;tryAllocate(deferralContext);
+    return tryAllocateSlow(deferralContext, size);
+}
+
+MarkedAllocator* Subspace::allocatorForSlow(size_t size)
+{
+    size_t index = MarkedSpace::sizeClassToIndex(size);
+    size_t sizeClass = MarkedSpace::s_sizeClassForSizeStep[index];
+    if (!sizeClass)
+        return nullptr;
+    
+    // This is written in such a way that it's OK for the JIT threads to end up here if they want
+    // to generate code that uses some allocator that hadn't been used yet. Note that a possibly-
+    // just-as-good solution would be to return null if we're in the JIT since the JIT treats null
+    // allocator as &quot;please always take the slow path&quot;. But, that could lead to performance
+    // surprises and the algorithm here is pretty easy. Only this code has to hold the lock, to
+    // prevent simultaneously MarkedAllocator creations from multiple threads. This code ensures
+    // that any &quot;forEachAllocator&quot; traversals will only see this allocator after it's initialized
+    // enough: it will have 
+    auto locker = holdLock(m_space.allocatorLock());
+    if (MarkedAllocator* allocator = m_allocatorForSizeStep[index])
+        return allocator;
+
+    if (false)
+        dataLog(&quot;Creating marked allocator for &quot;, m_name, &quot;, &quot;, m_attributes, &quot;, &quot;, sizeClass, &quot;.\n&quot;);
+    MarkedAllocator* allocator = m_space.addMarkedAllocator(locker, this, sizeClass);
+    index = MarkedSpace::sizeClassToIndex(sizeClass);
+    for (;;) {
+        if (MarkedSpace::s_sizeClassForSizeStep[index] != sizeClass)
+            break;
+
+        m_allocatorForSizeStep[index] = allocator;
+        
+        if (!index--)
+            break;
+    }
+    allocator-&gt;setNextAllocatorInSubspace(m_firstAllocator);
+    WTF::storeStoreFence();
+    m_firstAllocator = allocator;
+    return allocator;
+}
+
+void* Subspace::allocateSlow(GCDeferralContext* deferralContext, size_t size)
+{
+    void* result = tryAllocateSlow(deferralContext, size);
+    RELEASE_ASSERT(result);
+    return result;
+}
+
+void* Subspace::tryAllocateSlow(GCDeferralContext* deferralContext, size_t size)
+{
+    if (MarkedAllocator* allocator = allocatorFor(size))
+        return allocator-&gt;tryAllocate(deferralContext);
+    
+    if (size &lt;= Options::largeAllocationCutoff()
+        &amp;&amp; size &lt;= MarkedSpace::largeCutoff) {
+        dataLog(&quot;FATAL: attampting to allocate small object using large allocation.\n&quot;);
+        dataLog(&quot;Requested allocation size: &quot;, size, &quot;\n&quot;);
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+    
+    m_space.heap()-&gt;collectIfNecessaryOrDefer(deferralContext);
+    
+    size = WTF::roundUpToMultipleOf&lt;MarkedSpace::sizeStep&gt;(size);
+    LargeAllocation* allocation = LargeAllocation::tryCreate(*m_space.m_heap, size, this);
+    if (!allocation)
+        return nullptr;
+    
+    m_space.m_largeAllocations.append(allocation);
+    m_space.m_heap-&gt;didAllocate(size);
+    m_space.m_capacity += size;
+    
+    m_largeAllocations.append(allocation);
+        
+    return allocation-&gt;cell();
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSubspaceh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/Subspace.h (0 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Subspace.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/heap/Subspace.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -0,0 +1,122 @@
</span><ins>+/*
+ * Copyright (C) 2017 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 &quot;MarkedBlock.h&quot;
+#include &quot;MarkedSpace.h&quot;
+#include &lt;wtf/text/CString.h&gt;
+
+namespace JSC {
+
+// The idea of subspaces is that you can provide some custom behavior for your objects if you
+// allocate them from a custom Subspace in which you override some of the virtual methods. This
+// class is the baseclass of Subspaces and it provides a reasonable default implementation, where
+// sweeping assumes immortal structure. The common ways of overriding this are:
+//
+// - Provide customized destructor behavior. You can change how the destructor is called. You can
+//   also specialize the destructor call in the loop.
+//
+// - Use the Subspace as a quick way to iterate all of the objects in that subspace.
+class Subspace {
+    WTF_MAKE_NONCOPYABLE(Subspace);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    JS_EXPORT_PRIVATE Subspace(CString name, Heap&amp;, AllocatorAttributes);
+    JS_EXPORT_PRIVATE virtual ~Subspace();
+    
+    const char *name() const { return m_name.data(); }
+    MarkedSpace&amp; space() const { return m_space; }
+    
+    const AllocatorAttributes&amp; attributes() const { return m_attributes; }
+    
+    // The purpose of overriding this is to specialize the sweep for your destructors. This won't
+    // be called for no-destructor blocks. This must call MarkedBlock::finishSweepKnowingSubspace.
+    virtual FreeList finishSweep(MarkedBlock::Handle&amp;, MarkedBlock::Handle::SweepMode);
+    
+    // These get called for large objects.
+    virtual void destroy(VM&amp;, JSCell*);
+    
+    MarkedAllocator* tryAllocatorFor(size_t);
+    MarkedAllocator* allocatorFor(size_t);
+    
+    JS_EXPORT_PRIVATE void* allocate(size_t);
+    JS_EXPORT_PRIVATE void* allocate(GCDeferralContext*, size_t);
+    
+    JS_EXPORT_PRIVATE void* tryAllocate(size_t);
+    JS_EXPORT_PRIVATE void* tryAllocate(GCDeferralContext*, size_t);
+    
+    template&lt;typename Func&gt;
+    void forEachMarkedBlock(const Func&amp;);
+    
+    template&lt;typename Func&gt;
+    void forEachNotEmptyMarkedBlock(const Func&amp;);
+    
+    template&lt;typename Func&gt;
+    void forEachLargeAllocation(const Func&amp;);
+    
+    template&lt;typename Func&gt;
+    void forEachMarkedCell(const Func&amp;);
+    
+    static ptrdiff_t offsetOfAllocatorForSizeStep() { return OBJECT_OFFSETOF(Subspace, m_allocatorForSizeStep); }
+    
+    MarkedAllocator** allocatorForSizeStep() { return &amp;m_allocatorForSizeStep[0]; }
+
+private:
+    MarkedAllocator* allocatorForSlow(size_t);
+    
+    // These slow paths are concerned with large allocations and allocator creation.
+    void* allocateSlow(GCDeferralContext*, size_t);
+    void* tryAllocateSlow(GCDeferralContext*, size_t);
+    
+    MarkedSpace&amp; m_space;
+    
+    CString m_name;
+    AllocatorAttributes m_attributes;
+    
+    std::array&lt;MarkedAllocator*, MarkedSpace::numSizeClasses&gt; m_allocatorForSizeStep;
+    MarkedAllocator* m_firstAllocator { nullptr };
+    SentinelLinkedList&lt;LargeAllocation, BasicRawSentinelNode&lt;LargeAllocation&gt;&gt; m_largeAllocations;
+};
+
+ALWAYS_INLINE MarkedAllocator* Subspace::tryAllocatorFor(size_t size)
+{
+    if (size &lt;= MarkedSpace::largeCutoff)
+        return m_allocatorForSizeStep[MarkedSpace::sizeClassToIndex(size)];
+    return nullptr;
+}
+
+ALWAYS_INLINE MarkedAllocator* Subspace::allocatorFor(size_t size)
+{
+    if (size &lt;= MarkedSpace::largeCutoff) {
+        if (MarkedAllocator* result = m_allocatorForSizeStep[MarkedSpace::sizeClassToIndex(size)])
+            return result;
+        return allocatorForSlow(size);
+    }
+    return nullptr;
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSubspaceInlinesh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/SubspaceInlines.h (0 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SubspaceInlines.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/heap/SubspaceInlines.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -0,0 +1,76 @@
</span><ins>+/*
+ * Copyright (C) 2017 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 &quot;JSCell.h&quot;
+#include &quot;MarkedAllocator.h&quot;
+#include &quot;MarkedBlock.h&quot;
+#include &quot;MarkedSpace.h&quot;
+#include &quot;Subspace.h&quot;
+
+namespace JSC {
+
+template&lt;typename Func&gt;
+void Subspace::forEachMarkedBlock(const Func&amp; func)
+{
+    for (MarkedAllocator* allocator = m_firstAllocator; allocator; allocator = allocator-&gt;nextAllocatorInSubspace())
+        allocator-&gt;forEachBlock(func);
+}
+
+template&lt;typename Func&gt;
+void Subspace::forEachNotEmptyMarkedBlock(const Func&amp; func)
+{
+    for (MarkedAllocator* allocator = m_firstAllocator; allocator; allocator = allocator-&gt;nextAllocatorInSubspace())
+        allocator-&gt;forEachNotEmptyBlock(func);
+}
+
+template&lt;typename Func&gt;
+void Subspace::forEachLargeAllocation(const Func&amp; func)
+{
+    for (LargeAllocation* allocation = m_largeAllocations.begin(); allocation != m_largeAllocations.end(); allocation = allocation-&gt;next())
+        func(allocation);
+}
+
+template&lt;typename Func&gt;
+void Subspace::forEachMarkedCell(const Func&amp; func)
+{
+    forEachNotEmptyMarkedBlock(
+        [&amp;] (MarkedBlock::Handle* handle) {
+            handle-&gt;forEachMarkedCell(
+                [&amp;] (HeapCell* cell, HeapCell::Kind kind) -&gt; IterationStatus { 
+                    func(cell, kind);
+                    return IterationStatus::Continue;
+                });
+        });
+    forEachLargeAllocation(
+        [&amp;] (LargeAllocation* allocation) {
+            if (allocation-&gt;isMarked())
+                func(allocation-&gt;cell(), m_attributes.cellKind);
+        });
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapWeakBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/WeakBlock.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/WeakBlock.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/WeakBlock.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -100,7 +100,8 @@
</span><span class="cx"> {
</span><span class="cx">     HeapVersion markingVersion = visitor.markingVersion();
</span><span class="cx"> 
</span><del>-    for (size_t i = 0; i &lt; weakImplCount(); ++i) {
</del><ins>+    size_t count = weakImplCount();
+    for (size_t i = 0; i &lt; count; ++i) {
</ins><span class="cx">         WeakImpl* weakImpl = &amp;weakImpls()[i];
</span><span class="cx">         if (weakImpl-&gt;state() != WeakImpl::Live)
</span><span class="cx">             continue;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapWeakBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/WeakBlock.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/WeakBlock.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/WeakBlock.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -64,6 +64,7 @@
</span><span class="cx">     SweepResult takeSweepResult();
</span><span class="cx"> 
</span><span class="cx">     void visit(SlotVisitor&amp;);
</span><ins>+
</ins><span class="cx">     void reap();
</span><span class="cx"> 
</span><span class="cx">     void lastChanceToFinalize();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapWeakSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/WeakSet.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/WeakSet.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/heap/WeakSet.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -53,7 +53,8 @@
</span><span class="cx"> 
</span><span class="cx">     bool isEmpty() const;
</span><span class="cx"> 
</span><del>-    unsigned visit(SlotVisitor&amp;);
</del><ins>+    void visit(SlotVisitor&amp;);
+
</ins><span class="cx">     void reap();
</span><span class="cx">     void sweep();
</span><span class="cx">     void shrink();
</span><span class="lines">@@ -106,14 +107,10 @@
</span><span class="cx">         block-&gt;lastChanceToFinalize();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline unsigned WeakSet::visit(SlotVisitor&amp; visitor)
</del><ins>+inline void WeakSet::visit(SlotVisitor&amp; visitor)
</ins><span class="cx"> {
</span><del>-    unsigned count = 0;
-    for (WeakBlock* block = m_blocks.head(); block; block = block-&gt;next()) {
-        count++;
</del><ins>+    for (WeakBlock* block = m_blocks.head(); block; block = block-&gt;next())
</ins><span class="cx">         block-&gt;visit(visitor);
</span><del>-    }
-    return count;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline void WeakSet::reap()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -1542,7 +1542,7 @@
</span><span class="cx">         GPRReg resultGPR, StructureType structure, StorageType storage, GPRReg scratchGPR1,
</span><span class="cx">         GPRReg scratchGPR2, JumpList&amp; slowPath, size_t size)
</span><span class="cx">     {
</span><del>-        MarkedAllocator* allocator = vm()-&gt;heap.allocatorForObjectOfType&lt;ClassType&gt;(size);
</del><ins>+        MarkedAllocator* allocator = subspaceFor&lt;ClassType&gt;(*vm())-&gt;allocatorFor(size);
</ins><span class="cx">         if (!allocator) {
</span><span class="cx">             slowPath.append(jump());
</span><span class="cx">             return;
</span><span class="lines">@@ -1559,7 +1559,7 @@
</span><span class="cx">     
</span><span class="cx">     // allocationSize can be aliased with any of the other input GPRs. If it's not aliased then it
</span><span class="cx">     // won't be clobbered.
</span><del>-    void emitAllocateVariableSized(GPRReg resultGPR, MarkedSpace::Subspace&amp; subspace, GPRReg allocationSize, GPRReg scratchGPR1, GPRReg scratchGPR2, JumpList&amp; slowPath)
</del><ins>+    void emitAllocateVariableSized(GPRReg resultGPR, Subspace&amp; subspace, GPRReg allocationSize, GPRReg scratchGPR1, GPRReg scratchGPR2, JumpList&amp; slowPath)
</ins><span class="cx">     {
</span><span class="cx">         static_assert(!(MarkedSpace::sizeStep &amp; (MarkedSpace::sizeStep - 1)), &quot;MarkedSpace::sizeStep must be a power of two.&quot;);
</span><span class="cx">         
</span><span class="lines">@@ -1568,7 +1568,7 @@
</span><span class="cx">         add32(TrustedImm32(MarkedSpace::sizeStep - 1), allocationSize, scratchGPR1);
</span><span class="cx">         urshift32(TrustedImm32(stepShift), scratchGPR1);
</span><span class="cx">         slowPath.append(branch32(Above, scratchGPR1, TrustedImm32(MarkedSpace::largeCutoff &gt;&gt; stepShift)));
</span><del>-        move(TrustedImmPtr(&amp;subspace.allocatorForSizeStep[0] - 1), scratchGPR2);
</del><ins>+        move(TrustedImmPtr(subspace.allocatorForSizeStep() - 1), scratchGPR2);
</ins><span class="cx">         loadPtr(BaseIndex(scratchGPR2, scratchGPR1, timesPtr()), scratchGPR1);
</span><span class="cx">         
</span><span class="cx">         emitAllocate(resultGPR, nullptr, scratchGPR1, scratchGPR2, slowPath);
</span><span class="lines">@@ -1577,7 +1577,7 @@
</span><span class="cx">     template&lt;typename ClassType, typename StructureType&gt;
</span><span class="cx">     void emitAllocateVariableSizedCell(GPRReg resultGPR, StructureType structure, GPRReg allocationSize, GPRReg scratchGPR1, GPRReg scratchGPR2, JumpList&amp; slowPath)
</span><span class="cx">     {
</span><del>-        MarkedSpace::Subspace&amp; subspace = vm()-&gt;heap.template subspaceForObjectOfType&lt;ClassType&gt;();
</del><ins>+        Subspace&amp; subspace = *subspaceFor&lt;ClassType&gt;(*vm());
</ins><span class="cx">         emitAllocateVariableSized(resultGPR, subspace, allocationSize, scratchGPR1, scratchGPR2, slowPath);
</span><span class="cx">         emitStoreStructureWithTypeInfo(structure, resultGPR, scratchGPR2);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -83,7 +83,7 @@
</span><span class="cx"> {
</span><span class="cx">     Structure* structure = currentInstruction[3].u.objectAllocationProfile-&gt;structure();
</span><span class="cx">     size_t allocationSize = JSFinalObject::allocationSize(structure-&gt;inlineCapacity());
</span><del>-    MarkedAllocator* allocator = m_vm-&gt;heap.allocatorForObjectWithoutDestructor(allocationSize);
</del><ins>+    MarkedAllocator* allocator = subspaceFor&lt;JSFinalObject&gt;(*m_vm)-&gt;allocatorFor(allocationSize);
</ins><span class="cx"> 
</span><span class="cx">     RegisterID resultReg = regT0;
</span><span class="cx">     RegisterID allocatorReg = regT1;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodes32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -164,7 +164,7 @@
</span><span class="cx"> {
</span><span class="cx">     Structure* structure = currentInstruction[3].u.objectAllocationProfile-&gt;structure();
</span><span class="cx">     size_t allocationSize = JSFinalObject::allocationSize(structure-&gt;inlineCapacity());
</span><del>-    MarkedAllocator* allocator = m_vm-&gt;heap.allocatorForObjectWithoutDestructor(allocationSize);
</del><ins>+    MarkedAllocator* allocator = subspaceFor&lt;JSFinalObject&gt;(*m_vm)-&gt;allocatorFor(allocationSize);
</ins><span class="cx"> 
</span><span class="cx">     RegisterID resultReg = returnValueGPR;
</span><span class="cx">     RegisterID allocatorReg = regT1;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
</span><del>- *  Copyright (C) 2004-2008, 2012-2013, 2015-2016 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2004-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *  Copyright (C) 2006 Bjoern Graf (bjoern.graf@gmail.com)
</span><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="lines">@@ -166,7 +166,6 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     typedef JSNonFinalObject Base;
</span><del>-    static const bool needsDestruction = false;
</del><span class="cx"> 
</span><span class="cx">     Root* root() const { return m_root.get(); }
</span><span class="cx">     void setRoot(VM&amp; vm, Root* root) { m_root.set(vm, this, root); }
</span><span class="lines">@@ -267,7 +266,6 @@
</span><span class="cx">     typedef JSDestructibleObject Base;
</span><span class="cx"> 
</span><span class="cx">     DECLARE_INFO;
</span><del>-    static const bool needsDestruction = true;
</del><span class="cx"> 
</span><span class="cx">     static Structure* createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeButterflyInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ButterflyInlines.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ButterflyInlines.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/ButterflyInlines.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -59,10 +59,10 @@
</span><span class="cx">     return optimalContiguousVectorLength(structure ? structure-&gt;outOfLineCapacity() : 0, vectorLength);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline Butterfly* Butterfly::createUninitialized(VM&amp; vm, JSCell* intendedOwner, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes)
</del><ins>+inline Butterfly* Butterfly::createUninitialized(VM&amp; vm, JSCell*, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes)
</ins><span class="cx"> {
</span><span class="cx">     size_t size = totalSize(preCapacity, propertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes);
</span><del>-    void* base = vm.heap.allocateAuxiliary(intendedOwner, size);
</del><ins>+    void* base = vm.auxiliarySpace.allocate(size);
</ins><span class="cx">     Butterfly* result = fromBase(base, preCapacity, propertyCapacity);
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="lines">@@ -134,14 +134,16 @@
</span><span class="cx">     size_t newIndexingPayloadSizeInBytes)
</span><span class="cx"> {
</span><span class="cx">     ASSERT_UNUSED(oldStructure, !indexingHeader()-&gt;preCapacity(oldStructure));
</span><del>-    ASSERT_UNUSED(oldStructure, hadIndexingHeader == oldStructure-&gt;hasIndexingHeader(intendedOwner));
</del><ins>+    ASSERT_UNUSED(intendedOwner, hadIndexingHeader == oldStructure-&gt;hasIndexingHeader(intendedOwner));
</ins><span class="cx">     void* theBase = base(0, propertyCapacity);
</span><span class="cx">     size_t oldSize = totalSize(0, propertyCapacity, hadIndexingHeader, oldIndexingPayloadSizeInBytes);
</span><span class="cx">     size_t newSize = totalSize(0, propertyCapacity, true, newIndexingPayloadSizeInBytes);
</span><del>-    theBase = vm.heap.tryReallocateAuxiliary(intendedOwner, theBase, oldSize, newSize);
-    if (!theBase)
-        return 0;
-    return fromBase(theBase, 0, propertyCapacity);
</del><ins>+    void* newBase = vm.auxiliarySpace.tryAllocate(newSize);
+    if (!newBase)
+        return nullptr;
+    // FIXME: This probably shouldn't be a memcpy.
+    memcpy(newBase, theBase, oldSize);
+    return fromBase(newBase, 0, propertyCapacity);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline Butterfly* Butterfly::growArrayRight(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeClassInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ClassInfo.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ClassInfo.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/ClassInfo.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
</span><span class="cx">  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
</span><del>- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Library General Public
</span><span class="lines">@@ -38,7 +38,7 @@
</span><span class="cx"> 
</span><span class="cx">     typedef void (*VisitChildrenFunctionPtr)(JSCell*, SlotVisitor&amp;);
</span><span class="cx">     VisitChildrenFunctionPtr visitChildren;
</span><del>-
</del><ins>+    
</ins><span class="cx">     typedef CallType (*GetCallDataFunctionPtr)(JSCell*, CallData&amp;);
</span><span class="cx">     GetCallDataFunctionPtr getCallData;
</span><span class="cx"> 
</span><span class="lines">@@ -122,6 +122,9 @@
</span><span class="cx"> 
</span><span class="cx">     typedef size_t (*EstimatedSizeFunctionPtr)(JSCell*);
</span><span class="cx">     EstimatedSizeFunctionPtr estimatedSize;
</span><ins>+    
+    typedef void (*VisitOutputConstraintsPtr)(JSCell*, SlotVisitor&amp;);
+    VisitOutputConstraintsPtr visitOutputConstraints;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> #define CREATE_MEMBER_CHECKER(member) \
</span><span class="lines">@@ -174,7 +177,8 @@
</span><span class="cx">         &amp;ClassName::getPrototype, \
</span><span class="cx">         &amp;ClassName::dumpToStream, \
</span><span class="cx">         &amp;ClassName::heapSnapshot, \
</span><del>-        &amp;ClassName::estimatedSize \
</del><ins>+        &amp;ClassName::estimatedSize, \
+        &amp;ClassName::visitOutputConstraints \
</ins><span class="cx">     }, \
</span><span class="cx">     ClassName::TypedArrayStorageType
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeClonedArgumentscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ClonedArguments.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ClonedArguments.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/ClonedArguments.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -54,7 +54,7 @@
</span><span class="cx">         butterfly-&gt;arrayStorage()-&gt;m_numValuesInVector = vectorLength;
</span><span class="cx"> 
</span><span class="cx">     } else {
</span><del>-        void* temp = vm.heap.tryAllocateAuxiliary(nullptr, Butterfly::totalSize(0, structure-&gt;outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue)));
</del><ins>+        void* temp = vm.auxiliarySpace.tryAllocate(Butterfly::totalSize(0, structure-&gt;outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue)));
</ins><span class="cx">         if (!temp)
</span><span class="cx">             return 0;
</span><span class="cx">         butterfly = Butterfly::fromBase(temp, 0, structure-&gt;outOfLineCapacity());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeDirectArgumentscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -118,7 +118,7 @@
</span><span class="cx">     putDirect(vm, vm.propertyNames-&gt;callee, m_callee.get(), DontEnum);
</span><span class="cx">     putDirect(vm, vm.propertyNames-&gt;iteratorSymbol, globalObject()-&gt;arrayProtoValuesFunction(), DontEnum);
</span><span class="cx">     
</span><del>-    void* backingStore = vm.heap.tryAllocateAuxiliary(this, mappedArgumentsSize());
</del><ins>+    void* backingStore = vm.auxiliarySpace.tryAllocate(mappedArgumentsSize());
</ins><span class="cx">     RELEASE_ASSERT(backingStore);
</span><span class="cx">     bool* overrides = static_cast&lt;bool*&gt;(backingStore);
</span><span class="cx">     m_mappedArguments.set(vm, this, overrides);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeGenericArgumentsInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/GenericArgumentsInlines.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/GenericArgumentsInlines.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/GenericArgumentsInlines.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -259,7 +259,7 @@
</span><span class="cx">     RELEASE_ASSERT(!m_modifiedArgumentsDescriptor);
</span><span class="cx"> 
</span><span class="cx">     if (argsLength) {
</span><del>-        void* backingStore = vm.heap.tryAllocateAuxiliary(this, WTF::roundUpToMultipleOf&lt;8&gt;(argsLength));
</del><ins>+        void* backingStore = vm.auxiliarySpace.tryAllocate(WTF::roundUpToMultipleOf&lt;8&gt;(argsLength));
</ins><span class="cx">         RELEASE_ASSERT(backingStore);
</span><span class="cx">         bool* modifiedArguments = static_cast&lt;bool*&gt;(backingStore);
</span><span class="cx">         m_modifiedArgumentsDescriptor.set(vm, this, modifiedArguments);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeHashMapImplh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/HashMapImpl.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/HashMapImpl.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/HashMapImpl.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -171,11 +171,11 @@
</span><span class="cx">         return bitwise_cast&lt;BucketType**&gt;(this);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    static HashMapBuffer* create(ExecState* exec, VM&amp; vm, JSCell* owner, uint32_t capacity)
</del><ins>+    static HashMapBuffer* create(ExecState* exec, VM&amp; vm, JSCell*, uint32_t capacity)
</ins><span class="cx">     {
</span><span class="cx">         auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="cx">         size_t allocationSize = HashMapBuffer::allocationSize(capacity);
</span><del>-        void* data = vm.heap.tryAllocateAuxiliary(owner, allocationSize);
</del><ins>+        void* data = vm.auxiliarySpace.tryAllocate(allocationSize);
</ins><span class="cx">         if (!data) {
</span><span class="cx">             throwOutOfMemoryError(exec, scope);
</span><span class="cx">             return nullptr;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSArraycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSArray.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSArray.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/JSArray.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -75,7 +75,7 @@
</span><span class="cx">             || hasContiguous(indexingType));
</span><span class="cx"> 
</span><span class="cx">         unsigned vectorLength = Butterfly::optimalContiguousVectorLength(structure, initialLength);
</span><del>-        void* temp = vm.heap.tryAllocateAuxiliary(deferralContext, nullptr, Butterfly::totalSize(0, outOfLineStorage, true, vectorLength * sizeof(EncodedJSValue)));
</del><ins>+        void* temp = vm.auxiliarySpace.tryAllocate(deferralContext, Butterfly::totalSize(0, outOfLineStorage, true, vectorLength * sizeof(EncodedJSValue)));
</ins><span class="cx">         if (!temp)
</span><span class="cx">             return nullptr;
</span><span class="cx">         butterfly = Butterfly::fromBase(temp, 0, outOfLineStorage);
</span><span class="lines">@@ -90,7 +90,7 @@
</span><span class="cx">         }
</span><span class="cx">     } else {
</span><span class="cx">         unsigned vectorLength = ArrayStorage::optimalVectorLength(0, structure, initialLength);
</span><del>-        void* temp = vm.heap.tryAllocateAuxiliary(nullptr, Butterfly::totalSize(0, outOfLineStorage, true, ArrayStorage::sizeFor(vectorLength)));
</del><ins>+        void* temp = vm.auxiliarySpace.tryAllocate(deferralContext, Butterfly::totalSize(0, outOfLineStorage, true, ArrayStorage::sizeFor(vectorLength)));
</ins><span class="cx">         if (!temp)
</span><span class="cx">             return nullptr;
</span><span class="cx">         butterfly = Butterfly::fromBase(temp, 0, outOfLineStorage);
</span><span class="lines">@@ -347,7 +347,7 @@
</span><span class="cx">         allocatedNewStorage = false;
</span><span class="cx">     } else {
</span><span class="cx">         size_t newSize = Butterfly::totalSize(0, propertyCapacity, true, ArrayStorage::sizeFor(desiredCapacity));
</span><del>-        newAllocBase = vm.heap.tryAllocateAuxiliary(this, newSize);
</del><ins>+        newAllocBase = vm.auxiliarySpace.tryAllocate(newSize);
</ins><span class="cx">         if (!newAllocBase)
</span><span class="cx">             return false;
</span><span class="cx">         newStorageCapacity = desiredCapacity;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSArrayBufferViewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -65,7 +65,7 @@
</span><span class="cx">         void* temp;
</span><span class="cx">         size_t size = sizeOf(length, elementSize);
</span><span class="cx">         if (size) {
</span><del>-            temp = vm.heap.tryAllocateAuxiliary(nullptr, size);
</del><ins>+            temp = vm.auxiliarySpace.tryAllocate(nullptr, size);
</ins><span class="cx">             if (!temp)
</span><span class="cx">                 return;
</span><span class="cx">         } else
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCellh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCell.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCell.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/JSCell.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
</span><span class="cx">  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
</span><del>- *  Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2015 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Library General Public
</span><span class="lines">@@ -81,6 +81,12 @@
</span><span class="cx"> 
</span><span class="cx">     static const bool needsDestruction = false;
</span><span class="cx"> 
</span><ins>+    // Don't call this directly. Call JSC::subspaceFor&lt;Type&gt;(vm) instead.
+    // FIXME: Refer to Subspace by reference.
+    // https://bugs.webkit.org/show_bug.cgi?id=166988
+    template&lt;typename CellType&gt;
+    static Subspace* subspaceFor(VM&amp;);
+
</ins><span class="cx">     static JSCell* seenMultipleCalleeObjects() { return bitwise_cast&lt;JSCell*&gt;(static_cast&lt;uintptr_t&gt;(1)); }
</span><span class="cx"> 
</span><span class="cx">     enum CreatingEarlyCellTag { CreatingEarlyCell };
</span><span class="lines">@@ -154,6 +160,7 @@
</span><span class="cx">     JS_EXPORT_PRIVATE static size_t estimatedSize(JSCell*);
</span><span class="cx"> 
</span><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><ins>+    static void visitOutputConstraints(JSCell*, SlotVisitor&amp;);
</ins><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE static void heapSnapshot(JSCell*, HeapSnapshotBuilder&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -290,4 +297,12 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// FIXME: Refer to Subspace by reference.
+// https://bugs.webkit.org/show_bug.cgi?id=166988
+template&lt;typename Type&gt;
+inline Subspace* subspaceFor(VM&amp; vm)
+{
+    return Type::template subspaceFor&lt;Type&gt;(vm);
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCellInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCellInlines.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCellInlines.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/JSCellInlines.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -120,6 +120,10 @@
</span><span class="cx">     visitor.appendUnbarriered(cell-&gt;structure(visitor.vm()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline void JSCell::visitOutputConstraints(JSCell*, SlotVisitor&amp;)
+{
+}
+
</ins><span class="cx"> ALWAYS_INLINE VM&amp; ExecState::vm() const
</span><span class="cx"> {
</span><span class="cx">     ASSERT(callee());
</span><span class="lines">@@ -129,12 +133,20 @@
</span><span class="cx">     return *callee()-&gt;markedBlock().vm();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename CellType&gt;
+Subspace* JSCell::subspaceFor(VM&amp; vm)
+{
+    if (CellType::needsDestruction)
+        return &amp;vm.destructibleCellSpace;
+    return &amp;vm.cellSpace;
+}
+
</ins><span class="cx"> template&lt;typename T&gt;
</span><span class="cx"> void* allocateCell(Heap&amp; heap, size_t size)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!DisallowGC::isGCDisallowedOnCurrentThread());
</span><span class="cx">     ASSERT(size &gt;= sizeof(T));
</span><del>-    JSCell* result = static_cast&lt;JSCell*&gt;(heap.allocateObjectOfType&lt;T&gt;(size));
</del><ins>+    JSCell* result = static_cast&lt;JSCell*&gt;(subspaceFor&lt;T&gt;(*heap.vm())-&gt;allocate(size));
</ins><span class="cx"> #if ENABLE(GC_VALIDATION)
</span><span class="cx">     ASSERT(!heap.vm()-&gt;isInitializingObject());
</span><span class="cx">     heap.vm()-&gt;setInitializingObjectClass(T::info());
</span><span class="lines">@@ -153,7 +165,7 @@
</span><span class="cx"> void* allocateCell(Heap&amp; heap, GCDeferralContext* deferralContext, size_t size)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(size &gt;= sizeof(T));
</span><del>-    JSCell* result = static_cast&lt;JSCell*&gt;(heap.allocateObjectOfType&lt;T&gt;(deferralContext, size));
</del><ins>+    JSCell* result = static_cast&lt;JSCell*&gt;(subspaceFor&lt;T&gt;(*heap.vm())-&gt;allocate(deferralContext, size));
</ins><span class="cx"> #if ENABLE(GC_VALIDATION)
</span><span class="cx">     ASSERT(!heap.vm()-&gt;isInitializingObject());
</span><span class="cx">     heap.vm()-&gt;setInitializingObjectClass(T::info());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSDestructibleObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSDestructibleObject.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSDestructibleObject.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/JSDestructibleObject.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -36,6 +36,12 @@
</span><span class="cx">     typedef JSNonFinalObject Base;
</span><span class="cx"> 
</span><span class="cx">     static const bool needsDestruction = true;
</span><ins>+    
+    template&lt;typename CellType&gt;
+    static Subspace* subspaceFor(VM&amp; vm)
+    {
+        return &amp;vm.destructibleObjectSpace;
+    }
</ins><span class="cx"> 
</span><span class="cx">     const ClassInfo* classInfo() const { return m_classInfo; }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSDestructibleObjectSubspacecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/runtime/JSDestructibleObjectSubspace.cpp (0 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSDestructibleObjectSubspace.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/runtime/JSDestructibleObjectSubspace.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -0,0 +1,66 @@
</span><ins>+/*
+ * Copyright (C) 2017 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 &quot;config.h&quot;
+#include &quot;JSDestructibleObjectSubspace.h&quot;
+
+#include &quot;MarkedBlockInlines.h&quot;
+#include &quot;JSCInlines.h&quot;
+#include &quot;SubspaceInlines.h&quot;
+
+namespace JSC {
+
+namespace {
+
+struct DestroyFunc {
+    ALWAYS_INLINE void operator()(VM&amp;, JSCell* cell) const
+    {
+        static_cast&lt;JSDestructibleObject*&gt;(cell)-&gt;classInfo()-&gt;methodTable.destroy(cell);
+    }
+};
+
+} // anonymous namespace
+
+JSDestructibleObjectSubspace::JSDestructibleObjectSubspace(CString name, Heap&amp; heap)
+    : Subspace(name, heap, AllocatorAttributes(NeedsDestruction, HeapCell::JSCell))
+{
+}
+
+JSDestructibleObjectSubspace::~JSDestructibleObjectSubspace()
+{
+}
+
+FreeList JSDestructibleObjectSubspace::finishSweep(MarkedBlock::Handle&amp; handle, MarkedBlock::Handle::SweepMode sweepMode)
+{
+    return handle.finishSweepKnowingSubspace(sweepMode, DestroyFunc());
+}
+
+void JSDestructibleObjectSubspace::destroy(VM&amp; vm, JSCell* cell)
+{
+    DestroyFunc()(vm, cell);
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSDestructibleObjectSubspaceh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/runtime/JSDestructibleObjectSubspace.h (0 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSDestructibleObjectSubspace.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/runtime/JSDestructibleObjectSubspace.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -0,0 +1,42 @@
</span><ins>+/*
+ * Copyright (C) 2017 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 &quot;Subspace.h&quot;
+
+namespace JSC {
+
+class JSDestructibleObjectSubspace : public Subspace {
+public:
+    JS_EXPORT_PRIVATE JSDestructibleObjectSubspace(CString name, Heap&amp;);
+    JS_EXPORT_PRIVATE virtual ~JSDestructibleObjectSubspace();
+    
+    FreeList finishSweep(MarkedBlock::Handle&amp;, MarkedBlock::Handle::SweepMode) override;
+    void destroy(VM&amp;, JSCell*) override;
+};
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSObject.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSObject.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/JSObject.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
</span><span class="cx">  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
</span><del>- *  Copyright (C) 2003-2009, 2012-2016 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Library General Public
</span><span class="lines">@@ -1280,7 +1280,6 @@
</span><span class="cx">     : JSCell(vm, structure)
</span><span class="cx">     , m_butterfly(vm, this, butterfly)
</span><span class="cx"> {
</span><del>-    vm.heap.ascribeOwner(this, butterfly);
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline JSValue JSObject::getPrototypeDirect() const
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSObjectInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSObjectInlines.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSObjectInlines.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/JSObjectInlines.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
</span><span class="cx">  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
</span><del>- *  Copyright (C) 2003-2006, 2008, 2009, 2012-2016 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *  Copyright (C) 2007 Eric Seidel (eric@webkit.org)
</span><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSSegmentedVariableObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -85,7 +85,7 @@
</span><span class="cx">     
</span><span class="cx">     JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><span class="cx">     JS_EXPORT_PRIVATE static void heapSnapshot(JSCell*, HeapSnapshotBuilder&amp;);
</span><del>-
</del><ins>+    
</ins><span class="cx"> protected:
</span><span class="cx">     JSSegmentedVariableObject(VM&amp; vm, Structure* structure, JSScope* scope)
</span><span class="cx">         : JSSymbolTableObject(vm, structure, scope)
</span><span class="lines">@@ -99,6 +99,8 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx"> private:
</span><ins>+    // FIXME: This needs a destructor, which can only be added using custom subspace.
+    
</ins><span class="cx">     SegmentedVector&lt;WriteBarrier&lt;Unknown&gt;, 16&gt; m_variables;
</span><span class="cx">     ConcurrentJSLock m_lock;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSStringh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSString.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSString.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/JSString.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
</span><span class="cx">  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
</span><del>- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2014, 2016 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Library General Public
</span><span class="lines">@@ -85,9 +85,17 @@
</span><span class="cx"> 
</span><span class="cx">     static const bool needsDestruction = true;
</span><span class="cx">     static void destroy(JSCell*);
</span><del>-
</del><ins>+    
+    // We specialize the string subspace to get the fastest possible sweep. This wouldn't be
+    // necessary if JSString didn't have a destructor.
+    template&lt;typename&gt;
+    static Subspace* subspaceFor(VM&amp; vm)
+    {
+        return &amp;vm.stringSpace;
+    }
+    
</ins><span class="cx">     static const unsigned MaxLength = std::numeric_limits&lt;int32_t&gt;::max();
</span><del>-
</del><ins>+    
</ins><span class="cx"> private:
</span><span class="cx">     JSString(VM&amp; vm, PassRefPtr&lt;StringImpl&gt; value)
</span><span class="cx">         : JSCell(vm, vm.stringStructure.get())
</span><span class="lines">@@ -234,6 +242,8 @@
</span><span class="cx">     friend JSString* jsSubstring(ExecState*, JSString*, unsigned offset, unsigned length);
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+// NOTE: This class cannot override JSString's destructor. JSString's destructor is called directly
+// from JSStringSubspace::
</ins><span class="cx"> class JSRopeString final : public JSString {
</span><span class="cx">     friend class JSString;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSStringSubspacecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/runtime/JSStringSubspace.cpp (0 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSStringSubspace.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/runtime/JSStringSubspace.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -0,0 +1,66 @@
</span><ins>+/*
+ * Copyright (C) 2017 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 &quot;config.h&quot;
+#include &quot;JSStringSubspace.h&quot;
+
+#include &quot;MarkedBlockInlines.h&quot;
+#include &quot;JSCInlines.h&quot;
+#include &quot;SubspaceInlines.h&quot;
+
+namespace JSC {
+
+namespace {
+
+struct DestroyFunc {
+    ALWAYS_INLINE void operator()(VM&amp;, JSCell* cell) const
+    {
+        static_cast&lt;JSString*&gt;(cell)-&gt;JSString::~JSString();
+    }
+};
+
+} // anonymous namespace
+
+JSStringSubspace::JSStringSubspace(CString name, Heap&amp; heap)
+    : Subspace(name, heap, AllocatorAttributes(NeedsDestruction, HeapCell::JSCell))
+{
+}
+
+JSStringSubspace::~JSStringSubspace()
+{
+}
+
+FreeList JSStringSubspace::finishSweep(MarkedBlock::Handle&amp; handle, MarkedBlock::Handle::SweepMode sweepMode)
+{
+    return handle.finishSweepKnowingSubspace(sweepMode, DestroyFunc());
+}
+
+void JSStringSubspace::destroy(VM&amp; vm, JSCell* cell)
+{
+    DestroyFunc()(vm, cell);
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSStringSubspaceh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/runtime/JSStringSubspace.h (0 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSStringSubspace.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/runtime/JSStringSubspace.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -0,0 +1,42 @@
</span><ins>+/*
+ * Copyright (C) 2017 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 &quot;Subspace.h&quot;
+
+namespace JSC {
+
+class JSStringSubspace : public Subspace {
+public:
+    JS_EXPORT_PRIVATE JSStringSubspace(CString name, Heap&amp;);
+    JS_EXPORT_PRIVATE virtual ~JSStringSubspace();
+    
+    FreeList finishSweep(MarkedBlock::Handle&amp;, MarkedBlock::Handle::SweepMode) override;
+    void destroy(VM&amp;, JSCell*) override;
+};
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpMatchesArrayh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- *  Copyright (C) 2008, 2016 Apple Inc. All Rights Reserved.
</del><ins>+ *  Copyright (C) 2008-2017 Apple Inc. All Rights Reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Lesser General Public
</span><span class="lines">@@ -38,7 +38,7 @@
</span><span class="cx">     if (vectorLength &gt; MAX_STORAGE_VECTOR_LENGTH)
</span><span class="cx">         return 0;
</span><span class="cx"> 
</span><del>-    void* temp = vm.heap.tryAllocateAuxiliary(deferralContext, nullptr, Butterfly::totalSize(0, structure-&gt;outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue)));
</del><ins>+    void* temp = vm.auxiliarySpace.tryAllocate(deferralContext, Butterfly::totalSize(0, structure-&gt;outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue)));
</ins><span class="cx">     if (!temp)
</span><span class="cx">         return nullptr;
</span><span class="cx">     Butterfly* butterfly = Butterfly::fromBase(temp, 0, structure-&gt;outOfLineCapacity());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2011, 2013-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -166,6 +166,11 @@
</span><span class="cx">     , executableAllocator(*this)
</span><span class="cx"> #endif
</span><span class="cx">     , heap(this, heapType)
</span><ins>+    , auxiliarySpace(&quot;Auxiliary&quot;, heap, AllocatorAttributes(DoesNotNeedDestruction, HeapCell::Auxiliary))
+    , cellSpace(&quot;JSCell&quot;, heap, AllocatorAttributes(DoesNotNeedDestruction, HeapCell::JSCell))
+    , destructibleCellSpace(&quot;Destructible JSCell&quot;, heap, AllocatorAttributes(NeedsDestruction, HeapCell::JSCell))
+    , stringSpace(&quot;JSString&quot;, heap)
+    , destructibleObjectSpace(&quot;JSDestructibleObject&quot;, heap)
</ins><span class="cx">     , vmType(vmType)
</span><span class="cx">     , clientData(0)
</span><span class="cx">     , topVMEntryFrame(nullptr)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2009, 2013-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -40,7 +40,9 @@
</span><span class="cx"> #include &quot;Intrinsic.h&quot;
</span><span class="cx"> #include &quot;JITThunks.h&quot;
</span><span class="cx"> #include &quot;JSCJSValue.h&quot;
</span><ins>+#include &quot;JSDestructibleObjectSubspace.h&quot;
</ins><span class="cx"> #include &quot;JSLock.h&quot;
</span><ins>+#include &quot;JSStringSubspace.h&quot;
</ins><span class="cx"> #include &quot;MacroAssemblerCodeRef.h&quot;
</span><span class="cx"> #include &quot;Microtask.h&quot;
</span><span class="cx"> #include &quot;NumericStrings.h&quot;
</span><span class="lines">@@ -49,6 +51,7 @@
</span><span class="cx"> #include &quot;SmallStrings.h&quot;
</span><span class="cx"> #include &quot;SourceCode.h&quot;
</span><span class="cx"> #include &quot;Strong.h&quot;
</span><ins>+#include &quot;Subspace.h&quot;
</ins><span class="cx"> #include &quot;TemplateRegistryKeyTable.h&quot;
</span><span class="cx"> #include &quot;ThunkGenerators.h&quot;
</span><span class="cx"> #include &quot;VMEntryRecord.h&quot;
</span><span class="lines">@@ -287,6 +290,14 @@
</span><span class="cx">     // The heap should be just after executableAllocator and before other members to ensure that it's
</span><span class="cx">     // destructed after all the objects that reference it.
</span><span class="cx">     Heap heap;
</span><ins>+    
+    Subspace auxiliarySpace;
+    
+    // Whenever possible, use subspaceFor&lt;CellType&gt;(vm) to get one of these subspaces.
+    Subspace cellSpace;
+    Subspace destructibleCellSpace;
+    JSStringSubspace stringSpace;
+    JSDestructibleObjectSubspace destructibleObjectSpace;
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     std::unique_ptr&lt;DFG::LongLivedState&gt; dfgState;
</span></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/WebCore/CMakeLists.txt        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1189,6 +1189,7 @@
</span><span class="cx">     bindings/js/ScriptState.cpp
</span><span class="cx">     bindings/js/StructuredClone.cpp
</span><span class="cx">     bindings/js/SerializedScriptValue.cpp
</span><ins>+    bindings/js/WebCoreJSClientData.cpp
</ins><span class="cx">     bindings/js/WebCoreTypedArrayController.cpp
</span><span class="cx">     bindings/js/WorkerScriptController.cpp
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/WebCore/ChangeLog        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,3 +1,58 @@
</span><ins>+2017-01-16  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Make opaque root scanning truly constraint-based
+        https://bugs.webkit.org/show_bug.cgi?id=165760
+
+        Reviewed by Geoffrey Garen.
+
+        No new tests yet. I think that writing tests for this is a big investigation:
+        https://bugs.webkit.org/show_bug.cgi?id=165808
+        
+        Remove the previous advancing wavefront DOM write barrier. I don't think this will scale
+        very well. It's super confusing.
+        
+        This change makes it so that visitAdditionalChildren can become a GC constraint that
+        executes as part of the fixpoint. This changes all WebCore visitAdditionalChildren into
+        output constraints by using new JSC API for Subspaces and MarkingConstraints.
+
+        * ForwardingHeaders/heap/MarkedAllocatorInlines.h: Added.
+        * ForwardingHeaders/heap/MarkedBlockInlines.h: Added.
+        * ForwardingHeaders/heap/MarkingConstraint.h: Added.
+        * ForwardingHeaders/heap/SubspaceInlines.h: Added.
+        * ForwardingHeaders/heap/VisitingTimeout.h: Added.
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/CommonVM.cpp:
+        (WebCore::commonVMSlow):
+        (WebCore::writeBarrierOpaqueRootSlow): Deleted.
+        * bindings/js/CommonVM.h:
+        (WebCore::writeBarrierOpaqueRoot): Deleted.
+        * bindings/js/JSDOMGlobalObject.cpp:
+        (WebCore::JSDOMGlobalObject::finishCreation):
+        (WebCore::JSDOMGlobalObject::scriptExecutionContext):
+        * bindings/js/JSDOMWrapper.cpp:
+        (WebCore::outputConstraintSubspaceFor):
+        (WebCore::globalObjectOutputConstraintSubspaceFor):
+        * bindings/js/JSDOMWrapper.h:
+        * bindings/js/WebCoreJSClientData.cpp: Added.
+        (WebCore::JSVMClientData::JSVMClientData):
+        (WebCore::JSVMClientData::~JSVMClientData):
+        (WebCore::JSVMClientData::getAllWorlds):
+        (WebCore::initNormalWorldClientData):
+        * bindings/js/WebCoreJSClientData.h:
+        (WebCore::JSVMClientData::outputConstraintSpace):
+        (WebCore::JSVMClientData::globalObjectOutputConstraintSpace):
+        (WebCore::JSVMClientData::forEachOutputConstraintSpace):
+        (WebCore::JSVMClientData::JSVMClientData): Deleted.
+        (WebCore::JSVMClientData::~JSVMClientData): Deleted.
+        (WebCore::JSVMClientData::getAllWorlds): Deleted.
+        (WebCore::initNormalWorldClientData): Deleted.
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateHeader):
+        (GenerateImplementation):
+        * dom/ContainerNodeAlgorithms.cpp:
+        (WebCore::notifyChildNodeInserted):
+        (WebCore::notifyChildNodeRemoved):
+
</ins><span class="cx"> 2017-01-17  Michael Catanzaro  &lt;mcatanzaro@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r210834
</span></span></pre></div>
<a id="trunkSourceWebCoreForwardingHeadersheapMarkedAllocatorInlinesh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/ForwardingHeaders/heap/MarkedAllocatorInlines.h (0 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ForwardingHeaders/heap/MarkedAllocatorInlines.h                                (rev 0)
+++ trunk/Source/WebCore/ForwardingHeaders/heap/MarkedAllocatorInlines.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+#pragma once
+#include &lt;JavaScriptCore/MarkedAllocatorInlines.h&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreForwardingHeadersheapMarkedBlockInlinesh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/ForwardingHeaders/heap/MarkedBlockInlines.h (0 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ForwardingHeaders/heap/MarkedBlockInlines.h                                (rev 0)
+++ trunk/Source/WebCore/ForwardingHeaders/heap/MarkedBlockInlines.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+#pragma once
+#include &lt;JavaScriptCore/MarkedBlockInlines.h&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreForwardingHeadersheapMarkingConstrainth"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/ForwardingHeaders/heap/MarkingConstraint.h (0 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ForwardingHeaders/heap/MarkingConstraint.h                                (rev 0)
+++ trunk/Source/WebCore/ForwardingHeaders/heap/MarkingConstraint.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+#pragma once
+#include &lt;JavaScriptCore/MarkingConstraint.h&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreForwardingHeadersheapSubspaceInlinesh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/ForwardingHeaders/heap/SubspaceInlines.h (0 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ForwardingHeaders/heap/SubspaceInlines.h                                (rev 0)
+++ trunk/Source/WebCore/ForwardingHeaders/heap/SubspaceInlines.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+#pragma once
+#include &lt;JavaScriptCore/SubspaceInlines.h&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreForwardingHeadersheapVisitingTimeouth"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/ForwardingHeaders/heap/VisitingTimeout.h (0 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ForwardingHeaders/heap/VisitingTimeout.h                                (rev 0)
+++ trunk/Source/WebCore/ForwardingHeaders/heap/VisitingTimeout.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+#pragma once
+#include &lt;JavaScriptCore/VisitingTimeout.h&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -488,6 +488,7 @@
</span><span class="cx">                 0F6A12BD1A00923700C6DE72 /* DebugPageOverlays.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6A12BB1A00923700C6DE72 /* DebugPageOverlays.cpp */; };
</span><span class="cx">                 0F6A12BE1A00923700C6DE72 /* DebugPageOverlays.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6A12BC1A00923700C6DE72 /* DebugPageOverlays.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F7D07331884C56C00B4AF86 /* PlatformTextTrack.h in Headers */ = {isa = PBXBuildFile; fileRef = 072847E216EBC5B00043CFA4 /* PlatformTextTrack.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F7DF1481E2BF1B10095951B /* WebCoreJSClientData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7DF1471E2BF1A60095951B /* WebCoreJSClientData.cpp */; };
</ins><span class="cx">                 0F87166F1C869D83004FF0DE /* LengthPoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F87166D1C869D83004FF0DE /* LengthPoint.cpp */; };
</span><span class="cx">                 0F8716701C869D83004FF0DE /* LengthPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F87166E1C869D83004FF0DE /* LengthPoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F8B45721DC3FBA300443C3F /* IntersectionObserverCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8B45711DC3FBA300443C3F /* IntersectionObserverCallback.h */; };
</span><span class="lines">@@ -7482,6 +7483,7 @@
</span><span class="cx">                 0F6383DC18615B29003E5DB5 /* ThreadedScrollingTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadedScrollingTree.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F6A12BB1A00923700C6DE72 /* DebugPageOverlays.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DebugPageOverlays.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F6A12BC1A00923700C6DE72 /* DebugPageOverlays.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugPageOverlays.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F7DF1471E2BF1A60095951B /* WebCoreJSClientData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebCoreJSClientData.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F87166D1C869D83004FF0DE /* LengthPoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LengthPoint.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F87166E1C869D83004FF0DE /* LengthPoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LengthPoint.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F8B456F1DC3FB1000443C3F /* IntersectionObserverCallback.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = IntersectionObserverCallback.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -22087,6 +22089,7 @@
</span><span class="cx">                                 414B82031D6DF0D90077EBE3 /* StructuredClone.h */,
</span><span class="cx">                                 419BE7521BC7F3DB00E1C85B /* WebCoreBuiltinNames.h */,
</span><span class="cx">                                 BC53D910114310CC000D817E /* WebCoreJSClientData.h */,
</span><ins>+                                0F7DF1471E2BF1A60095951B /* WebCoreJSClientData.cpp */,
</ins><span class="cx">                                 0F099D0617B968A100FF84B9 /* WebCoreTypedArrayController.cpp */,
</span><span class="cx">                                 0F099D0717B968A100FF84B9 /* WebCoreTypedArrayController.h */,
</span><span class="cx">                                 E1A643FC0EC097A000779668 /* WorkerScriptController.cpp */,
</span><span class="lines">@@ -30191,6 +30194,7 @@
</span><span class="cx">                                 598365E61355F60D001B185D /* JSPositionErrorCallback.cpp in Sources */,
</span><span class="cx">                                 7C330A071DF9F95100D3395C /* JSPositionOptions.cpp in Sources */,
</span><span class="cx">                                 65DF31FF09D1CC60000BE325 /* JSProcessingInstruction.cpp in Sources */,
</span><ins>+                                0F7DF1481E2BF1B10095951B /* WebCoreJSClientData.cpp in Sources */,
</ins><span class="cx">                                 E44613ED0CD681BA00FADA75 /* JSProgressEvent.cpp in Sources */,
</span><span class="cx">                                 077664FC183E6B5C00133B92 /* JSQuickTimePluginReplacement.cpp in Sources */,
</span><span class="cx">                                 B658FFA11522EF3A00DD5595 /* JSRadioNodeList.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsCommonVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/CommonVM.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/CommonVM.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/WebCore/bindings/js/CommonVM.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -38,7 +38,6 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> VM* g_commonVMOrNull;
</span><del>-bool g_opaqueRootWriteBarrierEnabled;
</del><span class="cx"> 
</span><span class="cx"> VM&amp; commonVMSlow()
</span><span class="cx"> {
</span><span class="lines">@@ -60,18 +59,11 @@
</span><span class="cx"> #endif
</span><span class="cx">     
</span><span class="cx">     g_commonVMOrNull-&gt;setGlobalConstRedeclarationShouldThrow(Settings::globalConstRedeclarationShouldThrow());
</span><del>-    g_commonVMOrNull-&gt;heap.addMutatorShouldBeFencedCache(g_opaqueRootWriteBarrierEnabled);
</del><span class="cx">     
</span><del>-    initNormalWorldClientData(g_commonVMOrNull);
</del><ins>+    JSVMClientData::initNormalWorld(g_commonVMOrNull);
</ins><span class="cx">     
</span><span class="cx">     return *g_commonVMOrNull;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void writeBarrierOpaqueRootSlow(void* root)
-{
-    if (VM* vm = g_commonVMOrNull)
-        vm-&gt;heap.writeBarrierOpaqueRoot(root);
-}
-
</del><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsCommonVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/CommonVM.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/CommonVM.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/WebCore/bindings/js/CommonVM.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -32,10 +32,8 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> WEBCORE_EXPORT extern JSC::VM* g_commonVMOrNull;
</span><del>-WEBCORE_EXPORT extern bool g_opaqueRootWriteBarrierEnabled;
</del><span class="cx"> 
</span><span class="cx"> WEBCORE_EXPORT JSC::VM&amp; commonVMSlow();
</span><del>-WEBCORE_EXPORT void writeBarrierOpaqueRootSlow(void*);
</del><span class="cx"> 
</span><span class="cx"> inline JSC::VM&amp; commonVM()
</span><span class="cx"> {
</span><span class="lines">@@ -44,12 +42,5 @@
</span><span class="cx">     return commonVMSlow();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename Func&gt;
-void writeBarrierOpaqueRoot(const Func&amp; rootThunk)
-{
-    if (g_opaqueRootWriteBarrierEnabled)
-        writeBarrierOpaqueRootSlow(rootThunk());
-}
-
</del><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMGlobalObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -161,6 +161,8 @@
</span><span class="cx">     ASSERT(inherits(info()));
</span><span class="cx"> 
</span><span class="cx">     addBuiltinGlobals(vm);
</span><ins>+    
+    RELEASE_ASSERT(classInfo());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JSDOMGlobalObject::finishCreation(VM&amp; vm, JSObject* thisValue)
</span><span class="lines">@@ -169,6 +171,8 @@
</span><span class="cx">     ASSERT(inherits(info()));
</span><span class="cx"> 
</span><span class="cx">     addBuiltinGlobals(vm);
</span><ins>+    
+    RELEASE_ASSERT(classInfo());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> ScriptExecutionContext* JSDOMGlobalObject::scriptExecutionContext() const
</span><span class="lines">@@ -177,7 +181,8 @@
</span><span class="cx">         return jsCast&lt;const JSDOMWindowBase*&gt;(this)-&gt;scriptExecutionContext();
</span><span class="cx">     if (inherits(JSWorkerGlobalScopeBase::info()))
</span><span class="cx">         return jsCast&lt;const JSWorkerGlobalScopeBase*&gt;(this)-&gt;scriptExecutionContext();
</span><del>-    ASSERT_NOT_REACHED();
</del><ins>+    dataLog(&quot;Unexpected global object: &quot;, JSValue(this), &quot;\n&quot;);
+    RELEASE_ASSERT_NOT_REACHED();
</ins><span class="cx">     return 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMWrappercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMWrapper.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMWrapper.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/WebCore/bindings/js/JSDOMWrapper.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;DOMWrapperWorld.h&quot;
</span><span class="cx"> #include &quot;JSDOMWindow.h&quot;
</span><ins>+#include &quot;WebCoreJSClientData.h&quot;
</ins><span class="cx"> #include &lt;runtime/Error.h&gt;
</span><span class="cx"> 
</span><span class="cx"> using namespace JSC;
</span><span class="lines">@@ -43,4 +44,14 @@
</span><span class="cx">     return *domWindow;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Subspace* outputConstraintSubspaceFor(VM&amp; vm)
+{
+    return &amp;static_cast&lt;JSVMClientData*&gt;(vm.clientData)-&gt;outputConstraintSpace();
+}
+
+Subspace* globalObjectOutputConstraintSubspaceFor(VM&amp; vm)
+{
+    return &amp;static_cast&lt;JSVMClientData*&gt;(vm.clientData)-&gt;globalObjectOutputConstraintSpace();
+}
+
</ins><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMWrapperh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMWrapper.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMWrapper.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/WebCore/bindings/js/JSDOMWrapper.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -73,12 +73,15 @@
</span><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+WEBCORE_EXPORT JSC::Subspace* outputConstraintSubspaceFor(JSC::VM&amp;);
+WEBCORE_EXPORT JSC::Subspace* globalObjectOutputConstraintSubspaceFor(JSC::VM&amp;);
+
</ins><span class="cx"> template&lt;typename ImplementationClass&gt; class JSDOMWrapper : public JSDOMObject {
</span><span class="cx"> public:
</span><span class="cx">     typedef JSDOMObject Base;
</span><span class="cx">     typedef ImplementationClass DOMWrapped;
</span><span class="cx">     static constexpr bool isDOMWrapper = true;
</span><del>-
</del><ins>+    
</ins><span class="cx">     ImplementationClass&amp; wrapped() const { return m_wrapped; }
</span><span class="cx">     static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSDOMWrapper&lt;ImplementationClass&gt;, m_wrapped); }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsWebCoreJSClientDatacpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/bindings/js/WebCoreJSClientData.cpp (0 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/WebCoreJSClientData.cpp                                (rev 0)
+++ trunk/Source/WebCore/bindings/js/WebCoreJSClientData.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -0,0 +1,117 @@
</span><ins>+/*
+ * Copyright (C) 2017 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 &quot;config.h&quot;
+#include &quot;WebCoreJSClientData.h&quot;
+
+#include &quot;JSDOMBinding.h&quot;
+#include &lt;heap/HeapInlines.h&gt;
+#include &lt;heap/MarkingConstraint.h&gt;
+#include &lt;heap/MarkedAllocatorInlines.h&gt;
+#include &lt;heap/MarkedBlockInlines.h&gt;
+#include &lt;heap/SubspaceInlines.h&gt;
+#include &lt;heap/VisitingTimeout.h&gt;
+#include &lt;runtime/VM.h&gt;
+#include &lt;wtf/MainThread.h&gt;
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSVMClientData::JSVMClientData(VM&amp; vm)
+    : m_builtinFunctions(vm)
+    , m_builtinNames(&amp;vm)
+    , m_outputConstraintSpace(&quot;WebCore Wrapper w/ Output Constraint&quot;, vm.heap)
+    , m_globalObjectOutputConstraintSpace(&quot;WebCore Global Object w/ Output Constraint&quot;, vm.heap, AllocatorAttributes(DoesNotNeedDestruction, HeapCell::JSCell))
+{
+}
+
+JSVMClientData::~JSVMClientData()
+{
+    ASSERT(m_worldSet.contains(m_normalWorld.get()));
+    ASSERT(m_worldSet.size() == 1);
+    ASSERT(m_normalWorld-&gt;hasOneRef());
+    m_normalWorld = nullptr;
+    ASSERT(m_worldSet.isEmpty());
+}
+
+void JSVMClientData::getAllWorlds(Vector&lt;Ref&lt;DOMWrapperWorld&gt;&gt;&amp; worlds)
+{
+    ASSERT(worlds.isEmpty());
+    
+    worlds.reserveInitialCapacity(m_worldSet.size());
+    for (auto it = m_worldSet.begin(), end = m_worldSet.end(); it != end; ++it)
+        worlds.uncheckedAppend(*(*it));
+}
+
+void JSVMClientData::initNormalWorld(VM* vm)
+{
+    JSVMClientData* clientData = new JSVMClientData(*vm);
+    vm-&gt;clientData = clientData; // ~VM deletes this pointer.
+    
+    auto constraint = std::make_unique&lt;MarkingConstraint&gt;(
+        &quot;Wcoc&quot;, &quot;WebCore Output Constraints&quot;,
+        [vm, clientData, lastExecutionVersion = vm-&gt;heap.mutatorExecutionVersion()]
+        (SlotVisitor&amp; slotVisitor, const VisitingTimeout&amp;) mutable {
+            Heap&amp; heap = vm-&gt;heap;
+            
+            if (heap.mutatorExecutionVersion() == lastExecutionVersion)
+                return;
+            
+            lastExecutionVersion = heap.mutatorExecutionVersion();
+
+            // We have to manage the visit count here ourselves. We need to know that if this adds
+            // opaque roots then we cannot declare termination yet. The way we signal this to the
+            // constraint solver is by adding to the visit count.
+            
+            size_t numOpaqueRootsBefore = heap.numOpaqueRoots();
+
+            // FIXME: Make this parallel!
+            unsigned numRevisited = 0;
+            clientData-&gt;forEachOutputConstraintSpace(
+                [&amp;] (Subspace&amp; subspace) {
+                    subspace.forEachMarkedCell(
+                        [&amp;] (HeapCell* heapCell, HeapCell::Kind) {
+                            JSCell* cell = static_cast&lt;JSCell*&gt;(heapCell);
+                            cell-&gt;methodTable(*vm)-&gt;visitOutputConstraints(cell, slotVisitor);
+                            numRevisited++;
+                        });
+                });
+            if (Options::logGC())
+                dataLog(&quot;(&quot;, numRevisited, &quot;)&quot;);
+            
+            slotVisitor.mergeIfNecessary();
+            
+            slotVisitor.addToVisitCount(heap.numOpaqueRoots() - numOpaqueRootsBefore);
+        },
+        ConstraintVolatility::SeldomGreyed);
+    vm-&gt;heap.addMarkingConstraint(WTFMove(constraint));
+        
+    clientData-&gt;m_normalWorld = DOMWrapperWorld::create(*vm, true);
+    vm-&gt;m_typedArrayController = adoptRef(new WebCoreTypedArrayController());
+}
+
+} // namespace WebCore
+
</ins></span></pre></div>
<a id="trunkSourceWebCorebindingsjsWebCoreJSClientDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/WebCoreJSClientData.h (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/WebCoreJSClientData.h        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/WebCore/bindings/js/WebCoreJSClientData.h        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
</span><del>- *  Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *  Copyright (C) 2007 Samuel Weinig &lt;sam@webkit.org&gt;
</span><span class="cx">  *  Copyright (C) 2009 Google, Inc. All rights reserved.
</span><span class="cx">  *
</span><span class="lines">@@ -33,35 +33,18 @@
</span><span class="cx"> class JSVMClientData : public JSC::VM::ClientData {
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(JSVMClientData); WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx">     friend class VMWorldIterator;
</span><del>-    friend void initNormalWorldClientData(JSC::VM*);
</del><span class="cx"> 
</span><span class="cx"> public:
</span><del>-    explicit JSVMClientData(JSC::VM&amp; vm)
-        : m_builtinFunctions(vm)
-        , m_builtinNames(&amp;vm)
-    {
-    }
</del><ins>+    explicit JSVMClientData(JSC::VM&amp;);
</ins><span class="cx"> 
</span><del>-    virtual ~JSVMClientData()
-    {
-        ASSERT(m_worldSet.contains(m_normalWorld.get()));
-        ASSERT(m_worldSet.size() == 1);
-        ASSERT(m_normalWorld-&gt;hasOneRef());
-        m_normalWorld = nullptr;
-        ASSERT(m_worldSet.isEmpty());
-    }
</del><ins>+    virtual ~JSVMClientData();
+    
+    WEBCORE_EXPORT static void initNormalWorld(JSC::VM*);
</ins><span class="cx"> 
</span><span class="cx">     DOMWrapperWorld&amp; normalWorld() { return *m_normalWorld; }
</span><span class="cx"> 
</span><del>-    void getAllWorlds(Vector&lt;Ref&lt;DOMWrapperWorld&gt;&gt;&amp; worlds)
-    {
-        ASSERT(worlds.isEmpty());
</del><ins>+    void getAllWorlds(Vector&lt;Ref&lt;DOMWrapperWorld&gt;&gt;&amp;);
</ins><span class="cx"> 
</span><del>-        worlds.reserveInitialCapacity(m_worldSet.size());
-        for (auto it = m_worldSet.begin(), end = m_worldSet.end(); it != end; ++it)
-            worlds.uncheckedAppend(*(*it));
-    }
-
</del><span class="cx">     void rememberWorld(DOMWrapperWorld&amp; world)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(!m_worldSet.contains(&amp;world));
</span><span class="lines">@@ -76,6 +59,16 @@
</span><span class="cx"> 
</span><span class="cx">     WebCoreBuiltinNames&amp; builtinNames() { return m_builtinNames; }
</span><span class="cx">     JSBuiltinFunctions&amp; builtinFunctions() { return m_builtinFunctions; }
</span><ins>+    
+    JSC::Subspace&amp; outputConstraintSpace() { return m_outputConstraintSpace; }
+    JSC::Subspace&amp; globalObjectOutputConstraintSpace() { return m_globalObjectOutputConstraintSpace; }
+    
+    template&lt;typename Func&gt;
+    void forEachOutputConstraintSpace(const Func&amp; func)
+    {
+        func(m_outputConstraintSpace);
+        func(m_globalObjectOutputConstraintSpace);
+    }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     HashSet&lt;DOMWrapperWorld*&gt; m_worldSet;
</span><span class="lines">@@ -83,14 +76,9 @@
</span><span class="cx"> 
</span><span class="cx">     JSBuiltinFunctions m_builtinFunctions;
</span><span class="cx">     WebCoreBuiltinNames m_builtinNames;
</span><ins>+    
+    JSC::JSDestructibleObjectSubspace m_outputConstraintSpace;
+    JSC::Subspace m_globalObjectOutputConstraintSpace;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><del>-inline void initNormalWorldClientData(JSC::VM* vm)
-{
-    JSVMClientData* clientData = new JSVMClientData(*vm);
-    vm-&gt;clientData = clientData; // ~VM deletes this pointer.
-    clientData-&gt;m_normalWorld = DOMWrapperWorld::create(*vm, true);
-    vm-&gt;m_typedArrayController = adoptRef(new WebCoreTypedArrayController());
-}
-
</del><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsWorkerScriptControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/WorkerScriptController.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/WorkerScriptController.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/WebCore/bindings/js/WorkerScriptController.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -53,7 +53,7 @@
</span><span class="cx"> {
</span><span class="cx">     m_vm-&gt;heap.acquireAccess(); // It's not clear that we have good discipline for heap access, so turn it on permanently.
</span><span class="cx">     m_vm-&gt;ensureWatchdog();
</span><del>-    initNormalWorldClientData(m_vm.get());
</del><ins>+    JSVMClientData::initNormalWorld(m_vm.get());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> WorkerScriptController::~WorkerScriptController()
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptsCodeGeneratorJSpm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -1965,6 +1965,23 @@
</span><span class="cx">         push(@headerContent, &quot;    static void visitChildren(JSCell*, JSC::SlotVisitor&amp;);\n&quot;);
</span><span class="cx">         push(@headerContent, &quot;    void visitAdditionalChildren(JSC::SlotVisitor&amp;);\n&quot;) if $interface-&gt;extendedAttributes-&gt;{JSCustomMarkFunction};
</span><span class="cx">         push(@headerContent, &quot;\n&quot;);
</span><ins>+
+        if ($interface-&gt;extendedAttributes-&gt;{JSCustomMarkFunction}) {
+            # We assume that the logic in visitAdditionalChildren is highly volatile, and during a
+            # concurrent GC or in between eden GCs something may happen that would lead to this
+            # logic behaving differently. Since this could mark objects or add opaque roots, this
+            # means that after any increment of mutator resumption in a concurrent GC and at least
+            # once during any eden GC we need to re-execute visitAdditionalChildren on any objects
+            # that we had executed it on before. We do this using the DOM's own MarkingConstraint,
+            # which will call visitOutputConstraints on all objects in the DOM's own
+            # outputConstraintSubspace. visitOutputConstraints is the name JSC uses for the method
+            # that the GC calls to ask an object is it would like to mark anything else after the
+            # program resumed since the last call to visitChildren or visitOutputConstraints. Since
+            # this just calls visitAdditionalChildren, you usually don't have to worry about this.
+            push(@headerContent, &quot;    static void visitOutputConstraints(JSCell*, JSC::SlotVisitor&amp;);\n&quot;);
+            my $subspaceFunc = IsDOMGlobalObject($interface) ? &quot;globalObjectOutputConstraintSubspaceFor&quot; : &quot;outputConstraintSubspaceFor&quot;;
+            push(@headerContent, &quot;    template&lt;typename&gt; static JSC::Subspace* subspaceFor(JSC::VM&amp; vm) { return $subspaceFunc(vm); }\n&quot;);
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (InstanceNeedsEstimatedSize($interface)) {
</span><span class="lines">@@ -4134,6 +4151,15 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">         push(@implContent, &quot;}\n\n&quot;);
</span><ins>+        if ($interface-&gt;extendedAttributes-&gt;{JSCustomMarkFunction}) {
+            push(@implContent, &quot;void ${className}::visitOutputConstraints(JSCell* cell, SlotVisitor&amp; visitor)\n&quot;);
+            push(@implContent, &quot;{\n&quot;);
+            push(@implContent, &quot;    auto* thisObject = jsCast&lt;${className}*&gt;(cell);\n&quot;);
+            push(@implContent, &quot;    ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n&quot;);
+            push(@implContent, &quot;    Base::visitOutputConstraints(thisObject, visitor);\n&quot;);
+            push(@implContent, &quot;    thisObject-&gt;visitAdditionalChildren(visitor);\n&quot;);
+            push(@implContent, &quot;}\n\n&quot;);
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (InstanceNeedsEstimatedSize($interface)) {
</span></span></pre></div>
<a id="trunkSourceWebCoredomContainerNodeAlgorithmscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/ContainerNodeAlgorithms.cpp (210843 => 210844)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/ContainerNodeAlgorithms.cpp        2017-01-18 04:21:15 UTC (rev 210843)
+++ trunk/Source/WebCore/dom/ContainerNodeAlgorithms.cpp        2017-01-18 04:22:45 UTC (rev 210844)
</span><span class="lines">@@ -26,7 +26,6 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;ContainerNodeAlgorithms.h&quot;
</span><span class="cx"> 
</span><del>-#include &quot;CommonVM.h&quot;
</del><span class="cx"> #include &quot;HTMLFrameOwnerElement.h&quot;
</span><span class="cx"> #include &quot;InspectorInstrumentation.h&quot;
</span><span class="cx"> #include &quot;NoEventDispatchAssertion.h&quot;
</span><span class="lines">@@ -102,8 +101,6 @@
</span><span class="cx">         notifyNodeInsertedIntoDocument(insertionPoint, node, postInsertionNotificationTargets);
</span><span class="cx">     else if (is&lt;ContainerNode&gt;(node))
</span><span class="cx">         notifyNodeInsertedIntoTree(insertionPoint, downcast&lt;ContainerNode&gt;(node), postInsertionNotificationTargets);
</span><del>-
-    writeBarrierOpaqueRoot([&amp;insertionPoint] () -&gt; void* { return insertionPoint.opaqueRoot(); });
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void notifyNodeRemovedFromDocument(ContainerNode&amp; insertionPoint, Node&amp; node)
</span><span class="lines">@@ -155,8 +152,6 @@
</span><span class="cx"> 
</span><span class="cx"> void notifyChildNodeRemoved(ContainerNode&amp; insertionPoint, Node&amp; child)
</span><span class="cx"> {
</span><del>-    writeBarrierOpaqueRoot([&amp;child] () -&gt; void* { return &amp;child; });
-
</del><span class="cx">     if (!child.inDocument()) {
</span><span class="cx">         if (is&lt;ContainerNode&gt;(child))
</span><span class="cx">             notifyNodeRemovedFromTree(insertionPoint, downcast&lt;ContainerNode&gt;(child));
</span></span></pre>
</div>
</div>

</body>
</html>