| Index: Source/platform/heap/ThreadState.cpp
 | 
| diff --git a/Source/platform/heap/ThreadState.cpp b/Source/platform/heap/ThreadState.cpp
 | 
| index 7c857b9c609fc6962df5e713383dcfff6424b36c..d7c104263a1b4cd8216c13a959ae6972009fe51e 100644
 | 
| --- a/Source/platform/heap/ThreadState.cpp
 | 
| +++ b/Source/platform/heap/ThreadState.cpp
 | 
| @@ -97,8 +97,8 @@ ThreadState::ThreadState()
 | 
|      , m_sweepForbidden(false)
 | 
|      , m_noAllocationCount(0)
 | 
|      , m_gcForbiddenCount(0)
 | 
| -    , m_persistentAllocated(0)
 | 
| -    , m_persistentFreed(0)
 | 
| +    , m_wrapperAllocated(0)
 | 
| +    , m_wrapperFreed(0)
 | 
|      , m_vectorBackingHeapIndex(Vector1HeapIndex)
 | 
|      , m_currentHeapAges(0)
 | 
|      , m_isTerminating(false)
 | 
| @@ -558,110 +558,82 @@ CrossThreadPersistentRegion& ThreadState::crossThreadPersistentRegion()
 | 
|      return persistentRegion;
 | 
|  }
 | 
|  
 | 
| -void ThreadState::updatePersistentCounters()
 | 
| +void ThreadState::updateWrapperCounters()
 | 
|  {
 | 
| -    if (m_persistentAllocated >= m_persistentFreed)
 | 
| -        Heap::increasePersistentCount(m_persistentAllocated - m_persistentFreed);
 | 
| +    if (m_wrapperAllocated >= m_wrapperFreed)
 | 
| +        Heap::increaseWrapperCount(m_wrapperAllocated - m_wrapperFreed);
 | 
|      else
 | 
| -        Heap::decreasePersistentCount(m_persistentFreed - m_persistentAllocated);
 | 
| -    Heap::increaseCollectedPersistentCount(m_persistentFreed);
 | 
| -    m_persistentAllocated = 0;
 | 
| -    m_persistentFreed = 0;
 | 
| -}
 | 
| -
 | 
| -size_t ThreadState::estimatedLiveObjectSize()
 | 
| -{
 | 
| -    // We estimate the live object size with the following equations.
 | 
| -    //
 | 
| -    //   heapSizePerPersistent = (marked(t0, t1) + partitionAlloc(t0)) / persistentCount(t0)
 | 
| -    //   estimatedLiveObjectSize = marked(t0, t) + allocated(t0, t) + partitionAlloc(t) - heapSizePerPersistent * collectedPersistentCount(t0, t)
 | 
| -    //
 | 
| -    // t0:                 The time when the last collectGarbage runs.
 | 
| -    // t1:                 The time when the last completeSweep runs.
 | 
| -    // t:                  The current time.
 | 
| -    // marked(t0, t):      The size of marked objects between t0 and t.
 | 
| -    // allocated(t0, t):   The size of newly allocated objects between t0 and t.
 | 
| -    // persistentCount(t): The number of existing persistent handles at t.
 | 
| -    // collectedPersistentCount(t0, t):
 | 
| -    //                     The number of persistent handles collected between
 | 
| -    //                     t0 and t.
 | 
| -    // partitionAlloc(t):  The size of allocated memory in PartitionAlloc at t.
 | 
| -    size_t currentHeapSize = currentObjectSize();
 | 
| -    size_t heapSizeRetainedByCollectedPersistents = Heap::heapSizePerPersistent() * Heap::collectedPersistentCount();
 | 
| -    size_t estimatedSize = 0;
 | 
| -    if (currentHeapSize > heapSizeRetainedByCollectedPersistents)
 | 
| -        estimatedSize = currentHeapSize - heapSizeRetainedByCollectedPersistents;
 | 
| -    TRACE_COUNTER1("blink_gc", "ThreadState::currentHeapSizeKB", std::min(currentHeapSize / 1024, static_cast<size_t>(INT_MAX)));
 | 
| -    TRACE_COUNTER1("blink_gc", "ThreadState::estimatedLiveObjectSizeKB", std::min(estimatedSize / 1024, static_cast<size_t>(INT_MAX)));
 | 
| -    TRACE_COUNTER1("blink_gc", "ThreadState::heapGrowingRate", static_cast<int>(100.0 * currentHeapSize / estimatedSize));
 | 
| -    return estimatedSize;
 | 
| -}
 | 
