Unreviewed, rolling out r189079.
[WebKit-https.git] / Source / JavaScriptCore / runtime / Executable.h
index 233fb12..b513547 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009, 2010, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010, 2013-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
 #ifndef Executable_h
 #define Executable_h
 
+#include "ArityCheckMode.h"
 #include "CallData.h"
 #include "CodeBlockHash.h"
 #include "CodeSpecializationKind.h"
 #include "CompilationResult.h"
 #include "DFGPlan.h"
+#include "ExecutableInfo.h"
 #include "HandlerInfo.h"
-#include "JSFunction.h"
-#include "Interpreter.h"
+#include "InferredValue.h"
 #include "JITCode.h"
 #include "JSGlobalObject.h"
-#include "LLIntCLoop.h"
+#include "RegisterPreservationMode.h"
 #include "SamplingTool.h"
 #include "SourceCode.h"
+#include "TypeSet.h"
 #include "UnlinkedCodeBlock.h"
-#include <wtf/PassOwnPtr.h>
+#include "UnlinkedFunctionExecutable.h"
 
 namespace JSC {
 
-    class CodeBlock;
-    class Debugger;
-    class EvalCodeBlock;
-    class FunctionCodeBlock;
-    class LLIntOffsetsExtractor;
-    class ProgramCodeBlock;
-    class JSScope;
+class CodeBlock;
+class Debugger;
+class EvalCodeBlock;
+class FunctionCodeBlock;
+class LLIntOffsetsExtractor;
+class ProgramCodeBlock;
+class JSScope;
     
-    enum CompilationKind { FirstCompilation, OptimizingCompilation };
-
-    inline bool isCall(CodeSpecializationKind kind)
-    {
-        if (kind == CodeForCall)
-            return true;
-        ASSERT(kind == CodeForConstruct);
-        return false;
-    }
+enum CompilationKind { FirstCompilation, OptimizingCompilation };
+
+inline bool isCall(CodeSpecializationKind kind)
+{
+    if (kind == CodeForCall)
+        return true;
+    ASSERT(kind == CodeForConstruct);
+    return false;
+}
 
-    class ExecutableBase : public JSCell, public DoublyLinkedListNode<ExecutableBase> {
-        friend class WTF::DoublyLinkedListNode<ExecutableBase>;
-        friend class JIT;
+class ExecutableBase : public JSCell {
+    friend class JIT;
 
-    protected:
-        static const int NUM_PARAMETERS_IS_HOST = 0;
-        static const int NUM_PARAMETERS_NOT_COMPILED = -1;
+protected:
+    static const int NUM_PARAMETERS_IS_HOST = 0;
+    static const int NUM_PARAMETERS_NOT_COMPILED = -1;
 
-        ExecutableBase(VM& vm, Structure* structure, int numParameters)
-            : JSCell(vm, structure)
-            , m_numParametersForCall(numParameters)
-            , m_numParametersForConstruct(numParameters)
-        {
-        }
+    ExecutableBase(VM& vm, Structure* structure, int numParameters)
+        : JSCell(vm, structure)
+        , m_numParametersForCall(numParameters)
+        , m_numParametersForConstruct(numParameters)
+    {
+    }
 
-        void finishCreation(VM& vm)
-        {
-            Base::finishCreation(vm);
-        }
+    void finishCreation(VM& vm)
+    {
+        Base::finishCreation(vm);
+    }
 
-    public:
-        typedef JSCell Base;
+public:
+    typedef JSCell Base;
+    static const unsigned StructureFlags = Base::StructureFlags;
 
-#if ENABLE(JIT)
-        static const bool needsDestruction = true;
-        static const bool hasImmortalStructure = true;
-        static void destroy(JSCell*);
-#endif
+    static const bool needsDestruction = true;
+    static void destroy(JSCell*);
         
-        CodeBlockHash hashFor(CodeSpecializationKind) const;
+    CodeBlockHash hashFor(CodeSpecializationKind) const;
 
-        bool isFunctionExecutable()
-        {
-            return structure()->typeInfo().type() == FunctionExecutableType;
-        }
+    bool isEvalExecutable()
+    {
+        return type() == EvalExecutableType;
+    }
+    bool isFunctionExecutable()
+    {
+        return type() == FunctionExecutableType;
+    }
+    bool isProgramExecutable()
+    {
+        return type() == ProgramExecutableType;
+    }
 
-        bool isHostFunction() const
-        {
-            ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
-            return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
-        }
+    bool isHostFunction() const
+    {
+        ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
+        return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
+    }
 
-        static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); }
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); }
         
-        void clearCode();
-
-        static JS_EXPORTDATA const ClassInfo s_info;
+    void clearCode();
 
-    protected:
-        static const unsigned StructureFlags = 0;
-        int m_numParametersForCall;
-        int m_numParametersForConstruct;
+    DECLARE_EXPORT_INFO;
 
-    public:
-        static void clearCodeVirtual(ExecutableBase*);
+protected:
+    int m_numParametersForCall;
+    int m_numParametersForConstruct;
 
-#if ENABLE(JIT)
-        PassRefPtr<JITCode> generatedJITCodeForCall()
-        {
-            ASSERT(m_jitCodeForCall);
-            return m_jitCodeForCall;
-        }
-
-        PassRefPtr<JITCode> generatedJITCodeForConstruct()
-        {
-            ASSERT(m_jitCodeForConstruct);
-            return m_jitCodeForConstruct;
-        }
-        
-        PassRefPtr<JITCode> generatedJITCodeFor(CodeSpecializationKind kind)
-        {
-            if (kind == CodeForCall)
-                return generatedJITCodeForCall();
-            ASSERT(kind == CodeForConstruct);
-            return generatedJITCodeForConstruct();
-        }
+public:
+    static void clearCodeVirtual(ExecutableBase*);
 
