1/*
2 * Copyright (C) 2009, 2010, 2013 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef Executable_h
27#define Executable_h
28
29#include "ArityCheckMode.h"
30#include "CallData.h"
31#include "CodeBlockHash.h"
32#include "CodeSpecializationKind.h"
33#include "CompilationResult.h"
34#include "DFGPlan.h"
35#include "HandlerInfo.h"
36#include "JSFunction.h"
37#include "Interpreter.h"
38#include "JITCode.h"
39#include "JSGlobalObject.h"
40#include "RegisterPreservationMode.h"
41#include "SamplingTool.h"
42#include "SourceCode.h"
43#include "UnlinkedCodeBlock.h"
44#include <wtf/PassOwnPtr.h>
45
46namespace JSC {
47
48class CodeBlock;
49class Debugger;
50class EvalCodeBlock;
51class FunctionCodeBlock;
52class LLIntOffsetsExtractor;
53class ProgramCodeBlock;
54class JSScope;
55
56enum CompilationKind { FirstCompilation, OptimizingCompilation };
57
58inline bool isCall(CodeSpecializationKind kind)
59{
60    if (kind == CodeForCall)
61        return true;
62    ASSERT(kind == CodeForConstruct);
63    return false;
64}
65
66class ExecutableBase : public JSCell, public DoublyLinkedListNode<ExecutableBase> {
67    friend class WTF::DoublyLinkedListNode<ExecutableBase>;
68    friend class JIT;
69
70protected:
71    static const int NUM_PARAMETERS_IS_HOST = 0;
72    static const int NUM_PARAMETERS_NOT_COMPILED = -1;
73
74    ExecutableBase(VM& vm, Structure* structure, int numParameters)
75        : JSCell(vm, structure)
76        , m_numParametersForCall(numParameters)
77        , m_numParametersForConstruct(numParameters)
78    {
79    }
80
81    void finishCreation(VM& vm)
82    {
83        Base::finishCreation(vm);
84    }
85
86public:
87    typedef JSCell Base;
88
89#if ENABLE(JIT)
90    static const bool needsDestruction = true;
91    static const bool hasImmortalStructure = true;
92    static void destroy(JSCell*);
93#endif
94
95    CodeBlockHash hashFor(CodeSpecializationKind) const;
96
97    bool isEvalExecutable()
98    {
99        return type() == EvalExecutableType;
100    }
101    bool isFunctionExecutable()
102    {
103        return type() == FunctionExecutableType;
104    }
105    bool isProgramExecutable()
106    {
107        return type() == ProgramExecutableType;
108    }
109
110    bool isHostFunction() const
111    {
112        ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
113        return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
114    }
115
116    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CompoundType, StructureFlags), info()); }
117
118    void clearCode();
119
120    DECLARE_EXPORT_INFO;
121
122protected:
123    static const unsigned StructureFlags = StructureIsImmortal;
124    int m_numParametersForCall;
125    int m_numParametersForConstruct;
126
127public:
128    static void clearCodeVirtual(ExecutableBase*);
129
130    PassRefPtr<JITCode> generatedJITCodeForCall()
131    {
132        ASSERT(m_jitCodeForCall);
133        return m_jitCodeForCall;
134    }
135
136    PassRefPtr<JITCode> generatedJITCodeForConstruct()
137    {
138        ASSERT(m_jitCodeForConstruct);
139        return m_jitCodeForConstruct;
140    }
141
142    PassRefPtr<JITCode> generatedJITCodeFor(CodeSpecializationKind kind)
143    {
144        if (kind == CodeForCall)
145            return generatedJITCodeForCall();
146        ASSERT(kind == CodeForConstruct);
147        return generatedJITCodeForConstruct();
148    }
149
150    MacroAssemblerCodePtr entrypointFor(
151        VM& vm, CodeSpecializationKind kind, ArityCheckMode arity, RegisterPreservationMode registers)
152    {
153        // Check if we have a cached result. We only have it for arity check because we use the
154        // no-arity entrypoint in non-virtual calls, which will "cache" this value directly in
155        // machine code.
156        if (arity == MustCheckArity) {
157            switch (kind) {
158            case CodeForCall:
159                switch (registers) {
160                case RegisterPreservationNotRequired:
161                    if (MacroAssemblerCodePtr result = m_jitCodeForCallWithArityCheck)
162                        return result;
163                    break;
164                case MustPreserveRegisters:
165                    if (MacroAssemblerCodePtr result = m_jitCodeForCallWithArityCheckAndPreserveRegs)
166                        return result;
167                    break;
168                }
169                break;
170            case CodeForConstruct:
171                switch (registers) {
172                case RegisterPreservationNotRequired:
173                    if (MacroAssemblerCodePtr result = m_jitCodeForConstructWithArityCheck)
174                        return result;
175                    break;
176                case MustPreserveRegisters:
177                    if (MacroAssemblerCodePtr result = m_jitCodeForConstructWithArityCheckAndPreserveRegs)
178                        return result;
179                    break;
180                }
181                break;
182            }
183        }
184        MacroAssemblerCodePtr result =
185            generatedJITCodeFor(kind)->addressForCall(vm, this, arity, registers);
186        if (arity == MustCheckArity) {
187            // Cache the result; this is necessary for the JIT's virtual call optimizations.
188            switch (kind) {
189            case CodeForCall:
190                switch (registers) {
191                case RegisterPreservationNotRequired:
192                    m_jitCodeForCallWithArityCheck = result;
193                    break;
194                case MustPreserveRegisters:
195                    m_jitCodeForCallWithArityCheckAndPreserveRegs = result;
196                    break;
197                }
198                break;
199            case CodeForConstruct:
200                switch (registers) {
201                case RegisterPreservationNotRequired:
202                    m_jitCodeForConstructWithArityCheck = result;
203                    break;
204                case MustPreserveRegisters:
205                    m_jitCodeForConstructWithArityCheckAndPreserveRegs = result;
206                    break;
207                }
208                break;
209            }
210        }
211        return result;
212    }
213
214    static ptrdiff_t offsetOfJITCodeWithArityCheckFor(
215        CodeSpecializationKind kind, RegisterPreservationMode registers)
216    {
217        switch (kind) {
218        case CodeForCall:
219            switch (registers) {
220            case RegisterPreservationNotRequired:
221                return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
222            case MustPreserveRegisters:
223                return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheckAndPreserveRegs);
224            }
225        case CodeForConstruct:
226            switch (registers) {
227            case RegisterPreservationNotRequired:
228                return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
229            case MustPreserveRegisters:
230                return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheckAndPreserveRegs);
231            }
232        }
233        RELEASE_ASSERT_NOT_REACHED();
234        return 0;
235    }
236
237    static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind)
238    {
239        if (kind == CodeForCall)
240            return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall);
241        ASSERT(kind == CodeForConstruct);
242        return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct);
243    }
244
245    bool hasJITCodeForCall() const
246    {
247        return m_numParametersForCall >= 0;
248    }
249
250    bool hasJITCodeForConstruct() const
251    {
252        return m_numParametersForConstruct >= 0;
253    }
254
255    bool hasJITCodeFor(CodeSpecializationKind kind) const
256    {
257        if (kind == CodeForCall)
258            return hasJITCodeForCall();
259        ASSERT(kind == CodeForConstruct);
260        return hasJITCodeForConstruct();
261    }
262
263    // Intrinsics are only for calls, currently.
264    Intrinsic intrinsic() const;
265
266    Intrinsic intrinsicFor(CodeSpecializationKind kind) const
267    {
268        if (isCall(kind))
269            return intrinsic();
270        return NoIntrinsic;
271    }
272
273    void dump(PrintStream&) const;
274
275protected:
276    ExecutableBase* m_prev;
277    ExecutableBase* m_next;
278
279    RefPtr<JITCode> m_jitCodeForCall;
280    RefPtr<JITCode> m_jitCodeForConstruct;
281    MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
282    MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
283    MacroAssemblerCodePtr m_jitCodeForCallWithArityCheckAndPreserveRegs;
284    MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheckAndPreserveRegs;
285};
286
287class NativeExecutable : public ExecutableBase {
288    friend class JIT;
289    friend class LLIntOffsetsExtractor;
290public:
291    typedef ExecutableBase Base;
292
293    static NativeExecutable* create(VM& vm, PassRefPtr<JITCode> callThunk, NativeFunction function, PassRefPtr<JITCode> constructThunk, NativeFunction constructor, Intrinsic intrinsic)
294    {
295        NativeExecutable* executable;
296        executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
297        executable->finishCreation(vm, callThunk, constructThunk, intrinsic);
298        return executable;
299    }
300
301#if ENABLE(JIT)
302    static void destroy(JSCell*);
303#endif
304
305    CodeBlockHash hashFor(CodeSpecializationKind) const;
306
307    NativeFunction function() { return m_function; }
308    NativeFunction constructor() { return m_constructor; }
309
310    NativeFunction nativeFunctionFor(CodeSpecializationKind kind)
311    {
312        if (kind == CodeForCall)
313            return function();
314        ASSERT(kind == CodeForConstruct);
315        return constructor();
316    }
317
318    static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind)
319    {
320        if (kind == CodeForCall)
321            return OBJECT_OFFSETOF(NativeExecutable, m_function);
322        ASSERT(kind == CodeForConstruct);
323        return OBJECT_OFFSETOF(NativeExecutable, m_constructor);
324    }
325
326    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(LeafType, StructureFlags), info()); }
327
328    DECLARE_INFO;
329
330    Intrinsic intrinsic() const;
331
332protected:
333    void finishCreation(VM& vm, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, Intrinsic intrinsic)
334    {
335        Base::finishCreation(vm);
336        m_jitCodeForCall = callThunk;
337        m_jitCodeForConstruct = constructThunk;
338        m_intrinsic = intrinsic;
339    }
340
341private:
342    NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor)
343        : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
344        , m_function(function)
345        , m_constructor(constructor)
346    {
347    }
348
349    NativeFunction m_function;
350    NativeFunction m_constructor;
351
352    Intrinsic m_intrinsic;
353};
354
355class ScriptExecutable : public ExecutableBase {
356public:
357    typedef ExecutableBase Base;
358
359    ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext)
360        : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED)
361        , m_source(source)
362        , m_features(isInStrictContext ? StrictModeFeature : 0)
363        , m_neverInline(false)
364        , m_startColumn(UINT_MAX)
365        , m_endColumn(UINT_MAX)
366    {
367    }
368
369    ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
370        : ExecutableBase(exec->vm(), structure, NUM_PARAMETERS_NOT_COMPILED)
371        , m_source(source)
372        , m_features(isInStrictContext ? StrictModeFeature : 0)
373        , m_neverInline(false)
374        , m_startColumn(UINT_MAX)
375        , m_endColumn(UINT_MAX)
376    {
377    }
378
379#if ENABLE(JIT)
380    static void destroy(JSCell*);
381#endif
382
383    CodeBlockHash hashFor(CodeSpecializationKind) const;
384
385    const SourceCode& source() const { return m_source; }
386    intptr_t sourceID() const { return m_source.providerID(); }
387    const String& sourceURL() const { return m_source.provider()->url(); }
388    int lineNo() const { return m_firstLine; }
389    int lastLine() const { return m_lastLine; }
390    unsigned startColumn() const { return m_startColumn; }
391    unsigned endColumn() const { return m_endColumn; }
392
393    bool usesEval() const { return m_features & EvalFeature; }
394    bool usesArguments() const { return m_features & ArgumentsFeature; }
395    bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
396    bool isStrictMode() const { return m_features & StrictModeFeature; }
397    ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; }
398
399    void setNeverInline(bool value) { m_neverInline = value; }
400    bool neverInline() const { return m_neverInline; }
401    bool isInliningCandidate() const { return !neverInline(); }
402
403    void unlinkCalls();
404
405    CodeFeatures features() const { return m_features; }
406
407    DECLARE_INFO;
408
409    void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn, unsigned endColumn)
410    {
411        m_features = features;
412        m_hasCapturedVariables = hasCapturedVariables;
413        m_firstLine = firstLine;
414        m_lastLine = lastLine;
415        ASSERT(startColumn != UINT_MAX);
416        m_startColumn = startColumn;
417        ASSERT(endColumn != UINT_MAX);
418        m_endColumn = endColumn;
419    }
420
421    void installCode(CodeBlock*);
422    PassRefPtr<CodeBlock> newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope**, JSObject*& exception);
423    PassRefPtr<CodeBlock> newReplacementCodeBlockFor(CodeSpecializationKind);
424
425    JSObject* prepareForExecution(ExecState* exec, JSFunction* function, JSScope** scope, CodeSpecializationKind kind)
426    {
427        if (hasJITCodeFor(kind))
428            return 0;
429        return prepareForExecutionImpl(exec, function, scope, kind);
430    }
431
432    template <typename Functor> void forEachCodeBlock(Functor&&);
433
434private:
435    JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope**, CodeSpecializationKind);
436
437protected:
438    void finishCreation(VM& vm)
439    {
440        Base::finishCreation(vm);
441        vm.heap.addCompiledCode(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
442
443#if ENABLE(CODEBLOCK_SAMPLING)
444        if (SamplingTool* sampler = vm.interpreter->sampler())
445            sampler->notifyOfScope(vm, this);
446#endif
447    }
448
449    SourceCode m_source;
450    CodeFeatures m_features;
451    bool m_hasCapturedVariables;
452    bool m_neverInline;
453    int m_firstLine;
454    int m_lastLine;
455    unsigned m_startColumn;
456    unsigned m_endColumn;
457};
458
459class EvalExecutable : public ScriptExecutable {
460    friend class LLIntOffsetsExtractor;
461public:
462    typedef ScriptExecutable Base;
463
464    static void destroy(JSCell*);
465
466    EvalCodeBlock* codeBlock()
467    {
468        return m_evalCodeBlock.get();
469    }
470
471    static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext);
472
473    PassRefPtr<JITCode> generatedJITCode()
474    {
475        return generatedJITCodeForCall();
476    }
477
478    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
479    {
480        return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), info());
481    }
482
483    DECLARE_INFO;
484
485    void unlinkCalls();
486
487    void clearCode();
488
489    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false); }
490
491    unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
492    unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
493
494private:
495    friend class ScriptExecutable;
496    static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
497    EvalExecutable(ExecState*, const SourceCode&, bool);
498
499    static void visitChildren(JSCell*, SlotVisitor&);
500
501    RefPtr<EvalCodeBlock> m_evalCodeBlock;
502    WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
503};
504
505class ProgramExecutable : public ScriptExecutable {
506    friend class LLIntOffsetsExtractor;
507public:
508    typedef ScriptExecutable Base;
509
510    static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
511    {
512        ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
513        executable->finishCreation(exec->vm());
514        return executable;
515    }
516
517
518    JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
519
520    static void destroy(JSCell*);
521
522    ProgramCodeBlock* codeBlock()
523    {
524        return m_programCodeBlock.get();
525    }
526
527    JSObject* checkSyntax(ExecState*);
528
529    PassRefPtr<JITCode> generatedJITCode()
530    {
531        return generatedJITCodeForCall();
532    }
533
534    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
535    {
536        return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), info());
537    }
538
539    DECLARE_INFO;
540
541    void unlinkCalls();
542
543    void clearCode();
544
545    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false); }
546
547private:
548    friend class ScriptExecutable;
549
550    static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
551
552    ProgramExecutable(ExecState*, const SourceCode&);
553
554    static void visitChildren(JSCell*, SlotVisitor&);
555
556    WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
557    RefPtr<ProgramCodeBlock> m_programCodeBlock;
558};
559
560class FunctionExecutable : public ScriptExecutable {
561    friend class JIT;
562    friend class LLIntOffsetsExtractor;
563public:
564    typedef ScriptExecutable Base;
565
566    static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, bool bodyIncludesBraces = true)
567    {
568        FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn, endColumn, bodyIncludesBraces);
569        executable->finishCreation(vm);
570        return executable;
571    }
572    static FunctionExecutable* fromGlobalCode(const Identifier& name, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
573
574    static void destroy(JSCell*);
575
576    UnlinkedFunctionExecutable* unlinkedExecutable()
577    {
578        return m_unlinkedExecutable.get();
579    }
580
581    // Returns either call or construct bytecode. This can be appropriate
582    // for answering questions that that don't vary between call and construct --
583    // for example, argumentsRegister().
584    FunctionCodeBlock* eitherCodeBlock()
585    {
586        if (m_codeBlockForCall)
587            return m_codeBlockForCall.get();
588        return m_codeBlockForConstruct.get();
589    }
590
591    bool isGeneratedForCall() const
592    {
593        return m_codeBlockForCall;
594    }
595
596    FunctionCodeBlock* codeBlockForCall()
597    {
598        return m_codeBlockForCall.get();
599    }
600
601    bool isGeneratedForConstruct() const
602    {
603        return m_codeBlockForConstruct;
604    }
605
606    FunctionCodeBlock* codeBlockForConstruct()
607    {
608        return m_codeBlockForConstruct.get();
609    }
610
611    bool isGeneratedFor(CodeSpecializationKind kind)
612    {
613        if (kind == CodeForCall)
614            return isGeneratedForCall();
615        ASSERT(kind == CodeForConstruct);
616        return isGeneratedForConstruct();
617    }
618
619    FunctionCodeBlock* codeBlockFor(CodeSpecializationKind kind)
620    {
621        if (kind == CodeForCall)
622            return codeBlockForCall();
623        ASSERT(kind == CodeForConstruct);
624        return codeBlockForConstruct();
625    }
626
627    FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
628
629    FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
630    {
631        return baselineCodeBlockFor(kind);
632    }
633
634    FunctionMode functionMode() { return m_unlinkedExecutable->functionMode(); }
635    bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); }
636    const Identifier& name() { return m_unlinkedExecutable->name(); }
637    const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
638    JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
639    size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
640    String paramString() const;
641    SymbolTable* symbolTable(CodeSpecializationKind);
642
643    void clearCodeIfNotCompiling();
644    void clearUnlinkedCodeForRecompilationIfNotCompiling();
645    static void visitChildren(JSCell*, SlotVisitor&);
646    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
647    {
648        return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), info());
649    }
650
651    DECLARE_INFO;
652
653    void unlinkCalls();
654
655    void clearCode();
656
657    bool bodyIncludesBraces() const { return m_bodyIncludesBraces; }
658
659private:
660    FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, bool bodyIncludesBraces);
661
662    bool isCompiling()
663    {
664#if ENABLE(JIT)
665        if (!m_jitCodeForCall && m_codeBlockForCall)
666            return true;
667        if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
668            return true;
669#endif
670        return false;
671    }
672
673    friend class ScriptExecutable;
674
675    static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
676    WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
677    RefPtr<FunctionCodeBlock> m_codeBlockForCall;
678    RefPtr<FunctionCodeBlock> m_codeBlockForConstruct;
679    bool m_bodyIncludesBraces;
680    bool m_didParseForTheFirstTime;
681};
682
683inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
684{
685    switch (executable->type()) {
686    case EvalExecutableType:
687        return jsCast<EvalExecutable*>(executable)->clearCode();
688    case ProgramExecutableType:
689        return jsCast<ProgramExecutable*>(executable)->clearCode();
690    case FunctionExecutableType:
691        return jsCast<FunctionExecutable*>(executable)->clearCode();
692    default:
693        return jsCast<NativeExecutable*>(executable)->clearCode();
694    }
695}
696
697inline void ScriptExecutable::unlinkCalls()
698{
699    switch (type()) {
700    case EvalExecutableType:
701        return jsCast<EvalExecutable*>(this)->unlinkCalls();
702    case ProgramExecutableType:
703        return jsCast<ProgramExecutable*>(this)->unlinkCalls();
704    case FunctionExecutableType:
705        return jsCast<FunctionExecutable*>(this)->unlinkCalls();
706    default:
707        RELEASE_ASSERT_NOT_REACHED();
708    }
709}
710
711}
712
713#endif
714