| -
 | 
| -size_t ThreadState::currentObjectSize()
 | 
| -{
 | 
| -    return Heap::allocatedObjectSize() + Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages();
 | 
| +        Heap::decreaseWrapperCount(m_wrapperFreed - m_wrapperAllocated);
 | 
| +    Heap::increaseCollectedWrapperCount(m_wrapperFreed);
 | 
| +    m_wrapperAllocated = 0;
 | 
| +    m_wrapperFreed = 0;
 | 
|  }
 | 
|  
 | 
| -bool ThreadState::shouldForceMemoryPressureGC()
 | 
| +double ThreadState::partitionAllocGrowingRate()
 | 
|  {
 | 
| -    // Avoid potential overflow by truncating to Kb.
 | 
| -    size_t currentObjectSizeKb = currentObjectSize() >> 10;
 | 
| -    if (currentObjectSizeKb < 300 * 1024)
 | 
| +    size_t sizeAtLastGC = Heap::partitionAllocSizeAtLastGC();
 | 
| +    size_t wrapperCountAtLastGC = Heap::wrapperCountAtLastGC();
 | 
| +    size_t sizeRetainedByCollectedPersistents = wrapperCountAtLastGC ? Heap::collectedWrapperCount() * sizeAtLastGC / wrapperCountAtLastGC : 0;
 | 
| +    size_t estimatedLiveSize = sizeAtLastGC > sizeRetainedByCollectedPersistents ? sizeAtLastGC - sizeRetainedByCollectedPersistents : 0;
 | 
| +    double growingRate = estimatedLiveSize ? 1.0 * WTF::Partitions::totalSizeOfCommittedPages() / estimatedLiveSize : 0;
 | 
| +    TRACE_COUNTER1("blink_gc", "ThreadState::estimatedLivePartitionAllocSizeKB", std::min(estimatedLiveSize / 1024, static_cast<size_t>(INT_MAX)));
 | 
| +    TRACE_COUNTER1("blink_gc", "ThreadState::partitionAllocGrowingRate", static_cast<int>(100 * growingRate));
 | 
| +    return growingRate;
 | 
| +}
 | 
| +
 | 
| +double ThreadState::heapGrowingRate()
 | 
| +{
 | 
| +    size_t markedObjectSize = Heap::markedObjectSizeAtLastCompleteSweep();
 | 
| +    size_t currentObjectSize = Heap::allocatedObjectSize() + markedObjectSize;
 | 
| +    double growingRate = markedObjectSize ? 1.0 * currentObjectSize / markedObjectSize : 0;
 | 
| +    TRACE_COUNTER1("blink_gc", "ThreadState::currentObjectSizeKB", std::min(currentObjectSize / 1024, static_cast<size_t>(INT_MAX)));
 | 
| +    TRACE_COUNTER1("blink_gc", "ThreadState::heapGrowingRate", static_cast<int>(100 * growingRate));
 | 
| +    return growingRate;
 | 
| +}
 | 
| +
 | 
| +// TODO(haraken): We should improve the GC heuristics. These heuristics
 | 
| +// significantly affect performance.
 | 
| +bool ThreadState::judgeGCThreshold(size_t allocatedObjectSizeThreshold, double heapGrowingRateThreshold, double partitionAllocGrowingRateThreshold)
 | 
| +{
 | 
| +    if (Heap::allocatedObjectSize() < allocatedObjectSizeThreshold)
 | 
|          return false;
 | 
| +    if (heapGrowingRate() >= heapGrowingRateThreshold)
 | 
| +        return true;
 | 
| +    return partitionAllocGrowingRate() >= partitionAllocGrowingRateThreshold;
 | 
| +}
 | 
|  
 | 
| -    size_t estimatedLiveObjectSizeKb = estimatedLiveObjectSize() >> 10;
 | 
| -    // If we're consuming too much memory, trigger a conservative GC
 | 
| -    // aggressively. This is a safe guard to avoid OOM.
 | 
| -    return currentObjectSizeKb > (estimatedLiveObjectSizeKb * 3) / 2;
 | 
| +bool ThreadState::shouldForceMemoryPressureGC()
 | 