-        MacroAssemblerCodePtr generatedJITCodeForCallWithArityCheck()
-        {
-            ASSERT(m_jitCodeForCall);
-            ASSERT(m_jitCodeForCallWithArityCheck);
-            return m_jitCodeForCallWithArityCheck;
-        }
+    PassRefPtr<JITCode> generatedJITCodeForCall()
+    {
+        ASSERT(m_jitCodeForCall);
+        return m_jitCodeForCall;
+    }
 
-        MacroAssemblerCodePtr generatedJITCodeForConstructWithArityCheck()
-        {
-            ASSERT(m_jitCodeForConstruct);
-            ASSERT(m_jitCodeForConstructWithArityCheck);
-            return m_jitCodeForConstructWithArityCheck;
-        }
-        
-        MacroAssemblerCodePtr generatedJITCodeWithArityCheckFor(CodeSpecializationKind kind)
-        {
-            if (kind == CodeForCall)
-                return generatedJITCodeForCallWithArityCheck();
-            ASSERT(kind == CodeForConstruct);
-            return generatedJITCodeForConstructWithArityCheck();
-        }
-        
-        bool hasJITCodeForCall() const
-        {
-            return m_numParametersForCall >= 0;
-        }
+    PassRefPtr<JITCode> generatedJITCodeForConstruct()
+    {
+        ASSERT(m_jitCodeForConstruct);
+        return m_jitCodeForConstruct;
+    }
         
-        bool hasJITCodeForConstruct() const
-        {
-            return m_numParametersForConstruct >= 0;
+    PassRefPtr<JITCode> generatedJITCodeFor(CodeSpecializationKind kind)
+    {
+        if (kind == CodeForCall)
+            return generatedJITCodeForCall();
+        ASSERT(kind == CodeForConstruct);
+        return generatedJITCodeForConstruct();
+    }
+    
+    MacroAssemblerCodePtr entrypointFor(
+        VM& vm, CodeSpecializationKind kind, ArityCheckMode arity, RegisterPreservationMode registers)
+    {
+        // Check if we have a cached result. We only have it for arity check because we use the
+        // no-arity entrypoint in non-virtual calls, which will "cache" this value directly in
+        // machine code.
+        if (arity == MustCheckArity) {
+            switch (kind) {
+            case CodeForCall:
+                switch (registers) {
+                case RegisterPreservationNotRequired:
+                    if (MacroAssemblerCodePtr result = m_jitCodeForCallWithArityCheck)
+                        return result;
+                    break;
+                case MustPreserveRegisters:
+                    if (MacroAssemblerCodePtr result = m_jitCodeForCallWithArityCheckAndPreserveRegs)
+                        return result;
+                    break;
+                }
+                break;
+            case CodeForConstruct:
+                switch (registers) {
+                case RegisterPreservationNotRequired:
+                    if (MacroAssemblerCodePtr result = m_jitCodeForConstructWithArityCheck)
+                        return result;
+                    break;
+                case MustPreserveRegisters:
+                    if (MacroAssemblerCodePtr result = m_jitCodeForConstructWithArityCheckAndPreserveRegs)
+                        return result;
+                    break;
+                }
+                break;
+            }
         }
-        
-        bool hasJITCodeFor(CodeSpecializationKind kind) const
-        {
-            if (kind == CodeForCall)
-                return hasJITCodeForCall();
-            ASSERT(kind == CodeForConstruct);
-            return hasJITCodeForConstruct();
+        MacroAssemblerCodePtr result =
+            generatedJITCodeFor(kind)->addressForCall(vm, this, arity, registers);
+        if (arity == MustCheckArity) {
+            // Cache the result; this is necessary for the JIT's virtual call optimizations.
+            switch (kind) {
+            case CodeForCall:
+                switch (registers) {
+                case RegisterPreservationNotRequired:
+                    m_jitCodeForCallWithArityCheck = result;
+                    break;
+                case MustPreserveRegisters:
+                    m_jitCodeForCallWithArityCheckAndPreserveRegs = result;
+                    break;
+                }
+                break;
+            case CodeForConstruct:
+                switch (registers) {
+                case RegisterPreservationNotRequired:
+                    m_jitCodeForConstructWithArityCheck = result;
+                    break;
+                case MustPreserveRegisters:
+                    m_jitCodeForConstructWithArityCheckAndPreserveRegs = result;
+                    break;
+                }
+                break;
+            }
         }
+        return result;
+    }
 
-        static ptrdiff_t offsetOfJITCodeWithArityCheckFor(CodeSpecializationKind kind)
-        {
-            if (kind == CodeForCall)
+    static ptrdiff_t offsetOfJITCodeWithArityCheckFor(
+        CodeSpecializationKind kind, RegisterPreservationMode registers)
+    {
+        switch (kind) {
+        case CodeForCall:
+            switch (registers) {
+            case RegisterPreservationNotRequired:
                 return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
-            ASSERT(kind == CodeForConstruct);
-            return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
-        }
-        
-        static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind)
-        {
-            if (kind == CodeForCall)
-                return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall);
-            ASSERT(kind == CodeForConstruct);
-            return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct);
-        }
-#endif // ENABLE(JIT)
-
-        // Intrinsics are only for calls, currently.
-        Intrinsic intrinsic() const;
-        
-        Intrinsic intrinsicFor(CodeSpecializationKind kind) const
-        {
-            if (isCall(kind))
-                return intrinsic();
-            return NoIntrinsic;
-        }
-        
-#if ENABLE(JIT) || ENABLE(LLINT_C_LOOP)
-        MacroAssemblerCodePtr hostCodeEntryFor(CodeSpecializationKind kind)
-        {
-#if ENABLE(JIT)
-            return generatedJITCodeFor(kind)->addressForCall();
-#else
-            return LLInt::CLoop::hostCodeEntryFor(kind);
-#endif
-        }
-
-        MacroAssemblerCodePtr jsCodeEntryFor(CodeSpecializationKind kind)
-        {
-#if ENABLE(JIT)
-            return generatedJITCodeFor(kind)->addressForCall();
-#else
-            return LLInt::CLoop::jsCodeEntryFor(kind);
-#endif
-        }
-
-        MacroAssemblerCodePtr jsCodeWithArityCheckEntryFor(CodeSpecializationKind kind)
-        {
-#if ENABLE(JIT)
-            return generatedJITCodeWithArityCheckFor(kind);
-#else
-            return LLInt::CLoop::jsCodeEntryWithArityCheckFor(kind);
-#endif
-        }
-
-        static void* catchRoutineFor(HandlerInfo* handler, Instruction* catchPCForInterpreter)
-        {
-            #if ENABLE(JIT)
-            UNUSED_PARAM(catchPCForInterpreter);
-            return handler->nativeCode.executableAddress();
-            #else
-            UNUSED_PARAM(handler);
-            return LLInt::CLoop::catchRoutineFor(catchPCForInterpreter);
-            #endif
-        }
-#endif // ENABLE(JIT || ENABLE(LLINT_C_LOOP)
-
-    protected:
-        ExecutableBase* m_prev;
-        ExecutableBase* m_next;
-
-#if ENABLE(JIT)
-        RefPtr<JITCode> m_jitCodeForCall;
-        RefPtr<JITCode> m_jitCodeForConstruct;
-        MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
-        MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
-#endif
-    };
-
-    class NativeExecutable : public ExecutableBase {
-        friend class JIT;
-        friend class LLIntOffsetsExtractor;
-    public:
-        typedef ExecutableBase Base;
-
-#if ENABLE(JIT)
-        static NativeExecutable* create(VM& vm, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor, Intrinsic intrinsic)
-        {
-            NativeExecutable* executable;
-            if (!callThunk) {
-                executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
-                executable->finishCreation(vm, 0, 0, intrinsic);
-            } else {
-                executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
-                executable->finishCreation(vm, JITCode::hostFunction(callThunk), JITCode::hostFunction(constructThunk), intrinsic);
+            case MustPreserveRegisters:
+                return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheckAndPreserveRegs);
+            }
+        case CodeForConstruct:
+            switch (registers) {
+            case RegisterPreservationNotRequired:
+                return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
+            case MustPreserveRegisters:
+                return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheckAndPreserveRegs);
             }
-            return executable;
-        }
-#endif
-
-#if ENABLE(LLINT_C_LOOP)
-        static NativeExecutable* create(VM& vm, NativeFunction function, NativeFunction constructor)
-        {
-            ASSERT(!vm.canUseJIT());
-            NativeExecutable* executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
-            executable->finishCreation(vm);
-            return executable;
-        }
-#endif
-
-#if ENABLE(JIT)
-        static void destroy(JSCell*);
-#endif
-
-        CodeBlockHash hashFor(CodeSpecializationKind) const;
-
-        NativeFunction function() { return m_function; }
-        NativeFunction constructor() { return m_constructor; }
-        
-        NativeFunction nativeFunctionFor(CodeSpecializationKind kind)
-        {
-            if (kind == CodeForCall)
-                return function();
-            ASSERT(kind == CodeForConstruct);
-            return constructor();
-        }
-        
-        static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind)
-        {
-            if (kind == CodeForCall)
-                return OBJECT_OFFSETOF(NativeExecutable, m_function);
-            ASSERT(kind == CodeForConstruct);
-            return OBJECT_OFFSETOF(NativeExecutable, m_constructor);
         }
