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