Incremetal sweeper added to improve memory usage
authorHojong Han <hojong.han@samsung.com>
Fri, 21 Jun 2013 07:32:19 +0000 (16:32 +0900)
committerGerrit Code Review <gerrit@gerrit.vlan144.tizendev.org>
Tue, 25 Jun 2013 03:57:13 +0000 (03:57 +0000)
[Title] Incremetal sweeper added to improve memory usage
[Issue#] N/A
[Problem] N/A
[Cause] N/A
[Solution] GC Activity Callback modified and Incremental Sweeper added

Change-Id: I912fc9b537566cce20b8f6655a1bfc2b2d0942af

Source/JavaScriptCore/PlatformEfl.cmake
Source/JavaScriptCore/heap/HeapTimer.cpp
Source/JavaScriptCore/heap/HeapTimer.h
Source/JavaScriptCore/heap/IncrementalSweeper.cpp
Source/JavaScriptCore/heap/IncrementalSweeper.h
Source/JavaScriptCore/runtime/GCActivityCallback.h
Source/JavaScriptCore/runtime/GCActivityCallbackEfl.cpp
Source/cmakeconfig.h.cmake

index ae95146..177c80d 100755 (executable)
@@ -1,26 +1,20 @@
 LIST(APPEND JavaScriptCore_SOURCES
     jit/ExecutableAllocatorFixedVMPool.cpp
     jit/ExecutableAllocator.cpp
+    runtime/GCActivityCallbackEfl.cpp
 )
 
-IF (ENABLE_TIZEN_GC_ACTIVITY_CALLBACK)
-    LIST(REMOVE_ITEM JavaScriptCore_SOURCES
-        runtime/GCActivityCallback.cpp
-    )
-    LIST(APPEND JavaScriptCore_SOURCES
-        runtime/GCActivityCallbackEfl.cpp
-    )
-    LIST(APPEND JavaScriptCore_INCLUDE_DIRECTORIES
-        ${ECORE_X_INCLUDE_DIRS}
-        ${EINA_INCLUDE_DIRS}
-    )
-ENDIF ()
+LIST(REMOVE_ITEM JavaScriptCore_SOURCES
+    runtime/GCActivityCallback.cpp
+)
 
 LIST(APPEND JavaScriptCore_LIBRARIES
     ${ICU_I18N_LIBRARIES}
 )
 
 LIST(APPEND JavaScriptCore_INCLUDE_DIRECTORIES
+    ${ECORE_INCLUDE_DIRS}
+    ${EINA_INCLUDE_DIRS}
     ${ICU_INCLUDE_DIRS}
 )
 
index 59546a8..d90690a 100644 (file)
 #include "ScopeChain.h"
 #include <wtf/Threading.h>
 
+#if PLATFORM(EFL)
+#include <Ecore.h>
+#endif
+
 namespace JSC {
 
 #if USE(CF)
@@ -128,10 +132,11 @@ void HeapTimer::didStartVMShutdown()
     delete this;
 }
 
-#elif PLATFORM(EFL) && ENABLE(TIZEN_GC_ACTIVITY_CALLBACK)
+#elif PLATFORM(EFL)
 
 HeapTimer::HeapTimer(JSGlobalData* globalData)
     : m_globalData(globalData)
+    , m_timer(0)
 {
     ecore_init();
 }
@@ -155,10 +160,27 @@ void HeapTimer::invalidate()
 {
 }
 
-bool HeapTimer::timerDidFire(void* info)
+Ecore_Timer* HeapTimer::add(double delay, void* agent)
+{
+    return ecore_timer_add(delay, reinterpret_cast<Ecore_Task_Cb>(timerEvent), agent);
+}
+
+void HeapTimer::stop()
+{
+    if (!m_timer)
+        return;
+
+    ecore_timer_del(m_timer);
+    m_timer = 0;
+}
+
+bool HeapTimer::timerEvent(void* info)
 {
     HeapTimer* agent = static_cast<HeapTimer*>(info);
+
+    APIEntryShim shim(agent->m_globalData);
     agent->doWork();
+    agent->m_timer = 0;
 
     return ECORE_CALLBACK_CANCEL;
 }
index 14b9a37..56f8cdf 100644 (file)
 #include <CoreFoundation/CoreFoundation.h>
 #elif PLATFORM(BLACKBERRY)
 #include <BlackBerryPlatformTimer.h>
-#elif PLATFORM(EFL) && ENABLE(TIZEN_GC_ACTIVITY_CALLBACK)
-#include <Ecore.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
+#elif PLATFORM(EFL)
+typedef struct _Ecore_Timer Ecore_Timer;
 #endif
 
 namespace JSC {
@@ -75,11 +73,11 @@ protected:
 
     BlackBerry::Platform::Timer<HeapTimer> m_timer;
 
-#elif PLATFORM(EFL) && ENABLE(TIZEN_GC_ACTIVITY_CALLBACK)
-    void stop() { m_timer = nullptr; }
-    static bool timerDidFire(void*);
-
-    OwnPtr<Ecore_Timer> m_timer;
+#elif PLATFORM(EFL)
+    static bool timerEvent(void*);
+    Ecore_Timer* add(double delay, void* agent);
+    void stop();
+    Ecore_Timer* m_timer;
 #endif
     
 private:
index f284d8b..f1c365b 100644 (file)
 #include <wtf/HashSet.h>
 #include <wtf/WTFThreadData.h>
 
+#if PLATFORM(EFL)
+#include <wtf/MainThread.h>
+#endif
+
 namespace JSC {
 
 #if USE(CF)
@@ -124,6 +128,91 @@ void IncrementalSweeper::willFinishSweeping()
         cancelTimer();
 }
 
+#elif PLATFORM(EFL)
+
+static const double sweepTimeSlice = .01; // seconds
+static const double sweepTimeTotal = .10;
+static const double sweepTimeMultiplier = 1.0 / sweepTimeTotal;
+
+IncrementalSweeper::IncrementalSweeper(JSGlobalData* globalData)
+    : HeapTimer(globalData)
+    , m_enabled(WTF::isMainThread())
+    , m_structuresCanBeSwept(false)
+{
+}
+
+void IncrementalSweeper::doWork()
+{
+    double startTime = WTF::monotonicallyIncreasingTime();
+    while (m_currentBlockToSweepIndex < m_blocksToSweep.size()) {
+        sweepNextBlock();
+
+        double elapsedTime = WTF::monotonicallyIncreasingTime() - startTime;
+        if (elapsedTime < sweepTimeSlice)
+            continue;
+
+        scheduleTimer();
+        return;
+    }
+    m_blocksToSweep.clear();
+    cancelTimer();
+}
+
+void IncrementalSweeper::scheduleTimer()
+{
+    cancelTimer();
+    m_timer = add(sweepTimeSlice * sweepTimeMultiplier, this);
+}
+
+void IncrementalSweeper::cancelTimer()
+{
+    stop();
+}
+
+IncrementalSweeper* IncrementalSweeper::create(Heap* heap)
+{
+    return new IncrementalSweeper(heap->globalData());
+}
+
+void IncrementalSweeper::sweepNextBlock()
+{
+    while (m_currentBlockToSweepIndex < m_blocksToSweep.size()) {
+        MarkedBlock* block = m_blocksToSweep[m_currentBlockToSweepIndex++];
+        if (block->onlyContainsStructures())
+            m_structuresCanBeSwept = true;
+        else
+            ASSERT(!m_structuresCanBeSwept);
+
+        if (!block->needsSweeping())
+            continue;
+
+        block->sweep();
+        m_globalData->heap.objectSpace().freeOrShrinkBlock(block);
+        return;
+    }
+}
+
+void IncrementalSweeper::startSweeping(const HashSet<MarkedBlock*>& blockSnapshot)
+{
+    if (!isEnabled())
+        return;
+
+    m_blocksToSweep.resize(blockSnapshot.size());
+    CopyFunctor functor(m_blocksToSweep);
+    m_globalData->heap.objectSpace().forEachBlock(functor);
+    m_currentBlockToSweepIndex = 0;
+    m_structuresCanBeSwept = false;
+    scheduleTimer();
+}
+
+void IncrementalSweeper::willFinishSweeping()
+{
+    m_currentBlockToSweepIndex = 0;
+    m_structuresCanBeSwept = true;
+    m_blocksToSweep.clear();
+    if (m_globalData)
+        cancelTimer();
+}
 #else
 
 IncrementalSweeper::IncrementalSweeper(JSGlobalData* globalData)
index c8005b0..78684d5 100644 (file)
@@ -62,18 +62,27 @@ public:
 private:
 #if USE(CF)
     IncrementalSweeper(Heap*, CFRunLoopRef);
-    
+
     void doSweep(double startTime);
+#elif PLATFORM(EFL)
+    IncrementalSweeper(JSGlobalData*);
+
+    bool isEnabled() const { return m_enabled; }
+    bool m_enabled;
+#else
+
+    IncrementalSweeper(JSGlobalData*);
+
+#endif
+
+#if USE(CF) || PLATFORM(EFL)
     void scheduleTimer();
     void cancelTimer();
-    
+
     unsigned m_currentBlockToSweepIndex;
     Vector<MarkedBlock*> m_blocksToSweep;
-#else
-    
-    IncrementalSweeper(JSGlobalData*);
-    
 #endif
+
     bool m_structuresCanBeSwept;
 };
 
index 67ee174..584681e 100644 (file)
@@ -56,6 +56,12 @@ protected:
         , m_enabled(true)
     {
     }
+#elif PLATFORM(EFL)
+    GCActivityCallback(JSGlobalData* globalData, bool flag)
+        : HeapTimer(globalData)
+        , m_enabled(flag)
+    {
+    }
 # else
     GCActivityCallback(JSGlobalData* globalData)
         : HeapTimer(globalData)
@@ -83,12 +89,13 @@ public:
 protected:
     DefaultGCActivityCallback(Heap*, CFRunLoopRef);
     
-    void cancelTimer();
-    void scheduleTimer(double);
-    
 private:
     double m_delay;
 #endif
+#if USE(CF) || PLATFORM(EFL)
+    void cancelTimer();
+    void scheduleTimer(double);
+#endif
 };
 
 inline DefaultGCActivityCallback* DefaultGCActivityCallback::create(Heap* heap)
