]> git.saurik.com Git - apple/javascriptcore.git/blame_incremental - runtime/Executable.cpp
JavaScriptCore-7600.1.4.11.8.tar.gz
[apple/javascriptcore.git] / runtime / Executable.cpp
... / ...
CommitLineData
1/*
2 * Copyright (C) 2009, 2010, 2013 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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.
24 */
25
26#include "config.h"
27#include "Executable.h"
28
29#include "BatchedTransitionOptimizer.h"
30#include "BytecodeGenerator.h"
31#include "CodeBlock.h"
32#include "DFGDriver.h"
33#include "JIT.h"
34#include "LLIntEntrypoint.h"
35#include "JSCInlines.h"
36#include "Parser.h"
37#include "ProfilerDatabase.h"
38#include <wtf/CommaPrinter.h>
39#include <wtf/Vector.h>
40#include <wtf/text/StringBuilder.h>
41
42namespace JSC {
43
44const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0, CREATE_METHOD_TABLE(ExecutableBase) };
45
46#if ENABLE(JIT)
47void ExecutableBase::destroy(JSCell* cell)
48{
49 static_cast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();
50}
51#endif
52
53void ExecutableBase::clearCode()
54{
55#if ENABLE(JIT)
56 m_jitCodeForCall.clear();
57 m_jitCodeForConstruct.clear();
58 m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
59 m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
60 m_jitCodeForCallWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
61 m_jitCodeForConstructWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
62#endif
63 m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
64 m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
65}
66
67#if ENABLE(DFG_JIT)
68Intrinsic ExecutableBase::intrinsic() const
69{
70 if (const NativeExecutable* nativeExecutable = jsDynamicCast<const NativeExecutable*>(this))
71 return nativeExecutable->intrinsic();
72 return NoIntrinsic;
73}
74#else
75Intrinsic ExecutableBase::intrinsic() const
76{
77 return NoIntrinsic;
78}
79#endif
80
81const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(NativeExecutable) };
82
83#if ENABLE(JIT)
84void NativeExecutable::destroy(JSCell* cell)
85{
86 static_cast<NativeExecutable*>(cell)->NativeExecutable::~NativeExecutable();
87}
88#endif
89
90#if ENABLE(DFG_JIT)
91Intrinsic NativeExecutable::intrinsic() const
92{
93 return m_intrinsic;
94}
95#endif
96
97const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
98
99#if ENABLE(JIT)
100void ScriptExecutable::destroy(JSCell* cell)
101{
102 static_cast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
103}
104#endif
105
106void ScriptExecutable::installCode(CodeBlock* genericCodeBlock)
107{
108 RELEASE_ASSERT(genericCodeBlock->ownerExecutable() == this);
109 RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock->jitType()));
110
111 VM& vm = *genericCodeBlock->vm();
112
113 if (vm.m_perBytecodeProfiler)
114 vm.m_perBytecodeProfiler->ensureBytecodesFor(genericCodeBlock);
115
116 ASSERT(vm.heap.isDeferred());
117
118 CodeSpecializationKind kind = genericCodeBlock->specializationKind();
119
120 RefPtr<CodeBlock> oldCodeBlock;
121
122 switch (kind) {
123 case CodeForCall:
124 m_jitCodeForCall = genericCodeBlock->jitCode();
125 m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
126 m_jitCodeForCallWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
127 m_numParametersForCall = genericCodeBlock->numParameters();
128 break;
129 case CodeForConstruct:
130 m_jitCodeForConstruct = genericCodeBlock->jitCode();
131 m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
132 m_jitCodeForConstructWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
133 m_numParametersForConstruct = genericCodeBlock->numParameters();
134 break;
135 }
136
137 switch (genericCodeBlock->codeType()) {
138 case GlobalCode: {
139 ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
140 ProgramCodeBlock* codeBlock = static_cast<ProgramCodeBlock*>(genericCodeBlock);
141
142 ASSERT(kind == CodeForCall);
143
144 oldCodeBlock = executable->m_programCodeBlock;
145 executable->m_programCodeBlock = codeBlock;
146 break;
147 }
148
149 case EvalCode: {
150 EvalExecutable* executable = jsCast<EvalExecutable*>(this);
151 EvalCodeBlock* codeBlock = static_cast<EvalCodeBlock*>(genericCodeBlock);
152
153 ASSERT(kind == CodeForCall);
154
155 oldCodeBlock = executable->m_evalCodeBlock;
156 executable->m_evalCodeBlock = codeBlock;
157 break;
158 }
159
160 case FunctionCode: {
161 FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
162 FunctionCodeBlock* codeBlock = static_cast<FunctionCodeBlock*>(genericCodeBlock);
163
164 switch (kind) {
165 case CodeForCall:
166 oldCodeBlock = executable->m_codeBlockForCall;
167 executable->m_codeBlockForCall = codeBlock;
168 break;
169 case CodeForConstruct:
170 oldCodeBlock = executable->m_codeBlockForConstruct;
171 executable->m_codeBlockForConstruct = codeBlock;
172 break;
173 }
174 break;
175 } }
176
177 if (oldCodeBlock)
178 oldCodeBlock->unlinkIncomingCalls();
179
180 Debugger* debugger = genericCodeBlock->globalObject()->debugger();
181 if (debugger)
182 debugger->registerCodeBlock(genericCodeBlock);
183
184 Heap::heap(this)->writeBarrier(this);
185}
186
187PassRefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor(
188 CodeSpecializationKind kind, JSFunction* function, JSScope** scope, JSObject*& exception)
189{
190 VM* vm = (*scope)->vm();
191
192 ASSERT(vm->heap.isDeferred());
193 ASSERT(startColumn() != UINT_MAX);
194 ASSERT(endColumn() != UINT_MAX);
195
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()));
204 }
205
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()));
214 }
215
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();
221 ParserError error;
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));
232 return 0;
233 }
234
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();
241 }
242
243 SourceProvider* provider = executable->source().provider();
244 unsigned sourceOffset = executable->source().startOffset();
245 unsigned startColumn = executable->source().startColumn();
246
247 return adoptRef(new FunctionCodeBlock(
248 executable, unlinkedCodeBlock, *scope, provider, sourceOffset, startColumn));
249}
250
251PassRefPtr<CodeBlock> ScriptExecutable::newReplacementCodeBlockFor(
252 CodeSpecializationKind kind)
253{
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);
262 return result;
263 }
264
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);
273 return result;
274 }
275
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);
283 return result;
284}
285
286static void setupLLInt(VM& vm, CodeBlock* codeBlock)
287{
288 LLInt::setEntrypoint(vm, codeBlock);
289}
290
291static void setupJIT(VM& vm, CodeBlock* codeBlock)
292{
293#if ENABLE(JIT)
294 CompilationResult result = JIT::compile(&vm, codeBlock, JITCompilationMustSucceed);
295 RELEASE_ASSERT(result == CompilationSuccessful);
296#else
297 UNUSED_PARAM(vm);
298 UNUSED_PARAM(codeBlock);
299 UNREACHABLE_FOR_PLATFORM();
300#endif
301}
302
303JSObject* ScriptExecutable::prepareForExecutionImpl(
304 ExecState* exec, JSFunction* function, JSScope** scope, CodeSpecializationKind kind)
305{
306 VM& vm = exec->vm();
307 DeferGC deferGC(vm.heap);
308
309 JSObject* exception = 0;
310 RefPtr<CodeBlock> codeBlock = newCodeBlockFor(kind, function, scope, exception);
311 if (!codeBlock) {
312 RELEASE_ASSERT(exception);
313 return exception;
314 }
315
316 if (Options::validateBytecode())
317 codeBlock->validate();
318
319 if (Options::useLLInt())
320 setupLLInt(vm, codeBlock.get());
321 else
322 setupJIT(vm, codeBlock.get());
323
324 installCode(codeBlock.get());
325 return 0;
326}
327
328const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(EvalExecutable) };
329
330EvalExecutable* EvalExecutable::create(ExecState* exec, const SourceCode& source, bool isInStrictContext)
331{
332 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
333 if (!globalObject->evalEnabled()) {
334 exec->vm().throwException(exec, createEvalError(exec, globalObject->evalDisabledErrorMessage()));
335 return 0;
336 }
337
338 EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext);
339 executable->finishCreation(exec->vm());
340
341 UnlinkedEvalCodeBlock* unlinkedEvalCode = globalObject->createEvalCodeBlock(exec, executable);
342 if (!unlinkedEvalCode)
343 return 0;
344
345 executable->m_unlinkedEvalCodeBlock.set(exec->vm(), executable, unlinkedEvalCode);
346
347 return executable;
348}
349
350EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
351 : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec, source, inStrictContext)
352{
353}
354
355void EvalExecutable::destroy(JSCell* cell)
356{
357 static_cast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable();
358}
359
360const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(ProgramExecutable) };
361
362ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
363 : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec, source, false)
364{
365}
366
367void ProgramExecutable::destroy(JSCell* cell)
368{
369 static_cast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable();
370}
371
372const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
373
374FunctionExecutable::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)
379{
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;
388}
389
390void FunctionExecutable::destroy(JSCell* cell)
391{
392 static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
393}
394
395inline const char* samplingDescription(JITCode::JITType jitType)
396{
397 switch (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)";
406 default:
407 RELEASE_ASSERT_NOT_REACHED();
408 return 0;
409 }
410}
411
412void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
413{
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);
422}
423
424void EvalExecutable::unlinkCalls()
425{
426#if ENABLE(JIT)
427 if (!m_jitCodeForCall)
428 return;
429 RELEASE_ASSERT(m_evalCodeBlock);
430 m_evalCodeBlock->unlinkCalls();
431#endif
432}
433
434void EvalExecutable::clearCode()
435{
436 m_evalCodeBlock.clear();
437 m_unlinkedEvalCodeBlock.clear();
438 Base::clearCode();
439}
440
441JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
442{
443 ParserError error;
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);
447 if (programNode)
448 return 0;
449 ASSERT(error.m_type != ParserError::ErrorNone);
450 return error.toErrorObject(lexicalGlobalObject, m_source);
451}
452
453void ProgramExecutable::unlinkCalls()
454{
455#if ENABLE(JIT)
456 if (!m_jitCodeForCall)
457 return;
458 RELEASE_ASSERT(m_programCodeBlock);
459 m_programCodeBlock->unlinkCalls();
460#endif
461}
462
463JSObject* ProgramExecutable::initializeGlobalProperties(VM& vm, CallFrame* callFrame, JSScope* scope)
464{
465 RELEASE_ASSERT(scope);
466 JSGlobalObject* globalObject = scope->globalObject();
467 RELEASE_ASSERT(globalObject);
468 ASSERT(&globalObject->vm() == &vm);
469
470 JSObject* exception = 0;
471 UnlinkedProgramCodeBlock* unlinkedCodeBlock = globalObject->createProgramCodeBlock(callFrame, this, &exception);
472 if (exception)
473 return exception;
474
475 m_unlinkedProgramCodeBlock.set(vm, this, unlinkedCodeBlock);
476
477 BatchedTransitionOptimizer optimizer(vm, globalObject);
478
479 const UnlinkedProgramCodeBlock::VariableDeclations& variableDeclarations = unlinkedCodeBlock->variableDeclarations();
480 const UnlinkedProgramCodeBlock::FunctionDeclations& functionDeclarations = unlinkedCodeBlock->functionDeclarations();
481
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);
486 }
487
488 for (size_t i = 0; i < variableDeclarations.size(); ++i) {
489 if (variableDeclarations[i].second & DeclarationStacks::IsConstant)
490 globalObject->addConst(callFrame, variableDeclarations[i].first);
491 else
492 globalObject->addVar(callFrame, variableDeclarations[i].first);
493 }
494 return 0;
495}
496
497void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
498{
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);
507}
508
509void ProgramExecutable::clearCode()
510{
511 m_programCodeBlock.clear();
512 m_unlinkedProgramCodeBlock.clear();
513 Base::clearCode();
514}
515
516FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
517{
518 FunctionCodeBlock* result;
519 if (kind == CodeForCall)
520 result = m_codeBlockForCall.get();
521 else {
522 RELEASE_ASSERT(kind == CodeForConstruct);
523 result = m_codeBlockForConstruct.get();
524 }
525 if (!result)
526 return 0;
527 return static_cast<FunctionCodeBlock*>(result->baselineAlternative());
528}
529
530void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
531{
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);
542}
543
544SymbolTable* FunctionExecutable::symbolTable(CodeSpecializationKind kind)
545{
546 return codeBlockFor(kind)->symbolTable();
547}
548
549void FunctionExecutable::clearCodeIfNotCompiling()
550{
551 if (isCompiling())
552 return;
553 clearCode();
554}
555
556void FunctionExecutable::clearUnlinkedCodeForRecompilationIfNotCompiling()
557{
558 if (isCompiling())
559 return;
560 m_unlinkedExecutable->clearCodeForRecompilation();
561}
562
563void FunctionExecutable::clearCode()
564{
565 m_codeBlockForCall.clear();
566 m_codeBlockForConstruct.clear();
567 Base::clearCode();
568}
569
570void FunctionExecutable::unlinkCalls()
571{
572#if ENABLE(JIT)
573 if (!!m_jitCodeForCall) {
574 RELEASE_ASSERT(m_codeBlockForCall);
575 m_codeBlockForCall->unlinkCalls();
576 }
577 if (!!m_jitCodeForConstruct) {
578 RELEASE_ASSERT(m_codeBlockForConstruct);
579 m_codeBlockForConstruct->unlinkCalls();
580 }
581#endif
582}
583
584FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
585{
586 UnlinkedFunctionExecutable* unlinkedExecutable = UnlinkedFunctionExecutable::fromGlobalCode(name, exec, debugger, source, exception);
587 if (!unlinkedExecutable)
588 return 0;
589 unsigned lineCount = unlinkedExecutable->lineCount();
590 unsigned firstLine = source.firstLine() + unlinkedExecutable->firstLineOffset();
591 unsigned startOffset = source.startOffset() + unlinkedExecutable->startOffset();
592
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);
605
606 return FunctionExecutable::create(exec->vm(), bodySource, unlinkedExecutable, firstLine, firstLine + lineCount, startColumn, endColumnExcludingBraces, false);
607}
608
609String FunctionExecutable::paramString() const
610{
611 return m_unlinkedExecutable->paramString();
612}
613
614void ExecutableBase::dump(PrintStream& out) const
615{
616 ExecutableBase* realThis = const_cast<ExecutableBase*>(this);
617
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())));
621 return;
622 }
623
624 if (classInfo() == EvalExecutable::info()) {
625 EvalExecutable* eval = jsCast<EvalExecutable*>(realThis);
626 if (CodeBlock* codeBlock = eval->codeBlock())
627 out.print(*codeBlock);
628 else
629 out.print("EvalExecutable w/o CodeBlock");
630 return;
631 }
632
633 if (classInfo() == ProgramExecutable::info()) {
634 ProgramExecutable* eval = jsCast<ProgramExecutable*>(realThis);
635 if (CodeBlock* codeBlock = eval->codeBlock())
636 out.print(*codeBlock);
637 else
638 out.print("ProgramExecutable w/o CodeBlock");
639 return;
640 }
641
642 FunctionExecutable* function = jsCast<FunctionExecutable*>(realThis);
643 if (!function->eitherCodeBlock())
644 out.print("FunctionExecutable w/o CodeBlock");
645 else {
646 CommaPrinter comma("/");
647 if (function->codeBlockForCall())
648 out.print(comma, *function->codeBlockForCall());
649 if (function->codeBlockForConstruct())
650 out.print(comma, *function->codeBlockForConstruct());
651 }
652}
653
654CodeBlockHash ExecutableBase::hashFor(CodeSpecializationKind kind) const
655{
656 if (this->classInfo() == NativeExecutable::info())
657 return jsCast<const NativeExecutable*>(this)->hashFor(kind);
658
659 return jsCast<const ScriptExecutable*>(this)->hashFor(kind);
660}
661
662CodeBlockHash NativeExecutable::hashFor(CodeSpecializationKind kind) const
663{
664 if (kind == CodeForCall)
665 return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_function)));
666
667 RELEASE_ASSERT(kind == CodeForConstruct);
668 return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_constructor)));
669}
670
671CodeBlockHash ScriptExecutable::hashFor(CodeSpecializationKind kind) const
672{
673 return CodeBlockHash(source(), kind);
674}
675
676}