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