1/*
2 * Copyright (C) 2009, 2010, 2013 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "Executable.h"
28
29#include "BatchedTransitionOptimizer.h"
30#include "BytecodeGenerator.h"
31#include "CodeBlock.h"
32#include "DFGDriver.h"
33#include "JIT.h"
34#include "LLIntEntrypoint.h"
35#include "JSCInlines.h"
36#include "Parser.h"
37#include "ProfilerDatabase.h"
38#include <wtf/CommaPrinter.h>
39#include <wtf/Vector.h>
40#include <wtf/text/StringBuilder.h>
41
42namespace JSC {
43
44const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0, CREATE_METHOD_TABLE(ExecutableBase) };
45
46#if ENABLE(JIT)
47void ExecutableBase::destroy(JSCell* cell)
48{
49    static_cast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();
50}
51#endif
52
53void ExecutableBase::clearCode()
54{
55#if ENABLE(JIT)
56    m_jitCodeForCall.clear();
57    m_jitCodeForConstruct.clear();
58    m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
59    m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
60    m_jitCodeForCallWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
61    m_jitCodeForConstructWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
62#endif
63    m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
64    m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
65}
66
67#if ENABLE(DFG_JIT)
68Intrinsic ExecutableBase::intrinsic() const
69{
70    if (const NativeExecutable* nativeExecutable = jsDynamicCast<const NativeExecutable*>(this))
71        return nativeExecutable->intrinsic();
72    return NoIntrinsic;
73}
74#else
75Intrinsic ExecutableBase::intrinsic() const
76{
77    return NoIntrinsic;
78}
79#endif
80
81const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(NativeExecutable) };
82
83#if ENABLE(JIT)
84void NativeExecutable::destroy(JSCell* cell)
85{
86    static_cast<NativeExecutable*>(cell)->NativeExecutable::~NativeExecutable();
87}
88#endif
89
90#if ENABLE(DFG_JIT)
91Intrinsic NativeExecutable::intrinsic() const
92{
93    return m_intrinsic;
94}
95#endif
96
97const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
98
99#if ENABLE(JIT)
100void ScriptExecutable::destroy(JSCell* cell)
101{
102    static_cast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
103}
104#endif
105
106void ScriptExecutable::installCode(CodeBlock* genericCodeBlock)
107{
108    RELEASE_ASSERT(genericCodeBlock->ownerExecutable() == this);
109    RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock->jitType()));
110
111    VM& vm = *genericCodeBlock->vm();
112
113    if (vm.m_perBytecodeProfiler)
114        vm.m_perBytecodeProfiler->ensureBytecodesFor(genericCodeBlock);
115
116    ASSERT(vm.heap.isDeferred());
117
118    CodeSpecializationKind kind = genericCodeBlock->specializationKind();
119
120    RefPtr<CodeBlock> oldCodeBlock;
121
122    switch (kind) {
123    case CodeForCall:
124        m_jitCodeForCall = genericCodeBlock->jitCode();
125        m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
126        m_jitCodeForCallWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
127        m_numParametersForCall = genericCodeBlock->numParameters();
128        break;
129    case CodeForConstruct:
130        m_jitCodeForConstruct = genericCodeBlock->jitCode();
131        m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
132        m_jitCodeForConstructWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
133        m_numParametersForConstruct = genericCodeBlock->numParameters();
134        break;
135    }
136
137    switch (genericCodeBlock->codeType()) {
138    case GlobalCode: {
139        ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
140        ProgramCodeBlock* codeBlock = static_cast<ProgramCodeBlock*>(genericCodeBlock);
141
142        ASSERT(kind == CodeForCall);
143
144        oldCodeBlock = executable->m_programCodeBlock;
145        executable->m_programCodeBlock = codeBlock;
146        break;
147    }
148
149    case EvalCode: {
150        EvalExecutable* executable = jsCast<EvalExecutable*>(this);
151        EvalCodeBlock* codeBlock = static_cast<EvalCodeBlock*>(genericCodeBlock);
152
153        ASSERT(kind == CodeForCall);
154
155        oldCodeBlock = executable->m_evalCodeBlock;
156        executable->m_evalCodeBlock = codeBlock;
157        break;
158    }
159
160    case FunctionCode: {
161        FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
162        FunctionCodeBlock* codeBlock = static_cast<FunctionCodeBlock*>(genericCodeBlock);
163
164        switch (kind) {
165        case CodeForCall:
166            oldCodeBlock = executable->m_codeBlockForCall;
167            executable->m_codeBlockForCall = codeBlock;
168            break;
169        case CodeForConstruct:
170            oldCodeBlock = executable->m_codeBlockForConstruct;
171            executable->m_codeBlockForConstruct = codeBlock;
172            break;
173        }
174        break;
175    } }
176
177    if (oldCodeBlock)
178        oldCodeBlock->unlinkIncomingCalls();
179
180    Debugger* debugger = genericCodeBlock->globalObject()->debugger();
181    if (debugger)
182        debugger->registerCodeBlock(genericCodeBlock);
183
184    Heap::heap(this)->writeBarrier(this);
185}
186
187PassRefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor(
188    CodeSpecializationKind kind, JSFunction* function, JSScope** scope, JSObject*& exception)
189{
190    VM* vm = (*scope)->vm();
191
192    ASSERT(vm->heap.isDeferred());
193    ASSERT(startColumn() != UINT_MAX);
194    ASSERT(endColumn() != UINT_MAX);
195
196    if (classInfo() == EvalExecutable::info()) {
197        EvalExecutable* executable = jsCast<EvalExecutable*>(this);
198        RELEASE_ASSERT(kind == CodeForCall);
199        RELEASE_ASSERT(!executable->m_evalCodeBlock);
200        RELEASE_ASSERT(!function);
201        return adoptRef(new EvalCodeBlock(
202            executable, executable->m_unlinkedEvalCodeBlock.get(), *scope,
203            executable->source().provider()));
204    }
205
206    if (classInfo() == ProgramExecutable::info()) {
207        ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
208        RELEASE_ASSERT(kind == CodeForCall);
209        RELEASE_ASSERT(!executable->m_programCodeBlock);
210        RELEASE_ASSERT(!function);
211        return adoptRef(new ProgramCodeBlock(
212            executable, executable->m_unlinkedProgramCodeBlock.get(), *scope,
213            executable->source().provider(), executable->source().startColumn()));
214    }
215
216    RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
217    RELEASE_ASSERT(function);
218    FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
219    RELEASE_ASSERT(!executable->codeBlockFor(kind));
220    JSGlobalObject* globalObject = (*scope)->globalObject();
221    ParserError error;
222    DebuggerMode debuggerMode = globalObject->hasDebugger() ? DebuggerOn : DebuggerOff;
223    ProfilerMode profilerMode = globalObject->hasProfiler() ? ProfilerOn : ProfilerOff;
224    UnlinkedFunctionCodeBlock* unlinkedCodeBlock =
225        executable->m_unlinkedExecutable->codeBlockFor(
226            *vm, executable->m_source, kind, debuggerMode, profilerMode, executable->bodyIncludesBraces(), error);
227    recordParse(executable->m_unlinkedExecutable->features(), executable->m_unlinkedExecutable->hasCapturedVariables(), lineNo(), lastLine(), startColumn(), endColumn());
228    if (!unlinkedCodeBlock) {
229        exception = vm->throwException(
230            globalObject->globalExec(),
231            error.toErrorObject(globalObject, executable->m_source));
232        return 0;
233    }
234
235    // Parsing reveals whether our function uses features that require a separate function name object in the scope chain.
236    // Be sure to add this scope before linking the bytecode because this scope will change the resolution depth of non-local variables.
237    if (!executable->m_didParseForTheFirstTime) {
238        executable->m_didParseForTheFirstTime = true;
239        function->addNameScopeIfNeeded(*vm);
240        *scope = function->scope();
241    }
242
243    SourceProvider* provider = executable->source().provider();
244    unsigned sourceOffset = executable->source().startOffset();
245    unsigned startColumn = executable->source().startColumn();
246
247    return adoptRef(new FunctionCodeBlock(
248        executable, unlinkedCodeBlock, *scope, provider, sourceOffset, startColumn));
249}
250
251PassRefPtr<CodeBlock> ScriptExecutable::newReplacementCodeBlockFor(
252    CodeSpecializationKind kind)
253{
254    if (classInfo() == EvalExecutable::info()) {
255        RELEASE_ASSERT(kind == CodeForCall);
256        EvalExecutable* executable = jsCast<EvalExecutable*>(this);
257        EvalCodeBlock* baseline = static_cast<EvalCodeBlock*>(
258            executable->m_evalCodeBlock->baselineVersion());
259        RefPtr<EvalCodeBlock> result = adoptRef(new EvalCodeBlock(
260            CodeBlock::CopyParsedBlock, *baseline));
261        result->setAlternative(baseline);
262        return result;
263    }
264
265    if (classInfo() == ProgramExecutable::info()) {
266        RELEASE_ASSERT(kind == CodeForCall);
267        ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
268        ProgramCodeBlock* baseline = static_cast<ProgramCodeBlock*>(
269            executable->m_programCodeBlock->baselineVersion());
270        RefPtr<ProgramCodeBlock> result = adoptRef(new ProgramCodeBlock(
271            CodeBlock::CopyParsedBlock, *baseline));
272        result->setAlternative(baseline);
273        return result;
274    }
275
276    RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
277    FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
278    FunctionCodeBlock* baseline = static_cast<FunctionCodeBlock*>(
279        executable->codeBlockFor(kind)->baselineVersion());
280    RefPtr<FunctionCodeBlock> result = adoptRef(new FunctionCodeBlock(
281        CodeBlock::CopyParsedBlock, *baseline));
282    result->setAlternative(baseline);
283    return result;
284}
285
286static void setupLLInt(VM& vm, CodeBlock* codeBlock)
287{
288    LLInt::setEntrypoint(vm, codeBlock);
289}
290
291static void setupJIT(VM& vm, CodeBlock* codeBlock)
292{
293#if ENABLE(JIT)
294    CompilationResult result = JIT::compile(&vm, codeBlock, JITCompilationMustSucceed);
295    RELEASE_ASSERT(result == CompilationSuccessful);
296#else
297    UNUSED_PARAM(vm);
298    UNUSED_PARAM(codeBlock);
299    UNREACHABLE_FOR_PLATFORM();
300#endif
301}
302
303JSObject* ScriptExecutable::prepareForExecutionImpl(
304    ExecState* exec, JSFunction* function, JSScope** scope, CodeSpecializationKind kind)
305{
306    VM& vm = exec->vm();
307    DeferGC deferGC(vm.heap);
308
309    JSObject* exception = 0;
310    RefPtr<CodeBlock> codeBlock = newCodeBlockFor(kind, function, scope, exception);
311    if (!codeBlock) {
312        RELEASE_ASSERT(exception);
313        return exception;
314    }
315
316    if (Options::validateBytecode())
317        codeBlock->validate();
318
319    if (Options::useLLInt())
320        setupLLInt(vm, codeBlock.get());
321    else
322        setupJIT(vm, codeBlock.get());
323
324    installCode(codeBlock.get());
325    return 0;
326}
327
328const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(EvalExecutable) };
329
330EvalExecutable* EvalExecutable::create(ExecState* exec, const SourceCode& source, bool isInStrictContext)
331{
332    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
333    if (!globalObject->evalEnabled()) {
334        exec->vm().throwException(exec, createEvalError(exec, globalObject->evalDisabledErrorMessage()));
335        return 0;
336    }
337
338    EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext);
339    executable->finishCreation(exec->vm());
340
341    UnlinkedEvalCodeBlock* unlinkedEvalCode = globalObject->createEvalCodeBlock(exec, executable);
342    if (!unlinkedEvalCode)
343        return 0;
344
345    executable->m_unlinkedEvalCodeBlock.set(exec->vm(), executable, unlinkedEvalCode);
346
347    return executable;
348}
349
350EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
351    : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec, source, inStrictContext)
352{
353}
354
355void EvalExecutable::destroy(JSCell* cell)
356{
357    static_cast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable();
358}
359
360const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(ProgramExecutable) };
361
362ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
363    : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec, source, false)
364{
365}
366
367void ProgramExecutable::destroy(JSCell* cell)
368{
369    static_cast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable();
370}
371
372const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
373
374FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, bool bodyIncludesBraces)
375    : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->isInStrictContext())
376    , m_unlinkedExecutable(vm, this, unlinkedExecutable)
377    , m_bodyIncludesBraces(bodyIncludesBraces)
378    , m_didParseForTheFirstTime(false)
379{
380    RELEASE_ASSERT(!source.isNull());
381    ASSERT(source.length());
382    m_firstLine = firstLine;
383    m_lastLine = lastLine;
384    ASSERT(startColumn != UINT_MAX);
385    ASSERT(endColumn != UINT_MAX);
386    m_startColumn = startColumn;
387    m_endColumn = endColumn;
388}
389
390void FunctionExecutable::destroy(JSCell* cell)
391{
392    static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
393}
394
395inline const char* samplingDescription(JITCode::JITType jitType)
396{
397    switch (jitType) {
398    case JITCode::InterpreterThunk:
399        return "Interpreter Compilation (TOTAL)";
400    case JITCode::BaselineJIT:
401        return "Baseline Compilation (TOTAL)";
402    case JITCode::DFGJIT:
403        return "DFG Compilation (TOTAL)";
404    case JITCode::FTLJIT:
405        return "FTL Compilation (TOTAL)";
406    default:
407        RELEASE_ASSERT_NOT_REACHED();
408        return 0;
409    }
410}
411
412void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
413{
414    EvalExecutable* thisObject = jsCast<EvalExecutable*>(cell);
415    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
416    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
417    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
418    ScriptExecutable::visitChildren(thisObject, visitor);
419    if (thisObject->m_evalCodeBlock)
420        thisObject->m_evalCodeBlock->visitAggregate(visitor);
421    visitor.append(&thisObject->m_unlinkedEvalCodeBlock);
422}
423
424void EvalExecutable::unlinkCalls()
425{
426#if ENABLE(JIT)
427    if (!m_jitCodeForCall)
428        return;
429    RELEASE_ASSERT(m_evalCodeBlock);
430    m_evalCodeBlock->unlinkCalls();
431#endif
432}
433
434void EvalExecutable::clearCode()
435{
436    m_evalCodeBlock.clear();
437    m_unlinkedEvalCodeBlock.clear();
438    Base::clearCode();
439}
440
441JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
442{
443    ParserError error;
444    VM* vm = &exec->vm();
445    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
446    RefPtr<ProgramNode> programNode = parse<ProgramNode>(vm, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, error);
447    if (programNode)
448        return 0;
449    ASSERT(error.m_type != ParserError::ErrorNone);
450    return error.toErrorObject(lexicalGlobalObject, m_source);
451}
452
453void ProgramExecutable::unlinkCalls()
454{
455#if ENABLE(JIT)
456    if (!m_jitCodeForCall)
457        return;
458    RELEASE_ASSERT(m_programCodeBlock);
459    m_programCodeBlock->unlinkCalls();
460#endif
461}
462
463JSObject* ProgramExecutable::initializeGlobalProperties(VM& vm, CallFrame* callFrame, JSScope* scope)
464{
465    RELEASE_ASSERT(scope);
466    JSGlobalObject* globalObject = scope->globalObject();
467    RELEASE_ASSERT(globalObject);
468    ASSERT(&globalObject->vm() == &vm);
469
470    JSObject* exception = 0;
471    UnlinkedProgramCodeBlock* unlinkedCodeBlock = globalObject->createProgramCodeBlock(callFrame, this, &exception);
472    if (exception)
473        return exception;
474
475    m_unlinkedProgramCodeBlock.set(vm, this, unlinkedCodeBlock);
476
477    BatchedTransitionOptimizer optimizer(vm, globalObject);
478
479    const UnlinkedProgramCodeBlock::VariableDeclations& variableDeclarations = unlinkedCodeBlock->variableDeclarations();
480    const UnlinkedProgramCodeBlock::FunctionDeclations& functionDeclarations = unlinkedCodeBlock->functionDeclarations();
481
482    for (size_t i = 0; i < functionDeclarations.size(); ++i) {
483        UnlinkedFunctionExecutable* unlinkedFunctionExecutable = functionDeclarations[i].second.get();
484        JSValue value = JSFunction::create(vm, unlinkedFunctionExecutable->link(vm, m_source, lineNo()), scope);
485        globalObject->addFunction(callFrame, functionDeclarations[i].first, value);
486    }
487
488    for (size_t i = 0; i < variableDeclarations.size(); ++i) {
489        if (variableDeclarations[i].second & DeclarationStacks::IsConstant)
490            globalObject->addConst(callFrame, variableDeclarations[i].first);
491        else
492            globalObject->addVar(callFrame, variableDeclarations[i].first);
493    }
494    return 0;
495}
496
497void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
498{
499    ProgramExecutable* thisObject = jsCast<ProgramExecutable*>(cell);
500    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
501    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
502    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
503    ScriptExecutable::visitChildren(thisObject, visitor);
504    visitor.append(&thisObject->m_unlinkedProgramCodeBlock);
505    if (thisObject->m_programCodeBlock)
506        thisObject->m_programCodeBlock->visitAggregate(visitor);
507}
508
509void ProgramExecutable::clearCode()
510{
511    m_programCodeBlock.clear();
512    m_unlinkedProgramCodeBlock.clear();
513    Base::clearCode();
514}
515
516FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
517{
518    FunctionCodeBlock* result;
519    if (kind == CodeForCall)
520        result = m_codeBlockForCall.get();
521    else {
522        RELEASE_ASSERT(kind == CodeForConstruct);
523        result = m_codeBlockForConstruct.get();
524    }
525    if (!result)
526        return 0;
527    return static_cast<FunctionCodeBlock*>(result->baselineAlternative());
528}
529
530void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
531{
532    FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell);
533    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
534    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
535    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
536    ScriptExecutable::visitChildren(thisObject, visitor);
537    if (thisObject->m_codeBlockForCall)
538        thisObject->m_codeBlockForCall->visitAggregate(visitor);
539    if (thisObject->m_codeBlockForConstruct)
540        thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
541    visitor.append(&thisObject->m_unlinkedExecutable);
542}
543
544SymbolTable* FunctionExecutable::symbolTable(CodeSpecializationKind kind)
545{
546    return codeBlockFor(kind)->symbolTable();
547}
548
549void FunctionExecutable::clearCodeIfNotCompiling()
550{
551    if (isCompiling())
552        return;
553    clearCode();
554}
555
556void FunctionExecutable::clearUnlinkedCodeForRecompilationIfNotCompiling()
557{
558    if (isCompiling())
559        return;
560    m_unlinkedExecutable->clearCodeForRecompilation();
561}
562
563void FunctionExecutable::clearCode()
564{
565    m_codeBlockForCall.clear();
566    m_codeBlockForConstruct.clear();
567    Base::clearCode();
568}
569
570void FunctionExecutable::unlinkCalls()
571{
572#if ENABLE(JIT)
573    if (!!m_jitCodeForCall) {
574        RELEASE_ASSERT(m_codeBlockForCall);
575        m_codeBlockForCall->unlinkCalls();
576    }
577    if (!!m_jitCodeForConstruct) {
578        RELEASE_ASSERT(m_codeBlockForConstruct);
579        m_codeBlockForConstruct->unlinkCalls();
580    }
581#endif
582}
583
584FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
585{
586    UnlinkedFunctionExecutable* unlinkedExecutable = UnlinkedFunctionExecutable::fromGlobalCode(name, exec, debugger, source, exception);
587    if (!unlinkedExecutable)
588        return 0;
589    unsigned lineCount = unlinkedExecutable->lineCount();
590    unsigned firstLine = source.firstLine() + unlinkedExecutable->firstLineOffset();
591    unsigned startOffset = source.startOffset() + unlinkedExecutable->startOffset();
592
593    // We don't have any owner executable. The source string is effectively like a global
594    // string (like in the handling of eval). Hence, the startColumn is always 1.
595    unsigned startColumn = 1;
596    unsigned sourceLength = unlinkedExecutable->sourceLength();
597    bool endColumnIsOnStartLine = !lineCount;
598    // The unlinkedBodyEndColumn is based-0. Hence, we need to add 1 to it. But if the
599    // endColumn is on the startLine, then we need to subtract back the adjustment for
600    // the open brace resulting in an adjustment of 0.
601    unsigned endColumnExcludingBraces = unlinkedExecutable->unlinkedBodyEndColumn() + (endColumnIsOnStartLine ? 0 : 1);
602    unsigned startOffsetExcludingOpenBrace = startOffset + 1;
603    unsigned endOffsetExcludingCloseBrace = startOffset + sourceLength - 1;
604    SourceCode bodySource(source.provider(), startOffsetExcludingOpenBrace, endOffsetExcludingCloseBrace, firstLine, startColumn);
605
606    return FunctionExecutable::create(exec->vm(), bodySource, unlinkedExecutable, firstLine, firstLine + lineCount, startColumn, endColumnExcludingBraces, false);
607}
608
609String FunctionExecutable::paramString() const
610{
611    return m_unlinkedExecutable->paramString();
612}
613
614void ExecutableBase::dump(PrintStream& out) const
615{
616    ExecutableBase* realThis = const_cast<ExecutableBase*>(this);
617
618    if (classInfo() == NativeExecutable::info()) {
619        NativeExecutable* native = jsCast<NativeExecutable*>(realThis);
620        out.print("NativeExecutable:", RawPointer(bitwise_cast<void*>(native->function())), "/", RawPointer(bitwise_cast<void*>(native->constructor())));
621        return;
622    }
623
624    if (classInfo() == EvalExecutable::info()) {
625        EvalExecutable* eval = jsCast<EvalExecutable*>(realThis);
626        if (CodeBlock* codeBlock = eval->codeBlock())
627            out.print(*codeBlock);
628        else
629            out.print("EvalExecutable w/o CodeBlock");
630        return;
631    }
632
633    if (classInfo() == ProgramExecutable::info()) {
634        ProgramExecutable* eval = jsCast<ProgramExecutable*>(realThis);
635        if (CodeBlock* codeBlock = eval->codeBlock())
636            out.print(*codeBlock);
637        else
638            out.print("ProgramExecutable w/o CodeBlock");
639        return;
640    }
641
642    FunctionExecutable* function = jsCast<FunctionExecutable*>(realThis);
643    if (!function->eitherCodeBlock())
644        out.print("FunctionExecutable w/o CodeBlock");
645    else {
646        CommaPrinter comma("/");
647        if (function->codeBlockForCall())
648            out.print(comma, *function->codeBlockForCall());
649        if (function->codeBlockForConstruct())
650            out.print(comma, *function->codeBlockForConstruct());
651    }
652}
653
654CodeBlockHash ExecutableBase::hashFor(CodeSpecializationKind kind) const
655{
656    if (this->classInfo() == NativeExecutable::info())
657        return jsCast<const NativeExecutable*>(this)->hashFor(kind);
658
659    return jsCast<const ScriptExecutable*>(this)->hashFor(kind);
660}
661
662CodeBlockHash NativeExecutable::hashFor(CodeSpecializationKind kind) const
663{
664    if (kind == CodeForCall)
665        return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_function)));
666
667    RELEASE_ASSERT(kind == CodeForConstruct);
668    return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_constructor)));
669}
670
671CodeBlockHash ScriptExecutable::hashFor(CodeSpecializationKind kind) const
672{
673    return CodeBlockHash(source(), kind);
674}
675
676}
677