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

<h3>Log Message</h3>
<pre>Allow an object's marking state to track The Three Colors
https://bugs.webkit.org/show_bug.cgi?id=149654

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

I want to make GC marking concurrent (see https://bugs.webkit.org/show_bug.cgi?id=149432).
Concurrent GC require barriers to be executed during certain heap operations. We already have a
generational GC. Generational GCs also need barriers, and we already have those. The generational
GC barrier that we use is the &quot;sticky mark bit&quot; barrier. Ordinarily, mark bits get reset after a
collection. In our collector, there is a secondary mark bit that &quot;sticks&quot; - i.e. it does not get
reset. If the sticky mark bit is set in between two collections, then we know that the object is in
old space. This is sufficient to determine when to put things into remembered sets. Additionally,
the sticky mark bit is actually a tri-state that can also tell us if the object has been placed on
a remembered set.

This is awfully similar to what you want in a concurrent GC. Concurrent GCs typically want writes
to the heap that change the object graph to do different things depending on an object's marking
state, which is usually referred to as its color. White means that the object has never been seen
by the collector. All white objects are presumed dead at the flip. Grey objects are those that are
known to the collector but have not been scanned. Black objects are those that have been scanned,
and will not be scanned again. White is exactly just &quot;not being marked&quot;, and both grey and black
mean &quot;marked&quot; - with &quot;black&quot; meaning &quot;marked but not on any worklist&quot;. That's quite a bit like the
current &quot;Marked&quot; and &quot;MarkedAndRemembered&quot; states that we have for generational GC.
&quot;MarkedAndRemembered&quot; is a lot like &quot;grey&quot;, and &quot;Marked&quot; is a lot like &quot;black&quot;.

I want to make a concurrent GC that unifies the generational and concurrent barriers into a single
fast path check. Even better if the two barriers are entirely identical. You can do this using
Pirinen's technique #2 [1], originally due to Guy Steele [2]: when doing o.f=v where o is black and
v is white, turn o grey again. This is like remembering an object, in the sense that our gen GC
&quot;rememberes&quot; o when o is old and v is new. It remembers objects by putting them on the mark stack,
setting the generational state to MarkedAndRemembered, and doing nothing to the primary mark bit.

This makes our concurrent GC approach pretty obvious. We want to use one barrier for concurrent and
generational, and we want to basically keep our current barriers unchanged. The only things missing
are just some small changes to allow the concurrent GC to know precisely when an object is black,
and to know during object visiting if we are visiting the object for the first time during a
collection or a subsequent time due to barrier re-greying (concurrent GC) or barrier remembering
(generational GC). So, this patch does the following:

- Changes the terminology used for the gcData header byte in JSCell. This changes the name of this
  to cellState, and introduces a new enumeration called CellState. This new enumeration behaves a
  lot like the old GCData did. It has the following members, with the following correspondence to
  the old GCData:

  OldBlack: this is like Marked, with the exception that we ensure that an object becomes OldBlack
      as soon as the object starts to be scanned. Previously, an object might be
      MarkedAndRemembered during scanning and we'd turn all MarkedAndRemembered objects into Marked
      objects during a post-processing step at the end of GC. This patch gets rid of that
      post-processing. The act of visiting an object unconditionally makes it OldBlack. Note that
      our definition of &quot;black&quot; is not that the object is done being scanned, but that it is either
      being scanned right now or it has already been scanned. This is like a combination of
      Siebert's anthracite and black states [3].

  NewWhite: this is exactly NotMarked. It's the state that objects get when they are allocated.
      It's impossible for an object to return to this state.

  OldGrey: the object is on the mark stack and will be scanned at some point in the future. This
      also means that this isn't the first time in this cycle that the object has been grey. In an
      eden collection, an old object that has been remembered is thought of as being OldGrey, even
      if this is the first time during this eden collection that it is grey. That's because an eden
      collection must behave &quot;as if&quot; the grey-&gt;black transition for old objects magically happened
      at the start of GC. Remembered objects are like old objects that underwent a concurrent
      barrier re-greying just after the magical old object grey-&gt;black transition at the start of
      GC. This state is almost exactly like MarkedAndRemembered, except that an object now
      transitions from OldGrey to OldBlack at the beginning of visiting, rather than how previously
      we transitioned from MarkedAndRemembered to Marked at the bitter end of GC.

  NewGray: the object is on the mark stack and will be scanned at some point in the future. This
      state has no clear relative in the old state system. It means that the object became grey due
      to ordinary marking. Previously, ordinary marking would make the object Marked.

- Removal of the post-processing phase that &quot;clears&quot; the remembered set by moving all remembered
  objects to the Marked state. This now happens magically during visiting, as described above.

- SlotVisitor now remembers the state that the object did have just before visiting. While visiting
  that object, it's possible to query what the state was. This is used for copy space decisions and
  for extra memory usage accounting. We don't want to put the backing store on the copy worklist,
  and we don't want to count extra memory usage, if the object was OldGrey at the start of
  visiting. Previously, we would be able to just ask if the object was MarkedAndRemembered since
  that state wouldn't get cleared until after all marking finished. This change also simplifies
  some APIs, because there is no need to pass the JSCell* pointer, since these SlotVisitor methods
  no longer ask the cell for its state - instead they use the saved pre-visiting state.

- Removal of a bunch of helpers and abstractions. Previously we had various methods for asking if
  an object was &quot;marked&quot; and if an object was &quot;remembered&quot;. We had helpers for adjusting these
  states, and those helpers would assert that they were being used the right way. This is not very
  useful for concurrent GC, since now the set of possible state transitions is much larger. Also,
  the previous use of the word &quot;marked&quot; was pretty bad - for example in Heap, &quot;marked&quot; refers to
  the primary mark bit (that gets cleared at the flip), while in JSCell, &quot;marked&quot; refers to the
  sticky mark bit (that does not get cleared, ever). This change gets rid of a lot of those helpers
  and inlines their logic. This actually makes the code easier and more fun to read, since you can
  now look at the marking and barrier code and see how that code uses the four CellStates. For
  example, it's fun to see that the barrier gets fired for o.f=v exactly when o is OldBlack and v
  is NewWhite.

This change shouldn't have any effect on performance or GC behavior. It does put our code in a
weird state where we now have states and comments referencing a concurrent GC that doesn't exist
yet.

Finally, some thoughts about the concurrent GC barrier and its implications for performance. This
barrier exhibits very poor guarantees about collector progress, but maximizes throughput by just
reusing the existing barrier code we already emit and optimize. I believe that even our epoch-based
barrier insertion DFG phase is correct for the concurrent interpretation of our existing barrier.
But, the barrier can regress the progress that the collector has made for two reasons:

Incremental update: you don't want to use this barrier with a black stack, since that would mean
that heap loads of white objects will have to explicitly re-grey the stack. The way you implement
this kind of collector is that collector termination will rescan the stack. Termination is reached
only if the at-termination re-scan greys no objects. This means that the collector is a fixpoint.
Luckily, our collector is already a fixpoint because of opaque roots and structure transitions.

Marking ain't monotonic: normally, once an object is black, it stays that way. In this collector,
black objects may become grey again. I don't have personal experience with such concurrent GCs, but
I suspect that this will basically be fine. Concurrent collections finish pretty quickly, and the
mutator usually touches only a subset of the heap. Only that subset of the heap that the mutator is
touching could be re-greyed. Probably, the GC will have to be hybrid incremental and concurrent,
and towards the end of GC when we do the termination stack re-scan, we can ensure that the
collector does some minimal amount of marking. If the minimal amount of marking done by the
collector is large enough, we can ensure that we reach termination before the mutator can regress
progress. The barrier cannot un-terminate the collector; if the collector reaches termination and
the barrier re-greys an object then it's actually doing a generational remembering rather than a
concurrent re-greying.

That's sort of the cute thing about the barrier - it is exactly a re-greying barrier during GC and
it is exactly a remembering barrier in between GCs.

[1] http://www.cs.utexas.edu/ftp/garbage/submit/readable/ppirinen11.ps
[2] http://dl.acm.org/citation.cfm?id=361005
[3] http://www.aicas.com/papers/ISMM132-siebert.pdf

* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::visitChildren):
* ftl/FTLAbstractHeapRepository.cpp:
(JSC::FTL::AbstractHeapRepository::AbstractHeapRepository):
* ftl/FTLAbstractHeapRepository.h:
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::masqueradesAsUndefinedWatchpointIsStillValid):
(JSC::FTL::DFG::LowerDFGToLLVM::loadCellState):
(JSC::FTL::DFG::LowerDFGToLLVM::emitStoreBarrier):
(JSC::FTL::DFG::LowerDFGToLLVM::loadMarkByte): Deleted.
* heap/CellState.h: Added.
* heap/CodeBlockSet.cpp:
(JSC::CodeBlockSet::rememberCurrentlyExecutingCodeBlocks):
* heap/CopiedBlock.h:
* heap/CopiedBlockInlines.h:
(JSC::CopiedBlock::reportLiveBytes):
(JSC::CopiedBlock::shouldReportLiveBytes): Deleted.
* heap/GCLogging.cpp:
(JSC::LoggingFunctor::reviveCells):
* heap/Heap.cpp:
(JSC::Heap::markRoots):
(JSC::Heap::visitWeakHandles):
(JSC::Heap::updateObjectCounts):
(JSC::Heap::addToRememberedSet):
(JSC::Heap::clearRememberedSet): Deleted.
* heap/Heap.h:
* heap/HeapInlines.h:
(JSC::Heap::isLive):
(JSC::Heap::isMarked):
(JSC::Heap::writeBarrier):
(JSC::Heap::reportExtraMemoryAllocated):
(JSC::Heap::reportExtraMemoryVisited):
(JSC::Heap::isRemembered): Deleted.
* heap/SlotVisitor.cpp:
(JSC::SlotVisitor::append):
(JSC::SlotVisitor::visitChildren):
(JSC::SlotVisitor::donateKnownParallel):
(JSC::SlotVisitor::drain):
(JSC::visitChildren): Deleted.
* heap/SlotVisitor.h:
(JSC::SlotVisitor::childCount):
(JSC::SlotVisitor::incrementChildCount):
(JSC::SlotVisitor::dataBeforeVisitingCurrentObject):
* heap/SlotVisitorInlines.h:
(JSC::SlotVisitor::internalAppend):
(JSC::SlotVisitor::copyLater):
(JSC::SlotVisitor::reportExtraMemoryVisited):
(JSC::SlotVisitor::heap):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::jumpIfIsRememberedOrInEden):
* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/JSCell.h:
(JSC::JSCell::cellState):
(JSC::JSCell::setCellState):
(JSC::JSCell::structureIDOffset):
(JSC::JSCell::indexingTypeOffset):
(JSC::JSCell::cellStateOffset):
(JSC::JSCell::setMarked): Deleted.
(JSC::JSCell::setRemembered): Deleted.
(JSC::JSCell::isMarked): Deleted.
(JSC::JSCell::isRemembered): Deleted.
(JSC::JSCell::gcDataOffset): Deleted.
* runtime/JSCellInlines.h:
(JSC::JSCell::JSCell):
* runtime/JSGenericTypedArrayViewInlines.h:
(JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::visitChildren):
* runtime/JSObject.cpp:
(JSC::JSObject::copyBackingStore):
* runtime/JSString.cpp:
(JSC::JSString::visitChildren):
* runtime/StructureIDBlob.h:
(JSC::StructureIDBlob::StructureIDBlob):
(JSC::StructureIDBlob::operator=):
* runtime/WeakMapData.cpp:
(JSC::WeakMapData::visitChildren):
(JSC::WeakMapData::set):
* tests/stress/basic-eden-gc-test.js: Added.
    Hilariously, an earlier version of this patch that didn't have the NewGrey/OldGrey distinction
    would only crash super-big tests that GCd twice but it didn't crash any small focused test. All
    it took to show the need for the NewGrey/OldGrey distinction was this super simple test.

