fromGlobalCode has an unused Debugger* argument
[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 "JSFunctionNameScope.h"
35 #include "LLIntEntrypoint.h"
36 #include "Parser.h"
37 #include "ProfilerDatabase.h"
38 #include "TypeProfiler.h"
39 #include <wtf/CommaPrinter.h>
40 #include <wtf/Vector.h>
41 #include <wtf/text/StringBuilder.h>
42
43 namespace JSC {
44
45 const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, CREATE_METHOD_TABLE(ExecutableBase) };
46
47 void ExecutableBase::destroy(JSCell* cell)
48 {
49     static_cast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();
50 }
51
52 void ExecutableBase::clearCode()
53 {
54 #if ENABLE(JIT)
55     m_jitCodeForCall.clear();
56     m_jitCodeForConstruct.clear();
57     m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
58     m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
59     m_jitCodeForCallWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
60     m_jitCodeForConstructWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
61 #endif
62     m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
63     m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
64 }
65
66 #if ENABLE(DFG_JIT)
67 Intrinsic ExecutableBase::intrinsic() const
68 {
69     if (const NativeExecutable* nativeExecutable = jsDynamicCast<const NativeExecutable*>(this))
70         return nativeExecutable->intrinsic();
71     return NoIntrinsic;
72 }
73 #else
74 Intrinsic ExecutableBase::intrinsic() const
75 {
76     return NoIntrinsic;
77 }
78 #endif
79
80 const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, CREATE_METHOD_TABLE(NativeExecutable) };
81
82 void NativeExecutable::destroy(JSCell* cell)
83 {
84     static_cast<NativeExecutable*>(cell)->NativeExecutable::~NativeExecutable();
85 }
86
87 #if ENABLE(DFG_JIT)
88 Intrinsic NativeExecutable::intrinsic() const
89 {
90     return m_intrinsic;
91 }
92 #endif
93
94 const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
95
96 ScriptExecutable::ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext)
97     : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED)
98     , m_source(source)
99     , m_features(isInStrictContext ? StrictModeFeature : 0)
100     , m_hasCapturedVariables(false)
101     , m_neverInline(false)
102     , m_didTryToEnterInLoop(false)
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 PassRefPtr<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(
240             *vm, executable->m_source, kind, debuggerMode, profilerMode, executable->bodyIncludesBraces(), error);
241     recordParse(executable->m_unlinkedExecutable->features(), executable->m_unlinkedExecutable->hasCapturedVariables(), lineNo(), lastLine(), startColumn(), endColumn()); 
242     if (!unlinkedCodeBlock) {
243         exception = vm->throwException(
244             globalObject->globalExec(),
245             error.toErrorObject(globalObject, executable->m_source));
246         return 0;
247     }
248
249     // Parsing reveals whether our function uses features that require a separate function name object in the scope chain.
250     // Be sure to add this scope before linking the bytecode because this scope will change the resolution depth of non-local variables.
251     if (functionNameIsInScope(executable->name(), executable->functionMode())
252         && functionNameScopeIsDynamic(executable->usesEval(), executable->isStrictMode())) {
253         // We shouldn't have to do this. But we do, because bytecode linking requires a real scope
254         // chain.
255         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=141885
256         SymbolTable* symbolTable =
257             SymbolTable::createNameScopeTable(*vm, executable->name(), ReadOnly | DontDelete);
258         scope = JSFunctionNameScope::create(
259             *vm, scope->globalObject(), scope, symbolTable, function);
260     }
261     
262     SourceProvider* provider = executable->source().provider();
263     unsigned sourceOffset = executable->source().startOffset();
264     unsigned startColumn = executable->source().startColumn();
265
266     return adoptRef(new FunctionCodeBlock(
267         executable, unlinkedCodeBlock, scope, provider, sourceOffset, startColumn));
268 }
269
270 PassRefPtr<CodeBlock> ScriptExecutable::newReplacementCodeBlockFor(
271     CodeSpecializationKind kind)
272 {
273     if (classInfo() == EvalExecutable::info()) {
274         RELEASE_ASSERT(kind == CodeForCall);
275         EvalExecutable* executable = jsCast<EvalExecutable*>(this);
276         EvalCodeBlock* baseline = static_cast<EvalCodeBlock*>(
277             executable->m_evalCodeBlock->baselineVersion());
278         RefPtr<EvalCodeBlock> result = adoptRef(new EvalCodeBlock(
279             CodeBlock::CopyParsedBlock, *baseline));
280         result->setAlternative(baseline);
281         return result;
282     }
283     
284     if (classInfo() == ProgramExecutable::info()) {
285         RELEASE_ASSERT(kind == CodeForCall);
286         ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
287         ProgramCodeBlock* baseline = static_cast<ProgramCodeBlock*>(
288             executable->m_programCodeBlock->baselineVersion());
289         RefPtr<ProgramCodeBlock> result = adoptRef(new ProgramCodeBlock(
290             CodeBlock::CopyParsedBlock, *baseline));
291         result->setAlternative(baseline);
292         return result;
293     }
294
295     RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
296     FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
297     FunctionCodeBlock* baseline = static_cast<FunctionCodeBlock*>(
298         executable->codeBlockFor(kind)->baselineVersion());
299     RefPtr<FunctionCodeBlock> result = adoptRef(new FunctionCodeBlock(
300         CodeBlock::CopyParsedBlock, *baseline));
301     result->setAlternative(baseline);
302     return result;
303 }
304
305 static void setupLLInt(VM& vm, CodeBlock* codeBlock)
306 {
307     LLInt::setEntrypoint(vm, codeBlock);
308 }
309
310 static void setupJIT(VM& vm, CodeBlock* codeBlock)
311 {
312 #if ENABLE(JIT)
313     CompilationResult result = JIT::compile(&vm, codeBlock, JITCompilationMustSucceed);
314     RELEASE_ASSERT(result == CompilationSuccessful);
315 #else
316     UNUSED_PARAM(vm);
317     UNUSED_PARAM(codeBlock);
318     UNREACHABLE_FOR_PLATFORM();
319 #endif
320 }
321
322 JSObject* ScriptExecutable::prepareForExecutionImpl(
323     ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind)
324 {
325     VM& vm = exec->vm();
326     DeferGC deferGC(vm.heap);
327     
328     JSObject* exception = 0;
329     RefPtr<CodeBlock> codeBlock = newCodeBlockFor(kind, function, scope, exception);
330     if (!codeBlock) {
331         RELEASE_ASSERT(exception);
332         return exception;
333     }
334     
335     if (Options::validateBytecode())
336         codeBlock->validate();
337     
338     if (Options::useLLInt())
339         setupLLInt(vm, codeBlock.get());
340     else
341         setupJIT(vm, codeBlock.get());
342     
343     installCode(codeBlock.get());
344     return 0;
345 }
346
347 const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(EvalExecutable) };
348
349 EvalExecutable* EvalExecutable::create(ExecState* exec, const SourceCode& source, bool isInStrictContext) 
350 {
351     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
352     if (!globalObject->evalEnabled()) {
353         exec->vm().throwException(exec, createEvalError(exec, globalObject->evalDisabledErrorMessage()));
354         return 0;
355     }
356
357     EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext);
358     executable->finishCreation(exec->vm());
359
360     UnlinkedEvalCodeBlock* unlinkedEvalCode = globalObject->createEvalCodeBlock(exec, executable);
361     if (!unlinkedEvalCode)
362         return 0;
363
364     executable->m_unlinkedEvalCodeBlock.set(exec->vm(), executable, unlinkedEvalCode);
365
366     return executable;
367 }
368
369 EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
370     : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec->vm(), source, inStrictContext)
371 {
372 }
373
374 void EvalExecutable::destroy(JSCell* cell)
375 {
376     static_cast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable();
377 }
378
379 const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(ProgramExecutable) };
380
381 ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
382     : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec->vm(), source, false)
383 {
384     m_typeProfilingStartOffset = 0;
385     m_typeProfilingEndOffset = source.length() - 1;
386     if (exec->vm().typeProfiler() || exec->vm().controlFlowProfiler())
387         exec->vm().functionHasExecutedCache()->insertUnexecutedRange(sourceID(), m_typeProfilingStartOffset, m_typeProfilingEndOffset);
388 }
389
390 void ProgramExecutable::destroy(JSCell* cell)
391 {
392     static_cast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable();
393 }
394
395 const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
396
397 FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, bool bodyIncludesBraces)
398     : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->isInStrictContext())
399     , m_unlinkedExecutable(vm, this, unlinkedExecutable)
400     , m_bodyIncludesBraces(bodyIncludesBraces)
401 {
402     RELEASE_ASSERT(!source.isNull());
403     ASSERT(source.length());
404     m_firstLine = firstLine;
405     m_lastLine = lastLine;
406     ASSERT(startColumn != UINT_MAX);
407     ASSERT(endColumn != UINT_MAX);
408     m_startColumn = startColumn;
409     m_endColumn = endColumn;
410     m_typeProfilingStartOffset = unlinkedExecutable->typeProfilingStartOffset();
411     m_typeProfilingEndOffset = unlinkedExecutable->typeProfilingEndOffset();
412 }
413
414 void FunctionExecutable::destroy(JSCell* cell)
415 {
416     static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
417 }
418
419 inline const char* samplingDescription(JITCode::JITType jitType)
420 {
421     switch (jitType) {
422     case JITCode::InterpreterThunk:
423         return "Interpreter Compilation (TOTAL)";
424     case JITCode::BaselineJIT:
425         return "Baseline Compilation (TOTAL)";
426     case JITCode::DFGJIT:
427         return "DFG Compilation (TOTAL)";
428     case JITCode::FTLJIT:
429         return "FTL Compilation (TOTAL)";
430     default:
431         RELEASE_ASSERT_NOT_REACHED();
432         return 0;
433     }
434 }
435
436 void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
437 {
438     EvalExecutable* thisObject = jsCast<EvalExecutable*>(cell);
439     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
440     ScriptExecutable::visitChildren(thisObject, visitor);
441     if (thisObject->m_evalCodeBlock)
442         thisObject->m_evalCodeBlock->visitAggregate(visitor);
443     visitor.append(&thisObject->m_unlinkedEvalCodeBlock);
444 }
445
446 void EvalExecutable::unlinkCalls()
447 {
448 #if ENABLE(JIT)
449     if (!m_jitCodeForCall)
450         return;
451     RELEASE_ASSERT(m_evalCodeBlock);
452     m_evalCodeBlock->unlinkCalls();
453 #endif
454 }
455
456 void EvalExecutable::clearCode()
457 {
458     m_evalCodeBlock.clear();
459     m_unlinkedEvalCodeBlock.clear();
460     Base::clearCode();
461 }
462
463 JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
464 {
465     ParserError error;
466     VM* vm = &exec->vm();
467     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
468     std::unique_ptr<ProgramNode> programNode = parse<ProgramNode>(vm, m_source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error);
469     if (programNode)
470         return 0;
471     ASSERT(error.isValid());
472     return error.toErrorObject(lexicalGlobalObject, m_source);
473 }
474
475 void ProgramExecutable::unlinkCalls()
476 {
477 #if ENABLE(JIT)
478     if (!m_jitCodeForCall)
479         return;
480     RELEASE_ASSERT(m_programCodeBlock);
481     m_programCodeBlock->unlinkCalls();
482 #endif
483 }
484
485 JSObject* ProgramExecutable::initializeGlobalProperties(VM& vm, CallFrame* callFrame, JSScope* scope)
486 {
487     RELEASE_ASSERT(scope);
488     JSGlobalObject* globalObject = scope->globalObject();
489     RELEASE_ASSERT(globalObject);
490     ASSERT(&globalObject->vm() == &vm);
491
492     JSObject* exception = 0;
493     UnlinkedProgramCodeBlock* unlinkedCodeBlock = globalObject->createProgramCodeBlock(callFrame, this, &exception);
494     if (exception)
495         return exception;
496
497     m_unlinkedProgramCodeBlock.set(vm, this, unlinkedCodeBlock);
498
499     BatchedTransitionOptimizer optimizer(vm, globalObject);
500
501     const UnlinkedProgramCodeBlock::VariableDeclations& variableDeclarations = unlinkedCodeBlock->variableDeclarations();
502     const UnlinkedProgramCodeBlock::FunctionDeclations& functionDeclarations = unlinkedCodeBlock->functionDeclarations();
503
504     for (size_t i = 0; i < functionDeclarations.size(); ++i) {
505         UnlinkedFunctionExecutable* unlinkedFunctionExecutable = functionDeclarations[i].second.get();
506         JSValue value = JSFunction::create(vm, unlinkedFunctionExecutable->link(vm, m_source, lineNo()), scope);
507         globalObject->addFunction(callFrame, functionDeclarations[i].first, value);
508         if (vm.typeProfiler() || vm.controlFlowProfiler()) {
509             vm.functionHasExecutedCache()->insertUnexecutedRange(sourceID(), 
510                 unlinkedFunctionExecutable->typeProfilingStartOffset(), 
511                 unlinkedFunctionExecutable->typeProfilingEndOffset());
512         }
513     }
514
515     for (size_t i = 0; i < variableDeclarations.size(); ++i) {
516         if (variableDeclarations[i].second & DeclarationStacks::IsConstant)
517             globalObject->addConst(callFrame, variableDeclarations[i].first);
518         else
519             globalObject->addVar(callFrame, variableDeclarations[i].first);
520     }
521     return 0;
522 }
523
524 void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
525 {
526     ProgramExecutable* thisObject = jsCast<ProgramExecutable*>(cell);
527     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
528     ScriptExecutable::visitChildren(thisObject, visitor);
529     visitor.append(&thisObject->m_unlinkedProgramCodeBlock);
530     if (thisObject->m_programCodeBlock)
531         thisObject->m_programCodeBlock->visitAggregate(visitor);
532 }
533
534 void ProgramExecutable::clearCode()
535 {
536     m_programCodeBlock.clear();
537     m_unlinkedProgramCodeBlock.clear();
538     Base::clearCode();
539 }
540
541 FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
542 {
543     FunctionCodeBlock* result;
544     if (kind == CodeForCall)
545         result = m_codeBlockForCall.get();
546     else {
547         RELEASE_ASSERT(kind == CodeForConstruct);
548         result = m_codeBlockForConstruct.get();
549     }
550     if (!result)
551         return 0;
552     return static_cast<FunctionCodeBlock*>(result->baselineAlternative());
553 }
554
555 void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
556 {
557     FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell);
558     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
559     ScriptExecutable::visitChildren(thisObject, visitor);
560     if (thisObject->m_codeBlockForCall)
561         thisObject->m_codeBlockForCall->visitAggregate(visitor);
562     if (thisObject->m_codeBlockForConstruct)
563         thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
564     visitor.append(&thisObject->m_unlinkedExecutable);
565 }
566
567 SymbolTable* FunctionExecutable::symbolTable(CodeSpecializationKind kind)
568 {
569     return codeBlockFor(kind)->symbolTable();
570 }
571
572 void FunctionExecutable::clearCodeIfNotCompiling()
573 {
574     if (isCompiling())
575         return;
576     clearCode();
577 }
578
579 void FunctionExecutable::clearUnlinkedCodeForRecompilationIfNotCompiling()
580 {
581     if (isCompiling())
582         return;
583     m_unlinkedExecutable->clearCodeForRecompilation();
584 }
585
586 void FunctionExecutable::clearCode()
587 {
588     m_codeBlockForCall.clear();
589     m_codeBlockForConstruct.clear();
590     Base::clearCode();
591 }
592
593 void FunctionExecutable::unlinkCalls()
594 {
595 #if ENABLE(JIT)
596     if (!!m_jitCodeForCall) {
597         RELEASE_ASSERT(m_codeBlockForCall);
598         m_codeBlockForCall->unlinkCalls();
599     }
600     if (!!m_jitCodeForConstruct) {
601         RELEASE_ASSERT(m_codeBlockForConstruct);
602         m_codeBlockForConstruct->unlinkCalls();
603     }
604 #endif
605 }
606
607 FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& name, ExecState& exec, const SourceCode& source, JSObject*& exception)
608 {
609     UnlinkedFunctionExecutable* unlinkedExecutable = UnlinkedFunctionExecutable::fromGlobalCode(name, exec, source, exception);
610     if (!unlinkedExecutable)
611         return 0;
612     unsigned lineCount = unlinkedExecutable->lineCount();
613     unsigned firstLine = source.firstLine() + unlinkedExecutable->firstLineOffset();
614     unsigned startOffset = source.startOffset() + unlinkedExecutable->startOffset();
615
616     // We don't have any owner executable. The source string is effectively like a global
617     // string (like in the handling of eval). Hence, the startColumn is always 1.
618     unsigned startColumn = 1;
619     unsigned sourceLength = unlinkedExecutable->sourceLength();
620     bool endColumnIsOnStartLine = !lineCount;
621     // The unlinkedBodyEndColumn is based-0. Hence, we need to add 1 to it. But if the
622     // endColumn is on the startLine, then we need to subtract back the adjustment for
623     // the open brace resulting in an adjustment of 0.
624     unsigned endColumnExcludingBraces = unlinkedExecutable->unlinkedBodyEndColumn() + (endColumnIsOnStartLine ? 0 : 1);
625     unsigned startOffsetExcludingOpenBrace = startOffset + 1;
626     unsigned endOffsetExcludingCloseBrace = startOffset + sourceLength - 1;
627     SourceCode bodySource(source.provider(), startOffsetExcludingOpenBrace, endOffsetExcludingCloseBrace, firstLine, startColumn);
628
629     return FunctionExecutable::create(exec.vm(), bodySource, unlinkedExecutable, firstLine, firstLine + lineCount, startColumn, endColumnExcludingBraces, false);
630 }
631
632 String FunctionExecutable::paramString() const
633 {
634     return m_unlinkedExecutable->paramString();
635 }
636
637 void ExecutableBase::dump(PrintStream& out) const
638 {
639     ExecutableBase* realThis = const_cast<ExecutableBase*>(this);
640     
641     if (classInfo() == NativeExecutable::info()) {
642         NativeExecutable* native = jsCast<NativeExecutable*>(realThis);
643         out.print("NativeExecutable:", RawPointer(bitwise_cast<void*>(native->function())), "/", RawPointer(bitwise_cast<void*>(native->constructor())));
644         return;
645     }
646     
647     if (classInfo() == EvalExecutable::info()) {
648         EvalExecutable* eval = jsCast<EvalExecutable*>(realThis);
649         if (CodeBlock* codeBlock = eval->codeBlock())
650             out.print(*codeBlock);
651         else
652             out.print("EvalExecutable w/o CodeBlock");
653         return;
654     }
655     
656     if (classInfo() == ProgramExecutable::info()) {
657         ProgramExecutable* eval = jsCast<ProgramExecutable*>(realThis);
658         if (CodeBlock* codeBlock = eval->codeBlock())
659             out.print(*codeBlock);
660         else
661             out.print("ProgramExecutable w/o CodeBlock");
662         return;
663     }
664     
665     FunctionExecutable* function = jsCast<FunctionExecutable*>(realThis);
666     if (!function->eitherCodeBlock())
667         out.print("FunctionExecutable w/o CodeBlock");
668     else {
669         CommaPrinter comma("/");
670         if (function->codeBlockForCall())
671             out.print(comma, *function->codeBlockForCall());
672         if (function->codeBlockForConstruct())
673             out.print(comma, *function->codeBlockForConstruct());
674     }
675 }
676
677 CodeBlockHash ExecutableBase::hashFor(CodeSpecializationKind kind) const
678 {
679     if (this->classInfo() == NativeExecutable::info())
680         return jsCast<const NativeExecutable*>(this)->hashFor(kind);
681     
682     return jsCast<const ScriptExecutable*>(this)->hashFor(kind);
683 }
684
685 CodeBlockHash NativeExecutable::hashFor(CodeSpecializationKind kind) const
686 {
687     if (kind == CodeForCall)
688         return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_function)));
689     
690     RELEASE_ASSERT(kind == CodeForConstruct);
691     return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_constructor)));
692 }
693
694 CodeBlockHash ScriptExecutable::hashFor(CodeSpecializationKind kind) const
695 {
696     return CodeBlockHash(source(), kind);
697 }
698
699 }