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