CodeBlock compilation and installation should be simplified and rationalized
[WebKit-https.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 "Operations.h"
35 #include "Parser.h"
36 #include <wtf/Vector.h>
37 #include <wtf/text/StringBuilder.h>
38
39 namespace JSC {
40
41 const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0, CREATE_METHOD_TABLE(ExecutableBase) };
42
43 #if ENABLE(JIT)
44 void ExecutableBase::destroy(JSCell* cell)
45 {
46     static_cast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();
47 }
48 #endif
49
50 void ExecutableBase::clearCode()
51 {
52 #if ENABLE(JIT)
53     m_jitCodeForCall.clear();
54     m_jitCodeForConstruct.clear();
55     m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
56     m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
57 #endif
58     m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
59     m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
60 }
61
62 #if ENABLE(DFG_JIT)
63 Intrinsic ExecutableBase::intrinsic() const
64 {
65     if (const NativeExecutable* nativeExecutable = jsDynamicCast<const NativeExecutable*>(this))
66         return nativeExecutable->intrinsic();
67     return NoIntrinsic;
68 }
69 #else
70 Intrinsic ExecutableBase::intrinsic() const
71 {
72     return NoIntrinsic;
73 }
74 #endif
75
76 const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(NativeExecutable) };
77
78 #if ENABLE(JIT)
79 void NativeExecutable::destroy(JSCell* cell)
80 {
81     static_cast<NativeExecutable*>(cell)->NativeExecutable::~NativeExecutable();
82 }
83 #endif
84
85 #if ENABLE(DFG_JIT)
86 Intrinsic NativeExecutable::intrinsic() const
87 {
88     return m_intrinsic;
89 }
90 #endif
91
92 #if ENABLE(JIT)
93 // Utility method used for jettisoning code blocks.
94 template<typename T>
95 static void jettisonCodeBlock(VM& vm, RefPtr<T>& codeBlock)
96 {
97     ASSERT(JITCode::isOptimizingJIT(codeBlock->jitType()));
98     ASSERT(codeBlock->alternative());
99     RefPtr<T> codeBlockToJettison = codeBlock.release();
100     codeBlock = static_pointer_cast<T>(codeBlockToJettison->releaseAlternative());
101     codeBlockToJettison->unlinkIncomingCalls();
102     vm.heap.jettisonDFGCodeBlock(static_pointer_cast<CodeBlock>(codeBlockToJettison.release()));
103 }
104 #endif
105
106 const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
107
108 #if ENABLE(JIT)
109 void ScriptExecutable::destroy(JSCell* cell)
110 {
111     static_cast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
112 }
113 #endif
114
115 void ScriptExecutable::installCode(CodeBlock* genericCodeBlock)
116 {
117     RELEASE_ASSERT(genericCodeBlock->ownerExecutable() == this);
118     
119     VM& vm = *genericCodeBlock->vm();
120     
121     if (vm.m_perBytecodeProfiler)
122         vm.m_perBytecodeProfiler->ensureBytecodesFor(genericCodeBlock);
123     
124     ASSERT(vm.heap.isDeferred());
125     
126     if (JITCode::isJIT(genericCodeBlock->jitType())) {
127         vm.heap.reportExtraMemoryCost(
128             sizeof(CodeBlock) + genericCodeBlock->jitCode()->size());
129     } else
130         vm.heap.reportExtraMemoryCost(sizeof(CodeBlock));
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 = genericCodeBlock->jitCodeWithArityCheck();
140         m_numParametersForCall = genericCodeBlock->numParameters();
141         break;
142     case CodeForConstruct:
143         m_jitCodeForConstruct = genericCodeBlock->jitCode();
144         m_jitCodeForConstructWithArityCheck = genericCodeBlock->jitCodeWithArityCheck();
145         m_numParametersForConstruct = genericCodeBlock->numParameters();
146         break;
147     }
148     
149     switch (genericCodeBlock->codeType()) {
150     case GlobalCode: {
151         ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
152         ProgramCodeBlock* codeBlock = static_cast<ProgramCodeBlock*>(genericCodeBlock);
153         
154         ASSERT(!codeBlock->jitCodeWithArityCheck());
155         ASSERT(kind == CodeForCall);
156         
157         oldCodeBlock = executable->m_programCodeBlock;
158         executable->m_programCodeBlock = codeBlock;
159         break;
160     }
161         
162     case EvalCode: {
163         EvalExecutable* executable = jsCast<EvalExecutable*>(this);
164         EvalCodeBlock* codeBlock = static_cast<EvalCodeBlock*>(genericCodeBlock);
165         
166         ASSERT(!codeBlock->jitCodeWithArityCheck());
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
195 PassRefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor(
196     CodeSpecializationKind kind, JSScope* scope, JSObject*& exception)
197 {
198     VM* vm = scope->vm();
199
200     ASSERT(vm->heap.isDeferred());
201     
202     if (classInfo() == EvalExecutable::info()) {
203         EvalExecutable* executable = jsCast<EvalExecutable*>(this);
204         RELEASE_ASSERT(kind == CodeForCall);
205         RELEASE_ASSERT(!executable->m_evalCodeBlock);
206         return adoptRef(new EvalCodeBlock(
207             executable, executable->m_unlinkedEvalCodeBlock.get(), scope,
208             executable->source().provider()));
209     }
210     
211     if (classInfo() == ProgramExecutable::info()) {
212         ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
213         RELEASE_ASSERT(kind == CodeForCall);
214         RELEASE_ASSERT(!executable->m_programCodeBlock);
215         return adoptRef(new ProgramCodeBlock(
216             executable, executable->m_unlinkedProgramCodeBlock.get(), scope,
217             executable->source().provider(), executable->source().startColumn()));
218     }
219     
220     RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
221     FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
222     RELEASE_ASSERT(!executable->codeBlockFor(kind));
223     JSGlobalObject* globalObject = scope->globalObject();
224     ParserError error;
225     DebuggerMode debuggerMode = globalObject->hasDebugger() ? DebuggerOn : DebuggerOff;
226     ProfilerMode profilerMode = globalObject->hasProfiler() ? ProfilerOn : ProfilerOff;
227     UnlinkedFunctionCodeBlock* unlinkedCodeBlock =
228         executable->m_unlinkedExecutable->codeBlockFor(
229             *vm, executable->m_source, kind, debuggerMode, profilerMode, error);
230     if (!unlinkedCodeBlock) {
231         exception = vm->throwException(
232             globalObject->globalExec(),
233             error.toErrorObject(globalObject, executable->m_source));
234         return 0;
235     }
236     
237     SourceProvider* provider = executable->source().provider();
238     unsigned sourceOffset = executable->source().startOffset();
239     unsigned startColumn = executable->source().startColumn();
240
241     return adoptRef(new FunctionCodeBlock(
242         executable, unlinkedCodeBlock, scope, provider, sourceOffset, startColumn));
243 }
244
245 PassRefPtr<CodeBlock> ScriptExecutable::newReplacementCodeBlockFor(
246     CodeSpecializationKind kind)
247 {
248     if (classInfo() == EvalExecutable::info()) {
249         RELEASE_ASSERT(kind == CodeForCall);
250         EvalExecutable* executable = jsCast<EvalExecutable*>(this);
251         RefPtr<EvalCodeBlock> result = adoptRef(new EvalCodeBlock(
252             CodeBlock::CopyParsedBlock, *executable->m_evalCodeBlock));
253         result->setAlternative(executable->m_evalCodeBlock);
254         return result;
255     }
256     
257     if (classInfo() == ProgramExecutable::info()) {
258         RELEASE_ASSERT(kind == CodeForCall);
259         ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
260         RefPtr<ProgramCodeBlock> result = adoptRef(new ProgramCodeBlock(
261             CodeBlock::CopyParsedBlock, *executable->m_programCodeBlock));
262         result->setAlternative(executable->m_programCodeBlock);
263         return result;
264     }
265
266     RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
267     FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
268     RefPtr<FunctionCodeBlock> result = adoptRef(new FunctionCodeBlock(
269         CodeBlock::CopyParsedBlock, *executable->codeBlockFor(kind)));
270     result->setAlternative(executable->codeBlockFor(kind));
271     return result;
272 }
273
274 JSObject* ScriptExecutable::prepareForExecutionImpl(
275     ExecState* exec, JSScope* scope, CodeSpecializationKind kind)
276 {
277     VM& vm = exec->vm();
278     DeferGC deferGC(vm.heap);
279     
280     JSObject* exception = 0;
281     RefPtr<CodeBlock> codeBlock = newCodeBlockFor(kind, scope, exception);
282     if (!codeBlock) {
283         RELEASE_ASSERT(exception);
284         return exception;
285     }
286     
287     JITCode::JITType jitType;
288 #if ENABLE(LLINT)
289     jitType = JITCode::InterpreterThunk;
290 #else
291     jitType = JITCode::BaselineJIT;
292 #endif
293     codeBlock->prepareForExecution(exec, jitType);
294
295     installCode(codeBlock.get());
296     return 0;
297 }
298
299 const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(EvalExecutable) };
300
301 EvalExecutable* EvalExecutable::create(ExecState* exec, const SourceCode& source, bool isInStrictContext) 
302 {
303     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
304     if (!globalObject->evalEnabled()) {
305         exec->vm().throwException(exec, createEvalError(exec, globalObject->evalDisabledErrorMessage()));
306         return 0;
307     }
308
309     EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext);
310     executable->finishCreation(exec->vm());
311
312     UnlinkedEvalCodeBlock* unlinkedEvalCode = globalObject->createEvalCodeBlock(exec, executable);
313     if (!unlinkedEvalCode)
314         return 0;
315
316     executable->m_unlinkedEvalCodeBlock.set(exec->vm(), executable, unlinkedEvalCode);
317
318     return executable;
319 }
320
321 EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
322     : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec, source, inStrictContext)
323 {
324 }
325
326 void EvalExecutable::destroy(JSCell* cell)
327 {
328     static_cast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable();
329 }
330
331 const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(ProgramExecutable) };
332
333 ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
334     : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec, source, false)
335 {
336 }
337
338 void ProgramExecutable::destroy(JSCell* cell)
339 {
340     static_cast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable();
341 }
342
343 const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
344
345 FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn)
346     : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->isInStrictContext())
347     , m_unlinkedExecutable(vm, this, unlinkedExecutable)
348 {
349     RELEASE_ASSERT(!source.isNull());
350     ASSERT(source.length());
351     m_firstLine = firstLine;
352     m_lastLine = lastLine;
353     m_startColumn = startColumn;
354 }
355
356 void FunctionExecutable::destroy(JSCell* cell)
357 {
358     static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
359 }
360
361 inline const char* samplingDescription(JITCode::JITType jitType)
362 {
363     switch (jitType) {
364     case JITCode::InterpreterThunk:
365         return "Interpreter Compilation (TOTAL)";
366     case JITCode::BaselineJIT:
367         return "Baseline Compilation (TOTAL)";
368     case JITCode::DFGJIT:
369         return "DFG Compilation (TOTAL)";
370     case JITCode::FTLJIT:
371         return "FTL Compilation (TOTAL)";
372     default:
373         RELEASE_ASSERT_NOT_REACHED();
374         return 0;
375     }
376 }
377
378 #if ENABLE(JIT)
379 void EvalExecutable::jettisonOptimizedCode(VM& vm)
380 {
381     jettisonCodeBlock(vm, m_evalCodeBlock);
382     m_jitCodeForCall = m_evalCodeBlock->jitCode();
383     ASSERT(!m_jitCodeForCallWithArityCheck);
384 }
385 #endif // ENABLE(JIT)
386
387 void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
388 {
389     EvalExecutable* thisObject = jsCast<EvalExecutable*>(cell);
390     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
391     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
392     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
393     ScriptExecutable::visitChildren(thisObject, visitor);
394     if (thisObject->m_evalCodeBlock)
395         thisObject->m_evalCodeBlock->visitAggregate(visitor);
396     visitor.append(&thisObject->m_unlinkedEvalCodeBlock);
397 }
398
399 void EvalExecutable::unlinkCalls()
400 {
401 #if ENABLE(JIT)
402     if (!m_jitCodeForCall)
403         return;
404     RELEASE_ASSERT(m_evalCodeBlock);
405     m_evalCodeBlock->unlinkCalls();
406 #endif
407 }
408
409 void EvalExecutable::clearCode()
410 {
411     m_evalCodeBlock.clear();
412     m_unlinkedEvalCodeBlock.clear();
413     Base::clearCode();
414 }
415
416 JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
417 {
418     ParserError error;
419     VM* vm = &exec->vm();
420     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
421     RefPtr<ProgramNode> programNode = parse<ProgramNode>(vm, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, error);
422     if (programNode)
423         return 0;
424     ASSERT(error.m_type != ParserError::ErrorNone);
425     return error.toErrorObject(lexicalGlobalObject, m_source);
426 }
427
428 #if ENABLE(JIT)
429 void ProgramExecutable::jettisonOptimizedCode(VM& vm)
430 {
431     jettisonCodeBlock(vm, m_programCodeBlock);
432     m_jitCodeForCall = m_programCodeBlock->jitCode();
433     ASSERT(!m_jitCodeForCallWithArityCheck);
434 }
435 #endif
436
437 void ProgramExecutable::unlinkCalls()
438 {
439 #if ENABLE(JIT)
440     if (!m_jitCodeForCall)
441         return;
442     RELEASE_ASSERT(m_programCodeBlock);
443     m_programCodeBlock->unlinkCalls();
444 #endif
445 }
446
447 JSObject* ProgramExecutable::initializeGlobalProperties(VM& vm, CallFrame* callFrame, JSScope* scope)
448 {
449     RELEASE_ASSERT(scope);
450     JSGlobalObject* globalObject = scope->globalObject();
451     RELEASE_ASSERT(globalObject);
452     ASSERT(&globalObject->vm() == &vm);
453
454     JSObject* exception = 0;
455     UnlinkedProgramCodeBlock* unlinkedCode = globalObject->createProgramCodeBlock(callFrame, this, &exception);
456     if (exception)
457         return exception;
458
459     m_unlinkedProgramCodeBlock.set(vm, this, unlinkedCode);
460
461     BatchedTransitionOptimizer optimizer(vm, globalObject);
462
463     const UnlinkedProgramCodeBlock::VariableDeclations& variableDeclarations = unlinkedCode->variableDeclarations();
464     const UnlinkedProgramCodeBlock::FunctionDeclations& functionDeclarations = unlinkedCode->functionDeclarations();
465
466     CallFrame* globalExec = globalObject->globalExec();
467
468     for (size_t i = 0; i < functionDeclarations.size(); ++i) {
469         UnlinkedFunctionExecutable* unlinkedFunctionExecutable = functionDeclarations[i].second.get();
470         JSValue value = JSFunction::create(globalExec, unlinkedFunctionExecutable->link(vm, m_source, lineNo(), 0), scope);
471         globalObject->addFunction(callFrame, functionDeclarations[i].first, value);
472     }
473
474     for (size_t i = 0; i < variableDeclarations.size(); ++i) {
475         if (variableDeclarations[i].second & DeclarationStacks::IsConstant)
476             globalObject->addConst(callFrame, variableDeclarations[i].first);
477         else
478             globalObject->addVar(callFrame, variableDeclarations[i].first);
479     }
480     return 0;
481 }
482
483 void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
484 {
485     ProgramExecutable* thisObject = jsCast<ProgramExecutable*>(cell);
486     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
487     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
488     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
489     ScriptExecutable::visitChildren(thisObject, visitor);
490     visitor.append(&thisObject->m_unlinkedProgramCodeBlock);
491     if (thisObject->m_programCodeBlock)
492         thisObject->m_programCodeBlock->visitAggregate(visitor);
493 }
494
495 void ProgramExecutable::clearCode()
496 {
497     m_programCodeBlock.clear();
498     m_unlinkedProgramCodeBlock.clear();
499     Base::clearCode();
500 }
501
502 FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
503 {
504     FunctionCodeBlock* result;
505     if (kind == CodeForCall)
506         result = m_codeBlockForCall.get();
507     else {
508         RELEASE_ASSERT(kind == CodeForConstruct);
509         result = m_codeBlockForConstruct.get();
510     }
511     if (!result)
512         return 0;
513     while (result->alternative())
514         result = static_cast<FunctionCodeBlock*>(result->alternative());
515     RELEASE_ASSERT(result);
516     ASSERT(JITCode::isBaselineCode(result->jitType()));
517     return result;
518 }
519
520 #if ENABLE(JIT)
521 void FunctionExecutable::jettisonOptimizedCodeForCall(VM& vm)
522 {
523     jettisonCodeBlock(vm, m_codeBlockForCall);
524     m_jitCodeForCall = m_codeBlockForCall->jitCode();
525     m_jitCodeForCallWithArityCheck = m_codeBlockForCall->jitCodeWithArityCheck();
526 }
527
528 void FunctionExecutable::jettisonOptimizedCodeForConstruct(VM& vm)
529 {
530     jettisonCodeBlock(vm, m_codeBlockForConstruct);
531     m_jitCodeForConstruct = m_codeBlockForConstruct->jitCode();
532     m_jitCodeForConstructWithArityCheck = m_codeBlockForConstruct->jitCodeWithArityCheck();
533 }
534 #endif
535
536 void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
537 {
538     FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell);
539     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
540     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
541     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
542     ScriptExecutable::visitChildren(thisObject, visitor);
543     if (thisObject->m_codeBlockForCall)
544         thisObject->m_codeBlockForCall->visitAggregate(visitor);
545     if (thisObject->m_codeBlockForConstruct)
546         thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
547     visitor.append(&thisObject->m_unlinkedExecutable);
548 }
549
550 void FunctionExecutable::clearCodeIfNotCompiling()
551 {
552     if (isCompiling())
553         return;
554     clearCode();
555 }
556
557 void FunctionExecutable::clearUnlinkedCodeForRecompilationIfNotCompiling()
558 {
559     if (isCompiling())
560         return;
561     m_unlinkedExecutable->clearCodeForRecompilation();
562 }
563
564 void FunctionExecutable::clearCode()
565 {
566     m_codeBlockForCall.clear();
567     m_codeBlockForConstruct.clear();
568     Base::clearCode();
569 }
570
571 void FunctionExecutable::unlinkCalls()
572 {
573 #if ENABLE(JIT)
574     if (!!m_jitCodeForCall) {
575         RELEASE_ASSERT(m_codeBlockForCall);
576         m_codeBlockForCall->unlinkCalls();
577     }
578     if (!!m_jitCodeForConstruct) {
579         RELEASE_ASSERT(m_codeBlockForConstruct);
580         m_codeBlockForConstruct->unlinkCalls();
581     }
582 #endif
583 }
584
585 FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
586 {
587     UnlinkedFunctionExecutable* unlinkedFunction = UnlinkedFunctionExecutable::fromGlobalCode(name, exec, debugger, source, exception);
588     if (!unlinkedFunction)
589         return 0;
590     unsigned firstLine = source.firstLine() + unlinkedFunction->firstLineOffset();
591     unsigned startOffset = source.startOffset() + unlinkedFunction->startOffset();
592     unsigned startColumn = source.startColumn();
593     unsigned sourceLength = unlinkedFunction->sourceLength();
594     SourceCode functionSource(source.provider(), startOffset, startOffset + sourceLength, firstLine, startColumn);
595     return FunctionExecutable::create(exec->vm(), functionSource, unlinkedFunction, firstLine, unlinkedFunction->lineCount(), startColumn);
596 }
597
598 String FunctionExecutable::paramString() const
599 {
600     return m_unlinkedExecutable->paramString();
601 }
602
603 CodeBlockHash ExecutableBase::hashFor(CodeSpecializationKind kind) const
604 {
605     if (this->classInfo() == NativeExecutable::info())
606         return jsCast<const NativeExecutable*>(this)->hashFor(kind);
607     
608     return jsCast<const ScriptExecutable*>(this)->hashFor(kind);
609 }
610
611 CodeBlockHash NativeExecutable::hashFor(CodeSpecializationKind kind) const
612 {
613     if (kind == CodeForCall)
614         return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_function)));
615     
616     RELEASE_ASSERT(kind == CodeForConstruct);
617     return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_constructor)));
618 }
619
620 CodeBlockHash ScriptExecutable::hashFor(CodeSpecializationKind kind) const
621 {
622     return CodeBlockHash(source(), kind);
623 }
624
625 }