<!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>[209691] 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/209691">209691</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-12-11 17:19:47 -0800 (Sun, 11 Dec 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>MarkedBlock::marksConveyLivenessDuringMarking should take into account collection scope
https://bugs.webkit.org/show_bug.cgi?id=165741

Reviewed by Saam Barati.
        
Source/JavaScriptCore:

MarkedBlock::marksConveyLivenessDuringMarking thought that the off-by-one marking
version indicated liveness during any collection when it's just during full collection.
One of its users - MarkedBlock::sweep - knew this and had a special case, but the other
one - MarkedBlock::isLive - didn't. So, I moved the special case into
marksConveyLivenessDuringMarking.
        
Also, this cleans up some remaining bitvector races.
        
To find this bug, I significantly strengthened our assertions.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* heap/CellContainer.cpp: Added.
(JSC::CellContainer::isNewlyAllocated):
* heap/CellContainer.h:
* heap/MarkedAllocator.cpp:
(JSC::MarkedAllocator::addBlock):
(JSC::MarkedAllocator::removeBlock):
(JSC::MarkedAllocator::dumpBits):
* heap/MarkedAllocator.h:
(JSC::MarkedAllocator::forEachBitVector):
(JSC::MarkedAllocator::forEachBitVectorWithName):
* heap/MarkedBlock.cpp:
(JSC::MarkedBlock::tryCreate):
(JSC::MarkedBlock::Handle::~Handle):
(JSC::MarkedBlock::MarkedBlock):
(JSC::MarkedBlock::Handle::specializedSweep):
(JSC::MarkedBlock::Handle::sweepHelperSelectMarksMode):
(JSC::MarkedBlock::Handle::stopAllocating):
(JSC::MarkedBlock::Handle::resumeAllocating):
(JSC::MarkedBlock::aboutToMarkSlow):
(JSC::MarkedBlock::Handle::didConsumeFreeList):
(JSC::MarkedBlock::Handle::dumpState):
* heap/MarkedBlock.h:
(JSC::MarkedBlock::markingVersion):
(JSC::MarkedBlock::isMarkedRaw):
(JSC::MarkedBlock::isMarked):
* heap/MarkedBlockInlines.h:
(JSC::MarkedBlock::marksConveyLivenessDuringMarking):
* heap/SlotVisitor.cpp:
(JSC::SlotVisitor::appendJSCellOrAuxiliary):
* runtime/Options.cpp:
(JSC::recomputeDependentOptions):
* runtime/StructureIDTable.h:
(JSC::StructureIDTable::size):
(JSC::StructureIDTable::get):

Source/WTF:

To find this bug, I needed to seriously beef up our logging infrastructure.
        
It's now the case that:
        
    dataLog(...);
        
will print its output atomically. This happens with some careful magic:
        
- dataFile() is now a LockedPrintStream that locks around print().
        
- The lock is a recursive lock via RecursiveLockAdapter&lt;&gt;, so if the dump methods end
  up calling back into dataLog() then it just works. This is important: say the dump()
  calls a getter that itself does logging, maybe because it's encountering badness and
  wants to report it before crashing).
        
- The lock is a WordLock so that ParkingLot and Lock can keep using dataLog() for
  debugging. We probably won't need to debug WordLock anytime soon - the algorithm is
  so simple.
        
- LockedPrintStream::print(...) causes the print callbacks of its arguments to run on
  the underlying PrintStream, so that you don't need to do recursive lock acquisition
  on each individual argument and whatever printing it does recursively.

