]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/Executable.cpp
JavaScriptCore-1218.tar.gz
[apple/javascriptcore.git] / runtime / Executable.cpp
CommitLineData
f9bf01c6 1/*
14957cd0 2 * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
f9bf01c6
A
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
93a37866 29#include "BatchedTransitionOptimizer.h"
f9bf01c6
A
30#include "BytecodeGenerator.h"
31#include "CodeBlock.h"
6fe7ccc8
A
32#include "DFGDriver.h"
33#include "ExecutionHarness.h"
f9bf01c6 34#include "JIT.h"
6fe7ccc8 35#include "JITDriver.h"
93a37866 36#include "Operations.h"
f9bf01c6 37#include "Parser.h"
6fe7ccc8 38#include <wtf/Vector.h>
93a37866 39#include <wtf/text/StringBuilder.h>
f9bf01c6 40
6fe7ccc8
A
41namespace JSC {
42
43const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0, CREATE_METHOD_TABLE(ExecutableBase) };
44
45#if ENABLE(JIT)
46void ExecutableBase::destroy(JSCell* cell)
47{
93a37866 48 static_cast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();
6fe7ccc8 49}
14957cd0
A
50#endif
51
93a37866 52void ExecutableBase::clearCode()
6fe7ccc8
A
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}
f9bf01c6 63
6fe7ccc8
A
64#if ENABLE(DFG_JIT)
65Intrinsic ExecutableBase::intrinsic() const
66{
67 if (const NativeExecutable* nativeExecutable = jsDynamicCast<const NativeExecutable*>(this))
68 return nativeExecutable->intrinsic();
69 return NoIntrinsic;
70}
93a37866
A
71#else
72Intrinsic ExecutableBase::intrinsic() const
73{
74 return NoIntrinsic;
75}
6fe7ccc8
A
76#endif
77
78const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(NativeExecutable) };
14957cd0 79
f9bf01c6 80#if ENABLE(JIT)
6fe7ccc8
A
81void NativeExecutable::destroy(JSCell* cell)
82{
93a37866 83 static_cast<NativeExecutable*>(cell)->NativeExecutable::~NativeExecutable();
6fe7ccc8
A
84}
85#endif
86
87#if ENABLE(DFG_JIT)
88Intrinsic NativeExecutable::intrinsic() const
89{
90 return m_intrinsic;
91}
92#endif
14957cd0 93
6fe7ccc8
A
94#if ENABLE(JIT)
95// Utility method used for jettisoning code blocks.
96template<typename T>
93a37866 97static void jettisonCodeBlock(VM& vm, OwnPtr<T>& codeBlock)
f9bf01c6 98{
6fe7ccc8
A
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();
93a37866 104 vm.heap.jettisonDFGCodeBlock(static_pointer_cast<CodeBlock>(codeBlockToJettison.release()));
f9bf01c6
A
105}
106#endif
107
6fe7ccc8 108const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
14957cd0 109
6fe7ccc8
A
110#if ENABLE(JIT)
111void ScriptExecutable::destroy(JSCell* cell)
112{
93a37866 113 static_cast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
6fe7ccc8
A
114}
115#endif
116
117const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(EvalExecutable) };
14957cd0 118
93a37866
A
119EvalExecutable::EvalExecutable(ExecState* exec, PassRefPtr<CodeCache> codeCache, const SourceCode& source, bool inStrictContext)
120 : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec, source, inStrictContext)
121 , m_codeCache(codeCache)
f9bf01c6
A
122{
123}
124
6fe7ccc8 125void EvalExecutable::destroy(JSCell* cell)
f9bf01c6 126{
93a37866 127 static_cast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable();
14957cd0
A
128}
129
6fe7ccc8 130const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(ProgramExecutable) };
14957cd0
A
131
132ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
93a37866 133 : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec, source, false)
14957cd0 134{
f9bf01c6
A
135}
136
6fe7ccc8 137void ProgramExecutable::destroy(JSCell* cell)
f9bf01c6 138{
93a37866 139 static_cast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable();
f9bf01c6
A
140}
141
6fe7ccc8 142const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
14957cd0 143
93a37866
A
144FunctionExecutable::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)
6fe7ccc8 147{
93a37866
A
148 RELEASE_ASSERT(!source.isNull());
149 ASSERT(source.length());
150 m_firstLine = firstLine;
151 m_lastLine = lastLine;
152 m_startColumn = startColumn;
6fe7ccc8
A
153}
154
155void FunctionExecutable::destroy(JSCell* cell)
156{
93a37866 157 static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
6fe7ccc8
A
158}
159
93a37866 160JSObject* EvalExecutable::compileOptimized(ExecState* exec, JSScope* scope, unsigned bytecodeIndex)
f9bf01c6 161{
93a37866 162 ASSERT(exec->vm().dynamicGlobalObject);
6fe7ccc8
A
163 ASSERT(!!m_evalCodeBlock);
164 JSObject* error = 0;
165 if (m_evalCodeBlock->getJITType() != JITCode::topTierJIT())
93a37866 166 error = compileInternal(exec, scope, JITCode::nextTierJIT(m_evalCodeBlock->getJITType()), bytecodeIndex);
6fe7ccc8
A
167 ASSERT(!!m_evalCodeBlock);
168 return error;
14957cd0 169}
f9bf01c6 170
6fe7ccc8 171#if ENABLE(JIT)
93a37866 172bool EvalExecutable::jitCompile(ExecState* exec)
6fe7ccc8 173{
93a37866 174 return jitCompileIfAppropriate(exec, m_evalCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
6fe7ccc8
A
175}
176#endif
177
178inline 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:
93a37866 188 RELEASE_ASSERT_NOT_REACHED();
6fe7ccc8
A
189 return 0;
190 }
191}
14957cd0 192
93a37866 193JSObject* EvalExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCode::JITType jitType, unsigned bytecodeIndex)
14957cd0 194{
6fe7ccc8
A
195 SamplingRegion samplingRegion(samplingDescription(jitType));
196
197#if !ENABLE(JIT)
198 UNUSED_PARAM(jitType);
93a37866 199 UNUSED_PARAM(bytecodeIndex);
6fe7ccc8 200#endif
93a37866 201 VM* vm = &exec->vm();
14957cd0 202 JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
6fe7ccc8
A
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 {
93a37866
A
209 UNUSED_PARAM(scope);
210 UNUSED_PARAM(vm);
211 UNUSED_PARAM(lexicalGlobalObject);
6fe7ccc8 212 if (!lexicalGlobalObject->evalEnabled())
93a37866
A
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)
6fe7ccc8 218 return exception;
93a37866 219
6fe7ccc8
A
220 OwnPtr<CodeBlock> previousCodeBlock = m_evalCodeBlock.release();
221 ASSERT((jitType == JITCode::bottomTierJIT()) == !previousCodeBlock);
93a37866
A
222 m_unlinkedEvalCodeBlock.set(*vm, this, unlinkedEvalCode);
223 m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, unlinkedEvalCode, lexicalGlobalObject, source().provider(), scope->localDepth(), previousCodeBlock.release()));
6fe7ccc8 224 m_evalCodeBlock->copyPostParseDataFromAlternative();
14957cd0
A
225 }
226
14957cd0 227#if ENABLE(JIT)
93a37866 228 if (!prepareForExecution(exec, m_evalCodeBlock, m_jitCodeForCall, jitType, bytecodeIndex))
6fe7ccc8 229 return 0;
14957cd0
A
230#endif
231
232#if ENABLE(JIT)
14957cd0
A
233 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock) + m_jitCodeForCall.size());
234#else
235 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock));
236#endif
237
f9bf01c6
A
238 return 0;
239}
240
6fe7ccc8 241#if ENABLE(JIT)
93a37866 242void EvalExecutable::jettisonOptimizedCode(VM& vm)
6fe7ccc8 243{
93a37866 244 jettisonCodeBlock(vm, m_evalCodeBlock);
6fe7ccc8
A
245 m_jitCodeForCall = m_evalCodeBlock->getJITCode();
246 ASSERT(!m_jitCodeForCallWithArityCheck);
247}
248#endif
249
250void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
f9bf01c6 251{
6fe7ccc8
A
252 EvalExecutable* thisObject = jsCast<EvalExecutable*>(cell);
253 ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
14957cd0 254 COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
6fe7ccc8
A
255 ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
256 ScriptExecutable::visitChildren(thisObject, visitor);
257 if (thisObject->m_evalCodeBlock)
258 thisObject->m_evalCodeBlock->visitAggregate(visitor);
93a37866 259 visitor.append(&thisObject->m_unlinkedEvalCodeBlock);
f9bf01c6
A
260}
261
14957cd0 262void EvalExecutable::unlinkCalls()
f9bf01c6 263{
14957cd0
A
264#if ENABLE(JIT)
265 if (!m_jitCodeForCall)
266 return;
93a37866 267 RELEASE_ASSERT(m_evalCodeBlock);
14957cd0
A
268 m_evalCodeBlock->unlinkCalls();
269#endif
270}
f9bf01c6 271
93a37866 272void EvalExecutable::clearCode()
6fe7ccc8 273{
93a37866
A
274 m_evalCodeBlock.clear();
275 m_unlinkedEvalCodeBlock.clear();
6fe7ccc8
A
276 Base::clearCode();
277}
278
14957cd0
A
279JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
280{
93a37866
A
281 ParserError error;
282 VM* vm = &exec->vm();
14957cd0 283 JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
93a37866 284 RefPtr<ProgramNode> programNode = parse<ProgramNode>(vm, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, error);
14957cd0
A
285 if (programNode)
286 return 0;
93a37866
A
287 ASSERT(error.m_type != ParserError::ErrorNone);
288 return error.toErrorObject(lexicalGlobalObject, m_source);
f9bf01c6
A
289}
290
93a37866 291JSObject* ProgramExecutable::compileOptimized(ExecState* exec, JSScope* scope, unsigned bytecodeIndex)
f9bf01c6 292{
93a37866 293 RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
6fe7ccc8
A
294 ASSERT(!!m_programCodeBlock);
295 JSObject* error = 0;
296 if (m_programCodeBlock->getJITType() != JITCode::topTierJIT())
93a37866 297 error = compileInternal(exec, scope, JITCode::nextTierJIT(m_programCodeBlock->getJITType()), bytecodeIndex);
6fe7ccc8
A
298 ASSERT(!!m_programCodeBlock);
299 return error;
300}
f9bf01c6 301
6fe7ccc8 302#if ENABLE(JIT)
93a37866 303bool ProgramExecutable::jitCompile(ExecState* exec)
6fe7ccc8 304{
93a37866 305 return jitCompileIfAppropriate(exec, m_programCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
6fe7ccc8
A
306}
307#endif
308
93a37866 309JSObject* ProgramExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCode::JITType jitType, unsigned bytecodeIndex)
6fe7ccc8
A
310{
311 SamplingRegion samplingRegion(samplingDescription(jitType));
312
313#if !ENABLE(JIT)
93a37866 314 UNUSED_PARAM(exec);
6fe7ccc8 315 UNUSED_PARAM(jitType);
93a37866 316 UNUSED_PARAM(bytecodeIndex);
6fe7ccc8 317#endif
6fe7ccc8
A
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 {
93a37866
A
323 JSGlobalObject* globalObject = scope->globalObject();
324 m_programCodeBlock = adoptPtr(new ProgramCodeBlock(this, m_unlinkedProgramCodeBlock.get(), globalObject, source().provider(), source().startColumn(), m_programCodeBlock.release()));
6fe7ccc8 325 m_programCodeBlock->copyPostParseDataFromAlternative();
14957cd0 326 }
f9bf01c6 327
f9bf01c6 328#if ENABLE(JIT)
93a37866 329 if (!prepareForExecution(exec, m_programCodeBlock, m_jitCodeForCall, jitType, bytecodeIndex))
6fe7ccc8 330 return 0;
14957cd0 331#endif
f9bf01c6 332
14957cd0 333#if ENABLE(JIT)
93a37866 334 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock) + m_jitCodeForCall.size());
14957cd0
A
335#else
336 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock));
f9bf01c6 337#endif
14957cd0
A
338
339 return 0;
f9bf01c6
A
340}
341
6fe7ccc8 342#if ENABLE(JIT)
93a37866 343void ProgramExecutable::jettisonOptimizedCode(VM& vm)
6fe7ccc8 344{
93a37866 345 jettisonCodeBlock(vm, m_programCodeBlock);
6fe7ccc8
A
346 m_jitCodeForCall = m_programCodeBlock->getJITCode();
347 ASSERT(!m_jitCodeForCallWithArityCheck);
348}
349#endif
350
14957cd0 351void ProgramExecutable::unlinkCalls()
f9bf01c6 352{
14957cd0
A
353#if ENABLE(JIT)
354 if (!m_jitCodeForCall)
355 return;
93a37866 356 RELEASE_ASSERT(m_programCodeBlock);
14957cd0 357 m_programCodeBlock->unlinkCalls();
f9bf01c6
A
358#endif
359}
360
93a37866
A
361int 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
378JSObject* 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
6fe7ccc8 422void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
f9bf01c6 423{
6fe7ccc8
A
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);
93a37866 429 visitor.append(&thisObject->m_unlinkedProgramCodeBlock);
6fe7ccc8
A
430 if (thisObject->m_programCodeBlock)
431 thisObject->m_programCodeBlock->visitAggregate(visitor);
432}
f9bf01c6 433
93a37866 434void ProgramExecutable::clearCode()
6fe7ccc8 435{
93a37866
A
436 m_programCodeBlock.clear();
437 m_unlinkedProgramCodeBlock.clear();
6fe7ccc8
A
438 Base::clearCode();
439}
440
441FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
442{
443 FunctionCodeBlock* result;
444 if (kind == CodeForCall)
445 result = m_codeBlockForCall.get();
446 else {
93a37866 447 RELEASE_ASSERT(kind == CodeForConstruct);
6fe7ccc8
A
448 result = m_codeBlockForConstruct.get();
449 }
450 if (!result)
451 return 0;
452 while (result->alternative())
453 result = static_cast<FunctionCodeBlock*>(result->alternative());
93a37866 454 RELEASE_ASSERT(result);
6fe7ccc8
A
455 ASSERT(JITCode::isBaselineCode(result->getJITType()));
456 return result;
457}
458
93a37866 459JSObject* FunctionExecutable::compileOptimizedForCall(ExecState* exec, JSScope* scope, unsigned bytecodeIndex)
6fe7ccc8 460{
93a37866 461 RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
6fe7ccc8
A
462 ASSERT(!!m_codeBlockForCall);
463 JSObject* error = 0;
464 if (m_codeBlockForCall->getJITType() != JITCode::topTierJIT())
93a37866 465 error = compileForCallInternal(exec, scope, JITCode::nextTierJIT(m_codeBlockForCall->getJITType()), bytecodeIndex);
6fe7ccc8
A
466 ASSERT(!!m_codeBlockForCall);
467 return error;
468}
469
93a37866 470JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, JSScope* scope, unsigned bytecodeIndex)
6fe7ccc8 471{
93a37866 472 RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
6fe7ccc8
A
473 ASSERT(!!m_codeBlockForConstruct);
474 JSObject* error = 0;
475 if (m_codeBlockForConstruct->getJITType() != JITCode::topTierJIT())
93a37866 476 error = compileForConstructInternal(exec, scope, JITCode::nextTierJIT(m_codeBlockForConstruct->getJITType()), bytecodeIndex);
6fe7ccc8
A
477 ASSERT(!!m_codeBlockForConstruct);
478 return error;
479}
480
481#if ENABLE(JIT)
93a37866 482bool FunctionExecutable::jitCompileForCall(ExecState* exec)
6fe7ccc8 483{
93a37866 484 return jitCompileFunctionIfAppropriate(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
6fe7ccc8
A
485}
486
93a37866 487bool FunctionExecutable::jitCompileForConstruct(ExecState* exec)
6fe7ccc8 488{
93a37866 489 return jitCompileFunctionIfAppropriate(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
f9bf01c6 490}
f9bf01c6
A
491#endif
492
93a37866 493PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(JSScope* scope, CodeSpecializationKind specializationKind, JSObject*& exception)
f9bf01c6 494{
6fe7ccc8
A
495 if (!!codeBlockFor(specializationKind))
496 return adoptPtr(new FunctionCodeBlock(CodeBlock::CopyParsedBlock, *codeBlockFor(specializationKind)));
6fe7ccc8 497
93a37866
A
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);
6fe7ccc8 508 return nullptr;
14957cd0 509 }
f9bf01c6 510
93a37866
A
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));
6fe7ccc8
A
516 result->copyPostParseDataFrom(codeBlockFor(specializationKind).get());
517 return result.release();
518}
519
93a37866
A
520
521JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, JSScope* scope, JITCode::JITType jitType, unsigned bytecodeIndex)
6fe7ccc8
A
522{
523 SamplingRegion samplingRegion(samplingDescription(jitType));
524
525#if !ENABLE(JIT)
526 UNUSED_PARAM(exec);
527 UNUSED_PARAM(jitType);
528 UNUSED_PARAM(exec);
93a37866 529 UNUSED_PARAM(bytecodeIndex);
6fe7ccc8
A
530#endif
531 ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForCall);
93a37866
A
532 JSObject* exception = 0;
533 OwnPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scope, CodeForCall, exception);
6fe7ccc8 534 if (!newCodeBlock)
14957cd0 535 return exception;
f9bf01c6 536
6fe7ccc8
A
537 newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_codeBlockForCall.release()));
538 m_codeBlockForCall = newCodeBlock.release();
539
540 m_numParametersForCall = m_codeBlockForCall->numParameters();
93a37866 541 RELEASE_ASSERT(m_numParametersForCall);
f9bf01c6 542
f9bf01c6 543#if ENABLE(JIT)
93a37866 544 if (!prepareFunctionForExecution(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, jitType, bytecodeIndex, CodeForCall))
6fe7ccc8 545 return 0;
f9bf01c6
A
546#endif
547
14957cd0 548#if ENABLE(JIT)
93a37866 549 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall) + m_jitCodeForCall.size());
14957cd0
A
550#else
551 Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall));
552#endif
f9bf01c6 553
14957cd0 554 return 0;
f9bf01c6
A
555}
556
93a37866 557JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, JSScope* scope, JITCode::JITType jitType, unsigned bytecodeIndex)
f9bf01c6 558{
6fe7ccc8
A
559 SamplingRegion samplingRegion(samplingDescription(jitType));
560
561#if !ENABLE(JIT)
562 UNUSED_PARAM(jitType);
563 UNUSED_PARAM(exec);
93a37866 564 UNUSED_PARAM(bytecodeIndex);
6fe7ccc8
A
565#endif
566
567 ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForConstruct);
93a37866
A
568 JSObject* exception = 0;
569 OwnPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scope, CodeForConstruct, exception);
6fe7ccc8 570 if (!newCodeBlock)
14957cd0 571 return exception;
f9bf01c6 572
6fe7ccc8
A
573 newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_codeBlockForConstruct.release()));
574 m_codeBlockForConstruct = newCodeBlock.release();
575
576 m_numParametersForConstruct = m_codeBlockForConstruct->numParameters();
93a37866 577 RELEASE_ASSERT(m_numParametersForConstruct);
f9bf01c6 578
f9bf01c6 579#if ENABLE(JIT)
93a37866 580 if (!prepareFunctionForExecution(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, jitType, bytecodeIndex, CodeForConstruct))
6fe7ccc8 581 return 0;
f9bf01c6
A
582#endif
583
14957cd0 584#if ENABLE(JIT)
14957cd0
A
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
6fe7ccc8 593#if ENABLE(JIT)
93a37866 594void FunctionExecutable::jettisonOptimizedCodeForCall(VM& vm)
14957cd0 595{
93a37866 596 jettisonCodeBlock(vm, m_codeBlockForCall);
6fe7ccc8
A
597 m_jitCodeForCall = m_codeBlockForCall->getJITCode();
598 m_jitCodeForCallWithArityCheck = m_codeBlockForCall->getJITCodeWithArityCheck();
599}
600
93a37866 601void FunctionExecutable::jettisonOptimizedCodeForConstruct(VM& vm)
6fe7ccc8 602{
93a37866 603 jettisonCodeBlock(vm, m_codeBlockForConstruct);
6fe7ccc8
A
604 m_jitCodeForConstruct = m_codeBlockForConstruct->getJITCode();
605 m_jitCodeForConstructWithArityCheck = m_codeBlockForConstruct->getJITCodeWithArityCheck();
606}
607#endif
608
609void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
610{
611 FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell);
612 ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
14957cd0 613 COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
6fe7ccc8
A
614 ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
615 ScriptExecutable::visitChildren(thisObject, visitor);
6fe7ccc8
A
616 if (thisObject->m_codeBlockForCall)
617 thisObject->m_codeBlockForCall->visitAggregate(visitor);
618 if (thisObject->m_codeBlockForConstruct)
619 thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
93a37866 620 visitor.append(&thisObject->m_unlinkedExecutable);
f9bf01c6
A
621}
622
93a37866 623void FunctionExecutable::clearCodeIfNotCompiling()
f9bf01c6 624{
93a37866 625 if (isCompiling())
14957cd0 626 return;
6fe7ccc8
A
627 clearCode();
628}
629
93a37866 630void FunctionExecutable::clearUnlinkedCodeForRecompilationIfNotCompiling()
6fe7ccc8 631{
93a37866
A
632 if (isCompiling())
633 return;
634 m_unlinkedExecutable->clearCodeForRecompilation();
6fe7ccc8
A
635}
636
93a37866 637void FunctionExecutable::clearCode()
6fe7ccc8 638{
93a37866
A
639 m_codeBlockForCall.clear();
640 m_codeBlockForConstruct.clear();
6fe7ccc8 641 Base::clearCode();
f9bf01c6
A
642}
643
14957cd0 644void FunctionExecutable::unlinkCalls()
f9bf01c6 645{
14957cd0
A
646#if ENABLE(JIT)
647 if (!!m_jitCodeForCall) {
93a37866 648 RELEASE_ASSERT(m_codeBlockForCall);
14957cd0
A
649 m_codeBlockForCall->unlinkCalls();
650 }
651 if (!!m_jitCodeForConstruct) {
93a37866 652 RELEASE_ASSERT(m_codeBlockForConstruct);
14957cd0
A
653 m_codeBlockForConstruct->unlinkCalls();
654 }
655#endif
656}
657
93a37866 658FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
14957cd0 659{
93a37866
A
660 UnlinkedFunctionExecutable* unlinkedFunction = UnlinkedFunctionExecutable::fromGlobalCode(name, exec, debugger, source, exception);
661 if (!unlinkedFunction)
f9bf01c6 662 return 0;
93a37866
A
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}
f9bf01c6 670
93a37866
A
671String FunctionExecutable::paramString() const
672{
673 return m_unlinkedExecutable->paramString();
674}
14957cd0 675
93a37866
A
676CodeBlockHash 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);
f9bf01c6
A
682}
683
93a37866 684CodeBlockHash NativeExecutable::hashFor(CodeSpecializationKind kind) const
f9bf01c6 685{
93a37866
A
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
693CodeBlockHash ScriptExecutable::hashFor(CodeSpecializationKind kind) const
694{
695 return CodeBlockHash(source(), kind);
f9bf01c6
A
696}
697
14957cd0 698}