Merge r170090, r170092, r170129, r170141, r170161, r170215, r170275, r170375, r170376...
[WebKit-https.git] / Source / JavaScriptCore / runtime / Executable.h
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
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 #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(CellType, StructureFlags), info()); }
117         
118     void clearCode();
119
120     DECLARE_EXPORT_INFO;
121
122 protected:
123     static const unsigned StructureFlags = StructureIsImmortal;
124     int m_numParametersForCall;
125     int m_numParametersForConstruct;
126
127 public:
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         
275 protected:
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
287 class NativeExecutable : public ExecutableBase {
288     friend class JIT;
289     friend class LLIntOffsetsExtractor;
290 public:
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(CellType, StructureFlags), info()); }
327         
328     DECLARE_INFO;
329
330     Intrinsic intrinsic() const;
331
332 protected:
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
341 private:
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
355 class ScriptExecutable : public ExecutableBase {
356 public:
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
434 private:
435     JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope**, CodeSpecializationKind);
436
437 protected:
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
459 class EvalExecutable : public ScriptExecutable {
460     friend class LLIntOffsetsExtractor;
461 public:
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
494 private:
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
505 class ProgramExecutable : public ScriptExecutable {
506     friend class LLIntOffsetsExtractor;
507 public:
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
547 private:
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
560 class FunctionExecutable : public ScriptExecutable {
561     friend class JIT;
562     friend class LLIntOffsetsExtractor;
563 public:
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
659 private:
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
683 inline 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
697 inline 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