]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/Executable.cpp
JavaScriptCore-7600.1.4.9.tar.gz
[apple/javascriptcore.git] / runtime / Executable.cpp
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
42 namespace JSC {
43
44 const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0, CREATE_METHOD_TABLE(ExecutableBase) };
45
46 #if ENABLE(JIT)
47 void ExecutableBase::destroy(JSCell* cell)
48 {
49 static_cast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();
50 }
51 #endif
52
53 void 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)
68 Intrinsic ExecutableBase::intrinsic() const
69 {
70 if (const NativeExecutable* nativeExecutable = jsDynamicCast<const NativeExecutable*>(this))
71 return nativeExecutable->intrinsic();
72 return NoIntrinsic;
73 }
74 #else
75 Intrinsic ExecutableBase::intrinsic() const
76 {
77 return NoIntrinsic;
78 }
79 #endif
80
81 const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(NativeExecutable) };
82
83 #if ENABLE(JIT)
84 void NativeExecutable::destroy(JSCell* cell)
85 {
86 static_cast<NativeExecutable*>(cell)->NativeExecutable::~NativeExecutable();
87 }
88 #endif
89
90 #if ENABLE(DFG_JIT)
91 Intrinsic NativeExecutable::intrinsic() const
92 {
93 return m_intrinsic;
94 }
95 #endif
96
97 const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
98
99 #if ENABLE(JIT)
100 void ScriptExecutable::destroy(JSCell* cell)
101 {
102 static_cast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
103 }
104 #endif
105
106 void 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
187 PassRefPtr<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
251 PassRefPtr<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
286 static void setupLLInt(VM& vm, CodeBlock* codeBlock)
287 {
288 LLInt::setEntrypoint(vm, codeBlock);
289 }
290
291 static 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
303 JSObject* 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
328 const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(EvalExecutable) };
329
330 EvalExecutable* 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
350 EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
351 : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec, source, inStrictContext)
352 {
353 }
354
355 void EvalExecutable::destroy(JSCell* cell)
356 {
357 static_cast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable();
358 }
359
360 const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(ProgramExecutable) };
361
362 ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
363 : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec, source, false)
364 {
365 }
366
367 void ProgramExecutable::destroy(JSCell* cell)
368 {
369 static_cast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable();
370 }
371
372 const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
373
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)
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
390 void FunctionExecutable::destroy(JSCell* cell)
391 {
392 static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
393 }
394
395 inline 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
412 void 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
424 void 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
434 void EvalExecutable::clearCode()
435 {
436 m_evalCodeBlock.clear();
437 m_unlinkedEvalCodeBlock.clear();
438 Base::clearCode();
439 }
440
441 JSObject* 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
453 void 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
463 JSObject* 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
497 void 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
509 void ProgramExecutable::clearCode()
510 {
511 m_programCodeBlock.clear();
512 m_unlinkedProgramCodeBlock.clear();
513 Base::clearCode();
514 }
515
516 FunctionCodeBlock* 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
530 void 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
544 SymbolTable* FunctionExecutable::symbolTable(CodeSpecializationKind kind)
545 {
546 return codeBlockFor(kind)->symbolTable();
547 }
548
549 void FunctionExecutable::clearCodeIfNotCompiling()
550 {
551 if (isCompiling())
552 return;
553 clearCode();
554 }
555
556 void FunctionExecutable::clearUnlinkedCodeForRecompilationIfNotCompiling()
557 {
558 if (isCompiling())
559 return;
560 m_unlinkedExecutable->clearCodeForRecompilation();
561 }
562
563 void FunctionExecutable::clearCode()
564 {
565 m_codeBlockForCall.clear();
566 m_codeBlockForConstruct.clear();
567 Base::clearCode();
568 }
569
570 void 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
584 FunctionExecutable* 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
609 String FunctionExecutable::paramString() const
610 {
611 return m_unlinkedExecutable->paramString();
612 }
613
614 void 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
654 CodeBlockHash 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
662 CodeBlockHash 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
671 CodeBlockHash ScriptExecutable::hashFor(CodeSpecializationKind kind) const
672 {
673 return CodeBlockHash(source(), kind);
674 }
675
676 }