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