2 * Copyright (C) 2009, 2010 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.
27 #include "Executable.h"
29 #include "BytecodeGenerator.h"
30 #include "CodeBlock.h"
31 #include "DFGDriver.h"
32 #include "ExecutionHarness.h"
34 #include "JITDriver.h"
36 #include "UStringBuilder.h"
37 #include <wtf/Vector.h>
41 const ClassInfo
ExecutableBase::s_info
= { "Executable", 0, 0, 0, CREATE_METHOD_TABLE(ExecutableBase
) };
44 void ExecutableBase::destroy(JSCell
* cell
)
46 jsCast
<ExecutableBase
*>(cell
)->ExecutableBase::~ExecutableBase();
50 inline void ExecutableBase::clearCode()
53 m_jitCodeForCall
.clear();
54 m_jitCodeForConstruct
.clear();
55 m_jitCodeForCallWithArityCheck
= MacroAssemblerCodePtr();
56 m_jitCodeForConstructWithArityCheck
= MacroAssemblerCodePtr();
58 m_numParametersForCall
= NUM_PARAMETERS_NOT_COMPILED
;
59 m_numParametersForConstruct
= NUM_PARAMETERS_NOT_COMPILED
;
63 Intrinsic
ExecutableBase::intrinsic() const
65 if (const NativeExecutable
* nativeExecutable
= jsDynamicCast
<const NativeExecutable
*>(this))
66 return nativeExecutable
->intrinsic();
71 const ClassInfo
NativeExecutable::s_info
= { "NativeExecutable", &ExecutableBase::s_info
, 0, 0, CREATE_METHOD_TABLE(NativeExecutable
) };
74 void NativeExecutable::destroy(JSCell
* cell
)
76 jsCast
<NativeExecutable
*>(cell
)->NativeExecutable::~NativeExecutable();
81 Intrinsic
NativeExecutable::intrinsic() const
88 // Utility method used for jettisoning code blocks.
90 static void jettisonCodeBlock(JSGlobalData
& globalData
, OwnPtr
<T
>& codeBlock
)
92 ASSERT(JITCode::isOptimizingJIT(codeBlock
->getJITType()));
93 ASSERT(codeBlock
->alternative());
94 OwnPtr
<T
> codeBlockToJettison
= codeBlock
.release();
95 codeBlock
= static_pointer_cast
<T
>(codeBlockToJettison
->releaseAlternative());
96 codeBlockToJettison
->unlinkIncomingCalls();
97 globalData
.heap
.jettisonDFGCodeBlock(static_pointer_cast
<CodeBlock
>(codeBlockToJettison
.release()));
101 void NativeExecutable::finalize(JSCell
* cell
)
103 jsCast
<NativeExecutable
*>(cell
)->clearCode();
106 const ClassInfo
ScriptExecutable::s_info
= { "ScriptExecutable", &ExecutableBase::s_info
, 0, 0, CREATE_METHOD_TABLE(ScriptExecutable
) };
109 void ScriptExecutable::destroy(JSCell
* cell
)
111 jsCast
<ScriptExecutable
*>(cell
)->ScriptExecutable::~ScriptExecutable();
115 const ClassInfo
EvalExecutable::s_info
= { "EvalExecutable", &ScriptExecutable::s_info
, 0, 0, CREATE_METHOD_TABLE(EvalExecutable
) };
117 EvalExecutable::EvalExecutable(ExecState
* exec
, const SourceCode
& source
, bool inStrictContext
)
118 : ScriptExecutable(exec
->globalData().evalExecutableStructure
.get(), exec
, source
, inStrictContext
)
122 void EvalExecutable::destroy(JSCell
* cell
)
124 jsCast
<EvalExecutable
*>(cell
)->EvalExecutable::~EvalExecutable();
127 const ClassInfo
ProgramExecutable::s_info
= { "ProgramExecutable", &ScriptExecutable::s_info
, 0, 0, CREATE_METHOD_TABLE(ProgramExecutable
) };
129 ProgramExecutable::ProgramExecutable(ExecState
* exec
, const SourceCode
& source
)
130 : ScriptExecutable(exec
->globalData().programExecutableStructure
.get(), exec
, source
, false)
134 void ProgramExecutable::destroy(JSCell
* cell
)
136 jsCast
<ProgramExecutable
*>(cell
)->ProgramExecutable::~ProgramExecutable();
139 const ClassInfo
FunctionExecutable::s_info
= { "FunctionExecutable", &ScriptExecutable::s_info
, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable
) };
141 FunctionExecutable::FunctionExecutable(JSGlobalData
& globalData
, const Identifier
& name
, const Identifier
& inferredName
, const SourceCode
& source
, bool forceUsesArguments
, FunctionParameters
* parameters
, bool inStrictContext
)
142 : ScriptExecutable(globalData
.functionExecutableStructure
.get(), globalData
, source
, inStrictContext
)
143 , m_numCapturedVariables(0)
144 , m_forceUsesArguments(forceUsesArguments
)
145 , m_parameters(parameters
)
147 , m_inferredName(inferredName
.isNull() ? globalData
.propertyNames
->emptyIdentifier
: inferredName
)
154 FunctionExecutable::FunctionExecutable(ExecState
* exec
, const Identifier
& name
, const Identifier
& inferredName
, const SourceCode
& source
, bool forceUsesArguments
, FunctionParameters
* parameters
, bool inStrictContext
)
155 : ScriptExecutable(exec
->globalData().functionExecutableStructure
.get(), exec
, source
, inStrictContext
)
156 , m_numCapturedVariables(0)
157 , m_forceUsesArguments(forceUsesArguments
)
158 , m_parameters(parameters
)
160 , m_inferredName(inferredName
.isNull() ? exec
->globalData().propertyNames
->emptyIdentifier
: inferredName
)
167 void FunctionExecutable::destroy(JSCell
* cell
)
169 jsCast
<FunctionExecutable
*>(cell
)->FunctionExecutable::~FunctionExecutable();
172 JSObject
* EvalExecutable::compileOptimized(ExecState
* exec
, ScopeChainNode
* scopeChainNode
)
174 ASSERT(exec
->globalData().dynamicGlobalObject
);
175 ASSERT(!!m_evalCodeBlock
);
177 if (m_evalCodeBlock
->getJITType() != JITCode::topTierJIT())
178 error
= compileInternal(exec
, scopeChainNode
, JITCode::nextTierJIT(m_evalCodeBlock
->getJITType()));
179 ASSERT(!!m_evalCodeBlock
);
184 bool EvalExecutable::jitCompile(JSGlobalData
& globalData
)
186 return jitCompileIfAppropriate(globalData
, m_evalCodeBlock
, m_jitCodeForCall
, JITCode::bottomTierJIT(), JITCompilationCanFail
);
190 inline const char* samplingDescription(JITCode::JITType jitType
)
193 case JITCode::InterpreterThunk
:
194 return "Interpreter Compilation (TOTAL)";
195 case JITCode::BaselineJIT
:
196 return "Baseline Compilation (TOTAL)";
197 case JITCode::DFGJIT
:
198 return "DFG Compilation (TOTAL)";
200 ASSERT_NOT_REACHED();
205 JSObject
* EvalExecutable::compileInternal(ExecState
* exec
, ScopeChainNode
* scopeChainNode
, JITCode::JITType jitType
)
207 SamplingRegion
samplingRegion(samplingDescription(jitType
));
210 UNUSED_PARAM(jitType
);
212 JSObject
* exception
= 0;
213 JSGlobalData
* globalData
= &exec
->globalData();
214 JSGlobalObject
* lexicalGlobalObject
= exec
->lexicalGlobalObject();
216 if (!!m_evalCodeBlock
) {
217 OwnPtr
<EvalCodeBlock
> newCodeBlock
= adoptPtr(new EvalCodeBlock(CodeBlock::CopyParsedBlock
, *m_evalCodeBlock
));
218 newCodeBlock
->setAlternative(static_pointer_cast
<CodeBlock
>(m_evalCodeBlock
.release()));
219 m_evalCodeBlock
= newCodeBlock
.release();
221 if (!lexicalGlobalObject
->evalEnabled())
222 return throwError(exec
, createEvalError(exec
, "Eval is disabled"));
223 RefPtr
<EvalNode
> evalNode
= parse
<EvalNode
>(globalData
, lexicalGlobalObject
, m_source
, 0, isStrictMode() ? JSParseStrict
: JSParseNormal
, EvalNode::isFunctionNode
? JSParseFunctionCode
: JSParseProgramCode
, lexicalGlobalObject
->debugger(), exec
, &exception
);
228 recordParse(evalNode
->features(), evalNode
->hasCapturedVariables(), evalNode
->lineNo(), evalNode
->lastLine());
230 JSGlobalObject
* globalObject
= scopeChainNode
->globalObject
.get();
232 OwnPtr
<CodeBlock
> previousCodeBlock
= m_evalCodeBlock
.release();
233 ASSERT((jitType
== JITCode::bottomTierJIT()) == !previousCodeBlock
);
234 m_evalCodeBlock
= adoptPtr(new EvalCodeBlock(this, globalObject
, source().provider(), scopeChainNode
->localDepth(), previousCodeBlock
.release()));
235 OwnPtr
<BytecodeGenerator
> generator(adoptPtr(new BytecodeGenerator(evalNode
.get(), scopeChainNode
, m_evalCodeBlock
->symbolTable(), m_evalCodeBlock
.get(), !!m_evalCodeBlock
->alternative() ? OptimizingCompilation
: FirstCompilation
)));
236 if ((exception
= generator
->generate())) {
237 m_evalCodeBlock
= static_pointer_cast
<EvalCodeBlock
>(m_evalCodeBlock
->releaseAlternative());
238 evalNode
->destroyData();
242 evalNode
->destroyData();
243 m_evalCodeBlock
->copyPostParseDataFromAlternative();
247 if (!prepareForExecution(*globalData
, m_evalCodeBlock
, m_jitCodeForCall
, jitType
))
252 #if ENABLE(CLASSIC_INTERPRETER)
253 if (!m_jitCodeForCall
)
254 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock
));
257 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock
) + m_jitCodeForCall
.size());
259 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock
));
266 void EvalExecutable::jettisonOptimizedCode(JSGlobalData
& globalData
)
268 jettisonCodeBlock(globalData
, m_evalCodeBlock
);
269 m_jitCodeForCall
= m_evalCodeBlock
->getJITCode();
270 ASSERT(!m_jitCodeForCallWithArityCheck
);
274 void EvalExecutable::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
276 EvalExecutable
* thisObject
= jsCast
<EvalExecutable
*>(cell
);
277 ASSERT_GC_OBJECT_INHERITS(thisObject
, &s_info
);
278 COMPILE_ASSERT(StructureFlags
& OverridesVisitChildren
, OverridesVisitChildrenWithoutSettingFlag
);
279 ASSERT(thisObject
->structure()->typeInfo().overridesVisitChildren());
280 ScriptExecutable::visitChildren(thisObject
, visitor
);
281 if (thisObject
->m_evalCodeBlock
)
282 thisObject
->m_evalCodeBlock
->visitAggregate(visitor
);
285 void EvalExecutable::unlinkCalls()
288 if (!m_jitCodeForCall
)
290 ASSERT(m_evalCodeBlock
);
291 m_evalCodeBlock
->unlinkCalls();
295 void EvalExecutable::finalize(JSCell
* cell
)
297 jsCast
<EvalExecutable
*>(cell
)->clearCode();
300 inline void EvalExecutable::clearCode()
302 if (m_evalCodeBlock
) {
303 m_evalCodeBlock
->clearEvalCache();
304 m_evalCodeBlock
.clear();
309 JSObject
* ProgramExecutable::checkSyntax(ExecState
* exec
)
311 JSObject
* exception
= 0;
312 JSGlobalData
* globalData
= &exec
->globalData();
313 JSGlobalObject
* lexicalGlobalObject
= exec
->lexicalGlobalObject();
314 RefPtr
<ProgramNode
> programNode
= parse
<ProgramNode
>(globalData
, lexicalGlobalObject
, m_source
, 0, JSParseNormal
, ProgramNode::isFunctionNode
? JSParseFunctionCode
: JSParseProgramCode
, lexicalGlobalObject
->debugger(), exec
, &exception
);
321 JSObject
* ProgramExecutable::compileOptimized(ExecState
* exec
, ScopeChainNode
* scopeChainNode
)
323 ASSERT(exec
->globalData().dynamicGlobalObject
);
324 ASSERT(!!m_programCodeBlock
);
326 if (m_programCodeBlock
->getJITType() != JITCode::topTierJIT())
327 error
= compileInternal(exec
, scopeChainNode
, JITCode::nextTierJIT(m_programCodeBlock
->getJITType()));
328 ASSERT(!!m_programCodeBlock
);
333 bool ProgramExecutable::jitCompile(JSGlobalData
& globalData
)
335 return jitCompileIfAppropriate(globalData
, m_programCodeBlock
, m_jitCodeForCall
, JITCode::bottomTierJIT(), JITCompilationCanFail
);
339 JSObject
* ProgramExecutable::compileInternal(ExecState
* exec
, ScopeChainNode
* scopeChainNode
, JITCode::JITType jitType
)
341 SamplingRegion
samplingRegion(samplingDescription(jitType
));
344 UNUSED_PARAM(jitType
);
346 JSObject
* exception
= 0;
347 JSGlobalData
* globalData
= &exec
->globalData();
348 JSGlobalObject
* lexicalGlobalObject
= exec
->lexicalGlobalObject();
350 if (!!m_programCodeBlock
) {
351 OwnPtr
<ProgramCodeBlock
> newCodeBlock
= adoptPtr(new ProgramCodeBlock(CodeBlock::CopyParsedBlock
, *m_programCodeBlock
));
352 newCodeBlock
->setAlternative(static_pointer_cast
<CodeBlock
>(m_programCodeBlock
.release()));
353 m_programCodeBlock
= newCodeBlock
.release();
355 RefPtr
<ProgramNode
> programNode
= parse
<ProgramNode
>(globalData
, lexicalGlobalObject
, m_source
, 0, isStrictMode() ? JSParseStrict
: JSParseNormal
, ProgramNode::isFunctionNode
? JSParseFunctionCode
: JSParseProgramCode
, lexicalGlobalObject
->debugger(), exec
, &exception
);
360 recordParse(programNode
->features(), programNode
->hasCapturedVariables(), programNode
->lineNo(), programNode
->lastLine());
362 JSGlobalObject
* globalObject
= scopeChainNode
->globalObject
.get();
364 OwnPtr
<CodeBlock
> previousCodeBlock
= m_programCodeBlock
.release();
365 ASSERT((jitType
== JITCode::bottomTierJIT()) == !previousCodeBlock
);
366 m_programCodeBlock
= adoptPtr(new ProgramCodeBlock(this, GlobalCode
, globalObject
, source().provider(), previousCodeBlock
.release()));
367 OwnPtr
<BytecodeGenerator
> generator(adoptPtr(new BytecodeGenerator(programNode
.get(), scopeChainNode
, &globalObject
->symbolTable(), m_programCodeBlock
.get(), !!m_programCodeBlock
->alternative() ? OptimizingCompilation
: FirstCompilation
)));
368 if ((exception
= generator
->generate())) {
369 m_programCodeBlock
= static_pointer_cast
<ProgramCodeBlock
>(m_programCodeBlock
->releaseAlternative());
370 programNode
->destroyData();
374 programNode
->destroyData();
375 m_programCodeBlock
->copyPostParseDataFromAlternative();
379 if (!prepareForExecution(*globalData
, m_programCodeBlock
, m_jitCodeForCall
, jitType
))
384 #if ENABLE(CLASSIC_INTERPRETER)
385 if (!m_jitCodeForCall
)
386 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock
));
389 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock
) + m_jitCodeForCall
.size());
391 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock
));
398 void ProgramExecutable::jettisonOptimizedCode(JSGlobalData
& globalData
)
400 jettisonCodeBlock(globalData
, m_programCodeBlock
);
401 m_jitCodeForCall
= m_programCodeBlock
->getJITCode();
402 ASSERT(!m_jitCodeForCallWithArityCheck
);
406 void ProgramExecutable::unlinkCalls()
409 if (!m_jitCodeForCall
)
411 ASSERT(m_programCodeBlock
);
412 m_programCodeBlock
->unlinkCalls();
416 void ProgramExecutable::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
418 ProgramExecutable
* thisObject
= jsCast
<ProgramExecutable
*>(cell
);
419 ASSERT_GC_OBJECT_INHERITS(thisObject
, &s_info
);
420 COMPILE_ASSERT(StructureFlags
& OverridesVisitChildren
, OverridesVisitChildrenWithoutSettingFlag
);
421 ASSERT(thisObject
->structure()->typeInfo().overridesVisitChildren());
422 ScriptExecutable::visitChildren(thisObject
, visitor
);
423 if (thisObject
->m_programCodeBlock
)
424 thisObject
->m_programCodeBlock
->visitAggregate(visitor
);
427 void ProgramExecutable::finalize(JSCell
* cell
)
429 jsCast
<ProgramExecutable
*>(cell
)->clearCode();
432 inline void ProgramExecutable::clearCode()
434 if (m_programCodeBlock
) {
435 m_programCodeBlock
->clearEvalCache();
436 m_programCodeBlock
.clear();
441 FunctionCodeBlock
* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind
)
443 FunctionCodeBlock
* result
;
444 if (kind
== CodeForCall
)
445 result
= m_codeBlockForCall
.get();
447 ASSERT(kind
== CodeForConstruct
);
448 result
= m_codeBlockForConstruct
.get();
452 while (result
->alternative())
453 result
= static_cast<FunctionCodeBlock
*>(result
->alternative());
455 ASSERT(JITCode::isBaselineCode(result
->getJITType()));
459 JSObject
* FunctionExecutable::compileOptimizedForCall(ExecState
* exec
, ScopeChainNode
* scopeChainNode
)
461 ASSERT(exec
->globalData().dynamicGlobalObject
);
462 ASSERT(!!m_codeBlockForCall
);
464 if (m_codeBlockForCall
->getJITType() != JITCode::topTierJIT())
465 error
= compileForCallInternal(exec
, scopeChainNode
, JITCode::nextTierJIT(m_codeBlockForCall
->getJITType()));
466 ASSERT(!!m_codeBlockForCall
);
470 JSObject
* FunctionExecutable::compileOptimizedForConstruct(ExecState
* exec
, ScopeChainNode
* scopeChainNode
)
472 ASSERT(exec
->globalData().dynamicGlobalObject
);
473 ASSERT(!!m_codeBlockForConstruct
);
475 if (m_codeBlockForConstruct
->getJITType() != JITCode::topTierJIT())
476 error
= compileForConstructInternal(exec
, scopeChainNode
, JITCode::nextTierJIT(m_codeBlockForConstruct
->getJITType()));
477 ASSERT(!!m_codeBlockForConstruct
);
482 bool FunctionExecutable::jitCompileForCall(JSGlobalData
& globalData
)
484 return jitCompileFunctionIfAppropriate(globalData
, m_codeBlockForCall
, m_jitCodeForCall
, m_jitCodeForCallWithArityCheck
, m_symbolTable
, JITCode::bottomTierJIT(), JITCompilationCanFail
);
487 bool FunctionExecutable::jitCompileForConstruct(JSGlobalData
& globalData
)
489 return jitCompileFunctionIfAppropriate(globalData
, m_codeBlockForConstruct
, m_jitCodeForConstruct
, m_jitCodeForConstructWithArityCheck
, m_symbolTable
, JITCode::bottomTierJIT(), JITCompilationCanFail
);
493 FunctionCodeBlock
* FunctionExecutable::codeBlockWithBytecodeFor(CodeSpecializationKind kind
)
495 return baselineCodeBlockFor(kind
);
498 PassOwnPtr
<FunctionCodeBlock
> FunctionExecutable::produceCodeBlockFor(ScopeChainNode
* scopeChainNode
, CompilationKind compilationKind
, CodeSpecializationKind specializationKind
, JSObject
*& exception
)
500 if (!!codeBlockFor(specializationKind
))
501 return adoptPtr(new FunctionCodeBlock(CodeBlock::CopyParsedBlock
, *codeBlockFor(specializationKind
)));
504 JSGlobalData
* globalData
= scopeChainNode
->globalData
;
505 JSGlobalObject
* globalObject
= scopeChainNode
->globalObject
.get();
506 RefPtr
<FunctionBodyNode
> body
= parse
<FunctionBodyNode
>(globalData
, globalObject
, m_source
, m_parameters
.get(), isStrictMode() ? JSParseStrict
: JSParseNormal
, FunctionBodyNode::isFunctionNode
? JSParseFunctionCode
: JSParseProgramCode
, 0, 0, &exception
);
512 if (m_forceUsesArguments
)
513 body
->setUsesArguments();
514 body
->finishParsing(m_parameters
, m_name
);
515 recordParse(body
->features(), body
->hasCapturedVariables(), body
->lineNo(), body
->lastLine());
517 OwnPtr
<FunctionCodeBlock
> result
;
518 ASSERT((compilationKind
== FirstCompilation
) == !codeBlockFor(specializationKind
));
519 result
= adoptPtr(new FunctionCodeBlock(this, FunctionCode
, globalObject
, source().provider(), source().startOffset(), specializationKind
== CodeForConstruct
));
520 OwnPtr
<BytecodeGenerator
> generator(adoptPtr(new BytecodeGenerator(body
.get(), scopeChainNode
, result
->symbolTable(), result
.get(), compilationKind
)));
521 exception
= generator
->generate();
526 result
->copyPostParseDataFrom(codeBlockFor(specializationKind
).get());
527 return result
.release();
530 JSObject
* FunctionExecutable::compileForCallInternal(ExecState
* exec
, ScopeChainNode
* scopeChainNode
, JITCode::JITType jitType
)
532 SamplingRegion
samplingRegion(samplingDescription(jitType
));
536 UNUSED_PARAM(jitType
);
539 ASSERT((jitType
== JITCode::bottomTierJIT()) == !m_codeBlockForCall
);
541 OwnPtr
<FunctionCodeBlock
> newCodeBlock
= produceCodeBlockFor(scopeChainNode
, !!m_codeBlockForCall
? OptimizingCompilation
: FirstCompilation
, CodeForCall
, exception
);
545 newCodeBlock
->setAlternative(static_pointer_cast
<CodeBlock
>(m_codeBlockForCall
.release()));
546 m_codeBlockForCall
= newCodeBlock
.release();
548 m_numParametersForCall
= m_codeBlockForCall
->numParameters();
549 ASSERT(m_numParametersForCall
);
550 m_numCapturedVariables
= m_codeBlockForCall
->m_numCapturedVars
;
551 m_symbolTable
= m_codeBlockForCall
->sharedSymbolTable();
554 if (!prepareFunctionForExecution(exec
->globalData(), m_codeBlockForCall
, m_jitCodeForCall
, m_jitCodeForCallWithArityCheck
, m_symbolTable
, jitType
, CodeForCall
))
559 #if ENABLE(CLASSIC_INTERPRETER)
560 if (!m_jitCodeForCall
)
561 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall
));
564 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall
) + m_jitCodeForCall
.size());
566 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall
));
572 JSObject
* FunctionExecutable::compileForConstructInternal(ExecState
* exec
, ScopeChainNode
* scopeChainNode
, JITCode::JITType jitType
)
574 SamplingRegion
samplingRegion(samplingDescription(jitType
));
577 UNUSED_PARAM(jitType
);
581 ASSERT((jitType
== JITCode::bottomTierJIT()) == !m_codeBlockForConstruct
);
583 OwnPtr
<FunctionCodeBlock
> newCodeBlock
= produceCodeBlockFor(scopeChainNode
, !!m_codeBlockForConstruct
? OptimizingCompilation
: FirstCompilation
, CodeForConstruct
, exception
);
587 newCodeBlock
->setAlternative(static_pointer_cast
<CodeBlock
>(m_codeBlockForConstruct
.release()));
588 m_codeBlockForConstruct
= newCodeBlock
.release();
590 m_numParametersForConstruct
= m_codeBlockForConstruct
->numParameters();
591 ASSERT(m_numParametersForConstruct
);
592 m_numCapturedVariables
= m_codeBlockForConstruct
->m_numCapturedVars
;
593 m_symbolTable
= m_codeBlockForConstruct
->sharedSymbolTable();
596 if (!prepareFunctionForExecution(exec
->globalData(), m_codeBlockForConstruct
, m_jitCodeForConstruct
, m_jitCodeForConstructWithArityCheck
, m_symbolTable
, jitType
, CodeForConstruct
))
601 #if ENABLE(CLASSIC_INTERPRETER)
602 if (!m_jitCodeForConstruct
)
603 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct
));
606 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct
) + m_jitCodeForConstruct
.size());
608 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct
));
615 void FunctionExecutable::jettisonOptimizedCodeForCall(JSGlobalData
& globalData
)
617 jettisonCodeBlock(globalData
, m_codeBlockForCall
);
618 m_jitCodeForCall
= m_codeBlockForCall
->getJITCode();
619 m_jitCodeForCallWithArityCheck
= m_codeBlockForCall
->getJITCodeWithArityCheck();
622 void FunctionExecutable::jettisonOptimizedCodeForConstruct(JSGlobalData
& globalData
)
624 jettisonCodeBlock(globalData
, m_codeBlockForConstruct
);
625 m_jitCodeForConstruct
= m_codeBlockForConstruct
->getJITCode();
626 m_jitCodeForConstructWithArityCheck
= m_codeBlockForConstruct
->getJITCodeWithArityCheck();
630 void FunctionExecutable::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
632 FunctionExecutable
* thisObject
= jsCast
<FunctionExecutable
*>(cell
);
633 ASSERT_GC_OBJECT_INHERITS(thisObject
, &s_info
);
634 COMPILE_ASSERT(StructureFlags
& OverridesVisitChildren
, OverridesVisitChildrenWithoutSettingFlag
);
635 ASSERT(thisObject
->structure()->typeInfo().overridesVisitChildren());
636 ScriptExecutable::visitChildren(thisObject
, visitor
);
637 if (thisObject
->m_nameValue
)
638 visitor
.append(&thisObject
->m_nameValue
);
639 if (thisObject
->m_codeBlockForCall
)
640 thisObject
->m_codeBlockForCall
->visitAggregate(visitor
);
641 if (thisObject
->m_codeBlockForConstruct
)
642 thisObject
->m_codeBlockForConstruct
->visitAggregate(visitor
);
645 void FunctionExecutable::discardCode()
648 // These first two checks are to handle the rare case where
649 // we are trying to evict code for a function during its
651 if (!m_jitCodeForCall
&& m_codeBlockForCall
)
653 if (!m_jitCodeForConstruct
&& m_codeBlockForConstruct
)
659 void FunctionExecutable::finalize(JSCell
* cell
)
661 FunctionExecutable
* executable
= jsCast
<FunctionExecutable
*>(cell
);
662 Heap::heap(executable
)->removeFunctionExecutable(executable
);
663 executable
->clearCode();
666 inline void FunctionExecutable::clearCode()
668 if (m_codeBlockForCall
) {
669 m_codeBlockForCall
->clearEvalCache();
670 m_codeBlockForCall
.clear();
672 if (m_codeBlockForConstruct
) {
673 m_codeBlockForConstruct
->clearEvalCache();
674 m_codeBlockForConstruct
.clear();
679 void FunctionExecutable::unlinkCalls()
682 if (!!m_jitCodeForCall
) {
683 ASSERT(m_codeBlockForCall
);
684 m_codeBlockForCall
->unlinkCalls();
686 if (!!m_jitCodeForConstruct
) {
687 ASSERT(m_codeBlockForConstruct
);
688 m_codeBlockForConstruct
->unlinkCalls();
693 FunctionExecutable
* FunctionExecutable::fromGlobalCode(const Identifier
& functionName
, ExecState
* exec
, Debugger
* debugger
, const SourceCode
& source
, JSObject
** exception
)
695 JSGlobalObject
* lexicalGlobalObject
= exec
->lexicalGlobalObject();
696 RefPtr
<ProgramNode
> program
= parse
<ProgramNode
>(&exec
->globalData(), lexicalGlobalObject
, source
, 0, JSParseNormal
, ProgramNode::isFunctionNode
? JSParseFunctionCode
: JSParseProgramCode
, debugger
, exec
, exception
);
702 // Uses of this function that would not result in a single function expression are invalid.
703 StatementNode
* exprStatement
= program
->singleStatement();
704 ASSERT(exprStatement
);
705 ASSERT(exprStatement
->isExprStatement());
706 ExpressionNode
* funcExpr
= static_cast<ExprStatementNode
*>(exprStatement
)->expr();
708 ASSERT(funcExpr
->isFuncExprNode());
709 FunctionBodyNode
* body
= static_cast<FuncExprNode
*>(funcExpr
)->body();
712 return FunctionExecutable::create(exec
->globalData(), functionName
, functionName
, body
->source(), body
->usesArguments(), body
->parameters(), body
->isStrictMode(), body
->lineNo(), body
->lastLine());
715 UString
FunctionExecutable::paramString() const
717 FunctionParameters
& parameters
= *m_parameters
;
718 UStringBuilder builder
;
719 for (size_t pos
= 0; pos
< parameters
.size(); ++pos
) {
720 if (!builder
.isEmpty())
721 builder
.append(", ");
722 builder
.append(parameters
[pos
].ustring());
724 return builder
.toUString();