<!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>[200405] 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/200405">200405</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-05-03 19:23:28 -0700 (Tue, 03 May 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>References from code to Structures should be stronger than weak
https://bugs.webkit.org/show_bug.cgi?id=157324

Reviewed by Mark Lam.
        
If code refers to a Structure and the Structure dies, then previously we'd kill the code. 
This makes sense because the Structure could be the only thing left referring to some global
object or prototype.

But this also causes unnecessary churn. Sometimes there will be a structure that we just
haven't really done anything with recently and so it appears dead. The approach we use
elsewhere in our type inference is that the type that the code uses is general enough to
handle every past execution. Having the GC clear code when some Structure it uses dies means
that we forget that the code used that Structure. We'll either assume that the code is more
monomorphic than it really is (because after GC we patch in some other structure but not the
deleted one, so it looks like we only ever saw the new structure), or we'll assume that it's
crazier than it really is (because we'll remember that there had been some structure that
caused deletion, so we'll assume that deletions might happen in the future, so we'll use a
fully dynamic IC).

This change introduces a more nuanced policy: if it's cheap to mark a dead Structure then we
should mark it just so that all of the code that refers to it remembers that there had been
this exact Structure in the past. If the code often goes through different Structures then
we already have great mechanisms to realize that the code is nutty (namely, the
PolymorphicAccess size limit). But if the code just does this a handful of times then
remembering this old Structure is probably net good:

- It obeys the &quot;handle all past executions&quot; law.
- It preserves the history of the property access, allowing a precise measure of its past
  polymorphism.
- It makes the code ready to run fast if the user decides to use that Structure again.
  Marking the Structure means it will stay in whatever property transition tables it was in,
  so if the program does the same thing it did in the past, it will get this old Structure.

It looks like this is a progression in gbemu and it makes gbemu perform more
deterministically. Also, it seems that this makes JetStream run faster.
        
Over five in-browser runs of JetStream, here's what we see before and after:
        
Geometric Mean:
    Before              After
    229.23 +- 8.2523    230.70 +- 12.888
    232.91 +- 15.638    239.04 +- 13.766
    234.79 +- 12.760    236.32 +- 15.562
    236.20 +- 23.125    242.02 +- 3.3865
    237.22 +- 2.1929    237.23 +- 17.664
        
Just gbemu:
    Before              After
    541.0 +- 135.8      481.7 +- 143.4
    518.9 +- 15.65      508.1 +- 136.3
    362.5 +- 0.8884     489.7 +- 101.4
    470.7 +- 313.3      530.7 +- 11.49
    418.7 +- 180.6      537.2 +- 6.514
        
Notice that there is plenty of noise before and after, but the noise is now far less severe.
After this change I did not see any runs like &quot;470.7 +- 313.3&quot; where the size of the 
confidence interval (313.3 * 2) is greater than the score (470.7). Also, notice that the
least noisy run before the change also got a lower score than we ever observed after the
change (36.5 +- 0.8884). The noise, and these occasional very low scores, are due to a
pathology where the GC would reset some stubs at an unfortunate time during profiling,
causing the optimizing compiler to make many poor decisions. That pathology doesn't exist
anymore.
        
