/*
 * Copyright (C) 2008, 2014, 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. ``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 "StructureStubInfo.h"

#include "JSObject.h"
#include "PolymorphicAccess.h"
#include "Repatch.h"

namespace JSC {

#if ENABLE(JIT)
StructureStubInfo::StructureStubInfo(AccessType accessType)
    : callSiteIndex(UINT_MAX)
    , accessType(accessType)
    , cacheType(CacheType::Unset)
    , countdown(1) // For a totally clear stub, we'll patch it after the first execution.
    , repatchCount(0)
    , numberOfCoolDowns(0)
    , resetByGC(false)
    , tookSlowPath(false)
    , everConsidered(false)
{
}

StructureStubInfo::~StructureStubInfo()
{
}

void StructureStubInfo::initGetByIdSelf(CodeBlock* codeBlock, Structure* baseObjectStructure, PropertyOffset offset)
{
    cacheType = CacheType::GetByIdSelf;
    
    u.byIdSelf.baseObjectStructure.set(
        *codeBlock->vm(), codeBlock, baseObjectStructure);
    u.byIdSelf.offset = offset;
}

void StructureStubInfo::initPutByIdReplace(CodeBlock* codeBlock, Structure* baseObjectStructure, PropertyOffset offset)
{
    cacheType = CacheType::PutByIdReplace;
    
    u.byIdSelf.baseObjectStructure.set(
        *codeBlock->vm(), codeBlock, baseObjectStructure);
    u.byIdSelf.offset = offset;
}

void StructureStubInfo::initStub(CodeBlock*, std::unique_ptr<PolymorphicAccess> stub)
{
    cacheType = CacheType::Stub;
    u.stub = stub.release();
}

void StructureStubInfo::deref()
{
    switch (cacheType) {
    case CacheType::Stub:
        delete u.stub;
        return;
    case CacheType::Unset:
    case CacheType::GetByIdSelf:
    case CacheType::PutByIdReplace:
        return;
    }

    RELEASE_ASSERT_NOT_REACHED();
}

void StructureStubInfo::aboutToDie()
{
    switch (cacheType) {
    case CacheType::Stub:
        u.stub->aboutToDie();
        return;
    case CacheType::Unset:
    case CacheType::GetByIdSelf:
    case CacheType::PutByIdReplace:
        return;
    }

    RELEASE_ASSERT_NOT_REACHED();
}

MacroAssemblerCodePtr StructureStubInfo::addAccessCase(
    CodeBlock* codeBlock, const Identifier& ident, std::unique_ptr<AccessCase> accessCase)
{
    VM& vm = *codeBlock->vm();
    
    if (!accessCase)
        return MacroAssemblerCodePtr();
    
    if (cacheType == CacheType::Stub)
        return u.stub->regenerateWithCase(vm, codeBlock, *this, ident, WTF::move(accessCase));

    std::unique_ptr<PolymorphicAccess> access = std::make_unique<PolymorphicAccess>();
    
    Vector<std::unique_ptr<AccessCase>> accessCases;
    
    std::unique_ptr<AccessCase> previousCase =
        AccessCase::fromStructureStubInfo(vm, codeBlock, *this);
    if (previousCase)
        accessCases.append(WTF::move(previousCase));

    accessCases.append(WTF::move(accessCase));

    MacroAssemblerCodePtr result =
        access->regenerateWithCases(vm, codeBlock, *this, ident, WTF::move(accessCases));

    if (!result)
        return MacroAssemblerCodePtr();

    initStub(codeBlock, WTF::move(access));
    return result;
}

void StructureStubInfo::reset(CodeBlock* codeBlock)
{
    if (cacheType == CacheType::Unset)
        return;
    
    if (Options::verboseOSR()) {
        // This can be called from GC destructor calls, so we don't try to do a full dump
        // of the CodeBlock.
        dataLog("Clearing structure cache (kind ", static_cast<int>(accessType), ") in ", RawPointer(codeBlock), ".\n");
    }

    switch (accessType) {
    case AccessType::Get:
        resetGetByID(codeBlock, *this);
        break;
    case AccessType::Put:
        resetPutByID(codeBlock, *this);
        break;
    case AccessType::In:
        resetIn(codeBlock, *this);
        break;
    }
    
    deref();
    cacheType = CacheType::Unset;
}

void StructureStubInfo::visitWeakReferences(CodeBlock* codeBlock)
{
    VM& vm = *codeBlock->vm();

    switch (cacheType) {
    case CacheType::GetByIdSelf:
    case CacheType::PutByIdReplace:
        if (Heap::isMarked(u.byIdSelf.baseObjectStructure.get()))
            return;
        break;
    case CacheType::Stub:
        if (u.stub->visitWeak(vm))
            return;
        break;
    default:
        return;
    }

    reset(codeBlock);
    resetByGC = true;
}
#endif

} // namespace JSC