+        RELEASE_ASSERT_NOT_REACHED();
+        return 0;
+    }
+    
+    static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind)
+    {
+        if (kind == CodeForCall)
+            return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall);
+        ASSERT(kind == CodeForConstruct);
+        return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct);
+    }
 
-        static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(LeafType, StructureFlags), &s_info); }
+    bool hasJITCodeForCall() const
+    {
+        return m_numParametersForCall >= 0;
+    }
         
-        static const ClassInfo s_info;
-
-        Intrinsic intrinsic() const;
-
-    protected:
-#if ENABLE(JIT)
-        void finishCreation(VM& vm, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, Intrinsic intrinsic)
-        {
-            Base::finishCreation(vm);
-            m_jitCodeForCallWithArityCheck = callThunk ? callThunk->addressForCall() : MacroAssemblerCodePtr();
-            m_jitCodeForConstructWithArityCheck = constructThunk ? constructThunk->addressForCall() : MacroAssemblerCodePtr();
-            m_jitCodeForCall = callThunk;
-            m_jitCodeForConstruct = constructThunk;
-            m_intrinsic = intrinsic;
-        }
-#endif
-
-    private:
-        NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor)
-            : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
-            , m_function(function)
-            , m_constructor(constructor)
-        {
-        }
-
-        NativeFunction m_function;
-        NativeFunction m_constructor;
+    bool hasJITCodeForConstruct() const
+    {
+        return m_numParametersForConstruct >= 0;
+    }
         
-        Intrinsic m_intrinsic;
-    };
-
-    class ScriptExecutable : public ExecutableBase {
-    public:
-        typedef ExecutableBase Base;
-
-        ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext)
-            : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED)
-            , m_source(source)
-            , m_features(isInStrictContext ? StrictModeFeature : 0)
-        {
-        }
-
-        ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
-            : ExecutableBase(exec->vm(), structure, NUM_PARAMETERS_NOT_COMPILED)
-            , m_source(source)
-            , m_features(isInStrictContext ? StrictModeFeature : 0)
-        {
-        }
+    bool hasJITCodeFor(CodeSpecializationKind kind) const
+    {
+        if (kind == CodeForCall)
+            return hasJITCodeForCall();
+        ASSERT(kind == CodeForConstruct);
+        return hasJITCodeForConstruct();
+    }
 
