/*
 * Copyright (C) 2012, 2015 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "GCThread.h"

#include "CopyVisitor.h"
#include "CopyVisitorInlines.h"
#include "GCThreadSharedData.h"
#include "JSCInlines.h"
#include "SlotVisitor.h"
#include <wtf/MainThread.h>

namespace JSC {

GCThread::GCThread(GCThreadSharedData& shared, std::unique_ptr<SlotVisitor> slotVisitor, std::unique_ptr<CopyVisitor> copyVisitor)
    : m_threadID(0)
    , m_shared(shared)
    , m_slotVisitor(WTF::move(slotVisitor))
    , m_copyVisitor(WTF::move(copyVisitor))
{
}

ThreadIdentifier GCThread::threadID()
{
    ASSERT(m_threadID);
    return m_threadID;
}

void GCThread::initializeThreadID(ThreadIdentifier threadID)
{
    ASSERT(!m_threadID);
    m_threadID = threadID;
}

SlotVisitor* GCThread::slotVisitor()
{
    ASSERT(m_slotVisitor);
    return m_slotVisitor.get();
}

CopyVisitor* GCThread::copyVisitor()
{
    ASSERT(m_copyVisitor);
    return m_copyVisitor.get();
}

GCPhase GCThread::waitForNextPhase()
{
    std::unique_lock<Lock> lock(m_shared.m_phaseMutex);
    m_shared.m_phaseConditionVariable.wait(lock, [this] { return !m_shared.m_gcThreadsShouldWait; });

    m_shared.m_numberOfActiveGCThreads--;
    if (!m_shared.m_numberOfActiveGCThreads)
        m_shared.m_activityConditionVariable.notifyOne();

    m_shared.m_phaseConditionVariable.wait(lock, [this] { return m_shared.m_currentPhase != NoPhase; });
    m_shared.m_numberOfActiveGCThreads++;
    return m_shared.m_currentPhase;
}

void GCThread::gcThreadMain()
{
    GCPhase currentPhase;
#if ENABLE(PARALLEL_GC)
    WTF::registerGCThread();
#endif
    // Wait for the main thread to finish creating and initializing us. The main thread grabs this lock before 
    // creating this thread. We aren't guaranteed to have a valid threadID until the main thread releases this lock.
    {
        std::lock_guard<Lock> lock(m_shared.m_phaseMutex);
    }
    {
        ParallelModeEnabler enabler(*m_slotVisitor);
        while ((currentPhase = waitForNextPhase()) != Exit) {
            // Note: Each phase is responsible for its own termination conditions. The comments below describe 
            // how each phase reaches termination.
            switch (currentPhase) {
            case Mark:
                m_slotVisitor->drainFromShared(SlotVisitor::SlaveDrain);
                // GCThreads only return from drainFromShared() if the main thread sets the m_parallelMarkersShouldExit 
                // flag in the GCThreadSharedData. The only way the main thread sets that flag is if it realizes 
                // that all of the various subphases in Heap::markRoots() have been fully finished and there is 
                // no more marking work to do and all of the GCThreads are idle, meaning no more work can be generated.
                break;
            case Copy:
                // We don't have to call startCopying() because it's called for us on the main thread to avoid a 
                // race condition.
                m_copyVisitor->copyFromShared();
                // We know we're done copying when we return from copyFromShared() because we would 
                // only do so if there were no more chunks of copying work left to do. When there is no 
                // more copying work to do, the main thread will wait in CopiedSpace::doneCopying() until 
                // all of the blocks that the GCThreads borrowed have been returned. doneCopying() 
                // returns our borrowed CopiedBlock, allowing the copying phase to finish.
                m_copyVisitor->doneCopying();

                WTF::releaseFastMallocFreeMemoryForThisThread();

                break;
            case NoPhase:
                RELEASE_ASSERT_NOT_REACHED();
                break;
            case Exit:
                RELEASE_ASSERT_NOT_REACHED();
                break;
            }
        }
    }
}

void GCThread::gcThreadStartFunc(void* data)
{
    GCThread* thread = static_cast<GCThread*>(data);
    thread->gcThreadMain();
}

} // namespace JSC
