<!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>[209570] 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/209570">209570</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-12-08 14:14:50 -0800 (Thu, 08 Dec 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>
PerformanceTests:
Concurrent GC should be stable enough to land enabled
https://bugs.webkit.org/show_bug.cgi?id=164990

Reviewed by Geoffrey Garen.
        
Made CDjs more configurable and refined the &quot;large.js&quot; configuration. I was using that one and
the new &quot;long.js&quot; configuration to tune concurrent eden GCs.
        
Added a new way of running Splay in browser, which using chartjs to plot the execution times of
2000 iterations. This includes the minified chartjs.

* JetStream/Octane2/splay-detail.html: Added.
* JetStream/cdjs/benchmark.js:
(benchmarkImpl):
(benchmark):
* JetStream/cdjs/long.js: Added.

Source/JavaScriptCore:
Concurrent GC should be stable enough to land enabled on X86_64
https://bugs.webkit.org/show_bug.cgi?id=164990

Reviewed by Geoffrey Garen.
        
This fixes a ton of performance and correctness bugs revealed by getting the concurrent GC to
be stable enough to land enabled.
        
I had to redo the JSObject::visitChildren concurrency protocol again. This time I think it's
even more correct than ever!
        
This is an enormous win on JetStream/splay-latency and Octane/SplayLatency. It looks to be
mostly neutral on everything else, though Speedometer is showing statistically weak signs of a
slight regression.

* API/JSAPIWrapperObject.mm: Added locking.
(JSC::JSAPIWrapperObject::visitChildren):
* API/JSCallbackObject.h: Added locking.
(JSC::JSCallbackObjectData::visitChildren):
(JSC::JSCallbackObjectData::JSPrivatePropertyMap::setPrivateProperty):
(JSC::JSCallbackObjectData::JSPrivatePropertyMap::deletePrivateProperty):
(JSC::JSCallbackObjectData::JSPrivatePropertyMap::visitChildren):
* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::UnconditionalFinalizer::finalizeUnconditionally): This had a TOCTOU race on shouldJettisonDueToOldAge.
(JSC::EvalCodeCache::visitAggregate): Moved to EvalCodeCache.cpp.
* bytecode/DirectEvalCodeCache.cpp: Added. Outlined some functions and made them use locks.
(JSC::DirectEvalCodeCache::setSlow):
(JSC::DirectEvalCodeCache::clear):
(JSC::DirectEvalCodeCache::visitAggregate):
* bytecode/DirectEvalCodeCache.h:
(JSC::DirectEvalCodeCache::set):
(JSC::DirectEvalCodeCache::clear): Deleted.
* bytecode/UnlinkedCodeBlock.cpp: Added locking.
(JSC::UnlinkedCodeBlock::visitChildren):
(JSC::UnlinkedCodeBlock::setInstructions):
(JSC::UnlinkedCodeBlock::shrinkToFit):
* bytecode/UnlinkedCodeBlock.h: Added locking.
(JSC::UnlinkedCodeBlock::addRegExp):
(JSC::UnlinkedCodeBlock::addConstant):
(JSC::UnlinkedCodeBlock::addFunctionDecl):
(JSC::UnlinkedCodeBlock::addFunctionExpr):
(JSC::UnlinkedCodeBlock::createRareDataIfNecessary):
(JSC::UnlinkedCodeBlock::shrinkToFit): Deleted.
* debugger/Debugger.cpp: Use the right delete API.
(JSC::Debugger::recompileAllJSFunctions):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects): Fix a pre-existing bug in ToFunction constant folding.
* dfg/DFGClobberize.h: Add support for nuking.
(JSC::DFG::clobberize):
* dfg/DFGClobbersExitState.cpp: Add support for nuking.
(JSC::DFG::clobbersExitState):
* dfg/DFGFixupPhase.cpp: Add support for nuking.
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::indexForChecks):
(JSC::DFG::FixupPhase::originForCheck):
(JSC::DFG::FixupPhase::speculateForBarrier):
(JSC::DFG::FixupPhase::insertCheck):
(JSC::DFG::FixupPhase::fixupChecksInBlock):
* dfg/DFGSpeculativeJIT.cpp: Add support for nuking.
(JSC::DFG::SpeculativeJIT::compileAllocatePropertyStorage):
(JSC::DFG::SpeculativeJIT::compileReallocatePropertyStorage):
* ftl/FTLLowerDFGToB3.cpp: Add support for nuking.
(JSC::FTL::DFG::LowerDFGToB3::allocatePropertyStorage):
(JSC::FTL::DFG::LowerDFGToB3::reallocatePropertyStorage):
(JSC::FTL::DFG::LowerDFGToB3::mutatorFence):
(JSC::FTL::DFG::LowerDFGToB3::nukeStructureAndSetButterfly):
(JSC::FTL::DFG::LowerDFGToB3::setButterfly): Deleted.
* heap/CodeBlockSet.cpp: We need to be more careful about the CodeBlockSet workflow during GC, since we will allocate CodeBlocks in eden while collecting.
(JSC::CodeBlockSet::clearMarksForFullCollection):
(JSC::CodeBlockSet::deleteUnmarkedAndUnreferenced):
* heap/Heap.cpp: Added code to measure max pauses. Added a better collectContinuously mode.
(JSC::Heap::lastChanceToFinalize): Stop the collectContinuously thread.
(JSC::Heap::harvestWeakReferences): Inline SlotVisitor::harvestWeakReferences.
(JSC::Heap::finalizeUnconditionalFinalizers): Inline SlotVisitor::finalizeUnconditionalReferences.
(JSC::Heap::markToFixpoint): We need to do some MarkedSpace stuff before every conservative scan, rather than just at the start of marking, so we now call prepareForConservativeScan() before each conservative scan. Also call a less-parallel version of drainInParallel when the mutator is running.
(JSC::Heap::collectInThread): Inline Heap::prepareForAllocation().
(JSC::Heap::stopIfNecessarySlow): We need to be more careful about ensuring that we run finalization before and after stopping. Also, we should sanitize stack when stopping the world.
(JSC::Heap::acquireAccessSlow): Add some optional debug prints.
(JSC::Heap::handleNeedFinalize): Assert that we are running this when the world is not stopped.
(JSC::Heap::finalize): Remove the old collectContinuously code.
(JSC::Heap::requestCollection): We don't need to sanitize stack here anymore.
(JSC::Heap::notifyIsSafeToCollect): Start the collectContinuously thread. It will request collection 1 KHz.
(JSC::Heap::prepareForAllocation): Deleted.
(JSC::Heap::preventCollection): Prevent any new concurrent GCs from being initiated.
(JSC::Heap::allowCollection):
(JSC::Heap::forEachSlotVisitor): Allows us to safely iterate slot visitors.
* heap/Heap.h:
* heap/HeapInlines.h:
(JSC::Heap::writeBarrier): If the 'to' cell is not NewWhite then it could be AnthraciteOrBlack. During a full collection, objects may be AnthraciteOrBlack from a previous GC. Turns out, we don't benefit from this optimization so we can just kill it.
* heap/HeapSnapshotBuilder.cpp:
(JSC::HeapSnapshotBuilder::buildSnapshot): This needs to use PreventCollectionScope to ensure snapshot soundness.
* heap/ListableHandler.h:
(JSC::ListableHandler::isOnList): Useful helper.
* heap/LockDuringMarking.h:
(JSC::lockDuringMarking): It's a locker that only locks while we're marking.
* heap/MarkedAllocator.cpp:
(JSC::MarkedAllocator::addBlock): Hold the bitvector lock while resizing.
* heap/MarkedBlock.cpp: Hold the bitvector lock while accessing the bitvectors while the mutator is running.
* heap/MarkedSpace.cpp:
(JSC::MarkedSpace::prepareForConservativeScan): We used to do this in prepareForMarking, but we need to do it before each conservative scan not just before marking.
(JSC::MarkedSpace::prepareForMarking): Remove the logic moved to prepareForConservativeScan.
* heap/MarkedSpace.h:
* heap/PreventCollectionScope.h: Added.
* heap/SlotVisitor.cpp: Refactored drainFromShared so that we can write a similar function called drainInParallelPassively.
(JSC::SlotVisitor::updateMutatorIsStopped): Update whether we can use &quot;fast&quot; scanning.
(JSC::SlotVisitor::mutatorIsStoppedIsUpToDate):
(JSC::SlotVisitor::didReachTermination):
(JSC::SlotVisitor::hasWork):
(JSC::SlotVisitor::drain): This now uses the rightToRun lock to allow the main GC thread to safepoint the workers.
(JSC::SlotVisitor::drainFromShared):
(JSC::SlotVisitor::drainInParallelPassively): This runs marking with one fewer threads than normal. It's useful for when we have resumed the mutator, since then the mutator has a better chance of getting on a core.
(JSC::SlotVisitor::addWeakReferenceHarvester):
(JSC::SlotVisitor::addUnconditionalFinalizer):
(JSC::SlotVisitor::harvestWeakReferences): Deleted.
(JSC::SlotVisitor::finalizeUnconditionalFinalizers): Deleted.
* heap/SlotVisitor.h:
* heap/SlotVisitorInlines.h: Outline stuff.
(JSC::SlotVisitor::addWeakReferenceHarvester): Deleted.
(JSC::SlotVisitor::addUnconditionalFinalizer): Deleted.
* runtime/InferredType.cpp: This needed thread safety.
(JSC::InferredType::visitChildren): This needs to keep its structure finalizer alive until it runs.
(JSC::InferredType::set):
(JSC::InferredType::InferredStructureFinalizer::finalizeUnconditionally):
* runtime/InferredType.h:
* runtime/InferredValue.cpp: This needed thread safety.
(JSC::InferredValue::visitChildren):
(JSC::InferredValue::ValueCleanup::finalizeUnconditionally):
* runtime/JSArray.cpp:
(JSC::JSArray::unshiftCountSlowCase): Update to use new butterfly API.
(JSC::JSArray::unshiftCountWithArrayStorage): Update to use new butterfly API.
* runtime/JSArrayBufferView.cpp:
(JSC::JSArrayBufferView::visitChildren): Thread safety.
* runtime/JSCell.h:
(JSC::JSCell::setStructureIDDirectly): This is used for nuking the structure.
(JSC::JSCell::InternalLocker::InternalLocker): Deleted. The cell is now the lock.
(JSC::JSCell::InternalLocker::~InternalLocker): Deleted. The cell is now the lock.
* runtime/JSCellInlines.h:
(JSC::JSCell::structure): Clean this up.
(JSC::JSCell::lock): The cell is now the lock.
(JSC::JSCell::tryLock):
(JSC::JSCell::unlock):
(JSC::JSCell::isLocked):
(JSC::JSCell::lockInternalLock): Deleted.
(JSC::JSCell::unlockInternalLock): Deleted.
* runtime/JSFunction.cpp:
(JSC::JSFunction::visitChildren): Thread safety.
* runtime/JSGenericTypedArrayViewInlines.h:
(JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::visitChildren): Thread safety.
(JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::slowDownAndWasteMemory): Thread safety.
* runtime/JSObject.cpp:
(JSC::JSObject::markAuxiliaryAndVisitOutOfLineProperties): Factor out this &quot;easy&quot; step of butterfly visiting.
(JSC::JSObject::visitButterfly): Make this achieve 100% precision about structure-butterfly relationships. This relies on the mutator &quot;nuking&quot; the structure prior to &quot;locked&quot; structure-butterfly transitions.
(JSC::JSObject::visitChildren): Use the new, nicer API.
(JSC::JSFinalObject::visitChildren): Use the new, nicer API.
(JSC::JSObject::enterDictionaryIndexingModeWhenArrayStorageAlreadyExists): Use the new butterfly API.
(JSC::JSObject::createInitialUndecided): Use the new butterfly API.
(JSC::JSObject::createInitialInt32): Use the new butterfly API.
(JSC::JSObject::createInitialDouble): Use the new butterfly API.
(JSC::JSObject::createInitialContiguous): Use the new butterfly API.
(JSC::JSObject::createArrayStorage): Use the new butterfly API.
(JSC::JSObject::convertUndecidedToContiguous): Use the new butterfly API.
(JSC::JSObject::convertUndecidedToArrayStorage): Use the new butterfly API.
(JSC::JSObject::convertInt32ToArrayStorage): Use the new butterfly API.
(JSC::JSObject::convertDoubleToContiguous): Use the new butterfly API.
(JSC::JSObject::convertDoubleToArrayStorage): Use the new butterfly API.
(JSC::JSObject::convertContiguousToArrayStorage): Use the new butterfly API.
(JSC::JSObject::increaseVectorLength): Use the new butterfly API.
(JSC::JSObject::shiftButterflyAfterFlattening): Use the new butterfly API.
* runtime/JSObject.h:
(JSC::JSObject::setButterfly): This now does all of the fences. Only use this when you are not also transitioning the structure or the structure's lastOffset.
(JSC::JSObject::nukeStructureAndSetButterfly): Use this when doing locked structure-butterfly transitions.
* runtime/JSObjectInlines.h:
(JSC::JSObject::putDirectWithoutTransition): Use the newly factored out API.
(JSC::JSObject::prepareToPutDirectWithoutTransition): Factor this out!
(JSC::JSObject::putDirectInternal): Use the newly factored out API.
* runtime/JSPropertyNameEnumerator.cpp:
(JSC::JSPropertyNameEnumerator::finishCreation): Locks!
(JSC::JSPropertyNameEnumerator::visitChildren): Locks!
* runtime/JSSegmentedVariableObject.cpp:
(JSC::JSSegmentedVariableObject::visitChildren): Locks!
* runtime/JSString.cpp:
(JSC::JSString::visitChildren): Thread safety.
* runtime/ModuleProgramExecutable.cpp:
(JSC::ModuleProgramExecutable::visitChildren): Thread safety.
* runtime/Options.cpp: For now we disable concurrent GC on not-X86_64.
(JSC::recomputeDependentOptions):
* runtime/Options.h: Change the default max GC parallelism to 8. I don't know why it was still 7.
* runtime/SamplingProfiler.cpp:
(JSC::SamplingProfiler::stackTracesAsJSON): This needs to defer GC before grabbing its lock.
* runtime/SparseArrayValueMap.cpp: This needed thread safety.
(JSC::SparseArrayValueMap::add):
(JSC::SparseArrayValueMap::remove):
(JSC::SparseArrayValueMap::visitChildren):
* runtime/SparseArrayValueMap.h:
* runtime/Structure.cpp: This had a race between addNewPropertyTransition and visitChildren.
(JSC::Structure::Structure):
(JSC::Structure::materializePropertyTable):
(JSC::Structure::addNewPropertyTransition):
(JSC::Structure::flattenDictionaryStructure):
(JSC::Structure::add): Help out with nuking support - the m_offset needs to play along.
(JSC::Structure::visitChildren):
* runtime/Structure.h: Make some useful things public - like the notion of a lastOffset.
* runtime/StructureChain.cpp:
(JSC::StructureChain::visitChildren): Thread safety!
* runtime/StructureChain.h: Thread safety!
* runtime/StructureIDTable.cpp:
(JSC::StructureIDTable::allocateID): Ensure that we don't get nuked IDs.
* runtime/StructureIDTable.h: Add the notion of a nuked ID! It's a bit that the runtime never sees except during specific shady actions like locked structure-butterfly transitions. &quot;Nuking&quot; tells the GC to steer clear and rescan once we fire the barrier.
(JSC::nukedStructureIDBit):
(JSC::nuke):
(JSC::isNuked):
(JSC::decontaminate):
* runtime/StructureInlines.h:
(JSC::Structure::hasIndexingHeader): Better API.
(JSC::Structure::add):
* runtime/VM.cpp: Better GC interaction.
(JSC::VM::ensureWatchdog):
(JSC::VM::deleteAllLinkedCode):
(JSC::VM::deleteAllCode):
* runtime/VM.h:
(JSC::VM::getStructure): Why wasn't this always an API!
* runtime/WebAssemblyExecutable.cpp:
(JSC::WebAssemblyExecutable::visitChildren): Thread safety.

Source/WebCore:
Concurrent GC should be stable enough to land enabled on X86_64
https://bugs.webkit.org/show_bug.cgi?id=164990

Reviewed by Geoffrey Garen.
        
Made WebCore down with concurrent marking by adding some locking and adapting to some new API.

This has new test modes in run-sjc-stress-tests. Also, the way that LayoutTests run is already
a fantastic GC test.

* ForwardingHeaders/heap/DeleteAllCodeEffort.h: Added.
* ForwardingHeaders/heap/LockDuringMarking.h: Added.
* bindings/js/GCController.cpp:
(WebCore::GCController::deleteAllCode):
(WebCore::GCController::deleteAllLinkedCode):
* bindings/js/GCController.h:
* bindings/js/JSDOMBinding.cpp:
(WebCore::getCachedDOMStructure):
(WebCore::cacheDOMStructure):
* bindings/js/JSDOMGlobalObject.cpp:
(WebCore::JSDOMGlobalObject::addBuiltinGlobals):
(WebCore::JSDOMGlobalObject::visitChildren):
* bindings/js/JSDOMGlobalObject.h:
(WebCore::getDOMConstructor):
* bindings/js/JSDOMPromise.cpp:
(WebCore::DeferredPromise::DeferredPromise):
(WebCore::DeferredPromise::clear):
* bindings/js/JSXPathResultCustom.cpp:
(WebCore::JSXPathResult::visitAdditionalChildren):
* dom/EventListenerMap.cpp:
(WebCore::EventListenerMap::clear):
(WebCore::EventListenerMap::replace):
(WebCore::EventListenerMap::add):
(WebCore::EventListenerMap::remove):
(WebCore::EventListenerMap::find):
(WebCore::EventListenerMap::removeFirstEventListenerCreatedFromMarkup):
(WebCore::EventListenerMap::copyEventListenersNotCreatedFromMarkupToTarget):
(WebCore::EventListenerIterator::EventListenerIterator):
* dom/EventListenerMap.h:
(WebCore::EventListenerMap::lock):
* dom/EventTarget.cpp:
(WebCore::EventTarget::visitJSEventListeners):
* dom/EventTarget.h:
(WebCore::EventTarget::visitJSEventListeners): Deleted.
* dom/Node.cpp:
(WebCore::Node::eventTargetDataConcurrently):
(WebCore::Node::ensureEventTargetData):
(WebCore::Node::clearEventTargetData):
* dom/Node.h:
* page/MemoryRelease.cpp:
(WebCore::releaseCriticalMemory):
* page/cocoa/MemoryReleaseCocoa.mm:
(WebCore::jettisonExpensiveObjectsOnTopLevelNavigation):
(WebCore::registerMemoryReleaseNotifyCallbacks):

Source/WTF:
Concurrent GC should be stable enough to land enabled on X86_64
https://bugs.webkit.org/show_bug.cgi?id=164990

Reviewed by Geoffrey Garen.
        
Adds the ability to say:
        
auto locker = holdLock(any type of lock)
        
Instead of having to say:
        
Locker&lt;LockType&gt; locker(locks of type LockType)
        
I think that we should use &quot;auto locker = holdLock(lock)&quot; as the default way that we acquire
locks unless we need to use a special locker type.
        
This also adds the ability to safepoint a lock. Safepointing a lock is basically a super fast
way of unlocking it fairly and then immediately relocking it - i.e. letting anyone who is
waiting to run without losing steam of there is noone waiting.

* wtf/Lock.cpp:
(WTF::LockBase::safepointSlow):
* wtf/Lock.h:
(WTF::LockBase::safepoint):
* wtf/LockAlgorithm.h:
(WTF::LockAlgorithm::safepointFast):
(WTF::LockAlgorithm::safepoint):
(WTF::LockAlgorithm::safepointSlow):
* wtf/Locker.h:
(WTF::AbstractLocker::AbstractLocker):
(WTF::Locker::tryLock):
(WTF::Locker::operator bool):
(WTF::Locker::Locker):
(WTF::Locker::operator=):
(WTF::holdLock):
(WTF::tryHoldLock):

Tools:
Concurrent GC should be stable enough to land enabled
https://bugs.webkit.org/show_bug.cgi?id=164990

Reviewed by Geoffrey Garen.
        
Add a new mode that runs GC continuously. Also made eager modes run GC continuously.
        
It's clear that this works just fine in release, but I'm still trying to figure out if it's
safe for debug. It might be too slow for debug.

* Scripts/run-jsc-stress-tests:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsdomscripttestsrandomarraygcstressjs">trunk/LayoutTests/js/dom/script-tests/random-array-gc-stress.js</a></li>
<li><a href="#trunkPerformanceTestsChangeLog">trunk/PerformanceTests/ChangeLog</a></li>
<li><a href="#trunkPerformanceTestsJetStreamcdjsbenchmarkjs">trunk/PerformanceTests/JetStream/cdjs/benchmark.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreAPIJSAPIWrapperObjectmm">trunk/Source/JavaScriptCore/API/JSAPIWrapperObject.mm</a></li>
<li><a href="#trunkSourceJavaScriptCoreAPIJSCallbackObjecth">trunk/Source/JavaScriptCore/API/JSCallbackObject.h</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="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeDirectEvalCodeCacheh">trunk/Source/JavaScriptCore/bytecode/DirectEvalCodeCache.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePolymorphicAccesscpp">trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggercpp">trunk/Source/JavaScriptCore/debugger/Debugger.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobbersExitStatecpp">trunk/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCellContainerh">trunk/Source/JavaScriptCore/heap/CellContainer.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCellContainerInlinesh">trunk/Source/JavaScriptCore/heap/CellContainerInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCodeBlockSetcpp">trunk/Source/JavaScriptCore/heap/CodeBlockSet.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="#trunkSourceJavaScriptCoreheapHeapSnapshotBuildercpp">trunk/Source/JavaScriptCore/heap/HeapSnapshotBuilder.cpp</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="#trunkSourceJavaScriptCoreheapListableHandlerh">trunk/Source/JavaScriptCore/heap/ListableHandler.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="#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="#trunkSourceJavaScriptCoreheapWeakSetcpp">trunk/Source/JavaScriptCore/heap/WeakSet.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectoragentsInspectorHeapAgentcpp">trunk/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectoragentsInspectorRuntimeAgentcpp">trunk/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp</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="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeDirectArgumentscpp">trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeEvalExecutablecpp">trunk/Source/JavaScriptCore/runtime/EvalExecutable.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeFunctionExecutablecpp">trunk/Source/JavaScriptCore/runtime/FunctionExecutable.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeHashMapImplcpp">trunk/Source/JavaScriptCore/runtime/HashMapImpl.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeInferredTypecpp">trunk/Source/JavaScriptCore/runtime/InferredType.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeInferredTypeh">trunk/Source/JavaScriptCore/runtime/InferredType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeInferredValuecpp">trunk/Source/JavaScriptCore/runtime/InferredValue.cpp</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="#trunkSourceJavaScriptCoreruntimeJSFunctioncpp">trunk/Source/JavaScriptCore/runtime/JSFunction.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewInlinesh">trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSObjectcpp">trunk/Source/JavaScriptCore/runtime/JSObject.cpp</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="#trunkSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorcpp">trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSSegmentedVariableObjectcpp">trunk/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSStringcpp">trunk/Source/JavaScriptCore/runtime/JSString.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeModuleProgramExecutablecpp">trunk/Source/JavaScriptCore/runtime/ModuleProgramExecutable.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionscpp">trunk/Source/JavaScriptCore/runtime/Options.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeProgramExecutablecpp">trunk/Source/JavaScriptCore/runtime/ProgramExecutable.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpCachedResultcpp">trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeSamplingProfilercpp">trunk/Source/JavaScriptCore/runtime/SamplingProfiler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeSparseArrayValueMapcpp">trunk/Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeSparseArrayValueMaph">trunk/Source/JavaScriptCore/runtime/SparseArrayValueMap.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructurecpp">trunk/Source/JavaScriptCore/runtime/Structure.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructureh">trunk/Source/JavaScriptCore/runtime/Structure.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructureChaincpp">trunk/Source/JavaScriptCore/runtime/StructureChain.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructureChainh">trunk/Source/JavaScriptCore/runtime/StructureChain.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructureIDTablecpp">trunk/Source/JavaScriptCore/runtime/StructureIDTable.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructureIDTableh">trunk/Source/JavaScriptCore/runtime/StructureIDTable.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructureInlinesh">trunk/Source/JavaScriptCore/runtime/StructureInlines.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="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfLockcpp">trunk/Source/WTF/wtf/Lock.cpp</a></li>
<li><a href="#trunkSourceWTFwtfLockh">trunk/Source/WTF/wtf/Lock.h</a></li>
<li><a href="#trunkSourceWTFwtfLockAlgorithmh">trunk/Source/WTF/wtf/LockAlgorithm.h</a></li>
<li><a href="#trunkSourceWTFwtfLockerh">trunk/Source/WTF/wtf/Locker.h</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorebindingsjsGCControllercpp">trunk/Source/WebCore/bindings/js/GCController.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsGCControllerh">trunk/Source/WebCore/bindings/js/GCController.h</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMBindingcpp">trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMGlobalObjectcpp">trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMGlobalObjecth">trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.h</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMPromisecpp">trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSTextTrackCueCustomcpp">trunk/Source/WebCore/bindings/js/JSTextTrackCueCustom.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSXPathResultCustomcpp">trunk/Source/WebCore/bindings/js/JSXPathResultCustom.cpp</a></li>
<li><a href="#trunkSourceWebCoredomEventListenerMapcpp">trunk/Source/WebCore/dom/EventListenerMap.cpp</a></li>
<li><a href="#trunkSourceWebCoredomEventListenerMaph">trunk/Source/WebCore/dom/EventListenerMap.h</a></li>
<li><a href="#trunkSourceWebCoredomEventTargetcpp">trunk/Source/WebCore/dom/EventTarget.cpp</a></li>
<li><a href="#trunkSourceWebCoredomEventTargeth">trunk/Source/WebCore/dom/EventTarget.h</a></li>
<li><a href="#trunkSourceWebCoredomNodecpp">trunk/Source/WebCore/dom/Node.cpp</a></li>
<li><a href="#trunkSourceWebCoredomNodeh">trunk/Source/WebCore/dom/Node.h</a></li>
<li><a href="#trunkSourceWebCorepageMemoryReleasecpp">trunk/Source/WebCore/page/MemoryRelease.cpp</a></li>
<li><a href="#trunkSourceWebCorepagecocoaMemoryReleaseCocoamm">trunk/Source/WebCore/page/cocoa/MemoryReleaseCocoa.mm</a></li>
<li><a href="#trunkSourceWebKitmacWebViewWebViewmm">trunk/Source/WebKit/mac/WebView/WebView.mm</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsDumpRenderTreeTestRunnercpp">trunk/Tools/DumpRenderTree/TestRunner.cpp</a></li>
<li><a href="#trunkToolsScriptsrunjscstresstests">trunk/Tools/Scripts/run-jsc-stress-tests</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkPerformanceTestsJetStreamOctane2splaydetailhtml">trunk/PerformanceTests/JetStream/Octane2/splay-detail.html</a></li>
<li><a href="#trunkPerformanceTestsJetStreamcdjslongjs">trunk/PerformanceTests/JetStream/cdjs/long.js</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeDirectEvalCodeCachecpp">trunk/Source/JavaScriptCore/bytecode/DirectEvalCodeCache.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapDeleteAllCodeEfforth">trunk/Source/JavaScriptCore/heap/DeleteAllCodeEffort.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapLockDuringMarkingh">trunk/Source/JavaScriptCore/heap/LockDuringMarking.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapPreventCollectionScopeh">trunk/Source/JavaScriptCore/heap/PreventCollectionScope.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapVisitRaceKeycpp">trunk/Source/JavaScriptCore/heap/VisitRaceKey.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapVisitRaceKeyh">trunk/Source/JavaScriptCore/heap/VisitRaceKey.h</a></li>
<li><a href="#trunkSourceWebCoreForwardingHeadersheapDeleteAllCodeEfforth">trunk/Source/WebCore/ForwardingHeaders/heap/DeleteAllCodeEffort.h</a></li>
<li><a href="#trunkSourceWebCoreForwardingHeadersheapLockDuringMarkingh">trunk/Source/WebCore/ForwardingHeaders/heap/LockDuringMarking.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsjsdomscripttestsrandomarraygcstressjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/dom/script-tests/random-array-gc-stress.js (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/dom/script-tests/random-array-gc-stress.js        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/LayoutTests/js/dom/script-tests/random-array-gc-stress.js        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -42,5 +42,4 @@
</span><span class="cx">     test();
</span><span class="cx">     runs += 1;
</span><span class="cx">     global = [];
</span><del>-    gc();
</del><span class="cx"> }
</span></span></pre></div>
<a id="trunkPerformanceTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/PerformanceTests/ChangeLog (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/ChangeLog        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/PerformanceTests/ChangeLog        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2016-12-06  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Concurrent GC should be stable enough to land enabled
+        https://bugs.webkit.org/show_bug.cgi?id=164990
+
+        Reviewed by Geoffrey Garen.
+        
+        Made CDjs more configurable and refined the &quot;large.js&quot; configuration. I was using that one and
+        the new &quot;long.js&quot; configuration to tune concurrent eden GCs.
+        
+        Added a new way of running Splay in browser, which using chartjs to plot the execution times of
+        2000 iterations. This includes the minified chartjs.
+
+        * JetStream/Octane2/splay-detail.html: Added.
+        * JetStream/cdjs/benchmark.js:
+        (benchmarkImpl):
+        (benchmark):
+        * JetStream/cdjs/long.js: Added.
+
</ins><span class="cx"> 2016-12-07  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add IDB perf tests stressing key size.
</span></span></pre></div>
<a id="trunkPerformanceTestsJetStreamOctane2splaydetailhtml"></a>
<div class="addfile"><h4>Added: trunk/PerformanceTests/JetStream/Octane2/splay-detail.html (0 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/JetStream/Octane2/splay-detail.html                                (rev 0)
+++ trunk/PerformanceTests/JetStream/Octane2/splay-detail.html        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -0,0 +1,934 @@
</span><ins>+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;Splay Detail&lt;/title&gt;
+&lt;script&gt;
+/*!
+ * Chart.js
+ * http://chartjs.org/
+ * Version: 2.4.0
+ *
+ * Copyright 2016 Nick Downie
+ * Released under the MIT license
+ * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md
+ */
+!function(t){if(&quot;object&quot;==typeof exports&amp;&amp;&quot;undefined&quot;!=typeof module)module.exports=t();else if(&quot;function&quot;==typeof define&amp;&amp;define.amd)define([],t);else{var e;e=&quot;undefined&quot;!=typeof window?window:&quot;undefined&quot;!=typeof global?global:&quot;undefined&quot;!=typeof self?self:this,e.Chart=t()}}(function(){return function t(e,a,i){function n(r,l){if(!a[r]){if(!e[r]){var s=&quot;function&quot;==typeof require&amp;&amp;require;if(!l&amp;&amp;s)return s(r,!0);if(o)return o(r,!0);var d=new Error(&quot;Cannot find module '&quot;+r+&quot;'&quot;);throw d.code=&quot;MODULE_NOT_FOUND&quot;,d}var u=a[r]={exports:{}};e[r][0].call(u.exports,function(t){var a=e[r][1][t];return n(a?a:t)},u,u.exports,t,e,a,i)}return a[r].exports}for(var o=&quot;function&quot;==typeof require&amp;&amp;require,r=0;r&lt;i.length;r++)n(i[r]);return n}({1:[function(t,e,a){},{}],2:[function(t,e,a){function i(t){if(t){var e=/^#([a-fA-F0-9]{3})$/,a=/^#([a-fA
 -F0-9]{6})$/,i=/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/,n=/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/,o=/(\w+)/,r=[0,0,0],l=1,s=t.match(e);if(s){s=s[1];for(var d=0;d&lt;r.length;d++)r[d]=parseInt(s[d]+s[d],16)}else if(s=t.match(a)){s=s[1];for(var d=0;d&lt;r.length;d++)r[d]=parseInt(s.slice(2*d,2*d+2),16)}else if(s=t.match(i)){for(var d=0;d&lt;r.length;d++)r[d]=parseInt(s[d+1]);l=parseFloat(s[4])}else if(s=t.match(n)){for(var d=0;d&lt;r.length;d++)r[d]=Math.round(2.55*parseFloat(s[d+1]));l=parseFloat(s[4])}else if(s=t.match(o)){if(&quot;transparent&quot;==s[1])return[0,0,0,0];if(r=y[s[1]],!r)return}for(var d=0;d&lt;r.length;d++)r[d]=v(r[d],0,255);return l=l||0==l?v(l,0,1):1,r[3]=l,r}}function n(t){if(t){var e=/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,a=t.match(e);if(a){var i=parseFloat(a[4]),n=v(parse
 Int(a[1]),0,360),o=v(parseFloat(a[2]),0,100),r=v(parseFloat(a[3]),0,100),l=v(isNaN(i)?1:i,0,1);return[n,o,r,l]}}}function o(t){if(t){var e=/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,a=t.match(e);if(a){var i=parseFloat(a[4]),n=v(parseInt(a[1]),0,360),o=v(parseFloat(a[2]),0,100),r=v(parseFloat(a[3]),0,100),l=v(isNaN(i)?1:i,0,1);return[n,o,r,l]}}}function r(t){var e=i(t);return e&amp;&amp;e.slice(0,3)}function l(t){var e=n(t);return e&amp;&amp;e.slice(0,3)}function s(t){var e=i(t);return e?e[3]:(e=n(t))?e[3]:(e=o(t))?e[3]:void 0}function d(t){return&quot;#&quot;+x(t[0])+x(t[1])+x(t[2])}function u(t,e){return 1&gt;e||t[3]&amp;&amp;t[3]&lt;1?c(t,e):&quot;rgb(&quot;+t[0]+&quot;, &quot;+t[1]+&quot;, &quot;+t[2]+&quot;)&quot;}function c(t,e){return void 0===e&amp;&amp;(e=void 0!==t[3]?t[3]:1),&quot;rgba(&quot;+t[0]+&quot;, &quot;+t[1]+&quot;, &quot;+t[2]+&quot;, &quot;+e+&quot;)&quot;}function h(t,e){if(1&gt;e||t[3]&amp;&
 amp;t[3]&lt;1)return f(t,e);var a=Math.round(t[0]/255*100),i=Math.round(t[1]/255*100),n=Math.round(t[2]/255*100);return&quot;rgb(&quot;+a+&quot;%, &quot;+i+&quot;%, &quot;+n+&quot;%)&quot;}function f(t,e){var a=Math.round(t[0]/255*100),i=Math.round(t[1]/255*100),n=Math.round(t[2]/255*100);return&quot;rgba(&quot;+a+&quot;%, &quot;+i+&quot;%, &quot;+n+&quot;%, &quot;+(e||t[3]||1)+&quot;)&quot;}function g(t,e){return 1&gt;e||t[3]&amp;&amp;t[3]&lt;1?p(t,e):&quot;hsl(&quot;+t[0]+&quot;, &quot;+t[1]+&quot;%, &quot;+t[2]+&quot;%)&quot;}function p(t,e){return void 0===e&amp;&amp;(e=void 0!==t[3]?t[3]:1),&quot;hsla(&quot;+t[0]+&quot;, &quot;+t[1]+&quot;%, &quot;+t[2]+&quot;%, &quot;+e+&quot;)&quot;}function m(t,e){return void 0===e&amp;&amp;(e=void 0!==t[3]?t[3]:1),&quot;hwb(&quot;+t[0]+&quot;, &quot;+t[1]+&quot;%, &quot;+t[2]+&quot;%&quot;+(void 0!==e&amp;&amp;1!==e?&quot;, &quot;+e:&quot;&quot;)+&quot;)&quot;}function b(t){return k[t.slice(0,3)]}function v(t,e,a){return Math.min(Ma
 th.max(e,t),a)}function x(t){var e=t.toString(16).toUpperCase();return e.length&lt;2?&quot;0&quot;+e:e}var y=t(6);e.exports={getRgba:i,getHsla:n,getRgb:r,getHsl:l,getHwb:o,getAlpha:s,hexString:d,rgbString:u,rgbaString:c,percentString:h,percentaString:f,hslString:g,hslaString:p,hwbString:m,keyword:b};var k={};for(var S in y)k[y[S]]=S},{6:6}],3:[function(t,e,a){var i=t(5),n=t(2),o=function(t){if(t instanceof o)return t;if(!(this instanceof o))return new o(t);this.values={rgb:[0,0,0],hsl:[0,0,0],hsv:[0,0,0],hwb:[0,0,0],cmyk:[0,0,0,0],alpha:1};var e;if(&quot;string&quot;==typeof t)if(e=n.getRgba(t))this.setValues(&quot;rgb&quot;,e);else if(e=n.getHsla(t))this.setValues(&quot;hsl&quot;,e);else{if(!(e=n.getHwb(t)))throw new Error('Unable to parse color from string &quot;'+t+'&quot;');this.setValues(&quot;hwb&quot;,e)}else if(&quot;object&quot;==typeof t)if(e=t,void 0!==e.r||void 0!==e.red)this.setValues(&quot;rgb&quot;,e);else if(void 0!==e.l||void 0!==e.lightness)this.setValues(&
 quot;hsl&quot;,e);else if(void 0!==e.v||void 0!==e.value)this.setValues(&quot;hsv&quot;,e);else if(void 0!==e.w||void 0!==e.whiteness)this.setValues(&quot;hwb&quot;,e);else{if(void 0===e.c&amp;&amp;void 0===e.cyan)throw new Error(&quot;Unable to parse color from object &quot;+JSON.stringify(t));this.setValues(&quot;cmyk&quot;,e)}};o.prototype={rgb:function(){return this.setSpace(&quot;rgb&quot;,arguments)},hsl:function(){return this.setSpace(&quot;hsl&quot;,arguments)},hsv:function(){return this.setSpace(&quot;hsv&quot;,arguments)},hwb:function(){return this.setSpace(&quot;hwb&quot;,arguments)},cmyk:function(){return this.setSpace(&quot;cmyk&quot;,arguments)},rgbArray:function(){return this.values.rgb},hslArray:function(){return this.values.hsl},hsvArray:function(){return this.values.hsv},hwbArray:function(){var t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.con
 cat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues(&quot;alpha&quot;,t),this)},red:function(t){return this.setChannel(&quot;rgb&quot;,0,t)},green:function(t){return this.setChannel(&quot;rgb&quot;,1,t)},blue:function(t){return this.setChannel(&quot;rgb&quot;,2,t)},hue:function(t){return t&amp;&amp;(t%=360,t=0&gt;t?360+t:t),this.setChannel(&quot;hsl&quot;,0,t)},saturation:function(t){return this.setChannel(&quot;hsl&quot;,1,t)},lightness:function(t){return this.setChannel(&quot;hsl&quot;,2,t)},saturationv:function(t){return this.setChannel(&quot;hsv&quot;,1,t)},whiteness:function(t){return this.setChannel(&quot;hwb&quot;,1,t)},blackness:function(t){return this.setChannel(&quot;hwb&quot;,2,t)},value:function(t){return this.setChannel(&quot;hsv&quot;,2,t)},cyan:function(t){return this.setChannel(&quot;cmyk&quot;,0,t)},magenta:function(t){return this.setChannel(&quot;cmyk&qu
 ot;,1,t)},yellow:function(t){return this.setChannel(&quot;cmyk&quot;,2,t)},black:function(t){return this.setChannel(&quot;cmyk&quot;,3,t)},hexString:function(){return n.hexString(this.values.rgb)},rgbString:function(){return n.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return n.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return n.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return n.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return n.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return n.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return n.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]&lt;&lt;16|t[1]&lt;&lt;8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],a=0;a&lt;t.length;a++){var i=t[a]/255;e[a]=.03928&gt;=i?i/12.92:Math.pow((i+.055)/1.055,2.4)}return.2126*e[0]+.715
 2*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),a=t.luminosity();return e&gt;a?(e+.05)/(a+.05):(a+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e&gt;=7.1?&quot;AAA&quot;:e&gt;=4.5?&quot;AA&quot;:&quot;&quot;},dark:function(){var t=this.values.rgb,e=(299*t[0]+587*t[1]+114*t[2])/1e3;return 128&gt;e},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;3&gt;e;e++)t[e]=255-this.values.rgb[e];return this.setValues(&quot;rgb&quot;,t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues(&quot;hsl&quot;,e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues(&quot;hsl&quot;,e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues(&quot;hsl&quot;,e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues(&quot;hsl&quot;,e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues(&quot;hwb&quo
 t;,e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues(&quot;hwb&quot;,e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues(&quot;rgb&quot;,[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues(&quot;alpha&quot;,e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues(&quot;alpha&quot;,e+e*t),this},rotate:function(t){var e=this.values.hsl,a=(e[0]+t)%360;return e[0]=0&gt;a?360+a:a,this.setValues(&quot;hsl&quot;,e),this},mix:function(t,e){var a=this,i=t,n=void 0===e?.5:e,o=2*n-1,r=a.alpha()-i.alpha(),l=((o*r===-1?o:(o+r)/(1+o*r))+1)/2,s=1-l;return this.rgb(l*a.red()+s*i.red(),l*a.green()+s*i.green(),l*a.blue()+s*i.blue()).alpha(a.alpha()*n+i.alpha()*(1-n))},toJSON:function(){return this.rgb()},clone:function(){var t,e,a=new o,i=this.values,n=a.values;for(var r in i)i.hasOwnProperty(r)&amp;&amp;(t=i[r],e={}.toString.call(t),&quot;[object Array]&quo
 t;===e?n[r]=t.slice(0):&quot;[object Number]&quot;===e?n[r]=t:console.error(&quot;unexpected color value:&quot;,t));return a}},o.prototype.spaces={rgb:[&quot;red&quot;,&quot;green&quot;,&quot;blue&quot;],hsl:[&quot;hue&quot;,&quot;saturation&quot;,&quot;lightness&quot;],hsv:[&quot;hue&quot;,&quot;saturation&quot;,&quot;value&quot;],hwb:[&quot;hue&quot;,&quot;whiteness&quot;,&quot;blackness&quot;],cmyk:[&quot;cyan&quot;,&quot;magenta&quot;,&quot;yellow&quot;,&quot;black&quot;]},o.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},o.prototype.getValues=function(t){for(var e=this.values,a={},i=0;i&lt;t.length;i++)a[t.charAt(i)]=e[t][i];return 1!==e.alpha&amp;&amp;(a.a=e.alpha),a},o.prototype.setValues=function(t,e){var a,n=this.values,o=this.spaces,r=this.maxes,l=1;if(&quot;alpha&quot;===t)l=e;else if(e.length)n[t]=e.slice(0,t.length),l=e[t.length];else if(void 0!==e[t.charAt(0)]){for(a=0;a&lt;t.length;a++)n[t][a]=e[
 t.charAt(a)];l=e.a}else if(void 0!==e[o[t][0]]){var s=o[t];for(a=0;a&lt;t.length;a++)n[t][a]=e[s[a]];l=e.alpha}if(n.alpha=Math.max(0,Math.min(1,void 0===l?n.alpha:l)),&quot;alpha&quot;===t)return!1;var d;for(a=0;a&lt;t.length;a++)d=Math.max(0,Math.min(r[t][a],n[t][a])),n[t][a]=Math.round(d);for(var u in o)u!==t&amp;&amp;(n[u]=i[t][u](n[t]));return!0},o.prototype.setSpace=function(t,e){var a=e[0];return void 0===a?this.getValues(t):(&quot;number&quot;==typeof a&amp;&amp;(a=Array.prototype.slice.call(e)),this.setValues(t,a),this)},o.prototype.setChannel=function(t,e,a){var i=this.values[t];return void 0===a?i[e]:a===i[e]?this:(i[e]=a,this.setValues(t,i),this)},&quot;undefined&quot;!=typeof window&amp;&amp;(window.Color=o),e.exports=o},{2:2,5:5}],4:[function(t,e,a){function i(t){var e,a,i,n=t[0]/255,o=t[1]/255,r=t[2]/255,l=Math.min(n,o,r),s=Math.max(n,o,r),d=s-l;return s==l?e=0:n==s?e=(o-r)/d:o==s?e=2+(r-n)/d:r==s&amp;&amp;(e=4+(n-o)/d),e=Math.min(60*e,360),0&gt;e&amp;&amp;(e+=
 360),i=(l+s)/2,a=s==l?0:.5&gt;=i?d/(s+l):d/(2-s-l),[e,100*a,100*i]}function n(t){var e,a,i,n=t[0],o=t[1],r=t[2],l=Math.min(n,o,r),s=Math.max(n,o,r),d=s-l;return a=0==s?0:d/s*1e3/10,s==l?e=0:n==s?e=(o-r)/d:o==s?e=2+(r-n)/d:r==s&amp;&amp;(e=4+(n-o)/d),e=Math.min(60*e,360),0&gt;e&amp;&amp;(e+=360),i=s/255*1e3/10,[e,a,i]}function o(t){var e=t[0],a=t[1],n=t[2],o=i(t)[0],r=1/255*Math.min(e,Math.min(a,n)),n=1-1/255*Math.max(e,Math.max(a,n));return[o,100*r,100*n]}function l(t){var e,a,i,n,o=t[0]/255,r=t[1]/255,l=t[2]/255;return n=Math.min(1-o,1-r,1-l),e=(1-o-n)/(1-n)||0,a=(1-r-n)/(1-n)||0,i=(1-l-n)/(1-n)||0,[100*e,100*a,100*i,100*n]}function s(t){return G[JSON.stringify(t)]}function d(t){var e=t[0]/255,a=t[1]/255,i=t[2]/255;e=e&gt;.04045?Math.pow((e+.055)/1.055,2.4):e/12.92,a=a&gt;.04045?Math.pow((a+.055)/1.055,2.4):a/12.92,i=i&gt;.04045?Math.pow((i+.055)/1.055,2.4):i/12.92;var n=.4124*e+.3576*a+.1805*i,o=.2126*e+.7152*a+.0722*i,r=.0193*e+.1192*a+.9505*i;return[100*n,100*o,100*r]}fu
 nction u(t){var e,a,i,n=d(t),o=n[0],r=n[1],l=n[2];return o/=95.047,r/=100,l/=108.883,o=o&gt;.008856?Math.pow(o,1/3):7.787*o+16/116,r=r&gt;.008856?Math.pow(r,1/3):7.787*r+16/116,l=l&gt;.008856?Math.pow(l,1/3):7.787*l+16/116,e=116*r-16,a=500*(o-r),i=200*(r-l),[e,a,i]}function c(t){return W(u(t))}function h(t){var e,a,i,n,o,r=t[0]/360,l=t[1]/100,s=t[2]/100;if(0==l)return o=255*s,[o,o,o];a=.5&gt;s?s*(1+l):s+l-s*l,e=2*s-a,n=[0,0,0];for(var d=0;3&gt;d;d++)i=r+1/3*-(d-1),0&gt;i&amp;&amp;i++,i&gt;1&amp;&amp;i--,o=1&gt;6*i?e+6*(a-e)*i:1&gt;2*i?a:2&gt;3*i?e+(a-e)*(2/3-i)*6:e,n[d]=255*o;return n}function f(t){var e,a,i=t[0],n=t[1]/100,o=t[2]/100;return 0===o?[0,0,0]:(o*=2,n*=1&gt;=o?o:2-o,a=(o+n)/2,e=2*n/(o+n),[i,100*e,100*a])}function p(t){return o(h(t))}function m(t){return l(h(t))}function v(t){return s(h(t))}function x(t){var e=t[0]/60,a=t[1]/100,i=t[2]/100,n=Math.floor(e)%6,o=e-Math.floor(e),r=255*i*(1-a),l=255*i*(1-a*o),s=255*i*(1-a*(1-o)),i=255*i;switch(n){case 0:return[i,s,r];c
 ase 1:return[l,i,r];case 2:return[r,i,s];case 3:return[r,l,i];case 4:return[s,r,i];case 5:return[i,r,l]}}function y(t){var e,a,i=t[0],n=t[1]/100,o=t[2]/100;return a=(2-n)*o,e=n*o,e/=1&gt;=a?a:2-a,e=e||0,a/=2,[i,100*e,100*a]}function k(t){return o(x(t))}function S(t){return l(x(t))}function w(t){return s(x(t))}function M(t){var e,a,i,n,o=t[0]/360,l=t[1]/100,s=t[2]/100,d=l+s;switch(d&gt;1&amp;&amp;(l/=d,s/=d),e=Math.floor(6*o),a=1-s,i=6*o-e,0!=(1&amp;e)&amp;&amp;(i=1-i),n=l+i*(a-l),e){default:case 6:case 0:r=a,g=n,b=l;break;case 1:r=n,g=a,b=l;break;case 2:r=l,g=a,b=n;break;case 3:r=l,g=n,b=a;break;case 4:r=n,g=l,b=a;break;case 5:r=a,g=l,b=n}return[255*r,255*g,255*b]}function C(t){return i(M(t))}function D(t){return n(M(t))}function I(t){return l(M(t))}function A(t){return s(M(t))}function T(t){var e,a,i,n=t[0]/100,o=t[1]/100,r=t[2]/100,l=t[3]/100;return e=1-Math.min(1,n*(1-l)+l),a=1-Math.min(1,o*(1-l)+l),i=1-Math.min(1,r*(1-l)+l),[255*e,255*a,255*i]}function P(t){return i(T(t)
 )}function F(t){return n(T(t))}function _(t){return o(T(t))}function R(t){return s(T(t))}function V(t){var e,a,i,n=t[0]/100,o=t[1]/100,r=t[2]/100;return e=3.2406*n+-1.5372*o+r*-.4986,a=n*-.9689+1.8758*o+.0415*r,i=.0557*n+o*-.204+1.057*r,e=e&gt;.0031308?1.055*Math.pow(e,1/2.4)-.055:e=12.92*e,a=a&gt;.0031308?1.055*Math.pow(a,1/2.4)-.055:a=12.92*a,i=i&gt;.0031308?1.055*Math.pow(i,1/2.4)-.055:i=12.92*i,e=Math.min(Math.max(0,e),1),a=Math.min(Math.max(0,a),1),i=Math.min(Math.max(0,i),1),[255*e,255*a,255*i]}function L(t){var e,a,i,n=t[0],o=t[1],r=t[2];return n/=95.047,o/=100,r/=108.883,n=n&gt;.008856?Math.pow(n,1/3):7.787*n+16/116,o=o&gt;.008856?Math.pow(o,1/3):7.787*o+16/116,r=r&gt;.008856?Math.pow(r,1/3):7.787*r+16/116,e=116*o-16,a=500*(n-o),i=200*(o-r),[e,a,i]}function O(t){return W(L(t))}function B(t){var e,a,i,n,o=t[0],r=t[1],l=t[2];return 8&gt;=o?(a=100*o/903.3,n=7.787*(a/100)+16/116):(a=100*Math.pow((o+16)/116,3),n=Math.pow(a/100,1/3)),e=.008856&gt;=e/95.047?e=95.047*(r/500+
 n-16/116)/7.787:95.047*Math.pow(r/500+n,3),i=.008859&gt;=i/108.883?i=108.883*(n-l/200-16/116)/7.787:108.883*Math.pow(n-l/200,3),[e,a,i]}function W(t){var e,a,i,n=t[0],o=t[1],r=t[2];return e=Math.atan2(r,o),a=360*e/2/Math.PI,0&gt;a&amp;&amp;(a+=360),i=Math.sqrt(o*o+r*r),[n,i,a]}function z(t){return V(B(t))}function N(t){var e,a,i,n=t[0],o=t[1],r=t[2];return i=r/360*2*Math.PI,e=o*Math.cos(i),a=o*Math.sin(i),[n,e,a]}function E(t){return B(N(t))}function H(t){return z(N(t))}function U(t){return Z[t]}function j(t){return i(U(t))}function q(t){return n(U(t))}function Y(t){return o(U(t))}function X(t){return l(U(t))}function K(t){return u(U(t))}function J(t){return d(U(t))}e.exports={rgb2hsl:i,rgb2hsv:n,rgb2hwb:o,rgb2cmyk:l,rgb2keyword:s,rgb2xyz:d,rgb2lab:u,rgb2lch:c,hsl2rgb:h,hsl2hsv:f,hsl2hwb:p,hsl2cmyk:m,hsl2keyword:v,hsv2rgb:x,hsv2hsl:y,hsv2hwb:k,hsv2cmyk:S,hsv2keyword:w,hwb2rgb:M,hwb2hsl:C,hwb2hsv:D,hwb2cmyk:I,hwb2keyword:A,cmyk2rgb:T,cmyk2hsl:P,cmyk2hsv:F,cmyk2hwb:_,cmyk2keyw
 ord:R,keyword2rgb:U,keyword2hsl:j,keyword2hsv:q,keyword2hwb:Y,keyword2cmyk:X,keyword2lab:K,keyword2xyz:J,xyz2rgb:V,xyz2lab:L,xyz2lch:O,lab2xyz:B,lab2rgb:z,lab2lch:W,lch2lab:N,lch2xyz:E,lch2rgb:H};var Z={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darksl
 ateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:
 [135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128]
 ,rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},G={};for(var Q in Z)G[JSON.stringify(Z[Q])]=Q},{}],5:[function(t,e,a){var i=t(4),n=function(){return new d};for(var o in i){n[o+&quot;Raw&quot;]=function(t){return function(e){return&quot;number&quot;==typeof e&amp;&amp;(e=Array.prototype.slice.call(arguments)),i[t](e)}}(o);var r=/(\w+)2(\w+)/.exec(o),l=r[1],s=r[2];n[l]=n[l]||{},n[l][s]=n[o]=function(t){re
 turn function(e){&quot;number&quot;==typeof e&amp;&amp;(e=Array.prototype.slice.call(arguments));var a=i[t](e);if(&quot;string&quot;==typeof a||void 0===a)return a;for(var n=0;n&lt;a.length;n++)a[n]=Math.round(a[n]);return a}}(o)}var d=function(){this.convs={}};d.prototype.routeSpace=function(t,e){var a=e[0];return void 0===a?this.getValues(t):(&quot;number&quot;==typeof a&amp;&amp;(a=Array.prototype.slice.call(e)),this.setValues(t,a))},d.prototype.setValues=function(t,e){return this.space=t,this.convs={},this.convs[t]=e,this},d.prototype.getValues=function(t){var e=this.convs[t];if(!e){var a=this.space,i=this.convs[a];e=n[a][t](i),this.convs[t]=e}return e},[&quot;rgb&quot;,&quot;hsl&quot;,&quot;hsv&quot;,&quot;cmyk&quot;,&quot;keyword&quot;].forEach(function(t){d.prototype[t]=function(e){return this.routeSpace(t,arguments)}}),e.exports=n},{4:4}],6:[function(t,e,a){e.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[
 240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34
 ],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],medi
 umpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,1
 28,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},{}],7:[function(t,e,a){var i=t(28)();t(26)(i),t(22)(i),t(25)(i),t(21)(i),t(23)(i),t(24)(i),t(29)(i),t(33)(i),t(31)(i),t(34)(i),t(32)(i),t(35)(i),t(30)(i),t(27)(i),t(36)(i),t(37)(i),t(38)(i),t(39)(i),t(40)(i),t(43)(i),t(41)(i),t(42)(i),t(44)(i),t(45)(i),t(46)(i),t(15)(i),t(16)(i),t(17)(i),t(18)(i),t(19)(i),t(20)(i),t(8)(i),t(9)(i),t(10)(i),t(11)(i),t(12)(i),t(13)(i),t(14)(i),window.Chart=e.exports=i},{10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,19:19,20:20,21:21,22:22,23:23,24:24,25:25,26:26,27:27,28:28,29:29,30:30,31:31,32:32,33:33,34:34,35:35,36:36,37:37,38:38,39:39,40:40,41:41,42:42,43:43,44:44,45:45,46:46,8:8,9:9}],8:[function(t,e,a){&quot
 ;use strict&quot;;e.exports=function(t){t.Bar=function(e,a){return a.type=&quot;bar&quot;,new t(e,a)}}},{}],9:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){t.Bubble=function(e,a){return a.type=&quot;bubble&quot;,new t(e,a)}}},{}],10:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){t.Doughnut=function(e,a){return a.type=&quot;doughnut&quot;,new t(e,a)}}},{}],11:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){t.Line=function(e,a){return a.type=&quot;line&quot;,new t(e,a)}}},{}],12:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){t.PolarArea=function(e,a){return a.type=&quot;polarArea&quot;,new t(e,a)}}},{}],13:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){t.Radar=function(e,a){return a.type=&quot;radar&quot;,new t(e,a)}}},{}],14:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e={hover:{mode:&quot;single&quot;},scales:{xAxes:[{type:&quot;linear&quot;,position:&quot;bottom&quot;,id:&quot;x-
 axis-1&quot;}],yAxes:[{type:&quot;linear&quot;,position:&quot;left&quot;,id:&quot;y-axis-1&quot;}]},tooltips:{callbacks:{title:function(){return&quot;&quot;},label:function(t){return&quot;(&quot;+t.xLabel+&quot;, &quot;+t.yLabel+&quot;)&quot;}}}};t.defaults.scatter=e,t.controllers.scatter=t.controllers.line,t.Scatter=function(e,a){return a.type=&quot;scatter&quot;,new t(e,a)}}},{}],15:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers;t.defaults.bar={hover:{mode:&quot;label&quot;},scales:{xAxes:[{type:&quot;category&quot;,categoryPercentage:.8,barPercentage:.9,gridLines:{offsetGridLines:!0}}],yAxes:[{type:&quot;linear&quot;}]}},t.controllers.bar=t.DatasetController.extend({dataElementType:t.elements.Rectangle,initialize:function(e,a){t.DatasetController.prototype.initialize.call(this,e,a),this.getMeta().bar=!0},getBarCount:function(){var t=this,a=0;return e.each(t.chart.data.datasets,function(e,i){var n=t.chart.getDatasetMeta(i);n.bar&amp;&amp;t.ch
 art.isDatasetVisible(i)&amp;&amp;++a},t),a},update:function(t){var a=this;e.each(a.getMeta().data,function(e,i){a.updateElement(e,i,t)},a)},updateElement:function(t,a,i){var n=this,o=n.getMeta(),r=n.getScaleForId(o.xAxisID),l=n.getScaleForId(o.yAxisID),s=l.getBasePixel(),d=n.chart.options.elements.rectangle,u=t.custom||{},c=n.getDataset();t._xScale=r,t._yScale=l,t._datasetIndex=n.index,t._index=a;var h=n.getRuler(a);t._model={x:n.calculateBarX(a,n.index,h),y:i?s:n.calculateBarY(a,n.index),label:n.chart.data.labels[a],datasetLabel:c.label,base:i?s:n.calculateBarBase(n.index,a),width:n.calculateBarWidth(h),backgroundColor:u.backgroundColor?u.backgroundColor:e.getValueAtIndexOrDefault(c.backgroundColor,a,d.backgroundColor),borderSkipped:u.borderSkipped?u.borderSkipped:d.borderSkipped,borderColor:u.borderColor?u.borderColor:e.getValueAtIndexOrDefault(c.borderColor,a,d.borderColor),borderWidth:u.borderWidth?u.borderWidth:e.getValueAtIndexOrDefault(c.borderWidth,a,d.borderWidth)},
 t.pivot()},calculateBarBase:function(t,e){var a=this,i=a.getMeta(),n=a.getScaleForId(i.yAxisID),o=0;if(n.options.stacked){for(var r=a.chart,l=r.data.datasets,s=Number(l[t].data[e]),d=0;t&gt;d;d++){var u=l[d],c=r.getDatasetMeta(d);if(c.bar&amp;&amp;c.yAxisID===n.id&amp;&amp;r.isDatasetVisible(d)){var h=Number(u.data[e]);o+=0&gt;s?Math.min(h,0):Math.max(h,0)}}return n.getPixelForValue(o)}return n.getBasePixel()},getRuler:function(t){var e,a=this,i=a.getMeta(),n=a.getScaleForId(i.xAxisID),o=a.getBarCount();e=&quot;category&quot;===n.options.type?n.getPixelForTick(t+1)-n.getPixelForTick(t):n.width/n.ticks.length;var r=e*n.options.categoryPercentage,l=(e-e*n.options.categoryPercentage)/2,s=r/o;if(n.ticks.length!==a.chart.data.labels.length){var d=n.ticks.length/a.chart.data.labels.length;s*=d}var u=s*n.options.barPercentage,c=s-s*n.options.barPercentage;return{datasetCount:o,tickWidth:e,categoryWidth:r,categorySpacing:l,fullBarWidth:s,barWidth:u,barSpacing:c}},calculateBarWidth:f
 unction(t){var e=this.getScaleForId(this.getMeta().xAxisID);return e.options.barThickness?e.options.barThickness:e.options.stacked?t.categoryWidth:t.barWidth},getBarIndex:function(t){var e,a,i=0;for(a=0;t&gt;a;++a)e=this.chart.getDatasetMeta(a),e.bar&amp;&amp;this.chart.isDatasetVisible(a)&amp;&amp;++i;return i},calculateBarX:function(t,e,a){var i=this,n=i.getMeta(),o=i.getScaleForId(n.xAxisID),r=i.getBarIndex(e),l=o.getPixelForValue(null,t,e,i.chart.isCombo);return l-=i.chart.isCombo?a.tickWidth/2:0,o.options.stacked?l+a.categoryWidth/2+a.categorySpacing:l+a.barWidth/2+a.categorySpacing+a.barWidth*r+a.barSpacing/2+a.barSpacing*r},calculateBarY:function(t,e){var a=this,i=a.getMeta(),n=a.getScaleForId(i.yAxisID),o=Number(a.getDataset().data[t]);if(n.options.stacked){for(var r=0,l=0,s=0;e&gt;s;s++){var d=a.chart.data.datasets[s],u=a.chart.getDatasetMeta(s);if(u.bar&amp;&amp;u.yAxisID===n.id&amp;&amp;a.chart.isDatasetVisible(s)){var c=Number(d.data[t]);0&gt;c?l+=c||0:r+=c||0}}r
 eturn 0&gt;o?n.getPixelForValue(l+o):n.getPixelForValue(r+o)}return n.getPixelForValue(o)},draw:function(t){var e,a,i=this,n=t||1,o=i.getMeta().data,r=i.getDataset();for(e=0,a=o.length;a&gt;e;++e){var l=r.data[e];null===l||void 0===l||isNaN(l)||o[e].transition(n).draw()}},setHoverStyle:function(t){var a=this.chart.data.datasets[t._datasetIndex],i=t._index,n=t.custom||{},o=t._model;o.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:e.getValueAtIndexOrDefault(a.hoverBackgroundColor,i,e.getHoverColor(o.backgroundColor)),o.borderColor=n.hoverBorderColor?n.hoverBorderColor:e.getValueAtIndexOrDefault(a.hoverBorderColor,i,e.getHoverColor(o.borderColor)),o.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:e.getValueAtIndexOrDefault(a.hoverBorderWidth,i,o.borderWidth)},removeHoverStyle:function(t){var a=this.chart.data.datasets[t._datasetIndex],i=t._index,n=t.custom||{},o=t._model,r=this.chart.options.elements.rectangle;o.backgroundColor=n.backgroundColor?n.backgroundCol
 or:e.getValueAtIndexOrDefault(a.backgroundColor,i,r.backgroundColor),o.borderColor=n.borderColor?n.borderColor:e.getValueAtIndexOrDefault(a.borderColor,i,r.borderColor),o.borderWidth=n.borderWidth?n.borderWidth:e.getValueAtIndexOrDefault(a.borderWidth,i,r.borderWidth)}}),t.defaults.horizontalBar={hover:{mode:&quot;label&quot;},scales:{xAxes:[{type:&quot;linear&quot;,position:&quot;bottom&quot;}],yAxes:[{position:&quot;left&quot;,type:&quot;category&quot;,categoryPercentage:.8,barPercentage:.9,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:&quot;left&quot;}},tooltips:{callbacks:{title:function(t,e){var a=&quot;&quot;;return t.length&gt;0&amp;&amp;(t[0].yLabel?a=t[0].yLabel:e.labels.length&gt;0&amp;&amp;t[0].index&lt;e.labels.length&amp;&amp;(a=e.labels[t[0].index])),a},label:function(t,e){var a=e.datasets[t.datasetIndex].label||&quot;&quot;;return a+&quot;: &quot;+t.xLabel}}}},t.controllers.horizontalBar=t.controllers.bar.extend({updateElement:function(t
 ,a,i){var n=this,o=n.getMeta(),r=n.getScaleForId(o.xAxisID),l=n.getScaleForId(o.yAxisID),s=r.getBasePixel(),d=t.custom||{},u=n.getDataset(),c=n.chart.options.elements.rectangle;t._xScale=r,t._yScale=l,t._datasetIndex=n.index,t._index=a;var h=n.getRuler(a);t._model={x:i?s:n.calculateBarX(a,n.index),y:n.calculateBarY(a,n.index,h),label:n.chart.data.labels[a],datasetLabel:u.label,base:i?s:n.calculateBarBase(n.index,a),height:n.calculateBarHeight(h),backgroundColor:d.backgroundColor?d.backgroundColor:e.getValueAtIndexOrDefault(u.backgroundColor,a,c.backgroundColor),borderSkipped:d.borderSkipped?d.borderSkipped:c.borderSkipped,borderColor:d.borderColor?d.borderColor:e.getValueAtIndexOrDefault(u.borderColor,a,c.borderColor),borderWidth:d.borderWidth?d.borderWidth:e.getValueAtIndexOrDefault(u.borderWidth,a,c.borderWidth)},t.draw=function(){function t(t){return s[(u+t)%4]}var e=this._chart.ctx,a=this._view,i=a.height/2,n=a.y-i,o=a.y+i,r=a.base-(a.base-a.x),l=a.borderWidth/2;a.border
 Width&amp;&amp;(n+=l,o-=l,r+=l),e.beginPath(),e.fillStyle=a.backgroundColor,e.strokeStyle=a.borderColor,e.lineWidth=a.borderWidth;var s=[[a.base,o],[a.base,n],[r,n],[r,o]],d=[&quot;bottom&quot;,&quot;left&quot;,&quot;top&quot;,&quot;right&quot;],u=d.indexOf(a.borderSkipped,0);-1===u&amp;&amp;(u=0),e.moveTo.apply(e,t(0));for(var c=1;4&gt;c;c++)e.lineTo.apply(e,t(c));e.fill(),a.borderWidth&amp;&amp;e.stroke()},t.pivot()},calculateBarBase:function(t,e){var a=this,i=a.getMeta(),n=a.getScaleForId(i.xAxisID),o=0;if(n.options.stacked){for(var r=a.chart,l=r.data.datasets,s=Number(l[t].data[e]),d=0;t&gt;d;d++){var u=l[d],c=r.getDatasetMeta(d);if(c.bar&amp;&amp;c.xAxisID===n.id&amp;&amp;r.isDatasetVisible(d)){
+var h=Number(u.data[e]);o+=0&gt;s?Math.min(h,0):Math.max(h,0)}}return n.getPixelForValue(o)}return n.getBasePixel()},getRuler:function(t){var e,a=this,i=a.getMeta(),n=a.getScaleForId(i.yAxisID),o=a.getBarCount();e=&quot;category&quot;===n.options.type?n.getPixelForTick(t+1)-n.getPixelForTick(t):n.width/n.ticks.length;var r=e*n.options.categoryPercentage,l=(e-e*n.options.categoryPercentage)/2,s=r/o;if(n.ticks.length!==a.chart.data.labels.length){var d=n.ticks.length/a.chart.data.labels.length;s*=d}var u=s*n.options.barPercentage,c=s-s*n.options.barPercentage;return{datasetCount:o,tickHeight:e,categoryHeight:r,categorySpacing:l,fullBarHeight:s,barHeight:u,barSpacing:c}},calculateBarHeight:function(t){var e=this,a=e.getScaleForId(e.getMeta().yAxisID);return a.options.barThickness?a.options.barThickness:a.options.stacked?t.categoryHeight:t.barHeight},calculateBarX:function(t,e){var a=this,i=a.getMeta(),n=a.getScaleForId(i.xAxisID),o=Number(a.getDataset().data[t]);if(n.options.st
 acked){for(var r=0,l=0,s=0;e&gt;s;s++){var d=a.chart.data.datasets[s],u=a.chart.getDatasetMeta(s);if(u.bar&amp;&amp;u.xAxisID===n.id&amp;&amp;a.chart.isDatasetVisible(s)){var c=Number(d.data[t]);0&gt;c?l+=c||0:r+=c||0}}return 0&gt;o?n.getPixelForValue(l+o):n.getPixelForValue(r+o)}return n.getPixelForValue(o)},calculateBarY:function(t,e,a){var i=this,n=i.getMeta(),o=i.getScaleForId(n.yAxisID),r=i.getBarIndex(e),l=o.getPixelForValue(null,t,e,i.chart.isCombo);return l-=i.chart.isCombo?a.tickHeight/2:0,o.options.stacked?l+a.categoryHeight/2+a.categorySpacing:l+a.barHeight/2+a.categorySpacing+a.barHeight*r+a.barSpacing/2+a.barSpacing*r}})}},{}],16:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers;t.defaults.bubble={hover:{mode:&quot;single&quot;},scales:{xAxes:[{type:&quot;linear&quot;,position:&quot;bottom&quot;,id:&quot;x-axis-0&quot;}],yAxes:[{type:&quot;linear&quot;,position:&quot;left&quot;,id:&quot;y-axis-0&quot;}]},tooltips:{callbacks:{title:fun
 ction(){return&quot;&quot;},label:function(t,e){var a=e.datasets[t.datasetIndex].label||&quot;&quot;,i=e.datasets[t.datasetIndex].data[t.index];return a+&quot;: (&quot;+t.xLabel+&quot;, &quot;+t.yLabel+&quot;, &quot;+i.r+&quot;)&quot;}}}},t.controllers.bubble=t.DatasetController.extend({dataElementType:t.elements.Point,update:function(t){var a=this,i=a.getMeta(),n=i.data;e.each(n,function(e,i){a.updateElement(e,i,t)})},updateElement:function(a,i,n){var o=this,r=o.getMeta(),l=o.getScaleForId(r.xAxisID),s=o.getScaleForId(r.yAxisID),d=a.custom||{},u=o.getDataset(),c=u.data[i],h=o.chart.options.elements.point,f=o.index;e.extend(a,{_xScale:l,_yScale:s,_datasetIndex:f,_index:i,_model:{x:n?l.getPixelForDecimal(.5):l.getPixelForValue(&quot;object&quot;==typeof c?c:NaN,i,f,o.chart.isCombo),y:n?s.getBasePixel():s.getPixelForValue(c,i,f),radius:n?0:d.radius?d.radius:o.getRadius(c),hitRadius:d.hitRadius?d.hitRadius:e.getValueAtIndexOrDefault(u.hitRadius,i,h.hitRadius)}}),t.DatasetContro
 ller.prototype.removeHoverStyle.call(o,a,h);var g=a._model;g.skip=d.skip?d.skip:isNaN(g.x)||isNaN(g.y),a.pivot()},getRadius:function(t){return t.r||this.chart.options.elements.point.radius},setHoverStyle:function(a){var i=this;t.DatasetController.prototype.setHoverStyle.call(i,a);var n=i.chart.data.datasets[a._datasetIndex],o=a._index,r=a.custom||{},l=a._model;l.radius=r.hoverRadius?r.hoverRadius:e.getValueAtIndexOrDefault(n.hoverRadius,o,i.chart.options.elements.point.hoverRadius)+i.getRadius(n.data[o])},removeHoverStyle:function(e){var a=this;t.DatasetController.prototype.removeHoverStyle.call(a,e,a.chart.options.elements.point);var i=a.chart.data.datasets[e._datasetIndex].data[e._index],n=e.custom||{},o=e._model;o.radius=n.radius?n.radius:a.getRadius(i)}})}},{}],17:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers,a=t.defaults;a.doughnut={animation:{animateRotate:!0,animateScale:!1},aspectRatio:1,hover:{mode:&quot;single&quot;},legendCallback:f
 unction(t){var e=[];e.push('&lt;ul class=&quot;'+t.id+'-legend&quot;&gt;');var a=t.data,i=a.datasets,n=a.labels;if(i.length)for(var o=0;o&lt;i[0].data.length;++o)e.push('&lt;li&gt;&lt;span style=&quot;background-color:'+i[0].backgroundColor[o]+'&quot;&gt;&lt;/span&gt;'),n[o]&amp;&amp;e.push(n[o]),e.push(&quot;&lt;/li&gt;&quot;);return e.push(&quot;&lt;/ul&gt;&quot;),e.join(&quot;&quot;)},legend:{labels:{generateLabels:function(t){var a=t.data;return a.labels.length&amp;&amp;a.datasets.length?a.labels.map(function(i,n){var o=t.getDatasetMeta(0),r=a.datasets[0],l=o.data[n],s=l&amp;&amp;l.custom||{},d=e.getValueAtIndexOrDefault,u=t.options.elements.arc,c=s.backgroundColor?s.backgroundColor:d(r.backgroundColor,n,u.backgroundColor),h=s.borderColor?s.borderColor:d(r.borderColor,n,u.borderColor),f=s.borderWidth?s.borderWidth:d(r.borderWidth,n,u.borderWidth);return{text:i,fillStyle:c,strokeStyle:h,lineWidth:f,hidden:isNaN(r.data[n])||o.data[n].hidden,index:n}}):[]}},onClick:function
 (t,e){var a,i,n,o=e.index,r=this.chart;for(a=0,i=(r.data.datasets||[]).length;i&gt;a;++a)n=r.getDatasetMeta(a),n.data[o]&amp;&amp;(n.data[o].hidden=!n.data[o].hidden);r.update()}},cutoutPercentage:50,rotation:Math.PI*-.5,circumference:2*Math.PI,tooltips:{callbacks:{title:function(){return&quot;&quot;},label:function(t,a){var i=a.labels[t.index],n=&quot;: &quot;+a.datasets[t.datasetIndex].data[t.index];return e.isArray(i)?(i=i.slice(),i[0]+=n):i+=n,i}}}},a.pie=e.clone(a.doughnut),e.extend(a.pie,{cutoutPercentage:0}),t.controllers.doughnut=t.controllers.pie=t.DatasetController.extend({dataElementType:t.elements.Arc,linkScales:e.noop,getRingIndex:function(t){for(var e=0,a=0;t&gt;a;++a)this.chart.isDatasetVisible(a)&amp;&amp;++e;return e},update:function(t){var a=this,i=a.chart,n=i.chartArea,o=i.options,r=o.elements.arc,l=n.right-n.left-r.borderWidth,s=n.bottom-n.top-r.borderWidth,d=Math.min(l,s),u={x:0,y:0},c=a.getMeta(),h=o.cutoutPercentage,f=o.circumference;if(f&lt;2*Math.PI)
 {var g=o.rotation%(2*Math.PI);g+=2*Math.PI*(g&gt;=Math.PI?-1:g&lt;-Math.PI?1:0);var p=g+f,m={x:Math.cos(g),y:Math.sin(g)},b={x:Math.cos(p),y:Math.sin(p)},v=0&gt;=g&amp;&amp;p&gt;=0||g&lt;=2*Math.PI&amp;&amp;2*Math.PI&lt;=p,x=g&lt;=.5*Math.PI&amp;&amp;.5*Math.PI&lt;=p||g&lt;=2.5*Math.PI&amp;&amp;2.5*Math.PI&lt;=p,y=g&lt;=-Math.PI&amp;&amp;-Math.PI&lt;=p||g&lt;=Math.PI&amp;&amp;Math.PI&lt;=p,k=g&lt;=.5*-Math.PI&amp;&amp;.5*-Math.PI&lt;=p||g&lt;=1.5*Math.PI&amp;&amp;1.5*Math.PI&lt;=p,S=h/100,w={x:y?-1:Math.min(m.x*(m.x&lt;0?1:S),b.x*(b.x&lt;0?1:S)),y:k?-1:Math.min(m.y*(m.y&lt;0?1:S),b.y*(b.y&lt;0?1:S))},M={x:v?1:Math.max(m.x*(m.x&gt;0?1:S),b.x*(b.x&gt;0?1:S)),y:x?1:Math.max(m.y*(m.y&gt;0?1:S),b.y*(b.y&gt;0?1:S))},C={width:.5*(M.x-w.x),height:.5*(M.y-w.y)};d=Math.min(l/C.width,s/C.height),u={x:(M.x+w.x)*-.5,y:(M.y+w.y)*-.5}}i.borderWidth=a.getMaxBorderWidth(c.data),i.outerRadius=Math.max((d-i.borderWidth)/2,0),i.innerRadius=Math.max(h?i.outerRadius/100*h:1,0),i.radiusLength=(i.o
 uterRadius-i.innerRadius)/i.getVisibleDatasetCount(),i.offsetX=u.x*i.outerRadius,i.offsetY=u.y*i.outerRadius,c.total=a.calculateTotal(),a.outerRadius=i.outerRadius-i.radiusLength*a.getRingIndex(a.index),a.innerRadius=a.outerRadius-i.radiusLength,e.each(c.data,function(e,i){a.updateElement(e,i,t)})},updateElement:function(t,a,i){var n=this,o=n.chart,r=o.chartArea,l=o.options,s=l.animation,d=(r.left+r.right)/2,u=(r.top+r.bottom)/2,c=l.rotation,h=l.rotation,f=n.getDataset(),g=i&amp;&amp;s.animateRotate?0:t.hidden?0:n.calculateCircumference(f.data[a])*(l.circumference/(2*Math.PI)),p=i&amp;&amp;s.animateScale?0:n.innerRadius,m=i&amp;&amp;s.animateScale?0:n.outerRadius,b=e.getValueAtIndexOrDefault;e.extend(t,{_datasetIndex:n.index,_index:a,_model:{x:d+o.offsetX,y:u+o.offsetY,startAngle:c,endAngle:h,circumference:g,outerRadius:m,innerRadius:p,label:b(f.label,a,o.data.labels[a])}});var v=t._model;this.removeHoverStyle(t),i&amp;&amp;s.animateRotate||(0===a?v.startAngle=l.rotation:v.s
 tartAngle=n.getMeta().data[a-1]._model.endAngle,v.endAngle=v.startAngle+v.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,a=this.getDataset(),i=this.getMeta(),n=0;return e.each(i.data,function(e,i){t=a.data[i],isNaN(t)||e.hidden||(n+=Math.abs(t))}),n},calculateCircumference:function(t){var e=this.getMeta().total;return e&gt;0&amp;&amp;!isNaN(t)?2*Math.PI*(t/e):0},getMaxBorderWidth:function(t){for(var e,a,i=0,n=this.index,o=t.length,r=0;o&gt;r;r++)e=t[r]._model?t[r]._model.borderWidth:0,a=t[r]._chart?t[r]._chart.config.data.datasets[n].hoverBorderWidth:0,i=e&gt;i?e:i,i=a&gt;i?a:i;return i}})}},{}],18:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){function e(t,e){return a.getValueOrDefault(t.showLine,e.showLines)}var a=t.helpers;t.defaults.line={showLines:!0,spanGaps:!1,hover:{mode:&quot;label&quot;},scales:{xAxes:[{type:&quot;categ
 ory&quot;,id:&quot;x-axis-0&quot;}],yAxes:[{type:&quot;linear&quot;,id:&quot;y-axis-0&quot;}]}},t.controllers.line=t.DatasetController.extend({datasetElementType:t.elements.Line,dataElementType:t.elements.Point,update:function(t){var i,n,o,r=this,l=r.getMeta(),s=l.dataset,d=l.data||[],u=r.chart.options,c=u.elements.line,h=r.getScaleForId(l.yAxisID),f=r.getDataset(),g=e(f,u);for(g&amp;&amp;(o=s.custom||{},void 0!==f.tension&amp;&amp;void 0===f.lineTension&amp;&amp;(f.lineTension=f.tension),s._scale=h,s._datasetIndex=r.index,s._children=d,s._model={spanGaps:f.spanGaps?f.spanGaps:u.spanGaps,tension:o.tension?o.tension:a.getValueOrDefault(f.lineTension,c.tension),backgroundColor:o.backgroundColor?o.backgroundColor:f.backgroundColor||c.backgroundColor,borderWidth:o.borderWidth?o.borderWidth:f.borderWidth||c.borderWidth,borderColor:o.borderColor?o.borderColor:f.borderColor||c.borderColor,borderCapStyle:o.borderCapStyle?o.borderCapStyle:f.borderCapStyle||c.borderCapStyle,borderDash
 :o.borderDash?o.borderDash:f.borderDash||c.borderDash,borderDashOffset:o.borderDashOffset?o.borderDashOffset:f.borderDashOffset||c.borderDashOffset,borderJoinStyle:o.borderJoinStyle?o.borderJoinStyle:f.borderJoinStyle||c.borderJoinStyle,fill:o.fill?o.fill:void 0!==f.fill?f.fill:c.fill,steppedLine:o.steppedLine?o.steppedLine:a.getValueOrDefault(f.steppedLine,c.stepped),cubicInterpolationMode:o.cubicInterpolationMode?o.cubicInterpolationMode:a.getValueOrDefault(f.cubicInterpolationMode,c.cubicInterpolationMode),scaleTop:h.top,scaleBottom:h.bottom,scaleZero:h.getBasePixel()},s.pivot()),i=0,n=d.length;n&gt;i;++i)r.updateElement(d[i],i,t);for(g&amp;&amp;0!==s._model.tension&amp;&amp;r.updateBezierControlPoints(),i=0,n=d.length;n&gt;i;++i)d[i].pivot()},getPointBackgroundColor:function(t,e){var i=this.chart.options.elements.point.backgroundColor,n=this.getDataset(),o=t.custom||{};return o.backgroundColor?i=o.backgroundColor:n.pointBackgroundColor?i=a.getValueAtIndexOrDefault(n.poin
 tBackgroundColor,e,i):n.backgroundColor&amp;&amp;(i=n.backgroundColor),i},getPointBorderColor:function(t,e){var i=this.chart.options.elements.point.borderColor,n=this.getDataset(),o=t.custom||{};return o.borderColor?i=o.borderColor:n.pointBorderColor?i=a.getValueAtIndexOrDefault(n.pointBorderColor,e,i):n.borderColor&amp;&amp;(i=n.borderColor),i},getPointBorderWidth:function(t,e){var i=this.chart.options.elements.point.borderWidth,n=this.getDataset(),o=t.custom||{};return o.borderWidth?i=o.borderWidth:n.pointBorderWidth?i=a.getValueAtIndexOrDefault(n.pointBorderWidth,e,i):n.borderWidth&amp;&amp;(i=n.borderWidth),i},updateElement:function(t,e,i){var n,o,r=this,l=r.getMeta(),s=t.custom||{},d=r.getDataset(),u=r.index,c=d.data[e],h=r.getScaleForId(l.yAxisID),f=r.getScaleForId(l.xAxisID),g=r.chart.options.elements.point,p=r.chart.data.labels||[],m=1===p.length||1===d.data.length||r.chart.isCombo;void 0!==d.radius&amp;&amp;void 0===d.pointRadius&amp;&amp;(d.pointRadius=d.radius),vo
 id 0!==d.hitRadius&amp;&amp;void 0===d.pointHitRadius&amp;&amp;(d.pointHitRadius=d.hitRadius),n=f.getPixelForValue(&quot;object&quot;==typeof c?c:NaN,e,u,m),o=i?h.getBasePixel():r.calculatePointY(c,e,u),t._xScale=f,t._yScale=h,t._datasetIndex=u,t._index=e,t._model={x:n,y:o,skip:s.skip||isNaN(n)||isNaN(o),radius:s.radius||a.getValueAtIndexOrDefault(d.pointRadius,e,g.radius),pointStyle:s.pointStyle||a.getValueAtIndexOrDefault(d.pointStyle,e,g.pointStyle),backgroundColor:r.getPointBackgroundColor(t,e),borderColor:r.getPointBorderColor(t,e),borderWidth:r.getPointBorderWidth(t,e),tension:l.dataset._model?l.dataset._model.tension:0,steppedLine:l.dataset._model?l.dataset._model.steppedLine:!1,hitRadius:s.hitRadius||a.getValueAtIndexOrDefault(d.pointHitRadius,e,g.hitRadius)}},calculatePointY:function(t,e,a){var i,n,o,r=this,l=r.chart,s=r.getMeta(),d=r.getScaleForId(s.yAxisID),u=0,c=0;if(d.options.stacked){for(i=0;a&gt;i;i++)if(n=l.data.datasets[i],o=l.getDatasetMeta(i),&quot;line&qu
 ot;===o.type&amp;&amp;o.yAxisID===d.id&amp;&amp;l.isDatasetVisible(i)){var h=Number(d.getRightValue(n.data[e]));0&gt;h?c+=h||0:u+=h||0}var f=Number(d.getRightValue(t));return 0&gt;f?d.getPixelForValue(c+f):d.getPixelForValue(u+f)}return d.getPixelForValue(t)},updateBezierControlPoints:function(){function t(t,e,a){return Math.max(Math.min(t,a),e)}var e,i,n,o,r,l=this,s=l.getMeta(),d=l.chart.chartArea,u=s.data||[];if(s.dataset._model.spanGaps&amp;&amp;(u=u.filter(function(t){return!t._model.skip})),&quot;monotone&quot;===s.dataset._model.cubicInterpolationMode)a.splineCurveMonotone(u);else for(e=0,i=u.length;i&gt;e;++e)n=u[e],o=n._model,r=a.splineCurve(a.previousItem(u,e)._model,o,a.nextItem(u,e)._model,s.dataset._model.tension),o.controlPointPreviousX=r.previous.x,o.controlPointPreviousY=r.previous.y,o.controlPointNextX=r.next.x,o.controlPointNextY=r.next.y;if(l.chart.options.elements.line.capBezierPoints)for(e=0,i=u.length;i&gt;e;++e)o=u[e]._model,o.controlPointPreviousX=t(o
 .controlPointPreviousX,d.left,d.right),o.controlPointPreviousY=t(o.controlPointPreviousY,d.top,d.bottom),o.controlPointNextX=t(o.controlPointNextX,d.left,d.right),o.controlPointNextY=t(o.controlPointNextY,d.top,d.bottom)},draw:function(t){var a,i,n=this,o=n.getMeta(),r=o.data||[],l=t||1;for(a=0,i=r.length;i&gt;a;++a)r[a].transition(l);for(e(n.getDataset(),n.chart.options)&amp;&amp;o.dataset.transition(l).draw(),a=0,i=r.length;i&gt;a;++a)r[a].draw()},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],i=t._index,n=t.custom||{},o=t._model;o.radius=n.hoverRadius||a.getValueAtIndexOrDefault(e.pointHoverRadius,i,this.chart.options.elements.point.hoverRadius),o.backgroundColor=n.hoverBackgroundColor||a.getValueAtIndexOrDefault(e.pointHoverBackgroundColor,i,a.getHoverColor(o.backgroundColor)),o.borderColor=n.hoverBorderColor||a.getValueAtIndexOrDefault(e.pointHoverBorderColor,i,a.getHoverColor(o.borderColor)),o.borderWidth=n.hoverBorderWidth||a.getValueAtIndex
 OrDefault(e.pointHoverBorderWidth,i,o.borderWidth)},removeHoverStyle:function(t){var e=this,i=e.chart.data.datasets[t._datasetIndex],n=t._index,o=t.custom||{},r=t._model;void 0!==i.radius&amp;&amp;void 0===i.pointRadius&amp;&amp;(i.pointRadius=i.radius),r.radius=o.radius||a.getValueAtIndexOrDefault(i.pointRadius,n,e.chart.options.elements.point.radius),r.backgroundColor=e.getPointBackgroundColor(t,n),r.borderColor=e.getPointBorderColor(t,n),r.borderWidth=e.getPointBorderWidth(t,n)}})}},{}],19:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers;t.defaults.polarArea={scale:{type:&quot;radialLinear&quot;,lineArc:!0,ticks:{beginAtZero:!0}},animation:{animateRotate:!0,animateScale:!0},startAngle:-.5*Math.PI,aspectRatio:1,legendCallback:function(t){var e=[];e.push('&lt;ul class=&quot;'+t.id+'-legend&quot;&gt;');var a=t.data,i=a.datasets,n=a.labels;if(i.length)for(var o=0;o&lt;i[0].data.length;++o)e.push('&lt;li&gt;&lt;span style=&quot;background-color:'+i
 [0].backgroundColor[o]+'&quot;&gt;&lt;/span&gt;'),n[o]&amp;&amp;e.push(n[o]),e.push(&quot;&lt;/li&gt;&quot;);return e.push(&quot;&lt;/ul&gt;&quot;),e.join(&quot;&quot;)},legend:{labels:{generateLabels:function(t){var a=t.data;return a.labels.length&amp;&amp;a.datasets.length?a.labels.map(function(i,n){var o=t.getDatasetMeta(0),r=a.datasets[0],l=o.data[n],s=l.custom||{},d=e.getValueAtIndexOrDefault,u=t.options.elements.arc,c=s.backgroundColor?s.backgroundColor:d(r.backgroundColor,n,u.backgroundColor),h=s.borderColor?s.borderColor:d(r.borderColor,n,u.borderColor),f=s.borderWidth?s.borderWidth:d(r.borderWidth,n,u.borderWidth);return{text:i,fillStyle:c,strokeStyle:h,lineWidth:f,hidden:isNaN(r.data[n])||o.data[n].hidden,index:n}}):[]}},onClick:function(t,e){var a,i,n,o=e.index,r=this.chart;for(a=0,i=(r.data.datasets||[]).length;i&gt;a;++a)n=r.getDatasetMeta(a),n.data[o].hidden=!n.data[o].hidden;r.update()}},tooltips:{callbacks:{title:function(){return&quot;&quot;},label:function(
 t,e){return e.labels[t.index]+&quot;: &quot;+t.yLabel}}}},t.controllers.polarArea=t.DatasetController.extend({dataElementType:t.elements.Arc,linkScales:e.noop,update:function(t){var a=this,i=a.chart,n=i.chartArea,o=a.getMeta(),r=i.options,l=r.elements.arc,s=Math.min(n.right-n.left,n.bottom-n.top);i.outerRadius=Math.max((s-l.borderWidth/2)/2,0),i.innerRadius=Math.max(r.cutoutPercentage?i.outerRadius/100*r.cutoutPercentage:1,0),i.radiusLength=(i.outerRadius-i.innerRadius)/i.getVisibleDatasetCount(),a.outerRadius=i.outerRadius-i.radiusLength*a.index,a.innerRadius=a.outerRadius-i.radiusLength,o.count=a.countVisibleElements(),e.each(o.data,function(e,i){a.updateElement(e,i,t)})},updateElement:function(t,a,i){for(var n=this,o=n.chart,r=n.getDataset(),l=o.options,s=l.animation,d=o.scale,u=e.getValueAtIndexOrDefault,c=o.data.labels,h=n.calculateCircumference(r.data[a]),f=d.xCenter,g=d.yCenter,p=0,m=n.getMeta(),b=0;a&gt;b;++b)isNaN(r.data[b])||m.data[b].hidden||++p;var v=l.startAngle
 ,x=t.hidden?0:d.getDistanceFromCenterForValue(r.data[a]),y=v+h*p,k=y+(t.hidden?0:h),S=s.animateScale?0:d.getDistanceFromCenterForValue(r.data[a]);e.extend(t,{_datasetIndex:n.index,_index:a,_scale:d,_model:{x:f,y:g,innerRadius:0,outerRadius:i?S:x,startAngle:i&amp;&amp;s.animateRotate?v:y,endAngle:i&amp;&amp;s.animateRotate?v:k,label:u(c,a,c[a])}}),n.removeHoverStyle(t),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},countVisibleElements:function(){var t=this.getDataset(),a=this.getMeta(),i=0;return e.each(a.data,function(e,a){isNaN(t.data[a])||e.hidden||i++}),i},calculateCircumference:function(t){var e=this.getMeta().count;return e&gt;0&amp;&amp;!isNaN(t)?2*Math.PI/e:0}})}},{}],20:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers;t.defaults.radar={aspectRatio:1,scale:{type:&quot;radialLinear&quot;},elements:{line:{tension:0}}},t.controllers.radar=t.DatasetControlle
 r.extend({datasetElementType:t.elements.Line,dataElementType:t.elements.Point,linkScales:e.noop,update:function(t){var a=this,i=a.getMeta(),n=i.dataset,o=i.data,r=n.custom||{},l=a.getDataset(),s=a.chart.options.elements.line,d=a.chart.scale;void 0!==l.tension&amp;&amp;void 0===l.lineTension&amp;&amp;(l.lineTension=l.tension),e.extend(i.dataset,{_datasetIndex:a.index,_children:o,_loop:!0,_model:{tension:r.tension?r.tension:e.getValueOrDefault(l.lineTension,s.tension),backgroundColor:r.backgroundColor?r.backgroundColor:l.backgroundColor||s.backgroundColor,borderWidth:r.borderWidth?r.borderWidth:l.borderWidth||s.borderWidth,borderColor:r.borderColor?r.borderColor:l.borderColor||s.borderColor,fill:r.fill?r.fill:void 0!==l.fill?l.fill:s.fill,borderCapStyle:r.borderCapStyle?r.borderCapStyle:l.borderCapStyle||s.borderCapStyle,borderDash:r.borderDash?r.borderDash:l.borderDash||s.borderDash,borderDashOffset:r.borderDashOffset?r.borderDashOffset:l.borderDashOffset||s.borderDashOffset,
 borderJoinStyle:r.borderJoinStyle?r.borderJoinStyle:l.borderJoinStyle||s.borderJoinStyle,scaleTop:d.top,scaleBottom:d.bottom,scaleZero:d.getBasePosition()}}),i.dataset.pivot(),e.each(o,function(e,i){a.updateElement(e,i,t)},a),a.updateBezierControlPoints()},updateElement:function(t,a,i){var n=this,o=t.custom||{},r=n.getDataset(),l=n.chart.scale,s=n.chart.options.elements.point,d=l.getPointPositionForValue(a,r.data[a]);e.extend(t,{_datasetIndex:n.index,_index:a,_scale:l,_model:{x:i?l.xCenter:d.x,y:i?l.yCenter:d.y,tension:o.tension?o.tension:e.getValueOrDefault(r.tension,n.chart.options.elements.line.tension),radius:o.radius?o.radius:e.getValueAtIndexOrDefault(r.pointRadius,a,s.radius),backgroundColor:o.backgroundColor?o.backgroundColor:e.getValueAtIndexOrDefault(r.pointBackgroundColor,a,s.backgroundColor),borderColor:o.borderColor?o.borderColor:e.getValueAtIndexOrDefault(r.pointBorderColor,a,s.borderColor),borderWidth:o.borderWidth?o.borderWidth:e.getValueAtIndexOrDefault(r.po
 intBorderWidth,a,s.borderWidth),pointStyle:o.pointStyle?o.pointStyle:e.getValueAtIndexOrDefault(r.pointStyle,a,s.pointStyle),hitRadius:o.hitRadius?o.hitRadius:e.getValueAtIndexOrDefault(r.hitRadius,a,s.hitRadius)}}),t._model.skip=o.skip?o.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,a=this.getMeta();e.each(a.data,function(i,n){var o=i._model,r=e.splineCurve(e.previousItem(a.data,n,!0)._model,o,e.nextItem(a.data,n,!0)._model,o.tension);o.controlPointPreviousX=Math.max(Math.min(r.previous.x,t.right),t.left),o.controlPointPreviousY=Math.max(Math.min(r.previous.y,t.bottom),t.top),o.controlPointNextX=Math.max(Math.min(r.next.x,t.right),t.left),o.controlPointNextY=Math.max(Math.min(r.next.y,t.bottom),t.top),i.pivot()})},draw:function(t){var a=this.getMeta(),i=t||1;e.each(a.data,function(t){t.transition(i)}),a.dataset.transition(i).draw(),e.each(a.data,function(t){t.draw()})},setHoverStyle:function(t){var a=this.chart.da
 ta.datasets[t._datasetIndex],i=t.custom||{},n=t._index,o=t._model;o.radius=i.hoverRadius?i.hoverRadius:e.getValueAtIndexOrDefault(a.pointHoverRadius,n,this.chart.options.elements.point.hoverRadius),o.backgroundColor=i.hoverBackgroundColor?i.hoverBackgroundColor:e.getValueAtIndexOrDefault(a.pointHoverBackgroundColor,n,e.getHoverColor(o.backgroundColor)),o.borderColor=i.hoverBorderColor?i.hoverBorderColor:e.getValueAtIndexOrDefault(a.pointHoverBorderColor,n,e.getHoverColor(o.borderColor)),o.borderWidth=i.hoverBorderWidth?i.hoverBorderWidth:e.getValueAtIndexOrDefault(a.pointHoverBorderWidth,n,o.borderWidth)},removeHoverStyle:function(t){var a=this.chart.data.datasets[t._datasetIndex],i=t.custom||{},n=t._index,o=t._model,r=this.chart.options.elements.point;o.radius=i.radius?i.radius:e.getValueAtIndexOrDefault(a.radius,n,r.radius),o.backgroundColor=i.backgroundColor?i.backgroundColor:e.getValueAtIndexOrDefault(a.pointBackgroundColor,n,r.backgroundColor),o.borderColor=i.borderColo
 r?i.borderColor:e.getValueAtIndexOrDefault(a.pointBorderColor,n,r.borderColor),o.borderWidth=i.borderWidth?i.borderWidth:e.getValueAtIndexOrDefault(a.pointBorderWidth,n,r.borderWidth)}})}},{}],21:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers;t.defaults.global.animation={duration:1e3,easing:&quot;easeOutQuart&quot;,onProgress:e.noop,onComplete:e.noop},t.Animation=t.Element.extend({currentStep:null,numSteps:60,easing:&quot;&quot;,render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,a,i){var n=this;i||(t.animating=!0);for(var o=0;o&lt;n.animations.length;++o)if(n.animations[o].chartInstance===t)return void(n.animations[o].animationObject=e);n.animations.push({chartInstance:t,animationObject:e}),1===n.animations.length&amp;&amp;n.requestAnimationFrame()},cancelAnimation:function(t){var a=e.findIndex(this.animations,function(e){return e
 .chartInstance===t});-1!==a&amp;&amp;(this.animations.splice(a,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&amp;&amp;(t.request=e.requestAnimFrame.call(window,function(){t.request=null,t.startDigest()}))},startDigest:function(){var t=this,e=Date.now(),a=0;t.dropFrames&gt;1&amp;&amp;(a=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1);for(var i=0;i&lt;t.animations.length;)null===t.animations[i].animationObject.currentStep&amp;&amp;(t.animations[i].animationObject.currentStep=0),t.animations[i].animationObject.currentStep+=1+a,t.animations[i].animationObject.currentStep&gt;t.animations[i].animationObject.numSteps&amp;&amp;(t.animations[i].animationObject.currentStep=t.animations[i].animationObject.numSteps),t.animations[i].animationObject.render(t.animations[i].chartInstance,t.animations[i].animationObject),t.animations[i].animationObject.onAnimationProgress&amp;&amp;t.animations[i].animationObject.onAnimationProgress.call&amp;&amp;t.ani
 mations[i].animationObject.onAnimationProgress.call(t.animations[i].chartInstance,t.animations[i]),t.animations[i].animationObject.currentStep===t.animations[i].animationObject.numSteps?(t.animations[i].animationObject.onAnimationComplete&amp;&amp;t.animations[i].animationObject.onAnimationComplete.call&amp;&amp;t.animations[i].animationObject.onAnimationComplete.call(t.animations[i].chartInstance,t.animations[i]),t.animations[i].chartInstance.animating=!1,t.animations.splice(i,1)):++i;var n=Date.now(),o=(n-e)/t.frameDuration;t.dropFrames+=o,t.animations.length&gt;0&amp;&amp;t.requestAnimationFrame()}}}},{}],22:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.canvasHelpers={};e.drawPoint=function(t,e,a,i,n){var o,r,l,s,d,u;if(&quot;object&quot;==typeof e&amp;&amp;(o=e.toString(),&quot;[object HTMLImageElement]&quot;===o||&quot;[object HTMLCanvasElement]&quot;===o))return void t.drawImage(e,i-e.width/2,n-e.height/2);if(!(isNaN(a)||0&gt;=a)){switch(e){defa
 ult:t.beginPath(),t.arc(i,n,a,0,2*Math.PI),t.closePath(),t.fill();break;case&quot;triangle&quot;:t.beginPath(),r=3*a/Math.sqrt(3),d=r*Math.sqrt(3)/2,t.moveTo(i-r/2,n+d/3),t.lineTo(i+r/2,n+d/3),t.lineTo(i,n-2*d/3),t.closePath(),t.fill();break;case&quot;rect&quot;:u=1/Math.SQRT2*a,t.beginPath(),t.fillRect(i-u,n-u,2*u,2*u),t.strokeRect(i-u,n-u,2*u,2*u);break;case&quot;rectRot&quot;:u=1/Math.SQRT2*a,t.beginPath(),t.moveTo(i-u,n),t.lineTo(i,n+u),t.lineTo(i+u,n),t.lineTo(i,n-u),t.closePath(),t.fill();break;case&quot;cross&quot;:t.beginPath(),t.moveTo(i,n+a),t.lineTo(i,n-a),t.moveTo(i-a,n),t.lineTo(i+a,n),t.closePath();break;case&quot;crossRot&quot;:t.beginPath(),l=Math.cos(Math.PI/4)*a,s=Math.sin(Math.PI/4)*a,t.moveTo(i-l,n-s),t.lineTo(i+l,n+s),t.moveTo(i-l,n+s),t.lineTo(i+l,n-s),t.closePath();break;case&quot;star&quot;:t.beginPath(),t.moveTo(i,n+a),t.lineTo(i,n-a),t.moveTo(i-a,n),t.lineTo(i+a,n),l=Math.cos(Math.PI/4)*a,s=Math.sin(Math.PI/4)*a,t.moveTo(i-l,n-s),t.lineTo(i+l,n+s),t
 .moveTo(i-l,n+s),t.lineTo(i+l,n-s),t.closePath();break;case&quot;line&quot;:t.beginPath(),t.moveTo(i-a,n),t.lineTo(i+a,n),t.closePath();break;case&quot;dash&quot;:t.beginPath(),t.moveTo(i,n),t.lineTo(i+a,n),t.closePath()}t.stroke()}}}},{}],23:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){function e(t,e){var a=r.getStyle(t,e),i=a&amp;&amp;a.match(/(\d+)px/);return i?Number(i[1]):void 0}function a(t,a){var i=t.style,n=t.getAttribute(&quot;height&quot;),o=t.getAttribute(&quot;width&quot;);if(t._chartjs={initial:{height:n,width:o,style:{display:i.display,height:i.height,width:i.width}}},i.display=i.display||&quot;block&quot;,null===o||&quot;&quot;===o){var r=e(t,&quot;width&quot;);void 0!==r&amp;&amp;(t.width=r)}if(null===n||&quot;&quot;===n)if(&quot;&quot;===t.style.height)t.height=t.width/(a.options.aspectRatio||2);else{var l=e(t,&quot;height&quot;);void 0!==r&amp;&amp;(t.height=l)}return t}function i(t){if(t._chartjs){var e=t._chartjs.initial;[&quot;height&quo
 t;,&quot;width&quot;].forEach(function(a){var i=e[a];void 0===i||null===i?t.removeAttribute(a):t.setAttribute(a,i)}),r.each(e.style||{},function(e,a){t.style[a]=e}),t.width=t.width,delete t._chartjs}}function n(t,e){if(&quot;string&quot;==typeof t?t=document.getElementById(t):t.length&amp;&amp;(t=t[0]),t&amp;&amp;t.canvas&amp;&amp;(t=t.canvas),t instanceof HTMLCanvasElement){var i=t.getContext&amp;&amp;t.getContext(&quot;2d&quot;);if(i instanceof CanvasRenderingContext2D)return a(t,e),i}return null}function o(e){e=e||{};var a=e.data=e.data||{};return a.datasets=a.datasets||[],a.labels=a.labels||[],e.options=r.configMerge(t.defaults.global,t.defaults[e.type],e.options||{}),e}var r=t.helpers;t.types={},t.instances={},t.controllers={},t.Controller=function(e,a,i){var l=this;a=o(a);var s=n(e,a),d=s&amp;&amp;s.canvas,u=d&amp;&amp;d.height,c=d&amp;&amp;d.width;return i.ctx=s,i.canvas=d,i.config=a,i.width=c,i.height=u,i.aspectRatio=u?c/u:null,l.id=r.uid(),l.chart=i,l.config=a,l.opt
 ions=a.options,l._bufferedRender=!1,t.instances[l.id]=l,Object.defineProperty(l,&quot;data&quot;,{get:function(){return l.config.data}}),s&amp;&amp;d?(r.retinaScale(i),l.options.responsive&amp;&amp;(r.addResizeListener(d.parentNode,function(){l.resize()}),l.resize(!0)),l.initialize(),l):(console.error(&quot;Failed to create chart: can't acquire context from the given item&quot;),l)},r.extend(t.Controller.prototype,{initialize:function(){var e=this;return t.plugins.notify(&quot;beforeInit&quot;,[e]),e.bindEvents(),e.ensureScalesHaveIDs(),e.buildOrUpdateControllers(),e.buildScales(),e.updateLayout(),e.resetElements(),e.initToolTip(),e.update(),t.plugins.notify(&quot;afterInit&quot;,[e]),e},clear:function(){return r.clear(this.chart),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(e){var a=this,i=a.chart,n=a.options,o=i.canvas,l=n.maintainAspectRatio&amp;&amp;i.aspectRatio||null,s=Math.floor(r.getMaximumWidth(o)),d=Math.floor(l?s/l:r.
 getMaximumHeight(o));if(i.width!==s||i.height!==d){o.width=i.width=s,o.height=i.height=d,o.style.width=s+&quot;px&quot;,o.style.height=d+&quot;px&quot;,r.retinaScale(i);var u={width:s,height:d};t.plugins.notify(&quot;resize&quot;,[a,u]),a.options.onResize&amp;&amp;a.options.onResize(a,u),e||(a.stop(),a.update(a.options.responsiveAnimationDuration))}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},a=t.scale;r.each(e.xAxes,function(t,e){t.id=t.id||&quot;x-axis-&quot;+e}),r.each(e.yAxes,function(t,e){t.id=t.id||&quot;y-axis-&quot;+e}),a&amp;&amp;(a.id=a.id||&quot;scale&quot;)},buildScales:function(){var e=this,a=e.options,i=e.scales={},n=[];a.scales&amp;&amp;(n=n.concat((a.scales.xAxes||[]).map(function(t){return{options:t,dtype:&quot;category&quot;}}),(a.scales.yAxes||[]).map(function(t){return{options:t,dtype:&quot;linear&quot;}}))),a.scale&amp;&amp;n.push({options:a.scale,dtype:&quot;radialLinear&quot;,isDefault:!0}),r.each(n,function(a){var n=a.options,o=r
 .getValueOrDefault(n.type,a.dtype),l=t.scaleService.getScaleConstructor(o);if(l){var s=new l({id:n.id,options:n,ctx:e.chart.ctx,chart:e});i[s.id]=s,a.isDefault&amp;&amp;(e.scale=s)}}),t.scaleService.addScalesToLayout(this)},updateLayout:function(){t.layoutService.update(this,this.chart.width,this.chart.height)},buildOrUpdateControllers:function(){var e=this,a=[],i=[];if(r.each(e.data.datasets,function(n,o){var r=e.getDatasetMeta(o);r.type||(r.type=n.type||e.config.type),a.push(r.type),r.controller?r.controller.updateIndex(o):(r.controller=new t.controllers[r.type](e,o),i.push(r.controller))},e),a.length&gt;1)for(var n=1;n&lt;a.length;n++)if(a[n]!==a[n-1]){e.isCombo=!0;break}return i},resetElements:function(){var t=this;r.each(t.data.datasets,function(e,a){t.getDatasetMeta(a).controller.reset()},t)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(e,a){var i=this;t.plugins.notify(&quot;beforeUpdate&quot;,[i]),i.tooltip._data=i.data;var n=i.buil
 dOrUpdateControllers();r.each(i.data.datasets,function(t,e){i.getDatasetMeta(e).controller.buildOrUpdateElements()},i),t.layoutService.update(i,i.chart.width,i.chart.height),t.plugins.notify(&quot;afterScaleUpdate&quot;,[i]),r.each(n,function(t){t.reset()}),i.updateDatasets(),t.plugins.notify(&quot;afterUpdate&quot;,[i]),i._bufferedRender?i._bufferedRequest={lazy:a,duration:e}:i.render(e,a)},updateDatasets:function(){var e,a,i=this;if(t.plugins.notify(&quot;beforeDatasetsUpdate&quot;,[i])){for(e=0,a=i.data.datasets.length;a&gt;e;++e)i.getDatasetMeta(e).controller.update();t.plugins.notify(&quot;afterDatasetsUpdate&quot;,[i])}},render:function(e,a){var i=this;t.plugins.notify(&quot;beforeRender&quot;,[i]);var n=i.options.animation;if(n&amp;&amp;(&quot;undefined&quot;!=typeof e&amp;&amp;0!==e||&quot;undefined&quot;==typeof e&amp;&amp;0!==n.duration)){var o=new t.Animation;o.numSteps=(e||n.duration)/16.66,o.easing=n.easing,o.render=function(t,e){var a=r.easingEffects[e.easing],
 i=e.currentStep/e.numSteps,n=a(i);t.draw(n,i,e.currentStep)},o.onAnimationProgress=n.onProgress,o.onAnimationComplete=n.onComplete,t.animationService.addAnimation(i,o,e,a)}else i.draw(),n&amp;&amp;n.onComplete&amp;&amp;n.onComplete.call&amp;&amp;n.onComplete.call(i);return i},draw:function(e){var a=this,i=e||1;a.clear(),t.plugins.notify(&quot;beforeDraw&quot;,[a,i]),r.each(a.boxes,function(t){t.draw(a.chartArea)},a),a.scale&amp;&amp;a.scale.draw(),t.plugins.notify(&quot;beforeDatasetsDraw&quot;,[a,i]),r.each(a.data.datasets,function(t,i){a.isDatasetVisible(i)&amp;&amp;a.getDatasetMeta(i).controller.draw(e)},a,!0),t.plugins.notify(&quot;afterDatasetsDraw&quot;,[a,i]),a.tooltip.transition(i).draw(),t.plugins.notify(&quot;afterDraw&quot;,[a,i])},getElementAtEvent:function(e){return t.Interaction.modes.single(this,e)},getElementsAtEvent:function(e){return t.Interaction.modes.label(this,e,{intersect:!0})},getElementsAtXAxis:function(e){return t.Interaction.modes[&quot;x-axis&quot
 ;](this,e,{intersect:!0})},getElementsAtEventForMode:function(e,a,i){var n=t.Interaction.modes[a];return&quot;function&quot;==typeof n?n(this,e,i):[]},getDatasetAtEvent:function(e){return t.Interaction.modes.dataset(this,e)},getDatasetMeta:function(t){var e=this,a=e.data.datasets[t];a._meta||(a._meta={});
+var i=a._meta[e.id];return i||(i=a._meta[e.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,a=this.data.datasets.length;a&gt;e;++e)this.isDatasetVisible(e)&amp;&amp;t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return&quot;boolean&quot;==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroy:function(){var e,a,n,o=this,l=o.chart.canvas;for(o.stop(),a=0,n=o.data.datasets.length;n&gt;a;++a)e=o.getDatasetMeta(a),e.controller&amp;&amp;(e.controller.destroy(),e.controller=null);l&amp;&amp;(r.unbindEvents(o,o.events),r.removeResizeListener(l.parentNode),r.clear(o.chart),i(l),o.chart.canvas=null,o.chart.ctx=null),t.plugins.notify(&quot;destroy&quot;,[o]),delete t.instances[o.id]},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)},initToolTip
 :function(){var e=this;e.tooltip=new t.Tooltip({_chart:e.chart,_chartInstance:e,_data:e.data,_options:e.options.tooltips},e),e.tooltip.initialize()},bindEvents:function(){var t=this;r.bindEvents(t,t.options.events,function(e){t.eventHandler(e)})},updateHoverStyle:function(t,e,a){var i,n,o,r=a?&quot;setHoverStyle&quot;:&quot;removeHoverStyle&quot;;for(n=0,o=t.length;o&gt;n;++n)i=t[n],i&amp;&amp;this.getDatasetMeta(i._datasetIndex).controller[r](i)},eventHandler:function(t){var e=this,a=e.legend,i=e.tooltip,n=e.options.hover;e._bufferedRender=!0,e._bufferedRequest=null;var o=e.handleEvent(t);o|=a&amp;&amp;a.handleEvent(t),o|=i&amp;&amp;i.handleEvent(t);var r=e._bufferedRequest;return r?e.render(r.duration,r.lazy):o&amp;&amp;!e.animating&amp;&amp;(e.stop(),e.render(n.animationDuration,!0)),e._bufferedRender=!1,e._bufferedRequest=null,e},handleEvent:function(t){var e=this,a=e.options||{},i=a.hover,n=!1;return e.lastActive=e.lastActive||[],&quot;mouseout&quot;===t.type?e.active=[
 ]:e.active=e.getElementsAtEventForMode(t,i.mode,i),i.onHover&amp;&amp;i.onHover.call(e,e.active),(&quot;mouseup&quot;===t.type||&quot;click&quot;===t.type)&amp;&amp;a.onClick&amp;&amp;a.onClick.call(e,t,e.active),e.lastActive.length&amp;&amp;e.updateHoverStyle(e.lastActive,i.mode,!1),e.active.length&amp;&amp;i.mode&amp;&amp;e.updateHoverStyle(e.active,i.mode,!0),n=!r.arrayEquals(e.active,e.lastActive),e.lastActive=e.active,n}})}},{}],24:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){function e(t,e){return t._chartjs?void t._chartjs.listeners.push(e):(Object.defineProperty(t,&quot;_chartjs&quot;,{configurable:!0,enumerable:!1,value:{listeners:[e]}}),void n.forEach(function(e){var a=&quot;onData&quot;+e.charAt(0).toUpperCase()+e.slice(1),n=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value:function(){var e=Array.prototype.slice.call(arguments),o=n.apply(this,e);return i.each(t._chartjs.listeners,function(t){&quot;function&quot;==typeof t[a]&amp;
 &amp;t[a].apply(t,e)}),o}})}))}function a(t,e){var a=t._chartjs;if(a){var i=a.listeners,o=i.indexOf(e);-1!==o&amp;&amp;i.splice(o,1),i.length&gt;0||(n.forEach(function(e){delete t[e]}),delete t._chartjs)}}var i=t.helpers,n=[&quot;push&quot;,&quot;pop&quot;,&quot;shift&quot;,&quot;splice&quot;,&quot;unshift&quot;];t.DatasetController=function(t,e){this.initialize(t,e)},i.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){var a=this;a.chart=t,a.index=e,a.linkScales(),a.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),a=t.getDataset();null===e.xAxisID&amp;&amp;(e.xAxisID=a.xAxisID||t.chart.options.scales.xAxes[0].id),null===e.yAxisID&amp;&amp;(e.yAxisID=a.yAxisID||t.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.char
 t.scales[t]},reset:function(){this.update(!0)},destroy:function(){this._data&amp;&amp;a(this._data,this)},createMetaDataset:function(){var t=this,e=t.datasetElementType;return e&amp;&amp;new e({_chart:t.chart.chart,_datasetIndex:t.index})},createMetaData:function(t){var e=this,a=e.dataElementType;return a&amp;&amp;new a({_chart:e.chart.chart,_datasetIndex:e.index,_index:t})},addElements:function(){var t,e,a=this,i=a.getMeta(),n=a.getDataset().data||[],o=i.data;for(t=0,e=n.length;e&gt;t;++t)o[t]=o[t]||a.createMetaData(t);i.dataset=i.dataset||a.createMetaDataset()},addElementAndReset:function(t){var e=this.createMetaData(t);this.getMeta().data.splice(t,0,e),this.updateElement(e,t,!0)},buildOrUpdateElements:function(){var t=this,i=t.getDataset(),n=i.data||(i.data=[]);t._data!==n&amp;&amp;(t._data&amp;&amp;a(t._data,t),e(n,t),t._data=n),t.resyncElements()},update:i.noop,draw:function(t){var e,a,i=t||1,n=this.getMeta().data;for(e=0,a=n.length;a&gt;e;++e)n[e].transition(i).draw()}
 ,removeHoverStyle:function(t,e){var a=this.chart.data.datasets[t._datasetIndex],n=t._index,o=t.custom||{},r=i.getValueAtIndexOrDefault,l=t._model;l.backgroundColor=o.backgroundColor?o.backgroundColor:r(a.backgroundColor,n,e.backgroundColor),l.borderColor=o.borderColor?o.borderColor:r(a.borderColor,n,e.borderColor),l.borderWidth=o.borderWidth?o.borderWidth:r(a.borderWidth,n,e.borderWidth)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],a=t._index,n=t.custom||{},o=i.getValueAtIndexOrDefault,r=i.getHoverColor,l=t._model;l.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:o(e.hoverBackgroundColor,a,r(l.backgroundColor)),l.borderColor=n.hoverBorderColor?n.hoverBorderColor:o(e.hoverBorderColor,a,r(l.borderColor)),l.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:o(e.hoverBorderWidth,a,l.borderWidth)},resyncElements:function(){var t=this,e=t.getMeta(),a=t.getDataset().data,i=e.data.length,n=a.length;i&gt;n?e.data.splice(n,i-n):n&gt;i&amp;&am
 p;t.insertElements(i,n-i)},insertElements:function(t,e){for(var a=0;e&gt;a;++a)this.addElementAndReset(t+a)},onDataPush:function(){this.insertElements(this.getDataset().data.length-1,arguments.length)},onDataPop:function(){this.getMeta().data.pop()},onDataShift:function(){this.getMeta().data.shift()},onDataSplice:function(t,e){this.getMeta().data.splice(t,e),this.insertElements(t,arguments.length-2)},onDataUnshift:function(){this.insertElements(0,arguments.length)}}),t.DatasetController.extend=i.inherits}},{}],25:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers;t.elements={},t.Element=function(t){e.extend(this,t),this.initialize.apply(this,arguments)},e.extend(t.Element.prototype,{initialize:function(){this.hidden=!1},pivot:function(){var t=this;return t._view||(t._view=e.clone(t._model)),t._start=e.clone(t._view),t},transition:function(t){var a=this;return a._view||(a._view=e.clone(a._model)),1===t?(a._view=a._model,a._start=null,a):(a._start||a
 .pivot(),e.each(a._model,function(i,n){if(&quot;_&quot;===n[0]);else if(a._view.hasOwnProperty(n))if(i===a._view[n]);else if(&quot;string&quot;==typeof i)try{var o=e.color(a._model[n]).mix(e.color(a._start[n]),t);a._view[n]=o.rgbString()}catch(r){a._view[n]=i}else if(&quot;number&quot;==typeof i){var l=void 0!==a._start[n]&amp;&amp;isNaN(a._start[n])===!1?a._start[n]:0;a._view[n]=(a._model[n]-l)*t+l}else a._view[n]=i;else&quot;number&quot;!=typeof i||isNaN(a._view[n])?a._view[n]=i:a._view[n]=i*t},a),a)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return e.isNumber(this._model.x)&amp;&amp;e.isNumber(this._model.y)}}),t.Element.extend=e.inherits}},{}],26:[function(t,e,a){&quot;use strict&quot;;var i=t(3);e.exports=function(t){function e(t,e,a){var i;return&quot;string&quot;==typeof t?(i=parseInt(t,10),-1!==t.indexOf(&quot;%&quot;)&amp;&amp;(i=i/100*e.parentNode[a])):i=t,i}function a(t){return void 0!==t&amp;&amp;null!==t&amp;&amp;&qu
 ot;none&quot;!==t}function n(t,i,n){var o=document.defaultView,r=t.parentNode,l=o.getComputedStyle(t)[i],s=o.getComputedStyle(r)[i],d=a(l),u=a(s),c=Number.POSITIVE_INFINITY;return d||u?Math.min(d?e(l,t,n):c,u?e(s,r,n):c):&quot;none&quot;}var o=t.helpers={};o.each=function(t,e,a,i){var n,r;if(o.isArray(t))if(r=t.length,i)for(n=r-1;n&gt;=0;n--)e.call(a,t[n],n);else for(n=0;r&gt;n;n++)e.call(a,t[n],n);else if(&quot;object&quot;==typeof t){var l=Object.keys(t);for(r=l.length,n=0;r&gt;n;n++)e.call(a,t[l[n]],l[n])}},o.clone=function(t){var e={};return o.each(t,function(t,a){o.isArray(t)?e[a]=t.slice(0):&quot;object&quot;==typeof t&amp;&amp;null!==t?e[a]=o.clone(t):e[a]=t}),e},o.extend=function(t){for(var e=function(e,a){t[a]=e},a=1,i=arguments.length;i&gt;a;a++)o.each(arguments[a],e);return t},o.configMerge=function(e){var a=o.clone(e);return o.each(Array.prototype.slice.call(arguments,1),function(e){o.each(e,function(e,i){var n=a.hasOwnProperty(i),r=n?a[i]:{};&quot;scales&quot;==
 =i?a[i]=o.scaleMerge(r,e):&quot;scale&quot;===i?a[i]=o.configMerge(r,t.scaleService.getScaleDefaults(e.type),e):!n||&quot;object&quot;!=typeof r||o.isArray(r)||null===r||&quot;object&quot;!=typeof e||o.isArray(e)?a[i]=e:a[i]=o.configMerge(r,e)})}),a},o.scaleMerge=function(e,a){var i=o.clone(e);return o.each(a,function(e,a){&quot;xAxes&quot;===a||&quot;yAxes&quot;===a?i.hasOwnProperty(a)?o.each(e,function(e,n){var r=o.getValueOrDefault(e.type,&quot;xAxes&quot;===a?&quot;category&quot;:&quot;linear&quot;),l=t.scaleService.getScaleDefaults(r);n&gt;=i[a].length||!i[a][n].type?i[a].push(o.configMerge(l,e)):e.type&amp;&amp;e.type!==i[a][n].type?i[a][n]=o.configMerge(i[a][n],l,e):i[a][n]=o.configMerge(i[a][n],e)}):(i[a]=[],o.each(e,function(e){var n=o.getValueOrDefault(e.type,&quot;xAxes&quot;===a?&quot;category&quot;:&quot;linear&quot;);i[a].push(o.configMerge(t.scaleService.getScaleDefaults(n),e))})):i.hasOwnProperty(a)&amp;&amp;&quot;object&quot;==typeof i[a]&amp;&amp;null!==i[a
 ]&amp;&amp;&quot;object&quot;==typeof e?i[a]=o.configMerge(i[a],e):i[a]=e}),i},o.getValueAtIndexOrDefault=function(t,e,a){return void 0===t||null===t?a:o.isArray(t)?e&lt;t.length?t[e]:a:t},o.getValueOrDefault=function(t,e){return void 0===t?e:t},o.indexOf=Array.prototype.indexOf?function(t,e){return t.indexOf(e)}:function(t,e){for(var a=0,i=t.length;i&gt;a;++a)if(t[a]===e)return a;return-1},o.where=function(t,e){if(o.isArray(t)&amp;&amp;Array.prototype.filter)return t.filter(e);var a=[];return o.each(t,function(t){e(t)&amp;&amp;a.push(t)}),a},o.findIndex=Array.prototype.findIndex?function(t,e,a){return t.findIndex(e,a)}:function(t,e,a){a=void 0===a?t:a;for(var i=0,n=t.length;n&gt;i;++i)if(e.call(a,t[i],i,t))return i;return-1},o.findNextWhere=function(t,e,a){(void 0===a||null===a)&amp;&amp;(a=-1);for(var i=a+1;i&lt;t.length;i++){var n=t[i];if(e(n))return n}},o.findPreviousWhere=function(t,e,a){(void 0===a||null===a)&amp;&amp;(a=t.length);for(var i=a-1;i&gt;=0;i--){var n=t[i];
 if(e(n))return n}},o.inherits=function(t){var e=this,a=t&amp;&amp;t.hasOwnProperty(&quot;constructor&quot;)?t.constructor:function(){return e.apply(this,arguments)},i=function(){this.constructor=a};return i.prototype=e.prototype,a.prototype=new i,a.extend=o.inherits,t&amp;&amp;o.extend(a.prototype,t),a.__super__=e.prototype,a},o.noop=function(){},o.uid=function(){var t=0;return function(){return t++}}(),o.isNumber=function(t){return!isNaN(parseFloat(t))&amp;&amp;isFinite(t)},o.almostEquals=function(t,e,a){return Math.abs(t-e)&lt;a},o.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},o.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},o.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return t=+t,0===t||isNaN(t)?t:t&gt;0?1:-1},o.log10=Math.log10?function(t){return Math.log10(t)}:function(t){return Math.log(t)/Math.LN10},o.toRadians=function(t){return t*(M
 ath.PI/180)},o.toDegrees=function(t){return t*(180/Math.PI)},o.getAngleFromPoint=function(t,e){var a=e.x-t.x,i=e.y-t.y,n=Math.sqrt(a*a+i*i),o=Math.atan2(i,a);return o&lt;-.5*Math.PI&amp;&amp;(o+=2*Math.PI),{angle:o,distance:n}},o.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},o.aliasPixel=function(t){return t%2===0?0:.5},o.splineCurve=function(t,e,a,i){var n=t.skip?e:t,o=e,r=a.skip?e:a,l=Math.sqrt(Math.pow(o.x-n.x,2)+Math.pow(o.y-n.y,2)),s=Math.sqrt(Math.pow(r.x-o.x,2)+Math.pow(r.y-o.y,2)),d=l/(l+s),u=s/(l+s);d=isNaN(d)?0:d,u=isNaN(u)?0:u;var c=i*d,h=i*u;return{previous:{x:o.x-c*(r.x-n.x),y:o.y-c*(r.y-n.y)},next:{x:o.x+h*(r.x-n.x),y:o.y+h*(r.y-n.y)}}},o.EPSILON=Number.EPSILON||1e-14,o.splineCurveMonotone=function(t){var e,a,i,n,r=(t||[]).map(function(t){return{model:t._model,deltaK:0,mK:0}}),l=r.length;for(e=0;l&gt;e;++e)i=r[e],i.model.skip||(a=e&gt;0?r[e-1]:null,n=l-1&gt;e?r[e+1]:null,n&amp;&amp;!n.model.skip&amp;&amp;(i.delta
 K=(n.model.y-i.model.y)/(n.model.x-i.model.x)),!a||a.model.skip?i.mK=i.deltaK:!n||n.model.skip?i.mK=a.deltaK:this.sign(a.deltaK)!==this.sign(i.deltaK)?i.mK=0:i.mK=(a.deltaK+i.deltaK)/2);var s,d,u,c;for(e=0;l-1&gt;e;++e)i=r[e],n=r[e+1],i.model.skip||n.model.skip||(o.almostEquals(i.deltaK,0,this.EPSILON)?i.mK=n.mK=0:(s=i.mK/i.deltaK,d=n.mK/i.deltaK,c=Math.pow(s,2)+Math.pow(d,2),9&gt;=c||(u=3/Math.sqrt(c),i.mK=s*u*i.deltaK,n.mK=d*u*i.deltaK)));var h;for(e=0;l&gt;e;++e)i=r[e],i.model.skip||(a=e&gt;0?r[e-1]:null,n=l-1&gt;e?r[e+1]:null,a&amp;&amp;!a.model.skip&amp;&amp;(h=(i.model.x-a.model.x)/3,i.model.controlPointPreviousX=i.model.x-h,i.model.controlPointPreviousY=i.model.y-h*i.mK),n&amp;&amp;!n.model.skip&amp;&amp;(h=(n.model.x-i.model.x)/3,i.model.controlPointNextX=i.model.x+h,i.model.controlPointNextY=i.model.y+h*i.mK))},o.nextItem=function(t,e,a){return a?e&gt;=t.length-1?t[0]:t[e+1]:e&gt;=t.length-1?t[t.length-1]:t[e+1]},o.previousItem=function(t,e,a){return a?0&gt;=e?t[t.l
 ength-1]:t[e-1]:0&gt;=e?t[0]:t[e-1]},o.niceNum=function(t,e){var a,i=Math.floor(o.log10(t)),n=t/Math.pow(10,i);return a=e?1.5&gt;n?1:3&gt;n?2:7&gt;n?5:10:1&gt;=n?1:2&gt;=n?2:5&gt;=n?5:10,a*Math.pow(10,i)};var r=o.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)&lt;1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){return(t/=.5)&lt;1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)&lt;1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){return(t/=.5)&lt;1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return-1*Math.cos(t/1*(Math.PI/2
 ))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)&lt;1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t&gt;=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)&lt;1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,a=0,i=1;return 0===t?0:1===(t/=1)?1:(a||(a=.3),i&lt;Math.abs(1)?(i=1,e=a/4):e=a/(2*Math.PI)*Math.asin(1/i),-(i*Math.pow(2,10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/a)))},easeOutElastic:function(t){var e=1.70158,a=0,i=1;return 0===t?0:1===(t/=1)?1:(a||(a=.3),i&lt;Math.abs(1)?(i=1,e=a/4):e=a/(2*Math.PI)*Math.asin(1/i),i*Math.pow(2,-10*t)*Math.si
 n((1*t-e)*(2*Math.PI)/a)+1)},easeInOutElastic:function(t){var e=1.70158,a=0,i=1;return 0===t?0:2===(t/=.5)?1:(a||(a=1*(.3*1.5)),i&lt;Math.abs(1)?(i=1,e=a/4):e=a/(2*Math.PI)*Math.asin(1/i),1&gt;t?-.5*(i*Math.pow(2,10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/a)):i*Math.pow(2,-10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/a)*.5+1)},easeInBack:function(t){var e=1.70158;return 1*(t/=1)*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return 1*((t=t/1-1)*t*((e+1)*t+e)+1)},easeInOutBack:function(t){var e=1.70158;return(t/=.5)&lt;1?.5*(t*t*(((e*=1.525)+1)*t-e)):.5*((t-=2)*t*(((e*=1.525)+1)*t+e)+2)},easeInBounce:function(t){return 1-r.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)&lt;1/2.75?1*(7.5625*t*t):2/2.75&gt;t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75&gt;t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5&gt;t?.5*r.easeInBounce(2*t):.5*r.easeOutBounce(2*t-1)+.5}};o.requestAnimFrame=function(){return window.requestA
 nimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),o.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),o.getRelativePosition=function(t,e){var a,i,n=t.originalEvent||t,r=t.currentTarget||t.srcElement,l=r.getBoundingClientRect(),s=n.touches;s&amp;&amp;s.length&gt;0?(a=s[0].clientX,i=s[0].clientY):(a=n.clientX,i=n.clientY);var d=parseFloat(o.getStyle(r,&quot;padding-left&quot;)),u=parseFloat(o.getStyle(r,&quot;padding-top&quot;)),c=parseFloat(o.getStyle(r,&quot;padding-right&quot;)),h=parseFloat(o.getStyle(r,&quot;padding-bottom&quot;)),f=l.right-l.left-d-c,g=l.bottom-l.top-u-h;return a=Math.round((a-l.left-d)/f*r.width/e.currentDevicePixelRa
 tio),i=Math.round((i-l.top-u)/g*r.height/e.currentDevicePixelRatio),{x:a,y:i}},o.addEvent=function(t,e,a){t.addEventListener?t.addEventListener(e,a):t.attachEvent?t.attachEvent(&quot;on&quot;+e,a):t[&quot;on&quot;+e]=a},o.removeEvent=function(t,e,a){t.removeEventListener?t.removeEventListener(e,a,!1):t.detachEvent?t.detachEvent(&quot;on&quot;+e,a):t[&quot;on&quot;+e]=o.noop},o.bindEvents=function(t,e,a){var i=t.events=t.events||{};o.each(e,function(e){i[e]=function(){a.apply(t,arguments)},o.addEvent(t.chart.canvas,e,i[e])})},o.unbindEvents=function(t,e){var a=t.chart.canvas;o.each(e,function(t,e){o.removeEvent(a,e,t)})},o.getConstraintWidth=function(t){return n(t,&quot;max-width&quot;,&quot;clientWidth&quot;)},o.getConstraintHeight=function(t){return n(t,&quot;max-height&quot;,&quot;clientHeight&quot;)},o.getMaximumWidth=function(t){var e=t.parentNode,a=parseInt(o.getStyle(e,&quot;padding-left&quot;),10),i=parseInt(o.getStyle(e,&quot;padding-right&quot;),10),n=e.clientWidth-
 a-i,r=o.getConstraintWidth(t);return isNaN(r)?n:Math.min(n,r)},o.getMaximumHeight=function(t){var e=t.parentNode,a=parseInt(o.getStyle(e,&quot;padding-top&quot;),10),i=parseInt(o.getStyle(e,&quot;padding-bottom&quot;),10),n=e.clientHeight-a-i,r=o.getConstraintHeight(t);return isNaN(r)?n:Math.min(n,r)},o.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},o.retinaScale=function(t){var e=t.currentDevicePixelRatio=window.devicePixelRatio||1;if(1!==e){var a=t.canvas,i=t.height,n=t.width;a.height=i*e,a.width=n*e,t.ctx.scale(e,e),a.style.height=i+&quot;px&quot;,a.style.width=n+&quot;px&quot;}},o.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},o.fontString=function(t,e,a){return e+&quot; &quot;+t+&quot;px &quot;+a},o.longestText=function(t,e,a,i){i=i||{};var n=i.data=i.data||{},r=i.garbageCollect=i.garbageCollect||[];i.font!==e&amp;&amp;(n=i.data={},r=i.garbageCollect=[],i.font=e),t.font=e;var l=
 0;o.each(a,function(e){void 0!==e&amp;&amp;null!==e&amp;&amp;o.isArray(e)!==!0?l=o.measureText(t,n,r,l,e):o.isArray(e)&amp;&amp;o.each(e,function(e){void 0===e||null===e||o.isArray(e)||(l=o.measureText(t,n,r,l,e))})});var s=r.length/2;if(s&gt;a.length){for(var d=0;s&gt;d;d++)delete n[r[d]];r.splice(0,s)}return l},o.measureText=function(t,e,a,i,n){var o=e[n];return o||(o=e[n]=t.measureText(n).width,a.push(n)),o&gt;i&amp;&amp;(i=o),i},o.numberOfLabelLines=function(t){var e=1;return o.each(t,function(t){o.isArray(t)&amp;&amp;t.length&gt;e&amp;&amp;(e=t.length)}),e},o.drawRoundedRectangle=function(t,e,a,i,n,o){t.beginPath(),t.moveTo(e+o,a),t.lineTo(e+i-o,a),t.quadraticCurveTo(e+i,a,e+i,a+o),t.lineTo(e+i,a+n-o),t.quadraticCurveTo(e+i,a+n,e+i-o,a+n),t.lineTo(e+o,a+n),t.quadraticCurveTo(e,a+n,e,a+n-o),t.lineTo(e,a+o),t.quadraticCurveTo(e,a,e+o,a),t.closePath()},o.color=function(e){return i?i(e instanceof CanvasGradient?t.defaults.global.defaultColor:e):(console.error(&quot;Color.js
  not found!&quot;),e)},o.addResizeListener=function(t,e){var a=document.createElement(&quot;iframe&quot;);a.className=&quot;chartjs-hidden-iframe&quot;,a.style.cssText=&quot;display:block;overflow:hidden;border:0;margin:0;top:0;left:0;bottom:0;right:0;height:100%;width:100%;position:absolute;pointer-events:none;z-index:-1;&quot;,a.tabIndex=-1;var i=t._chartjs={resizer:a,ticking:!1},n=function(){i.ticking||(i.ticking=!0,o.requestAnimFrame.call(window,function(){return i.resizer?(i.ticking=!1,e()):void 0}))};o.addEvent(a,&quot;load&quot;,function(){o.addEvent(a.contentWindow||a,&quot;resize&quot;,n),n()}),t.insertBefore(a,t.firstChild)},o.removeResizeListener=function(t){if(t&amp;&amp;t._chartjs){var e=t._chartjs.resizer;e&amp;&amp;(e.parentNode.removeChild(e),t._chartjs.resizer=null),delete t._chartjs}},o.isArray=Array.isArray?function(t){return Array.isArray(t)}:function(t){return&quot;[object Array]&quot;===Object.prototype.toString.call(t)},o.arrayEquals=function(t,e){var 
 a,i,n,r;if(!t||!e||t.length!==e.length)return!1;for(a=0,i=t.length;i&gt;a;++a)if(n=t[a],r=e[a],n instanceof Array&amp;&amp;r instanceof Array){if(!o.arrayEquals(n,r))return!1}else if(n!==r)return!1;return!0},o.callCallback=function(t,e,a){t&amp;&amp;&quot;function&quot;==typeof t.call&amp;&amp;t.apply(a,e)},o.getHoverColor=function(t){return t instanceof CanvasPattern?t:o.color(t).saturate(.5).darken(.1).rgbString()}}},{3:3}],27:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){function e(t,e){var a,i,n,o,r,l=t.data.datasets;for(i=0,o=l.length;o&gt;i;++i)if(t.isDatasetVisible(i))for(a=t.getDatasetMeta(i),n=0,r=a.data.length;r&gt;n;++n){var s=a.data[n];s._view.skip||e(s)}}function a(t,a){var i=[];return e(t,function(t){t.inRange(a.x,a.y)&amp;&amp;i.push(t)}),i}function i(t,a,i,n){var r=Number.POSITIVE_INFINITY,l=[];return n||(n=o.distanceBetweenPoints),e(t,function(t){if(!i||t.inRange(a.x,a.y)){var e=t.getCenterPoint(),o=n(a,e);r&gt;o?(l=[t],r=o):o===r&amp;&amp;l.
 push(t)}}),l}function n(t,e,n){var r=o.getRelativePosition(e,t.chart),l=function(t,e){return Math.abs(t.x-e.x)},s=n.intersect?a(t,r):i(t,r,!1,l),d=[];return s.length?(t.data.datasets.forEach(function(e,a){if(t.isDatasetVisible(a)){var i=t.getDatasetMeta(a),n=i.data[s[0]._index];n&amp;&amp;!n._view.skip&amp;&amp;d.push(n)}}),d):[]}var o=t.helpers;t.Interaction={modes:{single:function(t,a){var i=o.getRelativePosition(a,t.chart),n=[];return e(t,function(t){return t.inRange(i.x,i.y)?(n.push(t),n):void 0}),n.slice(0,1)},label:n,index:n,dataset:function(t,e,n){var r=o.getRelativePosition(e,t.chart),l=n.intersect?a(t,r):i(t,r,!1);return l.length&gt;0&amp;&amp;(l=t.getDatasetMeta(l[0]._datasetIndex).data),l},&quot;x-axis&quot;:function(t,e){return n(t,e,!0)},point:function(t,e){var i=o.getRelativePosition(e,t.chart);return a(t,i)},nearest:function(t,e,a){var n=o.getRelativePosition(e,t.chart),r=i(t,n,a.intersect);return r.length&gt;1&amp;&amp;r.sort(function(t,e){var a=t.getArea(),i
 =e.getArea(),n=a-i;return 0===n&amp;&amp;(n=t._datasetIndex-e._datasetIndex),n}),r.slice(0,1)},x:function(t,a,i){var n=o.getRelativePosition(a,t.chart),r=[],l=!1;return e(t,function(t){t.inXRange(n.x)&amp;&amp;r.push(t),t.inRange(n.x,n.y)&amp;&amp;(l=!0)}),i.intersect&amp;&amp;!l&amp;&amp;(r=[]),r},y:function(t,a,i){var n=o.getRelativePosition(a,t.chart),r=[],l=!1;return e(t,function(t){t.inYRange(n.y)&amp;&amp;r.push(t),t.inRange(n.x,n.y)&amp;&amp;(l=!0)}),i.intersect&amp;&amp;!l&amp;&amp;(r=[]),r}}}}},{}],28:[function(t,e,a){&quot;use strict&quot;;e.exports=function(){var t=function(e,a){return this.controller=new t.Controller(e,a,this),this.controller};return t.defaults={global:{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:[&quot;mousemove&quot;,&quot;mouseout&quot;,&quot;click&quot;,&quot;touchstart&quot;,&quot;touchmove&quot;],hover:{onHover:null,mode:&quot;nearest&quot;,intersect:!0,animationDuration:400},onClick:null,defaultColor:&quot;rgb
 a(0,0,0,0.1)&quot;,defaultFontColor:&quot;#666&quot;,defaultFontFamily:&quot;'Helvetica Neue', 'Helvetica', 'Arial', sans-serif&quot;,defaultFontSize:12,defaultFontStyle:&quot;normal&quot;,showLines:!0,elements:{},legendCallback:function(t){var e=[];e.push('&lt;ul class=&quot;'+t.id+'-legend&quot;&gt;');for(var a=0;a&lt;t.data.datasets.length;a++)e.push('&lt;li&gt;&lt;span style=&quot;background-color:'+t.data.datasets[a].backgroundColor+'&quot;&gt;&lt;/span&gt;'),t.data.datasets[a].label&amp;&amp;e.push(t.data.datasets[a].label),e.push(&quot;&lt;/li&gt;&quot;);return e.push(&quot;&lt;/ul&gt;&quot;),e.join(&quot;&quot;)}}},t.Chart=t,t}},{}],29:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers;t.layoutService={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),t.boxes.push(e)},removeBox:function(t,e){t.boxes&amp;&amp;t.boxes.splice(t.boxes.indexOf(e),1)},update:function(t,a,i){function n(t){var e,a=t.isHorizontal();a?(e=t.update(t.options.fullW
 idth?x:C,M),D-=e.height):(e=t.update(w,S),C-=e.width),I.push({horizontal:a,minSize:e,box:t})}function o(t){var a=e.findNextWhere(I,function(e){return e.box===t});if(a)if(t.isHorizontal()){var i={left:A,right:T,top:0,bottom:0};t.update(t.options.fullWidth?x:C,y/2,i)}else t.update(a.minSize.width,D)}function r(t){var a=e.findNextWhere(I,function(e){return e.box===t}),i={left:0,right:0,top:P,bottom:F};a&amp;&amp;t.update(a.minSize.width,D,i)}function l(t){t.isHorizontal()?(t.left=t.options.fullWidth?u:A,t.right=t.options.fullWidth?a-c:A+C,t.top=L,t.bottom=L+t.height,L=t.bottom):(t.left=V,t.right=V+t.width,t.top=P,t.bottom=P+D,V=t.right)}if(t){var s=t.options.layout,d=s?s.padding:null,u=0,c=0,h=0,f=0;isNaN(d)?(u=d.left||0,c=d.right||0,h=d.top||0,f=d.bottom||0):(u=d,c=d,h=d,f=d);var g=e.where(t.boxes,function(t){return&quot;left&quot;===t.options.position}),p=e.where(t.boxes,function(t){return&quot;right&quot;===t.options.position}),m=e.where(t.boxes,function(t){return&quot;top&q
 uot;===t.options.position}),b=e.where(t.boxes,function(t){return&quot;bottom&quot;===t.options.position}),v=e.where(t.boxes,function(t){return&quot;chartArea&quot;===t.options.position});m.sort(function(t,e){return(e.options.fullWidth?1:0)-(t.options.fullWidth?1:0)}),b.sort(function(t,e){return(t.options.fullWidth?1:0)-(e.options.fullWidth?1:0)});var x=a-u-c,y=i-h-f,k=x/2,S=y/2,w=(a-k)/(g.length+p.length),M=(i-S)/(m.length+b.length),C=x,D=y,I=[];e.each(g.concat(p,m,b),n);var A=u,T=c,P=h,F=f;e.each(g.concat(p),o),e.each(g,function(t){A+=t.width}),e.each(p,function(t){T+=t.width}),e.each(m.concat(b),o),e.each(m,function(t){P+=t.height}),e.each(b,function(t){F+=t.height}),e.each(g.concat(p),r),A=u,T=c,P=h,F=f,e.each(g,function(t){A+=t.width}),e.each(p,function(t){T+=t.width}),e.each(m,function(t){P+=t.height}),e.each(b,function(t){F+=t.height});var _=i-P-F,R=a-A-T;(R!==C||_!==D)&amp;&amp;(e.each(g,function(t){t.height=_}),e.each(p,function(t){t.height=_}),e.each(m,function(t){t
 .options.fullWidth||(t.width=R)}),e.each(b,function(t){t.options.fullWidth||(t.width=R)}),D=_,C=R);var V=u,L=h;e.each(g.concat(m),l),V+=C,L+=D,e.each(p,l),e.each(b,l),t.chartArea={left:A,top:P,right:A+C,bottom:P+D},e.each(v,function(e){e.left=t.chartArea.left,e.top=t.chartArea.top,e.right=t.chartArea.right,e.bottom=t.chartArea.bottom,e.update(C,D)})}}}}},{}],30:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){function e(t,e){return t.usePointStyle?e*Math.SQRT2:t.boxWidth}var a=t.helpers,i=a.noop;t.defaults.global.legend={display:!0,position:&quot;top&quot;,fullWidth:!0,reverse:!1,onClick:function(t,e){var a=e.datasetIndex,i=this.chart,n=i.getDatasetMeta(a);n.hidden=null===n.hidden?!i.data.datasets[a].hidden:null,i.update()},onHover:null,labels:{boxWidth:40,padding:10,generateLabels:function(t){var e=t.data;return a.isArray(e.datasets)?e.datasets.map(function(e,i){return{text:e.label,fillStyle:a.isArray(e.backgroundColor)?e.backgroundColor[0]:e.backgroundColor,hi
 dden:!t.isDatasetVisible(i),lineCap:e.borderCapStyle,lineDash:e.borderDash,lineDashOffset:e.borderDashOffset,lineJoin:e.borderJoinStyle,lineWidth:e.borderWidth,strokeStyle:e.borderColor,pointStyle:e.pointStyle,datasetIndex:i}},this):[]}}},t.Legend=t.Element.extend({initialize:function(t){a.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:i,update:function(t,e,a){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=a,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:i,beforeSetDimensions:i,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:i,beforeBuildLabels:i,buildLabels:functio
 n(){var t=this;t.legendItems=t.options.labels.generateLabels.call(t,t.chart),t.options.reverse&amp;&amp;t.legendItems.reverse()},afterBuildLabels:i,beforeFit:i,fit:function(){var i=this,n=i.options,o=n.labels,r=n.display,l=i.ctx,s=t.defaults.global,d=a.getValueOrDefault,u=d(o.fontSize,s.defaultFontSize),c=d(o.fontStyle,s.defaultFontStyle),h=d(o.fontFamily,s.defaultFontFamily),f=a.fontString(u,c,h),g=i.legendHitBoxes=[],p=i.minSize,m=i.isHorizontal();if(m?(p.width=i.maxWidth,p.height=r?10:0):(p.width=r?10:0,p.height=i.maxHeight),r)if(l.font=f,m){var b=i.lineWidths=[0],v=i.legendItems.length?u+o.padding:0;l.textAlign=&quot;left&quot;,l.textBaseline=&quot;top&quot;,a.each(i.legendItems,function(t,a){var n=e(o,u),r=n+u/2+l.measureText(t.text).width;b[b.length-1]+r+o.padding&gt;=i.width&amp;&amp;(v+=u+o.padding,b[b.length]=i.left),g[a]={left:0,top:0,width:r,height:u},b[b.length-1]+=r+o.padding}),p.height+=v}else{var x=o.padding,y=i.columnWidths=[],k=o.padding,S=0,w=0,M=u+x;a.each
 (i.legendItems,function(t,a){var i=e(o,u),n=i+u/2+l.measureText(t.text).width;w+M&gt;p.height&amp;&amp;(k+=S+o.padding,y.push(S),S=0,w=0),S=Math.max(S,n),w+=M,g[a]={left:0,top:0,width:n,height:u}}),k+=S,y.push(S),p.width+=k}i.width=p.width,i.height=p.height},afterFit:i,isHorizontal:function(){return&quot;top&quot;===this.options.position||&quot;bottom&quot;===this.options.position},draw:function(){var i=this,n=i.options,o=n.labels,r=t.defaults.global,l=r.elements.line,s=i.width,d=i.lineWidths;if(n.display){var u,c=i.ctx,h=a.getValueOrDefault,f=h(o.fontColor,r.defaultFontColor),g=h(o.fontSize,r.defaultFontSize),p=h(o.fontStyle,r.defaultFontStyle),m=h(o.fontFamily,r.defaultFontFamily),b=a.fontString(g,p,m);c.textAlign=&quot;left&quot;,c.textBaseline=&quot;top&quot;,c.lineWidth=.5,c.strokeStyle=f,c.fillStyle=f,c.font=b;var v=e(o,g),x=i.legendHitBoxes,y=function(e,a,i){if(!(isNaN(v)||0&gt;=v)){c.save(),c.fillStyle=h(i.fillStyle,r.defaultColor),c.lineCap=h(i.lineCap,l.borderCapSt
 yle),c.lineDashOffset=h(i.lineDashOffset,l.borderDashOffset),c.lineJoin=h(i.lineJoin,l.borderJoinStyle),c.lineWidth=h(i.lineWidth,l.borderWidth),c.strokeStyle=h(i.strokeStyle,r.defaultColor);var o=0===h(i.lineWidth,l.borderWidth);if(c.setLineDash&amp;&amp;c.setLineDash(h(i.lineDash,l.borderDash)),n.labels&amp;&amp;n.labels.usePointStyle){var s=g*Math.SQRT2/2,d=s/Math.SQRT2,u=e+d,f=a+d;t.canvasHelpers.drawPoint(c,i.pointStyle,s,u,f)}else o||c.strokeRect(e,a,v,g),c.fillRect(e,a,v,g);c.restore()}},k=function(t,e,a,i){c.fillText(a.text,v+g/2+t,e),a.hidden&amp;&amp;(c.beginPath(),c.lineWidth=2,c.moveTo(v+g/2+t,e+g/2),c.lineTo(v+g/2+t+i,e+g/2),c.stroke())},S=i.isHorizontal();u=S?{x:i.left+(s-d[0])/2,y:i.top+o.padding,line:0}:{x:i.left+o.padding,y:i.top+o.padding,line:0};var w=g+o.padding;a.each(i.legendItems,function(t,e){var a=c.measureText(t.text).width,n=v+g/2+a,r=u.x,l=u.y;S?r+n&gt;=s&amp;&amp;(l=u.y+=w,u.line++,r=u.x=i.left+(s-d[u.line])/2):l+w&gt;i.bottom&amp;&amp;(r=u.x=r+i
 .columnWidths[u.line]+o.padding,l=u.y=i.top,u.line++),y(r,l,t),x[e].left=r,x[e].top=l,k(r,l,t,a),S?u.x+=n+o.padding:u.y+=w})}},handleEvent:function(t){var e=this,i=e.options,n=&quot;mouseup&quot;===t.type?&quot;click&quot;:t.type,o=!1;if(&quot;mousemove&quot;===n){if(!i.onHover)return}else{if(&quot;click&quot;!==n)return;if(!i.onClick)return}var r=a.getRelativePosition(t,e.chart.chart),l=r.x,s=r.y;if(l&gt;=e.left&amp;&amp;l&lt;=e.right&amp;&amp;s&gt;=e.top&amp;&amp;s&lt;=e.bottom)for(var d=e.legendHitBoxes,u=0;u&lt;d.length;++u){var c=d[u];if(l&gt;=c.left&amp;&amp;l&lt;=c.left+c.width&amp;&amp;s&gt;=c.top&amp;&amp;s&lt;=c.top+c.height){if(&quot;click&quot;===n){i.onClick.call(e,t,e.legendItems[u]),o=!0;break}if(&quot;mousemove&quot;===n){i.onHover.call(e,t,e.legendItems[u]),o=!0;break}}}return o}}),t.plugins.register({beforeInit:function(e){var a=e.options,i=a.legend;i&amp;&amp;(e.legend=new t.Legend({ctx:e.chart.ctx,options:i,chart:e}),t.layoutService.addBox(e,e.legend))}})
 }},{}],31:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers.noop;t.plugins={_plugins:[],register:function(t){var e=this._plugins;[].concat(t).forEach(function(t){-1===e.indexOf(t)&amp;&amp;e.push(t)})},unregister:function(t){var e=this._plugins;[].concat(t).forEach(function(t){var a=e.indexOf(t);-1!==a&amp;&amp;e.splice(a,1)})},clear:function(){this._plugins=[]},count:function(){return this._plugins.length},getAll:function(){return this._plugins},notify:function(t,e){var a,i,n=this._plugins,o=n.length;
+for(a=0;o&gt;a;++a)if(i=n[a],&quot;function&quot;==typeof i[t]&amp;&amp;i[t].apply(i,e||[])===!1)return!1;return!0}},t.PluginBase=t.Element.extend({beforeInit:e,afterInit:e,beforeUpdate:e,afterUpdate:e,beforeDraw:e,afterDraw:e,destroy:e}),t.pluginService=t.plugins}},{}],32:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers;t.defaults.scale={display:!0,position:&quot;left&quot;,gridLines:{display:!0,color:&quot;rgba(0, 0, 0, 0.1)&quot;,lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:&quot;rgba(0,0,0,0.25)&quot;,offsetGridLines:!1,borderDash:[],borderDashOffset:0},scaleLabel:{labelString:&quot;&quot;,display:!1},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:10,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:t.Ticks.formatters.values}},t.Scale=t.Element.extend({beforeUpdate:function(){e.callCallback(this.options.beforeUpdate,[this])},update:func
 tion(t,a,i){var n=this;return n.beforeUpdate(),n.maxWidth=t,n.maxHeight=a,n.margins=e.extend({left:0,right:0,top:0,bottom:0},i),n.beforeSetDimensions(),n.setDimensions(),n.afterSetDimensions(),n.beforeDataLimits(),n.determineDataLimits(),n.afterDataLimits(),n.beforeBuildTicks(),n.buildTicks(),n.afterBuildTicks(),n.beforeTickToLabelConversion(),n.convertTicksToLabels(),n.afterTickToLabelConversion(),n.beforeCalculateTickRotation(),n.calculateTickRotation(),n.afterCalculateTickRotation(),n.beforeFit(),n.fit(),n.afterFit(),n.afterUpdate(),n.minSize},afterUpdate:function(){e.callCallback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){e.callCallback(this.options.beforeSetDimensions,[this])},setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0},afterSetDimensions:function(){e.callCallback(this.options.aft
 erSetDimensions,[this])},beforeDataLimits:function(){e.callCallback(this.options.beforeDataLimits,[this])},determineDataLimits:e.noop,afterDataLimits:function(){e.callCallback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){e.callCallback(this.options.beforeBuildTicks,[this])},buildTicks:e.noop,afterBuildTicks:function(){e.callCallback(this.options.afterBuildTicks,[this])},beforeTickToLabelConversion:function(){e.callCallback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){var t=this,e=t.options.ticks;t.ticks=t.ticks.map(e.userCallback||e.callback)},afterTickToLabelConversion:function(){e.callCallback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){e.callCallback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var a=this,i=a.ctx,n=t.defaults.global,o=a.options.ticks,r=e.getValueOrDefault(o.fontSize,n.defaultFontSize),l=e.getValueOrDefault(o.fontStyle
 ,n.defaultFontStyle),s=e.getValueOrDefault(o.fontFamily,n.defaultFontFamily),d=e.fontString(r,l,s);i.font=d;var u,c=i.measureText(a.ticks[0]).width,h=i.measureText(a.ticks[a.ticks.length-1]).width;if(a.labelRotation=o.minRotation||0,a.paddingRight=0,a.paddingLeft=0,a.options.display&amp;&amp;a.isHorizontal()){a.paddingRight=h/2+3,a.paddingLeft=c/2+3,a.longestTextCache||(a.longestTextCache={});for(var f,g,p=e.longestText(i,d,a.ticks,a.longestTextCache),m=p,b=a.getPixelForTick(1)-a.getPixelForTick(0)-6;m&gt;b&amp;&amp;a.labelRotation&lt;o.maxRotation;){if(f=Math.cos(e.toRadians(a.labelRotation)),g=Math.sin(e.toRadians(a.labelRotation)),u=f*c,u+r/2&gt;a.yLabelWidth&amp;&amp;(a.paddingLeft=u+r/2),a.paddingRight=r/2,g*p&gt;a.maxHeight){a.labelRotation--;break}a.labelRotation++,m=f*p}}a.margins&amp;&amp;(a.paddingLeft=Math.max(a.paddingLeft-a.margins.left,0),a.paddingRight=Math.max(a.paddingRight-a.margins.right,0))},afterCalculateTickRotation:function(){e.callCallback(this.option
 s.afterCalculateTickRotation,[this])},beforeFit:function(){e.callCallback(this.options.beforeFit,[this])},fit:function(){var a=this,i=a.minSize={width:0,height:0},n=a.options,o=t.defaults.global,r=n.ticks,l=n.scaleLabel,s=n.gridLines,d=n.display,u=a.isHorizontal(),c=e.getValueOrDefault(r.fontSize,o.defaultFontSize),h=e.getValueOrDefault(r.fontStyle,o.defaultFontStyle),f=e.getValueOrDefault(r.fontFamily,o.defaultFontFamily),g=e.fontString(c,h,f),p=e.getValueOrDefault(l.fontSize,o.defaultFontSize),m=n.gridLines.tickMarkLength;if(u?i.width=a.isFullWidth()?a.maxWidth-a.margins.left-a.margins.right:a.maxWidth:i.width=d&amp;&amp;s.drawTicks?m:0,u?i.height=d&amp;&amp;s.drawTicks?m:0:i.height=a.maxHeight,l.display&amp;&amp;d&amp;&amp;(u?i.height+=1.5*p:i.width+=1.5*p),r.display&amp;&amp;d){a.longestTextCache||(a.longestTextCache={});var b=e.longestText(a.ctx,g,a.ticks,a.longestTextCache),v=e.numberOfLabelLines(a.ticks),x=.5*c;if(u){a.longestLabelWidth=b;var y=Math.sin(e.toRadians(a.
 labelRotation))*a.longestLabelWidth+c*v+x*v;i.height=Math.min(a.maxHeight,i.height+y),a.ctx.font=g;var k=a.ctx.measureText(a.ticks[0]).width,S=a.ctx.measureText(a.ticks[a.ticks.length-1]).width,w=Math.cos(e.toRadians(a.labelRotation)),M=Math.sin(e.toRadians(a.labelRotation));a.paddingLeft=0!==a.labelRotation?w*k+3:k/2+3,a.paddingRight=0!==a.labelRotation?M*(c/2)+3:S/2+3}else{var C=a.maxWidth-i.width,D=r.mirror;D?b=0:b+=a.options.ticks.padding,C&gt;b?i.width+=b:i.width=a.maxWidth,a.paddingTop=c/2,a.paddingBottom=c/2}}a.margins&amp;&amp;(a.paddingLeft=Math.max(a.paddingLeft-a.margins.left,0),a.paddingTop=Math.max(a.paddingTop-a.margins.top,0),a.paddingRight=Math.max(a.paddingRight-a.margins.right,0),a.paddingBottom=Math.max(a.paddingBottom-a.margins.bottom,0)),a.width=i.width,a.height=i.height},afterFit:function(){e.callCallback(this.options.afterFit,[this])},isHorizontal:function(){return&quot;top&quot;===this.options.position||&quot;bottom&quot;===this.options.position},isFu
 llWidth:function(){return this.options.fullWidth},getRightValue:function(t){return null===t||&quot;undefined&quot;==typeof t?NaN:&quot;number&quot;!=typeof t||isFinite(t)?&quot;object&quot;==typeof t?t instanceof Date||t.isValid?t:this.getRightValue(this.isHorizontal()?t.x:t.y):t:NaN},getLabelForIndex:e.noop,getPixelForValue:e.noop,getValueForPixel:e.noop,getPixelForTick:function(t,e){var a=this;if(a.isHorizontal()){var i=a.width-(a.paddingLeft+a.paddingRight),n=i/Math.max(a.ticks.length-(a.options.gridLines.offsetGridLines?0:1),1),o=n*t+a.paddingLeft;e&amp;&amp;(o+=n/2);var r=a.left+Math.round(o);return r+=a.isFullWidth()?a.margins.left:0}var l=a.height-(a.paddingTop+a.paddingBottom);return a.top+t*(l/(a.ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var a=e.width-(e.paddingLeft+e.paddingRight),i=a*t+e.paddingLeft,n=e.left+Math.round(i);return n+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){var t=this,e=
 t.min,a=t.max;return t.getPixelForValue(t.beginAtZero?0:0&gt;e&amp;&amp;0&gt;a?a:e&gt;0&amp;&amp;a&gt;0?e:0)},draw:function(a){var i=this,n=i.options;if(n.display){var o,r,l=i.ctx,s=t.defaults.global,d=n.ticks,u=n.gridLines,c=n.scaleLabel,h=0!==i.labelRotation,f=d.autoSkip,g=i.isHorizontal();d.maxTicksLimit&amp;&amp;(r=d.maxTicksLimit);var p=e.getValueOrDefault(d.fontColor,s.defaultFontColor),m=e.getValueOrDefault(d.fontSize,s.defaultFontSize),b=e.getValueOrDefault(d.fontStyle,s.defaultFontStyle),v=e.getValueOrDefault(d.fontFamily,s.defaultFontFamily),x=e.fontString(m,b,v),y=u.tickMarkLength,k=e.getValueOrDefault(u.borderDash,s.borderDash),S=e.getValueOrDefault(u.borderDashOffset,s.borderDashOffset),w=e.getValueOrDefault(c.fontColor,s.defaultFontColor),M=e.getValueOrDefault(c.fontSize,s.defaultFontSize),C=e.getValueOrDefault(c.fontStyle,s.defaultFontStyle),D=e.getValueOrDefault(c.fontFamily,s.defaultFontFamily),I=e.fontString(M,C,D),A=e.toRadians(i.labelRotation),T=Math.cos(
 A),P=i.longestLabelWidth*T;l.fillStyle=p;var F=[];if(g){if(o=!1,h&amp;&amp;(P/=2),(P+d.autoSkipPadding)*i.ticks.length&gt;i.width-(i.paddingLeft+i.paddingRight)&amp;&amp;(o=1+Math.floor((P+d.autoSkipPadding)*i.ticks.length/(i.width-(i.paddingLeft+i.paddingRight)))),r&amp;&amp;i.ticks.length&gt;r)for(;!o||i.ticks.length/(o||1)&gt;r;)o||(o=1),o+=1;f||(o=!1)}var _=&quot;right&quot;===n.position?i.left:i.right-y,R=&quot;right&quot;===n.position?i.left+y:i.right,V=&quot;bottom&quot;===n.position?i.top:i.bottom-y,L=&quot;bottom&quot;===n.position?i.top+y:i.bottom;if(e.each(i.ticks,function(t,r){if(void 0!==t&amp;&amp;null!==t){var l=i.ticks.length===r+1,s=o&gt;1&amp;&amp;r%o&gt;0||r%o===0&amp;&amp;r+o&gt;=i.ticks.length;if((!s||l)&amp;&amp;void 0!==t&amp;&amp;null!==t){var c,f;r===(&quot;undefined&quot;!=typeof i.zeroLineIndex?i.zeroLineIndex:0)?(c=u.zeroLineWidth,f=u.zeroLineColor):(c=e.getValueAtIndexOrDefault(u.lineWidth,r),f=e.getValueAtIndexOrDefault(u.color,r));var p,m,b,v,x
 ,w,M,C,D,I,T=&quot;middle&quot;,P=&quot;middle&quot;;if(g){h||(P=&quot;top&quot;===n.position?&quot;bottom&quot;:&quot;top&quot;),T=h?&quot;right&quot;:&quot;center&quot;;var O=i.getPixelForTick(r)+e.aliasPixel(c);D=i.getPixelForTick(r,u.offsetGridLines)+d.labelOffset,I=h?i.top+12:&quot;top&quot;===n.position?i.bottom-y:i.top+y,p=b=x=M=O,m=V,v=L,w=a.top,C=a.bottom}else{&quot;left&quot;===n.position?d.mirror?(D=i.right+d.padding,T=&quot;left&quot;):(D=i.right-d.padding,T=&quot;right&quot;):d.mirror?(D=i.left-d.padding,T=&quot;right&quot;):(D=i.left+d.padding,T=&quot;left&quot;);var B=i.getPixelForTick(r);B+=e.aliasPixel(c),I=i.getPixelForTick(r,u.offsetGridLines),p=_,b=R,x=a.left,M=a.right,m=v=w=C=B}F.push({tx1:p,ty1:m,tx2:b,ty2:v,x1:x,y1:w,x2:M,y2:C,labelX:D,labelY:I,glWidth:c,glColor:f,glBorderDash:k,glBorderDashOffset:S,rotation:-1*A,label:t,textBaseline:P,textAlign:T})}}}),e.each(F,function(t){if(u.display&amp;&amp;(l.save(),l.lineWidth=t.glWidth,l.strokeStyle=t.glColor,l
 .setLineDash&amp;&amp;(l.setLineDash(t.glBorderDash),l.lineDashOffset=t.glBorderDashOffset),l.beginPath(),u.drawTicks&amp;&amp;(l.moveTo(t.tx1,t.ty1),l.lineTo(t.tx2,t.ty2)),u.drawOnChartArea&amp;&amp;(l.moveTo(t.x1,t.y1),l.lineTo(t.x2,t.y2)),l.stroke(),l.restore()),d.display){l.save(),l.translate(t.labelX,t.labelY),l.rotate(t.rotation),l.font=x,l.textBaseline=t.textBaseline,l.textAlign=t.textAlign;var a=t.label;if(e.isArray(a))for(var i=0,n=-(a.length-1)*m*.75;i&lt;a.length;++i)l.fillText(&quot;&quot;+a[i],0,n),n+=1.5*m;else l.fillText(a,0,0);l.restore()}}),c.display){var O,B,W=0;if(g)O=i.left+(i.right-i.left)/2,B=&quot;bottom&quot;===n.position?i.bottom-M/2:i.top+M/2;else{var z=&quot;left&quot;===n.position;O=z?i.left+M/2:i.right-M/2,B=i.top+(i.bottom-i.top)/2,W=z?-.5*Math.PI:.5*Math.PI}l.save(),l.translate(O,B),l.rotate(W),l.textAlign=&quot;center&quot;,l.textBaseline=&quot;middle&quot;,l.fillStyle=w,l.font=I,l.fillText(c.labelString,0,0),l.restore()}if(u.drawBorder){l.lin
 eWidth=e.getValueAtIndexOrDefault(u.lineWidth,0),l.strokeStyle=e.getValueAtIndexOrDefault(u.color,0);var N=i.left,E=i.right,H=i.top,U=i.bottom,j=e.aliasPixel(l.lineWidth);g?(H=U=&quot;top&quot;===n.position?i.bottom:i.top,H+=j,U+=j):(N=E=&quot;left&quot;===n.position?i.right:i.left,N+=j,E+=j),l.beginPath(),l.moveTo(N,H),l.lineTo(E,U),l.stroke()}}}})}},{}],33:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers;t.scaleService={constructors:{},defaults:{},registerScaleType:function(t,a,i){this.constructors[t]=a,this.defaults[t]=e.clone(i)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(a){return this.defaults.hasOwnProperty(a)?e.scaleMerge(t.defaults.scale,this.defaults[a]):{}},updateScaleDefaults:function(t,a){var i=this.defaults;i.hasOwnProperty(t)&amp;&amp;(i[t]=e.extend(i[t],a))},addScalesToLayout:function(a){e.each(a.scales,function(e){t.layoutService.addBox(a,e)})}
 }}},{}],34:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers;t.Ticks={generators:{linear:function(t,a){var i,n=[];if(t.stepSize&amp;&amp;t.stepSize&gt;0)i=t.stepSize;else{var o=e.niceNum(a.max-a.min,!1);i=e.niceNum(o/(t.maxTicks-1),!0)}var r=Math.floor(a.min/i)*i,l=Math.ceil(a.max/i)*i;if(t.min&amp;&amp;t.max&amp;&amp;t.stepSize){var s=(t.max-t.min)%t.stepSize===0;s&amp;&amp;(r=t.min,l=t.max)}var d=(l-r)/i;d=e.almostEquals(d,Math.round(d),i/1e3)?Math.round(d):Math.ceil(d),n.push(void 0!==t.min?t.min:r);for(var u=1;d&gt;u;++u)n.push(r+u*i);return n.push(void 0!==t.max?t.max:l),n},logarithmic:function(t,a){for(var i=[],n=e.getValueOrDefault,o=n(t.min,Math.pow(10,Math.floor(e.log10(a.min))));o&lt;a.max;){i.push(o);var r,l;0===o?(r=Math.floor(e.log10(a.minNotZero)),l=Math.round(a.minNotZero/Math.pow(10,r))):(r=Math.floor(e.log10(o)),l=Math.floor(o/Math.pow(10,r))+1),10===l&amp;&amp;(l=1,++r),o=l*Math.pow(10,r)}var s=n(t.max,o);return i.push(s),i}},for
 matters:{values:function(t){return e.isArray(t)?t:&quot;&quot;+t},linear:function(t,a,i){var n=i.length&gt;3?i[2]-i[1]:i[1]-i[0];Math.abs(n)&gt;1&amp;&amp;t!==Math.floor(t)&amp;&amp;(n=t-Math.floor(t));var o=e.log10(Math.abs(n)),r=&quot;&quot;;if(0!==t){var l=-1*Math.floor(o);l=Math.max(Math.min(l,20),0),r=t.toFixed(l)}else r=&quot;0&quot;;return r},logarithmic:function(t,a,i){var n=t/Math.pow(10,Math.floor(e.log10(t)));return 0===t?&quot;0&quot;:1===n||2===n||5===n||0===a||a===i.length-1?t.toExponential():&quot;&quot;}}}}},{}],35:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers;t.defaults.global.title={display:!1,position:&quot;top&quot;,fullWidth:!0,fontStyle:&quot;bold&quot;,padding:10,text:&quot;&quot;};var a=e.noop;t.Title=t.Element.extend({initialize:function(a){var i=this;e.extend(i,a),i.options=e.configMerge(t.defaults.global.title,a.options),i.legendHitBoxes=[]},beforeUpdate:function(){var a=this.chart.options;a&amp;&amp;a.title&amp;&amp
 ;(this.options=e.configMerge(t.defaults.global.title,a.title))},update:function(t,e,a){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=a,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:a,beforeSetDimensions:a,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:a,beforeBuildLabels:a,buildLabels:a,afterBuildLabels:a,beforeFit:a,fit:function(){var a=this,i=e.getValueOrDefault,n=a.options,o=t.defaults.global,r=n.display,l=i(n.fontSize,o.defaultFontSize),s=a.minSize;a.isHorizontal()?(s.width=a.maxWidth,s.height=r?l+2*n.padding:0):(s.width=r?l+2*n.padding:0,s.height=a.maxHeight),a.width=s.width,a.height
 =s.height},afterFit:a,isHorizontal:function(){var t=this.options.position;return&quot;top&quot;===t||&quot;bottom&quot;===t},draw:function(){var a=this,i=a.ctx,n=e.getValueOrDefault,o=a.options,r=t.defaults.global;if(o.display){var l,s,d,u=n(o.fontSize,r.defaultFontSize),c=n(o.fontStyle,r.defaultFontStyle),h=n(o.fontFamily,r.defaultFontFamily),f=e.fontString(u,c,h),g=0,p=a.top,m=a.left,b=a.bottom,v=a.right;i.fillStyle=n(o.fontColor,r.defaultFontColor),i.font=f,a.isHorizontal()?(l=m+(v-m)/2,s=p+(b-p)/2,d=v-m):(l=&quot;left&quot;===o.position?m+u/2:v-u/2,s=p+(b-p)/2,d=b-p,g=Math.PI*(&quot;left&quot;===o.position?-.5:.5)),i.save(),i.translate(l,s),i.rotate(g),i.textAlign=&quot;center&quot;,i.textBaseline=&quot;middle&quot;,i.fillText(o.text,0,0,d),i.restore()}}}),t.plugins.register({beforeInit:function(e){var a=e.options,i=a.title;i&amp;&amp;(e.titleBlock=new t.Title({ctx:e.chart.ctx,options:i,chart:e}),t.layoutService.addBox(e,e.titleBlock))}})}},{}],36:[function(t,e,a){&quot;
 use strict&quot;;e.exports=function(t){function e(t,e){var a=s.color(t);return a.alpha(e*a.alpha()).rgbaString()}function a(t,e){return e&amp;&amp;(s.isArray(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function i(t){var e=t._xScale,a=t._yScale||t._scale,i=t._index,n=t._datasetIndex;return{xLabel:e?e.getLabelForIndex(i,n):&quot;&quot;,yLabel:a?a.getLabelForIndex(i,n):&quot;&quot;,index:i,datasetIndex:n,x:t._model.x,y:t._model.y}}function n(e){var a=t.defaults.global,i=s.getValueOrDefault;return{xPadding:e.xPadding,yPadding:e.yPadding,xAlign:e.xAlign,yAlign:e.yAlign,bodyFontColor:e.bodyFontColor,_bodyFontFamily:i(e.bodyFontFamily,a.defaultFontFamily),_bodyFontStyle:i(e.bodyFontStyle,a.defaultFontStyle),_bodyAlign:e.bodyAlign,bodyFontSize:i(e.bodyFontSize,a.defaultFontSize),bodySpacing:e.bodySpacing,titleFontColor:e.titleFontColor,_titleFontFamily:i(e.titleFontFamily,a.defaultFontFamily),_titleFontStyle:i(e.titleFontStyle,a.defaultFontStyle),titleFontSize:i(e.titleFontSize,
 a.defaultFontSize),_titleAlign:e.titleAlign,titleSpacing:e.titleSpacing,titleMarginBottom:e.titleMarginBottom,footerFontColor:e.footerFontColor,_footerFontFamily:i(e.footerFontFamily,a.defaultFontFamily),_footerFontStyle:i(e.footerFontStyle,a.defaultFontStyle),footerFontSize:i(e.footerFontSize,a.defaultFontSize),_footerAlign:e.footerAlign,footerSpacing:e.footerSpacing,footerMarginTop:e.footerMarginTop,caretSize:e.caretSize,cornerRadius:e.cornerRadius,backgroundColor:e.backgroundColor,opacity:0,legendColorBackground:e.multiKeyBackground,displayColors:e.displayColors}}function o(t,e){var a=t._chart.ctx,i=2*e.yPadding,n=0,o=e.body,r=o.reduce(function(t,e){return t+e.before.length+e.lines.length+e.after.length},0);r+=e.beforeBody.length+e.afterBody.length;var l=e.title.length,d=e.footer.length,u=e.titleFontSize,c=e.bodyFontSize,h=e.footerFontSize;i+=l*u,i+=l?(l-1)*e.titleSpacing:0,i+=l?e.titleMarginBottom:0,i+=r*c,i+=r?(r-1)*e.bodySpacing:0,i+=d?e.footerMarginTop:0,i+=d*h,i+=d?(
 d-1)*e.footerSpacing:0;var f=0,g=function(t){n=Math.max(n,a.measureText(t).width+f)};return a.font=s.fontString(u,e._titleFontStyle,e._titleFontFamily),s.each(e.title,g),a.font=s.fontString(c,e._bodyFontStyle,e._bodyFontFamily),s.each(e.beforeBody.concat(e.afterBody),g),f=e.displayColors?c+2:0,s.each(o,function(t){s.each(t.before,g),s.each(t.lines,g),s.each(t.after,g)}),f=0,a.font=s.fontString(h,e._footerFontStyle,e._footerFontFamily),s.each(e.footer,g),n+=2*e.xPadding,{width:n,height:i}}function r(t,e){var a=t._model,i=t._chart,n=t._chartInstance.chartArea,o=&quot;center&quot;,r=&quot;center&quot;;a.y&lt;e.height?r=&quot;top&quot;:a.y&gt;i.height-e.height&amp;&amp;(r=&quot;bottom&quot;);var l,s,d,u,c,h=(n.left+n.right)/2,f=(n.top+n.bottom)/2;&quot;center&quot;===r?(l=function(t){return h&gt;=t},s=function(t){return t&gt;h}):(l=function(t){return t&lt;=e.width/2},s=function(t){return t&gt;=i.width-e.width/2}),d=function(t){return t+e.width&gt;i.width},u=function(t){return t-
 e.width&lt;0},c=function(t){return f&gt;=t?&quot;top&quot;:&quot;bottom&quot;},l(a.x)?(o=&quot;left&quot;,d(a.x)&amp;&amp;(o=&quot;center&quot;,r=c(a.y))):s(a.x)&amp;&amp;(o=&quot;right&quot;,u(a.x)&amp;&amp;(o=&quot;center&quot;,r=c(a.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:o,yAlign:g.yAlign?g.yAlign:r}}function l(t,e,a){var i=t.x,n=t.y,o=t.caretSize,r=t.caretPadding,l=t.cornerRadius,s=a.xAlign,d=a.yAlign,u=o+r,c=l+r;return&quot;right&quot;===s?i-=e.width:&quot;center&quot;===s&amp;&amp;(i-=e.width/2),&quot;top&quot;===d?n+=u:n-=&quot;bottom&quot;===d?e.height+u:e.height/2,&quot;center&quot;===d?&quot;left&quot;===s?i+=u:&quot;right&quot;===s&amp;&amp;(i-=u):&quot;left&quot;===s?i-=c:&quot;right&quot;===s&amp;&amp;(i+=c),{x:i,y:n}}var s=t.helpers;t.defaults.global.tooltips={enabled:!0,custom:null,mode:&quot;nearest&quot;,position:&quot;average&quot;,intersect:!0,backgroundColor:&quot;rgba(0,0,0,0.8)&quot;,titleFontStyle:&quot;bold&quot;,titleSpacing:2,titleMar
 ginBottom:6,titleFontColor:&quot;#fff&quot;,titleAlign:&quot;left&quot;,bodySpacing:2,bodyFontColor:&quot;#fff&quot;,bodyAlign:&quot;left&quot;,footerFontStyle:&quot;bold&quot;,footerSpacing:2,footerMarginTop:6,footerFontColor:&quot;#fff&quot;,footerAlign:&quot;left&quot;,yPadding:6,xPadding:6,caretSize:5,cornerRadius:6,multiKeyBackground:&quot;#fff&quot;,displayColors:!0,callbacks:{beforeTitle:s.noop,title:function(t,e){var a=&quot;&quot;,i=e.labels,n=i?i.length:0;if(t.length&gt;0){var o=t[0];o.xLabel?a=o.xLabel:n&gt;0&amp;&amp;o.index&lt;n&amp;&amp;(a=i[o.index])}return a},afterTitle:s.noop,beforeBody:s.noop,beforeLabel:s.noop,label:function(t,e){var a=e.datasets[t.datasetIndex].label||&quot;&quot;;return a+&quot;: &quot;+t.yLabel},labelColor:function(t,e){var a=e.getDatasetMeta(t.datasetIndex),i=a.data[t.index],n=i._view;return{borderColor:n.borderColor,backgroundColor:n.backgroundColor}},afterLabel:s.noop,afterBody:s.noop,beforeFooter:s.noop,footer:s.noop,afterFooter:s.n
 oop}},t.Tooltip=t.Element.extend({initialize:function(){this._model=n(this._options)},getTitle:function(){var t=this,e=t._options,i=e.callbacks,n=i.beforeTitle.apply(t,arguments),o=i.title.apply(t,arguments),r=i.afterTitle.apply(t,arguments),l=[];return l=a(l,n),l=a(l,o),l=a(l,r)},getBeforeBody:function(){var t=this._options.callbacks.beforeBody.apply(this,arguments);return s.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,e){var i=this,n=i._options.callbacks,o=[];return s.each(t,function(t){var r={before:[],lines:[],after:[]};a(r.before,n.beforeLabel.call(i,t,e)),a(r.lines,n.label.call(i,t,e)),a(r.after,n.afterLabel.call(i,t,e)),o.push(r)}),o},getAfterBody:function(){var t=this._options.callbacks.afterBody.apply(this,arguments);return s.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this,e=t._options.callbacks,i=e.beforeFooter.apply(t,arguments),n=e.footer.apply(t,arguments),o=e.afterFooter.apply(t,arguments),r=[];return r=a(r,i),r=a(r,n),r=a(r,o)},update:fun
 ction(e){var a,d,u=this,c=u._options,h=u._model,f=u._model=n(c),g=u._active,p=u._data,m=u._chartInstance,b={xAlign:h.xAlign,yAlign:h.yAlign},v={x:h.x,y:h.y},x={width:h.width,height:h.height},y={x:h.caretX,y:h.caretY};if(g.length){f.opacity=1;var k=[];y=t.Tooltip.positioners[c.position](g,u._eventPosition);var S=[];for(a=0,d=g.length;d&gt;a;++a)S.push(i(g[a]));c.filter&amp;&amp;(S=S.filter(function(t){return c.filter(t,p)})),c.itemSort&amp;&amp;(S=S.sort(function(t,e){return c.itemSort(t,e,p)})),s.each(S,function(t){k.push(c.callbacks.labelColor.call(u,t,m))}),f.title=u.getTitle(S,p),f.beforeBody=u.getBeforeBody(S,p),f.body=u.getBody(S,p),f.afterBody=u.getAfterBody(S,p),f.footer=u.getFooter(S,p),f.x=Math.round(y.x),f.y=Math.round(y.y),f.caretPadding=s.getValueOrDefault(y.padding,2),f.labelColors=k,f.dataPoints=S,x=o(this,f),b=r(this,x),v=l(f,x,b)}else f.opacity=0;return f.xAlign=b.xAlign,f.yAlign=b.yAlign,f.x=v.x,f.y=v.y,f.width=x.width,f.height=x.height,f.caretX=y.x,f.caretY
 =y.y,u._model=f,e&amp;&amp;c.custom&amp;&amp;c.custom.call(u,f),u},drawCaret:function(t,a,i){var n,o,r,l,s,d,u=this._view,c=this._chart.ctx,h=u.caretSize,f=u.cornerRadius,g=u.xAlign,p=u.yAlign,m=t.x,b=t.y,v=a.width,x=a.height;&quot;center&quot;===p?(&quot;left&quot;===g?(n=m,o=n-h,r=n):(n=m+v,o=n+h,r=n),s=b+x/2,l=s-h,d=s+h):(&quot;left&quot;===g?(n=m+f,o=n+h,r=o+h):&quot;right&quot;===g?(n=m+v-f,o=n-h,r=o-h):(o=m+v/2,n=o-h,r=o+h),&quot;top&quot;===p?(l=b,s=l-h,d=l):(l=b+x,s=l+h,d=l)),c.fillStyle=e(u.backgroundColor,i),c.beginPath(),c.moveTo(n,l),c.lineTo(o,s),c.lineTo(r,d),c.closePath(),c.fill()},drawTitle:function(t,a,i,n){var o=a.title;if(o.length){i.textAlign=a._titleAlign,i.textBaseline=&quot;top&quot;;var r=a.titleFontSize,l=a.titleSpacing;i.fillStyle=e(a.titleFontColor,n),i.font=s.fontString(r,a._titleFontStyle,a._titleFontFamily);var d,u;for(d=0,u=o.length;u&gt;d;++d)i.fillText(o[d],t.x,t.y),t.y+=r+l,d+1===o.length&amp;&amp;(t.y+=a.titleMarginBottom-l)}},drawBody:func
 tion(t,a,i,n){var o=a.bodyFontSize,r=a.bodySpacing,l=a.body;i.textAlign=a._bodyAlign,i.textBaseline=&quot;top&quot;;var d=e(a.bodyFontColor,n);i.fillStyle=d,i.font=s.fontString(o,a._bodyFontStyle,a._bodyFontFamily);var u=0,c=function(e){i.fillText(e,t.x+u,t.y),t.y+=o+r};s.each(a.beforeBody,c);var h=a.displayColors;u=h?o+2:0,s.each(l,function(r,l){s.each(r.before,c),s.each(r.lines,function(r){h&amp;&amp;(i.fillStyle=e(a.legendColorBackground,n),i.fillRect(t.x,t.y,o,o),i.strokeStyle=e(a.labelColors[l].borderColor,n),i.strokeRect(t.x,t.y,o,o),i.fillStyle=e(a.labelColors[l].backgroundColor,n),i.fillRect(t.x+1,t.y+1,o-2,o-2),i.fillStyle=d),c(r)}),s.each(r.after,c)}),u=0,s.each(a.afterBody,c),t.y-=r},drawFooter:function(t,a,i,n){var o=a.footer;o.length&amp;&amp;(t.y+=a.footerMarginTop,i.textAlign=a._footerAlign,i.textBaseline=&quot;top&quot;,i.fillStyle=e(a.footerFontColor,n),i.font=s.fontString(a.footerFontSize,a._footerFontStyle,a._footerFontFamily),s.each(o,function(e){i.fillTe
 xt(e,t.x,t.y),t.y+=a.footerFontSize+a.footerSpacing}))},drawBackground:function(t,a,i,n,o){i.fillStyle=e(a.backgroundColor,o),s.drawRoundedRectangle(i,t.x,t.y,n.width,n.height,a.cornerRadius),i.fill()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var a={width:e.width,height:e.height},i={x:e.x,y:e.y},n=Math.abs(e.opacity&lt;.001)?0:e.opacity;this._options.enabled&amp;&amp;(this.drawBackground(i,e,t,a,n),this.drawCaret(i,a,n),i.x+=e.xPadding,i.y+=e.yPadding,this.drawTitle(i,e,t,n),this.drawBody(i,e,t,n),this.drawFooter(i,e,t,n))}},handleEvent:function(t){var e=this,a=e._options,i=!1;if(e._lastActive=e._lastActive||[],&quot;mouseout&quot;===t.type?e._active=[]:e._active=e._chartInstance.getElementsAtEventForMode(t,a.mode,a),i=!s.arrayEquals(e._active,e._lastActive),e._lastActive=e._active,a.enabled||a.custom){e._eventPosition=s.getRelativePosition(t,e._chart);var n=e._model;e.update(!0),e.pivot(),i|=n.x!==e._model.x||n.y!==e._model.y}return i}}),t.Toolti
 p.positioners={average:function(t){if(!t.length)return!1;var e,a,i=0,n=0,o=0;for(e=0,a=t.length;a&gt;e;++e){var r=t[e];if(r&amp;&amp;r.hasValue()){var l=r.tooltipPosition();i+=l.x,n+=l.y,++o}}return{x:Math.round(i/o),y:Math.round(n/o)}},nearest:function(t,e){var a,i,n,o=e.x,r=e.y,l=Number.POSITIVE_INFINITY;for(i=0,n=t.length;n&gt;i;++i){var d=t[i];if(d&amp;&amp;d.hasValue()){var u=d.getCenterPoint(),c=s.distanceBetweenPoints(e,u);l&gt;c&amp;&amp;(l=c,a=d)}}if(a){var h=a.tooltipPosition();o=h.x,r=h.y}return{x:o,y:r}}}}},{}],37:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers,a=t.defaults.global;a.elements.arc={backgroundColor:a.defaultColor,borderColor:&quot;#fff&quot;,borderWidth:2},t.elements.Arc=t.Element.extend({inLabelRange:function(t){var e=this._view;return e?Math.pow(t-e.x,2)&lt;Math.pow(e.radius+e.hoverRadius,2):!1},inRange:function(t,a){var i=this._view;if(i){for(var n=e.getAngleFromPoint(i,{x:t,y:a}),o=n.angle,r=n.distance,l=i.startAngl
 e,s=i.endAngle;l&gt;s;)s+=2*Math.PI;for(;o&gt;s;)o-=2*Math.PI;for(;l&gt;o;)o+=2*Math.PI;var d=o&gt;=l&amp;&amp;s&gt;=o,u=r&gt;=i.innerRadius&amp;&amp;r&lt;=i.outerRadius;return d&amp;&amp;u}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,a=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*a,y:t.y+Math.sin(e)*a}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,a=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*a,y:t.y+Math.sin(e)*a}},draw:function(){var t=this._chart.ctx,e=this._view,a=e.startAngle,i=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,a,i),t.arc(e.x,e.y,e.innerRadius,i,a,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin=&quot;bevel&quot;,e.bor
 derWidth&amp;&amp;t.stroke()}})}},{}],38:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers,a=t.defaults.global;t.defaults.global.elements.line={tension:.4,backgroundColor:a.defaultColor,borderWidth:3,borderColor:a.defaultColor,borderCapStyle:&quot;butt&quot;,borderDash:[],borderDashOffset:0,borderJoinStyle:&quot;miter&quot;,capBezierPoints:!0,fill:!0},t.elements.Line=t.Element.extend({draw:function(){function t(t,e){var a=e._view;e._view.steppedLine===!0?(s.lineTo(a.x,t._view.y),s.lineTo(a.x,a.y)):0===e._view.tension?s.lineTo(a.x,a.y):s.bezierCurveTo(t._view.controlPointNextX,t._view.controlPointNextY,a.controlPointPreviousX,a.controlPointPreviousY,a.x,a.y)}var i=this,n=i._view,o=n.spanGaps,r=n.scaleZero,l=i._loop;l||(&quot;top&quot;===n.fill?r=n.scaleTop:&quot;bottom&quot;===n.fill&amp;&amp;(r=n.scaleBottom));var s=i._chart.ctx;s.save();var d=i._children.slice(),u=-1;l&amp;&amp;d.length&amp;&amp;d.push(d[0]);var c,h,f,g;if(d.length&amp;&amp;n.fil
 l){for(s.beginPath(),c=0;c&lt;d.length;++c)h=d[c],f=e.previousItem(d,c),g=h._view,0===c?(l?s.moveTo(r.x,r.y):s.moveTo(g.x,r),g.skip||(u=c,s.lineTo(g.x,g.y))):(f=-1===u?f:d[u],g.skip?o||u!==c-1||(l?s.lineTo(r.x,r.y):s.lineTo(f._view.x,r)):(u!==c-1?o&amp;&amp;-1!==u?t(f,h):l?s.lineTo(g.x,g.y):(s.lineTo(g.x,r),s.lineTo(g.x,g.y)):t(f,h),u=c));l||-1===u||s.lineTo(d[u]._view.x,r),s.fillStyle=n.backgroundColor||a.defaultColor,s.closePath(),s.fill()}var p=a.elements.line;for(s.lineCap=n.borderCapStyle||p.borderCapStyle,s.setLineDash&amp;&amp;s.setLineDash(n.borderDash||p.borderDash),s.lineDashOffset=n.borderDashOffset||p.borderDashOffset,s.lineJoin=n.borderJoinStyle||p.borderJoinStyle,s.lineWidth=n.borderWidth||p.borderWidth,s.strokeStyle=n.borderColor||a.defaultColor,s.beginPath(),u=-1,c=0;c&lt;d.length;++c)h=d[c],f=e.previousItem(d,c),g=h._view,0===c?g.skip||(s.moveTo(g.x,g.y),u=c):(f=-1===u?f:d[u],g.skip||(u!==c-1&amp;&amp;!o||-1===u?s.moveTo(g.x,g.y):t(f,h),u=c));s.stroke(),s.re
 store()}})}},{}],39:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){function e(t){var e=this._view;return e?Math.pow(t-e.x,2)&lt;Math.pow(e.radius+e.hitRadius,2):!1}function a(t){var e=this._view;return e?Math.pow(t-e.y,2)&lt;Math.pow(e.radius+e.hitRadius,2):!1}var i=t.helpers,n=t.defaults.global,o=n.defaultColor;n.elements.point={radius:3,pointStyle:&quot;circle&quot;,backgroundColor:o,borderWidth:1,borderColor:o,hitRadius:1,hoverRadius:4,hoverBorderWidth:1},t.elements.Point=t.Element.extend({inRange:function(t,e){var a=this._view;return a?Math.pow(t-a.x,2)+Math.pow(e-a.y,2)&lt;Math.pow(a.hitRadius+a.radius,2):!1},inLabelRange:e,inXRange:e,inYRange:a,getCenterPoint:function(){var t=this._view;return{x:t.x,y:t.y}},getArea:function(){return Math.PI*Math.pow(this._view.radius,2)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(){var e=this._view,a=this._chart.ctx,r=e.pointStyle,l=e.radius,s=e.x,d=e.y;e
 .skip||(a.strokeStyle=e.borderColor||o,a.lineWidth=i.getValueOrDefault(e.borderWidth,n.elements.point.borderWidth),a.fillStyle=e.backgroundColor||o,t.canvasHelpers.drawPoint(a,r,l,s,d))}})}},{}],40:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){function e(t){return void 0!==t._view.width}function a(t){var a,i,n,o,r=t._view;if(e(t)){var l=r.width/2;a=r.x-l,i=r.x+l,n=Math.min(r.y,r.base),o=Math.max(r.y,r.base)}else{var s=r.height/2;a=Math.min(r.x,r.base),i=Math.max(r.x,r.base),n=r.y-s,o=r.y+s}return{left:a,top:n,right:i,bottom:o}}var i=t.defaults.global;i.elements.rectangle={backgroundColor:i.defaultColor,borderWidth:0,borderColor:i.defaultColor,borderSkipped:&quot;bottom&quot;},t.elements.Rectangle=t.Element.extend({draw:function(){function t(t){return s[(u+t)%4]}var e=this._chart.ctx,a=this._view,i=a.width/2,n=a.x-i,o=a.x+i,r=a.base-(a.base-a.y),l=a.borderWidth/2;a.borderWidth&amp;&amp;(n+=l,o-=l,r+=l),e.beginPath(),e.fillStyle=a.backgroundColor,e.strokeStyle=
 a.borderColor,e.lineWidth=a.borderWidth;var s=[[n,a.base],[n,r],[o,r],[o,a.base]],d=[&quot;bottom&quot;,&quot;left&quot;,&quot;top&quot;,&quot;right&quot;],u=d.indexOf(a.borderSkipped,0);-1===u&amp;&amp;(u=0);var c=t(0);e.moveTo(c[0],c[1]);for(var h=1;4&gt;h;h++)c=t(h),e.lineTo(c[0],c[1]);e.fill(),a.borderWidth&amp;&amp;e.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var i=!1;if(this._view){var n=a(this);i=t&gt;=n.left&amp;&amp;t&lt;=n.right&amp;&amp;e&gt;=n.top&amp;&amp;e&lt;=n.bottom}return i},inLabelRange:function(t,i){var n=this;if(!n._view)return!1;var o=!1,r=a(n);return o=e(n)?t&gt;=r.left&amp;&amp;t&lt;=r.right:i&gt;=r.top&amp;&amp;i&lt;=r.bottom},inXRange:function(t){var e=a(this);return t&gt;=e.left&amp;&amp;t&lt;=e.right},inYRange:function(t){var e=a(this);return t&gt;=e.top&amp;&amp;t&lt;=e.bottom},getCenterPoint:function(){var t,a,i=this._view;return e(this)?(t=i.x,a=(i.y+i.base)/2):(t=(i.x+i.base)/2,a=i.y),{x:t,y:a}},getAr
 ea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})}},{}],41:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers,a={position:&quot;bottom&quot;},i=t.Scale.extend({getLabels:function(){var t=this.chart.data;return(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels},determineDataLimits:function(){var t=this,a=t.getLabels();t.minIndex=0,t.maxIndex=a.length-1;var i;void 0!==t.options.ticks.min&amp;&amp;(i=e.indexOf(a,t.options.ticks.min),t.minIndex=-1!==i?i:t.minIndex),void 0!==t.options.ticks.max&amp;&amp;(i=e.indexOf(a,t.options.ticks.max),t.maxIndex=-1!==i?i:t.maxIndex),t.min=a[t.minIndex],t.max=a[t.maxIndex]},buildTicks:function(){var t=this,e=t.getLabels();t.ticks=0===t.minIndex&amp;&amp;t.maxIndex===e.length-1?e:e.slice(t.minIndex,t.maxIndex+1)},getLabelForIndex:function(t,e){var a=this,i=a.chart.data,n=a.isHorizontal();return i.xLabels&amp;&amp;n||i.yLabels&amp;&am
 p;!n?a.getRightValue(i.datasets[e].data[t]):a.ticks[t]},getPixelForValue:function(t,e,a,i){var n=this,o=Math.max(n.maxIndex+1-n.minIndex-(n.options.gridLines.offsetGridLines?0:1),1);if(void 0!==t&amp;&amp;isNaN(e)){var r=n.getLabels(),l=r.indexOf(t);e=-1!==l?l:e}if(n.isHorizontal()){var s=n.width-(n.paddingLeft+n.paddingRight),d=s/o,u=d*(e-n.minIndex)+n.paddingLeft;return(n.options.gridLines.offsetGridLines&amp;&amp;i||n.maxIndex===n.minIndex&amp;&amp;i)&amp;&amp;(u+=d/2),
+n.left+Math.round(u)}var c=n.height-(n.paddingTop+n.paddingBottom),h=c/o,f=h*(e-n.minIndex)+n.paddingTop;return n.options.gridLines.offsetGridLines&amp;&amp;i&amp;&amp;(f+=h/2),n.top+Math.round(f)},getPixelForTick:function(t,e){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null,e)},getValueForPixel:function(t){var e,a=this,i=Math.max(a.ticks.length-(a.options.gridLines.offsetGridLines?0:1),1),n=a.isHorizontal(),o=n?a.width-(a.paddingLeft+a.paddingRight):a.height-(a.paddingTop+a.paddingBottom),r=o/i;return t-=n?a.left:a.top,a.options.gridLines.offsetGridLines&amp;&amp;(t-=r/2),t-=n?a.paddingLeft:a.paddingTop,e=0&gt;=t?0:Math.round(t/r)},getBasePixel:function(){return this.bottom}});t.scaleService.registerScaleType(&quot;category&quot;,i,a)}},{}],42:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers,a={position:&quot;left&quot;,ticks:{callback:t.Ticks.formatters.linear}},i=t.LinearScaleBase.extend({determineDataLimits:function(){function
  t(t){return l?t.xAxisID===a.id:t.yAxisID===a.id}var a=this,i=a.options,n=a.chart,o=n.data,r=o.datasets,l=a.isHorizontal();if(a.min=null,a.max=null,i.stacked){var s={};e.each(r,function(o,r){var l=n.getDatasetMeta(r);void 0===s[l.type]&amp;&amp;(s[l.type]={positiveValues:[],negativeValues:[]});var d=s[l.type].positiveValues,u=s[l.type].negativeValues;n.isDatasetVisible(r)&amp;&amp;t(l)&amp;&amp;e.each(o.data,function(t,e){var n=+a.getRightValue(t);isNaN(n)||l.data[e].hidden||(d[e]=d[e]||0,u[e]=u[e]||0,i.relativePoints?d[e]=100:0&gt;n?u[e]+=n:d[e]+=n)})}),e.each(s,function(t){var i=t.positiveValues.concat(t.negativeValues),n=e.min(i),o=e.max(i);a.min=null===a.min?n:Math.min(a.min,n),a.max=null===a.max?o:Math.max(a.max,o)})}else e.each(r,function(i,o){var r=n.getDatasetMeta(o);n.isDatasetVisible(o)&amp;&amp;t(r)&amp;&amp;e.each(i.data,function(t,e){var i=+a.getRightValue(t);isNaN(i)||r.data[e].hidden||(null===a.min?a.min=i:i&lt;a.min&amp;&amp;(a.min=i),null===a.max?a.max=i:i&g
 t;a.max&amp;&amp;(a.max=i))})});this.handleTickRangeOptions()},getTickLimit:function(){var a,i=this,n=i.options.ticks;if(i.isHorizontal())a=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(i.width/50));else{var o=e.getValueOrDefault(n.fontSize,t.defaults.global.defaultFontSize);a=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(i.height/(2*o)))}return a},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e,a,i=this,n=i.paddingLeft,o=i.paddingBottom,r=i.start,l=+i.getRightValue(t),s=i.end-r;return i.isHorizontal()?(a=i.width-(n+i.paddingRight),e=i.left+a/s*(l-r),Math.round(e+n)):(a=i.height-(i.paddingTop+o),e=i.bottom-o-a/s*(l-r),Math.round(e))},getValueForPixel:function(t){var e=this,a=e.isHorizontal(),i=e.paddingLeft,n=e.paddingBottom,o=a?e.width-(i+e.paddingRight):e.height-(e.paddingTop+n),r=(a?t-e.left-i:e.bo
 ttom-n-t)/o;return e.start+(e.end-e.start)*r},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});t.scaleService.registerScaleType(&quot;linear&quot;,i,a)}},{}],43:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers,a=e.noop;t.LinearScaleBase=t.Scale.extend({handleTickRangeOptions:function(){var t=this,a=t.options,i=a.ticks;if(i.beginAtZero){var n=e.sign(t.min),o=e.sign(t.max);0&gt;n&amp;&amp;0&gt;o?t.max=0:n&gt;0&amp;&amp;o&gt;0&amp;&amp;(t.min=0)}void 0!==i.min?t.min=i.min:void 0!==i.suggestedMin&amp;&amp;(t.min=Math.min(t.min,i.suggestedMin)),void 0!==i.max?t.max=i.max:void 0!==i.suggestedMax&amp;&amp;(t.max=Math.max(t.max,i.suggestedMax)),t.min===t.max&amp;&amp;(t.max++,i.beginAtZero||t.min--)},getTickLimit:a,handleDirectionalChanges:a,buildTicks:function(){var a=this,i=a.options,n=i.ticks,o=a.getTickLimit();o=Math.max(2,o);var r={maxTicks:o,min:n.min,max:n.max,stepSize:e.getValueOrDefault(n.fixedStepSize,n.stepSi
 ze)},l=a.ticks=t.Ticks.generators.linear(r,a);a.handleDirectionalChanges(),a.max=e.max(l),a.min=e.min(l),n.reverse?(l.reverse(),a.start=a.max,a.end=a.min):(a.start=a.min,a.end=a.max)},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)}})}},{}],44:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers,a={position:&quot;left&quot;,ticks:{callback:t.Ticks.formatters.logarithmic}},i=t.Scale.extend({determineDataLimits:function(){function t(t){return d?t.xAxisID===a.id:t.yAxisID===a.id}var a=this,i=a.options,n=i.ticks,o=a.chart,r=o.data,l=r.datasets,s=e.getValueOrDefault,d=a.isHorizontal();if(a.min=null,a.max=null,a.minNotZero=null,i.stacked){var u={};e.each(l,function(n,r){var l=o.getDatasetMeta(r);o.isDatasetVisible(r)&amp;&amp;t(l)&amp;&amp;(void 0===u[l.type]&amp;&amp;(u[l.type]=[]),e.each(n.data,function(t,e){var n=u[l.type],o=+a.getRightValue(t);
 isNaN(o)||l.data[e].hidden||(n[e]=n[e]||0,i.relativePoints?n[e]=100:n[e]+=o)}))}),e.each(u,function(t){var i=e.min(t),n=e.max(t);a.min=null===a.min?i:Math.min(a.min,i),a.max=null===a.max?n:Math.max(a.max,n)})}else e.each(l,function(i,n){var r=o.getDatasetMeta(n);o.isDatasetVisible(n)&amp;&amp;t(r)&amp;&amp;e.each(i.data,function(t,e){var i=+a.getRightValue(t);isNaN(i)||r.data[e].hidden||(null===a.min?a.min=i:i&lt;a.min&amp;&amp;(a.min=i),null===a.max?a.max=i:i&gt;a.max&amp;&amp;(a.max=i),0!==i&amp;&amp;(null===a.minNotZero||i&lt;a.minNotZero)&amp;&amp;(a.minNotZero=i))})});a.min=s(n.min,a.min),a.max=s(n.max,a.max),a.min===a.max&amp;&amp;(0!==a.min&amp;&amp;null!==a.min?(a.min=Math.pow(10,Math.floor(e.log10(a.min))-1),a.max=Math.pow(10,Math.floor(e.log10(a.max))+1)):(a.min=1,a.max=10))},buildTicks:function(){var a=this,i=a.options,n=i.ticks,o={min:n.min,max:n.max},r=a.ticks=t.Ticks.generators.logarithmic(o,a);a.isHorizontal()||r.reverse(),a.max=e.max(r),a.min=e.min(r),n.rever
 se?(r.reverse(),a.start=a.max,a.end=a.min):(a.start=a.min,a.end=a.max)},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),t.Scale.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t){return this.getPixelForValue(this.tickValues[t])},getPixelForValue:function(t){var a,i,n,o=this,r=o.start,l=+o.getRightValue(t),s=o.paddingTop,d=o.paddingBottom,u=o.paddingLeft,c=o.options,h=c.ticks;return o.isHorizontal()?(n=e.log10(o.end)-e.log10(r),0===l?i=o.left+u:(a=o.width-(u+o.paddingRight),i=o.left+a/n*(e.log10(l)-e.log10(r)),i+=u)):(a=o.height-(s+d),0!==r||h.reverse?0===o.end&amp;&amp;h.reverse?(n=e.log10(o.start)-e.log10(o.minNotZero),i=l===o.end?o.top+s:l===o.minNotZero?o.top+s+.02*a:o.top+s+.02*a+.98*a/n*(e.log10(l)-e.log10(o.minNotZero))):(n=e.log10(o.end)-e.log10(r),a=o.height-(s+d),i=o.bottom-d-a/n*(e.log10(l)-e.log10(r))):(n=e.log10(o.end)-e.log10(o.mi
 nNotZero),i=l===r?o.bottom-d:l===o.minNotZero?o.bottom-d-.02*a:o.bottom-d-.02*a-.98*a/n*(e.log10(l)-e.log10(o.minNotZero)))),i},getValueForPixel:function(t){var a,i,n=this,o=e.log10(n.end)-e.log10(n.start);return n.isHorizontal()?(i=n.width-(n.paddingLeft+n.paddingRight),a=n.start*Math.pow(10,(t-n.left-n.paddingLeft)*o/i)):(i=n.height-(n.paddingTop+n.paddingBottom),a=Math.pow(10,(n.bottom-n.paddingBottom-t)*o/i)/n.start),a}});t.scaleService.registerScaleType(&quot;logarithmic&quot;,i,a)}},{}],45:[function(t,e,a){&quot;use strict&quot;;e.exports=function(t){var e=t.helpers,a=t.defaults.global,i={display:!0,animate:!0,lineArc:!1,position:&quot;chartArea&quot;,angleLines:{display:!0,color:&quot;rgba(0, 0, 0, 0.1)&quot;,lineWidth:1},ticks:{showLabelBackdrop:!0,backdropColor:&quot;rgba(255,255,255,0.75)&quot;,backdropPaddingY:2,backdropPaddingX:2,callback:t.Ticks.formatters.linear},pointLabels:{fontSize:10,callback:function(t){return t}}},n=t.LinearScaleBase.extend({getValueCount
 :function(){return this.chart.data.labels.length},setDimensions:function(){var t=this,i=t.options,n=i.ticks;t.width=t.maxWidth,t.height=t.maxHeight,t.xCenter=Math.round(t.width/2),t.yCenter=Math.round(t.height/2);var o=e.min([t.height,t.width]),r=e.getValueOrDefault(n.fontSize,a.defaultFontSize);t.drawingArea=i.display?o/2-(r/2+n.backdropPaddingY):o/2},determineDataLimits:function(){var t=this,a=t.chart;t.min=null,t.max=null,e.each(a.data.datasets,function(i,n){if(a.isDatasetVisible(n)){var o=a.getDatasetMeta(n);e.each(i.data,function(e,a){var i=+t.getRightValue(e);isNaN(i)||o.data[a].hidden||(null===t.min?t.min=i:i&lt;t.min&amp;&amp;(t.min=i),null===t.max?t.max=i:i&gt;t.max&amp;&amp;(t.max=i))})}}),t.handleTickRangeOptions()},getTickLimit:function(){var t=this.options.ticks,i=e.getValueOrDefault(t.fontSize,a.defaultFontSize);return Math.min(t.maxTicksLimit?t.maxTicksLimit:11,Math.ceil(this.drawingArea/(1.5*i)))},convertTicksToLabels:function(){var e=this;t.LinearScaleBase.p
 rototype.convertTicksToLabels.call(e),e.pointLabels=e.chart.data.labels.map(e.options.pointLabels.callback,e)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){var t,i,n,o,r,l,s,d,u,c,h,f,g=this.options.pointLabels,p=e.getValueOrDefault(g.fontSize,a.defaultFontSize),m=e.getValueOrDefault(g.fontStyle,a.defaultFontStyle),b=e.getValueOrDefault(g.fontFamily,a.defaultFontFamily),v=e.fontString(p,m,b),x=e.min([this.height/2-p-5,this.width/2]),y=this.width,k=0;for(this.ctx.font=v,i=0;i&lt;this.getValueCount();i++){t=this.getPointPosition(i,x),n=this.ctx.measureText(this.pointLabels[i]?this.pointLabels[i]:&quot;&quot;).width+5;var S=this.getIndexAngle(i)+Math.PI/2,w=360*S/(2*Math.PI)%360;0===w||180===w?(o=n/2,t.x+o&gt;y&amp;&amp;(y=t.x+o,r=i),t.x-o&lt;k&amp;&amp;(k=t.x-o,s=i)):180&gt;w?t.x+n&gt;y&amp;&amp;(y=t.x+n,r=i):t.x-n&lt;k&amp;&amp;(k=t.x-n,s=i)}u=k,c=Math.ceil(y-this.width),l=this.getIndexAngle(r),d=this.getIndexAn
 gle(s),h=c/Math.sin(l+Math.PI/2),f=u/Math.sin(d+Math.PI/2),h=e.isNumber(h)?h:0,f=e.isNumber(f)?f:0,this.drawingArea=Math.round(x-(f+h)/2),this.setCenterPoint(f,h)},setCenterPoint:function(t,e){var a=this,i=a.width-e-a.drawingArea,n=t+a.drawingArea;a.xCenter=Math.round((n+i)/2+a.left),a.yCenter=Math.round(a.height/2+a.top)},getIndexAngle:function(t){var e=2*Math.PI/this.getValueCount(),a=this.chart.options&amp;&amp;this.chart.options.startAngle?this.chart.options.startAngle:0,i=a*Math.PI*2/360;return t*e-Math.PI/2+i},getDistanceFromCenterForValue:function(t){var e=this;if(null===t)return 0;var a=e.drawingArea/(e.max-e.min);return e.options.reverse?(e.max-t)*a:(t-e.min)*a},getPointPosition:function(t,e){var a=this,i=a.getIndexAngle(t);return{x:Math.round(Math.cos(i)*e)+a.xCenter,y:Math.round(Math.sin(i)*e)+a.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this,e=t.min,a=t.m
 ax;return t.getPointPositionForValue(0,t.beginAtZero?0:0&gt;e&amp;&amp;0&gt;a?a:e&gt;0&amp;&amp;a&gt;0?e:0)},draw:function(){var t=this,i=t.options,n=i.gridLines,o=i.ticks,r=i.angleLines,l=i.pointLabels,s=e.getValueOrDefault;if(i.display){var d=t.ctx,u=s(o.fontSize,a.defaultFontSize),c=s(o.fontStyle,a.defaultFontStyle),h=s(o.fontFamily,a.defaultFontFamily),f=e.fontString(u,c,h);if(e.each(t.ticks,function(r,l){if(l&gt;0||i.reverse){var c=t.getDistanceFromCenterForValue(t.ticksAsNumbers[l]),h=t.yCenter-c;if(n.display&amp;&amp;0!==l)if(d.strokeStyle=e.getValueAtIndexOrDefault(n.color,l-1),d.lineWidth=e.getValueAtIndexOrDefault(n.lineWidth,l-1),i.lineArc)d.beginPath(),d.arc(t.xCenter,t.yCenter,c,0,2*Math.PI),d.closePath(),d.stroke();else{d.beginPath();for(var g=0;g&lt;t.getValueCount();g++){var p=t.getPointPosition(g,c);0===g?d.moveTo(p.x,p.y):d.lineTo(p.x,p.y)}d.closePath(),d.stroke()}if(o.display){var m=s(o.fontColor,a.defaultFontColor);if(d.font=f,o.showLabelBackdrop){var b=d
 .measureText(r).width;d.fillStyle=o.backdropColor,d.fillRect(t.xCenter-b/2-o.backdropPaddingX,h-u/2-o.backdropPaddingY,b+2*o.backdropPaddingX,u+2*o.backdropPaddingY)}d.textAlign=&quot;center&quot;,d.textBaseline=&quot;middle&quot;,d.fillStyle=m,d.fillText(r,t.xCenter,h)}}}),!i.lineArc){d.lineWidth=r.lineWidth,d.strokeStyle=r.color;for(var g=t.getDistanceFromCenterForValue(i.reverse?t.min:t.max),p=s(l.fontSize,a.defaultFontSize),m=s(l.fontStyle,a.defaultFontStyle),b=s(l.fontFamily,a.defaultFontFamily),v=e.fontString(p,m,b),x=t.getValueCount()-1;x&gt;=0;x--){if(r.display){var y=t.getPointPosition(x,g);d.beginPath(),d.moveTo(t.xCenter,t.yCenter),d.lineTo(y.x,y.y),d.stroke(),d.closePath()}var k=t.getPointPosition(x,g+5),S=s(l.fontColor,a.defaultFontColor);d.font=v,d.fillStyle=S;var w=t.pointLabels,M=this.getIndexAngle(x)+Math.PI/2,C=360*M/(2*Math.PI)%360;0===C||180===C?d.textAlign=&quot;center&quot;:180&gt;C?d.textAlign=&quot;left&quot;:d.textAlign=&quot;right&quot;,90===C||270=
 ==C?d.textBaseline=&quot;middle&quot;:C&gt;270||90&gt;C?d.textBaseline=&quot;bottom&quot;:d.textBaseline=&quot;top&quot;,d.fillText(w[x]?w[x]:&quot;&quot;,k.x,k.y)}}}}});t.scaleService.registerScaleType(&quot;radialLinear&quot;,n,i)}},{}],46:[function(t,e,a){&quot;use strict&quot;;var i=t(1);i=&quot;function&quot;==typeof i?i:window.moment,e.exports=function(t){var e=t.helpers,a={units:[{name:&quot;millisecond&quot;,steps:[1,2,5,10,20,50,100,250,500]},{name:&quot;second&quot;,steps:[1,2,5,10,30]},{name:&quot;minute&quot;,steps:[1,2,5,10,30]},{name:&quot;hour&quot;,steps:[1,2,3,6,12]},{name:&quot;day&quot;,steps:[1,2,5]},{name:&quot;week&quot;,maxStep:4},{name:&quot;month&quot;,maxStep:3},{name:&quot;quarter&quot;,maxStep:4},{name:&quot;year&quot;,maxStep:!1}]},n={position:&quot;bottom&quot;,time:{parser:!1,format:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,minUnit:&quot;millisecond&quot;,displayFormats:{millisecond:&quot;h:mm:ss.SSS a&quot;,second:&quot;h:mm:ss a&quot
 ;,minute:&quot;h:mm:ss a&quot;,hour:&quot;MMM D, hA&quot;,day:&quot;ll&quot;,week:&quot;ll&quot;,month:&quot;MMM YYYY&quot;,quarter:&quot;[Q]Q - YYYY&quot;,year:&quot;YYYY&quot;}},ticks:{autoSkip:!1}},o=t.Scale.extend({initialize:function(){if(!i)throw new Error(&quot;Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com&quot;);t.Scale.prototype.initialize.call(this)},getLabelMoment:function(t,e){return null===t||null===e?null:&quot;undefined&quot;!=typeof this.labelMoments[t]?this.labelMoments[t][e]:null},getLabelDiff:function(t,e){var a=this;return null===t||null===e?null:(void 0===a.labelDiffs&amp;&amp;a.buildLabelDiffs(),&quot;undefined&quot;!=typeof a.labelDiffs[t]?a.labelDiffs[t][e]:null)},getMomentStartOf:function(t){var e=this;return&quot;week&quot;===e.options.time.unit&amp;&amp;e.options.time.isoWeekday!==!1?t.clone().startOf(&quot;isoWeek&quot;).isoWeekday(e.options.time.isoWeekday):t.c
 lone().startOf(e.tickUnit)},determineDataLimits:function(){var t=this;t.labelMoments=[];var a=[];t.chart.data.labels&amp;&amp;t.chart.data.labels.length&gt;0?(e.each(t.chart.data.labels,function(e){var i=t.parseTime(e);i.isValid()&amp;&amp;(t.options.time.round&amp;&amp;i.startOf(t.options.time.round),a.push(i))},t),t.firstTick=i.min.call(t,a),t.lastTick=i.max.call(t,a)):(t.firstTick=null,t.lastTick=null),e.each(t.chart.data.datasets,function(n,o){var r=[],l=t.chart.isDatasetVisible(o);&quot;object&quot;==typeof n.data[0]&amp;&amp;null!==n.data[0]?e.each(n.data,function(e){var a=t.parseTime(t.getRightValue(e));a.isValid()&amp;&amp;(t.options.time.round&amp;&amp;a.startOf(t.options.time.round),r.push(a),l&amp;&amp;(t.firstTick=null!==t.firstTick?i.min(t.firstTick,a):a,t.lastTick=null!==t.lastTick?i.max(t.lastTick,a):a))},t):r=a,t.labelMoments.push(r)},t),t.options.time.min&amp;&amp;(t.firstTick=t.parseTime(t.options.time.min)),t.options.time.max&amp;&amp;(t.lastTick=t.parseTi
 me(t.options.time.max)),t.firstTick=(t.firstTick||i()).clone(),t.lastTick=(t.lastTick||i()).clone()},buildLabelDiffs:function(){var t=this;t.labelDiffs=[];var a=[];t.chart.data.labels&amp;&amp;t.chart.data.labels.length&gt;0&amp;&amp;e.each(t.chart.data.labels,function(e){var i=t.parseTime(e);i.isValid()&amp;&amp;(t.options.time.round&amp;&amp;i.startOf(t.options.time.round),a.push(i.diff(t.firstTick,t.tickUnit,!0)))},t),e.each(t.chart.data.datasets,function(i){var n=[];&quot;object&quot;==typeof i.data[0]&amp;&amp;null!==i.data[0]?e.each(i.data,function(e){var a=t.parseTime(t.getRightValue(e));a.isValid()&amp;&amp;(t.options.time.round&amp;&amp;a.startOf(t.options.time.round),n.push(a.diff(t.firstTick,t.tickUnit,!0)))},t):n=a,t.labelDiffs.push(n)},t)},buildTicks:function(){var i=this;i.ctx.save();var n=e.getValueOrDefault(i.options.ticks.fontSize,t.defaults.global.defaultFontSize),o=e.getValueOrDefault(i.options.ticks.fontStyle,t.defaults.global.defaultFontStyle),r=e.getVal
 ueOrDefault(i.options.ticks.fontFamily,t.defaults.global.defaultFontFamily),l=e.fontString(n,o,r);if(i.ctx.font=l,i.ticks=[],i.unitScale=1,i.scaleSizeInUnits=0,i.options.time.unit)i.tickUnit=i.options.time.unit||&quot;day&quot;,i.displayFormat=i.options.time.displayFormats[i.tickUnit],i.scaleSizeInUnits=i.lastTick.diff(i.firstTick,i.tickUnit,!0),i.unitScale=e.getValueOrDefault(i.options.time.unitStepSize,1);else{var s=i.isHorizontal()?i.width-(i.paddingLeft+i.paddingRight):i.height-(i.paddingTop+i.paddingBottom),d=i.tickFormatFunction(i.firstTick,0,[]),u=i.ctx.measureText(d).width,c=Math.cos(e.toRadians(i.options.ticks.maxRotation)),h=Math.sin(e.toRadians(i.options.ticks.maxRotation));u=u*c+n*h;var f=s/u;i.tickUnit=i.options.time.minUnit,i.scaleSizeInUnits=i.lastTick.diff(i.firstTick,i.tickUnit,!0),i.displayFormat=i.options.time.displayFormats[i.tickUnit];for(var g=0,p=a.units[g];g&lt;a.units.length;){if(i.unitScale=1,e.isArray(p.steps)&amp;&amp;Math.ceil(i.scaleSizeInUnits/
 f)&lt;e.max(p.steps)){for(var m=0;m&lt;p.steps.length;++m)if(p.steps[m]&gt;=Math.ceil(i.scaleSizeInUnits/f)){i.unitScale=e.getValueOrDefault(i.options.time.unitStepSize,p.steps[m]);break}break}if(p.maxStep===!1||Math.ceil(i.scaleSizeInUnits/f)&lt;p.maxStep){i.unitScale=e.getValueOrDefault(i.options.time.unitStepSize,Math.ceil(i.scaleSizeInUnits/f));break}++g,p=a.units[g],i.tickUnit=p.name;var b=i.firstTick.diff(i.getMomentStartOf(i.firstTick),i.tickUnit,!0),v=i.getMomentStartOf(i.lastTick.clone().add(1,i.tickUnit)).diff(i.lastTick,i.tickUnit,!0);i.scaleSizeInUnits=i.lastTick.diff(i.firstTick,i.tickUnit,!0)+b+v,i.displayFormat=i.options.time.displayFormats[p.name]}}var x;if(i.options.time.min?x=i.getMomentStartOf(i.firstTick):(i.firstTick=i.getMomentStartOf(i.firstTick),x=i.firstTick),!i.options.time.max){var y=i.getMomentStartOf(i.lastTick),k=y.diff(i.lastTick,i.tickUnit,!0);0&gt;k?i.lastTick=i.getMomentStartOf(i.lastTick.add(1,i.tickUnit)):k&gt;=0&amp;&amp;(i.lastTick=y),i.
 scaleSizeInUnits=i.lastTick.diff(i.firstTick,i.tickUnit,!0)}i.options.time.displayFormat&amp;&amp;(i.displayFormat=i.options.time.displayFormat),i.ticks.push(i.firstTick.clone());for(var S=1;S&lt;=i.scaleSizeInUnits;++S){var w=x.clone().add(S,i.tickUnit);if(i.options.time.max&amp;&amp;w.diff(i.lastTick,i.tickUnit,!0)&gt;=0)break;S%i.unitScale===0&amp;&amp;i.ticks.push(w)}var M=i.ticks[i.ticks.length-1].diff(i.lastTick,i.tickUnit);(0!==M||0===i.scaleSizeInUnits)&amp;&amp;(i.options.time.max?(i.ticks.push(i.lastTick.clone()),i.scaleSizeInUnits=i.lastTick.diff(i.ticks[0],i.tickUnit,!0)):(i.ticks.push(i.lastTick.clone()),i.scaleSizeInUnits=i.lastTick.diff(i.firstTick,i.tickUnit,!0))),i.ctx.restore(),i.labelDiffs=void 0},getLabelForIndex:function(t,e){var a=this,i=a.chart.data.labels&amp;&amp;t&lt;a.chart.data.labels.length?a.chart.data.labels[t]:&quot;&quot;;return&quot;object&quot;==typeof a.chart.data.datasets[e].data[0]&amp;&amp;(i=a.getRightValue(a.chart.data.datasets[e].dat
 a[t])),a.options.time.tooltipFormat&amp;&amp;(i=a.parseTime(i).format(a.options.time.tooltipFormat)),i},tickFormatFunction:function(t,a,i){var n=t.format(this.displayFormat),o=this.options.ticks,r=e.getValueOrDefault(o.callback,o.userCallback);return r?r(n,a,i):n},convertTicksToLabels:function(){var t=this;t.tickMoments=t.ticks,t.ticks=t.ticks.map(t.tickFormatFunction,t)},getPixelForValue:function(t,e,a){var i=this,n=null;if(void 0!==e&amp;&amp;void 0!==a&amp;&amp;(n=i.getLabelDiff(a,e)),null===n&amp;&amp;(t&amp;&amp;t.isValid||(t=i.parseTime(i.getRightValue(t))),t&amp;&amp;t.isValid&amp;&amp;t.isValid()&amp;&amp;(n=t.diff(i.firstTick,i.tickUnit,!0))),null!==n){var o=0!==n?n/i.scaleSizeInUnits:n;if(i.isHorizontal()){var r=i.width-(i.paddingLeft+i.paddingRight),l=r*o+i.paddingLeft;return i.left+Math.round(l)}var s=i.height-(i.paddingTop+i.paddingBottom),d=s*o+i.paddingTop;return i.top+Math.round(d)}},getPixelForTick:function(t){return this.getPixelForValue(this.tickMoments[t]
 ,null,null)},getValueForPixel:function(t){var e=this,a=e.isHorizontal()?e.width-(e.paddingLeft+e.paddingRight):e.height-(e.paddingTop+e.paddingBottom),n=(t-(e.isHorizontal()?e.left+e.paddingLeft:e.top+e.paddingTop))/a;return n*=e.scaleSizeInUnits,e.firstTick.clone().add(i.duration(n,e.tickUnit).asSeconds(),&quot;seconds&quot;)},parseTime:function(t){var e=this;return&quot;string&quot;==typeof e.options.time.parser?i(t,e.options.time.parser):&quot;function&quot;==typeof e.options.time.parser?e.options.time.parser(t):&quot;function&quot;==typeof t.getMonth||&quot;number&quot;==typeof t?i(t):t.isValid&amp;&amp;t.isValid()?t:&quot;string&quot;!=typeof e.options.time.format&amp;&amp;e.options.time.format.call?(console.warn(&quot;options.time.format is deprecated and replaced by options.time.parser. See http://nnnick.github.io/Chart.js/docs-v2/#scales-time-scale&quot;),e.options.time.format(t)):i(t,e.options.time.format)}});t.scaleService.registerScaleType(&quot;time&quot;,o,n)}},
 {1:1}]},{},[7])(7)});
+&lt;/script&gt;
+&lt;script&gt;
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Copyright (C) 2015 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:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// &quot;AS IS&quot; 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 THE COPYRIGHT
+// OWNER 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.
+
+
+// Performance.now is used in latency benchmarks, the fallback is Date.now.
+var performance = performance || {};
+performance.now = (function() {
+  return performance.now       ||
+         performance.mozNow    ||
+         performance.msNow     ||
+         performance.oNow      ||
+         performance.webkitNow ||
+         Date.now;
+})();
+
+// Simple framework for running the benchmark suites and
+// computing a score based on the timing measurements.
+
+
+// A benchmark has a name (string) and a function that will be run to
+// do the performance measurement. The optional setup and tearDown
+// arguments are functions that will be invoked before and after
+// running the benchmark, but the running time of these functions will
+// not be accounted for in the benchmark score.
+function Benchmark(name, doWarmup, doDeterministic, run, setup, tearDown, latencyResult, minIterations) {
+  this.name = name;
+  this.doWarmup = doWarmup;
+  this.doDeterministic = doDeterministic;
+  this.run = run;
+  this.Setup = setup ? setup : function() { };
+  this.TearDown = tearDown ? tearDown : function() { };
+  this.latencyResult = latencyResult ? latencyResult : null; 
+  this.minIterations = minIterations ? minIterations : 32;
+}
+
+
+// Benchmark results hold the benchmark and the measured time used to
+// run the benchmark. The benchmark score is computed later once a
+// full benchmark suite has run to completion. If latency is set to 0
+// then there is no latency score for this benchmark.
+function BenchmarkResult(benchmark, time, latency) {
+  this.benchmark = benchmark;
+  this.time = time;
+  this.latency = latency;
+}
+
+
+// Automatically convert results to numbers. Used by the geometric
+// mean computation.
+BenchmarkResult.prototype.valueOf = function() {
+  return this.time;
+}
+
+
+// Suites of benchmarks consist of a name and the set of benchmarks in
+// addition to the reference timing that the final score will be based
+// on. This way, all scores are relative to a reference run and higher
+// scores implies better performance.
+function BenchmarkSuite(name, reference, benchmarks) {
+  this.name = name;
+  this.reference = reference;
+  this.benchmarks = benchmarks;
+  BenchmarkSuite.suites.push(this);
+}
+
+
+// Keep track of all declared benchmark suites.
+BenchmarkSuite.suites = [];
+
+// Scores are not comparable across versions. Bump the version if
+// you're making changes that will affect that scores, e.g. if you add
+// a new benchmark or change an existing one.
+BenchmarkSuite.version = '9';
+
+// Override the alert function to throw an exception instead.
+alert = function(s) {
+  throw &quot;Alert called with argument: &quot; + s;
+};
+
+
+// To make the benchmark results predictable, we replace Math.random
+// with a 100% deterministic alternative.
+BenchmarkSuite.ResetRNG = function() {
+  Math.random = (function() {
+    var seed = 49734321;
+    return function() {
+      // Robert Jenkins' 32 bit integer hash function.
+      seed = ((seed + 0x7ed55d16) + (seed &lt;&lt; 12))  &amp; 0xffffffff;
+      seed = ((seed ^ 0xc761c23c) ^ (seed &gt;&gt;&gt; 19)) &amp; 0xffffffff;
+      seed = ((seed + 0x165667b1) + (seed &lt;&lt; 5))   &amp; 0xffffffff;
+      seed = ((seed + 0xd3a2646c) ^ (seed &lt;&lt; 9))   &amp; 0xffffffff;
+      seed = ((seed + 0xfd7046c5) + (seed &lt;&lt; 3))   &amp; 0xffffffff;
+      seed = ((seed ^ 0xb55a4f09) ^ (seed &gt;&gt;&gt; 16)) &amp; 0xffffffff;
+      return (seed &amp; 0xfffffff) / 0x10000000;
+    };
+  })();
+}
+
+
+// Runs all registered benchmark suites and optionally yields between
+// each individual benchmark to avoid running for too long in the
+// context of browsers. Once done, the final score is reported to the
+// runner.
+BenchmarkSuite.RunSuites = function(runner) {
+  var continuation = null;
+  var suites = BenchmarkSuite.suites;
+  var length = suites.length;
+  BenchmarkSuite.scores = [];
+  var index = 0;
+  function RunStep() {
+    while (continuation || index &lt; length) {
+      if (continuation) {
+        continuation = continuation();
+      } else {
+        var suite = suites[index++];
+        if (runner.NotifyStart) runner.NotifyStart(suite.name);
+        continuation = suite.RunStep(runner);
+      }
+      if (continuation &amp;&amp; typeof window != 'undefined' &amp;&amp; window.setTimeout) {
+        window.setTimeout(RunStep, 25);
+        return;
+      }
+    }
+
+    // show final result
+    if (runner.NotifyScore) {
+      var score = BenchmarkSuite.GeometricMean(BenchmarkSuite.scores);
+      var formatted = BenchmarkSuite.FormatScore(100 * score);
+      runner.NotifyScore(formatted);
+    }
+  }
+  RunStep();
+}
+
+
+// Counts the total number of registered benchmarks. Useful for
+// showing progress as a percentage.
+BenchmarkSuite.CountBenchmarks = function() {
+  var result = 0;
+  var suites = BenchmarkSuite.suites;
+  for (var i = 0; i &lt; suites.length; i++) {
+    result += suites[i].benchmarks.length;
+  }
+  return result;
+}
+
+
+// Computes the geometric mean of a set of numbers.
+BenchmarkSuite.GeometricMean = function(numbers) {
+  var log = 0;
+  for (var i = 0; i &lt; numbers.length; i++) {
+    log += Math.log(numbers[i]);
+  }
+  return Math.pow(Math.E, log / numbers.length);
+}
+
+
+// Computes the geometric mean of a set of throughput time measurements.
+BenchmarkSuite.GeometricMeanTime = function(measurements) {
+  var log = 0;
+  for (var i = 0; i &lt; measurements.length; i++) {
+    log += Math.log(measurements[i].time);
+  }
+  return Math.pow(Math.E, log / measurements.length);
+}
+
+
+// Computes the average of the worst samples. For example, if percentile is 99, this will report the
+// average of the worst 1% of the samples.
+BenchmarkSuite.AverageAbovePercentile = function(numbers, percentile) {
+  // Don't change the original array.
+  numbers = numbers.slice();
+  
+  // Sort in ascending order.
+  numbers.sort(function(a, b) { return a - b; });
+  
+  // Now the elements we want are at the end. Keep removing them until the array size shrinks too much.
+  // Examples assuming percentile = 99:
+  //
+  // - numbers.length starts at 100: we will remove just the worst entry and then not remove anymore,
+  //   since then numbers.length / originalLength = 0.99.
+  //
+  // - numbers.length starts at 1000: we will remove the ten worst.
+  //
+  // - numbers.length starts at 10: we will remove just the worst.
+  var numbersWeWant = [];
+  var originalLength = numbers.length;
+  while (numbers.length / originalLength &gt; percentile / 100)
+    numbersWeWant.push(numbers.pop());
+  
+  var sum = 0;
+  for (var i = 0; i &lt; numbersWeWant.length; ++i)
+    sum += numbersWeWant[i];
+  
+  var result = sum / numbersWeWant.length;
+  
+  // Do a sanity check.
+  if (numbers.length &amp;&amp; result &lt; numbers[numbers.length - 1]) {
+    throw &quot;Sanity check fail: the worst case result is &quot; + result +
+      &quot; but we didn't take into account &quot; + numbers;
+  }
+  
+  return result;
+}
+
+
+// Computes the geometric mean of a set of latency measurements.
+BenchmarkSuite.GeometricMeanLatency = function(measurements) {
+  var log = 0;
+  var hasLatencyResult = false;
+  for (var i = 0; i &lt; measurements.length; i++) {
+    if (measurements[i].latency != 0) {
+      log += Math.log(measurements[i].latency);
+      hasLatencyResult = true;
+    }
+  }
+  if (hasLatencyResult) {
+    return Math.pow(Math.E, log / measurements.length);
+  } else {
+    return 0;
+  }
+}
+
+
+// Converts a score value to a string with at least three significant
+// digits.
+BenchmarkSuite.FormatScore = function(value) {
+  if (value &gt; 100) {
+    return value.toFixed(0);
+  } else {
+    return value.toPrecision(3);
+  }
+}
+
+// Notifies the runner that we're done running a single benchmark in
+// the benchmark suite. This can be useful to report progress.
+BenchmarkSuite.prototype.NotifyStep = function(result) {
+  this.results.push(result);
+  if (this.runner.NotifyStep) this.runner.NotifyStep(result.benchmark.name);
+}
+
+
+// Notifies the runner that we're done with running a suite and that
+// we have a result which can be reported to the user if needed.
+BenchmarkSuite.prototype.NotifyResult = function() {
+  var mean = BenchmarkSuite.GeometricMeanTime(this.results);
+  var score = this.reference[0] / mean;
+  BenchmarkSuite.scores.push(score);
+  if (this.runner.NotifyResult) {
+    var formatted = BenchmarkSuite.FormatScore(100 * score);
+    this.runner.NotifyResult(this.name, formatted);
+  }
+  if (this.reference.length == 2) {
+    var meanLatency = BenchmarkSuite.GeometricMeanLatency(this.results);
+    if (meanLatency != 0) {
+      var scoreLatency = this.reference[1] / meanLatency;
+      BenchmarkSuite.scores.push(scoreLatency);
+      if (this.runner.NotifyResult) {
+        var formattedLatency = BenchmarkSuite.FormatScore(100 * scoreLatency)
+        this.runner.NotifyResult(this.name + &quot;Latency&quot;, formattedLatency);
+      }
+    }
+  }
+}
+
+
+// Notifies the runner that running a benchmark resulted in an error.
+BenchmarkSuite.prototype.NotifyError = function(error) {
+  if (this.runner.NotifyError) {
+    this.runner.NotifyError(this.name, error);
+  }
+  if (this.runner.NotifyStep) {
+    this.runner.NotifyStep(this.name);
+  }
+}
+
+
+// Runs a single benchmark for at least a second and computes the
+// average time it takes to run a single iteration.
+BenchmarkSuite.prototype.RunSingleBenchmark = function(benchmark, data) {
+  function Measure(data) {
+    var elapsed = 0;
+    var start = new Date();
+  
+  // Run either for 1 second or for the number of iterations specified
+  // by minIterations, depending on the config flag doDeterministic.
+    for (var i = 0; (benchmark.doDeterministic ? 
+      i&lt;benchmark.minIterations : elapsed &lt; 1000); i++) {
+      benchmark.run();
+      elapsed = new Date() - start;
+    }
+    if (data != null) {
+      data.runs += i;
+      data.elapsed += elapsed;
+    }
+  }
+
+  // Sets up data in order to skip or not the warmup phase.
+  if (!benchmark.doWarmup &amp;&amp; data == null) {
+    data = { runs: 0, elapsed: 0 };
+  }
+
+  if (data == null) {
+    Measure(null);
+    return { runs: 0, elapsed: 0 };
+  } else {
+    Measure(data);
+    // If we've run too few iterations, we continue for another second.
+    if (data.runs &lt; benchmark.minIterations) return data;
+    var usec = (data.elapsed * 1000) / data.runs;
+    var latencySamples = (benchmark.latencyResult != null) ? benchmark.latencyResult() : [0];
+    var percentile = 99.5;
+    var latency = BenchmarkSuite.AverageAbovePercentile(latencySamples, percentile) * 1000;
+    this.NotifyStep(new BenchmarkResult(benchmark, usec, latency));
+    return null;
+  }
+}
+
+
+// This function starts running a suite, but stops between each
+// individual benchmark in the suite and returns a continuation
+// function which can be invoked to run the next benchmark. Once the
+// last benchmark has been executed, null is returned.
+BenchmarkSuite.prototype.RunStep = function(runner) {
+  BenchmarkSuite.ResetRNG();
+  this.results = [];
+  this.runner = runner;
+  var length = this.benchmarks.length;
+  var index = 0;
+  var suite = this;
+  var data;
+
+  // Run the setup, the actual benchmark, and the tear down in three
+  // separate steps to allow the framework to yield between any of the
+  // steps.
+
+  function RunNextSetup() {
+    if (index &lt; length) {
+      try {
+        suite.benchmarks[index].Setup();
+      } catch (e) {
+        suite.NotifyError(e);
+        return null;
+      }
+      return RunNextBenchmark;
+    }
+    suite.NotifyResult();
+    return null;
+  }
+
+  function RunNextBenchmark() {
+    try {
+      data = suite.RunSingleBenchmark(suite.benchmarks[index], data);
+    } catch (e) {
+      suite.NotifyError(e);
+      return null;
+    }
+    // If data is null, we're done with this benchmark.
+    return (data == null) ? RunNextTearDown : RunNextBenchmark();
+  }
+
+  function RunNextTearDown() {
+    try {
+      suite.benchmarks[index++].TearDown();
+    } catch (e) {
+      suite.NotifyError(e);
+      return null;
+    }
+    return RunNextSetup;
+  }
+
+  // Start out running the setup.
+  return RunNextSetup();
+}
+
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright (C) 2015 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:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// &quot;AS IS&quot; 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 THE COPYRIGHT
+// OWNER 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.
+
+// This benchmark is based on a JavaScript log processing module used
+// by the V8 profiler to generate execution time profiles for runs of
+// JavaScript applications, and it effectively measures how fast the
+// JavaScript engine is at allocating nodes and reclaiming the memory
+// used for old nodes. Because of the way splay trees work, the engine
+// also has to deal with a lot of changes to the large tree object
+// graph.
+
+var Splay = new BenchmarkSuite('Splay', [81491, 2739514], [
+  new Benchmark(&quot;Splay&quot;, true, false, 
+    SplayRun, SplaySetup, SplayTearDown, SplayLatency)
+]);
+
+
+// Configuration.
+var kSplayTreeSize = 8000;
+var kSplayTreeModifications = 80;
+var kSplayTreePayloadDepth = 5;
+
+var splayTree = null;
+var splaySampleTimeStart = 0.0;
+
+function GeneratePayloadTree(depth, tag) {
+  if (depth == 0) {
+    return {
+      array  : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
+      string : 'String for key ' + tag + ' in leaf node'
+    };
+  } else {
+    return {
+      left:  GeneratePayloadTree(depth - 1, tag),
+      right: GeneratePayloadTree(depth - 1, tag)
+    };
+  }
+}
+
+
+function GenerateKey() {
+  // The benchmark framework guarantees that Math.random is
+  // deterministic; see base.js.
+  return Math.random();
+}
+
+var splaySamples = [];
+
+function SplayLatency() {
+  return splaySamples;
+}
+
+function SplayUpdateStats(time) {
+  var pause = time - splaySampleTimeStart;
+  splaySampleTimeStart = time;
+  splaySamples.push(pause);
+}
+
+function InsertNewNode() {
+  // Insert new node with a unique key.
+  var key;
+  do {
+    key = GenerateKey();
+  } while (splayTree.find(key) != null);
+  var payload = GeneratePayloadTree(kSplayTreePayloadDepth, String(key));
+  splayTree.insert(key, payload);
+  return key;
+}
+
+
+function SplaySetup() {
+  // Check if the platform has the performance.now high resolution timer.
+  // If not, throw exception and quit.
+  if (!performance.now) {
+    throw &quot;PerformanceNowUnsupported&quot;;
+  }
+
+  splayTree = new SplayTree();
+  splaySampleTimeStart = performance.now()
+  for (var i = 0; i &lt; kSplayTreeSize; i++) {
+    InsertNewNode();
+    if ((i+1) % 20 == 19) {
+      SplayUpdateStats(performance.now());
+    }
+  }
+}
+
+
+function SplayTearDown() {
+  // Allow the garbage collector to reclaim the memory
+  // used by the splay tree no matter how we exit the
+  // tear down function.
+  var keys = splayTree.exportKeys();
+  splayTree = null;
+
+  splaySamples = [];
+
+  // Verify that the splay tree has the right size.
+  var length = keys.length;
+  if (length != kSplayTreeSize) {
+    throw new Error(&quot;Splay tree has wrong size&quot;);
+  }
+
+  // Verify that the splay tree has sorted, unique keys.
+  for (var i = 0; i &lt; length - 1; i++) {
+    if (keys[i] &gt;= keys[i + 1]) {
+      throw new Error(&quot;Splay tree not sorted&quot;);
+    }
+  }
+}
+
+
+function SplayRun() {
+  // Replace a few nodes in the splay tree.
+  for (var i = 0; i &lt; kSplayTreeModifications; i++) {
+    var key = InsertNewNode();
+    var greatest = splayTree.findGreatestLessThan(key);
+    if (greatest == null) splayTree.remove(key);
+    else splayTree.remove(greatest.key);
+  }
+  SplayUpdateStats(performance.now());
+}
+
+
+/**
+ * Constructs a Splay tree.  A splay tree is a self-balancing binary
+ * search tree with the additional property that recently accessed
+ * elements are quick to access again. It performs basic operations
+ * such as insertion, look-up and removal in O(log(n)) amortized time.
+ *
+ * @constructor
+ */
+function SplayTree() {
+};
+
+
+/**
+ * Pointer to the root node of the tree.
+ *
+ * @type {SplayTree.Node}
+ * @private
+ */
+SplayTree.prototype.root_ = null;
+
+
+/**
+ * @return {boolean} Whether the tree is empty.
+ */
+SplayTree.prototype.isEmpty = function() {
+  return !this.root_;
+};
+
+
+/**
+ * Inserts a node into the tree with the specified key and value if
+ * the tree does not already contain a node with the specified key. If
+ * the value is inserted, it becomes the root of the tree.
+ *
+ * @param {number} key Key to insert into the tree.
+ * @param {*} value Value to insert into the tree.
+ */
+SplayTree.prototype.insert = function(key, value) {
+  if (this.isEmpty()) {
+    this.root_ = new SplayTree.Node(key, value);
+    return;
+  }
+  // Splay on the key to move the last node on the search path for
+  // the key to the root of the tree.
+  this.splay_(key);
+  if (this.root_.key == key) {
+    return;
+  }
+  var node = new SplayTree.Node(key, value);
+  if (key &gt; this.root_.key) {
+    node.left = this.root_;
+    node.right = this.root_.right;
+    this.root_.right = null;
+  } else {
+    node.right = this.root_;
+    node.left = this.root_.left;
+    this.root_.left = null;
+  }
+  this.root_ = node;
+};
+
+
+/**
+ * Removes a node with the specified key from the tree if the tree
+ * contains a node with this key. The removed node is returned. If the
+ * key is not found, an exception is thrown.
+ *
+ * @param {number} key Key to find and remove from the tree.
+ * @return {SplayTree.Node} The removed node.
+ */
+SplayTree.prototype.remove = function(key) {
+  if (this.isEmpty()) {
+    throw Error('Key not found: ' + key);
+  }
+  this.splay_(key);
+  if (this.root_.key != key) {
+    throw Error('Key not found: ' + key);
+  }
+  var removed = this.root_;
+  if (!this.root_.left) {
+    this.root_ = this.root_.right;
+  } else {
+    var right = this.root_.right;
+    this.root_ = this.root_.left;
+    // Splay to make sure that the new root has an empty right child.
+    this.splay_(key);
+    // Insert the original right child as the right child of the new
+    // root.
+    this.root_.right = right;
+  }
+  return removed;
+};
+
+
+/**
+ * Returns the node having the specified key or null if the tree doesn't contain
+ * a node with the specified key.
+ *
+ * @param {number} key Key to find in the tree.
+ * @return {SplayTree.Node} Node having the specified key.
+ */
+SplayTree.prototype.find = function(key) {
+  if (this.isEmpty()) {
+    return null;
+  }
+  this.splay_(key);
+  return this.root_.key == key ? this.root_ : null;
+};
+
+
+/**
+ * @return {SplayTree.Node} Node having the maximum key value.
+ */
+SplayTree.prototype.findMax = function(opt_startNode) {
+  if (this.isEmpty()) {
+    return null;
+  }
+  var current = opt_startNode || this.root_;
+  while (current.right) {
+    current = current.right;
+  }
+  return current;
+};
+
+
+/**
+ * @return {SplayTree.Node} Node having the maximum key value that
+ *     is less than the specified key value.
+ */
+SplayTree.prototype.findGreatestLessThan = function(key) {
+  if (this.isEmpty()) {
+    return null;
+  }
+  // Splay on the key to move the node with the given key or the last
+  // node on the search path to the top of the tree.
+  this.splay_(key);
+  // Now the result is either the root node or the greatest node in
+  // the left subtree.
+  if (this.root_.key &lt; key) {
+    return this.root_;
+  } else if (this.root_.left) {
+    return this.findMax(this.root_.left);
+  } else {
+    return null;
+  }
+};
+
+
+/**
+ * @return {Array&lt;*&gt;} An array containing all the keys of tree's nodes.
+ */
+SplayTree.prototype.exportKeys = function() {
+  var result = [];
+  if (!this.isEmpty()) {
+    this.root_.traverse_(function(node) { result.push(node.key); });
+  }
+  return result;
+};
+
+
+/**
+ * Perform the splay operation for the given key. Moves the node with
+ * the given key to the top of the tree.  If no node has the given
+ * key, the last node on the search path is moved to the top of the
+ * tree. This is the simplified top-down splaying algorithm from:
+ * &quot;Self-adjusting Binary Search Trees&quot; by Sleator and Tarjan
+ *
+ * @param {number} key Key to splay the tree on.
+ * @private
+ */
+SplayTree.prototype.splay_ = function(key) {
+  if (this.isEmpty()) {
+    return;
+  }
+  // Create a dummy node.  The use of the dummy node is a bit
+  // counter-intuitive: The right child of the dummy node will hold
+  // the L tree of the algorithm.  The left child of the dummy node
+  // will hold the R tree of the algorithm.  Using a dummy node, left
+  // and right will always be nodes and we avoid special cases.
+  var dummy, left, right;
+  dummy = left = right = new SplayTree.Node(null, null);
+  var current = this.root_;
+  while (true) {
+    if (key &lt; current.key) {
+      if (!current.left) {
+        break;
+      }
+      if (key &lt; current.left.key) {
+        // Rotate right.
+        var tmp = current.left;
+        current.left = tmp.right;
+        tmp.right = current;
+        current = tmp;
+        if (!current.left) {
+          break;
+        }
+      }
+      // Link right.
+      right.left = current;
+      right = current;
+      current = current.left;
+    } else if (key &gt; current.key) {
+      if (!current.right) {
+        break;
+      }
+      if (key &gt; current.right.key) {
+        // Rotate left.
+        var tmp = current.right;
+        current.right = tmp.left;
+        tmp.left = current;
+        current = tmp;
+        if (!current.right) {
+          break;
+        }
+      }
+      // Link left.
+      left.right = current;
+      left = current;
+      current = current.right;
+    } else {
+      break;
+    }
+  }
+  // Assemble.
+  left.right = current.left;
+  right.left = current.right;
+  current.left = dummy.right;
+  current.right = dummy.left;
+  this.root_ = current;
+};
+
+
+/**
+ * Constructs a Splay tree node.
+ *
+ * @param {number} key Key.
+ * @param {*} value Value.
+ */
+SplayTree.Node = function(key, value) {
+  this.key = key;
+  this.value = value;
+};
+
+
+/**
+ * @type {SplayTree.Node}
+ */
+SplayTree.Node.prototype.left = null;
+
+
+/**
+ * @type {SplayTree.Node}
+ */
+SplayTree.Node.prototype.right = null;
+
+
+/**
+ * Performs an ordered traversal of the subtree starting at
+ * this SplayTree.Node.
+ *
+ * @param {function(SplayTree.Node)} f Visitor function.
+ * @private
+ */
+SplayTree.Node.prototype.traverse_ = function(f) {
+  var current = this;
+  while (current) {
+    var left = current.left;
+    if (left) left.traverse_(f);
+    f(current);
+    current = current.right;
+  }
+};
+
+function report(msg)
+{
+    document.getElementById(&quot;console&quot;).innerHTML = msg + &quot;&lt;br/&gt;&quot; + document.getElementById(&quot;console&quot;).innerHTML;
+}
+
+var myChart;
+function start()
+{
+    SplaySetup();
+    var samples = [];
+    var before = performance.now();
+    for (var i = 0; i &lt; 2000; ++i) {
+        SplayRun();
+        var after = performance.now();
+        samples.push(after - before);
+        before = after;
+    }
+    SplayTearDown();
+    
+    var scatterData = [];
+    for (var i = 0; i &lt; samples.length; ++i)
+        scatterData.push({x: i + 1, y: samples[i]});
+    
+    if (myChart)
+        myChart.destroy();
+    myChart = new Chart(
+        document.getElementById(&quot;myChart&quot;),
+        {
+            type: &quot;line&quot;,
+            data: {
+                datasets: [{
+                    label: &quot;Splay Tick Times&quot;,
+                    pointBorderColor: &quot;rgba(0,0,0,0)&quot;,
+                    borderColor: &quot;rgba(50,50,150,0.8)&quot;,
+                    pointRadius: 0,
+                    data: scatterData
+                }]
+            },
+            options: {
+                scales: {
+                    xAxes: [{
+                        type: 'linear',
+                        position: 'bottom',
+                        scaleLabel: {
+                            display: true,
+                            labelString: &quot;Splay Iteration&quot;,
+                            fontSize: 24
+                        },
+                        ticks: {
+                            fontSize: 20
+                        }
+                    }],
+                    yAxes: [{
+                        scaleLabel: {
+                            display: true,
+                            labelString: &quot;Milliseconds&quot;,
+                            fontSize: 24
+                        },
+                        ticks: {
+                            fontSize: 20
+                        }
+                    }]
+                },
+                legend: {
+                    display: false
+                },
+                title: {
+                    display: true,
+                    fontSize: 27,
+                    text: &quot;Max latency: &quot; + Math.max.apply(Math, samples).toPrecision(4) + &quot; ms.&quot;
+                }
+            }
+        });
+    
+    report(&quot;JetStream-like Latency Score: &quot; + Math.round(4000 / BenchmarkSuite.AverageAbovePercentile(samples, 99.5)));
+    
+    var sumOfSquares = 0;
+    for (var i = 0; i &lt; samples.length; ++i)
+        sumOfSquares += samples[i] * samples[i];
+    report(&quot;Octane-like Latency Score: &quot; + Math.round(27395.14 / Math.sqrt(sumOfSquares / samples.length)));
+}
+
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;h1&gt;Splay Detail&lt;/h1&gt;
+&lt;p&gt;&lt;a href=&quot;javascript:void start()&quot;&gt;Start!&lt;/a&gt;&lt;/p&gt;
+&lt;p&gt;&lt;canvas id=&quot;myChart&quot; width=&quot;800&quot; height=&quot;400&quot;&gt;&lt;/canvas&gt;&lt;/p&gt;
+&lt;p&gt;&lt;div id=&quot;console&quot;&gt;&lt;/div&gt;&lt;/p&gt;
+&lt;/body&gt;
+&lt;/html&gt;
+
</ins></span></pre></div>
<a id="trunkPerformanceTestsJetStreamcdjsbenchmarkjs"></a>
<div class="modfile"><h4>Modified: trunk/PerformanceTests/JetStream/cdjs/benchmark.js (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/JetStream/cdjs/benchmark.js        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/PerformanceTests/JetStream/cdjs/benchmark.js        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx">     var numFrames = configuration.numFrames;
</span><span class="cx">     var expectedCollisions = configuration.expectedCollisions;
</span><span class="cx">     var percentile = configuration.percentile;
</span><ins>+    var exclude = configuration.exclude;
</ins><span class="cx"> 
</span><span class="cx">     var simulator = new Simulator(numAircraft);
</span><span class="cx">     var detector = new CollisionDetector();
</span><span class="lines">@@ -47,9 +48,13 @@
</span><span class="cx">             numCollisions: collisions.length
</span><span class="cx">         };
</span><span class="cx">         if (verbosity &gt;= 2)
</span><ins>+            print(&quot;CDjs: &quot; + result.time);
+        if (verbosity &gt;= 3)
</ins><span class="cx">             result.collisions = collisions;
</span><span class="cx">         results.push(result);
</span><span class="cx">     }
</span><ins>+    
+    results.splice(0, exclude);
</ins><span class="cx"> 
</span><span class="cx">     if (verbosity &gt;= 1) {
</span><span class="cx">         for (var i = 0; i &lt; results.length; ++i) {
</span><span class="lines">@@ -85,17 +90,30 @@
</span><span class="cx">         numAircraft: 1000,
</span><span class="cx">         numFrames: 200,
</span><span class="cx">         expectedCollisions: 14484,
</span><del>-        percentile: 95
</del><ins>+        percentile: 95,
+        exclude: 0
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+function longBenchmark() {
+    return benchmarkImpl({
+        verbosity: 0,
+        numAircraft: 1000,
+        numFrames: 20000,
+        expectedCollisions: 697299,
+        percentile: 99.5,
+        exclude: 0
+    });
+}
+
</ins><span class="cx"> function largeBenchmark() {
</span><span class="cx">     return benchmarkImpl({
</span><del>-        verbosity: 0,
</del><ins>+        verbosity: 1,
</ins><span class="cx">         numAircraft: 20000,
</span><del>-        numFrames: 100,
-        expectedCollisions: 5827,
-        percentile: 95
</del><ins>+        numFrames: 110,
+        expectedCollisions: 7316,
+        percentile: 97,
+        exclude: 10
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkPerformanceTestsJetStreamcdjslongjs"></a>
<div class="addfile"><h4>Added: trunk/PerformanceTests/JetStream/cdjs/long.js (0 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/JetStream/cdjs/long.js                                (rev 0)
+++ trunk/PerformanceTests/JetStream/cdjs/long.js        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -0,0 +1,45 @@
</span><ins>+// Copyright (c) 2001-2010, Purdue University. All rights reserved.
+// Copyright (C) 2016 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:
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * 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.
+//  * Neither the name of the Purdue University nor the
+//    names of its contributors may be used to endorse or promote products
+//    derived from this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot; 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 THE COPYRIGHT HOLDER 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.
+
+// This is run as a JSC stress test. Let the harness know that this is a slow test.
+//@ slow!
+
+load(&quot;constants.js&quot;);
+load(&quot;util.js&quot;);
+load(&quot;red_black_tree.js&quot;);
+load(&quot;call_sign.js&quot;);
+load(&quot;vector_2d.js&quot;);
+load(&quot;vector_3d.js&quot;);
+load(&quot;motion.js&quot;);
+load(&quot;reduce_collision_set.js&quot;);
+load(&quot;simulator.js&quot;);
+load(&quot;collision.js&quot;);
+load(&quot;collision_detector.js&quot;);
+load(&quot;benchmark.js&quot;);
+
+var result = longBenchmark();
+
+print(&quot;Average worst case: &quot; + result + &quot; ms.&quot;);
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreAPIJSAPIWrapperObjectmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/API/JSAPIWrapperObject.mm (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/API/JSAPIWrapperObject.mm        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/API/JSAPIWrapperObject.mm        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -101,8 +101,9 @@
</span><span class="cx">     JSAPIWrapperObject* thisObject = JSC::jsCast&lt;JSAPIWrapperObject*&gt;(cell);
</span><span class="cx">     Base::visitChildren(cell, visitor);
</span><span class="cx"> 
</span><del>-    if (thisObject-&gt;wrappedObject())
-        scanExternalObjectGraph(cell-&gt;structure()-&gt;globalObject()-&gt;vm(), visitor, thisObject-&gt;wrappedObject());
</del><ins>+    void* wrappedObject = thisObject-&gt;wrappedObject();
+    if (wrappedObject)
+        scanExternalObjectGraph(visitor.vm(), visitor, wrappedObject);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreAPIJSCallbackObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/API/JSCallbackObject.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/API/JSCallbackObject.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/API/JSCallbackObject.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -71,9 +71,10 @@
</span><span class="cx"> 
</span><span class="cx">     void visitChildren(SlotVisitor&amp; visitor)
</span><span class="cx">     {
</span><del>-        if (!m_privateProperties)
</del><ins>+        JSPrivatePropertyMap* properties = m_privateProperties.get();
+        if (!properties)
</ins><span class="cx">             return;
</span><del>-        m_privateProperties-&gt;visitChildren(visitor);
</del><ins>+        properties-&gt;visitChildren(visitor);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void* privateData;
</span><span class="lines">@@ -91,6 +92,7 @@
</span><span class="cx">         
</span><span class="cx">         void setPrivateProperty(VM&amp; vm, JSCell* owner, const Identifier&amp; propertyName, JSValue value)
</span><span class="cx">         {
</span><ins>+            LockHolder locker(m_lock);
</ins><span class="cx">             WriteBarrier&lt;Unknown&gt; empty;
</span><span class="cx">             m_propertyMap.add(propertyName.impl(), empty).iterator-&gt;value.set(vm, owner, value);
</span><span class="cx">         }
</span><span class="lines">@@ -97,11 +99,13 @@
</span><span class="cx">         
</span><span class="cx">         void deletePrivateProperty(const Identifier&amp; propertyName)
</span><span class="cx">         {
</span><ins>+            LockHolder locker(m_lock);
</ins><span class="cx">             m_propertyMap.remove(propertyName.impl());
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         void visitChildren(SlotVisitor&amp; visitor)
</span><span class="cx">         {
</span><ins>+            LockHolder locker(m_lock);
</ins><span class="cx">             for (PrivatePropertyMap::iterator ptr = m_propertyMap.begin(); ptr != m_propertyMap.end(); ++ptr) {
</span><span class="cx">                 if (ptr-&gt;value)
</span><span class="cx">                     visitor.append(&amp;ptr-&gt;value);
</span><span class="lines">@@ -111,6 +115,7 @@
</span><span class="cx">     private:
</span><span class="cx">         typedef HashMap&lt;RefPtr&lt;UniquedStringImpl&gt;, WriteBarrier&lt;Unknown&gt;, IdentifierRepHash&gt; PrivatePropertyMap;
</span><span class="cx">         PrivatePropertyMap m_propertyMap;
</span><ins>+        Lock m_lock;
</ins><span class="cx">     };
</span><span class="cx">     std::unique_ptr&lt;JSPrivatePropertyMap&gt; m_privateProperties;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -209,6 +209,7 @@
</span><span class="cx">     bytecode/DataFormat.cpp
</span><span class="cx">     bytecode/DeferredCompilationCallback.cpp
</span><span class="cx">     bytecode/DeferredSourceDump.cpp
</span><ins>+    bytecode/DirectEvalCodeCache.cpp
</ins><span class="cx">     bytecode/EvalCodeBlock.cpp
</span><span class="cx">     bytecode/ExecutionCounter.cpp
</span><span class="cx">     bytecode/ExitKind.cpp
</span><span class="lines">@@ -498,6 +499,7 @@
</span><span class="cx">     heap/MutatorState.cpp
</span><span class="cx">     heap/SlotVisitor.cpp
</span><span class="cx">     heap/StopIfNecessaryTimer.cpp
</span><ins>+    heap/VisitRaceKey.cpp
</ins><span class="cx">     heap/Weak.cpp
</span><span class="cx">     heap/WeakBlock.cpp
</span><span class="cx">     heap/WeakHandleOwner.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -1,3 +1,231 @@
</span><ins>+2016-12-06  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Concurrent GC should be stable enough to land enabled on X86_64
+        https://bugs.webkit.org/show_bug.cgi?id=164990
+
+        Reviewed by Geoffrey Garen.
+        
+        This fixes a ton of performance and correctness bugs revealed by getting the concurrent GC to
+        be stable enough to land enabled.
+        
+        I had to redo the JSObject::visitChildren concurrency protocol again. This time I think it's
+        even more correct than ever!
+        
+        This is an enormous win on JetStream/splay-latency and Octane/SplayLatency. It looks to be
+        mostly neutral on everything else, though Speedometer is showing statistically weak signs of a
+        slight regression.
+
+        * API/JSAPIWrapperObject.mm: Added locking.
+        (JSC::JSAPIWrapperObject::visitChildren):
+        * API/JSCallbackObject.h: Added locking.
+        (JSC::JSCallbackObjectData::visitChildren):
+        (JSC::JSCallbackObjectData::JSPrivatePropertyMap::setPrivateProperty):
+        (JSC::JSCallbackObjectData::JSPrivatePropertyMap::deletePrivateProperty):
+        (JSC::JSCallbackObjectData::JSPrivatePropertyMap::visitChildren):
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::UnconditionalFinalizer::finalizeUnconditionally): This had a TOCTOU race on shouldJettisonDueToOldAge.
+        (JSC::EvalCodeCache::visitAggregate): Moved to EvalCodeCache.cpp.
+        * bytecode/DirectEvalCodeCache.cpp: Added. Outlined some functions and made them use locks.
+        (JSC::DirectEvalCodeCache::setSlow):
+        (JSC::DirectEvalCodeCache::clear):
+        (JSC::DirectEvalCodeCache::visitAggregate):
+        * bytecode/DirectEvalCodeCache.h:
+        (JSC::DirectEvalCodeCache::set):
+        (JSC::DirectEvalCodeCache::clear): Deleted.
+        * bytecode/UnlinkedCodeBlock.cpp: Added locking.
+        (JSC::UnlinkedCodeBlock::visitChildren):
+        (JSC::UnlinkedCodeBlock::setInstructions):
+        (JSC::UnlinkedCodeBlock::shrinkToFit):
+        * bytecode/UnlinkedCodeBlock.h: Added locking.
+        (JSC::UnlinkedCodeBlock::addRegExp):
+        (JSC::UnlinkedCodeBlock::addConstant):
+        (JSC::UnlinkedCodeBlock::addFunctionDecl):
+        (JSC::UnlinkedCodeBlock::addFunctionExpr):
+        (JSC::UnlinkedCodeBlock::createRareDataIfNecessary):
+        (JSC::UnlinkedCodeBlock::shrinkToFit): Deleted.
+        * debugger/Debugger.cpp: Use the right delete API.
+        (JSC::Debugger::recompileAllJSFunctions):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects): Fix a pre-existing bug in ToFunction constant folding.
+        * dfg/DFGClobberize.h: Add support for nuking.
+        (JSC::DFG::clobberize):
+        * dfg/DFGClobbersExitState.cpp: Add support for nuking.
+        (JSC::DFG::clobbersExitState):
+        * dfg/DFGFixupPhase.cpp: Add support for nuking.
+        (JSC::DFG::FixupPhase::fixupNode):
+        (JSC::DFG::FixupPhase::indexForChecks):
+        (JSC::DFG::FixupPhase::originForCheck):
+        (JSC::DFG::FixupPhase::speculateForBarrier):
+        (JSC::DFG::FixupPhase::insertCheck):
+        (JSC::DFG::FixupPhase::fixupChecksInBlock):
+        * dfg/DFGSpeculativeJIT.cpp: Add support for nuking.
+        (JSC::DFG::SpeculativeJIT::compileAllocatePropertyStorage):
+        (JSC::DFG::SpeculativeJIT::compileReallocatePropertyStorage):
+        * ftl/FTLLowerDFGToB3.cpp: Add support for nuking.
+        (JSC::FTL::DFG::LowerDFGToB3::allocatePropertyStorage):
+        (JSC::FTL::DFG::LowerDFGToB3::reallocatePropertyStorage):
+        (JSC::FTL::DFG::LowerDFGToB3::mutatorFence):
+        (JSC::FTL::DFG::LowerDFGToB3::nukeStructureAndSetButterfly):
+        (JSC::FTL::DFG::LowerDFGToB3::setButterfly): Deleted.
+        * heap/CodeBlockSet.cpp: We need to be more careful about the CodeBlockSet workflow during GC, since we will allocate CodeBlocks in eden while collecting.
+        (JSC::CodeBlockSet::clearMarksForFullCollection):
+        (JSC::CodeBlockSet::deleteUnmarkedAndUnreferenced):
+        * heap/Heap.cpp: Added code to measure max pauses. Added a better collectContinuously mode.
+        (JSC::Heap::lastChanceToFinalize): Stop the collectContinuously thread.
+        (JSC::Heap::harvestWeakReferences): Inline SlotVisitor::harvestWeakReferences.
+        (JSC::Heap::finalizeUnconditionalFinalizers): Inline SlotVisitor::finalizeUnconditionalReferences.
+        (JSC::Heap::markToFixpoint): We need to do some MarkedSpace stuff before every conservative scan, rather than just at the start of marking, so we now call prepareForConservativeScan() before each conservative scan. Also call a less-parallel version of drainInParallel when the mutator is running.
+        (JSC::Heap::collectInThread): Inline Heap::prepareForAllocation().
+        (JSC::Heap::stopIfNecessarySlow): We need to be more careful about ensuring that we run finalization before and after stopping. Also, we should sanitize stack when stopping the world.
+        (JSC::Heap::acquireAccessSlow): Add some optional debug prints.
+        (JSC::Heap::handleNeedFinalize): Assert that we are running this when the world is not stopped.
+        (JSC::Heap::finalize): Remove the old collectContinuously code.
+        (JSC::Heap::requestCollection): We don't need to sanitize stack here anymore.
+        (JSC::Heap::notifyIsSafeToCollect): Start the collectContinuously thread. It will request collection 1 KHz.
+        (JSC::Heap::prepareForAllocation): Deleted.
+        (JSC::Heap::preventCollection): Prevent any new concurrent GCs from being initiated.
+        (JSC::Heap::allowCollection):
+        (JSC::Heap::forEachSlotVisitor): Allows us to safely iterate slot visitors.
+        * heap/Heap.h:
+        * heap/HeapInlines.h:
+        (JSC::Heap::writeBarrier): If the 'to' cell is not NewWhite then it could be AnthraciteOrBlack. During a full collection, objects may be AnthraciteOrBlack from a previous GC. Turns out, we don't benefit from this optimization so we can just kill it.
+        * heap/HeapSnapshotBuilder.cpp:
+        (JSC::HeapSnapshotBuilder::buildSnapshot): This needs to use PreventCollectionScope to ensure snapshot soundness.
+        * heap/ListableHandler.h:
+        (JSC::ListableHandler::isOnList): Useful helper.
+        * heap/LockDuringMarking.h:
+        (JSC::lockDuringMarking): It's a locker that only locks while we're marking.
+        * heap/MarkedAllocator.cpp:
+        (JSC::MarkedAllocator::addBlock): Hold the bitvector lock while resizing.
+        * heap/MarkedBlock.cpp: Hold the bitvector lock while accessing the bitvectors while the mutator is running.
+        * heap/MarkedSpace.cpp:
+        (JSC::MarkedSpace::prepareForConservativeScan): We used to do this in prepareForMarking, but we need to do it before each conservative scan not just before marking.
+        (JSC::MarkedSpace::prepareForMarking): Remove the logic moved to prepareForConservativeScan.
+        * heap/MarkedSpace.h:
+        * heap/PreventCollectionScope.h: Added.
+        * heap/SlotVisitor.cpp: Refactored drainFromShared so that we can write a similar function called drainInParallelPassively.
+        (JSC::SlotVisitor::updateMutatorIsStopped): Update whether we can use &quot;fast&quot; scanning.
+        (JSC::SlotVisitor::mutatorIsStoppedIsUpToDate):
+        (JSC::SlotVisitor::didReachTermination):
+        (JSC::SlotVisitor::hasWork):
+        (JSC::SlotVisitor::drain): This now uses the rightToRun lock to allow the main GC thread to safepoint the workers.
+        (JSC::SlotVisitor::drainFromShared):
+        (JSC::SlotVisitor::drainInParallelPassively): This runs marking with one fewer threads than normal. It's useful for when we have resumed the mutator, since then the mutator has a better chance of getting on a core.
+        (JSC::SlotVisitor::addWeakReferenceHarvester):
+        (JSC::SlotVisitor::addUnconditionalFinalizer):
+        (JSC::SlotVisitor::harvestWeakReferences): Deleted.
+        (JSC::SlotVisitor::finalizeUnconditionalFinalizers): Deleted.
+        * heap/SlotVisitor.h:
+        * heap/SlotVisitorInlines.h: Outline stuff.
+        (JSC::SlotVisitor::addWeakReferenceHarvester): Deleted.
+        (JSC::SlotVisitor::addUnconditionalFinalizer): Deleted.
+        * runtime/InferredType.cpp: This needed thread safety.
+        (JSC::InferredType::visitChildren): This needs to keep its structure finalizer alive until it runs.
+        (JSC::InferredType::set):
+        (JSC::InferredType::InferredStructureFinalizer::finalizeUnconditionally):
+        * runtime/InferredType.h:
+        * runtime/InferredValue.cpp: This needed thread safety.
+        (JSC::InferredValue::visitChildren):
+        (JSC::InferredValue::ValueCleanup::finalizeUnconditionally):
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::unshiftCountSlowCase): Update to use new butterfly API.
+        (JSC::JSArray::unshiftCountWithArrayStorage): Update to use new butterfly API.
+        * runtime/JSArrayBufferView.cpp:
+        (JSC::JSArrayBufferView::visitChildren): Thread safety.
+        * runtime/JSCell.h:
+        (JSC::JSCell::setStructureIDDirectly): This is used for nuking the structure.
+        (JSC::JSCell::InternalLocker::InternalLocker): Deleted. The cell is now the lock.
+        (JSC::JSCell::InternalLocker::~InternalLocker): Deleted. The cell is now the lock.
+        * runtime/JSCellInlines.h:
+        (JSC::JSCell::structure): Clean this up.
+        (JSC::JSCell::lock): The cell is now the lock.
+        (JSC::JSCell::tryLock):
+        (JSC::JSCell::unlock):
+        (JSC::JSCell::isLocked):
+        (JSC::JSCell::lockInternalLock): Deleted.
+        (JSC::JSCell::unlockInternalLock): Deleted.
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::visitChildren): Thread safety.
+        * runtime/JSGenericTypedArrayViewInlines.h:
+        (JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::visitChildren): Thread safety.
+        (JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::slowDownAndWasteMemory): Thread safety.
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::markAuxiliaryAndVisitOutOfLineProperties): Factor out this &quot;easy&quot; step of butterfly visiting.
+        (JSC::JSObject::visitButterfly): Make this achieve 100% precision about structure-butterfly relationships. This relies on the mutator &quot;nuking&quot; the structure prior to &quot;locked&quot; structure-butterfly transitions.
+        (JSC::JSObject::visitChildren): Use the new, nicer API.
+        (JSC::JSFinalObject::visitChildren): Use the new, nicer API.
+        (JSC::JSObject::enterDictionaryIndexingModeWhenArrayStorageAlreadyExists): Use the new butterfly API.
+        (JSC::JSObject::createInitialUndecided): Use the new butterfly API.
+        (JSC::JSObject::createInitialInt32): Use the new butterfly API.
+        (JSC::JSObject::createInitialDouble): Use the new butterfly API.
+        (JSC::JSObject::createInitialContiguous): Use the new butterfly API.
+        (JSC::JSObject::createArrayStorage): Use the new butterfly API.
+        (JSC::JSObject::convertUndecidedToContiguous): Use the new butterfly API.
+        (JSC::JSObject::convertUndecidedToArrayStorage): Use the new butterfly API.
+        (JSC::JSObject::convertInt32ToArrayStorage): Use the new butterfly API.
+        (JSC::JSObject::convertDoubleToContiguous): Use the new butterfly API.
+        (JSC::JSObject::convertDoubleToArrayStorage): Use the new butterfly API.
+        (JSC::JSObject::convertContiguousToArrayStorage): Use the new butterfly API.
+        (JSC::JSObject::increaseVectorLength): Use the new butterfly API.
+        (JSC::JSObject::shiftButterflyAfterFlattening): Use the new butterfly API.
+        * runtime/JSObject.h:
+        (JSC::JSObject::setButterfly): This now does all of the fences. Only use this when you are not also transitioning the structure or the structure's lastOffset.
+        (JSC::JSObject::nukeStructureAndSetButterfly): Use this when doing locked structure-butterfly transitions.
+        * runtime/JSObjectInlines.h:
+        (JSC::JSObject::putDirectWithoutTransition): Use the newly factored out API.
+        (JSC::JSObject::prepareToPutDirectWithoutTransition): Factor this out!
+        (JSC::JSObject::putDirectInternal): Use the newly factored out API.
+        * runtime/JSPropertyNameEnumerator.cpp:
+        (JSC::JSPropertyNameEnumerator::finishCreation): Locks!
+        (JSC::JSPropertyNameEnumerator::visitChildren): Locks!
+        * runtime/JSSegmentedVariableObject.cpp:
+        (JSC::JSSegmentedVariableObject::visitChildren): Locks!
+        * runtime/JSString.cpp:
+        (JSC::JSString::visitChildren): Thread safety.
+        * runtime/ModuleProgramExecutable.cpp:
+        (JSC::ModuleProgramExecutable::visitChildren): Thread safety.
+        * runtime/Options.cpp: For now we disable concurrent GC on not-X86_64.
+        (JSC::recomputeDependentOptions):
+        * runtime/Options.h: Change the default max GC parallelism to 8. I don't know why it was still 7.
+        * runtime/SamplingProfiler.cpp:
+        (JSC::SamplingProfiler::stackTracesAsJSON): This needs to defer GC before grabbing its lock.
+        * runtime/SparseArrayValueMap.cpp: This needed thread safety.
+        (JSC::SparseArrayValueMap::add):
+        (JSC::SparseArrayValueMap::remove):
+        (JSC::SparseArrayValueMap::visitChildren):
+        * runtime/SparseArrayValueMap.h:
+        * runtime/Structure.cpp: This had a race between addNewPropertyTransition and visitChildren.
+        (JSC::Structure::Structure):
+        (JSC::Structure::materializePropertyTable):
+        (JSC::Structure::addNewPropertyTransition):
+        (JSC::Structure::flattenDictionaryStructure):
+        (JSC::Structure::add): Help out with nuking support - the m_offset needs to play along.
+        (JSC::Structure::visitChildren):
+        * runtime/Structure.h: Make some useful things public - like the notion of a lastOffset.
+        * runtime/StructureChain.cpp:
+        (JSC::StructureChain::visitChildren): Thread safety!
+        * runtime/StructureChain.h: Thread safety!
+        * runtime/StructureIDTable.cpp:
+        (JSC::StructureIDTable::allocateID): Ensure that we don't get nuked IDs.
+        * runtime/StructureIDTable.h: Add the notion of a nuked ID! It's a bit that the runtime never sees except during specific shady actions like locked structure-butterfly transitions. &quot;Nuking&quot; tells the GC to steer clear and rescan once we fire the barrier.
+        (JSC::nukedStructureIDBit):
+        (JSC::nuke):
+        (JSC::isNuked):
+        (JSC::decontaminate):
+        * runtime/StructureInlines.h:
+        (JSC::Structure::hasIndexingHeader): Better API.
+        (JSC::Structure::add):
+        * runtime/VM.cpp: Better GC interaction.
+        (JSC::VM::ensureWatchdog):
+        (JSC::VM::deleteAllLinkedCode):
+        (JSC::VM::deleteAllCode):
+        * runtime/VM.h:
+        (JSC::VM::getStructure): Why wasn't this always an API!
+        * runtime/WebAssemblyExecutable.cpp:
+        (JSC::WebAssemblyExecutable::visitChildren): Thread safety.
+
</ins><span class="cx"> 2016-12-08  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Enable SharedArrayBuffer, remove the flag
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -136,6 +136,7 @@
</span><span class="cx">                 0F2017861DCAE14C00EA5950 /* DFGNodeFlowProjection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2017831DCAE14700EA5950 /* DFGNodeFlowProjection.cpp */; };
</span><span class="cx">                 0F2017891DCB942400EA5950 /* DFGNodeAbstractValuePair.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2017881DCB942200EA5950 /* DFGNodeAbstractValuePair.h */; };
</span><span class="cx">                 0F20178A1DCB942600EA5950 /* DFGNodeAbstractValuePair.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2017871DCB942200EA5950 /* DFGNodeAbstractValuePair.cpp */; };
</span><ins>+                0F208AD71DF0925D007D3269 /* LockDuringMarking.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F208AD61DF0925A007D3269 /* LockDuringMarking.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F20C2591A8013AB00DA3229 /* VirtualRegister.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F20C2581A8013AB00DA3229 /* VirtualRegister.cpp */; };
</span><span class="cx">                 0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F21C27F14BEAA8200ADC64B /* BytecodeConventions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -279,6 +280,7 @@
</span><span class="cx">                 0F2DD8151AB3D8BE00BBB8E8 /* DFGForAllKills.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2DD8101AB3D8BE00BBB8E8 /* DFGForAllKills.h */; };
</span><span class="cx">                 0F2E892C16D028AD009E4FD2 /* UnusedPointer.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2F16828A7E003C2F8D /* UnusedPointer.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F2E892D16D02BAF009E4FD2 /* DFGMinifiedID.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB4B51016B3A964003F696B /* DFGMinifiedID.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F2EBBAB1DEDF95000990369 /* DirectEvalCodeCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2EBBAA1DEDF94E00990369 /* DirectEvalCodeCache.cpp */; };
</ins><span class="cx">                 0F2FC77216E12F710038D976 /* DFGDCEPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2FC77016E12F6F0038D976 /* DFGDCEPhase.cpp */; };
</span><span class="cx">                 0F2FC77316E12F740038D976 /* DFGDCEPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */; };
</span><span class="cx">                 0F2FCCF918A60070001A27F8 /* DFGGraphSafepoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2FCCF218A60070001A27F8 /* DFGGraphSafepoint.cpp */; };
</span><span class="lines">@@ -419,6 +421,7 @@
</span><span class="cx">                 0F5A1274192D9FDF008764A3 /* DFGDoesGC.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5A1272192D9FDF008764A3 /* DFGDoesGC.h */; };
</span><span class="cx">                 0F5A6283188C98D40072C9DF /* FTLValueRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F5A6281188C98D40072C9DF /* FTLValueRange.cpp */; };
</span><span class="cx">                 0F5A6284188C98D40072C9DF /* FTLValueRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5A6282188C98D40072C9DF /* FTLValueRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F5AE2C41DF4F2800066EFE1 /* VMInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F5B4A331C84F0D600F1B17E /* SlowPathReturnType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5B4A321C84F0D600F1B17E /* SlowPathReturnType.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F5D085D1B8CF99D001143B4 /* DFGNodeOrigin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F5D085C1B8CF99D001143B4 /* DFGNodeOrigin.cpp */; };
</span><span class="cx">                 0F5EF91E16878F7A003E5C25 /* JITThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F5EF91B16878F78003E5C25 /* JITThunks.cpp */; };
</span><span class="lines">@@ -567,6 +570,8 @@
</span><span class="cx">                 0F93B4AA18B92C4D00178A3F /* PutByIdVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93B4A818B92C4D00178A3F /* PutByIdVariant.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F9495871C57F47500413A48 /* B3StackSlot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9495851C57F47500413A48 /* B3StackSlot.cpp */; };
</span><span class="cx">                 0F9495881C57F47500413A48 /* B3StackSlot.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9495861C57F47500413A48 /* B3StackSlot.h */; };
</span><ins>+                0F952AA11DF7860900E06FBD /* VisitRaceKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F952AA01DF7860700E06FBD /* VisitRaceKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F952AA21DF7860D00E06FBD /* VisitRaceKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F952A9F1DF7860700E06FBD /* VisitRaceKey.cpp */; };
</ins><span class="cx">                 0F952ABC1B487A7700C367C5 /* TrackedReferences.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F952ABA1B487A7700C367C5 /* TrackedReferences.cpp */; };
</span><span class="cx">                 0F952ABD1B487A7700C367C5 /* TrackedReferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F952ABB1B487A7700C367C5 /* TrackedReferences.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F9630391D4192C6005609D9 /* AllocatorAttributes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9630351D4192C3005609D9 /* AllocatorAttributes.cpp */; };
</span><span class="lines">@@ -655,6 +660,8 @@
</span><span class="cx">                 0FB7F39C15ED8E4600F167B2 /* PropertyStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB7F39015ED8E3800F167B2 /* PropertyStorage.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FB7F39D15ED8E4600F167B2 /* TypeError.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB7F39115ED8E3800F167B2 /* TypeError.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FB7F39E15ED8E4600F167B2 /* SparseArrayValueMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB7F39215ED8E3800F167B2 /* SparseArrayValueMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0FBB73B81DEF3AAE002C009E /* PreventCollectionScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBB73B61DEF3AAC002C009E /* PreventCollectionScope.h */; };
+                0FBB73BB1DEF8645002C009E /* DeleteAllCodeEffort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBB73BA1DEF8644002C009E /* DeleteAllCodeEffort.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0FBC0AE71496C7C400D4FBDD /* DFGExitProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBC0AE41496C7C100D4FBDD /* DFGExitProfile.cpp */; };
</span><span class="cx">                 0FBC0AE81496C7C700D4FBDD /* DFGExitProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FBD7E691447999600481315 /* CodeOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBD7E671447998F00481315 /* CodeOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -2554,6 +2561,7 @@
</span><span class="cx">                 0F2017841DCAE14700EA5950 /* DFGNodeFlowProjection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeFlowProjection.h; path = dfg/DFGNodeFlowProjection.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F2017871DCB942200EA5950 /* DFGNodeAbstractValuePair.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGNodeAbstractValuePair.cpp; path = dfg/DFGNodeAbstractValuePair.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F2017881DCB942200EA5950 /* DFGNodeAbstractValuePair.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeAbstractValuePair.h; path = dfg/DFGNodeAbstractValuePair.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F208AD61DF0925A007D3269 /* LockDuringMarking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LockDuringMarking.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F20C2581A8013AB00DA3229 /* VirtualRegister.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VirtualRegister.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeSpecializationKind.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeConventions.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -2695,6 +2703,7 @@
</span><span class="cx">                 0F2DD80E1AB3D8BE00BBB8E8 /* DFGArgumentsUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGArgumentsUtilities.cpp; path = dfg/DFGArgumentsUtilities.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F2DD80F1AB3D8BE00BBB8E8 /* DFGArgumentsUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArgumentsUtilities.h; path = dfg/DFGArgumentsUtilities.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F2DD8101AB3D8BE00BBB8E8 /* DFGForAllKills.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGForAllKills.h; path = dfg/DFGForAllKills.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F2EBBAA1DEDF94E00990369 /* DirectEvalCodeCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectEvalCodeCache.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F2FC77016E12F6F0038D976 /* DFGDCEPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDCEPhase.cpp; path = dfg/DFGDCEPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDCEPhase.h; path = dfg/DFGDCEPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F2FCCF218A60070001A27F8 /* DFGGraphSafepoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGGraphSafepoint.cpp; path = dfg/DFGGraphSafepoint.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -2980,6 +2989,8 @@
</span><span class="cx">                 0F93B4A818B92C4D00178A3F /* PutByIdVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutByIdVariant.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F9495851C57F47500413A48 /* B3StackSlot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3StackSlot.cpp; path = b3/B3StackSlot.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F9495861C57F47500413A48 /* B3StackSlot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3StackSlot.h; path = b3/B3StackSlot.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F952A9F1DF7860700E06FBD /* VisitRaceKey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VisitRaceKey.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F952AA01DF7860700E06FBD /* VisitRaceKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VisitRaceKey.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F952ABA1B487A7700C367C5 /* TrackedReferences.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrackedReferences.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F952ABB1B487A7700C367C5 /* TrackedReferences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackedReferences.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F9630351D4192C3005609D9 /* AllocatorAttributes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AllocatorAttributes.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -3078,6 +3089,8 @@
</span><span class="cx">                 0FB7F39015ED8E3800F167B2 /* PropertyStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PropertyStorage.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FB7F39115ED8E3800F167B2 /* TypeError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeError.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FB7F39215ED8E3800F167B2 /* SparseArrayValueMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SparseArrayValueMap.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0FBB73B61DEF3AAC002C009E /* PreventCollectionScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PreventCollectionScope.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FBB73BA1DEF8644002C009E /* DeleteAllCodeEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeleteAllCodeEffort.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0FBC0AE41496C7C100D4FBDD /* DFGExitProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DFGExitProfile.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFGExitProfile.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FBD7E671447998F00481315 /* CodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeOrigin.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5644,6 +5657,7 @@
</span><span class="cx">                                 149DAAF212EB559D0083B12B /* ConservativeRoots.h */,
</span><span class="cx">                                 2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */,
</span><span class="cx">                                 0F136D4B174AD69B0075B354 /* DeferGC.h */,
</span><ins>+                                0FBB73BA1DEF8644002C009E /* DeleteAllCodeEffort.h */,
</ins><span class="cx">                                 0F9630371D4192C3005609D9 /* DestructionMode.cpp */,
</span><span class="cx">                                 0F9630381D4192C3005609D9 /* DestructionMode.h */,
</span><span class="cx">                                 2A83638318D7D0EE0000EBCC /* EdenGCActivityCallback.cpp */,
</span><span class="lines">@@ -5711,6 +5725,7 @@
</span><span class="cx">                                 FE3913531B794AC900EDAF71 /* LiveObjectList.h */,
</span><span class="cx">                                 142E3130134FF0A600AFADB5 /* Local.h */,
</span><span class="cx">                                 142E3131134FF0A600AFADB5 /* LocalScope.h */,
</span><ins>+                                0F208AD61DF0925A007D3269 /* LockDuringMarking.h */,
</ins><span class="cx">                                 14B7233F12D7D0DA003BD5ED /* MachineStackMarker.cpp */,
</span><span class="cx">                                 14B7234012D7D0DA003BD5ED /* MachineStackMarker.h */,
</span><span class="cx">                                 C2B916C414DA040C00CBAC86 /* MarkedAllocator.cpp */,
</span><span class="lines">@@ -5727,6 +5742,7 @@
</span><span class="cx">                                 0FA762021DB9242300B7A2FD /* MutatorState.cpp */,
</span><span class="cx">                                 0FA762031DB9242300B7A2FD /* MutatorState.h */,
</span><span class="cx">                                 ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */,
</span><ins>+                                0FBB73B61DEF3AAC002C009E /* PreventCollectionScope.h */,
</ins><span class="cx">                                 0F7CF94E1DBEEE860098CC12 /* ReleaseHeapAccessScope.h */,
</span><span class="cx">                                 C225494215F7DBAA0065E898 /* SlotVisitor.cpp */,
</span><span class="cx">                                 14BA78F013AAB88F005B7C2C /* SlotVisitor.h */,
</span><span class="lines">@@ -5737,6 +5753,8 @@
</span><span class="cx">                                 145722851437E140005FDE26 /* StrongInlines.h */,
</span><span class="cx">                                 141448CC13A1783700F5BA1A /* TinyBloomFilter.h */,
</span><span class="cx">                                 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */,
</span><ins>+                                0F952A9F1DF7860700E06FBD /* VisitRaceKey.cpp */,
+                                0F952AA01DF7860700E06FBD /* VisitRaceKey.h */,
</ins><span class="cx">                                 1ACF7376171CA6FB00C9BB1E /* Weak.cpp */,
</span><span class="cx">                                 142E3133134FF0A600AFADB5 /* Weak.h */,
</span><span class="cx">                                 14E84F9914EE1ACC00D6D5D4 /* WeakBlock.cpp */,
</span><span class="lines">@@ -7200,11 +7218,12 @@
</span><span class="cx">                                 FE5068641AE246390009DAB7 /* DeferredSourceDump.h */,
</span><span class="cx">                                 0FBC0AE41496C7C100D4FBDD /* DFGExitProfile.cpp */,
</span><span class="cx">                                 0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */,
</span><ins>+                                0F2EBBAA1DEDF94E00990369 /* DirectEvalCodeCache.cpp */,
+                                969A07920ED1D3AE00F1F681 /* DirectEvalCodeCache.h */,
</ins><span class="cx">                                 E3BFD0B91DAF807C0065DEA2 /* DOMJITAccessCasePatchpointParams.cpp */,
</span><span class="cx">                                 E3BFD0BA1DAF807C0065DEA2 /* DOMJITAccessCasePatchpointParams.h */,
</span><span class="cx">                                 14AD91121DCA97FD0014F9FE /* EvalCodeBlock.cpp */,
</span><span class="cx">                                 14AD91061DCA92940014F9FE /* EvalCodeBlock.h */,
</span><del>-                                969A07920ED1D3AE00F1F681 /* DirectEvalCodeCache.h */,
</del><span class="cx">                                 14142E521B796EDD00F4BF4B /* ExecutableInfo.h */,
</span><span class="cx">                                 0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */,
</span><span class="cx">                                 0F56A1D115000F31002992B1 /* ExecutionCounter.h */,
</span><span class="lines">@@ -7832,6 +7851,7 @@
</span><span class="cx">                                 FEA08620182B7A0400F6D851 /* Breakpoint.h in Headers */,
</span><span class="cx">                                 A7D801A51880D66E0026C39B /* BuiltinExecutables.h in Headers */,
</span><span class="cx">                                 A75EE9B218AAB7E200AAD043 /* BuiltinNames.h in Headers */,
</span><ins>+                                0FBB73B81DEF3AAE002C009E /* PreventCollectionScope.h in Headers */,
</ins><span class="cx">                                 99DA00A61BD5993100F4575C /* builtins.py in Headers */,
</span><span class="cx">                                 99DA00A71BD5993100F4575C /* builtins_generate_combined_header.py in Headers */,
</span><span class="cx">                                 99DA00A81BD5993100F4575C /* builtins_generate_combined_implementation.py in Headers */,
</span><span class="lines">@@ -7886,6 +7906,7 @@
</span><span class="cx">                                 BC6AAAE50E1F426500AD87D8 /* ClassInfo.h in Headers */,
</span><span class="cx">                                 0F6B8AD91C4EDDA200969052 /* B3DuplicateTails.h in Headers */,
</span><span class="cx">                                 0FE050261AA9095600D33B33 /* ClonedArguments.h in Headers */,
</span><ins>+                                0F5AE2C41DF4F2800066EFE1 /* VMInlines.h in Headers */,
</ins><span class="cx">                                 AD2FCBFD1DB58DAD00B3E736 /* WebAssemblyTableConstructor.h in Headers */,
</span><span class="cx">                                 969A07970ED1D3AE00F1F681 /* CodeBlock.h in Headers */,
</span><span class="cx">                                 0F8F94411667633200D61971 /* CodeBlockHash.h in Headers */,
</span><span class="lines">@@ -7922,6 +7943,7 @@
</span><span class="cx">                                 DCF3D56D1CD29476003D5C65 /* LazyPropertyInlines.h in Headers */,
</span><span class="cx">                                 BC18C3F60E16F5CD00B34460 /* ConstructData.h in Headers */,
</span><span class="cx">                                 A57D23F21891B5B40031C7FA /* ContentSearchUtilities.h in Headers */,
</span><ins>+                                0F208AD71DF0925D007D3269 /* LockDuringMarking.h in Headers */,
</ins><span class="cx">                                 52678F911A04177C006A306D /* ControlFlowProfiler.h in Headers */,
</span><span class="cx">                                 53486BB71C1795C300F6F3AF /* JSTypedArray.h in Headers */,
</span><span class="cx">                                 C4F4B6F41A05C944005CAB76 /* cpp_generator.py in Headers */,
</span><span class="lines">@@ -8035,6 +8057,7 @@
</span><span class="cx">                                 A7D9A29617A0BC7400EE2618 /* DFGEdgeDominates.h in Headers */,
</span><span class="cx">                                 A7986D5717A0BB1E00A95DD0 /* DFGEdgeUsesStructure.h in Headers */,
</span><span class="cx">                                 0F8F14341ADF090100ED792C /* DFGEpoch.h in Headers */,
</span><ins>+                                0F952AA11DF7860900E06FBD /* VisitRaceKey.h in Headers */,
</ins><span class="cx">                                 AD4937C81DDD0AAE0077C807 /* WebAssemblyModuleRecord.h in Headers */,
</span><span class="cx">                                 0FBC0AE81496C7C700D4FBDD /* DFGExitProfile.h in Headers */,
</span><span class="cx">                                 A78A9775179738B8009DF744 /* DFGFailedFinalizer.h in Headers */,
</span><span class="lines">@@ -8469,6 +8492,7 @@
</span><span class="cx">                                 86FA9E92142BBB2E001773B7 /* JSBoundFunction.h in Headers */,
</span><span class="cx">                                 BC18C4190E16F5CD00B34460 /* JSCallbackConstructor.h in Headers */,
</span><span class="cx">                                 BC18C41A0E16F5CD00B34460 /* JSCallbackFunction.h in Headers */,
</span><ins>+                                0FBB73BB1DEF8645002C009E /* DeleteAllCodeEffort.h in Headers */,
</ins><span class="cx">                                 BC18C41B0E16F5CD00B34460 /* JSCallbackObject.h in Headers */,
</span><span class="cx">                                 BC18C41C0E16F5CD00B34460 /* JSCallbackObjectFunctions.h in Headers */,
</span><span class="cx">                                 657CF45919BF6662004ACBF2 /* JSCallee.h in Headers */,
</span><span class="lines">@@ -9747,6 +9771,7 @@
</span><span class="cx">                                 A7D89CF717A0B8CC00773AD8 /* DFGFlushFormat.cpp in Sources */,
</span><span class="cx">                                 0F69CC88193AC60A0045759E /* DFGFrozenValue.cpp in Sources */,
</span><span class="cx">                                 86EC9DC71328DF82002B2AD7 /* DFGGraph.cpp in Sources */,
</span><ins>+                                0F952AA21DF7860D00E06FBD /* VisitRaceKey.cpp in Sources */,
</ins><span class="cx">                                 0F7F988B1D9596C500F4F12E /* DFGStoreBarrierClusteringPhase.cpp in Sources */,
</span><span class="cx">                                 0F2FCCF918A60070001A27F8 /* DFGGraphSafepoint.cpp in Sources */,
</span><span class="cx">                                 0FB17660196B8F9E0091052A /* DFGHeapLocation.cpp in Sources */,
</span><span class="lines">@@ -9888,6 +9913,7 @@
</span><span class="cx">                                 0F485327187DFDEC0083B687 /* FTLAvailableRecovery.cpp in Sources */,
</span><span class="cx">                                 0FEA0A09170513DB00BB722C /* FTLCapabilities.cpp in Sources */,
</span><span class="cx">                                 0F338E1B1BF286EA0013C88F /* B3BlockInsertionSet.cpp in Sources */,
</span><ins>+                                0F2EBBAB1DEDF95000990369 /* DirectEvalCodeCache.cpp in Sources */,
</ins><span class="cx">                                 0FEA0A271709623B00BB722C /* FTLCommonValues.cpp in Sources */,
</span><span class="cx">                                 0F235BD317178E1C00690C7F /* FTLExitArgument.cpp in Sources */,
</span><span class="cx">                                 0F235BD517178E1C00690C7F /* FTLExitArgumentForOperand.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -2437,13 +2437,6 @@
</span><span class="cx">     m_argumentValueProfiles = RefCountedArray&lt;ValueProfile&gt;(newValue);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void DirectEvalCodeCache::visitAggregate(SlotVisitor&amp; visitor)
-{
-    EvalCacheMap::iterator end = m_cacheMap.end();
-    for (EvalCacheMap::iterator ptr = m_cacheMap.begin(); ptr != end; ++ptr)
-        visitor.append(&amp;ptr-&gt;value);
-}
-
</del><span class="cx"> CodeBlock* CodeBlock::specialOSREntryBlockOrNull()
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(FTL_JIT)
</span><span class="lines">@@ -2902,18 +2895,14 @@
</span><span class="cx">     
</span><span class="cx">     codeBlock-&gt;updateAllPredictions();
</span><span class="cx">     
</span><del>-#if ENABLE(DFG_JIT)
-    if (codeBlock-&gt;shouldJettisonDueToWeakReference()) {
-        codeBlock-&gt;jettison(Profiler::JettisonDueToWeakReference);
</del><ins>+    if (!Heap::isMarked(codeBlock)) {
+        if (codeBlock-&gt;shouldJettisonDueToWeakReference())
+            codeBlock-&gt;jettison(Profiler::JettisonDueToWeakReference);
+        else
+            codeBlock-&gt;jettison(Profiler::JettisonDueToOldAge);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><del>-#endif // ENABLE(DFG_JIT)
</del><span class="cx"> 
</span><del>-    if (codeBlock-&gt;shouldJettisonDueToOldAge(NoLockingNecessary)) {
-        codeBlock-&gt;jettison(Profiler::JettisonDueToOldAge);
-        return;
-    }
-
</del><span class="cx">     if (JITCode::couldBeInterpreted(codeBlock-&gt;jitType()))
</span><span class="cx">         codeBlock-&gt;finalizeLLIntInlineCaches();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeDirectEvalCodeCachecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/DirectEvalCodeCache.cpp (0 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/DirectEvalCodeCache.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/DirectEvalCodeCache.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+/*
+ * Copyright (C) 2016 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;DirectEvalCodeCache.h&quot;
+
+#include &quot;JSCInlines.h&quot;
+
+namespace JSC {
+
+void DirectEvalCodeCache::setSlow(ExecState* exec, JSCell* owner, const String&amp; evalSource, CallSiteIndex callSiteIndex, DirectEvalExecutable* evalExecutable)
+{
+    LockHolder locker(m_lock);
+    m_cacheMap.set(CacheKey(evalSource, callSiteIndex), WriteBarrier&lt;DirectEvalExecutable&gt;(exec-&gt;vm(), owner, evalExecutable));
+}
+
+void DirectEvalCodeCache::clear()
+{
+    LockHolder locker(m_lock);
+    m_cacheMap.clear();
+}
+
+void DirectEvalCodeCache::visitAggregate(SlotVisitor&amp; visitor)
+{
+    LockHolder locker(m_lock);
+    EvalCacheMap::iterator end = m_cacheMap.end();
+    for (EvalCacheMap::iterator ptr = m_cacheMap.begin(); ptr != end; ++ptr)
+        visitor.append(&amp;ptr-&gt;value);
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeDirectEvalCodeCacheh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/DirectEvalCodeCache.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/DirectEvalCodeCache.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/bytecode/DirectEvalCodeCache.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -92,7 +92,7 @@
</span><span class="cx">         void set(ExecState* exec, JSCell* owner, const String&amp; evalSource, CallSiteIndex callSiteIndex, DirectEvalExecutable* evalExecutable)
</span><span class="cx">         {
</span><span class="cx">             if (m_cacheMap.size() &lt; maxCacheEntries)
</span><del>-                m_cacheMap.set(CacheKey(evalSource, callSiteIndex), WriteBarrier&lt;DirectEvalExecutable&gt;(exec-&gt;vm(), owner, evalExecutable));
</del><ins>+                setSlow(exec, owner, evalSource, callSiteIndex, evalExecutable);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         bool isEmpty() const { return m_cacheMap.isEmpty(); }
</span><span class="lines">@@ -99,16 +99,16 @@
</span><span class="cx"> 
</span><span class="cx">         void visitAggregate(SlotVisitor&amp;);
</span><span class="cx"> 
</span><del>-        void clear()
-        {
-            m_cacheMap.clear();
-        }
</del><ins>+        void clear();
</ins><span class="cx"> 
</span><span class="cx">     private:
</span><span class="cx">         static const int maxCacheEntries = 64;
</span><span class="cx"> 
</span><ins>+        void setSlow(ExecState*, JSCell* owner, const String&amp; evalSource, CallSiteIndex, DirectEvalExecutable*);
+
</ins><span class="cx">         typedef HashMap&lt;CacheKey, WriteBarrier&lt;DirectEvalExecutable&gt;, CacheKey::Hash, CacheKey::HashTraits&gt; EvalCacheMap;
</span><span class="cx">         EvalCacheMap m_cacheMap;
</span><ins>+        Lock m_lock;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePolymorphicAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -1377,7 +1377,7 @@
</span><span class="cx">             // We set the new butterfly and the structure last. Doing it this way ensures that
</span><span class="cx">             // whatever we had done up to this point is forgotten if we choose to branch to slow
</span><span class="cx">             // path.
</span><del>-            jit.storeButterfly(scratchGPR, baseGPR);
</del><ins>+            jit.nukeStructureAndStoreButterfly(scratchGPR, baseGPR);
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         uint32_t structureBits = bitwise_cast&lt;uint32_t&gt;(newStructure()-&gt;id());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -92,6 +92,7 @@
</span><span class="cx">     UnlinkedCodeBlock* thisObject = jsCast&lt;UnlinkedCodeBlock*&gt;(cell);
</span><span class="cx">     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
</span><span class="cx">     Base::visitChildren(thisObject, visitor);
</span><ins>+    auto locker = holdLock(*thisObject);
</ins><span class="cx">     for (FunctionExpressionVector::iterator ptr = thisObject-&gt;m_functionDecls.begin(), end = thisObject-&gt;m_functionDecls.end(); ptr != end; ++ptr)
</span><span class="cx">         visitor.append(ptr);
</span><span class="cx">     for (FunctionExpressionVector::iterator ptr = thisObject-&gt;m_functionExprs.begin(), end = thisObject-&gt;m_functionExprs.end(); ptr != end; ++ptr)
</span><span class="lines">@@ -313,7 +314,10 @@
</span><span class="cx"> void UnlinkedCodeBlock::setInstructions(std::unique_ptr&lt;UnlinkedInstructionStream&gt; instructions)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(instructions);
</span><del>-    m_unlinkedInstructions = WTFMove(instructions);
</del><ins>+    {
+        auto locker = holdLock(*this);
+        m_unlinkedInstructions = WTFMove(instructions);
+    }
</ins><span class="cx">     Heap::heap(this)-&gt;reportExtraMemoryAllocated(m_unlinkedInstructions-&gt;sizeInBytes());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -385,4 +389,28 @@
</span><span class="cx">     recomputePreciseJumpTargets(this, graph.instructions().begin(), graph.instructions().size(), m_jumpTargets);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void UnlinkedCodeBlock::shrinkToFit()
+{
+    auto locker = holdLock(*this);
+    
+    m_jumpTargets.shrinkToFit();
+    m_identifiers.shrinkToFit();
+    m_bitVectors.shrinkToFit();
+    m_constantRegisters.shrinkToFit();
+    m_constantsSourceCodeRepresentation.shrinkToFit();
+    m_functionDecls.shrinkToFit();
+    m_functionExprs.shrinkToFit();
+    m_propertyAccessInstructions.shrinkToFit();
+    m_expressionInfo.shrinkToFit();
+
+    if (m_rareData) {
+        m_rareData-&gt;m_exceptionHandlers.shrinkToFit();
+        m_rareData-&gt;m_regexps.shrinkToFit();
+        m_rareData-&gt;m_constantBuffers.shrinkToFit();
+        m_rareData-&gt;m_switchJumpTables.shrinkToFit();
+        m_rareData-&gt;m_stringSwitchJumpTables.shrinkToFit();
+        m_rareData-&gt;m_expressionInfoFatPositions.shrinkToFit();
+    }
</ins><span class="cx"> }
</span><ins>+
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx"> #include &quot;Identifier.h&quot;
</span><span class="cx"> #include &quot;JSCell.h&quot;
</span><span class="cx"> #include &quot;JSString.h&quot;
</span><ins>+#include &quot;LockDuringMarking.h&quot;
</ins><span class="cx"> #include &quot;ParserModes.h&quot;
</span><span class="cx"> #include &quot;RegExp.h&quot;
</span><span class="cx"> #include &quot;SpecialPointer.h&quot;
</span><span class="lines">@@ -153,8 +154,10 @@
</span><span class="cx">     unsigned addRegExp(RegExp* r)
</span><span class="cx">     {
</span><span class="cx">         createRareDataIfNecessary();
</span><ins>+        VM&amp; vm = *this-&gt;vm();
+        auto locker = lockDuringMarking(vm.heap, *this);
</ins><span class="cx">         unsigned size = m_rareData-&gt;m_regexps.size();
</span><del>-        m_rareData-&gt;m_regexps.append(WriteBarrier&lt;RegExp&gt;(*vm(), this, r));
</del><ins>+        m_rareData-&gt;m_regexps.append(WriteBarrier&lt;RegExp&gt;(vm, this, r));
</ins><span class="cx">         return size;
</span><span class="cx">     }
</span><span class="cx">     unsigned numberOfRegExps() const
</span><span class="lines">@@ -182,14 +185,18 @@
</span><span class="cx"> 
</span><span class="cx">     unsigned addConstant(JSValue v, SourceCodeRepresentation sourceCodeRepresentation = SourceCodeRepresentation::Other)
</span><span class="cx">     {
</span><ins>+        VM&amp; vm = *this-&gt;vm();
+        auto locker = lockDuringMarking(vm.heap, *this);
</ins><span class="cx">         unsigned result = m_constantRegisters.size();
</span><span class="cx">         m_constantRegisters.append(WriteBarrier&lt;Unknown&gt;());
</span><del>-        m_constantRegisters.last().set(*vm(), this, v);
</del><ins>+        m_constantRegisters.last().set(vm, this, v);
</ins><span class="cx">         m_constantsSourceCodeRepresentation.append(sourceCodeRepresentation);
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx">     unsigned addConstant(LinkTimeConstant type)
</span><span class="cx">     {
</span><ins>+        VM&amp; vm = *this-&gt;vm();
+        auto locker = lockDuringMarking(vm.heap, *this);
</ins><span class="cx">         unsigned result = m_constantRegisters.size();
</span><span class="cx">         ASSERT(result);
</span><span class="cx">         unsigned index = static_cast&lt;unsigned&gt;(type);
</span><span class="lines">@@ -225,28 +232,8 @@
</span><span class="cx">     SuperBinding superBinding() const { return static_cast&lt;SuperBinding&gt;(m_superBinding); }
</span><span class="cx">     JSParserScriptMode scriptMode() const { return static_cast&lt;JSParserScriptMode&gt;(m_scriptMode); }
</span><span class="cx"> 
</span><del>-    void shrinkToFit()
-    {
-        m_jumpTargets.shrinkToFit();
-        m_identifiers.shrinkToFit();
-        m_bitVectors.shrinkToFit();
-        m_constantRegisters.shrinkToFit();
-        m_constantsSourceCodeRepresentation.shrinkToFit();
-        m_functionDecls.shrinkToFit();
-        m_functionExprs.shrinkToFit();
-        m_propertyAccessInstructions.shrinkToFit();
-        m_expressionInfo.shrinkToFit();
</del><ins>+    void shrinkToFit();
</ins><span class="cx"> 
</span><del>-        if (m_rareData) {
-            m_rareData-&gt;m_exceptionHandlers.shrinkToFit();
-            m_rareData-&gt;m_regexps.shrinkToFit();
-            m_rareData-&gt;m_constantBuffers.shrinkToFit();
-            m_rareData-&gt;m_switchJumpTables.shrinkToFit();
-            m_rareData-&gt;m_stringSwitchJumpTables.shrinkToFit();
-            m_rareData-&gt;m_expressionInfoFatPositions.shrinkToFit();
-        }
-    }
-
</del><span class="cx">     void setInstructions(std::unique_ptr&lt;UnlinkedInstructionStream&gt;);
</span><span class="cx">     const UnlinkedInstructionStream&amp; instructions() const;
</span><span class="cx"> 
</span><span class="lines">@@ -268,9 +255,11 @@
</span><span class="cx"> 
</span><span class="cx">     unsigned addFunctionDecl(UnlinkedFunctionExecutable* n)
</span><span class="cx">     {
</span><ins>+        VM&amp; vm = *this-&gt;vm();
+        auto locker = lockDuringMarking(vm.heap, *this);
</ins><span class="cx">         unsigned size = m_functionDecls.size();
</span><span class="cx">         m_functionDecls.append(WriteBarrier&lt;UnlinkedFunctionExecutable&gt;());
</span><del>-        m_functionDecls.last().set(*vm(), this, n);
</del><ins>+        m_functionDecls.last().set(vm, this, n);
</ins><span class="cx">         return size;
</span><span class="cx">     }
</span><span class="cx">     UnlinkedFunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); }
</span><span class="lines">@@ -277,9 +266,11 @@
</span><span class="cx">     size_t numberOfFunctionDecls() { return m_functionDecls.size(); }
</span><span class="cx">     unsigned addFunctionExpr(UnlinkedFunctionExecutable* n)
</span><span class="cx">     {
</span><ins>+        VM&amp; vm = *this-&gt;vm();
+        auto locker = lockDuringMarking(vm.heap, *this);
</ins><span class="cx">         unsigned size = m_functionExprs.size();
</span><span class="cx">         m_functionExprs.append(WriteBarrier&lt;UnlinkedFunctionExecutable&gt;());
</span><del>-        m_functionExprs.last().set(*vm(), this, n);
</del><ins>+        m_functionExprs.last().set(vm, this, n);
</ins><span class="cx">         return size;
</span><span class="cx">     }
</span><span class="cx">     UnlinkedFunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }
</span><span class="lines">@@ -404,8 +395,10 @@
</span><span class="cx"> 
</span><span class="cx">     void createRareDataIfNecessary()
</span><span class="cx">     {
</span><del>-        if (!m_rareData)
</del><ins>+        if (!m_rareData) {
+            auto locker = lockDuringMarking(*heap(), *this);
</ins><span class="cx">             m_rareData = std::make_unique&lt;RareData&gt;();
</span><ins>+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void getLineAndColumn(const ExpressionRangeInfo&amp;, unsigned&amp; line, unsigned&amp; column) const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/Debugger.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/Debugger.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/debugger/Debugger.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -333,7 +333,7 @@
</span><span class="cx"> 
</span><span class="cx"> void Debugger::recompileAllJSFunctions()
</span><span class="cx"> {
</span><del>-    m_vm.deleteAllCode();
</del><ins>+    m_vm.deleteAllCode(PreventCollectionAndDeleteAllCode);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> DebuggerParseData&amp; Debugger::debuggerParseData(SourceID sourceID, SourceProvider* provider)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -1213,7 +1213,7 @@
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             
</span><del>-            if (!(child.m_type &amp; (SpecFunction | SpecObjectOther))) {
</del><ins>+            if (!(child.m_type &amp; (SpecFunction | SpecObjectOther | SpecProxyObject))) {
</ins><span class="cx">                 setConstant(node, jsBoolean(false));
</span><span class="cx">                 constantWasSet = true;
</span><span class="cx">                 break;
</span><span class="lines">@@ -2309,6 +2309,8 @@
</span><span class="cx">     case GetButterfly:
</span><span class="cx">     case AllocatePropertyStorage:
</span><span class="cx">     case ReallocatePropertyStorage:
</span><ins>+        // FIXME: We don't model the fact that the structureID is nuked, simply because currently
+        // nobody would currently benefit from having that information. But it's a bug nonetheless.
</ins><span class="cx">         forNode(node).clear(); // The result is not a JS value.
</span><span class="cx">         break;
</span><span class="cx">     case CheckDOM: {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -900,6 +900,7 @@
</span><span class="cx">         
</span><span class="cx">     case AllocatePropertyStorage:
</span><span class="cx">         write(JSObject_butterfly);
</span><ins>+        write(JSCell_structureID);
</ins><span class="cx">         def(HeapLocation(ButterflyLoc, JSObject_butterfly, node-&gt;child1()), LazyNode(node));
</span><span class="cx">         return;
</span><span class="cx">         
</span><span class="lines">@@ -906,6 +907,7 @@
</span><span class="cx">     case ReallocatePropertyStorage:
</span><span class="cx">         read(JSObject_butterfly);
</span><span class="cx">         write(JSObject_butterfly);
</span><ins>+        write(JSCell_structureID);
</ins><span class="cx">         def(HeapLocation(ButterflyLoc, JSObject_butterfly, node-&gt;child1()), LazyNode(node));
</span><span class="cx">         return;
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobbersExitStatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -66,8 +66,6 @@
</span><span class="cx">     case PhantomCreateActivation:
</span><span class="cx">     case MaterializeCreateActivation:
</span><span class="cx">     case CountExecution:
</span><del>-    case AllocatePropertyStorage:
-    case ReallocatePropertyStorage:
</del><span class="cx">     case StoreBarrier:
</span><span class="cx">     case FencedStoreBarrier:
</span><span class="cx">         // These do clobber memory, but nothing that is observable. It may be nice to separate the
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -385,7 +385,7 @@
</span><span class="cx">         case ArithTrunc: {
</span><span class="cx">             if (node-&gt;child1()-&gt;shouldSpeculateInt32OrBoolean() &amp;&amp; m_graph.roundShouldSpeculateInt32(node, FixupPass)) {
</span><span class="cx">                 fixIntOrBooleanEdge(node-&gt;child1());
</span><del>-                insertCheck&lt;Int32Use&gt;(m_indexInBlock, node-&gt;child1().node());
</del><ins>+                insertCheck&lt;Int32Use&gt;(node-&gt;child1().node());
</ins><span class="cx">                 node-&gt;convertToIdentity();
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="lines">@@ -1325,8 +1325,9 @@
</span><span class="cx">             if (!node-&gt;child1()-&gt;hasStorageResult())
</span><span class="cx">                 fixEdge&lt;KnownCellUse&gt;(node-&gt;child1());
</span><span class="cx">             fixEdge&lt;KnownCellUse&gt;(node-&gt;child2());
</span><ins>+            unsigned index = indexForChecks();
</ins><span class="cx">             insertInferredTypeCheck(
</span><del>-                m_insertionSet, m_indexInBlock, node-&gt;origin, node-&gt;child3().node(),
</del><ins>+                m_insertionSet, index, originForCheck(index), node-&gt;child3().node(),
</ins><span class="cx">                 node-&gt;storageAccessData().inferredType);
</span><span class="cx">             speculateForBarrier(node-&gt;child3());
</span><span class="cx">             break;
</span><span class="lines">@@ -2495,6 +2496,19 @@
</span><span class="cx">         edge.setUseKind(useKind);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    unsigned indexForChecks()
+    {
+        unsigned index = m_indexInBlock;
+        while (!m_block-&gt;at(index)-&gt;origin.exitOK)
+            index--;
+        return index;
+    }
+    
+    NodeOrigin originForCheck(unsigned index)
+    {
+        return m_block-&gt;at(index)-&gt;origin.withSemantic(m_currentNode-&gt;origin.semantic);
+    }
+    
</ins><span class="cx">     void speculateForBarrier(Edge value)
</span><span class="cx">     {
</span><span class="cx">         // Currently, the DFG won't take advantage of this speculation. But, we want to do it in
</span><span class="lines">@@ -2502,37 +2516,37 @@
</span><span class="cx">         // we do an expensive compile.
</span><span class="cx">         
</span><span class="cx">         if (value-&gt;shouldSpeculateInt32()) {
</span><del>-            insertCheck&lt;Int32Use&gt;(m_indexInBlock, value.node());
</del><ins>+            insertCheck&lt;Int32Use&gt;(value.node());
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         if (value-&gt;shouldSpeculateBoolean()) {
</span><del>-            insertCheck&lt;BooleanUse&gt;(m_indexInBlock, value.node());
</del><ins>+            insertCheck&lt;BooleanUse&gt;(value.node());
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         if (value-&gt;shouldSpeculateOther()) {
</span><del>-            insertCheck&lt;OtherUse&gt;(m_indexInBlock, value.node());
</del><ins>+            insertCheck&lt;OtherUse&gt;(value.node());
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         if (value-&gt;shouldSpeculateNumber()) {
</span><del>-            insertCheck&lt;NumberUse&gt;(m_indexInBlock, value.node());
</del><ins>+            insertCheck&lt;NumberUse&gt;(value.node());
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         if (value-&gt;shouldSpeculateNotCell()) {
</span><del>-            insertCheck&lt;NotCellUse&gt;(m_indexInBlock, value.node());
</del><ins>+            insertCheck&lt;NotCellUse&gt;(value.node());
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     template&lt;UseKind useKind&gt;
</span><del>-    void insertCheck(unsigned indexInBlock, Node* node)
</del><ins>+    void insertCheck(Node* node)
</ins><span class="cx">     {
</span><span class="cx">         observeUseKindOnNode&lt;useKind&gt;(node);
</span><del>-        m_insertionSet.insertNode(
-            indexInBlock, SpecNone, Check, m_currentNode-&gt;origin, Edge(node, useKind));
</del><ins>+        unsigned index = indexForChecks();
+        m_insertionSet.insertNode(index, SpecNone, Check, originForCheck(index), Edge(node, useKind));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void fixIntConvertingEdge(Edge&amp; edge)
</span><span class="lines">@@ -2824,7 +2838,7 @@
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             originForChecks = originForChecks.withSemantic(node-&gt;origin.semantic);
</span><del>-
</del><ins>+            
</ins><span class="cx">             // First, try to relax the representational demands of each node, in order to have
</span><span class="cx">             // fewer conversions.
</span><span class="cx">             switch (node-&gt;op()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -7414,13 +7414,16 @@
</span><span class="cx">     if (useGCFences()) {
</span><span class="cx">         for (ptrdiff_t offset = 0; offset &lt; static_cast&lt;ptrdiff_t&gt;(size); offset += sizeof(void*))
</span><span class="cx">             m_jit.storePtr(TrustedImmPtr(0), JITCompiler::Address(scratchGPR1, -(offset + sizeof(JSValue) + sizeof(void*))));
</span><del>-        
-        m_jit.mutatorFence();
</del><span class="cx">     }
</span><span class="cx">         
</span><span class="cx">     addSlowPathGenerator(
</span><span class="cx">         slowPathCall(slowPath, this, operationAllocatePropertyStorageWithInitialCapacity, scratchGPR1));
</span><span class="cx"> 
</span><ins>+    if (useGCFences()) {
+        m_jit.store32(TrustedImm32(0), JITCompiler::Address(baseGPR, JSCell::structureIDOffset()));
+        m_jit.mutatorFence();
+    }
+
</ins><span class="cx">     m_jit.storePtr(scratchGPR1, JITCompiler::Address(baseGPR, JSObject::butterflyOffset()));
</span><span class="cx">     m_jit.mutatorFence();
</span><span class="cx"> 
</span><span class="lines">@@ -7482,7 +7485,7 @@
</span><span class="cx">         m_jit.storePtr(scratchGPR2, JITCompiler::Address(scratchGPR1, -(offset + sizeof(JSValue) + sizeof(void*))));
</span><span class="cx">     }
</span><span class="cx">         
</span><del>-    m_jit.storeButterfly(scratchGPR1, baseGPR);
</del><ins>+    m_jit.nukeStructureAndStoreButterfly(scratchGPR1, baseGPR);
</ins><span class="cx"> 
</span><span class="cx">     storageResult(scratchGPR1, node);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -9491,7 +9491,7 @@
</span><span class="cx">                 m_out.int64Zero, m_heaps.properties.atAnyNumber());
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        setButterfly(result, object);
</del><ins>+        nukeStructureAndSetButterfly(result, object);
</ins><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -9526,7 +9526,7 @@
</span><span class="cx">                 m_out.int64Zero, m_heaps.properties.atAnyNumber());
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        setButterfly(result, object);
</del><ins>+        nukeStructureAndSetButterfly(result, object);
</ins><span class="cx">         
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="lines">@@ -13048,7 +13048,7 @@
</span><span class="cx">     
</span><span class="cx">     void mutatorFence()
</span><span class="cx">     {
</span><del>-        if (isX86() || !useGCFences()) {
</del><ins>+        if (isX86()) {
</ins><span class="cx">             m_out.fence(&amp;m_heaps.root, nullptr);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="lines">@@ -13070,9 +13070,14 @@
</span><span class="cx">         m_out.appendTo(continuation, lastNext);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void setButterfly(LValue butterfly, LValue object)
</del><ins>+    void nukeStructureAndSetButterfly(LValue butterfly, LValue object)
</ins><span class="cx">     {
</span><del>-        if (isX86() || !useGCFences()) {
</del><ins>+        if (isX86()) {
+            m_out.store32(
+                m_out.bitOr(
+                    m_out.load32(object, m_heaps.JSCell_structureID),
+                    m_out.constInt32(nukedStructureIDBit())),
+                object, m_heaps.JSCell_structureID);
</ins><span class="cx">             m_out.fence(&amp;m_heaps.root, nullptr);
</span><span class="cx">             m_out.storePtr(butterfly, object, m_heaps.JSObject_butterfly);
</span><span class="cx">             m_out.fence(&amp;m_heaps.root, nullptr);
</span><span class="lines">@@ -13096,6 +13101,11 @@
</span><span class="cx">         
</span><span class="cx">         m_out.appendTo(slowPath, continuation);
</span><span class="cx">         
</span><ins>+        m_out.store32(
+            m_out.bitOr(
+                m_out.load32(object, m_heaps.JSCell_structureID),
+                m_out.constInt32(nukedStructureIDBit())),
+            object, m_heaps.JSCell_structureID);
</ins><span class="cx">         m_out.fence(&amp;m_heaps.root, nullptr);
</span><span class="cx">         m_out.storePtr(butterfly, object, m_heaps.JSObject_butterfly);
</span><span class="cx">         m_out.fence(&amp;m_heaps.root, nullptr);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCellContainerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CellContainer.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CellContainer.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/CellContainer.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -85,6 +85,7 @@
</span><span class="cx">     bool isMarked(HeapVersion markingVersion, HeapCell*) const;
</span><span class="cx">     
</span><span class="cx">     void noteMarked();
</span><ins>+    void assertValidCell(VM&amp;, HeapCell*) const;
</ins><span class="cx">     
</span><span class="cx">     size_t cellSize() const;
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCellContainerInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CellContainerInlines.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CellContainerInlines.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/CellContainerInlines.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -65,6 +65,14 @@
</span><span class="cx">         markedBlock().noteMarked();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline void CellContainer::assertValidCell(VM&amp; vm, HeapCell* cell) const
+{
+    if (isLargeAllocation())
+        largeAllocation().assertValidCell(vm, cell);
+    else
+        markedBlock().assertValidCell(vm, cell);
+}
+
</ins><span class="cx"> inline size_t CellContainer::cellSize() const
</span><span class="cx"> {
</span><span class="cx">     if (isLargeAllocation())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCodeBlockSetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -61,10 +61,6 @@
</span><span class="cx">     LockHolder locker(&amp;m_lock);
</span><span class="cx">     for (CodeBlock* codeBlock : m_oldCodeBlocks)
</span><span class="cx">         codeBlock-&gt;clearVisitWeaklyHasBeenCalled();
</span><del>-
-    // We promote after we clear marks on the old generation CodeBlocks because
-    // none of the young generations CodeBlocks need to be cleared.
-    promoteYoungCodeBlocks(locker);
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CodeBlockSet::lastChanceToFinalize()
</span><span class="lines">@@ -80,17 +76,29 @@
</span><span class="cx"> void CodeBlockSet::deleteUnmarkedAndUnreferenced(CollectionScope scope)
</span><span class="cx"> {
</span><span class="cx">     LockHolder locker(&amp;m_lock);
</span><del>-    HashSet&lt;CodeBlock*&gt;&amp; set = scope == CollectionScope::Eden ? m_newCodeBlocks : m_oldCodeBlocks;
</del><span class="cx">     Vector&lt;CodeBlock*&gt; unmarked;
</span><del>-    for (CodeBlock* codeBlock : set) {
-        if (Heap::isMarked(codeBlock))
-            continue;
-        unmarked.append(codeBlock);
-    }
</del><ins>+    
+    auto consider = [&amp;] (HashSet&lt;CodeBlock*&gt;&amp; set) {
+        for (CodeBlock* codeBlock : set) {
+            if (Heap::isMarked(codeBlock))
+                continue;;
+            unmarked.append(codeBlock);
+        }
+        for (CodeBlock* codeBlock : unmarked) {
+            codeBlock-&gt;classInfo()-&gt;methodTable.destroy(codeBlock);
+            set.remove(codeBlock);
+        }
+        unmarked.resize(0);
+    };
</ins><span class="cx"> 
</span><del>-    for (CodeBlock* codeBlock : unmarked) {
-        codeBlock-&gt;classInfo()-&gt;methodTable.destroy(codeBlock);
-        set.remove(codeBlock);
</del><ins>+    switch (scope) {
+    case CollectionScope::Eden:
+        consider(m_newCodeBlocks);
+        break;
+    case CollectionScope::Full:
+        consider(m_oldCodeBlocks);
+        consider(m_newCodeBlocks);
+        break;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Any remaining young CodeBlocks are live and need to be promoted to the set of old CodeBlocks.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapDeleteAllCodeEfforth"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/DeleteAllCodeEffort.h (0 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/DeleteAllCodeEffort.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/heap/DeleteAllCodeEffort.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -0,0 +1,36 @@
</span><ins>+/*
+ * Copyright (C) 2016 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
+
+namespace JSC {
+
+enum DeleteAllCodeEffort {
+    PreventCollectionAndDeleteAllCode,
+    DeleteAllCodeIfNotCollecting
+};
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -49,6 +49,7 @@
</span><span class="cx"> #include &quot;JSLock.h&quot;
</span><span class="cx"> #include &quot;JSVirtualMachineInternal.h&quot;
</span><span class="cx"> #include &quot;MarkedSpaceInlines.h&quot;
</span><ins>+#include &quot;PreventCollectionScope.h&quot;
</ins><span class="cx"> #include &quot;SamplingProfiler.h&quot;
</span><span class="cx"> #include &quot;ShadowChicken.h&quot;
</span><span class="cx"> #include &quot;SuperSampler.h&quot;
</span><span class="lines">@@ -80,9 +81,12 @@
</span><span class="cx"> 
</span><span class="cx"> namespace {
</span><span class="cx"> 
</span><ins>+bool verboseStop = false;
+
</ins><span class="cx"> double maxPauseMS(double thisPauseMS)
</span><span class="cx"> {
</span><del>-    static double maxPauseMS = std::max(thisPauseMS, maxPauseMS);
</del><ins>+    static double maxPauseMS;
+    maxPauseMS = std::max(thisPauseMS, maxPauseMS);
</ins><span class="cx">     return maxPauseMS;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -319,6 +323,8 @@
</span><span class="cx">     if (Options::verifyHeap())
</span><span class="cx">         m_verifier = std::make_unique&lt;HeapVerifier&gt;(this, Options::numberOfGCCyclesToRecordForVerification());
</span><span class="cx">     
</span><ins>+    m_collectorSlotVisitor-&gt;optimizeForStoppedMutator();
+    
</ins><span class="cx">     LockHolder locker(*m_threadLock);
</span><span class="cx">     m_thread = adoptRef(new Thread(locker, *this));
</span><span class="cx"> }
</span><span class="lines">@@ -346,6 +352,15 @@
</span><span class="cx">     RELEASE_ASSERT(!m_vm-&gt;entryScope);
</span><span class="cx">     RELEASE_ASSERT(m_mutatorState == MutatorState::Running);
</span><span class="cx">     
</span><ins>+    if (m_collectContinuouslyThread) {
+        {
+            LockHolder locker(m_collectContinuouslyLock);
+            m_shouldStopCollectingContinuously = true;
+            m_collectContinuouslyCondition.notifyOne();
+        }
+        waitForThreadCompletion(m_collectContinuouslyThread);
+    }
+    
</ins><span class="cx">     // Carefully bring the thread down. We need to use waitForCollector() until we know that there
</span><span class="cx">     // won't be any other collections.
</span><span class="cx">     bool stopped = false;
</span><span class="lines">@@ -465,12 +480,16 @@
</span><span class="cx"> 
</span><span class="cx"> void Heap::harvestWeakReferences()
</span><span class="cx"> {
</span><del>-    m_collectorSlotVisitor-&gt;harvestWeakReferences();
</del><ins>+    for (WeakReferenceHarvester* current = m_weakReferenceHarvesters.head(); current; current = current-&gt;next())
+        current-&gt;visitWeakReferences(*m_collectorSlotVisitor);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Heap::finalizeUnconditionalFinalizers()
</span><span class="cx"> {
</span><del>-    m_collectorSlotVisitor-&gt;finalizeUnconditionalFinalizers();
</del><ins>+    while (m_unconditionalFinalizers.hasNext()) {
+        UnconditionalFinalizer* finalizer = m_unconditionalFinalizers.removeNext();
+        finalizer-&gt;finalizeUnconditionally();
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Heap::willStartIterating()
</span><span class="lines">@@ -515,6 +534,10 @@
</span><span class="cx">                 if (m_availableParallelSlotVisitors.isEmpty()) {
</span><span class="cx">                     std::unique_ptr&lt;SlotVisitor&gt; newVisitor =
</span><span class="cx">                         std::make_unique&lt;SlotVisitor&gt;(*this);
</span><ins>+                    
+                    if (Options::optimizeParallelSlotVisitorsForStoppedMutator())
+                        newVisitor-&gt;optimizeForStoppedMutator();
+                    
</ins><span class="cx">                     slotVisitor = newVisitor.get();
</span><span class="cx">                     m_parallelSlotVisitors.append(WTFMove(newVisitor));
</span><span class="cx">                 } else
</span><span class="lines">@@ -547,10 +570,19 @@
</span><span class="cx">         std::max(
</span><span class="cx">             bytesAllocatedThisCycleAtTheBeginning,
</span><span class="cx">             static_cast&lt;double&gt;(m_maxEdenSize));
</span><ins>+    double bytesAllocatedThisCycle;
+    MonotonicTime nowForScheduling;
</ins><span class="cx">     
</span><ins>+    auto cacheSchedulingStats = [&amp;] () {
+        bytesAllocatedThisCycle = m_bytesAllocatedThisCycle;
+        nowForScheduling = MonotonicTime::now();
+    };
+    
+    cacheSchedulingStats();
+    
</ins><span class="cx">     auto targetMutatorUtilization = [&amp;] () -&gt; double {
</span><span class="cx">         double headroomFullness =
</span><del>-            (m_bytesAllocatedThisCycle - bytesAllocatedThisCycleAtTheBeginning) /
</del><ins>+            (bytesAllocatedThisCycle - bytesAllocatedThisCycleAtTheBeginning) /
</ins><span class="cx">             (bytesAllocatedThisCycleAtTheEnd - bytesAllocatedThisCycleAtTheBeginning);
</span><span class="cx">         
</span><span class="cx">         // headroomFullness can be NaN and other interesting things if
</span><span class="lines">@@ -578,32 +610,32 @@
</span><span class="cx">         return 1 - targetMutatorUtilization();
</span><span class="cx">     };
</span><span class="cx">     
</span><del>-    auto elapsedInPeriod = [&amp;] (MonotonicTime now) -&gt; Seconds {
-        return (now - initialTime) % period;
</del><ins>+    auto elapsedInPeriod = [&amp;] () -&gt; Seconds {
+        return (nowForScheduling - initialTime) % period;
</ins><span class="cx">     };
</span><span class="cx">     
</span><del>-    auto phase = [&amp;] (MonotonicTime now) -&gt; double {
-        return elapsedInPeriod(now) / period;
</del><ins>+    auto phase = [&amp;] () -&gt; double {
+        return elapsedInPeriod() / period;
</ins><span class="cx">     };
</span><span class="cx">     
</span><del>-    auto shouldBeResumed = [&amp;] (MonotonicTime now) -&gt; bool {
</del><ins>+    auto shouldBeResumed = [&amp;] () -&gt; bool {
</ins><span class="cx">         if (Options::collectorShouldResumeFirst())
</span><del>-            return phase(now) &lt;= targetMutatorUtilization();
-        return phase(now) &gt; targetCollectorUtilization();
</del><ins>+            return phase() &lt;= targetMutatorUtilization();
+        return phase() &gt; targetCollectorUtilization();
</ins><span class="cx">     };
</span><span class="cx">     
</span><del>-    auto timeToResume = [&amp;] (MonotonicTime now) -&gt; MonotonicTime {
-        ASSERT(!shouldBeResumed(now));
</del><ins>+    auto timeToResume = [&amp;] () -&gt; MonotonicTime {
+        ASSERT(!shouldBeResumed());
</ins><span class="cx">         if (Options::collectorShouldResumeFirst())
</span><del>-            return now - elapsedInPeriod(now) + period;
-        return now - elapsedInPeriod(now) + period * targetCollectorUtilization();
</del><ins>+            return nowForScheduling - elapsedInPeriod() + period;
+        return nowForScheduling - elapsedInPeriod() + period * targetCollectorUtilization();
</ins><span class="cx">     };
</span><span class="cx">     
</span><del>-    auto timeToStop = [&amp;] (MonotonicTime now) -&gt; MonotonicTime {
-        ASSERT(shouldBeResumed(now));
</del><ins>+    auto timeToStop = [&amp;] () -&gt; MonotonicTime {
+        ASSERT(shouldBeResumed());
</ins><span class="cx">         if (Options::collectorShouldResumeFirst())
</span><del>-            return now - elapsedInPeriod(now) + period * targetMutatorUtilization();
-        return now -  - elapsedInPeriod(now) + period;
</del><ins>+            return nowForScheduling - elapsedInPeriod() + period * targetMutatorUtilization();
+        return nowForScheduling - elapsedInPeriod() + period;
</ins><span class="cx">     };
</span><span class="cx">     
</span><span class="cx">     // Adjust the target extra pause ratio as necessary.
</span><span class="lines">@@ -624,6 +656,7 @@
</span><span class="cx">         MonotonicTime topOfLoop = MonotonicTime::now();
</span><span class="cx">         {
</span><span class="cx">             TimingScope preConvergenceTimingScope(*this, &quot;Heap::markToFixpoint conservative scan&quot;);
</span><ins>+            m_objectSpace.prepareForConservativeScan();
</ins><span class="cx">             ConservativeRoots conservativeRoots(*this);
</span><span class="cx">             SuperSamplerScope superSamplerScope(false);
</span><span class="cx">             gatherStackRoots(conservativeRoots);
</span><span class="lines">@@ -682,8 +715,10 @@
</span><span class="cx">         DFG::markCodeBlocks(*m_vm, *m_collectorSlotVisitor);
</span><span class="cx">         bool shouldTerminate = m_collectorSlotVisitor-&gt;isEmpty() &amp;&amp; m_mutatorMarkStack-&gt;isEmpty();
</span><span class="cx">         
</span><del>-        if (Options::logGC())
</del><ins>+        if (Options::logGC()) {
+            cacheSchedulingStats();
</ins><span class="cx">             dataLog(m_collectorSlotVisitor-&gt;collectorMarkStack().size(), &quot;+&quot;, m_mutatorMarkStack-&gt;size() + m_collectorSlotVisitor-&gt;mutatorMarkStack().size(), &quot;, a=&quot;, m_bytesAllocatedThisCycle / 1024, &quot; kb, b=&quot;, m_barriersExecuted, &quot;, mu=&quot;, targetMutatorUtilization(), &quot; &quot;);
</span><ins>+        }
</ins><span class="cx">         
</span><span class="cx">         // We want to do this to conservatively ensure that we rescan any code blocks that are
</span><span class="cx">         // running right now. However, we need to be sure to do it *after* we mark the code block
</span><span class="lines">@@ -722,12 +757,12 @@
</span><span class="cx">                 drainResult = m_collectorSlotVisitor-&gt;drainInParallel(initialTime);
</span><span class="cx">                 
</span><span class="cx">                 while (drainResult != SlotVisitor::SharedDrainResult::Done) {
</span><del>-                    MonotonicTime now = MonotonicTime::now();
-                    if (shouldBeResumed(now)) {
</del><ins>+                    cacheSchedulingStats();
+                    if (shouldBeResumed()) {
</ins><span class="cx">                         ResumeTheWorldScope resumeTheWorldScope(*this);
</span><del>-                        drainResult = m_collectorSlotVisitor-&gt;drainInParallel(timeToStop(now));
</del><ins>+                        drainResult = m_collectorSlotVisitor-&gt;drainInParallelPassively(timeToStop());
</ins><span class="cx">                     } else
</span><del>-                        drainResult = m_collectorSlotVisitor-&gt;drainInParallel(timeToResume(now));
</del><ins>+                        drainResult = m_collectorSlotVisitor-&gt;drainInParallel(timeToResume());
</ins><span class="cx">                 }
</span><span class="cx">             } else {
</span><span class="cx">                 // Disabling collector timeslicing is meant to be used together with
</span><span class="lines">@@ -893,6 +928,11 @@
</span><span class="cx"> 
</span><span class="cx"> void Heap::endMarking()
</span><span class="cx"> {
</span><ins>+    if (!m_visitRaces.isEmpty()) {
+        dataLog(&quot;Unresolved visit races: &quot;, listDump(m_visitRaces), &quot;\n&quot;);
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+    
</ins><span class="cx">     m_collectorSlotVisitor-&gt;reset();
</span><span class="cx"> 
</span><span class="cx">     for (auto&amp; parallelVisitor : m_parallelSlotVisitors)
</span><span class="lines">@@ -989,12 +1029,17 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::deleteAllCodeBlocks()
</del><ins>+void Heap::deleteAllCodeBlocks(DeleteAllCodeEffort effort)
</ins><span class="cx"> {
</span><ins>+    if (m_collectionScope &amp;&amp; effort == DeleteAllCodeIfNotCollecting)
+        return;
+    
+    PreventCollectionScope preventCollectionScope(*this);
+    
</ins><span class="cx">     // If JavaScript is running, it's not safe to delete all JavaScript code, since
</span><span class="cx">     // we'll end up returning to deleted code.
</span><span class="cx">     RELEASE_ASSERT(!m_vm-&gt;entryScope);
</span><del>-    ASSERT(!m_collectionScope);
</del><ins>+    RELEASE_ASSERT(!m_collectionScope);
</ins><span class="cx"> 
</span><span class="cx">     completeAllJITPlans();
</span><span class="cx"> 
</span><span class="lines">@@ -1002,8 +1047,15 @@
</span><span class="cx">         executable-&gt;clearCode();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::deleteAllUnlinkedCodeBlocks()
</del><ins>+void Heap::deleteAllUnlinkedCodeBlocks(DeleteAllCodeEffort effort)
</ins><span class="cx"> {
</span><ins>+    if (m_collectionScope &amp;&amp; effort == DeleteAllCodeIfNotCollecting)
+        return;
+    
+    PreventCollectionScope preventCollectionScope(*this);
+
+    RELEASE_ASSERT(!m_collectionScope);
+    
</ins><span class="cx">     for (ExecutableBase* current : m_executables) {
</span><span class="cx">         if (!current-&gt;isFunctionExecutable())
</span><span class="cx">             continue;
</span><span class="lines">@@ -1153,6 +1205,9 @@
</span><span class="cx"> #endif
</span><span class="cx">     
</span><span class="cx">     stopTheWorld();
</span><ins>+    
+    if (false)
+        dataLog(&quot;GC START!\n&quot;);
</ins><span class="cx"> 
</span><span class="cx">     MonotonicTime before;
</span><span class="cx">     if (Options::logGC()) {
</span><span class="lines">@@ -1204,7 +1259,7 @@
</span><span class="cx">     m_codeBlocks-&gt;writeBarrierCurrentlyExecuting(this);
</span><span class="cx">     m_codeBlocks-&gt;clearCurrentlyExecuting();
</span><span class="cx">         
</span><del>-    prepareForAllocation();
</del><ins>+    m_objectSpace.prepareForAllocation();
</ins><span class="cx">     updateAllocationLimits();
</span><span class="cx"> 
</span><span class="cx">     didFinishCollection(gcStartTime);
</span><span class="lines">@@ -1233,6 +1288,9 @@
</span><span class="cx">     }
</span><span class="cx">     ParkingLot::unparkAll(&amp;m_worldState);
</span><span class="cx"> 
</span><ins>+    if (false)
+        dataLog(&quot;GC END!\n&quot;);
+
</ins><span class="cx">     setNeedFinalize();
</span><span class="cx">     resumeTheWorld();
</span><span class="cx">     
</span><span class="lines">@@ -1248,6 +1306,11 @@
</span><span class="cx">     suspendCompilerThreads();
</span><span class="cx">     m_collectorBelievesThatTheWorldIsStopped = true;
</span><span class="cx"> 
</span><ins>+    forEachSlotVisitor(
+        [&amp;] (SlotVisitor&amp; slotVisitor) {
+            slotVisitor.updateMutatorIsStopped(NoLockingNecessary);
+        });
+
</ins><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     {
</span><span class="cx">         DeferGCForAWhile awhile(*this);
</span><span class="lines">@@ -1276,6 +1339,41 @@
</span><span class="cx">     
</span><span class="cx">     RELEASE_ASSERT(m_collectorBelievesThatTheWorldIsStopped);
</span><span class="cx">     m_collectorBelievesThatTheWorldIsStopped = false;
</span><ins>+    
+    // FIXME: This could be vastly improved: we want to grab the locks in the order in which they
+    // become available. We basically want a lockAny() method that will lock whatever lock is available
+    // and tell you which one it locked. That would require teaching ParkingLot how to park on multiple
+    // queues at once, which is totally achievable - it would just require memory allocation, which is
+    // suboptimal but not a disaster. Alternatively, we could replace the SlotVisitor rightToRun lock
+    // with a DLG-style handshake mechanism, but that seems not as general.
+    Vector&lt;SlotVisitor*, 8&gt; slotVisitorsToUpdate;
+
+    forEachSlotVisitor(
+        [&amp;] (SlotVisitor&amp; slotVisitor) {
+            slotVisitorsToUpdate.append(&amp;slotVisitor);
+        });
+    
+    for (unsigned countdown = 40; !slotVisitorsToUpdate.isEmpty() &amp;&amp; countdown--;) {
+        for (unsigned index = 0; index &lt; slotVisitorsToUpdate.size(); ++index) {
+            SlotVisitor&amp; slotVisitor = *slotVisitorsToUpdate[index];
+            bool remove = false;
+            if (slotVisitor.hasAcknowledgedThatTheMutatorIsResumed())
+                remove = true;
+            else if (auto locker = tryHoldLock(slotVisitor.rightToRun())) {
+                slotVisitor.updateMutatorIsStopped(locker);
+                remove = true;
+            }
+            if (remove) {
+                slotVisitorsToUpdate[index--] = slotVisitorsToUpdate.last();
+                slotVisitorsToUpdate.takeLast();
+            }
+        }
+        std::this_thread::yield();
+    }
+    
+    for (SlotVisitor* slotVisitor : slotVisitorsToUpdate)
+        slotVisitor-&gt;updateMutatorIsStopped();
+    
</ins><span class="cx">     resumeCompilerThreads();
</span><span class="cx">     resumeTheMutator();
</span><span class="cx"> }
</span><span class="lines">@@ -1339,7 +1437,12 @@
</span><span class="cx"> void Heap::stopIfNecessarySlow()
</span><span class="cx"> {
</span><span class="cx">     while (stopIfNecessarySlow(m_worldState.load())) { }
</span><ins>+    
+    RELEASE_ASSERT(m_worldState.load() &amp; hasAccessBit);
+    RELEASE_ASSERT(!(m_worldState.load() &amp; stoppedBit));
+    
</ins><span class="cx">     handleGCDidJIT();
</span><ins>+    handleNeedFinalize();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool Heap::stopIfNecessarySlow(unsigned oldState)
</span><span class="lines">@@ -1346,7 +1449,10 @@
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(oldState &amp; hasAccessBit);
</span><span class="cx">     
</span><del>-    if (handleNeedFinalize(oldState))
</del><ins>+    // It's possible for us to wake up with finalization already requested but the world not yet
+    // resumed. If that happens, we can't run finalization yet.
+    if (!(oldState &amp; stoppedBit)
+        &amp;&amp; handleNeedFinalize(oldState))
</ins><span class="cx">         return true;
</span><span class="cx">     
</span><span class="cx">     if (!(oldState &amp; shouldStopBit)) {
</span><span class="lines">@@ -1356,6 +1462,12 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    sanitizeStackForVM(m_vm);
+
+    if (verboseStop) {
+        dataLog(&quot;Stopping!\n&quot;);
+        WTFReportBacktrace();
+    }
</ins><span class="cx">     m_worldState.compareExchangeStrong(oldState, oldState | stoppedBit);
</span><span class="cx">     ParkingLot::unparkAll(&amp;m_worldState);
</span><span class="cx">     ParkingLot::compareAndPark(&amp;m_worldState, oldState | stoppedBit);
</span><span class="lines">@@ -1402,6 +1514,10 @@
</span><span class="cx">         
</span><span class="cx">         if (oldState &amp; shouldStopBit) {
</span><span class="cx">             RELEASE_ASSERT(oldState &amp; stoppedBit);
</span><ins>+            if (verboseStop) {
+                dataLog(&quot;Stopping in acquireAccess!\n&quot;);
+                WTFReportBacktrace();
+            }
</ins><span class="cx">             // Wait until we're not stopped anymore.
</span><span class="cx">             ParkingLot::compareAndPark(&amp;m_worldState, oldState);
</span><span class="cx">             continue;
</span><span class="lines">@@ -1458,6 +1574,8 @@
</span><span class="cx"> bool Heap::handleNeedFinalize(unsigned oldState)
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(oldState &amp; hasAccessBit);
</span><ins>+    RELEASE_ASSERT(!(oldState &amp; stoppedBit));
+    
</ins><span class="cx">     if (!(oldState &amp; needFinalizeBit))
</span><span class="cx">         return false;
</span><span class="cx">     if (m_worldState.compareExchangeWeak(oldState, oldState &amp; ~needFinalizeBit)) {
</span><span class="lines">@@ -1536,8 +1654,6 @@
</span><span class="cx">         sweepLargeAllocations();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    if (Options::collectContinuously())
-        collectAsync();
</del><span class="cx">     if (HasOwnPropertyCache* cache = vm()-&gt;hasOwnPropertyCache())
</span><span class="cx">         cache-&gt;clear();
</span><span class="cx"> }
</span><span class="lines">@@ -1549,8 +1665,6 @@
</span><span class="cx">     ASSERT(vm()-&gt;currentThreadIsHoldingAPILock());
</span><span class="cx">     RELEASE_ASSERT(vm()-&gt;atomicStringTable() == wtfThreadData().atomicStringTable());
</span><span class="cx">     
</span><del>-    sanitizeStackForVM(m_vm);
-
</del><span class="cx">     LockHolder locker(*m_threadLock);
</span><span class="cx">     m_requests.append(scope);
</span><span class="cx">     m_lastGrantedTicket++;
</span><span class="lines">@@ -1592,10 +1706,14 @@
</span><span class="cx">         m_shouldDoFullCollection = false;
</span><span class="cx">         if (Options::logGC())
</span><span class="cx">             dataLog(&quot;FullCollection, &quot;);
</span><ins>+        if (false)
+            dataLog(&quot;Full collection!\n&quot;);
</ins><span class="cx">     } else {
</span><span class="cx">         m_collectionScope = CollectionScope::Eden;
</span><span class="cx">         if (Options::logGC())
</span><span class="cx">             dataLog(&quot;EdenCollection, &quot;);
</span><ins>+        if (false)
+            dataLog(&quot;Eden collection!\n&quot;);
</ins><span class="cx">     }
</span><span class="cx">     if (m_collectionScope == CollectionScope::Full) {
</span><span class="cx">         m_sizeBeforeLastFullCollect = m_sizeAfterLastCollect + m_bytesAllocatedThisCycle;
</span><span class="lines">@@ -1668,11 +1786,6 @@
</span><span class="cx">     m_sweeper-&gt;startSweeping();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::prepareForAllocation()
-{
-    m_objectSpace.prepareForAllocation();
-}
-
</del><span class="cx"> void Heap::updateAllocationLimits()
</span><span class="cx"> {
</span><span class="cx">     static const bool verbose = false;
</span><span class="lines">@@ -2137,8 +2250,67 @@
</span><span class="cx"> void Heap::notifyIsSafeToCollect()
</span><span class="cx"> {
</span><span class="cx">     m_isSafeToCollect = true;
</span><del>-    if (Options::collectContinuously())
-        collectAsync();
</del><ins>+    
+    if (Options::collectContinuously()) {
+        m_collectContinuouslyThread = createThread(
+            &quot;JSC DEBUG Continuous GC&quot;,
+            [this] () {
+                MonotonicTime initialTime = MonotonicTime::now();
+                Seconds period = Seconds::fromMilliseconds(Options::collectContinuouslyPeriodMS());
+                while (!m_shouldStopCollectingContinuously) {
+                    {
+                        LockHolder locker(*m_threadLock);
+                        if (m_requests.isEmpty()) {
+                            m_requests.append(std::nullopt);
+                            m_lastGrantedTicket++;
+                            m_threadCondition-&gt;notifyOne(locker);
+                        }
+                    }
+                    
+                    {
+                        LockHolder locker(m_collectContinuouslyLock);
+                        Seconds elapsed = MonotonicTime::now() - initialTime;
+                        Seconds elapsedInPeriod = elapsed % period;
+                        MonotonicTime timeToWakeUp =
+                            initialTime + elapsed - elapsedInPeriod + period;
+                        while (!hasElapsed(timeToWakeUp) &amp;&amp; !m_shouldStopCollectingContinuously) {
+                            m_collectContinuouslyCondition.waitUntil(
+                                m_collectContinuouslyLock, timeToWakeUp);
+                        }
+                    }
+                }
+            });
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Heap::preventCollection()
+{
+    // This prevents the collectContinuously thread from starting a collection.
+    m_collectContinuouslyLock.lock();
+    
+    // Wait for all collections to finish.
+    waitForCollector(
+        [&amp;] (const LockHolder&amp;) -&gt; bool {
+            ASSERT(m_lastServedTicket &lt;= m_lastGrantedTicket);
+            return m_lastServedTicket == m_lastGrantedTicket;
+        });
+    
+    // Now a collection can only start if this thread starts it.
+    RELEASE_ASSERT(!m_collectionScope);
+}
+
+void Heap::allowCollection()
+{
+    m_collectContinuouslyLock.unlock();
+}
+
+template&lt;typename Func&gt;
+void Heap::forEachSlotVisitor(const Func&amp; func)
+{
+    auto locker = holdLock(m_parallelSlotVisitorLock);
+    func(*m_collectorSlotVisitor);
+    for (auto&amp; slotVisitor : m_parallelSlotVisitors)
+        func(*slotVisitor);
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/Heap.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -24,6 +24,7 @@
</span><span class="cx"> #include &quot;ArrayBuffer.h&quot;
</span><span class="cx"> #include &quot;CellState.h&quot;
</span><span class="cx"> #include &quot;CollectionScope.h&quot;
</span><ins>+#include &quot;DeleteAllCodeEffort.h&quot;
</ins><span class="cx"> #include &quot;GCIncomingRefCountedSet.h&quot;
</span><span class="cx"> #include &quot;HandleSet.h&quot;
</span><span class="cx"> #include &quot;HandleStack.h&quot;
</span><span class="lines">@@ -39,6 +40,7 @@
</span><span class="cx"> #include &quot;StructureIDTable.h&quot;
</span><span class="cx"> #include &quot;TinyBloomFilter.h&quot;
</span><span class="cx"> #include &quot;UnconditionalFinalizer.h&quot;
</span><ins>+#include &quot;VisitRaceKey.h&quot;
</ins><span class="cx"> #include &quot;WeakHandleOwner.h&quot;
</span><span class="cx"> #include &quot;WeakReferenceHarvester.h&quot;
</span><span class="cx"> #include &quot;WriteBarrierBuffer.h&quot;
</span><span class="lines">@@ -254,8 +256,8 @@
</span><span class="cx">     size_t sizeBeforeLastFullCollection() const { return m_sizeBeforeLastFullCollect; }
</span><span class="cx">     size_t sizeAfterLastFullCollection() const { return m_sizeAfterLastFullCollect; }
</span><span class="cx"> 
</span><del>-    void deleteAllCodeBlocks();
-    void deleteAllUnlinkedCodeBlocks();
</del><ins>+    void deleteAllCodeBlocks(DeleteAllCodeEffort);
+    void deleteAllUnlinkedCodeBlocks(DeleteAllCodeEffort);
</ins><span class="cx"> 
</span><span class="cx">     void didAllocate(size_t);
</span><span class="cx">     bool isPagedOut(double deadline);
</span><span class="lines">@@ -337,6 +339,16 @@
</span><span class="cx">     // already be called for you at the right times.
</span><span class="cx">     void stopIfNecessary();
</span><span class="cx">     
</span><ins>+    // This is a much stronger kind of stopping of the collector, and it may require waiting for a
+    // while. This is meant to be a legacy API for clients of collectAllGarbage that expect that there
+    // is no GC before or after that function call. After calling this, you are free to start GCs
+    // yourself but you can be sure that none are running.
+    //
+    // This both prevents new collections from being started asynchronously and waits for any
+    // outstanding collections to complete.
+    void preventCollection();
+    void allowCollection();
+    
</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">@@ -451,7 +463,6 @@
</span><span class="cx">     void snapshotUnswept();
</span><span class="cx">     void deleteSourceProviderCaches();
</span><span class="cx">     void notifyIncrementalSweeper();
</span><del>-    void prepareForAllocation();
</del><span class="cx">     void harvestWeakReferences();
</span><span class="cx">     void finalizeUnconditionalFinalizers();
</span><span class="cx">     void clearUnmarkedExecutables();
</span><span class="lines">@@ -523,6 +534,9 @@
</span><span class="cx">     Vector&lt;std::unique_ptr&lt;SlotVisitor&gt;&gt; m_parallelSlotVisitors;
</span><span class="cx">     Vector&lt;SlotVisitor*&gt; m_availableParallelSlotVisitors;
</span><span class="cx">     Lock m_parallelSlotVisitorLock;
</span><ins>+    
+    template&lt;typename Func&gt;
+    void forEachSlotVisitor(const Func&amp;);
</ins><span class="cx"> 
</span><span class="cx">     HandleSet m_handleSet;
</span><span class="cx">     HandleStack m_handleStack;
</span><span class="lines">@@ -565,6 +579,9 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     HashMap&lt;void*, std::function&lt;void()&gt;&gt; m_weakGCMaps;
</span><ins>+    
+    HashSet&lt;VisitRaceKey&gt; m_visitRaces;
+    Lock m_visitRaceLock;
</ins><span class="cx"> 
</span><span class="cx">     Lock m_markingMutex;
</span><span class="cx">     Condition m_markingConditionVariable;
</span><span class="lines">@@ -608,6 +625,11 @@
</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 class="cx">     
</span><ins>+    Lock m_collectContinuouslyLock;
+    Condition m_collectContinuouslyCondition;
+    bool m_shouldStopCollectingContinuously { false };
+    ThreadIdentifier m_collectContinuouslyThread { 0 };
+    
</ins><span class="cx">     MonotonicTime m_lastGCStartTime;
</span><span class="cx">     MonotonicTime m_lastGCEndTime;
</span><span class="cx">     MonotonicTime m_currentGCStartTime;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/HeapInlines.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapInlines.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/HeapInlines.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -134,7 +134,7 @@
</span><span class="cx">         return;
</span><span class="cx">     if (!isWithinThreshold(from-&gt;cellState(), barrierThreshold()))
</span><span class="cx">         return;
</span><del>-    if (LIKELY(!to || to-&gt;cellState() != CellState::NewWhite))
</del><ins>+    if (LIKELY(!to))
</ins><span class="cx">         return;
</span><span class="cx">     writeBarrierSlowPath(from);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapSnapshotBuildercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/HeapSnapshotBuilder.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapSnapshotBuilder.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/HeapSnapshotBuilder.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #include &quot;HeapSnapshot.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;JSCell.h&quot;
</span><ins>+#include &quot;PreventCollectionScope.h&quot;
</ins><span class="cx"> #include &quot;VM.h&quot;
</span><span class="cx"> #include &lt;wtf/text/StringBuilder.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -52,6 +53,8 @@
</span><span class="cx"> 
</span><span class="cx"> void HeapSnapshotBuilder::buildSnapshot()
</span><span class="cx"> {
</span><ins>+    PreventCollectionScope preventCollectionScope(m_profiler.vm().heap);
+    
</ins><span class="cx">     m_snapshot = std::make_unique&lt;HeapSnapshot&gt;(m_profiler.mostRecentSnapshot());
</span><span class="cx">     {
</span><span class="cx">         m_profiler.setActiveSnapshotBuilder(this);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapLargeAllocationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/LargeAllocation.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/LargeAllocation.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/LargeAllocation.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -108,5 +108,14 @@
</span><span class="cx">     out.print(RawPointer(this), &quot;:(cell at &quot;, RawPointer(cell()), &quot; with size &quot;, m_cellSize, &quot; and attributes &quot;, m_attributes, &quot;)&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if !ASSERT_DISABLED
+void LargeAllocation::assertValidCell(VM&amp; vm, HeapCell* cell) const
+{
+    ASSERT(&amp;vm == this-&gt;vm());
+    ASSERT(cell == this-&gt;cell());
+    ASSERT(m_hasValidCell);
+}
+#endif
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapLargeAllocationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/LargeAllocation.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/LargeAllocation.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/LargeAllocation.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -121,6 +121,12 @@
</span><span class="cx">     
</span><span class="cx">     void noteMarked() { }
</span><span class="cx">     
</span><ins>+#if ASSERT_DISABLED
+    void assertValidCell(VM&amp;, HeapCell*) const { }
+#else
+    void assertValidCell(VM&amp;, HeapCell*) const;
+#endif
+    
</ins><span class="cx">     void sweep();
</span><span class="cx">     
</span><span class="cx">     void destroy();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapListableHandlerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/ListableHandler.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/ListableHandler.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/ListableHandler.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- *  Copyright (C) 2011 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2011-2016 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">@@ -33,6 +33,12 @@
</span><span class="cx"> template&lt;typename T&gt;
</span><span class="cx"> class ListableHandler {
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(ListableHandler);
</span><ins>+
+public:    
+    bool isOnList() const
+    {
+        return m_nextAndFlag &amp; 1;
+    }
</ins><span class="cx">     
</span><span class="cx"> protected:
</span><span class="cx">     ListableHandler()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapLockDuringMarkingh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/LockDuringMarking.h (0 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/LockDuringMarking.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/heap/LockDuringMarking.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -0,0 +1,47 @@
</span><ins>+/*
+ * Copyright (C) 2016 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 &lt;heap/Heap.h&gt;
+#include &lt;wtf/Locker.h&gt;
+
+namespace JSC {
+
+// Use this lock scope like so:
+// auto locker = lockDuringMarking(heap, lock);
+template&lt;typename LockType&gt;
+Locker&lt;LockType&gt; lockDuringMarking(Heap&amp; heap, LockType&amp; passedLock)
+{
+    LockType* lock;
+    if (heap.mutatorShouldBeFenced())
+        lock = &amp;passedLock;
+    else
+        lock = nullptr;
+    return Locker&lt;LockType&gt;(lock);
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedAllocatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -104,7 +104,7 @@
</span><span class="cx">         if (m_allocationCursor &gt;= m_blocks.size())
</span><span class="cx">             break;
</span><span class="cx">         
</span><del>-        setIsCanAllocateButNotEmpty(m_allocationCursor, false);
</del><ins>+        setIsCanAllocateButNotEmpty(NoLockingNecessary, m_allocationCursor, false);
</ins><span class="cx"> 
</span><span class="cx">         if (void* result = tryAllocateIn(m_blocks[m_allocationCursor]))
</span><span class="cx">             return result;
</span><span class="lines">@@ -147,8 +147,8 @@
</span><span class="cx">         ASSERT(block-&gt;isFreeListed());
</span><span class="cx">         block-&gt;unsweepWithNoNewlyAllocated();
</span><span class="cx">         ASSERT(!block-&gt;isFreeListed());
</span><del>-        ASSERT(!isEmpty(block));
-        ASSERT(!isCanAllocateButNotEmpty(block));
</del><ins>+        ASSERT(!isEmpty(NoLockingNecessary, block));
+        ASSERT(!isCanAllocateButNotEmpty(NoLockingNecessary, block));
</ins><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -166,7 +166,7 @@
</span><span class="cx">         result = head;
</span><span class="cx">     }
</span><span class="cx">     RELEASE_ASSERT(result);
</span><del>-    setIsEden(m_currentBlock, true);
</del><ins>+    setIsEden(NoLockingNecessary, m_currentBlock, true);
</ins><span class="cx">     m_markedSpace-&gt;didAllocateInBlock(m_currentBlock);
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="lines">@@ -276,6 +276,7 @@
</span><span class="cx">             
</span><span class="cx">             ASSERT(m_blocks.capacity() &gt; oldCapacity);
</span><span class="cx">             
</span><ins>+            LockHolder locker(m_bitvectorLock);
</ins><span class="cx">             forEachBitVector(
</span><span class="cx">                 [&amp;] (FastBitVector&amp; vector) {
</span><span class="cx">                     vector.resize(m_blocks.capacity());
</span><span class="lines">@@ -295,8 +296,8 @@
</span><span class="cx">     // This is the point at which the block learns of its cellSize() and attributes().
</span><span class="cx">     block-&gt;didAddToAllocator(this, index);
</span><span class="cx">     
</span><del>-    setIsLive(index, true);
-    setIsEmpty(index, true);
</del><ins>+    setIsLive(NoLockingNecessary, index, true);
+    setIsEmpty(NoLockingNecessary, index, true);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MarkedAllocator::removeBlock(MarkedBlock::Handle* block)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedAllocatorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedAllocator.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedAllocator.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/MarkedAllocator.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -171,13 +171,13 @@
</span><span class="cx">     
</span><span class="cx">     static size_t blockSizeForBytes(size_t);
</span><span class="cx">     
</span><ins>+    Lock&amp; bitvectorLock() { return m_bitvectorLock; }
+   
</ins><span class="cx"> #define MARKED_ALLOCATOR_BIT_ACCESSORS(lowerBitName, capitalBitName)     \
</span><del>-    bool is ## capitalBitName(size_t index) const { return m_ ## lowerBitName[index]; } \
-    bool is ## capitalBitName(MarkedBlock::Handle* block) const { return is ## capitalBitName(block-&gt;index()); } \
-    void setIs ## capitalBitName(size_t index, bool value) { m_ ## lowerBitName[index] = value; } \
-    void setIs ## capitalBitName(MarkedBlock::Handle* block, bool value) { setIs ## capitalBitName(block-&gt;index(), value); } \
-    bool atomicSetAndCheckIs ## capitalBitName(size_t index, bool value) { return m_ ## lowerBitName.atomicSetAndCheck(index, value); } \
-    bool atomicSetAndCheckIs ## capitalBitName(MarkedBlock::Handle* block, bool value) { return m_ ## lowerBitName.atomicSetAndCheck(block-&gt;index(), value); }
</del><ins>+    bool is ## capitalBitName(const AbstractLocker&amp;, size_t index) const { return m_ ## lowerBitName[index]; } \
+    bool is ## capitalBitName(const AbstractLocker&amp; locker, MarkedBlock::Handle* block) const { return is ## capitalBitName(locker, block-&gt;index()); } \
+    void setIs ## capitalBitName(const AbstractLocker&amp;, size_t index, bool value) { m_ ## lowerBitName[index] = value; } \
+    void setIs ## capitalBitName(const AbstractLocker&amp; locker, MarkedBlock::Handle* block, bool value) { setIs ## capitalBitName(locker, block-&gt;index(), value); }
</ins><span class="cx">     FOR_EACH_MARKED_ALLOCATOR_BIT(MARKED_ALLOCATOR_BIT_ACCESSORS)
</span><span class="cx"> #undef MARKED_ALLOCATOR_BIT_ACCESSORS
</span><span class="cx"> 
</span><span class="lines">@@ -210,7 +210,7 @@
</span><span class="cx">     
</span><span class="cx">     void dump(PrintStream&amp;) const;
</span><span class="cx">     void dumpBits(PrintStream&amp; = WTF::dataFile());
</span><del>-   
</del><ins>+    
</ins><span class="cx"> private:
</span><span class="cx">     friend class MarkedBlock;
</span><span class="cx">     
</span><span class="lines">@@ -232,7 +232,10 @@
</span><span class="cx">     
</span><span class="cx">     Vector&lt;MarkedBlock::Handle*&gt; m_blocks;
</span><span class="cx">     Vector&lt;unsigned&gt; m_freeBlockIndices;
</span><del>-    
</del><ins>+
+    // Mutator uses this to guard resizing the bitvectors. Those things in the GC that may run
+    // concurrently to the mutator must lock this when accessing the bitvectors.
+    Lock m_bitvectorLock;
</ins><span class="cx"> #define MARKED_ALLOCATOR_BIT_DECLARATION(lowerBitName, capitalBitName) \
</span><span class="cx">     FastBitVector m_ ## lowerBitName;
</span><span class="cx">     FOR_EACH_MARKED_ALLOCATOR_BIT(MARKED_ALLOCATOR_BIT_DECLARATION)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx">     if (computeBalance) {
</span><span class="cx">         balance++;
</span><span class="cx">         if (!(balance % 10))
</span><del>-            dataLog(&quot;MarkedBlock Balance: &quot;, balance, &quot;\n&quot;);
</del><ins>+            dataLog(toCString(&quot;MarkedBlock Balance: &quot;, balance, &quot;\n&quot;));
</ins><span class="cx">     }
</span><span class="cx">     void* blockSpace = tryFastAlignedMalloc(blockSize, blockSize);
</span><span class="cx">     if (!blockSpace)
</span><span class="lines">@@ -71,7 +71,7 @@
</span><span class="cx">     if (computeBalance) {
</span><span class="cx">         balance--;
</span><span class="cx">         if (!(balance % 10))
</span><del>-            dataLog(&quot;MarkedBlock Balance: &quot;, balance, &quot;\n&quot;);
</del><ins>+            dataLog(toCString(&quot;MarkedBlock Balance: &quot;, balance, &quot;\n&quot;));
</ins><span class="cx">     }
</span><span class="cx">     removeFromAllocator();
</span><span class="cx">     m_block-&gt;~MarkedBlock();
</span><span class="lines">@@ -85,7 +85,7 @@
</span><span class="cx">     , m_vm(&amp;vm)
</span><span class="cx"> {
</span><span class="cx">     if (false)
</span><del>-        dataLog(RawPointer(this), &quot;: Allocated.\n&quot;);
</del><ins>+        dataLog(toCString(RawPointer(this), &quot;: Allocated.\n&quot;));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 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;
</span><span class="lines">@@ -98,13 +98,21 @@
</span><span class="cx">     MarkedBlock&amp; block = this-&gt;block();
</span><span class="cx">     
</span><span class="cx">     if (false)
</span><del>-        dataLog(RawPointer(this), &quot;: MarkedBlock::Handle::specializedSweep!\n&quot;);
</del><ins>+        dataLog(toCString(RawPointer(this), &quot;/&quot;, RawPointer(&amp;block), &quot;: MarkedBlock::Handle::specializedSweep!\n&quot;));
</ins><span class="cx">     
</span><span class="cx">     if (Options::useBumpAllocator()
</span><span class="cx">         &amp;&amp; emptyMode == IsEmpty
</span><span class="cx">         &amp;&amp; newlyAllocatedMode == DoesNotHaveNewlyAllocated) {
</span><del>-        ASSERT(marksMode == MarksStale || block.m_marks.isEmpty());
</del><span class="cx">         
</span><ins>+        // This is an incredibly powerful assertion that checks the sanity of our block bits.
+        if (marksMode == MarksNotStale &amp;&amp; !block.m_marks.isEmpty()) {
+            dataLog(toCString(&quot;Block &quot;, RawPointer(&amp;block), &quot;: marks not empty!\n&quot;));
+            dataLog(toCString(&quot;Block lock is held: &quot;, block.m_lock.isHeld(), &quot;\n&quot;));
+            dataLog(toCString(&quot;Marking version of block: &quot;, block.m_markingVersion, &quot;\n&quot;));
+            dataLog(toCString(&quot;Marking version of heap: &quot;, space()-&gt;markingVersion(), &quot;\n&quot;));
+            RELEASE_ASSERT_NOT_REACHED();
+        }
+        
</ins><span class="cx">         char* startOfLastCell = static_cast&lt;char*&gt;(cellAlign(block.atoms() + m_endAtom - 1));
</span><span class="cx">         char* payloadEnd = startOfLastCell + cellSize();
</span><span class="cx">         RELEASE_ASSERT(payloadEnd - MarkedBlock::blockSize &lt;= bitwise_cast&lt;char*&gt;(&amp;block));
</span><span class="lines">@@ -114,12 +122,12 @@
</span><span class="cx">         if (sweepMode == SweepToFreeList)
</span><span class="cx">             setIsFreeListed();
</span><span class="cx">         else
</span><del>-            m_allocator-&gt;setIsEmpty(this, true);
</del><ins>+            m_allocator-&gt;setIsEmpty(NoLockingNecessary, this, true);
</ins><span class="cx">         if (space()-&gt;isMarking())
</span><span class="cx">             block.m_lock.unlock();
</span><span class="cx">         FreeList result = FreeList::bump(payloadEnd, payloadEnd - payloadBegin);
</span><span class="cx">         if (false)
</span><del>-            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;);
</del><ins>+            dataLog(toCString(&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;));
</ins><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -176,15 +184,15 @@
</span><span class="cx">     if (sweepMode == SweepToFreeList)
</span><span class="cx">         setIsFreeListed();
</span><span class="cx">     else if (isEmpty)
</span><del>-        m_allocator-&gt;setIsEmpty(this, true);
</del><ins>+        m_allocator-&gt;setIsEmpty(NoLockingNecessary, this, true);
</ins><span class="cx">     if (false)
</span><del>-        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;);
</del><ins>+        dataLog(toCString(&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;));
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> FreeList MarkedBlock::Handle::sweep(SweepMode sweepMode)
</span><span class="cx"> {
</span><del>-    m_allocator-&gt;setIsUnswept(this, false);
</del><ins>+    m_allocator-&gt;setIsUnswept(NoLockingNecessary, this, false);
</ins><span class="cx">     
</span><span class="cx">     m_weakSet.sweep();
</span><span class="cx"> 
</span><span class="lines">@@ -196,7 +204,7 @@
</span><span class="cx">         return FreeList();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    ASSERT(!m_allocator-&gt;isAllocated(this));
</del><ins>+    ASSERT(!m_allocator-&gt;isAllocated(NoLockingNecessary, this));
</ins><span class="cx">     
</span><span class="cx">     if (space()-&gt;isMarking())
</span><span class="cx">         block().m_lock.lock();
</span><span class="lines">@@ -227,7 +235,7 @@
</span><span class="cx">     //   sweep proved that the block is empty.
</span><span class="cx">     // - It's false if there are any destructors that need to be called, even if the block has no
</span><span class="cx">     //   live objects.
</span><del>-    if (m_allocator-&gt;isEmpty(this))
</del><ins>+    if (m_allocator-&gt;isEmpty(NoLockingNecessary, this))
</ins><span class="cx">         return sweepHelperSelectHasNewlyAllocated&lt;IsEmpty, destructionMode, scribbleMode&gt;(sweepMode);
</span><span class="cx">     return sweepHelperSelectHasNewlyAllocated&lt;NotEmpty, destructionMode, scribbleMode&gt;(sweepMode);
</span><span class="cx"> }
</span><span class="lines">@@ -254,7 +262,7 @@
</span><span class="cx">     HeapVersion markingVersion = space()-&gt;markingVersion();
</span><span class="cx">     bool marksAreUseful = !block().areMarksStale(markingVersion);
</span><span class="cx">     
</span><del>-    if (space()-&gt;isMarking())
</del><ins>+    if (space()-&gt;isMarking() &amp;&amp; heap()-&gt;collectionScope() == CollectionScope::Full)
</ins><span class="cx">         marksAreUseful |= block().marksConveyLivenessDuringMarking(markingVersion);
</span><span class="cx">     
</span><span class="cx">     if (!marksAreUseful)
</span><span class="lines">@@ -270,19 +278,21 @@
</span><span class="cx"> 
</span><span class="cx"> void MarkedBlock::Handle::setIsFreeListed()
</span><span class="cx"> {
</span><del>-    m_allocator-&gt;setIsEmpty(this, false);
</del><ins>+    m_allocator-&gt;setIsEmpty(NoLockingNecessary, this, false);
</ins><span class="cx">     m_isFreeListed = true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MarkedBlock::Handle::stopAllocating(const FreeList&amp; freeList)
</span><span class="cx"> {
</span><ins>+    auto locker = holdLock(block().m_lock);
+    
</ins><span class="cx">     if (false)
</span><del>-        dataLog(RawPointer(this), &quot;: MarkedBlock::Handle::stopAllocating!\n&quot;);
-    ASSERT(!allocator()-&gt;isAllocated(this));
</del><ins>+        dataLog(toCString(RawPointer(this), &quot;: MarkedBlock::Handle::stopAllocating!\n&quot;));
+    ASSERT(!allocator()-&gt;isAllocated(NoLockingNecessary, this));
</ins><span class="cx"> 
</span><span class="cx">     if (!isFreeListed()) {
</span><span class="cx">         if (false)
</span><del>-            dataLog(&quot;There ain't no newly allocated.\n&quot;);
</del><ins>+            dataLog(toCString(&quot;There ain't no newly allocated.\n&quot;));
</ins><span class="cx">         // This means that we either didn't use this block at all for allocation since last GC,
</span><span class="cx">         // or someone had already done stopAllocating() before.
</span><span class="cx">         ASSERT(freeList.allocationWillFail());
</span><span class="lines">@@ -290,7 +300,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (false)
</span><del>-        dataLog(&quot;Free list: &quot;, freeList, &quot;\n&quot;);
</del><ins>+        dataLog(toCString(&quot;Free list: &quot;, freeList, &quot;\n&quot;));
</ins><span class="cx">     
</span><span class="cx">     // Roll back to a coherent state for Heap introspection. Cells newly
</span><span class="cx">     // allocated from our free list are not currently marked, so we need another
</span><span class="lines">@@ -309,7 +319,7 @@
</span><span class="cx">         freeList,
</span><span class="cx">         [&amp;] (HeapCell* cell) {
</span><span class="cx">             if (false)
</span><del>-                dataLog(&quot;Free cell: &quot;, RawPointer(cell), &quot;\n&quot;);
</del><ins>+                dataLog(toCString(&quot;Free cell: &quot;, RawPointer(cell), &quot;\n&quot;));
</ins><span class="cx">             if (m_attributes.destruction == NeedsDestruction)
</span><span class="cx">                 cell-&gt;zap();
</span><span class="cx">             clearNewlyAllocated(cell);
</span><span class="lines">@@ -320,7 +330,7 @@
</span><span class="cx"> 
</span><span class="cx"> void MarkedBlock::Handle::lastChanceToFinalize()
</span><span class="cx"> {
</span><del>-    allocator()-&gt;setIsAllocated(this, false);
</del><ins>+    allocator()-&gt;setIsAllocated(NoLockingNecessary, this, false);
</ins><span class="cx">     m_block-&gt;m_marks.clearAll();
</span><span class="cx">     m_block-&gt;clearHasAnyMarked();
</span><span class="cx">     m_block-&gt;m_markingVersion = heap()-&gt;objectSpace().markingVersion();
</span><span class="lines">@@ -332,16 +342,20 @@
</span><span class="cx"> 
</span><span class="cx"> FreeList MarkedBlock::Handle::resumeAllocating()
</span><span class="cx"> {
</span><del>-    if (false)
-        dataLog(RawPointer(this), &quot;: MarkedBlock::Handle::resumeAllocating!\n&quot;);
-    ASSERT(!allocator()-&gt;isAllocated(this));
-    ASSERT(!isFreeListed());
-
-    if (!hasAnyNewlyAllocated()) {
</del><ins>+    {
+        auto locker = holdLock(block().m_lock);
+        
</ins><span class="cx">         if (false)
</span><del>-            dataLog(&quot;There ain't no newly allocated.\n&quot;);
-        // This means we had already exhausted the block when we stopped allocation.
-        return FreeList();
</del><ins>+            dataLog(toCString(RawPointer(this), &quot;: MarkedBlock::Handle::resumeAllocating!\n&quot;));
+        ASSERT(!allocator()-&gt;isAllocated(NoLockingNecessary, this));
+        ASSERT(!isFreeListed());
+        
+        if (!hasAnyNewlyAllocated()) {
+            if (false)
+                dataLog(toCString(&quot;There ain't no newly allocated.\n&quot;));
+            // This means we had already exhausted the block when we stopped allocation.
+            return FreeList();
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Re-create our free list from before stopping allocation. Note that this may return an empty
</span><span class="lines">@@ -378,13 +392,16 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(vm()-&gt;heap.objectSpace().isMarking());
</span><span class="cx">     LockHolder locker(m_lock);
</span><ins>+    
</ins><span class="cx">     if (!areMarksStale(markingVersion))
</span><span class="cx">         return;
</span><span class="cx">     
</span><del>-    if (handle().allocator()-&gt;isAllocated(&amp;handle())
</del><ins>+    MarkedAllocator* allocator = handle().allocator();
+
+    if (handle().allocator()-&gt;isAllocated(holdLock(allocator-&gt;bitvectorLock()), &amp;handle())
</ins><span class="cx">         || !marksConveyLivenessDuringMarking(markingVersion)) {
</span><span class="cx">         if (false)
</span><del>-            dataLog(RawPointer(this), &quot;: Clearing marks without doing anything else.\n&quot;);
</del><ins>+            dataLog(toCString(RawPointer(this), &quot;: Clearing marks without doing anything else.\n&quot;));
</ins><span class="cx">         // We already know that the block is full and is already recognized as such, or that the
</span><span class="cx">         // block did not survive the previous GC. So, we can clear mark bits the old fashioned
</span><span class="cx">         // way. Note that it's possible for such a block to have newlyAllocated with an up-to-
</span><span class="lines">@@ -394,7 +411,7 @@
</span><span class="cx">         m_marks.clearAll();
</span><span class="cx">     } else {
</span><span class="cx">         if (false)
</span><del>-            dataLog(RawPointer(this), &quot;: Doing things.\n&quot;);
</del><ins>+            dataLog(toCString(RawPointer(this), &quot;: Doing things.\n&quot;));
</ins><span class="cx">         HeapVersion newlyAllocatedVersion = space()-&gt;newlyAllocatedVersion();
</span><span class="cx">         if (handle().m_newlyAllocatedVersion == newlyAllocatedVersion) {
</span><span class="cx">             // Merge the contents of marked into newlyAllocated. If we get the full set of bits
</span><span class="lines">@@ -412,7 +429,7 @@
</span><span class="cx">     m_markingVersion = markingVersion;
</span><span class="cx">     
</span><span class="cx">     // This means we're the first ones to mark any object in this block.
</span><del>-    handle().allocator()-&gt;atomicSetAndCheckIsMarkingNotEmpty(&amp;handle(), true);
</del><ins>+    allocator-&gt;setIsMarkingNotEmpty(holdLock(allocator-&gt;bitvectorLock()), &amp;handle(), true);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MarkedBlock::Handle::resetAllocated()
</span><span class="lines">@@ -458,11 +475,12 @@
</span><span class="cx"> 
</span><span class="cx"> void MarkedBlock::Handle::didConsumeFreeList()
</span><span class="cx"> {
</span><ins>+    auto locker = holdLock(block().m_lock);
</ins><span class="cx">     if (false)
</span><del>-        dataLog(RawPointer(this), &quot;: MarkedBlock::Handle::didConsumeFreeList!\n&quot;);
</del><ins>+        dataLog(toCString(RawPointer(this), &quot;: MarkedBlock::Handle::didConsumeFreeList!\n&quot;));
</ins><span class="cx">     ASSERT(isFreeListed());
</span><span class="cx">     m_isFreeListed = false;
</span><del>-    allocator()-&gt;atomicSetAndCheckIsAllocated(this, true);
</del><ins>+    allocator()-&gt;setIsAllocated(NoLockingNecessary, this, true);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> size_t MarkedBlock::markCount()
</span><span class="lines">@@ -472,7 +490,7 @@
</span><span class="cx"> 
</span><span class="cx"> bool MarkedBlock::Handle::isEmpty()
</span><span class="cx"> {
</span><del>-    return m_allocator-&gt;isEmpty(this);
</del><ins>+    return m_allocator-&gt;isEmpty(NoLockingNecessary, this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MarkedBlock::clearHasAnyMarked()
</span><span class="lines">@@ -482,7 +500,8 @@
</span><span class="cx"> 
</span><span class="cx"> void MarkedBlock::noteMarkedSlow()
</span><span class="cx"> {
</span><del>-    handle().allocator()-&gt;atomicSetAndCheckIsMarkingRetired(&amp;handle(), true);
</del><ins>+    MarkedAllocator* allocator = handle().allocator();
+    allocator-&gt;setIsMarkingRetired(holdLock(allocator-&gt;bitvectorLock()), &amp;handle(), true);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MarkedBlock::Handle::removeFromAllocator()
</span><span class="lines">@@ -546,6 +565,14 @@
</span><span class="cx">     return isLiveCell(space()-&gt;markingVersion(), space()-&gt;isMarking(), p);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if !ASSERT_DISABLED
+void MarkedBlock::assertValidCell(VM&amp; vm, HeapCell* cell) const
+{
+    ASSERT(&amp;vm == this-&gt;vm());
+    ASSERT(const_cast&lt;MarkedBlock*&gt;(this)-&gt;handle().cellAlign(cell) == cell);
+}
+#endif
+
</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 (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedBlock.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/MarkedBlock.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -271,6 +271,11 @@
</span><span class="cx">     
</span><span class="cx">     bool hasAnyMarked() const;
</span><span class="cx">     void noteMarked();
</span><ins>+#if ASSERT_DISABLED
+    void assertValidCell(VM&amp;, HeapCell*) const { }
+#else
+    void assertValidCell(VM&amp;, HeapCell*) const;
+#endif
</ins><span class="cx">         
</span><span class="cx">     WeakSet&amp; weakSet();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedBlockInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedBlockInlines.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedBlockInlines.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/MarkedBlockInlines.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -64,7 +64,7 @@
</span><span class="cx">             return true;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    if (allocator()-&gt;isAllocated(this))
</del><ins>+    if (allocator()-&gt;isAllocated(NoLockingNecessary, this))
</ins><span class="cx">         return true;
</span><span class="cx">     
</span><span class="cx">     MarkedBlock&amp; block = this-&gt;block();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedSpacecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -393,16 +393,13 @@
</span><span class="cx">         });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MarkedSpace::prepareForMarking()
</del><ins>+void MarkedSpace::prepareForConservativeScan()
</ins><span class="cx"> {
</span><del>-    if (m_heap-&gt;collectionScope() == CollectionScope::Eden)
-        m_largeAllocationsOffsetForThisCollection = m_largeAllocationsNurseryOffset;
-    else
-        m_largeAllocationsOffsetForThisCollection = 0;
</del><span class="cx">     m_largeAllocationsForThisCollectionBegin = m_largeAllocations.begin() + m_largeAllocationsOffsetForThisCollection;
</span><span class="cx">     m_largeAllocationsForThisCollectionSize = m_largeAllocations.size() - m_largeAllocationsOffsetForThisCollection;
</span><span class="cx">     m_largeAllocationsForThisCollectionEnd = m_largeAllocations.end();
</span><span class="cx">     RELEASE_ASSERT(m_largeAllocationsForThisCollectionEnd == m_largeAllocationsForThisCollectionBegin + m_largeAllocationsForThisCollectionSize);
</span><ins>+    
</ins><span class="cx">     std::sort(
</span><span class="cx">         m_largeAllocationsForThisCollectionBegin, m_largeAllocationsForThisCollectionEnd,
</span><span class="cx">         [&amp;] (LargeAllocation* a, LargeAllocation* b) {
</span><span class="lines">@@ -410,6 +407,14 @@
</span><span class="cx">         });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MarkedSpace::prepareForMarking()
+{
+    if (m_heap-&gt;collectionScope() == CollectionScope::Eden)
+        m_largeAllocationsOffsetForThisCollection = m_largeAllocationsNurseryOffset;
+    else
+        m_largeAllocationsOffsetForThisCollection = 0;
+}
+
</ins><span class="cx"> void MarkedSpace::resumeAllocating()
</span><span class="cx"> {
</span><span class="cx">     forEachAllocator(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedSpaceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedSpace.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedSpace.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/MarkedSpace.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -142,6 +142,8 @@
</span><span class="cx">     void resumeAllocating(); // If we just stopped allocation but we didn't do a collection, we need to resume allocation.
</span><span class="cx">     
</span><span class="cx">     void prepareForMarking();
</span><ins>+    
+    void prepareForConservativeScan();
</ins><span class="cx"> 
</span><span class="cx">     typedef HashSet&lt;MarkedBlock*&gt;::iterator BlockIterator;
</span><span class="cx"> 
</span><span class="lines">@@ -223,6 +225,7 @@
</span><span class="cx">     bool m_isIterating;
</span><span class="cx">     bool m_isMarking { false };
</span><span class="cx">     MarkedBlockSet m_blocks;
</span><ins>+    
</ins><span class="cx">     Vector&lt;LargeAllocation*&gt; m_largeAllocations;
</span><span class="cx">     unsigned m_largeAllocationsNurseryOffset { 0 };
</span><span class="cx">     unsigned m_largeAllocationsOffsetForThisCollection { 0 };
</span><span class="lines">@@ -230,6 +233,7 @@
</span><span class="cx">     LargeAllocation** m_largeAllocationsForThisCollectionBegin { nullptr };
</span><span class="cx">     LargeAllocation** m_largeAllocationsForThisCollectionEnd { nullptr };
</span><span class="cx">     unsigned m_largeAllocationsForThisCollectionSize { 0 };
</span><ins>+    
</ins><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><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapPreventCollectionScopeh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/PreventCollectionScope.h (0 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/PreventCollectionScope.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/heap/PreventCollectionScope.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -0,0 +1,50 @@
</span><ins>+/*
+ * Copyright (C) 2016 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;Heap.h&quot;
+
+namespace JSC { 
+
+class PreventCollectionScope {
+public:
+    PreventCollectionScope(Heap&amp; heap)
+        : m_heap(heap)
+    {
+        m_heap.preventCollection();
+    }
+    
+    ~PreventCollectionScope()
+    {
+        m_heap.allowCollection();
+    }
+
+private:
+    Heap&amp; m_heap;
+};
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -264,6 +264,7 @@
</span><span class="cx">     
</span><span class="cx">     CellContainer container = cell-&gt;cellContainer();
</span><span class="cx">     
</span><ins>+    container.assertValidCell(vm(), cell);
</ins><span class="cx">     container.noteMarked();
</span><span class="cx">     
</span><span class="cx">     m_visitCount++;
</span><span class="lines">@@ -328,7 +329,7 @@
</span><span class="cx">     default:
</span><span class="cx">         // FIXME: This could be so much better.
</span><span class="cx">         // https://bugs.webkit.org/show_bug.cgi?id=162462
</span><del>-        cell-&gt;methodTable()-&gt;visitChildren(const_cast&lt;JSCell*&gt;(cell), *this);
</del><ins>+        cell-&gt;methodTable(vm())-&gt;visitChildren(const_cast&lt;JSCell*&gt;(cell), *this);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -370,11 +371,41 @@
</span><span class="cx">     donateKnownParallel(m_mutatorStack, *m_heap.m_sharedMutatorMarkStack);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SlotVisitor::updateMutatorIsStopped(const AbstractLocker&amp;)
+{
+    m_mutatorIsStopped = (m_heap.collectorBelievesThatTheWorldIsStopped() &amp; m_canOptimizeForStoppedMutator);
+}
+
+void SlotVisitor::updateMutatorIsStopped()
+{
+    if (mutatorIsStoppedIsUpToDate())
+        return;
+    updateMutatorIsStopped(holdLock(m_rightToRun));
+}
+
+bool SlotVisitor::hasAcknowledgedThatTheMutatorIsResumed() const
+{
+    return !m_mutatorIsStopped;
+}
+
+bool SlotVisitor::mutatorIsStoppedIsUpToDate() const
+{
+    return m_mutatorIsStopped == (m_heap.collectorBelievesThatTheWorldIsStopped() &amp; m_canOptimizeForStoppedMutator);
+}
+
+void SlotVisitor::optimizeForStoppedMutator()
+{
+    m_canOptimizeForStoppedMutator = true;
+}
+
</ins><span class="cx"> void SlotVisitor::drain(MonotonicTime timeout)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_isInParallelMode);
</span><del>-   
</del><ins>+    
+    auto locker = holdLock(m_rightToRun);
+    
</ins><span class="cx">     while ((!m_collectorStack.isEmpty() || !m_mutatorStack.isEmpty()) &amp;&amp; !hasElapsed(timeout)) {
</span><ins>+        updateMutatorIsStopped(locker);
</ins><span class="cx">         if (!m_collectorStack.isEmpty()) {
</span><span class="cx">             m_collectorStack.refill();
</span><span class="cx">             m_isVisitingMutatorStack = false;
</span><span class="lines">@@ -389,6 +420,7 @@
</span><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">         }
</span><ins>+        m_rightToRun.safepoint();
</ins><span class="cx">         donateKnownParallel();
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -395,6 +427,19 @@
</span><span class="cx">     mergeOpaqueRootsIfNecessary();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool SlotVisitor::didReachTermination()
+{
+    return !m_heap.m_numberOfActiveParallelMarkers
+        &amp;&amp; m_heap.m_sharedCollectorMarkStack-&gt;isEmpty()
+        &amp;&amp; m_heap.m_sharedMutatorMarkStack-&gt;isEmpty();
+}
+
+bool SlotVisitor::hasWork()
+{
+    return !m_heap.m_sharedCollectorMarkStack-&gt;isEmpty()
+        || !m_heap.m_sharedMutatorMarkStack-&gt;isEmpty();
+}
+
</ins><span class="cx"> SlotVisitor::SharedDrainResult SlotVisitor::drainFromShared(SharedDrainMode sharedDrainMode, MonotonicTime timeout)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_isInParallelMode);
</span><span class="lines">@@ -402,39 +447,29 @@
</span><span class="cx">     ASSERT(Options::numberOfGCMarkers());
</span><span class="cx">     
</span><span class="cx">     {
</span><del>-        std::lock_guard&lt;Lock&gt; lock(m_heap.m_markingMutex);
</del><ins>+        LockHolder locker(m_heap.m_markingMutex);
</ins><span class="cx">         m_heap.m_numberOfActiveParallelMarkers++;
</span><span class="cx">     }
</span><span class="cx">     while (true) {
</span><span class="cx">         {
</span><del>-            std::unique_lock&lt;Lock&gt; lock(m_heap.m_markingMutex);
</del><ins>+            LockHolder locker(m_heap.m_markingMutex);
</ins><span class="cx">             m_heap.m_numberOfActiveParallelMarkers--;
</span><span class="cx">             m_heap.m_numberOfWaitingParallelMarkers++;
</span><span class="cx"> 
</span><del>-            // How we wait differs depending on drain mode.
</del><span class="cx">             if (sharedDrainMode == MasterDrain) {
</span><del>-                // Wait until either termination is reached, or until there is some work
-                // for us to do.
</del><span class="cx">                 while (true) {
</span><span class="cx">                     if (hasElapsed(timeout))
</span><span class="cx">                         return SharedDrainResult::TimedOut;
</span><span class="cx">                     
</span><del>-                    // Did we reach termination?
-                    if (!m_heap.m_numberOfActiveParallelMarkers
-                        &amp;&amp; m_heap.m_sharedCollectorMarkStack-&gt;isEmpty()
-                        &amp;&amp; m_heap.m_sharedMutatorMarkStack-&gt;isEmpty()) {
-                        // Let any sleeping slaves know it's time for them to return;
</del><ins>+                    if (didReachTermination()) {
</ins><span class="cx">                         m_heap.m_markingConditionVariable.notifyAll();
</span><span class="cx">                         return SharedDrainResult::Done;
</span><span class="cx">                     }
</span><span class="cx">                     
</span><del>-                    // Is there work to be done?
-                    if (!m_heap.m_sharedCollectorMarkStack-&gt;isEmpty()
-                        || !m_heap.m_sharedMutatorMarkStack-&gt;isEmpty())
</del><ins>+                    if (hasWork())
</ins><span class="cx">                         break;
</span><span class="cx">                     
</span><del>-                    // Otherwise wait.
-                    m_heap.m_markingConditionVariable.waitUntil(lock, timeout);
</del><ins>+                    m_heap.m_markingConditionVariable.waitUntil(m_heap.m_markingMutex, timeout);
</ins><span class="cx">                 }
</span><span class="cx">             } else {
</span><span class="cx">                 ASSERT(sharedDrainMode == SlaveDrain);
</span><span class="lines">@@ -442,21 +477,16 @@
</span><span class="cx">                 if (hasElapsed(timeout))
</span><span class="cx">                     return SharedDrainResult::TimedOut;
</span><span class="cx">                 
</span><del>-                // Did we detect termination? If so, let the master know.
-                if (!m_heap.m_numberOfActiveParallelMarkers
-                    &amp;&amp; m_heap.m_sharedCollectorMarkStack-&gt;isEmpty()
-                    &amp;&amp; m_heap.m_sharedMutatorMarkStack-&gt;isEmpty())
</del><ins>+                if (didReachTermination())
</ins><span class="cx">                     m_heap.m_markingConditionVariable.notifyAll();
</span><span class="cx"> 
</span><span class="cx">                 m_heap.m_markingConditionVariable.waitUntil(
</span><del>-                    lock, timeout,
</del><ins>+                    m_heap.m_markingMutex, timeout,
</ins><span class="cx">                     [this] {
</span><del>-                        return !m_heap.m_sharedCollectorMarkStack-&gt;isEmpty()
-                            || !m_heap.m_sharedMutatorMarkStack-&gt;isEmpty()
</del><ins>+                        return hasWork()
</ins><span class="cx">                             || m_heap.m_parallelMarkersShouldExit;
</span><span class="cx">                     });
</span><span class="cx">                 
</span><del>-                // Is the current phase done? If so, return from this function.
</del><span class="cx">                 if (m_heap.m_parallelMarkersShouldExit)
</span><span class="cx">                     return SharedDrainResult::Done;
</span><span class="cx">             }
</span><span class="lines">@@ -479,6 +509,32 @@
</span><span class="cx">     return drainFromShared(MasterDrain, timeout);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+SlotVisitor::SharedDrainResult SlotVisitor::drainInParallelPassively(MonotonicTime timeout)
+{
+    ASSERT(m_isInParallelMode);
+    
+    ASSERT(Options::numberOfGCMarkers());
+    
+    if (!m_heap.hasHeapAccess() || m_heap.collectorBelievesThatTheWorldIsStopped()) {
+        // This is an optimization over drainInParallel() when we have a concurrent mutator but
+        // otherwise it is not profitable.
+        return drainInParallel(timeout);
+    }
+    
+    LockHolder locker(m_heap.m_markingMutex);
+    for (;;) {
+        if (hasElapsed(timeout))
+            return SharedDrainResult::TimedOut;
+        
+        if (didReachTermination()) {
+            m_heap.m_markingConditionVariable.notifyAll();
+            return SharedDrainResult::Done;
+        }
+        
+        m_heap.m_markingConditionVariable.waitUntil(m_heap.m_markingMutex, timeout);
+    }
+}
+
</ins><span class="cx"> void SlotVisitor::addOpaqueRoot(void* root)
</span><span class="cx"> {
</span><span class="cx">     if (Options::numberOfGCMarkers() == 1) {
</span><span class="lines">@@ -547,18 +603,27 @@
</span><span class="cx">     m_opaqueRoots.clear();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SlotVisitor::harvestWeakReferences()
</del><ins>+void SlotVisitor::addWeakReferenceHarvester(WeakReferenceHarvester* weakReferenceHarvester)
</ins><span class="cx"> {
</span><del>-    for (WeakReferenceHarvester* current = m_heap.m_weakReferenceHarvesters.head(); current; current = current-&gt;next())
-        current-&gt;visitWeakReferences(*this);
</del><ins>+    m_heap.m_weakReferenceHarvesters.addThreadSafe(weakReferenceHarvester);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SlotVisitor::finalizeUnconditionalFinalizers()
</del><ins>+void SlotVisitor::addUnconditionalFinalizer(UnconditionalFinalizer* unconditionalFinalizer)
</ins><span class="cx"> {
</span><del>-    while (m_heap.m_unconditionalFinalizers.hasNext())
-        m_heap.m_unconditionalFinalizers.removeNext()-&gt;finalizeUnconditionally();
</del><ins>+    m_heap.m_unconditionalFinalizers.addThreadSafe(unconditionalFinalizer);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SlotVisitor::didRace(const VisitRaceKey&amp; race)
+{
+    if (Options::verboseVisitRace())
+        dataLog(toCString(&quot;GC visit race: &quot;, race, &quot;\n&quot;));
+    
+    if (!ASSERT_DISABLED) {
+        auto locker = holdLock(heap()-&gt;m_visitRaceLock);
+        heap()-&gt;m_visitRaces.add(race);
+    }
+}
+
</ins><span class="cx"> void SlotVisitor::dump(PrintStream&amp; out) const
</span><span class="cx"> {
</span><span class="cx">     out.print(&quot;Collector: [&quot;, pointerListDump(collectorMarkStack()), &quot;], Mutator: [&quot;, pointerListDump(mutatorMarkStack()), &quot;]&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitor.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitor.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitor.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #include &quot;HandleTypes.h&quot;
</span><span class="cx"> #include &quot;MarkStack.h&quot;
</span><span class="cx"> #include &quot;OpaqueRootSet.h&quot;
</span><ins>+#include &quot;VisitRaceKey.h&quot;
</ins><span class="cx"> #include &lt;wtf/MonotonicTime.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -106,10 +107,8 @@
</span><span class="cx">     SharedDrainResult drainFromShared(SharedDrainMode, MonotonicTime timeout = MonotonicTime::infinity());
</span><span class="cx"> 
</span><span class="cx">     SharedDrainResult drainInParallel(MonotonicTime timeout = MonotonicTime::infinity());
</span><ins>+    SharedDrainResult drainInParallelPassively(MonotonicTime timeout = MonotonicTime::infinity());
</ins><span class="cx"> 
</span><del>-    void harvestWeakReferences();
-    void finalizeUnconditionalFinalizers();
-    
</del><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="cx">     void markAuxiliary(const void* base);
</span><span class="lines">@@ -129,6 +128,23 @@
</span><span class="cx">     HeapVersion markingVersion() const { return m_markingVersion; }
</span><span class="cx"> 
</span><span class="cx">     void mergeOpaqueRootsIfNecessary();
</span><ins>+    
+    bool mutatorIsStopped() const { return m_mutatorIsStopped; }
+    
+    Lock&amp; rightToRun() { return m_rightToRun; }
+    
+    void updateMutatorIsStopped(const AbstractLocker&amp;);
+    void updateMutatorIsStopped();
+    
+    bool hasAcknowledgedThatTheMutatorIsResumed() const;
+    bool mutatorIsStoppedIsUpToDate() const;
+    
+    void optimizeForStoppedMutator();
+    
+    void didRace(const VisitRaceKey&amp;);
+    void didRace(JSCell* cell, const char* reason) { didRace(VisitRaceKey(cell, reason)); }
+    void didNotRace(const VisitRaceKey&amp;);
+    void didNotRace(JSCell* cell, const char* reason) { didNotRace(VisitRaceKey(cell, reason)); }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class ParallelModeEnabler;
</span><span class="lines">@@ -158,6 +174,9 @@
</span><span class="cx">     
</span><span class="cx">     void donateKnownParallel();
</span><span class="cx">     void donateKnownParallel(MarkStackArray&amp; from, MarkStackArray&amp; to);
</span><ins>+    
+    bool hasWork();
+    bool didReachTermination();
</ins><span class="cx"> 
</span><span class="cx">     MarkStackArray m_collectorStack;
</span><span class="cx">     MarkStackArray m_mutatorStack;
</span><span class="lines">@@ -174,7 +193,10 @@
</span><span class="cx">     HeapSnapshotBuilder* m_heapSnapshotBuilder { nullptr };
</span><span class="cx">     JSCell* m_currentCell { nullptr };
</span><span class="cx">     bool m_isVisitingMutatorStack { false };
</span><del>-
</del><ins>+    bool m_mutatorIsStopped { false };
+    bool m_canOptimizeForStoppedMutator { false };
+    Lock m_rightToRun;
+    
</ins><span class="cx"> public:
</span><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx">     bool m_isCheckingForDefaultMarkViolation;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitorInlines.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitorInlines.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitorInlines.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -93,16 +93,6 @@
</span><span class="cx">         appendHidden(&amp;barriers[i]);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void SlotVisitor::addWeakReferenceHarvester(WeakReferenceHarvester* weakReferenceHarvester)
-{
-    m_heap.m_weakReferenceHarvesters.addThreadSafe(weakReferenceHarvester);
-}
-
-inline void SlotVisitor::addUnconditionalFinalizer(UnconditionalFinalizer* unconditionalFinalizer)
-{
-    m_heap.m_unconditionalFinalizers.addThreadSafe(unconditionalFinalizer);
-}
-
</del><span class="cx"> inline void SlotVisitor::reportExtraMemoryVisited(size_t size)
</span><span class="cx"> {
</span><span class="cx">     if (!m_isVisitingMutatorStack)
</span><span class="lines">@@ -132,4 +122,18 @@
</span><span class="cx">     return *m_heap.m_vm;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline void SlotVisitor::didNotRace(const VisitRaceKey&amp; race)
+{
+    if (ASSERT_DISABLED)
+        return;
+    
+    if (!m_isVisitingMutatorStack) {
+        // This is the first visit so we don't need to remove anything.
+        return;
+    }
+    
+    auto locker = holdLock(heap()-&gt;m_visitRaceLock);
+    heap()-&gt;m_visitRaces.remove(race);
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapVisitRaceKeycpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/VisitRaceKey.cpp (0 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/VisitRaceKey.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/heap/VisitRaceKey.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;VisitRaceKey.h&quot;
+
+namespace JSC {
+
+const char* VisitRaceKey::m_deletedValueRaceName = &quot;deleted value&quot;;
+
+void VisitRaceKey::dump(PrintStream&amp; out) const
+{
+    out.print(RawPointer(m_cell), &quot;(&quot;, m_raceName, &quot;)&quot;);
+}
+
+} // namespace JSC
+
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapVisitRaceKeyh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/VisitRaceKey.h (0 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/VisitRaceKey.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/heap/VisitRaceKey.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -0,0 +1,107 @@
</span><ins>+/*
+ * Copyright (C) 2016 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/HashTable.h&gt;
+#include &lt;wtf/PrintStream.h&gt;
+
+namespace JSC {
+
+class JSCell;
+
+class VisitRaceKey {
+public:
+    VisitRaceKey() { }
+    
+    VisitRaceKey(JSCell* cell, const char* raceName)
+        : m_cell(cell)
+        , m_raceName(raceName)
+    {
+    }
+    
+    VisitRaceKey(WTF::HashTableDeletedValueType)
+        : m_raceName(m_deletedValueRaceName)
+    {
+    }
+    
+    bool operator==(const VisitRaceKey&amp; other) const
+    {
+        return m_cell == other.m_cell
+            &amp;&amp; m_raceName == other.m_raceName;
+    }
+    
+    bool operator!=(const VisitRaceKey&amp; other) const
+    {
+        return !(*this == other);
+    }
+    
+    explicit operator bool() const
+    {
+        return *this != VisitRaceKey();
+    }
+    
+    void dump(PrintStream&amp; out) const;
+    
+    JSCell* cell() const { return m_cell; }
+    const char* raceName() const { return m_raceName; }
+    
+    bool isHashTableDeletedValue() const
+    {
+        return *this == VisitRaceKey(WTF::HashTableDeletedValue);
+    }
+    
+    unsigned hash() const
+    {
+        return WTF::PtrHash&lt;JSCell*&gt;::hash(m_cell) ^ WTF::PtrHash&lt;const char*&gt;::hash(m_raceName);
+    }
+
+private:
+    static const char* m_deletedValueRaceName;
+    
+    JSCell* m_cell { nullptr };
+    const char* m_raceName { nullptr };
+};
+
+struct VisitRaceKeyHash {
+    static unsigned hash(const VisitRaceKey&amp; key) { return key.hash(); }
+    static bool equal(const VisitRaceKey&amp; a, const VisitRaceKey&amp; b) { return a == b; }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+} // namespace JSC
+
+namespace WTF {
+
+template&lt;typename T&gt; struct DefaultHash;
+template&lt;&gt; struct DefaultHash&lt;JSC::VisitRaceKey&gt; {
+    typedef JSC::VisitRaceKeyHash Hash;
+};
+
+template&lt;typename T&gt; struct HashTraits;
+template&lt;&gt; struct HashTraits&lt;JSC::VisitRaceKey&gt; : SimpleClassHashTraits&lt;JSC::VisitRaceKey&gt; { };
+
+} // namespace WTF
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapWeakSetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/WeakSet.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/WeakSet.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/heap/WeakSet.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -107,7 +107,7 @@
</span><span class="cx"> 
</span><span class="cx"> WeakBlock::FreeCell* WeakSet::addAllocator()
</span><span class="cx"> {
</span><del>-    if (m_blocks.isEmpty() &amp;&amp; !isOnList())
</del><ins>+    if (!isOnList())
</ins><span class="cx">         heap()-&gt;objectSpace().addActiveWeakSet(this);
</span><span class="cx">     
</span><span class="cx">     WeakBlock* block = WeakBlock::create(*heap(), m_container);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectoragentsInspectorHeapAgentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -334,8 +334,8 @@
</span><span class="cx"> 
</span><span class="cx"> void InspectorHeapAgent::willGarbageCollect()
</span><span class="cx"> {
</span><del>-    ASSERT(m_enabled);
-    ASSERT(std::isnan(m_gcStartTime));
</del><ins>+    if (!m_enabled)
+        return;
</ins><span class="cx"> 
</span><span class="cx">     m_gcStartTime = m_environment.executionStopwatch()-&gt;elapsedTime();
</span><span class="cx"> }
</span><span class="lines">@@ -342,9 +342,16 @@
</span><span class="cx"> 
</span><span class="cx"> void InspectorHeapAgent::didGarbageCollect(CollectionScope scope)
</span><span class="cx"> {
</span><del>-    ASSERT(m_enabled);
-    ASSERT(!std::isnan(m_gcStartTime));
</del><ins>+    if (!m_enabled) {
+        m_gcStartTime = NAN;
+        return;
+    }
</ins><span class="cx"> 
</span><ins>+    if (std::isnan(m_gcStartTime)) {
+        // We were not enabled when the GC began.
+        return;
+    }
+
</ins><span class="cx">     // FIXME: Include number of bytes freed by collection.
</span><span class="cx"> 
</span><span class="cx">     // Dispatch the event asynchronously because this method may be
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectoragentsInspectorRuntimeAgentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -336,7 +336,7 @@
</span><span class="cx">     vm.whenIdle([&amp;vm, isTypeProfilingEnabled] () {
</span><span class="cx">         bool shouldRecompileFromTypeProfiler = (isTypeProfilingEnabled ? vm.enableTypeProfiler() : vm.disableTypeProfiler());
</span><span class="cx">         if (shouldRecompileFromTypeProfiler)
</span><del>-            vm.deleteAllCode();
</del><ins>+            vm.deleteAllCode(PreventCollectionAndDeleteAllCode);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -351,7 +351,7 @@
</span><span class="cx">         bool shouldRecompileFromControlFlowProfiler = (isControlFlowProfilingEnabled ? vm.enableControlFlowProfiler() : vm.disableControlFlowProfiler());
</span><span class="cx"> 
</span><span class="cx">         if (shouldRecompileFromControlFlowProfiler)
</span><del>-            vm.deleteAllCode();
</del><ins>+            vm.deleteAllCode(PreventCollectionAndDeleteAllCode);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -1387,6 +1387,25 @@
</span><span class="cx">         done.link(this);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void nukeStructureAndStoreButterfly(GPRReg butterfly, GPRReg object)
+    {
+        if (isX86() || !useGCFences()) {
+            or32(TrustedImm32(bitwise_cast&lt;int32_t&gt;(nukedStructureIDBit())), Address(object, JSCell::structureIDOffset()));
+            storePtr(butterfly, Address(object, JSObject::butterflyOffset()));
+            return;
+        }
+        
+        Jump ok = jumpIfMutatorFenceNotNeeded();
+        or32(TrustedImm32(bitwise_cast&lt;int32_t&gt;(nukedStructureIDBit())), Address(object, JSCell::structureIDOffset()));
+        storeFence();
+        storePtr(butterfly, Address(object, JSObject::butterflyOffset()));
+        storeFence();
+        Jump done = jump();
+        ok.link(this);
+        storePtr(butterfly, Address(object, JSObject::butterflyOffset()));
+        done.link(this);
+    }
+    
</ins><span class="cx">     Jump jumpIfMutatorFenceNotNeeded()
</span><span class="cx">     {
</span><span class="cx">         return branchTest8(Zero, AbsoluteAddress(vm()-&gt;heap.addressOfMutatorShouldBeFenced()));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -94,6 +94,7 @@
</span><span class="cx">         addSlowCase(Jump());
</span><span class="cx">     JumpList slowCases;
</span><span class="cx">     emitAllocateJSObject(resultReg, allocator, allocatorReg, TrustedImmPtr(structure), TrustedImmPtr(0), scratchReg, slowCases);
</span><ins>+    emitInitializeInlineStorage(resultReg, structure-&gt;inlineCapacity());
</ins><span class="cx">     addSlowCase(slowCases);
</span><span class="cx">     emitPutVirtualRegister(currentInstruction[1].u.operand);
</span><span class="cx"> }
</span><span class="lines">@@ -752,6 +753,10 @@
</span><span class="cx"> 
</span><span class="cx">     JumpList slowCases;
</span><span class="cx">     emitAllocateJSObject(resultReg, nullptr, allocatorReg, structureReg, TrustedImmPtr(0), scratchReg, slowCases);
</span><ins>+    emitGetVirtualRegister(callee, scratchReg);
+    loadPtr(Address(scratchReg, JSFunction::offsetOfRareData()), scratchReg);
+    load32(Address(scratchReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfInlineCapacity()), scratchReg);
+    emitInitializeInlineStorage(resultReg, scratchReg);
</ins><span class="cx">     addSlowCase(slowCases);
</span><span class="cx">     emitPutVirtualRegister(currentInstruction[1].u.operand);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -2174,9 +2174,7 @@
</span><span class="cx"> 
</span><span class="cx">     ASSERT(!object-&gt;structure()-&gt;outOfLineCapacity());
</span><span class="cx">     Butterfly* result = object-&gt;allocateMoreOutOfLineStorage(vm, 0, initialOutOfLineCapacity);
</span><del>-    WTF::storeStoreFence();
-    object-&gt;setButterfly(vm, result);
-    WTF::storeStoreFence();
</del><ins>+    object-&gt;nukeStructureAndSetButterfly(vm, object-&gt;structureID(), result);
</ins><span class="cx">     return reinterpret_cast&lt;char*&gt;(result);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2186,9 +2184,7 @@
</span><span class="cx">     NativeCallFrameTracer tracer(&amp;vm, exec);
</span><span class="cx"> 
</span><span class="cx">     Butterfly* result = object-&gt;allocateMoreOutOfLineStorage(vm, object-&gt;structure()-&gt;outOfLineCapacity(), newSize);
</span><del>-    WTF::storeStoreFence();
-    object-&gt;setButterfly(vm, result);
-    WTF::storeStoreFence();
</del><ins>+    object-&gt;nukeStructureAndSetButterfly(vm, object-&gt;structureID(), result);
</ins><span class="cx">     return reinterpret_cast&lt;char*&gt;(result);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeDirectArgumentscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -98,9 +98,9 @@
</span><span class="cx">     
</span><span class="cx">     visitor.appendValues(thisObject-&gt;storage(), std::max(thisObject-&gt;m_length, thisObject-&gt;m_minCapacity));
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_callee);
</span><del>-    
-    if (thisObject-&gt;m_overrides)
-        visitor.markAuxiliary(thisObject-&gt;m_overrides.get());
</del><ins>+
+    if (bool* override = thisObject-&gt;m_overrides.get())
+        visitor.markAuxiliary(override);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Structure* DirectArguments::createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeEvalExecutablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/EvalExecutable.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/EvalExecutable.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/EvalExecutable.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -27,10 +27,7 @@
</span><span class="cx"> #include &quot;EvalExecutable.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;EvalCodeBlock.h&quot;
</span><del>-#include &quot;HeapCellInlines.h&quot;
-#include &quot;HeapInlines.h&quot;
-#include &quot;JSCJSValueInlines.h&quot;
-#include &quot;SlotVisitorInlines.h&quot;
</del><ins>+#include &quot;JSCInlines.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -53,8 +50,8 @@
</span><span class="cx">     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
</span><span class="cx">     ScriptExecutable::visitChildren(thisObject, visitor);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_unlinkedEvalCodeBlock);
</span><del>-    if (thisObject-&gt;m_evalCodeBlock)
-        thisObject-&gt;m_evalCodeBlock-&gt;visitWeakly(visitor);
</del><ins>+    if (EvalCodeBlock* evalCodeBlock = thisObject-&gt;m_evalCodeBlock.get())
+        evalCodeBlock-&gt;visitWeakly(visitor);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeFunctionExecutablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/FunctionExecutable.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/FunctionExecutable.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/FunctionExecutable.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -85,10 +85,10 @@
</span><span class="cx">     FunctionExecutable* thisObject = jsCast&lt;FunctionExecutable*&gt;(cell);
</span><span class="cx">     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
</span><span class="cx">     ScriptExecutable::visitChildren(thisObject, visitor);
</span><del>-    if (thisObject-&gt;m_codeBlockForCall)
-        thisObject-&gt;m_codeBlockForCall-&gt;visitWeakly(visitor);
-    if (thisObject-&gt;m_codeBlockForConstruct)
-        thisObject-&gt;m_codeBlockForConstruct-&gt;visitWeakly(visitor);
</del><ins>+    if (FunctionCodeBlock* codeBlockForCall = thisObject-&gt;m_codeBlockForCall.get())
+        codeBlockForCall-&gt;visitWeakly(visitor);
+    if (FunctionCodeBlock* codeBlockForConstruct = thisObject-&gt;m_codeBlockForConstruct.get())
+        codeBlockForConstruct-&gt;visitWeakly(visitor);
</ins><span class="cx">     visitor.append(&amp;thisObject-&gt;m_unlinkedExecutable);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_singletonFunction);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeHashMapImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/HashMapImpl.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/HashMapImpl.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/HashMapImpl.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -70,8 +70,8 @@
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_head);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_tail);
</span><span class="cx">     
</span><del>-    if (thisObject-&gt;m_buffer)
-        visitor.markAuxiliary(thisObject-&gt;m_buffer.get());
</del><ins>+    if (HashMapBufferType* buffer = thisObject-&gt;m_buffer.get())
+        visitor.markAuxiliary(buffer);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> const ClassInfo* getHashMapBucketKeyClassInfo()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeInferredTypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/InferredType.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/InferredType.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/InferredType.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 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,9 +89,15 @@
</span><span class="cx"> void InferredType::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
</span><span class="cx"> {
</span><span class="cx">     InferredType* inferredType = jsCast&lt;InferredType*&gt;(cell);
</span><ins>+    
+    ConcurrentJSLocker locker(inferredType-&gt;m_lock);
</ins><span class="cx"> 
</span><del>-    if (inferredType-&gt;m_structure)
</del><ins>+    if (inferredType-&gt;m_structure) {
+        // The mutator may clear the structure before the GC runs finalizers, so we have to protect
+        // the finalizer from being destroyed.
+        inferredType-&gt;m_structure-&gt;ref();
</ins><span class="cx">         visitor.addUnconditionalFinalizer(&amp;inferredType-&gt;m_structure-&gt;m_finalizer);
</span><ins>+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> InferredType::Kind InferredType::kindForFlags(PutByIdFlags flags)
</span><span class="lines">@@ -482,7 +488,7 @@
</span><span class="cx">             // We should agree on the structures if we get here.
</span><span class="cx">             ASSERT(newDescriptor.structure() == m_structure-&gt;structure());
</span><span class="cx">         } else {
</span><del>-            m_structure = std::make_unique&lt;InferredStructure&gt;(vm, this, newDescriptor.structure());
</del><ins>+            m_structure = adoptRef(new InferredStructure(vm, this, newDescriptor.structure()));
</ins><span class="cx">             newDescriptor.structure()-&gt;addTransitionWatchpoint(&amp;m_structure-&gt;m_watchpoint);
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -533,11 +539,18 @@
</span><span class="cx">     InferredStructure* inferredStructure =
</span><span class="cx">         bitwise_cast&lt;InferredStructure*&gt;(
</span><span class="cx">             bitwise_cast&lt;char*&gt;(this) - OBJECT_OFFSETOF(InferredStructure, m_finalizer));
</span><del>-
</del><ins>+    
</ins><span class="cx">     ASSERT(Heap::isMarked(inferredStructure-&gt;m_parent));
</span><span class="cx">     
</span><del>-    if (!Heap::isMarked(inferredStructure-&gt;m_structure.get()))
-        inferredStructure-&gt;m_parent-&gt;removeStructure();
</del><ins>+    // Monotonicity ensures that we shouldn't see a new structure that is different from us, but we
+    // could have been nulled. We only rely on it being the null case only in debug.
+    if (inferredStructure == inferredStructure-&gt;m_parent-&gt;m_structure.get()) {
+        if (!Heap::isMarked(inferredStructure-&gt;m_structure.get()))
+            inferredStructure-&gt;m_parent-&gt;removeStructure();
+    } else
+        ASSERT(!inferredStructure-&gt;m_parent-&gt;m_structure);
+    
+    inferredStructure-&gt;deref();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> InferredType::InferredStructure::InferredStructure(VM&amp; vm, InferredType* parent, Structure* structure)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeInferredTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/InferredType.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/InferredType.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/InferredType.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 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">@@ -30,6 +30,7 @@
</span><span class="cx"> #include &quot;PropertyName.h&quot;
</span><span class="cx"> #include &quot;PutByIdFlags.h&quot;
</span><span class="cx"> #include &quot;Watchpoint.h&quot;
</span><ins>+#include &lt;wtf/ThreadSafeRefCounted.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -253,8 +254,7 @@
</span><span class="cx">         void finalizeUnconditionally() override;
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    class InferredStructure {
-        WTF_MAKE_FAST_ALLOCATED;
</del><ins>+    class InferredStructure : public ThreadSafeRefCounted&lt;InferredStructure&gt; {
</ins><span class="cx">     public:
</span><span class="cx">         InferredStructure(VM&amp;, InferredType* parent, Structure*);
</span><span class="cx"> 
</span><span class="lines">@@ -272,7 +272,7 @@
</span><span class="cx">         InferredStructureFinalizer m_finalizer;
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    std::unique_ptr&lt;InferredStructure&gt; m_structure;
</del><ins>+    RefPtr&lt;InferredStructure&gt; m_structure;
</ins><span class="cx"> 
</span><span class="cx">     // NOTE: If this is being watched, we transform to Top because that implies that it wouldn't be
</span><span class="cx">     // profitable to watch it again. Also, this set is initialized clear, and is never exposed to the DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeInferredValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/InferredValue.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/InferredValue.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/InferredValue.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 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,14 +54,18 @@
</span><span class="cx"> {
</span><span class="cx">     InferredValue* inferredValue = jsCast&lt;InferredValue*&gt;(cell);
</span><span class="cx">     
</span><ins>+    auto locker = holdLock(*inferredValue);
+    
</ins><span class="cx">     if (inferredValue-&gt;m_set.hasBeenInvalidated()) {
</span><del>-        inferredValue-&gt;m_cleanup = nullptr;
</del><ins>+        if (inferredValue-&gt;m_cleanup &amp;&amp; !inferredValue-&gt;m_cleanup-&gt;isOnList())
+            inferredValue-&gt;m_cleanup = nullptr;
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    if (!inferredValue-&gt;m_value)
</del><ins>+    JSValue value = inferredValue-&gt;m_value.get();
+    if (!value)
</ins><span class="cx">         return;
</span><del>-    if (!inferredValue-&gt;m_value.get().isCell())
</del><ins>+    if (!value.isCell())
</ins><span class="cx">         return;
</span><span class="cx">     
</span><span class="cx">     if (!inferredValue-&gt;m_cleanup)
</span><span class="lines">@@ -119,12 +123,15 @@
</span><span class="cx"> 
</span><span class="cx"> void InferredValue::ValueCleanup::finalizeUnconditionally()
</span><span class="cx"> {
</span><del>-    ASSERT(m_owner-&gt;m_value);
-    ASSERT(m_owner-&gt;m_value.get().isCell());
</del><ins>+    JSValue value = m_owner-&gt;m_value.get();
</ins><span class="cx">     
</span><del>-    if (Heap::isMarked(m_owner-&gt;m_value.get().asCell()))
</del><ins>+    // Concurrent GC means that this could have changed since we installed the finalizer.
+    if (!value || !value.isCell())
</ins><span class="cx">         return;
</span><span class="cx">     
</span><ins>+    if (Heap::isMarked(value.asCell()))
+        return;
+    
</ins><span class="cx">     m_owner-&gt;invalidate(*m_owner-&gt;vm(), StringFireDetail(&quot;InferredValue clean-up during GC&quot;));
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSArraycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSArray.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSArray.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/JSArray.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -399,8 +399,6 @@
</span><span class="cx">     newButterfly-&gt;arrayStorage()-&gt;setVectorLength(newVectorLength);
</span><span class="cx">     newButterfly-&gt;arrayStorage()-&gt;m_indexBias = newIndexBias;
</span><span class="cx">     
</span><del>-    WTF::storeStoreFence();
-    
</del><span class="cx">     setButterfly(vm, newButterfly);
</span><span class="cx"> 
</span><span class="cx">     return true;
</span><span class="lines">@@ -1090,7 +1088,7 @@
</span><span class="cx">     // Need to have GC deferred around the unshiftCountSlowCase(), since that leaves the butterfly in
</span><span class="cx">     // a weird state: some parts of it will be left uninitialized, which we will fill in here.
</span><span class="cx">     DeferGC deferGC(vm.heap);
</span><del>-    JSCell::InternalLocker locker(this);
</del><ins>+    auto locker = holdLock(*this);
</ins><span class="cx">     
</span><span class="cx">     if (moveFront &amp;&amp; storage-&gt;m_indexBias &gt;= count) {
</span><span class="cx">         Butterfly* newButterfly = storage-&gt;butterfly()-&gt;unshift(structure(), count);
</span><span class="lines">@@ -1097,7 +1095,6 @@
</span><span class="cx">         storage = newButterfly-&gt;arrayStorage();
</span><span class="cx">         storage-&gt;m_indexBias -= count;
</span><span class="cx">         storage-&gt;setVectorLength(vectorLength + count);
</span><del>-        WTF::storeStoreFence();
</del><span class="cx">         setButterfly(vm, newButterfly);
</span><span class="cx">     } else if (!moveFront &amp;&amp; vectorLength - length &gt;= count)
</span><span class="cx">         storage = storage-&gt;butterfly()-&gt;arrayStorage();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSArrayBufferViewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -159,6 +159,7 @@
</span><span class="cx">     JSArrayBufferView* thisObject = jsCast&lt;JSArrayBufferView*&gt;(cell);
</span><span class="cx"> 
</span><span class="cx">     if (thisObject-&gt;hasArrayBuffer()) {
</span><ins>+        WTF::loadLoadFence();
</ins><span class="cx">         ArrayBuffer* buffer = thisObject-&gt;possiblySharedBuffer();
</span><span class="cx">         RELEASE_ASSERT(buffer);
</span><span class="cx">         visitor.addOpaqueRoot(buffer);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCellh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCell.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCell.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/JSCell.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -104,26 +104,11 @@
</span><span class="cx">     // Each cell has a built-in lock. Currently it's simply available for use if you need it. It's
</span><span class="cx">     // a full-blown WTF::Lock. Note that this lock is currently used in JSArray and that lock's
</span><span class="cx">     // ordering with the Structure lock is that the Structure lock must be acquired first.
</span><del>-    void lockInternalLock();
-    void unlockInternalLock();
</del><ins>+    void lock();
+    bool tryLock();
+    void unlock();
+    bool isLocked() const;
</ins><span class="cx">     
</span><del>-    class InternalLocker {
-    public:
-        InternalLocker(JSCell* cell)
-            : m_cell(cell)
-        {
-            m_cell-&gt;lockInternalLock();
-        }
-        
-        ~InternalLocker()
-        {
-            m_cell-&gt;unlockInternalLock();
-        }
-        
-    private:
-        JSCell* m_cell;
-    };
-
</del><span class="cx">     JSType type() const;
</span><span class="cx">     IndexingType indexingTypeAndMisc() const;
</span><span class="cx">     IndexingType indexingType() const;
</span><span class="lines">@@ -131,6 +116,7 @@
</span><span class="cx">     Structure* structure() const;
</span><span class="cx">     Structure* structure(VM&amp;) const;
</span><span class="cx">     void setStructure(VM&amp;, Structure*);
</span><ins>+    void setStructureIDDirectly(StructureID id) { m_structureID = id; }
</ins><span class="cx">     void clearStructure() { m_structureID = 0; }
</span><span class="cx"> 
</span><span class="cx">     TypeInfo::InlineTypeFlags inlineTypeFlags() const { return m_flags; }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCellInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCellInlines.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCellInlines.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/JSCellInlines.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -105,14 +105,14 @@
</span><span class="cx">     return indexingTypeAndMisc() &amp; AllArrayTypes;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline Structure* JSCell::structure() const
</del><ins>+ALWAYS_INLINE Structure* JSCell::structure() const
</ins><span class="cx"> {
</span><del>-    return Heap::heap(this)-&gt;structureIDTable().get(m_structureID);
</del><ins>+    return structure(*vm());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline Structure* JSCell::structure(VM&amp; vm) const
</del><ins>+ALWAYS_INLINE Structure* JSCell::structure(VM&amp; vm) const
</ins><span class="cx"> {
</span><del>-    return vm.heap.structureIDTable().get(m_structureID);
</del><ins>+    return vm.getStructure(m_structureID);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline void JSCell::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
</span><span class="lines">@@ -312,16 +312,28 @@
</span><span class="cx">     zap();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void JSCell::lockInternalLock()
</del><ins>+inline void JSCell::lock()
</ins><span class="cx"> {
</span><span class="cx">     Atomic&lt;IndexingType&gt;* lock = bitwise_cast&lt;Atomic&lt;IndexingType&gt;*&gt;(&amp;m_indexingTypeAndMisc);
</span><span class="cx">     IndexingTypeLockAlgorithm::lock(*lock);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void JSCell::unlockInternalLock()
</del><ins>+inline bool JSCell::tryLock()
</ins><span class="cx"> {
</span><span class="cx">     Atomic&lt;IndexingType&gt;* lock = bitwise_cast&lt;Atomic&lt;IndexingType&gt;*&gt;(&amp;m_indexingTypeAndMisc);
</span><ins>+    return IndexingTypeLockAlgorithm::tryLock(*lock);
+}
+
+inline void JSCell::unlock()
+{
+    Atomic&lt;IndexingType&gt;* lock = bitwise_cast&lt;Atomic&lt;IndexingType&gt;*&gt;(&amp;m_indexingTypeAndMisc);
</ins><span class="cx">     IndexingTypeLockAlgorithm::unlock(*lock);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool JSCell::isLocked() const
+{
+    Atomic&lt;IndexingType&gt;* lock = bitwise_cast&lt;Atomic&lt;IndexingType&gt;*&gt;(&amp;m_indexingTypeAndMisc);
+    return IndexingTypeLockAlgorithm::isLocked(*lock);
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSFunctioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSFunction.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSFunction.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/JSFunction.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -208,8 +208,7 @@
</span><span class="cx">     Base::visitChildren(thisObject, visitor);
</span><span class="cx"> 
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_executable);
</span><del>-    if (thisObject-&gt;m_rareData)
-        visitor.append(&amp;thisObject-&gt;m_rareData);
</del><ins>+    visitor.append(&amp;thisObject-&gt;m_rareData);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> CallType JSFunction::getCallData(JSCell* cell, CallData&amp; callData)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -512,8 +512,8 @@
</span><span class="cx">     
</span><span class="cx">     switch (thisObject-&gt;m_mode) {
</span><span class="cx">     case FastTypedArray: {
</span><del>-        if (thisObject-&gt;m_vector)
-            visitor.markAuxiliary(thisObject-&gt;m_vector.get());
</del><ins>+        if (void* vector = thisObject-&gt;m_vector.get())
+            visitor.markAuxiliary(vector);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="lines">@@ -582,6 +582,7 @@
</span><span class="cx"> 
</span><span class="cx">     thisObject-&gt;butterfly()-&gt;indexingHeader()-&gt;setArrayBuffer(buffer.get());
</span><span class="cx">     thisObject-&gt;m_vector.setWithoutBarrier(buffer-&gt;data());
</span><ins>+    WTF::storeStoreFence();
</ins><span class="cx">     thisObject-&gt;m_mode = WastefulTypedArray;
</span><span class="cx">     heap-&gt;addReference(thisObject, buffer.get());
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSObject.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSObject.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/JSObject.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -90,29 +90,311 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE void JSObject::visitButterfly(SlotVisitor&amp; visitor, Butterfly* butterfly, Structure* structure)
</del><ins>+ALWAYS_INLINE void JSObject::markAuxiliaryAndVisitOutOfLineProperties(SlotVisitor&amp; visitor, Butterfly* butterfly, Structure* structure, PropertyOffset lastOffset)
</ins><span class="cx"> {
</span><del>-    ASSERT(butterfly);
</del><ins>+    // We call this when we found everything without races.
+    ASSERT(structure);
</ins><span class="cx">     
</span><del>-    size_t storageSize = structure-&gt;outOfLineSize();
-    size_t propertyCapacity = structure-&gt;outOfLineCapacity();
</del><ins>+    if (!butterfly)
+        return;
+    
+    bool hasIndexingHeader = structure-&gt;hasIndexingHeader(this);
</ins><span class="cx">     size_t preCapacity;
</span><del>-    bool hasIndexingHeader = this-&gt;hasIndexingHeader();
-    if (UNLIKELY(hasIndexingHeader))
</del><ins>+    if (hasIndexingHeader)
</ins><span class="cx">         preCapacity = butterfly-&gt;indexingHeader()-&gt;preCapacity(structure);
</span><span class="cx">     else
</span><span class="cx">         preCapacity = 0;
</span><span class="cx">     
</span><del>-    HeapCell* base = bitwise_cast&lt;HeapCell*&gt;(butterfly-&gt;base(preCapacity, propertyCapacity));
</del><ins>+    HeapCell* base = bitwise_cast&lt;HeapCell*&gt;(
+        butterfly-&gt;base(preCapacity, Structure::outOfLineCapacity(lastOffset)));
</ins><span class="cx">     
</span><span class="cx">     ASSERT(Heap::heap(base) == visitor.heap());
</span><del>-
-    // Keep the butterfly alive.
</del><ins>+    
</ins><span class="cx">     visitor.markAuxiliary(base);
</span><span class="cx">     
</span><del>-    // Mark the properties.
-    visitor.appendValuesHidden(butterfly-&gt;propertyStorage() - storageSize, storageSize);
</del><ins>+    unsigned outOfLineSize = Structure::outOfLineSize(lastOffset);
+    visitor.appendValuesHidden(butterfly-&gt;propertyStorage() - outOfLineSize, outOfLineSize);
+}
</ins><span class="cx"> 
</span><ins>+ALWAYS_INLINE Structure* JSObject::visitButterfly(SlotVisitor&amp; visitor)
+{
+    static const char* raceReason = &quot;JSObject::visitButterfly&quot;;
+    Structure* result = visitButterflyImpl(visitor);
+    if (result)
+        visitor.didNotRace(this, raceReason);
+    else
+        visitor.didRace(this, raceReason);
+    return result;
+}
+
+ALWAYS_INLINE Structure* JSObject::visitButterflyImpl(SlotVisitor&amp; visitor)
+{
+    VM&amp; vm = visitor.vm();
+    
+    Butterfly* butterfly;
+    Structure* structure;
+    PropertyOffset lastOffset;
+    
+    if (visitor.mutatorIsStopped()) {
+        butterfly = this-&gt;butterfly();
+        structure = this-&gt;structure(vm);
+        lastOffset = structure-&gt;lastOffset();
+        
+        markAuxiliaryAndVisitOutOfLineProperties(visitor, butterfly, structure, lastOffset);
+        
+        switch (structure-&gt;indexingType()) {
+        case ALL_CONTIGUOUS_INDEXING_TYPES:
+            visitor.appendValuesHidden(butterfly-&gt;contiguous().data(), butterfly-&gt;publicLength());
+            break;
+        case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+            visitor.appendValuesHidden(butterfly-&gt;arrayStorage()-&gt;m_vector, butterfly-&gt;arrayStorage()-&gt;vectorLength());
+            if (butterfly-&gt;arrayStorage()-&gt;m_sparseMap)
+                visitor.append(&amp;butterfly-&gt;arrayStorage()-&gt;m_sparseMap);
+            break;
+        default:
+            break;
+        }
+        return structure;
+    }
+    
+    // We want to ensure that we only scan the butterfly if we have an exactly matched structure and an
+    // exactly matched size. The mutator is required to perform the following shenanigans when
+    // reallocating the butterfly with a concurrent collector, with all fencing necessary to ensure
+    // that this executes as if under sequential consistency:
+    //
+    //     object-&gt;structure = nuke(object-&gt;structure)
+    //     object-&gt;butterfly = newButterfly
+    //     structure-&gt;m_offset = newLastOffset
+    //     object-&gt;structure = newStructure
+    //
+    // It's OK to skip this when reallocating the butterfly in a way that does not affect the m_offset.
+    // We have other protocols in place for that.
+    //
+    // Note that the m_offset can change without the structure changing, but in that case the mutator
+    // will still store null to the structure.
+    //
+    // The collector will ensure that it always sees a matched butterfly/structure by reading the
+    // structure before and after reading the butterfly. For simplicity, let's first consider the case
+    // where the only way to change the outOfLineCapacity is to change the structure. This works
+    // because the mutator performs the following steps sequentially:
+    //
+    //     NukeStructure ChangeButterfly PutNewStructure
+    //
+    // Meanwhile the collector performs the following steps sequentially:
+    //
+    //     ReadStructureEarly ReadButterfly ReadStructureLate
+    //
+    // The collector is allowed to do any of these three things:
+    //
+    // BEFORE: Scan the object with the structure and butterfly *before* the mutator's transition.
+    // AFTER: Scan the object with the structure and butterfly *after* the mutator's transition.
+    // IGNORE: Give up, so long as the write barrier on PutNewStructure executes after ReadStructureEarly.
+    //
+    // In other words, the collector will never see any torn structure/butterfly mix. It will
+    // always see the structure/butterfly before the transition or after but not in between.
+    //
+    // We can prove that this is correct by exhaustively considering all interleavings:
+    //
+    // NukeStructure ChangeButterfly PutNewStructure ReadStructureEarly ReadButterfly ReadStructureLate: AFTER, trivially.
+    // NukeStructure ChangeButterfly ReadStructureEarly PutNewStructure ReadButterfly ReadStructureLate: IGNORE, because nuked structure read early
+    // NukeStructure ChangeButterfly ReadStructureEarly ReadButterfly PutNewStructure ReadStructureLate: IGNORE, because nuked structure read early
+    // NukeStructure ChangeButterfly ReadStructureEarly ReadButterfly ReadStructureLate PutNewStructure: IGNORE, because nuked structure read early
+    // NukeStructure ReadStructureEarly ChangeButterfly PutNewStructure ReadButterfly ReadStructureLate: IGNORE, because nuked structure read early
+    // NukeStructure ReadStructureEarly ChangeButterfly ReadButterfly PutNewStructure ReadStructureLate: IGNORE, because nuked structure read early
+    // NukeStructure ReadStructureEarly ChangeButterfly ReadButterfly ReadStructureLate PutNewStructure: IGNORE, because nuked structure read early
+    // NukeStructure ReadStructureEarly ReadButterfly ChangeButterfly PutNewStructure ReadStructureLate: IGNORE, because nuked structure read early
+    // NukeStructure ReadStructureEarly ReadButterfly ChangeButterfly ReadStructureLate PutNewStructure: IGNORE, because nuked structure read early
+    // NukeStructure ReadStructureEarly ReadButterfly ReadStructureLate ChangeButterfly PutNewStructure: IGNORE, because nuked structure read early
+    // ReadStructureEarly NukeStructure ChangeButterfly PutNewStructure ReadButterfly ReadStructureLate: IGNORE, because early and late structures don't match
+    // ReadStructureEarly NukeStructure ChangeButterfly ReadButterfly PutNewStructure ReadStructureLate: IGNORE, because early and late structures don't match
+    // ReadStructureEarly NukeStructure ChangeButterfly ReadButterfly ReadStructureLate PutNewStructure: IGNORE, because nuked structure read late
+    // ReadStructureEarly NukeStructure ReadButterfly ChangeButterfly PutNewStructure ReadStructureLate: IGNORE, because early and late structures don't match
+    // ReadStructureEarly NukeStructure ReadButterfly ChangeButterfly ReadStructureLate PutNewStructure: IGNORE, because nuked structure read late
+    // ReadStructureEarly NukeStructure ReadButterfly ReadStructureLate ChangeButterfly PutNewStructure: IGNORE, because nuked structure read late
+    // ReadStructureEarly ReadButterfly NukeStructure ChangeButterfly PutNewStructure ReadStructureLate: IGNORE, because early and late structures don't match
+    // ReadStructureEarly ReadButterfly NukeStructure ChangeButterfly ReadStructureLate PutNewStructure: IGNORE, because nuked structure read late
+    // ReadStructureEarly ReadButterfly NukeStructure ReadStructureLate ChangeButterfly PutNewStructure: IGNORE, because nuked structure read late
+    // ReadStructureEarly ReadButterfly ReadStructureLate NukeStructure ChangeButterfly PutNewStructure: BEFORE, trivially.
+    //
+    // But we additionally have to worry about the size changing. We make this work by requiring that
+    // the collector reads the size early and late as well. Lets consider the interleaving of the
+    // mutator changing the size without changing the structure:
+    //
+    //     NukeStructure ChangeButterfly ChangeLastOffset RestoreStructure
+    //
+    // Meanwhile the collector does:
+    //
+    //     ReadStructureEarly ReadLastOffsetEarly ReadButterfly ReadStructureLate ReadLastOffsetLate
+    //
+    // The collector can detect races by not only comparing the early structure to the late structure
+    // (which will be the same before and after the algorithm runs) but also by comparing the early and
+    // late lastOffsets.  Note: the IGNORE proofs do not cite all of the reasons why the collector will
+    // ignore the case, since we only need to identify one to say that we're in the ignore case.
+    //
+    // NukeStructure ChangeButterfly ChangeLastOffset RestoreStructure ReadStructureEarly ReadLastOffsetEarly ReadButterfly ReadStructureLate ReadLastOffsetLate: AFTER, trivially
+    // NukeStructure ChangeButterfly ChangeLastOffset ReadStructureEarly RestoreStructure ReadLastOffsetEarly ReadButterfly ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ChangeLastOffset ReadStructureEarly ReadLastOffsetEarly RestoreStructure ReadButterfly ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ChangeLastOffset ReadStructureEarly ReadLastOffsetEarly ReadButterfly RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ChangeLastOffset ReadStructureEarly ReadLastOffsetEarly ReadButterfly ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ChangeLastOffset ReadStructureEarly ReadLastOffsetEarly ReadButterfly ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ReadStructureEarly ChangeLastOffset RestoreStructure ReadLastOffsetEarly ReadButterfly ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ReadStructureEarly ChangeLastOffset ReadLastOffsetEarly RestoreStructure ReadButterfly ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ReadStructureEarly ChangeLastOffset ReadLastOffsetEarly ReadButterfly RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ReadStructureEarly ChangeLastOffset ReadLastOffsetEarly ReadButterfly ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ReadStructureEarly ChangeLastOffset ReadLastOffsetEarly ReadButterfly ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ReadStructureEarly ReadLastOffsetEarly ChangeLastOffset RestoreStructure ReadButterfly ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ReadStructureEarly ReadLastOffsetEarly ChangeLastOffset ReadButterfly RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ReadStructureEarly ReadLastOffsetEarly ChangeLastOffset ReadButterfly ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ReadStructureEarly ReadLastOffsetEarly ChangeLastOffset ReadButterfly ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ReadStructureEarly ReadLastOffsetEarly ReadButterfly ChangeLastOffset RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ReadStructureEarly ReadLastOffsetEarly ReadButterfly ChangeLastOffset ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ReadStructureEarly ReadLastOffsetEarly ReadButterfly ChangeLastOffset ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ReadStructureEarly ReadLastOffsetEarly ReadButterfly ReadStructureLate ChangeLastOffset RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ReadStructureEarly ReadLastOffsetEarly ReadButterfly ReadStructureLate ChangeLastOffset ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ChangeButterfly ReadStructureEarly ReadLastOffsetEarly ReadButterfly ReadStructureLate ReadLastOffsetLate ChangeLastOffset RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ChangeButterfly ChangeLastOffset RestoreStructure ReadLastOffsetEarly ReadButterfly ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ChangeButterfly ChangeLastOffset ReadLastOffsetEarly RestoreStructure ReadButterfly ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ChangeButterfly ChangeLastOffset ReadLastOffsetEarly ReadButterfly RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ChangeButterfly ChangeLastOffset ReadLastOffsetEarly ReadButterfly ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ChangeButterfly ChangeLastOffset ReadLastOffsetEarly ReadButterfly ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ChangeButterfly ReadLastOffsetEarly ChangeLastOffset RestoreStructure ReadButterfly ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ChangeButterfly ReadLastOffsetEarly ChangeLastOffset ReadButterfly RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ChangeButterfly ReadLastOffsetEarly ChangeLastOffset ReadButterfly ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ChangeButterfly ReadLastOffsetEarly ChangeLastOffset ReadButterfly ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ChangeButterfly ReadLastOffsetEarly ReadButterfly ChangeLastOffset RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ChangeButterfly ReadLastOffsetEarly ReadButterfly ChangeLastOffset ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ChangeButterfly ReadLastOffsetEarly ReadButterfly ChangeLastOffset ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ChangeButterfly ReadLastOffsetEarly ReadButterfly ReadStructureLate ChangeLastOffset RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ChangeButterfly ReadLastOffsetEarly ReadButterfly ReadStructureLate ChangeLastOffset ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ChangeButterfly ReadLastOffsetEarly ReadButterfly ReadStructureLate ReadLastOffsetLate ChangeLastOffset RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ChangeButterfly ChangeLastOffset RestoreStructure ReadButterfly ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ChangeButterfly ChangeLastOffset ReadButterfly RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ChangeButterfly ChangeLastOffset ReadButterfly ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ChangeButterfly ChangeLastOffset ReadButterfly ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ChangeButterfly ReadButterfly ChangeLastOffset RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ChangeButterfly ReadButterfly ChangeLastOffset ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ChangeButterfly ReadButterfly ChangeLastOffset ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ChangeButterfly ReadButterfly ReadStructureLate ChangeLastOffset RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ChangeButterfly ReadButterfly ReadStructureLate ChangeLastOffset ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ChangeButterfly ReadButterfly ReadStructureLate ReadLastOffsetLate ChangeLastOffset RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ReadButterfly ChangeButterfly ChangeLastOffset RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ReadButterfly ChangeButterfly ChangeLastOffset ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ReadButterfly ChangeButterfly ChangeLastOffset ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ReadButterfly ChangeButterfly ReadStructureLate ChangeLastOffset RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ReadButterfly ChangeButterfly ReadStructureLate ChangeLastOffset ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ReadButterfly ChangeButterfly ReadStructureLate ReadLastOffsetLate ChangeLastOffset RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ReadButterfly ReadStructureLate ChangeButterfly ChangeLastOffset RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ReadButterfly ReadStructureLate ChangeButterfly ChangeLastOffset ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ReadButterfly ReadStructureLate ChangeButterfly ReadLastOffsetLate ChangeLastOffset RestoreStructure: IGNORE, read nuked structure early
+    // NukeStructure ReadStructureEarly ReadLastOffsetEarly ReadButterfly ReadStructureLate ReadLastOffsetLate ChangeButterfly ChangeLastOffset RestoreStructure: IGNORE, read nuked structure early
+    // ReadStructureEarly NukeStructure ChangeButterfly ChangeLastOffset RestoreStructure ReadLastOffsetEarly ReadButterfly ReadStructureLate ReadLastOffsetLate: AFTER, the ReadStructureEarly sees the same structure as after and everything else runs after.
+    // ReadStructureEarly NukeStructure ChangeButterfly ChangeLastOffset ReadLastOffsetEarly RestoreStructure ReadButterfly ReadStructureLate ReadLastOffsetLate: AFTER, as above and the ReadLastOffsetEarly sees the lastOffset after.
+    // ReadStructureEarly NukeStructure ChangeButterfly ChangeLastOffset ReadLastOffsetEarly ReadButterfly RestoreStructure ReadStructureLate ReadLastOffsetLate: AFTER, as above and the ReadButterfly sees the right butterfly after.
+    // ReadStructureEarly NukeStructure ChangeButterfly ChangeLastOffset ReadLastOffsetEarly ReadButterfly ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure late
+    // ReadStructureEarly NukeStructure ChangeButterfly ChangeLastOffset ReadLastOffsetEarly ReadButterfly ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure late
+    // ReadStructureEarly NukeStructure ChangeButterfly ReadLastOffsetEarly ChangeLastOffset RestoreStructure ReadButterfly ReadStructureLate ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ChangeButterfly ReadLastOffsetEarly ChangeLastOffset ReadButterfly RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ChangeButterfly ReadLastOffsetEarly ChangeLastOffset ReadButterfly ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ChangeButterfly ReadLastOffsetEarly ChangeLastOffset ReadButterfly ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ChangeButterfly ReadLastOffsetEarly ReadButterfly ChangeLastOffset RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ChangeButterfly ReadLastOffsetEarly ReadButterfly ChangeLastOffset ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ChangeButterfly ReadLastOffsetEarly ReadButterfly ChangeLastOffset ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ChangeButterfly ReadLastOffsetEarly ReadButterfly ReadStructureLate ChangeLastOffset RestoreStructure ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ChangeButterfly ReadLastOffsetEarly ReadButterfly ReadStructureLate ChangeLastOffset ReadLastOffsetLate RestoreStructure: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ChangeButterfly ReadLastOffsetEarly ReadButterfly ReadStructureLate ReadLastOffsetLate ChangeLastOffset RestoreStructure: IGNORE, read nuked structure late
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ChangeButterfly ChangeLastOffset RestoreStructure ReadButterfly ReadStructureLate ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ChangeButterfly ChangeLastOffset ReadButterfly RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ChangeButterfly ChangeLastOffset ReadButterfly ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ChangeButterfly ChangeLastOffset ReadButterfly ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ChangeButterfly ReadButterfly ChangeLastOffset RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ChangeButterfly ReadButterfly ChangeLastOffset ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ChangeButterfly ReadButterfly ChangeLastOffset ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ChangeButterfly ReadButterfly ReadStructureLate ChangeLastOffset RestoreStructure ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ChangeButterfly ReadButterfly ReadStructureLate ChangeLastOffset ReadLastOffsetLate RestoreStructure: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ChangeButterfly ReadButterfly ReadStructureLate ReadLastOffsetLate ChangeLastOffset RestoreStructure: IGNORE, read nuked structure late
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ReadButterfly ChangeButterfly ChangeLastOffset RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ReadButterfly ChangeButterfly ChangeLastOffset ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ReadButterfly ChangeButterfly ChangeLastOffset ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ReadButterfly ChangeButterfly ReadStructureLate ChangeLastOffset RestoreStructure ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ReadButterfly ChangeButterfly ReadStructureLate ChangeLastOffset ReadLastOffsetLate RestoreStructure: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ReadButterfly ChangeButterfly ReadStructureLate ReadLastOffsetLate ChangeLastOffset RestoreStructure: IGNORE, read nuked structure late
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ReadButterfly ReadStructureLate ChangeButterfly ChangeLastOffset RestoreStructure ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ReadButterfly ReadStructureLate ChangeButterfly ChangeLastOffset ReadLastOffsetLate RestoreStructure: IGNORE, read different offsets
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ReadButterfly ReadStructureLate ChangeButterfly ReadLastOffsetLate ChangeLastOffset RestoreStructure: IGNORE, read nuked structure late
+    // ReadStructureEarly NukeStructure ReadLastOffsetEarly ReadButterfly ReadStructureLate ReadLastOffsetLate ChangeButterfly ChangeLastOffset RestoreStructure: IGNORE, read nuked structure late
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ChangeButterfly ChangeLastOffset RestoreStructure ReadButterfly ReadStructureLate ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ChangeButterfly ChangeLastOffset ReadButterfly RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ChangeButterfly ChangeLastOffset ReadButterfly ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure late
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ChangeButterfly ChangeLastOffset ReadButterfly ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure late
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ChangeButterfly ReadButterfly ChangeLastOffset RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ChangeButterfly ReadButterfly ChangeLastOffset ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ChangeButterfly ReadButterfly ChangeLastOffset ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ChangeButterfly ReadButterfly ReadStructureLate ChangeLastOffset RestoreStructure ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ChangeButterfly ReadButterfly ReadStructureLate ChangeLastOffset ReadLastOffsetLate RestoreStructure: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ChangeButterfly ReadButterfly ReadStructureLate ReadLastOffsetLate ChangeLastOffset RestoreStructure: IGNORE, read nuked structure late
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ReadButterfly ChangeButterfly ChangeLastOffset RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ReadButterfly ChangeButterfly ChangeLastOffset ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ReadButterfly ChangeButterfly ChangeLastOffset ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ReadButterfly ChangeButterfly ReadStructureLate ChangeLastOffset RestoreStructure ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ReadButterfly ChangeButterfly ReadStructureLate ChangeLastOffset ReadLastOffsetLate RestoreStructure: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ReadButterfly ChangeButterfly ReadStructureLate ReadLastOffsetLate ChangeLastOffset RestoreStructure: IGNORE, read nuked structure late
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ReadButterfly ReadStructureLate ChangeButterfly ChangeLastOffset RestoreStructure ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ReadButterfly ReadStructureLate ChangeButterfly ChangeLastOffset ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure late
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ReadButterfly ReadStructureLate ChangeButterfly ReadLastOffsetLate ChangeLastOffset RestoreStructure: IGNORE, read nuked structure late
+    // ReadStructureEarly ReadLastOffsetEarly NukeStructure ReadButterfly ReadStructureLate ReadLastOffsetLate ChangeButterfly ChangeLastOffset RestoreStructure: IGNORE, read nuked structure late
+    // ReadStructureEarly ReadLastOffsetEarly ReadButterfly NukeStructure ChangeButterfly ChangeLastOffset RestoreStructure ReadStructureLate ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly ReadButterfly NukeStructure ChangeButterfly ChangeLastOffset ReadStructureLate RestoreStructure ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly ReadButterfly NukeStructure ChangeButterfly ChangeLastOffset ReadStructureLate ReadLastOffsetLate RestoreStructure: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly ReadButterfly NukeStructure ChangeButterfly ReadStructureLate ChangeLastOffset RestoreStructure ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly ReadButterfly NukeStructure ChangeButterfly ReadStructureLate ChangeLastOffset ReadLastOffsetLate RestoreStructure: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly ReadButterfly NukeStructure ChangeButterfly ReadStructureLate ReadLastOffsetLate ChangeLastOffset RestoreStructure: IGNORE, read nuked structure late
+    // ReadStructureEarly ReadLastOffsetEarly ReadButterfly NukeStructure ReadStructureLate ChangeButterfly ChangeLastOffset RestoreStructure ReadLastOffsetLate: IGNORE, read nuked structure late
+    // ReadStructureEarly ReadLastOffsetEarly ReadButterfly NukeStructure ReadStructureLate ChangeButterfly ChangeLastOffset ReadLastOffsetLate RestoreStructure: IGNORE, read nuked structure late
+    // ReadStructureEarly ReadLastOffsetEarly ReadButterfly NukeStructure ReadStructureLate ChangeButterfly ReadLastOffsetLate ChangeLastOffset RestoreStructure: IGNORE, read nuked structure late
+    // ReadStructureEarly ReadLastOffsetEarly ReadButterfly NukeStructure ReadStructureLate ReadLastOffsetLate ChangeButterfly ChangeLastOffset RestoreStructure: IGNORE, read nuked structure late
+    // ReadStructureEarly ReadLastOffsetEarly ReadButterfly ReadStructureLate NukeStructure ChangeButterfly ChangeLastOffset RestoreStructure ReadLastOffsetLate: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly ReadButterfly ReadStructureLate NukeStructure ChangeButterfly ChangeLastOffset ReadLastOffsetLate RestoreStructure: IGNORE, read different offsets
+    // ReadStructureEarly ReadLastOffsetEarly ReadButterfly ReadStructureLate NukeStructure ChangeButterfly ReadLastOffsetLate ChangeLastOffset RestoreStructure: BEFORE, reads the offset before, everything else happens before
+    // ReadStructureEarly ReadLastOffsetEarly ReadButterfly ReadStructureLate NukeStructure ReadLastOffsetLate ChangeButterfly ChangeLastOffset RestoreStructure: BEFORE, reads the offset before, everything else happens before
+    // ReadStructureEarly ReadLastOffsetEarly ReadButterfly ReadStructureLate ReadLastOffsetLate NukeStructure ChangeButterfly ChangeLastOffset RestoreStructure: BEFORE, trivially
+    //
+    // Whew.
+    //
+    // What the collector is doing is just the &quot;double collect&quot; snapshot from &quot;The Unbounded Single-
+    // Writer Algorithm&quot; from Yehuda Afek et al's &quot;Atomic Snapshots of Shared Memory&quot; in JACM 1993,
+    // also available here:
+    //
+    // http://people.csail.mit.edu/shanir/publications/AADGMS.pdf
+    //
+    // Unlike Afek et al's algorithm, ours does not require extra hacks to force wait-freedom (see
+    // &quot;Observation 2&quot; in the paper). This simplifies the whole algorithm. Instead we are happy with
+    // obstruction-freedom, and like any good obstruction-free algorithm, we ensure progress using
+    // scheduling. We also only collect the butterfly once instead of twice; this optimization seems
+    // to hold up in my proofs above and I'm not sure it's part of Afek et al's algos.
+    //
+    // For more background on this kind of madness, I like this paper; it's where I learned about
+    // both the snapshot algorithm and obstruction-freedom:
+    //
+    // Lunchangco, Moir, Shavit. &quot;Nonblocking k-compare-single-swap.&quot; SPAA '03
+    // https://pdfs.semanticscholar.org/343f/7182cde7669ca2a7de3dc01127927f384ef7.pdf
+    
+    StructureID structureID = this-&gt;structureID();
+    if (isNuked(structureID))
+        return nullptr;
+    structure = vm.getStructure(structureID);
+    lastOffset = structure-&gt;lastOffset();
+    WTF::loadLoadFence();
+    butterfly = this-&gt;butterfly();
+    if (!butterfly)
+        return structure;
+    WTF::loadLoadFence();
+    if (this-&gt;structureID() != structureID)
+        return nullptr;
+    if (structure-&gt;lastOffset() != lastOffset)
+        return nullptr;
+    
+    markAuxiliaryAndVisitOutOfLineProperties(visitor, butterfly, structure, lastOffset);
+    
</ins><span class="cx">     IndexingType oldType = structure-&gt;indexingType();
</span><span class="cx">     switch (oldType) {
</span><span class="cx">     case ALL_CONTIGUOUS_INDEXING_TYPES:
</span><span class="lines">@@ -119,7 +401,7 @@
</span><span class="cx">     case ALL_ARRAY_STORAGE_INDEXING_TYPES: {
</span><span class="cx">         // This lock is here to protect Contiguous-&gt;ArrayStorage transitions, but we could make that
</span><span class="cx">         // race work if we needed to.
</span><del>-        JSCell::InternalLocker locker(this);
</del><ins>+        auto locker = holdLock(*this);
</ins><span class="cx">         IndexingType newType = this-&gt;indexingType();
</span><span class="cx">         butterfly = this-&gt;butterfly();
</span><span class="cx">         switch (newType) {
</span><span class="lines">@@ -137,6 +419,8 @@
</span><span class="cx">     default:
</span><span class="cx">         break;
</span><span class="cx">     }
</span><ins>+    
+    return structure;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> size_t JSObject::estimatedSize(JSCell* cell)
</span><span class="lines">@@ -156,35 +440,9 @@
</span><span class="cx"> #endif
</span><span class="cx">     
</span><span class="cx">     JSCell::visitChildren(thisObject, visitor);
</span><del>-
-    // We want to defend against multiple possible races with the mutator:
-    // - Mutator could install a bigger butterfly and then install a structure that claims more
-    //   properties. This trivially works.
-    // - Mutator could mutate the dictionary structure. Hence, we hold the structure lock for
-    //   dictionary structures.
-    // - The butterfly could shrink, but this could only happen if the object was a dictionary.
-    //   Usually, this means that we would get the dictionary structure and acquire a lock. That
-    //   trivially works. But we could load the structure before the object became a dictionary
-    //   and then load the butterfly that was shrunk. We protect against this case by checking
-    //   the structure a second time before scanning the butterfly. This means that the butterfly
-    //   is at worst the butterfly that the mutator had installed just prior to flipping the
-    //   sturcture. So if the structure we see is a non-dictionary then the butterfly cannot yet
-    //   have been shrunk.
-    VM&amp; vm = visitor.vm();
-    Structure* structure = thisObject-&gt;structure(vm);
-    bool wasDictionary = structure-&gt;isDictionary();
-    if (wasDictionary) {
-        structure-&gt;lock().lock();
-    } else
-        WTF::loadLoadFence();
-    if (Butterfly* butterfly = thisObject-&gt;m_butterfly.get()) {
-        WTF::loadLoadFence();
-        if (thisObject-&gt;structureID() == structure-&gt;id())
-            thisObject-&gt;visitButterfly(visitor, butterfly, structure);
-    }
-    if (wasDictionary)
-        structure-&gt;lock().unlock();
</del><span class="cx">     
</span><ins>+    thisObject-&gt;visitButterfly(visitor);
+    
</ins><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx">     visitor.m_isCheckingForDefaultMarkViolation = wasCheckingForDefaultMarkViolation;
</span><span class="cx"> #endif
</span><span class="lines">@@ -238,25 +496,11 @@
</span><span class="cx"> #endif
</span><span class="cx">     
</span><span class="cx">     JSCell::visitChildren(thisObject, visitor);
</span><del>-
-    VM&amp; vm = visitor.vm();
-    Structure* structure = thisObject-&gt;structure(vm);
-    bool wasDictionary = structure-&gt;isDictionary();
-    if (wasDictionary)
-        structure-&gt;lock().lock();
-    else
-        WTF::loadLoadFence();
-    if (Butterfly* butterfly = thisObject-&gt;butterfly()) {
-        WTF::loadLoadFence();
-        if (structure-&gt;id() == thisObject-&gt;structureID())
-            thisObject-&gt;visitButterfly(visitor, butterfly, structure);
</del><ins>+    
+    if (Structure* structure = thisObject-&gt;visitButterfly(visitor)) {
+        if (unsigned storageSize = structure-&gt;inlineSize())
+            visitor.appendValuesHidden(thisObject-&gt;inlineStorage(), storageSize);
</ins><span class="cx">     }
</span><del>-
-    size_t storageSize = structure-&gt;inlineSize();
-    if (storageSize)
-        visitor.appendValuesHidden(thisObject-&gt;inlineStorage(), storageSize);
-    if (wasDictionary)
-        structure-&gt;lock().unlock();
</del><span class="cx">     
</span><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx">     visitor.m_isCheckingForDefaultMarkViolation = wasCheckingForDefaultMarkViolation;
</span><span class="lines">@@ -711,7 +955,6 @@
</span><span class="cx">     newButterfly-&gt;arrayStorage()-&gt;m_indexBias = 0;
</span><span class="cx">     newButterfly-&gt;arrayStorage()-&gt;setVectorLength(0);
</span><span class="cx">     newButterfly-&gt;arrayStorage()-&gt;m_sparseMap.set(vm, this, map);
</span><del>-    WTF::storeStoreFence();
</del><span class="cx">     setButterfly(vm, newButterfly);
</span><span class="cx">     
</span><span class="cx">     return newButterfly-&gt;arrayStorage();
</span><span class="lines">@@ -776,10 +1019,10 @@
</span><span class="cx"> {
</span><span class="cx">     DeferGC deferGC(vm.heap);
</span><span class="cx">     Butterfly* newButterfly = createInitialIndexedStorage(vm, length);
</span><del>-    Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateUndecided);
-    WTF::storeStoreFence();
-    setButterfly(vm, newButterfly);
-    WTF::storeStoreFence();
</del><ins>+    StructureID oldStructureID = this-&gt;structureID();
+    Structure* oldStructure = vm.getStructure(oldStructureID);
+    Structure* newStructure = Structure::nonPropertyTransition(vm, oldStructure, NonPropertyTransition::AllocateUndecided);
+    nukeStructureAndSetButterfly(vm, oldStructureID, newButterfly);
</ins><span class="cx">     setStructure(vm, newStructure);
</span><span class="cx">     return newButterfly;
</span><span class="cx"> }
</span><span class="lines">@@ -790,10 +1033,10 @@
</span><span class="cx">     Butterfly* newButterfly = createInitialIndexedStorage(vm, length);
</span><span class="cx">     for (unsigned i = newButterfly-&gt;vectorLength(); i--;)
</span><span class="cx">         newButterfly-&gt;contiguousInt32()[i].setWithoutWriteBarrier(JSValue());
</span><del>-    Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateInt32);
-    WTF::storeStoreFence();
-    setButterfly(vm, newButterfly);
-    WTF::storeStoreFence();
</del><ins>+    StructureID oldStructureID = this-&gt;structureID();
+    Structure* oldStructure = vm.getStructure(oldStructureID);
+    Structure* newStructure = Structure::nonPropertyTransition(vm, oldStructure, NonPropertyTransition::AllocateInt32);
+    nukeStructureAndSetButterfly(vm, oldStructureID, newButterfly);
</ins><span class="cx">     setStructure(vm, newStructure);
</span><span class="cx">     return newButterfly-&gt;contiguousInt32();
</span><span class="cx"> }
</span><span class="lines">@@ -804,10 +1047,10 @@
</span><span class="cx">     Butterfly* newButterfly = createInitialIndexedStorage(vm, length);
</span><span class="cx">     for (unsigned i = newButterfly-&gt;vectorLength(); i--;)
</span><span class="cx">         newButterfly-&gt;contiguousDouble()[i] = PNaN;
</span><del>-    Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateDouble);
-    WTF::storeStoreFence();
-    setButterfly(vm, newButterfly);
-    WTF::storeStoreFence();
</del><ins>+    StructureID oldStructureID = this-&gt;structureID();
+    Structure* oldStructure = vm.getStructure(oldStructureID);
+    Structure* newStructure = Structure::nonPropertyTransition(vm, oldStructure, NonPropertyTransition::AllocateDouble);
+    nukeStructureAndSetButterfly(vm, oldStructureID, newButterfly);
</ins><span class="cx">     setStructure(vm, newStructure);
</span><span class="cx">     return newButterfly-&gt;contiguousDouble();
</span><span class="cx"> }
</span><span class="lines">@@ -818,10 +1061,10 @@
</span><span class="cx">     Butterfly* newButterfly = createInitialIndexedStorage(vm, length);
</span><span class="cx">     for (unsigned i = newButterfly-&gt;vectorLength(); i--;)
</span><span class="cx">         newButterfly-&gt;contiguous()[i].setWithoutWriteBarrier(JSValue());
</span><del>-    Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateContiguous);
-    WTF::storeStoreFence();
-    setButterfly(vm, newButterfly);
-    WTF::storeStoreFence();
</del><ins>+    StructureID oldStructureID = this-&gt;structureID();
+    Structure* oldStructure = vm.getStructure(oldStructureID);
+    Structure* newStructure = Structure::nonPropertyTransition(vm, oldStructure, NonPropertyTransition::AllocateContiguous);
+    nukeStructureAndSetButterfly(vm, oldStructureID, newButterfly);
</ins><span class="cx">     setStructure(vm, newStructure);
</span><span class="cx">     return newButterfly-&gt;contiguous();
</span><span class="cx"> }
</span><span class="lines">@@ -848,16 +1091,15 @@
</span><span class="cx"> ArrayStorage* JSObject::createArrayStorage(VM&amp; vm, unsigned length, unsigned vectorLength)
</span><span class="cx"> {
</span><span class="cx">     DeferGC deferGC(vm.heap);
</span><del>-    Structure* structure = this-&gt;structure(vm);
</del><ins>+    StructureID oldStructureID = this-&gt;structureID();
+    Structure* oldStructure = vm.getStructure(oldStructureID);
</ins><span class="cx">     IndexingType oldType = indexingType();
</span><span class="cx">     ASSERT_UNUSED(oldType, !hasIndexedProperties(oldType));
</span><span class="cx"> 
</span><del>-    Butterfly* newButterfly = createArrayStorageButterfly(vm, this, structure, length, vectorLength, m_butterfly.get());
</del><ins>+    Butterfly* newButterfly = createArrayStorageButterfly(vm, this, oldStructure, length, vectorLength, m_butterfly.get());
</ins><span class="cx">     ArrayStorage* result = newButterfly-&gt;arrayStorage();
</span><del>-    Structure* newStructure = Structure::nonPropertyTransition(vm, structure, structure-&gt;suggestedArrayStorageTransition());
-    WTF::storeStoreFence();
-    setButterfly(vm, newButterfly);
-    WTF::storeStoreFence();
</del><ins>+    Structure* newStructure = Structure::nonPropertyTransition(vm, oldStructure, oldStructure-&gt;suggestedArrayStorageTransition());
+    nukeStructureAndSetButterfly(vm, oldStructureID, newButterfly);
</ins><span class="cx">     setStructure(vm, newStructure);
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="lines">@@ -900,6 +1142,7 @@
</span><span class="cx">     for (unsigned i = butterfly-&gt;vectorLength(); i--;)
</span><span class="cx">         butterfly-&gt;contiguous()[i].setWithoutWriteBarrier(JSValue());
</span><span class="cx"> 
</span><ins>+    WTF::storeStoreFence();
</ins><span class="cx">     setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateContiguous));
</span><span class="cx">     return m_butterfly.get()-&gt;contiguous();
</span><span class="cx"> }
</span><span class="lines">@@ -940,10 +1183,10 @@
</span><span class="cx">     for (unsigned i = vectorLength; i--;)
</span><span class="cx">         storage-&gt;m_vector[i].setWithoutWriteBarrier(JSValue());
</span><span class="cx">     
</span><del>-    Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), transition);
-    WTF::storeStoreFence();
-    setButterfly(vm, storage-&gt;butterfly());
-    WTF::storeStoreFence();
</del><ins>+    StructureID oldStructureID = this-&gt;structureID();
+    Structure* oldStructure = vm.getStructure(oldStructureID);
+    Structure* newStructure = Structure::nonPropertyTransition(vm, oldStructure, transition);
+    nukeStructureAndSetButterfly(vm, oldStructureID, storage-&gt;butterfly());
</ins><span class="cx">     setStructure(vm, newStructure);
</span><span class="cx">     return storage;
</span><span class="cx"> }
</span><span class="lines">@@ -998,10 +1241,10 @@
</span><span class="cx">             newStorage-&gt;m_numValuesInVector++;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), transition);
-    WTF::storeStoreFence();
-    setButterfly(vm, newStorage-&gt;butterfly());
-    WTF::storeStoreFence();
</del><ins>+    StructureID oldStructureID = this-&gt;structureID();
+    Structure* oldStructure = vm.getStructure(oldStructureID);
+    Structure* newStructure = Structure::nonPropertyTransition(vm, oldStructure, transition);
+    nukeStructureAndSetButterfly(vm, oldStructureID, newStorage-&gt;butterfly());
</ins><span class="cx">     setStructure(vm, newStructure);
</span><span class="cx">     return newStorage;
</span><span class="cx"> }
</span><span class="lines">@@ -1028,6 +1271,7 @@
</span><span class="cx">         currentAsValue-&gt;setWithoutWriteBarrier(v);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    WTF::storeStoreFence();
</ins><span class="cx">     setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateContiguous));
</span><span class="cx">     return m_butterfly.get()-&gt;contiguous();
</span><span class="cx"> }
</span><span class="lines">@@ -1047,10 +1291,10 @@
</span><span class="cx">             newStorage-&gt;m_numValuesInVector++;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), transition);
-    WTF::storeStoreFence();
-    setButterfly(vm, newStorage-&gt;butterfly());
-    WTF::storeStoreFence();
</del><ins>+    StructureID oldStructureID = this-&gt;structureID();
+    Structure* oldStructure = vm.getStructure(oldStructureID);
+    Structure* newStructure = Structure::nonPropertyTransition(vm, oldStructure, transition);
+    nukeStructureAndSetButterfly(vm, oldStructureID, newStorage-&gt;butterfly());
</ins><span class="cx">     setStructure(vm, newStructure);
</span><span class="cx">     return newStorage;
</span><span class="cx"> }
</span><span class="lines">@@ -1089,10 +1333,18 @@
</span><span class="cx">     //
</span><span class="cx">     // Fortunately, we have the JSCell lock for this purpose!
</span><span class="cx">     
</span><del>-    InternalLocker locker(this);
-    setButterfly(vm, newStorage-&gt;butterfly());
-    WTF::storeStoreFence();
-    setStructure(vm, newStructure);
</del><ins>+    if (vm.heap.mutatorShouldBeFenced()) {
+        auto locker = holdLock(*this);
+        setStructureIDDirectly(nuke(structureID()));
+        WTF::storeStoreFence();
+        m_butterfly.set(vm, this, newStorage-&gt;butterfly());
+        WTF::storeStoreFence();
+        setStructure(vm, newStructure);
+    } else {
+        m_butterfly.set(vm, this, newStorage-&gt;butterfly());
+        setStructure(vm, newStructure);
+    }
+    
</ins><span class="cx">     return newStorage;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2814,7 +3066,6 @@
</span><span class="cx">         for (unsigned i = vectorLength; i &lt; newVectorLength; ++i)
</span><span class="cx">             newButterfly-&gt;arrayStorage()-&gt;m_vector[i].clear();
</span><span class="cx">         newButterfly-&gt;arrayStorage()-&gt;setVectorLength(newVectorLength);
</span><del>-        WTF::storeStoreFence();
</del><span class="cx">         setButterfly(vm, newButterfly);
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="lines">@@ -2832,7 +3083,6 @@
</span><span class="cx">         newButterfly-&gt;arrayStorage()-&gt;m_vector[i].clear();
</span><span class="cx">     newButterfly-&gt;arrayStorage()-&gt;setVectorLength(newVectorLength);
</span><span class="cx">     newButterfly-&gt;arrayStorage()-&gt;m_indexBias = newIndexBias;
</span><del>-    WTF::storeStoreFence();
</del><span class="cx">     setButterfly(vm, newButterfly);
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="lines">@@ -3218,7 +3468,6 @@
</span><span class="cx"> 
</span><span class="cx">     memcpy(newBase, currentBase, Butterfly::totalSize(0, outOfLineCapacityAfter, hasIndexingHeader, indexingPayloadSizeInBytes));
</span><span class="cx">     
</span><del>-    WTF::storeStoreFence();
</del><span class="cx">     setButterfly(vm, newButterfly);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSObject.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSObject.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/JSObject.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -748,8 +748,14 @@
</span><span class="cx">     void reifyAllStaticProperties(ExecState*);
</span><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE Butterfly* allocateMoreOutOfLineStorage(VM&amp;, size_t oldSize, size_t newSize);
</span><del>-        
-    void setButterfly(VM&amp;, Butterfly*); // Always change the butterfly before changing the structure!
</del><ins>+
+    // Call this when you do not need to change the structure.
+    void setButterfly(VM&amp;, Butterfly*);
+    
+    // Call this if you do need to change the structure, or if you changed something about a structure
+    // in-place.
+    void nukeStructureAndSetButterfly(VM&amp;, StructureID, Butterfly*);
+    
</ins><span class="cx">     void setStructure(VM&amp;, Structure*);
</span><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE void convertToDictionary(VM&amp;);
</span><span class="lines">@@ -865,8 +871,13 @@
</span><span class="cx">     // To instantiate objects you likely want JSFinalObject, below.
</span><span class="cx">     // To create derived types you likely want JSNonFinalObject, below.
</span><span class="cx">     JSObject(VM&amp;, Structure*, Butterfly* = 0);
</span><del>-        
-    void visitButterfly(SlotVisitor&amp;, Butterfly*, Structure*);
</del><ins>+    
+    // Visits the butterfly unless there is a race. Returns the structure if there was no race.
+    Structure* visitButterfly(SlotVisitor&amp;);
+    
+    Structure* visitButterflyImpl(SlotVisitor&amp;);
+    
+    void markAuxiliaryAndVisitOutOfLineProperties(SlotVisitor&amp;, Butterfly*, Structure*, PropertyOffset lastOffset);
</ins><span class="cx"> 
</span><span class="cx">     // Call this if you know that the object is in a mode where it has array
</span><span class="cx">     // storage. This will assert otherwise.
</span><span class="lines">@@ -1018,6 +1029,8 @@
</span><span class="cx">     ContiguousJSValues ensureContiguousSlow(VM&amp;);
</span><span class="cx">     JS_EXPORT_PRIVATE ArrayStorage* ensureArrayStorageSlow(VM&amp;);
</span><span class="cx"> 
</span><ins>+    PropertyOffset prepareToPutDirectWithoutTransition(VM&amp;, PropertyName, unsigned attributes, StructureID, Structure*);
+
</ins><span class="cx"> protected:
</span><span class="cx">     AuxiliaryBarrier&lt;Butterfly*&gt; m_butterfly;
</span><span class="cx"> #if USE(JSVALUE32_64)
</span><span class="lines">@@ -1214,9 +1227,29 @@
</span><span class="cx"> 
</span><span class="cx"> inline void JSObject::setButterfly(VM&amp; vm, Butterfly* butterfly)
</span><span class="cx"> {
</span><ins>+    if (isX86() || vm.heap.mutatorShouldBeFenced()) {
+        WTF::storeStoreFence();
+        m_butterfly.set(vm, this, butterfly);
+        WTF::storeStoreFence();
+        return;
+    }
+    
</ins><span class="cx">     m_butterfly.set(vm, this, butterfly);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline void JSObject::nukeStructureAndSetButterfly(VM&amp; vm, StructureID oldStructureID, Butterfly* butterfly)
+{
+    if (isX86() || vm.heap.mutatorShouldBeFenced()) {
+        setStructureIDDirectly(nuke(oldStructureID));
+        WTF::storeStoreFence();
+        m_butterfly.set(vm, this, butterfly);
+        WTF::storeStoreFence();
+        return;
+    }
+    
+    m_butterfly.set(vm, this, butterfly);
+}
+
</ins><span class="cx"> inline CallType getCallData(JSValue value, CallData&amp; callData)
</span><span class="cx"> {
</span><span class="cx">     CallType result = value.isCell() ? value.asCell()-&gt;methodTable()-&gt;getCallData(value.asCell(), callData) : CallType::None;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSObjectInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSObjectInlines.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSObjectInlines.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/JSObjectInlines.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -159,26 +159,36 @@
</span><span class="cx"> 
</span><span class="cx"> inline void JSObject::putDirectWithoutTransition(VM&amp; vm, PropertyName propertyName, JSValue value, unsigned attributes)
</span><span class="cx"> {
</span><del>-    DeferGC deferGC(vm.heap);
</del><span class="cx">     ASSERT(!value.isGetterSetter() &amp;&amp; !(attributes &amp; Accessor));
</span><span class="cx">     ASSERT(!value.isCustomGetterSetter());
</span><del>-    Butterfly* butterfly = m_butterfly.get();
-    Structure* structure = this-&gt;structure(vm);
</del><ins>+    StructureID structureID = this-&gt;structureID();
+    Structure* structure = vm.heap.structureIDTable().get(structureID);
+    PropertyOffset offset = prepareToPutDirectWithoutTransition(vm, propertyName, attributes, structureID, structure);
+    bool shouldOptimize = false;
+    structure-&gt;willStoreValueForNewTransition(vm, propertyName, value, shouldOptimize);
+    putDirect(vm, offset, value);
+    if (attributes &amp; ReadOnly)
+        structure-&gt;setContainsReadOnlyProperties();
+}
+
+ALWAYS_INLINE PropertyOffset JSObject::prepareToPutDirectWithoutTransition(VM&amp; vm, PropertyName propertyName, unsigned attributes, StructureID structureID, Structure* structure)
+{
</ins><span class="cx">     unsigned oldOutOfLineCapacity = structure-&gt;outOfLineCapacity();
</span><ins>+    PropertyOffset result;
</ins><span class="cx">     structure-&gt;addPropertyWithoutTransition(
</span><span class="cx">         vm, propertyName, attributes,
</span><del>-        [&amp;] (const GCSafeConcurrentJSLocker&amp;, PropertyOffset offset, unsigned newOutOfLineCapacity) {
</del><ins>+        [&amp;] (const GCSafeConcurrentJSLocker&amp;, PropertyOffset offset, PropertyOffset newLastOffset) {
+            unsigned newOutOfLineCapacity = Structure::outOfLineCapacity(newLastOffset);
</ins><span class="cx">             if (newOutOfLineCapacity != oldOutOfLineCapacity) {
</span><del>-                butterfly = allocateMoreOutOfLineStorage(vm, oldOutOfLineCapacity, newOutOfLineCapacity);
-                WTF::storeStoreFence();
-                setButterfly(vm, butterfly);
-            }
-            if (attributes &amp; ReadOnly)
-                structure-&gt;setContainsReadOnlyProperties();
-            bool shouldOptimize = false;
-            structure-&gt;willStoreValueForNewTransition(vm, propertyName, value, shouldOptimize);
-            putDirect(vm, offset, value);
</del><ins>+                Butterfly* butterfly = allocateMoreOutOfLineStorage(vm, oldOutOfLineCapacity, newOutOfLineCapacity);
+                nukeStructureAndSetButterfly(vm, structureID, butterfly);
+                structure-&gt;setLastOffset(newLastOffset);
+                setStructureIDDirectly(structureID);
+            } else
+                structure-&gt;setLastOffset(newLastOffset);
+            result = offset;
</ins><span class="cx">         });
</span><ins>+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // ECMA 8.6.2.2
</span><span class="lines">@@ -239,7 +249,8 @@
</span><span class="cx">     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
</span><span class="cx">     ASSERT(!parseIndex(propertyName));
</span><span class="cx"> 
</span><del>-    Structure* structure = this-&gt;structure(vm);
</del><ins>+    StructureID structureID = this-&gt;structureID();
+    Structure* structure = vm.heap.structureIDTable().get(structureID);
</ins><span class="cx">     if (structure-&gt;isDictionary()) {
</span><span class="cx">         ASSERT(!structure-&gt;hasInferredTypes());
</span><span class="cx">         
</span><span class="lines">@@ -263,20 +274,9 @@
</span><span class="cx">         if ((mode == PutModePut) &amp;&amp; !isStructureExtensible())
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><del>-        unsigned oldOutOfLineCapacity = structure-&gt;outOfLineCapacity();
-        offset = structure-&gt;addPropertyWithoutTransition(
-            vm, propertyName, attributes,
-            [&amp;] (const GCSafeConcurrentJSLocker&amp;, PropertyOffset offset, unsigned newOutOfLineCapacity) {
-                Butterfly* butterfly = this-&gt;butterfly();
-                if (newOutOfLineCapacity != oldOutOfLineCapacity) {
-                    butterfly = allocateMoreOutOfLineStorage(vm, oldOutOfLineCapacity, newOutOfLineCapacity);
-                    WTF::storeStoreFence();
-                    setButterfly(vm, butterfly);
-                }
-                validateOffset(offset);
-                putDirect(vm, offset, value);
-            });
-
</del><ins>+        offset = prepareToPutDirectWithoutTransition(vm, propertyName, attributes, structureID, structure);
+        validateOffset(offset);
+        putDirect(vm, offset, value);
</ins><span class="cx">         slot.setNewProperty(this, offset);
</span><span class="cx">         if (attributes &amp; ReadOnly)
</span><span class="cx">             this-&gt;structure()-&gt;setContainsReadOnlyProperties();
</span><span class="lines">@@ -291,14 +291,11 @@
</span><span class="cx">         newStructure-&gt;willStoreValueForExistingTransition(
</span><span class="cx">             vm, propertyName, value, slot.context() == PutPropertySlot::PutById);
</span><span class="cx">         
</span><del>-        DeferGC deferGC(vm.heap);
</del><span class="cx">         Butterfly* newButterfly = butterfly();
</span><span class="cx">         if (currentCapacity != newStructure-&gt;outOfLineCapacity()) {
</span><span class="cx">             ASSERT(newStructure != this-&gt;structure());
</span><span class="cx">             newButterfly = allocateMoreOutOfLineStorage(vm, currentCapacity, newStructure-&gt;outOfLineCapacity());
</span><del>-            WTF::storeStoreFence();
-            setButterfly(vm, newButterfly);
-            WTF::storeStoreFence();
</del><ins>+            nukeStructureAndSetButterfly(vm, structureID, newButterfly);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         validateOffset(offset);
</span><span class="lines">@@ -347,15 +344,12 @@
</span><span class="cx">     
</span><span class="cx">     validateOffset(offset);
</span><span class="cx">     ASSERT(newStructure-&gt;isValidOffset(offset));
</span><del>-    DeferGC deferGC(vm.heap);
</del><span class="cx">     size_t oldCapacity = structure-&gt;outOfLineCapacity();
</span><span class="cx">     size_t newCapacity = newStructure-&gt;outOfLineCapacity();
</span><span class="cx">     ASSERT(oldCapacity &lt;= newCapacity);
</span><span class="cx">     if (oldCapacity != newCapacity) {
</span><span class="cx">         Butterfly* newButterfly = allocateMoreOutOfLineStorage(vm, oldCapacity, newCapacity);
</span><del>-        WTF::storeStoreFence();
-        setButterfly(vm, newButterfly);
-        WTF::storeStoreFence();
</del><ins>+        nukeStructureAndSetButterfly(vm, structureID, newButterfly);
</ins><span class="cx">     }
</span><span class="cx">     putDirect(vm, offset, value);
</span><span class="cx">     setStructure(vm, newStructure);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014-2016 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">@@ -27,6 +27,7 @@
</span><span class="cx"> #include &quot;JSPropertyNameEnumerator.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;LockDuringMarking.h&quot;
</ins><span class="cx"> #include &quot;StrongInlines.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -70,7 +71,10 @@
</span><span class="cx">     m_endStructurePropertyIndex = endStructurePropertyIndex;
</span><span class="cx">     m_endGenericPropertyIndex = vector.size();
</span><span class="cx"> 
</span><del>-    m_propertyNames.resizeToFit(vector.size());
</del><ins>+    {
+        auto locker = lockDuringMarking(vm.heap, *this);
+        m_propertyNames.resizeToFit(vector.size());
+    }
</ins><span class="cx">     for (unsigned i = 0; i &lt; vector.size(); ++i) {
</span><span class="cx">         const Identifier&amp; identifier = vector[i];
</span><span class="cx">         m_propertyNames[i].set(vm, this, jsString(&amp;vm, identifier.string()));
</span><span class="lines">@@ -86,6 +90,7 @@
</span><span class="cx"> {
</span><span class="cx">     Base::visitChildren(cell, visitor);
</span><span class="cx">     JSPropertyNameEnumerator* thisObject = jsCast&lt;JSPropertyNameEnumerator*&gt;(cell);
</span><ins>+    auto locker = holdLock(*thisObject);
</ins><span class="cx">     for (unsigned i = 0; i &lt; thisObject-&gt;m_propertyNames.size(); ++i)
</span><span class="cx">         visitor.append(&amp;thisObject-&gt;m_propertyNames[i]);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_prototypeChain);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSSegmentedVariableObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -66,6 +66,9 @@
</span><span class="cx">     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
</span><span class="cx">     Base::visitChildren(thisObject, slotVisitor);
</span><span class="cx">     
</span><ins>+    // FIXME: We could avoid locking here if SegmentedVector was lock-free. It could be made lock-free
+    // relatively easily.
+    auto locker = holdLock(thisObject-&gt;m_lock);
</ins><span class="cx">     for (unsigned i = thisObject-&gt;m_variables.size(); i--;)
</span><span class="cx">         slotVisitor.appendHidden(&amp;thisObject-&gt;m_variables[i]);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSStringcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSString.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSString.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/JSString.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -97,11 +97,8 @@
</span><span class="cx">     
</span><span class="cx">     if (thisObject-&gt;isRope())
</span><span class="cx">         static_cast&lt;JSRopeString*&gt;(thisObject)-&gt;visitFibers(visitor);
</span><del>-    else {
-        StringImpl* impl = thisObject-&gt;m_value.impl();
-        ASSERT(impl);
</del><ins>+    if (StringImpl* impl = thisObject-&gt;m_value.impl())
</ins><span class="cx">         visitor.reportExtraMemoryVisited(impl-&gt;costDuringGC());
</span><del>-    }
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JSRopeString::visitFibers(SlotVisitor&amp; visitor)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeModuleProgramExecutablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ModuleProgramExecutable.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ModuleProgramExecutable.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/ModuleProgramExecutable.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -93,8 +93,8 @@
</span><span class="cx">     ScriptExecutable::visitChildren(thisObject, visitor);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_unlinkedModuleProgramCodeBlock);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_moduleEnvironmentSymbolTable);
</span><del>-    if (thisObject-&gt;m_moduleProgramCodeBlock)
-        thisObject-&gt;m_moduleProgramCodeBlock-&gt;visitWeakly(visitor);
</del><ins>+    if (ModuleProgramCodeBlock* moduleProgramCodeBlock = thisObject-&gt;m_moduleProgramCodeBlock.get())
+        moduleProgramCodeBlock-&gt;visitWeakly(visitor);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/Options.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -332,6 +332,10 @@
</span><span class="cx">     Options::useFTLJIT() = false;
</span><span class="cx"> #endif
</span><span class="cx">     
</span><ins>+#if !CPU(X86_64)
+    Options::useConcurrentGC() = false;
+#endif
+    
</ins><span class="cx"> #if OS(WINDOWS) &amp;&amp; CPU(X86) 
</span><span class="cx">     // Disable JIT on Windows if SSE2 is not present 
</span><span class="cx">     if (!MacroAssemblerX86::supportsFloatingPoint())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -184,9 +184,12 @@
</span><span class="cx">     v(bool, verboseSanitizeStack, false, Normal, nullptr) \
</span><span class="cx">     v(bool, useGenerationalGC, true, Normal, nullptr) \
</span><span class="cx">     v(bool, useConcurrentBarriers, true, Normal, nullptr) \
</span><del>-    v(bool, useConcurrentGC, false, Normal, nullptr) \
</del><ins>+    v(bool, useConcurrentGC, true, Normal, nullptr) \
</ins><span class="cx">     v(bool, collectContinuously, false, Normal, nullptr) \
</span><ins>+    v(double, collectContinuouslyPeriodMS, 1, Normal, nullptr) \
</ins><span class="cx">     v(bool, forceFencedBarrier, false, Normal, nullptr) \
</span><ins>+    v(bool, verboseVisitRace, false, Normal, nullptr) \
+    v(bool, optimizeParallelSlotVisitorsForStoppedMutator, false, Normal, nullptr) \
</ins><span class="cx">     v(unsigned, largeHeapSize, 32 * 1024 * 1024, Normal, nullptr) \
</span><span class="cx">     v(unsigned, smallHeapSize, 1 * 1024 * 1024, Normal, nullptr) \
</span><span class="cx">     v(double, smallHeapRAMFraction, 0.25, Normal, nullptr) \
</span><span class="lines">@@ -322,7 +325,7 @@
</span><span class="cx">     v(unsigned, maximumDirectCallStackSize, 200, Normal, nullptr) \
</span><span class="cx">     \
</span><span class="cx">     v(unsigned, minimumNumberOfScansBetweenRebalance, 100, Normal, nullptr) \
</span><del>-    v(unsigned, numberOfGCMarkers, computeNumberOfGCMarkers(7), Normal, nullptr) \
</del><ins>+    v(unsigned, numberOfGCMarkers, computeNumberOfGCMarkers(8), Normal, nullptr) \
</ins><span class="cx">     v(unsigned, opaqueRootMergeThreshold, 1000, Normal, nullptr) \
</span><span class="cx">     v(double, minHeapUtilization, 0.8, Normal, nullptr) \
</span><span class="cx">     v(double, minMarkedBlockUtilization, 0.9, Normal, nullptr) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeProgramExecutablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ProgramExecutable.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ProgramExecutable.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/ProgramExecutable.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -204,8 +204,8 @@
</span><span class="cx">     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
</span><span class="cx">     ScriptExecutable::visitChildren(thisObject, visitor);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_unlinkedProgramCodeBlock);
</span><del>-    if (thisObject-&gt;m_programCodeBlock)
-        thisObject-&gt;m_programCodeBlock-&gt;visitWeakly(visitor);
</del><ins>+    if (ProgramCodeBlock* programCodeBlock = thisObject-&gt;m_programCodeBlock.get())
+        programCodeBlock-&gt;visitWeakly(visitor);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpCachedResultcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -48,12 +48,13 @@
</span><span class="cx">     if (!m_reified) {
</span><span class="cx">         m_reifiedInput.set(exec-&gt;vm(), owner, m_lastInput.get());
</span><span class="cx">         if (m_result)
</span><del>-            m_reifiedResult.set(exec-&gt;vm(), owner, createRegExpMatchesArray(exec, exec-&gt;lexicalGlobalObject(), m_lastInput.get(), m_lastRegExp.get(), m_result.start));
</del><ins>+            m_reifiedResult.setWithoutWriteBarrier(createRegExpMatchesArray(exec, exec-&gt;lexicalGlobalObject(), m_lastInput.get(), m_lastRegExp.get(), m_result.start));
</ins><span class="cx">         else
</span><del>-            m_reifiedResult.set(exec-&gt;vm(), owner, createEmptyRegExpMatchesArray(exec-&gt;lexicalGlobalObject(), m_lastInput.get(), m_lastRegExp.get()));
</del><ins>+            m_reifiedResult.setWithoutWriteBarrier(createEmptyRegExpMatchesArray(exec-&gt;lexicalGlobalObject(), m_lastInput.get(), m_lastRegExp.get()));
</ins><span class="cx">         m_reifiedLeftContext.clear();
</span><span class="cx">         m_reifiedRightContext.clear();
</span><span class="cx">         m_reified = true;
</span><ins>+        exec-&gt;vm().heap.writeBarrier(owner);
</ins><span class="cx">     }
</span><span class="cx">     return m_reifiedResult.get();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeSamplingProfilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/SamplingProfiler.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/SamplingProfiler.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/SamplingProfiler.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -31,14 +31,12 @@
</span><span class="cx"> #include &quot;CallFrame.h&quot;
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><span class="cx"> #include &quot;CodeBlockSet.h&quot;
</span><del>-#include &quot;HeapInlines.h&quot;
</del><span class="cx"> #include &quot;HeapIterationScope.h&quot;
</span><span class="cx"> #include &quot;HeapUtil.h&quot;
</span><span class="cx"> #include &quot;InlineCallFrame.h&quot;
</span><span class="cx"> #include &quot;Interpreter.h&quot;
</span><del>-#include &quot;JSCJSValueInlines.h&quot;
</del><ins>+#include &quot;JSCInlines.h&quot;
</ins><span class="cx"> #include &quot;JSFunction.h&quot;
</span><del>-#include &quot;JSObjectInlines.h&quot;
</del><span class="cx"> #include &quot;LLIntPCRanges.h&quot;
</span><span class="cx"> #include &quot;MarkedBlock.h&quot;
</span><span class="cx"> #include &quot;MarkedBlockSet.h&quot;
</span><span class="lines">@@ -46,8 +44,6 @@
</span><span class="cx"> #include &quot;NativeExecutable.h&quot;
</span><span class="cx"> #include &quot;PCToCodeOriginMap.h&quot;
</span><span class="cx"> #include &quot;SlotVisitor.h&quot;
</span><del>-#include &quot;SlotVisitorInlines.h&quot;
-#include &quot;StructureInlines.h&quot;
</del><span class="cx"> #include &quot;VM.h&quot;
</span><span class="cx"> #include &lt;wtf/HashSet.h&gt;
</span><span class="cx"> #include &lt;wtf/RandomNumber.h&gt;
</span><span class="lines">@@ -737,6 +733,7 @@
</span><span class="cx"> 
</span><span class="cx"> String SamplingProfiler::stackTracesAsJSON()
</span><span class="cx"> {
</span><ins>+    DeferGC deferGC(m_vm.heap);
</ins><span class="cx">     LockHolder locker(m_lock);
</span><span class="cx"> 
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeSparseArrayValueMapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011-2012, 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011-2016 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">@@ -74,11 +74,16 @@
</span><span class="cx"> 
</span><span class="cx"> SparseArrayValueMap::AddResult SparseArrayValueMap::add(JSObject* array, unsigned i)
</span><span class="cx"> {
</span><del>-    SparseArrayEntry entry;
-    entry.setWithoutWriteBarrier(jsUndefined());
-
-    AddResult result = m_map.add(i, entry);
-    size_t capacity = m_map.capacity();
</del><ins>+    AddResult result;
+    size_t capacity;
+    {
+        auto locker = holdLock(*this);
+        SparseArrayEntry entry;
+        entry.setWithoutWriteBarrier(jsUndefined());
+        
+        result = m_map.add(i, entry);
+        capacity = m_map.capacity();
+    }
</ins><span class="cx">     if (capacity != m_reportedCapacity) {
</span><span class="cx">         // FIXME: Adopt reportExtraMemoryVisited, and switch to reportExtraMemoryAllocated.
</span><span class="cx">         // https://bugs.webkit.org/show_bug.cgi?id=142595
</span><span class="lines">@@ -88,6 +93,18 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SparseArrayValueMap::remove(iterator it)
+{
+    auto locker = holdLock(*this);
+    m_map.remove(it);
+}
+
+void SparseArrayValueMap::remove(unsigned i)
+{
+    auto locker = holdLock(*this);
+    m_map.remove(i);
+}
+
</ins><span class="cx"> bool SparseArrayValueMap::putEntry(ExecState* exec, JSObject* array, unsigned i, JSValue value, bool shouldThrow)
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="lines">@@ -182,6 +199,7 @@
</span><span class="cx">     Base::visitChildren(thisObject, visitor);
</span><span class="cx">     
</span><span class="cx">     SparseArrayValueMap* thisMap = jsCast&lt;SparseArrayValueMap*&gt;(thisObject);
</span><ins>+    auto locker = holdLock(*thisMap);
</ins><span class="cx">     iterator end = thisMap-&gt;m_map.end();
</span><span class="cx">     for (iterator it = thisMap-&gt;m_map.begin(); it != end; ++it)
</span><span class="cx">         visitor.append(&amp;it-&gt;value);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeSparseArrayValueMaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/SparseArrayValueMap.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/SparseArrayValueMap.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/SparseArrayValueMap.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011-2016 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">@@ -49,7 +49,6 @@
</span><span class="cx">     unsigned attributes;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-// FIXME: This needs to have a lock in it.
</del><span class="cx"> class SparseArrayValueMap final : public JSCell {
</span><span class="cx"> public:
</span><span class="cx">     typedef JSCell Base;
</span><span class="lines">@@ -111,8 +110,8 @@
</span><span class="cx">     AddResult add(JSObject*, unsigned);
</span><span class="cx">     iterator find(unsigned i) { return m_map.find(i); }
</span><span class="cx">     // This should ASSERT the remove is valid (check the result of the find).
</span><del>-    void remove(iterator it) { m_map.remove(it); }
-    void remove(unsigned i) { m_map.remove(i); }
</del><ins>+    void remove(iterator it);
+    void remove(unsigned i);
</ins><span class="cx"> 
</span><span class="cx">     // These methods do not mutate the contents of the map.
</span><span class="cx">     iterator notFound() { return m_map.end(); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructurecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Structure.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Structure.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/Structure.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -201,6 +201,7 @@
</span><span class="cx">     setStaticPropertiesReified(false);
</span><span class="cx">     setTransitionWatchpointIsLikelyToBeFired(false);
</span><span class="cx">     setHasBeenDictionary(false);
</span><ins>+    setIsAddingPropertyForTransition(false);
</ins><span class="cx">  
</span><span class="cx">     ASSERT(inlineCapacity &lt;= JSFinalObject::maxInlineCapacity());
</span><span class="cx">     ASSERT(static_cast&lt;PropertyOffset&gt;(inlineCapacity) &lt; firstOutOfLineOffset);
</span><span class="lines">@@ -232,6 +233,7 @@
</span><span class="cx">     setStaticPropertiesReified(false);
</span><span class="cx">     setTransitionWatchpointIsLikelyToBeFired(false);
</span><span class="cx">     setHasBeenDictionary(false);
</span><ins>+    setIsAddingPropertyForTransition(false);
</ins><span class="cx">  
</span><span class="cx">     TypeInfo typeInfo = TypeInfo(CellType, StructureFlags);
</span><span class="cx">     m_blob = StructureIDBlob(vm.heap.structureIDTable().allocateID(this), 0, typeInfo);
</span><span class="lines">@@ -261,6 +263,7 @@
</span><span class="cx">     setDidTransition(true);
</span><span class="cx">     setStaticPropertiesReified(previous-&gt;staticPropertiesReified());
</span><span class="cx">     setHasBeenDictionary(previous-&gt;hasBeenDictionary());
</span><ins>+    setIsAddingPropertyForTransition(false);
</ins><span class="cx">  
</span><span class="cx">     TypeInfo typeInfo = previous-&gt;typeInfo();
</span><span class="cx">     m_blob = StructureIDBlob(vm.heap.structureIDTable().allocateID(this), previous-&gt;indexingTypeIncludingHistory(), typeInfo);
</span><span class="lines">@@ -318,6 +321,7 @@
</span><span class="cx"> PropertyTable* Structure::materializePropertyTable(VM&amp; vm, bool setPropertyTable)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(structure()-&gt;classInfo() == info());
</span><ins>+    ASSERT(!isAddingPropertyForTransition());
</ins><span class="cx">     
</span><span class="cx">     DeferGC deferGC(vm.heap);
</span><span class="cx">     
</span><span class="lines">@@ -468,6 +472,21 @@
</span><span class="cx">     Structure* transition = create(vm, structure, deferred);
</span><span class="cx"> 
</span><span class="cx">     transition-&gt;m_cachedPrototypeChain.setMayBeNull(vm, transition, structure-&gt;m_cachedPrototypeChain.get());
</span><ins>+    
+    // While we are adding the property, rematerializing the property table is super weird: we already
+    // have a m_nameInPrevious and attributesInPrevious but the m_offset is still wrong. If the
+    // materialization algorithm runs, it'll build a property table that already has the property but
+    // at a bogus offset. Rather than try to teach the materialization code how to create a table under
+    // those conditions, we just tell the GC not to blow the table away during this period of time.
+    // Holding the lock ensures that we either do this before the GC starts scanning the structure, in
+    // which case the GC will not blow the table away, or we do it after the GC already ran in which
+    // case all is well.  If it wasn't for the lock, the GC would have TOCTOU: if could read
+    // isAddingPropertyForTransition before we set it to true, and then blow the table away after.
+    {
+        ConcurrentJSLocker locker(transition-&gt;m_lock);
+        transition-&gt;setIsAddingPropertyForTransition(true);
+    }
+    
</ins><span class="cx">     transition-&gt;m_nameInPrevious = propertyName.uid();
</span><span class="cx">     transition-&gt;setAttributesInPrevious(attributes);
</span><span class="cx">     transition-&gt;setPropertyTable(vm, structure-&gt;takePropertyTableOrCloneIfPinned(vm));
</span><span class="lines">@@ -476,6 +495,11 @@
</span><span class="cx"> 
</span><span class="cx">     offset = transition-&gt;add(vm, propertyName, attributes);
</span><span class="cx"> 
</span><ins>+    // Now that everything is fine with the new structure's bookkeeping, the GC is free to blow the
+    // table away if it wants. We can now rebuild it fine.
+    WTF::storeStoreFence();
+    transition-&gt;setIsAddingPropertyForTransition(false);
+
</ins><span class="cx">     checkOffset(transition-&gt;m_offset, transition-&gt;inlineCapacity());
</span><span class="cx">     {
</span><span class="cx">         ConcurrentJSLocker locker(structure-&gt;m_lock);
</span><span class="lines">@@ -720,6 +744,9 @@
</span><span class="cx">     ASSERT(isDictionary());
</span><span class="cx">     
</span><span class="cx">     GCSafeConcurrentJSLocker locker(m_lock, vm.heap);
</span><ins>+    
+    object-&gt;setStructureIDDirectly(nuke(id()));
+    WTF::storeStoreFence();
</ins><span class="cx"> 
</span><span class="cx">     size_t beforeOutOfLineCapacity = this-&gt;outOfLineCapacity();
</span><span class="cx">     if (isUncacheableDictionary()) {
</span><span class="lines">@@ -766,6 +793,10 @@
</span><span class="cx">             object-&gt;shiftButterflyAfterFlattening(locker, vm, this, afterOutOfLineCapacity);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    vm.heap.writeBarrier(object);
+    WTF::storeStoreFence();
+    object-&gt;setStructureIDDirectly(id());
+    
</ins><span class="cx">     return this;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -943,7 +974,11 @@
</span><span class="cx"> 
</span><span class="cx"> PropertyOffset Structure::add(VM&amp; vm, PropertyName propertyName, unsigned attributes)
</span><span class="cx"> {
</span><del>-    return add(vm, propertyName, attributes, [] (const GCSafeConcurrentJSLocker&amp;, PropertyOffset, unsigned) { });
</del><ins>+    return add(
+        vm, propertyName, attributes,
+        [this] (const GCSafeConcurrentJSLocker&amp;, PropertyOffset, PropertyOffset newLastOffset) {
+            setLastOffset(newLastOffset);
+        });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> PropertyOffset Structure::remove(PropertyName propertyName)
</span><span class="lines">@@ -1034,7 +1069,7 @@
</span><span class="cx">     }
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_previousOrRareData);
</span><span class="cx"> 
</span><del>-    if (thisObject-&gt;isPinnedPropertyTable()) {
</del><ins>+    if (thisObject-&gt;isPinnedPropertyTable() || thisObject-&gt;isAddingPropertyForTransition()) {
</ins><span class="cx">         // NOTE: This can interleave in pin(), in which case it may see a null property table.
</span><span class="cx">         // That's fine, because then the barrier will fire and we will scan this again.
</span><span class="cx">         visitor.append(&amp;thisObject-&gt;m_propertyTableUnsafe);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructureh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Structure.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Structure.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/Structure.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -296,7 +296,36 @@
</span><span class="cx">         return static_cast&lt;Structure*&gt;(cell);
</span><span class="cx">     }
</span><span class="cx">     bool transitivelyTransitionedFrom(Structure* structureToFind);
</span><ins>+    
+    PropertyOffset lastOffset() const { return m_offset; }
+    
+    void setLastOffset(PropertyOffset offset) { m_offset = offset; }
</ins><span class="cx"> 
</span><ins>+    static unsigned outOfLineCapacity(PropertyOffset lastOffset)
+    {
+        unsigned outOfLineSize = Structure::outOfLineSize(lastOffset);
+
+        // This algorithm completely determines the out-of-line property storage growth algorithm.
+        // The JSObject code will only trigger a resize if the value returned by this algorithm
+        // changed between the new and old structure. So, it's important to keep this simple because
+        // it's on a fast path.
+        
+        if (!outOfLineSize)
+            return 0;
+
+        if (outOfLineSize &lt;= initialOutOfLineCapacity)
+            return initialOutOfLineCapacity;
+
+        ASSERT(outOfLineSize &gt; initialOutOfLineCapacity);
+        COMPILE_ASSERT(outOfLineGrowthFactor == 2, outOfLineGrowthFactor_is_two);
+        return WTF::roundUpToPowerOfTwo(outOfLineSize);
+    }
+    
+    static unsigned outOfLineSize(PropertyOffset lastOffset)
+    {
+        return numberOfOutOfLineSlotsForLastOffset(lastOffset);
+    }
+
</ins><span class="cx">     unsigned outOfLineCapacity() const
</span><span class="cx">     {
</span><span class="cx">         return outOfLineCapacity(m_offset);
</span><span class="lines">@@ -457,8 +486,7 @@
</span><span class="cx">         // https://bugs.webkit.org/show_bug.cgi?id=133625
</span><span class="cx">         
</span><span class="cx">         // - We don't watch Structures that either decided not to be watched, or whose predecessors
</span><del>-        //   decided not to be watched. This happens either when a transition is fired while being
-        //   watched.
</del><ins>+        //   decided not to be watched. This happens when a transition is fired while being watched.
</ins><span class="cx">         if (transitionWatchpointIsLikelyToBeFired())
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="lines">@@ -607,6 +635,7 @@
</span><span class="cx">     DEFINE_BITFIELD(bool, didWatchInternalProperties, DidWatchInternalProperties, 1, 25);
</span><span class="cx">     DEFINE_BITFIELD(bool, transitionWatchpointIsLikelyToBeFired, TransitionWatchpointIsLikelyToBeFired, 1, 26);
</span><span class="cx">     DEFINE_BITFIELD(bool, hasBeenDictionary, HasBeenDictionary, 1, 27);
</span><ins>+    DEFINE_BITFIELD(bool, isAddingPropertyForTransition, IsAddingPropertyForTransition, 1, 28);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class LLIntOffsetsExtractor;
</span><span class="lines">@@ -627,33 +656,6 @@
</span><span class="cx">     
</span><span class="cx">     static Structure* toDictionaryTransition(VM&amp;, Structure*, DictionaryKind, DeferredStructureTransitionWatchpointFire* = nullptr);
</span><span class="cx">     
</span><del>-    unsigned outOfLineCapacity(PropertyOffset lastOffset) const
-    {
-        unsigned outOfLineSize = this-&gt;outOfLineSize(lastOffset);
-
-        // This algorithm completely determines the out-of-line property storage growth algorithm.
-        // The JSObject code will only trigger a resize if the value returned by this algorithm
-        // changed between the new and old structure. So, it's important to keep this simple because
-        // it's on a fast path.
-        
-        if (!outOfLineSize)
-            return 0;
-
-        if (outOfLineSize &lt;= initialOutOfLineCapacity)
-            return initialOutOfLineCapacity;
-
-        ASSERT(outOfLineSize &gt; initialOutOfLineCapacity);
-        COMPILE_ASSERT(outOfLineGrowthFactor == 2, outOfLineGrowthFactor_is_two);
-        return WTF::roundUpToPowerOfTwo(outOfLineSize);
-    }
-    
-    unsigned outOfLineSize(PropertyOffset lastOffset) const
-    {
-        ASSERT(structure()-&gt;classInfo() == info());
-            
-        return numberOfOutOfLineSlotsForLastOffset(lastOffset);
-    }
-
</del><span class="cx">     template&lt;typename Func&gt;
</span><span class="cx">     PropertyOffset add(VM&amp;, PropertyName, unsigned attributes, const Func&amp;);
</span><span class="cx">     PropertyOffset add(VM&amp;, PropertyName, unsigned attributes);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructureChaincpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StructureChain.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StructureChain.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/StructureChain.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -48,9 +48,11 @@
</span><span class="cx"> {
</span><span class="cx">     StructureChain* thisObject = jsCast&lt;StructureChain*&gt;(cell);
</span><span class="cx">     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
</span><del>-    size_t i = 0;
-    while (thisObject-&gt;m_vector[i])
-        visitor.append(&amp;thisObject-&gt;m_vector[i++]);
</del><ins>+    if (WriteBarrier&lt;Structure&gt;* vector = thisObject-&gt;m_vector.get()) {
+        size_t i = 0;
+        while (vector[i])
+            visitor.append(&amp;vector[i++]);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructureChainh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StructureChain.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StructureChain.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/StructureChain.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -69,11 +69,14 @@
</span><span class="cx">         for (Structure* current = head; current; current = current-&gt;storedPrototype().isNull() ? 0 : asObject(current-&gt;storedPrototype())-&gt;structure())
</span><span class="cx">             ++size;
</span><span class="cx"> 
</span><del>-        m_vector = std::make_unique&lt;WriteBarrier&lt;Structure&gt;[]&gt;(size + 1);
</del><ins>+        std::unique_ptr&lt;WriteBarrier&lt;Structure&gt;[]&gt; vector = std::make_unique&lt;WriteBarrier&lt;Structure&gt;[]&gt;(size + 1);
</ins><span class="cx"> 
</span><span class="cx">         size_t i = 0;
</span><span class="cx">         for (Structure* current = head; current; current = current-&gt;storedPrototype().isNull() ? 0 : asObject(current-&gt;storedPrototype())-&gt;structure())
</span><del>-            m_vector[i++].set(vm, this, current);
</del><ins>+            vector[i++].set(vm, this, current);
+        
+        vm.heap.mutatorFence();
+        m_vector = WTFMove(vector);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructureIDTablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StructureIDTable.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StructureIDTable.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/StructureIDTable.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -88,6 +88,7 @@
</span><span class="cx">         StructureID result = m_size;
</span><span class="cx">         table()[result] = newEntry;
</span><span class="cx">         m_size++;
</span><ins>+        ASSERT(!isNuked(result));
</ins><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -96,8 +97,10 @@
</span><span class="cx">     StructureID result = m_firstFreeOffset;
</span><span class="cx">     m_firstFreeOffset = table()[m_firstFreeOffset].offset;
</span><span class="cx">     table()[result].structure = structure;
</span><ins>+    ASSERT(!isNuked(result));
</ins><span class="cx">     return result;
</span><span class="cx"> #else
</span><ins>+    ASSERT(!isNuked(structure));
</ins><span class="cx">     return structure;
</span><span class="cx"> #endif
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructureIDTableh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StructureIDTable.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StructureIDTable.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/StructureIDTable.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -34,8 +34,48 @@
</span><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx"> typedef uint32_t StructureID;
</span><ins>+
+inline StructureID nukedStructureIDBit()
+{
+    return 0x80000000u;
+}
+
+inline StructureID nuke(StructureID id)
+{
+    return id | nukedStructureIDBit();
+}
+
+inline bool isNuked(StructureID id)
+{
+    return !!(id &amp; nukedStructureIDBit());
+}
+
+inline StructureID decontaminate(StructureID id)
+{
+    return id &amp; ~nukedStructureIDBit();
+}
</ins><span class="cx"> #else
</span><span class="cx"> typedef Structure* StructureID;
</span><ins>+
+inline StructureID nukedStructureIDBit()
+{
+    return bitwise_cast&lt;StructureID&gt;(static_cast&lt;uintptr_t&gt;(1));
+}
+
+inline StructureID nuke(StructureID id)
+{
+    return bitwise_cast&lt;StructureID&gt;(bitwise_cast&lt;uintptr_t&gt;(id) | bitwise_cast&lt;uintptr_t&gt;(nukedStructureIDBit()));
+}
+
+inline bool isNuked(StructureID id)
+{
+    return !!(bitwise_cast&lt;uintptr_t&gt;(id) &amp; bitwise_cast&lt;uintptr_t&gt;(nukedStructureIDBit()));
+}
+
+inline StructureID decontaminate(StructureID id)
+{
+    return bitwise_cast&lt;StructureID&gt;(bitwise_cast&lt;uintptr_t&gt;(id) &amp; ~bitwise_cast&lt;uintptr_t&gt;(nukedStructureIDBit()));
+}
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> class StructureIDTable {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructureInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StructureInlines.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StructureInlines.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/StructureInlines.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -146,7 +146,7 @@
</span><span class="cx">     if (hasIndexedProperties(indexingType()))
</span><span class="cx">         return true;
</span><span class="cx">     
</span><del>-    if (!isTypedView(m_classInfo-&gt;typedArrayStorageType))
</del><ins>+    if (!isTypedView(typedArrayTypeForType(m_blob.type())))
</ins><span class="cx">         return false;
</span><span class="cx">     
</span><span class="cx">     return jsCast&lt;const JSArrayBufferView*&gt;(cell)-&gt;mode() == WastefulTypedArray;
</span><span class="lines">@@ -307,9 +307,9 @@
</span><span class="cx">     PropertyOffset newLastOffset = m_offset;
</span><span class="cx">     table-&gt;add(PropertyMapEntry(rep, newOffset, attributes), newLastOffset, PropertyTable::PropertyOffsetMayChange);
</span><span class="cx">     
</span><del>-    func(locker, newOffset, outOfLineCapacity(newLastOffset));
-    vm.heap.mutatorFence();
-    m_offset = newLastOffset;
</del><ins>+    func(locker, newOffset, newLastOffset);
+    
+    ASSERT(m_offset == newLastOffset);
</ins><span class="cx"> 
</span><span class="cx">     checkConsistency();
</span><span class="cx">     return newOffset;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -454,7 +454,7 @@
</span><span class="cx">         // And if we've previously compiled any functions, we need to revert
</span><span class="cx">         // them because they don't have the needed polling checks for the watchdog
</span><span class="cx">         // yet.
</span><del>-        deleteAllCode();
</del><ins>+        deleteAllCode(PreventCollectionAndDeleteAllCode);
</ins><span class="cx">     }
</span><span class="cx">     return *m_watchdog;
</span><span class="cx"> }
</span><span class="lines">@@ -561,20 +561,20 @@
</span><span class="cx">     entryScope-&gt;addDidPopListener(callback);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void VM::deleteAllLinkedCode()
</del><ins>+void VM::deleteAllLinkedCode(DeleteAllCodeEffort effort)
</ins><span class="cx"> {
</span><del>-    whenIdle([this]() {
-        heap.deleteAllCodeBlocks();
</del><ins>+    whenIdle([=] () {
+        heap.deleteAllCodeBlocks(effort);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void VM::deleteAllCode()
</del><ins>+void VM::deleteAllCode(DeleteAllCodeEffort effort)
</ins><span class="cx"> {
</span><del>-    whenIdle([this]() {
</del><ins>+    whenIdle([=] () {
</ins><span class="cx">         m_codeCache-&gt;clear();
</span><span class="cx">         m_regExpCache-&gt;deleteAllCode();
</span><del>-        heap.deleteAllCodeBlocks();
-        heap.deleteAllUnlinkedCodeBlocks();
</del><ins>+        heap.deleteAllCodeBlocks(effort);
+        heap.deleteAllUnlinkedCodeBlocks(effort);
</ins><span class="cx">         heap.reportAbandonedObjectGraph();
</span><span class="cx">     });
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #include &quot;ConcurrentJSLock.h&quot;
</span><span class="cx"> #include &quot;ControlFlowProfiler.h&quot;
</span><span class="cx"> #include &quot;DateInstanceCache.h&quot;
</span><ins>+#include &quot;DeleteAllCodeEffort.h&quot;
</ins><span class="cx"> #include &quot;ExceptionEventLocation.h&quot;
</span><span class="cx"> #include &quot;ExecutableAllocator.h&quot;
</span><span class="cx"> #include &quot;FunctionHasExecutedCache.h&quot;
</span><span class="lines">@@ -476,12 +477,17 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    ALWAYS_INLINE Structure* getStructure(StructureID id)
+    {
+        return heap.structureIDTable().get(decontaminate(id));
+    }
+    
</ins><span class="cx">     void* stackPointerAtVMEntry() const { return m_stackPointerAtVMEntry; }
</span><span class="cx">     void setStackPointerAtVMEntry(void*);
</span><span class="cx"> 
</span><span class="cx">     size_t softReservedZoneSize() const { return m_currentSoftReservedZoneSize; }
</span><span class="cx">     size_t updateSoftReservedZoneSize(size_t softReservedZoneSize);
</span><del>-
</del><ins>+    
</ins><span class="cx">     static size_t committedStackByteCount();
</span><span class="cx">     inline bool ensureStackCapacityFor(Register* newTopOfStack);
</span><span class="cx"> 
</span><span class="lines">@@ -601,8 +607,8 @@
</span><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE void whenIdle(std::function&lt;void()&gt;);
</span><span class="cx"> 
</span><del>-    JS_EXPORT_PRIVATE void deleteAllCode();
-    JS_EXPORT_PRIVATE void deleteAllLinkedCode();
</del><ins>+    JS_EXPORT_PRIVATE void deleteAllCode(DeleteAllCodeEffort);
+    JS_EXPORT_PRIVATE void deleteAllLinkedCode(DeleteAllCodeEffort);
</ins><span class="cx"> 
</span><span class="cx">     WatchpointSet* ensureWatchpointSetForImpureProperty(const Identifier&amp;);
</span><span class="cx">     void registerWatchpointForImpureProperty(const Identifier&amp;, Watchpoint*);
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WTF/ChangeLog        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -1,3 +1,42 @@
</span><ins>+2016-12-06  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Concurrent GC should be stable enough to land enabled on X86_64
+        https://bugs.webkit.org/show_bug.cgi?id=164990
+
+        Reviewed by Geoffrey Garen.
+        
+        Adds the ability to say:
+        
+        auto locker = holdLock(any type of lock)
+        
+        Instead of having to say:
+        
+        Locker&lt;LockType&gt; locker(locks of type LockType)
+        
+        I think that we should use &quot;auto locker = holdLock(lock)&quot; as the default way that we acquire
+        locks unless we need to use a special locker type.
+        
+        This also adds the ability to safepoint a lock. Safepointing a lock is basically a super fast
+        way of unlocking it fairly and then immediately relocking it - i.e. letting anyone who is
+        waiting to run without losing steam of there is noone waiting.
+
+        * wtf/Lock.cpp:
+        (WTF::LockBase::safepointSlow):
+        * wtf/Lock.h:
+        (WTF::LockBase::safepoint):
+        * wtf/LockAlgorithm.h:
+        (WTF::LockAlgorithm::safepointFast):
+        (WTF::LockAlgorithm::safepoint):
+        (WTF::LockAlgorithm::safepointSlow):
+        * wtf/Locker.h:
+        (WTF::AbstractLocker::AbstractLocker):
+        (WTF::Locker::tryLock):
+        (WTF::Locker::operator bool):
+        (WTF::Locker::Locker):
+        (WTF::Locker::operator=):
+        (WTF::holdLock):
+        (WTF::tryHoldLock):
+
</ins><span class="cx"> 2016-12-08  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r209489.
</span></span></pre></div>
<a id="trunkSourceWTFwtfLockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Lock.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Lock.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WTF/wtf/Lock.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -43,5 +43,10 @@
</span><span class="cx">     DefaultLockAlgorithm::unlockSlow(m_byte, DefaultLockAlgorithm::Fair);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void LockBase::safepointSlow()
+{
+    DefaultLockAlgorithm::safepointSlow(m_byte);
+}
+
</ins><span class="cx"> } // namespace WTF
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWTFwtfLockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Lock.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Lock.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WTF/wtf/Lock.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -93,6 +93,12 @@
</span><span class="cx">         if (UNLIKELY(!DefaultLockAlgorithm::unlockFastAssumingZero(m_byte)))
</span><span class="cx">             unlockFairlySlow();
</span><span class="cx">     }
</span><ins>+    
+    void safepoint()
+    {
+        if (UNLIKELY(!DefaultLockAlgorithm::safepointFast(m_byte)))
+            safepointSlow();
+    }
</ins><span class="cx"> 
</span><span class="cx">     bool isHeld() const
</span><span class="cx">     {
</span><span class="lines">@@ -113,6 +119,7 @@
</span><span class="cx">     WTF_EXPORT_PRIVATE void lockSlow();
</span><span class="cx">     WTF_EXPORT_PRIVATE void unlockSlow();
</span><span class="cx">     WTF_EXPORT_PRIVATE void unlockFairlySlow();
</span><ins>+    WTF_EXPORT_PRIVATE void safepointSlow();
</ins><span class="cx"> 
</span><span class="cx">     // Method used for testing only.
</span><span class="cx">     bool isFullyReset() const
</span></span></pre></div>
<a id="trunkSourceWTFwtfLockAlgorithmh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/LockAlgorithm.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/LockAlgorithm.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WTF/wtf/LockAlgorithm.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -98,6 +98,18 @@
</span><span class="cx">             unlockSlow(lock, Fair);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    static bool safepointFast(const Atomic&lt;LockType&gt;&amp; lock)
+    {
+        WTF::compilerFence();
+        return !(lock.load(std::memory_order_relaxed) &amp; hasParkedBit);
+    }
+    
+    static void safepoint(Atomic&lt;LockType&gt;&amp; lock)
+    {
+        if (UNLIKELY(!safepointFast(lock)))
+            safepointSlow(lock);
+    }
+    
</ins><span class="cx">     static bool isLocked(const Atomic&lt;LockType&gt;&amp; lock)
</span><span class="cx">     {
</span><span class="cx">         return lock.load(std::memory_order_acquire) &amp; isHeldBit;
</span><span class="lines">@@ -205,6 +217,12 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    NEVER_INLINE static void safepointSlow(Atomic&lt;LockType&gt;&amp; lockWord)
+    {
+        unlockFairly(lockWord);
+        lock(lockWord);
+    }
+    
</ins><span class="cx"> private:
</span><span class="cx">     enum Token {
</span><span class="cx">         BargingOpportunity,
</span></span></pre></div>
<a id="trunkSourceWTFwtfLockerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Locker.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Locker.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WTF/wtf/Locker.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -35,9 +35,21 @@
</span><span class="cx"> 
</span><span class="cx"> enum NoLockingNecessaryTag { NoLockingNecessary };
</span><span class="cx"> 
</span><del>-template &lt;typename T&gt; class Locker {
-    WTF_MAKE_NONCOPYABLE(Locker);
</del><ins>+class AbstractLocker {
+    WTF_MAKE_NONCOPYABLE(AbstractLocker);
</ins><span class="cx"> public:
</span><ins>+    AbstractLocker(NoLockingNecessaryTag)
+    {
+    }
+    
+protected:
+    AbstractLocker()
+    {
+    }
+};
+
+template &lt;typename T&gt; class Locker : public AbstractLocker {
+public:
</ins><span class="cx">     explicit Locker(T&amp; lockable) : m_lockable(&amp;lockable) { lock(); }
</span><span class="cx">     explicit Locker(T* lockable) : m_lockable(lockable) { lock(); }
</span><span class="cx"> 
</span><span class="lines">@@ -56,11 +68,41 @@
</span><span class="cx">             m_lockable-&gt;unlock();
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    static Locker tryLock(T&amp; lockable)
+    {
+        Locker result(NoLockingNecessary);
+        if (lockable.tryLock()) {
+            result.m_lockable = &amp;lockable;
+            return result;
+        }
+        return result;
+    }
+    
+    explicit operator bool() const { return !!m_lockable; }
+    
</ins><span class="cx">     void unlockEarly()
</span><span class="cx">     {
</span><span class="cx">         m_lockable-&gt;unlock();
</span><span class="cx">         m_lockable = 0;
</span><span class="cx">     }
</span><ins>+    
+    // It's great to be able to pass lockers around. It enables custom locking adaptors like
+    // JSC::LockDuringMarking.
+    Locker(Locker&amp;&amp; other)
+        : m_lockable(other.m_lockable)
+    {
+        other.m_lockable = nullptr;
+    }
+    
+    Locker&amp; operator=(Locker&amp;&amp; other)
+    {
+        if (m_lockable)
+            m_lockable-&gt;unlock();
+        m_lockable = other.m_lockable;
+        other.m_lockable = nullptr;
+        return *this;
+    }
+    
</ins><span class="cx"> private:
</span><span class="cx">     void lock()
</span><span class="cx">     {
</span><span class="lines">@@ -71,10 +113,26 @@
</span><span class="cx">     T* m_lockable;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+// Use this lock scope like so:
+// auto locker = holdLock(lock);
+template&lt;typename LockType&gt;
+Locker&lt;LockType&gt; holdLock(LockType&amp; lock)
+{
+    return Locker&lt;LockType&gt;(lock);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename LockType&gt;
+Locker&lt;LockType&gt; tryHoldLock(LockType&amp; lock)
+{
+    return Locker&lt;LockType&gt;::tryLock(lock);
+}
+
+}
+
+using WTF::AbstractLocker;
</ins><span class="cx"> using WTF::Locker;
</span><span class="cx"> using WTF::NoLockingNecessaryTag;
</span><span class="cx"> using WTF::NoLockingNecessary;
</span><ins>+using WTF::holdLock;
</ins><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebCore/ChangeLog        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -1,3 +1,60 @@
</span><ins>+2016-12-06  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Concurrent GC should be stable enough to land enabled on X86_64
+        https://bugs.webkit.org/show_bug.cgi?id=164990
+
+        Reviewed by Geoffrey Garen.
+        
+        Made WebCore down with concurrent marking by adding some locking and adapting to some new API.
+
+        This has new test modes in run-sjc-stress-tests. Also, the way that LayoutTests run is already
+        a fantastic GC test.
+
+        * ForwardingHeaders/heap/DeleteAllCodeEffort.h: Added.
+        * ForwardingHeaders/heap/LockDuringMarking.h: Added.
+        * bindings/js/GCController.cpp:
+        (WebCore::GCController::deleteAllCode):
+        (WebCore::GCController::deleteAllLinkedCode):
+        * bindings/js/GCController.h:
+        * bindings/js/JSDOMBinding.cpp:
+        (WebCore::getCachedDOMStructure):
+        (WebCore::cacheDOMStructure):
+        * bindings/js/JSDOMGlobalObject.cpp:
+        (WebCore::JSDOMGlobalObject::addBuiltinGlobals):
+        (WebCore::JSDOMGlobalObject::visitChildren):
+        * bindings/js/JSDOMGlobalObject.h:
+        (WebCore::getDOMConstructor):
+        * bindings/js/JSDOMPromise.cpp:
+        (WebCore::DeferredPromise::DeferredPromise):
+        (WebCore::DeferredPromise::clear):
+        * bindings/js/JSXPathResultCustom.cpp:
+        (WebCore::JSXPathResult::visitAdditionalChildren):
+        * dom/EventListenerMap.cpp:
+        (WebCore::EventListenerMap::clear):
+        (WebCore::EventListenerMap::replace):
+        (WebCore::EventListenerMap::add):
+        (WebCore::EventListenerMap::remove):
+        (WebCore::EventListenerMap::find):
+        (WebCore::EventListenerMap::removeFirstEventListenerCreatedFromMarkup):
+        (WebCore::EventListenerMap::copyEventListenersNotCreatedFromMarkupToTarget):
+        (WebCore::EventListenerIterator::EventListenerIterator):
+        * dom/EventListenerMap.h:
+        (WebCore::EventListenerMap::lock):
+        * dom/EventTarget.cpp:
+        (WebCore::EventTarget::visitJSEventListeners):
+        * dom/EventTarget.h:
+        (WebCore::EventTarget::visitJSEventListeners): Deleted.
+        * dom/Node.cpp:
+        (WebCore::Node::eventTargetDataConcurrently):
+        (WebCore::Node::ensureEventTargetData):
+        (WebCore::Node::clearEventTargetData):
+        * dom/Node.h:
+        * page/MemoryRelease.cpp:
+        (WebCore::releaseCriticalMemory):
+        * page/cocoa/MemoryReleaseCocoa.mm:
+        (WebCore::jettisonExpensiveObjectsOnTopLevelNavigation):
+        (WebCore::registerMemoryReleaseNotifyCallbacks):
+
</ins><span class="cx"> 2016-12-08  Dave Hyatt  &lt;hyatt@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [CSS Parser] Add strict checking for right parens to selector functions like :matches, :not etc.
</span></span></pre></div>
<a id="trunkSourceWebCoreForwardingHeadersheapDeleteAllCodeEfforth"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/ForwardingHeaders/heap/DeleteAllCodeEffort.h (0 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ForwardingHeaders/heap/DeleteAllCodeEffort.h                                (rev 0)
+++ trunk/Source/WebCore/ForwardingHeaders/heap/DeleteAllCodeEffort.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+#ifndef WebCore_FWD_DeleteAllCodeEffort_h
+#define WebCore_FWD_DeleteAllCodeEffort_h
+#include &lt;JavaScriptCore/DeleteAllCodeEffort.h&gt;
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebCoreForwardingHeadersheapLockDuringMarkingh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/ForwardingHeaders/heap/LockDuringMarking.h (0 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ForwardingHeaders/heap/LockDuringMarking.h                                (rev 0)
+++ trunk/Source/WebCore/ForwardingHeaders/heap/LockDuringMarking.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+#ifndef WebCore_FWD_LockDuringMarking_h
+#define WebCore_FWD_LockDuringMarking_h
+#include &lt;JavaScriptCore/LockDuringMarking.h&gt;
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebCorebindingsjsGCControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/GCController.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/GCController.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebCore/bindings/js/GCController.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -116,16 +116,16 @@
</span><span class="cx">     JSDOMWindow::commonVM().heap.setGarbageCollectionTimerEnabled(enable);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void GCController::deleteAllCode()
</del><ins>+void GCController::deleteAllCode(DeleteAllCodeEffort effort)
</ins><span class="cx"> {
</span><span class="cx">     JSLockHolder lock(JSDOMWindow::commonVM());
</span><del>-    JSDOMWindow::commonVM().deleteAllCode();
</del><ins>+    JSDOMWindow::commonVM().deleteAllCode(effort);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void GCController::deleteAllLinkedCode()
</del><ins>+void GCController::deleteAllLinkedCode(DeleteAllCodeEffort effort)
</ins><span class="cx"> {
</span><span class="cx">     JSLockHolder lock(JSDOMWindow::commonVM());
</span><del>-    JSDOMWindow::commonVM().deleteAllLinkedCode();
</del><ins>+    JSDOMWindow::commonVM().deleteAllLinkedCode(effort);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsGCControllerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/GCController.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/GCController.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebCore/bindings/js/GCController.h        2016-12-08 22:14:50 UTC (rev 209570)
</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 &lt;heap/DeleteAllCodeEffort.h&gt;
</ins><span class="cx"> #include &lt;wtf/Forward.h&gt;
</span><span class="cx"> #include &lt;wtf/Noncopyable.h&gt;
</span><span class="cx"> #include &quot;Timer.h&quot;
</span><span class="lines">@@ -44,8 +45,8 @@
</span><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT void garbageCollectOnAlternateThreadForDebugging(bool waitUntilDone); // Used for stress testing.
</span><span class="cx">     WEBCORE_EXPORT void setJavaScriptGarbageCollectorTimerEnabled(bool);
</span><del>-    WEBCORE_EXPORT void deleteAllCode();
-    WEBCORE_EXPORT void deleteAllLinkedCode();
</del><ins>+    WEBCORE_EXPORT void deleteAllCode(JSC::DeleteAllCodeEffort);
+    WEBCORE_EXPORT void deleteAllLinkedCode(JSC::DeleteAllCodeEffort);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     GCController(); // Use singleton() instead.
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMBindingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -418,13 +418,14 @@
</span><span class="cx"> 
</span><span class="cx"> Structure* getCachedDOMStructure(JSDOMGlobalObject&amp; globalObject, const ClassInfo* classInfo)
</span><span class="cx"> {
</span><del>-    JSDOMStructureMap&amp; structures = globalObject.structures();
</del><ins>+    JSDOMStructureMap&amp; structures = globalObject.structures(NoLockingNecessary);
</ins><span class="cx">     return structures.get(classInfo).get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Structure* cacheDOMStructure(JSDOMGlobalObject&amp; globalObject, Structure* structure, const ClassInfo* classInfo)
</span><span class="cx"> {
</span><del>-    JSDOMStructureMap&amp; structures = globalObject.structures();
</del><ins>+    auto locker = lockDuringMarking(globalObject.vm().heap, globalObject.gcLock());
+    JSDOMStructureMap&amp; structures = globalObject.structures(locker);
</ins><span class="cx">     ASSERT(!structures.contains(classInfo));
</span><span class="cx">     return structures.set(classInfo, WriteBarrier&lt;Structure&gt;(globalObject.vm(), &amp;globalObject, structure)).iterator-&gt;value.get();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMGlobalObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -110,18 +110,21 @@
</span><span class="cx"> #endif
</span><span class="cx">     JSObject* privateReadableStreamDefaultReaderConstructor = createReadableStreamDefaultReaderPrivateConstructor(vm, *this);
</span><span class="cx"> 
</span><del>-    ASSERT(!constructors().get(privateReadableStreamDefaultControllerConstructor-&gt;info()).get());
</del><ins>+    ASSERT(!constructors(NoLockingNecessary).get(privateReadableStreamDefaultControllerConstructor-&gt;info()).get());
</ins><span class="cx"> #if ENABLE(READABLE_BYTE_STREAM_API)
</span><del>-    ASSERT(!constructors().get(privateReadableByteStreamControllerConstructor-&gt;info()).get());
</del><ins>+    ASSERT(!constructors(NoLockingNecessary).get(privateReadableByteStreamControllerConstructor-&gt;info()).get());
</ins><span class="cx"> #endif
</span><del>-    ASSERT(!constructors().get(privateReadableStreamDefaultReaderConstructor-&gt;info()).get());
</del><ins>+    ASSERT(!constructors(NoLockingNecessary).get(privateReadableStreamDefaultReaderConstructor-&gt;info()).get());
</ins><span class="cx">     JSC::WriteBarrier&lt;JSC::JSObject&gt; temp;
</span><del>-    constructors().add(privateReadableStreamDefaultControllerConstructor-&gt;info(), temp).iterator-&gt;value.set(vm, this, privateReadableStreamDefaultControllerConstructor);
</del><ins>+    {
+        auto locker = lockDuringMarking(vm.heap, m_gcLock);
+        constructors(locker).add(privateReadableStreamDefaultControllerConstructor-&gt;info(), temp).iterator-&gt;value.set(vm, this, privateReadableStreamDefaultControllerConstructor);
</ins><span class="cx"> #if ENABLE(READABLE_BYTE_STREAM_API)
</span><del>-    constructors().add(privateReadableByteStreamControllerConstructor-&gt;info(), temp).iterator-&gt;value.set(vm, this, privateReadableByteStreamControllerConstructor);
</del><ins>+        constructors(locker).add(privateReadableByteStreamControllerConstructor-&gt;info(), temp).iterator-&gt;value.set(vm, this, privateReadableByteStreamControllerConstructor);
</ins><span class="cx"> #endif
</span><del>-    constructors().add(privateReadableStreamDefaultReaderConstructor-&gt;info(), temp).iterator-&gt;value.set(vm, this, privateReadableStreamDefaultReaderConstructor);
</del><ins>+        constructors(locker).add(privateReadableStreamDefaultReaderConstructor-&gt;info(), temp).iterator-&gt;value.set(vm, this, privateReadableStreamDefaultReaderConstructor);
</ins><span class="cx"> #endif
</span><ins>+    }
</ins><span class="cx">     JSVMClientData&amp; clientData = *static_cast&lt;JSVMClientData*&gt;(vm.clientData);
</span><span class="cx">     JSDOMGlobalObject::GlobalPropertyInfo staticGlobals[] = {
</span><span class="cx">         JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().makeThisTypeErrorPrivateName(),
</span><span class="lines">@@ -183,16 +186,20 @@
</span><span class="cx">     JSDOMGlobalObject* thisObject = jsCast&lt;JSDOMGlobalObject*&gt;(cell);
</span><span class="cx">     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
</span><span class="cx">     Base::visitChildren(thisObject, visitor);
</span><ins>+    
+    {
+        auto locker = holdLock(thisObject-&gt;m_gcLock);
+        
+        for (auto&amp; structure : thisObject-&gt;structures(locker).values())
+            visitor.append(&amp;structure);
+        
+        for (auto&amp; constructor : thisObject-&gt;constructors(locker).values())
+            visitor.append(&amp;constructor);
+        
+        for (auto&amp; deferredPromise : thisObject-&gt;deferredPromises(locker))
+            deferredPromise-&gt;visitAggregate(visitor);
+    }
</ins><span class="cx"> 
</span><del>-    for (auto&amp; structure : thisObject-&gt;structures().values())
-        visitor.append(&amp;structure);
-
-    for (auto&amp; constructor : thisObject-&gt;constructors().values())
-        visitor.append(&amp;constructor);
-
-    for (auto&amp; deferredPromise : thisObject-&gt;deferredPromises())
-        deferredPromise-&gt;visitAggregate(visitor);
-
</del><span class="cx">     thisObject-&gt;m_builtinInternalFunctions.visit(visitor);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMGlobalObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;PlatformExportMacros.h&quot;
</span><span class="cx"> #include &quot;WebCoreJSBuiltinInternals.h&quot;
</span><ins>+#include &lt;heap/LockDuringMarking.h&gt;
</ins><span class="cx"> #include &lt;runtime/JSGlobalObject.h&gt;
</span><span class="cx"> #include &lt;runtime/StructureInlines.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -54,10 +55,12 @@
</span><span class="cx">         void finishCreation(JSC::VM&amp;, JSC::JSObject*);
</span><span class="cx"> 
</span><span class="cx">     public:
</span><del>-        JSDOMStructureMap&amp; structures() { return m_structures; }
-        JSDOMConstructorMap&amp; constructors() { return m_constructors; }
</del><ins>+        Lock&amp; gcLock() { return m_gcLock; }
+        
+        JSDOMStructureMap&amp; structures(const AbstractLocker&amp;) { return m_structures; }
+        JSDOMConstructorMap&amp; constructors(const AbstractLocker&amp;) { return m_constructors; }
</ins><span class="cx"> 
</span><del>-        DeferredPromiseSet&amp; deferredPromises() { return m_deferredPromises; }
</del><ins>+        DeferredPromiseSet&amp; deferredPromises(const AbstractLocker&amp;) { return m_deferredPromises; }
</ins><span class="cx"> 
</span><span class="cx">         ScriptExecutionContext* scriptExecutionContext() const;
</span><span class="cx"> 
</span><span class="lines">@@ -96,6 +99,7 @@
</span><span class="cx">         Event* m_currentEvent;
</span><span class="cx">         Ref&lt;DOMWrapperWorld&gt; m_world;
</span><span class="cx">         uint8_t m_worldIsNormal;
</span><ins>+        Lock m_gcLock;
</ins><span class="cx"> 
</span><span class="cx">     private:
</span><span class="cx">         void addBuiltinGlobals(JSC::VM&amp;);
</span><span class="lines">@@ -107,12 +111,14 @@
</span><span class="cx">     template&lt;class ConstructorClass&gt;
</span><span class="cx">     inline JSC::JSObject* getDOMConstructor(JSC::VM&amp; vm, const JSDOMGlobalObject&amp; globalObject)
</span><span class="cx">     {
</span><del>-        if (JSC::JSObject* constructor = const_cast&lt;JSDOMGlobalObject&amp;&gt;(globalObject).constructors().get(ConstructorClass::info()).get())
</del><ins>+        if (JSC::JSObject* constructor = const_cast&lt;JSDOMGlobalObject&amp;&gt;(globalObject).constructors(NoLockingNecessary).get(ConstructorClass::info()).get())
</ins><span class="cx">             return constructor;
</span><span class="cx">         JSC::JSObject* constructor = ConstructorClass::create(vm, ConstructorClass::createStructure(vm, const_cast&lt;JSDOMGlobalObject&amp;&gt;(globalObject), ConstructorClass::prototypeForStructure(vm, globalObject)), const_cast&lt;JSDOMGlobalObject&amp;&gt;(globalObject));
</span><del>-        ASSERT(!const_cast&lt;JSDOMGlobalObject&amp;&gt;(globalObject).constructors().contains(ConstructorClass::info()));
</del><ins>+        ASSERT(!const_cast&lt;JSDOMGlobalObject&amp;&gt;(globalObject).constructors(NoLockingNecessary).contains(ConstructorClass::info()));
</ins><span class="cx">         JSC::WriteBarrier&lt;JSC::JSObject&gt; temp;
</span><del>-        const_cast&lt;JSDOMGlobalObject&amp;&gt;(globalObject).constructors().add(ConstructorClass::info(), temp).iterator-&gt;value.set(vm, &amp;globalObject, constructor);
</del><ins>+        JSDOMGlobalObject&amp; mutableGlobalObject = const_cast&lt;JSDOMGlobalObject&amp;&gt;(globalObject);
+        auto locker = JSC::lockDuringMarking(vm.heap, mutableGlobalObject.gcLock());
+        mutableGlobalObject.constructors(locker).add(ConstructorClass::info(), temp).iterator-&gt;value.set(vm, &amp;globalObject, constructor);
</ins><span class="cx">         return constructor;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMPromisecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -43,8 +43,9 @@
</span><span class="cx">     , m_deferred(&amp;promiseDeferred)
</span><span class="cx">     , m_globalObject(&amp;globalObject)
</span><span class="cx"> {
</span><ins>+    auto locker = lockDuringMarking(globalObject.vm().heap, globalObject.gcLock());
</ins><span class="cx">     globalObject.vm().heap.writeBarrier(&amp;globalObject, &amp;promiseDeferred);
</span><del>-    globalObject.deferredPromises().add(this);
</del><ins>+    globalObject.deferredPromises(locker).add(this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> DeferredPromise::~DeferredPromise()
</span><span class="lines">@@ -55,8 +56,10 @@
</span><span class="cx"> void DeferredPromise::clear()
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!m_deferred || m_globalObject);
</span><del>-    if (m_deferred &amp;&amp; m_globalObject)
-        m_globalObject-&gt;deferredPromises().remove(this);
</del><ins>+    if (m_deferred &amp;&amp; m_globalObject) {
+        auto locker = lockDuringMarking(m_globalObject-&gt;vm().heap, m_globalObject-&gt;gcLock());
+        m_globalObject-&gt;deferredPromises(locker).remove(this);
+    }
</ins><span class="cx">     m_deferred.clear();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSTextTrackCueCustomcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSTextTrackCueCustom.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSTextTrackCueCustom.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebCore/bindings/js/JSTextTrackCueCustom.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -48,10 +48,6 @@
</span><span class="cx">     if (textTrackCue.isFiringEventListeners())
</span><span class="cx">         return true;
</span><span class="cx"> 
</span><del>-    // If the cue has no event listeners and has no custom properties, it is not reachable.
-    if (!textTrackCue.hasEventListeners() &amp;&amp; !jsTextTrackCue-&gt;hasCustomProperties())
-        return false;
-
</del><span class="cx">     // If the cue is not associated with a track, it is not reachable.
</span><span class="cx">     if (!textTrackCue.track())
</span><span class="cx">         return false;
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSXPathResultCustomcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSXPathResultCustom.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSXPathResultCustom.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebCore/bindings/js/JSXPathResultCustom.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx"> {
</span><span class="cx">     auto&amp; value = wrapped().value();
</span><span class="cx">     if (value.isNodeSet()) {
</span><ins>+        // FIXME: This looks like it might race, but I'm not sure.
</ins><span class="cx">         for (auto&amp; node : value.toNodeSet())
</span><span class="cx">             visitor.addOpaqueRoot(root(node.get()));
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceWebCoredomEventListenerMapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/EventListenerMap.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/EventListenerMap.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebCore/dom/EventListenerMap.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -82,6 +82,8 @@
</span><span class="cx"> 
</span><span class="cx"> void EventListenerMap::clear()
</span><span class="cx"> {
</span><ins>+    auto locker = holdLock(m_lock);
+    
</ins><span class="cx">     assertNoActiveIterators();
</span><span class="cx"> 
</span><span class="cx">     m_entries.clear();
</span><span class="lines">@@ -110,6 +112,8 @@
</span><span class="cx"> 
</span><span class="cx"> void EventListenerMap::replace(const AtomicString&amp; eventType, EventListener&amp; oldListener, Ref&lt;EventListener&gt;&amp;&amp; newListener, const RegisteredEventListener::Options&amp; options)
</span><span class="cx"> {
</span><ins>+    auto locker = holdLock(m_lock);
+    
</ins><span class="cx">     assertNoActiveIterators();
</span><span class="cx"> 
</span><span class="cx">     auto* listeners = find(eventType);
</span><span class="lines">@@ -123,6 +127,8 @@
</span><span class="cx"> 
</span><span class="cx"> bool EventListenerMap::add(const AtomicString&amp; eventType, Ref&lt;EventListener&gt;&amp;&amp; listener, const RegisteredEventListener::Options&amp; options)
</span><span class="cx"> {
</span><ins>+    auto locker = holdLock(m_lock);
+    
</ins><span class="cx">     assertNoActiveIterators();
</span><span class="cx"> 
</span><span class="cx">     if (auto* listeners = find(eventType)) {
</span><span class="lines">@@ -151,6 +157,8 @@
</span><span class="cx"> 
</span><span class="cx"> bool EventListenerMap::remove(const AtomicString&amp; eventType, EventListener&amp; listener, bool useCapture)
</span><span class="cx"> {
</span><ins>+    auto locker = holdLock(m_lock);
+    
</ins><span class="cx">     assertNoActiveIterators();
</span><span class="cx"> 
</span><span class="cx">     for (unsigned i = 0; i &lt; m_entries.size(); ++i) {
</span><span class="lines">@@ -167,8 +175,6 @@
</span><span class="cx"> 
</span><span class="cx"> EventListenerVector* EventListenerMap::find(const AtomicString&amp; eventType) const
</span><span class="cx"> {
</span><del>-    assertNoActiveIterators();
-
</del><span class="cx">     for (auto&amp; entry : m_entries) {
</span><span class="cx">         if (entry.first == eventType)
</span><span class="cx">             return entry.second.get();
</span><span class="lines">@@ -191,6 +197,8 @@
</span><span class="cx"> 
</span><span class="cx"> void EventListenerMap::removeFirstEventListenerCreatedFromMarkup(const AtomicString&amp; eventType)
</span><span class="cx"> {
</span><ins>+    auto locker = holdLock(m_lock);
+    
</ins><span class="cx">     assertNoActiveIterators();
</span><span class="cx"> 
</span><span class="cx">     for (unsigned i = 0; i &lt; m_entries.size(); ++i) {
</span><span class="lines">@@ -215,8 +223,6 @@
</span><span class="cx"> 
</span><span class="cx"> void EventListenerMap::copyEventListenersNotCreatedFromMarkupToTarget(EventTarget* target)
</span><span class="cx"> {
</span><del>-    assertNoActiveIterators();
-
</del><span class="cx">     for (auto&amp; entry : m_entries)
</span><span class="cx">         copyListenersNotCreatedFromMarkupToTarget(entry.first, *entry.second, target);
</span><span class="cx"> }
</span><span class="lines">@@ -236,7 +242,16 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+EventListenerIterator::EventListenerIterator(EventListenerMap* map)
+{
+    m_map = map;
+
</ins><span class="cx"> #ifndef NDEBUG
</span><ins>+    m_map-&gt;m_activeIteratorCount++;
+#endif
+}
+
+#ifndef NDEBUG
</ins><span class="cx"> EventListenerIterator::~EventListenerIterator()
</span><span class="cx"> {
</span><span class="cx">     if (m_map)
</span></span></pre></div>
<a id="trunkSourceWebCoredomEventListenerMaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/EventListenerMap.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/EventListenerMap.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebCore/dom/EventListenerMap.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> #include &lt;atomic&gt;
</span><span class="cx"> #include &lt;memory&gt;
</span><span class="cx"> #include &lt;wtf/Forward.h&gt;
</span><ins>+#include &lt;wtf/Lock.h&gt;
</ins><span class="cx"> #include &lt;wtf/text/AtomicString.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -63,6 +64,8 @@
</span><span class="cx"> 
</span><span class="cx">     void removeFirstEventListenerCreatedFromMarkup(const AtomicString&amp; eventType);
</span><span class="cx">     void copyEventListenersNotCreatedFromMarkupToTarget(EventTarget*);
</span><ins>+    
+    Lock&amp; lock() { return m_lock; }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class EventListenerIterator;
</span><span class="lines">@@ -74,6 +77,8 @@
</span><span class="cx"> #ifndef NDEBUG
</span><span class="cx">     std::atomic&lt;int&gt; m_activeIteratorCount { 0 };
</span><span class="cx"> #endif
</span><ins>+
+    Lock m_lock;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class EventListenerIterator {
</span><span class="lines">@@ -80,6 +85,7 @@
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(EventListenerIterator);
</span><span class="cx"> public:
</span><span class="cx">     explicit EventListenerIterator(EventTarget*);
</span><ins>+    explicit EventListenerIterator(EventListenerMap*);
</ins><span class="cx"> #ifndef NDEBUG
</span><span class="cx">     ~EventListenerIterator();
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoredomEventTargetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/EventTarget.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/EventTarget.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebCore/dom/EventTarget.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -274,4 +274,16 @@
</span><span class="cx">     data-&gt;eventListenerMap.clear();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void EventTarget::visitJSEventListeners(JSC::SlotVisitor&amp; visitor)
+{
+    EventTargetData* data = eventTargetDataConcurrently();
+    if (!data)
+        return;
+    
+    auto locker = holdLock(data-&gt;eventListenerMap.lock());
+    EventListenerIterator iterator(&amp;data-&gt;eventListenerMap);
+    while (auto* listener = iterator.nextListener())
+        listener-&gt;visitJSFunction(visitor);
+}
+
</ins><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoredomEventTargeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/EventTarget.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/EventTarget.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebCore/dom/EventTarget.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -123,6 +123,7 @@
</span><span class="cx">     virtual ~EventTarget() = default;
</span><span class="cx">     
</span><span class="cx">     virtual EventTargetData* eventTargetData() = 0;
</span><ins>+    virtual EventTargetData* eventTargetDataConcurrently() = 0;
</ins><span class="cx">     virtual EventTargetData&amp; ensureEventTargetData() = 0;
</span><span class="cx">     const EventTargetData* eventTargetData() const;
</span><span class="cx"> 
</span><span class="lines">@@ -138,6 +139,7 @@
</span><span class="cx"> class EventTargetWithInlineData : public EventTarget {
</span><span class="cx"> protected:
</span><span class="cx">     EventTargetData* eventTargetData() final { return &amp;m_eventTargetData; }
</span><ins>+    EventTargetData* eventTargetDataConcurrently() final { return &amp;m_eventTargetData; }
</ins><span class="cx">     EventTargetData&amp; ensureEventTargetData() final { return m_eventTargetData; }
</span><span class="cx"> private:
</span><span class="cx">     EventTargetData m_eventTargetData;
</span><span class="lines">@@ -148,13 +150,6 @@
</span><span class="cx">     return const_cast&lt;EventTarget*&gt;(this)-&gt;eventTargetData();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void EventTarget::visitJSEventListeners(JSC::SlotVisitor&amp; visitor)
-{
-    EventListenerIterator iterator { this };
-    while (auto* listener = iterator.nextListener())
-        listener-&gt;visitJSFunction(visitor);
-}
-
</del><span class="cx"> inline bool EventTarget::isFiringEventListeners() const
</span><span class="cx"> {
</span><span class="cx">     auto* data = eventTargetData();
</span></span></pre></div>
<a id="trunkSourceWebCoredomNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Node.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Node.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebCore/dom/Node.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -1997,16 +1997,25 @@
</span><span class="cx">     return map;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static StaticLock s_eventTargetDataMapLock;
+
</ins><span class="cx"> EventTargetData* Node::eventTargetData()
</span><span class="cx"> {
</span><span class="cx">     return hasEventTargetData() ? eventTargetDataMap().get(this) : nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+EventTargetData* Node::eventTargetDataConcurrently()
+{
+    auto locker = holdLock(s_eventTargetDataMapLock);
+    return hasEventTargetData() ? eventTargetDataMap().get(this) : nullptr;
+}
+
</ins><span class="cx"> EventTargetData&amp; Node::ensureEventTargetData()
</span><span class="cx"> {
</span><span class="cx">     if (hasEventTargetData())
</span><span class="cx">         return *eventTargetDataMap().get(this);
</span><span class="cx"> 
</span><ins>+    auto locker = holdLock(s_eventTargetDataMapLock);
</ins><span class="cx">     setHasEventTargetData(true);
</span><span class="cx">     return *eventTargetDataMap().add(this, std::make_unique&lt;EventTargetData&gt;()).iterator-&gt;value;
</span><span class="cx"> }
</span><span class="lines">@@ -2013,6 +2022,7 @@
</span><span class="cx"> 
</span><span class="cx"> void Node::clearEventTargetData()
</span><span class="cx"> {
</span><ins>+    auto locker = holdLock(s_eventTargetDataMapLock);
</ins><span class="cx">     eventTargetDataMap().remove(this);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Node.h (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Node.h        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebCore/dom/Node.h        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -530,6 +530,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     EventTargetData* eventTargetData() final;
</span><ins>+    EventTargetData* eventTargetDataConcurrently() final;
</ins><span class="cx">     EventTargetData&amp; ensureEventTargetData() final;
</span><span class="cx"> 
</span><span class="cx">     void getRegisteredMutationObserversOfType(HashMap&lt;MutationObserver*, MutationRecordDeliveryOptions&gt;&amp;, MutationObserver::MutationType, const QualifiedName* attributeName);
</span></span></pre></div>
<a id="trunkSourceWebCorepageMemoryReleasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/MemoryRelease.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/MemoryRelease.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebCore/page/MemoryRelease.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -109,7 +109,7 @@
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="cx">         MemoryPressureHandler::ReliefLogger log(&quot;Discard all JIT-compiled code&quot;);
</span><del>-        GCController::singleton().deleteAllCode();
</del><ins>+        GCController::singleton().deleteAllCode(JSC::DeleteAllCodeIfNotCollecting);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(VIDEO)
</span></span></pre></div>
<a id="trunkSourceWebCorepagecocoaMemoryReleaseCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/cocoa/MemoryReleaseCocoa.mm (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/cocoa/MemoryReleaseCocoa.mm        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebCore/page/cocoa/MemoryReleaseCocoa.mm        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -71,7 +71,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Throw away linked JS code. Linked code is tied to a global object and is not reusable.
</span><span class="cx">     // The immediate memory savings outweigh the cost of recompilation in case we go back again.
</span><del>-    GCController::singleton().deleteAllLinkedCode();
</del><ins>+    GCController::singleton().deleteAllLinkedCode(JSC::DeleteAllCodeIfNotCollecting);
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -84,7 +84,7 @@
</span><span class="cx">             GCController::singleton().garbageCollectNow();
</span><span class="cx">         });
</span><span class="cx">         notify_register_dispatch(&quot;com.apple.WebKit.deleteAllCode&quot;, &amp;dummy, dispatch_get_main_queue(), ^(int) {
</span><del>-            GCController::singleton().deleteAllCode();
</del><ins>+            GCController::singleton().deleteAllCode(JSC::PreventCollectionAndDeleteAllCode);
</ins><span class="cx">             GCController::singleton().garbageCollectNow();
</span><span class="cx">         });
</span><span class="cx">     });
</span></span></pre></div>
<a id="trunkSourceWebKitmacWebViewWebViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/WebView/WebView.mm (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/WebView/WebView.mm        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Source/WebKit/mac/WebView/WebView.mm        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -1749,7 +1749,7 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(WebThreadIsCurrent());
</span><span class="cx">     WebKit::MemoryMeasure measurer(&quot;Memory warning: Discarding JIT'ed code.&quot;);
</span><del>-    WebCore::GCController::singleton().deleteAllCode();
</del><ins>+    WebCore::GCController::singleton().deleteAllCode(PreventCollectionAndDeleteAllCode);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> + (BOOL)isCharacterSmartReplaceExempt:(unichar)character isPreviousCharacter:(BOOL)b
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Tools/ChangeLog        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2016-12-06  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Concurrent GC should be stable enough to land enabled
+        https://bugs.webkit.org/show_bug.cgi?id=164990
+
+        Reviewed by Geoffrey Garen.
+        
+        Add a new mode that runs GC continuously. Also made eager modes run GC continuously.
+        
+        It's clear that this works just fine in release, but I'm still trying to figure out if it's
+        safe for debug. It might be too slow for debug.
+
+        * Scripts/run-jsc-stress-tests:
+
</ins><span class="cx"> 2016-12-08  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Add SPI for sending WebsiteSettings to WebProcess during navigation
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreeTestRunnercpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/TestRunner.cpp (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/TestRunner.cpp        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Tools/DumpRenderTree/TestRunner.cpp        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -42,6 +42,7 @@
</span><span class="cx"> #include &lt;JavaScriptCore/JSObjectRef.h&gt;
</span><span class="cx"> #include &lt;JavaScriptCore/JSRetainPtr.h&gt;
</span><span class="cx"> #include &lt;JavaScriptCore/TypedArrayInlines.h&gt;
</span><ins>+#include &lt;JavaScriptCore/VMInlines.h&gt;
</ins><span class="cx"> #include &lt;WebCore/LogInitialization.h&gt;
</span><span class="cx"> #include &lt;cstring&gt;
</span><span class="cx"> #include &lt;locale.h&gt;
</span></span></pre></div>
<a id="trunkToolsScriptsrunjscstresstests"></a>
<div class="modfile"><h4>Modified: trunk/Tools/Scripts/run-jsc-stress-tests (209569 => 209570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/Scripts/run-jsc-stress-tests        2016-12-08 21:59:02 UTC (rev 209569)
+++ trunk/Tools/Scripts/run-jsc-stress-tests        2016-12-08 22:14:50 UTC (rev 209570)
</span><span class="lines">@@ -117,7 +117,7 @@
</span><span class="cx"> $filter = nil
</span><span class="cx"> $envVars = []
</span><span class="cx"> $quickMode = false
</span><del>-$buildType = &quot;release&quot;
</del><ins>+$buildType = :release
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> def usage
</span><span class="lines">@@ -226,9 +226,9 @@
</span><span class="cx">     when '--quick'
</span><span class="cx">         $quickMode = true
</span><span class="cx">     when '--debug'
</span><del>-        $buildType = &quot;debug&quot;
</del><ins>+        $buildType = :debug
</ins><span class="cx">     when '--release'
</span><del>-        $buildType = &quot;release&quot;
</del><ins>+        $buildType = :release
</ins><span class="cx">     end
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -252,7 +252,7 @@
</span><span class="cx"> unless jscArg
</span><span class="cx">     # If we're not provided a JSC path, try to come up with a sensible JSC path automagically.
</span><span class="cx">     command = SCRIPTS_PATH.join(&quot;webkit-build-directory&quot;).to_s
</span><del>-    command += ($buildType == &quot;release&quot;) ? &quot; --release&quot; : &quot; --debug&quot;
</del><ins>+    command += ($buildType == :release) ? &quot; --release&quot; : &quot; --debug&quot;
</ins><span class="cx">     command += &quot; --executablePath&quot;
</span><span class="cx"> 
</span><span class="cx">     output = `#{command}`.split(&quot;\n&quot;)
</span><span class="lines">@@ -425,6 +425,12 @@
</span><span class="cx"> NO_CJIT_OPTIONS = [&quot;--useConcurrentJIT=false&quot;, &quot;--thresholdForJITAfterWarmUp=100&quot;, &quot;--scribbleFreeCells=true&quot;]
</span><span class="cx"> FTL_OPTIONS = [&quot;--useFTLJIT=true&quot;]
</span><span class="cx"> 
</span><ins>+def shouldCollectContinuously?
+    $buildType == :release
+end
+
+COLLECT_CONTINUOUSLY_OPTIONS = shouldCollectContinuously? ? [&quot;--collectContinuously=true&quot;, &quot;--useGenerationalGC=false&quot;] : []
+
</ins><span class="cx"> $runlist = []
</span><span class="cx"> 
</span><span class="cx"> def frameworkFromJSCPath(jscPath)
</span><span class="lines">@@ -826,6 +832,10 @@
</span><span class="cx">     run(&quot;no-cjit-validate-phases&quot;, &quot;--validateBytecode=true&quot;, &quot;--validateGraphAtEachPhase=true&quot;, &quot;--useSourceProviderCache=false&quot;, *(NO_CJIT_OPTIONS + optionalTestSpecificOptions))
</span><span class="cx"> end
</span><span class="cx"> 
</span><ins>+def runNoCJITCollectContinuously(*optionalTestSpecificOptions)
+    run(&quot;no-cjit-collect-continuously&quot;, *(NO_CJIT_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS + optionalTestSpecificOptions))
+end
+
</ins><span class="cx"> def runDefault(*optionalTestSpecificOptions)
</span><span class="cx">     run(&quot;default&quot;, *(FTL_OPTIONS + optionalTestSpecificOptions))
</span><span class="cx"> end
</span><span class="lines">@@ -851,23 +861,23 @@
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> def runDFGEager(*optionalTestSpecificOptions)
</span><del>-    run(&quot;dfg-eager&quot;, *(EAGER_OPTIONS + optionalTestSpecificOptions))
</del><ins>+    run(&quot;dfg-eager&quot;, *(EAGER_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS + optionalTestSpecificOptions))
</ins><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> def runDFGEagerNoCJITValidate(*optionalTestSpecificOptions)
</span><del>-    run(&quot;dfg-eager-no-cjit-validate&quot;, &quot;--validateGraph=true&quot;, *(NO_CJIT_OPTIONS + EAGER_OPTIONS + optionalTestSpecificOptions))
</del><ins>+    run(&quot;dfg-eager-no-cjit-validate&quot;, &quot;--validateGraph=true&quot;, *(NO_CJIT_OPTIONS + EAGER_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS + optionalTestSpecificOptions))
</ins><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> def runFTLEager(*optionalTestSpecificOptions)
</span><del>-    run(&quot;ftl-eager&quot;, *(FTL_OPTIONS + EAGER_OPTIONS + optionalTestSpecificOptions))
</del><ins>+    run(&quot;ftl-eager&quot;, *(FTL_OPTIONS + EAGER_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS + optionalTestSpecificOptions))
</ins><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> def runFTLEagerNoCJITValidate(*optionalTestSpecificOptions)
</span><del>-    run(&quot;ftl-eager-no-cjit&quot;, &quot;--validateGraph=true&quot;, *(FTL_OPTIONS + NO_CJIT_OPTIONS + EAGER_OPTIONS + optionalTestSpecificOptions))
</del><ins>+    run(&quot;ftl-eager-no-cjit&quot;, &quot;--validateGraph=true&quot;, *(FTL_OPTIONS + NO_CJIT_OPTIONS + EAGER_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS + optionalTestSpecificOptions))
</ins><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> def runFTLEagerNoCJITOSRValidation(*optionalTestSpecificOptions)
</span><del>-    run(&quot;ftl-eager-no-cjit-osr-validation&quot;, &quot;--validateFTLOSRExitLiveness=true&quot;, *(FTL_OPTIONS + NO_CJIT_OPTIONS + EAGER_OPTIONS + optionalTestSpecificOptions))
</del><ins>+    run(&quot;ftl-eager-no-cjit-osr-validation&quot;, &quot;--validateFTLOSRExitLiveness=true&quot;, *(FTL_OPTIONS + NO_CJIT_OPTIONS + EAGER_OPTIONS + COLLECT_CONTINUOUSLY_OPTIONS + optionalTestSpecificOptions))
</ins><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> def runNoCJITNoASO(*optionalTestSpecificOptions)
</span><span class="lines">@@ -906,6 +916,7 @@
</span><span class="cx">         if $jitTests
</span><span class="cx">             runNoLLInt
</span><span class="cx">             runNoCJITValidatePhases
</span><ins>+            runNoCJITCollectContinuously if shouldCollectContinuously?
</ins><span class="cx">             runDFGEager
</span><span class="cx">             runDFGEagerNoCJITValidate
</span><span class="cx">             runDFGMaximalFlushPhase
</span><span class="lines">@@ -930,6 +941,7 @@
</span><span class="cx">         runDefault
</span><span class="cx">         if $jitTests
</span><span class="cx">             runNoCJITValidatePhases
</span><ins>+            runNoCJITCollectContinuously if shouldCollectContinuously?
</ins><span class="cx">             runDFGEager
</span><span class="cx">             runDFGEagerNoCJITValidate
</span><span class="cx">             runDFGMaximalFlushPhase
</span><span class="lines">@@ -982,6 +994,7 @@
</span><span class="cx">     if $jitTests
</span><span class="cx">         runNoLLInt
</span><span class="cx">         runNoCJITValidatePhases
</span><ins>+        runNoCJITCollectContinuously if shouldCollectContinuously?
</ins><span class="cx"> 
</span><span class="cx">         return if !$isFTLPlatform
</span><span class="cx"> 
</span><span class="lines">@@ -996,6 +1009,7 @@
</span><span class="cx">     if $jitTests
</span><span class="cx">         runNoLLInt
</span><span class="cx">         runNoCJITValidatePhases
</span><ins>+        runNoCJITCollectContinuously if shouldCollectContinuously?
</ins><span class="cx">         runDFGEager
</span><span class="cx">         runDFGEagerNoCJITValidate
</span><span class="cx">         runDFGMaximalFlushPhase
</span></span></pre>
</div>
</div>

</body>
</html>