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.
27 #include "Executable.h"
29 #include "BatchedTransitionOptimizer.h"
30 #include "BytecodeGenerator.h"
31 #include "CodeBlock.h"
32 #include "DFGDriver.h"
34 #include "LLIntEntrypoint.h"
35 #include "JSCInlines.h"
37 #include "ProfilerDatabase.h"
38 #include <wtf/CommaPrinter.h>
39 #include <wtf/Vector.h>
40 #include <wtf/text/StringBuilder.h>
44 const ClassInfo
ExecutableBase::s_info
= { "Executable", 0, 0, 0, CREATE_METHOD_TABLE(ExecutableBase
) };
47 void ExecutableBase::destroy(JSCell
* cell
)
49 static_cast<ExecutableBase
*>(cell
)->ExecutableBase::~ExecutableBase();
53 void ExecutableBase::clearCode()
56 m_jitCodeForCall
.clear();
57 m_jitCodeForConstruct
.clear();
58 m_jitCodeForCallWithArityCheck
= MacroAssemblerCodePtr();
59 m_jitCodeForConstructWithArityCheck
= MacroAssemblerCodePtr();
60 m_jitCodeForCallWithArityCheckAndPreserveRegs
= MacroAssemblerCodePtr();
61 m_jitCodeForConstructWithArityCheckAndPreserveRegs
= MacroAssemblerCodePtr();
63 m_numParametersForCall
= NUM_PARAMETERS_NOT_COMPILED
;
64 m_numParametersForConstruct
= NUM_PARAMETERS_NOT_COMPILED
;
68 Intrinsic
ExecutableBase::intrinsic() const
70 if (const NativeExecutable
* nativeExecutable
= jsDynamicCast
<const NativeExecutable
*>(this))
71 return nativeExecutable
->intrinsic();
75 Intrinsic
ExecutableBase::intrinsic() const
81 const ClassInfo
NativeExecutable::s_info
= { "NativeExecutable", &ExecutableBase::s_info
, 0, 0, CREATE_METHOD_TABLE(NativeExecutable
) };
84 void NativeExecutable::destroy(JSCell
* cell
)
86 static_cast<NativeExecutable
*>(cell
)->NativeExecutable::~NativeExecutable();
91 Intrinsic
NativeExecutable::intrinsic() const
97 const ClassInfo
ScriptExecutable::s_info
= { "ScriptExecutable", &ExecutableBase::s_info
, 0, 0, CREATE_METHOD_TABLE(ScriptExecutable
) };
100 void ScriptExecutable::destroy(JSCell
* cell
)
102 static_cast<ScriptExecutable
*>(cell
)->ScriptExecutable::~ScriptExecutable();
106 void ScriptExecutable::installCode(CodeBlock
* genericCodeBlock
)
108 RELEASE_ASSERT(genericCodeBlock
->ownerExecutable() == this);
109 RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock
->jitType()));
111 VM
& vm
= *genericCodeBlock
->vm();
113 if (vm
.m_perBytecodeProfiler
)
114 vm
.m_perBytecodeProfiler
->ensureBytecodesFor(genericCodeBlock
);
116 ASSERT(vm
.heap
.isDeferred());
118 CodeSpecializationKind kind
= genericCodeBlock
->specializationKind();
120 RefPtr
<CodeBlock
> oldCodeBlock
;
124 m_jitCodeForCall
= genericCodeBlock
->jitCode();
125 m_jitCodeForCallWithArityCheck
= MacroAssemblerCodePtr();
126 m_jitCodeForCallWithArityCheckAndPreserveRegs
= MacroAssemblerCodePtr();
127 m_numParametersForCall
= genericCodeBlock
->numParameters();
129 case CodeForConstruct
:
130 m_jitCodeForConstruct
= genericCodeBlock
->jitCode();
131 m_jitCodeForConstructWithArityCheck
= MacroAssemblerCodePtr();
132 m_jitCodeForConstructWithArityCheckAndPreserveRegs
= MacroAssemblerCodePtr();
133 m_numParametersForConstruct
= genericCodeBlock
->numParameters();
137 switch (genericCodeBlock
->codeType()) {
139 ProgramExecutable
* executable
= jsCast
<ProgramExecutable
*>(this);
140 ProgramCodeBlock
* codeBlock
= static_cast<ProgramCodeBlock
*>(genericCodeBlock
);
142 ASSERT(kind
== CodeForCall
);
144 oldCodeBlock
= executable
->m_programCodeBlock
;
145 executable
->m_programCodeBlock
= codeBlock
;
150 EvalExecutable
* executable
= jsCast
<EvalExecutable
*>(this);
151 EvalCodeBlock
* codeBlock
= static_cast<EvalCodeBlock
*>(genericCodeBlock
);
153 ASSERT(kind
== CodeForCall
);
155 oldCodeBlock
= executable
->m_evalCodeBlock
;
156 executable
->m_evalCodeBlock
= codeBlock
;
161 FunctionExecutable
* executable
= jsCast
<FunctionExecutable
*>(this);
162 FunctionCodeBlock
* codeBlock
= static_cast<FunctionCodeBlock
*>(genericCodeBlock
);
166 oldCodeBlock
= executable
->m_codeBlockForCall
;
167 executable
->m_codeBlockForCall
= codeBlock
;
169 case CodeForConstruct
:
170 oldCodeBlock
= executable
->m_codeBlockForConstruct
;
171 executable
->m_codeBlockForConstruct
= codeBlock
;
178 oldCodeBlock
->unlinkIncomingCalls();
180 Debugger
* debugger
= genericCodeBlock
->globalObject()->debugger();
182 debugger
->registerCodeBlock(genericCodeBlock
);
184 Heap::heap(this)->writeBarrier(this);
187 PassRefPtr
<CodeBlock
> ScriptExecutable::newCodeBlockFor(
188 CodeSpecializationKind kind
, JSFunction
* function
, JSScope
** scope
, JSObject
*& exception
)
190 VM
* vm
= (*scope
)->vm();
192 ASSERT(vm
->heap
.isDeferred());
193 ASSERT(startColumn() != UINT_MAX
);
194 ASSERT(endColumn() != UINT_MAX
);
196 if (classInfo() == EvalExecutable::info()) {
197 EvalExecutable
* executable
= jsCast
<EvalExecutable
*>(this);
198 RELEASE_ASSERT(kind
== CodeForCall
);
199 RELEASE_ASSERT(!executable
->m_evalCodeBlock
);
200 RELEASE_ASSERT(!function
);
201 return adoptRef(new EvalCodeBlock(
202 executable
, executable
->m_unlinkedEvalCodeBlock
.get(), *scope
,
203 executable
->source().provider()));
206 if (classInfo() == ProgramExecutable::info()) {
207 ProgramExecutable
* executable
= jsCast
<ProgramExecutable
*>(this);
208 RELEASE_ASSERT(kind
== CodeForCall
);
209 RELEASE_ASSERT(!executable
->m_programCodeBlock
);
210 RELEASE_ASSERT(!function
);
211 return adoptRef(new ProgramCodeBlock(
212 executable
, executable
->m_unlinkedProgramCodeBlock
.get(), *scope
,
213 executable
->source().provider(), executable
->source().startColumn()));
216 RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
217 RELEASE_ASSERT(function
);
218 FunctionExecutable
* executable
= jsCast
<FunctionExecutable
*>(this);
219 RELEASE_ASSERT(!executable
->codeBlockFor(kind
));
220 JSGlobalObject
* globalObject
= (*scope
)->globalObject();
222 DebuggerMode debuggerMode
= globalObject
->hasDebugger() ? DebuggerOn
: DebuggerOff
;
223 ProfilerMode profilerMode
= globalObject
->hasProfiler() ? ProfilerOn
: ProfilerOff
;
224 UnlinkedFunctionCodeBlock
* unlinkedCodeBlock
=
225 executable
->m_unlinkedExecutable
->codeBlockFor(
226 *vm
, executable
->m_source
, kind
, debuggerMode
, profilerMode
, executable
->bodyIncludesBraces(), error
);
227 recordParse(executable
->m_unlinkedExecutable
->features(), executable
->m_unlinkedExecutable
->hasCapturedVariables(), lineNo(), lastLine(), startColumn(), endColumn());
228 if (!unlinkedCodeBlock
) {
229 exception
= vm
->throwException(
230 globalObject
->globalExec(),
231 error
.toErrorObject(globalObject
, executable
->m_source
));
235 // Parsing reveals whether our function uses features that require a separate function name object in the scope chain.
236 // Be sure to add this scope before linking the bytecode because this scope will change the resolution depth of non-local variables.
237 if (!executable
->m_didParseForTheFirstTime
) {
238 executable
->m_didParseForTheFirstTime
= true;
239 function
->addNameScopeIfNeeded(*vm
);
240 *scope
= function
->scope();
243 SourceProvider
* provider
= executable
->source().provider();
244 unsigned sourceOffset
= executable
->source().startOffset();
245 unsigned startColumn
= executable
->source().startColumn();
247 return adoptRef(new FunctionCodeBlock(
248 executable
, unlinkedCodeBlock
, *scope
, provider
, sourceOffset
, startColumn
));
251 PassRefPtr
<CodeBlock
> ScriptExecutable::newReplacementCodeBlockFor(
252 CodeSpecializationKind kind
)
254 if (classInfo() == EvalExecutable::info()) {
255 RELEASE_ASSERT(kind
== CodeForCall
);
256 EvalExecutable
* executable
= jsCast
<EvalExecutable
*>(this);
257 EvalCodeBlock
* baseline
= static_cast<EvalCodeBlock
*>(
258 executable
->m_evalCodeBlock
->baselineVersion());
259 RefPtr
<EvalCodeBlock
> result
= adoptRef(new EvalCodeBlock(
260 CodeBlock::CopyParsedBlock
, *baseline
));
261 result
->setAlternative(baseline
);
265 if (classInfo() == ProgramExecutable::info()) {
266 RELEASE_ASSERT(kind
== CodeForCall
);
267 ProgramExecutable
* executable
= jsCast
<ProgramExecutable
*>(this);
268 ProgramCodeBlock
* baseline
= static_cast<ProgramCodeBlock
*>(
269 executable
->m_programCodeBlock
->baselineVersion());
270 RefPtr
<ProgramCodeBlock
> result
= adoptRef(new ProgramCodeBlock(
271 CodeBlock::CopyParsedBlock
, *baseline
));
272 result
->setAlternative(baseline
);
276 RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
277 FunctionExecutable
* executable
= jsCast
<FunctionExecutable
*>(this);
278 FunctionCodeBlock
* baseline
= static_cast<FunctionCodeBlock
*>(
279 executable
->codeBlockFor(kind
)->baselineVersion());
280 RefPtr
<FunctionCodeBlock
> result
= adoptRef(new FunctionCodeBlock(
281 CodeBlock::CopyParsedBlock
, *baseline
));
282 result
->setAlternative(baseline
);
286 static void setupLLInt(VM
& vm
, CodeBlock
* codeBlock
)
288 LLInt::setEntrypoint(vm
, codeBlock
);
291 static void setupJIT(VM
& vm
, CodeBlock
* codeBlock
)
294 CompilationResult result
= JIT::compile(&vm
, codeBlock
, JITCompilationMustSucceed
);
295 RELEASE_ASSERT(result
== CompilationSuccessful
);
298 UNUSED_PARAM(codeBlock
);
299 UNREACHABLE_FOR_PLATFORM();
303 JSObject
* ScriptExecutable::prepareForExecutionImpl(
304 ExecState
* exec
, JSFunction
* function
, JSScope
** scope
, CodeSpecializationKind kind
)
307 DeferGC
deferGC(vm
.heap
);
309 JSObject
* exception
= 0;
310 RefPtr
<CodeBlock
> codeBlock
= newCodeBlockFor(kind
, function
, scope
, exception
);
312 RELEASE_ASSERT(exception
);
316 if (Options::validateBytecode())
317 codeBlock
->validate();
319 if (Options::useLLInt())
320 setupLLInt(vm
, codeBlock
.get());
322 setupJIT(vm
, codeBlock
.get());
324 installCode(codeBlock
.get());
328 const ClassInfo
EvalExecutable::s_info
= { "EvalExecutable", &ScriptExecutable::s_info
, 0, 0, CREATE_METHOD_TABLE(EvalExecutable
) };
330 EvalExecutable
* EvalExecutable::create(ExecState
* exec
, const SourceCode
& source
, bool isInStrictContext
)
332 JSGlobalObject
* globalObject
= exec
->lexicalGlobalObject();
333 if (!globalObject
->evalEnabled()) {
334 exec
->vm().throwException(exec
, createEvalError(exec
, globalObject
->evalDisabledErrorMessage()));
338 EvalExecutable
* executable
= new (NotNull
, allocateCell
<EvalExecutable
>(*exec
->heap())) EvalExecutable(exec
, source
, isInStrictContext
);
339 executable
->finishCreation(exec
->vm());
341 UnlinkedEvalCodeBlock
* unlinkedEvalCode
= globalObject
->createEvalCodeBlock(exec
, executable
);
342 if (!unlinkedEvalCode
)
345 executable
->m_unlinkedEvalCodeBlock
.set(exec
->vm(), executable
, unlinkedEvalCode
);
350 EvalExecutable::EvalExecutable(ExecState
* exec
, const SourceCode
& source
, bool inStrictContext
)
351 : ScriptExecutable(exec
->vm().evalExecutableStructure
.get(), exec
, source
, inStrictContext
)
355 void EvalExecutable::destroy(JSCell
* cell
)
357 static_cast<EvalExecutable
*>(cell
)->EvalExecutable::~EvalExecutable();
360 const ClassInfo
ProgramExecutable::s_info
= { "ProgramExecutable", &ScriptExecutable::s_info
, 0, 0, CREATE_METHOD_TABLE(ProgramExecutable
) };
362 ProgramExecutable::ProgramExecutable(ExecState
* exec
, const SourceCode
& source
)
363 : ScriptExecutable(exec
->vm().programExecutableStructure
.get(), exec
, source
, false)
367 void ProgramExecutable::destroy(JSCell
* cell
)
369 static_cast<ProgramExecutable
*>(cell
)->ProgramExecutable::~ProgramExecutable();
372 const ClassInfo
FunctionExecutable::s_info
= { "FunctionExecutable", &ScriptExecutable::s_info
, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable
) };
374 FunctionExecutable::FunctionExecutable(VM
& vm
, const SourceCode
& source
, UnlinkedFunctionExecutable
* unlinkedExecutable
, unsigned firstLine
, unsigned lastLine
, unsigned startColumn
, unsigned endColumn
, bool bodyIncludesBraces
)
375 : ScriptExecutable(vm
.functionExecutableStructure
.get(), vm
, source
, unlinkedExecutable
->isInStrictContext())
376 , m_unlinkedExecutable(vm
, this, unlinkedExecutable
)
377 , m_bodyIncludesBraces(bodyIncludesBraces
)
378 , m_didParseForTheFirstTime(false)
380 RELEASE_ASSERT(!source
.isNull());
381 ASSERT(source
.length());
382 m_firstLine
= firstLine
;
383 m_lastLine
= lastLine
;
384 ASSERT(startColumn
!= UINT_MAX
);
385 ASSERT(endColumn
!= UINT_MAX
);
386 m_startColumn
= startColumn
;
387 m_endColumn
= endColumn
;
390 void FunctionExecutable::destroy(JSCell
* cell
)
392 static_cast<FunctionExecutable
*>(cell
)->FunctionExecutable::~FunctionExecutable();
395 inline const char* samplingDescription(JITCode::JITType jitType
)
398 case JITCode::InterpreterThunk
:
399 return "Interpreter Compilation (TOTAL)";
400 case JITCode::BaselineJIT
:
401 return "Baseline Compilation (TOTAL)";
402 case JITCode::DFGJIT
:
403 return "DFG Compilation (TOTAL)";
404 case JITCode::FTLJIT
:
405 return "FTL Compilation (TOTAL)";
407 RELEASE_ASSERT_NOT_REACHED();
412 void EvalExecutable::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
414 EvalExecutable
* thisObject
= jsCast
<EvalExecutable
*>(cell
);
415 ASSERT_GC_OBJECT_INHERITS(thisObject
, info());
416 COMPILE_ASSERT(StructureFlags
& OverridesVisitChildren
, OverridesVisitChildrenWithoutSettingFlag
);
417 ASSERT(thisObject
->structure()->typeInfo().overridesVisitChildren());
418 ScriptExecutable::visitChildren(thisObject
, visitor
);
419 if (thisObject
->m_evalCodeBlock
)
420 thisObject
->m_evalCodeBlock
->visitAggregate(visitor
);
421 visitor
.append(&thisObject
->m_unlinkedEvalCodeBlock
);
424 void EvalExecutable::unlinkCalls()
427 if (!m_jitCodeForCall
)
429 RELEASE_ASSERT(m_evalCodeBlock
);
430 m_evalCodeBlock
->unlinkCalls();
434 void EvalExecutable::clearCode()
436 m_evalCodeBlock
.clear();
437 m_unlinkedEvalCodeBlock
.clear();
441 JSObject
* ProgramExecutable::checkSyntax(ExecState
* exec
)
444 VM
* vm
= &exec
->vm();
445 JSGlobalObject
* lexicalGlobalObject
= exec
->lexicalGlobalObject();
446 RefPtr
<ProgramNode
> programNode
= parse
<ProgramNode
>(vm
, m_source
, 0, Identifier(), JSParseNormal
, ProgramNode::isFunctionNode
? JSParseFunctionCode
: JSParseProgramCode
, error
);
449 ASSERT(error
.m_type
!= ParserError::ErrorNone
);
450 return error
.toErrorObject(lexicalGlobalObject
, m_source
);
453 void ProgramExecutable::unlinkCalls()
456 if (!m_jitCodeForCall
)
458 RELEASE_ASSERT(m_programCodeBlock
);
459 m_programCodeBlock
->unlinkCalls();
463 JSObject
* ProgramExecutable::initializeGlobalProperties(VM
& vm
, CallFrame
* callFrame
, JSScope
* scope
)
465 RELEASE_ASSERT(scope
);
466 JSGlobalObject
* globalObject
= scope
->globalObject();
467 RELEASE_ASSERT(globalObject
);
468 ASSERT(&globalObject
->vm() == &vm
);
470 JSObject
* exception
= 0;
471 UnlinkedProgramCodeBlock
* unlinkedCodeBlock
= globalObject
->createProgramCodeBlock(callFrame
, this, &exception
);
475 m_unlinkedProgramCodeBlock
.set(vm
, this, unlinkedCodeBlock
);
477 BatchedTransitionOptimizer
optimizer(vm
, globalObject
);
479 const UnlinkedProgramCodeBlock::VariableDeclations
& variableDeclarations
= unlinkedCodeBlock
->variableDeclarations();
480 const UnlinkedProgramCodeBlock::FunctionDeclations
& functionDeclarations
= unlinkedCodeBlock
->functionDeclarations();
482 for (size_t i
= 0; i
< functionDeclarations
.size(); ++i
) {
483 UnlinkedFunctionExecutable
* unlinkedFunctionExecutable
= functionDeclarations
[i
].second
.get();
484 JSValue value
= JSFunction::create(vm
, unlinkedFunctionExecutable
->link(vm
, m_source
, lineNo()), scope
);
485 globalObject
->addFunction(callFrame
, functionDeclarations
[i
].first
, value
);
488 for (size_t i
= 0; i
< variableDeclarations
.size(); ++i
) {
489 if (variableDeclarations
[i
].second
& DeclarationStacks::IsConstant
)
490 globalObject
->addConst(callFrame
, variableDeclarations
[i
].first
);
492 globalObject
->addVar(callFrame
, variableDeclarations
[i
].first
);
497 void ProgramExecutable::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
499 ProgramExecutable
* thisObject
= jsCast
<ProgramExecutable
*>(cell
);
500 ASSERT_GC_OBJECT_INHERITS(thisObject
, info());
501 COMPILE_ASSERT(StructureFlags
& OverridesVisitChildren
, OverridesVisitChildrenWithoutSettingFlag
);
502 ASSERT(thisObject
->structure()->typeInfo().overridesVisitChildren());
503 ScriptExecutable::visitChildren(thisObject
, visitor
);
504 visitor
.append(&thisObject
->m_unlinkedProgramCodeBlock
);
505 if (thisObject
->m_programCodeBlock
)
506 thisObject
->m_programCodeBlock
->visitAggregate(visitor
);
509 void ProgramExecutable::clearCode()
511 m_programCodeBlock
.clear();
512 m_unlinkedProgramCodeBlock
.clear();
516 FunctionCodeBlock
* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind
)
518 FunctionCodeBlock
* result
;
519 if (kind
== CodeForCall
)
520 result
= m_codeBlockForCall
.get();
522 RELEASE_ASSERT(kind
== CodeForConstruct
);
523 result
= m_codeBlockForConstruct
.get();
527 return static_cast<FunctionCodeBlock
*>(result
->baselineAlternative());
530 void FunctionExecutable::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
532 FunctionExecutable
* thisObject
= jsCast
<FunctionExecutable
*>(cell
);
533 ASSERT_GC_OBJECT_INHERITS(thisObject
, info());
534 COMPILE_ASSERT(StructureFlags
& OverridesVisitChildren
, OverridesVisitChildrenWithoutSettingFlag
);
535 ASSERT(thisObject
->structure()->typeInfo().overridesVisitChildren());
536 ScriptExecutable::visitChildren(thisObject
, visitor
);
537 if (thisObject
->m_codeBlockForCall
)
538 thisObject
->m_codeBlockForCall
->visitAggregate(visitor
);
539 if (thisObject
->m_codeBlockForConstruct
)
540 thisObject
->m_codeBlockForConstruct
->visitAggregate(visitor
);
541 visitor
.append(&thisObject
->m_unlinkedExecutable
);
544 SymbolTable
* FunctionExecutable::symbolTable(CodeSpecializationKind kind
)
546 return codeBlockFor(kind
)->symbolTable();
549 void FunctionExecutable::clearCodeIfNotCompiling()
556 void FunctionExecutable::clearUnlinkedCodeForRecompilationIfNotCompiling()
560 m_unlinkedExecutable
->clearCodeForRecompilation();
563 void FunctionExecutable::clearCode()
565 m_codeBlockForCall
.clear();
566 m_codeBlockForConstruct
.clear();
570 void FunctionExecutable::unlinkCalls()
573 if (!!m_jitCodeForCall
) {
574 RELEASE_ASSERT(m_codeBlockForCall
);
575 m_codeBlockForCall
->unlinkCalls();
577 if (!!m_jitCodeForConstruct
) {
578 RELEASE_ASSERT(m_codeBlockForConstruct
);
579 m_codeBlockForConstruct
->unlinkCalls();
584 FunctionExecutable
* FunctionExecutable::fromGlobalCode(const Identifier
& name
, ExecState
* exec
, Debugger
* debugger
, const SourceCode
& source
, JSObject
** exception
)
586 UnlinkedFunctionExecutable
* unlinkedExecutable
= UnlinkedFunctionExecutable::fromGlobalCode(name
, exec
, debugger
, source
, exception
);
587 if (!unlinkedExecutable
)
589 unsigned lineCount
= unlinkedExecutable
->lineCount();
590 unsigned firstLine
= source
.firstLine() + unlinkedExecutable
->firstLineOffset();
591 unsigned startOffset
= source
.startOffset() + unlinkedExecutable
->startOffset();
593 // We don't have any owner executable. The source string is effectively like a global
594 // string (like in the handling of eval). Hence, the startColumn is always 1.
595 unsigned startColumn
= 1;
596 unsigned sourceLength
= unlinkedExecutable
->sourceLength();
597 bool endColumnIsOnStartLine
= !lineCount
;
598 // The unlinkedBodyEndColumn is based-0. Hence, we need to add 1 to it. But if the
599 // endColumn is on the startLine, then we need to subtract back the adjustment for
600 // the open brace resulting in an adjustment of 0.
601 unsigned endColumnExcludingBraces
= unlinkedExecutable
->unlinkedBodyEndColumn() + (endColumnIsOnStartLine
? 0 : 1);
602 unsigned startOffsetExcludingOpenBrace
= startOffset
+ 1;
603 unsigned endOffsetExcludingCloseBrace
= startOffset
+ sourceLength
- 1;
604 SourceCode
bodySource(source
.provider(), startOffsetExcludingOpenBrace
, endOffsetExcludingCloseBrace
, firstLine
, startColumn
);
606 return FunctionExecutable::create(exec
->vm(), bodySource
, unlinkedExecutable
, firstLine
, firstLine
+ lineCount
, startColumn
, endColumnExcludingBraces
, false);
609 String
FunctionExecutable::paramString() const
611 return m_unlinkedExecutable
->paramString();
614 void ExecutableBase::dump(PrintStream
& out
) const
616 ExecutableBase
* realThis
= const_cast<ExecutableBase
*>(this);
618 if (classInfo() == NativeExecutable::info()) {
619 NativeExecutable
* native
= jsCast
<NativeExecutable
*>(realThis
);
620 out
.print("NativeExecutable:", RawPointer(bitwise_cast
<void*>(native
->function())), "/", RawPointer(bitwise_cast
<void*>(native
->constructor())));
624 if (classInfo() == EvalExecutable::info()) {
625 EvalExecutable
* eval
= jsCast
<EvalExecutable
*>(realThis
);
626 if (CodeBlock
* codeBlock
= eval
->codeBlock())
627 out
.print(*codeBlock
);
629 out
.print("EvalExecutable w/o CodeBlock");
633 if (classInfo() == ProgramExecutable::info()) {
634 ProgramExecutable
* eval
= jsCast
<ProgramExecutable
*>(realThis
);
635 if (CodeBlock
* codeBlock
= eval
->codeBlock())
636 out
.print(*codeBlock
);
638 out
.print("ProgramExecutable w/o CodeBlock");
642 FunctionExecutable
* function
= jsCast
<FunctionExecutable
*>(realThis
);
643 if (!function
->eitherCodeBlock())
644 out
.print("FunctionExecutable w/o CodeBlock");
646 CommaPrinter
comma("/");
647 if (function
->codeBlockForCall())
648 out
.print(comma
, *function
->codeBlockForCall());
649 if (function
->codeBlockForConstruct())
650 out
.print(comma
, *function
->codeBlockForConstruct());
654 CodeBlockHash
ExecutableBase::hashFor(CodeSpecializationKind kind
) const
656 if (this->classInfo() == NativeExecutable::info())
657 return jsCast
<const NativeExecutable
*>(this)->hashFor(kind
);
659 return jsCast
<const ScriptExecutable
*>(this)->hashFor(kind
);
662 CodeBlockHash
NativeExecutable::hashFor(CodeSpecializationKind kind
) const
664 if (kind
== CodeForCall
)
665 return CodeBlockHash(static_cast<unsigned>(bitwise_cast
<size_t>(m_function
)));
667 RELEASE_ASSERT(kind
== CodeForConstruct
);
668 return CodeBlockHash(static_cast<unsigned>(bitwise_cast
<size_t>(m_constructor
)));
671 CodeBlockHash
ScriptExecutable::hashFor(CodeSpecializationKind kind
) const
673 return CodeBlockHash(source(), kind
);