-#if ENABLE(JIT)
-        static void destroy(JSCell*);
-#endif
+    // Intrinsics are only for calls, currently.
+    Intrinsic intrinsic() const;
         
-        CodeBlockHash hashFor(CodeSpecializationKind) const;
+    Intrinsic intrinsicFor(CodeSpecializationKind kind) const
+    {
+        if (isCall(kind))
+            return intrinsic();
+        return NoIntrinsic;
+    }
+    
+    void dump(PrintStream&) const;
+        
+protected:
+    RefPtr<JITCode> m_jitCodeForCall;
+    RefPtr<JITCode> m_jitCodeForConstruct;
+    MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
+    MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
+    MacroAssemblerCodePtr m_jitCodeForCallWithArityCheckAndPreserveRegs;
+    MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheckAndPreserveRegs;
+};
+
+class NativeExecutable final : public ExecutableBase {
+    friend class JIT;
+    friend class LLIntOffsetsExtractor;
+public:
+    typedef ExecutableBase Base;
+    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
+
+    static NativeExecutable* create(VM& vm, PassRefPtr<JITCode> callThunk, NativeFunction function, PassRefPtr<JITCode> constructThunk, NativeFunction constructor, Intrinsic intrinsic)
+    {
+        NativeExecutable* executable;
+        executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
+        executable->finishCreation(vm, callThunk, constructThunk, intrinsic);
+        return executable;
+    }
 
-        const SourceCode& source() const { return m_source; }
-        intptr_t sourceID() const { return m_source.providerID(); }
-        const String& sourceURL() const { return m_source.provider()->url(); }
-        int lineNo() const { return m_firstLine; }
-        int lastLine() const { return m_lastLine; }
-        unsigned startColumn() const { return m_startColumn; }
+    static void destroy(JSCell*);
 
-        bool usesEval() const { return m_features & EvalFeature; }
-        bool usesArguments() const { return m_features & ArgumentsFeature; }
-        bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
-        bool isStrictMode() const { return m_features & StrictModeFeature; }
+    CodeBlockHash hashFor(CodeSpecializationKind) const;
 
-        void unlinkCalls();
+    NativeFunction function() { return m_function; }
+    NativeFunction constructor() { return m_constructor; }
         
-        CodeFeatures features() const { return m_features; }
+    NativeFunction nativeFunctionFor(CodeSpecializationKind kind)
+    {
+        if (kind == CodeForCall)
+            return function();
+        ASSERT(kind == CodeForConstruct);
+        return constructor();
+    }
         
-        static const ClassInfo s_info;
-
-        void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn)
-        {
-            m_features = features;
-            m_hasCapturedVariables = hasCapturedVariables;
-            m_firstLine = firstLine;
-            m_lastLine = lastLine;
-            m_startColumn = startColumn;
-        }
-
-    protected:
-        void finishCreation(VM& vm)
-        {
-            Base::finishCreation(vm);
-            vm.heap.addCompiledCode(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
-
-#if ENABLE(CODEBLOCK_SAMPLING)
-            if (SamplingTool* sampler = vm.interpreter->sampler())
-                sampler->notifyOfScope(vm, this);
-#endif
-        }
+    static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind)
+    {
+        if (kind == CodeForCall)
+            return OBJECT_OFFSETOF(NativeExecutable, m_function);
+        ASSERT(kind == CodeForConstruct);
+        return OBJECT_OFFSETOF(NativeExecutable, m_constructor);
+    }
 
-        SourceCode m_source;
-        CodeFeatures m_features;
-        bool m_hasCapturedVariables;
-        int m_firstLine;
-        int m_lastLine;
-        unsigned m_startColumn;
-    };
-
-    class EvalExecutable : public ScriptExecutable {
-        friend class LLIntOffsetsExtractor;
-    public:
-        typedef ScriptExecutable Base;
-
-        static void destroy(JSCell*);
-
-        JSObject* compile(ExecState* exec, JSScope* scope)
-        {
-            RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
-            JSObject* error = 0;
-            if (!m_evalCodeBlock)
-                error = compileInternal(exec, scope, JITCode::bottomTierJIT());
-            ASSERT(!error == !!m_evalCodeBlock);
-            return error;
-        }
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); }
         
-        JSObject* compileOptimized(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
-        CompilationResult replaceWithDeferredOptimizedCode(PassRefPtr<DFG::Plan>);
-        
-#if ENABLE(JIT)
-        void jettisonOptimizedCode(VM&);
-        CompilationResult jitCompile(ExecState*);
-#endif
+    DECLARE_INFO;
 
-        EvalCodeBlock& generatedBytecode()
-        {
-            ASSERT(m_evalCodeBlock);
-            return *m_evalCodeBlock;
-        }
+    Intrinsic intrinsic() const;
 
-        static EvalExecutable* create(ExecState* exec, PassRefPtr<CodeCache> cache, const SourceCode& source, bool isInStrictContext)
-        {
-            EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, cache, source, isInStrictContext);
-            executable->finishCreation(exec->vm());
-            return executable;
-        }
+protected:
+    void finishCreation(VM& vm, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, Intrinsic intrinsic)
+    {
+        Base::finishCreation(vm);
+        m_jitCodeForCall = callThunk;
+        m_jitCodeForConstruct = constructThunk;
+        m_intrinsic = intrinsic;
+    }
 
-#if ENABLE(JIT)
-        PassRefPtr<JITCode> generatedJITCode()
-        {
-            return generatedJITCodeForCall();
-        }
-#endif
-        static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
-        {
-            return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), &s_info);
-        }
-        
-        static const ClassInfo s_info;
+private:
+    NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor)
+        : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
+        , m_function(function)
+        , m_constructor(constructor)
+    {
+    }
 
