<!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>[150465] branches/dfgFourthTier/Source</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/150465">150465</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2013-05-21 12:10:07 -0700 (Tue, 21 May 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>fourthTier: DFG should be able to run on a separate thread
https://bugs.webkit.org/show_bug.cgi?id=112839

Source/JavaScriptCore: 

Reviewed by Geoffrey Garen.
        
This is the final bit of concurrent JITing. The idea is that there is a
single global worklist, and a single global thread, that does all
optimizing compilation. This is the DFG::Worklist. It contains a queue of
DFG::Plans, and a map from CodeBlock* (the baseline code block we're
trying to optimize) to DFG::Plan. If the DFGDriver tries to concurrently
compile something, it puts the Plan on the Worklist. The Worklist's
thread will compile that Plan eventually, and when it's done, it will
signal its completion by (1) notifying anyone waiting for the Worklist to
be done, and (2) forcing the CodeBlock::m_jitExecuteCounter to take slow
path. The next Baseline JIT cti_optimize call will then install all ready
(i.e. compiled) Plans for that VM. Note that (1) is only for the GC and
VM shutdown, which will want to ensure that there aren't any outstanding
async compilations before proceeding. They do so by simply waiting for
all of the plans for the current VM to complete. (2) is the actual way
that code typically gets installed.
        
This is all very racy by design. For example, just as we try to force the
execute counter to take slow path, the main thread may be setting the
execute counter to some other value. The main thread must set it to
another value because (a) JIT code is constantly incrementing the counter
in a racy way, (b) the cti_optimize slow path will set it to some
large-ish negative value to ensure that cti_optimize isn't called
repeatedly, and (c) OSR exits from previously jettisoned code blocks may
still want to reset the counter values. This &quot;race&quot; is made benign, by
ensuring that while there is an asynchronous compilation, we at worse set
the counter to optimizeAfterWarmUp and never to deferIndefinitely. Hence
if the race happens then the worst case is that we wait another ~1000
counts before installing the optimized code. Another defense is that if
any CodeBlock calls into cti_optimize, then it will check for all ready
plans for the VM - so even if a code block has to wait another ~1000
executions before it calls cti_optimize to do the installation, it may
actually end up being installed sooner because a different code block had
called cti_optimize, potentially for an unrelated reason.
        
Special care is taken to ensure that installing plans informs the GC
about the increased memory usage, but also ensures that we don't recurse
infinitely - since at start of GC we try to install outstanding plans.
This is done by introducing a new GC deferral mechanism (the DeferGC
block-scoped thingy), which will ensure that GCs don't happen in the
scope but are allowed to happen after. This still leaves the strange
corner case that cti_optimize may install outstanding plans, then GC, and
that GC may jettison the code block that was installed. This, and the
fact that the plan that we took slow path to install could have been a
failed or invalid compile, mean that we have to take special precautions
in cti_optimize.
        
This patch also fixes a number of small concurrency bugs that I found
when things started running. There are probably more of those bugs still
left to fix. This patch just fixes the ones I know about.
        
Concurrent compilation is right now only enabled on X86_64 Mac. We need
platforms that are sufficiently CAStastic so that we can do the various
memory fence and CAS tricks that make this safe. We also need a platform
that uses JSVALUE64. And we need pthread_once. So, that pretty much means
just X64_64 for now. Enabling Linux-64_64 should be a breeze, but I'll
leave that up to the Qt and GTK+ ports to do at their discretion.
        
This is a solid speed-up on SunSpider (8-9%) and V8Spider (16%), our two
main compile-time benchmarks. Most peculiarly, this also appears to
reduce measurement noise, rather than increasing it as you would have
expected. I don't understand that result but I like it anyway. On the
other hand, this is a slight (1%) slow-down on V8v7. I will continue to
investigate this but I think that the results are already good enough
that we should land this as-is. So far, it appears that the slow-down is
due to this breaking the don't-compile-inlineables heuristics. See
investigation in https://bugs.webkit.org/show_bug.cgi?id=116556 and the
bug https://bugs.webkit.org/show_bug.cgi?id=116557.

* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC):
(JSC::CodeBlock::finalizeUnconditionally):
(JSC::CodeBlock::resetStubInternal):
(JSC::CodeBlock::baselineVersion):
(JSC::CodeBlock::hasOptimizedReplacement):
(JSC::CodeBlock::optimizationThresholdScalingFactor):
(JSC::CodeBlock::checkIfOptimizationThresholdReached):
(JSC::CodeBlock::optimizeNextInvocation):
(JSC::CodeBlock::dontOptimizeAnytimeSoon):
(JSC::CodeBlock::optimizeAfterWarmUp):
(JSC::CodeBlock::optimizeAfterLongWarmUp):
(JSC::CodeBlock::optimizeSoon):
(JSC::CodeBlock::forceOptimizationSlowPathConcurrently):
(JSC::CodeBlock::setOptimizationThresholdBasedOnCompilationResult):
(JSC::CodeBlock::updateAllPredictionsAndCountLiveness):
(JSC::CodeBlock::updateAllArrayPredictions):
(JSC::CodeBlock::shouldOptimizeNow):
* bytecode/CodeBlock.h:
(CodeBlock):
(JSC::CodeBlock::jitCompile):
* bytecode/CodeBlockLock.h:
(JSC):
* bytecode/ExecutionCounter.cpp:
(JSC::ExecutionCounter::forceSlowPathConcurrently):
(JSC):
(JSC::ExecutionCounter::setThreshold):
* bytecode/ExecutionCounter.h:
(ExecutionCounter):
* debugger/Debugger.cpp:
(JSC::Debugger::recompileAllJSFunctions):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::injectLazyOperandSpeculation):
(JSC::DFG::ByteCodeParser::getArrayMode):
(JSC::DFG::ByteCodeParser::getArrayModeAndEmitChecks):
* dfg/DFGCommon.h:
(JSC::DFG::enableConcurrentJIT):
(DFG):
* dfg/DFGDriver.cpp:
(JSC::DFG::compile):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::Graph):
* dfg/DFGGraph.h:
(Graph):
* dfg/DFGOSREntry.cpp:
(JSC::DFG::prepareOSREntry):
* dfg/DFGOperations.cpp:
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::Plan):
(JSC::DFG::Plan::compileInThread):
(JSC::DFG::Plan::key):
(DFG):
* dfg/DFGPlan.h:
(DFG):
(Plan):
* dfg/DFGWorklist.cpp: Added.
(DFG):
(JSC::DFG::Worklist::Worklist):
(JSC::DFG::Worklist::~Worklist):
(JSC::DFG::Worklist::finishCreation):
(JSC::DFG::Worklist::create):
(JSC::DFG::Worklist::enqueue):
(JSC::DFG::Worklist::compilationState):
(JSC::DFG::Worklist::waitUntilAllPlansForVMAreReady):
(JSC::DFG::Worklist::removeAllReadyPlansForVM):
(JSC::DFG::Worklist::completeAllReadyPlansForVM):
(JSC::DFG::Worklist::completeAllPlansForVM):
(JSC::DFG::Worklist::queueLength):
(JSC::DFG::Worklist::dump):
(JSC::DFG::Worklist::runThread):
(JSC::DFG::Worklist::threadFunction):
(JSC::DFG::initializeGlobalWorklistOnce):
(JSC::DFG::globalWorklist):
* dfg/DFGWorklist.h: Added.
(DFG):
(Worklist):
* heap/CopiedSpaceInlines.h:
(JSC::CopiedSpace::allocateBlock):
* heap/DeferGC.h: Added.
(JSC):
(DeferGC):
(JSC::DeferGC::DeferGC):
(JSC::DeferGC::~DeferGC):
* heap/Heap.cpp:
(JSC::Heap::Heap):
(JSC::Heap::reportExtraMemoryCostSlowCase):
(JSC::Heap::collectAllGarbage):
(JSC::Heap::collect):
(JSC::Heap::collectIfNecessaryOrDefer):
(JSC):
(JSC::Heap::incrementDeferralDepth):
(JSC::Heap::decrementDeferralDepthAndGCIfNeeded):
* heap/Heap.h:
(Heap):
(JSC::Heap::isCollecting):
(JSC):
* heap/MarkedAllocator.cpp:
(JSC::MarkedAllocator::allocateSlowCase):
* jit/JIT.cpp:
(JSC::JIT::privateCompile):
* jit/JIT.h:
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::jitCompileAndSetHeuristics):
(JSC::LLInt::entryOSR):
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* profiler/ProfilerBytecodes.h:
* runtime/ConcurrentJITLock.h: Added.
(JSC):
* runtime/ExecutionHarness.h:
(JSC::replaceWithDeferredOptimizedCode):
* runtime/JSSegmentedVariableObject.cpp:
(JSC::JSSegmentedVariableObject::findRegisterIndex):
(JSC::JSSegmentedVariableObject::addRegisters):
* runtime/JSSegmentedVariableObject.h:
(JSSegmentedVariableObject):
* runtime/Options.h:
(JSC):
* runtime/Structure.h:
(Structure):
* runtime/StructureInlines.h:
(JSC::Structure::propertyTable):
* runtime/SymbolTable.h:
(SymbolTable):
* runtime/VM.cpp:
(JSC::VM::VM):
(JSC::VM::~VM):
(JSC::VM::prepareToDiscardCode):
(JSC):
(JSC::VM::discardAllCode):
(JSC::VM::releaseExecutableMemory):
* runtime/VM.h:
(DFG):
(VM):

Source/WTF: 

Reviewed by Geoffrey Garen.
        
* wtf/ByteSpinLock.h:
Make it non-copyable. We previously had bugs where we used ByteSpinLock as a locker.
Clearly that's bad.

* wtf/MetaAllocatorHandle.h:
Make it thread-safe ref-counted, since we may now be passing them between the
concurrent JIT thread and the main thread.

