2 * Copyright (C) 2009, 2010, 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
30 #include "CodeBlockHash.h"
31 #include "CodeSpecializationKind.h"
32 #include "HandlerInfo.h"
33 #include "JSFunction.h"
34 #include "Interpreter.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>
48 class FunctionCodeBlock
;
49 class LLIntOffsetsExtractor
;
50 class ProgramCodeBlock
;
53 enum CompilationKind
{ FirstCompilation
, OptimizingCompilation
};
55 inline bool isCall(CodeSpecializationKind kind
)
57 if (kind
== CodeForCall
)
59 ASSERT(kind
== CodeForConstruct
);
63 class ExecutableBase
: public JSCell
, public DoublyLinkedListNode
<ExecutableBase
> {
64 friend class WTF::DoublyLinkedListNode
<ExecutableBase
>;
68 static const int NUM_PARAMETERS_IS_HOST
= 0;
69 static const int NUM_PARAMETERS_NOT_COMPILED
= -1;
71 ExecutableBase(VM
& vm
, Structure
* structure
, int numParameters
)
72 : JSCell(vm
, structure
)
73 , m_numParametersForCall(numParameters
)
74 , m_numParametersForConstruct(numParameters
)
78 void finishCreation(VM
& vm
)
80 Base::finishCreation(vm
);
87 static const bool needsDestruction
= true;
88 static const bool hasImmortalStructure
= true;
89 static void destroy(JSCell
*);
92 CodeBlockHash
hashFor(CodeSpecializationKind
) const;
94 bool isFunctionExecutable()
96 return structure()->typeInfo().type() == FunctionExecutableType
;
99 bool isHostFunction() const
101 ASSERT((m_numParametersForCall
== NUM_PARAMETERS_IS_HOST
) == (m_numParametersForConstruct
== NUM_PARAMETERS_IS_HOST
));
102 return m_numParametersForCall
== NUM_PARAMETERS_IS_HOST
;
105 static Structure
* createStructure(VM
& vm
, JSGlobalObject
* globalObject
, JSValue proto
) { return Structure::create(vm
, globalObject
, proto
, TypeInfo(CompoundType
, StructureFlags
), &s_info
); }
109 static JS_EXPORTDATA
const ClassInfo s_info
;
112 static const unsigned StructureFlags
= 0;
113 int m_numParametersForCall
;
114 int m_numParametersForConstruct
;
117 static void clearCodeVirtual(ExecutableBase
*);
120 JITCode
& generatedJITCodeForCall()
122 ASSERT(m_jitCodeForCall
);
123 return m_jitCodeForCall
;
126 JITCode
& generatedJITCodeForConstruct()
128 ASSERT(m_jitCodeForConstruct
);
129 return m_jitCodeForConstruct
;
132 JITCode
& generatedJITCodeFor(CodeSpecializationKind kind
)
134 if (kind
== CodeForCall
)
135 return generatedJITCodeForCall();
136 ASSERT(kind
== CodeForConstruct
);
137 return generatedJITCodeForConstruct();
140 MacroAssemblerCodePtr
generatedJITCodeForCallWithArityCheck()
142 ASSERT(m_jitCodeForCall
);
143 ASSERT(m_jitCodeForCallWithArityCheck
);
144 return m_jitCodeForCallWithArityCheck
;
147 MacroAssemblerCodePtr
generatedJITCodeForConstructWithArityCheck()
149 ASSERT(m_jitCodeForConstruct
);
150 ASSERT(m_jitCodeForConstructWithArityCheck
);
151 return m_jitCodeForConstructWithArityCheck
;
154 MacroAssemblerCodePtr
generatedJITCodeWithArityCheckFor(CodeSpecializationKind kind
)
156 if (kind
== CodeForCall
)
157 return generatedJITCodeForCallWithArityCheck();
158 ASSERT(kind
== CodeForConstruct
);
159 return generatedJITCodeForConstructWithArityCheck();
162 bool hasJITCodeForCall() const
164 return m_numParametersForCall
>= 0;
167 bool hasJITCodeForConstruct() const
169 return m_numParametersForConstruct
>= 0;
172 bool hasJITCodeFor(CodeSpecializationKind kind
) const
174 if (kind
== CodeForCall
)
175 return hasJITCodeForCall();
176 ASSERT(kind
== CodeForConstruct
);
177 return hasJITCodeForConstruct();
180 static ptrdiff_t offsetOfJITCodeFor(CodeSpecializationKind kind
)
182 if (kind
== CodeForCall
)
183 return OBJECT_OFFSETOF(ExecutableBase
, m_jitCodeForCall
);
184 ASSERT(kind
== CodeForConstruct
);
185 return OBJECT_OFFSETOF(ExecutableBase
, m_jitCodeForConstruct
);
188 static ptrdiff_t offsetOfJITCodeWithArityCheckFor(CodeSpecializationKind kind
)
190 if (kind
== CodeForCall
)
191 return OBJECT_OFFSETOF(ExecutableBase
, m_jitCodeForCallWithArityCheck
);
192 ASSERT(kind
== CodeForConstruct
);
193 return OBJECT_OFFSETOF(ExecutableBase
, m_jitCodeForConstructWithArityCheck
);
196 static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind
)
198 if (kind
== CodeForCall
)
199 return OBJECT_OFFSETOF(ExecutableBase
, m_numParametersForCall
);
200 ASSERT(kind
== CodeForConstruct
);
201 return OBJECT_OFFSETOF(ExecutableBase
, m_numParametersForConstruct
);
203 #endif // ENABLE(JIT)
205 // Intrinsics are only for calls, currently.
206 Intrinsic
intrinsic() const;
208 Intrinsic
intrinsicFor(CodeSpecializationKind kind
) const
215 #if ENABLE(JIT) || ENABLE(LLINT_C_LOOP)
216 MacroAssemblerCodePtr
hostCodeEntryFor(CodeSpecializationKind kind
)
219 return generatedJITCodeFor(kind
).addressForCall();
221 return LLInt::CLoop::hostCodeEntryFor(kind
);
225 MacroAssemblerCodePtr
jsCodeEntryFor(CodeSpecializationKind kind
)
228 return generatedJITCodeFor(kind
).addressForCall();
230 return LLInt::CLoop::jsCodeEntryFor(kind
);
234 MacroAssemblerCodePtr
jsCodeWithArityCheckEntryFor(CodeSpecializationKind kind
)
237 return generatedJITCodeWithArityCheckFor(kind
);
239 return LLInt::CLoop::jsCodeEntryWithArityCheckFor(kind
);
243 static void* catchRoutineFor(HandlerInfo
* handler
, Instruction
* catchPCForInterpreter
)
246 UNUSED_PARAM(catchPCForInterpreter
);
247 return handler
->nativeCode
.executableAddress();
249 UNUSED_PARAM(handler
);
250 return LLInt::CLoop::catchRoutineFor(catchPCForInterpreter
);
253 #endif // ENABLE(JIT || ENABLE(LLINT_C_LOOP)
256 ExecutableBase
* m_prev
;
257 ExecutableBase
* m_next
;
260 JITCode m_jitCodeForCall
;
261 JITCode m_jitCodeForConstruct
;
262 MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck
;
263 MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck
;
267 class NativeExecutable
: public ExecutableBase
{
269 friend class LLIntOffsetsExtractor
;
271 typedef ExecutableBase Base
;
274 static NativeExecutable
* create(VM
& vm
, MacroAssemblerCodeRef callThunk
, NativeFunction function
, MacroAssemblerCodeRef constructThunk
, NativeFunction constructor
, Intrinsic intrinsic
)
276 NativeExecutable
* executable
;
278 executable
= new (NotNull
, allocateCell
<NativeExecutable
>(vm
.heap
)) NativeExecutable(vm
, function
, constructor
);
279 executable
->finishCreation(vm
, JITCode(), JITCode(), intrinsic
);
281 executable
= new (NotNull
, allocateCell
<NativeExecutable
>(vm
.heap
)) NativeExecutable(vm
, function
, constructor
);
282 executable
->finishCreation(vm
, JITCode::HostFunction(callThunk
), JITCode::HostFunction(constructThunk
), intrinsic
);
288 #if ENABLE(LLINT_C_LOOP)
289 static NativeExecutable
* create(VM
& vm
, NativeFunction function
, NativeFunction constructor
)
291 ASSERT(!vm
.canUseJIT());
292 NativeExecutable
* executable
= new (NotNull
, allocateCell
<NativeExecutable
>(vm
.heap
)) NativeExecutable(vm
, function
, constructor
);
293 executable
->finishCreation(vm
);
299 static void destroy(JSCell
*);
302 CodeBlockHash
hashFor(CodeSpecializationKind
) const;
304 NativeFunction
function() { return m_function
; }
305 NativeFunction
constructor() { return m_constructor
; }
307 NativeFunction
nativeFunctionFor(CodeSpecializationKind kind
)
309 if (kind
== CodeForCall
)
311 ASSERT(kind
== CodeForConstruct
);
312 return constructor();
315 static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind
)
317 if (kind
== CodeForCall
)
318 return OBJECT_OFFSETOF(NativeExecutable
, m_function
);
319 ASSERT(kind
== CodeForConstruct
);
320 return OBJECT_OFFSETOF(NativeExecutable
, m_constructor
);
323 static Structure
* createStructure(VM
& vm
, JSGlobalObject
* globalObject
, JSValue proto
) { return Structure::create(vm
, globalObject
, proto
, TypeInfo(LeafType
, StructureFlags
), &s_info
); }
325 static const ClassInfo s_info
;
327 Intrinsic
intrinsic() const;
331 void finishCreation(VM
& vm
, JITCode callThunk
, JITCode constructThunk
, Intrinsic intrinsic
)
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
;
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
)
350 NativeFunction m_function
;
351 NativeFunction m_constructor
;
353 Intrinsic m_intrinsic
;
356 class ScriptExecutable
: public ExecutableBase
{
358 typedef ExecutableBase Base
;
360 ScriptExecutable(Structure
* structure
, VM
& vm
, const SourceCode
& source
, bool isInStrictContext
)
361 : ExecutableBase(vm
, structure
, NUM_PARAMETERS_NOT_COMPILED
)
363 , m_features(isInStrictContext
? StrictModeFeature
: 0)
367 ScriptExecutable(Structure
* structure
, ExecState
* exec
, const SourceCode
& source
, bool isInStrictContext
)
368 : ExecutableBase(exec
->vm(), structure
, NUM_PARAMETERS_NOT_COMPILED
)
370 , m_features(isInStrictContext
? StrictModeFeature
: 0)
375 static void destroy(JSCell
*);
378 CodeBlockHash
hashFor(CodeSpecializationKind
) const;
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
; }
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
; }
394 CodeFeatures
features() const { return m_features
; }
396 static const ClassInfo s_info
;
398 void recordParse(CodeFeatures features
, bool hasCapturedVariables
, int firstLine
, int lastLine
, unsigned startColumn
)
400 m_features
= features
;
401 m_hasCapturedVariables
= hasCapturedVariables
;
402 m_firstLine
= firstLine
;
403 m_lastLine
= lastLine
;
404 m_startColumn
= startColumn
;
408 void finishCreation(VM
& vm
)
410 Base::finishCreation(vm
);
411 vm
.heap
.addCompiledCode(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
413 #if ENABLE(CODEBLOCK_SAMPLING)
414 if (SamplingTool
* sampler
= vm
.interpreter
->sampler())
415 sampler
->notifyOfScope(vm
, this);
420 CodeFeatures m_features
;
421 bool m_hasCapturedVariables
;
424 unsigned m_startColumn
;
427 class EvalExecutable
: public ScriptExecutable
{
428 friend class LLIntOffsetsExtractor
;
430 typedef ScriptExecutable Base
;
432 static void destroy(JSCell
*);
434 JSObject
* compile(ExecState
* exec
, JSScope
* scope
)
436 RELEASE_ASSERT(exec
->vm().dynamicGlobalObject
);
438 if (!m_evalCodeBlock
)
439 error
= compileInternal(exec
, scope
, JITCode::bottomTierJIT());
440 ASSERT(!error
== !!m_evalCodeBlock
);
444 JSObject
* compileOptimized(ExecState
*, JSScope
*, unsigned bytecodeIndex
);
447 void jettisonOptimizedCode(VM
&);
448 bool jitCompile(ExecState
*);
451 EvalCodeBlock
& generatedBytecode()
453 ASSERT(m_evalCodeBlock
);
454 return *m_evalCodeBlock
;
457 static EvalExecutable
* create(ExecState
* exec
, PassRefPtr
<CodeCache
> cache
, const SourceCode
& source
, bool isInStrictContext
)
459 EvalExecutable
* executable
= new (NotNull
, allocateCell
<EvalExecutable
>(*exec
->heap())) EvalExecutable(exec
, cache
, source
, isInStrictContext
);
460 executable
->finishCreation(exec
->vm());
465 JITCode
& generatedJITCode()
467 return generatedJITCodeForCall();
470 static Structure
* createStructure(VM
& vm
, JSGlobalObject
* globalObject
, JSValue proto
)
472 return Structure::create(vm
, globalObject
, proto
, TypeInfo(EvalExecutableType
, StructureFlags
), &s_info
);
475 static const ClassInfo s_info
;
481 ExecutableInfo
executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
484 static const unsigned StructureFlags
= OverridesVisitChildren
| ScriptExecutable::StructureFlags
;
485 EvalExecutable(ExecState
*, PassRefPtr
<CodeCache
>, const SourceCode
&, bool);
487 JSObject
* compileInternal(ExecState
*, JSScope
*, JITCode::JITType
, unsigned bytecodeIndex
= UINT_MAX
);
488 static void visitChildren(JSCell
*, SlotVisitor
&);
490 OwnPtr
<EvalCodeBlock
> m_evalCodeBlock
;
491 WriteBarrier
<UnlinkedEvalCodeBlock
> m_unlinkedEvalCodeBlock
;
492 RefPtr
<CodeCache
> m_codeCache
;
495 class ProgramExecutable
: public ScriptExecutable
{
496 friend class LLIntOffsetsExtractor
;
498 typedef ScriptExecutable Base
;
500 static ProgramExecutable
* create(ExecState
* exec
, const SourceCode
& source
)
502 ProgramExecutable
* executable
= new (NotNull
, allocateCell
<ProgramExecutable
>(*exec
->heap())) ProgramExecutable(exec
, source
);
503 executable
->finishCreation(exec
->vm());
508 JSObject
* initializeGlobalProperties(VM
&, CallFrame
*, JSScope
*);
510 static void destroy(JSCell
*);
512 JSObject
* compile(ExecState
* exec
, JSScope
* scope
)
514 RELEASE_ASSERT(exec
->vm().dynamicGlobalObject
);
516 if (!m_programCodeBlock
)
517 error
= compileInternal(exec
, scope
, JITCode::bottomTierJIT());
518 ASSERT(!error
== !!m_programCodeBlock
);
522 JSObject
* compileOptimized(ExecState
*, JSScope
*, unsigned bytecodeIndex
);
525 void jettisonOptimizedCode(VM
&);
526 bool jitCompile(ExecState
*);
529 ProgramCodeBlock
& generatedBytecode()
531 ASSERT(m_programCodeBlock
);
532 return *m_programCodeBlock
;
535 JSObject
* checkSyntax(ExecState
*);
538 JITCode
& generatedJITCode()
540 return generatedJITCodeForCall();
544 static Structure
* createStructure(VM
& vm
, JSGlobalObject
* globalObject
, JSValue proto
)
546 return Structure::create(vm
, globalObject
, proto
, TypeInfo(ProgramExecutableType
, StructureFlags
), &s_info
);
549 static const ClassInfo s_info
;
555 ExecutableInfo
executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
558 static const unsigned StructureFlags
= OverridesVisitChildren
| ScriptExecutable::StructureFlags
;
560 ProgramExecutable(ExecState
*, const SourceCode
&);
562 enum ConstantMode
{ IsConstant
, IsVariable
};
563 enum FunctionMode
{ IsFunctionToSpecialize
, NotFunctionOrNotSpecializable
};
564 int addGlobalVar(JSGlobalObject
*, const Identifier
&, ConstantMode
, FunctionMode
);
566 JSObject
* compileInternal(ExecState
*, JSScope
*, JITCode::JITType
, unsigned bytecodeIndex
= UINT_MAX
);
567 static void visitChildren(JSCell
*, SlotVisitor
&);
569 WriteBarrier
<UnlinkedProgramCodeBlock
> m_unlinkedProgramCodeBlock
;
570 OwnPtr
<ProgramCodeBlock
> m_programCodeBlock
;
573 class FunctionExecutable
: public ScriptExecutable
{
575 friend class LLIntOffsetsExtractor
;
577 typedef ScriptExecutable Base
;
579 static FunctionExecutable
* create(VM
& vm
, const SourceCode
& source
, UnlinkedFunctionExecutable
* unlinkedExecutable
, unsigned firstLine
, unsigned lastLine
, unsigned startColumn
)
581 FunctionExecutable
* executable
= new (NotNull
, allocateCell
<FunctionExecutable
>(vm
.heap
)) FunctionExecutable(vm
, source
, unlinkedExecutable
, firstLine
, lastLine
, startColumn
);
582 executable
->finishCreation(vm
);
585 static FunctionExecutable
* fromGlobalCode(const Identifier
& name
, ExecState
*, Debugger
*, const SourceCode
&, JSObject
** exception
);
587 static void destroy(JSCell
*);
589 UnlinkedFunctionExecutable
* unlinkedExecutable()
591 return m_unlinkedExecutable
.get();
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()
599 if (m_codeBlockForCall
)
600 return *m_codeBlockForCall
;
601 ASSERT(m_codeBlockForConstruct
);
602 return *m_codeBlockForConstruct
;
605 PassOwnPtr
<FunctionCodeBlock
> produceCodeBlockFor(JSScope
*, CodeSpecializationKind
, JSObject
*& exception
);
607 JSObject
* compileForCall(ExecState
* exec
, JSScope
* scope
)
609 RELEASE_ASSERT(exec
->vm().dynamicGlobalObject
);
611 if (!m_codeBlockForCall
)
612 error
= compileForCallInternal(exec
, scope
, JITCode::bottomTierJIT());
613 ASSERT(!error
== !!m_codeBlockForCall
);
617 JSObject
* compileOptimizedForCall(ExecState
*, JSScope
*, unsigned bytecodeIndex
);
620 void jettisonOptimizedCodeForCall(VM
&);
621 bool jitCompileForCall(ExecState
*);
624 bool isGeneratedForCall() const
626 return m_codeBlockForCall
;
629 FunctionCodeBlock
& generatedBytecodeForCall()
631 ASSERT(m_codeBlockForCall
);
632 return *m_codeBlockForCall
;
635 JSObject
* compileForConstruct(ExecState
* exec
, JSScope
* scope
)
637 RELEASE_ASSERT(exec
->vm().dynamicGlobalObject
);
639 if (!m_codeBlockForConstruct
)
640 error
= compileForConstructInternal(exec
, scope
, JITCode::bottomTierJIT());
641 ASSERT(!error
== !!m_codeBlockForConstruct
);
645 JSObject
* compileOptimizedForConstruct(ExecState
*, JSScope
*, unsigned bytecodeIndex
);
648 void jettisonOptimizedCodeForConstruct(VM
&);
649 bool jitCompileForConstruct(ExecState
*);
652 bool isGeneratedForConstruct() const
654 return m_codeBlockForConstruct
;
657 FunctionCodeBlock
& generatedBytecodeForConstruct()
659 ASSERT(m_codeBlockForConstruct
);
660 return *m_codeBlockForConstruct
;
663 JSObject
* compileFor(ExecState
* exec
, JSScope
* scope
, CodeSpecializationKind kind
)
665 ASSERT(exec
->callee());
666 ASSERT(exec
->callee()->inherits(&JSFunction::s_info
));
667 ASSERT(jsCast
<JSFunction
*>(exec
->callee())->jsExecutable() == this);
669 if (kind
== CodeForCall
)
670 return compileForCall(exec
, scope
);
671 ASSERT(kind
== CodeForConstruct
);
672 return compileForConstruct(exec
, scope
);
675 JSObject
* compileOptimizedFor(ExecState
* exec
, JSScope
* scope
, unsigned bytecodeIndex
, CodeSpecializationKind kind
)
677 ASSERT(exec
->callee());
678 ASSERT(exec
->callee()->inherits(&JSFunction::s_info
));
679 ASSERT(jsCast
<JSFunction
*>(exec
->callee())->jsExecutable() == this);
681 if (kind
== CodeForCall
)
682 return compileOptimizedForCall(exec
, scope
, bytecodeIndex
);
683 ASSERT(kind
== CodeForConstruct
);
684 return compileOptimizedForConstruct(exec
, scope
, bytecodeIndex
);
689 void jettisonOptimizedCodeFor(VM
& vm
, CodeSpecializationKind kind
)
691 if (kind
== CodeForCall
)
692 jettisonOptimizedCodeForCall(vm
);
694 ASSERT(kind
== CodeForConstruct
);
695 jettisonOptimizedCodeForConstruct(vm
);
699 bool jitCompileFor(ExecState
* exec
, CodeSpecializationKind kind
)
701 if (kind
== CodeForCall
)
702 return jitCompileForCall(exec
);
703 ASSERT(kind
== CodeForConstruct
);
704 return jitCompileForConstruct(exec
);
708 bool isGeneratedFor(CodeSpecializationKind kind
)
710 if (kind
== CodeForCall
)
711 return isGeneratedForCall();
712 ASSERT(kind
== CodeForConstruct
);
713 return isGeneratedForConstruct();
716 FunctionCodeBlock
& generatedBytecodeFor(CodeSpecializationKind kind
)
718 if (kind
== CodeForCall
)
719 return generatedBytecodeForCall();
720 ASSERT(kind
== CodeForConstruct
);
721 return generatedBytecodeForConstruct();
724 FunctionCodeBlock
* baselineCodeBlockFor(CodeSpecializationKind
);
726 FunctionCodeBlock
* profiledCodeBlockFor(CodeSpecializationKind kind
)
728 return baselineCodeBlockFor(kind
);
731 const Identifier
& name() { return m_unlinkedExecutable
->name(); }
732 const Identifier
& inferredName() { return m_unlinkedExecutable
->inferredName(); }
733 JSString
* nameValue() const { return m_unlinkedExecutable
->nameValue(); }
734 size_t parameterCount() const { return m_unlinkedExecutable
->parameterCount(); } // Excluding 'this'!
735 String
paramString() const;
736 SharedSymbolTable
* symbolTable(CodeSpecializationKind kind
) const { return m_unlinkedExecutable
->symbolTable(kind
); }
738 void clearCodeIfNotCompiling();
739 void clearUnlinkedCodeForRecompilationIfNotCompiling();
740 static void visitChildren(JSCell
*, SlotVisitor
&);
741 static Structure
* createStructure(VM
& vm
, JSGlobalObject
* globalObject
, JSValue proto
)
743 return Structure::create(vm
, globalObject
, proto
, TypeInfo(FunctionExecutableType
, StructureFlags
), &s_info
);
746 static const ClassInfo s_info
;
753 FunctionExecutable(VM
&, const SourceCode
&, UnlinkedFunctionExecutable
*, unsigned firstLine
, unsigned lastLine
, unsigned startColumn
);
755 JSObject
* compileForCallInternal(ExecState
*, JSScope
*, JITCode::JITType
, unsigned bytecodeIndex
= UINT_MAX
);
756 JSObject
* compileForConstructInternal(ExecState
*, JSScope
*, JITCode::JITType
, unsigned bytecodeIndex
= UINT_MAX
);
758 OwnPtr
<FunctionCodeBlock
>& codeBlockFor(CodeSpecializationKind kind
)
760 if (kind
== CodeForCall
)
761 return m_codeBlockForCall
;
762 ASSERT(kind
== CodeForConstruct
);
763 return m_codeBlockForConstruct
;
769 if (!m_jitCodeForCall
&& m_codeBlockForCall
)
771 if (!m_jitCodeForConstruct
&& m_codeBlockForConstruct
)
777 static const unsigned StructureFlags
= OverridesVisitChildren
| ScriptExecutable::StructureFlags
;
778 WriteBarrier
<UnlinkedFunctionExecutable
> m_unlinkedExecutable
;
779 OwnPtr
<FunctionCodeBlock
> m_codeBlockForCall
;
780 OwnPtr
<FunctionCodeBlock
> m_codeBlockForConstruct
;
783 inline JSFunction::JSFunction(VM
& vm
, FunctionExecutable
* executable
, JSScope
* scope
)
784 : Base(vm
, scope
->globalObject()->functionStructure())
785 , m_executable(vm
, this, executable
)
786 , m_scope(vm
, this, scope
)
787 , m_allocationProfileWatchpoint(InitializedBlind
) // See comment in JSFunction.cpp concerning the reason for using InitializedBlind as opposed to InitializedWatching.
791 inline FunctionExecutable
* JSFunction::jsExecutable() const
793 ASSERT(!isHostFunctionNonInline());
794 return static_cast<FunctionExecutable
*>(m_executable
.get());
797 inline bool JSFunction::isHostFunction() const
799 ASSERT(m_executable
);
800 return m_executable
->isHostFunction();
803 inline NativeFunction
JSFunction::nativeFunction()
805 ASSERT(isHostFunction());
806 return static_cast<NativeExecutable
*>(m_executable
.get())->function();
809 inline NativeFunction
JSFunction::nativeConstructor()
811 ASSERT(isHostFunction());
812 return static_cast<NativeExecutable
*>(m_executable
.get())->constructor();
815 inline bool isHostFunction(JSValue value
, NativeFunction nativeFunction
)
817 JSFunction
* function
= jsCast
<JSFunction
*>(getJSFunction(value
));
818 if (!function
|| !function
->isHostFunction())
820 return function
->nativeFunction() == nativeFunction
;
823 inline void ExecutableBase::clearCodeVirtual(ExecutableBase
* executable
)
825 switch (executable
->structure()->typeInfo().type()) {
826 case EvalExecutableType
:
827 return jsCast
<EvalExecutable
*>(executable
)->clearCode();
828 case ProgramExecutableType
:
829 return jsCast
<ProgramExecutable
*>(executable
)->clearCode();
830 case FunctionExecutableType
:
831 return jsCast
<FunctionExecutable
*>(executable
)->clearCode();
833 return jsCast
<NativeExecutable
*>(executable
)->clearCode();
837 inline void ScriptExecutable::unlinkCalls()
839 switch (structure()->typeInfo().type()) {
840 case EvalExecutableType
:
841 return jsCast
<EvalExecutable
*>(this)->unlinkCalls();
842 case ProgramExecutableType
:
843 return jsCast
<ProgramExecutable
*>(this)->unlinkCalls();
844 case FunctionExecutableType
:
845 return jsCast
<FunctionExecutable
*>(this)->unlinkCalls();
847 RELEASE_ASSERT_NOT_REACHED();