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