/*
 *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
 *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
 *  Copyright (C) 2003-2019 Apple Inc. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library 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
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 *
 */

#pragma once

#include "AbstractPC.h"
#include "CalleeBits.h"
#include "MacroAssemblerCodeRef.h"
#include "Register.h"
#include "StackVisitor.h"
#include "VM.h"
#include "VMEntryRecord.h"
#include <wtf/EnumClassOperatorOverloads.h>

namespace JSC  {

    class Arguments;
    class CallFrame;
    class Interpreter;
    class JSCallee;
    class JSScope;
    class SourceOrigin;

    struct Instruction;

    class CallSiteIndex {
    public:
        CallSiteIndex() = default;
        
        explicit CallSiteIndex(BytecodeIndex bytecodeIndex)
            : m_bits(bytecodeIndex.offset())
        { 
            ASSERT(!bytecodeIndex.checkpoint());
        }
        explicit CallSiteIndex(uint32_t bits)
            : m_bits(bits)
        { }

        explicit operator bool() const { return !!m_bits; }
        bool operator==(const CallSiteIndex& other) const { return m_bits == other.m_bits; }

        uint32_t bits() const { return m_bits; }
        static CallSiteIndex fromBits(uint32_t bits) { return CallSiteIndex(bits); }

        BytecodeIndex bytecodeIndex() const { return BytecodeIndex(bits()); }

    private:
        uint32_t m_bits { BytecodeIndex().offset() };
    };

    class DisposableCallSiteIndex : public CallSiteIndex {
    public:
        DisposableCallSiteIndex() = default;

        explicit DisposableCallSiteIndex(uint32_t bits)
            : CallSiteIndex(bits)
        {
        }

        static DisposableCallSiteIndex fromCallSiteIndex(CallSiteIndex callSiteIndex)
        {
            return DisposableCallSiteIndex(callSiteIndex.bits());
        }
    };

    // arm64_32 expects caller frame and return pc to use 8 bytes 
    struct CallerFrameAndPC {
        alignas(CPURegister) CallFrame* callerFrame;
        alignas(CPURegister) void* returnPC;
        static constexpr int sizeInRegisters = 2 * sizeof(CPURegister) / sizeof(Register);
    };
    static_assert(CallerFrameAndPC::sizeInRegisters == sizeof(CallerFrameAndPC) / sizeof(Register), "CallerFrameAndPC::sizeInRegisters is incorrect.");

    enum class CallFrameSlot : int {
        codeBlock = CallerFrameAndPC::sizeInRegisters,
        callee = codeBlock + 1,
        argumentCountIncludingThis = callee + 1,
        thisArgument = argumentCountIncludingThis + 1,
        firstArgument = thisArgument + 1,
    };

    OVERLOAD_MATH_OPERATORS_FOR_ENUM_CLASS_WITH_INTEGRALS(CallFrameSlot)
    OVERLOAD_RELATIONAL_OPERATORS_FOR_ENUM_CLASS_WITH_INTEGRALS(CallFrameSlot)

    // Represents the current state of script execution.
    // Passed as the first argument to most functions.
    class CallFrame : private Register {
    public:
        static constexpr int headerSizeInRegisters = static_cast<int>(CallFrameSlot::argumentCountIncludingThis) + 1;

        // This function should only be called in very specific circumstances
        // when you've guaranteed the callee can't be a Wasm callee, and can
        // be an arbitrary JSValue. This function should basically never be used.
        // Its only use right now is when we are making a call, and we're not
        // yet sure if the callee is a cell. In general, a JS callee is guaranteed
        // to be a cell, however, there is a brief window where we need to check
        // to see if it's a cell, and if it's not, we throw an exception.
        inline JSValue guaranteedJSValueCallee() const;
        inline JSObject* jsCallee() const;
        CalleeBits callee() const { return CalleeBits(this[static_cast<int>(CallFrameSlot::callee)].pointer()); }
        SUPPRESS_ASAN CalleeBits unsafeCallee() const { return CalleeBits(this[static_cast<int>(CallFrameSlot::callee)].asanUnsafePointer()); }
        CodeBlock* codeBlock() const;
        CodeBlock** addressOfCodeBlock() const { return bitwise_cast<CodeBlock**>(this + static_cast<int>(CallFrameSlot::codeBlock)); }
        inline SUPPRESS_ASAN CodeBlock* unsafeCodeBlock() const;
        inline JSScope* scope(int scopeRegisterOffset) const;

        JS_EXPORT_PRIVATE bool isAnyWasmCallee();

        // Global object in which the currently executing code was defined.
        // Differs from VM::deprecatedVMEntryGlobalObject() during function calls across web browser frames.
        JSGlobalObject* lexicalGlobalObject(VM&) const;

