]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/Executable.cpp
JavaScriptCore-1097.3.3.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 "BytecodeGenerator.h"
30 #include "CodeBlock.h"
31 #include "DFGDriver.h"
32 #include "ExecutionHarness.h"
33 #include "JIT.h"
34 #include "JITDriver.h"
35 #include "Parser.h"
36 #include "UStringBuilder.h"
37 #include <wtf/Vector.h>
38
39 namespace JSC {
40
41 const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0, CREATE_METHOD_TABLE(ExecutableBase) };
42
43 #if ENABLE(JIT)
44 void ExecutableBase::destroy(JSCell* cell)
45 {
46 jsCast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();
47 }
48 #endif
49
50 inline void ExecutableBase::clearCode()
51 {
52 #if ENABLE(JIT)
53 m_jitCodeForCall.clear();
54 m_jitCodeForConstruct.clear();
55 m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
56 m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
57 #endif
58 m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
59 m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
60 }
61
62 #if ENABLE(DFG_JIT)
63 Intrinsic ExecutableBase::intrinsic() const
64 {
65 if (const NativeExecutable* nativeExecutable = jsDynamicCast<const NativeExecutable*>(this))
66 return nativeExecutable->intrinsic();
67 return NoIntrinsic;
68 }
69 #endif
70
71 const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(NativeExecutable) };
72
73 #if ENABLE(JIT)
74 void NativeExecutable::destroy(JSCell* cell)
75 {
76 jsCast<NativeExecutable*>(cell)->NativeExecutable::~NativeExecutable();
77 }
78 #endif
79
80 #if ENABLE(DFG_JIT)
81 Intrinsic NativeExecutable::intrinsic() const
82 {
83 return m_intrinsic;
84 }
85 #endif
86
87 #if ENABLE(JIT)
88 // Utility method used for jettisoning code blocks.
89 template<typename T>
90 static void jettisonCodeBlock(JSGlobalData& globalData, OwnPtr<T>& codeBlock)
91 {
92 ASSERT(JITCode::isOptimizingJIT(codeBlock->getJITType()));
93 ASSERT(codeBlock->alternative());
94 OwnPtr<T> codeBlockToJettison = codeBlock.release();
95 codeBlock = static_pointer_cast<T>(codeBlockToJettison->releaseAlternative());
96 codeBlockToJettison->unlinkIncomingCalls();
97 globalData.heap.jettisonDFGCodeBlock(static_pointer_cast<CodeBlock>(codeBlockToJettison.release()));
98 }
99 #endif
100
101 void NativeExecutable::finalize(JSCell* cell)
102 {
103 jsCast<NativeExecutable*>(cell)->clearCode();
104 }
105
106 const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
107
108 #if ENABLE(JIT)
109 void ScriptExecutable::destroy(JSCell* cell)
110 {
111 jsCast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
112 }
113 #endif
114
115 const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(EvalExecutable) };
116
117 EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
118 : ScriptExecutable(exec->globalData().evalExecutableStructure.get(), exec, source, inStrictContext)
119 {
120 }
121
122 void EvalExecutable::destroy(JSCell* cell)
123 {
124 jsCast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable();
125 }
126
127 const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(ProgramExecutable) };
128
129 ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
130 : ScriptExecutable(exec->globalData().programExecutableStructure.get(), exec, source, false)
131 {
132 }
133
134 void ProgramExecutable::destroy(JSCell* cell)
135 {
136 jsCast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable();
137 }
138
139 const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
140
141 FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext)
142 : ScriptExecutable(globalData.functionExecutableStructure.get(), globalData, source, inStrictContext)
143 , m_numCapturedVariables(0)
144 , m_forceUsesArguments(forceUsesArguments)
145 , m_parameters(parameters)
146 , m_name(name)
147 , m_inferredName(inferredName.isNull() ? globalData.propertyNames->emptyIdentifier : inferredName)
148 , m_symbolTable(0)
149 , m_next(0)
150 , m_prev(0)
151 {
152 }
153
154 FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext)
155 : ScriptExecutable(exec->globalData().functionExecutableStructure.get(), exec, source, inStrictContext)
156 , m_numCapturedVariables(0)
157 , m_forceUsesArguments(forceUsesArguments)
158 , m_parameters(parameters)
159 , m_name(name)
160 , m_inferredName(inferredName.isNull() ? exec->globalData().propertyNames->emptyIdentifier : inferredName)
161 , m_symbolTable(0)
162 , m_next(0)
163 , m_prev(0)
164 {
165 }
166
167 void FunctionExecutable::destroy(JSCell* cell)
168 {
169 jsCast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
170 }
171
172 JSObject* EvalExecutable::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
173 {
174 ASSERT(exec->globalData().dynamicGlobalObject);
175 ASSERT(!!m_evalCodeBlock);
176 JSObject* error = 0;
177 if (m_evalCodeBlock->getJITType() != JITCode::topTierJIT())
178 error = compileInternal(exec, scopeChainNode, JITCode::nextTierJIT(m_evalCodeBlock->getJITType()));
179 ASSERT(!!m_evalCodeBlock);
180 return error;
181 }
182
183 #if ENABLE(JIT)
184 bool EvalExecutable::jitCompile(JSGlobalData& globalData)
185 {
186 return jitCompileIfAppropriate(globalData, m_evalCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), JITCompilationCanFail);
187 }
188 #endif
189
190 inline const char* samplingDescription(JITCode::JITType jitType)
191 {
192 switch (jitType) {
193 case JITCode::InterpreterThunk:
194 return "Interpreter Compilation (TOTAL)";
195 case JITCode::BaselineJIT:
196 return "Baseline Compilation (TOTAL)";
197 case JITCode::DFGJIT:
198 return "DFG Compilation (TOTAL)";
199 default:
200 ASSERT_NOT_REACHED();
201 return 0;
202 }
203 }
204
205 JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
206 {
207 SamplingRegion samplingRegion(samplingDescription(jitType));
208
209 #if !ENABLE(JIT)
210 UNUSED_PARAM(jitType);
211 #endif
212 JSObject* exception = 0;
213 JSGlobalData* globalData = &exec->globalData();
214 JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
215
216 if (!!m_evalCodeBlock) {
217 OwnPtr<EvalCodeBlock> newCodeBlock = adoptPtr(new EvalCodeBlock(CodeBlock::CopyParsedBlock, *m_evalCodeBlock));
218 newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_evalCodeBlock.release()));
219 m_evalCodeBlock = newCodeBlock.release();
220 } else {
221 if (!lexicalGlobalObject->evalEnabled())
222 return throwError(exec, createEvalError(exec, "Eval is disabled"));
223 RefPtr<EvalNode> evalNode = parse<EvalNode>(globalData, lexicalGlobalObject, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, EvalNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
224 if (!evalNode) {
225 ASSERT(exception);
226 return exception;
227 }
228 recordParse(evalNode->features(), evalNode->hasCapturedVariables(), evalNode->lineNo(), evalNode->lastLine());
229
230 JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
231
232 OwnPtr<CodeBlock> previousCodeBlock = m_evalCodeBlock.release();
233 ASSERT((jitType == JITCode::bottomTierJIT()) == !previousCodeBlock);
234 m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, globalObject, source().provider(), scopeChainNode->localDepth(), previousCodeBlock.release()));
235 OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(evalNode.get(), scopeChainNode, m_evalCodeBlock->symbolTable(), m_evalCodeBlock.get(), !!m_evalCodeBlock->alternative() ? OptimizingCompilation : FirstCompilation)));
236 if ((exception = generator->generate())) {
237 m_evalCodeBlock = static_pointer_cast<EvalCodeBlock>(m_evalCodeBlock->releaseAlternative());
238 evalNode->destroyData();
239 return exception;
240 }
241
242 evalNode->destroyData();
243 m_evalCodeBlock->copyPostParseDataFromAlternative();
244 }
245
246 #if ENABLE(JIT)
247 if (!prepareForExecution(*globalData, m_evalCodeBlock, m_jitCodeForCall, jitType))
248 return 0;
249 #endif
250
251 #if ENABLE(JIT)
252 #if ENABLE(CLASSIC_INTERPRETER)
253 if (!m_jitCodeForCall)
254 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock));
255 else
256 #endif
257 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock) + m_jitCodeForCall.size());
258 #else
259 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock));
260 #endif
261
262 return 0;
263 }
264
265 #if ENABLE(JIT)
266 void EvalExecutable::jettisonOptimizedCode(JSGlobalData& globalData)
267 {
268 jettisonCodeBlock(globalData, m_evalCodeBlock);
269 m_jitCodeForCall = m_evalCodeBlock->getJITCode();
270 ASSERT(!m_jitCodeForCallWithArityCheck);
271 }
272 #endif
273
274 void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
275 {
276 EvalExecutable* thisObject = jsCast<EvalExecutable*>(cell);
277 ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
278 COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
279 ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
280 ScriptExecutable::visitChildren(thisObject, visitor);
281 if (thisObject->m_evalCodeBlock)
282 thisObject->m_evalCodeBlock->visitAggregate(visitor);
283 }
284
285 void EvalExecutable::unlinkCalls()
286 {
287 #if ENABLE(JIT)
288 if (!m_jitCodeForCall)
289 return;
290 ASSERT(m_evalCodeBlock);
291 m_evalCodeBlock->unlinkCalls();
292 #endif
293 }
294
295 void EvalExecutable::finalize(JSCell* cell)
296 {
297 jsCast<EvalExecutable*>(cell)->clearCode();
298 }
299
300 inline void EvalExecutable::clearCode()
301 {
302 if (m_evalCodeBlock) {
303 m_evalCodeBlock->clearEvalCache();
304 m_evalCodeBlock.clear();
305 }
306 Base::clearCode();
307 }
308
309 JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
310 {
311 JSObject* exception = 0;
312 JSGlobalData* globalData = &exec->globalData();
313 JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
314 RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
315 if (programNode)
316 return 0;
317 ASSERT(exception);
318 return exception;
319 }
320
321 JSObject* ProgramExecutable::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
322 {
323 ASSERT(exec->globalData().dynamicGlobalObject);
324 ASSERT(!!m_programCodeBlock);
325 JSObject* error = 0;
326 if (m_programCodeBlock->getJITType() != JITCode::topTierJIT())
327 error = compileInternal(exec, scopeChainNode, JITCode::nextTierJIT(m_programCodeBlock->getJITType()));
328 ASSERT(!!m_programCodeBlock);
329 return error;
330 }
331
332 #if ENABLE(JIT)
333 bool ProgramExecutable::jitCompile(JSGlobalData& globalData)
334 {
335 return jitCompileIfAppropriate(globalData, m_programCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), JITCompilationCanFail);
336 }
337 #endif
338
339 JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
340 {
341 SamplingRegion samplingRegion(samplingDescription(jitType));
342
343 #if !ENABLE(JIT)
344 UNUSED_PARAM(jitType);
345 #endif
346 JSObject* exception = 0;
347 JSGlobalData* globalData = &exec->globalData();
348 JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
349
350 if (!!m_programCodeBlock) {
351 OwnPtr<ProgramCodeBlock> newCodeBlock = adoptPtr(new ProgramCodeBlock(CodeBlock::CopyParsedBlock, *m_programCodeBlock));
352 newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_programCodeBlock.release()));
353 m_programCodeBlock = newCodeBlock.release();
354 } else {
355 RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
356 if (!programNode) {
357 ASSERT(exception);
358 return exception;
359 }
360 recordParse(programNode->features(), programNode->hasCapturedVariables(), programNode->lineNo(), programNode->lastLine());
361
362 JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
363
364 OwnPtr<CodeBlock> previousCodeBlock = m_programCodeBlock.release();
365 ASSERT((jitType == JITCode::bottomTierJIT()) == !previousCodeBlock);
366 m_programCodeBlock = adoptPtr(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider(), previousCodeBlock.release()));
367 OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(programNode.get(), scopeChainNode, &globalObject->symbolTable(), m_programCodeBlock.get(), !!m_programCodeBlock->alternative() ? OptimizingCompilation : FirstCompilation)));
368 if ((exception = generator->generate())) {
369 m_programCodeBlock = static_pointer_cast<ProgramCodeBlock>(m_programCodeBlock->releaseAlternative());
370 programNode->destroyData();
371 return exception;
372 }
373
374 programNode->destroyData();
375 m_programCodeBlock->copyPostParseDataFromAlternative();
376 }
377
378 #if ENABLE(JIT)
379 if (!prepareForExecution(*globalData, m_programCodeBlock, m_jitCodeForCall, jitType))
380 return 0;
381 #endif
382
383 #if ENABLE(JIT)
384 #if ENABLE(CLASSIC_INTERPRETER)
385 if (!m_jitCodeForCall)
386 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock));
387 else
388 #endif
389 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock) + m_jitCodeForCall.size());
390 #else
391 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock));
392 #endif
393
394 return 0;
395 }
396
397 #if ENABLE(JIT)
398 void ProgramExecutable::jettisonOptimizedCode(JSGlobalData& globalData)
399 {
400 jettisonCodeBlock(globalData, m_programCodeBlock);
401 m_jitCodeForCall = m_programCodeBlock->getJITCode();
402 ASSERT(!m_jitCodeForCallWithArityCheck);
403 }
404 #endif
405
406 void ProgramExecutable::unlinkCalls()
407 {
408 #if ENABLE(JIT)
409 if (!m_jitCodeForCall)
410 return;
411 ASSERT(m_programCodeBlock);
412 m_programCodeBlock->unlinkCalls();
413 #endif
414 }
415
416 void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
417 {
418 ProgramExecutable* thisObject = jsCast<ProgramExecutable*>(cell);
419 ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
420 COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
421 ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
422 ScriptExecutable::visitChildren(thisObject, visitor);
423 if (thisObject->m_programCodeBlock)
424 thisObject->m_programCodeBlock->visitAggregate(visitor);
425 }
426
427 void ProgramExecutable::finalize(JSCell* cell)
428 {
429 jsCast<ProgramExecutable*>(cell)->clearCode();
430 }
431
432 inline void ProgramExecutable::clearCode()
433 {
434 if (m_programCodeBlock) {
435 m_programCodeBlock->clearEvalCache();
436 m_programCodeBlock.clear();
437 }
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 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 ASSERT(result);
455 ASSERT(JITCode::isBaselineCode(result->getJITType()));
456 return result;
457 }
458
459 JSObject* FunctionExecutable::compileOptimizedForCall(ExecState* exec, ScopeChainNode* scopeChainNode)
460 {
461 ASSERT(exec->globalData().dynamicGlobalObject);
462 ASSERT(!!m_codeBlockForCall);
463 JSObject* error = 0;
464 if (m_codeBlockForCall->getJITType() != JITCode::topTierJIT())
465 error = compileForCallInternal(exec, scopeChainNode, JITCode::nextTierJIT(m_codeBlockForCall->getJITType()));
466 ASSERT(!!m_codeBlockForCall);
467 return error;
468 }
469
470 JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode)
471 {
472 ASSERT(exec->globalData().dynamicGlobalObject);
473 ASSERT(!!m_codeBlockForConstruct);
474 JSObject* error = 0;
475 if (m_codeBlockForConstruct->getJITType() != JITCode::topTierJIT())
476 error = compileForConstructInternal(exec, scopeChainNode, JITCode::nextTierJIT(m_codeBlockForConstruct->getJITType()));
477 ASSERT(!!m_codeBlockForConstruct);
478 return error;
479 }
480
481 #if ENABLE(JIT)
482 bool FunctionExecutable::jitCompileForCall(JSGlobalData& globalData)
483 {
484 return jitCompileFunctionIfAppropriate(globalData, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), JITCompilationCanFail);
485 }
486
487 bool FunctionExecutable::jitCompileForConstruct(JSGlobalData& globalData)
488 {
489 return jitCompileFunctionIfAppropriate(globalData, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), JITCompilationCanFail);
490 }
491 #endif
492
493 FunctionCodeBlock* FunctionExecutable::codeBlockWithBytecodeFor(CodeSpecializationKind kind)
494 {
495 return baselineCodeBlockFor(kind);
496 }
497
498 PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(ScopeChainNode* scopeChainNode, CompilationKind compilationKind, CodeSpecializationKind specializationKind, JSObject*& exception)
499 {
500 if (!!codeBlockFor(specializationKind))
501 return adoptPtr(new FunctionCodeBlock(CodeBlock::CopyParsedBlock, *codeBlockFor(specializationKind)));
502
503 exception = 0;
504 JSGlobalData* globalData = scopeChainNode->globalData;
505 JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
506 RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(globalData, globalObject, m_source, m_parameters.get(), isStrictMode() ? JSParseStrict : JSParseNormal, FunctionBodyNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, 0, 0, &exception);
507
508 if (!body) {
509 ASSERT(exception);
510 return nullptr;
511 }
512 if (m_forceUsesArguments)
513 body->setUsesArguments();
514 body->finishParsing(m_parameters, m_name);
515 recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
516
517 OwnPtr<FunctionCodeBlock> result;
518 ASSERT((compilationKind == FirstCompilation) == !codeBlockFor(specializationKind));
519 result = adoptPtr(new FunctionCodeBlock(this, FunctionCode, globalObject, source().provider(), source().startOffset(), specializationKind == CodeForConstruct));
520 OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), scopeChainNode, result->symbolTable(), result.get(), compilationKind)));
521 exception = generator->generate();
522 body->destroyData();
523 if (exception)
524 return nullptr;
525
526 result->copyPostParseDataFrom(codeBlockFor(specializationKind).get());
527 return result.release();
528 }
529
530 JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
531 {
532 SamplingRegion samplingRegion(samplingDescription(jitType));
533
534 #if !ENABLE(JIT)
535 UNUSED_PARAM(exec);
536 UNUSED_PARAM(jitType);
537 UNUSED_PARAM(exec);
538 #endif
539 ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForCall);
540 JSObject* exception;
541 OwnPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scopeChainNode, !!m_codeBlockForCall ? OptimizingCompilation : FirstCompilation, CodeForCall, exception);
542 if (!newCodeBlock)
543 return exception;
544
545 newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_codeBlockForCall.release()));
546 m_codeBlockForCall = newCodeBlock.release();
547
548 m_numParametersForCall = m_codeBlockForCall->numParameters();
549 ASSERT(m_numParametersForCall);
550 m_numCapturedVariables = m_codeBlockForCall->m_numCapturedVars;
551 m_symbolTable = m_codeBlockForCall->sharedSymbolTable();
552
553 #if ENABLE(JIT)
554 if (!prepareFunctionForExecution(exec->globalData(), m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, jitType, CodeForCall))
555 return 0;
556 #endif
557
558 #if ENABLE(JIT)
559 #if ENABLE(CLASSIC_INTERPRETER)
560 if (!m_jitCodeForCall)
561 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall));
562 else
563 #endif
564 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall) + m_jitCodeForCall.size());
565 #else
566 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall));
567 #endif
568
569 return 0;
570 }
571
572 JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
573 {
574 SamplingRegion samplingRegion(samplingDescription(jitType));
575
576 #if !ENABLE(JIT)
577 UNUSED_PARAM(jitType);
578 UNUSED_PARAM(exec);
579 #endif
580
581 ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForConstruct);
582 JSObject* exception;
583 OwnPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scopeChainNode, !!m_codeBlockForConstruct ? OptimizingCompilation : FirstCompilation, CodeForConstruct, exception);
584 if (!newCodeBlock)
585 return exception;
586
587 newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_codeBlockForConstruct.release()));
588 m_codeBlockForConstruct = newCodeBlock.release();
589
590 m_numParametersForConstruct = m_codeBlockForConstruct->numParameters();
591 ASSERT(m_numParametersForConstruct);
592 m_numCapturedVariables = m_codeBlockForConstruct->m_numCapturedVars;
593 m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable();
594
595 #if ENABLE(JIT)
596 if (!prepareFunctionForExecution(exec->globalData(), m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, jitType, CodeForConstruct))
597 return 0;
598 #endif
599
600 #if ENABLE(JIT)
601 #if ENABLE(CLASSIC_INTERPRETER)
602 if (!m_jitCodeForConstruct)
603 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct));
604 else
605 #endif
606 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct) + m_jitCodeForConstruct.size());
607 #else
608 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct));
609 #endif
610
611 return 0;
612 }
613
614 #if ENABLE(JIT)
615 void FunctionExecutable::jettisonOptimizedCodeForCall(JSGlobalData& globalData)
616 {
617 jettisonCodeBlock(globalData, m_codeBlockForCall);
618 m_jitCodeForCall = m_codeBlockForCall->getJITCode();
619 m_jitCodeForCallWithArityCheck = m_codeBlockForCall->getJITCodeWithArityCheck();
620 }
621
622 void FunctionExecutable::jettisonOptimizedCodeForConstruct(JSGlobalData& globalData)
623 {
624 jettisonCodeBlock(globalData, m_codeBlockForConstruct);
625 m_jitCodeForConstruct = m_codeBlockForConstruct->getJITCode();
626 m_jitCodeForConstructWithArityCheck = m_codeBlockForConstruct->getJITCodeWithArityCheck();
627 }
628 #endif
629
630 void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
631 {
632 FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell);
633 ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
634 COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
635 ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
636 ScriptExecutable::visitChildren(thisObject, visitor);
637 if (thisObject->m_nameValue)
638 visitor.append(&thisObject->m_nameValue);
639 if (thisObject->m_codeBlockForCall)
640 thisObject->m_codeBlockForCall->visitAggregate(visitor);
641 if (thisObject->m_codeBlockForConstruct)
642 thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
643 }
644
645 void FunctionExecutable::discardCode()
646 {
647 #if ENABLE(JIT)
648 // These first two checks are to handle the rare case where
649 // we are trying to evict code for a function during its
650 // codegen.
651 if (!m_jitCodeForCall && m_codeBlockForCall)
652 return;
653 if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
654 return;
655 #endif
656 clearCode();
657 }
658
659 void FunctionExecutable::finalize(JSCell* cell)
660 {
661 FunctionExecutable* executable = jsCast<FunctionExecutable*>(cell);
662 Heap::heap(executable)->removeFunctionExecutable(executable);
663 executable->clearCode();
664 }
665
666 inline void FunctionExecutable::clearCode()
667 {
668 if (m_codeBlockForCall) {
669 m_codeBlockForCall->clearEvalCache();
670 m_codeBlockForCall.clear();
671 }
672 if (m_codeBlockForConstruct) {
673 m_codeBlockForConstruct->clearEvalCache();
674 m_codeBlockForConstruct.clear();
675 }
676 Base::clearCode();
677 }
678
679 void FunctionExecutable::unlinkCalls()
680 {
681 #if ENABLE(JIT)
682 if (!!m_jitCodeForCall) {
683 ASSERT(m_codeBlockForCall);
684 m_codeBlockForCall->unlinkCalls();
685 }
686 if (!!m_jitCodeForConstruct) {
687 ASSERT(m_codeBlockForConstruct);
688 m_codeBlockForConstruct->unlinkCalls();
689 }
690 #endif
691 }
692
693 FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
694 {
695 JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
696 RefPtr<ProgramNode> program = parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, source, 0, JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, debugger, exec, exception);
697 if (!program) {
698 ASSERT(*exception);
699 return 0;
700 }
701
702 // Uses of this function that would not result in a single function expression are invalid.
703 StatementNode* exprStatement = program->singleStatement();
704 ASSERT(exprStatement);
705 ASSERT(exprStatement->isExprStatement());
706 ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
707 ASSERT(funcExpr);
708 ASSERT(funcExpr->isFuncExprNode());
709 FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
710 ASSERT(body);
711
712 return FunctionExecutable::create(exec->globalData(), functionName, functionName, body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
713 }
714
715 UString FunctionExecutable::paramString() const
716 {
717 FunctionParameters& parameters = *m_parameters;
718 UStringBuilder builder;
719 for (size_t pos = 0; pos < parameters.size(); ++pos) {
720 if (!builder.isEmpty())
721 builder.append(", ");
722 builder.append(parameters[pos].ustring());
723 }
724 return builder.toUString();
725 }
726
727 }