clearCode() should clear code
[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->codeBlockFor(*vm, executable->m_source, kind, debuggerMode, profilerMode, error, executable->isArrowFunction());
240     recordParse(executable->m_unlinkedExecutable->features(), executable->m_unlinkedExecutable->hasCapturedVariables(), firstLine(), lastLine(), startColumn(), endColumn()); 
241     if (!unlinkedCodeBlock) {
242         exception = vm->throwException(
243             globalObject->globalExec(),
244             error.toErrorObject(globalObject, executable->m_source));
245         return nullptr;
246     }
247
248     SourceProvider* provider = executable->source().provider();
249     unsigned sourceOffset = executable->source().startOffset();
250     unsigned startColumn = executable->source().startColumn();
251
252     return adoptRef(new FunctionCodeBlock(
253         executable, unlinkedCodeBlock, scope, provider, sourceOffset, startColumn));
254 }
255
256 PassRefPtr<CodeBlock> ScriptExecutable::newReplacementCodeBlockFor(
257     CodeSpecializationKind kind)
258 {
259     if (classInfo() == EvalExecutable::info()) {
260         RELEASE_ASSERT(kind == CodeForCall);
261         EvalExecutable* executable = jsCast<EvalExecutable*>(this);
262         EvalCodeBlock* baseline = static_cast<EvalCodeBlock*>(
263             executable->m_evalCodeBlock->baselineVersion());
264         RefPtr<EvalCodeBlock> result = adoptRef(new EvalCodeBlock(
265             CodeBlock::CopyParsedBlock, *baseline));
266         result->setAlternative(baseline);
267         return result;
268     }
269     
270     if (classInfo() == ProgramExecutable::info()) {
271         RELEASE_ASSERT(kind == CodeForCall);
272         ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
273         ProgramCodeBlock* baseline = static_cast<ProgramCodeBlock*>(
274             executable->m_programCodeBlock->baselineVersion());
275         RefPtr<ProgramCodeBlock> result = adoptRef(new ProgramCodeBlock(
276             CodeBlock::CopyParsedBlock, *baseline));
277         result->setAlternative(baseline);
278         return result;
279     }
280
281     RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
282     FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
283     FunctionCodeBlock* baseline = static_cast<FunctionCodeBlock*>(
284         executable->codeBlockFor(kind)->baselineVersion());
285     RefPtr<FunctionCodeBlock> result = adoptRef(new FunctionCodeBlock(
286         CodeBlock::CopyParsedBlock, *baseline));
287     result->setAlternative(baseline);
288     return result;
289 }
290
291 static void setupLLInt(VM& vm, CodeBlock* codeBlock)
292 {
293     LLInt::setEntrypoint(vm, codeBlock);
294 }
295
296 static void setupJIT(VM& vm, CodeBlock* codeBlock)
297 {
298 #if ENABLE(JIT)
299     CompilationResult result = JIT::compile(&vm, codeBlock, JITCompilationMustSucceed);
300     RELEASE_ASSERT(result == CompilationSuccessful);
301 #else
302     UNUSED_PARAM(vm);
303     UNUSED_PARAM(codeBlock);
304     UNREACHABLE_FOR_PLATFORM();
305 #endif
306 }
307
308 JSObject* ScriptExecutable::prepareForExecutionImpl(
309     ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind)
310 {
311     VM& vm = exec->vm();
312     DeferGC deferGC(vm.heap);
313     
314     JSObject* exception = 0;
315     RefPtr<CodeBlock> codeBlock = newCodeBlockFor(kind, function, scope, exception);
316     if (!codeBlock) {
317         RELEASE_ASSERT(exception);
318         return exception;
319     }
320     
321     if (Options::validateBytecode())
322         codeBlock->validate();
323     
324     if (Options::useLLInt())
325         setupLLInt(vm, codeBlock.get());
326     else
327         setupJIT(vm, codeBlock.get());
328     
329     installCode(codeBlock.get());
330     return 0;
331 }
332
333 const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(EvalExecutable) };
334
335 EvalExecutable* EvalExecutable::create(ExecState* exec, const SourceCode& source, bool isInStrictContext, ThisTDZMode thisTDZMode, const VariableEnvironment* variablesUnderTDZ)
336 {
337     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
338     if (!globalObject->evalEnabled()) {
339         exec->vm().throwException(exec, createEvalError(exec, globalObject->evalDisabledErrorMessage()));
340         return 0;
341     }
342
343     EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext);
344     executable->finishCreation(exec->vm());
345
346     UnlinkedEvalCodeBlock* unlinkedEvalCode = globalObject->createEvalCodeBlock(exec, executable, thisTDZMode, variablesUnderTDZ);
347     if (!unlinkedEvalCode)
348         return 0;
349
350     executable->m_unlinkedEvalCodeBlock.set(exec->vm(), executable, unlinkedEvalCode);
351
352     return executable;
353 }
354
355 EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
356     : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec->vm(), source, inStrictContext)
357 {
358 }
359
360 void EvalExecutable::destroy(JSCell* cell)
361 {
362     static_cast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable();
363 }
364
365 const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(ProgramExecutable) };
366
367 ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
368     : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec->vm(), source, false)
369 {
370     m_typeProfilingStartOffset = 0;
371     m_typeProfilingEndOffset = source.length() - 1;
372     if (exec->vm().typeProfiler() || exec->vm().controlFlowProfiler())
373         exec->vm().functionHasExecutedCache()->insertUnexecutedRange(sourceID(), m_typeProfilingStartOffset, m_typeProfilingEndOffset);
374 }
375
376 void ProgramExecutable::destroy(JSCell* cell)
377 {
378     static_cast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable();
379 }
380
381 const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
382
383 FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, 
384     UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, 
385     unsigned lastLine, unsigned startColumn, unsigned endColumn)
386     : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->isInStrictContext())
387     , m_unlinkedExecutable(vm, this, unlinkedExecutable)
388 {
389     RELEASE_ASSERT(!source.isNull());
390     ASSERT(source.length());
391     m_firstLine = firstLine;
392     m_lastLine = lastLine;
393     ASSERT(startColumn != UINT_MAX);
394     ASSERT(endColumn != UINT_MAX);
395     m_startColumn = startColumn;
396     m_endColumn = endColumn;
397     m_parametersStartOffset = unlinkedExecutable->parametersStartOffset();
398     m_typeProfilingStartOffset = unlinkedExecutable->typeProfilingStartOffset();
399     m_typeProfilingEndOffset = unlinkedExecutable->typeProfilingEndOffset();
400 }
401
402 void FunctionExecutable::finishCreation(VM& vm)
403 {
404     Base::finishCreation(vm);
405     m_singletonFunction.set(vm, this, InferredValue::create(vm));
406 }
407
408 void FunctionExecutable::destroy(JSCell* cell)
409 {
410     static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
411 }
412
413 inline const char* samplingDescription(JITCode::JITType jitType)
414 {
415     switch (jitType) {
416     case JITCode::InterpreterThunk:
417         return "Interpreter Compilation (TOTAL)";
418     case JITCode::BaselineJIT:
419         return "Baseline Compilation (TOTAL)";
420     case JITCode::DFGJIT:
421         return "DFG Compilation (TOTAL)";
422     case JITCode::FTLJIT:
423         return "FTL Compilation (TOTAL)";
424     default:
425         RELEASE_ASSERT_NOT_REACHED();
426         return 0;
427     }
428 }
429
430 void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
431 {
432     EvalExecutable* thisObject = jsCast<EvalExecutable*>(cell);
433     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
434     ScriptExecutable::visitChildren(thisObject, visitor);
435     if (thisObject->m_evalCodeBlock)
436         thisObject->m_evalCodeBlock->visitAggregate(visitor);
437     visitor.append(&thisObject->m_unlinkedEvalCodeBlock);
438 }
439
440 void EvalExecutable::unlinkCalls()
441 {
442 #if ENABLE(JIT)
443     if (!m_jitCodeForCall)
444         return;
445     RELEASE_ASSERT(m_evalCodeBlock);
446     m_evalCodeBlock->unlinkCalls();
447 #endif
448 }
449
450 void EvalExecutable::clearCode()
451 {
452     m_evalCodeBlock = nullptr;
453     m_unlinkedEvalCodeBlock.clear();
454     Base::clearCode();
455 }
456
457 JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
458 {
459     ParserError error;
460     VM* vm = &exec->vm();
461     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
462     std::unique_ptr<ProgramNode> programNode = parse<ProgramNode>(
463         vm, m_source, Identifier(), JSParserBuiltinMode::NotBuiltin, 
464         JSParserStrictMode::NotStrict, SourceParseMode::ProgramMode, error);
465     if (programNode)
466         return 0;
467     ASSERT(error.isValid());
468     return error.toErrorObject(lexicalGlobalObject, m_source);
469 }
470
471 void ProgramExecutable::unlinkCalls()
472 {
473 #if ENABLE(JIT)
474     if (!m_jitCodeForCall)
475         return;
476     RELEASE_ASSERT(m_programCodeBlock);
477     m_programCodeBlock->unlinkCalls();
478 #endif
479 }
480
481 JSObject* ProgramExecutable::initializeGlobalProperties(VM& vm, CallFrame* callFrame, JSScope* scope)
482 {
483     RELEASE_ASSERT(scope);
484     JSGlobalObject* globalObject = scope->globalObject();
485     RELEASE_ASSERT(globalObject);
486     ASSERT(&globalObject->vm() == &vm);
487
488     JSObject* exception = 0;
489     UnlinkedProgramCodeBlock* unlinkedCodeBlock = globalObject->createProgramCodeBlock(callFrame, this, &exception);
490     if (exception)
491         return exception;
492
493     m_unlinkedProgramCodeBlock.set(vm, this, unlinkedCodeBlock);
494
495     BatchedTransitionOptimizer optimizer(vm, globalObject);
496
497     for (size_t i = 0, numberOfFunctions = unlinkedCodeBlock->numberOfFunctionDecls(); i < numberOfFunctions; ++i) {
498         UnlinkedFunctionExecutable* unlinkedFunctionExecutable = unlinkedCodeBlock->functionDecl(i);
499         ASSERT(!unlinkedFunctionExecutable->name().isEmpty());
500         globalObject->addFunction(callFrame, unlinkedFunctionExecutable->name());
501         if (vm.typeProfiler() || vm.controlFlowProfiler()) {
502             vm.functionHasExecutedCache()->insertUnexecutedRange(sourceID(), 
503                 unlinkedFunctionExecutable->typeProfilingStartOffset(), 
504                 unlinkedFunctionExecutable->typeProfilingEndOffset());
505         }
506     }
507
508     const VariableEnvironment& variableDeclarations = unlinkedCodeBlock->variableDeclarations();
509     for (auto& entry : variableDeclarations) {
510         ASSERT(entry.value.isVar());
511         globalObject->addVar(callFrame, Identifier::fromUid(&vm, entry.key.get()));
512     }
513     return 0;
514 }
515
516 void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
517 {
518     ProgramExecutable* thisObject = jsCast<ProgramExecutable*>(cell);
519     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
520     ScriptExecutable::visitChildren(thisObject, visitor);
521     visitor.append(&thisObject->m_unlinkedProgramCodeBlock);
522     if (thisObject->m_programCodeBlock)
523         thisObject->m_programCodeBlock->visitAggregate(visitor);
524 }
525
526 void ProgramExecutable::clearCode()
527 {
528     m_programCodeBlock = nullptr;
529     m_unlinkedProgramCodeBlock.clear();
530     Base::clearCode();
531 }
532
533 FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
534 {
535     FunctionCodeBlock* result;
536     if (kind == CodeForCall)
537         result = m_codeBlockForCall.get();
538     else {
539         RELEASE_ASSERT(kind == CodeForConstruct);
540         result = m_codeBlockForConstruct.get();
541     }
542     if (!result)
543         return 0;
544     return static_cast<FunctionCodeBlock*>(result->baselineAlternative());
545 }
546
547 void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
548 {
549     FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell);
550     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
551     ScriptExecutable::visitChildren(thisObject, visitor);
552     if (thisObject->m_codeBlockForCall)
553         thisObject->m_codeBlockForCall->visitAggregate(visitor);
554     if (thisObject->m_codeBlockForConstruct)
555         thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
556     visitor.append(&thisObject->m_unlinkedExecutable);
557     visitor.append(&thisObject->m_singletonFunction);
558 }
559
560 void FunctionExecutable::clearCode()
561 {
562     m_unlinkedExecutable->clearCode();
563     m_codeBlockForCall = nullptr;
564     m_codeBlockForConstruct = nullptr;
565     Base::clearCode();
566 }
567
568 void FunctionExecutable::unlinkCalls()
569 {
570 #if ENABLE(JIT)
571     if (!!m_jitCodeForCall) {
572         RELEASE_ASSERT(m_codeBlockForCall);
573         m_codeBlockForCall->unlinkCalls();
574     }
575     if (!!m_jitCodeForConstruct) {
576         RELEASE_ASSERT(m_codeBlockForConstruct);
577         m_codeBlockForConstruct->unlinkCalls();
578     }
579 #endif
580 }
581
582 FunctionExecutable* FunctionExecutable::fromGlobalCode(
583     const Identifier& name, ExecState& exec, const SourceCode& source, 
584     JSObject*& exception, int overrideLineNumber)
585 {
586     UnlinkedFunctionExecutable* unlinkedExecutable = 
587         UnlinkedFunctionExecutable::fromGlobalCode(
588             name, exec, source, exception, overrideLineNumber);
589     if (!unlinkedExecutable)
590         return nullptr;
591
592     return unlinkedExecutable->link(exec.vm(), source, overrideLineNumber);
593 }
594
595 void ExecutableBase::dump(PrintStream& out) const
596 {
597     ExecutableBase* realThis = const_cast<ExecutableBase*>(this);
598     
599     if (classInfo() == NativeExecutable::info()) {
600         NativeExecutable* native = jsCast<NativeExecutable*>(realThis);
601         out.print("NativeExecutable:", RawPointer(bitwise_cast<void*>(native->function())), "/", RawPointer(bitwise_cast<void*>(native->constructor())));
602         return;
603     }
604     
605     if (classInfo() == EvalExecutable::info()) {
606         EvalExecutable* eval = jsCast<EvalExecutable*>(realThis);
607         if (CodeBlock* codeBlock = eval->codeBlock())
608             out.print(*codeBlock);
609         else
610             out.print("EvalExecutable w/o CodeBlock");
611         return;
612     }
613     
614     if (classInfo() == ProgramExecutable::info()) {
615         ProgramExecutable* eval = jsCast<ProgramExecutable*>(realThis);
616         if (CodeBlock* codeBlock = eval->codeBlock())
617             out.print(*codeBlock);
618         else
619             out.print("ProgramExecutable w/o CodeBlock");
620         return;
621     }
622     
623     FunctionExecutable* function = jsCast<FunctionExecutable*>(realThis);
624     if (!function->eitherCodeBlock())
625         out.print("FunctionExecutable w/o CodeBlock");
626     else {
627         CommaPrinter comma("/");
628         if (function->codeBlockForCall())
629             out.print(comma, *function->codeBlockForCall());
630         if (function->codeBlockForConstruct())
631             out.print(comma, *function->codeBlockForConstruct());
632     }
633 }
634
635 CodeBlockHash ExecutableBase::hashFor(CodeSpecializationKind kind) const
636 {
637     if (this->classInfo() == NativeExecutable::info())
638         return jsCast<const NativeExecutable*>(this)->hashFor(kind);
639     
640     return jsCast<const ScriptExecutable*>(this)->hashFor(kind);
641 }
642
643 CodeBlockHash NativeExecutable::hashFor(CodeSpecializationKind kind) const
644 {
645     if (kind == CodeForCall)
646         return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_function)));
647     
648     RELEASE_ASSERT(kind == CodeForConstruct);
649     return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_constructor)));
650 }
651
652 CodeBlockHash ScriptExecutable::hashFor(CodeSpecializationKind kind) const
653 {
654     return CodeBlockHash(source(), kind);
655 }
656
657 }