Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (220321 => 220322)
--- trunk/Source/_javascript_Core/ChangeLog 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-08-06 04:43:37 UTC (rev 220322)
@@ -1,3 +1,38 @@
+2017-08-05 Filip Pizlo <fpi...@apple.com>
+
+ REGRESSION (r219895-219897): Number of leaks on Open Source went from 9240 to 235983 and is now at 302372
+ https://bugs.webkit.org/show_bug.cgi?id=175083
+
+ Reviewed by Oliver Hunt.
+
+ This fixes the leak by making MarkedBlock::specializedSweep call destructors when the block is empty,
+ even if we are using the pop path.
+
+ Also, this fixes HeapCellInlines.h to no longer include MarkedBlockInlines.h. That's pretty
+ important, since MarkedBlockInlines.h is the GC's internal guts - we don't want to have to recompile
+ the world just because we changed it.
+
+ Finally, this adds a new testing SPI for waiting for all VMs to finish destructing. This makes it
+ easier to debug leaks.
+
+ * bytecode/AccessCase.cpp:
+ * bytecode/PolymorphicAccess.cpp:
+ * heap/HeapCell.cpp:
+ (JSC::HeapCell::isLive):
+ * heap/HeapCellInlines.h:
+ (JSC::HeapCell::isLive): Deleted.
+ * heap/MarkedAllocator.cpp:
+ (JSC::MarkedAllocator::tryAllocateWithoutCollecting):
+ (JSC::MarkedAllocator::endMarking):
+ * heap/MarkedBlockInlines.h:
+ (JSC::MarkedBlock::Handle::specializedSweep):
+ * jit/AssemblyHelpers.cpp:
+ * jit/Repatch.cpp:
+ * runtime/TestRunnerUtils.h:
+ * runtime/VM.cpp:
+ (JSC::waitForVMDestruction):
+ (JSC::VM::~VM):
+
2017-08-05 Mark Lam <mark....@apple.com>
Move DFG::OSRExitCompiler methods into DFG::OSRExit [step 3].
Modified: trunk/Source/_javascript_Core/bytecode/AccessCase.cpp (220321 => 220322)
--- trunk/Source/_javascript_Core/bytecode/AccessCase.cpp 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Source/_javascript_Core/bytecode/AccessCase.cpp 2017-08-06 04:43:37 UTC (rev 220322)
@@ -46,6 +46,7 @@
#include "ScratchRegisterAllocator.h"
#include "SlotVisitorInlines.h"
#include "StructureStubInfo.h"
+#include "SuperSampler.h"
#include "ThunkGenerators.h"
namespace JSC {
Modified: trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.cpp (220321 => 220322)
--- trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.cpp 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.cpp 2017-08-06 04:43:37 UTC (rev 220322)
@@ -38,6 +38,7 @@
#include "LinkBuffer.h"
#include "StructureStubClearingWatchpoint.h"
#include "StructureStubInfo.h"
+#include "SuperSampler.h"
#include <wtf/CommaPrinter.h>
#include <wtf/ListDump.h>
Modified: trunk/Source/_javascript_Core/heap/HeapCell.cpp (220321 => 220322)
--- trunk/Source/_javascript_Core/heap/HeapCell.cpp 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Source/_javascript_Core/heap/HeapCell.cpp 2017-08-06 04:43:37 UTC (rev 220322)
@@ -26,10 +26,22 @@
#include "config.h"
#include "HeapCell.h"
+#include "HeapCellInlines.h"
+#include "MarkedBlockInlines.h"
#include <wtf/PrintStream.h>
namespace JSC {
+bool HeapCell::isLive()
+{
+ if (isLargeAllocation())
+ return largeAllocation().isLive();
+ auto& markedBlockHandle = markedBlock().handle();
+ if (markedBlockHandle.isFreeListed())
+ return !markedBlockHandle.isFreeListedCell(this);
+ return markedBlockHandle.isLive(this);
+}
+
#if !COMPILER(GCC_OR_CLANG)
void HeapCell::use() const
{
Modified: trunk/Source/_javascript_Core/heap/HeapCellInlines.h (220321 => 220322)
--- trunk/Source/_javascript_Core/heap/HeapCellInlines.h 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Source/_javascript_Core/heap/HeapCellInlines.h 2017-08-06 04:43:37 UTC (rev 220322)
@@ -28,21 +28,10 @@
#include "CellContainer.h"
#include "HeapCell.h"
#include "LargeAllocation.h"
-#include "MarkedBlockInlines.h"
#include "VM.h"
namespace JSC {
-ALWAYS_INLINE bool HeapCell::isLive()
-{
- if (isLargeAllocation())
- return largeAllocation().isLive();
- auto& markedBlockHandle = markedBlock().handle();
- if (markedBlockHandle.isFreeListed())
- return !markedBlockHandle.isFreeListedCell(this);
- return markedBlockHandle.isLive(this);
-}
-
ALWAYS_INLINE bool HeapCell::isLargeAllocation() const
{
return LargeAllocation::isLargeAllocation(const_cast<HeapCell*>(this));
Modified: trunk/Source/_javascript_Core/heap/MarkedAllocator.cpp (220321 => 220322)
--- trunk/Source/_javascript_Core/heap/MarkedAllocator.cpp 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Source/_javascript_Core/heap/MarkedAllocator.cpp 2017-08-06 04:43:37 UTC (rev 220322)
@@ -39,6 +39,8 @@
namespace JSC {
+static constexpr bool tradeDestructorBlocks = true;
+
MarkedAllocator::MarkedAllocator(Heap* heap, Subspace* subspace, size_t cellSize)
: m_freeList(cellSize)
, m_currentBlock(0)
@@ -102,7 +104,8 @@
return result;
}
- if (Options::stealEmptyBlocksFromOtherAllocators()) {
+ if (Options::stealEmptyBlocksFromOtherAllocators()
+ && (tradeDestructorBlocks || !needsDestruction())) {
if (MarkedBlock::Handle* block = m_subspace->findEmptyBlockToSteal()) {
RELEASE_ASSERT(block->alignedMemoryAllocator() == m_subspace->alignedMemoryAllocator());
@@ -381,8 +384,14 @@
// know what kind of collection it is. That knowledge is already encoded in the m_markingXYZ
// vectors.
- m_empty = m_live & ~m_markingNotEmpty;
- m_canAllocateButNotEmpty = m_live & m_markingNotEmpty & ~m_markingRetired;
+ if (!tradeDestructorBlocks && needsDestruction()) {
+ ASSERT(m_empty.isEmpty());
+ m_canAllocateButNotEmpty = m_live & ~m_markingRetired;
+ } else {
+ m_empty = m_live & ~m_markingNotEmpty;
+ m_canAllocateButNotEmpty = m_live & m_markingNotEmpty & ~m_markingRetired;
+ }
+
if (needsDestruction()) {
// There are some blocks that we didn't allocate out of in the last cycle, but we swept them. This
// will forget that we did that and we will end up sweeping them again and attempting to call their
Modified: trunk/Source/_javascript_Core/heap/MarkedBlockInlines.h (220321 => 220322)
--- trunk/Source/_javascript_Core/heap/MarkedBlockInlines.h 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Source/_javascript_Core/heap/MarkedBlockInlines.h 2017-08-06 04:43:37 UTC (rev 220322)
@@ -223,7 +223,7 @@
auto handleDeadCell = [&] (size_t i) {
HeapCell* cell = reinterpret_cast_ptr<HeapCell*>(&block.atoms()[i]);
- if (destructionMode != BlockHasNoDestructors && emptyMode == NotEmpty)
+ if (destructionMode != BlockHasNoDestructors)
destroy(cell);
if (sweepMode == SweepToFreeList) {
Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp (220321 => 220322)
--- trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp 2017-08-06 04:43:37 UTC (rev 220322)
@@ -32,6 +32,7 @@
#include "JSCInlines.h"
#include "LinkBuffer.h"
#include "MaxFrameExtentForSlowPathCall.h"
+#include "SuperSampler.h"
#include "ThunkGenerators.h"
#if ENABLE(WEBASSEMBLY)
Modified: trunk/Source/_javascript_Core/jit/Repatch.cpp (220321 => 220322)
--- trunk/Source/_javascript_Core/jit/Repatch.cpp 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Source/_javascript_Core/jit/Repatch.cpp 2017-08-06 04:43:37 UTC (rev 220322)
@@ -58,6 +58,7 @@
#include "StructureRareDataInlines.h"
#include "StructureStubClearingWatchpoint.h"
#include "StructureStubInfo.h"
+#include "SuperSampler.h"
#include "ThunkGenerators.h"
#include <wtf/CommaPrinter.h>
#include <wtf/ListDump.h>
Modified: trunk/Source/_javascript_Core/runtime/TestRunnerUtils.h (220321 => 220322)
--- trunk/Source/_javascript_Core/runtime/TestRunnerUtils.h 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Source/_javascript_Core/runtime/TestRunnerUtils.h 2017-08-06 04:43:37 UTC (rev 220322)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -54,4 +54,6 @@
JS_EXPORT_PRIVATE void finalizeStatsAtEndOfTesting();
+JS_EXPORT_PRIVATE void waitForVMDestruction();
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (220321 => 220322)
--- trunk/Source/_javascript_Core/runtime/VM.cpp 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp 2017-08-06 04:43:37 UTC (rev 220322)
@@ -101,6 +101,7 @@
#include "StrictEvalActivation.h"
#include "StrongInlines.h"
#include "StructureInlines.h"
+#include "TestRunnerUtils.h"
#include "ThunkGenerators.h"
#include "TypeProfiler.h"
#include "TypeProfilerLog.h"
@@ -113,6 +114,7 @@
#include "WeakMapData.h"
#include <wtf/CurrentTime.h>
#include <wtf/ProcessID.h>
+#include <wtf/ReadWriteLock.h>
#include <wtf/SimpleStats.h>
#include <wtf/StringPrintStream.h>
#include <wtf/Threading.h>
@@ -341,8 +343,17 @@
VMInspector::instance().add(this);
}
+static StaticReadWriteLock s_destructionLock;
+
+void waitForVMDestruction()
+{
+ auto locker = holdLock(s_destructionLock.write());
+}
+
VM::~VM()
{
+ auto destructionLocker = holdLock(s_destructionLock.read());
+
Gigacage::removeDisableCallback(gigacageDisabledCallback, this);
promiseDeferredTimer->stopRunningTasks();
#if ENABLE(WEBASSEMBLY)
Modified: trunk/Source/WTF/ChangeLog (220321 => 220322)
--- trunk/Source/WTF/ChangeLog 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Source/WTF/ChangeLog 2017-08-06 04:43:37 UTC (rev 220322)
@@ -1,3 +1,37 @@
+2017-08-05 Filip Pizlo <fpi...@apple.com>
+
+ REGRESSION (r219895-219897): Number of leaks on Open Source went from 9240 to 235983 and is now at 302372
+ https://bugs.webkit.org/show_bug.cgi?id=175083
+
+ Reviewed by Oliver Hunt.
+
+ Adds a classic ReadWriteLock class. I wrote my own because I can never remember if the pthread one is
+ guaranted to bias in favor of writers or not.
+
+ * WTF.xcodeproj/project.pbxproj:
+ * wtf/Condition.h:
+ (WTF::ConditionBase::construct):
+ (WTF::Condition::Condition):
+ * wtf/Lock.h:
+ (WTF::LockBase::construct):
+ (WTF::Lock::Lock):
+ * wtf/ReadWriteLock.cpp: Added.
+ (WTF::ReadWriteLockBase::construct):
+ (WTF::ReadWriteLockBase::readLock):
+ (WTF::ReadWriteLockBase::readUnlock):
+ (WTF::ReadWriteLockBase::writeLock):
+ (WTF::ReadWriteLockBase::writeUnlock):
+ * wtf/ReadWriteLock.h: Added.
+ (WTF::ReadWriteLockBase::ReadLock::tryLock):
+ (WTF::ReadWriteLockBase::ReadLock::lock):
+ (WTF::ReadWriteLockBase::ReadLock::unlock):
+ (WTF::ReadWriteLockBase::WriteLock::tryLock):
+ (WTF::ReadWriteLockBase::WriteLock::lock):
+ (WTF::ReadWriteLockBase::WriteLock::unlock):
+ (WTF::ReadWriteLockBase::read):
+ (WTF::ReadWriteLockBase::write):
+ (WTF::ReadWriteLock::ReadWriteLock):
+
2017-08-04 Matt Lewis <jlew...@apple.com>
Unreviewed, rolling out r220271.
Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (220321 => 220322)
--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj 2017-08-06 04:43:37 UTC (rev 220322)
@@ -38,6 +38,7 @@
0FDDBFA71666DFA300C55FEF /* StringPrintStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDDBFA51666DFA300C55FEF /* StringPrintStream.cpp */; };
0FE1646A1B6FFC9600400E7C /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE164681B6FFC9600400E7C /* Lock.cpp */; };
0FE4479C1B7AAA03009498EB /* WordLock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE4479A1B7AAA03009498EB /* WordLock.cpp */; };
+ 0FEC3C5E1F368A9700F59B6C /* ReadWriteLock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC3C5C1F368A9700F59B6C /* ReadWriteLock.cpp */; };
0FFF19DC1BB334EB00886D91 /* ParallelHelperPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFF19DA1BB334EB00886D91 /* ParallelHelperPool.cpp */; };
14022F4118F5C3FC007FF0EB /* libbmalloc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14022F4018F5C3FC007FF0EB /* libbmalloc.a */; };
143F611F1565F0F900DB514A /* RAMSize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 143F611D1565F0F900DB514A /* RAMSize.cpp */; };
@@ -225,6 +226,8 @@
0FEB3DCE1BB5D684009D7AAD /* SharedTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SharedTask.h; sourceTree = "<group>"; };
0FEB3DD01BB7366B009D7AAD /* ParallelVectorIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParallelVectorIterator.h; sourceTree = "<group>"; };
0FEC3C4F1F323C6800F59B6C /* CagedPtr.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CagedPtr.h; sourceTree = "<group>"; };
+ 0FEC3C5C1F368A9700F59B6C /* ReadWriteLock.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ReadWriteLock.cpp; sourceTree = "<group>"; };
+ 0FEC3C5D1F368A9700F59B6C /* ReadWriteLock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReadWriteLock.h; sourceTree = "<group>"; };
0FEC84AE1BD825310080FF74 /* GraphNodeWorklist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GraphNodeWorklist.h; sourceTree = "<group>"; };
0FEC84B01BDACD390080FF74 /* ScopedLambda.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScopedLambda.h; sourceTree = "<group>"; };
0FED67B51B22D4D80066CE15 /* TinyPtrSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TinyPtrSet.h; sourceTree = "<group>"; };
@@ -909,6 +912,8 @@
0F2AC5601E89F70C0001EE3F /* Range.h */,
0F725CAB1C50461600AD943A /* RangeSet.h */,
0F87105916643F190090B0AD /* RawPointer.h */,
+ 0FEC3C5C1F368A9700F59B6C /* ReadWriteLock.cpp */,
+ 0FEC3C5D1F368A9700F59B6C /* ReadWriteLock.h */,
0FDE87F61DFD07CC0064C390 /* RecursiveLockAdapter.h */,
A8A472FE151A825B004123FF /* RedBlackTree.h */,
26299B6D17A9E5B800ADEBE5 /* Ref.h */,
@@ -1337,6 +1342,7 @@
A8A473D8151A825B004123FF /* HashTable.cpp in Sources */,
0FE1646A1B6FFC9600400E7C /* Lock.cpp in Sources */,
0F60F32F1DFCBD1B00416D6C /* LockedPrintStream.cpp in Sources */,
+ 0FEC3C5E1F368A9700F59B6C /* ReadWriteLock.cpp in Sources */,
53534F2A1EC0E10E00141B2F /* MachExceptions.defs in Sources */,
A8A473E5151A825B004123FF /* MainThread.cpp in Sources */,
A8A473E4151A825B004123FF /* MainThreadMac.mm in Sources */,
Modified: trunk/Source/WTF/wtf/CMakeLists.txt (220321 => 220322)
--- trunk/Source/WTF/wtf/CMakeLists.txt 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Source/WTF/wtf/CMakeLists.txt 2017-08-06 04:43:37 UTC (rev 220322)
@@ -110,6 +110,7 @@
Range.h
RangeSet.h
RawPointer.h
+ ReadWriteLock.h
RecursiveLockAdapter.h
RedBlackTree.h
Ref.h
@@ -241,6 +242,7 @@
RAMSize.cpp
RandomDevice.cpp
RandomNumber.cpp
+ ReadWriteLock.cpp
RefCountedLeakCounter.cpp
RunLoop.cpp
SHA1.cpp
Modified: trunk/Source/WTF/wtf/Condition.h (220321 => 220322)
--- trunk/Source/WTF/wtf/Condition.h 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Source/WTF/wtf/Condition.h 2017-08-06 04:43:37 UTC (rev 220322)
@@ -50,6 +50,11 @@
// are unlikely to be affected by the cost of conversions, it is better to use MonotonicTime.
typedef ParkingLot::Time Time;
+ void construct()
+ {
+ m_hasWaiters.store(false);
+ }
+
// Wait on a parking queue while releasing the given lock. It will unlock the lock just before
// parking, and relock it upon wakeup. Returns true if we woke up due to some call to
// notifyOne() or notifyAll(). Returns false if we woke up due to a timeout. Note that this form
@@ -168,7 +173,7 @@
ParkingLot::unparkAll(&m_hasWaiters);
}
-protected:
+private:
Atomic<bool> m_hasWaiters;
};
@@ -177,7 +182,7 @@
public:
Condition()
{
- m_hasWaiters.store(false);
+ construct();
}
};
Modified: trunk/Source/WTF/wtf/Lock.h (220321 => 220322)
--- trunk/Source/WTF/wtf/Lock.h 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Source/WTF/wtf/Lock.h 2017-08-06 04:43:37 UTC (rev 220322)
@@ -52,6 +52,11 @@
// This is a struct without a constructor or destructor so that it can be statically initialized.
// Use Lock in instance variables.
struct LockBase {
+ void construct()
+ {
+ m_byte.store(0, std::memory_order_relaxed);
+ }
+
void lock()
{
if (UNLIKELY(!DefaultLockAlgorithm::lockFastAssumingZero(m_byte)))
@@ -110,7 +115,7 @@
return isHeld();
}
-protected:
+private:
friend struct TestWebKitAPI::LockInspector;
static const uint8_t isHeldBit = 1;
@@ -136,7 +141,7 @@
public:
Lock()
{
- m_byte.store(0, std::memory_order_relaxed);
+ construct();
}
};
Added: trunk/Source/WTF/wtf/ReadWriteLock.cpp (0 => 220322)
--- trunk/Source/WTF/wtf/ReadWriteLock.cpp (rev 0)
+++ trunk/Source/WTF/wtf/ReadWriteLock.cpp 2017-08-06 04:43:37 UTC (rev 220322)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2017 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 "config.h"
+#include "ReadWriteLock.h"
+
+#include <wtf/Locker.h>
+
+namespace WTF {
+
+void ReadWriteLockBase::construct()
+{
+ m_lock.construct();
+ m_cond.construct();
+ m_isWriteLocked = false;
+ m_numReaders = 0;
+ m_numWaitingWriters = 0;
+}
+
+void ReadWriteLockBase::readLock()
+{
+ auto locker = holdLock(m_lock);
+ while (m_isWriteLocked || m_numWaitingWriters)
+ m_cond.wait(m_lock);
+ m_numReaders++;
+}
+
+void ReadWriteLockBase::readUnlock()
+{
+ auto locker = holdLock(m_lock);
+ m_numReaders--;
+ if (!m_numReaders)
+ m_cond.notifyAll();
+}
+
+void ReadWriteLockBase::writeLock()
+{
+ auto locker = holdLock(m_lock);
+ while (m_isWriteLocked || m_numReaders) {
+ m_numWaitingWriters++;
+ m_cond.wait(m_lock);
+ m_numWaitingWriters--;
+ }
+ m_isWriteLocked = true;
+}
+
+void ReadWriteLockBase::writeUnlock()
+{
+ auto locker = holdLock(m_lock);
+ m_isWriteLocked = false;
+ m_cond.notifyAll();
+}
+
+} // namespace WTF
+
Added: trunk/Source/WTF/wtf/ReadWriteLock.h (0 => 220322)
--- trunk/Source/WTF/wtf/ReadWriteLock.h (rev 0)
+++ trunk/Source/WTF/wtf/ReadWriteLock.h 2017-08-06 04:43:37 UTC (rev 220322)
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#pragma once
+
+#include <wtf/Condition.h>
+#include <wtf/Lock.h>
+
+namespace WTF {
+
+// This is a traditional read-write lock implementation that enables concurrency between readers so long as
+// the read critical section is long. Concurrent readers will experience contention on read().lock() and
+// read().unlock() if the work inside the critical section is short. The more cores participate in reading,
+// the longer the read critical section has to be for this locking scheme to be profitable.
+
+struct ReadWriteLockBase {
+ WTF_EXPORT_PRIVATE void construct();
+
+ // It's easiest to read lock like this:
+ //
+ // auto locker = holdLock(rwLock.read());
+ //
+ // It's easiest to write lock like this:
+ //
+ // auto locker = holdLock(rwLock.write());
+ //
+ WTF_EXPORT_PRIVATE void readLock();
+ WTF_EXPORT_PRIVATE void readUnlock();
+ WTF_EXPORT_PRIVATE void writeLock();
+ WTF_EXPORT_PRIVATE void writeUnlock();
+
+ class ReadLock;
+ class WriteLock;
+
+ ReadLock& read();
+ WriteLock& write();
+
+private:
+ // These fields must work when zero-filled, so that StaticReadWriteLock works.
+ LockBase m_lock;
+ ConditionBase m_cond;
+ bool m_isWriteLocked;
+ unsigned m_numReaders;
+ unsigned m_numWaitingWriters;
+};
+
+class ReadWriteLockBase::ReadLock : public ReadWriteLockBase {
+public:
+ bool tryLock() { return false; }
+ void lock() { readLock(); }
+ void unlock() { readUnlock(); }
+};
+
+class ReadWriteLockBase::WriteLock : public ReadWriteLockBase {
+public:
+ bool tryLock() { return false; }
+ void lock() { writeLock(); }
+ void unlock() { writeUnlock(); }
+};
+
+inline ReadWriteLockBase::ReadLock& ReadWriteLockBase::read() { return *static_cast<ReadLock*>(this); }
+inline ReadWriteLockBase::WriteLock& ReadWriteLockBase::write() { return *static_cast<WriteLock*>(this); }
+
+class ReadWriteLock : public ReadWriteLockBase {
+public:
+ ReadWriteLock()
+ {
+ construct();
+ }
+};
+
+typedef ReadWriteLockBase StaticReadWriteLock;
+
+} // namespace WTF
+
+using WTF::ReadWriteLock;
+using WTF::StaticReadWriteLock;
+
Modified: trunk/Tools/ChangeLog (220321 => 220322)
--- trunk/Tools/ChangeLog 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Tools/ChangeLog 2017-08-06 04:43:37 UTC (rev 220322)
@@ -1,3 +1,17 @@
+2017-08-05 Filip Pizlo <fpi...@apple.com>
+
+ REGRESSION (r219895-219897): Number of leaks on Open Source went from 9240 to 235983 and is now at 302372
+ https://bugs.webkit.org/show_bug.cgi?id=175083
+
+ Reviewed by Oliver Hunt.
+
+ Leaks results are super confusing if leaks runs while some VMs are destructing. This calls a new SPI
+ to wait for VM destructions to finish before running the next test. This makes it easier to
+ understand leaks results from workers tests, and leads to fewer reported leaks.
+
+ * DumpRenderTree/mac/DumpRenderTree.mm:
+ (runTest):
+
2017-08-05 Yoshiaki Jitsukawa <yoshiaki.jitsuk...@sony.com>
check-webkit-style: fix path-specific rules for WebKit2 rename
Modified: trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm (220321 => 220322)
--- trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm 2017-08-05 23:48:26 UTC (rev 220321)
+++ trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm 2017-08-06 04:43:37 UTC (rev 220322)
@@ -2088,6 +2088,8 @@
if (gcBetweenTests)
[WebCoreStatistics garbageCollectJavaScriptObjects];
+
+ JSC::waitForVMDestruction();
fputs("#EOF\n", stderr);
fflush(stderr);