/*
 * Copyright (C) 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. 
 */

#pragma once

#include "FunctionExecutable.h"
#include "JSCell.h"
#include "JSFunction.h"
#include "NativeExecutable.h"

namespace JSC {

// The CallVariant class is meant to encapsulate a callee in a way that is useful for call linking
// and inlining. Because JavaScript has closures, and because JSC implements the notion of internal
// non-function objects that nevertheless provide call traps, the call machinery wants to see a
// callee in one of the following four forms:
//
// JSFunction callee: This means that we expect the callsite to always call a particular function
//     instance, that is associated with a particular lexical environment. This pinpoints not
//     just the code that will be called (i.e. the executable) but also the scope within which
//     the code runs.
//
// Executable callee: This corresponds to a call to a closure. In this case, we know that the
//     callsite will call a JSFunction, but we do not know which particular JSFunction. We do know
//     what code will be called - i.e. we know the executable.
//
// InternalFunction callee: JSC supports a special kind of native functions that support bizarre
//     semantics. These are always singletons. If we know that the callee is an InternalFunction
//     then we know both the code that will be called and the scope; in fact the "scope" is really
//     just the InternalFunction itself.
//
// Something else: It's possible call all manner of rubbish in JavaScript. This implicitly supports
//     bizarre object callees, but it can't really tell you anything interesting about them other
//     than the fact that they don't fall into any of the above categories.
//
// This class serves as a kind of union over these four things. It does so by just holding a
// JSCell*. We determine which of the modes its in by doing type checks on the cell. Note that we
// cannot use WriteBarrier<> here because this gets used inside the compiler.

class CallVariant {
public:
    explicit CallVariant(JSCell* callee = nullptr)
        : m_callee(callee)
    {
    }
    
    CallVariant(WTF::HashTableDeletedValueType)
        : m_callee(deletedToken())
    {
    }
    
    bool operator!() const { return !m_callee; }
    
    // If this variant refers to a function, change it to refer to its executable.
    ALWAYS_INLINE CallVariant despecifiedClosure() const
    {
        if (m_callee->type() == JSFunctionType)
            return CallVariant(jsCast<JSFunction*>(m_callee)->executable());
        return *this;
    }
    
    JSCell* rawCalleeCell() const { return m_callee; }
    
    InternalFunction* internalFunction() const
    {
        return jsDynamicCast<InternalFunction*>(*m_callee->vm(), m_callee);
    }
    
    JSFunction* function() const
    {
        return jsDynamicCast<JSFunction*>(*m_callee->vm(), m_callee);
    }
    
    bool isClosureCall() const { return !!jsDynamicCast<ExecutableBase*>(*m_callee->vm(), m_callee); }
    
    ExecutableBase* executable() const
    {
        if (JSFunction* function = this->function())
            return function->executable();
        return jsDynamicCast<ExecutableBase*>(*m_callee->vm(), m_callee);
    }
    
    JSCell* nonExecutableCallee() const
    {
        RELEASE_ASSERT(!isClosureCall());
        return m_callee;
    }
    
    Intrinsic intrinsicFor(CodeSpecializationKind kind) const
    {
        if (ExecutableBase* executable = this->executable())
            return executable->intrinsicFor(kind);
        return NoIntrinsic;
    }
    
    FunctionExecutable* functionExecutable() const
    {
        if (ExecutableBase* executable = this->executable())
            return jsDynamicCast<FunctionExecutable*>(*m_callee->vm(), executable);
        return nullptr;
    }

    NativeExecutable* nativeExecutable() const
    {
        if (ExecutableBase* executable = this->executable())
            return jsDynamicCast<NativeExecutable*>(*m_callee->vm(), executable);
        return nullptr;
    }

    const DOMJIT::Signature* signatureFor(CodeSpecializationKind kind) const
    {
        if (NativeExecutable* nativeExecutable = this->nativeExecutable())
            return nativeExecutable->signatureFor(kind);
        return nullptr;
    }
    
    void dump(PrintStream& out) const;
    
    bool isHashTableDeletedValue() const
    {
        return m_callee == deletedToken();
    }
    
    bool operator==(const CallVariant& other) const
    {
        return m_callee == other.m_callee;
    }
    
    bool operator!=(const CallVariant& other) const
    {
        return !(*this == other);
    }
    
    bool operator<(const CallVariant& other) const
    {
        return m_callee < other.m_callee;
    }
    
    bool operator>(const CallVariant& other) const
    {
        return other < *this;
    }
    
    bool operator<=(const CallVariant& other) const
    {
        return !(*this < other);
    }
    
    bool operator>=(const CallVariant& other) const
    {
        return other <= *this;
    }
    
    unsigned hash() const
    {
        return WTF::PtrHash<JSCell*>::hash(m_callee);
    }
    
private:
    static JSCell* deletedToken() { return bitwise_cast<JSCell*>(static_cast<uintptr_t>(1)); }
    
    JSCell* m_callee;
};

struct CallVariantHash {
    static unsigned hash(const CallVariant& key) { return key.hash(); }
    static bool equal(const CallVariant& a, const CallVariant& b) { return a == b; }
    static const bool safeToCompareToEmptyOrDeleted = true;
};

typedef Vector<CallVariant, 1> CallVariantList;

// Returns a new variant list by attempting to either append the given variant or merge it with one
// of the variants we already have by despecifying closures.
CallVariantList variantListWithVariant(const CallVariantList&, CallVariant);

// Returns a new list where every element is despecified, and the list is deduplicated.
CallVariantList despecifiedVariantList(const CallVariantList&);

} // namespace JSC

namespace WTF {

template<typename T> struct DefaultHash;
template<> struct DefaultHash<JSC::CallVariant> {
    typedef JSC::CallVariantHash Hash;
};

template<typename T> struct HashTraits;
template<> struct HashTraits<JSC::CallVariant> : SimpleClassHashTraits<JSC::CallVariant> { };

} // namespace WTF