* wtf/Vector.h:
(WTF::Vector::takeLast):
I've wanted this method for ages, and now I finally added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreChangeLog">branches/dfgFourthTier/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">branches/dfgFourthTier/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCorebytecodeCodeBlockcpp">branches/dfgFourthTier/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCorebytecodeCodeBlockh">branches/dfgFourthTier/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCorebytecodeCodeBlockLockh">branches/dfgFourthTier/Source/JavaScriptCore/bytecode/CodeBlockLock.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCorebytecodeExecutionCountercpp">branches/dfgFourthTier/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCorebytecodeExecutionCounterh">branches/dfgFourthTier/Source/JavaScriptCore/bytecode/ExecutionCounter.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredebuggerDebuggercpp">branches/dfgFourthTier/Source/JavaScriptCore/debugger/Debugger.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGByteCodeParsercpp">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGCommonh">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGCommon.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGDrivercpp">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGDriver.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGGraphcpp">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGGraph.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGGraphh">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGGraph.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGOSREntrycpp">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGOSREntry.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGOperationscpp">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGPlancpp">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGPlan.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGPlanh">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGPlan.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreheapCopiedSpaceInlinesh">branches/dfgFourthTier/Source/JavaScriptCore/heap/CopiedSpaceInlines.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreheapHeapcpp">branches/dfgFourthTier/Source/JavaScriptCore/heap/Heap.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreheapHeaph">branches/dfgFourthTier/Source/JavaScriptCore/heap/Heap.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreheapMarkedAllocatorcpp">branches/dfgFourthTier/Source/JavaScriptCore/heap/MarkedAllocator.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCorejitJITcpp">branches/dfgFourthTier/Source/JavaScriptCore/jit/JIT.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCorejitJITh">branches/dfgFourthTier/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCorejitJITStubscpp">branches/dfgFourthTier/Source/JavaScriptCore/jit/JITStubs.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCorellintLLIntSlowPathscpp">branches/dfgFourthTier/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreprofilerProfilerBytecodesh">branches/dfgFourthTier/Source/JavaScriptCore/profiler/ProfilerBytecodes.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreruntimeExecutionHarnessh">branches/dfgFourthTier/Source/JavaScriptCore/runtime/ExecutionHarness.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreruntimeJSSegmentedVariableObjectcpp">branches/dfgFourthTier/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreruntimeJSSegmentedVariableObjecth">branches/dfgFourthTier/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreruntimeOptionsh">branches/dfgFourthTier/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreruntimeStructureh">branches/dfgFourthTier/Source/JavaScriptCore/runtime/Structure.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreruntimeStructureInlinesh">branches/dfgFourthTier/Source/JavaScriptCore/runtime/StructureInlines.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreruntimeSymbolTableh">branches/dfgFourthTier/Source/JavaScriptCore/runtime/SymbolTable.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreruntimeVMcpp">branches/dfgFourthTier/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreruntimeVMh">branches/dfgFourthTier/Source/JavaScriptCore/runtime/VM.h</a></li>
<li><a href="#branchesdfgFourthTierSourceWTFChangeLog">branches/dfgFourthTier/Source/WTF/ChangeLog</a></li>
<li><a href="#branchesdfgFourthTierSourceWTFwtfByteSpinLockh">branches/dfgFourthTier/Source/WTF/wtf/ByteSpinLock.h</a></li>
<li><a href="#branchesdfgFourthTierSourceWTFwtfMetaAllocatorHandleh">branches/dfgFourthTier/Source/WTF/wtf/MetaAllocatorHandle.h</a></li>
<li><a href="#branchesdfgFourthTierSourceWTFwtfVectorh">branches/dfgFourthTier/Source/WTF/wtf/Vector.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGWorklistcpp">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGWorklist.cpp</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoredfgDFGWorklisth">branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGWorklist.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreheapDeferGCh">branches/dfgFourthTier/Source/JavaScriptCore/heap/DeferGC.h</a></li>
<li><a href="#branchesdfgFourthTierSourceJavaScriptCoreruntimeConcurrentJITLockh">branches/dfgFourthTier/Source/JavaScriptCore/runtime/ConcurrentJITLock.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchesdfgFourthTierSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/ChangeLog (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/ChangeLog        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/ChangeLog        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -1,3 +1,215 @@
</span><ins>+2013-05-20  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        fourthTier: DFG should be able to run on a separate thread
+        https://bugs.webkit.org/show_bug.cgi?id=112839
+
+        Reviewed by Geoffrey Garen.
+        
+        This is the final bit of concurrent JITing. The idea is that there is a
+        single global worklist, and a single global thread, that does all
+        optimizing compilation. This is the DFG::Worklist. It contains a queue of
+        DFG::Plans, and a map from CodeBlock* (the baseline code block we're
+        trying to optimize) to DFG::Plan. If the DFGDriver tries to concurrently
+        compile something, it puts the Plan on the Worklist. The Worklist's
+        thread will compile that Plan eventually, and when it's done, it will
+        signal its completion by (1) notifying anyone waiting for the Worklist to
+        be done, and (2) forcing the CodeBlock::m_jitExecuteCounter to take slow
+        path. The next Baseline JIT cti_optimize call will then install all ready
+        (i.e. compiled) Plans for that VM. Note that (1) is only for the GC and
+        VM shutdown, which will want to ensure that there aren't any outstanding
+        async compilations before proceeding. They do so by simply waiting for
+        all of the plans for the current VM to complete. (2) is the actual way
+        that code typically gets installed.
+        
+        This is all very racy by design. For example, just as we try to force the
+        execute counter to take slow path, the main thread may be setting the
+        execute counter to some other value. The main thread must set it to
+        another value because (a) JIT code is constantly incrementing the counter
+        in a racy way, (b) the cti_optimize slow path will set it to some
+        large-ish negative value to ensure that cti_optimize isn't called
+        repeatedly, and (c) OSR exits from previously jettisoned code blocks may
+        still want to reset the counter values. This &quot;race&quot; is made benign, by
+        ensuring that while there is an asynchronous compilation, we at worse set
+        the counter to optimizeAfterWarmUp and never to deferIndefinitely. Hence
+        if the race happens then the worst case is that we wait another ~1000
+        counts before installing the optimized code. Another defense is that if
+        any CodeBlock calls into cti_optimize, then it will check for all ready
+        plans for the VM - so even if a code block has to wait another ~1000
+        executions before it calls cti_optimize to do the installation, it may
+        actually end up being installed sooner because a different code block had
+        called cti_optimize, potentially for an unrelated reason.
+        
+        Special care is taken to ensure that installing plans informs the GC
+        about the increased memory usage, but also ensures that we don't recurse
+        infinitely - since at start of GC we try to install outstanding plans.
+        This is done by introducing a new GC deferral mechanism (the DeferGC
+        block-scoped thingy), which will ensure that GCs don't happen in the
+        scope but are allowed to happen after. This still leaves the strange
+        corner case that cti_optimize may install outstanding plans, then GC, and
+        that GC may jettison the code block that was installed. This, and the
+        fact that the plan that we took slow path to install could have been a
+        failed or invalid compile, mean that we have to take special precautions
+        in cti_optimize.
+        
+        This patch also fixes a number of small concurrency bugs that I found
+        when things started running. There are probably more of those bugs still
+        left to fix. This patch just fixes the ones I know about.
+        
+        Concurrent compilation is right now only enabled on X86_64 Mac. We need
+        platforms that are sufficiently CAStastic so that we can do the various
+        memory fence and CAS tricks that make this safe. We also need a platform
+        that uses JSVALUE64. And we need pthread_once. So, that pretty much means
+        just X64_64 for now. Enabling Linux-64_64 should be a breeze, but I'll
+        leave that up to the Qt and GTK+ ports to do at their discretion.
+        
+        This is a solid speed-up on SunSpider (8-9%) and V8Spider (16%), our two
+        main compile-time benchmarks. Most peculiarly, this also appears to
+        reduce measurement noise, rather than increasing it as you would have
+        expected. I don't understand that result but I like it anyway. On the
+        other hand, this is a slight (1%) slow-down on V8v7. I will continue to
+        investigate this but I think that the results are already good enough
+        that we should land this as-is. So far, it appears that the slow-down is
+        due to this breaking the don't-compile-inlineables heuristics. See
+        investigation in https://bugs.webkit.org/show_bug.cgi?id=116556 and the
+        bug https://bugs.webkit.org/show_bug.cgi?id=116557.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/CodeBlock.cpp:
+        (JSC):
+        (JSC::CodeBlock::finalizeUnconditionally):
+        (JSC::CodeBlock::resetStubInternal):
+        (JSC::CodeBlock::baselineVersion):
+        (JSC::CodeBlock::hasOptimizedReplacement):
+        (JSC::CodeBlock::optimizationThresholdScalingFactor):
+        (JSC::CodeBlock::checkIfOptimizationThresholdReached):
+        (JSC::CodeBlock::optimizeNextInvocation):
+        (JSC::CodeBlock::dontOptimizeAnytimeSoon):
+        (JSC::CodeBlock::optimizeAfterWarmUp):
+        (JSC::CodeBlock::optimizeAfterLongWarmUp):
+        (JSC::CodeBlock::optimizeSoon):
+        (JSC::CodeBlock::forceOptimizationSlowPathConcurrently):
+        (JSC::CodeBlock::setOptimizationThresholdBasedOnCompilationResult):
+        (JSC::CodeBlock::updateAllPredictionsAndCountLiveness):
+        (JSC::CodeBlock::updateAllArrayPredictions):
+        (JSC::CodeBlock::shouldOptimizeNow):
+        * bytecode/CodeBlock.h:
+        (CodeBlock):
+        (JSC::CodeBlock::jitCompile):
+        * bytecode/CodeBlockLock.h:
+        (JSC):
+        * bytecode/ExecutionCounter.cpp:
+        (JSC::ExecutionCounter::forceSlowPathConcurrently):
+        (JSC):
+        (JSC::ExecutionCounter::setThreshold):
+        * bytecode/ExecutionCounter.h:
+        (ExecutionCounter):
+        * debugger/Debugger.cpp:
+        (JSC::Debugger::recompileAllJSFunctions):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::injectLazyOperandSpeculation):
+        (JSC::DFG::ByteCodeParser::getArrayMode):
+        (JSC::DFG::ByteCodeParser::getArrayModeAndEmitChecks):
+        * dfg/DFGCommon.h:
+        (JSC::DFG::enableConcurrentJIT):
+        (DFG):
+        * dfg/DFGDriver.cpp:
+        (JSC::DFG::compile):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::Graph):
+        * dfg/DFGGraph.h:
+        (Graph):
+        * dfg/DFGOSREntry.cpp:
+        (JSC::DFG::prepareOSREntry):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::Plan):
+        (JSC::DFG::Plan::compileInThread):
+        (JSC::DFG::Plan::key):
+        (DFG):
+        * dfg/DFGPlan.h:
+        (DFG):
+        (Plan):
+        * dfg/DFGWorklist.cpp: Added.
+        (DFG):
+        (JSC::DFG::Worklist::Worklist):
+        (JSC::DFG::Worklist::~Worklist):
+        (JSC::DFG::Worklist::finishCreation):
+        (JSC::DFG::Worklist::create):
+        (JSC::DFG::Worklist::enqueue):
+        (JSC::DFG::Worklist::compilationState):
+        (JSC::DFG::Worklist::waitUntilAllPlansForVMAreReady):
+        (JSC::DFG::Worklist::removeAllReadyPlansForVM):
+        (JSC::DFG::Worklist::completeAllReadyPlansForVM):
+        (JSC::DFG::Worklist::completeAllPlansForVM):
+        (JSC::DFG::Worklist::queueLength):
+        (JSC::DFG::Worklist::dump):
+        (JSC::DFG::Worklist::runThread):
+        (JSC::DFG::Worklist::threadFunction):
+        (JSC::DFG::initializeGlobalWorklistOnce):
+        (JSC::DFG::globalWorklist):
+        * dfg/DFGWorklist.h: Added.
+        (DFG):
+        (Worklist):
+        * heap/CopiedSpaceInlines.h:
+        (JSC::CopiedSpace::allocateBlock):
+        * heap/DeferGC.h: Added.
+        (JSC):
+        (DeferGC):
+        (JSC::DeferGC::DeferGC):
+        (JSC::DeferGC::~DeferGC):
+        * heap/Heap.cpp:
+        (JSC::Heap::Heap):
+        (JSC::Heap::reportExtraMemoryCostSlowCase):
+        (JSC::Heap::collectAllGarbage):
+        (JSC::Heap::collect):
+        (JSC::Heap::collectIfNecessaryOrDefer):
+        (JSC):
+        (JSC::Heap::incrementDeferralDepth):
+        (JSC::Heap::decrementDeferralDepthAndGCIfNeeded):
+        * heap/Heap.h:
+        (Heap):
+        (JSC::Heap::isCollecting):
+        (JSC):
+        * heap/MarkedAllocator.cpp:
+        (JSC::MarkedAllocator::allocateSlowCase):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompile):
+        * jit/JIT.h:
+        * jit/JITStubs.cpp:
+        (JSC::DEFINE_STUB_FUNCTION):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::jitCompileAndSetHeuristics):
+        (JSC::LLInt::entryOSR):
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * profiler/ProfilerBytecodes.h:
+        * runtime/ConcurrentJITLock.h: Added.
+        (JSC):
+        * runtime/ExecutionHarness.h:
+        (JSC::replaceWithDeferredOptimizedCode):
+        * runtime/JSSegmentedVariableObject.cpp:
+        (JSC::JSSegmentedVariableObject::findRegisterIndex):
+        (JSC::JSSegmentedVariableObject::addRegisters):
+        * runtime/JSSegmentedVariableObject.h:
+        (JSSegmentedVariableObject):
+        * runtime/Options.h:
+        (JSC):
+        * runtime/Structure.h:
+        (Structure):
+        * runtime/StructureInlines.h:
+        (JSC::Structure::propertyTable):
+        * runtime/SymbolTable.h:
+        (SymbolTable):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        (JSC::VM::~VM):
+        (JSC::VM::prepareToDiscardCode):
+        (JSC):
+        (JSC::VM::discardAllCode):
+        (JSC::VM::releaseExecutableMemory):
+        * runtime/VM.h:
+        (DFG):
+        (VM):
+
</ins><span class="cx"> 2013-05-17  Mark Hahnenberg  &lt;mhahnenberg@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         CheckArrays should be hoisted
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -75,6 +75,7 @@
</span><span class="cx">                 0F0CD4C415F6B6BB0032F1C0 /* SparseArrayValueMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0CD4C315F6B6B50032F1C0 /* SparseArrayValueMap.cpp */; };
</span><span class="cx">                 0F0D85B21723455400338210 /* CodeBlockLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0D85B11723455100338210 /* CodeBlockLock.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F0FC45A14BD15F500B81154 /* LLIntCallLinkInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F136D4D174AD69E0075B354 /* DeferGC.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F136D4B174AD69B0075B354 /* DeferGC.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F13912916771C33009CCB07 /* ProfilerBytecodeSequence.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F13912416771C30009CCB07 /* ProfilerBytecodeSequence.cpp */; };
</span><span class="cx">                 0F13912A16771C36009CCB07 /* ProfilerBytecodeSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F13912516771C30009CCB07 /* ProfilerBytecodeSequence.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F13912B16771C3A009CCB07 /* ProfilerProfiledBytecodes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F13912616771C30009CCB07 /* ProfilerProfiledBytecodes.cpp */; };
</span><span class="lines">@@ -331,6 +332,9 @@
</span><span class="cx">                 0FDB2CE01742D804007B3C1B /* DFGPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDB2CD81742D804007B3C1B /* DFGPlan.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FDB2CE21746C1FA007B3C1B /* CompilationResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDB2CE11746C1F8007B3C1B /* CompilationResult.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FDB2CE41746CE9F007B3C1B /* CompilationResult.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDB2CE31746CE9D007B3C1B /* CompilationResult.cpp */; };
</span><ins>+                0FDB2CE7174830A2007B3C1B /* DFGWorklist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDB2CE5174830A2007B3C1B /* DFGWorklist.cpp */; };
+                0FDB2CE8174830A2007B3C1B /* DFGWorklist.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDB2CE6174830A2007B3C1B /* DFGWorklist.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0FDB2CEA174896C7007B3C1B /* ConcurrentJITLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDB2CE9174896C7007B3C1B /* ConcurrentJITLock.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0FDDBFB51666EED800C55FEF /* DFGVariableAccessDataDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDDBFB21666EED500C55FEF /* DFGVariableAccessDataDump.cpp */; };
</span><span class="cx">                 0FDDBFB61666EEDA00C55FEF /* DFGVariableAccessDataDump.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDDBFB31666EED500C55FEF /* DFGVariableAccessDataDump.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FE228ED1436AB2700196C48 /* Options.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE228EB1436AB2300196C48 /* Options.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -1068,6 +1072,7 @@
</span><span class="cx">                 0F0CD4C315F6B6B50032F1C0 /* SparseArrayValueMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SparseArrayValueMap.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F0D85B11723455100338210 /* CodeBlockLock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CodeBlockLock.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLIntCallLinkInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F136D4B174AD69B0075B354 /* DeferGC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeferGC.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F13912416771C30009CCB07 /* ProfilerBytecodeSequence.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerBytecodeSequence.cpp; path = profiler/ProfilerBytecodeSequence.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F13912516771C30009CCB07 /* ProfilerBytecodeSequence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerBytecodeSequence.h; path = profiler/ProfilerBytecodeSequence.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F13912616771C30009CCB07 /* ProfilerProfiledBytecodes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerProfiledBytecodes.cpp; path = profiler/ProfilerProfiledBytecodes.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -1338,6 +1343,9 @@
</span><span class="cx">                 0FDB2CD81742D804007B3C1B /* DFGPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPlan.h; path = dfg/DFGPlan.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FDB2CE11746C1F8007B3C1B /* CompilationResult.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CompilationResult.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FDB2CE31746CE9D007B3C1B /* CompilationResult.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CompilationResult.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0FDB2CE5174830A2007B3C1B /* DFGWorklist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGWorklist.cpp; path = dfg/DFGWorklist.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FDB2CE6174830A2007B3C1B /* DFGWorklist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGWorklist.h; path = dfg/DFGWorklist.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FDB2CE9174896C7007B3C1B /* ConcurrentJITLock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConcurrentJITLock.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0FDDBFB21666EED500C55FEF /* DFGVariableAccessDataDump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGVariableAccessDataDump.cpp; path = dfg/DFGVariableAccessDataDump.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FDDBFB31666EED500C55FEF /* DFGVariableAccessDataDump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessDataDump.h; path = dfg/DFGVariableAccessDataDump.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FE228EA1436AB2300196C48 /* Options.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Options.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -2344,6 +2352,7 @@
</span><span class="cx">                                 C2239D1316262BDD005AC5FD /* CopyVisitor.h */,
</span><span class="cx">                                 C2239D1416262BDD005AC5FD /* CopyVisitorInlines.h */,
</span><span class="cx">                                 C218D13F1655CFD50062BB81 /* CopyWorkList.h */,
</span><ins>+                                0F136D4B174AD69B0075B354 /* DeferGC.h */,
</ins><span class="cx">                                 0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */,
</span><span class="cx">                                 0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */,
</span><span class="cx">                                 BCBE2CAD14E985AA000593AD /* GCAssertions.h */,
</span><span class="lines">@@ -2633,6 +2642,7 @@
</span><span class="cx">                                 0FDB2CE11746C1F8007B3C1B /* CompilationResult.h */,
</span><span class="cx">                                 969A09220ED1E09C00F1F681 /* Completion.cpp */,
</span><span class="cx">                                 F5BB2BC5030F772101FCFE1D /* Completion.h */,
</span><ins>+                                0FDB2CE9174896C7007B3C1B /* ConcurrentJITLock.h */,
</ins><span class="cx">                                 BCA62DFF0E2826310004F30D /* ConstructData.cpp */,
</span><span class="cx">                                 BC8F3CCF0DAF17BA00577A80 /* ConstructData.h */,
</span><span class="cx">                                 BCD203450E17135E002C7E82 /* DateConstructor.cpp */,
</span><span class="lines">@@ -3030,6 +3040,8 @@
</span><span class="cx">                                 0F85A31E16AB76AE0077571E /* DFGVariadicFunction.h */,
</span><span class="cx">                                 0FFFC95314EF909500C72532 /* DFGVirtualRegisterAllocationPhase.cpp */,
</span><span class="cx">                                 0FFFC95414EF909500C72532 /* DFGVirtualRegisterAllocationPhase.h */,
</span><ins>+                                0FDB2CE5174830A2007B3C1B /* DFGWorklist.cpp */,
+                                0FDB2CE6174830A2007B3C1B /* DFGWorklist.h */,
</ins><span class="cx">                         );
</span><span class="cx">                         name = dfg;
</span><span class="cx">                         sourceTree = &quot;&lt;group&gt;&quot;;
</span><span class="lines">@@ -3445,6 +3457,7 @@
</span><span class="cx">                                 0F5EF91F16878F7D003E5C25 /* JITThunks.h in Headers */,
</span><span class="cx">                                 A76F54A313B28AAB00EF2BCE /* JITWriteBarrier.h in Headers */,
</span><span class="cx">                                 BC18C4160E16F5CD00B34460 /* JSActivation.h in Headers */,
</span><ins>+                                0FDB2CEA174896C7007B3C1B /* ConcurrentJITLock.h in Headers */,
</ins><span class="cx">                                 840480131021A1D9008E7F01 /* JSAPIValueWrapper.h in Headers */,
</span><span class="cx">                                 0F235BE417178E1C00690C7F /* FTLValueFormat.h in Headers */,
</span><span class="cx">                                 BC18C4170E16F5CD00B34460 /* JSArray.h in Headers */,
</span><span class="lines">@@ -3576,6 +3589,7 @@
</span><span class="cx">                                 BC18C43F0E16F5CD00B34460 /* Nodes.h in Headers */,
</span><span class="cx">                                 BC18C4410E16F5CD00B34460 /* NumberConstructor.h in Headers */,
</span><span class="cx">                                 BC18C4420E16F5CD00B34460 /* NumberConstructor.lut.h in Headers */,
</span><ins>+                                0FDB2CE8174830A2007B3C1B /* DFGWorklist.h in Headers */,
</ins><span class="cx">                                 BC18C4430E16F5CD00B34460 /* NumberObject.h in Headers */,
</span><span class="cx">                                 BC18C4440E16F5CD00B34460 /* NumberPrototype.h in Headers */,
</span><span class="cx">                                 142D3939103E4560007DCB52 /* NumericStrings.h in Headers */,
</span><span class="lines">@@ -3747,6 +3761,7 @@
</span><span class="cx">                                 0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */,
</span><span class="cx">                                 0FCCAE4516D0CF7400D0C65B /* ParserError.h in Headers */,
</span><span class="cx">                                 0F714CA516EA92F200F3EBEB /* DFGBackwardsPropagationPhase.h in Headers */,
</span><ins>+                                0F136D4D174AD69E0075B354 /* DeferGC.h in Headers */,
</ins><span class="cx">                         );
</span><span class="cx">                         runOnlyForDeploymentPostprocessing = 0;
</span><span class="cx">                 };
</span><span class="lines">@@ -4366,6 +4381,7 @@
</span><span class="cx">                                 14469DE8107EC7E700650446 /* PropertySlot.cpp in Sources */,
</span><span class="cx">                                 0F8F2B95172E04A0007DBDA5 /* FTLLink.cpp in Sources */,
</span><span class="cx">                                 1474C33C16AA2D9B0062F01D /* PrototypeMap.cpp in Sources */,
</span><ins>+                                0FDB2CE7174830A2007B3C1B /* DFGWorklist.cpp in Sources */,
</ins><span class="cx">                                 0F9332A314CA7DD70085F3C6 /* PutByIdStatus.cpp in Sources */,
</span><span class="cx">                                 0FEA0A2A1709629600BB722C /* FTLOutput.cpp in Sources */,
</span><span class="cx">                                 0FF60AC316740F8800029779 /* ReduceWhitespace.cpp in Sources */,
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/bytecode/CodeBlock.cpp (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> #include &quot;DFGCommon.h&quot;
</span><span class="cx"> #include &quot;DFGNode.h&quot;
</span><span class="cx"> #include &quot;DFGRepatch.h&quot;
</span><ins>+#include &quot;DFGWorklist.h&quot;
</ins><span class="cx"> #include &quot;Debugger.h&quot;
</span><span class="cx"> #include &quot;FTLJITCode.h&quot;
</span><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="lines">@@ -2182,12 +2183,6 @@
</span><span class="cx">     performTracingFixpointIteration(visitor);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-static const bool verboseUnlinking = true;
-#else
-static const bool verboseUnlinking = false;
-#endif
-
</del><span class="cx"> void CodeBlock::finalizeUnconditionally()
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(LLINT)
</span><span class="lines">@@ -2203,7 +2198,7 @@
</span><span class="cx">             case op_put_by_id_out_of_line:
</span><span class="cx">                 if (!curInstruction[4].u.structure || Heap::isMarked(curInstruction[4].u.structure.get()))
</span><span class="cx">                     break;
</span><del>-                if (verboseUnlinking)
</del><ins>+                if (Options::verboseOSR())
</ins><span class="cx">                     dataLogF(&quot;Clearing LLInt property access with structure %p.\n&quot;, curInstruction[4].u.structure.get());
</span><span class="cx">                 curInstruction[4].u.structure.clear();
</span><span class="cx">                 curInstruction[5].u.operand = 0;
</span><span class="lines">@@ -2216,7 +2211,7 @@
</span><span class="cx">                     &amp;&amp; Heap::isMarked(curInstruction[6].u.structure.get())
</span><span class="cx">                     &amp;&amp; Heap::isMarked(curInstruction[7].u.structureChain.get()))
</span><span class="cx">                     break;
</span><del>-                if (verboseUnlinking) {
</del><ins>+                if (Options::verboseOSR()) {
</ins><span class="cx">                     dataLogF(&quot;Clearing LLInt put transition with structures %p -&gt; %p, chain %p.\n&quot;,
</span><span class="cx">                             curInstruction[4].u.structure.get(),
</span><span class="cx">                             curInstruction[6].u.structure.get(),
</span><span class="lines">@@ -2236,7 +2231,7 @@
</span><span class="cx"> 
</span><span class="cx">         for (unsigned i = 0; i &lt; m_llintCallLinkInfos.size(); ++i) {
</span><span class="cx">             if (m_llintCallLinkInfos[i].isLinked() &amp;&amp; !Heap::isMarked(m_llintCallLinkInfos[i].callee.get())) {
</span><del>-                if (verboseUnlinking)
</del><ins>+                if (Options::verboseOSR())
</ins><span class="cx">                     dataLog(&quot;Clearing LLInt call from &quot;, *this, &quot;\n&quot;);
</span><span class="cx">                 m_llintCallLinkInfos[i].unlink();
</span><span class="cx">             }
</span><span class="lines">@@ -2249,7 +2244,7 @@
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     // Check if we're not live. If we are, then jettison.
</span><span class="cx">     if (!(shouldImmediatelyAssumeLivenessDuringScan() || m_jitCode-&gt;dfgCommon()-&gt;livenessHasBeenProved)) {
</span><del>-        if (verboseUnlinking)
</del><ins>+        if (Options::verboseOSR())
</ins><span class="cx">             dataLog(*this, &quot; has dead weak references, jettisoning during GC.\n&quot;);
</span><span class="cx"> 
</span><span class="cx">         // Make sure that the baseline JIT knows that it should re-warm-up before
</span><span class="lines">@@ -2283,7 +2278,7 @@
</span><span class="cx"> 
</span><span class="cx">     for (size_t size = m_putToBaseOperations.size(), i = 0; i &lt; size; ++i) {
</span><span class="cx">         if (m_putToBaseOperations[i].m_structure &amp;&amp; !Heap::isMarked(m_putToBaseOperations[i].m_structure.get())) {
</span><del>-            if (verboseUnlinking)
</del><ins>+            if (Options::verboseOSR())
</ins><span class="cx">                 dataLog(&quot;Clearing putToBase info in &quot;, *this, &quot;\n&quot;);
</span><span class="cx">             m_putToBaseOperations[i].m_structure.clear();
</span><span class="cx">         }
</span><span class="lines">@@ -2297,7 +2292,7 @@
</span><span class="cx"> #endif
</span><span class="cx">         m_resolveOperations[i].last().m_structure.clear();
</span><span class="cx">         if (m_resolveOperations[i].last().m_structure &amp;&amp; !Heap::isMarked(m_resolveOperations[i].last().m_structure.get())) {
</span><del>-            if (verboseUnlinking)
</del><ins>+            if (Options::verboseOSR())
</ins><span class="cx">                 dataLog(&quot;Clearing resolve info in &quot;, *this, &quot;\n&quot;);
</span><span class="cx">             m_resolveOperations[i].last().m_structure.clear();
</span><span class="cx">         }
</span><span class="lines">@@ -2312,7 +2307,7 @@
</span><span class="cx">                 if (ClosureCallStubRoutine* stub = callLinkInfo(i).stub.get()) {
</span><span class="cx">                     if (!Heap::isMarked(stub-&gt;structure())
</span><span class="cx">                         || !Heap::isMarked(stub-&gt;executable())) {
</span><del>-                        if (verboseUnlinking) {
</del><ins>+                        if (Options::verboseOSR()) {
</ins><span class="cx">                             dataLog(
</span><span class="cx">                                 &quot;Clearing closure call from &quot;, *this, &quot; to &quot;,
</span><span class="cx">                                 stub-&gt;executable()-&gt;hashFor(callLinkInfo(i).specializationKind()),
</span><span class="lines">@@ -2321,7 +2316,7 @@
</span><span class="cx">                         callLinkInfo(i).unlink(*m_vm, repatchBuffer);
</span><span class="cx">                     }
</span><span class="cx">                 } else if (!Heap::isMarked(callLinkInfo(i).callee.get())) {
</span><del>-                    if (verboseUnlinking) {
</del><ins>+                    if (Options::verboseOSR()) {
</ins><span class="cx">                         dataLog(
</span><span class="cx">                             &quot;Clearing call from &quot;, *this, &quot; to &quot;,
</span><span class="cx">                             RawPointer(callLinkInfo(i).callee.get()), &quot; (&quot;,
</span><span class="lines">@@ -2362,7 +2357,7 @@
</span><span class="cx"> {
</span><span class="cx">     AccessType accessType = static_cast&lt;AccessType&gt;(stubInfo.accessType);
</span><span class="cx">     
</span><del>-    if (verboseUnlinking)
</del><ins>+    if (Options::verboseOSR())
</ins><span class="cx">         dataLog(&quot;Clearing structure cache (kind &quot;, static_cast&lt;int&gt;(stubInfo.accessType), &quot;) in &quot;, *this, &quot;.\n&quot;);
</span><span class="cx"> 
</span><span class="cx">     switch (getJITType()) {
</span><span class="lines">@@ -2427,6 +2422,42 @@
</span><span class="cx"> #endif    
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+CodeBlock* CodeBlock::baselineVersion()
+{
+#if ENABLE(JIT)
+    // When we're initializing the original baseline code block, we won't be able
+    // to get its replacement. But we'll know that it's the original baseline code
+    // block because it won't have JIT code yet and it won't have an alternative.
+    if (getJITType() == JITCode::None &amp;&amp; !alternative())
+        return this;
+    
+    CodeBlock* result = replacement();
+    ASSERT(result);
+    while (result-&gt;alternative())
+        result = result-&gt;alternative();
+    ASSERT(result);
+    ASSERT(JITCode::isBaselineCode(result-&gt;getJITType()));
+    return result;
+#else
+    return this;
+#endif
+}
+
+#if ENABLE(JIT)
+bool CodeBlock::hasOptimizedReplacement()
+{
+    ASSERT(JITCode::isBaselineCode(getJITType()));
+    bool result = JITCode::isHigherTier(replacement()-&gt;getJITType(), getJITType());
+    if (result)
+        ASSERT(JITCode::isOptimizingJIT(replacement()-&gt;getJITType()));
+    else {
+        ASSERT(JITCode::isBaselineCode(replacement()-&gt;getJITType()));
+        ASSERT(replacement() == this);
+    }
+    return result;
+}
+#endif
+
</ins><span class="cx"> HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(bytecodeOffset &lt; instructions().size());
</span><span class="lines">@@ -2983,9 +3014,12 @@
</span><span class="cx">     ASSERT(instructionCount); // Make sure this is called only after we have an instruction stream; otherwise it'll just return the value of d, which makes no sense.
</span><span class="cx">     
</span><span class="cx">     double result = d + a * sqrt(instructionCount + b) + c * instructionCount;
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-    dataLog(*this, &quot;: instruction count is &quot;, instructionCount, &quot;, scaling execution counter by &quot;, result, &quot; * &quot;, codeTypeThresholdMultiplier(), &quot;\n&quot;);
-#endif
</del><ins>+    if (Options::verboseOSR()) {
+        dataLog(
+            *this, &quot;: instruction count is &quot;, instructionCount,
+            &quot;, scaling execution counter by &quot;, result, &quot; * &quot;, codeTypeThresholdMultiplier(),
+            &quot;\n&quot;);
+    }
</ins><span class="cx">     return result * codeTypeThresholdMultiplier();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -3026,34 +3060,90 @@
</span><span class="cx"> 
</span><span class="cx"> bool CodeBlock::checkIfOptimizationThresholdReached()
</span><span class="cx"> {
</span><ins>+#if ENABLE(DFG_JIT)
+    if (m_vm-&gt;worklist
+        &amp;&amp; m_vm-&gt;worklist-&gt;compilationState(this) == DFG::Worklist::Compiled) {
+        optimizeNextInvocation();
+        return true;
+    }
+#endif
+    
</ins><span class="cx">     return m_jitExecuteCounter.checkIfThresholdCrossedAndSet(this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CodeBlock::optimizeNextInvocation()
</span><span class="cx"> {
</span><ins>+    if (Options::verboseOSR())
+        dataLog(*this, &quot;: Optimizing next invocation.\n&quot;);
</ins><span class="cx">     m_jitExecuteCounter.setNewThreshold(0, this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CodeBlock::dontOptimizeAnytimeSoon()
</span><span class="cx"> {
</span><ins>+    if (Options::verboseOSR())
+        dataLog(*this, &quot;: Not optimizing anytime soon.\n&quot;);
</ins><span class="cx">     m_jitExecuteCounter.deferIndefinitely();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CodeBlock::optimizeAfterWarmUp()
</span><span class="cx"> {
</span><ins>+    if (Options::verboseOSR())
+        dataLog(*this, &quot;: Optimizing after warm-up.\n&quot;);
</ins><span class="cx">     m_jitExecuteCounter.setNewThreshold(counterValueForOptimizeAfterWarmUp(), this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CodeBlock::optimizeAfterLongWarmUp()
</span><span class="cx"> {
</span><ins>+    if (Options::verboseOSR())
+        dataLog(*this, &quot;: Optimizing after long warm-up.\n&quot;);
</ins><span class="cx">     m_jitExecuteCounter.setNewThreshold(counterValueForOptimizeAfterLongWarmUp(), this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CodeBlock::optimizeSoon()
</span><span class="cx"> {
</span><ins>+    if (Options::verboseOSR())
+        dataLog(*this, &quot;: Optimizing soon.\n&quot;);
</ins><span class="cx">     m_jitExecuteCounter.setNewThreshold(counterValueForOptimizeSoon(), this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void CodeBlock::forceOptimizationSlowPathConcurrently()
+{
+    if (Options::verboseOSR())
+        dataLog(*this, &quot;: Forcing slow path concurrently.\n&quot;);
+    m_jitExecuteCounter.forceSlowPathConcurrently();
+}
+
+void CodeBlock::setOptimizationThresholdBasedOnCompilationResult(CompilationResult result)
+{
+    RELEASE_ASSERT(getJITType() == JITCode::BaselineJIT);
+    RELEASE_ASSERT((result == CompilationSuccessful) == (replacement() != this));
+    switch (result) {
+    case CompilationSuccessful:
+        RELEASE_ASSERT(JITCode::isOptimizingJIT(replacement()-&gt;getJITType()));
+        optimizeNextInvocation();
+        break;
+    case CompilationFailed:
+        dontOptimizeAnytimeSoon();
+        break;
+    case CompilationDeferred:
+        // We'd like to do dontOptimizeAnytimeSoon() but we cannot because
+        // forceOptimizationSlowPathConcurrently() is inherently racy. It won't
+        // necessarily guarantee anything. So, we make sure that even if that
+        // function ends up being a no-op, we still eventually retry and realize
+        // that we have optimized code ready.
+        optimizeAfterWarmUp();
+        break;
+    case CompilationInvalidated:
+        // Retry with exponential backoff.
+        countReoptimization();
+        optimizeAfterWarmUp();
+        break;
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+        break;
+    }
+}
+
</ins><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> uint32_t CodeBlock::adjustedExitCountThreshold(uint32_t desiredThreshold)
</span><span class="cx"> {
</span><span class="lines">@@ -3112,7 +3202,7 @@
</span><span class="cx"> void CodeBlock::updateAllPredictionsAndCountLiveness(
</span><span class="cx">     OperationInProgress operation, unsigned&amp; numberOfLiveNonArgumentValueProfiles, unsigned&amp; numberOfSamplesInProfiles)
</span><span class="cx"> {
</span><del>-    CodeBlockLock locker(m_lock);
</del><ins>+    CodeBlockLocker locker(m_lock);
</ins><span class="cx">     
</span><span class="cx">     numberOfLiveNonArgumentValueProfiles = 0;
</span><span class="cx">     numberOfSamplesInProfiles = 0; // If this divided by ValueProfile::numberOfBuckets equals numberOfValueProfiles() then value profiles are full.
</span><span class="lines">@@ -3144,7 +3234,7 @@
</span><span class="cx"> 
</span><span class="cx"> void CodeBlock::updateAllArrayPredictions(OperationInProgress operation)
</span><span class="cx"> {
</span><del>-    CodeBlockLock locker(m_lock);
</del><ins>+    CodeBlockLocker locker(m_lock);
</ins><span class="cx">     
</span><span class="cx">     for (unsigned i = m_arrayProfiles.size(); i--;)
</span><span class="cx">         m_arrayProfiles[i].computeUpdatedPrediction(locker, this, operation);
</span><span class="lines">@@ -3162,9 +3252,8 @@
</span><span class="cx"> 
</span><span class="cx"> bool CodeBlock::shouldOptimizeNow()
</span><span class="cx"> {
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-    dataLog(&quot;Considering optimizing &quot;, *this, &quot;...\n&quot;);
-#endif
</del><ins>+    if (Options::verboseOSR())
+        dataLog(&quot;Considering optimizing &quot;, *this, &quot;...\n&quot;);
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(VERBOSE_VALUE_PROFILE)
</span><span class="cx">     dumpValueProfiles();
</span><span class="lines">@@ -3179,9 +3268,14 @@
</span><span class="cx">     unsigned numberOfSamplesInProfiles;
</span><span class="cx">     updateAllPredictionsAndCountLiveness(NoOperation, numberOfLiveNonArgumentValueProfiles, numberOfSamplesInProfiles);
</span><span class="cx"> 
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-    dataLogF(&quot;Profile hotness: %lf (%u / %u), %lf (%u / %u)\n&quot;, (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles(), numberOfLiveNonArgumentValueProfiles, numberOfValueProfiles(), (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles(), numberOfSamplesInProfiles, ValueProfile::numberOfBuckets * numberOfValueProfiles());
-#endif
</del><ins>+    if (Options::verboseOSR()) {
+        dataLogF(
+            &quot;Profile hotness: %lf (%u / %u), %lf (%u / %u)\n&quot;,
+            (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles(),
+            numberOfLiveNonArgumentValueProfiles, numberOfValueProfiles(),
+            (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles(),
+            numberOfSamplesInProfiles, ValueProfile::numberOfBuckets * numberOfValueProfiles());
+    }
</ins><span class="cx"> 
</span><span class="cx">     if ((!numberOfValueProfiles() || (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles() &gt;= Options::desiredProfileLivenessRate())
</span><span class="cx">         &amp;&amp; (!totalNumberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / totalNumberOfValueProfiles() &gt;= Options::desiredProfileFullnessRate())
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/bytecode/CodeBlock.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/bytecode/CodeBlock.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/bytecode/CodeBlock.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -131,25 +131,7 @@
</span><span class="cx">             return specializationFromIsConstruct(m_isConstructor);
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-#if ENABLE(JIT)
-        CodeBlock* baselineVersion()
-        {
-            if (JITCode::isBaselineCode(getJITType()))
-                return this;
-            CodeBlock* result = replacement();
-            ASSERT(result);
-            while (result-&gt;alternative())
-                result = result-&gt;alternative();
-            ASSERT(result);
-            ASSERT(JITCode::isBaselineCode(result-&gt;getJITType()));
-            return result;
-        }
-#else
-        CodeBlock* baselineVersion()
-        {
-            return this;
-        }
-#endif
</del><ins>+        CodeBlock* baselineVersion();
</ins><span class="cx"> 
</span><span class="cx">         void visitAggregate(SlotVisitor&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -307,12 +289,7 @@
</span><span class="cx">                 ASSERT(getJITType() == JITCode::BaselineJIT);
</span><span class="cx">                 return CompilationNotNeeded;
</span><span class="cx">             }
</span><del>-#if ENABLE(JIT)
</del><span class="cx">             return jitCompileImpl(exec);
</span><del>-#else
-            UNUSED_PARAM(exec);
-            return CompilationFailed;
-#endif
</del><span class="cx">         }
</span><span class="cx">         virtual CodeBlock* replacement() = 0;
</span><span class="cx"> 
</span><span class="lines">@@ -325,20 +302,7 @@
</span><span class="cx">         }
</span><span class="cx">         DFG::CapabilityLevel canCompileWithDFGState() { return m_canCompileWithDFGState; }
</span><span class="cx"> 
</span><del>-        bool hasOptimizedReplacement()
-        {
-            ASSERT(JITCode::isBaselineCode(getJITType()));
-            bool result = JITCode::isHigherTier(replacement()-&gt;getJITType(), getJITType());
-#if !ASSERT_DISABLED
-            if (result)
-                ASSERT(JITCode::isOptimizingJIT(replacement()-&gt;getJITType()));
-            else {
-                ASSERT(JITCode::isBaselineCode(replacement()-&gt;getJITType()));
-                ASSERT(replacement() == this);
-            }
-#endif
-            return result;
-        }
</del><ins>+        bool hasOptimizedReplacement();
</ins><span class="cx"> #else
</span><span class="cx">         JITCode::JITType getJITType() const { return JITCode::BaselineJIT; }
</span><span class="cx"> #endif
</span><span class="lines">@@ -865,6 +829,10 @@
</span><span class="cx">         // to trigger optimization if one of those functions becomes hot
</span><span class="cx">         // in the baseline code.
</span><span class="cx">         void optimizeSoon();
</span><ins>+    
+        void forceOptimizationSlowPathConcurrently();
+    
+        void setOptimizationThresholdBasedOnCompilationResult(CompilationResult);
</ins><span class="cx">         
</span><span class="cx">         uint32_t osrExitCounter() const { return m_osrExitCounter; }
</span><span class="cx">         
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCorebytecodeCodeBlockLockh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/bytecode/CodeBlockLock.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/bytecode/CodeBlockLock.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/bytecode/CodeBlockLock.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -26,18 +26,12 @@
</span><span class="cx"> #ifndef CodeBlockLock_h
</span><span class="cx"> #define CodeBlockLock_h
</span><span class="cx"> 
</span><del>-#include &lt;wtf/ByteSpinLock.h&gt;
-#include &lt;wtf/NoLock.h&gt;
</del><ins>+#include &quot;ConcurrentJITLock.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-#if ENABLE(CONCURRENT_JIT)
-typedef ByteSpinLock CodeBlockLock;
-typedef ByteSpinLocker CodeBlockLocker;
-#else
-typedef NoLock CodeBlockLock;
-typedef NoLockLocker CodeBlockLocker;
-#endif
</del><ins>+typedef ConcurrentJITLock CodeBlockLock;
+typedef ConcurrentJITLocker CodeBlockLocker;
</ins><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCorebytecodeExecutionCountercpp"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -37,6 +37,11 @@
</span><span class="cx">     reset();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void ExecutionCounter::forceSlowPathConcurrently()
+{
+    m_counter = 0;
+}
+
</ins><span class="cx"> bool ExecutionCounter::checkIfThresholdCrossedAndSet(CodeBlock* codeBlock)
</span><span class="cx"> {
</span><span class="cx">     if (hasCrossedThreshold(codeBlock))
</span><span class="lines">@@ -124,11 +129,11 @@
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx">         
</span><del>-    ASSERT(!hasCrossedThreshold(codeBlock));
</del><ins>+    ASSERT(!m_activeThreshold || !hasCrossedThreshold(codeBlock));
</ins><span class="cx">         
</span><span class="cx">     // Compute the true total count.
</span><span class="cx">     double trueTotalCount = count();
</span><del>-        
</del><ins>+    
</ins><span class="cx">     // Correct the threshold for current memory usage.
</span><span class="cx">     double threshold = applyMemoryUsageHeuristics(m_activeThreshold, codeBlock);
</span><span class="cx">         
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCorebytecodeExecutionCounterh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/bytecode/ExecutionCounter.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/bytecode/ExecutionCounter.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/bytecode/ExecutionCounter.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx"> class ExecutionCounter {
</span><span class="cx"> public:
</span><span class="cx">     ExecutionCounter();
</span><ins>+    void forceSlowPathConcurrently(); // If you use this, checkIfThresholdCrossedAndSet() may still return false.
</ins><span class="cx">     bool checkIfThresholdCrossedAndSet(CodeBlock*);
</span><span class="cx">     void setNewThreshold(int32_t threshold, CodeBlock*);
</span><span class="cx">     void deferIndefinitely();
</span><span class="lines">@@ -74,7 +75,6 @@
</span><span class="cx">     void reset();
</span><span class="cx"> 
</span><span class="cx"> public:
</span><del>-
</del><span class="cx">     // NB. These are intentionally public because it will be modified from machine code.
</span><span class="cx">     
</span><span class="cx">     // This counter is incremented by the JIT or LLInt. It starts out negative and is
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredebuggerDebuggercpp"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/debugger/Debugger.cpp (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/debugger/Debugger.cpp        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/debugger/Debugger.cpp        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -118,6 +118,8 @@
</span><span class="cx">     ASSERT(!vm-&gt;dynamicGlobalObject);
</span><span class="cx">     if (vm-&gt;dynamicGlobalObject)
</span><span class="cx">         return;
</span><ins>+    
+    vm-&gt;prepareToDiscardCode();
</ins><span class="cx"> 
</span><span class="cx">     Recompiler recompiler(this);
</span><span class="cx">     vm-&gt;heap.objectSpace().forEachLiveCell(recompiler);
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -270,7 +270,7 @@
</span><span class="cx">     {
</span><span class="cx">         ASSERT(node-&gt;op() == GetLocal);
</span><span class="cx">         ASSERT(node-&gt;codeOrigin.bytecodeIndex == m_currentIndex);
</span><del>-        CodeBlockLock locker(m_inlineStackTop-&gt;m_profiledBlock-&gt;m_lock);
</del><ins>+        CodeBlockLocker locker(m_inlineStackTop-&gt;m_profiledBlock-&gt;m_lock);
</ins><span class="cx">         LazyOperandValueProfileKey key(m_currentIndex, node-&gt;local());
</span><span class="cx">         SpeculatedType prediction = m_inlineStackTop-&gt;m_lazyOperands.prediction(locker, key);
</span><span class="cx"> #if DFG_ENABLE(DEBUG_VERBOSE)
</span><span class="lines">@@ -843,7 +843,7 @@
</span><span class="cx">     
</span><span class="cx">     ArrayMode getArrayMode(ArrayProfile* profile, Array::Action action)
</span><span class="cx">     {
</span><del>-        CodeBlockLock locker(m_inlineStackTop-&gt;m_profiledBlock-&gt;m_lock);
</del><ins>+        CodeBlockLocker locker(m_inlineStackTop-&gt;m_profiledBlock-&gt;m_lock);
</ins><span class="cx">         profile-&gt;computeUpdatedPrediction(locker, m_inlineStackTop-&gt;m_profiledBlock);
</span><span class="cx">         return ArrayMode::fromObserved(locker, profile, action, false);
</span><span class="cx">     }
</span><span class="lines">@@ -855,7 +855,7 @@
</span><span class="cx">     
</span><span class="cx">     ArrayMode getArrayModeAndEmitChecks(ArrayProfile* profile, Array::Action action, Node* base)
</span><span class="cx">     {
</span><del>-        CodeBlockLock locker(m_inlineStackTop-&gt;m_profiledBlock-&gt;m_lock);
</del><ins>+        CodeBlockLocker locker(m_inlineStackTop-&gt;m_profiledBlock-&gt;m_lock);
</ins><span class="cx">         
</span><span class="cx">         profile-&gt;computeUpdatedPrediction(locker, m_inlineStackTop-&gt;m_profiledBlock);
</span><span class="cx">         
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGCommonh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGCommon.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGCommon.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGCommon.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -154,6 +154,15 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool enableConcurrentJIT()
+{
+#if ENABLE(CONCURRENT_JIT)
+    return Options::enableConcurrentJIT();
+#else
+    return false;
+#endif
+}
+
</ins><span class="cx"> enum SpillRegistersMode { NeedToSpill, DontSpill };
</span><span class="cx"> 
</span><span class="cx"> enum NoResultTag { NoResult };
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGDrivercpp"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGDriver.cpp (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGDriver.cpp        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGDriver.cpp        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -35,11 +35,13 @@
</span><span class="cx"> #include &quot;DFGJITCode.h&quot;
</span><span class="cx"> #include &quot;DFGPlan.h&quot;
</span><span class="cx"> #include &quot;DFGThunks.h&quot;
</span><ins>+#include &quot;DFGWorklist.h&quot;
</ins><span class="cx"> #include &quot;FTLThunks.h&quot;
</span><span class="cx"> #include &quot;JITCode.h&quot;
</span><span class="cx"> #include &quot;Operations.h&quot;
</span><span class="cx"> #include &quot;Options.h&quot;
</span><span class="cx"> #include &quot;SamplingTool.h&quot;
</span><ins>+#include &lt;wtf/Atomics.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="cx"> 
</span><span class="lines">@@ -66,19 +68,21 @@
</span><span class="cx">         return CompilationFailed;
</span><span class="cx">     
</span><span class="cx">     if (logCompilationChanges())
</span><del>-        dataLog(&quot;DFG compiling &quot;, *codeBlock, &quot;, number of instructions = &quot;, codeBlock-&gt;instructionCount(), &quot;\n&quot;);
</del><ins>+        dataLog(&quot;DFG(Driver) compiling &quot;, *codeBlock, &quot;, number of instructions = &quot;, codeBlock-&gt;instructionCount(), &quot;\n&quot;);
</ins><span class="cx">     
</span><ins>+    VM&amp; vm = exec-&gt;vm();
+    
</ins><span class="cx">     // Make sure that any stubs that the DFG is going to use are initialized. We want to
</span><span class="cx">     // make sure that al JIT code generation does finalization on the main thread.
</span><del>-    exec-&gt;vm().getCTIStub(osrExitGenerationThunkGenerator);
-    exec-&gt;vm().getCTIStub(throwExceptionFromCallSlowPathGenerator);
-    exec-&gt;vm().getCTIStub(linkCallThunkGenerator);
-    exec-&gt;vm().getCTIStub(linkConstructThunkGenerator);
-    exec-&gt;vm().getCTIStub(linkClosureCallThunkGenerator);
-    exec-&gt;vm().getCTIStub(virtualCallThunkGenerator);
-    exec-&gt;vm().getCTIStub(virtualConstructThunkGenerator);
</del><ins>+    vm.getCTIStub(osrExitGenerationThunkGenerator);
+    vm.getCTIStub(throwExceptionFromCallSlowPathGenerator);
+    vm.getCTIStub(linkCallThunkGenerator);
+    vm.getCTIStub(linkConstructThunkGenerator);
+    vm.getCTIStub(linkClosureCallThunkGenerator);
+    vm.getCTIStub(virtualCallThunkGenerator);
+    vm.getCTIStub(virtualConstructThunkGenerator);
</ins><span class="cx"> #if ENABLE(FTL_JIT)
</span><del>-    exec-&gt;vm().getCTIStub(FTL::osrExitGenerationThunkGenerator);
</del><ins>+    vm.getCTIStub(FTL::osrExitGenerationThunkGenerator);
</ins><span class="cx"> #endif
</span><span class="cx">     
</span><span class="cx">     // Derive our set of must-handle values. The compilation must be at least conservative
</span><span class="lines">@@ -105,7 +109,16 @@
</span><span class="cx">             plan-&gt;mustHandleValues[i] = exec-&gt;uncheckedR(operand).jsValue();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    plan-&gt;compileInThread();
</del><ins>+    if (enableConcurrentJIT()) {
+        if (!vm.worklist)
+            vm.worklist = globalWorklist();
+        if (logCompilationChanges())
+            dataLog(&quot;Deferring DFG compilation of &quot;, *codeBlock, &quot; with queue length &quot;, vm.worklist-&gt;queueLength(), &quot;.\n&quot;);
+        vm.worklist-&gt;enqueue(plan);
+        return CompilationDeferred;
+    }
+    
+    plan-&gt;compileInThread(*vm.dfgState);
</ins><span class="cx">     return plan-&gt;finalize(jitCode, jitCodeWithArityCheck);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGGraphcpp"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGGraph.cpp (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGGraph.cpp        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGGraph.cpp        2013-05-21 19:10:07 UTC (rev 150465)
</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, 2013 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">@@ -44,12 +44,12 @@
</span><span class="cx"> #undef STRINGIZE_DFG_OP_ENUM
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-Graph::Graph(VM&amp; vm, Plan&amp; plan)
</del><ins>+Graph::Graph(VM&amp; vm, Plan&amp; plan, LongLivedState&amp; longLivedState)
</ins><span class="cx">     : m_vm(vm)
</span><span class="cx">     , m_plan(plan)
</span><span class="cx">     , m_codeBlock(m_plan.codeBlock.get())
</span><span class="cx">     , m_profiledBlock(m_codeBlock-&gt;alternative())
</span><del>-    , m_allocator(vm.m_dfgState-&gt;m_allocator)
</del><ins>+    , m_allocator(longLivedState.m_allocator)
</ins><span class="cx">     , m_hasArguments(false)
</span><span class="cx">     , m_fixpointState(BeforeFixpoint)
</span><span class="cx">     , m_form(LoadStore)
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGGraphh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGGraph.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGGraph.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGGraph.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -90,7 +90,7 @@
</span><span class="cx"> // Nodes that are 'dead' remain in the vector with refCount 0.
</span><span class="cx"> class Graph {
</span><span class="cx"> public:
</span><del>-    Graph(VM&amp;, Plan&amp;);
</del><ins>+    Graph(VM&amp;, Plan&amp;, LongLivedState&amp;);
</ins><span class="cx">     ~Graph();
</span><span class="cx">     
</span><span class="cx">     void changeChild(Edge&amp; edge, Node* newNode)
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGOSREntrycpp"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGOSREntry.cpp (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGOSREntry.cpp        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGOSREntry.cpp        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -45,17 +45,18 @@
</span><span class="cx">     ASSERT(codeBlock-&gt;alternative()-&gt;getJITType() == JITCode::BaselineJIT);
</span><span class="cx">     ASSERT(!codeBlock-&gt;jitCodeMap());
</span><span class="cx"> 
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-    dataLog(&quot;OSR in &quot;, *codeBlock-&gt;alternative(), &quot; -&gt; &quot;, *codeBlock, &quot; from bc#&quot;, bytecodeIndex, &quot;\n&quot;);
-#endif
</del><ins>+    if (Options::verboseOSR()) {
+        dataLog(
+            &quot;OSR in &quot;, *codeBlock-&gt;alternative(), &quot; -&gt; &quot;, *codeBlock,
+            &quot; from bc#&quot;, bytecodeIndex, &quot;\n&quot;);
+    }
</ins><span class="cx">     
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     OSREntryData* entry = codeBlock-&gt;getJITCode()-&gt;dfg()-&gt;osrEntryDataForBytecodeIndex(bytecodeIndex);
</span><span class="cx">     
</span><span class="cx">     if (!entry) {
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-        dataLogF(&quot;    OSR failed because the entrypoint was optimized out.\n&quot;);
-#endif
</del><ins>+        if (Options::verboseOSR())
+            dataLogF(&quot;    OSR failed because the entrypoint was optimized out.\n&quot;);
</ins><span class="cx">         return 0;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -87,11 +88,11 @@
</span><span class="cx">     
</span><span class="cx">     for (size_t argument = 0; argument &lt; entry-&gt;m_expectedValues.numberOfArguments(); ++argument) {
</span><span class="cx">         if (argument &gt;= exec-&gt;argumentCountIncludingThis()) {
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-            dataLogF(&quot;    OSR failed because argument %zu was not passed, expected &quot;, argument);
-            entry-&gt;m_expectedValues.argument(argument).dump(WTF::dataFile());
-            dataLogF(&quot;.\n&quot;);
-#endif
</del><ins>+            if (Options::verboseOSR()) {
+                dataLogF(&quot;    OSR failed because argument %zu was not passed, expected &quot;, argument);
+                entry-&gt;m_expectedValues.argument(argument).dump(WTF::dataFile());
+                dataLogF(&quot;.\n&quot;);
+            }
</ins><span class="cx">             return 0;
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="lines">@@ -102,9 +103,11 @@
</span><span class="cx">             value = exec-&gt;argument(argument - 1);
</span><span class="cx">         
</span><span class="cx">         if (!entry-&gt;m_expectedValues.argument(argument).validate(value)) {
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-            dataLog(&quot;    OSR failed because argument &quot;, argument, &quot; is &quot;, value, &quot;, expected &quot;, entry-&gt;m_expectedValues.argument(argument), &quot;.\n&quot;);
-#endif
</del><ins>+            if (Options::verboseOSR()) {
+                dataLog(
+                    &quot;    OSR failed because argument &quot;, argument, &quot; is &quot;, value,
+                    &quot;, expected &quot;, entry-&gt;m_expectedValues.argument(argument), &quot;.\n&quot;);
+            }
</ins><span class="cx">             return 0;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -112,17 +115,22 @@
</span><span class="cx">     for (size_t local = 0; local &lt; entry-&gt;m_expectedValues.numberOfLocals(); ++local) {
</span><span class="cx">         if (entry-&gt;m_localsForcedDouble.get(local)) {
</span><span class="cx">             if (!exec-&gt;registers()[local].jsValue().isNumber()) {
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-                dataLog(&quot;    OSR failed because variable &quot;, local, &quot; is &quot;, exec-&gt;registers()[local].jsValue(), &quot;, expected number.\n&quot;);
-#endif
</del><ins>+                if (Options::verboseOSR()) {
+                    dataLog(
+                        &quot;    OSR failed because variable &quot;, local, &quot; is &quot;,
+                        exec-&gt;registers()[local].jsValue(), &quot;, expected number.\n&quot;);
+                }
</ins><span class="cx">                 return 0;
</span><span class="cx">             }
</span><span class="cx">             continue;
</span><span class="cx">         }
</span><span class="cx">         if (!entry-&gt;m_expectedValues.local(local).validate(exec-&gt;registers()[local].jsValue())) {
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-            dataLog(&quot;    OSR failed because variable &quot;, local, &quot; is &quot;, exec-&gt;registers()[local].jsValue(), &quot;, expected &quot;, entry-&gt;m_expectedValues.local(local), &quot;.\n&quot;);
-#endif
</del><ins>+            if (Options::verboseOSR()) {
+                dataLog(
+                    &quot;    OSR failed because variable &quot;, local, &quot; is &quot;,
+                    exec-&gt;registers()[local].jsValue(), &quot;, expected &quot;,
+                    entry-&gt;m_expectedValues.local(local), &quot;.\n&quot;);
+            }
</ins><span class="cx">             return 0;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -135,15 +143,13 @@
</span><span class="cx">     //    would have otherwise just kept running albeit less quickly.
</span><span class="cx">     
</span><span class="cx">     if (!vm-&gt;interpreter-&gt;stack().grow(&amp;exec-&gt;registers()[codeBlock-&gt;m_numCalleeRegisters])) {
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-        dataLogF(&quot;    OSR failed because stack growth failed.\n&quot;);
-#endif
</del><ins>+        if (Options::verboseOSR())
+            dataLogF(&quot;    OSR failed because stack growth failed.\n&quot;);
</ins><span class="cx">         return 0;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-    dataLogF(&quot;    OSR should succeed.\n&quot;);
-#endif
</del><ins>+    if (Options::verboseOSR())
+        dataLogF(&quot;    OSR should succeed.\n&quot;);
</ins><span class="cx">     
</span><span class="cx">     // 3) Perform data format conversions.
</span><span class="cx">     for (size_t local = 0; local &lt; entry-&gt;m_expectedValues.numberOfLocals(); ++local) {
</span><span class="lines">@@ -159,9 +165,8 @@
</span><span class="cx">     
</span><span class="cx">     void* result = codeBlock-&gt;getJITCode()-&gt;executableAddressAtOffset(entry-&gt;m_machineCodeOffset);
</span><span class="cx">     
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-    dataLogF(&quot;    OSR returning machine code address %p.\n&quot;, result);
-#endif
</del><ins>+    if (Options::verboseOSR())
+        dataLogF(&quot;    OSR returning machine code address %p.\n&quot;, result);
</ins><span class="cx">     
</span><span class="cx">     return result;
</span><span class="cx"> #else // DFG_ENABLE(OSR_ENTRY)
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGOperations.cpp (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGOperations.cpp        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGOperations.cpp        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -1686,9 +1686,8 @@
</span><span class="cx"> 
</span><span class="cx"> extern &quot;C&quot; void DFG_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock)
</span><span class="cx"> {
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-    dataLog(*codeBlock, &quot;: Entered reoptimize\n&quot;);
-#endif
</del><ins>+    if (Options::verboseOSR())
+        dataLog(*codeBlock, &quot;: Entered reoptimize\n&quot;);
</ins><span class="cx">     // We must be called with the baseline code block.
</span><span class="cx">     ASSERT(JITCode::isBaselineCode(codeBlock-&gt;getJITType()));
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGPlancpp"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGPlan.cpp (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGPlan.cpp        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGPlan.cpp        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -78,6 +78,7 @@
</span><span class="cx">     , mustHandleValues(codeBlock-&gt;numParameters(), numVarsWithValues)
</span><span class="cx">     , compilation(codeBlock-&gt;vm()-&gt;m_perBytecodeProfiler ? adoptRef(new Profiler::Compilation(codeBlock-&gt;vm()-&gt;m_perBytecodeProfiler-&gt;ensureBytecodesFor(codeBlock.get()), Profiler::DFG)) : 0)
</span><span class="cx">     , identifiers(codeBlock.get())
</span><ins>+    , isCompiled(false)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -85,12 +86,15 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Plan::compileInThread()
</del><ins>+void Plan::compileInThread(LongLivedState&amp; longLivedState)
</ins><span class="cx"> {
</span><span class="cx">     SamplingRegion samplingRegion(&quot;DFG Compilation (Plan)&quot;);
</span><span class="cx">     CompilationScope compilationScope;
</span><span class="cx"> 
</span><del>-    Graph dfg(vm, *this);
</del><ins>+    if (logCompilationChanges())
+        dataLog(&quot;DFG(Plan) compiling &quot;, *codeBlock, &quot;, number of instructions = &quot;, codeBlock-&gt;instructionCount(), &quot;\n&quot;);
+
+    Graph dfg(vm, *this, longLivedState);
</ins><span class="cx">     
</span><span class="cx">     if (!parse(dfg)) {
</span><span class="cx">         finalizer = adoptPtr(new FailedFinalizer(*this));
</span><span class="lines">@@ -199,6 +203,11 @@
</span><span class="cx">     return CompilationSuccessful;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+CodeBlock* Plan::key()
+{
+    return codeBlock-&gt;alternative();
+}
+
</ins><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(DFG_JIT)
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGPlanh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGPlan.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGPlan.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGPlan.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -43,6 +43,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace DFG {
</span><span class="cx"> 
</span><ins>+class LongLivedState;
+
</ins><span class="cx"> enum CompileMode { CompileFunction, CompileOther };
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="lines">@@ -53,10 +55,12 @@
</span><span class="cx">         unsigned osrEntryBytecodeIndex, unsigned numVarsWithValues);
</span><span class="cx">     ~Plan();
</span><span class="cx">     
</span><del>-    void compileInThread();
</del><ins>+    void compileInThread(LongLivedState&amp;);
</ins><span class="cx">     
</span><span class="cx">     CompilationResult finalize(RefPtr&lt;JSC::JITCode&gt;&amp; jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck);
</span><span class="cx">     
</span><ins>+    CodeBlock* key();
+    
</ins><span class="cx">     const CompileMode compileMode;
</span><span class="cx">     VM&amp; vm;
</span><span class="cx">     RefPtr&lt;CodeBlock&gt; codeBlock;
</span><span class="lines">@@ -71,6 +75,8 @@
</span><span class="cx">     DesiredWatchpoints watchpoints;
</span><span class="cx">     DesiredIdentifiers identifiers;
</span><span class="cx">     DesiredStructureChains chains;
</span><ins>+    
+    bool isCompiled;
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     bool isStillValid();
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGWorklistcpp"></a>
<div class="addfile"><h4>Added: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGWorklist.cpp (0 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGWorklist.cpp                                (rev 0)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGWorklist.cpp        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -0,0 +1,258 @@
</span><ins>+/*
+ * Copyright (C) 2013 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;DFGWorklist.h&quot;
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;CodeBlock.h&quot;
+#include &quot;DeferGC.h&quot;
+#include &quot;DFGLongLivedState.h&quot;
+
+namespace JSC { namespace DFG {
+
+Worklist::Worklist()
+{
+}
+
+Worklist::~Worklist()
+{
+    m_queue.append(nullptr); // Use null plan to indicate that we want the thread to terminate.
+    waitForThreadCompletion(m_thread);
+}
+
+void Worklist::finishCreation()
+{
+    m_thread = createThread(threadFunction, this, &quot;JSC Compilation Thread&quot;);
+}
+
+PassRefPtr&lt;Worklist&gt; Worklist::create()
+{
+    RefPtr&lt;Worklist&gt; result = adoptRef(new Worklist());
+    result-&gt;finishCreation();
+    return result;
+}
+
+void Worklist::enqueue(PassRefPtr&lt;Plan&gt; passedPlan)
+{
+    RefPtr&lt;Plan&gt; plan = passedPlan;
+    MutexLocker locker(m_lock);
+    if (Options::verboseCompilationQueue()) {
+        dump(locker, WTF::dataFile());
+        dataLog(&quot;: Enqueueing plan to optimize &quot;, *plan-&gt;key(), &quot;\n&quot;);
+    }
+    ASSERT(m_plans.find(plan-&gt;key()) == m_plans.end());
+    m_plans.add(plan-&gt;key(), plan);
+    m_queue.append(plan);
+    m_condition.broadcast();
+}
+
+Worklist::State Worklist::compilationState(CodeBlock* profiledBlock)
+{
+    MutexLocker locker(m_lock);
+    PlanMap::iterator iter = m_plans.find(profiledBlock);
+    if (iter == m_plans.end())
+        return NotKnown;
+    return iter-&gt;value-&gt;isCompiled ? Compiled : Compiling;
+}
+
+void Worklist::waitUntilAllPlansForVMAreReady(VM&amp; vm)
+{
+    DeferGC deferGC(vm.heap);
+    // Wait for all of the plans for the given VM to complete. The idea here
+    // is that we want all of the caller VM's plans to be done. We don't care
+    // about any other VM's plans, and we won't attempt to wait on those.
+    // After we release this lock, we know that although other VMs may still
+    // be adding plans, our VM will not be.
+    
+    MutexLocker locker(m_lock);
+    
+    if (Options::verboseCompilationQueue()) {
+        dump(locker, WTF::dataFile());
+        dataLog(&quot;: Waiting for all in VM to complete.\n&quot;);
+    }
+    
+    for (;;) {
+        bool allAreCompiled = true;
+        PlanMap::iterator end = m_plans.end();
+        for (PlanMap::iterator iter = m_plans.begin(); iter != end; ++iter) {
+            if (&amp;iter-&gt;value-&gt;vm != &amp;vm)
+                continue;
+            if (!iter-&gt;value-&gt;isCompiled) {
+                allAreCompiled = false;
+                break;
+            }
+        }
+        
+        if (allAreCompiled)
+            break;
+        
+        m_condition.wait(m_lock);
+    }
+}
+
+void Worklist::removeAllReadyPlansForVM(VM&amp; vm, Vector&lt;RefPtr&lt;Plan&gt;, 8&gt;&amp; myReadyPlans)
+{
+    DeferGC deferGC(vm.heap);
+    MutexLocker locker(m_lock);
+    for (size_t i = 0; i &lt; m_readyPlans.size(); ++i) {
+        RefPtr&lt;Plan&gt; plan = m_readyPlans[i];
+        if (&amp;plan-&gt;vm != &amp;vm)
+            continue;
+        if (!plan-&gt;isCompiled)
+            continue;
+        myReadyPlans.append(plan);
+        m_readyPlans[i--] = m_readyPlans.takeLast();
+        m_plans.remove(plan-&gt;key());
+    }
+}
+
+void Worklist::removeAllReadyPlansForVM(VM&amp; vm)
+{
+    Vector&lt;RefPtr&lt;Plan&gt;, 8&gt; myReadyPlans;
+    removeAllReadyPlansForVM(vm, myReadyPlans);
+}
+
+Worklist::State Worklist::completeAllReadyPlansForVM(VM&amp; vm, CodeBlock* requestedProfiledBlock)
+{
+    DeferGC deferGC(vm.heap);
+    Vector&lt;RefPtr&lt;Plan&gt;, 8&gt; myReadyPlans;
+    
+    removeAllReadyPlansForVM(vm, myReadyPlans);
+    
+    State resultingState = NotKnown;
+
+    while (!myReadyPlans.isEmpty()) {
+        RefPtr&lt;Plan&gt; plan = myReadyPlans.takeLast();
+        CodeBlock* profiledBlock = plan-&gt;key();
+        
+        if (Options::verboseCompilationQueue())
+            dataLog(*this, &quot;: Completing &quot;, *profiledBlock, &quot;\n&quot;);
+        
+        RELEASE_ASSERT(plan-&gt;isCompiled);
+        
+        CompilationResult compilationResult =
+            profiledBlock-&gt;replaceWithDeferredOptimizedCode(plan);
+        RELEASE_ASSERT(compilationResult != CompilationDeferred);
+        profiledBlock-&gt;setOptimizationThresholdBasedOnCompilationResult(compilationResult);
+        
+        if (profiledBlock == requestedProfiledBlock)
+            resultingState = Compiled;
+    }
+    
+    if (requestedProfiledBlock &amp;&amp; resultingState == NotKnown) {
+        MutexLocker locker(m_lock);
+        if (m_plans.contains(requestedProfiledBlock))
+            resultingState = Compiling;
+    }
+    
+    return resultingState;
+}
+
+void Worklist::completeAllPlansForVM(VM&amp; vm)
+{
+    DeferGC deferGC(vm.heap);
+    waitUntilAllPlansForVMAreReady(vm);
+    completeAllReadyPlansForVM(vm);
+}
+
+size_t Worklist::queueLength()
+{
+    MutexLocker locker(m_lock);
+    return m_queue.size();
+}
+
+void Worklist::dump(PrintStream&amp; out) const
+{
+    MutexLocker locker(m_lock);
+    dump(locker, out);
+}
+
+void Worklist::dump(const MutexLocker&amp;, PrintStream&amp; out) const
+{
+    out.print(
+        &quot;Worklist(&quot;, RawPointer(this), &quot;)[Queue Length = &quot;, m_queue.size(),
+        &quot;, Map Size = &quot;, m_plans.size(), &quot;]&quot;);
+}
+
+void Worklist::runThread()
+{
+    LongLivedState longLivedState;
+    
+    for (;;) {
+        RefPtr&lt;Plan&gt; plan;
+        {
+            MutexLocker locker(m_lock);
+            while (m_queue.isEmpty())
+                m_condition.wait(m_lock);
+            plan = m_queue.takeFirst();
+        }
+        
+        if (!plan)
+            return;
+        
+        plan-&gt;compileInThread(longLivedState);
+        
+        {
+            MutexLocker locker(m_lock);
+            plan-&gt;key()-&gt;forceOptimizationSlowPathConcurrently();
+            plan-&gt;isCompiled = true;
+            
+            if (Options::verboseCompilationQueue()) {
+                dump(locker, WTF::dataFile());
+                dataLog(&quot;: Compiled &quot;, *plan-&gt;key(), &quot; asynchronously\n&quot;);
+            }
+            
+            m_readyPlans.append(plan);
+            
+            m_condition.broadcast();
+        }
+    }
+}
+
+void Worklist::threadFunction(void* argument)
+{
+    static_cast&lt;Worklist*&gt;(argument)-&gt;runThread();
+}
+
+static pthread_once_t initializeGlobalWorklistKeyOnce = PTHREAD_ONCE_INIT;
+static Worklist* theGlobalWorklist;
+
+static void initializeGlobalWorklistOnce()
+{
+    theGlobalWorklist = Worklist::create().leakRef();
+}
+
+Worklist* globalWorklist()
+{
+    pthread_once(&amp;initializeGlobalWorklistKeyOnce, initializeGlobalWorklistOnce);
+    return theGlobalWorklist;
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
</ins></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoredfgDFGWorklisth"></a>
<div class="addfile"><h4>Added: branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGWorklist.h (0 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGWorklist.h                                (rev 0)
+++ branches/dfgFourthTier/Source/JavaScriptCore/dfg/DFGWorklist.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -0,0 +1,110 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGWorklist_h
+#define DFGWorklist_h
+
+#include &lt;wtf/Platform.h&gt;
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGPlan.h&quot;
+#include &lt;wtf/Deque.h&gt;
+#include &lt;wtf/HashMap.h&gt;
+#include &lt;wtf/Noncopyable.h&gt;
+#include &lt;wtf/PassOwnPtr.h&gt;
+#include &lt;wtf/ThreadingPrimitives.h&gt;
+
+namespace JSC { namespace DFG {
+
+class Worklist : public RefCounted&lt;Worklist&gt; {
+public:
+    enum State { NotKnown, Compiling, Compiled };
+
+    ~Worklist();
+    
+    static PassRefPtr&lt;Worklist&gt; create();
+    
+    void enqueue(PassRefPtr&lt;Plan&gt;);
+    
+    // This is equivalent to:
+    // worklist-&gt;waitUntilAllPlansForVMAreReady(vm);
+    // worklist-&gt;completeAllReadyPlansForVM(vm);
+    void completeAllPlansForVM(VM&amp;);
+    
+    void waitUntilAllPlansForVMAreReady(VM&amp;);
+    State completeAllReadyPlansForVM(VM&amp;, CodeBlock* profiledBlock = 0);
+    void removeAllReadyPlansForVM(VM&amp;);
+    
+    State compilationState(CodeBlock* profiledBlock);
+    
+    size_t queueLength();
+    void dump(PrintStream&amp;) const;
+    
+private:
+    Worklist();
+    void finishCreation();
+    
+    void runThread();
+    static void threadFunction(void* argument);
+    
+    void removeAllReadyPlansForVM(VM&amp;, Vector&lt;RefPtr&lt;Plan&gt;, 8&gt;&amp;);
+
+    void dump(const MutexLocker&amp;, PrintStream&amp;) const;
+
+    // Used to inform the thread about what work there is left to do.
+    Deque&lt;RefPtr&lt;Plan&gt;, 16&gt; m_queue;
+    
+    // Used to answer questions about the current state of a code block. This
+    // is particularly great for the cti_optimize OSR slow path, which wants
+    // to know: did I get here because a better version of me just got
+    // compiled?
+    typedef HashMap&lt;RefPtr&lt;CodeBlock&gt;, RefPtr&lt;Plan&gt; &gt; PlanMap;
+    PlanMap m_plans;
+    
+    // Used to quickly find which plans have been compiled and are ready to
+    // be completed.
+    Vector&lt;RefPtr&lt;Plan&gt;, 16&gt; m_readyPlans;
+    
+    mutable Mutex m_lock;
+    // We broadcast on this condition whenever:
+    // - Something is enqueued.
+    // - Something is completed.
+    ThreadCondition m_condition;
+    ThreadIdentifier m_thread;
+};
+
+// For now we use a single global worklist. It's not clear that this
+// is the right thing to do, but it is what we do, for now. This function
+// will lazily create one when it's needed. Currently this is only called
+// from DFGDriver.cpp, when it actually wants to enqueue something.
+Worklist* globalWorklist();
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGWorklist_h
+
</ins></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoreheapCopiedSpaceInlinesh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/heap/CopiedSpaceInlines.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/heap/CopiedSpaceInlines.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/heap/CopiedSpaceInlines.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -135,8 +135,7 @@
</span><span class="cx"> 
</span><span class="cx"> inline void CopiedSpace::allocateBlock()
</span><span class="cx"> {
</span><del>-    if (m_heap-&gt;shouldCollect())
-        m_heap-&gt;collect(Heap::DoNotSweep);
</del><ins>+    m_heap-&gt;collectIfNecessaryOrDefer();
</ins><span class="cx"> 
</span><span class="cx">     m_allocator.resetCurrentBlock();
</span><span class="cx">     
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoreheapDeferGCh"></a>
<div class="addfile"><h4>Added: branches/dfgFourthTier/Source/JavaScriptCore/heap/DeferGC.h (0 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/heap/DeferGC.h                                (rev 0)
+++ branches/dfgFourthTier/Source/JavaScriptCore/heap/DeferGC.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -0,0 +1,55 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DeferGC_h
+#define DeferGC_h
+
+#include &quot;Heap.h&quot;
+#include &lt;wtf/Noncopyable.h&gt;
+
+namespace JSC {
+
+class DeferGC {
+    WTF_MAKE_NONCOPYABLE(DeferGC);
+public:
+    DeferGC(Heap&amp; heap)
+        : m_heap(heap)
+    {
+        m_heap.incrementDeferralDepth();
+    }
+    
+    ~DeferGC()
+    {
+        m_heap.decrementDeferralDepthAndGCIfNeeded();
+    }
+
+private:
+    Heap&amp; m_heap;
+};
+
+} // namespace JSC
+
+#endif // DeferGC_h
+
</ins></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/heap/Heap.cpp (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/heap/Heap.cpp        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/heap/Heap.cpp        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2013 Apple Inc. All rights reserved.
</ins><span class="cx">  *  Copyright (C) 2007 Eric Seidel &lt;eric@webkit.org&gt;
</span><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #include &quot;CopiedSpace.h&quot;
</span><span class="cx"> #include &quot;CopiedSpaceInlines.h&quot;
</span><span class="cx"> #include &quot;CopyVisitorInlines.h&quot;
</span><ins>+#include &quot;DFGWorklist.h&quot;
</ins><span class="cx"> #include &quot;GCActivityCallback.h&quot;
</span><span class="cx"> #include &quot;HeapRootVisitor.h&quot;
</span><span class="cx"> #include &quot;HeapStatistics.h&quot;
</span><span class="lines">@@ -263,6 +264,7 @@
</span><span class="cx">     , m_lastCodeDiscardTime(WTF::currentTime())
</span><span class="cx">     , m_activityCallback(DefaultGCActivityCallback::create(this))
</span><span class="cx">     , m_sweeper(IncrementalSweeper::create(this))
</span><ins>+    , m_deferralDepth(0)
</ins><span class="cx"> {
</span><span class="cx">     m_storageSpace.init();
</span><span class="cx"> }
</span><span class="lines">@@ -305,8 +307,7 @@
</span><span class="cx">     // collecting more frequently as long as it stays alive.
</span><span class="cx"> 
</span><span class="cx">     didAllocate(cost);
</span><del>-    if (shouldCollect())
-        collect(DoNotSweep);
</del><ins>+    collectIfNecessaryOrDefer();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Heap::reportAbandonedObjectGraph()
</span><span class="lines">@@ -687,7 +688,7 @@
</span><span class="cx"> {
</span><span class="cx">     if (!m_isSafeToCollect)
</span><span class="cx">         return;
</span><del>-
</del><ins>+    
</ins><span class="cx">     collect(DoSweep);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -697,12 +698,18 @@
</span><span class="cx"> {
</span><span class="cx">     SamplingRegion samplingRegion(&quot;Garbage Collection&quot;);
</span><span class="cx">     
</span><ins>+    RELEASE_ASSERT(!m_deferralDepth);
</ins><span class="cx">     GCPHASE(Collect);
</span><span class="cx">     ASSERT(vm()-&gt;apiLock().currentThreadIsHoldingLock());
</span><span class="cx">     RELEASE_ASSERT(vm()-&gt;identifierTable == wtfThreadData().currentIdentifierTable());
</span><span class="cx">     ASSERT(m_isSafeToCollect);
</span><span class="cx">     JAVASCRIPTCORE_GC_BEGIN();
</span><span class="cx">     RELEASE_ASSERT(m_operationInProgress == NoOperation);
</span><ins>+    
+    m_deferralDepth++; // Make sure that we don't GC in this call.
+    m_vm-&gt;prepareToDiscardCode();
+    m_deferralDepth--; // Decrement deferal manually, so we don't GC when we do so, since we are already GCing!.
+    
</ins><span class="cx">     m_operationInProgress = Collection;
</span><span class="cx"> 
</span><span class="cx">     m_activityCallback-&gt;willCollect();
</span><span class="lines">@@ -803,6 +810,18 @@
</span><span class="cx">         HeapStatistics::showObjectStatistics(this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool Heap::collectIfNecessaryOrDefer()
+{
+    if (m_deferralDepth)
+        return false;
+    
+    if (!shouldCollect())
+        return false;
+    
+    collect(DoNotSweep);
+    return true;
+}
+
</ins><span class="cx"> void Heap::markDeadObjects()
</span><span class="cx"> {
</span><span class="cx">     m_objectSpace.forEachDeadCell&lt;MarkObject&gt;();
</span><span class="lines">@@ -896,4 +915,20 @@
</span><span class="cx">     m_objectSpace.forEachDeadCell&lt;Zombify&gt;();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Heap::incrementDeferralDepth()
+{
+    RELEASE_ASSERT(m_deferralDepth &lt; 100); // Sanity check to make sure this doesn't get ridiculous.
+    
+    m_deferralDepth++;
+}
+
+void Heap::decrementDeferralDepthAndGCIfNeeded()
+{
+    RELEASE_ASSERT(m_deferralDepth &gt;= 1);
+    
+    m_deferralDepth--;
+    
+    collectIfNecessaryOrDefer();
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/heap/Heap.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/heap/Heap.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/heap/Heap.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
</span><span class="cx">  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
</span><del>- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 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">@@ -110,6 +110,8 @@
</span><span class="cx"> 
</span><span class="cx">         JS_EXPORT_PRIVATE IncrementalSweeper* sweeper();
</span><span class="cx"> 
</span><ins>+        // true if collection is in progress
+        inline bool isCollecting();
</ins><span class="cx">         // true if an allocation or collection is in progress
</span><span class="cx">         inline bool isBusy();
</span><span class="cx">         
</span><span class="lines">@@ -131,6 +133,7 @@
</span><span class="cx">         enum SweepToggle { DoNotSweep, DoSweep };
</span><span class="cx">         bool shouldCollect();
</span><span class="cx">         void collect(SweepToggle);
</span><ins>+        bool collectIfNecessaryOrDefer(); // Returns true if it did collect.
</ins><span class="cx"> 
</span><span class="cx">         void reportExtraMemoryCost(size_t cost);
</span><span class="cx">         JS_EXPORT_PRIVATE void reportAbandonedObjectGraph();
</span><span class="lines">@@ -179,6 +182,7 @@
</span><span class="cx">     private:
</span><span class="cx">         friend class CodeBlock;
</span><span class="cx">         friend class CopiedBlock;
</span><ins>+        friend class DeferGC;
</ins><span class="cx">         friend class GCAwareJITStubRoutine;
</span><span class="cx">         friend class JITStubRoutine;
</span><span class="cx">         friend class LLIntOffsetsExtractor;
</span><span class="lines">@@ -220,6 +224,9 @@
</span><span class="cx"> 
</span><span class="cx">         JSStack&amp; stack();
</span><span class="cx">         BlockAllocator&amp; blockAllocator();
</span><ins>+        
+        void incrementDeferralDepth();
+        void decrementDeferralDepthAndGCIfNeeded();
</ins><span class="cx"> 
</span><span class="cx">         const HeapType m_heapType;
</span><span class="cx">         const size_t m_ramSize;
</span><span class="lines">@@ -266,6 +273,8 @@
</span><span class="cx">         GCActivityCallback* m_activityCallback;
</span><span class="cx">         IncrementalSweeper* m_sweeper;
</span><span class="cx">         Vector&lt;MarkedBlock*&gt; m_blockSnapshot;
</span><ins>+        
+        unsigned m_deferralDepth;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     struct MarkedBlockSnapshotFunctor : public MarkedBlock::VoidFunctor {
</span><span class="lines">@@ -293,6 +302,11 @@
</span><span class="cx">         return m_operationInProgress != NoOperation;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool Heap::isCollecting()
+    {
+        return m_operationInProgress == Collection;
+    }
+
</ins><span class="cx">     inline Heap* Heap::heap(const JSCell* cell)
</span><span class="cx">     {
</span><span class="cx">         return MarkedBlock::blockFor(cell)-&gt;heap();
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoreheapMarkedAllocatorcpp"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/heap/MarkedAllocator.cpp (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/heap/MarkedAllocator.cpp        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/heap/MarkedAllocator.cpp        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -84,9 +84,7 @@
</span><span class="cx">     if (LIKELY(result != 0))
</span><span class="cx">         return result;
</span><span class="cx">     
</span><del>-    if (m_heap-&gt;shouldCollect()) {
-        m_heap-&gt;collect(Heap::DoNotSweep);
-
</del><ins>+    if (m_heap-&gt;collectIfNecessaryOrDefer()) {
</ins><span class="cx">         result = tryAllocate(bytes);
</span><span class="cx">         if (result)
</span><span class="cx">             return result;
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/jit/JIT.cpp (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/jit/JIT.cpp        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/jit/JIT.cpp        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -601,10 +601,6 @@
</span><span class="cx"> 
</span><span class="cx"> PassRefPtr&lt;JITCode&gt; JIT::privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffort effort)
</span><span class="cx"> {
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-    printf(&quot;Compiling JIT code!\n&quot;);
-#endif
-    
</del><span class="cx"> #if ENABLE(VALUE_PROFILER)
</span><span class="cx">     DFG::CapabilityLevel level = m_codeBlock-&gt;canCompileWithDFG();
</span><span class="cx">     switch (level) {
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/jit/JIT.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/jit/JIT.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/jit/JIT.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -28,11 +28,6 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> 
</span><del>-// Verbose logging of code generation
-#define ENABLE_JIT_VERBOSE 0
-// Verbose logging for OSR-related code.
-#define ENABLE_JIT_VERBOSE_OSR 0
-
</del><span class="cx"> // We've run into some problems where changing the size of the class JIT leads to
</span><span class="cx"> // performance fluctuations.  Try forcing alignment in an attempt to stabalize this.
</span><span class="cx"> #if COMPILER(GCC)
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCorejitJITStubscpp"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/jit/JITStubs.cpp (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/jit/JITStubs.cpp        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/jit/JITStubs.cpp        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx"> #include &quot;CodeProfiling.h&quot;
</span><span class="cx"> #include &quot;CommonSlowPaths.h&quot;
</span><span class="cx"> #include &quot;DFGOSREntry.h&quot;
</span><ins>+#include &quot;DFGWorklist.h&quot;
</ins><span class="cx"> #include &quot;Debugger.h&quot;
</span><span class="cx"> #include &quot;ExceptionHelpers.h&quot;
</span><span class="cx"> #include &quot;GetterSetter.h&quot;
</span><span class="lines">@@ -906,31 +907,83 @@
</span><span class="cx">     CodeBlock* codeBlock = callFrame-&gt;codeBlock();
</span><span class="cx">     unsigned bytecodeIndex = stackFrame.args[0].int32();
</span><span class="cx"> 
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-    dataLog(
-        *codeBlock, &quot;: Entered optimize with bytecodeIndex = &quot;, bytecodeIndex,
-        &quot;, executeCounter = &quot;, codeBlock-&gt;jitExecuteCounter(),
-        &quot;, optimizationDelayCounter = &quot;, codeBlock-&gt;reoptimizationRetryCounter(),
-        &quot;, exitCounter = &quot;);
-    if (codeBlock-&gt;hasOptimizedReplacement())
-        dataLog(codeBlock-&gt;replacement()-&gt;osrExitCounter());
-    else
-        dataLog(&quot;N/A&quot;);
-    dataLog(&quot;\n&quot;);
-#endif
</del><ins>+    if (Options::verboseOSR()) {
+        dataLog(
+            *codeBlock, &quot;: Entered optimize with bytecodeIndex = &quot;, bytecodeIndex,
+            &quot;, executeCounter = &quot;, codeBlock-&gt;jitExecuteCounter(),
+            &quot;, optimizationDelayCounter = &quot;, codeBlock-&gt;reoptimizationRetryCounter(),
+            &quot;, exitCounter = &quot;);
+        if (codeBlock-&gt;hasOptimizedReplacement())
+            dataLog(codeBlock-&gt;replacement()-&gt;osrExitCounter());
+        else
+            dataLog(&quot;N/A&quot;);
+        dataLog(&quot;\n&quot;);
+    }
</ins><span class="cx"> 
</span><span class="cx">     if (!codeBlock-&gt;checkIfOptimizationThresholdReached()) {
</span><span class="cx">         codeBlock-&gt;updateAllPredictions();
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-        dataLog(&quot;Choosing not to optimize &quot;, *codeBlock, &quot; yet.\n&quot;);
-#endif
</del><ins>+        if (Options::verboseOSR())
+            dataLog(&quot;Choosing not to optimize &quot;, *codeBlock, &quot; yet.\n&quot;);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><del>-
-    if (codeBlock-&gt;hasOptimizedReplacement()) {
-#if ENABLE(JIT_VERBOSE_OSR)
-        dataLog(&quot;Considering OSR &quot;, *codeBlock, &quot; -&gt; &quot;, *codeBlock-&gt;replacement(), &quot;.\n&quot;);
-#endif
</del><ins>+    
+    // We cannot be in the process of asynchronous compilation and also have an optimized
+    // replacement.
+    ASSERT(
+        !stackFrame.vm-&gt;worklist
+        || !(stackFrame.vm-&gt;worklist-&gt;compilationState(codeBlock) != DFG::Worklist::NotKnown
+             &amp;&amp; codeBlock-&gt;hasOptimizedReplacement()));
+    
+    DFG::Worklist::State worklistState;
+    if (stackFrame.vm-&gt;worklist) {
+        // The call to DFG::Worklist::completeAllReadyPlansForVM() will complete all ready
+        // (i.e. compiled) code blocks. But if it completes ours, we also need to know
+        // what the result was so that we don't plow ahead and attempt OSR or immediate
+        // reoptimization. This will have already also set the appropriate JIT execution
+        // count threshold depending on what happened, so if the compilation was anything
+        // but successful we just want to return early. See the case for worklistState ==
+        // DFG::Worklist::Compiled, below.
+        
+        // Note that we could have alternatively just called Worklist::compilationState()
+        // here, and if it returned Compiled, we could have then called
+        // completeAndScheduleOSR() below. But that would have meant that it could take
+        // longer for code blocks to be completed: they would only complete when *their*
+        // execution count trigger fired; but that could take a while since the firing is
+        // racy. It could also mean that code blocks that never run again after being
+        // compiled would sit on the worklist until next GC. That's fine, but it's
+        // probably a waste of memory. Our goal here is to complete code blocks as soon as
+        // possible in order to minimize the chances of us executing baseline code after
+        // optimized code is already available.
+        
+        worklistState =
+            stackFrame.vm-&gt;worklist-&gt;completeAllReadyPlansForVM(*stackFrame.vm, codeBlock);
+    } else
+        worklistState = DFG::Worklist::NotKnown;
+    
+    if (worklistState == DFG::Worklist::Compiling) {
+        // We cannot be in the process of asynchronous compilation and also have an optimized
+        // replacement.
+        RELEASE_ASSERT(!codeBlock-&gt;hasOptimizedReplacement());
+        codeBlock-&gt;setOptimizationThresholdBasedOnCompilationResult(CompilationDeferred);
+        return;
+    }
+    
+    if (worklistState == DFG::Worklist::Compiled) {
+        // If we don't have an optimized replacement but we did just get compiled, then
+        // either of the following happened:
+        // - The compilation failed or was invalidated, in which case the execution count
+        //   thresholds have already been set appropriately by
+        //   CodeBlock::setOptimizationThresholdBasedOnCompilationResult() and we have
+        //   nothing left to do.
+        // - GC ran after DFG::Worklist::completeAllReadyPlansForVM() and jettisoned our
+        //   code block. Obviously that's unfortunate and we'd rather not have that
+        //   happen, but it can happen, and if it did then the jettisoning logic will
+        //   have set our threshold appropriately and we have nothing left to do.
+        if (!codeBlock-&gt;hasOptimizedReplacement())
+            return;
+    } else if (codeBlock-&gt;hasOptimizedReplacement()) {
+        if (Options::verboseOSR())
+            dataLog(&quot;Considering OSR &quot;, *codeBlock, &quot; -&gt; &quot;, *codeBlock-&gt;replacement(), &quot;.\n&quot;);
</ins><span class="cx">         // If we have an optimized replacement, then it must be the case that we entered
</span><span class="cx">         // cti_optimize from a loop. That's because is there's an optimized replacement,
</span><span class="cx">         // then all calls to this function will be relinked to the replacement and so
</span><span class="lines">@@ -945,60 +998,39 @@
</span><span class="cx">         // shouldReoptimizeFromLoopNow() to always return true. But we make it do some
</span><span class="cx">         // additional checking anyway, to reduce the amount of recompilation thrashing.
</span><span class="cx">         if (codeBlock-&gt;replacement()-&gt;shouldReoptimizeFromLoopNow()) {
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-            dataLog(&quot;Triggering reoptimization of &quot;, *codeBlock, &quot;(&quot;, *codeBlock-&gt;replacement(), &quot;) (in loop).\n&quot;);
-#endif
</del><ins>+            if (Options::verboseOSR()) {
+                dataLog(
+                    &quot;Triggering reoptimization of &quot;, *codeBlock,
+                    &quot;(&quot;, *codeBlock-&gt;replacement(), &quot;) (in loop).\n&quot;);
+            }
</ins><span class="cx">             codeBlock-&gt;reoptimize();
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">     } else {
</span><span class="cx">         if (!codeBlock-&gt;shouldOptimizeNow()) {
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-            dataLog(&quot;Delaying optimization for &quot;, *codeBlock, &quot; (in loop) because of insufficient profiling.\n&quot;);
-#endif
</del><ins>+            if (Options::verboseOSR()) {
+                dataLog(
+                    &quot;Delaying optimization for &quot;, *codeBlock,
+                    &quot; (in loop) because of insufficient profiling.\n&quot;);
+            }
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-        dataLog(&quot;Triggering optimized compilation of &quot;, *codeBlock, &quot;\n&quot;);
-#endif
</del><ins>+        if (Options::verboseOSR())
+            dataLog(&quot;Triggering optimized compilation of &quot;, *codeBlock, &quot;\n&quot;);
</ins><span class="cx">         
</span><span class="cx">         JSScope* scope = callFrame-&gt;scope();
</span><span class="cx">         CompilationResult result;
</span><span class="cx">         JSObject* error = codeBlock-&gt;compileOptimized(callFrame, scope, result, bytecodeIndex);
</span><del>-        if (Options::verboseCompilation()
-            || Options::showDisassembly()
-            || Options::showDFGDisassembly())
</del><ins>+        if (Options::verboseOSR()) {
</ins><span class="cx">             dataLog(&quot;Optimizing compilation of &quot;, *codeBlock, &quot; result: &quot;, result, &quot;\n&quot;);
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-        if (error)
-            dataLog(&quot;WARNING: optimized compilation failed with a JS error.\n&quot;);
-#else
-        UNUSED_PARAM(error);
-#endif
</del><ins>+            if (error)
+                dataLog(&quot;WARNING: optimized compilation failed with a JS error.\n&quot;);
+        }
</ins><span class="cx">         
</span><del>-        RELEASE_ASSERT((result == CompilationSuccessful) == (codeBlock-&gt;replacement() != codeBlock));
-        switch (result) {
-        case CompilationSuccessful:
-            break;
-        case CompilationFailed:
-        case CompilationDeferred:
-#if ENABLE(JIT_VERBOSE_OSR)
-            dataLog(&quot;Optimizing &quot;, *codeBlock, &quot; failed.\n&quot;);
-#endif
-            ASSERT(codeBlock-&gt;getJITType() == JITCode::BaselineJIT);
-            codeBlock-&gt;dontOptimizeAnytimeSoon();
</del><ins>+        codeBlock-&gt;setOptimizationThresholdBasedOnCompilationResult(result);
+        if (result != CompilationSuccessful)
</ins><span class="cx">             return;
</span><del>-        case CompilationInvalidated:
-            ASSERT(codeBlock-&gt;getJITType() == JITCode::BaselineJIT);
-            // Retry with exponential backoff.
-            codeBlock-&gt;countReoptimization();
-            codeBlock-&gt;optimizeAfterWarmUp();
-            return;
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-            return;
-        }
</del><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     CodeBlock* optimizedCodeBlock = codeBlock-&gt;replacement();
</span><span class="lines">@@ -1014,32 +1046,28 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (void* address = DFG::prepareOSREntry(callFrame, optimizedCodeBlock, bytecodeIndex)) {
</span><del>-        if (Options::showDFGDisassembly()) {
</del><ins>+        if (Options::verboseOSR()) {
</ins><span class="cx">             dataLog(
</span><span class="cx">                 &quot;Performing OSR &quot;, *codeBlock, &quot; -&gt; &quot;, *optimizedCodeBlock, &quot;, address &quot;,
</span><span class="cx">                 RawPointer((STUB_RETURN_ADDRESS).value()), &quot; -&gt; &quot;, RawPointer(address), &quot;.\n&quot;);
</span><span class="cx">         }
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-        dataLog(&quot;Optimizing &quot;, *codeBlock, &quot; succeeded, performing OSR after a delay of &quot;, codeBlock-&gt;optimizationDelayCounter(), &quot;.\n&quot;);
-#endif
</del><span class="cx"> 
</span><span class="cx">         codeBlock-&gt;optimizeSoon();
</span><span class="cx">         STUB_SET_RETURN_ADDRESS(address);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><del>-    
-#if ENABLE(JIT_VERBOSE_OSR)
-    dataLog(&quot;Optimizing &quot;, *codeBlock, &quot; succeeded, OSR failed, after a delay of &quot;, codeBlock-&gt;optimizationDelayCounter(), &quot;.\n&quot;);
-#endif
</del><span class="cx"> 
</span><ins>+    if (Options::verboseOSR()) {
+        dataLog(
+            &quot;Optimizing &quot;, *codeBlock, &quot; -&gt; &quot;, *codeBlock-&gt;replacement(),
+            &quot; succeeded, OSR failed, after a delay of &quot;,
+            codeBlock-&gt;optimizationDelayCounter(), &quot;.\n&quot;);
+    }
+
</ins><span class="cx">     // Count the OSR failure as a speculation failure. If this happens a lot, then
</span><span class="cx">     // reoptimize.
</span><span class="cx">     optimizedCodeBlock-&gt;countOSRExit();
</span><span class="cx">     
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-    dataLog(&quot;Encountered OSR failure &quot;, *codeBlock, &quot; -&gt; &quot;, *codeBlock-&gt;replacement(), &quot;.\n&quot;);
-#endif
-
</del><span class="cx">     // We are a lot more conservative about triggering reoptimization after OSR failure than
</span><span class="cx">     // before it. If we enter the optimize_from_loop trigger with a bucket full of fail
</span><span class="cx">     // already, then we really would like to reoptimize immediately. But this case covers
</span><span class="lines">@@ -1049,9 +1077,11 @@
</span><span class="cx">     // right now. So, we only trigger reoptimization only upon the more conservative (non-loop)
</span><span class="cx">     // reoptimization trigger.
</span><span class="cx">     if (optimizedCodeBlock-&gt;shouldReoptimizeNow()) {
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-        dataLog(&quot;Triggering reoptimization of &quot;, *codeBlock, &quot; -&gt; &quot;, *codeBlock-&gt;replacement(), &quot; (after OSR fail).\n&quot;);
-#endif
</del><ins>+        if (Options::verboseOSR()) {
+            dataLog(
+                &quot;Triggering reoptimization of &quot;, *codeBlock, &quot; -&gt; &quot;,
+                *codeBlock-&gt;replacement(), &quot; (after OSR fail).\n&quot;);
+        }
</ins><span class="cx">         codeBlock-&gt;reoptimize();
</span><span class="cx">         return;
</span><span class="cx">     }
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -282,30 +282,26 @@
</span><span class="cx">     codeBlock-&gt;updateAllValueProfilePredictions();
</span><span class="cx">     
</span><span class="cx">     if (!codeBlock-&gt;checkIfJITThresholdReached()) {
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-        dataLogF(&quot;    JIT threshold should be lifted.\n&quot;);
-#endif
</del><ins>+        if (Options::verboseOSR())
+            dataLogF(&quot;    JIT threshold should be lifted.\n&quot;);
</ins><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     CompilationResult result = codeBlock-&gt;jitCompile(exec);
</span><span class="cx">     switch (result) {
</span><span class="cx">     case CompilationNotNeeded:
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-        dataLogF(&quot;    Code was already compiled.\n&quot;);
-#endif
</del><ins>+        if (Options::verboseOSR())
+            dataLogF(&quot;    Code was already compiled.\n&quot;);
</ins><span class="cx">         codeBlock-&gt;jitSoon();
</span><span class="cx">         return true;
</span><span class="cx">     case CompilationFailed:
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-        dataLogF(&quot;    JIT compilation failed.\n&quot;);
-#endif
</del><ins>+        if (Options::verboseOSR())
+            dataLogF(&quot;    JIT compilation failed.\n&quot;);
</ins><span class="cx">         codeBlock-&gt;dontJITAnytimeSoon();
</span><span class="cx">         return false;
</span><span class="cx">     case CompilationSuccessful:
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-        dataLogF(&quot;    JIT compilation successful.\n&quot;);
-#endif
</del><ins>+        if (Options::verboseOSR())
+            dataLogF(&quot;    JIT compilation successful.\n&quot;);
</ins><span class="cx">         codeBlock-&gt;jitSoon();
</span><span class="cx">         return true;
</span><span class="cx">     default:
</span><span class="lines">@@ -317,11 +313,11 @@
</span><span class="cx"> enum EntryKind { Prologue, ArityCheck };
</span><span class="cx"> static SlowPathReturnType entryOSR(ExecState* exec, Instruction*, CodeBlock* codeBlock, const char *name, EntryKind kind)
</span><span class="cx"> {
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-    dataLog(*codeBlock, &quot;: Entered &quot;, name, &quot; with executeCounter = &quot;, codeBlock-&gt;llintExecuteCounter(), &quot;\n&quot;);
-#else
-    UNUSED_PARAM(name);
-#endif
</del><ins>+    if (Options::verboseOSR()) {
+        dataLog(
+            *codeBlock, &quot;: Entered &quot;, name, &quot; with executeCounter = &quot;,
+            codeBlock-&gt;llintExecuteCounter(), &quot;\n&quot;);
+    }
</ins><span class="cx">     
</span><span class="cx">     if (!shouldJIT(exec)) {
</span><span class="cx">         codeBlock-&gt;dontJITAnytimeSoon();
</span><span class="lines">@@ -364,11 +360,13 @@
</span><span class="cx"> LLINT_SLOW_PATH_DECL(loop_osr)
</span><span class="cx"> {
</span><span class="cx">     CodeBlock* codeBlock = exec-&gt;codeBlock();
</span><ins>+
+    if (Options::verboseOSR()) {
+        dataLog(
+            *codeBlock, &quot;: Entered loop_osr with executeCounter = &quot;,
+            codeBlock-&gt;llintExecuteCounter(), &quot;\n&quot;);
+    }
</ins><span class="cx">     
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-    dataLog(*codeBlock, &quot;: Entered loop_osr with executeCounter = &quot;, codeBlock-&gt;llintExecuteCounter(), &quot;\n&quot;);
-#endif
-    
</del><span class="cx">     if (!shouldJIT(exec)) {
</span><span class="cx">         codeBlock-&gt;dontJITAnytimeSoon();
</span><span class="cx">         LLINT_RETURN_TWO(0, exec);
</span><span class="lines">@@ -394,11 +392,13 @@
</span><span class="cx"> LLINT_SLOW_PATH_DECL(replace)
</span><span class="cx"> {
</span><span class="cx">     CodeBlock* codeBlock = exec-&gt;codeBlock();
</span><ins>+
+    if (Options::verboseOSR()) {
+        dataLog(
+            *codeBlock, &quot;: Entered replace with executeCounter = &quot;,
+            codeBlock-&gt;llintExecuteCounter(), &quot;\n&quot;);
+    }
</ins><span class="cx">     
</span><del>-#if ENABLE(JIT_VERBOSE_OSR)
-    dataLog(*codeBlock, &quot;: Entered replace with executeCounter = &quot;, codeBlock-&gt;llintExecuteCounter(), &quot;\n&quot;);
-#endif
-    
</del><span class="cx">     if (shouldJIT(exec))
</span><span class="cx">         jitCompileAndSetHeuristics(codeBlock, exec);
</span><span class="cx">     else
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoreprofilerProfilerBytecodesh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/profiler/ProfilerBytecodes.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/profiler/ProfilerBytecodes.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/profiler/ProfilerBytecodes.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -29,7 +29,6 @@
</span><span class="cx"> #include &quot;CodeBlockHash.h&quot;
</span><span class="cx"> #include &quot;JSCJSValue.h&quot;
</span><span class="cx"> #include &quot;ProfilerBytecodeSequence.h&quot;
</span><del>-#include &lt;wtf/ByteSpinLock.h&gt;
</del><span class="cx"> #include &lt;wtf/PrintStream.h&gt;
</span><span class="cx"> #include &lt;wtf/text/WTFString.h&gt;
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoreruntimeConcurrentJITLockh"></a>
<div class="addfile"><h4>Added: branches/dfgFourthTier/Source/JavaScriptCore/runtime/ConcurrentJITLock.h (0 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/runtime/ConcurrentJITLock.h                                (rev 0)
+++ branches/dfgFourthTier/Source/JavaScriptCore/runtime/ConcurrentJITLock.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -0,0 +1,45 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef ConcurrentJITLock_h
+#define ConcurrentJITLock_h
+
+#include &lt;wtf/ByteSpinLock.h&gt;
+#include &lt;wtf/NoLock.h&gt;
+
+namespace JSC {
+
+#if ENABLE(CONCURRENT_JIT)
+typedef ByteSpinLock ConcurrentJITLock;
+typedef ByteSpinLocker ConcurrentJITLocker;
+#else
+typedef NoLock ConcurrentJITLock;
+typedef NoLockLocker ConcurrentJITLocker;
+#endif
+
+} // namespace JSC
+
+#endif // ConcurrentJITLock_h
+
</ins></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoreruntimeExecutionHarnessh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/runtime/ExecutionHarness.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/runtime/ExecutionHarness.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/runtime/ExecutionHarness.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -141,12 +141,20 @@
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename CodeBlockType&gt;
</span><span class="cx"> inline CompilationResult replaceWithDeferredOptimizedCode(
</span><del>-    PassRefPtr&lt;DFG::Plan&gt; plan, RefPtr&lt;CodeBlockType&gt;&amp; sink, RefPtr&lt;JITCode&gt;&amp; jitCode,
</del><ins>+    PassRefPtr&lt;DFG::Plan&gt; passedPlan, RefPtr&lt;CodeBlockType&gt;&amp; sink, RefPtr&lt;JITCode&gt;&amp; jitCode,
</ins><span class="cx">     MacroAssemblerCodePtr* jitCodeWithArityCheck, int* numParameters)
</span><span class="cx"> {
</span><ins>+    RefPtr&lt;DFG::Plan&gt; plan = passedPlan;
+    CompilationResult result = DFG::tryFinalizePlan(plan, jitCode, jitCodeWithArityCheck);
+    if (Options::verboseOSR()) {
+        dataLog(
+            &quot;Deferred optimizing compilation &quot;, *plan-&gt;key(), &quot; -&gt; &quot;, *plan-&gt;codeBlock,
+            &quot; result: &quot;, result, &quot;\n&quot;);
+    }
+    if (result == CompilationSuccessful)
+        plan-&gt;codeBlock-&gt;alternative()-&gt;unlinkIncomingCalls();
</ins><span class="cx">     return installOptimizedCode(
</span><del>-        DFG::tryFinalizePlan(plan, jitCode, jitCodeWithArityCheck),
-        sink, static_cast&lt;CodeBlockType*&gt;(plan-&gt;codeBlock.get()), jitCode,
</del><ins>+        result, sink, static_cast&lt;CodeBlockType*&gt;(plan-&gt;codeBlock.get()), jitCode,
</ins><span class="cx">         jitCodeWithArityCheck ? *jitCodeWithArityCheck : MacroAssemblerCodePtr(),
</span><span class="cx">         numParameters);
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoreruntimeJSSegmentedVariableObjectcpp"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 2013 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">@@ -35,6 +35,8 @@
</span><span class="cx"> 
</span><span class="cx"> int JSSegmentedVariableObject::findRegisterIndex(void* registerAddress)
</span><span class="cx"> {
</span><ins>+    Locker locker(m_lock);
+    
</ins><span class="cx">     for (int i = m_registers.size(); i--;) {
</span><span class="cx">         if (&amp;m_registers[i] != registerAddress)
</span><span class="cx">             continue;
</span><span class="lines">@@ -46,6 +48,8 @@
</span><span class="cx"> 
</span><span class="cx"> int JSSegmentedVariableObject::addRegisters(int numberOfRegistersToAdd)
</span><span class="cx"> {
</span><ins>+    Locker locker(m_lock);
+    
</ins><span class="cx">     ASSERT(numberOfRegistersToAdd &gt;= 0);
</span><span class="cx">     
</span><span class="cx">     size_t oldSize = m_registers.size();
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoreruntimeJSSegmentedVariableObjecth"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #ifndef JSSegmentedVariableObject_h
</span><span class="cx"> #define JSSegmentedVariableObject_h
</span><span class="cx"> 
</span><ins>+#include &quot;ConcurrentJITLock.h&quot;
</ins><span class="cx"> #include &quot;JSObject.h&quot;
</span><span class="cx"> #include &quot;JSSymbolTableObject.h&quot;
</span><span class="cx"> #include &quot;Register.h&quot;
</span><span class="lines">@@ -91,8 +92,12 @@
</span><span class="cx">     {
</span><span class="cx">         Base::finishCreation(vm);
</span><span class="cx">     }
</span><ins>+    
+    typedef ConcurrentJITLock Lock;
+    typedef ConcurrentJITLocker Locker;
</ins><span class="cx"> 
</span><span class="cx">     SegmentedVector&lt;WriteBarrier&lt;Unknown&gt;, 16&gt; m_registers;
</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="branchesdfgFourthTierSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/runtime/Options.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/runtime/Options.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/runtime/Options.h        2013-05-21 19:10:07 UTC (rev 150465)
</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, 2012, 2013 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -81,6 +81,8 @@
</span><span class="cx">     v(bool, printEachOSRExit, false) \
</span><span class="cx">     v(bool, validateGraph, false) \
</span><span class="cx">     v(bool, validateGraphAtEachPhase, false) \
</span><ins>+    v(bool, verboseOSR, false) \
+    v(bool, verboseCompilationQueue, false) \
</ins><span class="cx">     \
</span><span class="cx">     v(bool, useExperimentalFTL, false) \
</span><span class="cx">     v(bool, useFTLTBAA, true) \
</span><span class="lines">@@ -88,6 +90,8 @@
</span><span class="cx">     v(bool, enableLLVMFastISel, true) \
</span><span class="cx">     v(unsigned, llvmOptimizationLevel, 2) \
</span><span class="cx">     \
</span><ins>+    v(bool, enableConcurrentJIT, true) \
+    \
</ins><span class="cx">     v(bool, enableProfiler, false) \
</span><span class="cx">     \
</span><span class="cx">     v(unsigned, maximumOptimizationCandidateInstructionCount, 10000) \
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoreruntimeStructureh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/runtime/Structure.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/runtime/Structure.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/runtime/Structure.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #define Structure_h
</span><span class="cx"> 
</span><span class="cx"> #include &quot;ClassInfo.h&quot;
</span><ins>+#include &quot;ConcurrentJITLock.h&quot;
</ins><span class="cx"> #include &quot;IndexingType.h&quot;
</span><span class="cx"> #include &quot;JSCJSValue.h&quot;
</span><span class="cx"> #include &quot;JSCell.h&quot;
</span><span class="lines">@@ -40,7 +41,6 @@
</span><span class="cx"> #include &quot;JSTypeInfo.h&quot;
</span><span class="cx"> #include &quot;Watchpoint.h&quot;
</span><span class="cx"> #include &quot;Weak.h&quot;
</span><del>-#include &lt;wtf/ByteSpinLock.h&gt;
</del><span class="cx"> #include &lt;wtf/CompilationThread.h&gt;
</span><span class="cx"> #include &lt;wtf/PassRefPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><span class="lines">@@ -72,8 +72,8 @@
</span><span class="cx"> 
</span><span class="cx">     typedef JSCell Base;
</span><span class="cx">     
</span><del>-    typedef ByteSpinLock Lock;
-    typedef ByteSpinLocker Locker;
</del><ins>+    typedef ConcurrentJITLock Lock;
+    typedef ConcurrentJITLocker Locker;
</ins><span class="cx"> 
</span><span class="cx">     static Structure* create(VM&amp;, JSGlobalObject*, JSValue prototype, const TypeInfo&amp;, const ClassInfo*, IndexingType = NonArray, unsigned inlineCapacity = 0);
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoreruntimeStructureInlinesh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/runtime/StructureInlines.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/runtime/StructureInlines.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/runtime/StructureInlines.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -226,7 +226,7 @@
</span><span class="cx"> 
</span><span class="cx"> ALWAYS_INLINE WriteBarrier&lt;PropertyTable&gt;&amp; Structure::propertyTable()
</span><span class="cx"> {
</span><del>-    ASSERT(!globalObject() || !globalObject()-&gt;vm().heap.isBusy());
</del><ins>+    ASSERT(!globalObject() || !globalObject()-&gt;vm().heap.isCollecting());
</ins><span class="cx">     return m_propertyTableUnsafe;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoreruntimeSymbolTableh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/runtime/SymbolTable.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/runtime/SymbolTable.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/runtime/SymbolTable.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #ifndef SymbolTable_h
</span><span class="cx"> #define SymbolTable_h
</span><span class="cx"> 
</span><ins>+#include &quot;ConcurrentJITLock.h&quot;
</ins><span class="cx"> #include &quot;JSObject.h&quot;
</span><span class="cx"> #include &quot;Watchpoint.h&quot;
</span><span class="cx"> #include &lt;wtf/AlwaysInline.h&gt;
</span><span class="lines">@@ -343,8 +344,8 @@
</span><span class="cx"> class SymbolTable {
</span><span class="cx"> public:
</span><span class="cx">     typedef HashMap&lt;RefPtr&lt;StringImpl&gt;, SymbolTableEntry, IdentifierRepHash, HashTraits&lt;RefPtr&lt;StringImpl&gt; &gt;, SymbolTableIndexHashTraits&gt; Map;
</span><del>-    typedef ByteSpinLock Lock;
-    typedef ByteSpinLocker Locker;
</del><ins>+    typedef ConcurrentJITLock Lock;
+    typedef ConcurrentJITLocker Locker;
</ins><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE SymbolTable();
</span><span class="cx">     JS_EXPORT_PRIVATE ~SymbolTable();
</span><span class="lines">@@ -434,7 +435,7 @@
</span><span class="cx"> private:
</span><span class="cx">     Map m_map;
</span><span class="cx"> public:
</span><del>-    mutable ByteSpinLock m_lock;
</del><ins>+    mutable ConcurrentJITLock m_lock;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/runtime/VM.cpp (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/runtime/VM.cpp        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/runtime/VM.cpp        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2011 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008, 2011, 2013 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">@@ -33,6 +33,7 @@
</span><span class="cx"> #include &quot;CodeCache.h&quot;
</span><span class="cx"> #include &quot;CommonIdentifiers.h&quot;
</span><span class="cx"> #include &quot;DFGLongLivedState.h&quot;
</span><ins>+#include &quot;DFGWorklist.h&quot;
</ins><span class="cx"> #include &quot;DebuggerActivation.h&quot;
</span><span class="cx"> #include &quot;FunctionConstructor.h&quot;
</span><span class="cx"> #include &quot;GCActivityCallback.h&quot;
</span><span class="lines">@@ -253,12 +254,19 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     if (canUseJIT())
</span><del>-        m_dfgState = adoptPtr(new DFG::LongLivedState());
</del><ins>+        dfgState = adoptPtr(new DFG::LongLivedState());
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> VM::~VM()
</span><span class="cx"> {
</span><ins>+    // Make sure concurrent compilations are done, but don't install them, since installing
+    // them might cause a GC. We don't want to GC right now.
+    if (worklist) {
+        worklist-&gt;waitUntilAllPlansForVMAreReady(*this);
+        worklist-&gt;removeAllReadyPlansForVM(*this);
+    }
+    
</ins><span class="cx">     // Clear this first to ensure that nobody tries to remove themselves from it.
</span><span class="cx">     m_perBytecodeProfiler.clear();
</span><span class="cx">     
</span><span class="lines">@@ -434,8 +442,19 @@
</span><span class="cx">     interpreter-&gt;stopSampling();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void VM::prepareToDiscardCode()
+{
+#if ENABLE(DFG_JIT)
+    if (!worklist)
+        return;
+    
+    worklist-&gt;completeAllPlansForVM(*this);
+#endif
+}
+
</ins><span class="cx"> void VM::discardAllCode()
</span><span class="cx"> {
</span><ins>+    prepareToDiscardCode();
</ins><span class="cx">     m_codeCache-&gt;clear();
</span><span class="cx">     heap.deleteAllCompiledCode();
</span><span class="cx">     heap.reportAbandonedObjectGraph();
</span><span class="lines">@@ -477,6 +496,8 @@
</span><span class="cx"> 
</span><span class="cx"> void VM::releaseExecutableMemory()
</span><span class="cx"> {
</span><ins>+    prepareToDiscardCode();
+    
</ins><span class="cx">     if (dynamicGlobalObject) {
</span><span class="cx">         StackPreservingRecompiler recompiler;
</span><span class="cx">         HashSet&lt;JSCell*&gt; roots;
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/JavaScriptCore/runtime/VM.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/JavaScriptCore/runtime/VM.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/JavaScriptCore/runtime/VM.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -97,6 +97,7 @@
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     namespace DFG {
</span><span class="cx">     class LongLivedState;
</span><ins>+    class Worklist;
</ins><span class="cx">     }
</span><span class="cx"> #endif // ENABLE(DFG_JIT)
</span><span class="cx"> 
</span><span class="lines">@@ -207,7 +208,8 @@
</span><span class="cx">         Heap heap;
</span><span class="cx">         
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><del>-        OwnPtr&lt;DFG::LongLivedState&gt; m_dfgState;
</del><ins>+        OwnPtr&lt;DFG::LongLivedState&gt; dfgState;
+        RefPtr&lt;DFG::Worklist&gt; worklist;
</ins><span class="cx"> #endif // ENABLE(DFG_JIT)
</span><span class="cx"> 
</span><span class="cx">         VMType vmType;
</span><span class="lines">@@ -479,6 +481,8 @@
</span><span class="cx">         JSLock&amp; apiLock() { return m_apiLock; }
</span><span class="cx">         CodeCache* codeCache() { return m_codeCache.get(); }
</span><span class="cx"> 
</span><ins>+        void prepareToDiscardCode();
+        
</ins><span class="cx">         JS_EXPORT_PRIVATE void discardAllCode();
</span><span class="cx"> 
</span><span class="cx">     private:
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/WTF/ChangeLog (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/WTF/ChangeLog        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/WTF/ChangeLog        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2013-05-21  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        fourthTier: DFG should be able to run on a separate thread
+        https://bugs.webkit.org/show_bug.cgi?id=112839
+
+        Reviewed by Geoffrey Garen.
+        
+        * wtf/ByteSpinLock.h:
+        Make it non-copyable. We previously had bugs where we used ByteSpinLock as a locker.
+        Clearly that's bad.
+
+        * wtf/MetaAllocatorHandle.h:
+        Make it thread-safe ref-counted, since we may now be passing them between the
+        concurrent JIT thread and the main thread.
+
+        * wtf/Vector.h:
+        (WTF::Vector::takeLast):
+        I've wanted this method for ages, and now I finally added.
+
</ins><span class="cx"> 2013-05-06  Geoffrey Garen  &lt;ggaren@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Cherry-pick merged some patches to the FTL branch.
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceWTFwtfByteSpinLockh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/WTF/wtf/ByteSpinLock.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/WTF/wtf/ByteSpinLock.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/WTF/wtf/ByteSpinLock.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -29,11 +29,13 @@
</span><span class="cx"> #include &lt;wtf/Assertions.h&gt;
</span><span class="cx"> #include &lt;wtf/Atomics.h&gt;
</span><span class="cx"> #include &lt;wtf/Locker.h&gt;
</span><ins>+#include &lt;wtf/Noncopyable.h&gt;
</ins><span class="cx"> #include &lt;wtf/ThreadingPrimitives.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="cx"> 
</span><span class="cx"> class ByteSpinLock {
</span><ins>+    WTF_MAKE_NONCOPYABLE(ByteSpinLock);
</ins><span class="cx"> public:
</span><span class="cx">     ByteSpinLock()
</span><span class="cx">         : m_lock(0)
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceWTFwtfMetaAllocatorHandleh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/WTF/wtf/MetaAllocatorHandle.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/WTF/wtf/MetaAllocatorHandle.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/WTF/wtf/MetaAllocatorHandle.h        2013-05-21 19:10:07 UTC (rev 150465)
</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, 2013 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -31,14 +31,14 @@
</span><span class="cx"> 
</span><span class="cx"> #include &lt;wtf/Assertions.h&gt;
</span><span class="cx"> #include &lt;wtf/RedBlackTree.h&gt;
</span><del>-#include &lt;wtf/RefCounted.h&gt;
</del><ins>+#include &lt;wtf/ThreadSafeRefCounted.h&gt;
</ins><span class="cx"> #include &lt;wtf/RefPtr.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="cx"> 
</span><span class="cx"> class MetaAllocator;
</span><span class="cx"> 
</span><del>-class MetaAllocatorHandle : public RefCounted&lt;MetaAllocatorHandle&gt;, public RedBlackTree&lt;MetaAllocatorHandle, void*&gt;::Node {
</del><ins>+class MetaAllocatorHandle : public ThreadSafeRefCounted&lt;MetaAllocatorHandle&gt;, public RedBlackTree&lt;MetaAllocatorHandle, void*&gt;::Node {
</ins><span class="cx"> private:
</span><span class="cx">     MetaAllocatorHandle(MetaAllocator*, void* start, size_t sizeInBytes, void* ownerUID);
</span><span class="cx">     
</span></span></pre></div>
<a id="branchesdfgFourthTierSourceWTFwtfVectorh"></a>
<div class="modfile"><h4>Modified: branches/dfgFourthTier/Source/WTF/wtf/Vector.h (150464 => 150465)</h4>
<pre class="diff"><span>
<span class="info">--- branches/dfgFourthTier/Source/WTF/wtf/Vector.h        2013-05-21 19:09:14 UTC (rev 150464)
+++ branches/dfgFourthTier/Source/WTF/wtf/Vector.h        2013-05-21 19:10:07 UTC (rev 150465)
</span><span class="lines">@@ -602,7 +602,14 @@
</span><span class="cx">         const T&amp; first() const { return at(0); }
</span><span class="cx">         T&amp; last() { return at(size() - 1); }
</span><span class="cx">         const T&amp; last() const { return at(size() - 1); }
</span><del>-
</del><ins>+        
+        T takeLast()
+        {
+            T result = last();
+            removeLast();
+            return result;
+        }
+        
</ins><span class="cx">         template&lt;typename U&gt; bool contains(const U&amp;) const;
</span><span class="cx">         template&lt;typename U&gt; size_t find(const U&amp;) const;
</span><span class="cx">         template&lt;typename U&gt; size_t reverseFind(const U&amp;) const;
</span></span></pre>
</div>
</div>

</body>
</html>