fourthTier: testRunner should be able to tell you if a function is DFG compiled
[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), &s_info); }
108         
109         void clearCode();
110
111         static JS_EXPORTDATA const ClassInfo s_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         bool hasJITCodeForCall() const
165         {
166             return m_numParametersForCall >= 0;
167         }
168         
169         bool hasJITCodeForConstruct() const
170         {
171             return m_numParametersForConstruct >= 0;
172         }
173         
174         bool hasJITCodeFor(CodeSpecializationKind kind) const
175         {
176             if (kind == CodeForCall)
177                 return hasJITCodeForCall();
178             ASSERT(kind == CodeForConstruct);
179             return hasJITCodeForConstruct();
180         }
181
182         static ptrdiff_t offsetOfJITCodeWithArityCheckFor(CodeSpecializationKind kind)
183         {
184             if (kind == CodeForCall)
185                 return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
186             ASSERT(kind == CodeForConstruct);
187             return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
188         }
189         
190         static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind)
191         {
192             if (kind == CodeForCall)
193                 return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall);
194             ASSERT(kind == CodeForConstruct);
195             return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct);
196         }
197 #endif // ENABLE(JIT)
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 #endif // ENABLE(JIT || ENABLE(LLINT_C_LOOP)
248
249     protected:
250         ExecutableBase* m_prev;
251         ExecutableBase* m_next;
252
253 #if ENABLE(JIT)
254         RefPtr<JITCode> m_jitCodeForCall;
255         RefPtr<JITCode> m_jitCodeForConstruct;
256         MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
257         MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
258 #endif
259     };
260
261     class NativeExecutable : public ExecutableBase {
262         friend class JIT;
263         friend class LLIntOffsetsExtractor;
264     public:
265         typedef ExecutableBase Base;
266
267 #if ENABLE(JIT)
268         static NativeExecutable* create(VM& vm, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor, Intrinsic intrinsic)
269         {
270             NativeExecutable* executable;
271             if (!callThunk) {
272                 executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
273                 executable->finishCreation(vm, 0, 0, intrinsic);
274             } else {
275                 executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
276                 executable->finishCreation(vm, JITCode::hostFunction(callThunk), JITCode::hostFunction(constructThunk), intrinsic);
277             }
278             return executable;
279         }
280 #endif
281
282 #if ENABLE(LLINT_C_LOOP)
283         static NativeExecutable* create(VM& vm, NativeFunction function, NativeFunction constructor)
284         {
285             ASSERT(!vm.canUseJIT());
286             NativeExecutable* executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
287             executable->finishCreation(vm);
288             return executable;
289         }
290 #endif
291
292 #if ENABLE(JIT)
293         static void destroy(JSCell*);
294 #endif
295
296         CodeBlockHash hashFor(CodeSpecializationKind) const;
297
298         NativeFunction function() { return m_function; }
299         NativeFunction constructor() { return m_constructor; }
300         
301         NativeFunction nativeFunctionFor(CodeSpecializationKind kind)
302         {
303             if (kind == CodeForCall)
304                 return function();
305             ASSERT(kind == CodeForConstruct);
306             return constructor();
307         }
308         
309         static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind)
310         {
311             if (kind == CodeForCall)
312                 return OBJECT_OFFSETOF(NativeExecutable, m_function);
313             ASSERT(kind == CodeForConstruct);
314             return OBJECT_OFFSETOF(NativeExecutable, m_constructor);
315         }
316
317         static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(LeafType, StructureFlags), &s_info); }
318         
319         static const ClassInfo s_info;
320
321         Intrinsic intrinsic() const;
322
323     protected:
324 #if ENABLE(JIT)
325         void finishCreation(VM& vm, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, Intrinsic intrinsic)
326         {
327             Base::finishCreation(vm);
328             m_jitCodeForCallWithArityCheck = callThunk ? callThunk->addressForCall() : MacroAssemblerCodePtr();
329             m_jitCodeForConstructWithArityCheck = constructThunk ? constructThunk->addressForCall() : MacroAssemblerCodePtr();
330             m_jitCodeForCall = callThunk;
331             m_jitCodeForConstruct = constructThunk;
332             m_intrinsic = intrinsic;
333         }
334 #endif
335
336     private:
337         NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor)
338             : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
339             , m_function(function)
340             , m_constructor(constructor)
341         {
342         }
343
344         NativeFunction m_function;
345         NativeFunction m_constructor;
346         
347         Intrinsic m_intrinsic;
348     };
349
350     class ScriptExecutable : public ExecutableBase {
351     public:
352         typedef ExecutableBase Base;
353
354         ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext)
355             : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED)
356             , m_source(source)
357             , m_features(isInStrictContext ? StrictModeFeature : 0)
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         {
366         }
367
368 #if ENABLE(JIT)
369         static void destroy(JSCell*);
370 #endif
371         
372         CodeBlockHash hashFor(CodeSpecializationKind) const;
373
374         const SourceCode& source() const { return m_source; }
375         intptr_t sourceID() const { return m_source.providerID(); }
376         const String& sourceURL() const { return m_source.provider()->url(); }
377         int lineNo() const { return m_firstLine; }
378         int lastLine() const { return m_lastLine; }
379         unsigned startColumn() const { return m_startColumn; }
380
381         bool usesEval() const { return m_features & EvalFeature; }
382         bool usesArguments() const { return m_features & ArgumentsFeature; }
383         bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
384         bool isStrictMode() const { return m_features & StrictModeFeature; }
385
386         void unlinkCalls();
387         
388         CodeFeatures features() const { return m_features; }
389         
390         static const ClassInfo s_info;
391
392         void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn)
393         {
394             m_features = features;
395             m_hasCapturedVariables = hasCapturedVariables;
396             m_firstLine = firstLine;
397             m_lastLine = lastLine;
398             m_startColumn = startColumn;
399         }
400
401     protected:
402         void finishCreation(VM& vm)
403         {
404             Base::finishCreation(vm);
405             vm.heap.addCompiledCode(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
406
407 #if ENABLE(CODEBLOCK_SAMPLING)
408             if (SamplingTool* sampler = vm.interpreter->sampler())
409                 sampler->notifyOfScope(vm, this);
410 #endif
411         }
412
413         SourceCode m_source;
414         CodeFeatures m_features;
415         bool m_hasCapturedVariables;
416         int m_firstLine;
417         int m_lastLine;
418         unsigned m_startColumn;
419     };
420
421     class EvalExecutable : public ScriptExecutable {
422         friend class LLIntOffsetsExtractor;
423     public:
424         typedef ScriptExecutable Base;
425
426         static void destroy(JSCell*);
427
428         JSObject* compile(ExecState* exec, JSScope* scope)
429         {
430             RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
431             JSObject* error = 0;
432             if (!m_evalCodeBlock)
433                 error = compileInternal(exec, scope, JITCode::bottomTierJIT());
434             ASSERT(!error == !!m_evalCodeBlock);
435             return error;
436         }
437         
438         JSObject* compileOptimized(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
439         CompilationResult replaceWithDeferredOptimizedCode(PassRefPtr<DFG::Plan>);
440         
441 #if ENABLE(JIT)
442         void jettisonOptimizedCode(VM&);
443         CompilationResult jitCompile(ExecState*);
444 #endif
445
446         EvalCodeBlock& generatedBytecode()
447         {
448             ASSERT(m_evalCodeBlock);
449             return *m_evalCodeBlock;
450         }
451
452         static EvalExecutable* create(ExecState* exec, PassRefPtr<CodeCache> cache, const SourceCode& source, bool isInStrictContext)
453         {
454             EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, cache, source, isInStrictContext);
455             executable->finishCreation(exec->vm());
456             return executable;
457         }
458
459 #if ENABLE(JIT)
460         PassRefPtr<JITCode> generatedJITCode()
461         {
462             return generatedJITCodeForCall();
463         }
464 #endif
465         static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
466         {
467             return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), &s_info);
468         }
469         
470         static const ClassInfo s_info;
471
472         void unlinkCalls();
473
474         void clearCode();
475
476         ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
477
478     private:
479         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
480         EvalExecutable(ExecState*, PassRefPtr<CodeCache>, const SourceCode&, bool);
481
482         JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, CompilationResult* = 0, unsigned bytecodeIndex = UINT_MAX);
483         static void visitChildren(JSCell*, SlotVisitor&);
484
485         RefPtr<EvalCodeBlock> m_evalCodeBlock;
486         WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
487         RefPtr<CodeCache> m_codeCache;
488     };
489
490     class ProgramExecutable : public ScriptExecutable {
491         friend class LLIntOffsetsExtractor;
492     public:
493         typedef ScriptExecutable Base;
494
495         static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
496         {
497             ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
498             executable->finishCreation(exec->vm());
499             return executable;
500         }
501
502
503         JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
504
505         static void destroy(JSCell*);
506
507         JSObject* compile(ExecState* exec, JSScope* scope)
508         {
509             RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
510             JSObject* error = 0;
511             if (!m_programCodeBlock)
512                 error = compileInternal(exec, scope, JITCode::bottomTierJIT());
513             ASSERT(!error == !!m_programCodeBlock);
514             return error;
515         }
516
517         JSObject* compileOptimized(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
518         CompilationResult replaceWithDeferredOptimizedCode(PassRefPtr<DFG::Plan>);
519         
520 #if ENABLE(JIT)
521         void jettisonOptimizedCode(VM&);
522         CompilationResult jitCompile(ExecState*);
523 #endif
524
525         ProgramCodeBlock& generatedBytecode()
526         {
527             ASSERT(m_programCodeBlock);
528             return *m_programCodeBlock;
529         }
530
531         JSObject* checkSyntax(ExecState*);
532
533 #if ENABLE(JIT)
534         PassRefPtr<JITCode> generatedJITCode()
535         {
536             return generatedJITCodeForCall();
537         }
538 #endif
539         
540         static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
541         {
542             return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), &s_info);
543         }
544         
545         static const ClassInfo s_info;
546         
547         void unlinkCalls();
548
549         void clearCode();
550
551         ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
552
553     private:
554         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
555
556         ProgramExecutable(ExecState*, const SourceCode&);
557
558         enum ConstantMode { IsConstant, IsVariable };
559         enum FunctionMode { IsFunctionToSpecialize, NotFunctionOrNotSpecializable };
560         int addGlobalVar(JSGlobalObject*, const Identifier&, ConstantMode, FunctionMode);
561
562         JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, CompilationResult* = 0, unsigned bytecodeIndex = UINT_MAX);
563         static void visitChildren(JSCell*, SlotVisitor&);
564
565         WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
566         RefPtr<ProgramCodeBlock> m_programCodeBlock;
567     };
568
569     class FunctionExecutable : public ScriptExecutable {
570         friend class JIT;
571         friend class LLIntOffsetsExtractor;
572     public:
573         typedef ScriptExecutable Base;
574
575         static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn)
576         {
577             FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn);
578             executable->finishCreation(vm);
579             return executable;
580         }
581         static FunctionExecutable* fromGlobalCode(const Identifier& name, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
582
583         static void destroy(JSCell*);
584         
585         UnlinkedFunctionExecutable* unlinkedExecutable()
586         {
587             return m_unlinkedExecutable.get();
588         }
589
590         // Returns either call or construct bytecode. This can be appropriate
591         // for answering questions that that don't vary between call and construct --
592         // for example, argumentsRegister().
593         FunctionCodeBlock& generatedBytecode()
594         {
595             if (m_codeBlockForCall)
596                 return *m_codeBlockForCall;
597             ASSERT(m_codeBlockForConstruct);
598             return *m_codeBlockForConstruct;
599         }
600         
601         PassRefPtr<FunctionCodeBlock> produceCodeBlockFor(JSScope*, CodeSpecializationKind, JSObject*& exception);
602
603         JSObject* compileForCall(ExecState* exec, JSScope* scope)
604         {
605             RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
606             JSObject* error = 0;
607             if (!m_codeBlockForCall)
608                 error = compileForCallInternal(exec, scope, JITCode::bottomTierJIT());
609             ASSERT(!error == !!m_codeBlockForCall);
610             return error;
611         }
612
613         JSObject* compileOptimizedForCall(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
614         CompilationResult replaceWithDeferredOptimizedCodeForCall(PassRefPtr<DFG::Plan>);
615         
616 #if ENABLE(JIT)
617         void jettisonOptimizedCodeForCall(VM&);
618         CompilationResult jitCompileForCall(ExecState*);
619 #endif
620
621         bool isGeneratedForCall() const
622         {
623             return m_codeBlockForCall;
624         }
625
626         FunctionCodeBlock& generatedBytecodeForCall()
627         {
628             ASSERT(m_codeBlockForCall);
629             return *m_codeBlockForCall;
630         }
631
632         JSObject* compileForConstruct(ExecState* exec, JSScope* scope)
633         {
634             RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
635             JSObject* error = 0;
636             if (!m_codeBlockForConstruct)
637                 error = compileForConstructInternal(exec, scope, JITCode::bottomTierJIT());
638             ASSERT(!error == !!m_codeBlockForConstruct);
639             return error;
640         }
641
642         JSObject* compileOptimizedForConstruct(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
643         CompilationResult replaceWithDeferredOptimizedCodeForConstruct(PassRefPtr<DFG::Plan>);
644         
645 #if ENABLE(JIT)
646         void jettisonOptimizedCodeForConstruct(VM&);
647         CompilationResult jitCompileForConstruct(ExecState*);
648 #endif
649
650         bool isGeneratedForConstruct() const
651         {
652             return m_codeBlockForConstruct;
653         }
654
655         FunctionCodeBlock& generatedBytecodeForConstruct()
656         {
657             ASSERT(m_codeBlockForConstruct);
658             return *m_codeBlockForConstruct;
659         }
660         
661         JSObject* compileFor(ExecState* exec, JSScope* scope, CodeSpecializationKind kind)
662         {
663             ASSERT(exec->callee());
664             ASSERT(exec->callee()->inherits(&JSFunction::s_info));
665             ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this);
666
667             if (kind == CodeForCall)
668                 return compileForCall(exec, scope);
669             ASSERT(kind == CodeForConstruct);
670             return compileForConstruct(exec, scope);
671         }
672         
673         JSObject* compileOptimizedFor(ExecState* exec, JSScope* scope, CompilationResult& result, unsigned bytecodeIndex, CodeSpecializationKind kind)
674         {
675             ASSERT(exec->callee());
676             ASSERT(exec->callee()->inherits(&JSFunction::s_info));
677             ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this);
678             
679             if (kind == CodeForCall)
680                 return compileOptimizedForCall(exec, scope, result, bytecodeIndex);
681             ASSERT(kind == CodeForConstruct);
682             return compileOptimizedForConstruct(exec, scope, result, bytecodeIndex);
683         }
684         
685         CompilationResult replaceWithDeferredOptimizedCodeFor(PassRefPtr<DFG::Plan> plan, CodeSpecializationKind kind)
686         {
687             if (kind == CodeForCall)
688                 return replaceWithDeferredOptimizedCodeForCall(plan);
689             return replaceWithDeferredOptimizedCodeForConstruct(plan);
690         }
691
692 #if ENABLE(JIT)
693         void jettisonOptimizedCodeFor(VM& vm, CodeSpecializationKind kind)
694         {
695             if (kind == CodeForCall) 
696                 jettisonOptimizedCodeForCall(vm);
697             else {
698                 ASSERT(kind == CodeForConstruct);
699                 jettisonOptimizedCodeForConstruct(vm);
700             }
701         }
702         
703         CompilationResult jitCompileFor(ExecState* exec, CodeSpecializationKind kind)
704         {
705             if (kind == CodeForCall)
706                 return jitCompileForCall(exec);
707             ASSERT(kind == CodeForConstruct);
708             return jitCompileForConstruct(exec);
709         }
710 #endif
711         
712         bool isGeneratedFor(CodeSpecializationKind kind)
713         {
714             if (kind == CodeForCall)
715                 return isGeneratedForCall();
716             ASSERT(kind == CodeForConstruct);
717             return isGeneratedForConstruct();
718         }
719         
720         FunctionCodeBlock& generatedBytecodeFor(CodeSpecializationKind kind)
721         {
722             if (kind == CodeForCall)
723                 return generatedBytecodeForCall();
724             ASSERT(kind == CodeForConstruct);
725             return generatedBytecodeForConstruct();
726         }
727
728         FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
729         
730         FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
731         {
732             return baselineCodeBlockFor(kind);
733         }
734         
735         const Identifier& name() { return m_unlinkedExecutable->name(); }
736         const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
737         JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
738         size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
739         String paramString() const;
740         SharedSymbolTable* symbolTable(CodeSpecializationKind kind) const { return m_unlinkedExecutable->symbolTable(kind); }
741
742         void clearCodeIfNotCompiling();
743         void clearUnlinkedCodeForRecompilationIfNotCompiling();
744         static void visitChildren(JSCell*, SlotVisitor&);
745         static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
746         {
747             return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), &s_info);
748         }
749         
750         static const ClassInfo s_info;
751         
752         void unlinkCalls();
753
754         void clearCode();
755
756     private:
757         FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn);
758
759         JSObject* compileForCallInternal(ExecState*, JSScope*, JITCode::JITType, CompilationResult* = 0, unsigned bytecodeIndex = UINT_MAX);
760         JSObject* compileForConstructInternal(ExecState*, JSScope*, JITCode::JITType, CompilationResult* = 0, unsigned bytecodeIndex = UINT_MAX);
761         
762         RefPtr<FunctionCodeBlock>& codeBlockFor(CodeSpecializationKind kind)
763         {
764             if (kind == CodeForCall)
765                 return m_codeBlockForCall;
766             ASSERT(kind == CodeForConstruct);
767             return m_codeBlockForConstruct;
768         }
769  
770         bool isCompiling()
771         {
772 #if ENABLE(JIT)
773             if (!m_jitCodeForCall && m_codeBlockForCall)
774                 return true;
775             if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
776                 return true;
777 #endif
778             return false;
779         }
780
781         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
782         WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
783         RefPtr<FunctionCodeBlock> m_codeBlockForCall;
784         RefPtr<FunctionCodeBlock> m_codeBlockForConstruct;
785     };
786
787     inline bool isHostFunction(JSValue value, NativeFunction nativeFunction)
788     {
789         JSFunction* function = jsCast<JSFunction*>(getJSFunction(value));
790         if (!function || !function->isHostFunction())
791             return false;
792         return function->nativeFunction() == nativeFunction;
793     }
794
795     inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
796     {
797         switch (executable->structure()->typeInfo().type()) {
798         case EvalExecutableType:
799             return jsCast<EvalExecutable*>(executable)->clearCode();
800         case ProgramExecutableType:
801             return jsCast<ProgramExecutable*>(executable)->clearCode();
802         case FunctionExecutableType:
803             return jsCast<FunctionExecutable*>(executable)->clearCode();
804         default:
805             return jsCast<NativeExecutable*>(executable)->clearCode();
806         }
807     }
808
809     inline void ScriptExecutable::unlinkCalls()
810     {
811         switch (structure()->typeInfo().type()) {
812         case EvalExecutableType:
813             return jsCast<EvalExecutable*>(this)->unlinkCalls();
814         case ProgramExecutableType:
815             return jsCast<ProgramExecutable*>(this)->unlinkCalls();
816         case FunctionExecutableType:
817             return jsCast<FunctionExecutable*>(this)->unlinkCalls();
818         default:
819             RELEASE_ASSERT_NOT_REACHED();
820         }
821     }
822
823 }
824
825 #endif