        // FIXME: Remove this function
        // https://bugs.webkit.org/show_bug.cgi?id=203272
        VM& deprecatedVM() const;

        static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); }
        Register* registers() { return this; }
        const Register* registers() const { return this; }

        CallFrame& operator=(const Register& r) { *static_cast<Register*>(this) = r; return *this; }

        CallFrame* callerFrame() const { return static_cast<CallFrame*>(callerFrameOrEntryFrame()); }
        void* callerFrameOrEntryFrame() const { return callerFrameAndPC().callerFrame; }
        SUPPRESS_ASAN void* unsafeCallerFrameOrEntryFrame() const { return unsafeCallerFrameAndPC().callerFrame; }

        CallFrame* unsafeCallerFrame(EntryFrame*&) const;
        JS_EXPORT_PRIVATE CallFrame* callerFrame(EntryFrame*&) const;

        JS_EXPORT_PRIVATE SourceOrigin callerSourceOrigin(VM&);

        static ptrdiff_t callerFrameOffset() { return OBJECT_OFFSETOF(CallerFrameAndPC, callerFrame); }

        ReturnAddressPtr returnPC() const { return ReturnAddressPtr(callerFrameAndPC().returnPC); }
        bool hasReturnPC() const { return !!callerFrameAndPC().returnPC; }
        void clearReturnPC() { callerFrameAndPC().returnPC = nullptr; }
        static ptrdiff_t returnPCOffset() { return OBJECT_OFFSETOF(CallerFrameAndPC, returnPC); }
        AbstractPC abstractReturnPC(VM& vm) { return AbstractPC(vm, this); }

        bool callSiteBitsAreBytecodeOffset() const;
        bool callSiteBitsAreCodeOriginIndex() const;

        unsigned callSiteAsRawBits() const;
        unsigned unsafeCallSiteAsRawBits() const;
        CallSiteIndex callSiteIndex() const;
        CallSiteIndex unsafeCallSiteIndex() const;
    private:
        unsigned callSiteBitsAsBytecodeOffset() const;
#if ENABLE(WEBASSEMBLY)
        JS_EXPORT_PRIVATE JSGlobalObject* lexicalGlobalObjectFromWasmCallee(VM&) const;
