<!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>[190561] trunk/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/190561">190561</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-10-05 10:05:24 -0700 (Mon, 05 Oct 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Inline cache repatching should be throttled if it happens a lot
https://bugs.webkit.org/show_bug.cgi?id=149796
rdar://problem/22674436

Reviewed by Saam Barati.

Source/JavaScriptCore:

We noticed a slight PLT regression from http://trac.webkit.org/changeset/189586. It's because
some pages do things that our inline caches mishandle, in the sense that some ICs end up
repatching themselves very frequently. The cost of repatching outweighs the speed-up on those
pages. There are probably super smart things we could do to tune the IC heuristics to make the
ICs do the right thing on those pages. But more fundamentally, we should ensure that our ICs
back off from continuous repatching if they repatch a lot. That's what this change does.

With this change, StructureStubInfo counts the number of repatchings. If that exceeds a
threshold, we put the IC into a cool-down mode, where some number of future repatch events do
nothing but decrement the cool-down counter. The duration of cool-down increases exponentially
every time we have to do it.

This change also outlines a lot of code. The fact that StructureStubInfo had a lot of inline
methods was starting to get on my nerves. Now it only has inline methods for things that need
to be inlined. Also, I changed StructureStubInfo to be a class rather than a struct. Maybe
with enough such incremental changes, eventually StructureStubInfo will actually behave like a
proper class.

This has no effect on JSC benchmarks. It progresses one of the pages that was hit by the
regression by 15%. It's hard to see if this totally fixes the entire PLT regression since the
geomean regression was very close to noise.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::printGetByIdCacheStatus):
(JSC::CodeBlock::printPutByIdCacheStatus):
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::checkIfOptimizationThresholdReached):
* bytecode/CodeBlock.h:
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback):
(JSC::GetByIdStatus::computeFor):
* bytecode/PolymorphicAccess.cpp:
(JSC::PolymorphicAccess::regenerate):
* bytecode/PolymorphicAccess.h:
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeForStubInfo):
* bytecode/StructureStubClearingWatchpoint.h:
* bytecode/StructureStubInfo.cpp:
(JSC::StructureStubInfo::StructureStubInfo):
(JSC::StructureStubInfo::~StructureStubInfo):
(JSC::StructureStubInfo::initGetByIdSelf):
(JSC::StructureStubInfo::initPutByIdReplace):
(JSC::StructureStubInfo::initStub):
(JSC::StructureStubInfo::deref):
(JSC::StructureStubInfo::addAccessCase):
* bytecode/StructureStubInfo.h:
(JSC::StructureStubInfo::considerCaching):
(JSC::StructureStubInfo::willRepatch):
(JSC::StructureStubInfo::willCoolDown):
(JSC::getStructureStubInfoCodeOrigin):
(JSC::StructureStubInfo::StructureStubInfo): Deleted.
(JSC::StructureStubInfo::initGetByIdSelf): Deleted.
(JSC::StructureStubInfo::initPutByIdReplace): Deleted.
(JSC::StructureStubInfo::initStub): Deleted.
(JSC::StructureStubInfo::seenOnce): Deleted.
(JSC::StructureStubInfo::setSeen): Deleted.
* jit/JIT.h:
* jit/JITOperations.cpp:
* jit/Repatch.cpp:
(JSC::tryCacheGetByID):
(JSC::tryCachePutByID):
(JSC::tryRepatchIn):
* runtime/Options.h:

Source/WTF:

Add some helpers for saturated math.

