Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (192772 => 192773)
--- trunk/Source/_javascript_Core/ChangeLog 2015-11-26 07:08:43 UTC (rev 192772)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-11-26 13:52:45 UTC (rev 192773)
@@ -1,3 +1,32 @@
+2015-11-26 Carlos Garcia Campos <[email protected]>
+
+ [GLIB] Implement garbage collector timers
+ https://bugs.webkit.org/show_bug.cgi?id=151391
+
+ Reviewed by Žan Doberšek.
+
+ Add GLib implementation using GSource.
+
+ * heap/EdenGCActivityCallback.cpp:
+ * heap/FullGCActivityCallback.cpp:
+ * heap/GCActivityCallback.cpp:
+ (JSC::GCActivityCallback::GCActivityCallback):
+ (JSC::GCActivityCallback::scheduleTimer):
+ (JSC::GCActivityCallback::cancelTimer):
+ * heap/GCActivityCallback.h:
+ * heap/Heap.cpp:
+ (JSC::Heap::Heap):
+ * heap/HeapTimer.cpp:
+ (JSC::HeapTimer::HeapTimer):
+ (JSC::HeapTimer::~HeapTimer):
+ (JSC::HeapTimer::timerDidFire):
+ * heap/HeapTimer.h:
+ * heap/IncrementalSweeper.cpp:
+ (JSC::IncrementalSweeper::IncrementalSweeper):
+ (JSC::IncrementalSweeper::scheduleTimer):
+ (JSC::IncrementalSweeper::cancelTimer):
+ * heap/IncrementalSweeper.h:
+
2015-11-24 Caitlin Potter <[email protected]>
[JSC] support Computed Property Names in destructuring Patterns
Modified: trunk/Source/_javascript_Core/heap/EdenGCActivityCallback.cpp (192772 => 192773)
--- trunk/Source/_javascript_Core/heap/EdenGCActivityCallback.cpp 2015-11-26 07:08:43 UTC (rev 192772)
+++ trunk/Source/_javascript_Core/heap/EdenGCActivityCallback.cpp 2015-11-26 13:52:45 UTC (rev 192773)
@@ -30,7 +30,7 @@
namespace JSC {
-#if USE(CF) || PLATFORM(EFL)
+#if USE(CF) || USE(GLIB)
EdenGCActivityCallback::EdenGCActivityCallback(Heap* heap)
: GCActivityCallback(heap)
Modified: trunk/Source/_javascript_Core/heap/FullGCActivityCallback.cpp (192772 => 192773)
--- trunk/Source/_javascript_Core/heap/FullGCActivityCallback.cpp 2015-11-26 07:08:43 UTC (rev 192772)
+++ trunk/Source/_javascript_Core/heap/FullGCActivityCallback.cpp 2015-11-26 13:52:45 UTC (rev 192773)
@@ -30,7 +30,7 @@
namespace JSC {
-#if USE(CF) || PLATFORM(EFL)
+#if USE(CF) || USE(GLIB)
#if !PLATFORM(IOS)
const double pagingTimeOut = 0.1; // Time in seconds to allow opportunistic timer to iterate over all blocks to see if the Heap is paged out.
Modified: trunk/Source/_javascript_Core/heap/GCActivityCallback.cpp (192772 => 192773)
--- trunk/Source/_javascript_Core/heap/GCActivityCallback.cpp 2015-11-26 07:08:43 UTC (rev 192772)
+++ trunk/Source/_javascript_Core/heap/GCActivityCallback.cpp 2015-11-26 13:52:45 UTC (rev 192773)
@@ -39,13 +39,15 @@
#if PLATFORM(EFL)
#include <wtf/MainThread.h>
+#elif USE(GLIB)
+#include <glib.h>
#endif
namespace JSC {
bool GCActivityCallback::s_shouldCreateGCTimer = true;
-#if USE(CF) || PLATFORM(EFL)
+#if USE(CF) || USE(GLIB)
const double timerSlop = 2.0; // Fudge factor to avoid performance cost of resetting timer.
@@ -64,6 +66,11 @@
: GCActivityCallback(heap->vm(), WTF::isMainThread())
{
}
+#elif USE(GLIB)
+GCActivityCallback::GCActivityCallback(Heap* heap)
+ : GCActivityCallback(heap->vm())
+{
+}
#endif
void GCActivityCallback::doWork()
@@ -114,6 +121,34 @@
m_delay = s_hour;
stop();
}
+#elif USE(GLIB)
+void GCActivityCallback::scheduleTimer(double newDelay)
+{
+ ASSERT(newDelay >= 0);
+ if (m_delay != -1 && newDelay * timerSlop > m_delay)
+ return;
+
+ m_delay = newDelay;
+ if (!m_delay) {
+ g_source_set_ready_time(m_timer.get(), 0);
+ return;
+ }
+
+ auto delayDuration = std::chrono::duration<double>(m_delay);
+ auto safeDelayDuration = std::chrono::microseconds::max();
+ if (delayDuration < safeDelayDuration)
+ safeDelayDuration = std::chrono::duration_cast<std::chrono::microseconds>(delayDuration);
+ gint64 currentTime = g_get_monotonic_time();
+ gint64 targetTime = currentTime + std::min<gint64>(G_MAXINT64 - currentTime, safeDelayDuration.count());
+ ASSERT(targetTime >= currentTime);
+ g_source_set_ready_time(m_timer.get(), targetTime);
+}
+
+void GCActivityCallback::cancelTimer()
+{
+ m_delay = -1;
+ g_source_set_ready_time(m_timer.get(), -1);
+}
#endif
void GCActivityCallback::didAllocate(size_t bytes)
Modified: trunk/Source/_javascript_Core/heap/GCActivityCallback.h (192772 => 192773)
--- trunk/Source/_javascript_Core/heap/GCActivityCallback.h 2015-11-26 07:08:43 UTC (rev 192772)
+++ trunk/Source/_javascript_Core/heap/GCActivityCallback.h 2015-11-26 13:52:45 UTC (rev 192773)
@@ -81,6 +81,13 @@
, m_delay(s_hour)
{
}
+#elif USE(GLIB)
+ GCActivityCallback(VM* vm)
+ : HeapTimer(vm)
+ , m_enabled(true)
+ , m_delay(-1)
+ {
+ }
#else
GCActivityCallback(VM* vm)
: HeapTimer(vm)
@@ -95,7 +102,7 @@
protected:
GCActivityCallback(Heap*, CFRunLoopRef);
#endif
-#if USE(CF) || PLATFORM(EFL)
+#if USE(CF) || USE(GLIB)
protected:
void cancelTimer();
void scheduleTimer(double);
Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (192772 => 192773)
--- trunk/Source/_javascript_Core/heap/Heap.cpp 2015-11-26 07:08:43 UTC (rev 192772)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp 2015-11-26 13:52:45 UTC (rev 192773)
@@ -347,7 +347,7 @@
#if USE(CF)
, m_sweeper(std::make_unique<IncrementalSweeper>(this, CFRunLoopGetCurrent()))
#else
- , m_sweeper(std::make_unique<IncrementalSweeper>(this->vm()))
+ , m_sweeper(std::make_unique<IncrementalSweeper>(this))
#endif
, m_deferralDepth(0)
#if USE(CF)
Modified: trunk/Source/_javascript_Core/heap/HeapTimer.cpp (192772 => 192773)
--- trunk/Source/_javascript_Core/heap/HeapTimer.cpp 2015-11-26 07:08:43 UTC (rev 192772)
+++ trunk/Source/_javascript_Core/heap/HeapTimer.cpp 2015-11-26 13:52:45 UTC (rev 192773)
@@ -36,6 +36,8 @@
#if PLATFORM(EFL)
#include <Ecore.h>
+#elif USE(GLIB)
+#include <glib.h>
#endif
namespace JSC {
@@ -140,6 +142,61 @@
return ECORE_CALLBACK_CANCEL;
}
+
+#elif USE(GLIB)
+
+static GSourceFuncs heapTimerSourceFunctions = {
+ nullptr, // prepare
+ nullptr, // check
+ // dispatch
+ [](GSource* source, GSourceFunc callback, gpointer userData) -> gboolean
+ {
+ if (g_source_get_ready_time(source) == -1)
+ return G_SOURCE_CONTINUE;
+ g_source_set_ready_time(source, -1);
+ return callback(userData);
+ },
+ nullptr, // finalize
+ nullptr, // closure_callback
+ nullptr, // closure_marshall
+};
+
+HeapTimer::HeapTimer(VM* vm)
+ : m_vm(vm)
+ , m_apiLock(&vm->apiLock())
+ , m_timer(adoptGRef(g_source_new(&heapTimerSourceFunctions, sizeof(GSource))))
+{
+ g_source_set_name(m_timer.get(), "[_javascript_Core] HeapTimer");
+ g_source_set_callback(m_timer.get(), [](gpointer userData) -> gboolean {
+ static_cast<HeapTimer*>(userData)->timerDidFire();
+ return G_SOURCE_CONTINUE;
+ }, this, nullptr);
+ g_source_attach(m_timer.get(), g_main_context_get_thread_default());
+}
+
+HeapTimer::~HeapTimer()
+{
+ g_source_destroy(m_timer.get());
+}
+
+void HeapTimer::timerDidFire()
+{
+ m_apiLock->lock();
+
+ if (!m_apiLock->vm()) {
+ // The VM has been destroyed, so we should just give up.
+ m_apiLock->unlock();
+ return;
+ }
+
+ {
+ JSLockHolder locker(m_vm);
+ doWork();
+ }
+
+ m_apiLock->unlock();
+}
+
#else
HeapTimer::HeapTimer(VM* vm)
: m_vm(vm)
Modified: trunk/Source/_javascript_Core/heap/HeapTimer.h (192772 => 192773)
--- trunk/Source/_javascript_Core/heap/HeapTimer.h 2015-11-26 07:08:43 UTC (rev 192772)
+++ trunk/Source/_javascript_Core/heap/HeapTimer.h 2015-11-26 13:52:45 UTC (rev 192773)
@@ -34,8 +34,13 @@
#include <CoreFoundation/CoreFoundation.h>
#endif
+#if USE(GLIB) && !PLATFORM(EFL)
+#include <wtf/glib/GRefPtr.h>
+#endif
+
namespace JSC {
+class JSLock;
class VM;
class HeapTimer {
@@ -66,6 +71,10 @@
Ecore_Timer* add(double delay, void* agent);
void stop();
Ecore_Timer* m_timer;
+#elif USE(GLIB)
+ void timerDidFire();
+ RefPtr<JSLock> m_apiLock;
+ GRefPtr<GSource> m_timer;
#endif
private:
Modified: trunk/Source/_javascript_Core/heap/IncrementalSweeper.cpp (192772 => 192773)
--- trunk/Source/_javascript_Core/heap/IncrementalSweeper.cpp 2015-11-26 07:08:43 UTC (rev 192772)
+++ trunk/Source/_javascript_Core/heap/IncrementalSweeper.cpp 2015-11-26 13:52:45 UTC (rev 192773)
@@ -35,14 +35,19 @@
#include <wtf/HashSet.h>
#include <wtf/WTFThreadData.h>
+#if USE(GLIB) && !PLATFORM(EFL)
+#include <glib.h>
+#endif
+
namespace JSC {
-#if USE(CF)
+#if USE(CF) || (USE(GLIB) && !PLATFORM(EFL))
static const double sweepTimeSlice = .01; // seconds
static const double sweepTimeTotal = .10;
static const double sweepTimeMultiplier = 1.0 / sweepTimeTotal;
+#if USE(CF)
IncrementalSweeper::IncrementalSweeper(Heap* heap, CFRunLoopRef runLoop)
: HeapTimer(heap->vm(), runLoop)
, m_blocksToSweep(heap->m_blockSnapshot)
@@ -58,7 +63,28 @@
{
CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + s_decade);
}
+#elif USE(GLIB)
+IncrementalSweeper::IncrementalSweeper(Heap* heap)
+ : HeapTimer(heap->vm())
+ , m_blocksToSweep(heap->m_blockSnapshot)
+{
+}
+void IncrementalSweeper::scheduleTimer()
+{
+ auto delayDuration = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::duration<double>(sweepTimeSlice * sweepTimeMultiplier));
+ gint64 currentTime = g_get_monotonic_time();
+ gint64 targetTime = currentTime + std::min<gint64>(G_MAXINT64 - currentTime, delayDuration.count());
+ ASSERT(targetTime >= currentTime);
+ g_source_set_ready_time(m_timer.get(), targetTime);
+}
+
+void IncrementalSweeper::cancelTimer()
+{
+ g_source_set_ready_time(m_timer.get(), -1);
+}
+#endif
+
void IncrementalSweeper::doWork()
{
doSweep(WTF::monotonicallyIncreasingTime());
@@ -110,8 +136,8 @@
#else
-IncrementalSweeper::IncrementalSweeper(VM* vm)
- : HeapTimer(vm)
+IncrementalSweeper::IncrementalSweeper(Heap* heap)
+ : HeapTimer(heap->vm())
{
}
Modified: trunk/Source/_javascript_Core/heap/IncrementalSweeper.h (192772 => 192773)
--- trunk/Source/_javascript_Core/heap/IncrementalSweeper.h 2015-11-26 07:08:43 UTC (rev 192772)
+++ trunk/Source/_javascript_Core/heap/IncrementalSweeper.h 2015-11-26 13:52:45 UTC (rev 192773)
@@ -40,7 +40,7 @@
#if USE(CF)
JS_EXPORT_PRIVATE IncrementalSweeper(Heap*, CFRunLoopRef);
#else
- explicit IncrementalSweeper(VM*);
+ explicit IncrementalSweeper(Heap*);
#endif
void startSweeping();
@@ -49,7 +49,7 @@
bool sweepNextBlock();
void willFinishSweeping();
-#if USE(CF)
+#if USE(CF) || (USE(GLIB) && !PLATFORM(EFL))
private:
void doSweep(double startTime);
void scheduleTimer();