#endif
    public:

        // This will try to get you the bytecode offset, but you should be aware that
        // this bytecode offset may be bogus in the presence of inlining. This will
        // also return 0 if the call frame has no notion of bytecode offsets (for
        // example if it's native code).
        // https://bugs.webkit.org/show_bug.cgi?id=121754
        BytecodeIndex bytecodeIndex();
        
        // This will get you a CodeOrigin. It will always succeed. May return
        // CodeOrigin(BytecodeIndex(0)) if we're in native code.
        JS_EXPORT_PRIVATE CodeOrigin codeOrigin();

        inline Register* topOfFrame();
    
        const Instruction* currentVPC() const; // This only makes sense in the LLInt and baseline.
        void setCurrentVPC(const Instruction*);

        void setCallerFrame(CallFrame* frame) { callerFrameAndPC().callerFrame = frame; }
        inline void setScope(int scopeRegisterOffset, JSScope*);

        static void initDeprecatedCallFrameForDebugger(CallFrame* globalExec, JSCallee* globalCallee);

        // Read a register from the codeframe (or constant from the CodeBlock).
        Register& r(VirtualRegister);
        // Read a register for a known non-constant
        Register& uncheckedR(VirtualRegister);

        // Access to arguments as passed. (After capture, arguments may move to a different location.)
        size_t argumentCount() const { return argumentCountIncludingThis() - 1; }
        size_t argumentCountIncludingThis() const { return this[static_cast<int>(CallFrameSlot::argumentCountIncludingThis)].payload(); }
        static int argumentOffset(int argument) { return (CallFrameSlot::firstArgument + argument); }
        static int argumentOffsetIncludingThis(int argument) { return (CallFrameSlot::thisArgument + argument); }

        // In the following (argument() and setArgument()), the 'argument'
        // parameter is the index of the arguments of the target function of
        // this frame. The index starts at 0 for the first arg, 1 for the
        // second, etc.
        //
        // The arguments (in this case) do not include the 'this' value.
        // arguments(0) will not fetch the 'this' value. To get/set 'this',
        // use thisValue() and setThisValue() below.

        JSValue* addressOfArgumentsStart() const { return bitwise_cast<JSValue*>(this + argumentOffset(0)); }
        JSValue argument(size_t argument)
        {
            if (argument >= argumentCount())
                 return jsUndefined();
            return getArgumentUnsafe(argument);
        }
        JSValue uncheckedArgument(size_t argument)
        {
            ASSERT(argument < argumentCount());
            return getArgumentUnsafe(argument);
        }
        void setArgument(size_t argument, JSValue value)
        {
            this[argumentOffset(argument)] = value;
        }

        JSValue getArgumentUnsafe(size_t argIndex)
        {
            // User beware! This method does not verify that there is a valid
            // argument at the specified argIndex. This is used for debugging
            // and verification code only. The caller is expected to know what
            // he/she is doing when calling this method.
            return this[argumentOffset(argIndex)].jsValue();
        }

        static int thisArgumentOffset() { return argumentOffsetIncludingThis(0); }
        JSValue thisValue() { return this[thisArgumentOffset()].jsValue(); }
        void setThisValue(JSValue value) { this[thisArgumentOffset()] = value; }

        // Under the constructor implemented in C++, thisValue holds the newTarget instead of the automatically constructed value.
        // The result of this function is only effective under the "construct" context.
        JSValue newTarget() { return thisValue(); }

        JSValue argumentAfterCapture(size_t argument);

        static int offsetFor(size_t argumentCountIncludingThis) { return CallFrameSlot::thisArgument + argumentCountIncludingThis - 1; }

        static CallFrame* noCaller() { return nullptr; }
        bool isDeprecatedCallFrameForDebugger() const
        {
            return callerFrameAndPC().callerFrame == noCaller() && callerFrameAndPC().returnPC == nullptr;
        }

        void convertToStackOverflowFrame(VM&, CodeBlock* codeBlockToKeepAliveUntilFrameIsUnwound);
        bool isStackOverflowFrame() const;
        bool isWasmFrame() const;

        void setArgumentCountIncludingThis(int count) { static_cast<Register*>(this)[static_cast<int>(CallFrameSlot::argumentCountIncludingThis)].payload() = count; }
        inline void setCallee(JSObject*);
        inline void setCodeBlock(CodeBlock*);
        void setReturnPC(void* value) { callerFrameAndPC().returnPC = value; }

        String friendlyFunctionName();

        // CallFrame::iterate() expects a Functor that implements the following method:
        //     StackVisitor::Status operator()(StackVisitor&) const;
        // FIXME: This method is improper. We rely on the fact that we can call it with a null
        // receiver. We should always be using StackVisitor directly.
        // It's only valid to call this from a non-wasm top frame.
        template <StackVisitor::EmptyEntryFrameAction action = StackVisitor::ContinueIfTopEntryFrameIsEmpty, typename Functor> void iterate(VM& vm, const Functor& functor)
        {
            void* rawThis = this;
            if (!!rawThis)
                RELEASE_ASSERT(callee().isCell());
            StackVisitor::visit<action, Functor>(this, vm, functor);
        }

        void dump(PrintStream&);

    private:

        CallFrame();
        ~CallFrame();

        Register* topOfFrameInternal();

        // The following are for internal use in debugging and verification
        // code only and not meant as an API for general usage:

        size_t argIndexForRegister(Register* reg)
        {
            // The register at 'offset' number of slots from the frame pointer
            // i.e.
            //       reg = frame[offset];
            //   ==> reg = frame + offset;
            //   ==> offset = reg - frame;
            int offset = reg - this->registers();

            // The offset is defined (based on argumentOffset()) to be:
            //       offset = CallFrameSlot::firstArgument - argIndex;
            // Hence:
            //       argIndex = CallFrameSlot::firstArgument - offset;
            size_t argIndex = offset - CallFrameSlot::firstArgument;
            return argIndex;
        }

        CallerFrameAndPC& callerFrameAndPC() { return *reinterpret_cast<CallerFrameAndPC*>(this); }
        const CallerFrameAndPC& callerFrameAndPC() const { return *reinterpret_cast<const CallerFrameAndPC*>(this); }
        SUPPRESS_ASAN const CallerFrameAndPC& unsafeCallerFrameAndPC() const { return *reinterpret_cast<const CallerFrameAndPC*>(this); }
    };

JS_EXPORT_PRIVATE bool isFromJSCode(void* returnAddress);

#if USE(BUILTIN_FRAME_ADDRESS)
#define DECLARE_CALL_FRAME(vm) \
    ({ \
        ASSERT(JSC::isFromJSCode(removeCodePtrTag<void*>(__builtin_return_address(0)))); \
        bitwise_cast<JSC::CallFrame*>(__builtin_frame_address(1)); \
    })
#else
#define DECLARE_CALL_FRAME(vm) ((vm).topCallFrame)
#endif


} // namespace JSC
