/*
 *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
 *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "config.h"
#include "Heap.h"

#include "CodeBlock.h"
#include "ConservativeRoots.h"
#include "GCActivityCallback.h"
#include "Interpreter.h"
#include "JSGlobalData.h"
#include "JSGlobalObject.h"
#include "JSLock.h"
#include "JSONObject.h"
#include "Tracing.h"
#include <algorithm>

#define COLLECT_ON_EVERY_SLOW_ALLOCATION 0

using namespace std;

namespace JSC {

const size_t minBytesPerCycle = 512 * 1024;

Heap::Heap(JSGlobalData* globalData)
    : m_operationInProgress(NoOperation)
    , m_markedSpace(globalData)
    , m_markListSet(0)
    , m_activityCallback(DefaultGCActivityCallback::create(this))
    , m_globalData(globalData)
    , m_machineThreads(this)
    , m_markStack(globalData->jsArrayVPtr)
    , m_handleHeap(globalData)
    , m_extraCost(0)
{
    m_markedSpace.setHighWaterMark(minBytesPerCycle);
    (*m_activityCallback)();
}

Heap::~Heap()
{
    // The destroy function must already have been called, so assert this.
    ASSERT(!m_globalData);
}

void Heap::destroy()
{
    JSLock lock(SilenceAssertionsOnly);

    if (!m_globalData)
        return;

    ASSERT(!m_globalData->dynamicGlobalObject);
    ASSERT(m_operationInProgress == NoOperation);
    
    // The global object is not GC protected at this point, so sweeping may delete it
    // (and thus the global data) before other objects that may use the global data.
    RefPtr<JSGlobalData> protect(m_globalData);

#if ENABLE(JIT)
    m_globalData->jitStubs->clearHostFunctionStubs();
#endif

    delete m_markListSet;
    m_markListSet = 0;
    m_markedSpace.clearMarks();
    m_handleHeap.finalizeWeakHandles();
    m_markedSpace.destroy();

    m_globalData = 0;
}

void Heap::reportExtraMemoryCostSlowCase(size_t cost)
{
    // Our frequency of garbage collection tries to balance memory use against speed
    // by collecting based on the number of newly created values. However, for values
    // that hold on to a great deal of memory that's not in the form of other JS values,
    // that is not good enough - in some cases a lot of those objects can pile up and
    // use crazy amounts of memory without a GC happening. So we track these extra
    // memory costs. Only unusually large objects are noted, and we only keep track
    // of this extra cost until the next GC. In garbage collected languages, most values
    // are either very short lived temporaries, or have extremely long lifetimes. So
    // if a large value survives one garbage collection, there is not much point to
    // collecting more frequently as long as it stays alive.

    if (m_extraCost > maxExtraCost && m_extraCost > m_markedSpace.highWaterMark() / 2)
        collectAllGarbage();
    m_extraCost += cost;
}

void* Heap::allocateSlowCase(size_t bytes)
{
    ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
    ASSERT(JSLock::lockCount() > 0);
    ASSERT(JSLock::currentThreadIsHoldingLock());
    ASSERT(bytes <= MarkedSpace::maxCellSize);
    ASSERT(m_operationInProgress == NoOperation);

#if COLLECT_ON_EVERY_SLOW_ALLOCATION
    collectAllGarbage();
    ASSERT(m_operationInProgress == NoOperation);
#endif

    reset(DoNotSweep);

    m_operationInProgress = Allocation;
    void* result = m_markedSpace.allocate(bytes);
    m_operationInProgress = NoOperation;

    ASSERT(result);
    return result;
}

void Heap::protect(JSValue k)
{
    ASSERT(k);
    ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance());

    if (!k.isCell())
        return;

    m_protectedValues.add(k.asCell());
}

bool Heap::unprotect(JSValue k)
{
    ASSERT(k);
    ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance());

    if (!k.isCell())
        return false;

    return m_protectedValues.remove(k.asCell());
}

void Heap::markProtectedObjects(HeapRootMarker& heapRootMarker)
{
    ProtectCountSet::iterator end = m_protectedValues.end();
    for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
        heapRootMarker.mark(&it->first);
}

void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector)
{
    m_tempSortingVectors.append(tempVector);
}

void Heap::popTempSortVector(Vector<ValueStringPair>* tempVector)
{
    ASSERT_UNUSED(tempVector, tempVector == m_tempSortingVectors.last());
    m_tempSortingVectors.removeLast();
}
    
void Heap::markTempSortVectors(HeapRootMarker& heapRootMarker)
{
    typedef Vector<Vector<ValueStringPair>* > VectorOfValueStringVectors;

    VectorOfValueStringVectors::iterator end = m_tempSortingVectors.end();
    for (VectorOfValueStringVectors::iterator it = m_tempSortingVectors.begin(); it != end; ++it) {
        Vector<ValueStringPair>* tempSortingVector = *it;

        Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end();
        for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) {
            if (vectorIt->first)
                heapRootMarker.mark(&vectorIt->first);
        }
    }
}

inline RegisterFile& Heap::registerFile()
{
    return m_globalData->interpreter->registerFile();
}

void Heap::markRoots()
{
#ifndef NDEBUG
    if (m_globalData->isSharedInstance()) {
        ASSERT(JSLock::lockCount() > 0);
        ASSERT(JSLock::currentThreadIsHoldingLock());
    }
#endif

    void* dummy;

    ASSERT(m_operationInProgress == NoOperation);
    if (m_operationInProgress != NoOperation)
        CRASH();

    m_operationInProgress = Collection;

    MarkStack& markStack = m_markStack;
    HeapRootMarker heapRootMarker(markStack);
    
    // We gather conservative roots before clearing mark bits because
    // conservative gathering uses the mark bits from our last mark pass to
    // determine whether a reference is valid.
    ConservativeRoots machineThreadRoots(this);
    m_machineThreads.gatherConservativeRoots(machineThreadRoots, &dummy);

    ConservativeRoots registerFileRoots(this);
    registerFile().gatherConservativeRoots(registerFileRoots);

    m_markedSpace.clearMarks();

    markStack.append(machineThreadRoots);
    markStack.drain();

    markStack.append(registerFileRoots);
    markStack.drain();

    markProtectedObjects(heapRootMarker);
    markStack.drain();
    
    markTempSortVectors(heapRootMarker);
    markStack.drain();

    if (m_markListSet && m_markListSet->size())
        MarkedArgumentBuffer::markLists(heapRootMarker, *m_markListSet);
    if (m_globalData->exception)
        heapRootMarker.mark(&m_globalData->exception);
    markStack.drain();

    m_handleHeap.markStrongHandles(heapRootMarker);
    markStack.drain();

    m_handleStack.mark(heapRootMarker);
    markStack.drain();

    // Mark the small strings cache as late as possible, since it will clear
    // itself if nothing else has marked it.
    // FIXME: Change the small strings cache to use Weak<T>.
    m_globalData->smallStrings.markChildren(heapRootMarker);
    markStack.drain();
    
    // Weak handles must be marked last, because their owners use the set of
    // opaque roots to determine reachability.
    int lastOpaqueRootCount;
    do {
        lastOpaqueRootCount = markStack.opaqueRootCount();
        m_handleHeap.markWeakHandles(heapRootMarker);
        markStack.drain();
    // If the set of opaque roots has grown, more weak handles may have become reachable.
    } while (lastOpaqueRootCount != markStack.opaqueRootCount());

    markStack.reset();

    m_operationInProgress = NoOperation;
}

size_t Heap::objectCount() const
{
    return m_markedSpace.objectCount();
}

size_t Heap::size() const
{
    return m_markedSpace.size();
}

size_t Heap::capacity() const
{
    return m_markedSpace.capacity();
}

size_t Heap::globalObjectCount()
{
    return m_globalData->globalObjectCount;
}

size_t Heap::protectedGlobalObjectCount()
{
    size_t count = m_handleHeap.protectedGlobalObjectCount();

    ProtectCountSet::iterator end = m_protectedValues.end();
    for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) {
        if (it->first->isObject() && asObject(it->first)->isGlobalObject())
            count++;
    }

    return count;
}

size_t Heap::protectedObjectCount()
{
    return m_protectedValues.size();
}

class TypeCounter {
public:
    TypeCounter();
    void operator()(JSCell*);
    PassOwnPtr<TypeCountSet> take();
    
private:
    const char* typeName(JSCell*);
    OwnPtr<TypeCountSet> m_typeCountSet;
};

inline TypeCounter::TypeCounter()
    : m_typeCountSet(new TypeCountSet)
{
}

inline const char* TypeCounter::typeName(JSCell* cell)
{
    if (cell->isString())
        return "string";
    if (cell->isGetterSetter())
        return "Getter-Setter";
    if (cell->isAPIValueWrapper())
        return "API wrapper";
    if (cell->isPropertyNameIterator())
        return "For-in iterator";
    if (const ClassInfo* info = cell->classInfo())
        return info->className;
    if (!cell->isObject())
        return "[empty cell]";
    return "Object";
}

inline void TypeCounter::operator()(JSCell* cell)
{
    m_typeCountSet->add(typeName(cell));
}

inline PassOwnPtr<TypeCountSet> TypeCounter::take()
{
    return m_typeCountSet.release();
}

PassOwnPtr<TypeCountSet> Heap::protectedObjectTypeCounts()
{
    TypeCounter typeCounter;

    ProtectCountSet::iterator end = m_protectedValues.end();
    for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
        typeCounter(it->first);
    m_handleHeap.protectedObjectTypeCounts(typeCounter);

    return typeCounter.take();
}

void HandleHeap::protectedObjectTypeCounts(TypeCounter& typeCounter)
{
    Node* end = m_strongList.end();
    for (Node* node = m_strongList.begin(); node != end; node = node->next()) {
        JSValue value = *node->slot();
        if (value && value.isCell())
            typeCounter(value.asCell());
    }
}

PassOwnPtr<TypeCountSet> Heap::objectTypeCounts()
{
    TypeCounter typeCounter;
    forEach(typeCounter);
    return typeCounter.take();
}

bool Heap::isBusy()
{
    return m_operationInProgress != NoOperation;
}

void Heap::collectAllGarbage()
{
    reset(DoSweep);
}

void Heap::reset(SweepToggle sweepToggle)
{
    ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
    JAVASCRIPTCORE_GC_BEGIN();

    markRoots();
    m_handleHeap.finalizeWeakHandles();

    JAVASCRIPTCORE_GC_MARKED();

    m_markedSpace.reset();
    m_extraCost = 0;

#if ENABLE(JSC_ZOMBIES)
    sweepToggle = DoSweep;
#endif

    if (sweepToggle == DoSweep) {
        m_markedSpace.sweep();
        m_markedSpace.shrink();
    }

    // To avoid pathological GC churn in large heaps, we set the allocation high
    // water mark to be proportional to the current size of the heap. The exact
    // proportion is a bit arbitrary. A 2X multiplier gives a 1:1 (heap size :
    // new bytes allocated) proportion, and seems to work well in benchmarks.
    size_t proportionalBytes = 2 * m_markedSpace.size();
    m_markedSpace.setHighWaterMark(max(proportionalBytes, minBytesPerCycle));

    JAVASCRIPTCORE_GC_END();

    (*m_activityCallback)();
}

void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback)
{
    m_activityCallback = activityCallback;
}

GCActivityCallback* Heap::activityCallback()
{
    return m_activityCallback.get();
}

} // namespace JSC
