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

#ifndef Executable_h
#define Executable_h

#include "JSFunction.h"
#include "Interpreter.h"
#include "Nodes.h"
#include "SamplingTool.h"

namespace JSC {

    class CodeBlock;
    class Debugger;
    class EvalCodeBlock;
    class ProgramCodeBlock;
    class ScopeChainNode;

    struct ExceptionInfo;

    class ExecutableBase : public RefCounted<ExecutableBase> {
        friend class JIT;

    protected:
        static const int NUM_PARAMETERS_IS_HOST = 0;
        static const int NUM_PARAMETERS_NOT_COMPILED = -1;
    
    public:
        ExecutableBase(int numParameters)
            : m_numParameters(numParameters)
        {
        }

        virtual ~ExecutableBase() {}

        bool isHostFunction() const { return m_numParameters == NUM_PARAMETERS_IS_HOST; }

    protected:
        int m_numParameters;

#if ENABLE(JIT)
    public:
        JITCode& generatedJITCode()
        {
            ASSERT(m_jitCode);
            return m_jitCode;
        }

        ExecutablePool* getExecutablePool()
        {
            return m_jitCode.getExecutablePool();
        }

    protected:
        JITCode m_jitCode;
#endif
    };

#if ENABLE(JIT)
    class NativeExecutable : public ExecutableBase {
    public:
        NativeExecutable(ExecState* exec)
            : ExecutableBase(NUM_PARAMETERS_IS_HOST)
        {
            m_jitCode = JITCode(JITCode::HostFunction(exec->globalData().jitStubs.ctiNativeCallThunk()));
        }

        ~NativeExecutable();
    };
#endif

    class VPtrHackExecutable : public ExecutableBase {
    public:
        VPtrHackExecutable()
            : ExecutableBase(NUM_PARAMETERS_IS_HOST)
        {
        }

        ~VPtrHackExecutable();
    };

    class ScriptExecutable : public ExecutableBase {
    public:
        ScriptExecutable(JSGlobalData* globalData, const SourceCode& source)
            : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
            , m_source(source)
            , m_features(0)
        {
#if ENABLE(CODEBLOCK_SAMPLING)
            if (SamplingTool* sampler = globalData->interpreter->sampler())
                sampler->notifyOfScope(this);
#else
            UNUSED_PARAM(globalData);
#endif
        }

        ScriptExecutable(ExecState* exec, const SourceCode& source)
            : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
            , m_source(source)
            , m_features(0)
        {
#if ENABLE(CODEBLOCK_SAMPLING)
            if (SamplingTool* sampler = exec->globalData().interpreter->sampler())
                sampler->notifyOfScope(this);
#else
            UNUSED_PARAM(exec);
#endif
        }

        const SourceCode& source() { return m_source; }
        intptr_t sourceID() const { return m_source.provider()->asID(); }
        const UString& sourceURL() const { return m_source.provider()->url(); }
        int lineNo() const { return m_firstLine; }
        int lastLine() const { return m_lastLine; }

        bool usesEval() const { return m_features & EvalFeature; }
        bool usesArguments() const { return m_features & ArgumentsFeature; }
        bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); }

        virtual ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) = 0;

    protected:
        void recordParse(CodeFeatures features, int firstLine, int lastLine)
        {
            m_features = features;
            m_firstLine = firstLine;
            m_lastLine = lastLine;
        }

        SourceCode m_source;
        CodeFeatures m_features;
        int m_firstLine;
        int m_lastLine;
    };

    class EvalExecutable : public ScriptExecutable {
    public:

        ~EvalExecutable();

        EvalCodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode)
        {
            if (!m_evalCodeBlock) {
                JSObject* error = compile(exec, scopeChainNode);
                ASSERT_UNUSED(!error, error);
            }
            return *m_evalCodeBlock;
        }

        JSObject* compile(ExecState*, ScopeChainNode*);

        ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
        static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source) { return adoptRef(new EvalExecutable(exec, source)); }

    private:
        EvalExecutable(ExecState* exec, const SourceCode& source)
            : ScriptExecutable(exec, source)
            , m_evalCodeBlock(0)
        {
        }
        EvalCodeBlock* m_evalCodeBlock;

