<!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>[233236] trunk</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/233236">233236</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2018-06-26 18:08:25 -0700 (Tue, 26 Jun 2018)</dd>
</dl>

<h3>Log Message</h3>
<pre>JSImmutableButterfly can't be allocated from a subspace with HeapCell::Kind::Auxiliary
https://bugs.webkit.org/show_bug.cgi?id=186878
<rdar://problem/40568659>

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

This patch fixes a bug in our JSImmutableButterfly implementation uncovered by
our stress GC bots. Before this patch, JSImmutableButterfly was allocated
with HeapCell::Kind::Auxiliary. This is wrong. Things that are JSCells can't
be allocated from HeapCell::Kind::Auxiliary. This patch adds a new HeapCell::Kind
called JSCellWithInteriorPointers. It behaves like JSCell in all ways, except
conservative scan knows to treat it like a butterfly in when we we may be
pointing into the middle of it.

The way we were crashing on the stress GC bots is that our conservative marking
won't do cell visiting for things that are Auxiliary. This meant that if the
stack were the only thing pointing to a JSImmutableButterfly when a GC took place,
that JSImmutableButterfly would not be visited. This is now fixed.

* bytecompiler/NodesCodegen.cpp:
(JSC::ArrayNode::emitBytecode):
* debugger/Debugger.cpp:
* heap/ConservativeRoots.cpp:
(JSC::ConservativeRoots::genericAddPointer):
* heap/Heap.cpp:
(JSC::GatherHeapSnapshotData::operator() const):
(JSC::RemoveDeadHeapSnapshotNodes::operator() const):
(JSC::Heap::globalObjectCount):
(JSC::Heap::objectTypeCounts):
(JSC::Heap::deleteAllCodeBlocks):
* heap/HeapCell.cpp:
(WTF::printInternal):
* heap/HeapCell.h:
(JSC::isJSCellKind):
(JSC::hasInteriorPointers):
* heap/HeapUtil.h:
(JSC::HeapUtil::findGCObjectPointersForMarking):
(JSC::HeapUtil::isPointerGCObjectJSCell):
* heap/MarkedBlock.cpp:
(JSC::MarkedBlock::Handle::didAddToDirectory):
* heap/SlotVisitor.cpp:
(JSC::SlotVisitor::appendJSCellOrAuxiliary):
* runtime/JSGlobalObject.cpp:
* runtime/JSImmutableButterfly.h:
(JSC::JSImmutableButterfly::subspaceFor):
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:
* tools/CellProfile.h:
(JSC::CellProfile::CellProfile):
(JSC::CellProfile::isJSCell const):
* tools/HeapVerifier.cpp:
(JSC::HeapVerifier::validateCell):

LayoutTests:

Make these test not susceptible to conservative scan leaks by ensuring at least
one object gets collected when we allocate many of them. Before, these were just
testing that a fixed number of objects were collected.