-        void unlinkCalls();
+    NativeFunction m_function;
+    NativeFunction m_constructor;
+        
+    Intrinsic m_intrinsic;
+};
+
+class ScriptExecutable : public ExecutableBase {
+public:
+    typedef ExecutableBase Base;
+    static const unsigned StructureFlags = Base::StructureFlags;
+
+    static void destroy(JSCell*);
+        
+    CodeBlockHash hashFor(CodeSpecializationKind) const;
+
+    const SourceCode& source() const { return m_source; }
+    intptr_t sourceID() const { return m_source.providerID(); }
+    const String& sourceURL() const { return m_source.provider()->url(); }
+    int firstLine() const { return m_firstLine; }
+    void setOverrideLineNumber(int overrideLineNumber) { m_overrideLineNumber = overrideLineNumber; }
+    bool hasOverrideLineNumber() const { return m_overrideLineNumber != -1; }
+    int overrideLineNumber() const { return m_overrideLineNumber; }
+    int lastLine() const { return m_lastLine; }
+    unsigned startColumn() const { return m_startColumn; }
+    unsigned endColumn() const { return m_endColumn; }
+    unsigned typeProfilingStartOffset() const { return m_typeProfilingStartOffset; }
+    unsigned typeProfilingEndOffset() const { return m_typeProfilingEndOffset; }
+
+    bool usesEval() const { return m_features & EvalFeature; }
+    bool usesArguments() const { return m_features & ArgumentsFeature; }
+    bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
+    bool isStrictMode() const { return m_features & StrictModeFeature; }
+    ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; }
+        
+    void setNeverInline(bool value) { m_neverInline = value; }
+    void setDidTryToEnterInLoop(bool value) { m_didTryToEnterInLoop = value; }
+    bool neverInline() const { return m_neverInline; }
+    bool didTryToEnterInLoop() const { return m_didTryToEnterInLoop; }
+    bool isInliningCandidate() const { return !neverInline(); }
+    
+    bool* addressOfDidTryToEnterInLoop() { return &m_didTryToEnterInLoop; }
 
-        void clearCode();
+    CodeFeatures features() const { return m_features; }
+        
+    DECLARE_INFO;
 
-        ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
+    void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn, unsigned endColumn)
+    {
+        m_features = features;
+        m_hasCapturedVariables = hasCapturedVariables;
+        m_firstLine = firstLine;
+        m_lastLine = lastLine;
+        ASSERT(startColumn != UINT_MAX);
+        m_startColumn = startColumn;
+        ASSERT(endColumn != UINT_MAX);
+        m_endColumn = endColumn;
+    }
 
-    private:
-        static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
-        EvalExecutable(ExecState*, PassRefPtr<CodeCache>, const SourceCode&, bool);
+    void installCode(CodeBlock*);
+    RefPtr<CodeBlock> newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception);
+    PassRefPtr<CodeBlock> newReplacementCodeBlockFor(CodeSpecializationKind);
+    
+    JSObject* prepareForExecution(ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind)
+    {
+        if (hasJITCodeFor(kind))
+            return 0;
+        return prepareForExecutionImpl(exec, function, scope, kind);
+    }
 
-        JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, CompilationResult* = 0, unsigned bytecodeIndex = UINT_MAX);
-        static void visitChildren(JSCell*, SlotVisitor&);
+    template <typename Functor> void forEachCodeBlock(Functor&&);
 
-        RefPtr<EvalCodeBlock> m_evalCodeBlock;
-        WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
-        RefPtr<CodeCache> m_codeCache;
-    };
+private:
+    JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind);
 
-    class ProgramExecutable : public ScriptExecutable {
-        friend class LLIntOffsetsExtractor;
-    public:
-        typedef ScriptExecutable Base;
+protected:
+    ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext);
 
-        static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
-        {
-            ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
-            executable->finishCreation(exec->vm());
-            return executable;
-        }
+    void finishCreation(VM& vm)
+    {
+        Base::finishCreation(vm);
+        vm.heap.addExecutable(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
 
+#if ENABLE(CODEBLOCK_SAMPLING)
+        if (SamplingTool* sampler = vm.interpreter->sampler())
+            sampler->notifyOfScope(vm, this);
+#endif
+    }
 
-        JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
+    SourceCode m_source;
+    CodeFeatures m_features;
+    bool m_hasCapturedVariables;
+    bool m_neverInline;
+    bool m_didTryToEnterInLoop;
+    int m_overrideLineNumber;
+    int m_firstLine;
+    int m_lastLine;
+    unsigned m_startColumn;
+    unsigned m_endColumn;
+    unsigned m_typeProfilingStartOffset;
+    unsigned m_typeProfilingEndOffset;
+};
+
+class EvalExecutable final : public ScriptExecutable {
+    friend class LLIntOffsetsExtractor;
+public:
+    typedef ScriptExecutable Base;
+    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
+
+    static void destroy(JSCell*);
+
+    EvalCodeBlock* codeBlock()
+    {
+        return m_evalCodeBlock.get();
+    }
 
-        static void destroy(JSCell*);
+    static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, ThisTDZMode, const VariableEnvironment*);
 
-        JSObject* compile(ExecState* exec, JSScope* scope)
-        {
-            RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
-            JSObject* error = 0;
-            if (!m_programCodeBlock)
-                error = compileInternal(exec, scope, JITCode::bottomTierJIT());
-            ASSERT(!error == !!m_programCodeBlock);
-            return error;
-        }
+    PassRefPtr<JITCode> generatedJITCode()
+    {
+        return generatedJITCodeForCall();
+    }
 
-        JSObject* compileOptimized(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
-        CompilationResult replaceWithDeferredOptimizedCode(PassRefPtr<DFG::Plan>);
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
+    {
+        return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), info());
+    }
         
