REGRESSION (r219895-219897): Number of leaks on Open Source went from 9240 to 235983...
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 6 Aug 2017 04:43:37 +0000 (04:43 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 6 Aug 2017 04:43:37 +0000 (04:43 +0000)
https://bugs.webkit.org/show_bug.cgi?id=175083

Reviewed by Oliver Hunt.

Source/JavaScriptCore:

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):

Source/WTF:

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):

Tools:

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):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@220322 268f45cc-cd09-0410-ab3c-d52691b4dbfc

20 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/AccessCase.cpp
Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp
Source/JavaScriptCore/heap/HeapCell.cpp
Source/JavaScriptCore/heap/HeapCellInlines.h
Source/JavaScriptCore/heap/MarkedAllocator.cpp
Source/JavaScriptCore/heap/MarkedBlockInlines.h
Source/JavaScriptCore/jit/AssemblyHelpers.cpp
Source/JavaScriptCore/jit/Repatch.cpp
Source/JavaScriptCore/runtime/TestRunnerUtils.h
Source/JavaScriptCore/runtime/VM.cpp
Source/WTF/ChangeLog
Source/WTF/WTF.xcodeproj/project.pbxproj
Source/WTF/wtf/CMakeLists.txt
Source/WTF/wtf/Condition.h
Source/WTF/wtf/Lock.h
Source/WTF/wtf/ReadWriteLock.cpp [new file with mode: 0644]
Source/WTF/wtf/ReadWriteLock.h [new file with mode: 0644]
Tools/ChangeLog
Tools/DumpRenderTree/mac/DumpRenderTree.mm

index d0cdd39bd4c454ce610095fd399d2187789ef785..a5e26c090e5bc883ccb10f942b51caccea3bbbe5 100644 (file)
@@ -1,3 +1,38 @@
+2017-08-05  Filip Pizlo  <fpizlo@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.lam@apple.com>
 
         Move DFG::OSRExitCompiler methods into DFG::OSRExit [step 3].
index 804204f866446f5da4ad47947e5ae217166b9328..89ac5be9bccff0c015e05499d395ecc7105afffd 100644 (file)
@@ -46,6 +46,7 @@
 #include "ScratchRegisterAllocator.h"
 #include "SlotVisitorInlines.h"
 #include "StructureStubInfo.h"
+#include "SuperSampler.h"
 #include "ThunkGenerators.h"
 
 namespace JSC {
index d2d89d15e091006abe364938206e33f45fdac8ea..fb0b6a9d8c2ddc8fc3f9c9191dbf22b9bd402988 100644 (file)
@@ -38,6 +38,7 @@
 #include "LinkBuffer.h"
 #include "StructureStubClearingWatchpoint.h"
 #include "StructureStubInfo.h"
+#include "SuperSampler.h"
 #include <wtf/CommaPrinter.h>
 #include <wtf/ListDump.h>
 
index edaf50ea5857b11f14c7315839e5033f8b90d819..cd792c1cac38b8c55236b4d9c306c1238f597cfc 100644 (file)
 #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
 {
index bde5e4a873a61d32ce2abdb90e8e5666a5dd2d80..4e6973475b60ae757add0326c14cbae3c7e7dfa5 100644 (file)
 #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));
index f6d203b7b5ab456c5254021a877d92bb806c07d8..aa2144c0f7a923a3ff6799e0a350601abb69f551 100644 (file)
@@ -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 @@ void* MarkedAllocator::tryAllocateWithoutCollecting()
             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 @@ void MarkedAllocator::endMarking()
     // 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
index d262522cd8462b99c9ae2e2ab17473756cc9ab4c..0019ba852c460e65dcb8a4bf3477409ba05c262f 100644 (file)
@@ -223,7 +223,7 @@ void MarkedBlock::Handle::specializedSweep(FreeList* freeList, MarkedBlock::Hand
     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) {
index 8528fe2e66b6e471f9682ced41d3d5768b0e5474..8d31f7a5a8082cfe64784d48d2a555b03c812097 100644 (file)
@@ -32,6 +32,7 @@
 #include "JSCInlines.h"
 #include "LinkBuffer.h"
 #include "MaxFrameExtentForSlowPathCall.h"
+#include "SuperSampler.h"
 #include "ThunkGenerators.h"
 
 #if ENABLE(WEBASSEMBLY)
index e6a2a180373eb73b1b92cf2f0812e26d302d9b0d..7215c40329c054f8d596a9566dc0dced2a175e03 100644 (file)
@@ -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>
index 321ae4ea8cbfba2b3fe9c99a2290bc6a9271483c..b0046dde2b9f91afe77bd6c5d590b7d1e280c0ce 100644 (file)
@@ -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 unsigned numberOfOSRExitFuzzChecks();
 
 JS_EXPORT_PRIVATE void finalizeStatsAtEndOfTesting();
 
+JS_EXPORT_PRIVATE void waitForVMDestruction();
+
 } // namespace JSC
index 9e3fafd1bc7265b6b13ceebbb5b6d81ecca6754a..998c4ab860300e871b6de5b962a29030d9aed461 100644 (file)
 #include "StrictEvalActivation.h"
 #include "StrongInlines.h"
 #include "StructureInlines.h"
+#include "TestRunnerUtils.h"
 #include "ThunkGenerators.h"
 #include "TypeProfiler.h"
 #include "TypeProfilerLog.h"
 #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 @@ VM::VM(VMType vmType, HeapType heapType)
     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)
index 892f4ace5e7735c7b8bb1c9a081df52238463a52..e0e4187c0da8d9897e3e646629ac2ad2a20c5f37 100644 (file)
@@ -1,3 +1,37 @@
+2017-08-05  Filip Pizlo  <fpizlo@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  <jlewis3@apple.com>
 
         Unreviewed, rolling out r220271.
index ca9e3752b7c916ef1e81c67cdf06d61cde9ed154..6af063c99052338ca7f00a5b1c04741dd3ed2f57 100644 (file)
@@ -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 */; };
                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>"; };
                                0F2AC5601E89F70C0001EE3F /* Range.h */,
                                0F725CAB1C50461600AD943A /* RangeSet.h */,
                                0F87105916643F190090B0AD /* RawPointer.h */,