#if ENABLE(JIT)
    public:
        JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode)
        {
            if (!m_jitCode)
                generateJITCode(exec, scopeChainNode);
            return m_jitCode;
        }

    private:
        void generateJITCode(ExecState*, ScopeChainNode*);
#endif
    };

    class ProgramExecutable : public ScriptExecutable {
    public:
        static PassRefPtr<ProgramExecutable> create(ExecState* exec, const SourceCode& source)
        {
            return adoptRef(new ProgramExecutable(exec, source));
        }

        ~ProgramExecutable();

        ProgramCodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode)
        {
            if (!m_programCodeBlock) {
                JSObject* error = compile(exec, scopeChainNode);
                ASSERT_UNUSED(!error, error);
            }
            return *m_programCodeBlock;
        }

        JSObject* checkSyntax(ExecState*);
        JSObject* compile(ExecState*, ScopeChainNode*);

        // CodeBlocks for program code are transient and therefore do not gain from from throwing out there exception information.
        ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) { ASSERT_NOT_REACHED(); return 0; }

    private:
        ProgramExecutable(ExecState* exec, const SourceCode& source)
            : ScriptExecutable(exec, source)
            , m_programCodeBlock(0)
        {
        }
        ProgramCodeBlock* m_programCodeBlock;

#if ENABLE(JIT)
    public:
        JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode)
        {
            if (!m_jitCode)
                generateJITCode(exec, scopeChainNode);
            return m_jitCode;
        }

    private:
        void generateJITCode(ExecState*, ScopeChainNode*);
#endif
    };

    class FunctionExecutable : public ScriptExecutable {
        friend class JIT;
    public:
        static PassRefPtr<FunctionExecutable> create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
        {
            return adoptRef(new FunctionExecutable(exec, name, source, forceUsesArguments, parameters, firstLine, lastLine));
        }

        static PassRefPtr<FunctionExecutable> create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
        {
            return adoptRef(new FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, firstLine, lastLine));
        }

        ~FunctionExecutable();

        JSFunction* make(ExecState* exec, ScopeChainNode* scopeChain)
        {
            return new (exec) JSFunction(exec, this, scopeChain);
        }

        CodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode) 
        {
            ASSERT(scopeChainNode);
            if (!m_codeBlock)
                compile(exec, scopeChainNode);
            return *m_codeBlock;
        }

        bool isGenerated() const
        {
            return m_codeBlock;
        }

        CodeBlock& generatedBytecode()
        {
            ASSERT(m_codeBlock);
            return *m_codeBlock;
        }

        const Identifier& name() { return m_name; }
        size_t parameterCount() const { return m_parameters->size(); }
        size_t variableCount() const { return m_numVariables; }
        UString paramString() const;

        void recompile(ExecState*);
        ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
        void markAggregate(MarkStack& markStack);
        static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, int* errLine = 0, UString* errMsg = 0);

    private:
        FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
            : ScriptExecutable(globalData, source)
            , m_forceUsesArguments(forceUsesArguments)
            , m_parameters(parameters)
            , m_codeBlock(0)
            , m_name(name)
            , m_numVariables(0)
        {
            m_firstLine = firstLine;
            m_lastLine = lastLine;
        }

        FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
            : ScriptExecutable(exec, source)
            , m_forceUsesArguments(forceUsesArguments)
            , m_parameters(parameters)
            , m_codeBlock(0)
            , m_name(name)
            , m_numVariables(0)
        {
            m_firstLine = firstLine;
            m_lastLine = lastLine;
        }

        void compile(ExecState*, ScopeChainNode*);

        bool m_forceUsesArguments;
        RefPtr<FunctionParameters> m_parameters;
        CodeBlock* m_codeBlock;
        Identifier m_name;
        size_t m_numVariables;

#if ENABLE(JIT)
    public:
        JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode)
        {
            if (!m_jitCode)
                generateJITCode(exec, scopeChainNode);
            return m_jitCode;
        }

    private:
        void generateJITCode(ExecState*, ScopeChainNode*);
#endif
    };

    inline FunctionExecutable* JSFunction::jsExecutable() const
    {
        ASSERT(!isHostFunctionNonInline());
        return static_cast<FunctionExecutable*>(m_executable.get());
    }

    inline bool JSFunction::isHostFunction() const
    {
        ASSERT(m_executable);
        return m_executable->isHostFunction();
    }

}

#endif
