2 * Copyright (C) 2009, 2010, 2013, 2015 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 "CodeBlock.h"
31 #include "DFGDriver.h"
33 #include "JSCInlines.h"
34 #include "JSFunctionNameScope.h"
35 #include "LLIntEntrypoint.h"
37 #include "ProfilerDatabase.h"
38 #include "TypeProfiler.h"
39 #include <wtf/CommaPrinter.h>
40 #include <wtf/Vector.h>
41 #include <wtf/text/StringBuilder.h>
45 const ClassInfo
ExecutableBase::s_info
= { "Executable", 0, 0, CREATE_METHOD_TABLE(ExecutableBase
) };
47 void ExecutableBase::destroy(JSCell
* cell
)
49 static_cast<ExecutableBase
*>(cell
)->ExecutableBase::~ExecutableBase();
52 void ExecutableBase::clearCode()
55 m_jitCodeForCall
= nullptr;
56 m_jitCodeForConstruct
= nullptr;
57 m_jitCodeForCallWithArityCheck
= MacroAssemblerCodePtr();
58 m_jitCodeForConstructWithArityCheck
= MacroAssemblerCodePtr();
59 m_jitCodeForCallWithArityCheckAndPreserveRegs
= MacroAssemblerCodePtr();
60 m_jitCodeForConstructWithArityCheckAndPreserveRegs
= MacroAssemblerCodePtr();
62 m_numParametersForCall
= NUM_PARAMETERS_NOT_COMPILED
;
63 m_numParametersForConstruct
= NUM_PARAMETERS_NOT_COMPILED
;
67 Intrinsic
ExecutableBase::intrinsic() const
69 if (const NativeExecutable
* nativeExecutable
= jsDynamicCast
<const NativeExecutable
*>(this))
70 return nativeExecutable
->intrinsic();
74 Intrinsic
ExecutableBase::intrinsic() const
80 const ClassInfo
NativeExecutable::s_info
= { "NativeExecutable", &ExecutableBase::s_info
, 0, CREATE_METHOD_TABLE(NativeExecutable
) };
82 void NativeExecutable::destroy(JSCell
* cell
)
84 static_cast<NativeExecutable
*>(cell
)->NativeExecutable::~NativeExecutable();
88 Intrinsic
NativeExecutable::intrinsic() const
94 const ClassInfo
ScriptExecutable::s_info
= { "ScriptExecutable", &ExecutableBase::s_info
, 0, CREATE_METHOD_TABLE(ScriptExecutable
) };
96 ScriptExecutable::ScriptExecutable(Structure
* structure
, VM
& vm
, const SourceCode
& source
, bool isInStrictContext
)
97 : ExecutableBase(vm
, structure
, NUM_PARAMETERS_NOT_COMPILED
)
99 , m_features(isInStrictContext
? StrictModeFeature
: 0)
100 , m_hasCapturedVariables(false)
101 , m_neverInline(false)
102 , m_didTryToEnterInLoop(false)
103 , m_overrideLineNumber(-1)
106 , m_startColumn(UINT_MAX
)
107 , m_endColumn(UINT_MAX
)
108 , m_typeProfilingStartOffset(UINT_MAX
)
109 , m_typeProfilingEndOffset(UINT_MAX
)
113 void ScriptExecutable::destroy(JSCell
* cell
)
115 static_cast<ScriptExecutable
*>(cell
)->ScriptExecutable::~ScriptExecutable();
118 void ScriptExecutable::installCode(CodeBlock
* genericCodeBlock
)
120 RELEASE_ASSERT(genericCodeBlock
->ownerExecutable() == this);
121 RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock
->jitType()));
123 if (Options::verboseOSR())
124 dataLog("Installing ", *genericCodeBlock
, "\n");
126 VM
& vm
= *genericCodeBlock
->vm();
128 if (vm
.m_perBytecodeProfiler
)
129 vm
.m_perBytecodeProfiler
->ensureBytecodesFor(genericCodeBlock
);
131 ASSERT(vm
.heap
.isDeferred());
133 CodeSpecializationKind kind
= genericCodeBlock
->specializationKind();
135 RefPtr
<CodeBlock
> oldCodeBlock
;
139 m_jitCodeForCall
= genericCodeBlock
->jitCode();
140 m_jitCodeForCallWithArityCheck
= MacroAssemblerCodePtr();
141 m_jitCodeForCallWithArityCheckAndPreserveRegs
= MacroAssemblerCodePtr();
142 m_numParametersForCall
= genericCodeBlock
->numParameters();
144 case CodeForConstruct
:
145 m_jitCodeForConstruct
= genericCodeBlock
->jitCode();
146 m_jitCodeForConstructWithArityCheck
= MacroAssemblerCodePtr();
147 m_jitCodeForConstructWithArityCheckAndPreserveRegs
= MacroAssemblerCodePtr();
148 m_numParametersForConstruct
= genericCodeBlock
->numParameters();
152 switch (genericCodeBlock
->codeType()) {
154 ProgramExecutable
* executable
= jsCast
<ProgramExecutable
*>(this);
155 ProgramCodeBlock
* codeBlock
= static_cast<ProgramCodeBlock
*>(genericCodeBlock
);
157 ASSERT(kind
== CodeForCall
);
159 oldCodeBlock
= executable
->m_programCodeBlock
;
160 executable
->m_programCodeBlock
= codeBlock
;
165 EvalExecutable
* executable
= jsCast
<EvalExecutable
*>(this);
166 EvalCodeBlock
* codeBlock
= static_cast<EvalCodeBlock
*>(genericCodeBlock
);
168 ASSERT(kind
== CodeForCall
);
170 oldCodeBlock
= executable
->m_evalCodeBlock
;
171 executable
->m_evalCodeBlock
= codeBlock
;
176 FunctionExecutable
* executable
= jsCast
<FunctionExecutable
*>(this);
177 FunctionCodeBlock
* codeBlock
= static_cast<FunctionCodeBlock
*>(genericCodeBlock
);
181 oldCodeBlock
= executable
->m_codeBlockForCall
;
182 executable
->m_codeBlockForCall
= codeBlock
;
184 case CodeForConstruct
:
185 oldCodeBlock
= executable
->m_codeBlockForConstruct
;
186 executable
->m_codeBlockForConstruct
= codeBlock
;
193 oldCodeBlock
->unlinkIncomingCalls();
195 Debugger
* debugger
= genericCodeBlock
->globalObject()->debugger();
197 debugger
->registerCodeBlock(genericCodeBlock
);
199 Heap::heap(this)->writeBarrier(this);
202 RefPtr
<CodeBlock
> ScriptExecutable::newCodeBlockFor(
203 CodeSpecializationKind kind
, JSFunction
* function
, JSScope
* scope
, JSObject
*& exception
)
205 VM
* vm
= scope
->vm();
207 ASSERT(vm
->heap
.isDeferred());
208 ASSERT(startColumn() != UINT_MAX
);
209 ASSERT(endColumn() != UINT_MAX
);
211 if (classInfo() == EvalExecutable::info()) {
212 EvalExecutable
* executable
= jsCast
<EvalExecutable
*>(this);
213 RELEASE_ASSERT(kind
== CodeForCall
);
214 RELEASE_ASSERT(!executable
->m_evalCodeBlock
);
215 RELEASE_ASSERT(!function
);
216 return adoptRef(new EvalCodeBlock(
217 executable
, executable
->m_unlinkedEvalCodeBlock
.get(), scope
,
218 executable
->source().provider()));
221 if (classInfo() == ProgramExecutable::info()) {
222 ProgramExecutable
* executable
= jsCast
<ProgramExecutable
*>(this);
223 RELEASE_ASSERT(kind
== CodeForCall
);
224 RELEASE_ASSERT(!executable
->m_programCodeBlock
);
225 RELEASE_ASSERT(!function
);
226 return adoptRef(new ProgramCodeBlock(
227 executable
, executable
->m_unlinkedProgramCodeBlock
.get(), scope
,
228 executable
->source().provider(), executable
->source().startColumn()));
231 RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
232 RELEASE_ASSERT(function
);
233 FunctionExecutable
* executable
= jsCast
<FunctionExecutable
*>(this);
234 RELEASE_ASSERT(!executable
->codeBlockFor(kind
));
235 JSGlobalObject
* globalObject
= scope
->globalObject();
237 DebuggerMode debuggerMode
= globalObject
->hasDebugger() ? DebuggerOn
: DebuggerOff
;
238 ProfilerMode profilerMode
= globalObject
->hasProfiler() ? ProfilerOn
: ProfilerOff
;
239 UnlinkedFunctionCodeBlock
* unlinkedCodeBlock
=
240 executable
->m_unlinkedExecutable
->codeBlockFor(
241 *vm
, executable
->m_source
, kind
, debuggerMode
, profilerMode
, error
);
242 recordParse(executable
->m_unlinkedExecutable
->features(), executable
->m_unlinkedExecutable
->hasCapturedVariables(), firstLine(), lastLine(), startColumn(), endColumn());
243 if (!unlinkedCodeBlock
) {
244 exception
= vm
->throwException(
245 globalObject
->globalExec(),
246 error
.toErrorObject(globalObject
, executable
->m_source
));
250 // Parsing reveals whether our function uses features that require a separate function name object in the scope chain.
251 // Be sure to add this scope before linking the bytecode because this scope will change the resolution depth of non-local variables.
252 if (functionNameIsInScope(executable
->name(), executable
->functionMode())
253 && functionNameScopeIsDynamic(executable
->usesEval(), executable
->isStrictMode())) {
254 // We shouldn't have to do this. But we do, because bytecode linking requires a real scope
256 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=141885
257 SymbolTable
* symbolTable
=
258 SymbolTable::createNameScopeTable(*vm
, executable
->name(), ReadOnly
| DontDelete
);
259 scope
= JSFunctionNameScope::create(
260 *vm
, scope
->globalObject(), scope
, symbolTable
, function
);
263 SourceProvider
* provider
= executable
->source().provider();
264 unsigned sourceOffset
= executable
->source().startOffset();
265 unsigned startColumn
= executable
->source().startColumn();
267 return adoptRef(new FunctionCodeBlock(
268 executable
, unlinkedCodeBlock
, scope
, provider
, sourceOffset
, startColumn
));
271 PassRefPtr
<CodeBlock
> ScriptExecutable::newReplacementCodeBlockFor(
272 CodeSpecializationKind kind
)
274 if (classInfo() == EvalExecutable::info()) {
275 RELEASE_ASSERT(kind
== CodeForCall
);
276 EvalExecutable
* executable
= jsCast
<EvalExecutable
*>(this);
277 EvalCodeBlock
* baseline
= static_cast<EvalCodeBlock
*>(
278 executable
->m_evalCodeBlock
->baselineVersion());
279 RefPtr
<EvalCodeBlock
> result
= adoptRef(new EvalCodeBlock(
280 CodeBlock::CopyParsedBlock
, *baseline
));
281 result
->setAlternative(baseline
);
285 if (classInfo() == ProgramExecutable::info()) {
286 RELEASE_ASSERT(kind
== CodeForCall
);
287 ProgramExecutable
* executable
= jsCast
<ProgramExecutable
*>(this);
288 ProgramCodeBlock
* baseline
= static_cast<ProgramCodeBlock
*>(
289 executable
->m_programCodeBlock
->baselineVersion());
290 RefPtr
<ProgramCodeBlock
> result
= adoptRef(new ProgramCodeBlock(
291 CodeBlock::CopyParsedBlock
, *baseline
));
292 result
->setAlternative(baseline
);
296 RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
297 FunctionExecutable
* executable
= jsCast
<FunctionExecutable
*>(this);
298 FunctionCodeBlock
* baseline
= static_cast<FunctionCodeBlock
*>(
299 executable
->codeBlockFor(kind
)->baselineVersion());
300 RefPtr
<FunctionCodeBlock
> result
= adoptRef(new FunctionCodeBlock(
301 CodeBlock::CopyParsedBlock
, *baseline
));
302 result
->setAlternative(baseline
);
306 static void setupLLInt(VM
& vm
, CodeBlock
* codeBlock
)
308 LLInt::setEntrypoint(vm
, codeBlock
);
311 static void setupJIT(VM
& vm
, CodeBlock
* codeBlock
)
314 CompilationResult result
= JIT::compile(&vm
, codeBlock
, JITCompilationMustSucceed
);
315 RELEASE_ASSERT(result
== CompilationSuccessful
);
318 UNUSED_PARAM(codeBlock
);
319 UNREACHABLE_FOR_PLATFORM();
323 JSObject
* ScriptExecutable::prepareForExecutionImpl(
324 ExecState
* exec
, JSFunction
* function
, JSScope
* scope
, CodeSpecializationKind kind
)
327 DeferGC
deferGC(vm
.heap
);
329 JSObject
* exception
= 0;
330 RefPtr
<CodeBlock
> codeBlock
= newCodeBlockFor(kind
, function
, scope
, exception
);
332 RELEASE_ASSERT(exception
);
336 if (Options::validateBytecode())
337 codeBlock
->validate();
339 if (Options::useLLInt())
340 setupLLInt(vm
, codeBlock
.get());
342 setupJIT(vm
, codeBlock
.get());
344 installCode(codeBlock
.get());
348 const ClassInfo
EvalExecutable::s_info
= { "EvalExecutable", &ScriptExecutable::s_info
, 0, CREATE_METHOD_TABLE(EvalExecutable
) };
350 EvalExecutable
* EvalExecutable::create(ExecState
* exec
, const SourceCode
& source
, bool isInStrictContext
, ThisTDZMode thisTDZMode
)
352 JSGlobalObject
* globalObject
= exec
->lexicalGlobalObject();
353 if (!globalObject
->evalEnabled()) {
354 exec
->vm().throwException(exec
, createEvalError(exec
, globalObject
->evalDisabledErrorMessage()));
358 EvalExecutable
* executable
= new (NotNull
, allocateCell
<EvalExecutable
>(*exec
->heap())) EvalExecutable(exec
, source
, isInStrictContext
);
359 executable
->finishCreation(exec
->vm());
361 UnlinkedEvalCodeBlock
* unlinkedEvalCode
= globalObject
->createEvalCodeBlock(exec
, executable
, thisTDZMode
);
362 if (!unlinkedEvalCode
)
365 executable
->m_unlinkedEvalCodeBlock
.set(exec
->vm(), executable
, unlinkedEvalCode
);
370 EvalExecutable::EvalExecutable(ExecState
* exec
, const SourceCode
& source
, bool inStrictContext
)
371 : ScriptExecutable(exec
->vm().evalExecutableStructure
.get(), exec
->vm(), source
, inStrictContext
)
375 void EvalExecutable::destroy(JSCell
* cell
)
377 static_cast<EvalExecutable
*>(cell
)->EvalExecutable::~EvalExecutable();
380 const ClassInfo
ProgramExecutable::s_info
= { "ProgramExecutable", &ScriptExecutable::s_info
, 0, CREATE_METHOD_TABLE(ProgramExecutable
) };
382 ProgramExecutable::ProgramExecutable(ExecState
* exec
, const SourceCode
& source
)
383 : ScriptExecutable(exec
->vm().programExecutableStructure
.get(), exec
->vm(), source
, false)
385 m_typeProfilingStartOffset
= 0;
386 m_typeProfilingEndOffset
= source
.length() - 1;
387 if (exec
->vm().typeProfiler() || exec
->vm().controlFlowProfiler())
388 exec
->vm().functionHasExecutedCache()->insertUnexecutedRange(sourceID(), m_typeProfilingStartOffset
, m_typeProfilingEndOffset
);
391 void ProgramExecutable::destroy(JSCell
* cell
)
393 static_cast<ProgramExecutable
*>(cell
)->ProgramExecutable::~ProgramExecutable();
396 const ClassInfo
FunctionExecutable::s_info
= { "FunctionExecutable", &ScriptExecutable::s_info
, 0, CREATE_METHOD_TABLE(FunctionExecutable
) };
398 FunctionExecutable::FunctionExecutable(VM
& vm
, const SourceCode
& source
,
399 UnlinkedFunctionExecutable
* unlinkedExecutable
, unsigned firstLine
,
400 unsigned lastLine
, unsigned startColumn
, unsigned endColumn
)
401 : ScriptExecutable(vm
.functionExecutableStructure
.get(), vm
, source
, unlinkedExecutable
->isInStrictContext())
402 , m_unlinkedExecutable(vm
, this, unlinkedExecutable
)
404 RELEASE_ASSERT(!source
.isNull());
405 ASSERT(source
.length());
406 m_firstLine
= firstLine
;
407 m_lastLine
= lastLine
;
408 ASSERT(startColumn
!= UINT_MAX
);
409 ASSERT(endColumn
!= UINT_MAX
);
410 m_startColumn
= startColumn
;
411 m_endColumn
= endColumn
;
412 m_parametersStartOffset
= unlinkedExecutable
->parametersStartOffset();
413 m_typeProfilingStartOffset
= unlinkedExecutable
->typeProfilingStartOffset();
414 m_typeProfilingEndOffset
= unlinkedExecutable
->typeProfilingEndOffset();
417 void FunctionExecutable::finishCreation(VM
& vm
)
419 Base::finishCreation(vm
);
420 m_singletonFunction
.set(vm
, this, InferredValue::create(vm
));
423 void FunctionExecutable::destroy(JSCell
* cell
)
425 static_cast<FunctionExecutable
*>(cell
)->FunctionExecutable::~FunctionExecutable();
428 inline const char* samplingDescription(JITCode::JITType jitType
)
431 case JITCode::InterpreterThunk
:
432 return "Interpreter Compilation (TOTAL)";
433 case JITCode::BaselineJIT
:
434 return "Baseline Compilation (TOTAL)";
435 case JITCode::DFGJIT
:
436 return "DFG Compilation (TOTAL)";
437 case JITCode::FTLJIT
:
438 return "FTL Compilation (TOTAL)";
440 RELEASE_ASSERT_NOT_REACHED();
445 void EvalExecutable::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
447 EvalExecutable
* thisObject
= jsCast
<EvalExecutable
*>(cell
);
448 ASSERT_GC_OBJECT_INHERITS(thisObject
, info());
449 ScriptExecutable::visitChildren(thisObject
, visitor
);
450 if (thisObject
->m_evalCodeBlock
)
451 thisObject
->m_evalCodeBlock
->visitAggregate(visitor
);
452 visitor
.append(&thisObject
->m_unlinkedEvalCodeBlock
);
455 void EvalExecutable::unlinkCalls()
458 if (!m_jitCodeForCall
)
460 RELEASE_ASSERT(m_evalCodeBlock
);
461 m_evalCodeBlock
->unlinkCalls();
465 void EvalExecutable::clearCode()
467 m_evalCodeBlock
= nullptr;
468 m_unlinkedEvalCodeBlock
.clear();
472 JSObject
* ProgramExecutable::checkSyntax(ExecState
* exec
)
475 VM
* vm
= &exec
->vm();
476 JSGlobalObject
* lexicalGlobalObject
= exec
->lexicalGlobalObject();
477 std::unique_ptr
<ProgramNode
> programNode
= parse
<ProgramNode
>(
478 vm
, m_source
, 0, Identifier(), JSParserBuiltinMode::NotBuiltin
,
479 JSParserStrictMode::NotStrict
, JSParserCodeType::Program
, error
);
482 ASSERT(error
.isValid());
483 return error
.toErrorObject(lexicalGlobalObject
, m_source
);
486 void ProgramExecutable::unlinkCalls()
489 if (!m_jitCodeForCall
)
491 RELEASE_ASSERT(m_programCodeBlock
);
492 m_programCodeBlock
->unlinkCalls();
496 JSObject
* ProgramExecutable::initializeGlobalProperties(VM
& vm
, CallFrame
* callFrame
, JSScope
* scope
)
498 RELEASE_ASSERT(scope
);
499 JSGlobalObject
* globalObject
= scope
->globalObject();
500 RELEASE_ASSERT(globalObject
);
501 ASSERT(&globalObject
->vm() == &vm
);
503 JSObject
* exception
= 0;
504 UnlinkedProgramCodeBlock
* unlinkedCodeBlock
= globalObject
->createProgramCodeBlock(callFrame
, this, &exception
);
508 m_unlinkedProgramCodeBlock
.set(vm
, this, unlinkedCodeBlock
);
510 BatchedTransitionOptimizer
optimizer(vm
, globalObject
);
512 const UnlinkedProgramCodeBlock::VariableDeclations
& variableDeclarations
= unlinkedCodeBlock
->variableDeclarations();
514 for (size_t i
= 0, numberOfFunctions
= unlinkedCodeBlock
->numberOfFunctionDecls(); i
< numberOfFunctions
; ++i
) {
515 UnlinkedFunctionExecutable
* unlinkedFunctionExecutable
= unlinkedCodeBlock
->functionDecl(i
);
516 ASSERT(!unlinkedFunctionExecutable
->name().isEmpty());
517 globalObject
->addFunction(callFrame
, unlinkedFunctionExecutable
->name());
518 if (vm
.typeProfiler() || vm
.controlFlowProfiler()) {
519 vm
.functionHasExecutedCache()->insertUnexecutedRange(sourceID(),
520 unlinkedFunctionExecutable
->typeProfilingStartOffset(),
521 unlinkedFunctionExecutable
->typeProfilingEndOffset());
525 for (size_t i
= 0; i
< variableDeclarations
.size(); ++i
) {
526 if (variableDeclarations
[i
].second
& DeclarationStacks::IsConstant
)
527 globalObject
->addConst(callFrame
, variableDeclarations
[i
].first
);
529 globalObject
->addVar(callFrame
, variableDeclarations
[i
].first
);
534 void ProgramExecutable::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
536 ProgramExecutable
* thisObject
= jsCast
<ProgramExecutable
*>(cell
);
537 ASSERT_GC_OBJECT_INHERITS(thisObject
, info());
538 ScriptExecutable::visitChildren(thisObject
, visitor
);
539 visitor
.append(&thisObject
->m_unlinkedProgramCodeBlock
);
540 if (thisObject
->m_programCodeBlock
)
541 thisObject
->m_programCodeBlock
->visitAggregate(visitor
);
544 void ProgramExecutable::clearCode()
546 m_programCodeBlock
= nullptr;
547 m_unlinkedProgramCodeBlock
.clear();
551 FunctionCodeBlock
* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind
)
553 FunctionCodeBlock
* result
;
554 if (kind
== CodeForCall
)
555 result
= m_codeBlockForCall
.get();
557 RELEASE_ASSERT(kind
== CodeForConstruct
);
558 result
= m_codeBlockForConstruct
.get();
562 return static_cast<FunctionCodeBlock
*>(result
->baselineAlternative());
565 void FunctionExecutable::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
567 FunctionExecutable
* thisObject
= jsCast
<FunctionExecutable
*>(cell
);
568 ASSERT_GC_OBJECT_INHERITS(thisObject
, info());
569 ScriptExecutable::visitChildren(thisObject
, visitor
);
570 if (thisObject
->m_codeBlockForCall
)
571 thisObject
->m_codeBlockForCall
->visitAggregate(visitor
);
572 if (thisObject
->m_codeBlockForConstruct
)
573 thisObject
->m_codeBlockForConstruct
->visitAggregate(visitor
);
574 visitor
.append(&thisObject
->m_unlinkedExecutable
);
575 visitor
.append(&thisObject
->m_singletonFunction
);
578 SymbolTable
* FunctionExecutable::symbolTable(CodeSpecializationKind kind
)
580 return codeBlockFor(kind
)->symbolTable();
583 void FunctionExecutable::clearUnlinkedCodeForRecompilation()
585 m_unlinkedExecutable
->clearCodeForRecompilation();
588 void FunctionExecutable::clearCode()
590 m_codeBlockForCall
= nullptr;
591 m_codeBlockForConstruct
= nullptr;
595 void FunctionExecutable::unlinkCalls()
598 if (!!m_jitCodeForCall
) {
599 RELEASE_ASSERT(m_codeBlockForCall
);
600 m_codeBlockForCall
->unlinkCalls();
602 if (!!m_jitCodeForConstruct
) {
603 RELEASE_ASSERT(m_codeBlockForConstruct
);
604 m_codeBlockForConstruct
->unlinkCalls();
609 FunctionExecutable
* FunctionExecutable::fromGlobalCode(
610 const Identifier
& name
, ExecState
& exec
, const SourceCode
& source
,
611 JSObject
*& exception
, int overrideLineNumber
)
613 UnlinkedFunctionExecutable
* unlinkedExecutable
=
614 UnlinkedFunctionExecutable::fromGlobalCode(
615 name
, exec
, source
, exception
, overrideLineNumber
);
616 if (!unlinkedExecutable
)
619 return unlinkedExecutable
->link(exec
.vm(), source
, overrideLineNumber
);
622 void ExecutableBase::dump(PrintStream
& out
) const
624 ExecutableBase
* realThis
= const_cast<ExecutableBase
*>(this);
626 if (classInfo() == NativeExecutable::info()) {
627 NativeExecutable
* native
= jsCast
<NativeExecutable
*>(realThis
);
628 out
.print("NativeExecutable:", RawPointer(bitwise_cast
<void*>(native
->function())), "/", RawPointer(bitwise_cast
<void*>(native
->constructor())));
632 if (classInfo() == EvalExecutable::info()) {
633 EvalExecutable
* eval
= jsCast
<EvalExecutable
*>(realThis
);
634 if (CodeBlock
* codeBlock
= eval
->codeBlock())
635 out
.print(*codeBlock
);
637 out
.print("EvalExecutable w/o CodeBlock");
641 if (classInfo() == ProgramExecutable::info()) {
642 ProgramExecutable
* eval
= jsCast
<ProgramExecutable
*>(realThis
);
643 if (CodeBlock
* codeBlock
= eval
->codeBlock())
644 out
.print(*codeBlock
);
646 out
.print("ProgramExecutable w/o CodeBlock");
650 FunctionExecutable
* function
= jsCast
<FunctionExecutable
*>(realThis
);
651 if (!function
->eitherCodeBlock())
652 out
.print("FunctionExecutable w/o CodeBlock");
654 CommaPrinter
comma("/");
655 if (function
->codeBlockForCall())
656 out
.print(comma
, *function
->codeBlockForCall());
657 if (function
->codeBlockForConstruct())
658 out
.print(comma
, *function
->codeBlockForConstruct());
662 CodeBlockHash
ExecutableBase::hashFor(CodeSpecializationKind kind
) const
664 if (this->classInfo() == NativeExecutable::info())
665 return jsCast
<const NativeExecutable
*>(this)->hashFor(kind
);
667 return jsCast
<const ScriptExecutable
*>(this)->hashFor(kind
);
670 CodeBlockHash
NativeExecutable::hashFor(CodeSpecializationKind kind
) const
672 if (kind
== CodeForCall
)
673 return CodeBlockHash(static_cast<unsigned>(bitwise_cast
<size_t>(m_function
)));
675 RELEASE_ASSERT(kind
== CodeForConstruct
);
676 return CodeBlockHash(static_cast<unsigned>(bitwise_cast
<size_t>(m_constructor
)));
679 CodeBlockHash
ScriptExecutable::hashFor(CodeSpecializationKind kind
) const
681 return CodeBlockHash(source(), kind
);