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 "BatchedTransitionOptimizer.h"
30 #include "BytecodeGenerator.h"
31 #include "CodeBlock.h"
32 #include "DFGDriver.h"
33 #include "ExecutionHarness.h"
35 #include "JITDriver.h"
36 #include "Operations.h"
38 #include <wtf/Vector.h>
39 #include <wtf/text/StringBuilder.h>
43 const ClassInfo
ExecutableBase::s_info
= { "Executable", 0, 0, 0, CREATE_METHOD_TABLE(ExecutableBase
) };
46 void ExecutableBase::destroy(JSCell
* cell
)
48 static_cast<ExecutableBase
*>(cell
)->ExecutableBase::~ExecutableBase();
52 void ExecutableBase::clearCode()
55 m_jitCodeForCall
.clear();
56 m_jitCodeForConstruct
.clear();
57 m_jitCodeForCallWithArityCheck
= MacroAssemblerCodePtr();
58 m_jitCodeForConstructWithArityCheck
= MacroAssemblerCodePtr();
60 m_numParametersForCall
= NUM_PARAMETERS_NOT_COMPILED
;
61 m_numParametersForConstruct
= NUM_PARAMETERS_NOT_COMPILED
;
65 Intrinsic
ExecutableBase::intrinsic() const
67 if (const NativeExecutable
* nativeExecutable
= jsDynamicCast
<const NativeExecutable
*>(this))
68 return nativeExecutable
->intrinsic();
72 Intrinsic
ExecutableBase::intrinsic() const
78 const ClassInfo
NativeExecutable::s_info
= { "NativeExecutable", &ExecutableBase::s_info
, 0, 0, CREATE_METHOD_TABLE(NativeExecutable
) };
81 void NativeExecutable::destroy(JSCell
* cell
)
83 static_cast<NativeExecutable
*>(cell
)->NativeExecutable::~NativeExecutable();
88 Intrinsic
NativeExecutable::intrinsic() const
95 // Utility method used for jettisoning code blocks.
97 static void jettisonCodeBlock(VM
& vm
, OwnPtr
<T
>& codeBlock
)
99 ASSERT(JITCode::isOptimizingJIT(codeBlock
->getJITType()));
100 ASSERT(codeBlock
->alternative());
101 OwnPtr
<T
> codeBlockToJettison
= codeBlock
.release();
102 codeBlock
= static_pointer_cast
<T
>(codeBlockToJettison
->releaseAlternative());
103 codeBlockToJettison
->unlinkIncomingCalls();
104 vm
.heap
.jettisonDFGCodeBlock(static_pointer_cast
<CodeBlock
>(codeBlockToJettison
.release()));
108 const ClassInfo
ScriptExecutable::s_info
= { "ScriptExecutable", &ExecutableBase::s_info
, 0, 0, CREATE_METHOD_TABLE(ScriptExecutable
) };
111 void ScriptExecutable::destroy(JSCell
* cell
)
113 static_cast<ScriptExecutable
*>(cell
)->ScriptExecutable::~ScriptExecutable();
117 const ClassInfo
EvalExecutable::s_info
= { "EvalExecutable", &ScriptExecutable::s_info
, 0, 0, CREATE_METHOD_TABLE(EvalExecutable
) };
119 EvalExecutable::EvalExecutable(ExecState
* exec
, PassRefPtr
<CodeCache
> codeCache
, const SourceCode
& source
, bool inStrictContext
)
120 : ScriptExecutable(exec
->vm().evalExecutableStructure
.get(), exec
, source
, inStrictContext
)
121 , m_codeCache(codeCache
)
125 void EvalExecutable::destroy(JSCell
* cell
)
127 static_cast<EvalExecutable
*>(cell
)->EvalExecutable::~EvalExecutable();
130 const ClassInfo
ProgramExecutable::s_info
= { "ProgramExecutable", &ScriptExecutable::s_info
, 0, 0, CREATE_METHOD_TABLE(ProgramExecutable
) };
132 ProgramExecutable::ProgramExecutable(ExecState
* exec
, const SourceCode
& source
)
133 : ScriptExecutable(exec
->vm().programExecutableStructure
.get(), exec
, source
, false)
137 void ProgramExecutable::destroy(JSCell
* cell
)
139 static_cast<ProgramExecutable
*>(cell
)->ProgramExecutable::~ProgramExecutable();
142 const ClassInfo
FunctionExecutable::s_info
= { "FunctionExecutable", &ScriptExecutable::s_info
, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable
) };
144 FunctionExecutable::FunctionExecutable(VM
& vm
, const SourceCode
& source
, UnlinkedFunctionExecutable
* unlinkedExecutable
, unsigned firstLine
, unsigned lastLine
, unsigned startColumn
)
145 : ScriptExecutable(vm
.functionExecutableStructure
.get(), vm
, source
, unlinkedExecutable
->isInStrictContext())
146 , m_unlinkedExecutable(vm
, this, unlinkedExecutable
)
148 RELEASE_ASSERT(!source
.isNull());
149 ASSERT(source
.length());
150 m_firstLine
= firstLine
;
151 m_lastLine
= lastLine
;
152 m_startColumn
= startColumn
;
155 void FunctionExecutable::destroy(JSCell
* cell
)
157 static_cast<FunctionExecutable
*>(cell
)->FunctionExecutable::~FunctionExecutable();
160 JSObject
* EvalExecutable::compileOptimized(ExecState
* exec
, JSScope
* scope
, unsigned bytecodeIndex
)
162 ASSERT(exec
->vm().dynamicGlobalObject
);
163 ASSERT(!!m_evalCodeBlock
);
165 if (m_evalCodeBlock
->getJITType() != JITCode::topTierJIT())
166 error
= compileInternal(exec
, scope
, JITCode::nextTierJIT(m_evalCodeBlock
->getJITType()), bytecodeIndex
);
167 ASSERT(!!m_evalCodeBlock
);
172 bool EvalExecutable::jitCompile(ExecState
* exec
)
174 return jitCompileIfAppropriate(exec
, m_evalCodeBlock
, m_jitCodeForCall
, JITCode::bottomTierJIT(), UINT_MAX
, JITCompilationCanFail
);
178 inline const char* samplingDescription(JITCode::JITType jitType
)
181 case JITCode::InterpreterThunk
:
182 return "Interpreter Compilation (TOTAL)";
183 case JITCode::BaselineJIT
:
184 return "Baseline Compilation (TOTAL)";
185 case JITCode::DFGJIT
:
186 return "DFG Compilation (TOTAL)";
188 RELEASE_ASSERT_NOT_REACHED();
193 JSObject
* EvalExecutable::compileInternal(ExecState
* exec
, JSScope
* scope
, JITCode::JITType jitType
, unsigned bytecodeIndex
)
195 SamplingRegion
samplingRegion(samplingDescription(jitType
));
198 UNUSED_PARAM(jitType
);
199 UNUSED_PARAM(bytecodeIndex
);
201 VM
* vm
= &exec
->vm();
202 JSGlobalObject
* lexicalGlobalObject
= exec
->lexicalGlobalObject();
204 if (!!m_evalCodeBlock
) {
205 OwnPtr
<EvalCodeBlock
> newCodeBlock
= adoptPtr(new EvalCodeBlock(CodeBlock::CopyParsedBlock
, *m_evalCodeBlock
));
206 newCodeBlock
->setAlternative(static_pointer_cast
<CodeBlock
>(m_evalCodeBlock
.release()));
207 m_evalCodeBlock
= newCodeBlock
.release();
211 UNUSED_PARAM(lexicalGlobalObject
);
212 if (!lexicalGlobalObject
->evalEnabled())
213 return throwError(exec
, createEvalError(exec
, lexicalGlobalObject
->evalDisabledErrorMessage()));
215 JSObject
* exception
= 0;
216 UnlinkedEvalCodeBlock
* unlinkedEvalCode
= lexicalGlobalObject
->createEvalCodeBlock(m_codeCache
.get(), exec
, scope
, this, &exception
);
217 if (!unlinkedEvalCode
)
220 OwnPtr
<CodeBlock
> previousCodeBlock
= m_evalCodeBlock
.release();
221 ASSERT((jitType
== JITCode::bottomTierJIT()) == !previousCodeBlock
);
222 m_unlinkedEvalCodeBlock
.set(*vm
, this, unlinkedEvalCode
);
223 m_evalCodeBlock
= adoptPtr(new EvalCodeBlock(this, unlinkedEvalCode
, lexicalGlobalObject
, source().provider(), scope
->localDepth(), previousCodeBlock
.release()));
224 m_evalCodeBlock
->copyPostParseDataFromAlternative();
228 if (!prepareForExecution(exec
, m_evalCodeBlock
, m_jitCodeForCall
, jitType
, bytecodeIndex
))
233 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock
) + m_jitCodeForCall
.size());
235 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock
));
242 void EvalExecutable::jettisonOptimizedCode(VM
& vm
)
244 jettisonCodeBlock(vm
, m_evalCodeBlock
);
245 m_jitCodeForCall
= m_evalCodeBlock
->getJITCode();
246 ASSERT(!m_jitCodeForCallWithArityCheck
);
250 void EvalExecutable::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
252 EvalExecutable
* thisObject
= jsCast
<EvalExecutable
*>(cell
);
253 ASSERT_GC_OBJECT_INHERITS(thisObject
, &s_info
);
254 COMPILE_ASSERT(StructureFlags
& OverridesVisitChildren
, OverridesVisitChildrenWithoutSettingFlag
);
255 ASSERT(thisObject
->structure()->typeInfo().overridesVisitChildren());
256 ScriptExecutable::visitChildren(thisObject
, visitor
);
257 if (thisObject
->m_evalCodeBlock
)
258 thisObject
->m_evalCodeBlock
->visitAggregate(visitor
);
259 visitor
.append(&thisObject
->m_unlinkedEvalCodeBlock
);
262 void EvalExecutable::unlinkCalls()
265 if (!m_jitCodeForCall
)
267 RELEASE_ASSERT(m_evalCodeBlock
);
268 m_evalCodeBlock
->unlinkCalls();
272 void EvalExecutable::clearCode()
274 m_evalCodeBlock
.clear();
275 m_unlinkedEvalCodeBlock
.clear();
279 JSObject
* ProgramExecutable::checkSyntax(ExecState
* exec
)
282 VM
* vm
= &exec
->vm();
283 JSGlobalObject
* lexicalGlobalObject
= exec
->lexicalGlobalObject();
284 RefPtr
<ProgramNode
> programNode
= parse
<ProgramNode
>(vm
, m_source
, 0, Identifier(), JSParseNormal
, ProgramNode::isFunctionNode
? JSParseFunctionCode
: JSParseProgramCode
, error
);
287 ASSERT(error
.m_type
!= ParserError::ErrorNone
);
288 return error
.toErrorObject(lexicalGlobalObject
, m_source
);
291 JSObject
* ProgramExecutable::compileOptimized(ExecState
* exec
, JSScope
* scope
, unsigned bytecodeIndex
)
293 RELEASE_ASSERT(exec
->vm().dynamicGlobalObject
);
294 ASSERT(!!m_programCodeBlock
);
296 if (m_programCodeBlock
->getJITType() != JITCode::topTierJIT())
297 error
= compileInternal(exec
, scope
, JITCode::nextTierJIT(m_programCodeBlock
->getJITType()), bytecodeIndex
);
298 ASSERT(!!m_programCodeBlock
);
303 bool ProgramExecutable::jitCompile(ExecState
* exec
)
305 return jitCompileIfAppropriate(exec
, m_programCodeBlock
, m_jitCodeForCall
, JITCode::bottomTierJIT(), UINT_MAX
, JITCompilationCanFail
);
309 JSObject
* ProgramExecutable::compileInternal(ExecState
* exec
, JSScope
* scope
, JITCode::JITType jitType
, unsigned bytecodeIndex
)
311 SamplingRegion
samplingRegion(samplingDescription(jitType
));
315 UNUSED_PARAM(jitType
);
316 UNUSED_PARAM(bytecodeIndex
);
318 if (!!m_programCodeBlock
) {
319 OwnPtr
<ProgramCodeBlock
> newCodeBlock
= adoptPtr(new ProgramCodeBlock(CodeBlock::CopyParsedBlock
, *m_programCodeBlock
));
320 newCodeBlock
->setAlternative(static_pointer_cast
<CodeBlock
>(m_programCodeBlock
.release()));
321 m_programCodeBlock
= newCodeBlock
.release();
323 JSGlobalObject
* globalObject
= scope
->globalObject();
324 m_programCodeBlock
= adoptPtr(new ProgramCodeBlock(this, m_unlinkedProgramCodeBlock
.get(), globalObject
, source().provider(), source().startColumn(), m_programCodeBlock
.release()));
325 m_programCodeBlock
->copyPostParseDataFromAlternative();
329 if (!prepareForExecution(exec
, m_programCodeBlock
, m_jitCodeForCall
, jitType
, bytecodeIndex
))
334 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock
) + m_jitCodeForCall
.size());
336 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock
));
343 void ProgramExecutable::jettisonOptimizedCode(VM
& vm
)
345 jettisonCodeBlock(vm
, m_programCodeBlock
);
346 m_jitCodeForCall
= m_programCodeBlock
->getJITCode();
347 ASSERT(!m_jitCodeForCallWithArityCheck
);
351 void ProgramExecutable::unlinkCalls()
354 if (!m_jitCodeForCall
)
356 RELEASE_ASSERT(m_programCodeBlock
);
357 m_programCodeBlock
->unlinkCalls();
361 int ProgramExecutable::addGlobalVar(JSGlobalObject
* globalObject
, const Identifier
& ident
, ConstantMode constantMode
, FunctionMode functionMode
)
363 // Try to share the symbolTable if possible
364 SharedSymbolTable
* symbolTable
= globalObject
->symbolTable();
365 UNUSED_PARAM(functionMode
);
366 int index
= symbolTable
->size();
367 SymbolTableEntry
newEntry(index
, (constantMode
== IsConstant
) ? ReadOnly
: 0);
368 if (functionMode
== IsFunctionToSpecialize
)
369 newEntry
.attemptToWatch();
370 SymbolTable::AddResult result
= symbolTable
->add(ident
.impl(), newEntry
);
371 if (!result
.isNewEntry
) {
372 result
.iterator
->value
.notifyWrite();
373 index
= result
.iterator
->value
.getIndex();
378 JSObject
* ProgramExecutable::initializeGlobalProperties(VM
& vm
, CallFrame
* callFrame
, JSScope
* scope
)
380 RELEASE_ASSERT(scope
);
381 JSGlobalObject
* globalObject
= scope
->globalObject();
382 RELEASE_ASSERT(globalObject
);
383 ASSERT(&globalObject
->vm() == &vm
);
385 JSObject
* exception
= 0;
386 UnlinkedProgramCodeBlock
* unlinkedCode
= globalObject
->createProgramCodeBlock(callFrame
, this, &exception
);
390 m_unlinkedProgramCodeBlock
.set(vm
, this, unlinkedCode
);
392 BatchedTransitionOptimizer
optimizer(vm
, globalObject
);
394 const UnlinkedProgramCodeBlock::VariableDeclations
& variableDeclarations
= unlinkedCode
->variableDeclarations();
395 const UnlinkedProgramCodeBlock::FunctionDeclations
& functionDeclarations
= unlinkedCode
->functionDeclarations();
397 size_t newGlobals
= variableDeclarations
.size() + functionDeclarations
.size();
400 globalObject
->addRegisters(newGlobals
);
401 CallFrame
* globalExec
= globalObject
->globalExec();
403 for (size_t i
= 0; i
< functionDeclarations
.size(); ++i
) {
404 bool propertyDidExist
= globalObject
->removeDirect(vm
, functionDeclarations
[i
].first
); // Newly declared functions overwrite existing properties.
405 UnlinkedFunctionExecutable
* unlinkedFunctionExecutable
= functionDeclarations
[i
].second
.get();
406 JSValue value
= JSFunction::create(globalExec
, unlinkedFunctionExecutable
->link(vm
, m_source
, lineNo(), 0), scope
);
407 int index
= addGlobalVar(globalObject
, functionDeclarations
[i
].first
, IsVariable
,
408 !propertyDidExist
? IsFunctionToSpecialize
: NotFunctionOrNotSpecializable
);
409 globalObject
->registerAt(index
).set(vm
, globalObject
, value
);
412 for (size_t i
= 0; i
< variableDeclarations
.size(); ++i
) {
413 if (globalObject
->hasProperty(globalExec
, variableDeclarations
[i
].first
))
415 addGlobalVar(globalObject
, variableDeclarations
[i
].first
,
416 (variableDeclarations
[i
].second
& DeclarationStacks::IsConstant
) ? IsConstant
: IsVariable
,
417 NotFunctionOrNotSpecializable
);
422 void ProgramExecutable::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
424 ProgramExecutable
* thisObject
= jsCast
<ProgramExecutable
*>(cell
);
425 ASSERT_GC_OBJECT_INHERITS(thisObject
, &s_info
);
426 COMPILE_ASSERT(StructureFlags
& OverridesVisitChildren
, OverridesVisitChildrenWithoutSettingFlag
);
427 ASSERT(thisObject
->structure()->typeInfo().overridesVisitChildren());
428 ScriptExecutable::visitChildren(thisObject
, visitor
);
429 visitor
.append(&thisObject
->m_unlinkedProgramCodeBlock
);
430 if (thisObject
->m_programCodeBlock
)
431 thisObject
->m_programCodeBlock
->visitAggregate(visitor
);
434 void ProgramExecutable::clearCode()
436 m_programCodeBlock
.clear();
437 m_unlinkedProgramCodeBlock
.clear();
441 FunctionCodeBlock
* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind
)
443 FunctionCodeBlock
* result
;
444 if (kind
== CodeForCall
)
445 result
= m_codeBlockForCall
.get();
447 RELEASE_ASSERT(kind
== CodeForConstruct
);
448 result
= m_codeBlockForConstruct
.get();
452 while (result
->alternative())
453 result
= static_cast<FunctionCodeBlock
*>(result
->alternative());
454 RELEASE_ASSERT(result
);
455 ASSERT(JITCode::isBaselineCode(result
->getJITType()));
459 JSObject
* FunctionExecutable::compileOptimizedForCall(ExecState
* exec
, JSScope
* scope
, unsigned bytecodeIndex
)
461 RELEASE_ASSERT(exec
->vm().dynamicGlobalObject
);
462 ASSERT(!!m_codeBlockForCall
);
464 if (m_codeBlockForCall
->getJITType() != JITCode::topTierJIT())
465 error
= compileForCallInternal(exec
, scope
, JITCode::nextTierJIT(m_codeBlockForCall
->getJITType()), bytecodeIndex
);
466 ASSERT(!!m_codeBlockForCall
);
470 JSObject
* FunctionExecutable::compileOptimizedForConstruct(ExecState
* exec
, JSScope
* scope
, unsigned bytecodeIndex
)
472 RELEASE_ASSERT(exec
->vm().dynamicGlobalObject
);
473 ASSERT(!!m_codeBlockForConstruct
);
475 if (m_codeBlockForConstruct
->getJITType() != JITCode::topTierJIT())
476 error
= compileForConstructInternal(exec
, scope
, JITCode::nextTierJIT(m_codeBlockForConstruct
->getJITType()), bytecodeIndex
);
477 ASSERT(!!m_codeBlockForConstruct
);
482 bool FunctionExecutable::jitCompileForCall(ExecState
* exec
)
484 return jitCompileFunctionIfAppropriate(exec
, m_codeBlockForCall
, m_jitCodeForCall
, m_jitCodeForCallWithArityCheck
, JITCode::bottomTierJIT(), UINT_MAX
, JITCompilationCanFail
);
487 bool FunctionExecutable::jitCompileForConstruct(ExecState
* exec
)
489 return jitCompileFunctionIfAppropriate(exec
, m_codeBlockForConstruct
, m_jitCodeForConstruct
, m_jitCodeForConstructWithArityCheck
, JITCode::bottomTierJIT(), UINT_MAX
, JITCompilationCanFail
);
493 PassOwnPtr
<FunctionCodeBlock
> FunctionExecutable::produceCodeBlockFor(JSScope
* scope
, CodeSpecializationKind specializationKind
, JSObject
*& exception
)
495 if (!!codeBlockFor(specializationKind
))
496 return adoptPtr(new FunctionCodeBlock(CodeBlock::CopyParsedBlock
, *codeBlockFor(specializationKind
)));
498 VM
* vm
= scope
->vm();
499 JSGlobalObject
* globalObject
= scope
->globalObject();
501 DebuggerMode debuggerMode
= globalObject
->hasDebugger() ? DebuggerOn
: DebuggerOff
;
502 ProfilerMode profilerMode
= globalObject
->hasProfiler() ? ProfilerOn
: ProfilerOff
;
503 UnlinkedFunctionCodeBlock
* unlinkedCodeBlock
= m_unlinkedExecutable
->codeBlockFor(*vm
, scope
, m_source
, specializationKind
, debuggerMode
, profilerMode
, error
);
504 recordParse(m_unlinkedExecutable
->features(), m_unlinkedExecutable
->hasCapturedVariables(), lineNo(), lastLine(), startColumn());
506 if (!unlinkedCodeBlock
) {
507 exception
= error
.toErrorObject(globalObject
, m_source
);
511 SourceProvider
* provider
= source().provider();
512 unsigned sourceOffset
= source().startOffset();
513 unsigned startColumn
= source().startColumn();
515 OwnPtr
<FunctionCodeBlock
> result
= adoptPtr(new FunctionCodeBlock(this, unlinkedCodeBlock
, globalObject
, provider
, sourceOffset
, startColumn
));
516 result
->copyPostParseDataFrom(codeBlockFor(specializationKind
).get());
517 return result
.release();
521 JSObject
* FunctionExecutable::compileForCallInternal(ExecState
* exec
, JSScope
* scope
, JITCode::JITType jitType
, unsigned bytecodeIndex
)
523 SamplingRegion
samplingRegion(samplingDescription(jitType
));
527 UNUSED_PARAM(jitType
);
529 UNUSED_PARAM(bytecodeIndex
);
531 ASSERT((jitType
== JITCode::bottomTierJIT()) == !m_codeBlockForCall
);
532 JSObject
* exception
= 0;
533 OwnPtr
<FunctionCodeBlock
> newCodeBlock
= produceCodeBlockFor(scope
, CodeForCall
, exception
);
537 newCodeBlock
->setAlternative(static_pointer_cast
<CodeBlock
>(m_codeBlockForCall
.release()));
538 m_codeBlockForCall
= newCodeBlock
.release();
540 m_numParametersForCall
= m_codeBlockForCall
->numParameters();
541 RELEASE_ASSERT(m_numParametersForCall
);
544 if (!prepareFunctionForExecution(exec
, m_codeBlockForCall
, m_jitCodeForCall
, m_jitCodeForCallWithArityCheck
, jitType
, bytecodeIndex
, CodeForCall
))
549 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall
) + m_jitCodeForCall
.size());
551 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall
));
557 JSObject
* FunctionExecutable::compileForConstructInternal(ExecState
* exec
, JSScope
* scope
, JITCode::JITType jitType
, unsigned bytecodeIndex
)
559 SamplingRegion
samplingRegion(samplingDescription(jitType
));
562 UNUSED_PARAM(jitType
);
564 UNUSED_PARAM(bytecodeIndex
);
567 ASSERT((jitType
== JITCode::bottomTierJIT()) == !m_codeBlockForConstruct
);
568 JSObject
* exception
= 0;
569 OwnPtr
<FunctionCodeBlock
> newCodeBlock
= produceCodeBlockFor(scope
, CodeForConstruct
, exception
);
573 newCodeBlock
->setAlternative(static_pointer_cast
<CodeBlock
>(m_codeBlockForConstruct
.release()));
574 m_codeBlockForConstruct
= newCodeBlock
.release();
576 m_numParametersForConstruct
= m_codeBlockForConstruct
->numParameters();
577 RELEASE_ASSERT(m_numParametersForConstruct
);
580 if (!prepareFunctionForExecution(exec
, m_codeBlockForConstruct
, m_jitCodeForConstruct
, m_jitCodeForConstructWithArityCheck
, jitType
, bytecodeIndex
, CodeForConstruct
))
585 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct
) + m_jitCodeForConstruct
.size());
587 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct
));
594 void FunctionExecutable::jettisonOptimizedCodeForCall(VM
& vm
)
596 jettisonCodeBlock(vm
, m_codeBlockForCall
);
597 m_jitCodeForCall
= m_codeBlockForCall
->getJITCode();
598 m_jitCodeForCallWithArityCheck
= m_codeBlockForCall
->getJITCodeWithArityCheck();
601 void FunctionExecutable::jettisonOptimizedCodeForConstruct(VM
& vm
)
603 jettisonCodeBlock(vm
, m_codeBlockForConstruct
);
604 m_jitCodeForConstruct
= m_codeBlockForConstruct
->getJITCode();
605 m_jitCodeForConstructWithArityCheck
= m_codeBlockForConstruct
->getJITCodeWithArityCheck();
609 void FunctionExecutable::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
611 FunctionExecutable
* thisObject
= jsCast
<FunctionExecutable
*>(cell
);
612 ASSERT_GC_OBJECT_INHERITS(thisObject
, &s_info
);
613 COMPILE_ASSERT(StructureFlags
& OverridesVisitChildren
, OverridesVisitChildrenWithoutSettingFlag
);
614 ASSERT(thisObject
->structure()->typeInfo().overridesVisitChildren());
615 ScriptExecutable::visitChildren(thisObject
, visitor
);
616 if (thisObject
->m_codeBlockForCall
)
617 thisObject
->m_codeBlockForCall
->visitAggregate(visitor
);
618 if (thisObject
->m_codeBlockForConstruct
)
619 thisObject
->m_codeBlockForConstruct
->visitAggregate(visitor
);
620 visitor
.append(&thisObject
->m_unlinkedExecutable
);
623 void FunctionExecutable::clearCodeIfNotCompiling()
630 void FunctionExecutable::clearUnlinkedCodeForRecompilationIfNotCompiling()
634 m_unlinkedExecutable
->clearCodeForRecompilation();
637 void FunctionExecutable::clearCode()
639 m_codeBlockForCall
.clear();
640 m_codeBlockForConstruct
.clear();
644 void FunctionExecutable::unlinkCalls()
647 if (!!m_jitCodeForCall
) {
648 RELEASE_ASSERT(m_codeBlockForCall
);
649 m_codeBlockForCall
->unlinkCalls();
651 if (!!m_jitCodeForConstruct
) {
652 RELEASE_ASSERT(m_codeBlockForConstruct
);
653 m_codeBlockForConstruct
->unlinkCalls();
658 FunctionExecutable
* FunctionExecutable::fromGlobalCode(const Identifier
& name
, ExecState
* exec
, Debugger
* debugger
, const SourceCode
& source
, JSObject
** exception
)
660 UnlinkedFunctionExecutable
* unlinkedFunction
= UnlinkedFunctionExecutable::fromGlobalCode(name
, exec
, debugger
, source
, exception
);
661 if (!unlinkedFunction
)
663 unsigned firstLine
= source
.firstLine() + unlinkedFunction
->firstLineOffset();
664 unsigned startOffset
= source
.startOffset() + unlinkedFunction
->startOffset();
665 unsigned startColumn
= source
.startColumn();
666 unsigned sourceLength
= unlinkedFunction
->sourceLength();
667 SourceCode
functionSource(source
.provider(), startOffset
, startOffset
+ sourceLength
, firstLine
, startColumn
);
668 return FunctionExecutable::create(exec
->vm(), functionSource
, unlinkedFunction
, firstLine
, unlinkedFunction
->lineCount(), startColumn
);
671 String
FunctionExecutable::paramString() const
673 return m_unlinkedExecutable
->paramString();
676 CodeBlockHash
ExecutableBase::hashFor(CodeSpecializationKind kind
) const
678 if (this->classInfo() == &NativeExecutable::s_info
)
679 return jsCast
<const NativeExecutable
*>(this)->hashFor(kind
);
681 return jsCast
<const ScriptExecutable
*>(this)->hashFor(kind
);
684 CodeBlockHash
NativeExecutable::hashFor(CodeSpecializationKind kind
) const
686 if (kind
== CodeForCall
)
687 return CodeBlockHash(static_cast<unsigned>(bitwise_cast
<size_t>(m_function
)));
689 RELEASE_ASSERT(kind
== CodeForConstruct
);
690 return CodeBlockHash(static_cast<unsigned>(bitwise_cast
<size_t>(m_constructor
)));
693 CodeBlockHash
ScriptExecutable::hashFor(CodeSpecializationKind kind
) const
695 return CodeBlockHash(source(), kind
);