5ffb8db7f0505b4d1626a36847a2881fb4a17523
[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::unlinkCalls()
446 {
447 #if ENABLE(JIT)
448     if (!m_jitCodeForCall)
449         return;
450     RELEASE_ASSERT(m_evalCodeBlock);
451     m_evalCodeBlock->unlinkCalls();
452 #endif
453 }
454
455 void EvalExecutable::clearCode()
456 {
457     m_evalCodeBlock = nullptr;
458     m_unlinkedEvalCodeBlock.clear();
459     Base::clearCode();
460 }
461
462 JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
463 {
464     ParserError error;
465     VM* vm = &exec->vm();
466     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
467     std::unique_ptr<ProgramNode> programNode = parse<ProgramNode>(
468         vm, m_source, Identifier(), JSParserBuiltinMode::NotBuiltin, 
469         JSParserStrictMode::NotStrict, SourceParseMode::ProgramMode, error);
470     if (programNode)
471         return 0;
472     ASSERT(error.isValid());
473     return error.toErrorObject(lexicalGlobalObject, m_source);
474 }
475
476 void ProgramExecutable::unlinkCalls()
477 {
478 #if ENABLE(JIT)
479     if (!m_jitCodeForCall)
480         return;
481     RELEASE_ASSERT(m_programCodeBlock);
482     m_programCodeBlock->unlinkCalls();
483 #endif
484 }
485
486 JSObject* ProgramExecutable::initializeGlobalProperties(VM& vm, CallFrame* callFrame, JSScope* scope)
487 {
488     RELEASE_ASSERT(scope);
489     JSGlobalObject* globalObject = scope->globalObject();
490     RELEASE_ASSERT(globalObject);
491     ASSERT(&globalObject->vm() == &vm);
492
493     JSObject* exception = 0;
494     UnlinkedProgramCodeBlock* unlinkedCodeBlock = globalObject->createProgramCodeBlock(callFrame, this, &exception);
495     if (exception)
496         return exception;
497
498     m_unlinkedProgramCodeBlock.set(vm, this, unlinkedCodeBlock);
499
500     BatchedTransitionOptimizer optimizer(vm, globalObject);
501
502     for (size_t i = 0, numberOfFunctions = unlinkedCodeBlock->numberOfFunctionDecls(); i < numberOfFunctions; ++i) {
503         UnlinkedFunctionExecutable* unlinkedFunctionExecutable = unlinkedCodeBlock->functionDecl(i);
504         ASSERT(!unlinkedFunctionExecutable->name().isEmpty());
505         globalObject->addFunction(callFrame, unlinkedFunctionExecutable->name());
506         if (vm.typeProfiler() || vm.controlFlowProfiler()) {
507             vm.functionHasExecutedCache()->insertUnexecutedRange(sourceID(), 
508                 unlinkedFunctionExecutable->typeProfilingStartOffset(), 
509                 unlinkedFunctionExecutable->typeProfilingEndOffset());
510         }
511     }
512
513     const VariableEnvironment& variableDeclarations = unlinkedCodeBlock->variableDeclarations();
514     for (auto& entry : variableDeclarations) {
515         ASSERT(entry.value.isVar());
516         globalObject->addVar(callFrame, Identifier::fromUid(&vm, entry.key.get()));
517     }
518     return 0;
519 }
520
521 void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
522 {
523     ProgramExecutable* thisObject = jsCast<ProgramExecutable*>(cell);
524     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
525     ScriptExecutable::visitChildren(thisObject, visitor);
526     visitor.append(&thisObject->m_unlinkedProgramCodeBlock);
527     if (thisObject->m_programCodeBlock)
528         thisObject->m_programCodeBlock->visitAggregate(visitor);
529 }
530
531 void ProgramExecutable::clearCode()
532 {
533     m_programCodeBlock = nullptr;
534     m_unlinkedProgramCodeBlock.clear();
535     Base::clearCode();
536 }
537
538 FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
539 {
540     FunctionCodeBlock* result;
541     if (kind == CodeForCall)
542         result = m_codeBlockForCall.get();
543     else {
544         RELEASE_ASSERT(kind == CodeForConstruct);
545         result = m_codeBlockForConstruct.get();
546     }
547     if (!result)
548         return 0;
549     return static_cast<FunctionCodeBlock*>(result->baselineAlternative());
550 }
551
552 void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
553 {
554     FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell);
555     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
556     ScriptExecutable::visitChildren(thisObject, visitor);
557     if (thisObject->m_codeBlockForCall)
558         thisObject->m_codeBlockForCall->visitAggregate(visitor);
559     if (thisObject->m_codeBlockForConstruct)
560         thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
561     visitor.append(&thisObject->m_unlinkedExecutable);
562     visitor.append(&thisObject->m_singletonFunction);
563 }
564
565 void FunctionExecutable::clearCode()
566 {
567     m_codeBlockForCall = nullptr;
568     m_codeBlockForConstruct = nullptr;
569     Base::clearCode();
570 }
571
572 void FunctionExecutable::unlinkCalls()
573 {
574 #if ENABLE(JIT)
575     if (!!m_jitCodeForCall) {
576         RELEASE_ASSERT(m_codeBlockForCall);
577         m_codeBlockForCall->unlinkCalls();
578     }
579     if (!!m_jitCodeForConstruct) {
580         RELEASE_ASSERT(m_codeBlockForConstruct);
581         m_codeBlockForConstruct->unlinkCalls();
582     }
583 #endif
584 }
585
586 FunctionExecutable* FunctionExecutable::fromGlobalCode(
587     const Identifier& name, ExecState& exec, const SourceCode& source, 
588     JSObject*& exception, int overrideLineNumber)
589 {
590     UnlinkedFunctionExecutable* unlinkedExecutable = 
591         UnlinkedFunctionExecutable::fromGlobalCode(
592             name, exec, source, exception, overrideLineNumber);
593     if (!unlinkedExecutable)
594         return nullptr;
595
596     return unlinkedExecutable->link(exec.vm(), source, overrideLineNumber);
597 }
598
599 void ExecutableBase::dump(PrintStream& out) const
600 {
601     ExecutableBase* realThis = const_cast<ExecutableBase*>(this);
602     
603     if (classInfo() == NativeExecutable::info()) {
604         NativeExecutable* native = jsCast<NativeExecutable*>(realThis);
605         out.print("NativeExecutable:", RawPointer(bitwise_cast<void*>(native->function())), "/", RawPointer(bitwise_cast<void*>(native->constructor())));
606         return;
607     }
608     
609     if (classInfo() == EvalExecutable::info()) {
610         EvalExecutable* eval = jsCast<EvalExecutable*>(realThis);
611         if (CodeBlock* codeBlock = eval->codeBlock())
612             out.print(*codeBlock);
613         else
614             out.print("EvalExecutable w/o CodeBlock");
615         return;
616     }
617     
618     if (classInfo() == ProgramExecutable::info()) {
619         ProgramExecutable* eval = jsCast<ProgramExecutable*>(realThis);
620         if (CodeBlock* codeBlock = eval->codeBlock())
621             out.print(*codeBlock);
622         else
623             out.print("ProgramExecutable w/o CodeBlock");
624         return;
625     }
626     
627     FunctionExecutable* function = jsCast<FunctionExecutable*>(realThis);
628     if (!function->eitherCodeBlock())
629         out.print("FunctionExecutable w/o CodeBlock");
630     else {
631         CommaPrinter comma("/");
632         if (function->codeBlockForCall())
633             out.print(comma, *function->codeBlockForCall());
634         if (function->codeBlockForConstruct())
635             out.print(comma, *function->codeBlockForConstruct());
636     }
637 }
638
639 CodeBlockHash ExecutableBase::hashFor(CodeSpecializationKind kind) const
640 {
641     if (this->classInfo() == NativeExecutable::info())
642         return jsCast<const NativeExecutable*>(this)->hashFor(kind);
643     
644     return jsCast<const ScriptExecutable*>(this)->hashFor(kind);
645 }
646
647 CodeBlockHash NativeExecutable::hashFor(CodeSpecializationKind kind) const
648 {
649     if (kind == CodeForCall)
650         return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_function)));
651     
652     RELEASE_ASSERT(kind == CodeForConstruct);
653     return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_constructor)));
654 }
655
656 CodeBlockHash ScriptExecutable::hashFor(CodeSpecializationKind kind) const
657 {
658     return CodeBlockHash(source(), kind);
659 }
660
661 }