WebKit Bugzilla
Attachment 347749 Details for
Bug 188832
: REGRESSION(r235107): "It revealed bugs in Blob code as well as regressed JS performance tests" (Requested by saamyjoon on #webkit).
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
ROLLOUT of r235107
bug-188832-20180821212210.patch (text/plain), 48.64 KB, created by
WebKit Commit Bot
on 2018-08-21 18:22:11 PDT
(
hide
)
Description:
ROLLOUT of r235107
Filename:
MIME Type:
Creator:
WebKit Commit Bot
Created:
2018-08-21 18:22:11 PDT
Size:
48.64 KB
patch
obsolete
>Subversion Revision: 235151 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index ea61d673cd31c627ba7f2a35938cbd704005e2c7..31482bbe78ca947d69fcb5905ac10b864d4924e4 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,18 @@ >+2018-08-21 Commit Queue <commit-queue@webkit.org> >+ >+ Unreviewed, rolling out r235107. >+ https://bugs.webkit.org/show_bug.cgi?id=188832 >+ >+ "It revealed bugs in Blob code as well as regressed JS >+ performance tests" (Requested by saamyjoon on #webkit). >+ >+ Reverted changeset: >+ >+ "JSRunLoopTimer may run part of a member function after it's >+ destroyed" >+ https://bugs.webkit.org/show_bug.cgi?id=188426 >+ https://trac.webkit.org/changeset/235107 >+ > 2018-08-21 Saam barati <sbarati@apple.com> > > JSRunLoopTimer may run part of a member function after it's destroyed >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index cc7d46d77fd9f44531295b201165274366ebff45..603644c7b0d8706961f4c29bfb100042af052b42 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,18 @@ >+2018-08-21 Commit Queue <commit-queue@webkit.org> >+ >+ Unreviewed, rolling out r235107. >+ https://bugs.webkit.org/show_bug.cgi?id=188832 >+ >+ "It revealed bugs in Blob code as well as regressed JS >+ performance tests" (Requested by saamyjoon on #webkit). >+ >+ Reverted changeset: >+ >+ "JSRunLoopTimer may run part of a member function after it's >+ destroyed" >+ https://bugs.webkit.org/show_bug.cgi?id=188426 >+ https://trac.webkit.org/changeset/235107 >+ > 2018-08-21 Megan Gardner <megan_gardner@apple.com> > > Use VisiblePosition to calculate selection ranges >diff --git a/Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp b/Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp >index 0ca5014fe64c4780d3348ac1e5d93be0d5922083..b6bde3dd17f85d40c297cd36d477107ef0fd5ae1 100644 >--- a/Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp >+++ b/Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp >@@ -36,20 +36,21 @@ EdenGCActivityCallback::EdenGCActivityCallback(Heap* heap) > { > } > >-void EdenGCActivityCallback::doCollection(VM& vm) >+void EdenGCActivityCallback::doCollection() > { >- vm.heap.collectAsync(CollectionScope::Eden); >+ m_vm->heap.collectAsync(CollectionScope::Eden); > } > >-Seconds EdenGCActivityCallback::lastGCLength(Heap& heap) >+Seconds EdenGCActivityCallback::lastGCLength() > { >- return heap.lastEdenGCLength(); >+ return m_vm->heap.lastEdenGCLength(); > } > >-double EdenGCActivityCallback::deathRate(Heap& heap) >+double EdenGCActivityCallback::deathRate() > { >- size_t sizeBefore = heap.sizeBeforeLastEdenCollection(); >- size_t sizeAfter = heap.sizeAfterLastEdenCollection(); >+ Heap* heap = &m_vm->heap; >+ size_t sizeBefore = heap->sizeBeforeLastEdenCollection(); >+ size_t sizeAfter = heap->sizeAfterLastEdenCollection(); > if (!sizeBefore) > return 1.0; > if (sizeAfter > sizeBefore) { >diff --git a/Source/JavaScriptCore/heap/EdenGCActivityCallback.h b/Source/JavaScriptCore/heap/EdenGCActivityCallback.h >index 52e0a28fe3c90cf9f2f8185779a76ff1925375cc..87482bdfb30186c016b1a6a84cbaed992709fc96 100644 >--- a/Source/JavaScriptCore/heap/EdenGCActivityCallback.h >+++ b/Source/JavaScriptCore/heap/EdenGCActivityCallback.h >@@ -33,12 +33,12 @@ class JS_EXPORT_PRIVATE EdenGCActivityCallback : public GCActivityCallback { > public: > EdenGCActivityCallback(Heap*); > >- void doCollection(VM&) override; >+ void doCollection() override; > > protected: >- Seconds lastGCLength(Heap&) override; >+ Seconds lastGCLength() override; > double gcTimeSlice(size_t bytes) override; >- double deathRate(Heap&) override; >+ double deathRate() override; > }; > > inline RefPtr<GCActivityCallback> GCActivityCallback::createEdenTimer(Heap* heap) >diff --git a/Source/JavaScriptCore/heap/FullGCActivityCallback.cpp b/Source/JavaScriptCore/heap/FullGCActivityCallback.cpp >index c9ef7fe1224cc3942c29e2bd578c97dd3f7cb866..d998a29d526b6f1756831bfb375dc72cf613bc77 100644 >--- a/Source/JavaScriptCore/heap/FullGCActivityCallback.cpp >+++ b/Source/JavaScriptCore/heap/FullGCActivityCallback.cpp >@@ -39,9 +39,9 @@ FullGCActivityCallback::FullGCActivityCallback(Heap* heap) > { > } > >-void FullGCActivityCallback::doCollection(VM& vm) >+void FullGCActivityCallback::doCollection() > { >- Heap& heap = vm.heap; >+ Heap& heap = m_vm->heap; > m_didGCRecently = false; > > #if !PLATFORM(IOS) >@@ -56,15 +56,16 @@ void FullGCActivityCallback::doCollection(VM& vm) > heap.collectAsync(CollectionScope::Full); > } > >-Seconds FullGCActivityCallback::lastGCLength(Heap& heap) >+Seconds FullGCActivityCallback::lastGCLength() > { >- return heap.lastFullGCLength(); >+ return m_vm->heap.lastFullGCLength(); > } > >-double FullGCActivityCallback::deathRate(Heap& heap) >+double FullGCActivityCallback::deathRate() > { >- size_t sizeBefore = heap.sizeBeforeLastFullCollection(); >- size_t sizeAfter = heap.sizeAfterLastFullCollection(); >+ Heap* heap = &m_vm->heap; >+ size_t sizeBefore = heap->sizeBeforeLastFullCollection(); >+ size_t sizeAfter = heap->sizeAfterLastFullCollection(); > if (!sizeBefore) > return 1.0; > if (sizeAfter > sizeBefore) { >diff --git a/Source/JavaScriptCore/heap/FullGCActivityCallback.h b/Source/JavaScriptCore/heap/FullGCActivityCallback.h >index 5ce034a0cd81f55d298f1289826de6f8bef62bba..da89c7d3778c4fb0d801ff9b7e40e01d452b077a 100644 >--- a/Source/JavaScriptCore/heap/FullGCActivityCallback.h >+++ b/Source/JavaScriptCore/heap/FullGCActivityCallback.h >@@ -33,15 +33,15 @@ class JS_EXPORT_PRIVATE FullGCActivityCallback : public GCActivityCallback { > public: > FullGCActivityCallback(Heap*); > >- void doCollection(VM&) override; >+ void doCollection() override; > > bool didGCRecently() const { return m_didGCRecently; } > void setDidGCRecently() { m_didGCRecently = true; } > > protected: >- Seconds lastGCLength(Heap&) override; >+ Seconds lastGCLength() override; > double gcTimeSlice(size_t bytes) override; >- double deathRate(Heap&) override; >+ double deathRate() override; > > bool m_didGCRecently { false }; > }; >diff --git a/Source/JavaScriptCore/heap/GCActivityCallback.cpp b/Source/JavaScriptCore/heap/GCActivityCallback.cpp >index e5a78027a20dba9ac8c78f72354fc6721b737ace..007fdd8133871cccf35bab62cf7d55ed83bda9c0 100644 >--- a/Source/JavaScriptCore/heap/GCActivityCallback.cpp >+++ b/Source/JavaScriptCore/heap/GCActivityCallback.cpp >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2010-2018 Apple Inc. All rights reserved. >+ * Copyright (C) 2010-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 >@@ -45,52 +45,83 @@ GCActivityCallback::GCActivityCallback(Heap* heap) > { > } > >-void GCActivityCallback::doWork(VM& vm) >+void GCActivityCallback::doWork() > { >+ Heap* heap = &m_vm->heap; > if (!isEnabled()) > return; > >- ASSERT(vm.currentThreadIsHoldingAPILock()); >- Heap& heap = vm.heap; >- if (heap.isDeferred()) { >+ JSLockHolder locker(m_vm); >+ if (heap->isDeferred()) { > scheduleTimer(0_s); > return; > } > >- doCollection(vm); >+ doCollection(); > } > >+#if USE(CF) > void GCActivityCallback::scheduleTimer(Seconds newDelay) > { > if (newDelay * timerSlop > m_delay) > return; > Seconds delta = m_delay - newDelay; > m_delay = newDelay; >- if (auto timeUntilFire = this->timeUntilFire()) >- setTimeUntilFire(*timeUntilFire - delta); >- else >- setTimeUntilFire(delta); >+ CFRunLoopTimerSetNextFireDate(m_timer.get(), CFRunLoopTimerGetNextFireDate(m_timer.get()) - delta.seconds()); > } > >-void GCActivityCallback::didAllocate(Heap& heap, size_t bytes) >+void GCActivityCallback::cancelTimer() >+{ >+ m_delay = s_decade; >+ CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + s_decade.seconds()); >+} >+ >+MonotonicTime GCActivityCallback::nextFireTime() >+{ >+ return MonotonicTime::now() + Seconds(CFRunLoopTimerGetNextFireDate(m_timer.get()) - CFAbsoluteTimeGetCurrent()); >+} >+#else >+void GCActivityCallback::scheduleTimer(Seconds newDelay) >+{ >+ if (newDelay * timerSlop > m_delay) >+ return; >+ Seconds delta = m_delay - newDelay; >+ m_delay = newDelay; >+ >+ Seconds secondsUntilFire = m_timer.secondsUntilFire(); >+ m_timer.startOneShot(std::max<Seconds>(secondsUntilFire - delta, 0_s)); >+} >+ >+void GCActivityCallback::cancelTimer() >+{ >+ m_delay = s_decade; >+ m_timer.startOneShot(s_decade); >+} >+ >+MonotonicTime GCActivityCallback::nextFireTime() >+{ >+ return MonotonicTime::now() + m_timer.secondsUntilFire(); >+} >+#endif >+ >+void GCActivityCallback::didAllocate(size_t bytes) > { > // The first byte allocated in an allocation cycle will report 0 bytes to didAllocate. > // We pretend it's one byte so that we don't ignore this allocation entirely. > if (!bytes) > bytes = 1; >- double bytesExpectedToReclaim = static_cast<double>(bytes) * deathRate(heap); >- Seconds newDelay = lastGCLength(heap) / gcTimeSlice(bytesExpectedToReclaim); >+ double bytesExpectedToReclaim = static_cast<double>(bytes) * deathRate(); >+ Seconds newDelay = lastGCLength() / gcTimeSlice(bytesExpectedToReclaim); > scheduleTimer(newDelay); > } > > void GCActivityCallback::willCollect() > { >- cancel(); >+ cancelTimer(); > } > > void GCActivityCallback::cancel() > { >- m_delay = s_decade; > cancelTimer(); > } > >diff --git a/Source/JavaScriptCore/heap/GCActivityCallback.h b/Source/JavaScriptCore/heap/GCActivityCallback.h >index 9dfdd0f7007d213b4fb95449b16efedd8e4c3a36..4b4067610c193e52ee1ebab7142725d3674a4580 100644 >--- a/Source/JavaScriptCore/heap/GCActivityCallback.h >+++ b/Source/JavaScriptCore/heap/GCActivityCallback.h >@@ -48,22 +48,24 @@ public: > > GCActivityCallback(Heap*); > >- void doWork(VM&) override; >+ void doWork() override; > >- virtual void doCollection(VM&) = 0; >+ virtual void doCollection() = 0; > >- void didAllocate(Heap&, size_t); >- void willCollect(); >- void cancel(); >+ virtual void didAllocate(size_t); >+ virtual void willCollect(); >+ virtual void cancel(); > bool isEnabled() const { return m_enabled; } > void setEnabled(bool enabled) { m_enabled = enabled; } > > static bool s_shouldCreateGCTimer; > >+ MonotonicTime nextFireTime(); >+ > protected: >- virtual Seconds lastGCLength(Heap&) = 0; >+ virtual Seconds lastGCLength() = 0; > virtual double gcTimeSlice(size_t bytes) = 0; >- virtual double deathRate(Heap&) = 0; >+ virtual double deathRate() = 0; > > GCActivityCallback(VM* vm) > : Base(vm) >@@ -75,6 +77,7 @@ protected: > bool m_enabled; > > protected: >+ void cancelTimer(); > void scheduleTimer(Seconds); > > private: >diff --git a/Source/JavaScriptCore/heap/Heap.cpp b/Source/JavaScriptCore/heap/Heap.cpp >index f84f7e64442b6454c6fba4ef22c95f010b8f6130..c782fcbb7051dbd65b13dedfa526626b67c73c5f 100644 >--- a/Source/JavaScriptCore/heap/Heap.cpp >+++ b/Source/JavaScriptCore/heap/Heap.cpp >@@ -539,7 +539,7 @@ void Heap::reportAbandonedObjectGraph() > // be more profitable. Since allocation is the trigger for collection, > // we hasten the next collection by pretending that we've allocated more memory. > if (m_fullActivityCallback) { >- m_fullActivityCallback->didAllocate(*this, >+ m_fullActivityCallback->didAllocate( > m_sizeAfterLastCollect - m_sizeAfterLastFullCollect + m_bytesAllocatedThisCycle + m_bytesAbandonedSinceLastFullCollect); > } > m_bytesAbandonedSinceLastFullCollect += abandonedBytes; >@@ -2194,7 +2194,7 @@ void Heap::notifyIncrementalSweeper() > m_indexOfNextLogicallyEmptyWeakBlockToSweep = 0; > } > >- m_sweeper->startSweeping(*this); >+ m_sweeper->startSweeping(); > } > > void Heap::updateAllocationLimits() >@@ -2273,7 +2273,7 @@ void Heap::updateAllocationLimits() > dataLog("Eden: maxEdenSize = ", m_maxEdenSize, "\n"); > if (m_fullActivityCallback) { > ASSERT(currentHeapSize >= m_sizeAfterLastFullCollect); >- m_fullActivityCallback->didAllocate(*this, currentHeapSize - m_sizeAfterLastFullCollect); >+ m_fullActivityCallback->didAllocate(currentHeapSize - m_sizeAfterLastFullCollect); > } > } > >@@ -2354,7 +2354,7 @@ void Heap::setGarbageCollectionTimerEnabled(bool enable) > void Heap::didAllocate(size_t bytes) > { > if (m_edenActivityCallback) >- m_edenActivityCallback->didAllocate(*this, m_bytesAllocatedThisCycle + m_bytesAbandonedSinceLastFullCollect); >+ m_edenActivityCallback->didAllocate(m_bytesAllocatedThisCycle + m_bytesAbandonedSinceLastFullCollect); > m_bytesAllocatedThisCycle += bytes; > performIncrement(bytes); > } >diff --git a/Source/JavaScriptCore/heap/IncrementalSweeper.cpp b/Source/JavaScriptCore/heap/IncrementalSweeper.cpp >index 22d8393726f2b50052c8de79605bb86ae07827ad..e5e49dd8ea495803afda8d1aaae2078e4dc9cc5a 100644 >--- a/Source/JavaScriptCore/heap/IncrementalSweeper.cpp >+++ b/Source/JavaScriptCore/heap/IncrementalSweeper.cpp >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2012-2018 Apple Inc. All rights reserved. >+ * Copyright (C) 2012, 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 >@@ -34,13 +34,13 @@ > > namespace JSC { > >-static const Seconds sweepTimeSlice = 10_ms; >+static const Seconds sweepTimeSlice = 10_ms; // seconds > static const double sweepTimeTotal = .10; > static const double sweepTimeMultiplier = 1.0 / sweepTimeTotal; > > void IncrementalSweeper::scheduleTimer() > { >- setTimeUntilFire(sweepTimeSlice * sweepTimeMultiplier); >+ Base::scheduleTimer(sweepTimeSlice * sweepTimeMultiplier); > } > > IncrementalSweeper::IncrementalSweeper(Heap* heap) >@@ -49,14 +49,14 @@ IncrementalSweeper::IncrementalSweeper(Heap* heap) > { > } > >-void IncrementalSweeper::doWork(VM& vm) >+void IncrementalSweeper::doWork() > { >- doSweep(vm, MonotonicTime::now()); >+ doSweep(MonotonicTime::now()); > } > >-void IncrementalSweeper::doSweep(VM& vm, MonotonicTime sweepBeginTime) >+void IncrementalSweeper::doSweep(MonotonicTime sweepBeginTime) > { >- while (sweepNextBlock(vm)) { >+ while (sweepNextBlock()) { > Seconds elapsedTime = MonotonicTime::now() - sweepBeginTime; > if (elapsedTime < sweepTimeSlice) > continue; >@@ -72,9 +72,9 @@ void IncrementalSweeper::doSweep(VM& vm, MonotonicTime sweepBeginTime) > cancelTimer(); > } > >-bool IncrementalSweeper::sweepNextBlock(VM& vm) >+bool IncrementalSweeper::sweepNextBlock() > { >- vm.heap.stopIfNecessary(); >+ m_vm->heap.stopIfNecessary(); > > MarkedBlock::Handle* block = nullptr; > >@@ -85,25 +85,26 @@ bool IncrementalSweeper::sweepNextBlock(VM& vm) > } > > if (block) { >- DeferGCForAWhile deferGC(vm.heap); >+ DeferGCForAWhile deferGC(m_vm->heap); > block->sweep(nullptr); >- vm.heap.objectSpace().freeOrShrinkBlock(block); >+ m_vm->heap.objectSpace().freeOrShrinkBlock(block); > return true; > } > >- return vm.heap.sweepNextLogicallyEmptyWeakBlock(); >+ return m_vm->heap.sweepNextLogicallyEmptyWeakBlock(); > } > >-void IncrementalSweeper::startSweeping(Heap& heap) >+void IncrementalSweeper::startSweeping() > { > scheduleTimer(); >- m_currentDirectory = heap.objectSpace().firstDirectory(); >+ m_currentDirectory = m_vm->heap.objectSpace().firstDirectory(); > } > > void IncrementalSweeper::stopSweeping() > { > m_currentDirectory = nullptr; >- cancelTimer(); >+ if (m_vm) >+ cancelTimer(); > } > > } // namespace JSC >diff --git a/Source/JavaScriptCore/heap/IncrementalSweeper.h b/Source/JavaScriptCore/heap/IncrementalSweeper.h >index 12646debb0bf2766a3057136334bf4d427b4fe09..abd8e69f69018ddf46aa38f035696222d81b52c0 100644 >--- a/Source/JavaScriptCore/heap/IncrementalSweeper.h >+++ b/Source/JavaScriptCore/heap/IncrementalSweeper.h >@@ -37,15 +37,15 @@ public: > using Base = JSRunLoopTimer; > JS_EXPORT_PRIVATE explicit IncrementalSweeper(Heap*); > >- JS_EXPORT_PRIVATE void startSweeping(Heap&); >+ JS_EXPORT_PRIVATE void startSweeping(); > void freeFastMallocMemoryAfterSweeping() { m_shouldFreeFastMallocMemoryAfterSweeping = true; } > >- void doWork(VM&) override; >- void stopSweeping(); >+ JS_EXPORT_PRIVATE void doWork() override; >+ bool sweepNextBlock(); >+ JS_EXPORT_PRIVATE void stopSweeping(); > > private: >- bool sweepNextBlock(VM&); >- void doSweep(VM&, MonotonicTime startTime); >+ void doSweep(MonotonicTime startTime); > void scheduleTimer(); > > BlockDirectory* m_currentDirectory; >diff --git a/Source/JavaScriptCore/heap/StopIfNecessaryTimer.cpp b/Source/JavaScriptCore/heap/StopIfNecessaryTimer.cpp >index 450d8d8855345fe906731fe4aa7be61a01751ba8..62396109447f64cd6edfcf2a8f9d9a635cdb13d3 100644 >--- a/Source/JavaScriptCore/heap/StopIfNecessaryTimer.cpp >+++ b/Source/JavaScriptCore/heap/StopIfNecessaryTimer.cpp >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2016-2018 Apple Inc. All rights reserved. >+ * 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 >@@ -35,11 +35,11 @@ StopIfNecessaryTimer::StopIfNecessaryTimer(VM* vm) > { > } > >-void StopIfNecessaryTimer::doWork(VM& vm) >+void StopIfNecessaryTimer::doWork() > { > cancelTimer(); > WTF::storeStoreFence(); >- vm.heap.stopIfNecessary(); >+ m_vm->heap.stopIfNecessary(); > } > > void StopIfNecessaryTimer::scheduleSoon() >@@ -48,7 +48,7 @@ void StopIfNecessaryTimer::scheduleSoon() > WTF::loadLoadFence(); > return; > } >- setTimeUntilFire(0_s); >+ scheduleTimer(0_s); > } > > } // namespace JSC >diff --git a/Source/JavaScriptCore/heap/StopIfNecessaryTimer.h b/Source/JavaScriptCore/heap/StopIfNecessaryTimer.h >index 1f133730a8e2d3fe4a85e3282f0e43b5eccd63c2..e1836a14c8ed52a258f46207235b054b9ca2aeab 100644 >--- a/Source/JavaScriptCore/heap/StopIfNecessaryTimer.h >+++ b/Source/JavaScriptCore/heap/StopIfNecessaryTimer.h >@@ -36,7 +36,7 @@ public: > using Base = JSRunLoopTimer; > explicit StopIfNecessaryTimer(VM*); > >- void doWork(VM&) override; >+ void doWork() override; > > void scheduleSoon(); > }; >diff --git a/Source/JavaScriptCore/runtime/JSRunLoopTimer.cpp b/Source/JavaScriptCore/runtime/JSRunLoopTimer.cpp >index a56e462d4bbdee012224ec5976bfbd02a5cc5a11..89edb6813900f36e702011cdf0b70928e983c5b3 100644 >--- a/Source/JavaScriptCore/runtime/JSRunLoopTimer.cpp >+++ b/Source/JavaScriptCore/runtime/JSRunLoopTimer.cpp >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2012-2018 Apple Inc. All rights reserved. >+ * Copyright (C) 2012-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 >@@ -26,13 +26,13 @@ > #include "config.h" > #include "JSRunLoopTimer.h" > >+#include "GCActivityCallback.h" > #include "IncrementalSweeper.h" > #include "JSCInlines.h" > #include "JSObject.h" > #include "JSString.h" > > #include <wtf/MainThread.h> >-#include <wtf/NoTailCalls.h> > #include <wtf/Threading.h> > > #if USE(GLIB_EVENT_LOOP) >@@ -46,288 +46,107 @@ namespace JSC { > > const Seconds JSRunLoopTimer::s_decade { 60 * 60 * 24 * 365 * 10 }; > >-static inline JSRunLoopTimer::Manager::EpochTime epochTime(Seconds delay) >-{ >-#if USE(CF) >- return Seconds { CFAbsoluteTimeGetCurrent() + delay.value() }; >-#else >- return MonotonicTime::now().secondsSinceEpoch() + delay; >-#endif >-} >- >-#if USE(CF) >-void JSRunLoopTimer::Manager::timerDidFireCallback(CFRunLoopTimerRef, void* contextPtr) >-{ >- static_cast<JSRunLoopTimer::Manager*>(contextPtr)->timerDidFire(); >-} >- >-void JSRunLoopTimer::Manager::PerVMData::setRunLoop(Manager* manager, CFRunLoopRef newRunLoop) >+void JSRunLoopTimer::timerDidFire() > { >- if (runLoop) { >- CFRunLoopRemoveTimer(runLoop.get(), timer.get(), kCFRunLoopCommonModes); >- CFRunLoopTimerInvalidate(timer.get()); >- runLoop.clear(); >- timer.clear(); >+ JSLock* apiLock = m_apiLock.get(); >+ if (!apiLock) { >+ // Likely a buggy usage: the timer fired while JSRunLoopTimer was being destroyed. >+ return; > } > >- if (newRunLoop) { >- runLoop = newRunLoop; >- memset(&context, 0, sizeof(CFRunLoopTimerContext)); >- RELEASE_ASSERT(manager); >- context.info = manager; >- timer = adoptCF(CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + s_decade.seconds(), CFAbsoluteTimeGetCurrent() + s_decade.seconds(), 0, 0, JSRunLoopTimer::Manager::timerDidFireCallback, &context)); >- CFRunLoopAddTimer(runLoop.get(), timer.get(), kCFRunLoopCommonModes); >- >- EpochTime scheduleTime = epochTime(s_decade); >- for (auto& pair : timers) >- scheduleTime = std::min(pair.second, scheduleTime); >- CFRunLoopTimerSetNextFireDate(timer.get(), scheduleTime.value()); >+ std::lock_guard<JSLock> lock(*apiLock); >+ RefPtr<VM> vm = apiLock->vm(); >+ if (!vm) { >+ // The VM has been destroyed, so we should just give up. >+ return; > } >-} >-#else >-JSRunLoopTimer::Manager::PerVMData::PerVMData(Manager& manager) >- : runLoop(&RunLoop::current()) >- , timer(std::make_unique<RunLoop::Timer<Manager>>(*runLoop, &manager, &JSRunLoopTimer::Manager::timerDidFireCallback)) >-{ >-#if USE(GLIB_EVENT_LOOP) >- timer->setPriority(RunLoopSourcePriority::JavascriptTimer); >- timer->setName("[JavaScriptCore] JSRunLoopTimer"); >-#endif >-} >- >-void JSRunLoopTimer::Manager::timerDidFireCallback() >-{ >- timerDidFire(); >-} >-#endif > >-JSRunLoopTimer::Manager::PerVMData::~PerVMData() >-{ >-#if USE(CF) >- setRunLoop(nullptr, nullptr); >-#endif >+ doWork(); > } > >-void JSRunLoopTimer::Manager::timerDidFire() >-{ >- Vector<Ref<JSRunLoopTimer>> timersToFire; >- >- { >- auto locker = holdLock(m_lock); >-#if USE(CF) >- CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent(); >-#else >- RunLoop* currentRunLoop = &RunLoop::current(); >-#endif >- EpochTime nowEpochTime = epochTime(0_s); >- for (auto& entry : m_mapping) { >- PerVMData& data = entry.value; >-#if USE(CF) >- if (data.runLoop.get() != currentRunLoop) >- continue; >-#else >- if (data.runLoop != currentRunLoop) >- continue; >-#endif >- >- EpochTime scheduleTime = epochTime(s_decade); >- for (size_t i = 0; i < data.timers.size(); ++i) { >- { >- auto& pair = data.timers[i]; >- if (pair.second > nowEpochTime) { >- scheduleTime = std::min(pair.second, scheduleTime); >- continue; >- } >- auto& last = data.timers.last(); >- if (&last != &pair) >- std::swap(pair, last); >- --i; >- } >- >- auto pair = data.timers.takeLast(); >- timersToFire.append(WTFMove(pair.first)); >- } >- > #if USE(CF) >- CFRunLoopTimerSetNextFireDate(data.timer.get(), scheduleTime.value()); >-#else >- data.timer->startOneShot(std::max(0_s, scheduleTime - MonotonicTime::now().secondsSinceEpoch())); >-#endif >- } >- } >- >- for (auto& timer : timersToFire) >- timer->timerDidFire(); >-} > >-JSRunLoopTimer::Manager& JSRunLoopTimer::Manager::shared() >-{ >- static Manager* manager; >- static std::once_flag once; >- std::call_once(once, [&] { >- manager = new Manager; >- }); >- return *manager; >-} >- >-void JSRunLoopTimer::Manager::registerVM(VM& vm) >-{ >- PerVMData data { *this }; >-#if USE(CF) >- data.setRunLoop(this, vm.runLoop()); >-#endif >- >- auto locker = holdLock(m_lock); >- auto addResult = m_mapping.add({ vm.apiLock() }, WTFMove(data)); >- RELEASE_ASSERT(addResult.isNewEntry); >-} >- >-void JSRunLoopTimer::Manager::unregisterVM(VM& vm) >+JSRunLoopTimer::JSRunLoopTimer(VM* vm) >+ : m_vm(vm) >+ , m_apiLock(&vm->apiLock()) > { >- auto locker = holdLock(m_lock); >- >- auto iter = m_mapping.find({ vm.apiLock() }); >- RELEASE_ASSERT(iter != m_mapping.end()); >- m_mapping.remove(iter); >+ m_vm->registerRunLoopTimer(this); > } > >-void JSRunLoopTimer::Manager::scheduleTimer(JSRunLoopTimer& timer, Seconds delay) >+void JSRunLoopTimer::setRunLoop(CFRunLoopRef runLoop) > { >- EpochTime fireEpochTime = epochTime(delay); >- >- auto locker = holdLock(m_lock); >- auto iter = m_mapping.find(timer.m_apiLock); >- RELEASE_ASSERT(iter != m_mapping.end()); // We don't allow calling this after the VM dies. >- >- PerVMData& data = iter->value; >- EpochTime scheduleTime = fireEpochTime; >- bool found = false; >- for (auto& entry : data.timers) { >- if (entry.first.ptr() == &timer) { >- entry.second = fireEpochTime; >- found = true; >- } >- scheduleTime = std::min(scheduleTime, entry.second); >+ if (m_runLoop) { >+ CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes); >+ CFRunLoopTimerInvalidate(m_timer.get()); >+ m_runLoop.clear(); >+ m_timer.clear(); > } > >- if (!found) >- data.timers.append({ timer, fireEpochTime }); >- >-#if USE(CF) >- CFRunLoopTimerSetNextFireDate(data.timer.get(), scheduleTime.value()); >-#else >- data.timer->startOneShot(std::max(0_s, scheduleTime - MonotonicTime::now().secondsSinceEpoch())); >-#endif >+ m_runLoop = runLoop; >+ if (runLoop) { >+ memset(&m_context, 0, sizeof(CFRunLoopTimerContext)); >+ m_context.info = this; >+ m_timer = adoptCF(CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + s_decade.seconds(), s_decade.seconds(), 0, 0, JSRunLoopTimer::timerDidFireCallback, &m_context)); >+ CFRunLoopAddTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes); >+ } > } > >-void JSRunLoopTimer::Manager::cancelTimer(JSRunLoopTimer& timer) >+JSRunLoopTimer::~JSRunLoopTimer() > { >- auto locker = holdLock(m_lock); >- auto iter = m_mapping.find(timer.m_apiLock); >- if (iter == m_mapping.end()) { >- // It's trivial to allow this to be called after the VM dies, so we allow for it. >- return; >- } >- >- PerVMData& data = iter->value; >- EpochTime scheduleTime = epochTime(s_decade); >- for (unsigned i = 0; i < data.timers.size(); ++i) { >- { >- auto& entry = data.timers[i]; >- if (entry.first.ptr() == &timer) { >- RELEASE_ASSERT(timer.refCount() >= 2); // If we remove it from the entry below, we should not be the last thing pointing to it! >- auto& last = data.timers.last(); >- if (&last != &entry) >- std::swap(entry, last); >- data.timers.removeLast(); >- i--; >- continue; >- } >- } >- >- scheduleTime = std::min(scheduleTime, data.timers[i].second); >- } >- >-#if USE(CF) >- CFRunLoopTimerSetNextFireDate(data.timer.get(), scheduleTime.value()); >-#else >- data.timer->startOneShot(std::max(0_s, scheduleTime - MonotonicTime::now().secondsSinceEpoch())); >-#endif >+ JSLock* apiLock = m_apiLock.get(); >+ std::lock_guard<JSLock> lock(*apiLock); >+ m_vm->unregisterRunLoopTimer(this); >+ m_apiLock = nullptr; > } > >-std::optional<Seconds> JSRunLoopTimer::Manager::timeUntilFire(JSRunLoopTimer& timer) >+void JSRunLoopTimer::timerDidFireCallback(CFRunLoopTimerRef, void* contextPtr) > { >- auto locker = holdLock(m_lock); >- auto iter = m_mapping.find(timer.m_apiLock); >- RELEASE_ASSERT(iter != m_mapping.end()); // We only allow this to be called with a live VM. >- >- PerVMData& data = iter->value; >- for (auto& entry : data.timers) { >- if (entry.first.ptr() == &timer) { >- EpochTime nowEpochTime = epochTime(0_s); >- return entry.second - nowEpochTime; >- } >- } >- >- return std::nullopt; >+ static_cast<JSRunLoopTimer*>(contextPtr)->timerDidFire(); > } > >-#if USE(CF) >-void JSRunLoopTimer::Manager::didChangeRunLoop(VM& vm, CFRunLoopRef newRunLoop) >+void JSRunLoopTimer::scheduleTimer(Seconds intervalInSeconds) > { >- auto locker = holdLock(m_lock); >- auto iter = m_mapping.find({ vm.apiLock() }); >- RELEASE_ASSERT(iter != m_mapping.end()); >- >- PerVMData& data = iter->value; >- data.setRunLoop(this, newRunLoop); >+ CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + intervalInSeconds.seconds()); >+ m_isScheduled = true; >+ auto locker = holdLock(m_timerCallbacksLock); >+ for (auto& task : m_timerSetCallbacks) >+ task->run(); > } >-#endif > >-void JSRunLoopTimer::timerDidFire() >+void JSRunLoopTimer::cancelTimer() > { >- NO_TAIL_CALLS(); >- >- { >- auto locker = holdLock(m_lock); >- if (!m_isScheduled) { >- // We raced between this callback being called and cancel() being called. >- // That's fine, we just don't do anything here. >- return; >- } >- } >- >- std::lock_guard<JSLock> lock(m_apiLock.get()); >- RefPtr<VM> vm = m_apiLock->vm(); >- if (!vm) { >- // The VM has been destroyed, so we should just give up. >- return; >- } >- >- doWork(*vm); >+ CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + s_decade.seconds()); >+ m_isScheduled = false; > } > >+#else >+ > JSRunLoopTimer::JSRunLoopTimer(VM* vm) >- : m_apiLock(vm->apiLock()) >+ : m_vm(vm) >+ , m_apiLock(&vm->apiLock()) >+ , m_timer(RunLoop::current(), this, &JSRunLoopTimer::timerDidFireCallback) > { >+#if USE(GLIB_EVENT_LOOP) >+ m_timer.setPriority(RunLoopSourcePriority::JavascriptTimer); >+ m_timer.setName("[JavaScriptCore] JSRunLoopTimer"); >+#endif >+ m_timer.startOneShot(s_decade); > } > > JSRunLoopTimer::~JSRunLoopTimer() > { > } > >-std::optional<Seconds> JSRunLoopTimer::timeUntilFire() >+void JSRunLoopTimer::timerDidFireCallback() > { >- return Manager::shared().timeUntilFire(*this); >+ m_timer.startOneShot(s_decade); >+ timerDidFire(); > } > >-void JSRunLoopTimer::setTimeUntilFire(Seconds intervalInSeconds) >+void JSRunLoopTimer::scheduleTimer(Seconds intervalInSeconds) > { >- { >- auto locker = holdLock(m_lock); >- m_isScheduled = true; >- Manager::shared().scheduleTimer(*this, intervalInSeconds); >- } >+ m_timer.startOneShot(intervalInSeconds); >+ m_isScheduled = true; > > auto locker = holdLock(m_timerCallbacksLock); > for (auto& task : m_timerSetCallbacks) >@@ -336,11 +155,12 @@ void JSRunLoopTimer::setTimeUntilFire(Seconds intervalInSeconds) > > void JSRunLoopTimer::cancelTimer() > { >- auto locker = holdLock(m_lock); >+ m_timer.startOneShot(s_decade); > m_isScheduled = false; >- Manager::shared().cancelTimer(*this); > } > >+#endif >+ > void JSRunLoopTimer::addTimerSetNotification(TimerNotificationCallback callback) > { > auto locker = holdLock(m_timerCallbacksLock); >diff --git a/Source/JavaScriptCore/runtime/JSRunLoopTimer.h b/Source/JavaScriptCore/runtime/JSRunLoopTimer.h >index 6651672739eb9dca8f1ffcdbe735beda5af17240..06c5f17d37a75f789dd54f4425b24e749fe57c04 100644 >--- a/Source/JavaScriptCore/runtime/JSRunLoopTimer.h >+++ b/Source/JavaScriptCore/runtime/JSRunLoopTimer.h >@@ -47,91 +47,54 @@ public: > typedef void TimerNotificationType(); > using TimerNotificationCallback = RefPtr<WTF::SharedTask<TimerNotificationType>>; > >- class Manager { >-#if USE(CF) >- static void timerDidFireCallback(CFRunLoopTimerRef, void*); >-#else >- void timerDidFireCallback(); >-#endif >- >- void timerDidFire(); >- >- public: >- using EpochTime = Seconds; >- >- static Manager& shared(); >- void registerVM(VM&); >- void unregisterVM(VM&); >- void scheduleTimer(JSRunLoopTimer&, Seconds nextFireTime); >- void cancelTimer(JSRunLoopTimer&); >- >- std::optional<Seconds> timeUntilFire(JSRunLoopTimer&); >- >-#if USE(CF) >- void didChangeRunLoop(VM&, CFRunLoopRef newRunLoop); >-#endif >- >- private: >- Lock m_lock; >- >- struct PerVMData { >- PerVMData() = default; >-#if USE(CF) >- PerVMData(Manager&) { } >-#else >- PerVMData(Manager&); >-#endif >- PerVMData(PerVMData&&) = default; >- PerVMData& operator=(PerVMData&&) = default; >- >- ~PerVMData(); >- >+ JSRunLoopTimer(VM*); > #if USE(CF) >- void setRunLoop(Manager*, CFRunLoopRef); >- RetainPtr<CFRunLoopTimerRef> timer; >- RetainPtr<CFRunLoopRef> runLoop; >- CFRunLoopTimerContext context; >+ static void timerDidFireCallback(CFRunLoopTimerRef, void*); > #else >- RunLoop* runLoop; >- std::unique_ptr<RunLoop::Timer<Manager>> timer; >+ void timerDidFireCallback(); > #endif >- Vector<std::pair<Ref<JSRunLoopTimer>, EpochTime>> timers; >- }; > >- HashMap<Ref<JSLock>, PerVMData> m_mapping; >- }; >- >- JSRunLoopTimer(VM*); > JS_EXPORT_PRIVATE virtual ~JSRunLoopTimer(); >- virtual void doWork(VM&) = 0; >+ virtual void doWork() = 0; > >- void setTimeUntilFire(Seconds intervalInSeconds); >+ void scheduleTimer(Seconds intervalInSeconds); > void cancelTimer(); > bool isScheduled() const { return m_isScheduled; } > > // Note: The only thing the timer notification callback cannot do is >- // call setTimeUntilFire(). This will cause a deadlock. It would not >+ // call scheduleTimer(). This will cause a deadlock. It would not > // be hard to make this work, however, there are no clients that need > // this behavior. We should implement it only if we find that we need it. > JS_EXPORT_PRIVATE void addTimerSetNotification(TimerNotificationCallback); > JS_EXPORT_PRIVATE void removeTimerSetNotification(TimerNotificationCallback); > >- JS_EXPORT_PRIVATE std::optional<Seconds> timeUntilFire(); >+#if USE(CF) >+ JS_EXPORT_PRIVATE void setRunLoop(CFRunLoopRef); >+#endif // USE(CF) > > protected: >+ VM* m_vm; >+ > static const Seconds s_decade; >- Ref<JSLock> m_apiLock; > >-private: >- friend class Manager; >+ RefPtr<JSLock> m_apiLock; >+ bool m_isScheduled { false }; >+#if USE(CF) >+ RetainPtr<CFRunLoopTimerRef> m_timer; >+ RetainPtr<CFRunLoopRef> m_runLoop; > >- void timerDidFire(); >+ CFRunLoopTimerContext m_context; > >- HashSet<TimerNotificationCallback> m_timerSetCallbacks; >- Lock m_timerCallbacksLock; >+ Lock m_shutdownMutex; >+#else >+ RunLoop::Timer<JSRunLoopTimer> m_timer; >+#endif > >- Lock m_lock; >- bool m_isScheduled { false }; >+ Lock m_timerCallbacksLock; >+ HashSet<TimerNotificationCallback> m_timerSetCallbacks; >+ >+private: >+ void timerDidFire(); > }; > > } // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/PromiseDeferredTimer.cpp b/Source/JavaScriptCore/runtime/PromiseDeferredTimer.cpp >index 343ee2a9977ec23e1894d57c8880799097cda212..db851dc0e8338f4405e4c5dbfb6278ee1353aa63 100644 >--- a/Source/JavaScriptCore/runtime/PromiseDeferredTimer.cpp >+++ b/Source/JavaScriptCore/runtime/PromiseDeferredTimer.cpp >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2017-2018 Apple Inc. All rights reserved. >+ * 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 >@@ -43,9 +43,9 @@ PromiseDeferredTimer::PromiseDeferredTimer(VM& vm) > { > } > >-void PromiseDeferredTimer::doWork(VM& vm) >+void PromiseDeferredTimer::doWork() > { >- ASSERT(vm.currentThreadIsHoldingAPILock()); >+ ASSERT(m_vm->currentThreadIsHoldingAPILock()); > m_taskLock.lock(); > cancelTimer(); > if (!m_runTasks) { >@@ -66,7 +66,7 @@ void PromiseDeferredTimer::doWork(VM& vm) > m_taskLock.unlock(); > > task(); >- vm.drainMicrotasks(); >+ m_vm->drainMicrotasks(); > > m_taskLock.lock(); > m_currentlyRunningTask = false; >@@ -75,7 +75,7 @@ void PromiseDeferredTimer::doWork(VM& vm) > > if (m_pendingPromises.isEmpty() && m_shouldStopRunLoopWhenAllPromisesFinish) { > #if USE(CF) >- CFRunLoopStop(vm.runLoop()); >+ CFRunLoopStop(m_runLoop.get()); > #else > RunLoop::current().stop(); > #endif >@@ -86,30 +86,29 @@ void PromiseDeferredTimer::doWork(VM& vm) > > void PromiseDeferredTimer::runRunLoop() > { >- ASSERT(!m_apiLock->vm()->currentThreadIsHoldingAPILock()); >+ ASSERT(!m_vm->currentThreadIsHoldingAPILock()); > #if USE(CF) >- ASSERT(CFRunLoopGetCurrent() == m_apiLock->vm()->runLoop()); >+ ASSERT(CFRunLoopGetCurrent() == m_runLoop.get()); > #endif > m_shouldStopRunLoopWhenAllPromisesFinish = true; >- if (m_pendingPromises.size()) { >+ if (m_pendingPromises.size()) > #if USE(CF) > CFRunLoopRun(); > #else > RunLoop::run(); > #endif >- } > } > >-void PromiseDeferredTimer::addPendingPromise(VM& vm, JSPromiseDeferred* ticket, Vector<Strong<JSCell>>&& dependencies) >+void PromiseDeferredTimer::addPendingPromise(JSPromiseDeferred* ticket, Vector<Strong<JSCell>>&& dependencies) > { >- ASSERT(vm.currentThreadIsHoldingAPILock()); >+ ASSERT(m_vm->currentThreadIsHoldingAPILock()); > for (unsigned i = 0; i < dependencies.size(); ++i) > ASSERT(dependencies[i].get() != ticket); > > auto result = m_pendingPromises.add(ticket, Vector<Strong<JSCell>>()); > if (result.isNewEntry) { > dataLogLnIf(PromiseDeferredTimerInternal::verbose, "Adding new pending promise: ", RawPointer(ticket)); >- dependencies.append(Strong<JSCell>(vm, ticket)); >+ dependencies.append(Strong<JSCell>(*m_vm, ticket)); > result.iterator->value = WTFMove(dependencies); > } else { > dataLogLnIf(PromiseDeferredTimerInternal::verbose, "Adding new dependencies for promise: ", RawPointer(ticket)); >@@ -123,13 +122,13 @@ void PromiseDeferredTimer::addPendingPromise(VM& vm, JSPromiseDeferred* ticket, > > bool PromiseDeferredTimer::hasPendingPromise(JSPromiseDeferred* ticket) > { >- ASSERT(ticket->vm()->currentThreadIsHoldingAPILock()); >+ ASSERT(m_vm->currentThreadIsHoldingAPILock()); > return m_pendingPromises.contains(ticket); > } > > bool PromiseDeferredTimer::hasDependancyInPendingPromise(JSPromiseDeferred* ticket, JSCell* dependency) > { >- ASSERT(ticket->vm()->currentThreadIsHoldingAPILock()); >+ ASSERT(m_vm->currentThreadIsHoldingAPILock()); > ASSERT(m_pendingPromises.contains(ticket)); > > auto result = m_pendingPromises.get(ticket); >@@ -138,7 +137,7 @@ bool PromiseDeferredTimer::hasDependancyInPendingPromise(JSPromiseDeferred* tick > > bool PromiseDeferredTimer::cancelPendingPromise(JSPromiseDeferred* ticket) > { >- ASSERT(ticket->vm()->currentThreadIsHoldingAPILock()); >+ ASSERT(m_vm->currentThreadIsHoldingAPILock()); > bool result = m_pendingPromises.remove(ticket); > > if (result) >@@ -152,7 +151,7 @@ void PromiseDeferredTimer::scheduleWorkSoon(JSPromiseDeferred* ticket, Task&& ta > LockHolder locker(m_taskLock); > m_tasks.append(std::make_tuple(ticket, WTFMove(task))); > if (!isScheduled() && !m_currentlyRunningTask) >- setTimeUntilFire(0_s); >+ scheduleTimer(0_s); > } > > } // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/PromiseDeferredTimer.h b/Source/JavaScriptCore/runtime/PromiseDeferredTimer.h >index a52eb64b3a7079ca19befb38bfcb1af3d060359e..615b0877e78ab75e3f0ae8acecf640dd1414688d 100644 >--- a/Source/JavaScriptCore/runtime/PromiseDeferredTimer.h >+++ b/Source/JavaScriptCore/runtime/PromiseDeferredTimer.h >@@ -44,9 +44,9 @@ public: > > PromiseDeferredTimer(VM&); > >- void doWork(VM&) override; >+ void doWork() override; > >- void addPendingPromise(VM&, JSPromiseDeferred*, Vector<Strong<JSCell>>&& dependencies); >+ void addPendingPromise(JSPromiseDeferred*, Vector<Strong<JSCell>>&& dependencies); > JS_EXPORT_PRIVATE bool hasPendingPromise(JSPromiseDeferred* ticket); > JS_EXPORT_PRIVATE bool hasDependancyInPendingPromise(JSPromiseDeferred* ticket, JSCell* dependency); > // JSPromiseDeferred should handle canceling when the promise is resolved or rejected. >diff --git a/Source/JavaScriptCore/runtime/VM.cpp b/Source/JavaScriptCore/runtime/VM.cpp >index b9a9036284c8e2083660aa4ea160b509993912ec..f10ffdbc57fae1ea0be5ca5cf6bbca0b7ae54cc4 100644 >--- a/Source/JavaScriptCore/runtime/VM.cpp >+++ b/Source/JavaScriptCore/runtime/VM.cpp >@@ -381,8 +381,6 @@ VM::VM(VMType vmType, HeapType heapType) > updateSoftReservedZoneSize(Options::softReservedZoneSize()); > setLastStackTop(stack.origin()); > >- JSRunLoopTimer::Manager::shared().registerVM(*this); >- > // Need to be careful to keep everything consistent here > JSLockHolder lock(this); > AtomicStringTable* existingEntryAtomicStringTable = Thread::current().setCurrentAtomicStringTable(m_atomicStringTable); >@@ -583,8 +581,6 @@ VM::~VM() > ASSERT(currentThreadIsHoldingAPILock()); > m_apiLock->willDestroyVM(this); > heap.lastChanceToFinalize(); >- >- JSRunLoopTimer::Manager::shared().unregisterVM(*this); > > delete interpreter; > #ifndef NDEBUG >@@ -1213,11 +1209,27 @@ void VM::verifyExceptionCheckNeedIsSatisfied(unsigned recursionDepth, ExceptionE > #endif > > #if USE(CF) >+void VM::registerRunLoopTimer(JSRunLoopTimer* timer) >+{ >+ ASSERT(runLoop()); >+ ASSERT(!m_runLoopTimers.contains(timer)); >+ m_runLoopTimers.add(timer); >+ timer->setRunLoop(runLoop()); >+} >+ >+void VM::unregisterRunLoopTimer(JSRunLoopTimer* timer) >+{ >+ ASSERT(m_runLoopTimers.contains(timer)); >+ m_runLoopTimers.remove(timer); >+ timer->setRunLoop(nullptr); >+} >+ > void VM::setRunLoop(CFRunLoopRef runLoop) > { > ASSERT(runLoop); > m_runLoop = runLoop; >- JSRunLoopTimer::Manager::shared().didChangeRunLoop(*this, runLoop); >+ for (auto timer : m_runLoopTimers) >+ timer->setRunLoop(runLoop); > } > #endif // USE(CF) > >diff --git a/Source/JavaScriptCore/runtime/VM.h b/Source/JavaScriptCore/runtime/VM.h >index 8d6a8f80eb8c80d045e587ef7cb8edbe1fb99952..f1b91017c3492b5c15a602113d8331bb6fc172a2 100644 >--- a/Source/JavaScriptCore/runtime/VM.h >+++ b/Source/JavaScriptCore/runtime/VM.h >@@ -302,6 +302,7 @@ private: > RefPtr<JSLock> m_apiLock; > #if USE(CF) > // These need to be initialized before heap below. >+ HashSet<JSRunLoopTimer*> m_runLoopTimers; > RetainPtr<CFRunLoopRef> m_runLoop; > #endif > >@@ -881,6 +882,8 @@ public: > > #if USE(CF) > CFRunLoopRef runLoop() const { return m_runLoop.get(); } >+ void registerRunLoopTimer(JSRunLoopTimer*); >+ void unregisterRunLoopTimer(JSRunLoopTimer*); > JS_EXPORT_PRIVATE void setRunLoop(CFRunLoopRef); > #endif // USE(CF) > >diff --git a/Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.cpp b/Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.cpp >index 96d4c14d74c7ee1af8aee7610c494aa7c94b06c5..0866aaf313e0c994b31c12d04d07c517af54b5e2 100644 >--- a/Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.cpp >+++ b/Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.cpp >@@ -91,7 +91,7 @@ static void webAssemblyModuleValidateAsyncInternal(ExecState* exec, JSPromiseDef > Vector<Strong<JSCell>> dependencies; > dependencies.append(Strong<JSCell>(vm, globalObject)); > >- vm.promiseDeferredTimer->addPendingPromise(vm, promise, WTFMove(dependencies)); >+ vm.promiseDeferredTimer->addPendingPromise(promise, WTFMove(dependencies)); > > Wasm::Module::validateAsync(&vm.wasmContext, WTFMove(source), createSharedTask<Wasm::Module::CallbackType>([promise, globalObject, &vm] (Wasm::Module::ValidationResult&& result) mutable { > vm.promiseDeferredTimer->scheduleWorkSoon(promise, [promise, globalObject, result = WTFMove(result), &vm] () mutable { >@@ -173,7 +173,7 @@ static void instantiate(VM& vm, ExecState* exec, JSPromiseDeferred* promise, JSW > // The instance keeps the module alive. > dependencies.append(Strong<JSCell>(vm, instance)); > dependencies.append(Strong<JSCell>(vm, importObject)); >- vm.promiseDeferredTimer->addPendingPromise(vm, promise, WTFMove(dependencies)); >+ vm.promiseDeferredTimer->addPendingPromise(promise, WTFMove(dependencies)); > // Note: This completion task may or may not get called immediately. > module->module().compileAsync(&vm.wasmContext, instance->memoryMode(), createSharedTask<Wasm::CodeBlock::CallbackType>([promise, instance, module, importObject, resolveKind, creationMode, &vm] (Ref<Wasm::CodeBlock>&& refCodeBlock) mutable { > RefPtr<Wasm::CodeBlock> codeBlock = WTFMove(refCodeBlock); >@@ -194,7 +194,7 @@ static void compileAndInstantiate(VM& vm, ExecState* exec, JSPromiseDeferred* pr > Vector<Strong<JSCell>> dependencies; > dependencies.append(Strong<JSCell>(vm, importObject)); > dependencies.append(Strong<JSCell>(vm, moduleKeyCell)); >- vm.promiseDeferredTimer->addPendingPromise(vm, promise, WTFMove(dependencies)); >+ vm.promiseDeferredTimer->addPendingPromise(promise, WTFMove(dependencies)); > > Vector<uint8_t> source = createSourceBufferFromValue(vm, exec, buffer); > RETURN_IF_EXCEPTION(scope, reject(exec, scope, promise)); >@@ -231,7 +231,7 @@ static void webAssemblyModuleInstantinateAsyncInternal(ExecState* exec, JSPromis > Vector<Strong<JSCell>> dependencies; > dependencies.append(Strong<JSCell>(vm, importObject)); > dependencies.append(Strong<JSCell>(vm, globalObject)); >- vm.promiseDeferredTimer->addPendingPromise(vm, promise, WTFMove(dependencies)); >+ vm.promiseDeferredTimer->addPendingPromise(promise, WTFMove(dependencies)); > > Wasm::Module::validateAsync(&vm.wasmContext, WTFMove(source), createSharedTask<Wasm::Module::CallbackType>([promise, importObject, globalObject, &vm] (Wasm::Module::ValidationResult&& result) mutable { > vm.promiseDeferredTimer->scheduleWorkSoon(promise, [promise, importObject, globalObject, result = WTFMove(result), &vm] () mutable { >@@ -310,7 +310,7 @@ EncodedJSValue JSC_HOST_CALL webAssemblyCompileStreamingInternal(ExecState* exec > > Vector<Strong<JSCell>> dependencies; > dependencies.append(Strong<JSCell>(vm, globalObject)); >- vm.promiseDeferredTimer->addPendingPromise(vm, promise, WTFMove(dependencies)); >+ vm.promiseDeferredTimer->addPendingPromise(promise, WTFMove(dependencies)); > > if (globalObject->globalObjectMethodTable()->compileStreaming) > globalObject->globalObjectMethodTable()->compileStreaming(globalObject, exec, promise, exec->argument(0)); >@@ -347,7 +347,7 @@ EncodedJSValue JSC_HOST_CALL webAssemblyInstantiateStreamingInternal(ExecState* > Vector<Strong<JSCell>> dependencies; > dependencies.append(Strong<JSCell>(vm, globalObject)); > dependencies.append(Strong<JSCell>(vm, importObject)); >- vm.promiseDeferredTimer->addPendingPromise(vm, promise, WTFMove(dependencies)); >+ vm.promiseDeferredTimer->addPendingPromise(promise, WTFMove(dependencies)); > > // FIXME: <http://webkit.org/b/184888> if there's an importObject and it contains a Memory, then we can compile the module with the right memory type (fast or not) by looking at the memory's type. > globalObject->globalObjectMethodTable()->instantiateStreaming(globalObject, exec, promise, exec->argument(0), importObject); >diff --git a/Source/WebCore/page/cocoa/ResourceUsageThreadCocoa.mm b/Source/WebCore/page/cocoa/ResourceUsageThreadCocoa.mm >index fe5af8da922f72d9b8f6ae8a743c55ff9342dfbd..7e482247bca143cb24bca3df6aa25bdddbb09ced 100644 >--- a/Source/WebCore/page/cocoa/ResourceUsageThreadCocoa.mm >+++ b/Source/WebCore/page/cocoa/ResourceUsageThreadCocoa.mm >@@ -248,9 +248,8 @@ void ResourceUsageThread::platformThreadBody(JSC::VM* vm, ResourceUsageData& dat > > data.totalExternalSize = currentGCOwnedExternal; > >- auto now = MonotonicTime::now(); >- data.timeOfNextEdenCollection = now + vm->heap.edenActivityCallback()->timeUntilFire().value_or(Seconds(std::numeric_limits<double>::infinity())); >- data.timeOfNextFullCollection = now + vm->heap.fullActivityCallback()->timeUntilFire().value_or(Seconds(std::numeric_limits<double>::infinity())); >+ data.timeOfNextEdenCollection = vm->heap.edenActivityCallback()->nextFireTime(); >+ data.timeOfNextFullCollection = vm->heap.fullActivityCallback()->nextFireTime(); > } > > } >diff --git a/Source/WebCore/page/linux/ResourceUsageThreadLinux.cpp b/Source/WebCore/page/linux/ResourceUsageThreadLinux.cpp >index dcafb6f8affedb94b58a7639fc03a346506414a5..70f0d69c11b176e6ea85eece6921fd94d002b693 100644 >--- a/Source/WebCore/page/linux/ResourceUsageThreadLinux.cpp >+++ b/Source/WebCore/page/linux/ResourceUsageThreadLinux.cpp >@@ -1,6 +1,5 @@ > /* > * Copyright (C) 2017 Igalia S.L. >- * Copyright (C) 2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -169,9 +168,8 @@ void ResourceUsageThread::platformThreadBody(JSC::VM* vm, ResourceUsageData& dat > > data.totalExternalSize = currentGCOwnedExternal; > >- auto now = MonotonicTime::now(); >- data.timeOfNextEdenCollection = now + vm->heap.edenActivityCallback()->timeUntilFire().value_or(Seconds(std::numeric_limits<double>::infinity())); >- data.timeOfNextFullCollection = now + vm->heap.fullActivityCallback()->timeUntilFire().value_or(Seconds(std::numeric_limits<double>::infinity())); >+ data.timeOfNextEdenCollection = vm->heap.edenActivityCallback()->nextFireTime(); >+ data.timeOfNextFullCollection = vm->heap.fullActivityCallback()->nextFireTime(); > } > > } // namespace WebCore
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 188832
: 347749