/*
 * Copyright (C) 2013-2018 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. ``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
 * 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 "DFGCommonData.h"

#if ENABLE(DFG_JIT)

#include "CodeBlock.h"
#include "DFGNode.h"
#include "DFGPlan.h"
#include "InlineCallFrame.h"
#include "JSCInlines.h"
#include "TrackedReferences.h"
#include "VM.h"

#include <wtf/NeverDestroyed.h>

namespace JSC { namespace DFG {

void CommonData::notifyCompilingStructureTransition(Plan& plan, CodeBlock* codeBlock, Node* node)
{
    plan.transitions().addLazily(
        codeBlock,
        node->origin.semantic.codeOriginOwner(),
        node->transition()->previous.get(),
        node->transition()->next.get());
}

CallSiteIndex CommonData::addCodeOrigin(CodeOrigin codeOrigin)
{
    if (codeOrigins.isEmpty()
        || codeOrigins.last() != codeOrigin)
        codeOrigins.append(codeOrigin);
    unsigned index = codeOrigins.size() - 1;
    ASSERT(codeOrigins[index] == codeOrigin);
    return CallSiteIndex(BytecodeIndex(index));
}

CallSiteIndex CommonData::addUniqueCallSiteIndex(CodeOrigin codeOrigin)
{
    codeOrigins.append(codeOrigin);
    unsigned index = codeOrigins.size() - 1;
    ASSERT(codeOrigins[index] == codeOrigin);
    return CallSiteIndex(BytecodeIndex(index));
}

CallSiteIndex CommonData::lastCallSite() const
{
    RELEASE_ASSERT(codeOrigins.size());
    return CallSiteIndex(BytecodeIndex(codeOrigins.size() - 1));
}

DisposableCallSiteIndex CommonData::addDisposableCallSiteIndex(CodeOrigin codeOrigin)
{
    if (callSiteIndexFreeList.size()) {
        unsigned index = callSiteIndexFreeList.takeAny();
        codeOrigins[index] = codeOrigin;
        return DisposableCallSiteIndex(index);
    }

    codeOrigins.append(codeOrigin);
    unsigned index = codeOrigins.size() - 1;
    ASSERT(codeOrigins[index] == codeOrigin);
    return DisposableCallSiteIndex(index);
}


void CommonData::removeDisposableCallSiteIndex(DisposableCallSiteIndex callSite)
{
    RELEASE_ASSERT(callSite.bits() < codeOrigins.size());
    callSiteIndexFreeList.add(callSite.bits());
    codeOrigins[callSite.bits()] = CodeOrigin();
}

void CommonData::shrinkToFit()
{
    codeOrigins.shrinkToFit();
    dfgIdentifiers.shrinkToFit();
    weakReferences.shrinkToFit();
    weakStructureReferences.shrinkToFit();
    transitions.shrinkToFit();
    catchEntrypoints.shrinkToFit();
    jumpReplacements.shrinkToFit();
}

static Lock pcCodeBlockMapLock;
inline HashMap<void*, CodeBlock*>& pcCodeBlockMap(AbstractLocker&)
{
    static NeverDestroyed<HashMap<void*, CodeBlock*>> pcCodeBlockMap;
    return pcCodeBlockMap;
}

bool CommonData::invalidate()
{
    if (!isStillValid)
        return false;

    if (UNLIKELY(hasVMTrapsBreakpointsInstalled)) {
        LockHolder locker(pcCodeBlockMapLock);
        auto& map = pcCodeBlockMap(locker);
        for (auto& jumpReplacement : jumpReplacements)
            map.remove(jumpReplacement.dataLocation());
        hasVMTrapsBreakpointsInstalled = false;
    }

    for (unsigned i = jumpReplacements.size(); i--;)
        jumpReplacements[i].fire();
    isStillValid = false;
    return true;
}

CommonData::~CommonData()
{
    if (UNLIKELY(hasVMTrapsBreakpointsInstalled)) {
        LockHolder locker(pcCodeBlockMapLock);
        auto& map = pcCodeBlockMap(locker);
        for (auto& jumpReplacement : jumpReplacements)
            map.remove(jumpReplacement.dataLocation());
    }
}

void CommonData::installVMTrapBreakpoints(CodeBlock* owner)
{
    LockHolder locker(pcCodeBlockMapLock);
    if (!isStillValid || hasVMTrapsBreakpointsInstalled)
        return;
    hasVMTrapsBreakpointsInstalled = true;

    auto& map = pcCodeBlockMap(locker);
#if !defined(NDEBUG)
    // We need to be able to handle more than one invalidation point at the same pc
    // but we want to make sure we don't forget to remove a pc from the map.
    HashSet<void*> newReplacements;
#endif
    for (auto& jumpReplacement : jumpReplacements) {
        jumpReplacement.installVMTrapBreakpoint();
        void* source = jumpReplacement.dataLocation();
        auto result = map.add(source, owner);
        UNUSED_PARAM(result);
#if !defined(NDEBUG)
        ASSERT(result.isNewEntry || newReplacements.contains(source));
        newReplacements.add(source);
#endif
    }
}

CodeBlock* codeBlockForVMTrapPC(void* pc)
{
    ASSERT(isJITPC(pc));
    LockHolder locker(pcCodeBlockMapLock);
    auto& map = pcCodeBlockMap(locker);
    auto result = map.find(pc);
    if (result == map.end())
        return nullptr;
    return result->value;
}

bool CommonData::isVMTrapBreakpoint(void* address)
{
    if (!isStillValid)
        return false;
    for (unsigned i = jumpReplacements.size(); i--;) {
        if (address == jumpReplacements[i].dataLocation())
            return true;
    }
    return false;
}

void CommonData::validateReferences(const TrackedReferences& trackedReferences)
{
    if (InlineCallFrameSet* set = inlineCallFrames.get()) {
        for (InlineCallFrame* inlineCallFrame : *set) {
            for (ValueRecovery& recovery : inlineCallFrame->argumentsWithFixup) {
                if (recovery.isConstant())
                    trackedReferences.check(recovery.constant());
            }
            
            if (CodeBlock* baselineCodeBlock = inlineCallFrame->baselineCodeBlock.get())
                trackedReferences.check(baselineCodeBlock);
            
            if (inlineCallFrame->calleeRecovery.isConstant())
                trackedReferences.check(inlineCallFrame->calleeRecovery.constant());
        }
    }
    
    for (AdaptiveStructureWatchpoint* watchpoint : adaptiveStructureWatchpoints)
        watchpoint->key().validateReferences(trackedReferences);
}

void CommonData::finalizeCatchEntrypoints()
{
    std::sort(catchEntrypoints.begin(), catchEntrypoints.end(),
        [] (const CatchEntrypointData& a, const CatchEntrypointData& b) { return a.bytecodeIndex < b.bytecodeIndex; });

#if !ASSERT_DISABLED
    for (unsigned i = 0; i + 1 < catchEntrypoints.size(); ++i)
        ASSERT(catchEntrypoints[i].bytecodeIndex <= catchEntrypoints[i + 1].bytecodeIndex);
#endif
}

void CommonData::clearWatchpoints()
{
    watchpoints.clear();
    adaptiveStructureWatchpoints.clear();
    adaptiveInferredPropertyValueWatchpoints.clear();
}

} } // namespace JSC::DFG

#endif // ENABLE(DFG_JIT)

