]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/Executable.cpp
JavaScriptCore-1218.34.tar.gz
[apple/javascriptcore.git] / 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 OwnPtr<EvalCodeBlock> newCodeBlock = adoptPtr(new EvalCodeBlock(CodeBlock::CopyParsedBlock, *m_evalCodeBlock));
206 newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_evalCodeBlock.release()));
207 m_evalCodeBlock = newCodeBlock.release();
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 }