* wtf/MathExtras.h:
(WTF::incrementWithSaturation):
(WTF::leftShiftWithSaturation):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeGetByIdStatuscpp">trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePolymorphicAccesscpp">trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePolymorphicAccessh">trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePutByIdStatuscpp">trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeStructureStubClearingWatchpointh">trunk/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeStructureStubInfocpp">trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeStructureStubInfoh">trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRepatchcpp">trunk/Source/JavaScriptCore/jit/Repatch.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfMathExtrash">trunk/Source/WTF/wtf/MathExtras.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (190560 => 190561)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-10-05 15:12:27 UTC (rev 190560)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-10-05 17:05:24 UTC (rev 190561)
</span><span class="lines">@@ -1,5 +1,77 @@
</span><span class="cx"> 2015-10-04  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Inline cache repatching should be throttled if it happens a lot
+        https://bugs.webkit.org/show_bug.cgi?id=149796
+        rdar://problem/22674436
+
+        Reviewed by Saam Barati.
+
+        We noticed a slight PLT regression from http://trac.webkit.org/changeset/189586. It's because
+        some pages do things that our inline caches mishandle, in the sense that some ICs end up
+        repatching themselves very frequently. The cost of repatching outweighs the speed-up on those
+        pages. There are probably super smart things we could do to tune the IC heuristics to make the
+        ICs do the right thing on those pages. But more fundamentally, we should ensure that our ICs
+        back off from continuous repatching if they repatch a lot. That's what this change does.
+
+        With this change, StructureStubInfo counts the number of repatchings. If that exceeds a
+        threshold, we put the IC into a cool-down mode, where some number of future repatch events do
+        nothing but decrement the cool-down counter. The duration of cool-down increases exponentially
+        every time we have to do it.
+
+        This change also outlines a lot of code. The fact that StructureStubInfo had a lot of inline
+        methods was starting to get on my nerves. Now it only has inline methods for things that need
+        to be inlined. Also, I changed StructureStubInfo to be a class rather than a struct. Maybe
+        with enough such incremental changes, eventually StructureStubInfo will actually behave like a
+        proper class.
+
+        This has no effect on JSC benchmarks. It progresses one of the pages that was hit by the
+        regression by 15%. It's hard to see if this totally fixes the entire PLT regression since the
+        geomean regression was very close to noise.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::printGetByIdCacheStatus):
+        (JSC::CodeBlock::printPutByIdCacheStatus):
+        (JSC::CodeBlock::CodeBlock):
+        (JSC::CodeBlock::checkIfOptimizationThresholdReached):
+        * bytecode/CodeBlock.h:
+        * bytecode/GetByIdStatus.cpp:
+        (JSC::GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback):
+        (JSC::GetByIdStatus::computeFor):
+        * bytecode/PolymorphicAccess.cpp:
+        (JSC::PolymorphicAccess::regenerate):
+        * bytecode/PolymorphicAccess.h:
+        * bytecode/PutByIdStatus.cpp:
+        (JSC::PutByIdStatus::computeForStubInfo):
+        * bytecode/StructureStubClearingWatchpoint.h:
+        * bytecode/StructureStubInfo.cpp:
+        (JSC::StructureStubInfo::StructureStubInfo):
+        (JSC::StructureStubInfo::~StructureStubInfo):
+        (JSC::StructureStubInfo::initGetByIdSelf):
+        (JSC::StructureStubInfo::initPutByIdReplace):
+        (JSC::StructureStubInfo::initStub):
+        (JSC::StructureStubInfo::deref):
+        (JSC::StructureStubInfo::addAccessCase):
+        * bytecode/StructureStubInfo.h:
+        (JSC::StructureStubInfo::considerCaching):
+        (JSC::StructureStubInfo::willRepatch):
+        (JSC::StructureStubInfo::willCoolDown):
+        (JSC::getStructureStubInfoCodeOrigin):
+        (JSC::StructureStubInfo::StructureStubInfo): Deleted.
+        (JSC::StructureStubInfo::initGetByIdSelf): Deleted.
+        (JSC::StructureStubInfo::initPutByIdReplace): Deleted.
+        (JSC::StructureStubInfo::initStub): Deleted.
+        (JSC::StructureStubInfo::seenOnce): Deleted.
+        (JSC::StructureStubInfo::setSeen): Deleted.
+        * jit/JIT.h:
+        * jit/JITOperations.cpp:
+        * jit/Repatch.cpp:
+        (JSC::tryCacheGetByID):
+        (JSC::tryCachePutByID):
+        (JSC::tryRepatchIn):
+        * runtime/Options.h:
+
+2015-10-04  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
</ins><span class="cx">         CodeBlock.h shouldn't be included from everywhere
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=149785
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (190560 => 190561)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-10-05 15:12:27 UTC (rev 190560)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-10-05 17:05:24 UTC (rev 190561)
</span><span class="lines">@@ -341,39 +341,37 @@
</span><span class="cx">         if (stubInfo.resetByGC)
</span><span class="cx">             out.print(&quot; (Reset By GC)&quot;);
</span><span class="cx">         
</span><del>-        if (stubInfo.seen) {
-            out.printf(&quot; jit(&quot;);
</del><ins>+        out.printf(&quot; jit(&quot;);
</ins><span class="cx">             
</span><del>-            Structure* baseStructure = nullptr;
-            PolymorphicAccess* stub = nullptr;
</del><ins>+        Structure* baseStructure = nullptr;
+        PolymorphicAccess* stub = nullptr;
</ins><span class="cx">             
</span><del>-            switch (stubInfo.cacheType) {
-            case CacheType::GetByIdSelf:
-                out.printf(&quot;self&quot;);
-                baseStructure = stubInfo.u.byIdSelf.baseObjectStructure.get();
-                break;
-            case CacheType::Stub:
-                out.printf(&quot;stub&quot;);
-                stub = stubInfo.u.stub;
-                break;
-            case CacheType::Unset:
-                out.printf(&quot;unset&quot;);
-                break;
-            default:
-                RELEASE_ASSERT_NOT_REACHED();
-                break;
-            }
</del><ins>+        switch (stubInfo.cacheType) {
+        case CacheType::GetByIdSelf:
+            out.printf(&quot;self&quot;);
+            baseStructure = stubInfo.u.byIdSelf.baseObjectStructure.get();
+            break;
+        case CacheType::Stub:
+            out.printf(&quot;stub&quot;);
+            stub = stubInfo.u.stub;
+            break;
+        case CacheType::Unset:
+            out.printf(&quot;unset&quot;);
+            break;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
+        }
</ins><span class="cx">             
</span><del>-            if (baseStructure) {
-                out.printf(&quot;, &quot;);
-                dumpStructure(out, &quot;struct&quot;, baseStructure, ident);
-            }
</del><ins>+        if (baseStructure) {
+            out.printf(&quot;, &quot;);
+            dumpStructure(out, &quot;struct&quot;, baseStructure, ident);
+        }
</ins><span class="cx"> 
</span><del>-            if (stub)
-                out.print(&quot;, &quot;, *stub);
</del><ins>+        if (stub)
+            out.print(&quot;, &quot;, *stub);
</ins><span class="cx"> 
</span><del>-            out.printf(&quot;)&quot;);
-        }
</del><ins>+        out.printf(&quot;)&quot;);
</ins><span class="cx">     }
</span><span class="cx"> #else
</span><span class="cx">     UNUSED_PARAM(map);
</span><span class="lines">@@ -413,27 +411,25 @@
</span><span class="cx">         if (stubInfo.resetByGC)
</span><span class="cx">             out.print(&quot; (Reset By GC)&quot;);
</span><span class="cx">         
</span><del>-        if (stubInfo.seen) {
-            out.printf(&quot; jit(&quot;);
-            
-            switch (stubInfo.cacheType) {
-            case CacheType::PutByIdReplace:
-                out.print(&quot;replace, &quot;);
-                dumpStructure(out, &quot;struct&quot;, stubInfo.u.byIdSelf.baseObjectStructure.get(), ident);
-                break;
-            case CacheType::Stub: {
-                out.print(&quot;stub, &quot;, *stubInfo.u.stub);
-                break;
-            }
-            case CacheType::Unset:
-                out.printf(&quot;unset&quot;);
-                break;
-            default:
-                RELEASE_ASSERT_NOT_REACHED();
-                break;
-            }
-            out.printf(&quot;)&quot;);
</del><ins>+        out.printf(&quot; jit(&quot;);
+        
+        switch (stubInfo.cacheType) {
+        case CacheType::PutByIdReplace:
+            out.print(&quot;replace, &quot;);
+            dumpStructure(out, &quot;struct&quot;, stubInfo.u.byIdSelf.baseObjectStructure.get(), ident);
+            break;
+        case CacheType::Stub: {
+            out.print(&quot;stub, &quot;, *stubInfo.u.stub);
+            break;
</ins><span class="cx">         }
</span><ins>+        case CacheType::Unset:
+            out.printf(&quot;unset&quot;);
+            break;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
+        }
+        out.printf(&quot;)&quot;);
</ins><span class="cx">     }
</span><span class="cx"> #else
</span><span class="cx">     UNUSED_PARAM(map);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeGetByIdStatuscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp (190560 => 190561)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp        2015-10-05 15:12:27 UTC (rev 190560)
+++ trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp        2015-10-05 17:05:24 UTC (rev 190561)
</span><span class="lines">@@ -137,12 +137,9 @@
</span><span class="cx">     const ConcurrentJITLocker&amp; locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, UniquedStringImpl* uid,
</span><span class="cx">     CallLinkStatus::ExitSiteData callExitSiteData)
</span><span class="cx"> {
</span><del>-    if (!stubInfo)
</del><ins>+    if (!stubInfo || !stubInfo-&gt;everConsidered)
</ins><span class="cx">         return GetByIdStatus(NoInformation);
</span><del>-    
-    if (!stubInfo-&gt;seen)
-        return GetByIdStatus(NoInformation);
-    
</del><ins>+
</ins><span class="cx">     PolymorphicAccess* list = 0;
</span><span class="cx">     State slowPathState = TakesSlowPath;
</span><span class="cx">     if (stubInfo-&gt;cacheType == CacheType::Stub) {
</span><span class="lines">@@ -269,7 +266,7 @@
</span><span class="cx">             result = computeForStubInfoWithoutExitSiteFeedback(
</span><span class="cx">                 locker, dfgBlock, dfgMap.get(codeOrigin), uid, exitSiteData);
</span><span class="cx">         }
</span><del>-        
</del><ins>+
</ins><span class="cx">         if (result.takesSlowPath())
</span><span class="cx">             return result;
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePolymorphicAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp (190560 => 190561)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2015-10-05 15:12:27 UTC (rev 190560)
+++ trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2015-10-05 17:05:24 UTC (rev 190561)
</span><span class="lines">@@ -1127,14 +1127,18 @@
</span><span class="cx">         state.failAndRepatch.append(binarySwitch.fallThrough());
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    state.failAndIgnore.link(&amp;jit);
</del><ins>+    if (!state.failAndIgnore.empty()) {
+        state.failAndIgnore.link(&amp;jit);
+        
+        // Make sure that the inline cache optimization code knows that we are taking slow path because
+        // of something that isn't patchable. The slow path will decrement &quot;countdown&quot; and will only
+        // patch things if the countdown reaches zero. We increment the slow path count here to ensure
+        // that the slow path does not try to patch.
+        jit.load8(&amp;stubInfo.countdown, state.scratchGPR);
+        jit.add32(CCallHelpers::TrustedImm32(1), state.scratchGPR);
+        jit.store8(state.scratchGPR, &amp;stubInfo.countdown);
+    }
</ins><span class="cx"> 
</span><del>-    // Make sure that the inline cache optimization code knows that we are taking slow path because
-    // of something that isn't patchable. &quot;seen&quot; being false means that we bypass patching. This is
-    // pretty gross but it means that we don't need to have two slow path entrypoints - one for
-    // patching and one for normal slow stuff.
-    jit.store8(CCallHelpers::TrustedImm32(false), &amp;stubInfo.seen);
-
</del><span class="cx">     CCallHelpers::JumpList failure;
</span><span class="cx">     if (allocator.didReuseRegisters()) {
</span><span class="cx">         state.failAndRepatch.link(&amp;jit);
</span><span class="lines">@@ -1161,6 +1165,9 @@
</span><span class="cx">     
</span><span class="cx">     for (auto callback : state.callbacks)
</span><span class="cx">         callback(linkBuffer);
</span><ins>+
+    if (verbose)
+        dataLog(*codeBlock, &quot; &quot;, stubInfo.codeOrigin, &quot;: Generating polymorphic access stub for &quot;, listDump(cases), &quot;\n&quot;);
</ins><span class="cx">     
</span><span class="cx">     MacroAssemblerCodeRef code = FINALIZE_CODE_FOR(
</span><span class="cx">         codeBlock, linkBuffer,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePolymorphicAccessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.h (190560 => 190561)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.h        2015-10-05 15:12:27 UTC (rev 190560)
+++ trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.h        2015-10-05 17:05:24 UTC (rev 190561)
</span><span class="lines">@@ -39,8 +39,8 @@
</span><span class="cx"> 
</span><span class="cx"> class CodeBlock;
</span><span class="cx"> class PolymorphicAccess;
</span><ins>+class StructureStubInfo;
</ins><span class="cx"> class WatchpointsOnStructureStubInfo;
</span><del>-struct StructureStubInfo;
</del><span class="cx"> 
</span><span class="cx"> struct AccessGenerationState;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePutByIdStatuscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp (190560 => 190561)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp        2015-10-05 15:12:27 UTC (rev 190560)
+++ trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp        2015-10-05 17:05:24 UTC (rev 190561)
</span><span class="lines">@@ -144,18 +144,15 @@
</span><span class="cx">     const ConcurrentJITLocker&amp; locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo,
</span><span class="cx">     UniquedStringImpl* uid, CallLinkStatus::ExitSiteData callExitSiteData)
</span><span class="cx"> {
</span><del>-    if (!stubInfo)
</del><ins>+    if (!stubInfo || !stubInfo-&gt;everConsidered)
</ins><span class="cx">         return PutByIdStatus();
</span><span class="cx">     
</span><span class="cx">     if (stubInfo-&gt;tookSlowPath)
</span><span class="cx">         return PutByIdStatus(TakesSlowPath);
</span><span class="cx">     
</span><del>-    if (!stubInfo-&gt;seen)
-        return PutByIdStatus();
-    
</del><span class="cx">     switch (stubInfo-&gt;cacheType) {
</span><span class="cx">     case CacheType::Unset:
</span><del>-        // If the JIT saw it but didn't optimize it, then assume that this takes slow path.
</del><ins>+        // This means that we attempted to cache but failed for some reason.
</ins><span class="cx">         return PutByIdStatus(TakesSlowPath);
</span><span class="cx">         
</span><span class="cx">     case CacheType::PutByIdReplace: {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeStructureStubClearingWatchpointh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h (190560 => 190561)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h        2015-10-05 15:12:27 UTC (rev 190560)
+++ trunk/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h        2015-10-05 17:05:24 UTC (rev 190561)
</span><span class="lines">@@ -37,8 +37,8 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> class CodeBlock;
</span><ins>+class StructureStubInfo;
</ins><span class="cx"> class WatchpointsOnStructureStubInfo;
</span><del>-struct StructureStubInfo;
</del><span class="cx"> 
</span><span class="cx"> class StructureStubClearingWatchpoint : public Watchpoint {
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(StructureStubClearingWatchpoint);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeStructureStubInfocpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp (190560 => 190561)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp        2015-10-05 15:12:27 UTC (rev 190560)
+++ trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp        2015-10-05 17:05:24 UTC (rev 190561)
</span><span class="lines">@@ -33,6 +33,47 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(JIT)
</span><ins>+StructureStubInfo::StructureStubInfo(AccessType accessType)
+    : callSiteIndex(UINT_MAX)
+    , accessType(accessType)
+    , cacheType(CacheType::Unset)
+    , countdown(1) // For a totally clear stub, we'll patch it after the first execution.
+    , repatchCount(0)
+    , numberOfCoolDowns(0)
+    , resetByGC(false)
+    , tookSlowPath(false)
+    , everConsidered(false)
+{
+}
+
+StructureStubInfo::~StructureStubInfo()
+{
+}
+
+void StructureStubInfo::initGetByIdSelf(CodeBlock* codeBlock, Structure* baseObjectStructure, PropertyOffset offset)
+{
+    cacheType = CacheType::GetByIdSelf;
+    
+    u.byIdSelf.baseObjectStructure.set(
+        *codeBlock-&gt;vm(), codeBlock-&gt;ownerExecutable(), baseObjectStructure);
+    u.byIdSelf.offset = offset;
+}
+
+void StructureStubInfo::initPutByIdReplace(CodeBlock* codeBlock, Structure* baseObjectStructure, PropertyOffset offset)
+{
+    cacheType = CacheType::PutByIdReplace;
+    
+    u.byIdSelf.baseObjectStructure.set(
+        *codeBlock-&gt;vm(), codeBlock-&gt;ownerExecutable(), baseObjectStructure);
+    u.byIdSelf.offset = offset;
+}
+
+void StructureStubInfo::initStub(CodeBlock*, std::unique_ptr&lt;PolymorphicAccess&gt; stub)
+{
+    cacheType = CacheType::Stub;
+    u.stub = stub.release();
+}
+
</ins><span class="cx"> void StructureStubInfo::deref()
</span><span class="cx"> {
</span><span class="cx">     switch (cacheType) {
</span><span class="lines">@@ -49,8 +90,10 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MacroAssemblerCodePtr StructureStubInfo::addAccessCase(
</span><del>-    VM&amp; vm, CodeBlock* codeBlock, const Identifier&amp; ident, std::unique_ptr&lt;AccessCase&gt; accessCase)
</del><ins>+    CodeBlock* codeBlock, const Identifier&amp; ident, std::unique_ptr&lt;AccessCase&gt; accessCase)
</ins><span class="cx"> {
</span><ins>+    VM&amp; vm = *codeBlock-&gt;vm();
+    
</ins><span class="cx">     if (!accessCase)
</span><span class="cx">         return MacroAssemblerCodePtr();
</span><span class="cx">     
</span><span class="lines">@@ -74,8 +117,7 @@
</span><span class="cx">     if (!result)
</span><span class="cx">         return MacroAssemblerCodePtr();
</span><span class="cx"> 
</span><del>-    cacheType = CacheType::Stub;
-    u.stub = access.release();
</del><ins>+    initStub(codeBlock, WTF::move(access));
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeStructureStubInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h (190560 => 190561)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h        2015-10-05 15:12:27 UTC (rev 190560)
+++ trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h        2015-10-05 17:05:24 UTC (rev 190561)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #include &quot;MacroAssembler.h&quot;
</span><span class="cx"> #include &quot;ObjectPropertyConditionSet.h&quot;
</span><span class="cx"> #include &quot;Opcode.h&quot;
</span><ins>+#include &quot;Options.h&quot;
</ins><span class="cx"> #include &quot;PolymorphicAccess.h&quot;
</span><span class="cx"> #include &quot;RegisterSet.h&quot;
</span><span class="cx"> #include &quot;SpillRegistersMode.h&quot;
</span><span class="lines">@@ -57,41 +58,19 @@
</span><span class="cx">     Stub
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-struct StructureStubInfo {
-    StructureStubInfo(AccessType accessType)
-        : accessType(accessType)
-        , cacheType(CacheType::Unset)
-        , seen(false)
-        , resetByGC(false)
-        , tookSlowPath(false)
-        , callSiteIndex(UINT_MAX)
-    {
-    }
</del><ins>+class StructureStubInfo {
+    WTF_MAKE_NONCOPYABLE(StructureStubInfo);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    StructureStubInfo(AccessType);
+    ~StructureStubInfo();
</ins><span class="cx"> 
</span><del>-    void initGetByIdSelf(VM&amp; vm, JSCell* owner, Structure* baseObjectStructure, PropertyOffset offset)
-    {
-        cacheType = CacheType::GetByIdSelf;
</del><ins>+    void initGetByIdSelf(CodeBlock*, Structure* baseObjectStructure, PropertyOffset);
+    void initPutByIdReplace(CodeBlock*, Structure* baseObjectStructure, PropertyOffset);
+    void initStub(CodeBlock*, std::unique_ptr&lt;PolymorphicAccess&gt;);
</ins><span class="cx"> 
</span><del>-        u.byIdSelf.baseObjectStructure.set(vm, owner, baseObjectStructure);
-        u.byIdSelf.offset = offset;
-    }
-
-    void initPutByIdReplace(VM&amp; vm, JSCell* owner, Structure* baseObjectStructure, PropertyOffset offset)
-    {
-        cacheType = CacheType::PutByIdReplace;
-
-        u.byIdSelf.baseObjectStructure.set(vm, owner, baseObjectStructure);
-        u.byIdSelf.offset = offset;
-    }
-
-    void initStub(std::unique_ptr&lt;PolymorphicAccess&gt; stub)
-    {
-        cacheType = CacheType::Stub;
-        u.stub = stub.release();
-    }
-
</del><span class="cx">     MacroAssemblerCodePtr addAccessCase(
</span><del>-        VM&amp;, CodeBlock*, const Identifier&amp;, std::unique_ptr&lt;AccessCase&gt;);
</del><ins>+        CodeBlock*, const Identifier&amp;, std::unique_ptr&lt;AccessCase&gt;);
</ins><span class="cx"> 
</span><span class="cx">     void reset(CodeBlock*);
</span><span class="cx"> 
</span><span class="lines">@@ -101,25 +80,56 @@
</span><span class="cx">     // either entirely or just enough to ensure that those dead pointers don't get used anymore.
</span><span class="cx">     void visitWeakReferences(CodeBlock*);
</span><span class="cx">         
</span><del>-    bool seenOnce()
</del><ins>+    ALWAYS_INLINE bool considerCaching()
</ins><span class="cx">     {
</span><del>-        return seen;
</del><ins>+        everConsidered = true;
+        if (!countdown) {
+            // Check if we have been doing repatching too frequently. If so, then we should cool off
+            // for a while.
+            willRepatch();
+            if (repatchCount &gt; Options::repatchCountForCoolDown()) {
+                // We've been repatching too much, so don't do it now.
+                repatchCount = 0;
+                // The amount of time we require for cool-down depends on the number of times we've
+                // had to cool down in the past. The relationship is exponential. The max value we
+                // allow here is 2^256 - 2, since the slow paths may increment the count to indicate
+                // that they'd like to temporarily skip patching just this once.
+                countdown = WTF::leftShiftWithSaturation(
+                    static_cast&lt;uint8_t&gt;(Options::initialCoolDownCount()),
+                    numberOfCoolDowns,
+                    static_cast&lt;uint8_t&gt;(std::numeric_limits&lt;uint8_t&gt;::max() - 1));
+                willCoolDown();
+                return false;
+            }
+            return true;
+        }
+        countdown--;
+        return false;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void setSeen()
</del><ins>+    ALWAYS_INLINE void willRepatch()
</ins><span class="cx">     {
</span><del>-        seen = true;
</del><ins>+        WTF::incrementWithSaturation(repatchCount);
</ins><span class="cx">     }
</span><del>-        
-    AccessType accessType;
-    CacheType cacheType;
-    bool seen;
-    bool resetByGC : 1;
-    bool tookSlowPath : 1;
</del><span class="cx"> 
</span><ins>+    ALWAYS_INLINE void willCoolDown()
+    {
+        WTF::incrementWithSaturation(numberOfCoolDowns);
+    }
+
+    CodeLocationCall callReturnLocation;
+
</ins><span class="cx">     CodeOrigin codeOrigin;
</span><span class="cx">     CallSiteIndex callSiteIndex;
</span><span class="cx"> 
</span><ins>+    union {
+        struct {
+            WriteBarrierBase&lt;Structure&gt; baseObjectStructure;
+            PropertyOffset offset;
+        } byIdSelf;
+        PolymorphicAccess* stub;
+    } u;
+
</ins><span class="cx">     struct {
</span><span class="cx">         unsigned spillMode : 8;
</span><span class="cx">         int8_t baseGPR;
</span><span class="lines">@@ -141,15 +151,14 @@
</span><span class="cx"> #endif
</span><span class="cx">     } patch;
</span><span class="cx"> 
</span><del>-    union {
-        struct {
-            WriteBarrierBase&lt;Structure&gt; baseObjectStructure;
-            PropertyOffset offset;
-        } byIdSelf;
-        PolymorphicAccess* stub;
-    } u;
-
-    CodeLocationCall callReturnLocation;
</del><ins>+    AccessType accessType;
+    CacheType cacheType;
+    uint8_t countdown; // We repatch only when this is zero. If not zero, we decrement.
+    uint8_t repatchCount;
+    uint8_t numberOfCoolDowns;
+    bool resetByGC : 1;
+    bool tookSlowPath : 1;
+    bool everConsidered : 1;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> inline CodeOrigin getStructureStubInfoCodeOrigin(StructureStubInfo&amp; structureStubInfo)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (190560 => 190561)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2015-10-05 15:12:27 UTC (rev 190560)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2015-10-05 17:05:24 UTC (rev 190561)
</span><span class="lines">@@ -63,12 +63,12 @@
</span><span class="cx">     class MarkedAllocator;
</span><span class="cx">     class Register;
</span><span class="cx">     class StructureChain;
</span><ins>+    class StructureStubInfo;
</ins><span class="cx"> 
</span><span class="cx">     struct Instruction;
</span><span class="cx">     struct OperandTypes;
</span><span class="cx">     struct SimpleJumpTable;
</span><span class="cx">     struct StringJumpTable;
</span><del>-    struct StructureStubInfo;
</del><span class="cx"> 
</span><span class="cx">     struct CallRecord {
</span><span class="cx">         MacroAssembler::Call from;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (190560 => 190561)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-10-05 15:12:27 UTC (rev 190560)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-10-05 17:05:24 UTC (rev 190561)
</span><span class="lines">@@ -184,10 +184,8 @@
</span><span class="cx">     PropertySlot slot(baseValue);
</span><span class="cx">     
</span><span class="cx">     bool hasResult = baseValue.getPropertySlot(exec, ident, slot);
</span><del>-    if (stubInfo-&gt;seen)
</del><ins>+    if (stubInfo-&gt;considerCaching())
</ins><span class="cx">         repatchGetByID(exec, baseValue, ident, slot, *stubInfo);
</span><del>-    else
-        stubInfo-&gt;seen = true;
</del><span class="cx">     
</span><span class="cx">     return JSValue::encode(hasResult? slot.getValue(exec, ident) : jsUndefined());
</span><span class="cx"> }
</span><span class="lines">@@ -210,10 +208,8 @@
</span><span class="cx">     
</span><span class="cx">     RELEASE_ASSERT(accessType == stubInfo-&gt;accessType);
</span><span class="cx">     
</span><del>-    if (stubInfo-&gt;seen)
</del><ins>+    if (stubInfo-&gt;considerCaching())
</ins><span class="cx">         repatchIn(exec, base, ident, result, slot, *stubInfo);
</span><del>-    else
-        stubInfo-&gt;seen = true;
</del><span class="cx">     
</span><span class="cx">     return JSValue::encode(jsBoolean(result));
</span><span class="cx"> }
</span><span class="lines">@@ -308,10 +304,8 @@
</span><span class="cx">     if (accessType != static_cast&lt;AccessType&gt;(stubInfo-&gt;accessType))
</span><span class="cx">         return;
</span><span class="cx">     
</span><del>-    if (stubInfo-&gt;seen)
</del><ins>+    if (stubInfo-&gt;considerCaching())
</ins><span class="cx">         repatchPutByID(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
</span><del>-    else
-        stubInfo-&gt;seen = true;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT_OPERATION operationPutByIdNonStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
</span><span class="lines">@@ -332,10 +326,8 @@
</span><span class="cx">     if (accessType != static_cast&lt;AccessType&gt;(stubInfo-&gt;accessType))
</span><span class="cx">         return;
</span><span class="cx">     
</span><del>-    if (stubInfo-&gt;seen)
</del><ins>+    if (stubInfo-&gt;considerCaching())
</ins><span class="cx">         repatchPutByID(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
</span><del>-    else
-        stubInfo-&gt;seen = true;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT_OPERATION operationPutByIdDirectStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
</span><span class="lines">@@ -356,10 +348,8 @@
</span><span class="cx">     if (accessType != static_cast&lt;AccessType&gt;(stubInfo-&gt;accessType))
</span><span class="cx">         return;
</span><span class="cx">     
</span><del>-    if (stubInfo-&gt;seen)
</del><ins>+    if (stubInfo-&gt;considerCaching())
</ins><span class="cx">         repatchPutByID(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
</span><del>-    else
-        stubInfo-&gt;seen = true;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT_OPERATION operationPutByIdDirectNonStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
</span><span class="lines">@@ -380,10 +370,8 @@
</span><span class="cx">     if (accessType != static_cast&lt;AccessType&gt;(stubInfo-&gt;accessType))
</span><span class="cx">         return;
</span><span class="cx">     
</span><del>-    if (stubInfo-&gt;seen)
</del><ins>+    if (stubInfo-&gt;considerCaching())
</ins><span class="cx">         repatchPutByID(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
</span><del>-    else
-        stubInfo-&gt;seen = true;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT_OPERATION operationReallocateStorageAndFinishPut(ExecState* exec, JSObject* base, Structure* structure, PropertyOffset offset, EncodedJSValue value)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.cpp (190560 => 190561)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.cpp        2015-10-05 15:12:27 UTC (rev 190560)
+++ trunk/Source/JavaScriptCore/jit/Repatch.cpp        2015-10-05 17:05:24 UTC (rev 190561)
</span><span class="lines">@@ -266,7 +266,7 @@
</span><span class="cx">             &amp;&amp; !loadTargetFromProxy) {
</span><span class="cx">             structure-&gt;startWatchingPropertyForReplacements(vm, slot.cachedOffset());
</span><span class="cx">             repatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), operationGetByIdOptimize, true);
</span><del>-            stubInfo.initGetByIdSelf(vm, codeBlock-&gt;ownerExecutable(), structure, slot.cachedOffset());
</del><ins>+            stubInfo.initGetByIdSelf(codeBlock, structure, slot.cachedOffset());
</ins><span class="cx">             return RetryCacheLater;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -308,8 +308,8 @@
</span><span class="cx">             slot.isCacheableCustom() ? slot.slotBase() : nullptr);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    MacroAssemblerCodePtr codePtr = stubInfo.addAccessCase(
-        vm, codeBlock, propertyName, WTF::move(newCase));
</del><ins>+    MacroAssemblerCodePtr codePtr =
+        stubInfo.addAccessCase(codeBlock, propertyName, WTF::move(newCase));
</ins><span class="cx"> 
</span><span class="cx">     if (!codePtr)
</span><span class="cx">         return GiveUpOnCache;
</span><span class="lines">@@ -384,8 +384,7 @@
</span><span class="cx">                 repatchByIdSelfAccess(
</span><span class="cx">                     codeBlock, stubInfo, structure, slot.cachedOffset(),
</span><span class="cx">                     appropriateOptimizingPutByIdFunction(slot, putKind), false);
</span><del>-                stubInfo.initPutByIdReplace(
-                    vm, codeBlock-&gt;ownerExecutable(), structure, slot.cachedOffset());
</del><ins>+                stubInfo.initPutByIdReplace(codeBlock, structure, slot.cachedOffset());
</ins><span class="cx">                 return RetryCacheLater;
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="lines">@@ -452,8 +451,7 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    MacroAssemblerCodePtr codePtr = stubInfo.addAccessCase(
-        vm, codeBlock, ident, WTF::move(newCase));
</del><ins>+    MacroAssemblerCodePtr codePtr = stubInfo.addAccessCase(codeBlock, ident, WTF::move(newCase));
</ins><span class="cx">     
</span><span class="cx">     if (!codePtr)
</span><span class="cx">         return GiveUpOnCache;
</span><span class="lines">@@ -511,7 +509,7 @@
</span><span class="cx">     std::unique_ptr&lt;AccessCase&gt; newCase = AccessCase::in(
</span><span class="cx">         vm, owner, wasFound ? AccessCase::InHit : AccessCase::InMiss, structure, conditionSet);
</span><span class="cx"> 
</span><del>-    MacroAssemblerCodePtr codePtr = stubInfo.addAccessCase(vm, codeBlock, ident, WTF::move(newCase));
</del><ins>+    MacroAssemblerCodePtr codePtr = stubInfo.addAccessCase(codeBlock, ident, WTF::move(newCase));
</ins><span class="cx">     if (!codePtr)
</span><span class="cx">         return GiveUpOnCache;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (190560 => 190561)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2015-10-05 15:12:27 UTC (rev 190560)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2015-10-05 17:05:24 UTC (rev 190561)
</span><span class="lines">@@ -121,6 +121,9 @@
</span><span class="cx">     v(bool, forceCodeBlockLiveness, false, nullptr) \
</span><span class="cx">     v(bool, forceICFailure, false, nullptr) \
</span><span class="cx">     \
</span><ins>+    v(unsigned, repatchCountForCoolDown, 10, nullptr) \
+    v(unsigned, initialCoolDownCount, 20, nullptr) \
+    \
</ins><span class="cx">     v(bool, dumpGeneratedBytecodes, false, nullptr) \
</span><span class="cx">     v(bool, dumpBytecodeLivenessResults, false, nullptr) \
</span><span class="cx">     v(bool, validateBytecode, false, nullptr) \
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (190560 => 190561)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2015-10-05 15:12:27 UTC (rev 190560)
+++ trunk/Source/WTF/ChangeLog        2015-10-05 17:05:24 UTC (rev 190561)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2015-10-04  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Inline cache repatching should be throttled if it happens a lot
+        https://bugs.webkit.org/show_bug.cgi?id=149796
+        rdar://problem/22674436
+
+        Reviewed by Saam Barati.
+
+        Add some helpers for saturated math.
+
+        * wtf/MathExtras.h:
+        (WTF::incrementWithSaturation):
+        (WTF::leftShiftWithSaturation):
+
</ins><span class="cx"> 2015-10-01  Brent Fulgham  &lt;bfulgham@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Win] Unreviewed CMake build fixes.
</span></span></pre></div>
<a id="trunkSourceWTFwtfMathExtrash"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/MathExtras.h (190560 => 190561)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/MathExtras.h        2015-10-05 15:12:27 UTC (rev 190560)
+++ trunk/Source/WTF/wtf/MathExtras.h        2015-10-05 17:05:24 UTC (rev 190561)
</span><span class="lines">@@ -400,6 +400,25 @@
</span><span class="cx">     return static_cast&lt;int&gt;(value) == value;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename T&gt;
+inline void incrementWithSaturation(T&amp; value)
+{
+    if (value != std::numeric_limits&lt;T&gt;::max())
+        value++;
+}
+
+template&lt;typename T&gt;
+inline T leftShiftWithSaturation(T value, unsigned shiftAmount, T max = std::numeric_limits&lt;T&gt;::max())
+{
+    T result = value &lt;&lt; shiftAmount;
+    // We will have saturated if shifting right doesn't recover the original value.
+    if (result &gt;&gt; shiftAmount != value)
+        return max;
+    if (result &gt; max)
+        return max;
+    return result;
+}
+
</ins><span class="cx"> } // namespace WTF
</span><span class="cx"> 
</span><span class="cx"> #endif // #ifndef WTF_MathExtras_h
</span></span></pre>
</div>
</div>

</body>
</html>