fourthTier: JITCode should abstract exactly how the JIT code is structured and where...
[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 "HandlerInfo.h"
33 #include "JSFunction.h"
34 #include "Interpreter.h"
35 #include "JITCode.h"
36 #include "JSGlobalObject.h"
37 #include "LLIntCLoop.h"
38 #include "SamplingTool.h"
39 #include "SourceCode.h"
40 #include "UnlinkedCodeBlock.h"
41 #include <wtf/PassOwnPtr.h>
42
43 namespace JSC {
44
45     class CodeBlock;
46     class Debugger;
47     class EvalCodeBlock;
48     class FunctionCodeBlock;
49     class LLIntOffsetsExtractor;
50     class ProgramCodeBlock;
51     class JSScope;
52     
53     enum CompilationKind { FirstCompilation, OptimizingCompilation };
54
55     inline bool isCall(CodeSpecializationKind kind)
56     {
57         if (kind == CodeForCall)
58             return true;
59         ASSERT(kind == CodeForConstruct);
60         return false;
61     }
62
63     class ExecutableBase : public JSCell, public DoublyLinkedListNode<ExecutableBase> {
64         friend class WTF::DoublyLinkedListNode<ExecutableBase>;
65         friend class JIT;
66
67     protected:
68         static const int NUM_PARAMETERS_IS_HOST = 0;
69         static const int NUM_PARAMETERS_NOT_COMPILED = -1;
70
71         ExecutableBase(VM& vm, Structure* structure, int numParameters)
72             : JSCell(vm, structure)
73             , m_numParametersForCall(numParameters)
74             , m_numParametersForConstruct(numParameters)
75         {
76         }
77
78         void finishCreation(VM& vm)
79         {
80             Base::finishCreation(vm);
81         }
82
83     public:
84         typedef JSCell Base;
85
86 #if ENABLE(JIT)
87         static const bool needsDestruction = true;
88         static const bool hasImmortalStructure = true;
89         static void destroy(JSCell*);
90 #endif
91         
92         CodeBlockHash hashFor(CodeSpecializationKind) const;
93
94         bool isFunctionExecutable()
95         {
96             return structure()->typeInfo().type() == FunctionExecutableType;
97         }
98
99         bool isHostFunction() const
100         {
101             ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
102             return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
103         }
104
105         static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); }
106         
107         void clearCode();
108
109         static JS_EXPORTDATA const ClassInfo s_info;
110
111     protected:
112         static const unsigned StructureFlags = 0;
113         int m_numParametersForCall;
114         int m_numParametersForConstruct;
115
116     public:
117         static void clearCodeVirtual(ExecutableBase*);
118
119 #if ENABLE(JIT)
120         PassRefPtr<JITCode> generatedJITCodeForCall()
121         {
122             ASSERT(m_jitCodeForCall);
123             return m_jitCodeForCall;
124         }
125
126         PassRefPtr<JITCode> generatedJITCodeForConstruct()
127         {
128             ASSERT(m_jitCodeForConstruct);
129             return m_jitCodeForConstruct;
130         }
131         
132         PassRefPtr<JITCode> generatedJITCodeFor(CodeSpecializationKind kind)
133         {
134             if (kind == CodeForCall)
135                 return generatedJITCodeForCall();
136             ASSERT(kind == CodeForConstruct);
137             return generatedJITCodeForConstruct();
138         }
139
140         MacroAssemblerCodePtr generatedJITCodeForCallWithArityCheck()
141         {
142             ASSERT(m_jitCodeForCall);
143             ASSERT(m_jitCodeForCallWithArityCheck);
144             return m_jitCodeForCallWithArityCheck;
145         }
146
147         MacroAssemblerCodePtr generatedJITCodeForConstructWithArityCheck()
148         {
149             ASSERT(m_jitCodeForConstruct);
150             ASSERT(m_jitCodeForConstructWithArityCheck);
151             return m_jitCodeForConstructWithArityCheck;
152         }
153         
154         MacroAssemblerCodePtr generatedJITCodeWithArityCheckFor(CodeSpecializationKind kind)
155         {
156             if (kind == CodeForCall)
157                 return generatedJITCodeForCallWithArityCheck();
158             ASSERT(kind == CodeForConstruct);
159             return generatedJITCodeForConstructWithArityCheck();
160         }
161         
162         bool hasJITCodeForCall() const
163         {
164             return m_numParametersForCall >= 0;
165         }
166         
167         bool hasJITCodeForConstruct() const
168         {
169             return m_numParametersForConstruct >= 0;
170         }
171         
172         bool hasJITCodeFor(CodeSpecializationKind kind) const
173         {
174             if (kind == CodeForCall)
175                 return hasJITCodeForCall();
176             ASSERT(kind == CodeForConstruct);
177             return hasJITCodeForConstruct();
178         }
179
180         static ptrdiff_t offsetOfJITCodeWithArityCheckFor(CodeSpecializationKind kind)
181         {
182             if (kind == CodeForCall)
183                 return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
184             ASSERT(kind == CodeForConstruct);
185             return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
186         }
187         
188         static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind)
189         {
190             if (kind == CodeForCall)
191                 return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall);
192             ASSERT(kind == CodeForConstruct);
193             return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct);
194         }
195 #endif // ENABLE(JIT)
196
197         // Intrinsics are only for calls, currently.
198         Intrinsic intrinsic() const;
199         
200         Intrinsic intrinsicFor(CodeSpecializationKind kind) const
201         {
202             if (isCall(kind))
203                 return intrinsic();
204             return NoIntrinsic;
205         }
206         
207 #if ENABLE(JIT) || ENABLE(LLINT_C_LOOP)
208         MacroAssemblerCodePtr hostCodeEntryFor(CodeSpecializationKind kind)
209         {
210 #if ENABLE(JIT)
211             return generatedJITCodeFor(kind)->addressForCall();
212 #else
213             return LLInt::CLoop::hostCodeEntryFor(kind);
214 #endif
215         }
216
217         MacroAssemblerCodePtr jsCodeEntryFor(CodeSpecializationKind kind)
218         {
219 #if ENABLE(JIT)
220             return generatedJITCodeFor(kind)->addressForCall();
221 #else
222             return LLInt::CLoop::jsCodeEntryFor(kind);
223 #endif
224         }
225
226         MacroAssemblerCodePtr jsCodeWithArityCheckEntryFor(CodeSpecializationKind kind)
227         {
228 #if ENABLE(JIT)
229             return generatedJITCodeWithArityCheckFor(kind);
230 #else
231             return LLInt::CLoop::jsCodeEntryWithArityCheckFor(kind);
232 #endif
233         }
234
235         static void* catchRoutineFor(HandlerInfo* handler, Instruction* catchPCForInterpreter)
236         {
237             #if ENABLE(JIT)
238             UNUSED_PARAM(catchPCForInterpreter);
239             return handler->nativeCode.executableAddress();
240             #else
241             UNUSED_PARAM(handler);
242             return LLInt::CLoop::catchRoutineFor(catchPCForInterpreter);
243             #endif
244         }
245 #endif // ENABLE(JIT || ENABLE(LLINT_C_LOOP)
246
247     protected:
248         ExecutableBase* m_prev;
249         ExecutableBase* m_next;
250
251 #if ENABLE(JIT)
252         RefPtr<JITCode> m_jitCodeForCall;
253         RefPtr<JITCode> m_jitCodeForConstruct;
254         MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
255         MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
256 #endif
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), &s_info); }
316         
317         static const ClassInfo s_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         {
357         }
358
359         ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
360             : ExecutableBase(exec->vm(), structure, NUM_PARAMETERS_NOT_COMPILED)
361             , m_source(source)
362             , m_features(isInStrictContext ? StrictModeFeature : 0)
363         {
364         }
365
366 #if ENABLE(JIT)
367         static void destroy(JSCell*);
368 #endif
369         
370         CodeBlockHash hashFor(CodeSpecializationKind) const;
371
372         const SourceCode& source() const { return m_source; }
373         intptr_t sourceID() const { return m_source.providerID(); }
374         const String& sourceURL() const { return m_source.provider()->url(); }
375         int lineNo() const { return m_firstLine; }
376         int lastLine() const { return m_lastLine; }
377         unsigned startColumn() const { return m_startColumn; }
378
379         bool usesEval() const { return m_features & EvalFeature; }
380         bool usesArguments() const { return m_features & ArgumentsFeature; }
381         bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
382         bool isStrictMode() const { return m_features & StrictModeFeature; }
383
384         void unlinkCalls();
385
386         CodeFeatures features() const { return m_features; }
387         
388         static const ClassInfo s_info;
389
390         void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn)
391         {
392             m_features = features;
393             m_hasCapturedVariables = hasCapturedVariables;
394             m_firstLine = firstLine;
395             m_lastLine = lastLine;
396             m_startColumn = startColumn;
397         }
398
399     protected:
400         void finishCreation(VM& vm)
401         {
402             Base::finishCreation(vm);
403             vm.heap.addCompiledCode(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
404
405 #if ENABLE(CODEBLOCK_SAMPLING)
406             if (SamplingTool* sampler = vm.interpreter->sampler())
407                 sampler->notifyOfScope(vm, this);
408 #endif
409         }
410
411         SourceCode m_source;
412         CodeFeatures m_features;
413         bool m_hasCapturedVariables;
414         int m_firstLine;
415         int m_lastLine;
416         unsigned m_startColumn;
417     };
418
419     class EvalExecutable : public ScriptExecutable {
420         friend class LLIntOffsetsExtractor;
421     public:
422         typedef ScriptExecutable Base;
423
424         static void destroy(JSCell*);
425
426         JSObject* compile(ExecState* exec, JSScope* scope)
427         {
428             RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
429             JSObject* error = 0;
430             if (!m_evalCodeBlock)
431                 error = compileInternal(exec, scope, JITCode::bottomTierJIT());
432             ASSERT(!error == !!m_evalCodeBlock);
433             return error;
434         }
435         
436         JSObject* compileOptimized(ExecState*, JSScope*, unsigned bytecodeIndex);
437         
438 #if ENABLE(JIT)
439         void jettisonOptimizedCode(VM&);
440         bool jitCompile(ExecState*);
441 #endif
442
443         EvalCodeBlock& generatedBytecode()
444         {
445             ASSERT(m_evalCodeBlock);
446             return *m_evalCodeBlock;
447         }
448
449         static EvalExecutable* create(ExecState* exec, PassRefPtr<CodeCache> cache, const SourceCode& source, bool isInStrictContext)
450         {
451             EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, cache, source, isInStrictContext);
452             executable->finishCreation(exec->vm());
453             return executable;
454         }
455
456 #if ENABLE(JIT)
457         PassRefPtr<JITCode> generatedJITCode()
458         {
459             return generatedJITCodeForCall();
460         }
461 #endif
462         static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
463         {
464             return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), &s_info);
465         }
466         
467         static const ClassInfo s_info;
468
469         void unlinkCalls();
470
471         void clearCode();
472
473         ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
474
475     private:
476         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
477         EvalExecutable(ExecState*, PassRefPtr<CodeCache>, const SourceCode&, bool);
478
479         JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
480         static void visitChildren(JSCell*, SlotVisitor&);
481
482         OwnPtr<EvalCodeBlock> m_evalCodeBlock;
483         WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
484         RefPtr<CodeCache> m_codeCache;
485     };
486
487     class ProgramExecutable : public ScriptExecutable {
488         friend class LLIntOffsetsExtractor;
489     public:
490         typedef ScriptExecutable Base;
491
492         static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
493         {
494             ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
495             executable->finishCreation(exec->vm());
496             return executable;
497         }
498
499
500         JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
501
502         static void destroy(JSCell*);
503
504         JSObject* compile(ExecState* exec, JSScope* scope)
505         {
506             RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
507             JSObject* error = 0;
508             if (!m_programCodeBlock)
509                 error = compileInternal(exec, scope, JITCode::bottomTierJIT());
510             ASSERT(!error == !!m_programCodeBlock);
511             return error;
512         }
513
514         JSObject* compileOptimized(ExecState*, JSScope*, unsigned bytecodeIndex);
515         
516 #if ENABLE(JIT)
517         void jettisonOptimizedCode(VM&);
518         bool jitCompile(ExecState*);
519 #endif
520
521         ProgramCodeBlock& generatedBytecode()
522         {
523             ASSERT(m_programCodeBlock);
524             return *m_programCodeBlock;
525         }
526
527         JSObject* checkSyntax(ExecState*);
528
529 #if ENABLE(JIT)
530         PassRefPtr<JITCode> generatedJITCode()
531         {
532             return generatedJITCodeForCall();
533         }
534 #endif
535         
536         static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
537         {
538             return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), &s_info);
539         }
540         
541         static const ClassInfo s_info;
542         
543         void unlinkCalls();
544
545         void clearCode();
546
547         ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
548
549     private:
550         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
551
552         ProgramExecutable(ExecState*, const SourceCode&);
553
554         enum ConstantMode { IsConstant, IsVariable };
555         enum FunctionMode { IsFunctionToSpecialize, NotFunctionOrNotSpecializable };
556         int addGlobalVar(JSGlobalObject*, const Identifier&, ConstantMode, FunctionMode);
557
558         JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
559         static void visitChildren(JSCell*, SlotVisitor&);
560
561         WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
562         OwnPtr<ProgramCodeBlock> m_programCodeBlock;
563     };
564
565     class FunctionExecutable : public ScriptExecutable {
566         friend class JIT;
567         friend class LLIntOffsetsExtractor;
568     public:
569         typedef ScriptExecutable Base;
570
571         static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn)
572         {
573             FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn);
574             executable->finishCreation(vm);
575             return executable;
576         }
577         static FunctionExecutable* fromGlobalCode(const Identifier& name, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
578
579         static void destroy(JSCell*);
580         
581         UnlinkedFunctionExecutable* unlinkedExecutable()
582         {
583             return m_unlinkedExecutable.get();
584         }
585
586         // Returns either call or construct bytecode. This can be appropriate
587         // for answering questions that that don't vary between call and construct --
588         // for example, argumentsRegister().
589         FunctionCodeBlock& generatedBytecode()
590         {
591             if (m_codeBlockForCall)
592                 return *m_codeBlockForCall;
593             ASSERT(m_codeBlockForConstruct);
594             return *m_codeBlockForConstruct;
595         }
596         
597         PassOwnPtr<FunctionCodeBlock> produceCodeBlockFor(JSScope*, CodeSpecializationKind, JSObject*& exception);
598
599         JSObject* compileForCall(ExecState* exec, JSScope* scope)
600         {
601             RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
602             JSObject* error = 0;
603             if (!m_codeBlockForCall)
604                 error = compileForCallInternal(exec, scope, JITCode::bottomTierJIT());
605             ASSERT(!error == !!m_codeBlockForCall);
606             return error;
607         }
608
609         JSObject* compileOptimizedForCall(ExecState*, JSScope*, unsigned bytecodeIndex);
610         
611 #if ENABLE(JIT)
612         void jettisonOptimizedCodeForCall(VM&);
613         bool jitCompileForCall(ExecState*);
614 #endif
615
616         bool isGeneratedForCall() const
617         {
618             return m_codeBlockForCall;
619         }
620
621         FunctionCodeBlock& generatedBytecodeForCall()
622         {
623             ASSERT(m_codeBlockForCall);
624             return *m_codeBlockForCall;
625         }
626
627         JSObject* compileForConstruct(ExecState* exec, JSScope* scope)
628         {
629             RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
630             JSObject* error = 0;
631             if (!m_codeBlockForConstruct)
632                 error = compileForConstructInternal(exec, scope, JITCode::bottomTierJIT());
633             ASSERT(!error == !!m_codeBlockForConstruct);
634             return error;
635         }
636
637         JSObject* compileOptimizedForConstruct(ExecState*, JSScope*, unsigned bytecodeIndex);
638         
639 #if ENABLE(JIT)
640         void jettisonOptimizedCodeForConstruct(VM&);
641         bool jitCompileForConstruct(ExecState*);
642 #endif
643
644         bool isGeneratedForConstruct() const
645         {
646             return m_codeBlockForConstruct;
647         }
648
649         FunctionCodeBlock& generatedBytecodeForConstruct()
650         {
651             ASSERT(m_codeBlockForConstruct);
652             return *m_codeBlockForConstruct;
653         }
654         
655         JSObject* compileFor(ExecState* exec, JSScope* scope, CodeSpecializationKind kind)
656         {
657             ASSERT(exec->callee());
658             ASSERT(exec->callee()->inherits(&JSFunction::s_info));
659             ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this);
660
661             if (kind == CodeForCall)
662                 return compileForCall(exec, scope);
663             ASSERT(kind == CodeForConstruct);
664             return compileForConstruct(exec, scope);
665         }
666         
667         JSObject* compileOptimizedFor(ExecState* exec, JSScope* scope, unsigned bytecodeIndex, CodeSpecializationKind kind)
668         {
669             ASSERT(exec->callee());
670             ASSERT(exec->callee()->inherits(&JSFunction::s_info));
671             ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this);
672             
673             if (kind == CodeForCall)
674                 return compileOptimizedForCall(exec, scope, bytecodeIndex);
675             ASSERT(kind == CodeForConstruct);
676             return compileOptimizedForConstruct(exec, scope, bytecodeIndex);
677         }
678         
679 #if ENABLE(JIT)
680         void jettisonOptimizedCodeFor(VM& vm, CodeSpecializationKind kind)
681         {
682             if (kind == CodeForCall) 
683                 jettisonOptimizedCodeForCall(vm);
684             else {
685                 ASSERT(kind == CodeForConstruct);
686                 jettisonOptimizedCodeForConstruct(vm);
687             }
688         }
689         
690         bool jitCompileFor(ExecState* exec, CodeSpecializationKind kind)
691         {
692             if (kind == CodeForCall)
693                 return jitCompileForCall(exec);
694             ASSERT(kind == CodeForConstruct);
695             return jitCompileForConstruct(exec);
696         }
697 #endif
698         
699         bool isGeneratedFor(CodeSpecializationKind kind)
700         {
701             if (kind == CodeForCall)
702                 return isGeneratedForCall();
703             ASSERT(kind == CodeForConstruct);
704             return isGeneratedForConstruct();
705         }
706         
707         FunctionCodeBlock& generatedBytecodeFor(CodeSpecializationKind kind)
708         {
709             if (kind == CodeForCall)
710                 return generatedBytecodeForCall();
711             ASSERT(kind == CodeForConstruct);
712             return generatedBytecodeForConstruct();
713         }
714
715         FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
716         
717         FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
718         {
719             return baselineCodeBlockFor(kind);
720         }
721         
722         const Identifier& name() { return m_unlinkedExecutable->name(); }
723         const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
724         JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
725         size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
726         String paramString() const;
727         SharedSymbolTable* symbolTable(CodeSpecializationKind kind) const { return m_unlinkedExecutable->symbolTable(kind); }
728
729         void clearCodeIfNotCompiling();
730         void clearUnlinkedCodeForRecompilationIfNotCompiling();
731         static void visitChildren(JSCell*, SlotVisitor&);
732         static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
733         {
734             return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), &s_info);
735         }
736         
737         static const ClassInfo s_info;
738         
739         void unlinkCalls();
740
741         void clearCode();
742
743     private:
744         FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn);
745
746         JSObject* compileForCallInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
747         JSObject* compileForConstructInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
748         
749         OwnPtr<FunctionCodeBlock>& codeBlockFor(CodeSpecializationKind kind)
750         {
751             if (kind == CodeForCall)
752                 return m_codeBlockForCall;
753             ASSERT(kind == CodeForConstruct);
754             return m_codeBlockForConstruct;
755         }
756  
757         bool isCompiling()
758         {
759 #if ENABLE(JIT)
760             if (!m_jitCodeForCall && m_codeBlockForCall)
761                 return true;
762             if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
763                 return true;
764 #endif
765             return false;
766         }
767
768         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
769         WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
770         OwnPtr<FunctionCodeBlock> m_codeBlockForCall;
771         OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct;
772     };
773
774     inline JSFunction::JSFunction(VM& vm, FunctionExecutable* executable, JSScope* scope)
775         : Base(vm, scope->globalObject()->functionStructure())
776         , m_executable(vm, this, executable)
777         , m_scope(vm, this, scope)
778         , m_allocationProfileWatchpoint(InitializedBlind) // See comment in JSFunction.cpp concerning the reason for using InitializedBlind as opposed to InitializedWatching.
779     {
780     }
781
782     inline FunctionExecutable* JSFunction::jsExecutable() const
783     {
784         ASSERT(!isHostFunctionNonInline());
785         return static_cast<FunctionExecutable*>(m_executable.get());
786     }
787
788     inline bool JSFunction::isHostFunction() const
789     {
790         ASSERT(m_executable);
791         return m_executable->isHostFunction();
792     }
793
794     inline NativeFunction JSFunction::nativeFunction()
795     {
796         ASSERT(isHostFunction());
797         return static_cast<NativeExecutable*>(m_executable.get())->function();
798     }
799
800     inline NativeFunction JSFunction::nativeConstructor()
801     {
802         ASSERT(isHostFunction());
803         return static_cast<NativeExecutable*>(m_executable.get())->constructor();
804     }
805
806     inline bool isHostFunction(JSValue value, NativeFunction nativeFunction)
807     {
808         JSFunction* function = jsCast<JSFunction*>(getJSFunction(value));
809         if (!function || !function->isHostFunction())
810             return false;
811         return function->nativeFunction() == nativeFunction;
812     }
813
814     inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
815     {
816         switch (executable->structure()->typeInfo().type()) {
817         case EvalExecutableType:
818             return jsCast<EvalExecutable*>(executable)->clearCode();
819         case ProgramExecutableType:
820             return jsCast<ProgramExecutable*>(executable)->clearCode();
821         case FunctionExecutableType:
822             return jsCast<FunctionExecutable*>(executable)->clearCode();
823         default:
824             return jsCast<NativeExecutable*>(executable)->clearCode();
825         }
826     }
827
828     inline void ScriptExecutable::unlinkCalls()
829     {
830         switch (structure()->typeInfo().type()) {
831         case EvalExecutableType:
832             return jsCast<EvalExecutable*>(this)->unlinkCalls();
833         case ProgramExecutableType:
834             return jsCast<ProgramExecutable*>(this)->unlinkCalls();
835         case FunctionExecutableType:
836             return jsCast<FunctionExecutable*>(this)->unlinkCalls();
837         default:
838             RELEASE_ASSERT_NOT_REACHED();
839         }
840     }
841
842 }
843
844 #endif