<!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>[165005] trunk/Source/JavaScriptCore</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/165005">165005</a></dd>
<dt>Author</dt> <dd>mark.lam@apple.com</dd>
<dt>Date</dt> <dd>2014-03-03 13:39:21 -0800 (Mon, 03 Mar 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>ASSERTION FAILED: m_numBreakpoints &gt;= numBreakpoints when deleting breakpoints.
&lt;https://webkit.org/b/129393&gt;

Reviewed by Geoffrey Garen.

The issue manifests because the debugger will iterate all CodeBlocks in
the heap when setting / clearing breakpoints, but it is possible for a
CodeBlock to have been instantiate but is not yet registered with the
debugger.  This can happen because of the following:

1. DFG worklist compilation is still in progress, and the target
   codeBlock is not ready for installation in its executable yet.

2. DFG compilation failed and we have a codeBlock that will never be
   installed in its executable, and the codeBlock has not been cleaned
   up by the GC yet.

The code for installing the codeBlock in its executable is the same code
that registers it with the debugger.  Hence, these codeBlocks are not
registered with the debugger, and any pending breakpoints that would map
to that CodeBlock is as yet unset or will never be set.  As such, an
attempt to remove a breakpoint in that CodeBlock will fail that assertion.

To fix this, we do the following:

1. We'll eagerly clean up any zombie CodeBlocks due to failed DFG / FTL
   compilation.  This is achieved by providing a
   DeferredCompilationCallback::compilationDidComplete() that does this
   clean up, and have all sub classes call it at the end of their
   compilationDidComplete() methods.

2. Before the debugger or profiler iterates CodeBlocks in the heap, they
   will wait for all compilations to complete before proceeding.  This
   ensures that:
   1. any zombie CodeBlocks would have been cleaned up, and won't be
      seen by the debugger or profiler.
   2. all CodeBlocks that the debugger and profiler needs to operate on
      will be &quot;ready&quot; for whatever needs to be done to them e.g.
      jettison'ing of DFG codeBlocks.

* bytecode/DeferredCompilationCallback.cpp:
(JSC::DeferredCompilationCallback::compilationDidComplete):
* bytecode/DeferredCompilationCallback.h:
- Provide default implementation method to clean up zombie CodeBlocks.

* debugger/Debugger.cpp:
(JSC::Debugger::forEachCodeBlock):
- Utility function to iterate CodeBlocks.  It ensures that all compilations
  are complete before proceeding.
(JSC::Debugger::setSteppingMode):
(JSC::Debugger::toggleBreakpoint):
(JSC::Debugger::recompileAllJSFunctions):
(JSC::Debugger::clearBreakpoints):
(JSC::Debugger::clearDebuggerRequests):
- Use the utility iterator function.

* debugger/Debugger.h:
* dfg/DFGOperations.cpp:
- Added an assert to ensure that zombie CodeBlocks will be imminently cleaned up.

* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::finalizeWithoutNotifyingCallback):
- Remove unneeded code (that was not the best solution anyway) for ensuring
  that we don't generate new DFG codeBlocks after enabling the debugger or
  profiler.  Now that we wait for compilations to complete before proceeding
  with debugger and profiler work, this scenario will never happen.

* dfg/DFGToFTLDeferredCompilationCallback.cpp:
(JSC::DFG::ToFTLDeferredCompilationCallback::compilationDidComplete):
- Call the super class method to clean up zombie codeBlocks.

* dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp:
(JSC::DFG::ToFTLForOSREntryDeferredCompilationCallback::compilationDidComplete):
- Call the super class method to clean up zombie codeBlocks.

* heap/CodeBlockSet.cpp:
(JSC::CodeBlockSet::remove):
* heap/CodeBlockSet.h:
* heap/Heap.h:
(JSC::Heap::removeCodeBlock):
- New method to remove a codeBlock from the codeBlock set.

* jit/JITOperations.cpp:
- Added an assert to ensure that zombie CodeBlocks will be imminently cleaned up.

