Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (215222 => 215223)
--- trunk/Source/_javascript_Core/ChangeLog 2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-04-11 09:34:36 UTC (rev 215223)
@@ -1,3 +1,16 @@
+2017-04-11 Yusuke Suzuki <[email protected]>
+
+ [JSC] Enable JSRunLoopTimer for JSCOnly and Windows
+ https://bugs.webkit.org/show_bug.cgi?id=170655
+
+ Reviewed by Carlos Garcia Campos.
+
+ * runtime/JSRunLoopTimer.cpp:
+ (JSC::JSRunLoopTimer::JSRunLoopTimer):
+ (JSC::JSRunLoopTimer::scheduleTimer):
+ (JSC::JSRunLoopTimer::cancelTimer):
+ * runtime/JSRunLoopTimer.h:
+
2017-04-10 Alex Christensen <[email protected]>
Revert r215217
Modified: trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.cpp (215222 => 215223)
--- trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.cpp 2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.cpp 2017-04-11 09:34:36 UTC (rev 215223)
@@ -161,10 +161,17 @@
g_source_set_ready_time(m_timer.get(), g_get_monotonic_time() + s_decade * G_USEC_PER_SEC);
m_isScheduled = false;
}
+
#else
+
+const Seconds JSRunLoopTimer::s_decade { 60 * 60 * 24 * 365 * 10 };
+
JSRunLoopTimer::JSRunLoopTimer(VM* vm)
: m_vm(vm)
+ , m_apiLock(&vm->apiLock())
+ , m_timer(RunLoop::current(), this, &JSRunLoopTimer::timerDidFire)
{
+ m_timer.startOneShot(s_decade);
}
JSRunLoopTimer::~JSRunLoopTimer()
@@ -171,13 +178,18 @@
{
}
-void JSRunLoopTimer::scheduleTimer(double)
+void JSRunLoopTimer::scheduleTimer(double intervalInSeconds)
{
+ m_timer.startOneShot(intervalInSeconds);
+ m_isScheduled = true;
}
void JSRunLoopTimer::cancelTimer()
{
+ m_timer.startOneShot(s_decade);
+ m_isScheduled = false;
}
+
#endif
-
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.h (215222 => 215223)
--- trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.h 2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.h 2017-04-11 09:34:36 UTC (rev 215223)
@@ -28,6 +28,7 @@
#include <wtf/Lock.h>
#include <wtf/RefPtr.h>
#include <wtf/RetainPtr.h>
+#include <wtf/RunLoop.h>
#include <wtf/ThreadSafeRefCounted.h>
#include <wtf/Threading.h>
@@ -79,6 +80,9 @@
#elif USE(GLIB)
static const long s_decade;
GRefPtr<GSource> m_timer;
+#else
+ static const Seconds s_decade;
+ RunLoop::Timer<JSRunLoopTimer> m_timer;
#endif
private:
Modified: trunk/Source/WTF/ChangeLog (215222 => 215223)
--- trunk/Source/WTF/ChangeLog 2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/WTF/ChangeLog 2017-04-11 09:34:36 UTC (rev 215223)
@@ -1,3 +1,35 @@
+2017-04-11 Yusuke Suzuki <[email protected]>
+
+ [JSC] Enable JSRunLoopTimer for JSCOnly and Windows
+ https://bugs.webkit.org/show_bug.cgi?id=170655
+
+ Reviewed by Carlos Garcia Campos.
+
+ This patch makes RunLoop::Timer in Generic and Windows thread-safe to use it
+ in JSC's JSRunLoopTimer. Eventually, we would like to replace JSRunLoopTimer's
+ platform-dependent implementation to WTF::RunLoop::Timer.
+
+ * wtf/RunLoop.h:
+ * wtf/cf/RunLoopCF.cpp:
+ (WTF::RunLoop::TimerBase::start):
+ * wtf/generic/RunLoopGeneric.cpp:
+ (WTF::RunLoop::TimerBase::ScheduledTask::EarliestSchedule::operator()):
+ (WTF::RunLoop::populateTasks):
+ (WTF::RunLoop::runImpl):
+ (WTF::RunLoop::schedule):
+ (WTF::RunLoop::scheduleAndWakeUp):
+ (WTF::RunLoop::TimerBase::~TimerBase):
+ (WTF::RunLoop::TimerBase::start):
+ (WTF::RunLoop::TimerBase::stop):
+ (WTF::RunLoop::TimerBase::isActive):
+ * wtf/glib/RunLoopGLib.cpp:
+ (WTF::RunLoop::TimerBase::TimerBase):
+ * wtf/win/RunLoopWin.cpp:
+ (WTF::RunLoop::TimerBase::timerFired):
+ (WTF::RunLoop::TimerBase::start):
+ (WTF::RunLoop::TimerBase::stop):
+ (WTF::RunLoop::TimerBase::isActive):
+
2017-04-11 Zan Dobersek <[email protected]>
REGRESSION(r213645): It made JSC tests super slow and timeout on AArch64 Linux
Modified: trunk/Source/WTF/wtf/RunLoop.h (215222 => 215223)
--- trunk/Source/WTF/wtf/RunLoop.h 2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/WTF/wtf/RunLoop.h 2017-04-11 09:34:36 UTC (rev 215223)
@@ -103,7 +103,7 @@
private:
WTF_EXPORT_PRIVATE void start(double nextFireInterval, bool repeat);
- RunLoop& m_runLoop;
+ Ref<RunLoop> m_runLoop;
#if USE(WINDOWS_EVENT_LOOP)
static void timerFired(RunLoop*, uint64_t ID);
@@ -118,6 +118,9 @@
bool m_isRepeating { false };
Seconds m_fireInterval { 0 };
#elif USE(GENERIC_EVENT_LOOP)
+ bool isActive(const AbstractLocker&) const;
+ void stop(const AbstractLocker&);
+
class ScheduledTask;
RefPtr<ScheduledTask> m_scheduledTask;
#endif
@@ -159,6 +162,7 @@
HWND m_runLoopMessageWindow;
typedef HashMap<uint64_t, TimerBase*> TimerMap;
+ Lock m_activeTimersLock;
TimerMap m_activeTimers;
#elif USE(COCOA_EVENT_LOOP)
static void performWork(void*);
@@ -172,7 +176,7 @@
void schedule(Ref<TimerBase::ScheduledTask>&&);
void schedule(const AbstractLocker&, Ref<TimerBase::ScheduledTask>&&);
void wakeUp(const AbstractLocker&);
- void scheduleAndWakeUp(Ref<TimerBase::ScheduledTask>&&);
+ void scheduleAndWakeUp(const AbstractLocker&, Ref<TimerBase::ScheduledTask>&&);
enum class RunMode {
Iterate,
@@ -184,12 +188,14 @@
Stopping,
};
void runImpl(RunMode);
- bool populateTasks(RunMode, Status&, Deque<Ref<TimerBase::ScheduledTask>>&);
+ bool populateTasks(RunMode, Status&, Deque<RefPtr<TimerBase::ScheduledTask>>&);
+ friend class TimerBase;
+
Lock m_loopLock;
Condition m_readyToRun;
Condition m_stopCondition;
- Vector<Ref<TimerBase::ScheduledTask>> m_schedules;
+ Vector<RefPtr<TimerBase::ScheduledTask>> m_schedules;
Vector<Status*> m_mainLoops;
bool m_shutdown { false };
bool m_pendingTasks { false };
Modified: trunk/Source/WTF/wtf/cf/RunLoopCF.cpp (215222 => 215223)
--- trunk/Source/WTF/wtf/cf/RunLoopCF.cpp 2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/WTF/wtf/cf/RunLoopCF.cpp 2017-04-11 09:34:36 UTC (rev 215223)
@@ -102,7 +102,7 @@
CFRunLoopTimerContext context = { 0, this, 0, 0, 0 };
CFTimeInterval repeatInterval = repeat ? nextFireInterval : 0;
m_timer = adoptCF(CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + nextFireInterval, repeatInterval, 0, 0, timerFired, &context));
- CFRunLoopAddTimer(m_runLoop.m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
+ CFRunLoopAddTimer(m_runLoop->m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
}
void RunLoop::TimerBase::stop()
Modified: trunk/Source/WTF/wtf/generic/RunLoopGeneric.cpp (215222 => 215223)
--- trunk/Source/WTF/wtf/generic/RunLoopGeneric.cpp 2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/WTF/wtf/generic/RunLoopGeneric.cpp 2017-04-11 09:34:36 UTC (rev 215223)
@@ -73,7 +73,7 @@
}
struct EarliestSchedule {
- bool operator()(const Ref<ScheduledTask>& lhs, const Ref<ScheduledTask>& rhs)
+ bool operator()(const RefPtr<ScheduledTask>& lhs, const RefPtr<ScheduledTask>& rhs)
{
return lhs->scheduledTimePoint() > rhs->scheduledTimePoint();
}
@@ -112,7 +112,7 @@
m_stopCondition.wait(m_loopLock);
}
-inline bool RunLoop::populateTasks(RunMode runMode, Status& statusOfThisLoop, Deque<Ref<TimerBase::ScheduledTask>>& firedTimers)
+inline bool RunLoop::populateTasks(RunMode runMode, Status& statusOfThisLoop, Deque<RefPtr<TimerBase::ScheduledTask>>& firedTimers)
{
LockHolder locker(m_loopLock);
@@ -139,7 +139,7 @@
// Check expired timers.
MonotonicTime now = MonotonicTime::now();
while (!m_schedules.isEmpty()) {
- Ref<TimerBase::ScheduledTask> earliest = m_schedules.first().copyRef();
+ RefPtr<TimerBase::ScheduledTask> earliest = m_schedules.first();
if (earliest->scheduledTimePoint() > now)
break;
std::pop_heap(m_schedules.begin(), m_schedules.end(), TimerBase::ScheduledTask::EarliestSchedule());
@@ -160,7 +160,7 @@
m_mainLoops.append(&statusOfThisLoop);
}
- Deque<Ref<TimerBase::ScheduledTask>> firedTimers;
+ Deque<RefPtr<TimerBase::ScheduledTask>> firedTimers;
while (true) {
if (!populateTasks(runMode, statusOfThisLoop, firedTimers))
return;
@@ -167,12 +167,12 @@
// Dispatch scheduled timers.
while (!firedTimers.isEmpty()) {
- Ref<TimerBase::ScheduledTask> task = firedTimers.takeFirst();
+ RefPtr<TimerBase::ScheduledTask> task = firedTimers.takeFirst();
if (task->fired()) {
// Reschedule because the timer requires repeating.
// Since we will query the timers' time points before sleeping,
// we do not call wakeUp() here.
- schedule(WTFMove(task));
+ schedule(*task);
}
}
performWork();
@@ -220,7 +220,7 @@
void RunLoop::schedule(const AbstractLocker&, Ref<TimerBase::ScheduledTask>&& task)
{
- m_schedules.append(WTFMove(task));
+ m_schedules.append(task.ptr());
std::push_heap(m_schedules.begin(), m_schedules.end(), TimerBase::ScheduledTask::EarliestSchedule());
}
@@ -230,9 +230,8 @@
schedule(locker, WTFMove(task));
}
-void RunLoop::scheduleAndWakeUp(Ref<TimerBase::ScheduledTask>&& task)
+void RunLoop::scheduleAndWakeUp(const AbstractLocker& locker, Ref<TimerBase::ScheduledTask>&& task)
{
- LockHolder locker(m_loopLock);
schedule(locker, WTFMove(task));
wakeUp(locker);
}
@@ -247,11 +246,6 @@
// Since RunLoop does not own the registered TimerBase,
// TimerBase and its owner should manage these lifetime.
-//
-// And more importantly, TimerBase operations are not thread-safe.
-// So threads that do not belong to the ScheduledTask's RunLoop
-// should not operate the RunLoop::TimerBase.
-// This is the same to the RunLoopWin, which is RunLoop for Windows.
RunLoop::TimerBase::TimerBase(RunLoop& runLoop)
: m_runLoop(runLoop)
, m_scheduledTask(nullptr)
@@ -260,19 +254,21 @@
RunLoop::TimerBase::~TimerBase()
{
- stop();
+ LockHolder locker(m_runLoop->m_loopLock);
+ stop(locker);
}
void RunLoop::TimerBase::start(double interval, bool repeating)
{
- stop();
+ LockHolder locker(m_runLoop->m_loopLock);
+ stop(locker);
m_scheduledTask = ScheduledTask::create([this] {
fired();
}, Seconds(interval), repeating);
- m_runLoop.scheduleAndWakeUp(*m_scheduledTask);
+ m_runLoop->scheduleAndWakeUp(locker, *m_scheduledTask);
}
-void RunLoop::TimerBase::stop()
+void RunLoop::TimerBase::stop(const AbstractLocker&)
{
if (m_scheduledTask) {
m_scheduledTask->deactivate();
@@ -280,8 +276,20 @@
}
}
+void RunLoop::TimerBase::stop()
+{
+ LockHolder locker(m_runLoop->m_loopLock);
+ stop(locker);
+}
+
bool RunLoop::TimerBase::isActive() const
{
+ LockHolder locker(m_runLoop->m_loopLock);
+ return isActive(locker);
+}
+
+bool RunLoop::TimerBase::isActive(const AbstractLocker&) const
+{
return m_scheduledTask;
}
Modified: trunk/Source/WTF/wtf/glib/RunLoopGLib.cpp (215222 => 215223)
--- trunk/Source/WTF/wtf/glib/RunLoopGLib.cpp 2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/WTF/wtf/glib/RunLoopGLib.cpp 2017-04-11 09:34:36 UTC (rev 215223)
@@ -168,7 +168,7 @@
timer->updateReadyTime();
return G_SOURCE_CONTINUE;
}, this, nullptr);
- g_source_attach(m_source.get(), m_runLoop.m_mainContext.get());
+ g_source_attach(m_source.get(), m_runLoop->m_mainContext.get());
}
RunLoop::TimerBase::~TimerBase()
Modified: trunk/Source/WTF/wtf/win/RunLoopWin.cpp (215222 => 215223)
--- trunk/Source/WTF/wtf/win/RunLoopWin.cpp 2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/WTF/wtf/win/RunLoopWin.cpp 2017-04-11 09:34:36 UTC (rev 215223)
@@ -117,17 +117,21 @@
void RunLoop::TimerBase::timerFired(RunLoop* runLoop, uint64_t ID)
{
- TimerMap::iterator it = runLoop->m_activeTimers.find(ID);
- if (it == runLoop->m_activeTimers.end()) {
- // The timer must have been stopped after the WM_TIMER message was posted to the message queue.
- return;
- }
+ TimerBase* timer = nullptr;
+ {
+ LockHolder locker(runLoop->m_activeTimersLock);
+ TimerMap::iterator it = runLoop->m_activeTimers.find(ID);
+ if (it == runLoop->m_activeTimers.end()) {
+ // The timer must have been stopped after the WM_TIMER message was posted to the message queue.
+ return;
+ }
- TimerBase* timer = it->value;
+ timer = it->value;
- if (!timer->m_isRepeating) {
- runLoop->m_activeTimers.remove(it);
- ::KillTimer(runLoop->m_runLoopMessageWindow, ID);
+ if (!timer->m_isRepeating) {
+ runLoop->m_activeTimers.remove(it);
+ ::KillTimer(runLoop->m_runLoopMessageWindow, ID);
+ }
}
timer->fired();
@@ -153,24 +157,27 @@
void RunLoop::TimerBase::start(double nextFireInterval, bool repeat)
{
+ LockHolder locker(m_runLoop->m_activeTimersLock);
m_isRepeating = repeat;
- m_runLoop.m_activeTimers.set(m_ID, this);
- ::SetTimer(m_runLoop.m_runLoopMessageWindow, m_ID, nextFireInterval * 1000, 0);
+ m_runLoop->m_activeTimers.set(m_ID, this);
+ ::SetTimer(m_runLoop->m_runLoopMessageWindow, m_ID, nextFireInterval * 1000, 0);
}
void RunLoop::TimerBase::stop()
{
- TimerMap::iterator it = m_runLoop.m_activeTimers.find(m_ID);
- if (it == m_runLoop.m_activeTimers.end())
+ LockHolder locker(m_runLoop->m_activeTimersLock);
+ TimerMap::iterator it = m_runLoop->m_activeTimers.find(m_ID);
+ if (it == m_runLoop->m_activeTimers.end())
return;
- m_runLoop.m_activeTimers.remove(it);
- ::KillTimer(m_runLoop.m_runLoopMessageWindow, m_ID);
+ m_runLoop->m_activeTimers.remove(it);
+ ::KillTimer(m_runLoop->m_runLoopMessageWindow, m_ID);
}
bool RunLoop::TimerBase::isActive() const
{
- return m_runLoop.m_activeTimers.contains(m_ID);
+ LockHolder locker(m_runLoop->m_activeTimersLock);
+ return m_runLoop->m_activeTimers.contains(m_ID);
}
} // namespace WTF