4a14f953719cbd9c13fb2b95792c6aa931f014b9
[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     EvalCodeBlock* codeBlock()
449     {
450         return m_evalCodeBlock.get();
451     }
452
453     static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext);
454
455 #if ENABLE(JIT)
456     PassRefPtr<JITCode> generatedJITCode()
457     {
458         return generatedJITCodeForCall();
459     }
460 #endif
461     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
462     {
463         return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), info());
464     }
465         
466     DECLARE_INFO;
467
468     void unlinkCalls();
469
470     void clearCode();
471
472     ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
473
474     unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
475     unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
476
477 private:
478     friend class ScriptExecutable;
479     static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
480     EvalExecutable(ExecState*, const SourceCode&, bool);
481
482     static void visitChildren(JSCell*, SlotVisitor&);
483
484     RefPtr<EvalCodeBlock> m_evalCodeBlock;
485     WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
486 };
487
488 class ProgramExecutable : public ScriptExecutable {
489     friend class LLIntOffsetsExtractor;
490 public:
491     typedef ScriptExecutable Base;
492
493     static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
494     {
495         ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
496         executable->finishCreation(exec->vm());
497         return executable;
498     }
499
500
501     JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
502
503     static void destroy(JSCell*);
504
505     ProgramCodeBlock* codeBlock()
506     {
507         return m_programCodeBlock.get();
508     }
509
510     JSObject* checkSyntax(ExecState*);
511
512 #if ENABLE(JIT)
513     PassRefPtr<JITCode> generatedJITCode()
514     {
515         return generatedJITCodeForCall();
516     }
517 #endif
518         
519     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
520     {
521         return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), info());
522     }
523         
524     DECLARE_INFO;
525         
526     void unlinkCalls();
527
528     void clearCode();
529
530     ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
531
532 private:
533     friend class ScriptExecutable;
534     
535     static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
536
537     ProgramExecutable(ExecState*, const SourceCode&);
538
539     static void visitChildren(JSCell*, SlotVisitor&);
540
541     WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
542     RefPtr<ProgramCodeBlock> m_programCodeBlock;
543 };
544
545 class FunctionExecutable : public ScriptExecutable {
546     friend class JIT;
547     friend class LLIntOffsetsExtractor;
548 public:
549     typedef ScriptExecutable Base;
550
551     static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn)
552     {
553         FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn);
554         executable->finishCreation(vm);
555         return executable;
556     }
557     static FunctionExecutable* fromGlobalCode(const Identifier& name, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
558
559     static void destroy(JSCell*);
560         
561     UnlinkedFunctionExecutable* unlinkedExecutable()
562     {
563         return m_unlinkedExecutable.get();
564     }
565
566     // Returns either call or construct bytecode. This can be appropriate
567     // for answering questions that that don't vary between call and construct --
568     // for example, argumentsRegister().
569     FunctionCodeBlock* eitherCodeBlock()
570     {
571         if (m_codeBlockForCall)
572             return m_codeBlockForCall.get();
573         return m_codeBlockForConstruct.get();
574     }
575         
576     bool isGeneratedForCall() const
577     {
578         return m_codeBlockForCall;
579     }
580
581     FunctionCodeBlock* codeBlockForCall()
582     {
583         return m_codeBlockForCall.get();
584     }
585
586     bool isGeneratedForConstruct() const
587     {
588         return m_codeBlockForConstruct;
589     }
590
591     FunctionCodeBlock* codeBlockForConstruct()
592     {
593         return m_codeBlockForConstruct.get();
594     }
595         
596     bool isGeneratedFor(CodeSpecializationKind kind)
597     {
598         if (kind == CodeForCall)
599             return isGeneratedForCall();
600         ASSERT(kind == CodeForConstruct);
601         return isGeneratedForConstruct();
602     }
603         
604     FunctionCodeBlock* codeBlockFor(CodeSpecializationKind kind)
605     {
606         if (kind == CodeForCall)
607             return codeBlockForCall();
608         ASSERT(kind == CodeForConstruct);
609         return codeBlockForConstruct();
610     }
611
612     FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
613         
614     FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
615     {
616         return baselineCodeBlockFor(kind);
617     }
618         
619     const Identifier& name() { return m_unlinkedExecutable->name(); }
620     const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
621     JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
622     size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
623     String paramString() const;
624     SharedSymbolTable* symbolTable(CodeSpecializationKind kind) const { return m_unlinkedExecutable->symbolTable(kind); }
625
626     void clearCodeIfNotCompiling();
627     void clearUnlinkedCodeForRecompilationIfNotCompiling();
628     static void visitChildren(JSCell*, SlotVisitor&);
629     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
630     {
631         return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), info());
632     }
633         
634     DECLARE_INFO;
635         
636     void unlinkCalls();
637
638     void clearCode();
639
640 private:
641     FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn);
642
643     bool isCompiling()
644     {
645 #if ENABLE(JIT)
646         if (!m_jitCodeForCall && m_codeBlockForCall)
647             return true;
648         if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
649             return true;
650 #endif
651         return false;
652     }
653
654     friend class ScriptExecutable;
655
656     static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
657     WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
658     RefPtr<FunctionCodeBlock> m_codeBlockForCall;
659     RefPtr<FunctionCodeBlock> m_codeBlockForConstruct;
660 };
661
662 inline bool isHostFunction(JSValue value, NativeFunction nativeFunction)
663 {
664     JSFunction* function = jsCast<JSFunction*>(getJSFunction(value));
665     if (!function || !function->isHostFunction())
666         return false;
667     return function->nativeFunction() == nativeFunction;
668 }
669
670 inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
671 {
672     switch (executable->structure()->typeInfo().type()) {
673     case EvalExecutableType:
674         return jsCast<EvalExecutable*>(executable)->clearCode();
675     case ProgramExecutableType:
676         return jsCast<ProgramExecutable*>(executable)->clearCode();
677     case FunctionExecutableType:
678         return jsCast<FunctionExecutable*>(executable)->clearCode();
679     default:
680         return jsCast<NativeExecutable*>(executable)->clearCode();
681     }
682 }
683
684 inline void ScriptExecutable::unlinkCalls()
685 {
686     switch (structure()->typeInfo().type()) {
687     case EvalExecutableType:
688         return jsCast<EvalExecutable*>(this)->unlinkCalls();
689     case ProgramExecutableType:
690         return jsCast<ProgramExecutable*>(this)->unlinkCalls();
691     case FunctionExecutableType:
692         return jsCast<FunctionExecutable*>(this)->unlinkCalls();
693     default:
694         RELEASE_ASSERT_NOT_REACHED();
695     }
696 }
697
698 }
699
700 #endif