* jit/JITToDFGDeferredCompilationCallback.cpp:
(JSC::JITToDFGDeferredCompilationCallback::compilationDidComplete):
- Call the super class method to clean up zombie codeBlocks.

* runtime/VM.cpp:
(JSC::VM::waitForCompilationsToComplete):
- Renamed from prepareToDiscardCode() to be clearer about what it does.

(JSC::VM::discardAllCode):
(JSC::VM::releaseExecutableMemory):
(JSC::VM::setEnabledProfiler):
- Wait for compilation to complete before enabling the profiler.

* runtime/VM.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeDeferredCompilationCallbackcpp">trunk/Source/JavaScriptCore/bytecode/DeferredCompilationCallback.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeDeferredCompilationCallbackh">trunk/Source/JavaScriptCore/bytecode/DeferredCompilationCallback.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggercpp">trunk/Source/JavaScriptCore/debugger/Debugger.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggerh">trunk/Source/JavaScriptCore/debugger/Debugger.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPlancpp">trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGToFTLDeferredCompilationCallbackcpp">trunk/Source/JavaScriptCore/dfg/DFGToFTLDeferredCompilationCallback.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGToFTLForOSREntryDeferredCompilationCallbackcpp">trunk/Source/JavaScriptCore/dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCodeBlockSetcpp">trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCodeBlockSeth">trunk/Source/JavaScriptCore/heap/CodeBlockSet.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeaph">trunk/Source/JavaScriptCore/heap/Heap.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITToDFGDeferredCompilationCallbackcpp">trunk/Source/JavaScriptCore/jit/JITToDFGDeferredCompilationCallback.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMcpp">trunk/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (165004 => 165005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-03-03 21:33:17 UTC (rev 165004)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-03-03 21:39:21 UTC (rev 165005)
</span><span class="lines">@@ -1,3 +1,105 @@
</span><ins>+2014-03-03  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        ASSERTION FAILED: m_numBreakpoints &gt;= numBreakpoints when deleting breakpoints.
+        &lt;https://webkit.org/b/129393&gt;
+
+        Reviewed by Geoffrey Garen.
+
+        The issue manifests because the debugger will iterate all CodeBlocks in
+        the heap when setting / clearing breakpoints, but it is possible for a
+        CodeBlock to have been instantiate but is not yet registered with the
+        debugger.  This can happen because of the following:
+
+        1. DFG worklist compilation is still in progress, and the target
+           codeBlock is not ready for installation in its executable yet.
+
+        2. DFG compilation failed and we have a codeBlock that will never be
+           installed in its executable, and the codeBlock has not been cleaned
+           up by the GC yet.
+
+        The code for installing the codeBlock in its executable is the same code
+        that registers it with the debugger.  Hence, these codeBlocks are not
+        registered with the debugger, and any pending breakpoints that would map
+        to that CodeBlock is as yet unset or will never be set.  As such, an
+        attempt to remove a breakpoint in that CodeBlock will fail that assertion.
+
+        To fix this, we do the following:
+
+        1. We'll eagerly clean up any zombie CodeBlocks due to failed DFG / FTL
+           compilation.  This is achieved by providing a
+           DeferredCompilationCallback::compilationDidComplete() that does this
+           clean up, and have all sub classes call it at the end of their
+           compilationDidComplete() methods.
+
+        2. Before the debugger or profiler iterates CodeBlocks in the heap, they
+           will wait for all compilations to complete before proceeding.  This
+           ensures that:
+           1. any zombie CodeBlocks would have been cleaned up, and won't be
+              seen by the debugger or profiler.
+           2. all CodeBlocks that the debugger and profiler needs to operate on
+              will be &quot;ready&quot; for whatever needs to be done to them e.g.
+              jettison'ing of DFG codeBlocks.
+
+        * bytecode/DeferredCompilationCallback.cpp:
+        (JSC::DeferredCompilationCallback::compilationDidComplete):
+        * bytecode/DeferredCompilationCallback.h:
+        - Provide default implementation method to clean up zombie CodeBlocks.
+
+        * debugger/Debugger.cpp:
+        (JSC::Debugger::forEachCodeBlock):
+        - Utility function to iterate CodeBlocks.  It ensures that all compilations
+          are complete before proceeding.
+        (JSC::Debugger::setSteppingMode):
+        (JSC::Debugger::toggleBreakpoint):
+        (JSC::Debugger::recompileAllJSFunctions):
+        (JSC::Debugger::clearBreakpoints):
+        (JSC::Debugger::clearDebuggerRequests):
+        - Use the utility iterator function.
+
+        * debugger/Debugger.h:
+        * dfg/DFGOperations.cpp:
+        - Added an assert to ensure that zombie CodeBlocks will be imminently cleaned up.
+
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::finalizeWithoutNotifyingCallback):
+        - Remove unneeded code (that was not the best solution anyway) for ensuring
+          that we don't generate new DFG codeBlocks after enabling the debugger or
+          profiler.  Now that we wait for compilations to complete before proceeding
+          with debugger and profiler work, this scenario will never happen.
+
+        * dfg/DFGToFTLDeferredCompilationCallback.cpp:
+        (JSC::DFG::ToFTLDeferredCompilationCallback::compilationDidComplete):
+        - Call the super class method to clean up zombie codeBlocks.
+
+        * dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp:
+        (JSC::DFG::ToFTLForOSREntryDeferredCompilationCallback::compilationDidComplete):
+        - Call the super class method to clean up zombie codeBlocks.
+
+        * heap/CodeBlockSet.cpp:
+        (JSC::CodeBlockSet::remove):
+        * heap/CodeBlockSet.h:
+        * heap/Heap.h:
+        (JSC::Heap::removeCodeBlock):
+        - New method to remove a codeBlock from the codeBlock set.
+
+        * jit/JITOperations.cpp:
+        - Added an assert to ensure that zombie CodeBlocks will be imminently cleaned up.
+
+        * jit/JITToDFGDeferredCompilationCallback.cpp:
+        (JSC::JITToDFGDeferredCompilationCallback::compilationDidComplete):
+        - Call the super class method to clean up zombie codeBlocks.
+
+        * runtime/VM.cpp:
+        (JSC::VM::waitForCompilationsToComplete):
+        - Renamed from prepareToDiscardCode() to be clearer about what it does.
+
+        (JSC::VM::discardAllCode):
+        (JSC::VM::releaseExecutableMemory):
+        (JSC::VM::setEnabledProfiler):
+        - Wait for compilation to complete before enabling the profiler.
+
+        * runtime/VM.h:
+
</ins><span class="cx"> 2014-03-03  Brian Burg  &lt;bburg@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Another unreviewed build fix attempt for Windows after r164986.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeDeferredCompilationCallbackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/DeferredCompilationCallback.cpp (165004 => 165005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/DeferredCompilationCallback.cpp        2014-03-03 21:33:17 UTC (rev 165004)
+++ trunk/Source/JavaScriptCore/bytecode/DeferredCompilationCallback.cpp        2014-03-03 21:39:21 UTC (rev 165005)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2014 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">@@ -26,10 +26,26 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;DeferredCompilationCallback.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;CodeBlock.h&quot;
+
</ins><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> DeferredCompilationCallback::DeferredCompilationCallback() { }
</span><span class="cx"> DeferredCompilationCallback::~DeferredCompilationCallback() { }
</span><span class="cx"> 
</span><ins>+void DeferredCompilationCallback::compilationDidComplete(CodeBlock* codeBlock, CompilationResult result)
+{
+    switch (result) {
+    case CompilationFailed:
+    case CompilationInvalidated:
+        codeBlock-&gt;heap()-&gt;removeCodeBlock(codeBlock);
+        break;
+    case CompilationSuccessful:
+        break;
+    case CompilationDeferred:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+}
+
</ins><span class="cx"> } // JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeDeferredCompilationCallbackh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/DeferredCompilationCallback.h (165004 => 165005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/DeferredCompilationCallback.h        2014-03-03 21:33:17 UTC (rev 165004)
+++ trunk/Source/JavaScriptCore/bytecode/DeferredCompilationCallback.h        2014-03-03 21:39:21 UTC (rev 165005)
</span><span class="lines">@@ -41,7 +41,7 @@
</span><span class="cx">     virtual ~DeferredCompilationCallback();
</span><span class="cx"> 
</span><span class="cx">     virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*) = 0;
</span><del>-    virtual void compilationDidComplete(CodeBlock*, CompilationResult) = 0;
</del><ins>+    virtual void compilationDidComplete(CodeBlock*, CompilationResult);
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/Debugger.cpp (165004 => 165005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/Debugger.cpp        2014-03-03 21:33:17 UTC (rev 165004)
+++ trunk/Source/JavaScriptCore/debugger/Debugger.cpp        2014-03-03 21:39:21 UTC (rev 165005)
</span><span class="lines">@@ -138,6 +138,13 @@
</span><span class="cx">     Debugger&amp; m_debugger;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+template&lt;typename Functor&gt;
+void Debugger::forEachCodeBlock(Functor&amp; functor)
+{
+    m_vm-&gt;waitForCompilationsToComplete();
+    m_vm-&gt;heap.forEachCodeBlock(functor);
+}
+
</ins><span class="cx"> Debugger::Debugger(bool isInWorkerThread)
</span><span class="cx">     : m_vm(nullptr)
</span><span class="cx">     , m_pauseOnExceptionsState(DontPauseOnExceptions)
</span><span class="lines">@@ -232,7 +239,7 @@
</span><span class="cx">     if (!m_vm)
</span><span class="cx">         return;
</span><span class="cx">     SetSteppingModeFunctor functor(this, mode);
</span><del>-    m_vm-&gt;heap.forEachCodeBlock(functor);
</del><ins>+    forEachCodeBlock(functor);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Debugger::registerCodeBlock(CodeBlock* codeBlock)
</span><span class="lines">@@ -316,7 +323,7 @@
</span><span class="cx">     if (!m_vm)
</span><span class="cx">         return;
</span><span class="cx">     ToggleBreakpointFunctor functor(this, breakpoint, enabledOrNot);
</span><del>-    m_vm-&gt;heap.forEachCodeBlock(functor);
</del><ins>+    forEachCodeBlock(functor);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Debugger::recompileAllJSFunctions(VM* vm)
</span><span class="lines">@@ -328,7 +335,7 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    vm-&gt;prepareToDiscardCode();
</del><ins>+    vm-&gt;waitForCompilationsToComplete();
</ins><span class="cx"> 
</span><span class="cx">     Recompiler recompiler(this);
</span><span class="cx">     HeapIterationScope iterationScope(vm-&gt;heap);
</span><span class="lines">@@ -496,7 +503,7 @@
</span><span class="cx">     if (!m_vm)
</span><span class="cx">         return;
</span><span class="cx">     ClearCodeBlockDebuggerRequestsFunctor functor(this);
</span><del>-    m_vm-&gt;heap.forEachCodeBlock(functor);
</del><ins>+    forEachCodeBlock(functor);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> class Debugger::ClearDebuggerRequestsFunctor {
</span><span class="lines">@@ -521,7 +528,7 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_vm);
</span><span class="cx">     ClearDebuggerRequestsFunctor functor(globalObject);
</span><del>-    m_vm-&gt;heap.forEachCodeBlock(functor);
</del><ins>+    forEachCodeBlock(functor);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Debugger::setBreakpointsActivated(bool activated)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/Debugger.h (165004 => 165005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/Debugger.h        2014-03-03 21:33:17 UTC (rev 165004)
+++ trunk/Source/JavaScriptCore/debugger/Debugger.h        2014-03-03 21:39:21 UTC (rev 165005)
</span><span class="lines">@@ -182,6 +182,8 @@
</span><span class="cx"> 
</span><span class="cx">     void clearDebuggerRequests(JSGlobalObject*);
</span><span class="cx"> 
</span><ins>+    template&lt;typename Functor&gt; inline void forEachCodeBlock(Functor&amp;);
+
</ins><span class="cx">     VM* m_vm;
</span><span class="cx">     HashSet&lt;JSGlobalObject*&gt; m_globalObjects;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (165004 => 165005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2014-03-03 21:33:17 UTC (rev 165004)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2014-03-03 21:39:21 UTC (rev 165005)
</span><span class="lines">@@ -1253,13 +1253,16 @@
</span><span class="cx">     Operands&lt;JSValue&gt; mustHandleValues;
</span><span class="cx">     jitCode-&gt;reconstruct(
</span><span class="cx">         exec, codeBlock, CodeOrigin(bytecodeIndex), streamIndex, mustHandleValues);
</span><ins>+    RefPtr&lt;CodeBlock&gt; replacementCodeBlock = codeBlock-&gt;newReplacement();
</ins><span class="cx">     CompilationResult forEntryResult = compile(
</span><del>-        *vm, codeBlock-&gt;newReplacement().get(), codeBlock, FTLForOSREntryMode, bytecodeIndex,
</del><ins>+        *vm, replacementCodeBlock.get(), codeBlock, FTLForOSREntryMode, bytecodeIndex,
</ins><span class="cx">         mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(codeBlock));
</span><span class="cx">     
</span><del>-    if (forEntryResult != CompilationSuccessful)
</del><ins>+    if (forEntryResult != CompilationSuccessful) {
+        ASSERT(forEntryResult == CompilationDeferred || replacementCodeBlock-&gt;hasOneRef());
</ins><span class="cx">         return 0;
</span><del>-    
</del><ins>+    }
+
</ins><span class="cx">     // It's possible that the for-entry compile already succeeded. In that case OSR
</span><span class="cx">     // entry will succeed unless we ran out of stack. It's not clear what we should do.
</span><span class="cx">     // We signal to try again after a while if that happens.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp (165004 => 165005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2014-03-03 21:33:17 UTC (rev 165004)
+++ trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2014-03-03 21:39:21 UTC (rev 165005)
</span><span class="lines">@@ -391,13 +391,6 @@
</span><span class="cx">     if (!isStillValid())
</span><span class="cx">         return CompilationInvalidated;
</span><span class="cx"> 
</span><del>-    if (vm.enabledProfiler())
-        return CompilationInvalidated;
-
-    Debugger* debugger = codeBlock-&gt;globalObject()-&gt;debugger();
-    if (debugger &amp;&amp; (debugger-&gt;isStepping() || codeBlock-&gt;baselineAlternative()-&gt;hasDebuggerRequests()))
-        return CompilationInvalidated;
-
</del><span class="cx">     bool result;
</span><span class="cx">     if (codeBlock-&gt;codeType() == FunctionCode)
</span><span class="cx">         result = finalizer-&gt;finalizeFunction();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGToFTLDeferredCompilationCallbackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGToFTLDeferredCompilationCallback.cpp (165004 => 165005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGToFTLDeferredCompilationCallback.cpp        2014-03-03 21:33:17 UTC (rev 165004)
+++ trunk/Source/JavaScriptCore/dfg/DFGToFTLDeferredCompilationCallback.cpp        2014-03-03 21:39:21 UTC (rev 165005)
</span><span class="lines">@@ -85,6 +85,8 @@
</span><span class="cx">     
</span><span class="cx">     m_dfgCodeBlock-&gt;jitCode()-&gt;dfg()-&gt;setOptimizationThresholdBasedOnCompilationResult(
</span><span class="cx">         m_dfgCodeBlock.get(), result);
</span><ins>+
+    DeferredCompilationCallback::compilationDidComplete(codeBlock, result);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGToFTLForOSREntryDeferredCompilationCallbackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp (165004 => 165005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp        2014-03-03 21:33:17 UTC (rev 165004)
+++ trunk/Source/JavaScriptCore/dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp        2014-03-03 21:39:21 UTC (rev 165005)
</span><span class="lines">@@ -79,19 +79,19 @@
</span><span class="cx">     switch (result) {
</span><span class="cx">     case CompilationSuccessful:
</span><span class="cx">         jitCode-&gt;osrEntryBlock = codeBlock;
</span><del>-        return;
</del><ins>+        break;
</ins><span class="cx">     case CompilationFailed:
</span><span class="cx">         jitCode-&gt;osrEntryRetry = 0;
</span><span class="cx">         jitCode-&gt;abandonOSREntry = true;
</span><del>-        return;
</del><ins>+        break;
</ins><span class="cx">     case CompilationDeferred:
</span><del>-        return;
</del><ins>+        RELEASE_ASSERT_NOT_REACHED();
</ins><span class="cx">     case CompilationInvalidated:
</span><span class="cx">         jitCode-&gt;osrEntryRetry = 0;
</span><del>-        return;
</del><ins>+        break;
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    RELEASE_ASSERT_NOT_REACHED();
</del><ins>+    DeferredCompilationCallback::compilationDidComplete(codeBlock, result);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCodeBlockSetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp (165004 => 165005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp        2014-03-03 21:33:17 UTC (rev 165004)
+++ trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp        2014-03-03 21:39:21 UTC (rev 165005)
</span><span class="lines">@@ -96,6 +96,12 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void CodeBlockSet::remove(CodeBlock* codeBlock)
+{
+    codeBlock-&gt;deref();
+    m_set.remove(codeBlock);
+}
+
</ins><span class="cx"> void CodeBlockSet::traceMarked(SlotVisitor&amp; visitor)
</span><span class="cx"> {
</span><span class="cx">     if (verbose)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCodeBlockSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CodeBlockSet.h (165004 => 165005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CodeBlockSet.h        2014-03-03 21:33:17 UTC (rev 165004)
+++ trunk/Source/JavaScriptCore/heap/CodeBlockSet.h        2014-03-03 21:39:21 UTC (rev 165005)
</span><span class="lines">@@ -65,6 +65,8 @@
</span><span class="cx">     // by this set), and that have not been marked.
</span><span class="cx">     void deleteUnmarkedAndUnreferenced();
</span><span class="cx">     
</span><ins>+    void remove(CodeBlock*);
+    
</ins><span class="cx">     // Trace all marked code blocks. The CodeBlock is free to make use of
</span><span class="cx">     // mayBeExecuting.
</span><span class="cx">     void traceMarked(SlotVisitor&amp;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.h (165004 => 165005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.h        2014-03-03 21:33:17 UTC (rev 165004)
+++ trunk/Source/JavaScriptCore/heap/Heap.h        2014-03-03 21:39:21 UTC (rev 165005)
</span><span class="lines">@@ -209,6 +209,8 @@
</span><span class="cx">         template&lt;typename T&gt; void releaseSoon(RetainPtr&lt;T&gt;&amp;&amp;);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+        void removeCodeBlock(CodeBlock* cb) { m_codeBlocks.remove(cb); }
+
</ins><span class="cx">     private:
</span><span class="cx">         friend class CodeBlock;
</span><span class="cx">         friend class CopiedBlock;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (165004 => 165005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2014-03-03 21:33:17 UTC (rev 165004)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2014-03-03 21:39:21 UTC (rev 165005)
</span><span class="lines">@@ -1199,12 +1199,15 @@
</span><span class="cx">                 mustHandleValues[i] = exec-&gt;uncheckedR(operand).jsValue();
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        RefPtr&lt;CodeBlock&gt; replacementCodeBlock = codeBlock-&gt;newReplacement();
</ins><span class="cx">         CompilationResult result = DFG::compile(
</span><del>-            vm, codeBlock-&gt;newReplacement().get(), 0, DFG::DFGMode, bytecodeIndex,
</del><ins>+            vm, replacementCodeBlock.get(), 0, DFG::DFGMode, bytecodeIndex,
</ins><span class="cx">             mustHandleValues, JITToDFGDeferredCompilationCallback::create());
</span><span class="cx">         
</span><del>-        if (result != CompilationSuccessful)
</del><ins>+        if (result != CompilationSuccessful) {
+            ASSERT(result == CompilationDeferred || replacementCodeBlock-&gt;hasOneRef());
</ins><span class="cx">             return encodeResult(0, 0);
</span><ins>+        }
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     CodeBlock* optimizedCodeBlock = codeBlock-&gt;replacement();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITToDFGDeferredCompilationCallbackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITToDFGDeferredCompilationCallback.cpp (165004 => 165005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITToDFGDeferredCompilationCallback.cpp        2014-03-03 21:33:17 UTC (rev 165004)
+++ trunk/Source/JavaScriptCore/jit/JITToDFGDeferredCompilationCallback.cpp        2014-03-03 21:39:21 UTC (rev 165005)
</span><span class="lines">@@ -65,6 +65,8 @@
</span><span class="cx">         codeBlock-&gt;install();
</span><span class="cx">     
</span><span class="cx">     codeBlock-&gt;alternative()-&gt;setOptimizationThresholdBasedOnCompilationResult(result);
</span><ins>+
+    DeferredCompilationCallback::compilationDidComplete(codeBlock, result);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (165004 => 165005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2014-03-03 21:33:17 UTC (rev 165004)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2014-03-03 21:39:21 UTC (rev 165005)
</span><span class="lines">@@ -512,7 +512,7 @@
</span><span class="cx">     interpreter-&gt;stopSampling();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void VM::prepareToDiscardCode()
</del><ins>+void VM::waitForCompilationsToComplete()
</ins><span class="cx"> {
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     for (unsigned i = DFG::numberOfWorklists(); i--;) {
</span><span class="lines">@@ -524,7 +524,7 @@
</span><span class="cx"> 
</span><span class="cx"> void VM::discardAllCode()
</span><span class="cx"> {
</span><del>-    prepareToDiscardCode();
</del><ins>+    waitForCompilationsToComplete();
</ins><span class="cx">     m_codeCache-&gt;clear();
</span><span class="cx">     heap.deleteAllCompiledCode();
</span><span class="cx">     heap.reportAbandonedObjectGraph();
</span><span class="lines">@@ -566,7 +566,7 @@
</span><span class="cx"> 
</span><span class="cx"> void VM::releaseExecutableMemory()
</span><span class="cx"> {
</span><del>-    prepareToDiscardCode();
</del><ins>+    waitForCompilationsToComplete();
</ins><span class="cx">     
</span><span class="cx">     if (entryScope) {
</span><span class="cx">         StackPreservingRecompiler recompiler;
</span><span class="lines">@@ -872,6 +872,7 @@
</span><span class="cx"> {
</span><span class="cx">     m_enabledProfiler = profiler;
</span><span class="cx">     if (m_enabledProfiler) {
</span><ins>+        waitForCompilationsToComplete();
</ins><span class="cx">         SetEnabledProfilerFunctor functor;
</span><span class="cx">         heap.forEachCodeBlock(functor);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (165004 => 165005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2014-03-03 21:33:17 UTC (rev 165004)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2014-03-03 21:39:21 UTC (rev 165005)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008, 2009, 2013, 2014 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">@@ -498,7 +498,7 @@
</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><del>-        void prepareToDiscardCode();
</del><ins>+        void waitForCompilationsToComplete();
</ins><span class="cx">         
</span><span class="cx">         JS_EXPORT_PRIVATE void discardAllCode();
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>