| +{
 | 
| +    size_t totalObjectSize = Heap::allocatedObjectSize() + Heap::markedObjectSizeAtLastCompleteSweep() + WTF::Partitions::totalSizeOfCommittedPages();
 | 
| +    if (totalObjectSize < 300 * 1024 * 1024)
 | 
| +        return false;
 | 
| +    return judgeGCThreshold(0, 1.5, 1.5);
 | 
|  }
 | 
|  
 | 
| -// TODO(haraken): We should improve the GC heuristics.
 | 
| -// These heuristics affect performance significantly.
 | 
|  bool ThreadState::shouldScheduleIdleGC()
 | 
|  {
 | 
|      if (gcState() != NoGCScheduled)
 | 
|          return false;
 | 
|  #if ENABLE(IDLE_GC)
 | 
| -    // Avoid potential overflow by truncating to Kb.
 | 
| -    size_t allocatedObjectSizeKb = Heap::allocatedObjectSize() >> 10;
 | 
| -    // The estimated size is updated when the main thread finishes lazy
 | 
| -    // sweeping. If this thread reaches here before the main thread finishes
 | 
| -    // lazy sweeping, the thread will use the estimated size of the last GC.
 | 
| -    size_t estimatedLiveObjectSizeKb = estimatedLiveObjectSize() >> 10;
 | 
| -    // Heap::markedObjectSize() may be underestimated if any thread has not
 | 
| -    // finished completeSweep().
 | 
| -    size_t currentObjectSizeKb = currentObjectSize() >> 10;
 | 
| -    // Schedule an idle GC if Oilpan has allocated more than 1 MB since
 | 
| -    // the last GC and the current memory usage is >50% larger than
 | 
| -    // the estimated live memory usage.
 | 
| -    return allocatedObjectSizeKb >= 1024 && currentObjectSizeKb > (estimatedLiveObjectSizeKb * 3) / 2;
 | 
| +    return judgeGCThreshold(1024 * 1024, 1.5, 1.5);
 | 
|  #else
 | 
|      return false;
 | 
|  #endif
 | 
|  }
 | 
|  
 | 
| -// TODO(haraken): We should improve the GC heuristics.
 | 
| -// These heuristics affect performance significantly.
 | 
|  bool ThreadState::shouldSchedulePreciseGC()
 | 
|  {
 | 
| -    if (gcState() != NoGCScheduled)
 | 
| +    if (isGCForbidden())
 | 
|          return false;
 | 
| +
 | 
| +    if (shouldForceMemoryPressureGC())
 | 
| +        return true;
 | 
| +
 | 
|  #if ENABLE(IDLE_GC)
 | 
| -    return false;
 | 
| +    return judgeGCThreshold(32 * 1024 * 1024, 4.0, 4.0);
 | 
| +    // return false;
 | 
|  #else
 | 
| -    // Avoid potential overflow by truncating to Kb.
 | 
| -    size_t allocatedObjectSizeKb = Heap::allocatedObjectSize() >> 10;
 | 
| -    // The estimated size is updated when the main thread finishes lazy
 | 
| -    // sweeping. If this thread reaches here before the main thread finishes
 | 
| -    // lazy sweeping, the thread will use the estimated size of the last GC.
 | 
| -    size_t estimatedLiveObjectSizeKb = estimatedLiveObjectSize() >> 10;
 | 
| -    // Heap::markedObjectSize() may be underestimated if any thread has not
 | 
| -    // finished completeSweep().
 | 
| -    size_t currentObjectSizeKb = currentObjectSize() >> 10;
 | 
| -    // Schedule a precise GC if Oilpan has allocated more than 1 MB since
 | 
| -    // the last GC and the current memory usage is >50% larger than
 | 
| -    // the estimated live memory usage.
 | 
| -    return allocatedObjectSizeKb >= 1024 && currentObjectSizeKb > (estimatedLiveObjectSizeKb * 3) / 2;
 | 
| +    return judgeGCThreshold(1024 * 1024, 1.5, 1.5);
 | 
|  #endif
 | 
|  }
 | 
|  
 | 
| @@ -714,26 +686,13 @@ void ThreadState::schedulePageNavigationGC()
 | 
|  // These heuristics affect performance significantly.
 | 
|  bool ThreadState::shouldForceConservativeGC()
 | 
