fourthTier: Recursive deadlock in DFG::ByteCodeParser
[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             , m_neverInline(false)
359         {
360         }
361
362         ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
363             : ExecutableBase(exec->vm(), structure, NUM_PARAMETERS_NOT_COMPILED)
364             , m_source(source)
365             , m_features(isInStrictContext ? StrictModeFeature : 0)
366             , m_neverInline(false)
367         {
368         }
369
370 #if ENABLE(JIT)
371         static void destroy(JSCell*);
372 #endif
373         
374         CodeBlockHash hashFor(CodeSpecializationKind) const;
375
376         const SourceCode& source() const { return m_source; }
377         intptr_t sourceID() const { return m_source.providerID(); }
378         const String& sourceURL() const { return m_source.provider()->url(); }
379         int lineNo() const { return m_firstLine; }
380         int lastLine() const { return m_lastLine; }
381         unsigned startColumn() const { return m_startColumn; }
382
383         bool usesEval() const { return m_features & EvalFeature; }
384         bool usesArguments() const { return m_features & ArgumentsFeature; }
385         bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
386         bool isStrictMode() const { return m_features & StrictModeFeature; }
387         
388         void setNeverInline(bool value) { m_neverInline = value; }
389         bool neverInline() const { return m_neverInline; }
390         bool isInliningCandidate() const { return !neverInline(); }
391
392         void unlinkCalls();
393         
394         CodeFeatures features() const { return m_features; }
395         
396         static const ClassInfo s_info;
397
398         void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn)
399         {
400             m_features = features;
401             m_hasCapturedVariables = hasCapturedVariables;
402             m_firstLine = firstLine;
403             m_lastLine = lastLine;
404             m_startColumn = startColumn;
405         }
406
407     protected:
408         void finishCreation(VM& vm)
409         {
410             Base::finishCreation(vm);
411             vm.heap.addCompiledCode(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
412
413 #if ENABLE(CODEBLOCK_SAMPLING)
414             if (SamplingTool* sampler = vm.interpreter->sampler())
415                 sampler->notifyOfScope(vm, this);
416 #endif
417         }
418
419         SourceCode m_source;
420         CodeFeatures m_features;
421         bool m_hasCapturedVariables;
422         bool m_neverInline;
423         int m_firstLine;
424         int m_lastLine;
425         unsigned m_startColumn;
426     };
427
428     class EvalExecutable : public ScriptExecutable {
429         friend class LLIntOffsetsExtractor;
430     public:
431         typedef ScriptExecutable Base;
432
433         static void destroy(JSCell*);
434
435         JSObject* compile(ExecState* exec, JSScope* scope)
436         {
437             RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
438             JSObject* error = 0;
439             if (!m_evalCodeBlock)
440                 error = compileInternal(exec, scope, JITCode::bottomTierJIT());
441             ASSERT(!error == !!m_evalCodeBlock);
442             return error;
443         }
444         
445 #if ENABLE(DFG_JIT)
446         JSObject* compileOptimized(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
447         CompilationResult replaceWithDeferredOptimizedCode(PassRefPtr<DFG::Plan>);
448 #endif // ENABLE(DFG_JIT)
449         
450 #if ENABLE(JIT)
451         void jettisonOptimizedCode(VM&);
452         CompilationResult jitCompile(ExecState*);
453 #endif
454
455         EvalCodeBlock& generatedBytecode()
456         {
457             ASSERT(m_evalCodeBlock);
458             return *m_evalCodeBlock;
459         }
460
461         static EvalExecutable* create(ExecState* exec, PassRefPtr<CodeCache> cache, const SourceCode& source, bool isInStrictContext)
462         {
463             EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, cache, source, isInStrictContext);
464             executable->finishCreation(exec->vm());
465             return executable;
466         }
467
468 #if ENABLE(JIT)
469         PassRefPtr<JITCode> generatedJITCode()
470         {
471             return generatedJITCodeForCall();
472         }
473 #endif
474         static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
475         {
476             return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), &s_info);
477         }
478         
479         static const ClassInfo s_info;
480
481         void unlinkCalls();
482
483         void clearCode();
484
485         ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
486
487     private:
488         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
489         EvalExecutable(ExecState*, PassRefPtr<CodeCache>, const SourceCode&, bool);
490
491         JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, CompilationResult* = 0, unsigned bytecodeIndex = UINT_MAX);
492         static void visitChildren(JSCell*, SlotVisitor&);
493
494         RefPtr<EvalCodeBlock> m_evalCodeBlock;
495         WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
496         RefPtr<CodeCache> m_codeCache;
497     };
498
499     class ProgramExecutable : public ScriptExecutable {
500         friend class LLIntOffsetsExtractor;
501     public:
502         typedef ScriptExecutable Base;
503
504         static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
505         {
506             ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
507             executable->finishCreation(exec->vm());
508             return executable;
509         }
510
511
512         JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
513
514         static void destroy(JSCell*);
515
516         JSObject* compile(ExecState* exec, JSScope* scope)
517         {
518             RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
519             JSObject* error = 0;
520             if (!m_programCodeBlock)
521                 error = compileInternal(exec, scope, JITCode::bottomTierJIT());
522             ASSERT(!error == !!m_programCodeBlock);
523             return error;
524         }
525
526 #if ENABLE(DFG_JIT)
527         JSObject* compileOptimized(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
528         CompilationResult replaceWithDeferredOptimizedCode(PassRefPtr<DFG::Plan>);
529 #endif // ENABLE(DFG_JIT)
530         
531 #if ENABLE(JIT)
532         void jettisonOptimizedCode(VM&);
533         CompilationResult jitCompile(ExecState*);
534 #endif
535
536         ProgramCodeBlock& generatedBytecode()
537         {
538             ASSERT(m_programCodeBlock);
539             return *m_programCodeBlock;
540         }
541
542         JSObject* checkSyntax(ExecState*);
543
544 #if ENABLE(JIT)
545         PassRefPtr<JITCode> generatedJITCode()
546         {
547             return generatedJITCodeForCall();
548         }
549 #endif
550         
551         static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
552         {
553             return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), &s_info);
554         }
555         
556         static const ClassInfo s_info;
557         
558         void unlinkCalls();
559
560         void clearCode();
561
562         ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
563
564     private:
565         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
566
567         ProgramExecutable(ExecState*, const SourceCode&);
568
569         enum ConstantMode { IsConstant, IsVariable };
570         enum FunctionMode { IsFunctionToSpecialize, NotFunctionOrNotSpecializable };
571         int addGlobalVar(JSGlobalObject*, const Identifier&, ConstantMode, FunctionMode);
572
573         JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, CompilationResult* = 0, unsigned bytecodeIndex = UINT_MAX);
574         static void visitChildren(JSCell*, SlotVisitor&);
575
576         WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
577         RefPtr<ProgramCodeBlock> m_programCodeBlock;
578     };
579
580     class FunctionExecutable : public ScriptExecutable {
581         friend class JIT;
582         friend class LLIntOffsetsExtractor;
583     public:
584         typedef ScriptExecutable Base;
585
586         static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn)
587         {
588             FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn);
589             executable->finishCreation(vm);
590             return executable;
591         }
592         static FunctionExecutable* fromGlobalCode(const Identifier& name, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
593
594         static void destroy(JSCell*);
595         
596         UnlinkedFunctionExecutable* unlinkedExecutable()
597         {
598             return m_unlinkedExecutable.get();
599         }
600
601         // Returns either call or construct bytecode. This can be appropriate
602         // for answering questions that that don't vary between call and construct --
603         // for example, argumentsRegister().
604         FunctionCodeBlock& generatedBytecode()
605         {
606             if (m_codeBlockForCall)
607                 return *m_codeBlockForCall;
608             ASSERT(m_codeBlockForConstruct);
609             return *m_codeBlockForConstruct;
610         }
611         
612         PassRefPtr<FunctionCodeBlock> produceCodeBlockFor(JSScope*, CodeSpecializationKind, JSObject*& exception);
613
614         JSObject* compileForCall(ExecState* exec, JSScope* scope)
615         {
616             RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
617             JSObject* error = 0;
618             if (!m_codeBlockForCall)
619                 error = compileForCallInternal(exec, scope, JITCode::bottomTierJIT());
620             ASSERT(!error == !!m_codeBlockForCall);
621             return error;
622         }
623
624 #if ENABLE(DFG_JIT)
625         JSObject* compileOptimizedForCall(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
626         CompilationResult replaceWithDeferredOptimizedCodeForCall(PassRefPtr<DFG::Plan>);
627 #endif // ENABLE(DFG_JIT)
628         
629 #if ENABLE(JIT)
630         void jettisonOptimizedCodeForCall(VM&);
631         CompilationResult jitCompileForCall(ExecState*);
632 #endif
633
634         bool isGeneratedForCall() const
635         {
636             return m_codeBlockForCall;
637         }
638
639         FunctionCodeBlock& generatedBytecodeForCall()
640         {
641             ASSERT(m_codeBlockForCall);
642             return *m_codeBlockForCall;
643         }
644
645         JSObject* compileForConstruct(ExecState* exec, JSScope* scope)
646         {
647             RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
648             JSObject* error = 0;
649             if (!m_codeBlockForConstruct)
650                 error = compileForConstructInternal(exec, scope, JITCode::bottomTierJIT());
651             ASSERT(!error == !!m_codeBlockForConstruct);
652             return error;
653         }
654
655 #if ENABLE(DFG_JIT)
656         JSObject* compileOptimizedForConstruct(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
657         CompilationResult replaceWithDeferredOptimizedCodeForConstruct(PassRefPtr<DFG::Plan>);
658 #endif // ENABLE(DFG_JIT)
659         
660 #if ENABLE(JIT)
661         void jettisonOptimizedCodeForConstruct(VM&);
662         CompilationResult jitCompileForConstruct(ExecState*);
663 #endif
664
665         bool isGeneratedForConstruct() const
666         {
667             return m_codeBlockForConstruct;
668         }
669
670         FunctionCodeBlock& generatedBytecodeForConstruct()
671         {
672             ASSERT(m_codeBlockForConstruct);
673             return *m_codeBlockForConstruct;
674         }
675         
676         JSObject* compileFor(ExecState* exec, JSScope* scope, CodeSpecializationKind kind)
677         {
678             ASSERT(exec->callee());
679             ASSERT(exec->callee()->inherits(&JSFunction::s_info));
680             ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this);
681
682             if (kind == CodeForCall)
683                 return compileForCall(exec, scope);
684             ASSERT(kind == CodeForConstruct);
685             return compileForConstruct(exec, scope);
686         }
687         
688 #if ENABLE(DFG_JIT)
689         JSObject* compileOptimizedFor(ExecState* exec, JSScope* scope, CompilationResult& result, unsigned bytecodeIndex, CodeSpecializationKind kind)
690         {
691             ASSERT(exec->callee());
692             ASSERT(exec->callee()->inherits(&JSFunction::s_info));
693             ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this);
694             
695             if (kind == CodeForCall)
696                 return compileOptimizedForCall(exec, scope, result, bytecodeIndex);
697             ASSERT(kind == CodeForConstruct);
698             return compileOptimizedForConstruct(exec, scope, result, bytecodeIndex);
699         }
700         
701         CompilationResult replaceWithDeferredOptimizedCodeFor(PassRefPtr<DFG::Plan> plan, CodeSpecializationKind kind)
702         {
703             if (kind == CodeForCall)
704                 return replaceWithDeferredOptimizedCodeForCall(plan);
705             return replaceWithDeferredOptimizedCodeForConstruct(plan);
706         }
707 #endif // ENABLE(DFG_JIT)
708
709 #if ENABLE(JIT)
710         void jettisonOptimizedCodeFor(VM& vm, CodeSpecializationKind kind)
711         {
712             if (kind == CodeForCall) 
713                 jettisonOptimizedCodeForCall(vm);
714             else {
715                 ASSERT(kind == CodeForConstruct);
716                 jettisonOptimizedCodeForConstruct(vm);
717             }
718         }
719         
720         CompilationResult jitCompileFor(ExecState* exec, CodeSpecializationKind kind)
721         {
722             if (kind == CodeForCall)
723                 return jitCompileForCall(exec);
724             ASSERT(kind == CodeForConstruct);
725             return jitCompileForConstruct(exec);
726         }
727 #endif
728         
729         bool isGeneratedFor(CodeSpecializationKind kind)
730         {
731             if (kind == CodeForCall)
732                 return isGeneratedForCall();
733             ASSERT(kind == CodeForConstruct);
734             return isGeneratedForConstruct();
735         }
736         
737         FunctionCodeBlock& generatedBytecodeFor(CodeSpecializationKind kind)
738         {
739             if (kind == CodeForCall)
740                 return generatedBytecodeForCall();
741             ASSERT(kind == CodeForConstruct);
742             return generatedBytecodeForConstruct();
743         }
744
745         FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
746         
747         FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
748         {
749             return baselineCodeBlockFor(kind);
750         }
751         
752         const Identifier& name() { return m_unlinkedExecutable->name(); }
753         const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
754         JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
755         size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
756         String paramString() const;
757         SharedSymbolTable* symbolTable(CodeSpecializationKind kind) const { return m_unlinkedExecutable->symbolTable(kind); }
758
759         void clearCodeIfNotCompiling();
760         void clearUnlinkedCodeForRecompilationIfNotCompiling();
761         static void visitChildren(JSCell*, SlotVisitor&);
762         static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
763         {
764             return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), &s_info);
765         }
766         
767         static const ClassInfo s_info;
768         
769         void unlinkCalls();
770
771         void clearCode();
772
773     private:
774         FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn);
775
776         JSObject* compileForCallInternal(ExecState*, JSScope*, JITCode::JITType, CompilationResult* = 0, unsigned bytecodeIndex = UINT_MAX);
777         JSObject* compileForConstructInternal(ExecState*, JSScope*, JITCode::JITType, CompilationResult* = 0, unsigned bytecodeIndex = UINT_MAX);
778         
779         RefPtr<FunctionCodeBlock>& codeBlockFor(CodeSpecializationKind kind)
780         {
781             if (kind == CodeForCall)
782                 return m_codeBlockForCall;
783             ASSERT(kind == CodeForConstruct);
784             return m_codeBlockForConstruct;
785         }
786  
787         bool isCompiling()
788         {
789 #if ENABLE(JIT)
790             if (!m_jitCodeForCall && m_codeBlockForCall)
791                 return true;
792             if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
793                 return true;
794 #endif
795             return false;
796         }
797
798         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
799         WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
800         RefPtr<FunctionCodeBlock> m_codeBlockForCall;
801         RefPtr<FunctionCodeBlock> m_codeBlockForConstruct;
802     };
803
804     inline bool isHostFunction(JSValue value, NativeFunction nativeFunction)
805     {
806         JSFunction* function = jsCast<JSFunction*>(getJSFunction(value));
807         if (!function || !function->isHostFunction())
808             return false;
809         return function->nativeFunction() == nativeFunction;
810     }
811
812     inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
813     {
814         switch (executable->structure()->typeInfo().type()) {
815         case EvalExecutableType:
816             return jsCast<EvalExecutable*>(executable)->clearCode();
817         case ProgramExecutableType:
818             return jsCast<ProgramExecutable*>(executable)->clearCode();
819         case FunctionExecutableType:
820             return jsCast<FunctionExecutable*>(executable)->clearCode();
821         default:
822             return jsCast<NativeExecutable*>(executable)->clearCode();
823         }
824     }
825
826     inline void ScriptExecutable::unlinkCalls()
827     {
828         switch (structure()->typeInfo().type()) {
829         case EvalExecutableType:
830             return jsCast<EvalExecutable*>(this)->unlinkCalls();
831         case ProgramExecutableType:
832             return jsCast<ProgramExecutable*>(this)->unlinkCalls();
833         case FunctionExecutableType:
834             return jsCast<FunctionExecutable*>(this)->unlinkCalls();
835         default:
836             RELEASE_ASSERT_NOT_REACHED();
837         }
838     }
839
840 }
841
842 #endif