fourthTier: JITCode should abstract exactly how the JIT code is structured and where...
[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, OwnPtr<T>& codeBlock)
98 {
99     ASSERT(JITCode::isOptimizingJIT(codeBlock->getJITType()));
100     ASSERT(codeBlock->alternative());
101     OwnPtr<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(ExecState* exec, PassRefPtr<CodeCache> codeCache, const SourceCode& source, bool inStrictContext)
120     : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec, source, inStrictContext)
121     , m_codeCache(codeCache)
122 {
123 }
124
125 void EvalExecutable::destroy(JSCell* cell)
126 {
127     static_cast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable();
128 }
129
130 const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(ProgramExecutable) };
131
132 ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
133     : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec, source, false)
134 {
135 }
136
137 void ProgramExecutable::destroy(JSCell* cell)
138 {
139     static_cast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable();
140 }
141
142 const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
143
144 FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn)
145     : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->isInStrictContext())
146     , m_unlinkedExecutable(vm, this, unlinkedExecutable)
147 {
148     RELEASE_ASSERT(!source.isNull());
149     ASSERT(source.length());
150     m_firstLine = firstLine;
151     m_lastLine = lastLine;
152     m_startColumn = startColumn;
153 }
154
155 void FunctionExecutable::destroy(JSCell* cell)
156 {
157     static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
158 }
159
160 JSObject* EvalExecutable::compileOptimized(ExecState* exec, JSScope* scope, unsigned bytecodeIndex)
161 {
162     ASSERT(exec->vm().dynamicGlobalObject);
163     ASSERT(!!m_evalCodeBlock);
164     JSObject* error = 0;
165     if (m_evalCodeBlock->getJITType() != JITCode::topTierJIT())
166         error = compileInternal(exec, scope, JITCode::nextTierJIT(m_evalCodeBlock->getJITType()), bytecodeIndex);
167     ASSERT(!!m_evalCodeBlock);
168     return error;
169 }
170
171 #if ENABLE(JIT)
172 bool EvalExecutable::jitCompile(ExecState* exec)
173 {
174     return jitCompileIfAppropriate(exec, m_evalCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
175 }
176 #endif
177
178 inline const char* samplingDescription(JITCode::JITType jitType)
179 {
180     switch (jitType) {
181     case JITCode::InterpreterThunk:
182         return "Interpreter Compilation (TOTAL)";
183     case JITCode::BaselineJIT:
184         return "Baseline Compilation (TOTAL)";
185     case JITCode::DFGJIT:
186         return "DFG Compilation (TOTAL)";
187     default:
188         RELEASE_ASSERT_NOT_REACHED();
189         return 0;
190     }
191 }
192
193 JSObject* EvalExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCode::JITType jitType, unsigned bytecodeIndex)
194 {
195     SamplingRegion samplingRegion(samplingDescription(jitType));
196     
197 #if !ENABLE(JIT)
198     UNUSED_PARAM(jitType);
199     UNUSED_PARAM(bytecodeIndex);
200 #endif
201     VM* vm = &exec->vm();
202     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
203     
204     if (!!m_evalCodeBlock) {
205         PassOwnPtr<EvalCodeBlock> newCodeBlock = adoptPtr(new EvalCodeBlock(CodeBlock::CopyParsedBlock, *m_evalCodeBlock));
206         newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_evalCodeBlock.release()));
207         m_evalCodeBlock = newCodeBlock;
208     } else {
209         UNUSED_PARAM(scope);
210         UNUSED_PARAM(vm);
211         UNUSED_PARAM(lexicalGlobalObject);
212         if (!lexicalGlobalObject->evalEnabled())
213             return throwError(exec, createEvalError(exec, lexicalGlobalObject->evalDisabledErrorMessage()));
214
215         JSObject* exception = 0;
216         UnlinkedEvalCodeBlock* unlinkedEvalCode = lexicalGlobalObject->createEvalCodeBlock(m_codeCache.get(), exec, scope, this, &exception);
217         if (!unlinkedEvalCode)
218             return exception;
219
220         OwnPtr<CodeBlock> previousCodeBlock = m_evalCodeBlock.release();
221         ASSERT((jitType == JITCode::bottomTierJIT()) == !previousCodeBlock);
222         m_unlinkedEvalCodeBlock.set(*vm, this, unlinkedEvalCode);
223         m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, unlinkedEvalCode, lexicalGlobalObject, source().provider(), scope->localDepth(), previousCodeBlock.release()));
224         m_evalCodeBlock->copyPostParseDataFromAlternative();
225     }
226
227 #if ENABLE(JIT)
228     if (!prepareForExecution(exec, m_evalCodeBlock, m_jitCodeForCall, jitType, bytecodeIndex))
229         return 0;
230 #endif
231
232 #if ENABLE(JIT)
233     Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock) + m_jitCodeForCall->size());
234 #else
235     Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock));
236 #endif
237
238     return 0;
239 }
240
241 #if ENABLE(JIT)
242 void EvalExecutable::jettisonOptimizedCode(VM& vm)
243 {
244     jettisonCodeBlock(vm, m_evalCodeBlock);
245     m_jitCodeForCall = m_evalCodeBlock->getJITCode();
246     ASSERT(!m_jitCodeForCallWithArityCheck);
247 }
248 #endif
249
250 void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
251 {
252     EvalExecutable* thisObject = jsCast<EvalExecutable*>(cell);
253     ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
254     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
255     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
256     ScriptExecutable::visitChildren(thisObject, visitor);
257     if (thisObject->m_evalCodeBlock)
258         thisObject->m_evalCodeBlock->visitAggregate(visitor);
259     visitor.append(&thisObject->m_unlinkedEvalCodeBlock);
260 }
261
262 void EvalExecutable::unlinkCalls()
263 {
264 #if ENABLE(JIT)
265     if (!m_jitCodeForCall)
266         return;
267     RELEASE_ASSERT(m_evalCodeBlock);
268     m_evalCodeBlock->unlinkCalls();
269 #endif
270 }
271
272 void EvalExecutable::clearCode()
273 {
274     m_evalCodeBlock.clear();
275     m_unlinkedEvalCodeBlock.clear();
276     Base::clearCode();
277 }
278
279 JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
280 {
281     ParserError error;
282     VM* vm = &exec->vm();
283     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
284     RefPtr<ProgramNode> programNode = parse<ProgramNode>(vm, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, error);
285     if (programNode)
286         return 0;
287     ASSERT(error.m_type != ParserError::ErrorNone);
288     return error.toErrorObject(lexicalGlobalObject, m_source);
289 }
290
291 JSObject* ProgramExecutable::compileOptimized(ExecState* exec, JSScope* scope, unsigned bytecodeIndex)
292 {
293     RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
294     ASSERT(!!m_programCodeBlock);
295     JSObject* error = 0;
296     if (m_programCodeBlock->getJITType() != JITCode::topTierJIT())
297         error = compileInternal(exec, scope, JITCode::nextTierJIT(m_programCodeBlock->getJITType()), bytecodeIndex);
298     ASSERT(!!m_programCodeBlock);
299     return error;
300 }
301
302 #if ENABLE(JIT)
303 bool ProgramExecutable::jitCompile(ExecState* exec)
304 {
305     return jitCompileIfAppropriate(exec, m_programCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
306 }
307 #endif
308
309 JSObject* ProgramExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCode::JITType jitType, unsigned bytecodeIndex)
310 {
311     SamplingRegion samplingRegion(samplingDescription(jitType));
312     
313 #if !ENABLE(JIT)
314     UNUSED_PARAM(exec);
315     UNUSED_PARAM(jitType);
316     UNUSED_PARAM(bytecodeIndex);
317 #endif
318     if (!!m_programCodeBlock) {
319         OwnPtr<ProgramCodeBlock> newCodeBlock = adoptPtr(new ProgramCodeBlock(CodeBlock::CopyParsedBlock, *m_programCodeBlock));
320         newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_programCodeBlock.release()));
321         m_programCodeBlock = newCodeBlock.release();
322     } else {
323         JSGlobalObject* globalObject = scope->globalObject();
324         m_programCodeBlock = adoptPtr(new ProgramCodeBlock(this, m_unlinkedProgramCodeBlock.get(), globalObject, source().provider(), source().startColumn(), m_programCodeBlock.release()));
325         m_programCodeBlock->copyPostParseDataFromAlternative();
326     }
327
328 #if ENABLE(JIT)
329     if (!prepareForExecution(exec, m_programCodeBlock, m_jitCodeForCall, jitType, bytecodeIndex))
330         return 0;
331 #endif
332
333 #if ENABLE(JIT)
334     Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock) + m_jitCodeForCall->size());
335 #else
336     Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock));
337 #endif
338
339     return 0;
340 }
341
342 #if ENABLE(JIT)
343 void ProgramExecutable::jettisonOptimizedCode(VM& vm)
344 {
345     jettisonCodeBlock(vm, m_programCodeBlock);
346     m_jitCodeForCall = m_programCodeBlock->getJITCode();
347     ASSERT(!m_jitCodeForCallWithArityCheck);
348 }
349 #endif
350
351 void ProgramExecutable::unlinkCalls()
352 {
353 #if ENABLE(JIT)
354     if (!m_jitCodeForCall)
355         return;
356     RELEASE_ASSERT(m_programCodeBlock);
357     m_programCodeBlock->unlinkCalls();
358 #endif
359 }
360
361 int ProgramExecutable::addGlobalVar(JSGlobalObject* globalObject, const Identifier& ident, ConstantMode constantMode, FunctionMode functionMode)
362 {
363     // Try to share the symbolTable if possible
364     SharedSymbolTable* symbolTable = globalObject->symbolTable();
365     UNUSED_PARAM(functionMode);
366     int index = symbolTable->size();
367     SymbolTableEntry newEntry(index, (constantMode == IsConstant) ? ReadOnly : 0);
368     if (functionMode == IsFunctionToSpecialize)
369         newEntry.attemptToWatch();
370     SymbolTable::AddResult result = symbolTable->add(ident.impl(), newEntry);
371     if (!result.isNewEntry) {
372         result.iterator->value.notifyWrite();
373         index = result.iterator->value.getIndex();
374     }
375     return index;
376 }
377
378 JSObject* ProgramExecutable::initializeGlobalProperties(VM& vm, CallFrame* callFrame, JSScope* scope)
379 {
380     RELEASE_ASSERT(scope);
381     JSGlobalObject* globalObject = scope->globalObject();
382     RELEASE_ASSERT(globalObject);
383     ASSERT(&globalObject->vm() == &vm);
384
385     JSObject* exception = 0;
386     UnlinkedProgramCodeBlock* unlinkedCode = globalObject->createProgramCodeBlock(callFrame, this, &exception);
387     if (exception)
388         return exception;
389
390     m_unlinkedProgramCodeBlock.set(vm, this, unlinkedCode);
391
392     BatchedTransitionOptimizer optimizer(vm, globalObject);
393
394     const UnlinkedProgramCodeBlock::VariableDeclations& variableDeclarations = unlinkedCode->variableDeclarations();
395     const UnlinkedProgramCodeBlock::FunctionDeclations& functionDeclarations = unlinkedCode->functionDeclarations();
396
397     size_t newGlobals = variableDeclarations.size() + functionDeclarations.size();
398     if (!newGlobals)
399         return 0;
400     globalObject->addRegisters(newGlobals);
401     CallFrame* globalExec = globalObject->globalExec();
402
403     for (size_t i = 0; i < functionDeclarations.size(); ++i) {
404         bool propertyDidExist = globalObject->removeDirect(vm, functionDeclarations[i].first); // Newly declared functions overwrite existing properties.
405         UnlinkedFunctionExecutable* unlinkedFunctionExecutable = functionDeclarations[i].second.get();
406         JSValue value = JSFunction::create(globalExec, unlinkedFunctionExecutable->link(vm, m_source, lineNo(), 0), scope);
407         int index = addGlobalVar(globalObject, functionDeclarations[i].first, IsVariable,
408             !propertyDidExist ? IsFunctionToSpecialize : NotFunctionOrNotSpecializable);
409         globalObject->registerAt(index).set(vm, globalObject, value);
410     }
411
412     for (size_t i = 0; i < variableDeclarations.size(); ++i) {
413         if (globalObject->hasProperty(globalExec, variableDeclarations[i].first))
414             continue;
415         addGlobalVar(globalObject, variableDeclarations[i].first,
416             (variableDeclarations[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable,
417             NotFunctionOrNotSpecializable);
418     }
419     return 0;
420 }
421
422 void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
423 {
424     ProgramExecutable* thisObject = jsCast<ProgramExecutable*>(cell);
425     ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
426     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
427     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
428     ScriptExecutable::visitChildren(thisObject, visitor);
429     visitor.append(&thisObject->m_unlinkedProgramCodeBlock);
430     if (thisObject->m_programCodeBlock)
431         thisObject->m_programCodeBlock->visitAggregate(visitor);
432 }
433
434 void ProgramExecutable::clearCode()
435 {
436     m_programCodeBlock.clear();
437     m_unlinkedProgramCodeBlock.clear();
438     Base::clearCode();
439 }
440
441 FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
442 {
443     FunctionCodeBlock* result;
444     if (kind == CodeForCall)
445         result = m_codeBlockForCall.get();
446     else {
447         RELEASE_ASSERT(kind == CodeForConstruct);
448         result = m_codeBlockForConstruct.get();
449     }
450     if (!result)
451         return 0;
452     while (result->alternative())
453         result = static_cast<FunctionCodeBlock*>(result->alternative());
454     RELEASE_ASSERT(result);
455     ASSERT(JITCode::isBaselineCode(result->getJITType()));
456     return result;
457 }
458
459 JSObject* FunctionExecutable::compileOptimizedForCall(ExecState* exec, JSScope* scope, unsigned bytecodeIndex)
460 {
461     RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
462     ASSERT(!!m_codeBlockForCall);
463     JSObject* error = 0;
464     if (m_codeBlockForCall->getJITType() != JITCode::topTierJIT())
465         error = compileForCallInternal(exec, scope, JITCode::nextTierJIT(m_codeBlockForCall->getJITType()), bytecodeIndex);
466     ASSERT(!!m_codeBlockForCall);
467     return error;
468 }
469
470 JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, JSScope* scope, unsigned bytecodeIndex)
471 {
472     RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
473     ASSERT(!!m_codeBlockForConstruct);
474     JSObject* error = 0;
475     if (m_codeBlockForConstruct->getJITType() != JITCode::topTierJIT())
476         error = compileForConstructInternal(exec, scope, JITCode::nextTierJIT(m_codeBlockForConstruct->getJITType()), bytecodeIndex);
477     ASSERT(!!m_codeBlockForConstruct);
478     return error;
479 }
480
481 #if ENABLE(JIT)
482 bool FunctionExecutable::jitCompileForCall(ExecState* exec)
483 {
484     return jitCompileFunctionIfAppropriate(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
485 }
486
487 bool FunctionExecutable::jitCompileForConstruct(ExecState* exec)
488 {
489     return jitCompileFunctionIfAppropriate(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
490 }
491 #endif
492
493 PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(JSScope* scope, CodeSpecializationKind specializationKind, JSObject*& exception)
494 {
495     if (!!codeBlockFor(specializationKind))
496         return adoptPtr(new FunctionCodeBlock(CodeBlock::CopyParsedBlock, *codeBlockFor(specializationKind)));
497
498     VM* vm = scope->vm();
499     JSGlobalObject* globalObject = scope->globalObject();
500     ParserError error;
501     DebuggerMode debuggerMode = globalObject->hasDebugger() ? DebuggerOn : DebuggerOff;
502     ProfilerMode profilerMode = globalObject->hasProfiler() ? ProfilerOn : ProfilerOff;
503     UnlinkedFunctionCodeBlock* unlinkedCodeBlock = m_unlinkedExecutable->codeBlockFor(*vm, scope, m_source, specializationKind, debuggerMode, profilerMode, error);
504     recordParse(m_unlinkedExecutable->features(), m_unlinkedExecutable->hasCapturedVariables(), lineNo(), lastLine(), startColumn());
505
506     if (!unlinkedCodeBlock) {
507         exception = error.toErrorObject(globalObject, m_source);
508         return nullptr;
509     }
510
511     SourceProvider* provider = source().provider();
512     unsigned sourceOffset = source().startOffset();
513     unsigned startColumn = source().startColumn();
514
515     OwnPtr<FunctionCodeBlock> result = adoptPtr(new FunctionCodeBlock(this, unlinkedCodeBlock, globalObject, provider, sourceOffset, startColumn));
516     result->copyPostParseDataFrom(codeBlockFor(specializationKind).get());
517     return result.release();
518 }
519
520
521 JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, JSScope* scope, JITCode::JITType jitType, unsigned bytecodeIndex)
522 {
523     SamplingRegion samplingRegion(samplingDescription(jitType));
524     
525 #if !ENABLE(JIT)
526     UNUSED_PARAM(exec);
527     UNUSED_PARAM(jitType);
528     UNUSED_PARAM(exec);
529     UNUSED_PARAM(bytecodeIndex);
530 #endif
531     ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForCall);
532     JSObject* exception = 0;
533     OwnPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scope, CodeForCall, exception);
534     if (!newCodeBlock)
535         return exception;
536
537     newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_codeBlockForCall.release()));
538     m_codeBlockForCall = newCodeBlock.release();
539     
540     m_numParametersForCall = m_codeBlockForCall->numParameters();
541     RELEASE_ASSERT(m_numParametersForCall);
542
543 #if ENABLE(JIT)
544     if (!prepareFunctionForExecution(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, jitType, bytecodeIndex, CodeForCall))
545         return 0;
546 #endif
547
548 #if ENABLE(JIT)
549     Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall) + m_jitCodeForCall->size());
550 #else
551     Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall));
552 #endif
553
554     return 0;
555 }
556
557 JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, JSScope* scope, JITCode::JITType jitType, unsigned bytecodeIndex)
558 {
559     SamplingRegion samplingRegion(samplingDescription(jitType));
560     
561 #if !ENABLE(JIT)
562     UNUSED_PARAM(jitType);
563     UNUSED_PARAM(exec);
564     UNUSED_PARAM(bytecodeIndex);
565 #endif
566     
567     ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForConstruct);
568     JSObject* exception = 0;
569     OwnPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scope, CodeForConstruct, exception);
570     if (!newCodeBlock)
571         return exception;
572
573     newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_codeBlockForConstruct.release()));
574     m_codeBlockForConstruct = newCodeBlock.release();
575     
576     m_numParametersForConstruct = m_codeBlockForConstruct->numParameters();
577     RELEASE_ASSERT(m_numParametersForConstruct);
578
579 #if ENABLE(JIT)
580     if (!prepareFunctionForExecution(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, jitType, bytecodeIndex, CodeForConstruct))
581         return 0;
582 #endif
583
584 #if ENABLE(JIT)
585     Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct) + m_jitCodeForConstruct->size());
586 #else
587     Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct));
588 #endif
589
590     return 0;
591 }
592
593 #if ENABLE(JIT)
594 void FunctionExecutable::jettisonOptimizedCodeForCall(VM& vm)
595 {
596     jettisonCodeBlock(vm, m_codeBlockForCall);
597     m_jitCodeForCall = m_codeBlockForCall->getJITCode();
598     m_jitCodeForCallWithArityCheck = m_codeBlockForCall->getJITCodeWithArityCheck();
599 }
600
601 void FunctionExecutable::jettisonOptimizedCodeForConstruct(VM& vm)
602 {
603     jettisonCodeBlock(vm, m_codeBlockForConstruct);
604     m_jitCodeForConstruct = m_codeBlockForConstruct->getJITCode();
605     m_jitCodeForConstructWithArityCheck = m_codeBlockForConstruct->getJITCodeWithArityCheck();
606 }
607 #endif
608
609 void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
610 {
611     FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell);
612     ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
613     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
614     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
615     ScriptExecutable::visitChildren(thisObject, visitor);
616     if (thisObject->m_codeBlockForCall)
617         thisObject->m_codeBlockForCall->visitAggregate(visitor);
618     if (thisObject->m_codeBlockForConstruct)
619         thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
620     visitor.append(&thisObject->m_unlinkedExecutable);
621 }
622
623 void FunctionExecutable::clearCodeIfNotCompiling()
624 {
625     if (isCompiling())
626         return;
627     clearCode();
628 }
629
630 void FunctionExecutable::clearUnlinkedCodeForRecompilationIfNotCompiling()
631 {
632     if (isCompiling())
633         return;
634     m_unlinkedExecutable->clearCodeForRecompilation();
635 }
636
637 void FunctionExecutable::clearCode()
638 {
639     m_codeBlockForCall.clear();
640     m_codeBlockForConstruct.clear();
641     Base::clearCode();
642 }
643
644 void FunctionExecutable::unlinkCalls()
645 {
646 #if ENABLE(JIT)
647     if (!!m_jitCodeForCall) {
648         RELEASE_ASSERT(m_codeBlockForCall);
649         m_codeBlockForCall->unlinkCalls();
650     }
651     if (!!m_jitCodeForConstruct) {
652         RELEASE_ASSERT(m_codeBlockForConstruct);
653         m_codeBlockForConstruct->unlinkCalls();
654     }
655 #endif
656 }
657
658 FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
659 {
660     UnlinkedFunctionExecutable* unlinkedFunction = UnlinkedFunctionExecutable::fromGlobalCode(name, exec, debugger, source, exception);
661     if (!unlinkedFunction)
662         return 0;
663     unsigned firstLine = source.firstLine() + unlinkedFunction->firstLineOffset();
664     unsigned startOffset = source.startOffset() + unlinkedFunction->startOffset();
665     unsigned startColumn = source.startColumn();
666     unsigned sourceLength = unlinkedFunction->sourceLength();
667     SourceCode functionSource(source.provider(), startOffset, startOffset + sourceLength, firstLine, startColumn);
668     return FunctionExecutable::create(exec->vm(), functionSource, unlinkedFunction, firstLine, unlinkedFunction->lineCount(), startColumn);
669 }
670
671 String FunctionExecutable::paramString() const
672 {
673     return m_unlinkedExecutable->paramString();
674 }
675
676 CodeBlockHash ExecutableBase::hashFor(CodeSpecializationKind kind) const
677 {
678     if (this->classInfo() == &NativeExecutable::s_info)
679         return jsCast<const NativeExecutable*>(this)->hashFor(kind);
680     
681     return jsCast<const ScriptExecutable*>(this)->hashFor(kind);
682 }
683
684 CodeBlockHash NativeExecutable::hashFor(CodeSpecializationKind kind) const
685 {
686     if (kind == CodeForCall)
687         return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_function)));
688     
689     RELEASE_ASSERT(kind == CodeForConstruct);
690     return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_constructor)));
691 }
692
693 CodeBlockHash ScriptExecutable::hashFor(CodeSpecializationKind kind) const
694 {
695     return CodeBlockHash(source(), kind);
696 }
697
698 }