Diff
Modified: branches/safari-611-branch/Source/_javascript_Core/ChangeLog (276516 => 276517)
--- branches/safari-611-branch/Source/_javascript_Core/ChangeLog 2021-04-23 21:01:01 UTC (rev 276516)
+++ branches/safari-611-branch/Source/_javascript_Core/ChangeLog 2021-04-23 21:29:59 UTC (rev 276517)
@@ -1,3 +1,100 @@
+2021-04-23 Russell Epstein <[email protected]>
+
+ Cherry-pick r276324. rdar://problem/77086404
+
+ FullGCActivityCallback should use the percentage of pages uncompressed in RAM to determine deferral.
+ https://bugs.webkit.org/show_bug.cgi?id=224817
+
+ Reviewed by Filip Pizlo.
+
+ Source/_javascript_Core:
+
+ Right now we try to determine if too many pages are paged out by
+ dereferencing them and bailing out of the GC if we go over a
+ deadline. While this works if the only goal is to avoid causing
+ extensive thrashing on spinny disks (HDD), it doesn't prevent
+ thrashing when access to disk is fast (e.g. SSD). This is because
+ on fast disks the proportional time to load the memory from disk
+ is much lower. Additionally, on SSDs in particular we don't want
+ to load the pages into RAM then bail as that will force a
+ different page onto disk, increasing wear.
+
+ This patch switches to asking the OS if each MarkedBlock is paged
+ out. Then if we are over a threshold we wait until we would have
+ GC'd anyway. This patch uses the (maxVMGrowthFactor - 1) as the
+ percentage of "slow" pages (paged out or compressed) needed to
+ defer the GC. The idea behind that threshold is that if we add
+ that many pages then the same number of pages would be forced
+ out of RAM for us to do a GC anyway (in the limit).
+
+ * heap/BlockDirectory.cpp:
+ (JSC::BlockDirectory::updatePercentageOfPagedOutPages):
+ (JSC::BlockDirectory::isPagedOut): Deleted.
+ * heap/BlockDirectory.h:
+ * heap/FullGCActivityCallback.cpp:
+ (JSC::FullGCActivityCallback::doCollection):
+ * heap/Heap.cpp:
+ (JSC::Heap::isPagedOut):
+ * heap/Heap.h:
+ * heap/MarkedSpace.cpp:
+ (JSC::MarkedSpace::isPagedOut):
+ * heap/MarkedSpace.h:
+ * runtime/OptionsList.h:
+
+ Source/WebKit:
+
+ Add mincore to the acceptable syscall list.
+
+ * WebProcess/com.apple.WebProcess.sb.in:
+
+ Source/WTF:
+
+ Add a noexcept flavor of FunctionTraits. On Linux mincore (and probably other syscalls) are marked noexcept so the existing overloads don't work.
+
+ * wtf/FunctionTraits.h:
+
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@276324 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2021-04-20 Keith Miller <[email protected]>
+
+ FullGCActivityCallback should use the percentage of pages uncompressed in RAM to determine deferral.
+ https://bugs.webkit.org/show_bug.cgi?id=224817
+
+ Reviewed by Filip Pizlo.
+
+ Right now we try to determine if too many pages are paged out by
+ dereferencing them and bailing out of the GC if we go over a
+ deadline. While this works if the only goal is to avoid causing
+ extensive thrashing on spinny disks (HDD), it doesn't prevent
+ thrashing when access to disk is fast (e.g. SSD). This is because
+ on fast disks the proportional time to load the memory from disk
+ is much lower. Additionally, on SSDs in particular we don't want
+ to load the pages into RAM then bail as that will force a
+ different page onto disk, increasing wear.
+
+ This patch switches to asking the OS if each MarkedBlock is paged
+ out. Then if we are over a threshold we wait until we would have
+ GC'd anyway. This patch uses the (maxVMGrowthFactor - 1) as the
+ percentage of "slow" pages (paged out or compressed) needed to
+ defer the GC. The idea behind that threshold is that if we add
+ that many pages then the same number of pages would be forced
+ out of RAM for us to do a GC anyway (in the limit).
+
+ * heap/BlockDirectory.cpp:
+ (JSC::BlockDirectory::updatePercentageOfPagedOutPages):
+ (JSC::BlockDirectory::isPagedOut): Deleted.
+ * heap/BlockDirectory.h:
+ * heap/FullGCActivityCallback.cpp:
+ (JSC::FullGCActivityCallback::doCollection):
+ * heap/Heap.cpp:
+ (JSC::Heap::isPagedOut):
+ * heap/Heap.h:
+ * heap/MarkedSpace.cpp:
+ (JSC::MarkedSpace::isPagedOut):
+ * heap/MarkedSpace.h:
+ * runtime/OptionsList.h:
+
2021-04-16 Alan Coon <[email protected]>
Cherry-pick r276155. rdar://problem/76781047
Modified: branches/safari-611-branch/Source/_javascript_Core/heap/BlockDirectory.cpp (276516 => 276517)
--- branches/safari-611-branch/Source/_javascript_Core/heap/BlockDirectory.cpp 2021-04-23 21:01:01 UTC (rev 276516)
+++ branches/safari-611-branch/Source/_javascript_Core/heap/BlockDirectory.cpp 2021-04-23 21:29:59 UTC (rev 276517)
@@ -31,6 +31,9 @@
#include "SubspaceInlines.h"
#include "SuperSampler.h"
+#include <wtf/FunctionTraits.h>
+#include <wtf/SimpleStats.h>
+
namespace JSC {
DEFINE_ALLOCATOR_WITH_HEAP_IDENTIFIER(BlockDirectory);
@@ -53,21 +56,35 @@
m_subspace = subspace;
}
-bool BlockDirectory::isPagedOut(MonotonicTime deadline)
+void BlockDirectory::updatePercentageOfPagedOutPages(SimpleStats& stats)
{
- unsigned itersSinceLastTimeCheck = 0;
- for (auto* block : m_blocks) {
- if (block)
- block->block().populatePage();
- ++itersSinceLastTimeCheck;
- if (itersSinceLastTimeCheck >= Heap::s_timeCheckResolution) {
- MonotonicTime currentTime = MonotonicTime::now();
- if (currentTime > deadline)
- return true;
- itersSinceLastTimeCheck = 0;
- }
+ // FIXME: We should figure out a solution for Windows.
+#if OS(UNIX)
+ size_t pageSize = WTF::pageSize();
+ ASSERT(!(MarkedBlock::blockSize % pageSize));
+ auto numberOfPagesInMarkedBlock = MarkedBlock::blockSize / pageSize;
+ // For some reason this can be unsigned char or char on different OSes...
+ using MincoreBufferType = std::remove_pointer_t<FunctionTraits<decltype(mincore)>::ArgumentType<2>>;
+ static_assert(std::is_same_v<std::make_unsigned_t<MincoreBufferType>, unsigned char>);
+ // pageSize is effectively a constant so this isn't really variable.
+ IGNORE_CLANG_WARNINGS_BEGIN("vla")
+ MincoreBufferType pagedBits[numberOfPagesInMarkedBlock];
+ IGNORE_CLANG_WARNINGS_END
+
+ for (auto* handle : m_blocks) {
+ if (!handle)
+ continue;
+
+ auto markedBlockSizeInBytes = static_cast<size_t>(reinterpret_cast<char*>(handle->end()) - reinterpret_cast<char*>(handle->start()));
+ RELEASE_ASSERT(markedBlockSizeInBytes / pageSize <= numberOfPagesInMarkedBlock);
+ // We could cache this in bulk (e.g. 25 MB chunks) but we haven't seen any data that it actually matters.
+ auto result = mincore(handle->start(), markedBlockSizeInBytes, pagedBits);
+ RELEASE_ASSERT(!result);
+ constexpr unsigned pageIsResidentAndNotCompressed = 1;
+ for (unsigned i = 0; i < numberOfPagesInMarkedBlock; ++i)
+ stats.add(!(pagedBits[i] & pageIsResidentAndNotCompressed));
}
- return false;
+#endif
}
MarkedBlock::Handle* BlockDirectory::findEmptyBlockToSteal()
Modified: branches/safari-611-branch/Source/_javascript_Core/heap/BlockDirectory.h (276516 => 276517)
--- branches/safari-611-branch/Source/_javascript_Core/heap/BlockDirectory.h 2021-04-23 21:01:01 UTC (rev 276516)
+++ branches/safari-611-branch/Source/_javascript_Core/heap/BlockDirectory.h 2021-04-23 21:29:59 UTC (rev 276517)
@@ -37,6 +37,10 @@
#include <wtf/SharedTask.h>
#include <wtf/Vector.h>
+namespace WTF {
+class SimpleStats;
+}
+
namespace JSC {
class GCDeferralContext;
@@ -87,7 +91,7 @@
// If WillDeleteBlock::Yes is passed then the block will be left in an invalid state. We do this, however, to avoid potentially paging in / decompressing old blocks to update their handle just before freeing them.
void removeBlock(MarkedBlock::Handle*, WillDeleteBlock = WillDeleteBlock::No);
- bool isPagedOut(MonotonicTime deadline);
+ void updatePercentageOfPagedOutPages(WTF::SimpleStats&);
Lock& bitvectorLock() { return m_bitvectorLock; }
Modified: branches/safari-611-branch/Source/_javascript_Core/heap/FullGCActivityCallback.cpp (276516 => 276517)
--- branches/safari-611-branch/Source/_javascript_Core/heap/FullGCActivityCallback.cpp 2021-04-23 21:01:01 UTC (rev 276516)
+++ branches/safari-611-branch/Source/_javascript_Core/heap/FullGCActivityCallback.cpp 2021-04-23 21:29:59 UTC (rev 276517)
@@ -30,10 +30,6 @@
namespace JSC {
-#if !PLATFORM(IOS_FAMILY)
-const constexpr Seconds pagingTimeOut { 100_ms }; // Time in seconds to allow opportunistic timer to iterate over all blocks to see if the Heap is paged out.
-#endif
-
FullGCActivityCallback::FullGCActivityCallback(Heap* heap)
: GCActivityCallback(heap)
{
@@ -44,11 +40,11 @@
Heap& heap = vm.heap;
m_didGCRecently = false;
-#if !PLATFORM(IOS_FAMILY)
+#if !PLATFORM(IOS_FAMILY) || PLATFORM(MACCATALYST)
MonotonicTime startTime = MonotonicTime::now();
- if (heap.isPagedOut(startTime + pagingTimeOut)) {
+ if (heap.isPagedOut()) {
cancel();
- heap.increaseLastFullGCLength(pagingTimeOut);
+ heap.increaseLastFullGCLength(MonotonicTime::now() - startTime);
return;
}
#endif
Modified: branches/safari-611-branch/Source/_javascript_Core/heap/Heap.cpp (276516 => 276517)
--- branches/safari-611-branch/Source/_javascript_Core/heap/Heap.cpp 2021-04-23 21:01:01 UTC (rev 276516)
+++ branches/safari-611-branch/Source/_javascript_Core/heap/Heap.cpp 2021-04-23 21:29:59 UTC (rev 276517)
@@ -354,9 +354,9 @@
WeakBlock::destroy(*this, block);
}
-bool Heap::isPagedOut(MonotonicTime deadline)
+bool Heap::isPagedOut()
{
- return m_objectSpace.isPagedOut(deadline);
+ return m_objectSpace.isPagedOut();
}
void Heap::dumpHeapStatisticsAtVMDestruction()
Modified: branches/safari-611-branch/Source/_javascript_Core/heap/Heap.h (276516 => 276517)
--- branches/safari-611-branch/Source/_javascript_Core/heap/Heap.h 2021-04-23 21:01:01 UTC (rev 276516)
+++ branches/safari-611-branch/Source/_javascript_Core/heap/Heap.h 2021-04-23 21:29:59 UTC (rev 276517)
@@ -271,7 +271,7 @@
void deleteAllUnlinkedCodeBlocks(DeleteAllCodeEffort);
void didAllocate(size_t);
- bool isPagedOut(MonotonicTime deadline);
+ bool isPagedOut();
const JITStubRoutineSet& jitStubRoutines() { return *m_jitStubRoutines; }
Modified: branches/safari-611-branch/Source/_javascript_Core/heap/MarkedSpace.cpp (276516 => 276517)
--- branches/safari-611-branch/Source/_javascript_Core/heap/MarkedSpace.cpp 2021-04-23 21:01:01 UTC (rev 276516)
+++ branches/safari-611-branch/Source/_javascript_Core/heap/MarkedSpace.cpp 2021-04-23 21:29:59 UTC (rev 276517)
@@ -27,6 +27,7 @@
#include "MarkedBlockInlines.h"
#include "MarkedSpaceInlines.h"
#include <wtf/ListDump.h>
+#include <wtf/SimpleStats.h>
namespace JSC {
@@ -354,19 +355,19 @@
// Nothing to do for PreciseAllocations.
}
-bool MarkedSpace::isPagedOut(MonotonicTime deadline)
+bool MarkedSpace::isPagedOut()
{
- bool result = false;
+ SimpleStats pagedOutPagesStats;
+
forEachDirectory(
[&] (BlockDirectory& directory) -> IterationStatus {
- if (directory.isPagedOut(deadline)) {
- result = true;
- return IterationStatus::Done;
- }
+ directory.updatePercentageOfPagedOutPages(pagedOutPagesStats);
return IterationStatus::Continue;
});
// FIXME: Consider taking PreciseAllocations into account here.
- return result;
+ double maxHeapGrowthFactor = VM::isInMiniMode() ? Options::miniVMHeapGrowthFactor() : Options::largeHeapGrowthFactor();
+ double bailoutPercentage = Options::customFullGCCallbackBailThreshold() == -1.0 ? maxHeapGrowthFactor - 1 : Options::customFullGCCallbackBailThreshold();
+ return pagedOutPagesStats.mean() > pagedOutPagesStats.count() * bailoutPercentage;
}
void MarkedSpace::freeBlock(MarkedBlock::Handle* block)
Modified: branches/safari-611-branch/Source/_javascript_Core/heap/MarkedSpace.h (276516 => 276517)
--- branches/safari-611-branch/Source/_javascript_Core/heap/MarkedSpace.h 2021-04-23 21:01:01 UTC (rev 276516)
+++ branches/safari-611-branch/Source/_javascript_Core/heap/MarkedSpace.h 2021-04-23 21:29:59 UTC (rev 276517)
@@ -148,7 +148,7 @@
size_t size();
size_t capacity();
- bool isPagedOut(MonotonicTime deadline);
+ bool isPagedOut();
HeapVersion markingVersion() const { return m_markingVersion; }
HeapVersion newlyAllocatedVersion() const { return m_newlyAllocatedVersion; }
Modified: branches/safari-611-branch/Source/_javascript_Core/runtime/OptionsList.h (276516 => 276517)
--- branches/safari-611-branch/Source/_javascript_Core/runtime/OptionsList.h 2021-04-23 21:01:01 UTC (rev 276516)
+++ branches/safari-611-branch/Source/_javascript_Core/runtime/OptionsList.h 2021-04-23 21:29:59 UTC (rev 276517)
@@ -198,6 +198,7 @@
v(Double, largeHeapGrowthFactor, 1.24, Normal, nullptr) \
v(Double, miniVMHeapGrowthFactor, 1.27, Normal, nullptr) \
v(Double, criticalGCMemoryThreshold, 0.80, Normal, "percent memory in use the GC considers critical. The collector is much more aggressive above this threshold") \
+ v(Double, customFullGCCallbackBailThreshold, -1.0, Normal, "percent of memory paged out before we bail out of timer based Full GCs. -1.0 means use (maxHeapGrowthFactor - 1)") \
v(Double, minimumMutatorUtilization, 0, Normal, nullptr) \
v(Double, maximumMutatorUtilization, 0.7, Normal, nullptr) \
v(Double, epsilonMutatorUtilization, 0.01, Normal, nullptr) \
Modified: branches/safari-611-branch/Source/WTF/ChangeLog (276516 => 276517)
--- branches/safari-611-branch/Source/WTF/ChangeLog 2021-04-23 21:01:01 UTC (rev 276516)
+++ branches/safari-611-branch/Source/WTF/ChangeLog 2021-04-23 21:29:59 UTC (rev 276517)
@@ -1,3 +1,72 @@
+2021-04-23 Russell Epstein <[email protected]>
+
+ Cherry-pick r276324. rdar://problem/77086404
+
+ FullGCActivityCallback should use the percentage of pages uncompressed in RAM to determine deferral.
+ https://bugs.webkit.org/show_bug.cgi?id=224817
+
+ Reviewed by Filip Pizlo.
+
+ Source/_javascript_Core:
+
+ Right now we try to determine if too many pages are paged out by
+ dereferencing them and bailing out of the GC if we go over a
+ deadline. While this works if the only goal is to avoid causing
+ extensive thrashing on spinny disks (HDD), it doesn't prevent
+ thrashing when access to disk is fast (e.g. SSD). This is because
+ on fast disks the proportional time to load the memory from disk
+ is much lower. Additionally, on SSDs in particular we don't want
+ to load the pages into RAM then bail as that will force a
+ different page onto disk, increasing wear.
+
+ This patch switches to asking the OS if each MarkedBlock is paged
+ out. Then if we are over a threshold we wait until we would have
+ GC'd anyway. This patch uses the (maxVMGrowthFactor - 1) as the
+ percentage of "slow" pages (paged out or compressed) needed to
+ defer the GC. The idea behind that threshold is that if we add
+ that many pages then the same number of pages would be forced
+ out of RAM for us to do a GC anyway (in the limit).
+
+ * heap/BlockDirectory.cpp:
+ (JSC::BlockDirectory::updatePercentageOfPagedOutPages):
+ (JSC::BlockDirectory::isPagedOut): Deleted.
+ * heap/BlockDirectory.h:
+ * heap/FullGCActivityCallback.cpp:
+ (JSC::FullGCActivityCallback::doCollection):
+ * heap/Heap.cpp:
+ (JSC::Heap::isPagedOut):
+ * heap/Heap.h:
+ * heap/MarkedSpace.cpp:
+ (JSC::MarkedSpace::isPagedOut):
+ * heap/MarkedSpace.h:
+ * runtime/OptionsList.h:
+
+ Source/WebKit:
+
+ Add mincore to the acceptable syscall list.
+
+ * WebProcess/com.apple.WebProcess.sb.in:
+
+ Source/WTF:
+
+ Add a noexcept flavor of FunctionTraits. On Linux mincore (and probably other syscalls) are marked noexcept so the existing overloads don't work.
+
+ * wtf/FunctionTraits.h:
+
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@276324 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2021-04-20 Keith Miller <[email protected]>
+
+ FullGCActivityCallback should use the percentage of pages uncompressed in RAM to determine deferral.
+ https://bugs.webkit.org/show_bug.cgi?id=224817
+
+ Reviewed by Filip Pizlo.
+
+ Add a noexcept flavor of FunctionTraits. On Linux mincore (and probably other syscalls) are marked noexcept so the existing overloads don't work.
+
+ * wtf/FunctionTraits.h:
+
2021-04-08 Russell Epstein <[email protected]>
Cherry-pick r275003. rdar://problem/76411341
Modified: branches/safari-611-branch/Source/WTF/wtf/FunctionTraits.h (276516 => 276517)
--- branches/safari-611-branch/Source/WTF/wtf/FunctionTraits.h 2021-04-23 21:01:01 UTC (rev 276516)
+++ branches/safari-611-branch/Source/WTF/wtf/FunctionTraits.h 2021-04-23 21:29:59 UTC (rev 276517)
@@ -80,6 +80,14 @@
struct FunctionTraits<Result(*)(Args...)> : public FunctionTraits<Result(Args...)> {
};
+template<typename Result, typename... Args>
+struct FunctionTraits<Result(Args...) noexcept> : public FunctionTraits<Result(Args...)> {
+};
+
+template<typename Result, typename... Args>
+struct FunctionTraits<Result(*)(Args...) noexcept> : public FunctionTraits<Result(Args...)> {
+};
+
} // namespace WTF
using WTF::FunctionTraits;
Modified: branches/safari-611-branch/Source/WebKit/ChangeLog (276516 => 276517)
--- branches/safari-611-branch/Source/WebKit/ChangeLog 2021-04-23 21:01:01 UTC (rev 276516)
+++ branches/safari-611-branch/Source/WebKit/ChangeLog 2021-04-23 21:29:59 UTC (rev 276517)
@@ -1,5 +1,74 @@
2021-04-23 Russell Epstein <[email protected]>
+ Cherry-pick r276324. rdar://problem/77086404
+
+ FullGCActivityCallback should use the percentage of pages uncompressed in RAM to determine deferral.
+ https://bugs.webkit.org/show_bug.cgi?id=224817
+
+ Reviewed by Filip Pizlo.
+
+ Source/_javascript_Core:
+
+ Right now we try to determine if too many pages are paged out by
+ dereferencing them and bailing out of the GC if we go over a
+ deadline. While this works if the only goal is to avoid causing
+ extensive thrashing on spinny disks (HDD), it doesn't prevent
+ thrashing when access to disk is fast (e.g. SSD). This is because
+ on fast disks the proportional time to load the memory from disk
+ is much lower. Additionally, on SSDs in particular we don't want
+ to load the pages into RAM then bail as that will force a
+ different page onto disk, increasing wear.
+
+ This patch switches to asking the OS if each MarkedBlock is paged
+ out. Then if we are over a threshold we wait until we would have
+ GC'd anyway. This patch uses the (maxVMGrowthFactor - 1) as the
+ percentage of "slow" pages (paged out or compressed) needed to
+ defer the GC. The idea behind that threshold is that if we add
+ that many pages then the same number of pages would be forced
+ out of RAM for us to do a GC anyway (in the limit).
+
+ * heap/BlockDirectory.cpp:
+ (JSC::BlockDirectory::updatePercentageOfPagedOutPages):
+ (JSC::BlockDirectory::isPagedOut): Deleted.
+ * heap/BlockDirectory.h:
+ * heap/FullGCActivityCallback.cpp:
+ (JSC::FullGCActivityCallback::doCollection):
+ * heap/Heap.cpp:
+ (JSC::Heap::isPagedOut):
+ * heap/Heap.h:
+ * heap/MarkedSpace.cpp:
+ (JSC::MarkedSpace::isPagedOut):
+ * heap/MarkedSpace.h:
+ * runtime/OptionsList.h:
+
+ Source/WebKit:
+
+ Add mincore to the acceptable syscall list.
+
+ * WebProcess/com.apple.WebProcess.sb.in:
+
+ Source/WTF:
+
+ Add a noexcept flavor of FunctionTraits. On Linux mincore (and probably other syscalls) are marked noexcept so the existing overloads don't work.
+
+ * wtf/FunctionTraits.h:
+
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@276324 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2021-04-20 Keith Miller <[email protected]>
+
+ FullGCActivityCallback should use the percentage of pages uncompressed in RAM to determine deferral.
+ https://bugs.webkit.org/show_bug.cgi?id=224817
+
+ Reviewed by Filip Pizlo.
+
+ Add mincore to the acceptable syscall list.
+
+ * WebProcess/com.apple.WebProcess.sb.in:
+
+2021-04-23 Russell Epstein <[email protected]>
+
Cherry-pick r276482. rdar://problem/77074513
[Mac] CMBaseClass object pointers can become unaligned on x86
Modified: branches/safari-611-branch/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in (276516 => 276517)
--- branches/safari-611-branch/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in 2021-04-23 21:01:01 UTC (rev 276516)
+++ branches/safari-611-branch/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in 2021-04-23 21:29:59 UTC (rev 276517)
@@ -1515,6 +1515,7 @@
(syscall-number SYS_munmap)
(syscall-number SYS_mprotect)
(syscall-number SYS_madvise)
+ (syscall-number SYS_mincore)
(syscall-number SYS_fcntl)
(syscall-number SYS_select)
(syscall-number SYS_fsync)