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