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