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