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