+                               0FEC3C5C1F368A9700F59B6C /* ReadWriteLock.cpp */,
+                               0FEC3C5D1F368A9700F59B6C /* ReadWriteLock.h */,
                                0FDE87F61DFD07CC0064C390 /* RecursiveLockAdapter.h */,
                                A8A472FE151A825B004123FF /* RedBlackTree.h */,
                                26299B6D17A9E5B800ADEBE5 /* Ref.h */,
                                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 */,
index 7f8fb7c95cf9d95aaf1cceed74db443d84592c16..3736824deecbf5873684fde552b72ccd7504c032 100644 (file)
@@ -110,6 +110,7 @@ set(WTF_HEADERS
     Range.h
     RangeSet.h
     RawPointer.h
+    ReadWriteLock.h
     RecursiveLockAdapter.h
     RedBlackTree.h
     Ref.h
@@ -241,6 +242,7 @@ set(WTF_SOURCES
     RAMSize.cpp
     RandomDevice.cpp
     RandomNumber.cpp
+    ReadWriteLock.cpp
     RefCountedLeakCounter.cpp
     RunLoop.cpp
     SHA1.cpp
index 9444f949eedefdff661dbc6a4b1dacdf54e6b75d..fcf32c84d454b06202aa382a00b52bcdf065242d 100644 (file)
@@ -50,6 +50,11 @@ struct ConditionBase {
     // 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 @@ struct ConditionBase {
         ParkingLot::unparkAll(&m_hasWaiters);
     }
     
-protected:
+private:
     Atomic<bool> m_hasWaiters;
 };
 
@@ -177,7 +182,7 @@ class Condition : public ConditionBase {
 public:
     Condition()
     {
-        m_hasWaiters.store(false);
+        construct();
     }
 };
 
index 9dec84c1f00a75c9d735bb281bc11dbbc358f741..95a0ba616e00d4c003be235f044903302f6e3682 100644 (file)
@@ -52,6 +52,11 @@ typedef LockAlgorithm<uint8_t, 1, 2> DefaultLockAlgorithm;
 // 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 @@ struct LockBase {
         return isHeld();
     }
 
-protected:
+private:
     friend struct TestWebKitAPI::LockInspector;
     
     static const uint8_t isHeldBit = 1;
@@ -136,7 +141,7 @@ class Lock : public LockBase {
 public:
     Lock()
     {
-        m_byte.store(0, std::memory_order_relaxed);
+        construct();
     }
 };
 
diff --git a/Source/WTF/wtf/ReadWriteLock.cpp b/Source/WTF/wtf/ReadWriteLock.cpp
new file mode 100644 (file)
index 0000000..4622765
--- /dev/null
@@ -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
+
diff --git a/Source/WTF/wtf/ReadWriteLock.h b/Source/WTF/wtf/ReadWriteLock.h
new file mode 100644 (file)
index 0000000..953c4f2
--- /dev/null
@@ -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;
+
index 60f6527e28337ac3c78535bbf2b6d2c8764e087c..f2d3b1b8795c41d8a86fd85721949caaea81949b 100644 (file)
@@ -1,3 +1,17 @@
+2017-08-05  Filip Pizlo  <fpizlo@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.Jitsukawa@sony.com>
 
         check-webkit-style: fix path-specific rules for WebKit2 rename
index 427e47fa7a2e607f68b818819fbe013f22ea599c..a980d17bce81a5219be51eb037401ace49de987c 100644 (file)
@@ -2088,6 +2088,8 @@ static void runTest(const string& inputLine)
 
     if (gcBetweenTests)
         [WebCoreStatistics garbageCollectJavaScriptObjects];
+    
+    JSC::waitForVMDestruction();
 
     fputs("#EOF\n", stderr);
     fflush(stderr);