Source/WebCore:

No new tests because no new behavior.

* bindings/scripts/CodeGeneratorJS.pm:
(GenerateImplementation):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositorycpp">trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh">trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCodeBlockSetcpp">trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCopiedBlockh">trunk/Source/JavaScriptCore/heap/CopiedBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCopiedBlockInlinesh">trunk/Source/JavaScriptCore/heap/CopiedBlockInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapGCLoggingcpp">trunk/Source/JavaScriptCore/heap/GCLogging.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapcpp">trunk/Source/JavaScriptCore/heap/Heap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeaph">trunk/Source/JavaScriptCore/heap/Heap.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapInlinesh">trunk/Source/JavaScriptCore/heap/HeapInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSlotVisitorcpp">trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSlotVisitorh">trunk/Source/JavaScriptCore/heap/SlotVisitor.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSlotVisitorInlinesh">trunk/Source/JavaScriptCore/heap/SlotVisitorInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAssemblyHelpersh">trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreterasm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCellh">trunk/Source/JavaScriptCore/runtime/JSCell.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCellInlinesh">trunk/Source/JavaScriptCore/runtime/JSCellInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewInlinesh">trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSObjectcpp">trunk/Source/JavaScriptCore/runtime/JSObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSStringcpp">trunk/Source/JavaScriptCore/runtime/JSString.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructureIDBlobh">trunk/Source/JavaScriptCore/runtime/StructureIDBlob.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeWeakMapDatacpp">trunk/Source/JavaScriptCore/runtime/WeakMapData.cpp</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptsCodeGeneratorJSpm">trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreheapCellStateh">trunk/Source/JavaScriptCore/heap/CellState.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressbasicedengctestjs">trunk/Source/JavaScriptCore/tests/stress/basic-eden-gc-test.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -1,3 +1,221 @@
</span><ins>+2015-10-03  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Allow an object's marking state to track The Three Colors
+        https://bugs.webkit.org/show_bug.cgi?id=149654
+
+        Reviewed by Geoffrey Garen.
+
+        I want to make GC marking concurrent (see https://bugs.webkit.org/show_bug.cgi?id=149432).
+        Concurrent GC require barriers to be executed during certain heap operations. We already have a
+        generational GC. Generational GCs also need barriers, and we already have those. The generational
+        GC barrier that we use is the &quot;sticky mark bit&quot; barrier. Ordinarily, mark bits get reset after a
+        collection. In our collector, there is a secondary mark bit that &quot;sticks&quot; - i.e. it does not get
+        reset. If the sticky mark bit is set in between two collections, then we know that the object is in
+        old space. This is sufficient to determine when to put things into remembered sets. Additionally,
+        the sticky mark bit is actually a tri-state that can also tell us if the object has been placed on
+        a remembered set.
+
+        This is awfully similar to what you want in a concurrent GC. Concurrent GCs typically want writes
+        to the heap that change the object graph to do different things depending on an object's marking
+        state, which is usually referred to as its color. White means that the object has never been seen
+        by the collector. All white objects are presumed dead at the flip. Grey objects are those that are
+        known to the collector but have not been scanned. Black objects are those that have been scanned,
+        and will not be scanned again. White is exactly just &quot;not being marked&quot;, and both grey and black
+        mean &quot;marked&quot; - with &quot;black&quot; meaning &quot;marked but not on any worklist&quot;. That's quite a bit like the
+        current &quot;Marked&quot; and &quot;MarkedAndRemembered&quot; states that we have for generational GC.
+        &quot;MarkedAndRemembered&quot; is a lot like &quot;grey&quot;, and &quot;Marked&quot; is a lot like &quot;black&quot;.
+
+        I want to make a concurrent GC that unifies the generational and concurrent barriers into a single
+        fast path check. Even better if the two barriers are entirely identical. You can do this using
+        Pirinen's technique #2 [1], originally due to Guy Steele [2]: when doing o.f=v where o is black and
+        v is white, turn o grey again. This is like remembering an object, in the sense that our gen GC
+        &quot;rememberes&quot; o when o is old and v is new. It remembers objects by putting them on the mark stack,
+        setting the generational state to MarkedAndRemembered, and doing nothing to the primary mark bit.
+
+        This makes our concurrent GC approach pretty obvious. We want to use one barrier for concurrent and
+        generational, and we want to basically keep our current barriers unchanged. The only things missing
+        are just some small changes to allow the concurrent GC to know precisely when an object is black,
+        and to know during object visiting if we are visiting the object for the first time during a
+        collection or a subsequent time due to barrier re-greying (concurrent GC) or barrier remembering
+        (generational GC). So, this patch does the following:
+
+        - Changes the terminology used for the gcData header byte in JSCell. This changes the name of this
+          to cellState, and introduces a new enumeration called CellState. This new enumeration behaves a
+          lot like the old GCData did. It has the following members, with the following correspondence to
+          the old GCData:
+
+          OldBlack: this is like Marked, with the exception that we ensure that an object becomes OldBlack
+              as soon as the object starts to be scanned. Previously, an object might be
+              MarkedAndRemembered during scanning and we'd turn all MarkedAndRemembered objects into Marked
+              objects during a post-processing step at the end of GC. This patch gets rid of that
+              post-processing. The act of visiting an object unconditionally makes it OldBlack. Note that
+              our definition of &quot;black&quot; is not that the object is done being scanned, but that it is either
+              being scanned right now or it has already been scanned. This is like a combination of
+              Siebert's anthracite and black states [3].
+
+          NewWhite: this is exactly NotMarked. It's the state that objects get when they are allocated.
+              It's impossible for an object to return to this state.
+
+          OldGrey: the object is on the mark stack and will be scanned at some point in the future. This
+              also means that this isn't the first time in this cycle that the object has been grey. In an
+              eden collection, an old object that has been remembered is thought of as being OldGrey, even
+              if this is the first time during this eden collection that it is grey. That's because an eden
+              collection must behave &quot;as if&quot; the grey-&gt;black transition for old objects magically happened
+              at the start of GC. Remembered objects are like old objects that underwent a concurrent
+              barrier re-greying just after the magical old object grey-&gt;black transition at the start of
+              GC. This state is almost exactly like MarkedAndRemembered, except that an object now
+              transitions from OldGrey to OldBlack at the beginning of visiting, rather than how previously
+              we transitioned from MarkedAndRemembered to Marked at the bitter end of GC.
+
+          NewGray: the object is on the mark stack and will be scanned at some point in the future. This
+              state has no clear relative in the old state system. It means that the object became grey due
+              to ordinary marking. Previously, ordinary marking would make the object Marked.
+
+        - Removal of the post-processing phase that &quot;clears&quot; the remembered set by moving all remembered
+          objects to the Marked state. This now happens magically during visiting, as described above.
+
+        - SlotVisitor now remembers the state that the object did have just before visiting. While visiting
+          that object, it's possible to query what the state was. This is used for copy space decisions and
+          for extra memory usage accounting. We don't want to put the backing store on the copy worklist,
+          and we don't want to count extra memory usage, if the object was OldGrey at the start of
+          visiting. Previously, we would be able to just ask if the object was MarkedAndRemembered since
+          that state wouldn't get cleared until after all marking finished. This change also simplifies
+          some APIs, because there is no need to pass the JSCell* pointer, since these SlotVisitor methods
+          no longer ask the cell for its state - instead they use the saved pre-visiting state.
+
+        - Removal of a bunch of helpers and abstractions. Previously we had various methods for asking if
+          an object was &quot;marked&quot; and if an object was &quot;remembered&quot;. We had helpers for adjusting these
+          states, and those helpers would assert that they were being used the right way. This is not very
+          useful for concurrent GC, since now the set of possible state transitions is much larger. Also,
+          the previous use of the word &quot;marked&quot; was pretty bad - for example in Heap, &quot;marked&quot; refers to
+          the primary mark bit (that gets cleared at the flip), while in JSCell, &quot;marked&quot; refers to the
+          sticky mark bit (that does not get cleared, ever). This change gets rid of a lot of those helpers
+          and inlines their logic. This actually makes the code easier and more fun to read, since you can
+          now look at the marking and barrier code and see how that code uses the four CellStates. For
+          example, it's fun to see that the barrier gets fired for o.f=v exactly when o is OldBlack and v
+          is NewWhite.
+
+        This change shouldn't have any effect on performance or GC behavior. It does put our code in a
+        weird state where we now have states and comments referencing a concurrent GC that doesn't exist
+        yet.
+
+        Finally, some thoughts about the concurrent GC barrier and its implications for performance. This
+        barrier exhibits very poor guarantees about collector progress, but maximizes throughput by just
+        reusing the existing barrier code we already emit and optimize. I believe that even our epoch-based
+        barrier insertion DFG phase is correct for the concurrent interpretation of our existing barrier.
+        But, the barrier can regress the progress that the collector has made for two reasons:
+
+        Incremental update: you don't want to use this barrier with a black stack, since that would mean
+        that heap loads of white objects will have to explicitly re-grey the stack. The way you implement
+        this kind of collector is that collector termination will rescan the stack. Termination is reached
+        only if the at-termination re-scan greys no objects. This means that the collector is a fixpoint.
+        Luckily, our collector is already a fixpoint because of opaque roots and structure transitions.
+
+        Marking ain't monotonic: normally, once an object is black, it stays that way. In this collector,
+        black objects may become grey again. I don't have personal experience with such concurrent GCs, but
+        I suspect that this will basically be fine. Concurrent collections finish pretty quickly, and the
+        mutator usually touches only a subset of the heap. Only that subset of the heap that the mutator is
+        touching could be re-greyed. Probably, the GC will have to be hybrid incremental and concurrent,
+        and towards the end of GC when we do the termination stack re-scan, we can ensure that the
+        collector does some minimal amount of marking. If the minimal amount of marking done by the
+        collector is large enough, we can ensure that we reach termination before the mutator can regress
+        progress. The barrier cannot un-terminate the collector; if the collector reaches termination and
+        the barrier re-greys an object then it's actually doing a generational remembering rather than a
+        concurrent re-greying.
+
+        That's sort of the cute thing about the barrier - it is exactly a re-greying barrier during GC and
+        it is exactly a remembering barrier in between GCs.
+
+        [1] http://www.cs.utexas.edu/ftp/garbage/submit/readable/ppirinen11.ps
+        [2] http://dl.acm.org/citation.cfm?id=361005
+        [3] http://www.aicas.com/papers/ISMM132-siebert.pdf
+
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::visitChildren):
+        * ftl/FTLAbstractHeapRepository.cpp:
+        (JSC::FTL::AbstractHeapRepository::AbstractHeapRepository):
+        * ftl/FTLAbstractHeapRepository.h:
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::DFG::LowerDFGToLLVM::masqueradesAsUndefinedWatchpointIsStillValid):
+        (JSC::FTL::DFG::LowerDFGToLLVM::loadCellState):
+        (JSC::FTL::DFG::LowerDFGToLLVM::emitStoreBarrier):
+        (JSC::FTL::DFG::LowerDFGToLLVM::loadMarkByte): Deleted.
+        * heap/CellState.h: Added.
+        * heap/CodeBlockSet.cpp:
+        (JSC::CodeBlockSet::rememberCurrentlyExecutingCodeBlocks):
+        * heap/CopiedBlock.h:
+        * heap/CopiedBlockInlines.h:
+        (JSC::CopiedBlock::reportLiveBytes):
+        (JSC::CopiedBlock::shouldReportLiveBytes): Deleted.
+        * heap/GCLogging.cpp:
+        (JSC::LoggingFunctor::reviveCells):
+        * heap/Heap.cpp:
+        (JSC::Heap::markRoots):
+        (JSC::Heap::visitWeakHandles):
+        (JSC::Heap::updateObjectCounts):
+        (JSC::Heap::addToRememberedSet):
+        (JSC::Heap::clearRememberedSet): Deleted.
+        * heap/Heap.h:
+        * heap/HeapInlines.h:
+        (JSC::Heap::isLive):
+        (JSC::Heap::isMarked):
+        (JSC::Heap::writeBarrier):
+        (JSC::Heap::reportExtraMemoryAllocated):
+        (JSC::Heap::reportExtraMemoryVisited):
+        (JSC::Heap::isRemembered): Deleted.
+        * heap/SlotVisitor.cpp:
+        (JSC::SlotVisitor::append):
+        (JSC::SlotVisitor::visitChildren):
+        (JSC::SlotVisitor::donateKnownParallel):
+        (JSC::SlotVisitor::drain):
+        (JSC::visitChildren): Deleted.
+        * heap/SlotVisitor.h:
+        (JSC::SlotVisitor::childCount):
+        (JSC::SlotVisitor::incrementChildCount):
+        (JSC::SlotVisitor::dataBeforeVisitingCurrentObject):
+        * heap/SlotVisitorInlines.h:
+        (JSC::SlotVisitor::internalAppend):
+        (JSC::SlotVisitor::copyLater):
+        (JSC::SlotVisitor::reportExtraMemoryVisited):
+        (JSC::SlotVisitor::heap):
+        * jit/AssemblyHelpers.h:
+        (JSC::AssemblyHelpers::jumpIfIsRememberedOrInEden):
+        * llint/LowLevelInterpreter.asm:
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * runtime/JSCell.h:
+        (JSC::JSCell::cellState):
+        (JSC::JSCell::setCellState):
+        (JSC::JSCell::structureIDOffset):
+        (JSC::JSCell::indexingTypeOffset):
+        (JSC::JSCell::cellStateOffset):
+        (JSC::JSCell::setMarked): Deleted.
+        (JSC::JSCell::setRemembered): Deleted.
+        (JSC::JSCell::isMarked): Deleted.
+        (JSC::JSCell::isRemembered): Deleted.
+        (JSC::JSCell::gcDataOffset): Deleted.
+        * runtime/JSCellInlines.h:
+        (JSC::JSCell::JSCell):
+        * runtime/JSGenericTypedArrayViewInlines.h:
+        (JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::visitChildren):
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::copyBackingStore):
+        * runtime/JSString.cpp:
+        (JSC::JSString::visitChildren):
+        * runtime/StructureIDBlob.h:
+        (JSC::StructureIDBlob::StructureIDBlob):
+        (JSC::StructureIDBlob::operator=):
+        * runtime/WeakMapData.cpp:
+        (JSC::WeakMapData::visitChildren):
+        (JSC::WeakMapData::set):
+        * tests/stress/basic-eden-gc-test.js: Added.
+            Hilariously, an earlier version of this patch that didn't have the NewGrey/OldGrey distinction
+            would only crash super-big tests that GCd twice but it didn't crash any small focused test. All
+            it took to show the need for the NewGrey/OldGrey distinction was this super simple test.
+
</ins><span class="cx"> 2015-10-05  Geoffrey Garen  &lt;ggaren@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         JSC::SlotVisitor should not be a hot mess
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -1326,6 +1326,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\ftl\FTLValueRange.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\ftl\FTLWeight.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\ftl\FTLWeightedTarget.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\heap\CellState.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\heap\CodeBlockSet.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\heap\ConservativeRoots.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\heap\CopiedAllocator.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -2219,6 +2219,9 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\disassembler\Disassembler.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;disassembler&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\heap\CellState.h&quot;&gt;
+      &lt;Filter&gt;heap&lt;/Filter&gt;
+    &lt;/ClInclude&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\heap\ConservativeRoots.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;heap&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -115,6 +115,7 @@
</span><span class="cx">                 0F18D3D01B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F18D3CE1B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.h */; };
</span><span class="cx">                 0F190CAC189D82F6000AE5F0 /* ProfilerJettisonReason.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F190CAA189D82F6000AE5F0 /* ProfilerJettisonReason.cpp */; };
</span><span class="cx">                 0F190CAD189D82F6000AE5F0 /* ProfilerJettisonReason.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F190CAB189D82F6000AE5F0 /* ProfilerJettisonReason.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F1C3DDA1BBCE09E00E523E4 /* CellState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1C3DD91BBCE09E00E523E4 /* CellState.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F1DD84A18A945BE0026F3FA /* JSCInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1DD84918A945BE0026F3FA /* JSCInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F1E3A461534CBAF000F9456 /* DFGArgumentPosition.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A431534CBAD000F9456 /* DFGArgumentPosition.h */; };
</span><span class="cx">                 0F1E3A471534CBB9000F9456 /* DFGDoubleFormatState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A441534CBAD000F9456 /* DFGDoubleFormatState.h */; };
</span><span class="lines">@@ -1964,6 +1965,7 @@
</span><span class="cx">                 0F18D3CE1B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAdaptiveStructureWatchpoint.h; path = dfg/DFGAdaptiveStructureWatchpoint.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F190CAA189D82F6000AE5F0 /* ProfilerJettisonReason.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerJettisonReason.cpp; path = profiler/ProfilerJettisonReason.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F190CAB189D82F6000AE5F0 /* ProfilerJettisonReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerJettisonReason.h; path = profiler/ProfilerJettisonReason.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F1C3DD91BBCE09E00E523E4 /* CellState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CellState.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F1DD84918A945BE0026F3FA /* JSCInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F1E3A431534CBAD000F9456 /* DFGArgumentPosition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArgumentPosition.h; path = dfg/DFGArgumentPosition.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F1E3A441534CBAD000F9456 /* DFGDoubleFormatState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDoubleFormatState.h; path = dfg/DFGDoubleFormatState.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4226,6 +4228,7 @@
</span><span class="cx">                 142E312A134FF0A600AFADB5 /* heap */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><ins>+                                0F1C3DD91BBCE09E00E523E4 /* CellState.h */,
</ins><span class="cx">                                 0FD8A31117D4326C00CA2C40 /* CodeBlockSet.cpp */,
</span><span class="cx">                                 0FD8A31217D4326C00CA2C40 /* CodeBlockSet.h */,
</span><span class="cx">                                 146B14DB12EB5B12001BEC1B /* ConservativeRoots.cpp */,
</span><span class="lines">@@ -6917,6 +6920,7 @@
</span><span class="cx">                                 14142E511B796ECE00F4BF4B /* UnlinkedFunctionExecutable.h in Headers */,
</span><span class="cx">                                 0F2E892C16D028AD009E4FD2 /* UnusedPointer.h in Headers */,
</span><span class="cx">                                 0F963B3813FC6FE90002D9B2 /* ValueProfile.h in Headers */,
</span><ins>+                                0F1C3DDA1BBCE09E00E523E4 /* CellState.h in Headers */,
</ins><span class="cx">                                 0F426A481460CBB300131F8F /* ValueRecovery.h in Headers */,
</span><span class="cx">                                 79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */,
</span><span class="cx">                                 0F6C73511AC9F99F00BE1682 /* VariableWriteFireDetail.h in Headers */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -2245,15 +2245,15 @@
</span><span class="cx">     if (CodeBlock* otherBlock = specialOSREntryBlockOrNull())
</span><span class="cx">         otherBlock-&gt;visitAggregate(visitor);
</span><span class="cx"> 
</span><del>-    visitor.reportExtraMemoryVisited(ownerExecutable(), sizeof(CodeBlock));
</del><ins>+    visitor.reportExtraMemoryVisited(sizeof(CodeBlock));
</ins><span class="cx">     if (m_jitCode)
</span><del>-        visitor.reportExtraMemoryVisited(ownerExecutable(), m_jitCode-&gt;size());
</del><ins>+        visitor.reportExtraMemoryVisited(m_jitCode-&gt;size());
</ins><span class="cx">     if (m_instructions.size()) {
</span><span class="cx">         // Divide by refCount() because m_instructions points to something that is shared
</span><span class="cx">         // by multiple CodeBlocks, and we only want to count it towards the heap size once.
</span><span class="cx">         // Having each CodeBlock report only its proportional share of the size is one way
</span><span class="cx">         // of accomplishing this.
</span><del>-        visitor.reportExtraMemoryVisited(ownerExecutable(), m_instructions.size() * sizeof(Instruction) / m_instructions.refCount());
</del><ins>+        visitor.reportExtraMemoryVisited(m_instructions.size() * sizeof(Instruction) / m_instructions.refCount());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     visitor.append(&amp;m_unlinkedCode);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositorycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -69,12 +69,12 @@
</span><span class="cx">     RELEASE_ASSERT(!(JSCell_indexingType.offset() &amp; (sizeof(int32_t) - 1)));
</span><span class="cx">     RELEASE_ASSERT(JSCell_indexingType.offset() + 1 == JSCell_typeInfoType.offset());
</span><span class="cx">     RELEASE_ASSERT(JSCell_indexingType.offset() + 2 == JSCell_typeInfoFlags.offset());
</span><del>-    RELEASE_ASSERT(JSCell_indexingType.offset() + 3 == JSCell_gcData.offset());
</del><ins>+    RELEASE_ASSERT(JSCell_indexingType.offset() + 3 == JSCell_cellState.offset());
</ins><span class="cx"> 
</span><span class="cx">     JSCell_indexingType.changeParent(&amp;JSCell_usefulBytes);
</span><span class="cx">     JSCell_typeInfoType.changeParent(&amp;JSCell_usefulBytes);
</span><span class="cx">     JSCell_typeInfoFlags.changeParent(&amp;JSCell_usefulBytes);
</span><del>-    JSCell_gcData.changeParent(&amp;JSCell_usefulBytes);
</del><ins>+    JSCell_cellState.changeParent(&amp;JSCell_usefulBytes);
</ins><span class="cx">     
</span><span class="cx">     root.m_tbaaMetadata = mdNode(m_context, mdString(m_context, root.m_heapName));
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -52,12 +52,12 @@
</span><span class="cx">     macro(JSArrayBufferView_length, JSArrayBufferView::offsetOfLength()) \
</span><span class="cx">     macro(JSArrayBufferView_mode, JSArrayBufferView::offsetOfMode()) \
</span><span class="cx">     macro(JSArrayBufferView_vector, JSArrayBufferView::offsetOfVector()) \
</span><ins>+    macro(JSCell_cellState, JSCell::cellStateOffset()) \
+    macro(JSCell_indexingType, JSCell::indexingTypeOffset()) \
</ins><span class="cx">     macro(JSCell_structureID, JSCell::structureIDOffset()) \
</span><del>-    macro(JSCell_usefulBytes, JSCell::indexingTypeOffset()) \
</del><span class="cx">     macro(JSCell_typeInfoFlags, JSCell::typeInfoFlagsOffset()) \
</span><span class="cx">     macro(JSCell_typeInfoType, JSCell::typeInfoTypeOffset()) \
</span><del>-    macro(JSCell_indexingType, JSCell::indexingTypeOffset()) \
-    macro(JSCell_gcData, JSCell::gcDataOffset()) \
</del><ins>+    macro(JSCell_usefulBytes, JSCell::indexingTypeOffset()) \
</ins><span class="cx">     macro(JSFunction_executable, JSFunction::offsetOfExecutable()) \
</span><span class="cx">     macro(JSFunction_scope, JSFunction::offsetOfScopeChain()) \
</span><span class="cx">     macro(JSFunction_rareData, JSFunction::offsetOfRareData()) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -8260,9 +8260,9 @@
</span><span class="cx">         return m_graph.masqueradesAsUndefinedWatchpointIsStillValid(m_node-&gt;origin.semantic);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    LValue loadMarkByte(LValue base)
</del><ins>+    LValue loadCellState(LValue base)
</ins><span class="cx">     {
</span><del>-        return m_out.load8(base, m_heaps.JSCell_gcData);
</del><ins>+        return m_out.load8(base, m_heaps.JSCell_cellState);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void emitStoreBarrier(LValue base)
</span><span class="lines">@@ -8274,7 +8274,7 @@
</span><span class="cx"> 
</span><span class="cx">         // Check the mark byte. 
</span><span class="cx">         m_out.branch(
</span><del>-            m_out.notZero8(loadMarkByte(base)), usually(continuation), rarely(isMarkedAndNotRemembered));
</del><ins>+            m_out.notZero8(loadCellState(base)), usually(continuation), rarely(isMarkedAndNotRemembered));
</ins><span class="cx"> 
</span><span class="cx">         // Append to the write barrier buffer.
</span><span class="cx">         LBasicBlock lastNext = m_out.appendTo(isMarkedAndNotRemembered, bufferHasSpace);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCellStateh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/CellState.h (0 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CellState.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/heap/CellState.h        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -0,0 +1,60 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CellState_h
+#define CellState_h
+
+namespace JSC {
+
+enum class CellState : uint8_t {
+    // The object is black as far as this GC is concerned. When not in GC, this just means that it's an
+    // old gen object. Note that we deliberately arrange OldBlack to be zero, so that the store barrier on
+    // a target object &quot;from&quot; is just:
+    //
+    // if (!from-&gt;cellState())
+    //     slowPath(from);
+    //
+    // There is a bunch of code in the LLInt and JITs that rely on this being the case. You'd have to
+    // change a lot of code if you ever wanted the store barrier to be anything but a non-zero check on
+    // cellState.
+    OldBlack = 0,
+    
+    // The object is in eden. During GC, this means that the object has not been marked yet.
+    NewWhite = 1,
+
+    // The object is grey - i.e. it will be scanned - but it either belongs to old gen (if this is eden
+    // GC) or it is grey a second time in this current GC (because a concurrent store barrier requested
+    // re-greying).
+    OldGrey = 2,
+
+    // The object is grey - i.e. it will be scanned - and this is the first time in this GC that we are
+    // going to scan it. If this is an eden GC, this also means that the object is in eden.
+    NewGrey = 3
+};
+
+} // namespace JSC
+
+#endif // CellState_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCodeBlockSetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -151,7 +151,7 @@
</span><span class="cx">     if (verbose)
</span><span class="cx">         dataLog(&quot;Remembering &quot;, m_currentlyExecuting.size(), &quot; code blocks.\n&quot;);
</span><span class="cx">     for (const RefPtr&lt;CodeBlock&gt;&amp; codeBlock : m_currentlyExecuting)
</span><del>-        heap-&gt;addToRememberedSet(codeBlock-&gt;ownerExecutable());
</del><ins>+        heap-&gt;writeBarrier(codeBlock-&gt;ownerExecutable());
</ins><span class="cx"> 
</span><span class="cx">     // It's safe to clear these RefPtr sets because we won't delete the CodeBlocks
</span><span class="cx">     // in them until the next GC, and we'll recompute them at that time.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCopiedBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CopiedBlock.h (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CopiedBlock.h        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/heap/CopiedBlock.h        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -54,7 +54,6 @@
</span><span class="cx">     void didPromote();
</span><span class="cx"> 
</span><span class="cx">     unsigned liveBytes();
</span><del>-    bool shouldReportLiveBytes(LockHolder&amp;, JSCell* owner);
</del><span class="cx">     void reportLiveBytes(LockHolder&amp;, JSCell*, CopyToken, unsigned);
</span><span class="cx">     void reportLiveBytesDuringCopying(unsigned);
</span><span class="cx">     void didSurviveGC();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCopiedBlockInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CopiedBlockInlines.h (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CopiedBlockInlines.h        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/heap/CopiedBlockInlines.h        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 2013, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -33,16 +33,6 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx">     
</span><del>-inline bool CopiedBlock::shouldReportLiveBytes(LockHolder&amp;, JSCell* owner)
-{
-    // We want to add to live bytes if the owner isn't part of the remembered set or
-    // if this block was allocated during the last cycle. 
-    // If we always added live bytes we would double count for elements in the remembered
-    // set across collections. 
-    // If we didn't always add live bytes to new blocks, we'd get too few.
-    return !Heap::isRemembered(owner) || !m_isOld;
-}
-
</del><span class="cx"> inline void CopiedBlock::reportLiveBytes(LockHolder&amp;, JSCell* owner, CopyToken token, unsigned bytes)
</span><span class="cx"> {
</span><span class="cx">     checkConsistency();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapGCLoggingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/GCLogging.cpp (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/GCLogging.cpp        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/heap/GCLogging.cpp        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -91,7 +91,7 @@
</span><span class="cx"> 
</span><span class="cx">         for (const JSCell* cell : m_savedMarkStack) {
</span><span class="cx">             m_slotVisitor.markStack().append(cell);
</span><del>-            const_cast&lt;JSCell*&gt;(cell)-&gt;setRemembered(true);
</del><ins>+            cell-&gt;setCellState(CellState::OldGrey);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -596,7 +596,6 @@
</span><span class="cx">     // the liveness of the rest of the object graph.
</span><span class="cx">     visitWeakHandles(heapRootVisitor);
</span><span class="cx"> 
</span><del>-    clearRememberedSet(rememberedSet);
</del><span class="cx">     {
</span><span class="cx">         std::lock_guard&lt;Lock&gt; lock(m_markingMutex);
</span><span class="cx">         m_parallelMarkersShouldExit = true;
</span><span class="lines">@@ -852,13 +851,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::clearRememberedSet(Vector&lt;const JSCell*&gt;&amp; rememberedSet)
-{
-    GCPHASE(ClearRememberedSet);
-    for (auto* cell : rememberedSet)
-        const_cast&lt;JSCell*&gt;(cell)-&gt;setRemembered(false);
-}
-
</del><span class="cx"> void Heap::updateObjectCounts(double gcStartTime)
</span><span class="cx"> {
</span><span class="cx">     GCCOUNTER(VisitedValueCount, m_slotVisitor.visitCount());
</span><span class="lines">@@ -1008,9 +1000,13 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(cell);
</span><span class="cx">     ASSERT(!Options::enableConcurrentJIT() || !isCompilationThread());
</span><del>-    if (isRemembered(cell))
-        return;
-    const_cast&lt;JSCell*&gt;(cell)-&gt;setRemembered(true);
</del><ins>+    ASSERT(cell-&gt;cellState() == CellState::OldBlack);
+    // Indicate that this object is grey and that it's one of the following:
+    // - A re-greyed object during a concurrent collection.
+    // - An old remembered object.
+    // &quot;OldGrey&quot; doesn't tell us which of these things is true, but we usually treat the two cases the
+    // same.
+    cell-&gt;setCellState(CellState::OldGrey);
</ins><span class="cx">     m_slotVisitor.appendToMarkStack(const_cast&lt;JSCell*&gt;(cell));
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.h (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.h        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/heap/Heap.h        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -101,9 +101,7 @@
</span><span class="cx">     static bool isMarked(const void*);
</span><span class="cx">     static bool testAndSetMarked(const void*);
</span><span class="cx">     static void setMarked(const void*);
</span><del>-    static bool isRemembered(const void*);
</del><span class="cx"> 
</span><del>-    JS_EXPORT_PRIVATE void addToRememberedSet(const JSCell*);
</del><span class="cx">     static bool isWriteBarrierEnabled();
</span><span class="cx">     void writeBarrier(const JSCell*);
</span><span class="cx">     void writeBarrier(const JSCell*, JSValue);
</span><span class="lines">@@ -167,7 +165,7 @@
</span><span class="cx">     // call both of these functions: Calling only one may trigger catastropic
</span><span class="cx">     // memory growth.
</span><span class="cx">     void reportExtraMemoryAllocated(size_t);
</span><del>-    void reportExtraMemoryVisited(JSCell*, size_t);
</del><ins>+    void reportExtraMemoryVisited(CellState cellStateBeforeVisiting, size_t);
</ins><span class="cx"> 
</span><span class="cx">     // Use this API to report non-GC memory if you can't use the better API above.
</span><span class="cx">     void deprecatedReportExtraMemory(size_t);
</span><span class="lines">@@ -306,7 +304,6 @@
</span><span class="cx">     void traceCodeBlocksAndJITStubRoutines();
</span><span class="cx">     void converge();
</span><span class="cx">     void visitWeakHandles(HeapRootVisitor&amp;);
</span><del>-    void clearRememberedSet(Vector&lt;const JSCell*&gt;&amp;);
</del><span class="cx">     void updateObjectCounts(double gcStartTime);
</span><span class="cx">     void resetVisitors();
</span><span class="cx"> 
</span><span class="lines">@@ -323,6 +320,7 @@
</span><span class="cx">     void finalizeUnconditionalFinalizers();
</span><span class="cx">     void clearUnmarkedExecutables();
</span><span class="cx">     void deleteUnmarkedCompiledCode();
</span><ins>+    JS_EXPORT_PRIVATE void addToRememberedSet(const JSCell*);
</ins><span class="cx">     void updateAllocationLimits();
</span><span class="cx">     void didFinishCollection(double gcStartTime);
</span><span class="cx">     void resumeCompilerThreads();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/HeapInlines.h (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapInlines.h        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/heap/HeapInlines.h        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -70,14 +70,6 @@
</span><span class="cx">     return MarkedBlock::blockFor(cell)-&gt;isLiveCell(cell);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline bool Heap::isRemembered(const void* ptr)
-{
-    const JSCell* cell = static_cast&lt;const JSCell*&gt;(ptr);
-    ASSERT(cell);
-    ASSERT(!Options::enableConcurrentJIT() || !isCompilationThread());
-    return cell-&gt;isRemembered();
-}
-
</del><span class="cx"> inline bool Heap::isMarked(const void* cell)
</span><span class="cx"> {
</span><span class="cx">     return MarkedBlock::blockFor(cell)-&gt;isMarked(cell);
</span><span class="lines">@@ -113,25 +105,18 @@
</span><span class="cx"> #if ENABLE(WRITE_BARRIER_PROFILING)
</span><span class="cx">     WriteBarrierCounters::countWriteBarrier();
</span><span class="cx"> #endif
</span><del>-    if (!from || !from-&gt;isMarked()) {
-        ASSERT(!from || !isMarked(from));
</del><ins>+    if (!from || from-&gt;cellState() != CellState::OldBlack)
</ins><span class="cx">         return;
</span><del>-    }
-    if (!to || to-&gt;isMarked()) {
-        ASSERT(!to || isMarked(to));
</del><ins>+    if (!to || to-&gt;cellState() != CellState::NewWhite)
</ins><span class="cx">         return;
</span><del>-    }
</del><span class="cx">     addToRememberedSet(from);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline void Heap::writeBarrier(const JSCell* from)
</span><span class="cx"> {
</span><span class="cx">     ASSERT_GC_OBJECT_LOOKS_VALID(const_cast&lt;JSCell*&gt;(from));
</span><del>-    if (!from || !from-&gt;isMarked()) {
-        ASSERT(!from || !isMarked(from));
</del><ins>+    if (!from || from-&gt;cellState() != CellState::OldBlack)
</ins><span class="cx">         return;
</span><del>-    }
-    ASSERT(isMarked(from));
</del><span class="cx">     addToRememberedSet(from);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -141,10 +126,10 @@
</span><span class="cx">         reportExtraMemoryAllocatedSlowCase(size);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void Heap::reportExtraMemoryVisited(JSCell* owner, size_t size)
</del><ins>+inline void Heap::reportExtraMemoryVisited(CellState dataBeforeVisiting, size_t size)
</ins><span class="cx"> {
</span><span class="cx">     // We don't want to double-count the extra memory that was reported in previous collections.
</span><del>-    if (operationInProgress() == EdenCollection &amp;&amp; Heap::isRemembered(owner))
</del><ins>+    if (operationInProgress() == EdenCollection &amp;&amp; dataBeforeVisiting == CellState::OldGrey)
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     size_t* counter = &amp;m_extraMemorySize;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -139,7 +139,11 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    cell-&gt;setMarked();
</del><ins>+    // Indicate that the object is grey and that:
+    // In case of concurrent GC: it's the first time it is grey in this GC cycle.
+    // In case of eden collection: it's a new object that became grey rather than an old remembered object.
+    cell-&gt;setCellState(CellState::NewGrey);
+
</ins><span class="cx">     appendToMarkStack(cell);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -153,26 +157,29 @@
</span><span class="cx">     m_stack.append(cell);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE static void visitChildren(SlotVisitor&amp; visitor, const JSCell* cell)
</del><ins>+ALWAYS_INLINE void SlotVisitor::visitChildren(const JSCell* cell)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(Heap::isMarked(cell));
</span><ins>+
+    m_currentObjectCellStateBeforeVisiting = cell-&gt;cellState();
+    cell-&gt;setCellState(CellState::OldBlack);
</ins><span class="cx">     
</span><span class="cx">     if (isJSString(cell)) {
</span><del>-        JSString::visitChildren(const_cast&lt;JSCell*&gt;(cell), visitor);
</del><ins>+        JSString::visitChildren(const_cast&lt;JSCell*&gt;(cell), *this);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (isJSFinalObject(cell)) {
</span><del>-        JSFinalObject::visitChildren(const_cast&lt;JSCell*&gt;(cell), visitor);
</del><ins>+        JSFinalObject::visitChildren(const_cast&lt;JSCell*&gt;(cell), *this);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (isJSArray(cell)) {
</span><del>-        JSArray::visitChildren(const_cast&lt;JSCell*&gt;(cell), visitor);
</del><ins>+        JSArray::visitChildren(const_cast&lt;JSCell*&gt;(cell), *this);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    cell-&gt;methodTable()-&gt;visitChildren(const_cast&lt;JSCell*&gt;(cell), visitor);
</del><ins>+    cell-&gt;methodTable()-&gt;visitChildren(const_cast&lt;JSCell*&gt;(cell), *this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SlotVisitor::donateKnownParallel()
</span><span class="lines">@@ -208,7 +215,7 @@
</span><span class="cx">     while (!m_stack.isEmpty()) {
</span><span class="cx">         m_stack.refill();
</span><span class="cx">         for (unsigned countdown = Options::minimumNumberOfScansBetweenRebalance(); m_stack.canRemoveLast() &amp;&amp; countdown--;)
</span><del>-            visitChildren(*this, m_stack.removeLast());
</del><ins>+            visitChildren(m_stack.removeLast());
</ins><span class="cx">         donateKnownParallel();
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -364,7 +371,14 @@
</span><span class="cx">     ASSERT(heap()-&gt;m_storageSpace.contains(block));
</span><span class="cx"> 
</span><span class="cx">     LockHolder locker(&amp;block-&gt;workListLock());
</span><del>-    if (heap()-&gt;operationInProgress() == FullCollection || block-&gt;shouldReportLiveBytes(locker, owner)) {
</del><ins>+    // We always report live bytes, except if during an eden collection we see an old object pointing to an
+    // old backing store and the old object is being marked because of the remembered set. Note that if we
+    // ask the object itself, it will always tell us that it's an old black object - because even during an
+    // eden collection we have already indicated that the object is old. That's why we use the
+    // SlotVisitor's cache of the object's old state.
+    if (heap()-&gt;operationInProgress() == FullCollection
+        || !block-&gt;isOld()
+        || m_currentObjectCellStateBeforeVisiting != CellState::OldGrey) {
</ins><span class="cx">         m_bytesCopied += bytes;
</span><span class="cx">         block-&gt;reportLiveBytes(locker, owner, token, bytes);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitor.h (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitor.h        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitor.h        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011, 2012, 2013, 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011-2013, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #ifndef SlotVisitor_h
</span><span class="cx"> #define SlotVisitor_h
</span><span class="cx"> 
</span><ins>+#include &quot;CellState.h&quot;
</ins><span class="cx"> #include &quot;CopyToken.h&quot;
</span><span class="cx"> #include &quot;HandleTypes.h&quot;
</span><span class="cx"> #include &quot;MarkStack.h&quot;
</span><span class="lines">@@ -103,7 +104,7 @@
</span><span class="cx"> 
</span><span class="cx">     void copyLater(JSCell*, CopyToken, void*, size_t);
</span><span class="cx">     
</span><del>-    void reportExtraMemoryVisited(JSCell* owner, size_t);
</del><ins>+    void reportExtraMemoryVisited(size_t);
</ins><span class="cx">     
</span><span class="cx">     void addWeakReferenceHarvester(WeakReferenceHarvester*);
</span><span class="cx">     void addUnconditionalFinalizer(UnconditionalFinalizer*);
</span><span class="lines">@@ -121,6 +122,8 @@
</span><span class="cx">     JS_EXPORT_PRIVATE void mergeOpaqueRoots();
</span><span class="cx">     void mergeOpaqueRootsIfNecessary();
</span><span class="cx">     void mergeOpaqueRootsIfProfitable();
</span><ins>+
+    void visitChildren(const JSCell*);
</ins><span class="cx">     
</span><span class="cx">     void donateKnownParallel();
</span><span class="cx"> 
</span><span class="lines">@@ -134,6 +137,8 @@
</span><span class="cx">     
</span><span class="cx">     Heap&amp; m_heap;
</span><span class="cx"> 
</span><ins>+    CellState m_currentObjectCellStateBeforeVisiting { CellState::NewWhite };
+
</ins><span class="cx"> public:
</span><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx">     bool m_isCheckingForDefaultMarkViolation;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitorInlines.h (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitorInlines.h        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitorInlines.h        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -92,9 +92,9 @@
</span><span class="cx">     m_heap.m_unconditionalFinalizers.addThreadSafe(unconditionalFinalizer);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void SlotVisitor::reportExtraMemoryVisited(JSCell* owner, size_t size)
</del><ins>+inline void SlotVisitor::reportExtraMemoryVisited(size_t size)
</ins><span class="cx"> {
</span><del>-    heap()-&gt;reportExtraMemoryVisited(owner, size);
</del><ins>+    heap()-&gt;reportExtraMemoryVisited(m_currentObjectCellStateBeforeVisiting, size);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline Heap* SlotVisitor::heap() const
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -1165,12 +1165,12 @@
</span><span class="cx"> 
</span><span class="cx">     Jump jumpIfIsRememberedOrInEden(GPRReg cell)
</span><span class="cx">     {
</span><del>-        return branchTest8(MacroAssembler::NonZero, MacroAssembler::Address(cell, JSCell::gcDataOffset()));
</del><ins>+        return branchTest8(MacroAssembler::NonZero, MacroAssembler::Address(cell, JSCell::cellStateOffset()));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     Jump jumpIfIsRememberedOrInEden(JSCell* cell)
</span><span class="cx">     {
</span><del>-        uint8_t* address = reinterpret_cast&lt;uint8_t*&gt;(cell) + JSCell::gcDataOffset();
</del><ins>+        uint8_t* address = reinterpret_cast&lt;uint8_t*&gt;(cell) + JSCell::cellStateOffset();
</ins><span class="cx">         return branchTest8(MacroAssembler::NonZero, MacroAssembler::AbsoluteAddress(address));
</span><span class="cx">     }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -799,7 +799,7 @@
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> macro skipIfIsRememberedOrInEden(cell, scratch1, scratch2, continuation)
</span><del>-    loadb JSCell::m_gcData[cell], scratch1
</del><ins>+    loadb JSCell::m_cellState[cell], scratch1
</ins><span class="cx">     continuation(scratch1)
</span><span class="cx"> end
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -497,8 +497,8 @@
</span><span class="cx">     loadisFromInstruction(cellOperand, t1)
</span><span class="cx">     loadConstantOrVariablePayload(t1, CellTag, t2, .writeBarrierDone)
</span><span class="cx">     skipIfIsRememberedOrInEden(t2, t1, t3, 
</span><del>-        macro(gcData)
-            btbnz gcData, .writeBarrierDone
</del><ins>+        macro(cellState)
+            btbnz cellState, .writeBarrierDone
</ins><span class="cx">             push cfr, PC
</span><span class="cx">             # We make two extra slots because cCall2 will poke.
</span><span class="cx">             subp 8, sp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -401,8 +401,8 @@
</span><span class="cx">     loadisFromInstruction(cellOperand, t1)
</span><span class="cx">     loadConstantOrVariableCell(t1, t2, .writeBarrierDone)
</span><span class="cx">     skipIfIsRememberedOrInEden(t2, t1, t3, 
</span><del>-        macro(gcData)
-            btbnz gcData, .writeBarrierDone
</del><ins>+        macro(cellState)
+            btbnz cellState, .writeBarrierDone
</ins><span class="cx">             push PB, PC
</span><span class="cx">             move t2, a1 # t2 can be a0 (not on 64 bits, but better safe than sorry)
</span><span class="cx">             move cfr, a0
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCellh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCell.h (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCell.h        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/runtime/JSCell.h        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
</span><span class="cx">  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
</span><del>- *  Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Library General Public
</span><span class="lines">@@ -24,6 +24,7 @@
</span><span class="cx"> #define JSCell_h
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CallData.h&quot;
</span><ins>+#include &quot;CellState.h&quot;
</ins><span class="cx"> #include &quot;ConstructData.h&quot;
</span><span class="cx"> #include &quot;EnumerationMode.h&quot;
</span><span class="cx"> #include &quot;Heap.h&quot;
</span><span class="lines">@@ -154,37 +155,13 @@
</span><span class="cx">     static bool canUseFastGetOwnProperty(const Structure&amp;);
</span><span class="cx">     JSValue fastGetOwnProperty(VM&amp;, Structure&amp;, PropertyName);
</span><span class="cx"> 
</span><del>-    enum GCData : uint8_t {
-        Marked = 0, // The object has survived a GC and is in the old gen.
-        NotMarked = 1, // The object is new and in the eden gen.
-        MarkedAndRemembered = 2, // The object is in the GC's remembered set.
</del><ins>+    // The recommended idiom for using cellState() is to switch on it or perform an == comparison on it
+    // directly. We deliberately avoid helpers for this, because we want transparency about how the various
+    // CellState values influences our various algorithms. 
+    CellState cellState() const { return m_cellState; }
+    
+    void setCellState(CellState data) const { const_cast&lt;JSCell*&gt;(this)-&gt;m_cellState = data; }
</ins><span class="cx"> 
</span><del>-        // The object being in the GC's remembered set implies that it is also
-        // Marked. This is because objects are only added to the remembered sets
-        // by write barriers, and write barriers are only interested in old gen
-        // objects that point to potential eden gen objects.
-    };
-
-    void setMarked() { m_gcData = Marked; }
-    void setRemembered(bool remembered)
-    {
-        ASSERT(m_gcData == (remembered ? Marked : MarkedAndRemembered));
-        m_gcData = remembered ? MarkedAndRemembered : Marked; 
-    }
-    bool isMarked() const
-    {
-        switch (m_gcData) {
-        case Marked:
-        case MarkedAndRemembered:
-            return true;
-        case NotMarked:
-            return false;
-        }
-        RELEASE_ASSERT_NOT_REACHED();
-        return false;
-    }
-    bool isRemembered() const { return m_gcData == MarkedAndRemembered; }
-
</del><span class="cx">     static ptrdiff_t structureIDOffset()
</span><span class="cx">     {
</span><span class="cx">         return OBJECT_OFFSETOF(JSCell, m_structureID);
</span><span class="lines">@@ -205,9 +182,9 @@
</span><span class="cx">         return OBJECT_OFFSETOF(JSCell, m_indexingType);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    static ptrdiff_t gcDataOffset()
</del><ins>+    static ptrdiff_t cellStateOffset()
</ins><span class="cx">     {
</span><del>-        return OBJECT_OFFSETOF(JSCell, m_gcData);
</del><ins>+        return OBJECT_OFFSETOF(JSCell, m_cellState);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     static const TypedArrayType TypedArrayStorageType = NotTypedArray;
</span><span class="lines">@@ -241,7 +218,7 @@
</span><span class="cx">     IndexingType m_indexingType;
</span><span class="cx">     JSType m_type;
</span><span class="cx">     TypeInfo::InlineTypeFlags m_flags;
</span><del>-    uint8_t m_gcData;
</del><ins>+    CellState m_cellState;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename To, typename From&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCellInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCellInlines.h (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCellInlines.h        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/runtime/JSCellInlines.h        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 2013, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -41,7 +41,7 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> inline JSCell::JSCell(CreatingEarlyCellTag)
</span><del>-    : m_gcData(NotMarked)
</del><ins>+    : m_cellState(CellState::NewWhite)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!isCompilationThread());
</span><span class="cx"> }
</span><span class="lines">@@ -51,7 +51,7 @@
</span><span class="cx">     , m_indexingType(structure-&gt;indexingType())
</span><span class="cx">     , m_type(structure-&gt;typeInfo().type())
</span><span class="cx">     , m_flags(structure-&gt;typeInfo().inlineTypeFlags())
</span><del>-    , m_gcData(NotMarked)
</del><ins>+    , m_cellState(CellState::NewWhite)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!isCompilationThread());
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -446,7 +446,7 @@
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="cx">     case OversizeTypedArray: {
</span><del>-        visitor.reportExtraMemoryVisited(thisObject, thisObject-&gt;byteSize());
</del><ins>+        visitor.reportExtraMemoryVisited(thisObject-&gt;byteSize());
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSObject.cpp (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSObject.cpp        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/runtime/JSObject.cpp        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -219,7 +219,7 @@
</span><span class="cx"> {
</span><span class="cx">     JSObject* thisObject = jsCast&lt;JSObject*&gt;(cell);
</span><span class="cx">     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
</span><del>-    
</del><ins>+
</ins><span class="cx">     if (token != ButterflyCopyToken)
</span><span class="cx">         return;
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSStringcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSString.cpp (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSString.cpp        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/runtime/JSString.cpp        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
</span><span class="cx">  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
</span><del>- *  Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2004, 2007, 2008, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Library General Public
</span><span class="lines">@@ -77,7 +77,7 @@
</span><span class="cx">     else {
</span><span class="cx">         StringImpl* impl = thisObject-&gt;m_value.impl();
</span><span class="cx">         ASSERT(impl);
</span><del>-        visitor.reportExtraMemoryVisited(thisObject, impl-&gt;costDuringGC());
</del><ins>+        visitor.reportExtraMemoryVisited(impl-&gt;costDuringGC());
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructureIDBlobh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StructureIDBlob.h (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StructureIDBlob.h        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/runtime/StructureIDBlob.h        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #ifndef StructureIDBlob_h
</span><span class="cx"> #define StructureIDBlob_h
</span><span class="cx"> 
</span><ins>+#include &quot;CellState.h&quot;
</ins><span class="cx"> #include &quot;IndexingType.h&quot;
</span><span class="cx"> #include &quot;JSTypeInfo.h&quot;
</span><span class="cx"> #include &quot;StructureIDTable.h&quot;
</span><span class="lines">@@ -46,7 +47,7 @@
</span><span class="cx">         u.fields.indexingType = indexingType;
</span><span class="cx">         u.fields.type = typeInfo.type();
</span><span class="cx">         u.fields.inlineTypeFlags = typeInfo.inlineTypeFlags();
</span><del>-        u.fields.defaultGCData = JSCell::NotMarked;
</del><ins>+        u.fields.defaultCellState = CellState::NewWhite;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void operator=(const StructureIDBlob&amp; other) { u.doubleWord = other.u.doubleWord; }
</span><span class="lines">@@ -79,7 +80,7 @@
</span><span class="cx">             IndexingType indexingType;
</span><span class="cx">             JSType type;
</span><span class="cx">             TypeInfo::InlineTypeFlags inlineTypeFlags;
</span><del>-            JSCell::GCData defaultGCData;
</del><ins>+            CellState defaultCellState;
</ins><span class="cx">         } fields;
</span><span class="cx">         struct {
</span><span class="cx">             int32_t word1;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeWeakMapDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/WeakMapData.cpp (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/WeakMapData.cpp        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/JavaScriptCore/runtime/WeakMapData.cpp        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -64,7 +64,7 @@
</span><span class="cx">     // Rough approximation of the external storage needed for the hashtable.
</span><span class="cx">     // This isn't exact, but it is close enough, and proportional to the actual
</span><span class="cx">     // external mermory usage.
</span><del>-    visitor.reportExtraMemoryVisited(thisObj, thisObj-&gt;m_map.capacity() * (sizeof(JSObject*) + sizeof(WriteBarrier&lt;Unknown&gt;)));
</del><ins>+    visitor.reportExtraMemoryVisited(thisObj-&gt;m_map.capacity() * (sizeof(JSObject*) + sizeof(WriteBarrier&lt;Unknown&gt;)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WeakMapData::set(VM&amp; vm, JSObject* key, JSValue value)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressbasicedengctestjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/basic-eden-gc-test.js (0 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/basic-eden-gc-test.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/basic-eden-gc-test.js        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+var o = {f:42};
+edenGC();
+var p = {f:42};
+edenGC();
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/WebCore/ChangeLog        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2015-10-03  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Allow an object's marking state to track The Three Colors
+        https://bugs.webkit.org/show_bug.cgi?id=149654
+
+        Reviewed by Geoffrey Garen.
+
+        No new tests because no new behavior.
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateImplementation):
+
</ins><span class="cx"> 2015-10-05  Katlyn Graff  &lt;kgraff@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Update setImageSmoothingQuality for additional reviews.
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptsCodeGeneratorJSpm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (190568 => 190569)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm        2015-10-05 18:49:54 UTC (rev 190568)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm        2015-10-05 19:35:32 UTC (rev 190569)
</span><span class="lines">@@ -2989,7 +2989,7 @@
</span><span class="cx">         }
</span><span class="cx">         push(@implContent, &quot;    thisObject-&gt;visitAdditionalChildren(visitor);\n&quot;) if $interface-&gt;extendedAttributes-&gt;{&quot;JSCustomMarkFunction&quot;};
</span><span class="cx">         if ($interface-&gt;extendedAttributes-&gt;{&quot;ReportExtraMemoryCost&quot;}) {
</span><del>-            push(@implContent, &quot;    visitor.reportExtraMemoryVisited(cell, thisObject-&gt;impl().memoryCost());\n&quot;);
</del><ins>+            push(@implContent, &quot;    visitor.reportExtraMemoryVisited(thisObject-&gt;impl().memoryCost());\n&quot;);
</ins><span class="cx">         }
</span><span class="cx">         if ($numCachedAttributes &gt; 0) {
</span><span class="cx">             foreach (@{$interface-&gt;attributes}) {
</span></span></pre>
</div>
</div>

</body>
</html>