* WTF.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/DataLog.cpp:
(WTF::initializeLogFileOnce):
(WTF::initializeLogFile):
(WTF::dataFile):
* wtf/DataLog.h:
* wtf/LockedPrintStream.cpp: Added.
(WTF::LockedPrintStream::LockedPrintStream):
(WTF::LockedPrintStream::~LockedPrintStream):
(WTF::LockedPrintStream::vprintf):
(WTF::LockedPrintStream::flush):
(WTF::LockedPrintStream::begin):
(WTF::LockedPrintStream::end):
* wtf/LockedPrintStream.h: Added.
* wtf/PrintStream.cpp:
(WTF::PrintStream::printfVariableFormat):
(WTF::PrintStream::begin):
(WTF::PrintStream::end):
* wtf/PrintStream.h:
(WTF::PrintStream::atomically):
(WTF::PrintStream::print):
(WTF::PrintStream::println):
(WTF::PrintStream::printImpl):
(WTF::&gt;::unpack):
(WTF::FormatImpl::FormatImpl):
(WTF::FormatImpl::dump):
(WTF::format):
(WTF::printInternal):
* wtf/RecursiveLockAdapter.h: Added.
(WTF::RecursiveLockAdapter::RecursiveLockAdapter):
(WTF::RecursiveLockAdapter::lock):
(WTF::RecursiveLockAdapter::unlock):
(WTF::RecursiveLockAdapter::tryLock):
(WTF::RecursiveLockAdapter::isLocked):
* wtf/WordLock.cpp:
* wtf/WordLock.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCellContainerh">trunk/Source/JavaScriptCore/heap/CellContainer.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedAllocatorcpp">trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedAllocatorh">trunk/Source/JavaScriptCore/heap/MarkedAllocator.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedBlockcpp">trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedBlockh">trunk/Source/JavaScriptCore/heap/MarkedBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedBlockInlinesh">trunk/Source/JavaScriptCore/heap/MarkedBlockInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSlotVisitorcpp">trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructureIDTableh">trunk/Source/JavaScriptCore/runtime/StructureIDTable.h</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFWTFxcodeprojprojectpbxproj">trunk/Source/WTF/WTF.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWTFwtfCMakeListstxt">trunk/Source/WTF/wtf/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWTFwtfDataLogcpp">trunk/Source/WTF/wtf/DataLog.cpp</a></li>
<li><a href="#trunkSourceWTFwtfDataLogh">trunk/Source/WTF/wtf/DataLog.h</a></li>
<li><a href="#trunkSourceWTFwtfPrintStreamcpp">trunk/Source/WTF/wtf/PrintStream.cpp</a></li>
<li><a href="#trunkSourceWTFwtfPrintStreamh">trunk/Source/WTF/wtf/PrintStream.h</a></li>
<li><a href="#trunkSourceWTFwtfWordLockcpp">trunk/Source/WTF/wtf/WordLock.cpp</a></li>
<li><a href="#trunkSourceWTFwtfWordLockh">trunk/Source/WTF/wtf/WordLock.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreheapCellContainercpp">trunk/Source/JavaScriptCore/heap/CellContainer.cpp</a></li>
<li><a href="#trunkSourceWTFwtfLockedPrintStreamcpp">trunk/Source/WTF/wtf/LockedPrintStream.cpp</a></li>
<li><a href="#trunkSourceWTFwtfLockedPrintStreamh">trunk/Source/WTF/wtf/LockedPrintStream.h</a></li>
<li><a href="#trunkSourceWTFwtfRecursiveLockAdapterh">trunk/Source/WTF/wtf/RecursiveLockAdapter.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -464,6 +464,7 @@
</span><span class="cx">     ftl/FTLValueRange.cpp
</span><span class="cx"> 
</span><span class="cx">     heap/AllocatorAttributes.cpp
</span><ins>+    heap/CellContainer.cpp
</ins><span class="cx">     heap/CodeBlockSet.cpp
</span><span class="cx">     heap/CollectionScope.cpp
</span><span class="cx">     heap/ConservativeRoots.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -1,5 +1,59 @@
</span><span class="cx"> 2016-12-10  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        MarkedBlock::marksConveyLivenessDuringMarking should take into account collection scope
+        https://bugs.webkit.org/show_bug.cgi?id=165741
+
+        Reviewed by Saam Barati.
+        
+        MarkedBlock::marksConveyLivenessDuringMarking thought that the off-by-one marking
+        version indicated liveness during any collection when it's just during full collection.
+        One of its users - MarkedBlock::sweep - knew this and had a special case, but the other
+        one - MarkedBlock::isLive - didn't. So, I moved the special case into
+        marksConveyLivenessDuringMarking.
+        
+        Also, this cleans up some remaining bitvector races.
+        
+        To find this bug, I significantly strengthened our assertions.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * heap/CellContainer.cpp: Added.
+        (JSC::CellContainer::isNewlyAllocated):
+        * heap/CellContainer.h:
+        * heap/MarkedAllocator.cpp:
+        (JSC::MarkedAllocator::addBlock):
+        (JSC::MarkedAllocator::removeBlock):
+        (JSC::MarkedAllocator::dumpBits):
+        * heap/MarkedAllocator.h:
+        (JSC::MarkedAllocator::forEachBitVector):
+        (JSC::MarkedAllocator::forEachBitVectorWithName):
+        * heap/MarkedBlock.cpp:
+        (JSC::MarkedBlock::tryCreate):
+        (JSC::MarkedBlock::Handle::~Handle):
+        (JSC::MarkedBlock::MarkedBlock):
+        (JSC::MarkedBlock::Handle::specializedSweep):
+        (JSC::MarkedBlock::Handle::sweepHelperSelectMarksMode):
+        (JSC::MarkedBlock::Handle::stopAllocating):
+        (JSC::MarkedBlock::Handle::resumeAllocating):
+        (JSC::MarkedBlock::aboutToMarkSlow):
+        (JSC::MarkedBlock::Handle::didConsumeFreeList):
+        (JSC::MarkedBlock::Handle::dumpState):
+        * heap/MarkedBlock.h:
+        (JSC::MarkedBlock::markingVersion):
+        (JSC::MarkedBlock::isMarkedRaw):
+        (JSC::MarkedBlock::isMarked):
+        * heap/MarkedBlockInlines.h:
+        (JSC::MarkedBlock::marksConveyLivenessDuringMarking):
+        * heap/SlotVisitor.cpp:
+        (JSC::SlotVisitor::appendJSCellOrAuxiliary):
+        * runtime/Options.cpp:
+        (JSC::recomputeDependentOptions):
+        * runtime/StructureIDTable.h:
+        (JSC::StructureIDTable::size):
+        (JSC::StructureIDTable::get):
+
+2016-12-10  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
</ins><span class="cx">         The DOM should have an advancing wavefront opaque root barrier
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=165712
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -752,6 +752,7 @@
</span><span class="cx">                 0FDB2CEA174896C7007B3C1B /* ConcurrentJSLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDB2CE9174896C7007B3C1B /* ConcurrentJSLock.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FDDBFB51666EED800C55FEF /* DFGVariableAccessDataDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDDBFB21666EED500C55FEF /* DFGVariableAccessDataDump.cpp */; };
</span><span class="cx">                 0FDDBFB61666EEDA00C55FEF /* DFGVariableAccessDataDump.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDDBFB31666EED500C55FEF /* DFGVariableAccessDataDump.h */; };
</span><ins>+                0FDE87F91DFD0C760064C390 /* CellContainer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDE87F81DFD0C6D0064C390 /* CellContainer.cpp */; };
</ins><span class="cx">                 0FDF67D21D9C6D27001B9825 /* B3Kind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDF67D11D9C6086001B9825 /* B3Kind.h */; };
</span><span class="cx">                 0FDF67D31D9C6D2A001B9825 /* B3Kind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDF67D01D9C6086001B9825 /* B3Kind.cpp */; };
</span><span class="cx">                 0FDF67D61D9DC440001B9825 /* AirKind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDF67D41D9DC43E001B9825 /* AirKind.cpp */; };
</span><span class="lines">@@ -3178,6 +3179,7 @@
</span><span class="cx">                 0FDB2CE9174896C7007B3C1B /* ConcurrentJSLock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConcurrentJSLock.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FDDBFB21666EED500C55FEF /* DFGVariableAccessDataDump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGVariableAccessDataDump.cpp; path = dfg/DFGVariableAccessDataDump.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FDDBFB31666EED500C55FEF /* DFGVariableAccessDataDump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessDataDump.h; path = dfg/DFGVariableAccessDataDump.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0FDE87F81DFD0C6D0064C390 /* CellContainer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CellContainer.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0FDF67D01D9C6086001B9825 /* B3Kind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3Kind.cpp; path = b3/B3Kind.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FDF67D11D9C6086001B9825 /* B3Kind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3Kind.h; path = b3/B3Kind.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FDF67D41D9DC43E001B9825 /* AirKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirKind.cpp; path = b3/air/AirKind.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5629,6 +5631,7 @@
</span><span class="cx">                                 0FA7620A1DB959F600B7A2FD /* AllocatingScope.h */,
</span><span class="cx">                                 0F9630351D4192C3005609D9 /* AllocatorAttributes.cpp */,
</span><span class="cx">                                 0F9630361D4192C3005609D9 /* AllocatorAttributes.h */,
</span><ins>+                                0FDE87F81DFD0C6D0064C390 /* CellContainer.cpp */,
</ins><span class="cx">                                 0F070A421D543A89006E7232 /* CellContainer.h */,
</span><span class="cx">                                 0F070A431D543A89006E7232 /* CellContainerInlines.h */,
</span><span class="cx">                                 0F1C3DD91BBCE09E00E523E4 /* CellState.h */,
</span><span class="lines">@@ -10242,6 +10245,7 @@
</span><span class="cx">                                 0FB1058B1675483100F8AB6E /* ProfilerOSRExit.cpp in Sources */,
</span><span class="cx">                                 0FB1058D1675483700F8AB6E /* ProfilerOSRExitSite.cpp in Sources */,
</span><span class="cx">                                 0F61832B1C45BF070072450B /* AirCustom.cpp in Sources */,
</span><ins>+                                0FDE87F91DFD0C760064C390 /* CellContainer.cpp in Sources */,
</ins><span class="cx">                                 0F13912B16771C3A009CCB07 /* ProfilerProfiledBytecodes.cpp in Sources */,
</span><span class="cx">                                 0FD3E40D1B618B6600C80E1E /* PropertyCondition.cpp in Sources */,
</span><span class="cx">                                 E35CA1531DBC3A5C00F83516 /* DOMJITHeapRange.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCellContainercpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/CellContainer.cpp (0 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CellContainer.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/heap/CellContainer.cpp        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -0,0 +1,43 @@
</span><ins>+/*
+ * Copyright (C) 2016 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. ``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
+ * 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. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;CellContainer.h&quot;
+
+#include &quot;MarkedBlockInlines.h&quot;
+
+namespace JSC {
+
+bool CellContainer::isNewlyAllocated(HeapCell* cell) const
+{
+    if (isLargeAllocation())
+        return largeAllocation().isNewlyAllocated();
+    MarkedBlock::Handle&amp; handle = markedBlock().handle();
+    return !handle.isNewlyAllocatedStale()
+        &amp;&amp; handle.isNewlyAllocated(cell);
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCellContainerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CellContainer.h (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CellContainer.h        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/JavaScriptCore/heap/CellContainer.h        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -84,6 +84,8 @@
</span><span class="cx">     bool isMarked(HeapCell*) const;
</span><span class="cx">     bool isMarked(HeapVersion markingVersion, HeapCell*) const;
</span><span class="cx">     
</span><ins>+    bool isNewlyAllocated(HeapCell*) const;
+    
</ins><span class="cx">     void noteMarked();
</span><span class="cx">     void assertValidCell(VM&amp;, HeapCell*) const;
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedAllocatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -270,6 +270,7 @@
</span><span class="cx">         m_blocks.append(block);
</span><span class="cx">         if (m_blocks.capacity() != oldCapacity) {
</span><span class="cx">             forEachBitVector(
</span><ins>+                NoLockingNecessary,
</ins><span class="cx">                 [&amp;] (FastBitVector&amp; vector) {
</span><span class="cx">                     ASSERT_UNUSED(vector, vector.numBits() == oldCapacity);
</span><span class="cx">                 });
</span><span class="lines">@@ -278,6 +279,7 @@
</span><span class="cx">             
</span><span class="cx">             LockHolder locker(m_bitvectorLock);
</span><span class="cx">             forEachBitVector(
</span><ins>+                locker,
</ins><span class="cx">                 [&amp;] (FastBitVector&amp; vector) {
</span><span class="cx">                     vector.resize(m_blocks.capacity());
</span><span class="cx">                 });
</span><span class="lines">@@ -289,6 +291,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     forEachBitVector(
</span><ins>+        NoLockingNecessary,
</ins><span class="cx">         [&amp;] (FastBitVector&amp; vector) {
</span><span class="cx">             ASSERT_UNUSED(vector, !vector[index]);
</span><span class="cx">         });
</span><span class="lines">@@ -309,6 +312,7 @@
</span><span class="cx">     m_freeBlockIndices.append(block-&gt;index());
</span><span class="cx">     
</span><span class="cx">     forEachBitVector(
</span><ins>+        holdLock(m_bitvectorLock),
</ins><span class="cx">         [&amp;] (FastBitVector&amp; vector) {
</span><span class="cx">             vector[block-&gt;index()] = false;
</span><span class="cx">         });
</span><span class="lines">@@ -467,6 +471,7 @@
</span><span class="cx"> {
</span><span class="cx">     unsigned maxNameLength = 0;
</span><span class="cx">     forEachBitVectorWithName(
</span><ins>+        NoLockingNecessary,
</ins><span class="cx">         [&amp;] (FastBitVector&amp;, const char* name) {
</span><span class="cx">             unsigned length = strlen(name);
</span><span class="cx">             maxNameLength = std::max(maxNameLength, length);
</span><span class="lines">@@ -473,6 +478,7 @@
</span><span class="cx">         });
</span><span class="cx">     
</span><span class="cx">     forEachBitVectorWithName(
</span><ins>+        NoLockingNecessary,
</ins><span class="cx">         [&amp;] (FastBitVector&amp; vector, const char* name) {
</span><span class="cx">             out.print(&quot;    &quot;, name, &quot;: &quot;);
</span><span class="cx">             for (unsigned i = maxNameLength - strlen(name); i--;)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedAllocatorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedAllocator.h (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedAllocator.h        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/JavaScriptCore/heap/MarkedAllocator.h        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -182,7 +182,7 @@
</span><span class="cx"> #undef MARKED_ALLOCATOR_BIT_ACCESSORS
</span><span class="cx"> 
</span><span class="cx">     template&lt;typename Func&gt;
</span><del>-    void forEachBitVector(const Func&amp; func)
</del><ins>+    void forEachBitVector(const AbstractLocker&amp;, const Func&amp; func)
</ins><span class="cx">     {
</span><span class="cx"> #define MARKED_ALLOCATOR_BIT_CALLBACK(lowerBitName, capitalBitName) \
</span><span class="cx">         func(m_ ## lowerBitName);
</span><span class="lines">@@ -191,7 +191,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     template&lt;typename Func&gt;
</span><del>-    void forEachBitVectorWithName(const Func&amp; func)
</del><ins>+    void forEachBitVectorWithName(const AbstractLocker&amp;, const Func&amp; func)
</ins><span class="cx">     {
</span><span class="cx"> #define MARKED_ALLOCATOR_BIT_CALLBACK(lowerBitName, capitalBitName) \
</span><span class="cx">         func(m_ ## lowerBitName, #capitalBitName);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx">     if (computeBalance) {
</span><span class="cx">         balance++;
</span><span class="cx">         if (!(balance % 10))
</span><del>-            dataLog(toCString(&quot;MarkedBlock Balance: &quot;, balance, &quot;\n&quot;));
</del><ins>+            dataLog(&quot;MarkedBlock Balance: &quot;, balance, &quot;\n&quot;);
</ins><span class="cx">     }
</span><span class="cx">     void* blockSpace = tryFastAlignedMalloc(blockSize, blockSize);
</span><span class="cx">     if (!blockSpace)
</span><span class="lines">@@ -71,7 +71,7 @@
</span><span class="cx">     if (computeBalance) {
</span><span class="cx">         balance--;
</span><span class="cx">         if (!(balance % 10))
</span><del>-            dataLog(toCString(&quot;MarkedBlock Balance: &quot;, balance, &quot;\n&quot;));
</del><ins>+            dataLog(&quot;MarkedBlock Balance: &quot;, balance, &quot;\n&quot;);
</ins><span class="cx">     }
</span><span class="cx">     removeFromAllocator();
</span><span class="cx">     m_block-&gt;~MarkedBlock();
</span><span class="lines">@@ -85,7 +85,7 @@
</span><span class="cx">     , m_vm(&amp;vm)
</span><span class="cx"> {
</span><span class="cx">     if (false)
</span><del>-        dataLog(toCString(RawPointer(this), &quot;: Allocated.\n&quot;));
</del><ins>+        dataLog(RawPointer(this), &quot;: Allocated.\n&quot;);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;MarkedBlock::Handle::EmptyMode emptyMode, MarkedBlock::Handle::SweepMode sweepMode, MarkedBlock::Handle::SweepDestructionMode destructionMode, MarkedBlock::Handle::ScribbleMode scribbleMode, MarkedBlock::Handle::NewlyAllocatedMode newlyAllocatedMode, MarkedBlock::Handle::MarksMode marksMode&gt;
</span><span class="lines">@@ -98,7 +98,7 @@
</span><span class="cx">     MarkedBlock&amp; block = this-&gt;block();
</span><span class="cx">     
</span><span class="cx">     if (false)
</span><del>-        dataLog(toCString(RawPointer(this), &quot;/&quot;, RawPointer(&amp;block), &quot;: MarkedBlock::Handle::specializedSweep!\n&quot;));
</del><ins>+        dataLog(RawPointer(this), &quot;/&quot;, RawPointer(&amp;block), &quot;: MarkedBlock::Handle::specializedSweep!\n&quot;);
</ins><span class="cx">     
</span><span class="cx">     if (Options::useBumpAllocator()
</span><span class="cx">         &amp;&amp; emptyMode == IsEmpty
</span><span class="lines">@@ -106,11 +106,14 @@
</span><span class="cx">         
</span><span class="cx">         // This is an incredibly powerful assertion that checks the sanity of our block bits.
</span><span class="cx">         if (marksMode == MarksNotStale &amp;&amp; !block.m_marks.isEmpty()) {
</span><del>-            dataLog(toCString(&quot;Block &quot;, RawPointer(&amp;block), &quot;: marks not empty!\n&quot;));
-            dataLog(toCString(&quot;Block lock is held: &quot;, block.m_lock.isHeld(), &quot;\n&quot;));
-            dataLog(toCString(&quot;Marking version of block: &quot;, block.m_markingVersion, &quot;\n&quot;));
-            dataLog(toCString(&quot;Marking version of heap: &quot;, space()-&gt;markingVersion(), &quot;\n&quot;));
-            RELEASE_ASSERT_NOT_REACHED();
</del><ins>+            WTF::dataFile().atomically(
+                [&amp;] (PrintStream&amp; out) {
+                    out.print(&quot;Block &quot;, RawPointer(&amp;block), &quot;: marks not empty!\n&quot;);
+                    out.print(&quot;Block lock is held: &quot;, block.m_lock.isHeld(), &quot;\n&quot;);
+                    out.print(&quot;Marking version of block: &quot;, block.m_markingVersion, &quot;\n&quot;);
+                    out.print(&quot;Marking version of heap: &quot;, space()-&gt;markingVersion(), &quot;\n&quot;);
+                    UNREACHABLE_FOR_PLATFORM();
+                });
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         char* startOfLastCell = static_cast&lt;char*&gt;(cellAlign(block.atoms() + m_endAtom - 1));
</span><span class="lines">@@ -127,7 +130,7 @@
</span><span class="cx">             block.m_lock.unlock();
</span><span class="cx">         FreeList result = FreeList::bump(payloadEnd, payloadEnd - payloadBegin);
</span><span class="cx">         if (false)
</span><del>-            dataLog(toCString(&quot;Quickly swept block &quot;, RawPointer(this), &quot; with cell size &quot;, cellSize(), &quot; and attributes &quot;, m_attributes, &quot;: &quot;, result, &quot;\n&quot;));
</del><ins>+            dataLog(&quot;Quickly swept block &quot;, RawPointer(this), &quot; with cell size &quot;, cellSize(), &quot; and attributes &quot;, m_attributes, &quot;: &quot;, result, &quot;\n&quot;);
</ins><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -186,7 +189,7 @@
</span><span class="cx">     else if (isEmpty)
</span><span class="cx">         m_allocator-&gt;setIsEmpty(NoLockingNecessary, this, true);
</span><span class="cx">     if (false)
</span><del>-        dataLog(toCString(&quot;Slowly swept block &quot;, RawPointer(&amp;block), &quot; with cell size &quot;, cellSize(), &quot; and attributes &quot;, m_attributes, &quot;: &quot;, result, &quot;\n&quot;));
</del><ins>+        dataLog(&quot;Slowly swept block &quot;, RawPointer(&amp;block), &quot; with cell size &quot;, cellSize(), &quot; and attributes &quot;, m_attributes, &quot;: &quot;, result, &quot;\n&quot;);
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -262,7 +265,7 @@
</span><span class="cx">     HeapVersion markingVersion = space()-&gt;markingVersion();
</span><span class="cx">     bool marksAreUseful = !block().areMarksStale(markingVersion);
</span><span class="cx">     
</span><del>-    if (space()-&gt;isMarking() &amp;&amp; heap()-&gt;collectionScope() == CollectionScope::Full)
</del><ins>+    if (space()-&gt;isMarking())
</ins><span class="cx">         marksAreUseful |= block().marksConveyLivenessDuringMarking(markingVersion);
</span><span class="cx">     
</span><span class="cx">     if (!marksAreUseful)
</span><span class="lines">@@ -287,12 +290,12 @@
</span><span class="cx">     auto locker = holdLock(block().m_lock);
</span><span class="cx">     
</span><span class="cx">     if (false)
</span><del>-        dataLog(toCString(RawPointer(this), &quot;: MarkedBlock::Handle::stopAllocating!\n&quot;));
</del><ins>+        dataLog(RawPointer(this), &quot;: MarkedBlock::Handle::stopAllocating!\n&quot;);
</ins><span class="cx">     ASSERT(!allocator()-&gt;isAllocated(NoLockingNecessary, this));
</span><span class="cx"> 
</span><span class="cx">     if (!isFreeListed()) {
</span><span class="cx">         if (false)
</span><del>-            dataLog(toCString(&quot;There ain't no newly allocated.\n&quot;));
</del><ins>+            dataLog(&quot;There ain't no newly allocated.\n&quot;);
</ins><span class="cx">         // This means that we either didn't use this block at all for allocation since last GC,
</span><span class="cx">         // or someone had already done stopAllocating() before.
</span><span class="cx">         ASSERT(freeList.allocationWillFail());
</span><span class="lines">@@ -300,7 +303,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (false)
</span><del>-        dataLog(toCString(&quot;Free list: &quot;, freeList, &quot;\n&quot;));
</del><ins>+        dataLog(&quot;Free list: &quot;, freeList, &quot;\n&quot;);
</ins><span class="cx">     
</span><span class="cx">     // Roll back to a coherent state for Heap introspection. Cells newly
</span><span class="cx">     // allocated from our free list are not currently marked, so we need another
</span><span class="lines">@@ -319,7 +322,7 @@
</span><span class="cx">         freeList,
</span><span class="cx">         [&amp;] (HeapCell* cell) {
</span><span class="cx">             if (false)
</span><del>-                dataLog(toCString(&quot;Free cell: &quot;, RawPointer(cell), &quot;\n&quot;));
</del><ins>+                dataLog(&quot;Free cell: &quot;, RawPointer(cell), &quot;\n&quot;);
</ins><span class="cx">             if (m_attributes.destruction == NeedsDestruction)
</span><span class="cx">                 cell-&gt;zap();
</span><span class="cx">             clearNewlyAllocated(cell);
</span><span class="lines">@@ -346,13 +349,13 @@
</span><span class="cx">         auto locker = holdLock(block().m_lock);
</span><span class="cx">         
</span><span class="cx">         if (false)
</span><del>-            dataLog(toCString(RawPointer(this), &quot;: MarkedBlock::Handle::resumeAllocating!\n&quot;));
</del><ins>+            dataLog(RawPointer(this), &quot;: MarkedBlock::Handle::resumeAllocating!\n&quot;);
</ins><span class="cx">         ASSERT(!allocator()-&gt;isAllocated(NoLockingNecessary, this));
</span><span class="cx">         ASSERT(!isFreeListed());
</span><span class="cx">         
</span><span class="cx">         if (!hasAnyNewlyAllocated()) {
</span><span class="cx">             if (false)
</span><del>-                dataLog(toCString(&quot;There ain't no newly allocated.\n&quot;));
</del><ins>+                dataLog(&quot;There ain't no newly allocated.\n&quot;);
</ins><span class="cx">             // This means we had already exhausted the block when we stopped allocation.
</span><span class="cx">             return FreeList();
</span><span class="cx">         }
</span><span class="lines">@@ -401,7 +404,7 @@
</span><span class="cx">     if (handle().allocator()-&gt;isAllocated(holdLock(allocator-&gt;bitvectorLock()), &amp;handle())
</span><span class="cx">         || !marksConveyLivenessDuringMarking(markingVersion)) {
</span><span class="cx">         if (false)
</span><del>-            dataLog(toCString(RawPointer(this), &quot;: Clearing marks without doing anything else.\n&quot;));
</del><ins>+            dataLog(RawPointer(this), &quot;: Clearing marks without doing anything else.\n&quot;);
</ins><span class="cx">         // We already know that the block is full and is already recognized as such, or that the
</span><span class="cx">         // block did not survive the previous GC. So, we can clear mark bits the old fashioned
</span><span class="cx">         // way. Note that it's possible for such a block to have newlyAllocated with an up-to-
</span><span class="lines">@@ -411,7 +414,7 @@
</span><span class="cx">         m_marks.clearAll();
</span><span class="cx">     } else {
</span><span class="cx">         if (false)
</span><del>-            dataLog(toCString(RawPointer(this), &quot;: Doing things.\n&quot;));
</del><ins>+            dataLog(RawPointer(this), &quot;: Doing things.\n&quot;);
</ins><span class="cx">         HeapVersion newlyAllocatedVersion = space()-&gt;newlyAllocatedVersion();
</span><span class="cx">         if (handle().m_newlyAllocatedVersion == newlyAllocatedVersion) {
</span><span class="cx">             // Merge the contents of marked into newlyAllocated. If we get the full set of bits
</span><span class="lines">@@ -477,7 +480,7 @@
</span><span class="cx"> {
</span><span class="cx">     auto locker = holdLock(block().m_lock);
</span><span class="cx">     if (false)
</span><del>-        dataLog(toCString(RawPointer(this), &quot;: MarkedBlock::Handle::didConsumeFreeList!\n&quot;));
</del><ins>+        dataLog(RawPointer(this), &quot;: MarkedBlock::Handle::didConsumeFreeList!\n&quot;);
</ins><span class="cx">     ASSERT(isFreeListed());
</span><span class="cx">     m_isFreeListed = false;
</span><span class="cx">     allocator()-&gt;setIsAllocated(NoLockingNecessary, this, true);
</span><span class="lines">@@ -573,6 +576,16 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+void MarkedBlock::Handle::dumpState(PrintStream&amp; out)
+{
+    CommaPrinter comma;
+    allocator()-&gt;forEachBitVectorWithName(
+        holdLock(allocator()-&gt;bitvectorLock()),
+        [&amp;] (FastBitVector&amp; bitvector, const char* name) {
+            out.print(comma, name, &quot;:&quot;, bitvector[index()] ? &quot;YES&quot; : &quot;no&quot;);
+        });
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedBlock.h (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedBlock.h        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/JavaScriptCore/heap/MarkedBlock.h        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -187,6 +187,8 @@
</span><span class="cx">         void didAddToAllocator(MarkedAllocator*, size_t index);
</span><span class="cx">         void didRemoveFromAllocator();
</span><span class="cx">         
</span><ins>+        void dumpState(PrintStream&amp;);
+        
</ins><span class="cx">     private:
</span><span class="cx">         Handle(Heap&amp;, void*);
</span><span class="cx">         
</span><span class="lines">@@ -298,6 +300,9 @@
</span><span class="cx">     
</span><span class="cx">     void resetMarks();
</span><span class="cx">     
</span><ins>+    bool isMarkedRaw(const void* p);
+    HeapVersion markingVersion() const { return m_markingVersion; }
+    
</ins><span class="cx"> private:
</span><span class="cx">     static const size_t atomAlignmentMask = atomSize - 1;
</span><span class="cx"> 
</span><span class="lines">@@ -518,9 +523,14 @@
</span><span class="cx">     block().assertMarksNotStale();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool MarkedBlock::isMarkedRaw(const void* p)
+{
+    return m_marks.get(atomNumber(p));
+}
+
</ins><span class="cx"> inline bool MarkedBlock::isMarked(HeapVersion markingVersion, const void* p)
</span><span class="cx"> {
</span><del>-    return areMarksStale(markingVersion) ? false : m_marks.get(atomNumber(p));
</del><ins>+    return areMarksStale(markingVersion) ? false : isMarkedRaw(p);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline bool MarkedBlock::isMarkedConcurrently(HeapVersion markingVersion, const void* p)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedBlockInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedBlockInlines.h (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedBlockInlines.h        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/JavaScriptCore/heap/MarkedBlockInlines.h        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #include &quot;MarkedAllocator.h&quot;
</span><span class="cx"> #include &quot;MarkedBlock.h&quot;
</span><span class="cx"> #include &quot;MarkedSpace.h&quot;
</span><ins>+#include &quot;VM.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -51,6 +52,8 @@
</span><span class="cx">     // back&quot; state only makes sense when we're in a concurrent collection and have to be
</span><span class="cx">     // conservative.
</span><span class="cx">     ASSERT(space()-&gt;isMarking());
</span><ins>+    if (heap()-&gt;collectionScope() != CollectionScope::Full)
+        return false;
</ins><span class="cx">     return m_markingVersion == MarkedSpace::nullVersion
</span><span class="cx">         || MarkedSpace::nextVersion(m_markingVersion) == markingVersion;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -135,18 +135,75 @@
</span><span class="cx">     
</span><span class="cx">     ASSERT(!m_isCheckingForDefaultMarkViolation);
</span><span class="cx">     
</span><ins>+    auto validateCell = [&amp;] (JSCell* jsCell) {
+        StructureID structureID = jsCell-&gt;structureID();
+        
+        auto die = [&amp;] (const char* text) {
+            WTF::dataFile().atomically(
+                [&amp;] (PrintStream&amp; out) {
+                    out.print(text);
+                    out.print(&quot;GC type: &quot;, heap()-&gt;collectionScope(), &quot;\n&quot;);
+                    out.print(&quot;Object at: &quot;, RawPointer(jsCell), &quot;\n&quot;);
+#if USE(JSVALUE64)
+                    out.print(&quot;Structure ID: &quot;, structureID, &quot; (0x&quot;, format(&quot;%x&quot;, structureID), &quot;)\n&quot;);
+                    out.print(&quot;Structure ID table size: &quot;, heap()-&gt;structureIDTable().size(), &quot;\n&quot;);
+#else
+                    out.print(&quot;Structure: &quot;, RawPointer(structureID), &quot;\n&quot;);
+#endif
+                    out.print(&quot;Object contents:&quot;);
+                    for (unsigned i = 0; i &lt; 2; ++i)
+                        out.print(&quot; &quot;, format(&quot;0x%016llx&quot;, bitwise_cast&lt;uint64_t*&gt;(jsCell)[i]));
+                    out.print(&quot;\n&quot;);
+                    CellContainer container = jsCell-&gt;cellContainer();
+                    out.print(&quot;Is marked: &quot;, container.isMarked(jsCell), &quot;\n&quot;);
+                    out.print(&quot;Is newly allocated: &quot;, container.isNewlyAllocated(jsCell), &quot;\n&quot;);
+                    if (container.isMarkedBlock()) {
+                        MarkedBlock&amp; block = container.markedBlock();
+                        out.print(&quot;Block: &quot;, RawPointer(&amp;block), &quot;\n&quot;);
+                        block.handle().dumpState(out);
+                        out.print(&quot;\n&quot;);
+                        out.print(&quot;Is marked raw: &quot;, block.isMarkedRaw(jsCell), &quot;\n&quot;);
+                        out.print(&quot;Marking version: &quot;, block.markingVersion(), &quot;\n&quot;);
+                        out.print(&quot;Heap marking version: &quot;, heap()-&gt;objectSpace().markingVersion(), &quot;\n&quot;);
+                        out.print(&quot;Is newly allocated raw: &quot;, block.handle().isNewlyAllocated(jsCell), &quot;\n&quot;);
+                        out.print(&quot;Newly allocated version: &quot;, block.handle().newlyAllocatedVersion(), &quot;\n&quot;);
+                        out.print(&quot;Heap newly allocated version: &quot;, heap()-&gt;objectSpace().newlyAllocatedVersion(), &quot;\n&quot;);
+                    }
+                    UNREACHABLE_FOR_PLATFORM();
+                });
+        };
+        
+        // It's not OK for the structure to be null at any GC scan point. We must not GC while
+        // an object is not fully initialized.
+        if (!structureID)
+            die(&quot;GC scan found corrupt object: structureID is zero!\n&quot;);
+        
+        // It's not OK for the structure to be nuked at any GC scan point.
+        if (isNuked(structureID))
+            die(&quot;GC scan found object in bad state: structureID is nuked!\n&quot;);
+        
+#if USE(JSVALUE64)
+        // This detects the worst of the badness.
+        if (structureID &gt;= heap()-&gt;structureIDTable().size())
+            die(&quot;GC scan found corrupt object: structureID is out of bounds!\n&quot;);
+#endif
+    };
+    
+    // In debug mode, we validate before marking since this makes it clearer what the problem
+    // was. It's also slower, so we don't do it normally.
+    if (!ASSERT_DISABLED &amp;&amp; heapCell-&gt;cellKind() == HeapCell::JSCell)
+        validateCell(static_cast&lt;JSCell*&gt;(heapCell));
+    
</ins><span class="cx">     if (Heap::testAndSetMarked(m_markingVersion, heapCell))
</span><span class="cx">         return;
</span><span class="cx">     
</span><span class="cx">     switch (heapCell-&gt;cellKind()) {
</span><span class="cx">     case HeapCell::JSCell: {
</span><ins>+        // We have ample budget to perform validation here.
+    
</ins><span class="cx">         JSCell* jsCell = static_cast&lt;JSCell*&gt;(heapCell);
</span><ins>+        validateCell(jsCell);
</ins><span class="cx">         
</span><del>-        if (!jsCell-&gt;structure()) {
-            ASSERT_NOT_REACHED();
-            return;
-        }
-        
</del><span class="cx">         jsCell-&gt;setCellState(CellState::Grey);
</span><span class="cx"> 
</span><span class="cx">         appendToMarkStack(jsCell);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructureIDTableh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StructureIDTable.h (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StructureIDTable.h        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/JavaScriptCore/runtime/StructureIDTable.h        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -90,6 +90,8 @@
</span><span class="cx">     StructureID allocateID(Structure*);
</span><span class="cx"> 
</span><span class="cx">     void flushOldTables();
</span><ins>+    
+    size_t size() const { return m_size; }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     void resize(size_t newCapacity);
</span><span class="lines">@@ -121,7 +123,9 @@
</span><span class="cx"> inline Structure* StructureIDTable::get(StructureID structureID)
</span><span class="cx"> {
</span><span class="cx"> #if USE(JSVALUE64)
</span><del>-    ASSERT_WITH_SECURITY_IMPLICATION(structureID &amp;&amp; structureID &lt; m_capacity);
</del><ins>+    ASSERT_WITH_SECURITY_IMPLICATION(structureID);
+    ASSERT_WITH_SECURITY_IMPLICATION(!isNuked(structureID));
+    ASSERT_WITH_SECURITY_IMPLICATION(structureID &lt; m_capacity);
</ins><span class="cx">     return table()[structureID].structure;
</span><span class="cx"> #else
</span><span class="cx">     return structureID;
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/WTF/ChangeLog        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -1,3 +1,71 @@
</span><ins>+2016-12-10  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        MarkedBlock::marksConveyLivenessDuringMarking should take into account collection scope
+        https://bugs.webkit.org/show_bug.cgi?id=165741
+
+        Reviewed by Saam Barati.
+        
+        To find this bug, I needed to seriously beef up our logging infrastructure.
+        
+        It's now the case that:
+        
+            dataLog(...);
+        
+        will print its output atomically. This happens with some careful magic:
+        
+        - dataFile() is now a LockedPrintStream that locks around print().
+        
+        - The lock is a recursive lock via RecursiveLockAdapter&lt;&gt;, so if the dump methods end
+          up calling back into dataLog() then it just works. This is important: say the dump()
+          calls a getter that itself does logging, maybe because it's encountering badness and
+          wants to report it before crashing).
+        
+        - The lock is a WordLock so that ParkingLot and Lock can keep using dataLog() for
+          debugging. We probably won't need to debug WordLock anytime soon - the algorithm is
+          so simple.
+        
+        - LockedPrintStream::print(...) causes the print callbacks of its arguments to run on
+          the underlying PrintStream, so that you don't need to do recursive lock acquisition
+          on each individual argument and whatever printing it does recursively.
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/CMakeLists.txt:
+        * wtf/DataLog.cpp:
+        (WTF::initializeLogFileOnce):
+        (WTF::initializeLogFile):
+        (WTF::dataFile):
+        * wtf/DataLog.h:
+        * wtf/LockedPrintStream.cpp: Added.
+        (WTF::LockedPrintStream::LockedPrintStream):
+        (WTF::LockedPrintStream::~LockedPrintStream):
+        (WTF::LockedPrintStream::vprintf):
+        (WTF::LockedPrintStream::flush):
+        (WTF::LockedPrintStream::begin):
+        (WTF::LockedPrintStream::end):
+        * wtf/LockedPrintStream.h: Added.
+        * wtf/PrintStream.cpp:
+        (WTF::PrintStream::printfVariableFormat):
+        (WTF::PrintStream::begin):
+        (WTF::PrintStream::end):
+        * wtf/PrintStream.h:
+        (WTF::PrintStream::atomically):
+        (WTF::PrintStream::print):
+        (WTF::PrintStream::println):
+        (WTF::PrintStream::printImpl):
+        (WTF::&gt;::unpack):
+        (WTF::FormatImpl::FormatImpl):
+        (WTF::FormatImpl::dump):
+        (WTF::format):
+        (WTF::printInternal):
+        * wtf/RecursiveLockAdapter.h: Added.
+        (WTF::RecursiveLockAdapter::RecursiveLockAdapter):
+        (WTF::RecursiveLockAdapter::lock):
+        (WTF::RecursiveLockAdapter::unlock):
+        (WTF::RecursiveLockAdapter::tryLock):
+        (WTF::RecursiveLockAdapter::isLocked):
+        * wtf/WordLock.cpp:
+        * wtf/WordLock.h:
+
</ins><span class="cx"> 2016-12-11  Darin Adler  &lt;darin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Use std::vsnprintf instead of vasprintf
</span></span></pre></div>
<a id="trunkSourceWTFWTFxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -30,6 +30,8 @@
</span><span class="cx">                 0F43D8F21DB5ADDC00108FB6 /* AutomaticThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F43D8F01DB5ADDC00108FB6 /* AutomaticThread.h */; };
</span><span class="cx">                 0F4570431BE5B58F0062A629 /* Dominators.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4570421BE5B58F0062A629 /* Dominators.h */; };
</span><span class="cx">                 0F4570451BE834410062A629 /* BubbleSort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4570441BE834410062A629 /* BubbleSort.h */; };
</span><ins>+                0F60F32F1DFCBD1B00416D6C /* LockedPrintStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F60F32D1DFCBD1B00416D6C /* LockedPrintStream.cpp */; };
+                0F60F3301DFCBD1B00416D6C /* LockedPrintStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F60F32E1DFCBD1B00416D6C /* LockedPrintStream.h */; };
</ins><span class="cx">                 0F66B28A1DC97BAB004A1D3F /* ClockType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F66B2801DC97BAB004A1D3F /* ClockType.cpp */; };
</span><span class="cx">                 0F66B28B1DC97BAB004A1D3F /* ClockType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66B2811DC97BAB004A1D3F /* ClockType.h */; };
</span><span class="cx">                 0F66B28C1DC97BAB004A1D3F /* MonotonicTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F66B2821DC97BAB004A1D3F /* MonotonicTime.cpp */; };
</span><span class="lines">@@ -63,6 +65,7 @@
</span><span class="cx">                 0FDB698E1B7C643A000C1078 /* Condition.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDB698D1B7C643A000C1078 /* Condition.h */; };
</span><span class="cx">                 0FDDBFA71666DFA300C55FEF /* StringPrintStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDDBFA51666DFA300C55FEF /* StringPrintStream.cpp */; };
</span><span class="cx">                 0FDDBFA81666DFA300C55FEF /* StringPrintStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDDBFA61666DFA300C55FEF /* StringPrintStream.h */; };
</span><ins>+                0FDE87F71DFD07CC0064C390 /* RecursiveLockAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDE87F61DFD07CC0064C390 /* RecursiveLockAdapter.h */; };
</ins><span class="cx">                 0FE1646A1B6FFC9600400E7C /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE164681B6FFC9600400E7C /* Lock.cpp */; };
</span><span class="cx">                 0FE1646B1B6FFC9600400E7C /* Lock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE164691B6FFC9600400E7C /* Lock.h */; };
</span><span class="cx">                 0FE4479C1B7AAA03009498EB /* WordLock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE4479A1B7AAA03009498EB /* WordLock.cpp */; };
</span><span class="lines">@@ -388,6 +391,8 @@
</span><span class="cx">                 0F43D8F01DB5ADDC00108FB6 /* AutomaticThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutomaticThread.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F4570421BE5B58F0062A629 /* Dominators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Dominators.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F4570441BE834410062A629 /* BubbleSort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BubbleSort.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F60F32D1DFCBD1B00416D6C /* LockedPrintStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LockedPrintStream.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F60F32E1DFCBD1B00416D6C /* LockedPrintStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LockedPrintStream.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F66B2801DC97BAB004A1D3F /* ClockType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClockType.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F66B2811DC97BAB004A1D3F /* ClockType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClockType.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F66B2821DC97BAB004A1D3F /* MonotonicTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MonotonicTime.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -421,6 +426,7 @@
</span><span class="cx">                 0FDB698D1B7C643A000C1078 /* Condition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Condition.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FDDBFA51666DFA300C55FEF /* StringPrintStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringPrintStream.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FDDBFA61666DFA300C55FEF /* StringPrintStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringPrintStream.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0FDE87F61DFD07CC0064C390 /* RecursiveLockAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecursiveLockAdapter.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0FE164681B6FFC9600400E7C /* Lock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Lock.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FE164691B6FFC9600400E7C /* Lock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Lock.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FE4479A1B7AAA03009498EB /* WordLock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WordLock.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -858,7 +864,6 @@
</span><span class="cx">                 A876DBD6151816E500DADB95 /* wtf */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><del>-                                AD7C434A1DD2A4A70026888B /* Expected.h */,
</del><span class="cx">                                 2CDED0F018115C3F004DBA70 /* cf */,
</span><span class="cx">                                 E4A0AD3B1A96251900536DF6 /* cocoa */,
</span><span class="cx">                                 A8A47281151A825A004123FF /* dtoa */,
</span><span class="lines">@@ -926,6 +931,7 @@
</span><span class="cx">                                 A8A47297151A825A004123FF /* dtoa.cpp */,
</span><span class="cx">                                 A8A47298151A825A004123FF /* dtoa.h */,
</span><span class="cx">                                 1AEA88E11D6BBCF400E5AD64 /* EnumTraits.h */,
</span><ins>+                                AD7C434A1DD2A4A70026888B /* Expected.h */,
</ins><span class="cx">                                 A8A4729F151A825A004123FF /* ExportMacros.h */,
</span><span class="cx">                                 0F7C5FB51D885CF20044F5E2 /* FastBitVector.cpp */,
</span><span class="cx">                                 0FD81AC4154FB22E00983E72 /* FastBitVector.h */,
</span><span class="lines">@@ -966,6 +972,8 @@
</span><span class="cx">                                 0FE164681B6FFC9600400E7C /* Lock.cpp */,
</span><span class="cx">                                 0FE164691B6FFC9600400E7C /* Lock.h */,
</span><span class="cx">                                 0F0FCDDD1DD167F900CCAB53 /* LockAlgorithm.h */,
</span><ins>+                                0F60F32D1DFCBD1B00416D6C /* LockedPrintStream.cpp */,
+                                0F60F32E1DFCBD1B00416D6C /* LockedPrintStream.h */,
</ins><span class="cx">                                 A8A472C3151A825A004123FF /* Locker.h */,
</span><span class="cx">                                 513E170A1CD7D5BF00E3650B /* LoggingAccumulator.h */,
</span><span class="cx">                                 A8A472C6151A825A004123FF /* MainThread.cpp */,
</span><span class="lines">@@ -1025,6 +1033,7 @@
</span><span class="cx">                                 A8A472FD151A825B004123FF /* RandomNumberSeed.h */,
</span><span class="cx">                                 0F725CAB1C50461600AD943A /* RangeSet.h */,
</span><span class="cx">                                 0F87105916643F190090B0AD /* RawPointer.h */,
</span><ins>+                                0FDE87F61DFD07CC0064C390 /* RecursiveLockAdapter.h */,
</ins><span class="cx">                                 A8A472FE151A825B004123FF /* RedBlackTree.h */,
</span><span class="cx">                                 26299B6D17A9E5B800ADEBE5 /* Ref.h */,
</span><span class="cx">                                 A8A472FF151A825B004123FF /* RefCounted.h */,
</span><span class="lines">@@ -1386,6 +1395,7 @@
</span><span class="cx">                                 7CDD7FFA186D2A54007433CD /* IteratorRange.h in Headers */,
</span><span class="cx">                                 0F43D8F21DB5ADDC00108FB6 /* AutomaticThread.h in Headers */,
</span><span class="cx">                                 93AC91A818942FC400244939 /* LChar.h in Headers */,
</span><ins>+                                0F60F3301DFCBD1B00416D6C /* LockedPrintStream.h in Headers */,
</ins><span class="cx">                                 539EB0631D55284200C82EF7 /* LEBDecoder.h in Headers */,
</span><span class="cx">                                 A70DA0851799F04D00529A9B /* ListDump.h in Headers */,
</span><span class="cx">                                 0F66B2931DC97BAB004A1D3F /* WallTime.h in Headers */,
</span><span class="lines">@@ -1459,6 +1469,7 @@
</span><span class="cx">                                 0FEB3DCF1BB5D684009D7AAD /* SharedTask.h in Headers */,
</span><span class="cx">                                 A8A47423151A825B004123FF /* SimpleStats.h in Headers */,
</span><span class="cx">                                 A8A47424151A825B004123FF /* SinglyLinkedList.h in Headers */,
</span><ins>+                                0FDE87F71DFD07CC0064C390 /* RecursiveLockAdapter.h in Headers */,
</ins><span class="cx">                                 A748745317A0BDAE00FA04CB /* SixCharacterHash.h in Headers */,
</span><span class="cx">                                 79EC70611C99F9BC003A3AE2 /* SmallPtrSet.h in Headers */,
</span><span class="cx">                                 A8A47426151A825B004123FF /* Spectrum.h in Headers */,
</span><span class="lines">@@ -1654,6 +1665,7 @@
</span><span class="cx">                                 A8A473B0151A825B004123FF /* double-conversion.cc in Sources */,
</span><span class="cx">                                 A8A473BA151A825B004123FF /* dtoa.cpp in Sources */,
</span><span class="cx">                                 A8A473B3151A825B004123FF /* fast-dtoa.cc in Sources */,
</span><ins>+                                0F60F32F1DFCBD1B00416D6C /* LockedPrintStream.cpp in Sources */,
</ins><span class="cx">                                 A8A473C3151A825B004123FF /* FastMalloc.cpp in Sources */,
</span><span class="cx">                                 0F9D3360165DBA73005AD387 /* FilePrintStream.cpp in Sources */,
</span><span class="cx">                                 A8A473B5151A825B004123FF /* fixed-dtoa.cc in Sources */,
</span></span></pre></div>
<a id="trunkSourceWTFwtfCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/CMakeLists.txt (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/CMakeLists.txt        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/WTF/wtf/CMakeLists.txt        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -57,6 +57,7 @@
</span><span class="cx">     ListHashSet.h
</span><span class="cx">     Lock.h
</span><span class="cx">     LockAlgorithm.h
</span><ins>+    LockedPrintStream.h
</ins><span class="cx">     Locker.h
</span><span class="cx">     MD5.h
</span><span class="cx">     MainThread.h
</span><span class="lines">@@ -92,6 +93,7 @@
</span><span class="cx">     RandomNumberSeed.h
</span><span class="cx">     RangeSet.h
</span><span class="cx">     RawPointer.h
</span><ins>+    RecursiveLockAdapter.h
</ins><span class="cx">     RedBlackTree.h
</span><span class="cx">     Ref.h
</span><span class="cx">     RefCounted.h
</span><span class="lines">@@ -198,6 +200,7 @@
</span><span class="cx">     GregorianDateTime.cpp
</span><span class="cx">     HashTable.cpp
</span><span class="cx">     Lock.cpp
</span><ins>+    LockedPrintStream.cpp
</ins><span class="cx">     MD5.cpp
</span><span class="cx">     MainThread.cpp
</span><span class="cx">     MediaTime.cpp
</span></span></pre></div>
<a id="trunkSourceWTFwtfDataLogcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/DataLog.cpp (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/DataLog.cpp        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/WTF/wtf/DataLog.cpp        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -28,7 +28,10 @@
</span><span class="cx"> #include &lt;stdarg.h&gt;
</span><span class="cx"> #include &lt;string.h&gt;
</span><span class="cx"> #include &lt;wtf/FilePrintStream.h&gt;
</span><ins>+#include &lt;wtf/LockedPrintStream.h&gt;
</ins><span class="cx"> #include &lt;wtf/Threading.h&gt;
</span><ins>+#include &lt;mutex&gt;
+#include &lt;thread&gt;
</ins><span class="cx"> 
</span><span class="cx"> #if OS(UNIX) || OS(DARWIN)
</span><span class="cx"> #include &lt;unistd.h&gt;
</span><span class="lines">@@ -47,16 +50,14 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="cx"> 
</span><del>-#if USE(PTHREADS)
-static pthread_once_t initializeLogFileOnceKey = PTHREAD_ONCE_INIT;
-#endif
</del><ins>+static PrintStream* s_file;
</ins><span class="cx"> 
</span><del>-static FilePrintStream* file;
</del><ins>+static uint64_t s_fileData[(sizeof(FilePrintStream) + 7) / 8];
</ins><span class="cx"> 
</span><del>-static uint64_t fileData[(sizeof(FilePrintStream) + 7) / 8];
-
</del><span class="cx"> static void initializeLogFileOnce()
</span><span class="cx"> {
</span><ins>+    FilePrintStream* file = nullptr;
+    
</ins><span class="cx"> #if DATA_LOG_TO_FILE
</span><span class="cx">     const long maxPathLength = 1024;
</span><span class="cx"> 
</span><span class="lines">@@ -117,29 +118,38 @@
</span><span class="cx">             WTFLogAlways(&quot;Warning: Could not open DataLog file %s for writing.\n&quot;, actualFilename);
</span><span class="cx">     }
</span><span class="cx"> #endif // DATA_LOG_TO_FILE
</span><ins>+    
+    bool wrapWithLocked = true;
+    
</ins><span class="cx">     if (!file) {
</span><span class="cx">         // Use placement new; this makes it easier to use dataLog() to debug
</span><span class="cx">         // fastMalloc.
</span><del>-        file = new (fileData) FilePrintStream(stderr, FilePrintStream::Borrow);
</del><ins>+        file = new (s_fileData) FilePrintStream(stderr, FilePrintStream::Borrow);
+        wrapWithLocked = false;
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     setvbuf(file-&gt;file(), 0, _IONBF, 0); // Prefer unbuffered output, so that we get a full log upon crash or deadlock.
</span><ins>+    
+    if (wrapWithLocked)
+        s_file = new LockedPrintStream(std::unique_ptr&lt;FilePrintStream&gt;(file));
+    else
+        s_file = file;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void initializeLogFile()
</span><span class="cx"> {
</span><del>-#if USE(PTHREADS)
-    pthread_once(&amp;initializeLogFileOnceKey, initializeLogFileOnce);
-#else
-    if (!file)
-        initializeLogFileOnce();
-#endif
</del><ins>+    static std::once_flag once;
+    std::call_once(
+        once,
+        [] {
+            initializeLogFileOnce();
+        });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-FilePrintStream&amp; dataFile()
</del><ins>+PrintStream&amp; dataFile()
</ins><span class="cx"> {
</span><span class="cx">     initializeLogFile();
</span><del>-    return *file;
</del><ins>+    return *s_file;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void dataLogFV(const char* format, va_list argList)
</span></span></pre></div>
<a id="trunkSourceWTFwtfDataLogh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/DataLog.h (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/DataLog.h        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/WTF/wtf/DataLog.h        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -28,12 +28,12 @@
</span><span class="cx"> 
</span><span class="cx"> #include &lt;stdarg.h&gt;
</span><span class="cx"> #include &lt;stdio.h&gt;
</span><del>-#include &lt;wtf/FilePrintStream.h&gt;
</del><ins>+#include &lt;wtf/PrintStream.h&gt;
</ins><span class="cx"> #include &lt;wtf/StdLibExtras.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="cx"> 
</span><del>-WTF_EXPORT_PRIVATE FilePrintStream&amp; dataFile();
</del><ins>+WTF_EXPORT_PRIVATE PrintStream&amp; dataFile();
</ins><span class="cx"> 
</span><span class="cx"> WTF_EXPORT_PRIVATE void dataLogFV(const char* format, va_list) WTF_ATTRIBUTE_PRINTF(1, 0);
</span><span class="cx"> WTF_EXPORT_PRIVATE void dataLogF(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
</span></span></pre></div>
<a id="trunkSourceWTFwtfLockedPrintStreamcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WTF/wtf/LockedPrintStream.cpp (0 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/LockedPrintStream.cpp                                (rev 0)
+++ trunk/Source/WTF/wtf/LockedPrintStream.cpp        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -0,0 +1,64 @@
</span><ins>+/*
+ * Copyright (C) 2016 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. ``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
+ * 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. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;LockedPrintStream.h&quot;
+
+namespace WTF {
+
+LockedPrintStream::LockedPrintStream(std::unique_ptr&lt;PrintStream&gt; target)
+    : m_target(WTFMove(target))
+{
+}
+
+LockedPrintStream::~LockedPrintStream()
+{
+}
+
+void LockedPrintStream::vprintf(const char* format, va_list args)
+{
+    auto locker = holdLock(m_lock);
+    m_target-&gt;vprintf(format, args);
+}
+
+void LockedPrintStream::flush()
+{
+    auto locker = holdLock(m_lock);
+    m_target-&gt;flush();
+}
+
+PrintStream&amp; LockedPrintStream::begin()
+{
+    m_lock.lock();
+    return *m_target;
+}
+
+void LockedPrintStream::end()
+{
+    m_lock.unlock();
+}
+
+} // namespace WTF
+
</ins></span></pre></div>
<a id="trunkSourceWTFwtfLockedPrintStreamh"></a>
<div class="addfile"><h4>Added: trunk/Source/WTF/wtf/LockedPrintStream.h (0 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/LockedPrintStream.h                                (rev 0)
+++ trunk/Source/WTF/wtf/LockedPrintStream.h        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -0,0 +1,60 @@
</span><ins>+/*
+ * Copyright (C) 2016 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. ``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
+ * 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 LockedPrintStream_h
+#define LockedPrintStream_h
+
+#include &lt;wtf/PrintStream.h&gt;
+#include &lt;wtf/RecursiveLockAdapter.h&gt;
+#include &lt;wtf/WordLock.h&gt;
+
+namespace WTF {
+
+// Makes every call to print() atomic.
+class LockedPrintStream : public PrintStream {
+public:
+    LockedPrintStream(std::unique_ptr&lt;PrintStream&gt; target);
+    virtual ~LockedPrintStream();
+    
+    void vprintf(const char* format, va_list) override WTF_ATTRIBUTE_PRINTF(2, 0);
+    void flush() override;
+
+protected:
+    PrintStream&amp; begin() override;
+    void end() override;
+
+private:
+    // This needs to be a recursive lock because a printInternal or dump method could assert,
+    // and that assert might want to log. Better to let it. This needs to be a WordLock so that
+    // LockedPrintStream (i.e. cataLog) can be used to debug ParkingLot and Lock.
+    RecursiveLockAdapter&lt;WordLock&gt; m_lock;
+    std::unique_ptr&lt;PrintStream&gt; m_target;
+};
+
+} // namespace WTF
+
+using WTF::LockedPrintStream;
+
+#endif // LockedPrintStream_h
</ins></span></pre></div>
<a id="trunkSourceWTFwtfPrintStreamcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/PrintStream.cpp (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/PrintStream.cpp        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/WTF/wtf/PrintStream.cpp        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -44,10 +44,30 @@
</span><span class="cx">     va_end(argList);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void PrintStream::printfVariableFormat(const char* format, ...)
+{
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored &quot;-Wformat-nonliteral&quot;
+    va_list argList;
+    va_start(argList, format);
+    vprintf(format, argList);
+    va_end(argList);
+#pragma clang diagnostic pop
+}
+
</ins><span class="cx"> void PrintStream::flush()
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+PrintStream&amp; PrintStream::begin()
+{
+    return *this;
+}
+
+void PrintStream::end()
+{
+}
+
</ins><span class="cx"> void printInternal(PrintStream&amp; out, const char* string)
</span><span class="cx"> {
</span><span class="cx">     out.printf(&quot;%s&quot;, string);
</span></span></pre></div>
<a id="trunkSourceWTFwtfPrintStreamh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/PrintStream.h (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/PrintStream.h        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/WTF/wtf/PrintStream.h        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> #include &lt;stdarg.h&gt;
</span><span class="cx"> #include &lt;wtf/FastMalloc.h&gt;
</span><span class="cx"> #include &lt;wtf/Noncopyable.h&gt;
</span><ins>+#include &lt;wtf/Optional.h&gt;
</ins><span class="cx"> #include &lt;wtf/RawPointer.h&gt;
</span><span class="cx"> #include &lt;wtf/RefPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/StdLibExtras.h&gt;
</span><span class="lines">@@ -50,6 +51,7 @@
</span><span class="cx">     virtual ~PrintStream();
</span><span class="cx"> 
</span><span class="cx">     WTF_EXPORT_PRIVATE void printf(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
</span><ins>+    WTF_EXPORT_PRIVATE void printfVariableFormat(const char* format, ...);
</ins><span class="cx">     virtual void vprintf(const char* format, va_list) WTF_ATTRIBUTE_PRINTF(2, 0) = 0;
</span><span class="cx"> 
</span><span class="cx">     // Typically a no-op for many subclasses of PrintStream, this is a hint that
</span><span class="lines">@@ -56,27 +58,40 @@
</span><span class="cx">     // the implementation should flush its buffers if it had not done so already.
</span><span class="cx">     virtual void flush();
</span><span class="cx">     
</span><del>-    void print() { }
-
-    template&lt;typename T&gt;
-    void print(const T&amp; value)
</del><ins>+    template&lt;typename Func&gt;
+    void atomically(const Func&amp; func)
</ins><span class="cx">     {
</span><del>-        printInternal(*this, value);
</del><ins>+        func(begin());
+        end();
</ins><span class="cx">     }
</span><del>-
-    template&lt;typename T, typename... Types&gt;
-    void print(const T&amp; value, const Types&amp;... remainingValues)
</del><ins>+    
+    template&lt;typename... Types&gt;
+    void print(const Types&amp;... values)
</ins><span class="cx">     {
</span><del>-        printInternal(*this, value);
-        print(remainingValues...);
</del><ins>+        atomically(
+            [&amp;] (PrintStream&amp; out) {
+                out.printImpl(values...);
+            });
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     template&lt;typename... Types&gt;
</span><span class="cx">     void println(const Types&amp;... values)
</span><span class="cx">     {
</span><del>-        print(values...);
-        print(&quot;\n&quot;);
</del><ins>+        print(values..., &quot;\n&quot;);
</ins><span class="cx">     }
</span><ins>+
+protected:
+    void printImpl() { }
+
+    template&lt;typename T, typename... Types&gt;
+    void printImpl(const T&amp; value, const Types&amp;... remainingValues)
+    {
+        printInternal(*this, value);
+        printImpl(remainingValues...);
+    }
+    
+    virtual PrintStream&amp; begin();
+    virtual void end();
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> WTF_EXPORT_PRIVATE void printInternal(PrintStream&amp;, const char*);
</span><span class="lines">@@ -266,11 +281,66 @@
</span><span class="cx">     return ValueIgnoringContext&lt;T, U&gt;(value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;unsigned index, typename... Types&gt;
+struct FormatImplUnpacker {
+    template&lt;typename... Args&gt;
+    static void unpack(PrintStream&amp; out, const std::tuple&lt;Types...&gt;&amp; tuple, const Args&amp;... values);
+};
+    
+template&lt;typename... Types&gt;
+struct FormatImplUnpacker&lt;0, Types...&gt; {
+    template&lt;typename... Args&gt;
+    static void unpack(PrintStream&amp; out, const std::tuple&lt;Types...&gt;&amp; tuple, const Args&amp;... values)
+    {
+        out.printfVariableFormat(std::get&lt;0&gt;(tuple), values...);
+    }
+};
+    
+template&lt;unsigned index, typename... Types&gt;
+template&lt;typename... Args&gt;
+void FormatImplUnpacker&lt;index, Types...&gt;::unpack(PrintStream&amp; out, const std::tuple&lt;Types...&gt;&amp; tuple, const Args&amp;... values)
+{
+    FormatImplUnpacker&lt;index - 1, Types...&gt;::unpack(out, tuple, std::get&lt;index&gt;(tuple), values...);
+}
+
+template&lt;typename... Types&gt;
+class FormatImpl {
+public:
+    FormatImpl(Types... values)
+        : m_values(values...)
+    {
+    }
+    
+    void dump(PrintStream&amp; out) const
+    {
+        FormatImplUnpacker&lt;sizeof...(Types) - 1, Types...&gt;::unpack(out, m_values);
+    }
+
+private:
+    std::tuple&lt;Types...&gt; m_values;
+};
+
+template&lt;typename... Types&gt;
+FormatImpl&lt;Types...&gt; format(Types... values)
+{
+    return FormatImpl&lt;Types...&gt;(values...);
+}
+
+template&lt;typename T&gt;
+void printInternal(PrintStream&amp; out, const std::optional&lt;T&gt;&amp; value)
+{
+    if (value)
+        out.print(*value);
+    else
+        out.print(&quot;&lt;nullopt&gt;&quot;);
+}
+
</ins><span class="cx"> } // namespace WTF
</span><span class="cx"> 
</span><span class="cx"> using WTF::CharacterDump;
</span><span class="cx"> using WTF::PointerDump;
</span><span class="cx"> using WTF::PrintStream;
</span><ins>+using WTF::format;
</ins><span class="cx"> using WTF::ignoringContext;
</span><span class="cx"> using WTF::inContext;
</span><span class="cx"> using WTF::pointerDump;
</span></span></pre></div>
<a id="trunkSourceWTFwtfRecursiveLockAdapterh"></a>
<div class="addfile"><h4>Added: trunk/Source/WTF/wtf/RecursiveLockAdapter.h (0 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/RecursiveLockAdapter.h                                (rev 0)
+++ trunk/Source/WTF/wtf/RecursiveLockAdapter.h        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -0,0 +1,95 @@
</span><ins>+/*
+ * Copyright (C) 2016 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. ``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
+ * 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 WTF_RecursiveLockAdapter_h
+#define WTF_RecursiveLockAdapter_h
+
+#include &lt;wtf/Threading.h&gt;
+
+namespace WTF {
+
+template&lt;typename LockType&gt;
+class RecursiveLockAdapter {
+public:
+    RecursiveLockAdapter()
+    {
+    }
+    
+    void lock()
+    {
+        ThreadIdentifier me = currentThread();
+        if (me == m_owner) {
+            m_recursionCount++;
+            return;
+        }
+        
+        m_lock.lock();
+        ASSERT(!m_owner);
+        ASSERT(!m_recursionCount);
+        m_owner = me;
+        m_recursionCount = 1;
+    }
+    
+    void unlock()
+    {
+        if (--m_recursionCount)
+            return;
+        m_owner = 0;
+        m_lock.unlock();
+    }
+    
+    bool tryLock()
+    {
+        ThreadIdentifier me = currentThread();
+        if (me == m_owner) {
+            m_recursionCount++;
+            return true;
+        }
+        
+        if (!m_lock.tryLock())
+            return false;
+        
+        ASSERT(!m_owner);
+        ASSERT(!m_recursionCount);
+        m_owner = me;
+        m_recursionCount = 1;
+        return true;
+    }
+    
+    bool isLocked() const
+    {
+        return m_lock.isLocked();
+    }
+    
+private:
+    ThreadIdentifier m_owner { 0 };
+    unsigned m_recursionCount { 0 };
+    LockType m_lock;
+};
+
+} // namespace WTF
+
+#endif // WTF_RecursiveLockAdapter_h
+
</ins></span></pre></div>
<a id="trunkSourceWTFwtfWordLockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/WordLock.cpp (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/WordLock.cpp        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/WTF/wtf/WordLock.cpp        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -26,8 +26,6 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;WordLock.h&quot;
</span><span class="cx"> 
</span><del>-#include &quot;DataLog.h&quot;
-#include &quot;StringPrintStream.h&quot;
</del><span class="cx"> #include &quot;ThreadSpecific.h&quot;
</span><span class="cx"> #include &quot;ThreadingPrimitives.h&quot;
</span><span class="cx"> #include &lt;condition_variable&gt;
</span></span></pre></div>
<a id="trunkSourceWTFwtfWordLockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/WordLock.h (209690 => 209691)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/WordLock.h        2016-12-12 01:10:00 UTC (rev 209690)
+++ trunk/Source/WTF/wtf/WordLock.h        2016-12-12 01:19:47 UTC (rev 209691)
</span><span class="lines">@@ -42,6 +42,10 @@
</span><span class="cx"> // Lock instead. WordLock sits lower in the stack and is used to implement Lock, so Lock is the main
</span><span class="cx"> // client of WordLock.
</span><span class="cx"> 
</span><ins>+// NOTE: This is also a great lock to use if you are very low in the stack. For example,
+// PrintStream uses this so that ParkingLot and Lock can use PrintStream. This means that if you
+// try to use dataLog to debug this code, you will have a bad time.
+
</ins><span class="cx"> struct WordLockBase {
</span><span class="cx">     void lock()
</span><span class="cx">     {
</span></span></pre>
</div>
</div>

</body>
</html>