On the other hand, prior to this change it was possible for gbemu to sometimes run sooooper
fast because the GC would cause the profiler to forget gbemu's behavior on the first tick
and focus only on its behavior in subsequent ticks. So, in steady state, we'd optimize gbemu
for its later behavior rather than a combination of its early behavior and later behavior.
We rarely got lucky this way, so it's not fair to view this quirk as a feature.
        
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::propagateTransitions):
* bytecode/PolymorphicAccess.cpp:
(JSC::AccessCase::visitWeak):
(JSC::AccessCase::propagateTransitions):
(JSC::AccessCase::generateWithGuard):
(JSC::PolymorphicAccess::visitWeak):
(JSC::PolymorphicAccess::propagateTransitions):
(JSC::PolymorphicAccess::dump):
* bytecode/PolymorphicAccess.h:
* bytecode/StructureStubInfo.cpp:
(JSC::StructureStubInfo::visitWeakReferences):
(JSC::StructureStubInfo::propagateTransitions):
(JSC::StructureStubInfo::containsPC):
* bytecode/StructureStubInfo.h:
(JSC::StructureStubInfo::considerCaching):
* runtime/Structure.cpp:
(JSC::Structure::visitChildren):
(JSC::Structure::isCheapDuringGC):
(JSC::Structure::markIfCheap):
(JSC::Structure::prototypeChainMayInterceptStoreTo):
* runtime/Structure.h:</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="#trunkSourceJavaScriptCorebytecodePolymorphicAccesscpp">trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePolymorphicAccessh">trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.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="#trunkSourceJavaScriptCoreruntimeStructurecpp">trunk/Source/JavaScriptCore/runtime/Structure.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructureh">trunk/Source/JavaScriptCore/runtime/Structure.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (200404 => 200405)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-05-04 01:54:39 UTC (rev 200404)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-05-04 02:23:28 UTC (rev 200405)
</span><span class="lines">@@ -1,3 +1,98 @@
</span><ins>+2016-05-03  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        References from code to Structures should be stronger than weak
+        https://bugs.webkit.org/show_bug.cgi?id=157324
+
+        Reviewed by Mark Lam.
+        
+        If code refers to a Structure and the Structure dies, then previously we'd kill the code. 
+        This makes sense because the Structure could be the only thing left referring to some global
+        object or prototype.
+
+        But this also causes unnecessary churn. Sometimes there will be a structure that we just
+        haven't really done anything with recently and so it appears dead. The approach we use
+        elsewhere in our type inference is that the type that the code uses is general enough to
+        handle every past execution. Having the GC clear code when some Structure it uses dies means
+        that we forget that the code used that Structure. We'll either assume that the code is more
+        monomorphic than it really is (because after GC we patch in some other structure but not the
+        deleted one, so it looks like we only ever saw the new structure), or we'll assume that it's
+        crazier than it really is (because we'll remember that there had been some structure that
+        caused deletion, so we'll assume that deletions might happen in the future, so we'll use a
+        fully dynamic IC).
+
+        This change introduces a more nuanced policy: if it's cheap to mark a dead Structure then we
+        should mark it just so that all of the code that refers to it remembers that there had been
+        this exact Structure in the past. If the code often goes through different Structures then
+        we already have great mechanisms to realize that the code is nutty (namely, the
+        PolymorphicAccess size limit). But if the code just does this a handful of times then
+        remembering this old Structure is probably net good:
+
+        - It obeys the &quot;handle all past executions&quot; law.
+        - It preserves the history of the property access, allowing a precise measure of its past
+          polymorphism.
+        - It makes the code ready to run fast if the user decides to use that Structure again.
+          Marking the Structure means it will stay in whatever property transition tables it was in,
+          so if the program does the same thing it did in the past, it will get this old Structure.
+
+        It looks like this is a progression in gbemu and it makes gbemu perform more
+        deterministically. Also, it seems that this makes JetStream run faster.
+        
+        Over five in-browser runs of JetStream, here's what we see before and after:
+        
+        Geometric Mean:
+            Before              After
+            229.23 +- 8.2523    230.70 +- 12.888
+            232.91 +- 15.638    239.04 +- 13.766
+            234.79 +- 12.760    236.32 +- 15.562
+            236.20 +- 23.125    242.02 +- 3.3865
+            237.22 +- 2.1929    237.23 +- 17.664
+        
+        Just gbemu:
+            Before              After
+            541.0 +- 135.8      481.7 +- 143.4
+            518.9 +- 15.65      508.1 +- 136.3
+            362.5 +- 0.8884     489.7 +- 101.4
+            470.7 +- 313.3      530.7 +- 11.49
+            418.7 +- 180.6      537.2 +- 6.514
+        
+        Notice that there is plenty of noise before and after, but the noise is now far less severe.
+        After this change I did not see any runs like &quot;470.7 +- 313.3&quot; where the size of the 
+        confidence interval (313.3 * 2) is greater than the score (470.7). Also, notice that the
+        least noisy run before the change also got a lower score than we ever observed after the
+        change (36.5 +- 0.8884). The noise, and these occasional very low scores, are due to a
+        pathology where the GC would reset some stubs at an unfortunate time during profiling,
+        causing the optimizing compiler to make many poor decisions. That pathology doesn't exist
+        anymore.
+        
+        On the other hand, prior to this change it was possible for gbemu to sometimes run sooooper
+        fast because the GC would cause the profiler to forget gbemu's behavior on the first tick
+        and focus only on its behavior in subsequent ticks. So, in steady state, we'd optimize gbemu
+        for its later behavior rather than a combination of its early behavior and later behavior.
+        We rarely got lucky this way, so it's not fair to view this quirk as a feature.
+        
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::propagateTransitions):
+        * bytecode/PolymorphicAccess.cpp:
+        (JSC::AccessCase::visitWeak):
+        (JSC::AccessCase::propagateTransitions):
+        (JSC::AccessCase::generateWithGuard):
+        (JSC::PolymorphicAccess::visitWeak):
+        (JSC::PolymorphicAccess::propagateTransitions):
+        (JSC::PolymorphicAccess::dump):
+        * bytecode/PolymorphicAccess.h:
+        * bytecode/StructureStubInfo.cpp:
+        (JSC::StructureStubInfo::visitWeakReferences):
+        (JSC::StructureStubInfo::propagateTransitions):
+        (JSC::StructureStubInfo::containsPC):
+        * bytecode/StructureStubInfo.h:
+        (JSC::StructureStubInfo::considerCaching):
+        * runtime/Structure.cpp:
+        (JSC::Structure::visitChildren):
+        (JSC::Structure::isCheapDuringGC):
+        (JSC::Structure::markIfCheap):
+        (JSC::Structure::prototypeChainMayInterceptStoreTo):
+        * runtime/Structure.h:
+
</ins><span class="cx"> 2016-05-03  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Simplify console.clear
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (200404 => 200405)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-05-04 01:54:39 UTC (rev 200404)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-05-04 02:23:28 UTC (rev 200405)
</span><span class="lines">@@ -2616,32 +2616,16 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     if (JITCode::isJIT(jitType())) {
</span><del>-        for (Bag&lt;StructureStubInfo&gt;::iterator iter = m_stubInfos.begin(); !!iter; ++iter) {
-            StructureStubInfo&amp; stubInfo = **iter;
-            if (stubInfo.cacheType != CacheType::Stub)
-                continue;
-            PolymorphicAccess* list = stubInfo.u.stub;
-            JSCell* origin = stubInfo.codeOrigin.codeOriginOwner();
-            if (origin &amp;&amp; !Heap::isMarked(origin)) {
-                allAreMarkedSoFar = false;
-                continue;
-            }
-            for (unsigned j = list-&gt;size(); j--;) {
-                const AccessCase&amp; access = list-&gt;at(j);
-                if (access.type() != AccessCase::Transition)
-                    continue;
-                if (Heap::isMarked(access.structure()))
-                    visitor.appendUnbarrieredReadOnlyPointer(access.newStructure());
-                else
-                    allAreMarkedSoFar = false;
-            }
-        }
</del><ins>+        for (Bag&lt;StructureStubInfo&gt;::iterator iter = m_stubInfos.begin(); !!iter; ++iter)
+            allAreMarkedSoFar &amp;= (*iter)-&gt;propagateTransitions(visitor);
</ins><span class="cx">     }
</span><span class="cx"> #endif // ENABLE(JIT)
</span><span class="cx">     
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     if (JITCode::isOptimizingJIT(jitType())) {
</span><span class="cx">         DFG::CommonData* dfgCommon = m_jitCode-&gt;dfgCommon();
</span><ins>+        for (auto&amp; weakReference : dfgCommon-&gt;weakStructureReferences)
+            allAreMarkedSoFar &amp;= weakReference-&gt;markIfCheap(visitor);
</ins><span class="cx">         
</span><span class="cx">         for (unsigned i = 0; i &lt; dfgCommon-&gt;transitions.size(); ++i) {
</span><span class="cx">             if (shouldMarkTransition(dfgCommon-&gt;transitions[i])) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePolymorphicAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp (200404 => 200405)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2016-05-04 01:54:39 UTC (rev 200404)
+++ trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2016-05-04 02:23:28 UTC (rev 200405)
</span><span class="lines">@@ -554,6 +554,27 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool AccessCase::propagateTransitions(SlotVisitor&amp; visitor) const
+{
+    bool result = true;
+    
+    if (m_structure)
+        result &amp;= m_structure-&gt;markIfCheap(visitor);
+    
+    switch (m_type) {
+    case Transition:
+        if (Heap::isMarked(m_structure-&gt;previousID()))
+            visitor.appendUnbarrieredReadOnlyPointer(m_structure.get());
+        else
+            result = false;
+        break;
+    default:
+        break;
+    }
+    
+    return result;
+}
+
</ins><span class="cx"> void AccessCase::generateWithGuard(
</span><span class="cx">     AccessGenerationState&amp; state, CCallHelpers::JumpList&amp; fallThrough)
</span><span class="cx"> {
</span><span class="lines">@@ -1487,6 +1508,14 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool PolymorphicAccess::propagateTransitions(SlotVisitor&amp; visitor) const
+{
+    bool result = true;
+    for (unsigned i = 0; i &lt; size(); ++i)
+        result &amp;= at(i).propagateTransitions(visitor);
+    return result;
+}
+
</ins><span class="cx"> void PolymorphicAccess::dump(PrintStream&amp; out) const
</span><span class="cx"> {
</span><span class="cx">     out.print(RawPointer(this), &quot;:[&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePolymorphicAccessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.h (200404 => 200405)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.h        2016-05-04 01:54:39 UTC (rev 200404)
+++ trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.h        2016-05-04 02:23:28 UTC (rev 200405)
</span><span class="lines">@@ -248,6 +248,7 @@
</span><span class="cx">     AccessCase();
</span><span class="cx"> 
</span><span class="cx">     bool visitWeak(VM&amp;) const;
</span><ins>+    bool propagateTransitions(SlotVisitor&amp;) const;
</ins><span class="cx">     
</span><span class="cx">     // FIXME: This only exists because of how AccessCase puts post-generation things into itself.
</span><span class="cx">     // https://bugs.webkit.org/show_bug.cgi?id=156456
</span><span class="lines">@@ -396,6 +397,10 @@
</span><span class="cx"> 
</span><span class="cx">     // If this returns false then we are requesting a reset of the owning StructureStubInfo.
</span><span class="cx">     bool visitWeak(VM&amp;) const;
</span><ins>+    
+    // This returns true if it has marked everything it will ever marked. This can be used as an
+    // optimization to then avoid calling this method again during the fixpoint.
+    bool propagateTransitions(SlotVisitor&amp;) const;
</ins><span class="cx"> 
</span><span class="cx">     void aboutToDie();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeStructureStubInfocpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp (200404 => 200405)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp        2016-05-04 01:54:39 UTC (rev 200404)
+++ trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp        2016-05-04 02:23:28 UTC (rev 200405)
</span><span class="lines">@@ -230,7 +230,10 @@
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = *codeBlock-&gt;vm();
</span><span class="cx">     
</span><del>-    bufferedStructures.clear();
</del><ins>+    bufferedStructures.genericFilter(
+        [&amp;] (Structure* structure) -&gt; bool {
+            return Heap::isMarked(structure);
+        });
</ins><span class="cx"> 
</span><span class="cx">     switch (cacheType) {
</span><span class="cx">     case CacheType::GetByIdSelf:
</span><span class="lines">@@ -250,6 +253,22 @@
</span><span class="cx">     resetByGC = true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool StructureStubInfo::propagateTransitions(SlotVisitor&amp; visitor)
+{
+    switch (cacheType) {
+    case CacheType::Unset:
+        return true;
+    case CacheType::GetByIdSelf:
+    case CacheType::PutByIdReplace:
+        return u.byIdSelf.baseObjectStructure-&gt;markIfCheap(visitor);
+    case CacheType::Stub:
+        return u.stub-&gt;propagateTransitions(visitor);
+    }
+    
+    RELEASE_ASSERT_NOT_REACHED();
+    return true;
+}
+
</ins><span class="cx"> bool StructureStubInfo::containsPC(void* pc) const
</span><span class="cx"> {
</span><span class="cx">     if (cacheType != CacheType::Stub)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeStructureStubInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h (200404 => 200405)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h        2016-05-04 01:54:39 UTC (rev 200404)
+++ trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h        2016-05-04 02:23:28 UTC (rev 200405)
</span><span class="lines">@@ -81,6 +81,9 @@
</span><span class="cx">     // Check if the stub has weak references that are dead. If it does, then it resets itself,
</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><ins>+    
+    // This returns true if it has marked everything that it will ever mark.
+    bool propagateTransitions(SlotVisitor&amp;);
</ins><span class="cx">         
</span><span class="cx">     ALWAYS_INLINE bool considerCaching(Structure* structure)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructurecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Structure.cpp (200404 => 200405)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Structure.cpp        2016-05-04 01:54:39 UTC (rev 200404)
+++ trunk/Source/JavaScriptCore/runtime/Structure.cpp        2016-05-04 02:23:28 UTC (rev 200405)
</span><span class="lines">@@ -1135,6 +1135,25 @@
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_inferredTypeTable);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool Structure::isCheapDuringGC()
+{
+    // FIXME: We could make this even safer by returning false if this structure's property table
+    // has any large property names.
+    // https://bugs.webkit.org/show_bug.cgi?id=157334
+    
+    return (!m_globalObject || Heap::isMarked(m_globalObject.get()))
+        &amp;&amp; (!storedPrototypeObject() || Heap::isMarked(storedPrototypeObject()));
+}
+
+bool Structure::markIfCheap(SlotVisitor&amp; visitor)
+{
+    if (!isCheapDuringGC())
+        return Heap::isMarked(this);
+    
+    visitor.appendUnbarrieredReadOnlyPointer(this);
+    return true;
+}
+
</ins><span class="cx"> bool Structure::prototypeChainMayInterceptStoreTo(VM&amp; vm, PropertyName propertyName)
</span><span class="cx"> {
</span><span class="cx">     if (parseIndex(propertyName))
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructureh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Structure.h (200404 => 200405)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Structure.h        2016-05-04 01:54:39 UTC (rev 200404)
+++ trunk/Source/JavaScriptCore/runtime/Structure.h        2016-05-04 02:23:28 UTC (rev 200405)
</span><span class="lines">@@ -260,6 +260,17 @@
</span><span class="cx">     StructureChain* prototypeChain(VM&amp;, JSGlobalObject*) const;
</span><span class="cx">     StructureChain* prototypeChain(ExecState*) const;
</span><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><ins>+    
+    // A Structure is cheap to mark during GC if doing so would only add a small and bounded amount
+    // to our heap footprint. For example, if the structure refers to a global object that is not
+    // yet marked, then as far as we know, the decision to mark this Structure would lead to a large
+    // increase in footprint because no other object refers to that global object. This method
+    // returns true if all user-controlled (and hence unbounded in size) objects referenced from the
+    // Structure are already marked.
+    bool isCheapDuringGC();
+    
+    // Returns true if this structure is now marked.
+    bool markIfCheap(SlotVisitor&amp;);
</ins><span class="cx">         
</span><span class="cx">     // Will just the prototype chain intercept this property access?
</span><span class="cx">     JS_EXPORT_PRIVATE bool prototypeChainMayInterceptStoreTo(VM&amp;, PropertyName);
</span></span></pre>
</div>
</div>

</body>
</html>