-#if ENABLE(JIT)
-        void jettisonOptimizedCode(VM&);
-        CompilationResult jitCompile(ExecState*);
-#endif
+    DECLARE_INFO;
 
-        ProgramCodeBlock& generatedBytecode()
-        {
-            ASSERT(m_programCodeBlock);
-            return *m_programCodeBlock;
-        }
+    void clearCode();
 
-        JSObject* checkSyntax(ExecState*);
+    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, false); }
 
-#if ENABLE(JIT)
-        PassRefPtr<JITCode> generatedJITCode()
-        {
-            return generatedJITCodeForCall();
-        }
-#endif
-        
-        static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
-        {
-            return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), &s_info);
-        }
-        
-        static const ClassInfo s_info;
-        
-        void unlinkCalls();
+    unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
+    unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
 
-        void clearCode();
+private:
+    friend class ScriptExecutable;
+    EvalExecutable(ExecState*, const SourceCode&, bool);
 
-        ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
+    static void visitChildren(JSCell*, SlotVisitor&);
 
-    private:
-        static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
+    RefPtr<EvalCodeBlock> m_evalCodeBlock;
+    WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
+};
 
-        ProgramExecutable(ExecState*, const SourceCode&);
+class ProgramExecutable final : public ScriptExecutable {
+    friend class LLIntOffsetsExtractor;
+public:
+    typedef ScriptExecutable Base;
+    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
 
-        enum ConstantMode { IsConstant, IsVariable };
-        enum FunctionMode { IsFunctionToSpecialize, NotFunctionOrNotSpecializable };
-        int addGlobalVar(JSGlobalObject*, const Identifier&, ConstantMode, FunctionMode);
+    static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
+    {
+        ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
+        executable->finishCreation(exec->vm());
+        return executable;
+    }
 
-        JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, CompilationResult* = 0, unsigned bytecodeIndex = UINT_MAX);
-        static void visitChildren(JSCell*, SlotVisitor&);
 
-        WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
-        RefPtr<ProgramCodeBlock> m_programCodeBlock;
-    };
+    JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
 
-    class FunctionExecutable : public ScriptExecutable {
-        friend class JIT;
-        friend class LLIntOffsetsExtractor;
-    public:
-        typedef ScriptExecutable Base;
+    static void destroy(JSCell*);
 
-        static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn)
-        {
-            FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn);
-            executable->finishCreation(vm);
-            return executable;
-        }
-        static FunctionExecutable* fromGlobalCode(const Identifier& name, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
+    ProgramCodeBlock* codeBlock()
+    {
+        return m_programCodeBlock.get();
+    }
 
-        static void destroy(JSCell*);
-        
-        UnlinkedFunctionExecutable* unlinkedExecutable()
-        {
-            return m_unlinkedExecutable.get();
-        }
+    JSObject* checkSyntax(ExecState*);
 
-        // Returns either call or construct bytecode. This can be appropriate
-        // for answering questions that that don't vary between call and construct --
-        // for example, argumentsRegister().
-        FunctionCodeBlock& generatedBytecode()
-        {
-            if (m_codeBlockForCall)
-                return *m_codeBlockForCall;
-            ASSERT(m_codeBlockForConstruct);
-            return *m_codeBlockForConstruct;
-        }
+    PassRefPtr<JITCode> generatedJITCode()
+    {
+        return generatedJITCodeForCall();
+    }
         
-        PassRefPtr<FunctionCodeBlock> produceCodeBlockFor(JSScope*, CodeSpecializationKind, JSObject*& exception);
-
-        JSObject* compileForCall(ExecState* exec, JSScope* scope)
-        {
-            RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
-            JSObject* error = 0;
-            if (!m_codeBlockForCall)
-                error = compileForCallInternal(exec, scope, JITCode::bottomTierJIT());
-            ASSERT(!error == !!m_codeBlockForCall);
-            return error;
-        }
-
-        JSObject* compileOptimizedForCall(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
-        CompilationResult replaceWithDeferredOptimizedCodeForCall(PassRefPtr<DFG::Plan>);
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
+    {
+        return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), info());
+    }
         
-#if ENABLE(JIT)
-        void jettisonOptimizedCodeForCall(VM&);
-        CompilationResult jitCompileForCall(ExecState*);
-#endif
+    DECLARE_INFO;
 
-        bool isGeneratedForCall() const
-        {
-            return m_codeBlockForCall;
-        }
+    void clearCode();
 
-        FunctionCodeBlock& generatedBytecodeForCall()
-        {
-            ASSERT(m_codeBlockForCall);
-            return *m_codeBlockForCall;
-        }
+    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, false); }
 
-        JSObject* compileForConstruct(ExecState* exec, JSScope* scope)
-        {
-            RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
-            JSObject* error = 0;
-            if (!m_codeBlockForConstruct)
-                error = compileForConstructInternal(exec, scope, JITCode::bottomTierJIT());
-            ASSERT(!error == !!m_codeBlockForConstruct);
-            return error;
-        }
+private:
+    friend class ScriptExecutable;
 
