<!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>[188792] 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/188792">188792</a></dd>
<dt>Author</dt> <dd>ggaren@apple.com</dd>
<dt>Date</dt> <dd>2015-08-21 15:48:49 -0700 (Fri, 21 Aug 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Unify code paths for manually deleting all code
https://bugs.webkit.org/show_bug.cgi?id=148280

Reviewed by Saam Barati.

We used to have three paths for manually deleting all code. Now we have
one shared path.

* debugger/Debugger.cpp:
(JSC::Debugger::attach): Notify the debugger of all previous code when
it attaches. We used to do this when recompiling, which was only correct
by accident.

(JSC::Debugger::recompileAllJSFunctions): Switch to the shared path.

* heap/Heap.h:
(JSC::Heap::compiledCode):

* inspector/agents/InspectorRuntimeAgent.cpp:
(Inspector::InspectorRuntimeAgent::getRuntimeTypesForVariablesAtOffsets):
(Inspector::InspectorRuntimeAgent::willDestroyFrontendAndBackend):
(Inspector::InspectorRuntimeAgent::setTypeProfilerEnabledState):
(Inspector::InspectorRuntimeAgent::getBasicBlocks):
(Inspector::TypeRecompiler::visit): Deleted.
(Inspector::TypeRecompiler::operator()): Deleted.
(Inspector::recompileAllJSFunctionsForTypeProfiling): Deleted. Switch
to the shared path.

* runtime/VM.cpp:
(JSC::VM::afterVMExit): Added a helper for scheduling an activity after
VM exit. We can't delete code while it's on the stack, and we can't
delete auxiliary profiling data while profiling code is on the stack,
so in those cases, we schedule the deletion for the next time we exit.

(JSC::VM::deleteAllCode): Use afterVMExit because we might have code
on the stack when debugger, profiler, or watchdog state changes.

* runtime/VM.h:

* runtime/VMEntryScope.cpp:
(JSC::VMEntryScope::VMEntryScope):
(JSC::VMEntryScope::addDidPopListener):
(JSC::VMEntryScope::~VMEntryScope):
(JSC::VMEntryScope::setEntryScopeDidPopListener): Deleted.
* runtime/VMEntryScope.h:
(JSC::VMEntryScope::globalObject): Removed the uniquing feature from
the scope pop listener list because we don't have a client that wants
it, and it's not convenient to use correctly since you can't take
the address of a member function, a lambda, or an std::function. We can
add this feature back if we discover that we want it.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggercpp">trunk/Source/JavaScriptCore/debugger/Debugger.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeaph">trunk/Source/JavaScriptCore/heap/Heap.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectoragentsInspectorRuntimeAgentcpp">trunk/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.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>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMEntryScopecpp">trunk/Source/JavaScriptCore/runtime/VMEntryScope.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMEntryScopeh">trunk/Source/JavaScriptCore/runtime/VMEntryScope.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (188791 => 188792)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-08-21 22:42:35 UTC (rev 188791)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-08-21 22:48:49 UTC (rev 188792)
</span><span class="lines">@@ -1,3 +1,56 @@
</span><ins>+2015-08-21  Geoffrey Garen  &lt;ggaren@apple.com&gt;
+
+        Unify code paths for manually deleting all code
+        https://bugs.webkit.org/show_bug.cgi?id=148280
+
+        Reviewed by Saam Barati.
+
+        We used to have three paths for manually deleting all code. Now we have
+        one shared path.
+
+        * debugger/Debugger.cpp:
+        (JSC::Debugger::attach): Notify the debugger of all previous code when
+        it attaches. We used to do this when recompiling, which was only correct
+        by accident.
+
+        (JSC::Debugger::recompileAllJSFunctions): Switch to the shared path.
+
+        * heap/Heap.h:
+        (JSC::Heap::compiledCode):
+
+        * inspector/agents/InspectorRuntimeAgent.cpp:
+        (Inspector::InspectorRuntimeAgent::getRuntimeTypesForVariablesAtOffsets):
+        (Inspector::InspectorRuntimeAgent::willDestroyFrontendAndBackend):
+        (Inspector::InspectorRuntimeAgent::setTypeProfilerEnabledState):
+        (Inspector::InspectorRuntimeAgent::getBasicBlocks):
+        (Inspector::TypeRecompiler::visit): Deleted.
+        (Inspector::TypeRecompiler::operator()): Deleted.
+        (Inspector::recompileAllJSFunctionsForTypeProfiling): Deleted. Switch
+        to the shared path.
+
+        * runtime/VM.cpp:
+        (JSC::VM::afterVMExit): Added a helper for scheduling an activity after
+        VM exit. We can't delete code while it's on the stack, and we can't
+        delete auxiliary profiling data while profiling code is on the stack,
+        so in those cases, we schedule the deletion for the next time we exit.
+
+        (JSC::VM::deleteAllCode): Use afterVMExit because we might have code
+        on the stack when debugger, profiler, or watchdog state changes.
+
+        * runtime/VM.h:
+
+        * runtime/VMEntryScope.cpp:
+        (JSC::VMEntryScope::VMEntryScope):
+        (JSC::VMEntryScope::addDidPopListener):
+        (JSC::VMEntryScope::~VMEntryScope):
+        (JSC::VMEntryScope::setEntryScopeDidPopListener): Deleted.
+        * runtime/VMEntryScope.h:
+        (JSC::VMEntryScope::globalObject): Removed the uniquing feature from
+        the scope pop listener list because we don't have a client that wants
+        it, and it's not convenient to use correctly since you can't take
+        the address of a member function, a lambda, or an std::function. We can
+        add this feature back if we discover that we want it.
+
</ins><span class="cx"> 2015-08-21  Sukolsak Sakshuwong  &lt;sukolsak@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Implement WebAssembly function parser
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/Debugger.cpp (188791 => 188792)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/Debugger.cpp        2015-08-21 22:42:35 UTC (rev 188791)
+++ trunk/Source/JavaScriptCore/debugger/Debugger.cpp        2015-08-21 22:48:49 UTC (rev 188792)
</span><span class="lines">@@ -35,72 +35,6 @@
</span><span class="cx"> #include &quot;Protect.h&quot;
</span><span class="cx"> #include &quot;VMEntryScope.h&quot;
</span><span class="cx"> 
</span><del>-namespace {
-
-using namespace JSC;
-
-class Recompiler : public MarkedBlock::VoidFunctor {
-public:
-    Recompiler(JSC::Debugger*);
-    ~Recompiler();
-    IterationStatus operator()(JSCell*);
-
-private:
-    typedef HashSet&lt;FunctionExecutable*&gt; FunctionExecutableSet;
-    typedef HashMap&lt;SourceProvider*, ExecState*&gt; SourceProviderMap;
-    
-    void visit(JSCell*);
-    
-    JSC::Debugger* m_debugger;
-    FunctionExecutableSet m_functionExecutables;
-    SourceProviderMap m_sourceProviders;
-};
-
-inline Recompiler::Recompiler(JSC::Debugger* debugger)
-    : m_debugger(debugger)
-{
-}
-
-inline Recompiler::~Recompiler()
-{
-    // Call sourceParsed() after reparsing all functions because it will execute
-    // JavaScript in the inspector.
-    SourceProviderMap::const_iterator end = m_sourceProviders.end();
-    for (SourceProviderMap::const_iterator iter = m_sourceProviders.begin(); iter != end; ++iter)
-        m_debugger-&gt;sourceParsed(iter-&gt;value, iter-&gt;key, -1, String());
-}
-
-inline void Recompiler::visit(JSCell* cell)
-{
-    if (!cell-&gt;inherits(JSFunction::info()))
-        return;
-
-    JSFunction* function = jsCast&lt;JSFunction*&gt;(cell);
-    if (function-&gt;executable()-&gt;isHostFunction())
-        return;
-
-    FunctionExecutable* executable = function-&gt;jsExecutable();
-
-    // Check if the function is already in the set - if so,
-    // we've already retranslated it, nothing to do here.
-    if (!m_functionExecutables.add(executable).isNewEntry)
-        return;
-
-    ExecState* exec = function-&gt;scope()-&gt;globalObject()-&gt;JSGlobalObject::globalExec();
-    executable-&gt;clearCode();
-    executable-&gt;clearUnlinkedCodeForRecompilation();
-    if (m_debugger == function-&gt;scope()-&gt;globalObject()-&gt;debugger())
-        m_sourceProviders.add(executable-&gt;source().provider(), exec);
-}
-
-inline IterationStatus Recompiler::operator()(JSCell* cell)
-{
-    visit(cell);
-    return IterationStatus::Continue;
-}
-
-} // namespace
-
</del><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> class DebuggerPausedScope {
</span><span class="lines">@@ -180,6 +114,15 @@
</span><span class="cx">         ASSERT(m_vm == &amp;globalObject-&gt;vm());
</span><span class="cx">     globalObject-&gt;setDebugger(this);
</span><span class="cx">     m_globalObjects.add(globalObject);
</span><ins>+
+    // Call sourceParsed() because it will execute JavaScript in the inspector.
+    for (size_t i = 0; i &lt; m_vm-&gt;heap.compiledCode().size(); ++i) {
+        ExecutableBase* base = m_vm-&gt;heap.compiledCode()[i];
+        if (!base-&gt;isFunctionExecutable())
+            continue;
+        FunctionExecutable* executable = static_cast&lt;FunctionExecutable*&gt;(base);
+        sourceParsed(globalObject-&gt;globalExec(), executable-&gt;source().provider(), -1, String());
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Debugger::detach(JSGlobalObject* globalObject, ReasonForDetach reason)
</span><span class="lines">@@ -336,26 +279,7 @@
</span><span class="cx"> 
</span><span class="cx"> void Debugger::recompileAllJSFunctions(VM* vm)
</span><span class="cx"> {
</span><del>-    // If JavaScript is running, it's not safe to recompile, since we'll end
-    // up throwing away code that is live on the stack.
-    if (vm-&gt;entryScope) {
-        auto listener = [] (VM&amp; vm, JSGlobalObject* globalObject) 
-        {
-            if (Debugger* debugger = globalObject-&gt;debugger())
-                debugger-&gt;recompileAllJSFunctions(&amp;vm);
-        };
-
-        vm-&gt;entryScope-&gt;setEntryScopeDidPopListener(this, listener);
-        return;
-    }
-
-#if ENABLE(DFG_JIT)
-    DFG::completeAllPlansForVM(*vm);
-#endif
-
-    Recompiler recompiler(this);
-    HeapIterationScope iterationScope(vm-&gt;heap);
-    vm-&gt;heap.objectSpace().forEachLiveCell(iterationScope, recompiler);
</del><ins>+    vm-&gt;deleteAllCode();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> BreakpointID Debugger::setBreakpoint(Breakpoint breakpoint, unsigned&amp; actualLine, unsigned&amp; actualColumn)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.h (188791 => 188792)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.h        2015-08-21 22:42:35 UTC (rev 188791)
+++ trunk/Source/JavaScriptCore/heap/Heap.h        2015-08-21 22:48:49 UTC (rev 188792)
</span><span class="lines">@@ -237,6 +237,8 @@
</span><span class="cx"> 
</span><span class="cx">     void addLogicallyEmptyWeakBlock(WeakBlock*);
</span><span class="cx"> 
</span><ins>+    Vector&lt;ExecutableBase*&gt;&amp; compiledCode() { return m_compiledCode; }
+
</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="trunkSourceJavaScriptCoreinspectoragentsInspectorRuntimeAgentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp (188791 => 188792)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp        2015-08-21 22:42:35 UTC (rev 188791)
+++ trunk/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp        2015-08-21 22:48:49 UTC (rev 188792)
</span><span class="lines">@@ -308,40 +308,6 @@
</span><span class="cx">         dataLogF(&quot;Inspector::getRuntimeTypesForVariablesAtOffsets took %lfms\n&quot;, end - start);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-class TypeRecompiler : public MarkedBlock::VoidFunctor {
-public:
-    inline void visit(JSCell* cell)
-    {
-        if (!cell-&gt;inherits(FunctionExecutable::info()))
-            return;
-
-        FunctionExecutable* executable = jsCast&lt;FunctionExecutable*&gt;(cell);
-        executable-&gt;clearCode();
-        executable-&gt;clearUnlinkedCodeForRecompilation();
-    }
-    inline IterationStatus operator()(JSCell* cell)
-    {
-        visit(cell);
-        return IterationStatus::Continue;
-    }
-};
-
-static void recompileAllJSFunctionsForTypeProfiling(VM&amp; vm, bool shouldEnableTypeProfiling)
-{
-    bool shouldRecompileFromTypeProfiler = (shouldEnableTypeProfiling ? vm.enableTypeProfiler() : vm.disableTypeProfiler());
-    bool shouldRecompileFromControlFlowProfiler = (shouldEnableTypeProfiling ? vm.enableControlFlowProfiler() : vm.disableControlFlowProfiler());
-    bool needsToRecompile = shouldRecompileFromTypeProfiler || shouldRecompileFromControlFlowProfiler;
-
-    if (needsToRecompile) {
-#if ENABLE(DFG_JIT)
-        DFG::completeAllPlansForVM(vm);
-#endif
-        TypeRecompiler recompiler;
-        HeapIterationScope iterationScope(vm.heap);
-        vm.heap.objectSpace().forEachLiveCell(iterationScope, recompiler);
-    }
-}
-
</del><span class="cx"> void InspectorRuntimeAgent::willDestroyFrontendAndBackend(DisconnectReason reason)
</span><span class="cx"> {
</span><span class="cx">     if (reason != DisconnectReason::InspectedTargetDestroyed &amp;&amp; m_isTypeProfilingEnabled)
</span><span class="lines">@@ -358,25 +324,21 @@
</span><span class="cx">     setTypeProfilerEnabledState(false);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void InspectorRuntimeAgent::setTypeProfilerEnabledState(bool shouldEnableTypeProfiling)
</del><ins>+void InspectorRuntimeAgent::setTypeProfilerEnabledState(bool isTypeProfilingEnabled)
</ins><span class="cx"> {
</span><del>-    if (m_isTypeProfilingEnabled == shouldEnableTypeProfiling)
</del><ins>+    if (m_isTypeProfilingEnabled == isTypeProfilingEnabled)
</ins><span class="cx">         return;
</span><ins>+    m_isTypeProfilingEnabled = isTypeProfilingEnabled;
</ins><span class="cx"> 
</span><del>-    m_isTypeProfilingEnabled = shouldEnableTypeProfiling;
-
</del><span class="cx">     VM&amp; vm = globalVM();
</span><ins>+    vm.whenIdle([&amp;vm, isTypeProfilingEnabled] () {
+        bool shouldRecompileFromTypeProfiler = (isTypeProfilingEnabled ? vm.enableTypeProfiler() : vm.disableTypeProfiler());
+        bool shouldRecompileFromControlFlowProfiler = (isTypeProfilingEnabled ? vm.enableControlFlowProfiler() : vm.disableControlFlowProfiler());
+        bool needsToRecompile = shouldRecompileFromTypeProfiler || shouldRecompileFromControlFlowProfiler;
</ins><span class="cx"> 
</span><del>-    // If JavaScript is running, it's not safe to recompile, since we'll end
-    // up throwing away code that is live on the stack.
-    if (vm.entryScope) {
-        vm.entryScope-&gt;setEntryScopeDidPopListener(this,
-            [=] (VM&amp; vm, JSGlobalObject*) {
-                recompileAllJSFunctionsForTypeProfiling(vm, shouldEnableTypeProfiling);
-            }
-        );
-    } else
-        recompileAllJSFunctionsForTypeProfiling(vm, shouldEnableTypeProfiling);
</del><ins>+        if (needsToRecompile)
+            vm.deleteAllCode();
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void InspectorRuntimeAgent::getBasicBlocks(ErrorString&amp; errorString, const String&amp; sourceIDAsString, RefPtr&lt;Inspector::Protocol::Array&lt;Inspector::Protocol::Runtime::BasicBlock&gt;&gt;&amp; basicBlocks)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (188791 => 188792)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2015-08-21 22:42:35 UTC (rev 188791)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2015-08-21 22:48:49 UTC (rev 188792)
</span><span class="lines">@@ -86,6 +86,7 @@
</span><span class="cx"> #include &quot;TypeProfiler.h&quot;
</span><span class="cx"> #include &quot;TypeProfilerLog.h&quot;
</span><span class="cx"> #include &quot;UnlinkedCodeBlock.h&quot;
</span><ins>+#include &quot;VMEntryScope.h&quot;
</ins><span class="cx"> #include &quot;Watchdog.h&quot;
</span><span class="cx"> #include &quot;WeakGCMapInlines.h&quot;
</span><span class="cx"> #include &quot;WeakMapData.h&quot;
</span><span class="lines">@@ -471,16 +472,28 @@
</span><span class="cx">     interpreter-&gt;stopSampling();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void VM::whenIdle(std::function&lt;void()&gt; callback)
+{
+    if (!entryScope) {
+        callback();
+        return;
+    }
+
+    entryScope-&gt;addDidPopListener(callback);
+}
+
</ins><span class="cx"> void VM::deleteAllCode()
</span><span class="cx"> {
</span><del>-    m_codeCache-&gt;clear();
-    m_regExpCache-&gt;deleteAllCode();
</del><ins>+    whenIdle([this]() {
+        m_codeCache-&gt;clear();
+        m_regExpCache-&gt;deleteAllCode();
</ins><span class="cx"> #if ENABLE(DFG_JIT)
</span><del>-    DFG::completeAllPlansForVM(*this);
</del><ins>+        DFG::completeAllPlansForVM(*this);
</ins><span class="cx"> #endif
</span><del>-    heap.deleteAllCompiledCode();
-    heap.deleteAllUnlinkedFunctionCode();
-    heap.reportAbandonedObjectGraph();
</del><ins>+        heap.deleteAllCompiledCode();
+        heap.deleteAllUnlinkedFunctionCode();
+        heap.reportAbandonedObjectGraph();
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void VM::dumpSampleData(ExecState* exec)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (188791 => 188792)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2015-08-21 22:42:35 UTC (rev 188791)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2015-08-21 22:48:49 UTC (rev 188792)
</span><span class="lines">@@ -541,6 +541,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 whenIdle(std::function&lt;void()&gt;);
+
</ins><span class="cx">     JS_EXPORT_PRIVATE void deleteAllCode();
</span><span class="cx"> 
</span><span class="cx">     void registerWatchpointForImpureProperty(const Identifier&amp;, Watchpoint*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMEntryScopecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VMEntryScope.cpp (188791 => 188792)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VMEntryScope.cpp        2015-08-21 22:42:35 UTC (rev 188791)
+++ trunk/Source/JavaScriptCore/runtime/VMEntryScope.cpp        2015-08-21 22:48:49 UTC (rev 188792)
</span><span class="lines">@@ -57,9 +57,9 @@
</span><span class="cx">     vm.clearLastException();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void VMEntryScope::setEntryScopeDidPopListener(void* key, EntryScopeDidPopListener listener)
</del><ins>+void VMEntryScope::addDidPopListener(std::function&lt;void ()&gt; listener)
</ins><span class="cx"> {
</span><del>-    m_allEntryScopeDidPopListeners.set(key, listener);
</del><ins>+    m_didPopListeners.append(listener);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> VMEntryScope::~VMEntryScope()
</span><span class="lines">@@ -72,8 +72,8 @@
</span><span class="cx"> 
</span><span class="cx">     m_vm.entryScope = nullptr;
</span><span class="cx"> 
</span><del>-    for (auto&amp; listener : m_allEntryScopeDidPopListeners.values())
-        listener(m_vm, m_globalObject);
</del><ins>+    for (auto&amp; listener : m_didPopListeners)
+        listener();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMEntryScopeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VMEntryScope.h (188791 => 188792)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VMEntryScope.h        2015-08-21 22:42:35 UTC (rev 188791)
+++ trunk/Source/JavaScriptCore/runtime/VMEntryScope.h        2015-08-21 22:48:49 UTC (rev 188792)
</span><span class="lines">@@ -27,9 +27,9 @@
</span><span class="cx"> #define VMEntryScope_h
</span><span class="cx"> 
</span><span class="cx"> #include &quot;Interpreter.h&quot;
</span><del>-#include &lt;wtf/HashMap.h&gt;
</del><span class="cx"> #include &lt;wtf/StackBounds.h&gt;
</span><span class="cx"> #include &lt;wtf/StackStats.h&gt;
</span><ins>+#include &lt;wtf/Vector.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -43,13 +43,12 @@
</span><span class="cx"> 
</span><span class="cx">     JSGlobalObject* globalObject() const { return m_globalObject; }
</span><span class="cx"> 
</span><del>-    typedef std::function&lt;void (VM&amp;, JSGlobalObject*)&gt; EntryScopeDidPopListener;
-    void setEntryScopeDidPopListener(void*, EntryScopeDidPopListener);
</del><ins>+    void addDidPopListener(std::function&lt;void ()&gt;);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     VM&amp; m_vm;
</span><span class="cx">     JSGlobalObject* m_globalObject;
</span><del>-    HashMap&lt;void*, EntryScopeDidPopListener&gt; m_allEntryScopeDidPopListeners;
</del><ins>+    Vector&lt;std::function&lt;void ()&gt;&gt; m_didPopListeners;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre>
</div>
</div>

</body>
</html>