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