Foo::s_info should be Foo::info(), so that you can change how the s_info is actually...
[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         throwError(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 int ProgramExecutable::addGlobalVar(JSGlobalObject* globalObject, const Identifier& ident, ConstantMode constantMode, FunctionMode functionMode)
375 {
376     // Try to share the symbolTable if possible
377     SharedSymbolTable* symbolTable = globalObject->symbolTable();
378     UNUSED_PARAM(functionMode);
379     ConcurrentJITLocker locker(symbolTable->m_lock);
380     int index = symbolTable->size(locker);
381     SymbolTableEntry newEntry(index, (constantMode == IsConstant) ? ReadOnly : 0);
382     if (functionMode == IsFunctionToSpecialize)
383         newEntry.attemptToWatch();
384     SymbolTable::Map::AddResult result = symbolTable->add(locker, ident.impl(), newEntry);
385     if (!result.isNewEntry) {
386         result.iterator->value.notifyWrite();
387         index = result.iterator->value.getIndex();
388     }
389     return index;
390 }
391
392 JSObject* ProgramExecutable::initializeGlobalProperties(VM& vm, CallFrame* callFrame, JSScope* scope)
393 {
394     RELEASE_ASSERT(scope);
395     JSGlobalObject* globalObject = scope->globalObject();
396     RELEASE_ASSERT(globalObject);
397     ASSERT(&globalObject->vm() == &vm);
398
399     JSObject* exception = 0;
400     UnlinkedProgramCodeBlock* unlinkedCode = globalObject->createProgramCodeBlock(callFrame, this, &exception);
401     if (exception)
402         return exception;
403
404     m_unlinkedProgramCodeBlock.set(vm, this, unlinkedCode);
405
406     BatchedTransitionOptimizer optimizer(vm, globalObject);
407
408     const UnlinkedProgramCodeBlock::VariableDeclations& variableDeclarations = unlinkedCode->variableDeclarations();
409     const UnlinkedProgramCodeBlock::FunctionDeclations& functionDeclarations = unlinkedCode->functionDeclarations();
410
411     size_t newGlobals = variableDeclarations.size() + functionDeclarations.size();
412     if (!newGlobals)
413         return 0;
414     globalObject->addRegisters(newGlobals);
415     CallFrame* globalExec = globalObject->globalExec();
416
417     for (size_t i = 0; i < functionDeclarations.size(); ++i) {
418         bool propertyDidExist = globalObject->removeDirect(vm, functionDeclarations[i].first); // Newly declared functions overwrite existing properties.
419         UnlinkedFunctionExecutable* unlinkedFunctionExecutable = functionDeclarations[i].second.get();
420         JSValue value = JSFunction::create(globalExec, unlinkedFunctionExecutable->link(vm, m_source, lineNo(), 0), scope);
421         int index = addGlobalVar(globalObject, functionDeclarations[i].first, IsVariable,
422             !propertyDidExist ? IsFunctionToSpecialize : NotFunctionOrNotSpecializable);
423         globalObject->registerAt(index).set(vm, globalObject, value);
424     }
425
426     for (size_t i = 0; i < variableDeclarations.size(); ++i) {
427         if (globalObject->hasProperty(globalExec, variableDeclarations[i].first))
428             continue;
429         addGlobalVar(globalObject, variableDeclarations[i].first,
430             (variableDeclarations[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable,
431             NotFunctionOrNotSpecializable);
432     }
433     return 0;
434 }
435
436 void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
437 {
438     ProgramExecutable* thisObject = jsCast<ProgramExecutable*>(cell);
439     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
440     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
441     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
442     ScriptExecutable::visitChildren(thisObject, visitor);
443     visitor.append(&thisObject->m_unlinkedProgramCodeBlock);
444     if (thisObject->m_programCodeBlock)
445         thisObject->m_programCodeBlock->visitAggregate(visitor);
446 }
447
448 void ProgramExecutable::clearCode()
449 {
450     m_programCodeBlock.clear();
451     m_unlinkedProgramCodeBlock.clear();
452     Base::clearCode();
453 }
454
455 FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
456 {
457     FunctionCodeBlock* result;
458     if (kind == CodeForCall)
459         result = m_codeBlockForCall.get();
460     else {
461         RELEASE_ASSERT(kind == CodeForConstruct);
462         result = m_codeBlockForConstruct.get();
463     }
464     if (!result)
465         return 0;
466     while (result->alternative())
467         result = static_cast<FunctionCodeBlock*>(result->alternative());
468     RELEASE_ASSERT(result);
469     ASSERT(JITCode::isBaselineCode(result->jitType()));
470     return result;
471 }
472
473 #if ENABLE(DFG_JIT)
474 JSObject* FunctionExecutable::compileOptimizedForCall(ExecState* exec, JSScope* scope, CompilationResult& result, unsigned bytecodeIndex)
475 {
476     RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
477     ASSERT(!!m_codeBlockForCall);
478     JSObject* error = 0;
479     if (!JITCode::isOptimizingJIT(m_codeBlockForCall->jitType()))
480         error = compileForCallInternal(exec, scope, JITCode::nextTierJIT(m_codeBlockForCall->jitType()), &result, bytecodeIndex);
481     else
482         result = CompilationNotNeeded;
483     ASSERT(!!m_codeBlockForCall);
484     return error;
485 }
486
487 JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, JSScope* scope, CompilationResult& result, unsigned bytecodeIndex)
488 {
489     RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
490     ASSERT(!!m_codeBlockForConstruct);
491     JSObject* error = 0;
492     if (!JITCode::isOptimizingJIT(m_codeBlockForConstruct->jitType()))
493         error = compileForConstructInternal(exec, scope, JITCode::nextTierJIT(m_codeBlockForConstruct->jitType()), &result, bytecodeIndex);
494     else
495         result = CompilationNotNeeded;
496     ASSERT(!!m_codeBlockForConstruct);
497     return error;
498 }
499 #endif // ENABLE(DFG_JIT)
500
501 #if ENABLE(JIT)
502 CompilationResult FunctionExecutable::jitCompileForCall(ExecState* exec)
503 {
504     return jitCompileFunctionIfAppropriate(exec, m_codeBlockForCall.get(), m_jitCodeForCall, m_jitCodeForCallWithArityCheck, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
505 }
506
507 CompilationResult FunctionExecutable::jitCompileForConstruct(ExecState* exec)
508 {
509     return jitCompileFunctionIfAppropriate(exec, m_codeBlockForConstruct.get(), m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
510 }
511 #endif
512
513 PassRefPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(JSScope* scope, CodeSpecializationKind specializationKind, JSObject*& exception)
514 {
515     RefPtr<FunctionCodeBlock> alternative = codeBlockFor(specializationKind);
516     
517     if (!!alternative) {
518         RefPtr<FunctionCodeBlock> result = adoptRef(new FunctionCodeBlock(CodeBlock::CopyParsedBlock, *codeBlockFor(specializationKind)));
519         result->setAlternative(alternative);
520         return result.release();
521     }
522
523     VM* vm = scope->vm();
524     JSGlobalObject* globalObject = scope->globalObject();
525     ParserError error;
526     DebuggerMode debuggerMode = globalObject->hasDebugger() ? DebuggerOn : DebuggerOff;
527     ProfilerMode profilerMode = globalObject->hasProfiler() ? ProfilerOn : ProfilerOff;
528     UnlinkedFunctionCodeBlock* unlinkedCodeBlock = m_unlinkedExecutable->codeBlockFor(*vm, m_source, specializationKind, debuggerMode, profilerMode, error);
529     recordParse(m_unlinkedExecutable->features(), m_unlinkedExecutable->hasCapturedVariables(), lineNo(), lastLine(), startColumn());
530
531     if (!unlinkedCodeBlock) {
532         exception = error.toErrorObject(globalObject, m_source);
533         return 0;
534     }
535
536     SourceProvider* provider = source().provider();
537     unsigned sourceOffset = source().startOffset();
538     unsigned startColumn = source().startColumn();
539
540     return adoptRef(new FunctionCodeBlock(this, unlinkedCodeBlock, scope, provider, sourceOffset, startColumn));
541 }
542
543
544 JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, JSScope* scope, JITCode::JITType jitType, CompilationResult* result, unsigned bytecodeIndex)
545 {
546     SamplingRegion samplingRegion(samplingDescription(jitType));
547     
548     if (result)
549         *result = CompilationFailed;
550     
551     ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForCall);
552     JSObject* exception = 0;
553     
554     RefPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scope, CodeForCall, exception);
555     if (!newCodeBlock)
556         return exception;
557     
558     CompilationResult theResult = prepareFunctionForExecution(
559         exec, m_codeBlockForCall, newCodeBlock.get(), m_jitCodeForCall,
560         m_jitCodeForCallWithArityCheck, m_numParametersForCall, jitType,
561         bytecodeIndex, CodeForCall);
562     if (result)
563         *result = theResult;
564     return 0;
565 }
566
567 #if ENABLE(DFG_JIT)
568 CompilationResult FunctionExecutable::replaceWithDeferredOptimizedCodeForCall(PassRefPtr<DFG::Plan> plan)
569 {
570     return JSC::replaceWithDeferredOptimizedCode(
571         plan, m_codeBlockForCall, m_jitCodeForCall, &m_jitCodeForCallWithArityCheck,
572         &m_numParametersForCall);
573 }
574 #endif // ENABLE(DFG_JIT)
575
576 JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, JSScope* scope, JITCode::JITType jitType, CompilationResult* result, unsigned bytecodeIndex)
577 {
578     SamplingRegion samplingRegion(samplingDescription(jitType));
579     
580     if (result)
581         *result = CompilationFailed;
582     
583     ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForConstruct);
584     JSObject* exception = 0;
585     RefPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scope, CodeForConstruct, exception);
586     if (!newCodeBlock)
587         return exception;
588
589     CompilationResult theResult = prepareFunctionForExecution(
590         exec, m_codeBlockForConstruct, newCodeBlock.get(), m_jitCodeForConstruct,
591         m_jitCodeForConstructWithArityCheck, m_numParametersForConstruct, jitType,
592         bytecodeIndex, CodeForConstruct);
593     if (result)
594         *result = theResult;
595
596     return 0;
597 }
598
599 #if ENABLE(DFG_JIT)
600 CompilationResult FunctionExecutable::replaceWithDeferredOptimizedCodeForConstruct(PassRefPtr<DFG::Plan> plan)
601 {
602     return JSC::replaceWithDeferredOptimizedCode(
603         plan, m_codeBlockForConstruct, m_jitCodeForConstruct,
604         &m_jitCodeForConstructWithArityCheck, &m_numParametersForConstruct);
605 }
606 #endif // ENABLE(DFG_JIT)
607
608 #if ENABLE(JIT)
609 void FunctionExecutable::jettisonOptimizedCodeForCall(VM& vm)
610 {
611     jettisonCodeBlock(vm, m_codeBlockForCall);
612     m_jitCodeForCall = m_codeBlockForCall->jitCode();
613     m_jitCodeForCallWithArityCheck = m_codeBlockForCall->jitCodeWithArityCheck();
614 }
615
616 void FunctionExecutable::jettisonOptimizedCodeForConstruct(VM& vm)
617 {
618     jettisonCodeBlock(vm, m_codeBlockForConstruct);
619     m_jitCodeForConstruct = m_codeBlockForConstruct->jitCode();
620     m_jitCodeForConstructWithArityCheck = m_codeBlockForConstruct->jitCodeWithArityCheck();
621 }
622 #endif
623
624 void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
625 {
626     FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell);
627     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
628     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
629     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
630     ScriptExecutable::visitChildren(thisObject, visitor);
631     if (thisObject->m_codeBlockForCall)
632         thisObject->m_codeBlockForCall->visitAggregate(visitor);
633     if (thisObject->m_codeBlockForConstruct)
634         thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
635     visitor.append(&thisObject->m_unlinkedExecutable);
636 }
637
638 void FunctionExecutable::clearCodeIfNotCompiling()
639 {
640     if (isCompiling())
641         return;
642     clearCode();
643 }
644
645 void FunctionExecutable::clearUnlinkedCodeForRecompilationIfNotCompiling()
646 {
647     if (isCompiling())
648         return;
649     m_unlinkedExecutable->clearCodeForRecompilation();
650 }
651
652 void FunctionExecutable::clearCode()
653 {
654     m_codeBlockForCall.clear();
655     m_codeBlockForConstruct.clear();
656     Base::clearCode();
657 }
658
659 void FunctionExecutable::unlinkCalls()
660 {
661 #if ENABLE(JIT)
662     if (!!m_jitCodeForCall) {
663         RELEASE_ASSERT(m_codeBlockForCall);
664         m_codeBlockForCall->unlinkCalls();
665     }
666     if (!!m_jitCodeForConstruct) {
667         RELEASE_ASSERT(m_codeBlockForConstruct);
668         m_codeBlockForConstruct->unlinkCalls();
669     }
670 #endif
671 }
672
673 FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
674 {
675     UnlinkedFunctionExecutable* unlinkedFunction = UnlinkedFunctionExecutable::fromGlobalCode(name, exec, debugger, source, exception);
676     if (!unlinkedFunction)
677         return 0;
678     unsigned firstLine = source.firstLine() + unlinkedFunction->firstLineOffset();
679     unsigned startOffset = source.startOffset() + unlinkedFunction->startOffset();
680     unsigned startColumn = source.startColumn();
681     unsigned sourceLength = unlinkedFunction->sourceLength();
682     SourceCode functionSource(source.provider(), startOffset, startOffset + sourceLength, firstLine, startColumn);
683     return FunctionExecutable::create(exec->vm(), functionSource, unlinkedFunction, firstLine, unlinkedFunction->lineCount(), startColumn);
684 }
685
686 String FunctionExecutable::paramString() const
687 {
688     return m_unlinkedExecutable->paramString();
689 }
690
691 CodeBlockHash ExecutableBase::hashFor(CodeSpecializationKind kind) const
692 {
693     if (this->classInfo() == NativeExecutable::info())
694         return jsCast<const NativeExecutable*>(this)->hashFor(kind);
695     
696     return jsCast<const ScriptExecutable*>(this)->hashFor(kind);
697 }
698
699 CodeBlockHash NativeExecutable::hashFor(CodeSpecializationKind kind) const
700 {
701     if (kind == CodeForCall)
702         return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_function)));
703     
704     RELEASE_ASSERT(kind == CodeForConstruct);
705     return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_constructor)));
706 }
707
708 CodeBlockHash ScriptExecutable::hashFor(CodeSpecializationKind kind) const
709 {
710     return CodeBlockHash(source(), kind);
711 }
712
713 }