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