]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/Executable.cpp
JavaScriptCore-7600.1.4.16.1.tar.gz
[apple/javascriptcore.git] / runtime / Executable.cpp
CommitLineData
f9bf01c6 1/*
81345200 2 * Copyright (C) 2009, 2010, 2013 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 32#include "DFGDriver.h"
f9bf01c6 33#include "JIT.h"
81345200
A
34#include "LLIntEntrypoint.h"
35#include "JSCInlines.h"
f9bf01c6 36#include "Parser.h"
81345200
A
37#include "ProfilerDatabase.h"
38#include <wtf/CommaPrinter.h>
6fe7ccc8 39#include <wtf/Vector.h>
93a37866 40#include <wtf/text/StringBuilder.h>
f9bf01c6 41
6fe7ccc8
A
42namespace JSC {
43
44const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0, CREATE_METHOD_TABLE(ExecutableBase) };
45
46#if ENABLE(JIT)
47void ExecutableBase::destroy(JSCell* cell)
48{
93a37866 49 static_cast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();
6fe7ccc8 50}
14957cd0
A
51#endif
52
93a37866 53void ExecutableBase::clearCode()
6fe7ccc8
A
54{
55#if ENABLE(JIT)
56 m_jitCodeForCall.clear();
57 m_jitCodeForConstruct.clear();
58 m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
59 m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
81345200
A
60 m_jitCodeForCallWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
61 m_jitCodeForConstructWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
6fe7ccc8
A
62#endif
63 m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
64 m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
65}
f9bf01c6 66
6fe7ccc8
A
67#if ENABLE(DFG_JIT)
68Intrinsic ExecutableBase::intrinsic() const
69{
70 if (const NativeExecutable* nativeExecutable = jsDynamicCast<const NativeExecutable*>(this))
71 return nativeExecutable->intrinsic();
72 return NoIntrinsic;
73}
93a37866
A
74#else
75Intrinsic ExecutableBase::intrinsic() const
76{
77 return NoIntrinsic;
78}
6fe7ccc8
A
79#endif
80
81const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(NativeExecutable) };
14957cd0 82
f9bf01c6 83#if ENABLE(JIT)
6fe7ccc8
A
84void NativeExecutable::destroy(JSCell* cell)
85{
93a37866 86 static_cast<NativeExecutable*>(cell)->NativeExecutable::~NativeExecutable();
6fe7ccc8
A
87}
88#endif
89
90#if ENABLE(DFG_JIT)
91Intrinsic NativeExecutable::intrinsic() const
92{
93 return m_intrinsic;
94}
95#endif
14957cd0 96
81345200
A
97const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
98
6fe7ccc8 99#if ENABLE(JIT)
81345200 100void ScriptExecutable::destroy(JSCell* cell)
f9bf01c6 101{
81345200 102 static_cast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
f9bf01c6
A
103}
104#endif
105
81345200
A
106void ScriptExecutable::installCode(CodeBlock* genericCodeBlock)
107{
108 RELEASE_ASSERT(genericCodeBlock->ownerExecutable() == this);
109 RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock->jitType()));
110
111 VM& vm = *genericCodeBlock->vm();
112
113 if (vm.m_perBytecodeProfiler)
114 vm.m_perBytecodeProfiler->ensureBytecodesFor(genericCodeBlock);
115
116 ASSERT(vm.heap.isDeferred());
117
118 CodeSpecializationKind kind = genericCodeBlock->specializationKind();
119
120 RefPtr<CodeBlock> oldCodeBlock;
121
122 switch (kind) {
123 case CodeForCall:
124 m_jitCodeForCall = genericCodeBlock->jitCode();
125 m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
126 m_jitCodeForCallWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
127 m_numParametersForCall = genericCodeBlock->numParameters();
128 break;
129 case CodeForConstruct:
130 m_jitCodeForConstruct = genericCodeBlock->jitCode();
131 m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
132 m_jitCodeForConstructWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
133 m_numParametersForConstruct = genericCodeBlock->numParameters();
134 break;
135 }
136
137 switch (genericCodeBlock->codeType()) {
138 case GlobalCode: {
139 ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
140 ProgramCodeBlock* codeBlock = static_cast<ProgramCodeBlock*>(genericCodeBlock);
141
142 ASSERT(kind == CodeForCall);
143
144 oldCodeBlock = executable->m_programCodeBlock;
145 executable->m_programCodeBlock = codeBlock;
146 break;
147 }
148
149 case EvalCode: {
150 EvalExecutable* executable = jsCast<EvalExecutable*>(this);
151 EvalCodeBlock* codeBlock = static_cast<EvalCodeBlock*>(genericCodeBlock);
152
153 ASSERT(kind == CodeForCall);
154
155 oldCodeBlock = executable->m_evalCodeBlock;
156 executable->m_evalCodeBlock = codeBlock;
157 break;
158 }
159
160 case FunctionCode: {
161 FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
162 FunctionCodeBlock* codeBlock = static_cast<FunctionCodeBlock*>(genericCodeBlock);
163
164 switch (kind) {
165 case CodeForCall:
166 oldCodeBlock = executable->m_codeBlockForCall;
167 executable->m_codeBlockForCall = codeBlock;
168 break;
169 case CodeForConstruct:
170 oldCodeBlock = executable->m_codeBlockForConstruct;
171 executable->m_codeBlockForConstruct = codeBlock;
172 break;
173 }
174 break;
175 } }
176
177 if (oldCodeBlock)
178 oldCodeBlock->unlinkIncomingCalls();
179
180 Debugger* debugger = genericCodeBlock->globalObject()->debugger();
181 if (debugger)
182 debugger->registerCodeBlock(genericCodeBlock);
183
184 Heap::heap(this)->writeBarrier(this);
185}
186
187PassRefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor(
188 CodeSpecializationKind kind, JSFunction* function, JSScope** scope, JSObject*& exception)
189{
190 VM* vm = (*scope)->vm();
191
192 ASSERT(vm->heap.isDeferred());
193 ASSERT(startColumn() != UINT_MAX);
194 ASSERT(endColumn() != UINT_MAX);
195
196 if (classInfo() == EvalExecutable::info()) {
197 EvalExecutable* executable = jsCast<EvalExecutable*>(this);
198 RELEASE_ASSERT(kind == CodeForCall);
199 RELEASE_ASSERT(!executable->m_evalCodeBlock);
200 RELEASE_ASSERT(!function);
201 return adoptRef(new EvalCodeBlock(
202 executable, executable->m_unlinkedEvalCodeBlock.get(), *scope,
203 executable->source().provider()));
204 }
205
206 if (classInfo() == ProgramExecutable::info()) {
207 ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
208 RELEASE_ASSERT(kind == CodeForCall);
209 RELEASE_ASSERT(!executable->m_programCodeBlock);
210 RELEASE_ASSERT(!function);
211 return adoptRef(new ProgramCodeBlock(
212 executable, executable->m_unlinkedProgramCodeBlock.get(), *scope,
213 executable->source().provider(), executable->source().startColumn()));
214 }
215
216 RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
217 RELEASE_ASSERT(function);
218 FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
219 RELEASE_ASSERT(!executable->codeBlockFor(kind));
220 JSGlobalObject* globalObject = (*scope)->globalObject();
221 ParserError error;
222 DebuggerMode debuggerMode = globalObject->hasDebugger() ? DebuggerOn : DebuggerOff;
223 ProfilerMode profilerMode = globalObject->hasProfiler() ? ProfilerOn : ProfilerOff;
224 UnlinkedFunctionCodeBlock* unlinkedCodeBlock =
225 executable->m_unlinkedExecutable->codeBlockFor(
226 *vm, executable->m_source, kind, debuggerMode, profilerMode, executable->bodyIncludesBraces(), error);
227 recordParse(executable->m_unlinkedExecutable->features(), executable->m_unlinkedExecutable->hasCapturedVariables(), lineNo(), lastLine(), startColumn(), endColumn());
228 if (!unlinkedCodeBlock) {
229 exception = vm->throwException(
230 globalObject->globalExec(),
231 error.toErrorObject(globalObject, executable->m_source));
232 return 0;
233 }
14957cd0 234
81345200
A
235 // Parsing reveals whether our function uses features that require a separate function name object in the scope chain.
236 // Be sure to add this scope before linking the bytecode because this scope will change the resolution depth of non-local variables.
237 if (!executable->m_didParseForTheFirstTime) {
238 executable->m_didParseForTheFirstTime = true;
239 function->addNameScopeIfNeeded(*vm);
240 *scope = function->scope();
241 }
242
243 SourceProvider* provider = executable->source().provider();
244 unsigned sourceOffset = executable->source().startOffset();
245 unsigned startColumn = executable->source().startColumn();
246
247 return adoptRef(new FunctionCodeBlock(
248 executable, unlinkedCodeBlock, *scope, provider, sourceOffset, startColumn));
249}
250
251PassRefPtr<CodeBlock> ScriptExecutable::newReplacementCodeBlockFor(
252 CodeSpecializationKind kind)
253{
254 if (classInfo() == EvalExecutable::info()) {
255 RELEASE_ASSERT(kind == CodeForCall);
256 EvalExecutable* executable = jsCast<EvalExecutable*>(this);
257 EvalCodeBlock* baseline = static_cast<EvalCodeBlock*>(
258 executable->m_evalCodeBlock->baselineVersion());
259 RefPtr<EvalCodeBlock> result = adoptRef(new EvalCodeBlock(
260 CodeBlock::CopyParsedBlock, *baseline));
261 result->setAlternative(baseline);
262 return result;
263 }
264
265 if (classInfo() == ProgramExecutable::info()) {
266 RELEASE_ASSERT(kind == CodeForCall);
267 ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
268 ProgramCodeBlock* baseline = static_cast<ProgramCodeBlock*>(
269 executable->m_programCodeBlock->baselineVersion());
270 RefPtr<ProgramCodeBlock> result = adoptRef(new ProgramCodeBlock(
271 CodeBlock::CopyParsedBlock, *baseline));
272 result->setAlternative(baseline);
273 return result;
274 }
275
276 RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
277 FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
278 FunctionCodeBlock* baseline = static_cast<FunctionCodeBlock*>(
279 executable->codeBlockFor(kind)->baselineVersion());
280 RefPtr<FunctionCodeBlock> result = adoptRef(new FunctionCodeBlock(
281 CodeBlock::CopyParsedBlock, *baseline));
282 result->setAlternative(baseline);
283 return result;
284}
285
286static void setupLLInt(VM& vm, CodeBlock* codeBlock)
6fe7ccc8 287{
81345200 288 LLInt::setEntrypoint(vm, codeBlock);
6fe7ccc8 289}
81345200
A
290
291static void setupJIT(VM& vm, CodeBlock* codeBlock)
292{
293#if ENABLE(JIT)
294 CompilationResult result = JIT::compile(&vm, codeBlock, JITCompilationMustSucceed);
295 RELEASE_ASSERT(result == CompilationSuccessful);
296#else
297 UNUSED_PARAM(vm);
298 UNUSED_PARAM(codeBlock);
299 UNREACHABLE_FOR_PLATFORM();
6fe7ccc8 300#endif
81345200
A
301}
302
303JSObject* ScriptExecutable::prepareForExecutionImpl(
304 ExecState* exec, JSFunction* function, JSScope** scope, CodeSpecializationKind kind)
305{
306 VM& vm = exec->vm();
307 DeferGC deferGC(vm.heap);
308
309 JSObject* exception = 0;
310 RefPtr<CodeBlock> codeBlock = newCodeBlockFor(kind, function, scope, exception);
311 if (!codeBlock) {
312 RELEASE_ASSERT(exception);
313 return exception;
314 }
315
316 if (Options::validateBytecode())
317 codeBlock->validate();
318
319 if (Options::useLLInt())
320 setupLLInt(vm, codeBlock.get());
321 else
322 setupJIT(vm, codeBlock.get());
323
324 installCode(codeBlock.get());
325 return 0;
326}
6fe7ccc8
A
327
328const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(EvalExecutable) };
14957cd0 329
81345200
A
330EvalExecutable* EvalExecutable::create(ExecState* exec, const SourceCode& source, bool isInStrictContext)
331{
332 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
333 if (!globalObject->evalEnabled()) {
334 exec->vm().throwException(exec, createEvalError(exec, globalObject->evalDisabledErrorMessage()));
335 return 0;
336 }
337
338 EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext);
339 executable->finishCreation(exec->vm());
340
341 UnlinkedEvalCodeBlock* unlinkedEvalCode = globalObject->createEvalCodeBlock(exec, executable);
342 if (!unlinkedEvalCode)
343 return 0;
344
345 executable->m_unlinkedEvalCodeBlock.set(exec->vm(), executable, unlinkedEvalCode);
346
347 return executable;
348}
349
350EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
93a37866 351 : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec, source, inStrictContext)
f9bf01c6
A
352{
353}
354
6fe7ccc8 355void EvalExecutable::destroy(JSCell* cell)
f9bf01c6 356{
93a37866 357 static_cast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable();
14957cd0
A
358}
359
6fe7ccc8 360const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(ProgramExecutable) };
14957cd0
A
361
362ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
93a37866 363 : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec, source, false)
14957cd0 364{
f9bf01c6
A
365}
366
6fe7ccc8 367void ProgramExecutable::destroy(JSCell* cell)
f9bf01c6 368{
93a37866 369 static_cast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable();
f9bf01c6
A
370}
371
6fe7ccc8 372const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
14957cd0 373
81345200 374FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, bool bodyIncludesBraces)
93a37866
A
375 : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->isInStrictContext())
376 , m_unlinkedExecutable(vm, this, unlinkedExecutable)
81345200
A
377 , m_bodyIncludesBraces(bodyIncludesBraces)
378 , m_didParseForTheFirstTime(false)
6fe7ccc8 379{
93a37866
A
380 RELEASE_ASSERT(!source.isNull());
381 ASSERT(source.length());
382 m_firstLine = firstLine;
383 m_lastLine = lastLine;
81345200
A
384 ASSERT(startColumn != UINT_MAX);
385 ASSERT(endColumn != UINT_MAX);
93a37866 386 m_startColumn = startColumn;
81345200 387 m_endColumn = endColumn;
6fe7ccc8
A
388}
389
390void FunctionExecutable::destroy(JSCell* cell)
391{
93a37866 392 static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
6fe7ccc8
A
393}
394
6fe7ccc8
A
395inline const char* samplingDescription(JITCode::JITType jitType)
396{
397 switch (jitType) {
398 case JITCode::InterpreterThunk:
399 return "Interpreter Compilation (TOTAL)";
400 case JITCode::BaselineJIT:
401 return "Baseline Compilation (TOTAL)";
402 case JITCode::DFGJIT:
403 return "DFG Compilation (TOTAL)";
81345200
A
404 case JITCode::FTLJIT:
405 return "FTL Compilation (TOTAL)";
6fe7ccc8 406 default:
93a37866 407 RELEASE_ASSERT_NOT_REACHED();
6fe7ccc8
A
408 return 0;
409 }
410}
14957cd0 411
6fe7ccc8 412void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
f9bf01c6 413{
6fe7ccc8 414 EvalExecutable* thisObject = jsCast<EvalExecutable*>(cell);
81345200 415 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
14957cd0 416 COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
6fe7ccc8
A
417 ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
418 ScriptExecutable::visitChildren(thisObject, visitor);
419 if (thisObject->m_evalCodeBlock)
420 thisObject->m_evalCodeBlock->visitAggregate(visitor);
93a37866 421 visitor.append(&thisObject->m_unlinkedEvalCodeBlock);
f9bf01c6
A
422}
423
14957cd0 424void EvalExecutable::unlinkCalls()
f9bf01c6 425{
14957cd0
A
426#if ENABLE(JIT)
427 if (!m_jitCodeForCall)
428 return;
93a37866 429 RELEASE_ASSERT(m_evalCodeBlock);
14957cd0
A
430 m_evalCodeBlock->unlinkCalls();
431#endif
432}
f9bf01c6 433
93a37866 434void EvalExecutable::clearCode()
6fe7ccc8 435{
93a37866
A
436 m_evalCodeBlock.clear();
437 m_unlinkedEvalCodeBlock.clear();
6fe7ccc8
A
438 Base::clearCode();
439}
440
14957cd0
A
441JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
442{
93a37866
A
443 ParserError error;
444 VM* vm = &exec->vm();
14957cd0 445 JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
93a37866 446 RefPtr<ProgramNode> programNode = parse<ProgramNode>(vm, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, error);
14957cd0
A
447 if (programNode)
448 return 0;
93a37866
A
449 ASSERT(error.m_type != ParserError::ErrorNone);
450 return error.toErrorObject(lexicalGlobalObject, m_source);
f9bf01c6
A
451}
452
14957cd0 453void ProgramExecutable::unlinkCalls()
f9bf01c6 454{
14957cd0
A
455#if ENABLE(JIT)
456 if (!m_jitCodeForCall)
457 return;
93a37866 458 RELEASE_ASSERT(m_programCodeBlock);
14957cd0 459 m_programCodeBlock->unlinkCalls();
f9bf01c6
A
460#endif
461}
462
93a37866
A
463JSObject* ProgramExecutable::initializeGlobalProperties(VM& vm, CallFrame* callFrame, JSScope* scope)
464{
465 RELEASE_ASSERT(scope);
466 JSGlobalObject* globalObject = scope->globalObject();
467 RELEASE_ASSERT(globalObject);
468 ASSERT(&globalObject->vm() == &vm);
469
470 JSObject* exception = 0;
81345200 471 UnlinkedProgramCodeBlock* unlinkedCodeBlock = globalObject->createProgramCodeBlock(callFrame, this, &exception);
93a37866
A
472 if (exception)
473 return exception;
474
81345200 475 m_unlinkedProgramCodeBlock.set(vm, this, unlinkedCodeBlock);
93a37866
A
476
477 BatchedTransitionOptimizer optimizer(vm, globalObject);
478
81345200
A
479 const UnlinkedProgramCodeBlock::VariableDeclations& variableDeclarations = unlinkedCodeBlock->variableDeclarations();
480 const UnlinkedProgramCodeBlock::FunctionDeclations& functionDeclarations = unlinkedCodeBlock->functionDeclarations();
93a37866
A
481
482 for (size_t i = 0; i < functionDeclarations.size(); ++i) {
93a37866 483 UnlinkedFunctionExecutable* unlinkedFunctionExecutable = functionDeclarations[i].second.get();
81345200
A
484 JSValue value = JSFunction::create(vm, unlinkedFunctionExecutable->link(vm, m_source, lineNo()), scope);
485 globalObject->addFunction(callFrame, functionDeclarations[i].first, value);
93a37866
A
486 }
487
488 for (size_t i = 0; i < variableDeclarations.size(); ++i) {
81345200
A
489 if (variableDeclarations[i].second & DeclarationStacks::IsConstant)
490 globalObject->addConst(callFrame, variableDeclarations[i].first);
491 else
492 globalObject->addVar(callFrame, variableDeclarations[i].first);
93a37866
A
493 }
494 return 0;
495}
496
6fe7ccc8 497void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
f9bf01c6 498{
6fe7ccc8 499 ProgramExecutable* thisObject = jsCast<ProgramExecutable*>(cell);
81345200 500 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
6fe7ccc8
A
501 COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
502 ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
503 ScriptExecutable::visitChildren(thisObject, visitor);
93a37866 504 visitor.append(&thisObject->m_unlinkedProgramCodeBlock);
6fe7ccc8
A
505 if (thisObject->m_programCodeBlock)
506 thisObject->m_programCodeBlock->visitAggregate(visitor);
507}
f9bf01c6 508
93a37866 509void ProgramExecutable::clearCode()
6fe7ccc8 510{
93a37866
A
511 m_programCodeBlock.clear();
512 m_unlinkedProgramCodeBlock.clear();
6fe7ccc8
A
513 Base::clearCode();
514}
515
516FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
517{
518 FunctionCodeBlock* result;
519 if (kind == CodeForCall)
520 result = m_codeBlockForCall.get();
521 else {
93a37866 522 RELEASE_ASSERT(kind == CodeForConstruct);
6fe7ccc8
A
523 result = m_codeBlockForConstruct.get();
524 }
525 if (!result)
526 return 0;
81345200 527 return static_cast<FunctionCodeBlock*>(result->baselineAlternative());
6fe7ccc8 528}
6fe7ccc8
A
529
530void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
531{
532 FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell);
81345200 533 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
14957cd0 534 COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
6fe7ccc8
A
535 ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
536 ScriptExecutable::visitChildren(thisObject, visitor);
6fe7ccc8
A
537 if (thisObject->m_codeBlockForCall)
538 thisObject->m_codeBlockForCall->visitAggregate(visitor);
539 if (thisObject->m_codeBlockForConstruct)
540 thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
93a37866 541 visitor.append(&thisObject->m_unlinkedExecutable);
f9bf01c6
A
542}
543
81345200
A
544SymbolTable* FunctionExecutable::symbolTable(CodeSpecializationKind kind)
545{
546 return codeBlockFor(kind)->symbolTable();
547}
548
93a37866 549void FunctionExecutable::clearCodeIfNotCompiling()
f9bf01c6 550{
93a37866 551 if (isCompiling())
14957cd0 552 return;
6fe7ccc8
A
553 clearCode();
554}
555
93a37866 556void FunctionExecutable::clearUnlinkedCodeForRecompilationIfNotCompiling()
6fe7ccc8 557{
93a37866
A
558 if (isCompiling())
559 return;
560 m_unlinkedExecutable->clearCodeForRecompilation();
6fe7ccc8
A
561}
562
93a37866 563void FunctionExecutable::clearCode()
6fe7ccc8 564{
93a37866
A
565 m_codeBlockForCall.clear();
566 m_codeBlockForConstruct.clear();
6fe7ccc8 567 Base::clearCode();
f9bf01c6
A
568}
569
14957cd0 570void FunctionExecutable::unlinkCalls()
f9bf01c6 571{
14957cd0
A
572#if ENABLE(JIT)
573 if (!!m_jitCodeForCall) {
93a37866 574 RELEASE_ASSERT(m_codeBlockForCall);
14957cd0
A
575 m_codeBlockForCall->unlinkCalls();
576 }
577 if (!!m_jitCodeForConstruct) {
93a37866 578 RELEASE_ASSERT(m_codeBlockForConstruct);
14957cd0
A
579 m_codeBlockForConstruct->unlinkCalls();
580 }
581#endif
582}
583
93a37866 584FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
14957cd0 585{
81345200
A
586 UnlinkedFunctionExecutable* unlinkedExecutable = UnlinkedFunctionExecutable::fromGlobalCode(name, exec, debugger, source, exception);
587 if (!unlinkedExecutable)
f9bf01c6 588 return 0;
81345200
A
589 unsigned lineCount = unlinkedExecutable->lineCount();
590 unsigned firstLine = source.firstLine() + unlinkedExecutable->firstLineOffset();
591 unsigned startOffset = source.startOffset() + unlinkedExecutable->startOffset();
592
593 // We don't have any owner executable. The source string is effectively like a global
594 // string (like in the handling of eval). Hence, the startColumn is always 1.
595 unsigned startColumn = 1;
596 unsigned sourceLength = unlinkedExecutable->sourceLength();
597 bool endColumnIsOnStartLine = !lineCount;
598 // The unlinkedBodyEndColumn is based-0. Hence, we need to add 1 to it. But if the
599 // endColumn is on the startLine, then we need to subtract back the adjustment for
600 // the open brace resulting in an adjustment of 0.
601 unsigned endColumnExcludingBraces = unlinkedExecutable->unlinkedBodyEndColumn() + (endColumnIsOnStartLine ? 0 : 1);
602 unsigned startOffsetExcludingOpenBrace = startOffset + 1;
603 unsigned endOffsetExcludingCloseBrace = startOffset + sourceLength - 1;
604 SourceCode bodySource(source.provider(), startOffsetExcludingOpenBrace, endOffsetExcludingCloseBrace, firstLine, startColumn);
605
606 return FunctionExecutable::create(exec->vm(), bodySource, unlinkedExecutable, firstLine, firstLine + lineCount, startColumn, endColumnExcludingBraces, false);
93a37866 607}
f9bf01c6 608
93a37866
A
609String FunctionExecutable::paramString() const
610{
611 return m_unlinkedExecutable->paramString();
612}
14957cd0 613
81345200
A
614void ExecutableBase::dump(PrintStream& out) const
615{
616 ExecutableBase* realThis = const_cast<ExecutableBase*>(this);
617
618 if (classInfo() == NativeExecutable::info()) {
619 NativeExecutable* native = jsCast<NativeExecutable*>(realThis);
620 out.print("NativeExecutable:", RawPointer(bitwise_cast<void*>(native->function())), "/", RawPointer(bitwise_cast<void*>(native->constructor())));
621 return;
622 }
623
624 if (classInfo() == EvalExecutable::info()) {
625 EvalExecutable* eval = jsCast<EvalExecutable*>(realThis);
626 if (CodeBlock* codeBlock = eval->codeBlock())
627 out.print(*codeBlock);
628 else
629 out.print("EvalExecutable w/o CodeBlock");
630 return;
631 }
632
633 if (classInfo() == ProgramExecutable::info()) {
634 ProgramExecutable* eval = jsCast<ProgramExecutable*>(realThis);
635 if (CodeBlock* codeBlock = eval->codeBlock())
636 out.print(*codeBlock);
637 else
638 out.print("ProgramExecutable w/o CodeBlock");
639 return;
640 }
641
642 FunctionExecutable* function = jsCast<FunctionExecutable*>(realThis);
643 if (!function->eitherCodeBlock())
644 out.print("FunctionExecutable w/o CodeBlock");
645 else {
646 CommaPrinter comma("/");
647 if (function->codeBlockForCall())
648 out.print(comma, *function->codeBlockForCall());
649 if (function->codeBlockForConstruct())
650 out.print(comma, *function->codeBlockForConstruct());
651 }
652}
653
93a37866
A
654CodeBlockHash ExecutableBase::hashFor(CodeSpecializationKind kind) const
655{
81345200 656 if (this->classInfo() == NativeExecutable::info())
93a37866
A
657 return jsCast<const NativeExecutable*>(this)->hashFor(kind);
658
659 return jsCast<const ScriptExecutable*>(this)->hashFor(kind);
f9bf01c6
A
660}
661
93a37866 662CodeBlockHash NativeExecutable::hashFor(CodeSpecializationKind kind) const
f9bf01c6 663{
93a37866
A
664 if (kind == CodeForCall)
665 return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_function)));
666
667 RELEASE_ASSERT(kind == CodeForConstruct);
668 return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_constructor)));
669}
670
671CodeBlockHash ScriptExecutable::hashFor(CodeSpecializationKind kind) const
672{
673 return CodeBlockHash(source(), kind);
f9bf01c6
A
674}
675
14957cd0 676}