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     CompilationResult result = codeBlock->prepareForExecution(exec, jitType);
294     RELEASE_ASSERT(result == CompilationSuccessful);
295
296     installCode(codeBlock.get());
297     return 0;
298 }
299
300 const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(EvalExecutable) };
301
302 EvalExecutable* EvalExecutable::create(ExecState* exec, const SourceCode& source, bool isInStrictContext) 
303 {
304     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
305     if (!globalObject->evalEnabled()) {
306         exec->vm().throwException(exec, createEvalError(exec, globalObject->evalDisabledErrorMessage()));
307         return 0;
308     }
309
310     EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext);
311     executable->finishCreation(exec->vm());
312
313     UnlinkedEvalCodeBlock* unlinkedEvalCode = globalObject->createEvalCodeBlock(exec, executable);
314     if (!unlinkedEvalCode)
315         return 0;
316
317     executable->m_unlinkedEvalCodeBlock.set(exec->vm(), executable, unlinkedEvalCode);
318
319     return executable;
320 }
321
322 EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
323     : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec, source, inStrictContext)
324 {
325 }
326
327 void EvalExecutable::destroy(JSCell* cell)
328 {
329     static_cast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable();
330 }
331
332 const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(ProgramExecutable) };
333
334 ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
335     : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec, source, false)
336 {
337 }
338
339 void ProgramExecutable::destroy(JSCell* cell)
340 {
341     static_cast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable();
342 }
343
344 const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
345
346 FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn)
347     : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->isInStrictContext())
348     , m_unlinkedExecutable(vm, this, unlinkedExecutable)
349 {
350     RELEASE_ASSERT(!source.isNull());
351     ASSERT(source.length());
352     m_firstLine = firstLine;
353     m_lastLine = lastLine;
354     m_startColumn = startColumn;
355 }
356
357 void FunctionExecutable::destroy(JSCell* cell)
358 {
359     static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
360 }
361
362 inline const char* samplingDescription(JITCode::JITType jitType)
363 {
364     switch (jitType) {
365     case JITCode::InterpreterThunk:
366         return "Interpreter Compilation (TOTAL)";
367     case JITCode::BaselineJIT:
368         return "Baseline Compilation (TOTAL)";
369     case JITCode::DFGJIT:
370         return "DFG Compilation (TOTAL)";
371     case JITCode::FTLJIT:
372         return "FTL Compilation (TOTAL)";
373     default:
374         RELEASE_ASSERT_NOT_REACHED();
375         return 0;
376     }
377 }
378
379 #if ENABLE(JIT)
380 void EvalExecutable::jettisonOptimizedCode(VM& vm)
381 {
382     jettisonCodeBlock(vm, m_evalCodeBlock);
383     m_jitCodeForCall = m_evalCodeBlock->jitCode();
384     ASSERT(!m_jitCodeForCallWithArityCheck);
385 }
386 #endif // ENABLE(JIT)
387
388 void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
389 {
390     EvalExecutable* thisObject = jsCast<EvalExecutable*>(cell);
391     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
392     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
393     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
394     ScriptExecutable::visitChildren(thisObject, visitor);
395     if (thisObject->m_evalCodeBlock)
396         thisObject->m_evalCodeBlock->visitAggregate(visitor);
397     visitor.append(&thisObject->m_unlinkedEvalCodeBlock);
398 }
399
400 void EvalExecutable::unlinkCalls()
401 {
402 #if ENABLE(JIT)
403     if (!m_jitCodeForCall)
404         return;
405     RELEASE_ASSERT(m_evalCodeBlock);
406     m_evalCodeBlock->unlinkCalls();
407 #endif
408 }
409
410 void EvalExecutable::clearCode()
411 {
412     m_evalCodeBlock.clear();
413     m_unlinkedEvalCodeBlock.clear();
414     Base::clearCode();
415 }
416
417 JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
418 {
419     ParserError error;
420     VM* vm = &exec->vm();
421     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
422     RefPtr<ProgramNode> programNode = parse<ProgramNode>(vm, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, error);
423     if (programNode)
424         return 0;
425     ASSERT(error.m_type != ParserError::ErrorNone);
426     return error.toErrorObject(lexicalGlobalObject, m_source);
427 }
428
429 #if ENABLE(JIT)
430 void ProgramExecutable::jettisonOptimizedCode(VM& vm)
431 {
432     jettisonCodeBlock(vm, m_programCodeBlock);
433     m_jitCodeForCall = m_programCodeBlock->jitCode();
434     ASSERT(!m_jitCodeForCallWithArityCheck);
435 }
436 #endif
437
438 void ProgramExecutable::unlinkCalls()
439 {
440 #if ENABLE(JIT)
441     if (!m_jitCodeForCall)
442         return;
443     RELEASE_ASSERT(m_programCodeBlock);
444     m_programCodeBlock->unlinkCalls();
445 #endif
446 }
447
448 JSObject* ProgramExecutable::initializeGlobalProperties(VM& vm, CallFrame* callFrame, JSScope* scope)
449 {
450     RELEASE_ASSERT(scope);
451     JSGlobalObject* globalObject = scope->globalObject();
452     RELEASE_ASSERT(globalObject);
453     ASSERT(&globalObject->vm() == &vm);
454
455     JSObject* exception = 0;
456     UnlinkedProgramCodeBlock* unlinkedCode = globalObject->createProgramCodeBlock(callFrame, this, &exception);
457     if (exception)
458         return exception;
459
460     m_unlinkedProgramCodeBlock.set(vm, this, unlinkedCode);
461
462     BatchedTransitionOptimizer optimizer(vm, globalObject);
463
464     const UnlinkedProgramCodeBlock::VariableDeclations& variableDeclarations = unlinkedCode->variableDeclarations();
465     const UnlinkedProgramCodeBlock::FunctionDeclations& functionDeclarations = unlinkedCode->functionDeclarations();
466
467     CallFrame* globalExec = globalObject->globalExec();
468
469     for (size_t i = 0; i < functionDeclarations.size(); ++i) {
470         UnlinkedFunctionExecutable* unlinkedFunctionExecutable = functionDeclarations[i].second.get();
471         JSValue value = JSFunction::create(globalExec, unlinkedFunctionExecutable->link(vm, m_source, lineNo(), 0), scope);
472         globalObject->addFunction(callFrame, functionDeclarations[i].first, value);
473     }
474
475     for (size_t i = 0; i < variableDeclarations.size(); ++i) {
476         if (variableDeclarations[i].second & DeclarationStacks::IsConstant)
477             globalObject->addConst(callFrame, variableDeclarations[i].first);
478         else
479             globalObject->addVar(callFrame, variableDeclarations[i].first);
480     }
481     return 0;
482 }
483
484 void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
485 {
486     ProgramExecutable* thisObject = jsCast<ProgramExecutable*>(cell);
487     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
488     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
489     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
490     ScriptExecutable::visitChildren(thisObject, visitor);
491     visitor.append(&thisObject->m_unlinkedProgramCodeBlock);
492     if (thisObject->m_programCodeBlock)
493         thisObject->m_programCodeBlock->visitAggregate(visitor);
494 }
495
496 void ProgramExecutable::clearCode()
497 {
498     m_programCodeBlock.clear();
499     m_unlinkedProgramCodeBlock.clear();
500     Base::clearCode();
501 }
502
503 FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
504 {
505     FunctionCodeBlock* result;
506     if (kind == CodeForCall)
507         result = m_codeBlockForCall.get();
508     else {
509         RELEASE_ASSERT(kind == CodeForConstruct);
510         result = m_codeBlockForConstruct.get();
511     }
512     if (!result)
513         return 0;
514     while (result->alternative())
515         result = static_cast<FunctionCodeBlock*>(result->alternative());
516     RELEASE_ASSERT(result);
517     ASSERT(JITCode::isBaselineCode(result->jitType()));
518     return result;
519 }
520
521 #if ENABLE(JIT)
522 void FunctionExecutable::jettisonOptimizedCodeForCall(VM& vm)
523 {
524     jettisonCodeBlock(vm, m_codeBlockForCall);
525     m_jitCodeForCall = m_codeBlockForCall->jitCode();
526     m_jitCodeForCallWithArityCheck = m_codeBlockForCall->jitCodeWithArityCheck();
527 }
528
529 void FunctionExecutable::jettisonOptimizedCodeForConstruct(VM& vm)
530 {
531     jettisonCodeBlock(vm, m_codeBlockForConstruct);
532     m_jitCodeForConstruct = m_codeBlockForConstruct->jitCode();
533     m_jitCodeForConstructWithArityCheck = m_codeBlockForConstruct->jitCodeWithArityCheck();
534 }
535 #endif
536
537 void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
538 {
539     FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell);
540     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
541     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
542     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
543     ScriptExecutable::visitChildren(thisObject, visitor);
544     if (thisObject->m_codeBlockForCall)
545         thisObject->m_codeBlockForCall->visitAggregate(visitor);
546     if (thisObject->m_codeBlockForConstruct)
547         thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
548     visitor.append(&thisObject->m_unlinkedExecutable);
549 }
550
551 void FunctionExecutable::clearCodeIfNotCompiling()
552 {
553     if (isCompiling())
554         return;
555     clearCode();
556 }
557
558 void FunctionExecutable::clearUnlinkedCodeForRecompilationIfNotCompiling()
559 {
560     if (isCompiling())
561         return;
562     m_unlinkedExecutable->clearCodeForRecompilation();
563 }
564
565 void FunctionExecutable::clearCode()
566 {
567     m_codeBlockForCall.clear();
568     m_codeBlockForConstruct.clear();
569     Base::clearCode();
570 }
571
572 void FunctionExecutable::unlinkCalls()
573 {
574 #if ENABLE(JIT)
575     if (!!m_jitCodeForCall) {
576         RELEASE_ASSERT(m_codeBlockForCall);
577         m_codeBlockForCall->unlinkCalls();
578     }
579     if (!!m_jitCodeForConstruct) {
580         RELEASE_ASSERT(m_codeBlockForConstruct);
581         m_codeBlockForConstruct->unlinkCalls();
582     }
583 #endif
584 }
585
586 FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
587 {
588     UnlinkedFunctionExecutable* unlinkedFunction = UnlinkedFunctionExecutable::fromGlobalCode(name, exec, debugger, source, exception);
589     if (!unlinkedFunction)
590         return 0;
591     unsigned firstLine = source.firstLine() + unlinkedFunction->firstLineOffset();
592     unsigned startOffset = source.startOffset() + unlinkedFunction->startOffset();
593     unsigned startColumn = source.startColumn();
594     unsigned sourceLength = unlinkedFunction->sourceLength();
595     SourceCode functionSource(source.provider(), startOffset, startOffset + sourceLength, firstLine, startColumn);
596     return FunctionExecutable::create(exec->vm(), functionSource, unlinkedFunction, firstLine, unlinkedFunction->lineCount(), startColumn);
597 }
598
599 String FunctionExecutable::paramString() const
600 {
601     return m_unlinkedExecutable->paramString();
602 }
603
604 CodeBlockHash ExecutableBase::hashFor(CodeSpecializationKind kind) const
605 {
606     if (this->classInfo() == NativeExecutable::info())
607         return jsCast<const NativeExecutable*>(this)->hashFor(kind);
608     
609     return jsCast<const ScriptExecutable*>(this)->hashFor(kind);
610 }
611
612 CodeBlockHash NativeExecutable::hashFor(CodeSpecializationKind kind) const
613 {
614     if (kind == CodeForCall)
615         return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_function)));
616     
617     RELEASE_ASSERT(kind == CodeForConstruct);
618     return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_constructor)));
619 }
620
621 CodeBlockHash ScriptExecutable::hashFor(CodeSpecializationKind kind) const
622 {
623     return CodeBlockHash(source(), kind);
624 }
625
626 }