Remove the unused *Executable::unlinkCalls() and CodeBlock::unlinkCalls()
[WebKit-https.git] / Source / JavaScriptCore / runtime / Executable.cpp
1 /*
2  * Copyright (C) 2009, 2010, 2013, 2015 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 "CodeBlock.h"
31 #include "DFGDriver.h"
32 #include "JIT.h"
33 #include "JSCInlines.h"
34 #include "LLIntEntrypoint.h"
35 #include "Parser.h"
36 #include "ProfilerDatabase.h"
37 #include "TypeProfiler.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, CREATE_METHOD_TABLE(ExecutableBase) };
45
46 void ExecutableBase::destroy(JSCell* cell)
47 {
48     static_cast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();
49 }
50
51 void ExecutableBase::clearCode()
52 {
53 #if ENABLE(JIT)
54     m_jitCodeForCall = nullptr;
55     m_jitCodeForConstruct = nullptr;
56     m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
57     m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
58     m_jitCodeForCallWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
59     m_jitCodeForConstructWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
60 #endif
61     m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
62     m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
63 }
64
65 #if ENABLE(DFG_JIT)
66 Intrinsic ExecutableBase::intrinsic() const
67 {
68     if (const NativeExecutable* nativeExecutable = jsDynamicCast<const NativeExecutable*>(this))
69         return nativeExecutable->intrinsic();
70     return NoIntrinsic;
71 }
72 #else
73 Intrinsic ExecutableBase::intrinsic() const
74 {
75     return NoIntrinsic;
76 }
77 #endif
78
79 const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, CREATE_METHOD_TABLE(NativeExecutable) };
80
81 void NativeExecutable::destroy(JSCell* cell)
82 {
83     static_cast<NativeExecutable*>(cell)->NativeExecutable::~NativeExecutable();
84 }
85
86 #if ENABLE(DFG_JIT)
87 Intrinsic NativeExecutable::intrinsic() const
88 {
89     return m_intrinsic;
90 }
91 #endif
92
93 const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
94
95 ScriptExecutable::ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext)
96     : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED)
97     , m_source(source)
98     , m_features(isInStrictContext ? StrictModeFeature : 0)
99     , m_hasCapturedVariables(false)
100     , m_neverInline(false)
101     , m_didTryToEnterInLoop(false)
102     , m_overrideLineNumber(-1)
103     , m_firstLine(-1)
104     , m_lastLine(-1)
105     , m_startColumn(UINT_MAX)
106     , m_endColumn(UINT_MAX)
107     , m_typeProfilingStartOffset(UINT_MAX)
108     , m_typeProfilingEndOffset(UINT_MAX)
109 {
110 }
111
112 void ScriptExecutable::destroy(JSCell* cell)
113 {
114     static_cast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
115 }
116
117 void ScriptExecutable::installCode(CodeBlock* genericCodeBlock)
118 {
119     RELEASE_ASSERT(genericCodeBlock->ownerExecutable() == this);
120     RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock->jitType()));
121     
122     if (Options::verboseOSR())
123         dataLog("Installing ", *genericCodeBlock, "\n");
124     
125     VM& vm = *genericCodeBlock->vm();
126     
127     if (vm.m_perBytecodeProfiler)
128         vm.m_perBytecodeProfiler->ensureBytecodesFor(genericCodeBlock);
129     
130     ASSERT(vm.heap.isDeferred());
131     
132     CodeSpecializationKind kind = genericCodeBlock->specializationKind();
133     
134     RefPtr<CodeBlock> oldCodeBlock;
135     
136     switch (kind) {
137     case CodeForCall:
138         m_jitCodeForCall = genericCodeBlock->jitCode();
139         m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
140         m_jitCodeForCallWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
141         m_numParametersForCall = genericCodeBlock->numParameters();
142         break;
143     case CodeForConstruct:
144         m_jitCodeForConstruct = genericCodeBlock->jitCode();
145         m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
146         m_jitCodeForConstructWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
147         m_numParametersForConstruct = genericCodeBlock->numParameters();
148         break;
149     }
150     
151     switch (genericCodeBlock->codeType()) {
152     case GlobalCode: {
153         ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
154         ProgramCodeBlock* codeBlock = static_cast<ProgramCodeBlock*>(genericCodeBlock);
155         
156         ASSERT(kind == CodeForCall);
157         
158         oldCodeBlock = executable->m_programCodeBlock;
159         executable->m_programCodeBlock = codeBlock;
160         break;
161     }
162         
163     case EvalCode: {
164         EvalExecutable* executable = jsCast<EvalExecutable*>(this);
165         EvalCodeBlock* codeBlock = static_cast<EvalCodeBlock*>(genericCodeBlock);
166         
167         ASSERT(kind == CodeForCall);
168         
169         oldCodeBlock = executable->m_evalCodeBlock;
170         executable->m_evalCodeBlock = codeBlock;
171         break;
172     }
173         
174     case FunctionCode: {
175         FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
176         FunctionCodeBlock* codeBlock = static_cast<FunctionCodeBlock*>(genericCodeBlock);
177         
178         switch (kind) {
179         case CodeForCall:
180             oldCodeBlock = executable->m_codeBlockForCall;
181             executable->m_codeBlockForCall = codeBlock;
182             break;
183         case CodeForConstruct:
184             oldCodeBlock = executable->m_codeBlockForConstruct;
185             executable->m_codeBlockForConstruct = codeBlock;
186             break;
187         }
188         break;
189     } }
190
191     if (oldCodeBlock)
192         oldCodeBlock->unlinkIncomingCalls();
193
194     Debugger* debugger = genericCodeBlock->globalObject()->debugger();
195     if (debugger)
196         debugger->registerCodeBlock(genericCodeBlock);
197
198     Heap::heap(this)->writeBarrier(this);
199 }
200
201 RefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor(
202     CodeSpecializationKind kind, JSFunction* function, JSScope* scope, JSObject*& exception)
203 {
204     VM* vm = scope->vm();
205
206     ASSERT(vm->heap.isDeferred());
207     ASSERT(startColumn() != UINT_MAX);
208     ASSERT(endColumn() != UINT_MAX);
209
210     if (classInfo() == EvalExecutable::info()) {
211         EvalExecutable* executable = jsCast<EvalExecutable*>(this);
212         RELEASE_ASSERT(kind == CodeForCall);
213         RELEASE_ASSERT(!executable->m_evalCodeBlock);
214         RELEASE_ASSERT(!function);
215         return adoptRef(new EvalCodeBlock(
216             executable, executable->m_unlinkedEvalCodeBlock.get(), scope,
217             executable->source().provider()));
218     }
219     
220     if (classInfo() == ProgramExecutable::info()) {
221         ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
222         RELEASE_ASSERT(kind == CodeForCall);
223         RELEASE_ASSERT(!executable->m_programCodeBlock);
224         RELEASE_ASSERT(!function);
225         return adoptRef(new ProgramCodeBlock(
226             executable, executable->m_unlinkedProgramCodeBlock.get(), scope,
227             executable->source().provider(), executable->source().startColumn()));
228     }
229     
230     RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
231     RELEASE_ASSERT(function);
232     FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
233     RELEASE_ASSERT(!executable->codeBlockFor(kind));
234     JSGlobalObject* globalObject = scope->globalObject();
235     ParserError error;
236     DebuggerMode debuggerMode = globalObject->hasDebugger() ? DebuggerOn : DebuggerOff;
237     ProfilerMode profilerMode = globalObject->hasProfiler() ? ProfilerOn : ProfilerOff;
238     UnlinkedFunctionCodeBlock* unlinkedCodeBlock = 
239         executable->m_unlinkedExecutable->unlinkedCodeBlockFor(
240             *vm, executable->m_source, kind, debuggerMode, profilerMode, error, 
241             executable->isArrowFunction());
242     recordParse(
243         executable->m_unlinkedExecutable->features(), 
244         executable->m_unlinkedExecutable->hasCapturedVariables(), firstLine(), 
245         lastLine(), startColumn(), endColumn()); 
246     if (!unlinkedCodeBlock) {
247         exception = vm->throwException(
248             globalObject->globalExec(),
249             error.toErrorObject(globalObject, executable->m_source));
250         return nullptr;
251     }
252
253     SourceProvider* provider = executable->source().provider();
254     unsigned sourceOffset = executable->source().startOffset();
255     unsigned startColumn = executable->source().startColumn();
256
257     return adoptRef(new FunctionCodeBlock(
258         executable, unlinkedCodeBlock, scope, provider, sourceOffset, startColumn));
259 }
260
261 PassRefPtr<CodeBlock> ScriptExecutable::newReplacementCodeBlockFor(
262     CodeSpecializationKind kind)
263 {
264     if (classInfo() == EvalExecutable::info()) {
265         RELEASE_ASSERT(kind == CodeForCall);
266         EvalExecutable* executable = jsCast<EvalExecutable*>(this);
267         EvalCodeBlock* baseline = static_cast<EvalCodeBlock*>(
268             executable->m_evalCodeBlock->baselineVersion());
269         RefPtr<EvalCodeBlock> result = adoptRef(new EvalCodeBlock(
270             CodeBlock::CopyParsedBlock, *baseline));
271         result->setAlternative(baseline);
272         return result;
273     }
274     
275     if (classInfo() == ProgramExecutable::info()) {
276         RELEASE_ASSERT(kind == CodeForCall);
277         ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
278         ProgramCodeBlock* baseline = static_cast<ProgramCodeBlock*>(
279             executable->m_programCodeBlock->baselineVersion());
280         RefPtr<ProgramCodeBlock> result = adoptRef(new ProgramCodeBlock(
281             CodeBlock::CopyParsedBlock, *baseline));
282         result->setAlternative(baseline);
283         return result;
284     }
285
286     RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
287     FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
288     FunctionCodeBlock* baseline = static_cast<FunctionCodeBlock*>(
289         executable->codeBlockFor(kind)->baselineVersion());
290     RefPtr<FunctionCodeBlock> result = adoptRef(new FunctionCodeBlock(
291         CodeBlock::CopyParsedBlock, *baseline));
292     result->setAlternative(baseline);
293     return result;
294 }
295
296 static void setupLLInt(VM& vm, CodeBlock* codeBlock)
297 {
298     LLInt::setEntrypoint(vm, codeBlock);
299 }
300
301 static void setupJIT(VM& vm, CodeBlock* codeBlock)
302 {
303 #if ENABLE(JIT)
304     CompilationResult result = JIT::compile(&vm, codeBlock, JITCompilationMustSucceed);
305     RELEASE_ASSERT(result == CompilationSuccessful);
306 #else
307     UNUSED_PARAM(vm);
308     UNUSED_PARAM(codeBlock);
309     UNREACHABLE_FOR_PLATFORM();
310 #endif
311 }
312
313 JSObject* ScriptExecutable::prepareForExecutionImpl(
314     ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind)
315 {
316     VM& vm = exec->vm();
317     DeferGC deferGC(vm.heap);
318     
319     JSObject* exception = 0;
320     RefPtr<CodeBlock> codeBlock = newCodeBlockFor(kind, function, scope, exception);
321     if (!codeBlock) {
322         RELEASE_ASSERT(exception);
323         return exception;
324     }
325     
326     if (Options::validateBytecode())
327         codeBlock->validate();
328     
329     if (Options::useLLInt())
330         setupLLInt(vm, codeBlock.get());
331     else
332         setupJIT(vm, codeBlock.get());
333     
334     installCode(codeBlock.get());
335     return 0;
336 }
337
338 const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(EvalExecutable) };
339
340 EvalExecutable* EvalExecutable::create(ExecState* exec, const SourceCode& source, bool isInStrictContext, ThisTDZMode thisTDZMode, const VariableEnvironment* variablesUnderTDZ)
341 {
342     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
343     if (!globalObject->evalEnabled()) {
344         exec->vm().throwException(exec, createEvalError(exec, globalObject->evalDisabledErrorMessage()));
345         return 0;
346     }
347
348     EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext);
349     executable->finishCreation(exec->vm());
350
351     UnlinkedEvalCodeBlock* unlinkedEvalCode = globalObject->createEvalCodeBlock(exec, executable, thisTDZMode, variablesUnderTDZ);
352     if (!unlinkedEvalCode)
353         return 0;
354
355     executable->m_unlinkedEvalCodeBlock.set(exec->vm(), executable, unlinkedEvalCode);
356
357     return executable;
358 }
359
360 EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
361     : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec->vm(), source, inStrictContext)
362 {
363 }
364
365 void EvalExecutable::destroy(JSCell* cell)
366 {
367     static_cast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable();
368 }
369
370 const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(ProgramExecutable) };
371
372 ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
373     : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec->vm(), source, false)
374 {
375     m_typeProfilingStartOffset = 0;
376     m_typeProfilingEndOffset = source.length() - 1;
377     if (exec->vm().typeProfiler() || exec->vm().controlFlowProfiler())
378         exec->vm().functionHasExecutedCache()->insertUnexecutedRange(sourceID(), m_typeProfilingStartOffset, m_typeProfilingEndOffset);
379 }
380
381 void ProgramExecutable::destroy(JSCell* cell)
382 {
383     static_cast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable();
384 }
385
386 const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
387
388 FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, 
389     UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, 
390     unsigned lastLine, unsigned startColumn, unsigned endColumn)
391     : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->isInStrictContext())
392     , m_unlinkedExecutable(vm, this, unlinkedExecutable)
393 {
394     RELEASE_ASSERT(!source.isNull());
395     ASSERT(source.length());
396     m_firstLine = firstLine;
397     m_lastLine = lastLine;
398     ASSERT(startColumn != UINT_MAX);
399     ASSERT(endColumn != UINT_MAX);
400     m_startColumn = startColumn;
401     m_endColumn = endColumn;
402     m_parametersStartOffset = unlinkedExecutable->parametersStartOffset();
403     m_typeProfilingStartOffset = unlinkedExecutable->typeProfilingStartOffset();
404     m_typeProfilingEndOffset = unlinkedExecutable->typeProfilingEndOffset();
405 }
406
407 void FunctionExecutable::finishCreation(VM& vm)
408 {
409     Base::finishCreation(vm);
410     m_singletonFunction.set(vm, this, InferredValue::create(vm));
411 }
412
413 void FunctionExecutable::destroy(JSCell* cell)
414 {
415     static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
416 }
417
418 inline const char* samplingDescription(JITCode::JITType jitType)
419 {
420     switch (jitType) {
421     case JITCode::InterpreterThunk:
422         return "Interpreter Compilation (TOTAL)";
423     case JITCode::BaselineJIT:
424         return "Baseline Compilation (TOTAL)";
425     case JITCode::DFGJIT:
426         return "DFG Compilation (TOTAL)";
427     case JITCode::FTLJIT:
428         return "FTL Compilation (TOTAL)";
429     default:
430         RELEASE_ASSERT_NOT_REACHED();
431         return 0;
432     }
433 }
434
435 void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
436 {
437     EvalExecutable* thisObject = jsCast<EvalExecutable*>(cell);
438     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
439     ScriptExecutable::visitChildren(thisObject, visitor);
440     if (thisObject->m_evalCodeBlock)
441         thisObject->m_evalCodeBlock->visitAggregate(visitor);
442     visitor.append(&thisObject->m_unlinkedEvalCodeBlock);
443 }
444
445 void EvalExecutable::clearCode()
446 {
447     m_evalCodeBlock = nullptr;
448     m_unlinkedEvalCodeBlock.clear();
449     Base::clearCode();
450 }
451
452 JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
453 {
454     ParserError error;
455     VM* vm = &exec->vm();
456     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
457     std::unique_ptr<ProgramNode> programNode = parse<ProgramNode>(
458         vm, m_source, Identifier(), JSParserBuiltinMode::NotBuiltin, 
459         JSParserStrictMode::NotStrict, SourceParseMode::ProgramMode, error);
460     if (programNode)
461         return 0;
462     ASSERT(error.isValid());
463     return error.toErrorObject(lexicalGlobalObject, m_source);
464 }
465
466 JSObject* ProgramExecutable::initializeGlobalProperties(VM& vm, CallFrame* callFrame, JSScope* scope)
467 {
468     RELEASE_ASSERT(scope);
469     JSGlobalObject* globalObject = scope->globalObject();
470     RELEASE_ASSERT(globalObject);
471     ASSERT(&globalObject->vm() == &vm);
472
473     JSObject* exception = 0;
474     UnlinkedProgramCodeBlock* unlinkedCodeBlock = globalObject->createProgramCodeBlock(callFrame, this, &exception);
475     if (exception)
476         return exception;
477
478     m_unlinkedProgramCodeBlock.set(vm, this, unlinkedCodeBlock);
479
480     BatchedTransitionOptimizer optimizer(vm, globalObject);
481
482     for (size_t i = 0, numberOfFunctions = unlinkedCodeBlock->numberOfFunctionDecls(); i < numberOfFunctions; ++i) {
483         UnlinkedFunctionExecutable* unlinkedFunctionExecutable = unlinkedCodeBlock->functionDecl(i);
484         ASSERT(!unlinkedFunctionExecutable->name().isEmpty());
485         globalObject->addFunction(callFrame, unlinkedFunctionExecutable->name());
486         if (vm.typeProfiler() || vm.controlFlowProfiler()) {
487             vm.functionHasExecutedCache()->insertUnexecutedRange(sourceID(), 
488                 unlinkedFunctionExecutable->typeProfilingStartOffset(), 
489                 unlinkedFunctionExecutable->typeProfilingEndOffset());
490         }
491     }
492
493     const VariableEnvironment& variableDeclarations = unlinkedCodeBlock->variableDeclarations();
494     for (auto& entry : variableDeclarations) {
495         ASSERT(entry.value.isVar());
496         globalObject->addVar(callFrame, Identifier::fromUid(&vm, entry.key.get()));
497     }
498     return 0;
499 }
500
501 void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
502 {
503     ProgramExecutable* thisObject = jsCast<ProgramExecutable*>(cell);
504     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
505     ScriptExecutable::visitChildren(thisObject, visitor);
506     visitor.append(&thisObject->m_unlinkedProgramCodeBlock);
507     if (thisObject->m_programCodeBlock)
508         thisObject->m_programCodeBlock->visitAggregate(visitor);
509 }
510
511 void ProgramExecutable::clearCode()
512 {
513     m_programCodeBlock = nullptr;
514     m_unlinkedProgramCodeBlock.clear();
515     Base::clearCode();
516 }
517
518 FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
519 {
520     FunctionCodeBlock* result;
521     if (kind == CodeForCall)
522         result = m_codeBlockForCall.get();
523     else {
524         RELEASE_ASSERT(kind == CodeForConstruct);
525         result = m_codeBlockForConstruct.get();
526     }
527     if (!result)
528         return 0;
529     return static_cast<FunctionCodeBlock*>(result->baselineAlternative());
530 }
531
532 void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
533 {
534     FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell);
535     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
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     visitor.append(&thisObject->m_singletonFunction);
543 }
544
545 void FunctionExecutable::clearCode()
546 {
547     m_codeBlockForCall = nullptr;
548     m_codeBlockForConstruct = nullptr;
549     Base::clearCode();
550 }
551
552 FunctionExecutable* FunctionExecutable::fromGlobalCode(
553     const Identifier& name, ExecState& exec, const SourceCode& source, 
554     JSObject*& exception, int overrideLineNumber)
555 {
556     UnlinkedFunctionExecutable* unlinkedExecutable = 
557         UnlinkedFunctionExecutable::fromGlobalCode(
558             name, exec, source, exception, overrideLineNumber);
559     if (!unlinkedExecutable)
560         return nullptr;
561
562     return unlinkedExecutable->link(exec.vm(), source, overrideLineNumber);
563 }
564
565 void ExecutableBase::dump(PrintStream& out) const
566 {
567     ExecutableBase* realThis = const_cast<ExecutableBase*>(this);
568     
569     if (classInfo() == NativeExecutable::info()) {
570         NativeExecutable* native = jsCast<NativeExecutable*>(realThis);
571         out.print("NativeExecutable:", RawPointer(bitwise_cast<void*>(native->function())), "/", RawPointer(bitwise_cast<void*>(native->constructor())));
572         return;
573     }
574     
575     if (classInfo() == EvalExecutable::info()) {
576         EvalExecutable* eval = jsCast<EvalExecutable*>(realThis);
577         if (CodeBlock* codeBlock = eval->codeBlock())
578             out.print(*codeBlock);
579         else
580             out.print("EvalExecutable w/o CodeBlock");
581         return;
582     }
583     
584     if (classInfo() == ProgramExecutable::info()) {
585         ProgramExecutable* eval = jsCast<ProgramExecutable*>(realThis);
586         if (CodeBlock* codeBlock = eval->codeBlock())
587             out.print(*codeBlock);
588         else
589             out.print("ProgramExecutable w/o CodeBlock");
590         return;
591     }
592     
593     FunctionExecutable* function = jsCast<FunctionExecutable*>(realThis);
594     if (!function->eitherCodeBlock())
595         out.print("FunctionExecutable w/o CodeBlock");
596     else {
597         CommaPrinter comma("/");
598         if (function->codeBlockForCall())
599             out.print(comma, *function->codeBlockForCall());
600         if (function->codeBlockForConstruct())
601             out.print(comma, *function->codeBlockForConstruct());
602     }
603 }
604
605 CodeBlockHash ExecutableBase::hashFor(CodeSpecializationKind kind) const
606 {
607     if (this->classInfo() == NativeExecutable::info())
608         return jsCast<const NativeExecutable*>(this)->hashFor(kind);
609     
610     return jsCast<const ScriptExecutable*>(this)->hashFor(kind);
611 }
612
613 CodeBlockHash NativeExecutable::hashFor(CodeSpecializationKind kind) const
614 {
615     if (kind == CodeForCall)
616         return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_function)));
617     
618     RELEASE_ASSERT(kind == CodeForConstruct);
619     return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_constructor)));
620 }
621
622 CodeBlockHash ScriptExecutable::hashFor(CodeSpecializationKind kind) const
623 {
624     return CodeBlockHash(source(), kind);
625 }
626
627 }