-        JSObject* compileOptimizedForConstruct(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
-        CompilationResult replaceWithDeferredOptimizedCodeForConstruct(PassRefPtr<DFG::Plan>);
-        
-#if ENABLE(JIT)
-        void jettisonOptimizedCodeForConstruct(VM&);
-        CompilationResult jitCompileForConstruct(ExecState*);
-#endif
+    ProgramExecutable(ExecState*, const SourceCode&);
 
-        bool isGeneratedForConstruct() const
-        {
-            return m_codeBlockForConstruct;
-        }
+    static void visitChildren(JSCell*, SlotVisitor&);
 
-        FunctionCodeBlock& generatedBytecodeForConstruct()
-        {
-            ASSERT(m_codeBlockForConstruct);
-            return *m_codeBlockForConstruct;
-        }
-        
-        JSObject* compileFor(ExecState* exec, JSScope* scope, CodeSpecializationKind kind)
-        {
-            ASSERT(exec->callee());
-            ASSERT(exec->callee()->inherits(&JSFunction::s_info));
-            ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this);
-
-            if (kind == CodeForCall)
-                return compileForCall(exec, scope);
-            ASSERT(kind == CodeForConstruct);
-            return compileForConstruct(exec, scope);
-        }
-        
-        JSObject* compileOptimizedFor(ExecState* exec, JSScope* scope, CompilationResult& result, unsigned bytecodeIndex, CodeSpecializationKind kind)
-        {
-            ASSERT(exec->callee());
-            ASSERT(exec->callee()->inherits(&JSFunction::s_info));
-            ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this);
-            
-            if (kind == CodeForCall)
-                return compileOptimizedForCall(exec, scope, result, bytecodeIndex);
-            ASSERT(kind == CodeForConstruct);
-            return compileOptimizedForConstruct(exec, scope, result, bytecodeIndex);
-        }
-        
-        CompilationResult replaceWithDeferredOptimizedCodeFor(PassRefPtr<DFG::Plan> plan, CodeSpecializationKind kind)
-        {
-            if (kind == CodeForCall)
-                return replaceWithDeferredOptimizedCodeForCall(plan);
-            return replaceWithDeferredOptimizedCodeForConstruct(plan);
-        }
+    WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
+    RefPtr<ProgramCodeBlock> m_programCodeBlock;
+};
 
-#if ENABLE(JIT)
-        void jettisonOptimizedCodeFor(VM& vm, CodeSpecializationKind kind)
-        {
-            if (kind == CodeForCall) 
-                jettisonOptimizedCodeForCall(vm);
-            else {
-                ASSERT(kind == CodeForConstruct);
-                jettisonOptimizedCodeForConstruct(vm);
-            }
-        }
-        
-        CompilationResult jitCompileFor(ExecState* exec, CodeSpecializationKind kind)
-        {
-            if (kind == CodeForCall)
-                return jitCompileForCall(exec);
-            ASSERT(kind == CodeForConstruct);
-            return jitCompileForConstruct(exec);
-        }
-#endif
-        
-        bool isGeneratedFor(CodeSpecializationKind kind)
-        {
-            if (kind == CodeForCall)
-                return isGeneratedForCall();
-            ASSERT(kind == CodeForConstruct);
-            return isGeneratedForConstruct();
-        }
-        
-        FunctionCodeBlock& generatedBytecodeFor(CodeSpecializationKind kind)
-        {
-            if (kind == CodeForCall)
-                return generatedBytecodeForCall();
-            ASSERT(kind == CodeForConstruct);
-            return generatedBytecodeForConstruct();
-        }
-
-        FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
-        
-        FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
-        {
-            return baselineCodeBlockFor(kind);
-        }
-        
-        const Identifier& name() { return m_unlinkedExecutable->name(); }
-        const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
-        JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
-        size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
-        String paramString() const;
-        SharedSymbolTable* symbolTable(CodeSpecializationKind kind) const { return m_unlinkedExecutable->symbolTable(kind); }
-
-        void clearCodeIfNotCompiling();
-        void clearUnlinkedCodeForRecompilationIfNotCompiling();
-        static void visitChildren(JSCell*, SlotVisitor&);
-        static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
-        {
-            return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), &s_info);
-        }
-        
-        static const ClassInfo s_info;
-        
-        void unlinkCalls();
+class FunctionExecutable final : public ScriptExecutable {
+    friend class JIT;
+    friend class LLIntOffsetsExtractor;
+public:
+    typedef ScriptExecutable Base;
+    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
 
-        void clearCode();
-
-    private:
-        FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn);
+    static FunctionExecutable* create(
+        VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, 
+        unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn)
+    {
+        FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn, endColumn);
+        executable->finishCreation(vm);
+        return executable;
+    }
+    static FunctionExecutable* fromGlobalCode(
+        const Identifier& name, ExecState&, const SourceCode&, 
+        JSObject*& exception, int overrideLineNumber);
 
-        JSObject* compileForCallInternal(ExecState*, JSScope*, JITCode::JITType, CompilationResult* = 0, unsigned bytecodeIndex = UINT_MAX);
-        JSObject* compileForConstructInternal(ExecState*, JSScope*, JITCode::JITType, CompilationResult* = 0, unsigned bytecodeIndex = UINT_MAX);
+    static void destroy(JSCell*);
         
-        RefPtr<FunctionCodeBlock>& codeBlockFor(CodeSpecializationKind kind)
-        {
-            if (kind == CodeForCall)
-                return m_codeBlockForCall;
-            ASSERT(kind == CodeForConstruct);
-            return m_codeBlockForConstruct;
-        }
-        bool isCompiling()
-        {
-#if ENABLE(JIT)
-            if (!m_jitCodeForCall && m_codeBlockForCall)
-                return true;
-            if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
-                return true;
-#endif
-            return false;
-        }
-
-        static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
-        WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
-        RefPtr<FunctionCodeBlock> m_codeBlockForCall;
-        RefPtr<FunctionCodeBlock> m_codeBlockForConstruct;
-    };
-
-    inline JSFunction::JSFunction(VM& vm, FunctionExecutable* executable, JSScope* scope)
-        : Base(vm, scope->globalObject()->functionStructure())
-        , m_executable(vm, this, executable)
-        , m_scope(vm, this, scope)
-        , m_allocationProfileWatchpoint(InitializedBlind) // See comment in JSFunction.cpp concerning the reason for using InitializedBlind as opposed to InitializedWatching.
+    UnlinkedFunctionExecutable* unlinkedExecutable()
     {
+        return m_unlinkedExecutable.get();
     }
 