|  {
 | 
| -    if (UNLIKELY(isGCForbidden()))
 | 
| +    if (isGCForbidden())
 | 
|          return false;
 | 
|  
 | 
|      if (shouldForceMemoryPressureGC())
 | 
|          return true;
 | 
|  
 | 
| -    // Avoid potential overflow by truncating to Kb.
 | 
| -    size_t allocatedObjectSizeKb = Heap::allocatedObjectSize() >> 10;
 | 
| -    // The estimated size is updated when the main thread finishes lazy
 | 
| -    // sweeping. If this thread reaches here before the main thread finishes
 | 
| -    // lazy sweeping, the thread will use the estimated size of the last GC.
 | 
| -    size_t estimatedLiveObjectSizeKb = estimatedLiveObjectSize() >> 10;
 | 
| -    // Heap::markedObjectSize() may be underestimated if any thread has not
 | 
| -    // finished completeSweep().
 | 
| -    size_t currentObjectSizeKb = currentObjectSize() >> 10;
 | 
| -    // Schedule a conservative GC if Oilpan has allocated more than 32 MB since
 | 
| -    // the last GC and the current memory usage is >400% larger than
 | 
| -    // the estimated live memory usage.
 | 
| -    // TODO(haraken): 400% is too large. Lower the heap growing factor.
 | 
| -    return allocatedObjectSizeKb >= 32 * 1024 && currentObjectSizeKb > 5 * estimatedLiveObjectSizeKb;
 | 
| +    return judgeGCThreshold(32 * 1024 * 1024, 5.0, 5.0);
 | 
|  }
 | 
|  
 | 
|  void ThreadState::scheduleGCIfNeeded()
 | 
| @@ -938,18 +897,6 @@ ThreadState::GCState ThreadState::gcState() const
 | 
|      return m_gcState;
 | 
|  }
 | 
|  
 | 
| -void ThreadState::didV8MajorGC()
 | 
| -{
 | 
| -    ASSERT(checkThread());
 | 
| -    if (isMainThread()) {
 | 
| -        if (shouldForceMemoryPressureGC()) {
 | 
| -            // Under memory pressure, force a conservative GC.
 | 
| -            Heap::collectGarbage(HeapPointersOnStack, GCWithoutSweep, Heap::ConservativeGC);
 | 
| -            return;
 | 
| -        }
 | 
| -    }
 | 
| -}
 | 
| -
 | 
|  void ThreadState::runScheduledGC(StackState stackState)
 | 
|  {
 | 
|      ASSERT(checkThread());
 | 
| @@ -1012,7 +959,7 @@ void ThreadState::preGC()
 | 
|      makeConsistentForGC();
 | 
|      flushHeapDoesNotContainCacheIfNeeded();
 | 
|      clearHeapAges();
 | 
| -    updatePersistentCounters();
 | 
| +    updateWrapperCounters();
 | 
|  }
 | 
|  
 | 
|  void ThreadState::postGC(GCType gcType)
 | 
| @@ -1193,14 +1140,11 @@ void ThreadState::postSweep()
 | 
|      Heap::reportMemoryUsageForTracing();
 | 
|  
 | 
|      if (isMainThread()) {
 | 
| -        // See the comment in estimatedLiveObjectSize() for what we're
 | 
| -        // calculating here.
 | 
| -        //
 | 
|          // Heap::markedObjectSize() may be underestimated here if any other
 | 
|          // thread has not yet finished lazy sweeping.
 | 
| -        if (Heap::persistentCountAtLastGC() > 0) {
 | 
| -            TRACE_EVENT1("blink_gc", "ThreadState::postSweep", "collection rate", 1.0 * Heap::markedObjectSize() / Heap::objectSizeAtLastGC());
 | 
| -            Heap::setHeapSizePerPersistent((Heap::markedObjectSize() + Heap::partitionAllocSizeAtLastGC()) / Heap::persistentCountAtLastGC());
 | 
| +        if (Heap::objectSizeAtLastGC()) {
 | 
| +            TRACE_EVENT1("blink_gc", "ThreadState::postSweep", "collection rate", 1 - 1.0 * Heap::markedObjectSize() / Heap::objectSizeAtLastGC());
 | 
| +            Heap::setMarkedObjectSizeAtLastCompleteSweep(Heap::markedObjectSize());
 | 
|          }
 | 
|      }
 | 
|  
 | 
| 
 |