index 92c03e0..4e6f17d 100644 (file)
 #include "config.h"
 #include "GCActivityCallback.h"
 
+#include "APIShims.h"
 #include "Heap.h"
 #include "JSGlobalData.h"
 
+#include <wtf/MainThread.h>
+
 namespace JSC {
 
-const double timerInterval = 0.3;
+const double timeInterval = 0.3;
+const size_t threshold = 1 * MB;
 
 DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
-    : GCActivityCallback(heap->globalData())
+    : GCActivityCallback(heap->globalData(), WTF::isMainThread())
 {
 }
 
 void DefaultGCActivityCallback::doWork()
 {
-    JSLockHolder lock(m_globalData);
+    APIEntryShim shim(m_globalData);
     m_globalData->heap.collect(Heap::DoNotSweep);
 }
 
-void DefaultGCActivityCallback::didAllocate(size_t bytes)
+void DefaultGCActivityCallback::scheduleTimer(double newDelay)
 {
-    if (bytes < 1 * MB)
-        return;
+    stop();
+    ASSERT(!m_timer);
+    m_timer = add(newDelay, this);
+}
 
-    if (m_timer || m_globalData->usingAPI())
+void DefaultGCActivityCallback::cancelTimer()
+{
+    stop();
+}
+
+void DefaultGCActivityCallback::didAllocate(size_t bytes)
+{
+    if (!isEnabled() || (bytes < threshold) || m_timer)
         return;
 
-    m_timer = adoptPtr(ecore_timer_add(timerInterval, reinterpret_cast<Ecore_Task_Cb>(HeapTimer::timerDidFire), this));
+    ASSERT(WTF::isMainThread());
+    scheduleTimer(timeInterval);
 }
 
 void DefaultGCActivityCallback::willCollect()
 {
-    stop();
+    cancelTimer();
 }
 
 void DefaultGCActivityCallback::cancel()
 {
-    stop();
+    cancelTimer();
 }
 
 } // namespace JSC
index b5955e9..e90d2d1 100644 (file)
 #cmakedefine01 ENABLE_TIZEN_SUPPORT_WEBAPP_META_TAG
 #cmakedefine01 ENABLE_TIZEN_SQL_DATABASE_ENCRYPTION
 #cmakedefine01 ENABLE_TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP
-#cmakedefine01 ENABLE_TIZEN_GC_ACTIVITY_CALLBACK
 #cmakedefine01 ENABLE_TIZEN_GESTURE
 #cmakedefine01 ENABLE_TIZEN_WEBKIT2_TEXT_SELECTION