* editing/selection/navigation-clears-editor-state-expected.txt:
* editing/selection/navigation-clears-editor-state.html:
* fast/dom/reference-cycle-leaks.html:
* fast/misc/resources/test-observegc.js:
* fast/misc/test-observegc-expected.txt:
* platform/mac-wk2/plugins/refcount-leaks-expected.txt:
* plugins/refcount-leaks-expected.txt:
* plugins/refcount-leaks.html:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestseditingselectionnavigationclearseditorstateexpectedtxt">trunk/LayoutTests/editing/selection/navigation-clears-editor-state-expected.txt</a></li>
<li><a href="#trunkLayoutTestseditingselectionnavigationclearseditorstatehtml">trunk/LayoutTests/editing/selection/navigation-clears-editor-state.html</a></li>
<li><a href="#trunkLayoutTestsfastdomreferencecycleleakshtml">trunk/LayoutTests/fast/dom/reference-cycle-leaks.html</a></li>
<li><a href="#trunkLayoutTestsfastmiscresourcestestobservegcjs">trunk/LayoutTests/fast/misc/resources/test-observegc.js</a></li>
<li><a href="#trunkLayoutTestsfastmisctestobservegcexpectedtxt">trunk/LayoutTests/fast/misc/test-observegc-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformmacwk2pluginsrefcountleaksexpectedtxt">trunk/LayoutTests/platform/mac-wk2/plugins/refcount-leaks-expected.txt</a></li>
<li><a href="#trunkLayoutTestspluginsrefcountleaksexpectedtxt">trunk/LayoutTests/plugins/refcount-leaks-expected.txt</a></li>
<li><a href="#trunkLayoutTestspluginsrefcountleakshtml">trunk/LayoutTests/plugins/refcount-leaks.html</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerNodesCodegencpp">trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggercpp">trunk/Source/JavaScriptCore/debugger/Debugger.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapConservativeRootscpp">trunk/Source/JavaScriptCore/heap/ConservativeRoots.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapcpp">trunk/Source/JavaScriptCore/heap/Heap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapCellcpp">trunk/Source/JavaScriptCore/heap/HeapCell.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapCellh">trunk/Source/JavaScriptCore/heap/HeapCell.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapUtilh">trunk/Source/JavaScriptCore/heap/HeapUtil.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedBlockcpp">trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSlotVisitorcpp">trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGlobalObjectcpp">trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSImmutableButterflyh">trunk/Source/JavaScriptCore/runtime/JSImmutableButterfly.h</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="#trunkSourceJavaScriptCoretoolsCellProfileh">trunk/Source/JavaScriptCore/tools/CellProfile.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretoolsHeapVerifiercpp">trunk/Source/JavaScriptCore/tools/HeapVerifier.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog      2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/LayoutTests/ChangeLog 2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2018-06-26  Saam Barati  <sbarati@apple.com>
+
+        JSImmutableButterfly can't be allocated from a subspace with HeapCell::Kind::Auxiliary
+        https://bugs.webkit.org/show_bug.cgi?id=186878
+        <rdar://problem/40568659>
+
+        Reviewed by Filip Pizlo.
+
+        Make these test not susceptible to conservative scan leaks by ensuring at least
+        one object gets collected when we allocate many of them. Before, these were just
+        testing that a fixed number of objects were collected.
+
+        * editing/selection/navigation-clears-editor-state-expected.txt:
+        * editing/selection/navigation-clears-editor-state.html:
+        * fast/dom/reference-cycle-leaks.html:
+        * fast/misc/resources/test-observegc.js:
+        * fast/misc/test-observegc-expected.txt:
+        * platform/mac-wk2/plugins/refcount-leaks-expected.txt:
+        * plugins/refcount-leaks-expected.txt:
+        * plugins/refcount-leaks.html:
+
</ins><span class="cx"> 2018-06-26  Truitt Savell  <tsavell@apple.com>
</span><span class="cx"> 
</span><span class="cx">         [iOS] Rebaseline two webanimations tests after r233164
</span></span></pre></div>
<a id="trunkLayoutTestseditingselectionnavigationclearseditorstateexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/editing/selection/navigation-clears-editor-state-expected.txt (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/editing/selection/navigation-clears-editor-state-expected.txt  2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/LayoutTests/editing/selection/navigation-clears-editor-state-expected.txt     2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -3,10 +3,7 @@
</span><span class="cx"> On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-iframe = appendIframe()
-PASS internals.numberOfLiveDocuments() is initialDocumentCount + 1
-iframe.src = "resources/select-iframe-focusin-document-crash-frame.html"
-PASS internals.numberOfLiveDocuments() is initialDocumentCount + 1
</del><ins>+PASS freed more than 60 documents
</ins><span class="cx"> PASS successfullyParsed is true
</span><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span></span></pre></div>
<a id="trunkLayoutTestseditingselectionnavigationclearseditorstatehtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/editing/selection/navigation-clears-editor-state.html (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/editing/selection/navigation-clears-editor-state.html  2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/LayoutTests/editing/selection/navigation-clears-editor-state.html     2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -35,21 +35,36 @@
</span><span class="cx"> {
</span><span class="cx">     initialDocumentCount = internals.numberOfLiveDocuments();
</span><span class="cx"> 
</span><del>-    evalAndLog('iframe = appendIframe()');
</del><ins>+    let frames = [];
+    const count = 200;
+    for (let i = 0; i < count; ++i)
+        frames.push(appendIframe());
</ins><span class="cx"> 
</span><span class="cx">     await wait(0); // Make sure the transient document created by inserting an iframe is removed.
</span><span class="cx">     GCController.collect();
</span><span class="cx"> 
</span><del>-    shouldBe('internals.numberOfLiveDocuments()', 'initialDocumentCount + 1');
-    setEditorStates(iframe);
</del><ins>+    for (let frame of frames)
+        setEditorStates(frame);
</ins><span class="cx"> 
</span><span class="cx">     await wait(0); // Wait for UI update timer to fire.
</span><span class="cx"> 
</span><del>-    evalAndLog('iframe.src = "resources/select-iframe-focusin-document-crash-frame.html"');
-    iframe.onload = () => {
-        GCController.collect();
-        shouldBe('internals.numberOfLiveDocuments()', 'initialDocumentCount + 1');
-        finishJSTest();                
</del><ins>+    let resolved = 0;
+    for (let frame of frames) {
+        frame.src = "resources/select-iframe-focusin-document-crash-frame.html";
+        frame.onload = () => {
+            ++resolved;
+            if (resolved !== count)
+                return;
+            let before = internals.numberOfLiveDocuments();
+            GCController.collect();
+            let after = internals.numberOfLiveDocuments();
+            let delta = before - after;
+            if (delta > 0.3 * count)
+                debug("PASS freed more than 60 documents");
+            else
+                debug("FAIL freed fewer than 60 documents");
+            finishJSTest();                
+        };
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -57,7 +72,7 @@
</span><span class="cx">     debug('This test requires GCController and internals');
</span><span class="cx"> } else {
</span><span class="cx">     if (window.testRunner)
</span><del>-        setTimeout(() => testRunner.notifyDone(), 3000);
</del><ins>+        setTimeout(() => testRunner.notifyDone(), 5000);
</ins><span class="cx">     // Clear out any lingering documents from the previous tests.
</span><span class="cx">     GCController.collect();
</span><span class="cx">     GCController.collect();
</span></span></pre></div>
<a id="trunkLayoutTestsfastdomreferencecycleleakshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/dom/reference-cycle-leaks.html (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/dom/reference-cycle-leaks.html    2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/LayoutTests/fast/dom/reference-cycle-leaks.html       2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -7,7 +7,7 @@
</span><span class="cx"> function checkForNodeLeaks(testFunction, underlyingClass)
</span><span class="cx"> {
</span><span class="cx">     // Bump this number as high as we need to, to get reproducible results.
</span><del>-    const repetitions = 20;
</del><ins>+    const repetitions = 40;
</ins><span class="cx"> 
</span><span class="cx">     gc();
</span><span class="cx">     const beforeCount = internals.numberOfLiveNodes();
</span></span></pre></div>
<a id="trunkLayoutTestsfastmiscresourcestestobservegcjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/misc/resources/test-observegc.js (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/misc/resources/test-observegc.js  2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/LayoutTests/fast/misc/resources/test-observegc.js     2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -1,9 +1,19 @@
</span><span class="cx"> description("Ensures that window.internals.observegc works as expected");
</span><span class="cx"> 
</span><del>-var testObject = { testProperty : "testValue" };
</del><ins>+var observers = [];
+for (let i = 0; i < 1000; ++i) {
+    let testObject = { testProperty : "testValue" };
+    let observer = internals.observeGC(testObject);
+    observers.push(observer);
+    testObject = null;
+}
</ins><span class="cx"> 
</span><del>-var observer = internals.observeGC(testObject);
-testObject = null;
</del><span class="cx"> gc();
</span><span class="cx"> 
</span><del>-shouldBe('observer.wasCollected', 'true');
</del><ins>+var anyCollected = false;
+for (let observer of observers) {
+    if (observer.wasCollected)
+        anyCollected = true;
+}
+
+shouldBe('anyCollected', 'true');
</ins></span></pre></div>
<a id="trunkLayoutTestsfastmisctestobservegcexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/misc/test-observegc-expected.txt (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/misc/test-observegc-expected.txt  2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/LayoutTests/fast/misc/test-observegc-expected.txt     2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -3,7 +3,7 @@
</span><span class="cx"> On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-PASS observer.wasCollected is true
</del><ins>+PASS anyCollected is true
</ins><span class="cx"> PASS successfullyParsed is true
</span><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacwk2pluginsrefcountleaksexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac-wk2/plugins/refcount-leaks-expected.txt (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac-wk2/plugins/refcount-leaks-expected.txt   2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/LayoutTests/platform/mac-wk2/plugins/refcount-leaks-expected.txt      2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -1,12 +1,8 @@
</span><ins>+PASS countAfterCreate === countOrig + 50 is true
+FAIL countAfterGC < countAfterCreate should be true. Was false.
+PASS refAfterGet === refOrig + 50 is true
+FAIL refAfterGetGC < refAfterGet should be true. Was false.
+PASS refAfterPass === refBeforePass + 50 is true
+FAIL refAfterPassAndGC < refAfterPass should be true. Was false.
</ins><span class="cx"> Test that we can get an NPObject returned through a method on an NPAPI Object.
</span><del>-Prints "SUCCESS" on success, "FAILURE" on failure.  
</del><span class="cx"> 
</span><del>---- num test objects:
-countAfterCreate == countOrig + 3? PASS
-countOrig == countAfterGC? FAIL
-
---- refcount on plug.testObject:
-originally: 2
-after GC: 5
-after passing: 8
-FAILURE
</del></span></pre></div>
<a id="trunkLayoutTestspluginsrefcountleaksexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/plugins/refcount-leaks-expected.txt (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/plugins/refcount-leaks-expected.txt    2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/LayoutTests/plugins/refcount-leaks-expected.txt       2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -1,12 +1,8 @@
</span><ins>+PASS countAfterCreate === countOrig + 50 is true
+PASS countAfterGC < countAfterCreate is true
+PASS refAfterGet === refOrig + 50 is true
+PASS refAfterGetGC < refAfterGet is true
+PASS refAfterPass === refBeforePass + 50 is true
+PASS refAfterPassAndGC < refAfterPass is true
</ins><span class="cx"> Test that we can get an NPObject returned through a method on an NPAPI Object.
</span><del>-Prints "SUCCESS" on success, "FAILURE" on failure.  
</del><span class="cx"> 
</span><del>---- num test objects:
-countAfterCreate == countOrig + 3? PASS
-countOrig == countAfterGC? PASS
-
---- refcount on plug.testObject:
-originally: 2
-after GC: 2
-after passing: 2
-SUCCESS
</del></span></pre></div>
<a id="trunkLayoutTestspluginsrefcountleakshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/plugins/refcount-leaks.html (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/plugins/refcount-leaks.html    2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/LayoutTests/plugins/refcount-leaks.html       2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -1,83 +1,74 @@
</span><ins>+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+
</ins><span class="cx"> <script>
</span><del>-  function noop(x) {
-  }
</del><ins>+function noop(x) {
+}
</ins><span class="cx"> 
</span><del>-  function doGC() {
-    if (window.GCController) {
-      // GC twice to make sure everything is cleaned up.
-      for (var i = 0; i < 2; i++) {
-        window.GCController.collect();
-      }
</del><ins>+function doGC() {
+    // GC twice to make sure everything is cleaned up.
+    for (var i = 0; i < 2; i++) {
+        gc();
</ins><span class="cx">     }
</span><del>-  }
</del><ins>+}
</ins><span class="cx"> 
</span><del>-  function runtest() {
</del><ins>+var countOrig;
+var countAfterCreate;
+var countAfterGC;
+var testObj;
+var refOrig;
+var refAfterGet;
+var refAfterGetGC;
+var refBeforePass;
+var refAfterPass;
+var refAfterPassAndGC;
+
+function runtest() {
</ins><span class="cx">     if (window.testRunner)
</span><del>-      testRunner.dumpAsText();
</del><ins>+        testRunner.dumpAsText();
</ins><span class="cx"> 
</span><del>-
-    var output = document.getElementById("output");
-    output.innerHTML = "";
-
</del><span class="cx">     // Test that objects are deleted after their JS references are released.
</span><del>-    var countOrig = plug.testObjectCount;
-    o1 = plug.testCreateTestObject();
-    o2 = plug.testCreateTestObject();
-    o3 = plug.testCreateTestObject();
-    var countAfterCreate = plug.testObjectCount;
-    o1 = o2 = o3 = null;
</del><ins>+    countOrig = plug.testObjectCount;
+    let x;
+    for (let i = 0; i < 50; ++i)
+        x = plug.testCreateTestObject();
+    countAfterCreate = plug.testObjectCount;
+    x = null;
</ins><span class="cx">     doGC();
</span><del>-    var countAfterGC = plug.testObjectCount;
</del><ins>+    countAfterGC = plug.testObjectCount;
+    shouldBe('countAfterCreate === countOrig + 50', 'true');
+    shouldBe('countAfterGC < countAfterCreate', 'true');
</ins><span class="cx"> 
</span><del>-    output.innerHTML += "--- num test objects:<br>";
-    output.innerHTML += "countAfterCreate == countOrig + 3? "
-        + ((countAfterCreate == countOrig + 3) ? "PASS" : "FAIL")
-        + "<br>";
-    output.innerHTML += "countOrig == countAfterGC? "
-        + ((countOrig == countAfterGC) ? "PASS" : "FAIL")
-        + "<br>";
-    output.innerHTML += "<br>";
-
</del><span class="cx">     // Test that the object refcount returns to normal after JS references
</span><span class="cx">     // are released.
</span><del>-    var testObj = plug.testObject;
-    var refOrig = testObj.refCount;
-    var o1 = plug.testObject;
-    var o2 = plug.testObject;
-    var o3 = plug.testObject;
-    var refAfterGet = testObj.refCount;
-    o1 = o2 = o3 = null;
</del><ins>+    testObj = plug.testObject;
+    refOrig = testObj.refCount;
+    for (let i = 0; i < 50; ++i)
+        plug.testObject;
+    refAfterGet = testObj.refCount;
</ins><span class="cx">     doGC();
</span><del>-    var refAfterGetGC = testObj.refCount;
</del><ins>+    refAfterGetGC = testObj.refCount;
+    shouldBe('refAfterGet === refOrig + 50', 'true');
+    shouldBe('refAfterGetGC < refAfterGet', 'true');
</ins><span class="cx"> 
</span><span class="cx">     // Test that calling NPN_Invoke with our object as a parameter returns
</span><span class="cx">     // our refcount to normal (may require a GC).
</span><del>-    plug.testPassTestObject("noop", testObj);
-    plug.testPassTestObject("noop", testObj);
-    plug.testPassTestObject("noop", testObj);
</del><ins>+    refBeforePass = testObj.refCount;
+    for (let i = 0; i < 50; ++i)
+        plug.testPassTestObject("noop", testObj);
+    refAfterPass = testObj.refCount;
</ins><span class="cx">     doGC();
</span><del>-    var refAfterPass = testObj.refCount;
-
-    output.innerHTML += "--- refcount on plug.testObject:<br>";
-    output.innerHTML += "originally: " + refOrig + "<br>";
-    output.innerHTML += "after GC: " + refAfterGetGC + "<br>";
-    output.innerHTML += "after passing: " + refAfterPass + "<br>";
-
-    var success = (countAfterGC == countOrig) && (refAfterPass == refOrig);
-    output.innerHTML += (success ? "SUCCESS" : "FAILURE");
-  }
</del><ins>+    refAfterPassAndGC = testObj.refCount;
+    shouldBe('refAfterPass === refBeforePass + 50', 'true');
+    shouldBe('refAfterPassAndGC < refAfterPass', 'true');
+}
</ins><span class="cx"> </script>
</span><span class="cx"> 
</span><span class="cx"> <body onload="runtest()">
</span><span class="cx"> 
</span><del>-Test that we can get an NPObject returned through a method on
-an NPAPI Object.<P>
</del><ins>+    Test that we can get an NPObject returned through a method on
+    an NPAPI Object.<P>
</ins><span class="cx"> 
</span><del>-Prints "SUCCESS" on success, "FAILURE" on failure.
-
-<embed name="plug" type="application/x-webkit-test-netscape">
-
-<div id=output>FAILURE</div>
-
</del><ins>+    <embed name="plug" type="application/x-webkit-test-netscape">
</ins><span class="cx"> </body>
</span><del>-
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog    2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/Source/JavaScriptCore/ChangeLog       2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -1,3 +1,59 @@
</span><ins>+2018-06-26  Saam Barati  <sbarati@apple.com>
+
+        JSImmutableButterfly can't be allocated from a subspace with HeapCell::Kind::Auxiliary
+        https://bugs.webkit.org/show_bug.cgi?id=186878
+        <rdar://problem/40568659>
+
+        Reviewed by Filip Pizlo.
+
+        This patch fixes a bug in our JSImmutableButterfly implementation uncovered by
+        our stress GC bots. Before this patch, JSImmutableButterfly was allocated
+        with HeapCell::Kind::Auxiliary. This is wrong. Things that are JSCells can't
+        be allocated from HeapCell::Kind::Auxiliary. This patch adds a new HeapCell::Kind
+        called JSCellWithInteriorPointers. It behaves like JSCell in all ways, except
+        conservative scan knows to treat it like a butterfly in when we we may be
+        pointing into the middle of it.
+        
+        The way we were crashing on the stress GC bots is that our conservative marking
+        won't do cell visiting for things that are Auxiliary. This meant that if the
+        stack were the only thing pointing to a JSImmutableButterfly when a GC took place,
+        that JSImmutableButterfly would not be visited. This is now fixed.
+
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ArrayNode::emitBytecode):
+        * debugger/Debugger.cpp:
+        * heap/ConservativeRoots.cpp:
+        (JSC::ConservativeRoots::genericAddPointer):
+        * heap/Heap.cpp:
+        (JSC::GatherHeapSnapshotData::operator() const):
+        (JSC::RemoveDeadHeapSnapshotNodes::operator() const):
+        (JSC::Heap::globalObjectCount):
+        (JSC::Heap::objectTypeCounts):
+        (JSC::Heap::deleteAllCodeBlocks):
+        * heap/HeapCell.cpp:
+        (WTF::printInternal):
+        * heap/HeapCell.h:
+        (JSC::isJSCellKind):
+        (JSC::hasInteriorPointers):
+        * heap/HeapUtil.h:
+        (JSC::HeapUtil::findGCObjectPointersForMarking):
+        (JSC::HeapUtil::isPointerGCObjectJSCell):
+        * heap/MarkedBlock.cpp:
+        (JSC::MarkedBlock::Handle::didAddToDirectory):
+        * heap/SlotVisitor.cpp:
+        (JSC::SlotVisitor::appendJSCellOrAuxiliary):
+        * runtime/JSGlobalObject.cpp:
+        * runtime/JSImmutableButterfly.h:
+        (JSC::JSImmutableButterfly::subspaceFor):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+        * tools/CellProfile.h:
+        (JSC::CellProfile::CellProfile):
+        (JSC::CellProfile::isJSCell const):
+        * tools/HeapVerifier.cpp:
+        (JSC::HeapVerifier::validateCell):
+
</ins><span class="cx"> 2018-06-26  Mark Lam  <mark.lam@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Skip some unnecessary work in Interpreter::getStackTrace().
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp   2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -406,6 +406,7 @@
</span><span class="cx">     auto newArray = [&] (RegisterID* dst, ElementNode* elements, unsigned length, bool hadVariableExpression) {
</span><span class="cx">         if (length && !hadVariableExpression) {
</span><span class="cx">             recommendedIndexingType |= CopyOnWrite;
</span><ins>+            ASSERT(generator.vm()->heap.isDeferred()); // We run bytecode generator under a DeferGC. If we stopped doing that, we'd need to put a DeferGC here as we filled in these slots.
</ins><span class="cx">             auto* array = JSImmutableButterfly::create(*generator.vm(), recommendedIndexingType, length);
</span><span class="cx">             unsigned index = 0;
</span><span class="cx">             for (ElementNode* element = elements; index < length; element = element->next()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/Debugger.cpp (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/Debugger.cpp        2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/Source/JavaScriptCore/debugger/Debugger.cpp   2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -51,7 +51,7 @@
</span><span class="cx"> 
</span><span class="cx">     IterationStatus operator()(HeapCell* heapCell, HeapCell::Kind kind) const
</span><span class="cx">     {
</span><del>-        if (kind != HeapCell::JSCell)
</del><ins>+        if (!isJSCellKind(kind))
</ins><span class="cx">             return IterationStatus::Continue;
</span><span class="cx">         
</span><span class="cx">         JSCell* cell = static_cast<JSCell*>(heapCell);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapConservativeRootscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/ConservativeRoots.cpp (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/ConservativeRoots.cpp   2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/Source/JavaScriptCore/heap/ConservativeRoots.cpp      2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -73,7 +73,7 @@
</span><span class="cx">     HeapUtil::findGCObjectPointersForMarking(
</span><span class="cx">         m_heap, markingVersion, newlyAllocatedVersion, filter, p,
</span><span class="cx">         [&] (void* p, HeapCell::Kind cellKind) {
</span><del>-            if (cellKind == HeapCell::JSCell)
</del><ins>+            if (isJSCellKind(cellKind))
</ins><span class="cx">                 markHook.markKnownJSCell(static_cast<JSCell*>(p));
</span><span class="cx">             
</span><span class="cx">             if (m_size == m_capacity)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp   2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -720,7 +720,7 @@
</span><span class="cx"> 
</span><span class="cx">     IterationStatus operator()(HeapCell* heapCell, HeapCell::Kind kind) const
</span><span class="cx">     {
</span><del>-        if (kind == HeapCell::JSCell) {
</del><ins>+        if (isJSCellKind(kind)) {
</ins><span class="cx">             JSCell* cell = static_cast<JSCell*>(heapCell);
</span><span class="cx">             cell->methodTable()->heapSnapshot(cell, m_builder);
</span><span class="cx">         }
</span><span class="lines">@@ -747,7 +747,7 @@
</span><span class="cx"> 
</span><span class="cx">     IterationStatus operator()(HeapCell* cell, HeapCell::Kind kind) const
</span><span class="cx">     {
</span><del>-        if (kind == HeapCell::JSCell)
</del><ins>+        if (isJSCellKind(kind))
</ins><span class="cx">             m_snapshot.sweepCell(static_cast<JSCell*>(cell));
</span><span class="cx">         return IterationStatus::Continue;
</span><span class="cx">     }
</span><span class="lines">@@ -836,7 +836,7 @@
</span><span class="cx">     m_objectSpace.forEachLiveCell(
</span><span class="cx">         iterationScope,
</span><span class="cx">         [&] (HeapCell* heapCell, HeapCell::Kind kind) -> IterationStatus {
</span><del>-            if (kind != HeapCell::JSCell)
</del><ins>+            if (!isJSCellKind(kind))
</ins><span class="cx">                 return IterationStatus::Continue;
</span><span class="cx">             JSCell* cell = static_cast<JSCell*>(heapCell);
</span><span class="cx">             if (cell->isObject() && asObject(cell)->isGlobalObject())
</span><span class="lines">@@ -873,7 +873,7 @@
</span><span class="cx">     m_objectSpace.forEachLiveCell(
</span><span class="cx">         iterationScope,
</span><span class="cx">         [&] (HeapCell* cell, HeapCell::Kind kind) -> IterationStatus {
</span><del>-            if (kind == HeapCell::JSCell)
</del><ins>+            if (isJSCellKind(kind))
</ins><span class="cx">                 recordType(*vm(), *result, static_cast<JSCell*>(cell));
</span><span class="cx">             return IterationStatus::Continue;
</span><span class="cx">         });
</span><span class="lines">@@ -915,7 +915,7 @@
</span><span class="cx">         // it uses a callee check, but then it will call into dead code.
</span><span class="cx">         HeapIterationScope heapIterationScope(*this);
</span><span class="cx">         vm.webAssemblyCodeBlockSpace.forEachLiveCell([&] (HeapCell* cell, HeapCell::Kind kind) {
</span><del>-            ASSERT_UNUSED(kind, kind == HeapCell::Kind::JSCell);
</del><ins>+            ASSERT_UNUSED(kind, kind == HeapCell::JSCell);
</ins><span class="cx">             JSWebAssemblyCodeBlock* codeBlock = static_cast<JSWebAssemblyCodeBlock*>(cell);
</span><span class="cx">             codeBlock->clearJSCallICs(vm);
</span><span class="cx">         });
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapCellcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/HeapCell.cpp (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapCell.cpp    2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/Source/JavaScriptCore/heap/HeapCell.cpp       2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -60,6 +60,9 @@
</span><span class="cx">     case HeapCell::JSCell:
</span><span class="cx">         out.print("JSCell");
</span><span class="cx">         return;
</span><ins>+    case HeapCell::JSCellWithInteriorPointers:
+        out.print("JSCellWithInteriorPointers");
+        return;
</ins><span class="cx">     case HeapCell::Auxiliary:
</span><span class="cx">         out.print("Auxiliary");
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapCellh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/HeapCell.h (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapCell.h      2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/Source/JavaScriptCore/heap/HeapCell.h 2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -43,6 +43,7 @@
</span><span class="cx"> public:
</span><span class="cx">     enum Kind : int8_t {
</span><span class="cx">         JSCell,
</span><ins>+        JSCellWithInteriorPointers,
</ins><span class="cx">         Auxiliary
</span><span class="cx">     };
</span><span class="cx">     
</span><span class="lines">@@ -86,6 +87,16 @@
</span><span class="cx"> #endif
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+inline bool isJSCellKind(HeapCell::Kind kind)
+{
+    return kind == HeapCell::JSCell || kind == HeapCell::JSCellWithInteriorPointers;
+}
+
+inline bool hasInteriorPointers(HeapCell::Kind kind)
+{
+    return kind == HeapCell::Auxiliary || kind == HeapCell::JSCellWithInteriorPointers;
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapUtilh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/HeapUtil.h (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapUtil.h      2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/Source/JavaScriptCore/heap/HeapUtil.h 2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -88,7 +88,7 @@
</span><span class="cx">             MarkedBlock* previousCandidate = MarkedBlock::blockFor(previousPointer);
</span><span class="cx">             if (!filter.ruleOut(bitwise_cast<Bits>(previousCandidate))
</span><span class="cx">                 && set.contains(previousCandidate)
</span><del>-                && previousCandidate->handle().cellKind() == HeapCell::Auxiliary) {
</del><ins>+                && hasInteriorPointers(previousCandidate->handle().cellKind())) {
</ins><span class="cx">                 previousPointer = static_cast<char*>(previousCandidate->handle().cellAlign(previousPointer));
</span><span class="cx">                 if (previousCandidate->handle().isLiveCell(markingVersion, newlyAllocatedVersion, isMarking, previousPointer))
</span><span class="cx">                     func(previousPointer, previousCandidate->handle().cellKind());
</span><span class="lines">@@ -110,12 +110,11 @@
</span><span class="cx">                 func(pointer, cellKind);
</span><span class="cx">         };
</span><span class="cx">     
</span><del>-        if (candidate->handle().cellKind() == HeapCell::JSCell) {
-            if (!MarkedBlock::isAtomAligned(pointer))
</del><ins>+        if (isJSCellKind(cellKind)) {
+            if (MarkedBlock::isAtomAligned(pointer))
+                tryPointer(pointer);
+            if (!hasInteriorPointers(cellKind))
</ins><span class="cx">                 return;
</span><del>-        
-            tryPointer(pointer);
-            return;
</del><span class="cx">         }
</span><span class="cx">     
</span><span class="cx">         // A butterfly could point into the middle of an object.
</span><span class="lines">@@ -144,14 +143,14 @@
</span><span class="cx">                 if (result) {
</span><span class="cx">                     if (result > largeAllocations.begin()
</span><span class="cx">                         && result[-1]->cell() == pointer
</span><del>-                        && result[-1]->attributes().cellKind == HeapCell::JSCell)
</del><ins>+                        && isJSCellKind(result[-1]->attributes().cellKind))
</ins><span class="cx">                         return true;
</span><span class="cx">                     if (result[0]->cell() == pointer
</span><del>-                        && result[0]->attributes().cellKind == HeapCell::JSCell)
</del><ins>+                        && isJSCellKind(result[0]->attributes().cellKind))
</ins><span class="cx">                         return true;
</span><span class="cx">                     if (result + 1 < largeAllocations.end()
</span><span class="cx">                         && result[1]->cell() == pointer
</span><del>-                        && result[1]->attributes().cellKind == HeapCell::JSCell)
</del><ins>+                        && isJSCellKind(result[1]->attributes().cellKind))
</ins><span class="cx">                         return true;
</span><span class="cx">                 }
</span><span class="cx">             }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp 2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp    2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -351,7 +351,7 @@
</span><span class="cx">     
</span><span class="cx">     m_attributes = directory->attributes();
</span><span class="cx"> 
</span><del>-    if (m_attributes.cellKind != HeapCell::JSCell)
</del><ins>+    if (!isJSCellKind(m_attributes.cellKind))
</ins><span class="cx">         RELEASE_ASSERT(m_attributes.destruction == DoesNotNeedDestruction);
</span><span class="cx">     
</span><span class="cx">     double markCountBias = -(Options::minMarkedBlockUtilization() * cellsPerBlock());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp 2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp    2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -196,7 +196,7 @@
</span><span class="cx">     
</span><span class="cx">     // In debug mode, we validate before marking since this makes it clearer what the problem
</span><span class="cx">     // was. It's also slower, so we don't do it normally.
</span><del>-    if (!ASSERT_DISABLED && heapCell->cellKind() == HeapCell::JSCell)
</del><ins>+    if (!ASSERT_DISABLED && isJSCellKind(heapCell->cellKind()))
</ins><span class="cx">         validateCell(static_cast<JSCell*>(heapCell));
</span><span class="cx">     
</span><span class="cx">     if (Heap::testAndSetMarked(m_markingVersion, heapCell))
</span><span class="lines">@@ -203,7 +203,8 @@
</span><span class="cx">         return;
</span><span class="cx">     
</span><span class="cx">     switch (heapCell->cellKind()) {
</span><del>-    case HeapCell::JSCell: {
</del><ins>+    case HeapCell::JSCell:
+    case HeapCell::JSCellWithInteriorPointers: {
</ins><span class="cx">         // We have ample budget to perform validation here.
</span><span class="cx">     
</span><span class="cx">         JSCell* jsCell = static_cast<JSCell*>(heapCell);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp   2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp      2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -1239,7 +1239,7 @@
</span><span class="cx"> 
</span><span class="cx"> IterationStatus ObjectsWithBrokenIndexingFinder::operator()(HeapCell* cell, HeapCell::Kind kind) const
</span><span class="cx"> {
</span><del>-    if (kind == HeapCell::JSCell) {
</del><ins>+    if (isJSCellKind(kind)) {
</ins><span class="cx">         // FIXME: This const_cast exists because this isn't a C++ lambda.
</span><span class="cx">         // https://bugs.webkit.org/show_bug.cgi?id=159644
</span><span class="cx">         const_cast<ObjectsWithBrokenIndexingFinder*>(this)->visit(static_cast<JSCell*>(cell));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSImmutableButterflyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSImmutableButterfly.h (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSImmutableButterfly.h       2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/Source/JavaScriptCore/runtime/JSImmutableButterfly.h  2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -89,7 +89,7 @@
</span><span class="cx">     static CompleteSubspace* subspaceFor(VM& vm)
</span><span class="cx">     {
</span><span class="cx">         // We allocate out of the JSValue gigacage as other code expects all butterflies to live there.
</span><del>-        return &vm.jsValueGigacageAuxiliarySpace;
</del><ins>+        return &vm.immutableButterflyJSValueGigacageAuxiliarySpace;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Only call this if you just allocated this butterfly.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp       2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp  2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -254,6 +254,7 @@
</span><span class="cx">     , jsValueGigacageAllocator(std::make_unique<GigacageAlignedMemoryAllocator>(Gigacage::JSValue))
</span><span class="cx">     , auxiliaryHeapCellType(std::make_unique<HeapCellType>(CellAttributes(DoesNotNeedDestruction, HeapCell::Auxiliary)))
</span><span class="cx">     , cellJSValueOOBHeapCellType(std::make_unique<HeapCellType>(CellAttributes(DoesNotNeedDestruction, HeapCell::JSCell)))
</span><ins>+    , immutableButterflyHeapCellType(std::make_unique<HeapCellType>(CellAttributes(DoesNotNeedDestruction, HeapCell::JSCellWithInteriorPointers)))
</ins><span class="cx">     , cellDangerousBitsHeapCellType(std::make_unique<HeapCellType>(CellAttributes(DoesNotNeedDestruction, HeapCell::JSCell)))
</span><span class="cx">     , destructibleCellHeapCellType(std::make_unique<HeapCellType>(CellAttributes(NeedsDestruction, HeapCell::JSCell)))
</span><span class="cx">     , stringHeapCellType(std::make_unique<JSStringHeapCellType>())
</span><span class="lines">@@ -264,6 +265,7 @@
</span><span class="cx"> #endif
</span><span class="cx">     , primitiveGigacageAuxiliarySpace("Primitive Gigacage Auxiliary", heap, auxiliaryHeapCellType.get(), primitiveGigacageAllocator.get())
</span><span class="cx">     , jsValueGigacageAuxiliarySpace("JSValue Gigacage Auxiliary", heap, auxiliaryHeapCellType.get(), jsValueGigacageAllocator.get())
</span><ins>+    , immutableButterflyJSValueGigacageAuxiliarySpace("ImmutableButterfly Gigacage JSCellWithInteriorPointers", heap, immutableButterflyHeapCellType.get(), jsValueGigacageAllocator.get())
</ins><span class="cx">     , cellJSValueOOBSpace("JSCell JSValueOOB", heap, cellJSValueOOBHeapCellType.get(), fastMallocAllocator.get())
</span><span class="cx">     , cellDangerousBitsSpace("JSCell DangerousBits", heap, cellDangerousBitsHeapCellType.get(), fastMallocAllocator.get())
</span><span class="cx">     , jsValueGigacageCellSpace("JSValue Gigacage JSCell", heap, cellJSValueOOBHeapCellType.get(), jsValueGigacageAllocator.get())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h 2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/Source/JavaScriptCore/runtime/VM.h    2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -306,6 +306,7 @@
</span><span class="cx"> 
</span><span class="cx">     std::unique_ptr<HeapCellType> auxiliaryHeapCellType;
</span><span class="cx">     std::unique_ptr<HeapCellType> cellJSValueOOBHeapCellType;
</span><ins>+    std::unique_ptr<HeapCellType> immutableButterflyHeapCellType;
</ins><span class="cx">     std::unique_ptr<HeapCellType> cellDangerousBitsHeapCellType;
</span><span class="cx">     std::unique_ptr<HeapCellType> destructibleCellHeapCellType;
</span><span class="cx">     std::unique_ptr<JSStringHeapCellType> stringHeapCellType;
</span><span class="lines">@@ -317,6 +318,7 @@
</span><span class="cx">     
</span><span class="cx">     CompleteSubspace primitiveGigacageAuxiliarySpace; // Typed arrays, strings, bitvectors, etc go here.
</span><span class="cx">     CompleteSubspace jsValueGigacageAuxiliarySpace; // Butterflies, arrays of JSValues, etc go here.
</span><ins>+    CompleteSubspace immutableButterflyJSValueGigacageAuxiliarySpace; // JSImmutableButterfly goes here.
</ins><span class="cx"> 
</span><span class="cx">     // We make cross-cutting assumptions about typed arrays being in the primitive Gigacage and butterflies
</span><span class="cx">     // being in the JSValue gigacage. For some types, it's super obvious where they should go, and so we
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretoolsCellProfileh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tools/CellProfile.h (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tools/CellProfile.h  2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/Source/JavaScriptCore/tools/CellProfile.h     2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -45,7 +45,7 @@
</span><span class="cx">         , m_liveness(liveness)
</span><span class="cx">         , m_timestamp(MonotonicTime::now())
</span><span class="cx">     {
</span><del>-        if (m_kind == HeapCell::JSCell && m_liveness != Dead)
</del><ins>+        if (isJSCellKind(m_kind) && m_liveness != Dead)
</ins><span class="cx">             m_className = jsCell()->structure()->classInfo()->className;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -65,7 +65,7 @@
</span><span class="cx">         return static_cast<JSCell*>(m_cell);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool isJSCell() const { return m_kind == HeapCell::JSCell; }
</del><ins>+    bool isJSCell() const { return isJSCellKind(m_kind); }
</ins><span class="cx">     
</span><span class="cx">     HeapCell::Kind kind() const { return m_kind; }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretoolsHeapVerifiercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tools/HeapVerifier.cpp (233235 => 233236)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tools/HeapVerifier.cpp       2018-06-27 01:07:27 UTC (rev 233235)
+++ trunk/Source/JavaScriptCore/tools/HeapVerifier.cpp  2018-06-27 01:08:25 UTC (rev 233236)
</span><span class="lines">@@ -188,7 +188,7 @@
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (cell->cellKind() != HeapCell::JSCell)
</del><ins>+    if (!isJSCellKind(cell->cellKind()))
</ins><span class="cx">         return true; // Nothing more to validate.
</span><span class="cx"> 
</span><span class="cx">     JSCell* jsCell = static_cast<JSCell*>(cell);
</span></span></pre>
</div>
</div>

</body>
</html>