Add tracking of endColumn for Executables.
[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 "CallData.h"
30 #include "CodeBlockHash.h"
31 #include "CodeSpecializationKind.h"
32 #include "CompilationResult.h"
33 #include "DFGPlan.h"
34 #include "HandlerInfo.h"
35 #include "JSFunction.h"
36 #include "Interpreter.h"
37 #include "JITCode.h"
38 #include "JSGlobalObject.h"
39 #include "LLIntCLoop.h"
40 #include "SamplingTool.h"
41 #include "SourceCode.h"
42 #include "UnlinkedCodeBlock.h"
43 #include <wtf/PassOwnPtr.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, public DoublyLinkedListNode<ExecutableBase> {
66     friend class WTF::DoublyLinkedListNode<ExecutableBase>;
67     friend class JIT;
68
69 protected:
70     static const int NUM_PARAMETERS_IS_HOST = 0;
71     static const int NUM_PARAMETERS_NOT_COMPILED = -1;
72
73     ExecutableBase(VM& vm, Structure* structure, int numParameters)
74         : JSCell(vm, structure)
75         , m_numParametersForCall(numParameters)
76         , m_numParametersForConstruct(numParameters)
77     {
78     }
79
80     void finishCreation(VM& vm)
81     {
82         Base::finishCreation(vm);
83     }
84
85 public:
86     typedef JSCell Base;
87
88 #if ENABLE(JIT)
89     static const bool needsDestruction = true;
90     static const bool hasImmortalStructure = true;
91     static void destroy(JSCell*);
92 #endif
93         
94     CodeBlockHash hashFor(CodeSpecializationKind) const;
95
96     bool isEvalExecutable()
97     {
98         return structure()->typeInfo().type() == EvalExecutableType;
99     }
100     bool isFunctionExecutable()
101     {
102         return structure()->typeInfo().type() == FunctionExecutableType;
103     }
104     bool isProgramExecutable()
105     {
106         return structure()->typeInfo().type() == ProgramExecutableType;
107     }
108
109     bool isHostFunction() const
110     {
111         ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
112         return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
113     }
114
115     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CompoundType, StructureFlags), info()); }
116         
117     void clearCode();
118
119     DECLARE_EXPORT_INFO;
120
121 protected:
122     static const unsigned StructureFlags = 0;
123     int m_numParametersForCall;
124     int m_numParametersForConstruct;
125
126 public:
127     static void clearCodeVirtual(ExecutableBase*);
128
129 #if ENABLE(JIT)
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 generatedJITCodeForCallWithArityCheck()
151     {
152         ASSERT(m_jitCodeForCall);
153         ASSERT(m_jitCodeForCallWithArityCheck);
154         return m_jitCodeForCallWithArityCheck;
155     }
156
157     MacroAssemblerCodePtr generatedJITCodeForConstructWithArityCheck()
158     {
159         ASSERT(m_jitCodeForConstruct);
160         ASSERT(m_jitCodeForConstructWithArityCheck);
161         return m_jitCodeForConstructWithArityCheck;
162     }
163         
164     MacroAssemblerCodePtr generatedJITCodeWithArityCheckFor(CodeSpecializationKind kind)
165     {
166         if (kind == CodeForCall)
167             return generatedJITCodeForCallWithArityCheck();
168         ASSERT(kind == CodeForConstruct);
169         return generatedJITCodeForConstructWithArityCheck();
170     }
171         
172     static ptrdiff_t offsetOfJITCodeWithArityCheckFor(CodeSpecializationKind kind)
173     {
174         if (kind == CodeForCall)
175             return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
176         ASSERT(kind == CodeForConstruct);
177         return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
178     }
179         
180     static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind)
181     {
182         if (kind == CodeForCall)
183             return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall);
184         ASSERT(kind == CodeForConstruct);
185         return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct);
186     }
187 #endif // ENABLE(JIT)
188
189     bool hasJITCodeForCall() const
190     {
191         return m_numParametersForCall >= 0;
192     }
193         
194     bool hasJITCodeForConstruct() const
195     {
196         return m_numParametersForConstruct >= 0;
197     }
198         
199     bool hasJITCodeFor(CodeSpecializationKind kind) const
200     {
201         if (kind == CodeForCall)
202             return hasJITCodeForCall();
203         ASSERT(kind == CodeForConstruct);
204         return hasJITCodeForConstruct();
205     }
206
207     // Intrinsics are only for calls, currently.
208     Intrinsic intrinsic() const;
209         
210     Intrinsic intrinsicFor(CodeSpecializationKind kind) const
211     {
212         if (isCall(kind))
213             return intrinsic();
214         return NoIntrinsic;
215     }
216         
217 #if ENABLE(JIT) || ENABLE(LLINT_C_LOOP)
218     MacroAssemblerCodePtr hostCodeEntryFor(CodeSpecializationKind kind)
219     {
220 #if ENABLE(JIT)
221         return generatedJITCodeFor(kind)->addressForCall();
222 #else
223         return LLInt::CLoop::hostCodeEntryFor(kind);
224 #endif
225     }
226
227     MacroAssemblerCodePtr jsCodeEntryFor(CodeSpecializationKind kind)
228     {
229 #if ENABLE(JIT)
230         return generatedJITCodeFor(kind)->addressForCall();
231 #else
232         return LLInt::CLoop::jsCodeEntryFor(kind);
233 #endif
234     }
235
236     MacroAssemblerCodePtr jsCodeWithArityCheckEntryFor(CodeSpecializationKind kind)
237     {
238 #if ENABLE(JIT)
239         return generatedJITCodeWithArityCheckFor(kind);
240 #else
241         return LLInt::CLoop::jsCodeEntryWithArityCheckFor(kind);
242 #endif
243     }
244
245     static void* catchRoutineFor(HandlerInfo* handler, Instruction* catchPCForInterpreter)
246     {
247 #if ENABLE(JIT)
248         UNUSED_PARAM(catchPCForInterpreter);
249         return handler->nativeCode.executableAddress();
250 #else
251         UNUSED_PARAM(handler);
252         return LLInt::CLoop::catchRoutineFor(catchPCForInterpreter);
253 #endif
254     }
255     
256 #endif // ENABLE(JIT || ENABLE(LLINT_C_LOOP)
257
258 protected:
259     ExecutableBase* m_prev;
260     ExecutableBase* m_next;
261
262     RefPtr<JITCode> m_jitCodeForCall;
263     RefPtr<JITCode> m_jitCodeForConstruct;
264     MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
265     MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
266 };
267
268 class NativeExecutable : public ExecutableBase {
269     friend class JIT;
270     friend class LLIntOffsetsExtractor;
271 public:
272     typedef ExecutableBase Base;
273
274 #if ENABLE(JIT)
275     static NativeExecutable* create(VM& vm, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor, Intrinsic intrinsic)
276     {
277         NativeExecutable* executable;
278         if (!callThunk) {
279             executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
280             executable->finishCreation(vm, 0, 0, intrinsic);
281         } else {
282             executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
283             executable->finishCreation(vm, JITCode::hostFunction(callThunk), JITCode::hostFunction(constructThunk), intrinsic);
284         }
285         return executable;
286     }
287 #endif
288
289 #if ENABLE(LLINT_C_LOOP)
290     static NativeExecutable* create(VM& vm, NativeFunction function, NativeFunction constructor)
291     {
292         ASSERT(!vm.canUseJIT());
293         NativeExecutable* executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
294         executable->finishCreation(vm);
295         return executable;
296     }
297 #endif
298
299 #if ENABLE(JIT)
300     static void destroy(JSCell*);
301 #endif
302
303     CodeBlockHash hashFor(CodeSpecializationKind) const;
304
305     NativeFunction function() { return m_function; }
306     NativeFunction constructor() { return m_constructor; }
307         
308     NativeFunction nativeFunctionFor(CodeSpecializationKind kind)
309     {
310         if (kind == CodeForCall)
311             return function();
312         ASSERT(kind == CodeForConstruct);
313         return constructor();
314     }
315         
316     static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind)
317     {
318         if (kind == CodeForCall)
319             return OBJECT_OFFSETOF(NativeExecutable, m_function);
320         ASSERT(kind == CodeForConstruct);
321         return OBJECT_OFFSETOF(NativeExecutable, m_constructor);
322     }
323
324     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(LeafType, StructureFlags), info()); }
325         
326     DECLARE_INFO;
327
328     Intrinsic intrinsic() const;
329
330 protected:
331 #if ENABLE(JIT)
332     void finishCreation(VM& vm, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, Intrinsic intrinsic)
333     {
334         Base::finishCreation(vm);
335         m_jitCodeForCallWithArityCheck = callThunk ? callThunk->addressForCall() : MacroAssemblerCodePtr();
336         m_jitCodeForConstructWithArityCheck = constructThunk ? constructThunk->addressForCall() : MacroAssemblerCodePtr();
337         m_jitCodeForCall = callThunk;
338         m_jitCodeForConstruct = constructThunk;
339         m_intrinsic = intrinsic;
340     }
341 #endif
342
343 private:
344     NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor)
345         : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
346         , m_function(function)
347         , m_constructor(constructor)
348     {
349     }
350
351     NativeFunction m_function;
352     NativeFunction m_constructor;
353         
354     Intrinsic m_intrinsic;
355 };
356
357 class ScriptExecutable : public ExecutableBase {
358 public:
359     typedef ExecutableBase Base;
360
361     ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext)
362         : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED)
363         , m_source(source)
364         , m_features(isInStrictContext ? StrictModeFeature : 0)
365         , m_neverInline(false)
366         , m_startColumn(UINT_MAX)
367         , m_endColumn(UINT_MAX)
368     {
369     }
370
371     ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
372         : ExecutableBase(exec->vm(), structure, NUM_PARAMETERS_NOT_COMPILED)
373         , m_source(source)
374         , m_features(isInStrictContext ? StrictModeFeature : 0)
375         , m_neverInline(false)
376         , m_startColumn(UINT_MAX)
377         , m_endColumn(UINT_MAX)
378     {
379     }
380
381 #if ENABLE(JIT)
382     static void destroy(JSCell*);
383 #endif
384         
385     CodeBlockHash hashFor(CodeSpecializationKind) const;
386
387     const SourceCode& source() const { return m_source; }
388     intptr_t sourceID() const { return m_source.providerID(); }
389     const String& sourceURL() const { return m_source.provider()->url(); }
390     int lineNo() const { return m_firstLine; }
391     int lastLine() const { return m_lastLine; }
392     unsigned startColumn() const { return m_startColumn; }
393     unsigned endColumn() const { return m_endColumn; }
394
395     bool usesEval() const { return m_features & EvalFeature; }
396     bool usesArguments() const { return m_features & ArgumentsFeature; }
397     bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
398     bool isStrictMode() const { return m_features & StrictModeFeature; }
399     ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; }
400         
401     void setNeverInline(bool value) { m_neverInline = value; }
402     bool neverInline() const { return m_neverInline; }
403     bool isInliningCandidate() const { return !neverInline(); }
404
405     void unlinkCalls();
406         
407     CodeFeatures features() const { return m_features; }
408         
409     DECLARE_INFO;
410
411     void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn, unsigned endColumn)
412     {
413         m_features = features;
414         m_hasCapturedVariables = hasCapturedVariables;
415         m_firstLine = firstLine;
416         m_lastLine = lastLine;
417         ASSERT(startColumn != UINT_MAX);
418         m_startColumn = startColumn;
419         ASSERT(endColumn != UINT_MAX);
420         m_endColumn = endColumn;
421     }
422
423     void installCode(CodeBlock*);
424     PassRefPtr<CodeBlock> newCodeBlockFor(CodeSpecializationKind, JSScope*, JSObject*& exception);
425     PassRefPtr<CodeBlock> newReplacementCodeBlockFor(CodeSpecializationKind);
426     
427     JSObject* prepareForExecution(ExecState* exec, JSScope* scope, CodeSpecializationKind kind)
428     {
429         if (hasJITCodeFor(kind))
430             return 0;
431         return prepareForExecutionImpl(exec, scope, kind);
432     }
433
434 private:
435     JSObject* prepareForExecutionImpl(ExecState*, 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 #if ENABLE(JIT)
474     PassRefPtr<JITCode> generatedJITCode()
475     {
476         return generatedJITCodeForCall();
477     }
478 #endif
479     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
480     {
481         return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), info());
482     }
483         
484     DECLARE_INFO;
485
486     void unlinkCalls();
487
488     void clearCode();
489
490     ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
491
492     unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
493     unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
494
495 private:
496     friend class ScriptExecutable;
497     static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
498     EvalExecutable(ExecState*, const SourceCode&, bool);
499
500     static void visitChildren(JSCell*, SlotVisitor&);
501
502     RefPtr<EvalCodeBlock> m_evalCodeBlock;
503     WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
504 };
505
506 class ProgramExecutable : public ScriptExecutable {
507     friend class LLIntOffsetsExtractor;
508 public:
509     typedef ScriptExecutable Base;
510
511     static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
512     {
513         ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
514         executable->finishCreation(exec->vm());
515         return executable;
516     }
517
518
519     JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
520
521     static void destroy(JSCell*);
522
523     ProgramCodeBlock* codeBlock()
524     {
525         return m_programCodeBlock.get();
526     }
527
528     JSObject* checkSyntax(ExecState*);
529
530 #if ENABLE(JIT)
531     PassRefPtr<JITCode> generatedJITCode()
532     {
533         return generatedJITCodeForCall();
534     }
535 #endif
536         
537     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
538     {
539         return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), info());
540     }
541         
542     DECLARE_INFO;
543         
544     void unlinkCalls();
545
546     void clearCode();
547
548     ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
549
550 private:
551     friend class ScriptExecutable;
552     
553     static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
554
555     ProgramExecutable(ExecState*, const SourceCode&);
556
557     static void visitChildren(JSCell*, SlotVisitor&);
558
559     WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
560     RefPtr<ProgramCodeBlock> m_programCodeBlock;
561 };
562
563 class FunctionExecutable : public ScriptExecutable {
564     friend class JIT;
565     friend class LLIntOffsetsExtractor;
566 public:
567     typedef ScriptExecutable Base;
568
569     static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, bool bodyIncludesBraces = true)
570     {
571         FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn, endColumn, bodyIncludesBraces);
572         executable->finishCreation(vm);
573         return executable;
574     }
575     static FunctionExecutable* fromGlobalCode(const Identifier& name, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
576
577     static void destroy(JSCell*);
578         
579     UnlinkedFunctionExecutable* unlinkedExecutable()
580     {
581         return m_unlinkedExecutable.get();
582     }
583
584     // Returns either call or construct bytecode. This can be appropriate
585     // for answering questions that that don't vary between call and construct --
586     // for example, argumentsRegister().
587     FunctionCodeBlock* eitherCodeBlock()
588     {
589         if (m_codeBlockForCall)
590             return m_codeBlockForCall.get();
591         return m_codeBlockForConstruct.get();
592     }
593         
594     bool isGeneratedForCall() const
595     {
596         return m_codeBlockForCall;
597     }
598
599     FunctionCodeBlock* codeBlockForCall()
600     {
601         return m_codeBlockForCall.get();
602     }
603
604     bool isGeneratedForConstruct() const
605     {
606         return m_codeBlockForConstruct;
607     }
608
609     FunctionCodeBlock* codeBlockForConstruct()
610     {
611         return m_codeBlockForConstruct.get();
612     }
613         
614     bool isGeneratedFor(CodeSpecializationKind kind)
615     {
616         if (kind == CodeForCall)
617             return isGeneratedForCall();
618         ASSERT(kind == CodeForConstruct);
619         return isGeneratedForConstruct();
620     }
621         
622     FunctionCodeBlock* codeBlockFor(CodeSpecializationKind kind)
623     {
624         if (kind == CodeForCall)
625             return codeBlockForCall();
626         ASSERT(kind == CodeForConstruct);
627         return codeBlockForConstruct();
628     }
629
630     FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
631         
632     FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
633     {
634         return baselineCodeBlockFor(kind);
635     }
636         
637     const Identifier& name() { return m_unlinkedExecutable->name(); }
638     const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
639     JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
640     size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
641     String paramString() const;
642     SharedSymbolTable* symbolTable(CodeSpecializationKind kind) const { return m_unlinkedExecutable->symbolTable(kind); }
643
644     void clearCodeIfNotCompiling();
645     void clearUnlinkedCodeForRecompilationIfNotCompiling();
646     static void visitChildren(JSCell*, SlotVisitor&);
647     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
648     {
649         return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), info());
650     }
651         
652     DECLARE_INFO;
653         
654     void unlinkCalls();
655
656     void clearCode();
657
658     bool bodyIncludesBraces() const { return m_bodyIncludesBraces; }
659
660 private:
661     FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, bool bodyIncludesBraces);
662
663     bool isCompiling()
664     {
665 #if ENABLE(JIT)
666         if (!m_jitCodeForCall && m_codeBlockForCall)
667             return true;
668         if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
669             return true;
670 #endif
671         return false;
672     }
673
674     friend class ScriptExecutable;
675
676     static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
677     WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
678     RefPtr<FunctionCodeBlock> m_codeBlockForCall;
679     RefPtr<FunctionCodeBlock> m_codeBlockForConstruct;
680     bool m_bodyIncludesBraces;
681 };
682
683 inline bool isHostFunction(JSValue value, NativeFunction nativeFunction)
684 {
685     JSFunction* function = jsCast<JSFunction*>(getJSFunction(value));
686     if (!function || !function->isHostFunction())
687         return false;
688     return function->nativeFunction() == nativeFunction;
689 }
690
691 inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
692 {
693     switch (executable->structure()->typeInfo().type()) {
694     case EvalExecutableType:
695         return jsCast<EvalExecutable*>(executable)->clearCode();
696     case ProgramExecutableType:
697         return jsCast<ProgramExecutable*>(executable)->clearCode();
698     case FunctionExecutableType:
699         return jsCast<FunctionExecutable*>(executable)->clearCode();
700     default:
701         return jsCast<NativeExecutable*>(executable)->clearCode();
702     }
703 }
704
705 inline void ScriptExecutable::unlinkCalls()
706 {
707     switch (structure()->typeInfo().type()) {
708     case EvalExecutableType:
709         return jsCast<EvalExecutable*>(this)->unlinkCalls();
710     case ProgramExecutableType:
711         return jsCast<ProgramExecutable*>(this)->unlinkCalls();
712     case FunctionExecutableType:
713         return jsCast<FunctionExecutable*>(this)->unlinkCalls();
714     default:
715         RELEASE_ASSERT_NOT_REACHED();
716     }
717 }
718
719 }
720
721 #endif