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