-    inline FunctionExecutable* JSFunction::jsExecutable() const
+    // Returns either call or construct bytecode. This can be appropriate
+    // for answering questions that that don't vary between call and construct --
+    // for example, argumentsRegister().
+    FunctionCodeBlock* eitherCodeBlock()
+    {
+        if (m_codeBlockForCall)
+            return m_codeBlockForCall.get();
+        return m_codeBlockForConstruct.get();
+    }
+        
+    bool isGeneratedForCall() const
     {
-        ASSERT(!isHostFunctionNonInline());
-        return static_cast<FunctionExecutable*>(m_executable.get());
+        return m_codeBlockForCall;
     }
 
-    inline bool JSFunction::isHostFunction() const
+    FunctionCodeBlock* codeBlockForCall()
     {
-        ASSERT(m_executable);
-        return m_executable->isHostFunction();
+        return m_codeBlockForCall.get();
     }
 
-    inline NativeFunction JSFunction::nativeFunction()
+    bool isGeneratedForConstruct() const
     {
-        ASSERT(isHostFunction());
-        return static_cast<NativeExecutable*>(m_executable.get())->function();
+        return m_codeBlockForConstruct;
     }
 
-    inline NativeFunction JSFunction::nativeConstructor()
+    FunctionCodeBlock* codeBlockForConstruct()
+    {
+        return m_codeBlockForConstruct.get();
+    }
+        
+    bool isGeneratedFor(CodeSpecializationKind kind)
+    {
+        if (kind == CodeForCall)
+            return isGeneratedForCall();
+        ASSERT(kind == CodeForConstruct);
+        return isGeneratedForConstruct();
+    }
+        
+    FunctionCodeBlock* codeBlockFor(CodeSpecializationKind kind)
     {
-        ASSERT(isHostFunction());
-        return static_cast<NativeExecutable*>(m_executable.get())->constructor();
+        if (kind == CodeForCall)
+            return codeBlockForCall();
+        ASSERT(kind == CodeForConstruct);
+        return codeBlockForConstruct();
     }
 
-    inline bool isHostFunction(JSValue value, NativeFunction nativeFunction)
+    FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
+        
+    FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
     {
-        JSFunction* function = jsCast<JSFunction*>(getJSFunction(value));
-        if (!function || !function->isHostFunction())
-            return false;
-        return function->nativeFunction() == nativeFunction;
+        return baselineCodeBlockFor(kind);
     }
 
-    inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
+    RefPtr<TypeSet> returnStatementTypeSet() 
     {
-        switch (executable->structure()->typeInfo().type()) {
-        case EvalExecutableType:
-            return jsCast<EvalExecutable*>(executable)->clearCode();
-        case ProgramExecutableType:
-            return jsCast<ProgramExecutable*>(executable)->clearCode();
-        case FunctionExecutableType:
-            return jsCast<FunctionExecutable*>(executable)->clearCode();
-        default:
-            return jsCast<NativeExecutable*>(executable)->clearCode();
-        }
+        if (!m_returnStatementTypeSet)
+            m_returnStatementTypeSet = TypeSet::create();
+
+        return m_returnStatementTypeSet;
+    }
+        
+    FunctionMode functionMode() { return m_unlinkedExecutable->functionMode(); }
+    bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); }
+    ConstructAbility constructAbility() const { return m_unlinkedExecutable->constructAbility(); }
+    bool isArrowFunction() const { return m_unlinkedExecutable->isArrowFunction(); }
+    bool isClassConstructorFunction() const { return m_unlinkedExecutable->isClassConstructorFunction(); }
+    const Identifier& name() { return m_unlinkedExecutable->name(); }
+    const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
+    JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
+    size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
+
+    static void visitChildren(JSCell*, SlotVisitor&);
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
+    {
+        return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), info());
     }
 
-    inline void ScriptExecutable::unlinkCalls()
+    unsigned parametersStartOffset() const { return m_parametersStartOffset; }
+
+    void overrideParameterAndTypeProfilingStartEndOffsets(unsigned parametersStartOffset, unsigned typeProfilingStartOffset, unsigned typeProfilingEndOffset)
     {
-        switch (structure()->typeInfo().type()) {
-        case EvalExecutableType:
-            return jsCast<EvalExecutable*>(this)->unlinkCalls();
-        case ProgramExecutableType:
-            return jsCast<ProgramExecutable*>(this)->unlinkCalls();
-        case FunctionExecutableType:
-            return jsCast<FunctionExecutable*>(this)->unlinkCalls();
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-        }
+        m_parametersStartOffset = parametersStartOffset;
+        m_typeProfilingStartOffset = typeProfilingStartOffset;
+        m_typeProfilingEndOffset = typeProfilingEndOffset;
     }
 
+    DECLARE_INFO;
+
+    void clearCode();
+    
+    InferredValue* singletonFunction() { return m_singletonFunction.get(); }
+
+private:
+    FunctionExecutable(
+        VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, 
+        unsigned lastLine, unsigned startColumn, unsigned endColumn);
+    
+    void finishCreation(VM&);
+
+    friend class ScriptExecutable;
+    
+    WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
+    RefPtr<FunctionCodeBlock> m_codeBlockForCall;
+    RefPtr<FunctionCodeBlock> m_codeBlockForConstruct;
+    RefPtr<TypeSet> m_returnStatementTypeSet;
+    unsigned m_parametersStartOffset;
+    WriteBarrier<InferredValue> m_singletonFunction;
+};
+
+inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
+{
+    switch (executable->type()) {
+    case EvalExecutableType:
+        return jsCast<EvalExecutable*>(executable)->clearCode();
+    case ProgramExecutableType:
+        return jsCast<ProgramExecutable*>(executable)->clearCode();
+    case FunctionExecutableType:
+        return jsCast<FunctionExecutable*>(executable)->clearCode();
+    default:
+        return jsCast<NativeExecutable*>(executable)->clearCode();
+    }
+}
+
 }
 
 #endif