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