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