]> git.saurik.com Git - apple/javascriptcore.git/blame - interpreter/Interpreter.cpp
JavaScriptCore-7600.1.4.9.tar.gz
[apple/javascriptcore.git] / interpreter / Interpreter.cpp
CommitLineData
9dae56ea 1/*
81345200 2 * Copyright (C) 2008, 2009, 2010, 2012, 2013, 2014 Apple Inc. All rights reserved.
9dae56ea
A
3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
81345200 14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
9dae56ea
A
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include "config.h"
31#include "Interpreter.h"
32
33#include "Arguments.h"
34#include "BatchedTransitionOptimizer.h"
ba379fdc 35#include "CallFrameClosure.h"
81345200 36#include "CallFrameInlines.h"
9dae56ea 37#include "CodeBlock.h"
14957cd0 38#include "Heap.h"
ba379fdc 39#include "Debugger.h"
9dae56ea 40#include "DebuggerCallFrame.h"
14957cd0 41#include "ErrorInstance.h"
9dae56ea
A
42#include "EvalCodeCache.h"
43#include "ExceptionHelpers.h"
4e4e5a6f 44#include "GetterSetter.h"
9dae56ea
A
45#include "JSActivation.h"
46#include "JSArray.h"
6fe7ccc8 47#include "JSBoundFunction.h"
93a37866 48#include "JSNameScope.h"
9dae56ea
A
49#include "JSNotAnObject.h"
50#include "JSPropertyNameIterator.h"
93a37866 51#include "JSStackInlines.h"
9dae56ea 52#include "JSString.h"
93a37866
A
53#include "JSWithScope.h"
54#include "LLIntCLoop.h"
81345200 55#include "LLIntThunks.h"
93a37866
A
56#include "LegacyProfiler.h"
57#include "LiteralParser.h"
58#include "NameInstance.h"
9dae56ea 59#include "ObjectPrototype.h"
81345200 60#include "JSCInlines.h"
9dae56ea 61#include "Parser.h"
81345200 62#include "ProtoCallFrame.h"
9dae56ea
A
63#include "RegExpObject.h"
64#include "RegExpPrototype.h"
65#include "Register.h"
9dae56ea 66#include "SamplingTool.h"
81345200
A
67#include "StackAlignment.h"
68#include "StackVisitor.h"
14957cd0 69#include "StrictEvalActivation.h"
6fe7ccc8 70#include "StrongInlines.h"
81345200
A
71#include "VMEntryScope.h"
72#include "VirtualRegister.h"
73
f9bf01c6 74#include <limits.h>
9dae56ea 75#include <stdio.h>
93a37866 76#include <wtf/StackStats.h>
81345200 77#include <wtf/StdLibExtras.h>
93a37866 78#include <wtf/StringPrintStream.h>
ba379fdc 79#include <wtf/Threading.h>
93a37866 80#include <wtf/WTFThreadData.h>
6fe7ccc8 81#include <wtf/text/StringBuilder.h>
9dae56ea
A
82
83#if ENABLE(JIT)
84#include "JIT.h"
85#endif
86
81345200 87#define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND (!defined(__llvm__))
4e4e5a6f 88
9dae56ea
A
89using namespace std;
90
91namespace JSC {
9dae56ea 92
6fe7ccc8 93JSValue eval(CallFrame* callFrame)
9dae56ea 94{
6fe7ccc8 95 if (!callFrame->argumentCount())
9dae56ea
A
96 return jsUndefined();
97
6fe7ccc8 98 JSValue program = callFrame->argument(0);
9dae56ea
A
99 if (!program.isString())
100 return program;
6fe7ccc8 101
93a37866
A
102 TopCallFrameSetter topCallFrame(callFrame->vm(), callFrame);
103 String programSource = asString(program)->value(callFrame);
4e4e5a6f
A
104 if (callFrame->hadException())
105 return JSValue();
14957cd0 106
6fe7ccc8
A
107 CallFrame* callerFrame = callFrame->callerFrame();
108 CodeBlock* callerCodeBlock = callerFrame->codeBlock();
93a37866 109 JSScope* callerScopeChain = callerFrame->scope();
6fe7ccc8
A
110 EvalExecutable* eval = callerCodeBlock->evalCodeCache().tryGet(callerCodeBlock->isStrictMode(), programSource, callerScopeChain);
111
112 if (!eval) {
113 if (!callerCodeBlock->isStrictMode()) {
114 // FIXME: We can use the preparser in strict mode, we just need additional logic
115 // to prevent duplicates.
116 if (programSource.is8Bit()) {
117 LiteralParser<LChar> preparser(callFrame, programSource.characters8(), programSource.length(), NonStrictJSON);
118 if (JSValue parsedObject = preparser.tryLiteralParse())
119 return parsedObject;
120 } else {
121 LiteralParser<UChar> preparser(callFrame, programSource.characters16(), programSource.length(), NonStrictJSON);
122 if (JSValue parsedObject = preparser.tryLiteralParse())
123 return parsedObject;
124 }
125 }
93a37866
A
126
127 // If the literal parser bailed, it should not have thrown exceptions.
81345200 128 ASSERT(!callFrame->vm().exception());
6fe7ccc8 129
81345200
A
130 eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock->ownerExecutable(), callerCodeBlock->isStrictMode(), programSource, callerScopeChain);
131 if (!eval)
132 return jsUndefined();
14957cd0 133 }
f9bf01c6 134
6fe7ccc8 135 JSValue thisValue = callerFrame->thisValue();
93a37866
A
136 Interpreter* interpreter = callFrame->vm().interpreter;
137 return interpreter->execute(eval, callFrame, thisValue, callerScopeChain);
6fe7ccc8
A
138}
139
81345200 140CallFrame* sizeFrameForVarargs(CallFrame* callFrame, JSStack* stack, JSValue arguments, int firstFreeRegister, uint32_t firstVarArgOffset)
6fe7ccc8
A
141{
142 if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
143 unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
81345200
A
144 if (argumentCountIncludingThis > firstVarArgOffset)
145 argumentCountIncludingThis -= firstVarArgOffset;
146 else
147 argumentCountIncludingThis = 1;
148 unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister + argumentCountIncludingThis + JSStack::CallFrameHeaderSize + 1);
149 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
150 if (argumentCountIncludingThis > Arguments::MaxArguments + 1 || !stack->ensureCapacityFor(newCallFrame->registers())) {
151 throwStackOverflowError(callFrame);
6fe7ccc8
A
152 return 0;
153 }
6fe7ccc8
A
154 return newCallFrame;
155 }
156
157 if (arguments.isUndefinedOrNull()) {
81345200
A
158 unsigned argumentCountIncludingThis = 1;
159 unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister + argumentCountIncludingThis + JSStack::CallFrameHeaderSize + 1);
160 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
161 if (!stack->ensureCapacityFor(newCallFrame->registers())) {
162 throwStackOverflowError(callFrame);
6fe7ccc8
A
163 return 0;
164 }
6fe7ccc8
A
165 return newCallFrame;
166 }
167
168 if (!arguments.isObject()) {
81345200 169 callFrame->vm().throwException(callFrame, createInvalidParameterError(callFrame, "Function.prototype.apply", arguments));
6fe7ccc8
A
170 return 0;
171 }
9dae56ea 172
81345200 173 if (asObject(arguments)->classInfo() == Arguments::info()) {
6fe7ccc8
A
174 Arguments* argsObject = asArguments(arguments);
175 unsigned argCount = argsObject->length(callFrame);
81345200
A
176 if (argCount >= firstVarArgOffset)
177 argCount -= firstVarArgOffset;
178 else
179 argCount = 0;
180 unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister + CallFrame::offsetFor(argCount + 1));
181 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
182 if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
183 throwStackOverflowError(callFrame);
6fe7ccc8
A
184 return 0;
185 }
6fe7ccc8
A
186 return newCallFrame;
187 }
188
189 if (isJSArray(arguments)) {
190 JSArray* array = asArray(arguments);
191 unsigned argCount = array->length();
81345200
A
192 if (argCount >= firstVarArgOffset)
193 argCount -= firstVarArgOffset;
194 else
195 argCount = 0;
196 unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister + CallFrame::offsetFor(argCount + 1));
197 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
198 if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
199 throwStackOverflowError(callFrame);
6fe7ccc8
A
200 return 0;
201 }
6fe7ccc8
A
202 return newCallFrame;
203 }
9dae56ea 204
6fe7ccc8
A
205 JSObject* argObject = asObject(arguments);
206 unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
81345200
A
207 if (argCount >= firstVarArgOffset)
208 argCount -= firstVarArgOffset;
209 else
210 argCount = 0;
211 unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister + CallFrame::offsetFor(argCount + 1));
212 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
213 if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
214 throwStackOverflowError(callFrame);
6fe7ccc8
A
215 return 0;
216 }
81345200
A
217 return newCallFrame;
218}
219
220void loadVarargs(CallFrame* callFrame, CallFrame* newCallFrame, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset)
221{
222 if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
223 unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
224 if (argumentCountIncludingThis > firstVarArgOffset)
225 argumentCountIncludingThis -= firstVarArgOffset;
226 else
227 argumentCountIncludingThis = 1;
228 newCallFrame->setArgumentCountIncludingThis(argumentCountIncludingThis);
229 newCallFrame->setThisValue(thisValue);
230 for (size_t i = firstVarArgOffset; i < callFrame->argumentCount(); ++i)
231 newCallFrame->setArgument(i - firstVarArgOffset, callFrame->argumentAfterCapture(i));
232 return;
233 }
234
235 if (arguments.isUndefinedOrNull()) {
236 newCallFrame->setArgumentCountIncludingThis(1);
237 newCallFrame->setThisValue(thisValue);
238 return;
239 }
240
241 if (asObject(arguments)->classInfo() == Arguments::info()) {
242 Arguments* argsObject = asArguments(arguments);
243 unsigned argCount = argsObject->length(callFrame);
244 if (argCount >= firstVarArgOffset) {
245 argCount -= firstVarArgOffset;
246 newCallFrame->setArgumentCountIncludingThis(argCount + 1);
247 argsObject->copyToArguments(callFrame, newCallFrame, argCount, firstVarArgOffset);
248 } else
249 newCallFrame->setArgumentCountIncludingThis(1);
250 newCallFrame->setThisValue(thisValue);
251 return;
252 }
253
254 if (isJSArray(arguments)) {
255 JSArray* array = asArray(arguments);
256 unsigned argCount = array->length();
257 if (argCount >= firstVarArgOffset) {
258 argCount -= firstVarArgOffset;
259 newCallFrame->setArgumentCountIncludingThis(argCount + 1);
260 array->copyToArguments(callFrame, newCallFrame, argCount, firstVarArgOffset);
261 } else
262 newCallFrame->setArgumentCountIncludingThis(1);
263 newCallFrame->setThisValue(thisValue);
264 return;
265 }
266
267 JSObject* argObject = asObject(arguments);
268 unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
269 if (argCount >= firstVarArgOffset) {
270 argCount -= firstVarArgOffset;
271 newCallFrame->setArgumentCountIncludingThis(argCount + 1);
272 } else
273 newCallFrame->setArgumentCountIncludingThis(1);
274
6fe7ccc8
A
275 newCallFrame->setThisValue(thisValue);
276 for (size_t i = 0; i < argCount; ++i) {
81345200
A
277 newCallFrame->setArgument(i, asObject(arguments)->get(callFrame, i + firstVarArgOffset));
278 if (UNLIKELY(callFrame->vm().exception()))
279 return;
6fe7ccc8 280 }
9dae56ea
A
281}
282
93a37866 283Interpreter::Interpreter(VM& vm)
f9bf01c6 284 : m_sampleEntryDepth(0)
81345200 285 , m_vm(vm)
93a37866
A
286 , m_stack(vm)
287 , m_errorHandlingModeReentry(0)
6fe7ccc8
A
288#if !ASSERT_DISABLED
289 , m_initialized(false)
290#endif
9dae56ea 291{
6fe7ccc8
A
292}
293
294Interpreter::~Interpreter()
295{
6fe7ccc8
A
296}
297
93a37866 298void Interpreter::initialize(bool canUseJIT)
6fe7ccc8 299{
6fe7ccc8
A
300 UNUSED_PARAM(canUseJIT);
301
81345200 302#if ENABLE(COMPUTED_GOTO_OPCODES)
93a37866 303 m_opcodeTable = LLInt::opcodeMap();
ba379fdc
A
304 for (int i = 0; i < numOpcodeIDs; ++i)
305 m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
6fe7ccc8 306#endif
93a37866 307
6fe7ccc8
A
308#if !ASSERT_DISABLED
309 m_initialized = true;
310#endif
f9bf01c6
A
311
312#if ENABLE(OPCODE_SAMPLING)
313 enableSampler();
314#endif
9dae56ea
A
315}
316
93a37866
A
317#ifdef NDEBUG
318
319void Interpreter::dumpCallFrame(CallFrame*)
320{
321}
322
323#else
9dae56ea
A
324
325void Interpreter::dumpCallFrame(CallFrame* callFrame)
326{
93a37866 327 callFrame->codeBlock()->dumpBytecode();
9dae56ea
A
328 dumpRegisters(callFrame);
329}
330
81345200
A
331class DumpRegisterFunctor {
332public:
333 DumpRegisterFunctor(const Register*& it)
334 : m_hasSkippedFirstFrame(false)
335 , m_it(it)
336 {
337 }
338
339 StackVisitor::Status operator()(StackVisitor& visitor)
340 {
341 if (!m_hasSkippedFirstFrame) {
342 m_hasSkippedFirstFrame = true;
343 return StackVisitor::Continue;
344 }
345
346 unsigned line = 0;
347 unsigned unusedColumn = 0;
348 visitor->computeLineAndColumn(line, unusedColumn);
349 dataLogF("[ReturnVPC] | %10p | %d (line %d)\n", m_it, visitor->bytecodeOffset(), line);
350 --m_it;
351 return StackVisitor::Done;
352 }
353
354private:
355 bool m_hasSkippedFirstFrame;
356 const Register*& m_it;
357};
358
9dae56ea
A
359void Interpreter::dumpRegisters(CallFrame* callFrame)
360{
93a37866
A
361 dataLogF("Register frame: \n\n");
362 dataLogF("-----------------------------------------------------------------------------\n");
363 dataLogF(" use | address | value \n");
364 dataLogF("-----------------------------------------------------------------------------\n");
9dae56ea
A
365
366 CodeBlock* codeBlock = callFrame->codeBlock();
9dae56ea
A
367 const Register* it;
368 const Register* end;
369
81345200
A
370 it = callFrame->registers() + JSStack::ThisArgument + callFrame->argumentCount();
371 end = callFrame->registers() + JSStack::ThisArgument - 1;
372 while (it > end) {
93a37866
A
373 JSValue v = it->jsValue();
374 int registerNumber = it - callFrame->registers();
81345200 375 String name = codeBlock->nameForRegister(VirtualRegister(registerNumber));
93a37866 376 dataLogF("[r% 3d %14s] | %10p | %-16s 0x%lld \n", registerNumber, name.ascii().data(), it, toCString(v).data(), (long long)JSValue::encode(v));
81345200 377 --it;
9dae56ea 378 }
93a37866
A
379
380 dataLogF("-----------------------------------------------------------------------------\n");
381 dataLogF("[ArgumentCount] | %10p | %lu \n", it, (unsigned long) callFrame->argumentCount());
81345200 382 --it;
93a37866 383 dataLogF("[CallerFrame] | %10p | %p \n", it, callFrame->callerFrame());
81345200 384 --it;
93a37866 385 dataLogF("[Callee] | %10p | %p \n", it, callFrame->callee());
81345200 386 --it;
93a37866 387 dataLogF("[ScopeChain] | %10p | %p \n", it, callFrame->scope());
81345200 388 --it;
93a37866
A
389#if ENABLE(JIT)
390 AbstractPC pc = callFrame->abstractReturnPC(callFrame->vm());
391 if (pc.hasJITReturnAddress())
392 dataLogF("[ReturnJITPC] | %10p | %p \n", it, pc.jitReturnAddress().value());
393#endif
81345200
A
394
395 DumpRegisterFunctor functor(it);
396 callFrame->iterate(functor);
397
93a37866 398 dataLogF("[CodeBlock] | %10p | %p \n", it, callFrame->codeBlock());
81345200 399 --it;
93a37866 400 dataLogF("-----------------------------------------------------------------------------\n");
9dae56ea 401
81345200 402 end = it - codeBlock->m_numVars;
9dae56ea
A
403 if (it != end) {
404 do {
93a37866
A
405 JSValue v = it->jsValue();
406 int registerNumber = it - callFrame->registers();
81345200 407 String name = codeBlock->nameForRegister(VirtualRegister(registerNumber));
93a37866 408 dataLogF("[r% 3d %14s] | %10p | %-16s 0x%lld \n", registerNumber, name.ascii().data(), it, toCString(v).data(), (long long)JSValue::encode(v));
81345200 409 --it;
9dae56ea
A
410 } while (it != end);
411 }
93a37866 412 dataLogF("-----------------------------------------------------------------------------\n");
9dae56ea 413
81345200 414 end = it - codeBlock->m_numCalleeRegisters + codeBlock->m_numVars;
9dae56ea
A
415 if (it != end) {
416 do {
93a37866 417 JSValue v = (*it).jsValue();
81345200
A
418 int registerNumber = it - callFrame->registers();
419 dataLogF("[r% 3d] | %10p | %-16s 0x%lld \n", registerNumber, it, toCString(v).data(), (long long)JSValue::encode(v));
420 --it;
9dae56ea
A
421 } while (it != end);
422 }
93a37866 423 dataLogF("-----------------------------------------------------------------------------\n");
9dae56ea
A
424}
425
426#endif
427
428bool Interpreter::isOpcode(Opcode opcode)
429{
93a37866 430#if ENABLE(COMPUTED_GOTO_OPCODES)
9dae56ea
A
431 return opcode != HashTraits<Opcode>::emptyValue()
432 && !HashTraits<Opcode>::isDeletedValue(opcode)
433 && m_opcodeIDTable.contains(opcode);
434#else
435 return opcode >= 0 && opcode <= op_end;
436#endif
437}
438
81345200 439static bool unwindCallFrame(StackVisitor& visitor)
9dae56ea 440{
81345200
A
441 CallFrame* callFrame = visitor->callFrame();
442 CodeBlock* codeBlock = visitor->codeBlock();
93a37866 443 JSScope* scope = callFrame->scope();
9dae56ea 444
81345200
A
445 if (Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger()) {
446 ClearExceptionScope scope(&callFrame->vm());
9dae56ea 447 if (callFrame->callee())
81345200 448 debugger->returnEvent(callFrame);
9dae56ea 449 else
81345200
A
450 debugger->didExecuteProgram(callFrame);
451 ASSERT(!callFrame->hadException());
93a37866
A
452 }
453
454 JSValue activation;
81345200 455 if (codeBlock->codeType() == FunctionCode && codeBlock->needsActivation()) {
6fe7ccc8 456#if ENABLE(DFG_JIT)
81345200 457 RELEASE_ASSERT(!visitor->isInlinedFrame());
6fe7ccc8 458#endif
81345200
A
459 activation = callFrame->uncheckedActivation();
460 // Protect against the activation not being created, or the variable still being
461 // initialized to Undefined inside op_enter.
462 if (activation && activation.isCell()) {
463 JSActivation* activationObject = jsCast<JSActivation*>(activation);
464 // Protect against throwing exceptions after tear-off.
465 if (!activationObject->isTornOff())
466 activationObject->tearOff(*scope->vm());
467 }
93a37866 468 }
6fe7ccc8 469
81345200
A
470 if (codeBlock->codeType() == FunctionCode && codeBlock->usesArguments()) {
471 if (Arguments* arguments = visitor->existingArguments()) {
472 if (activation && activation.isCell())
473 arguments->didTearOffActivation(callFrame, jsCast<JSActivation*>(activation));
6fe7ccc8 474#if ENABLE(DFG_JIT)
81345200
A
475 else if (visitor->isInlinedFrame())
476 arguments->tearOff(callFrame, visitor->inlineCallFrame());
6fe7ccc8 477#endif
81345200
A
478 else
479 arguments->tearOff(callFrame);
93a37866 480 }
6fe7ccc8
A
481 }
482
81345200
A
483 CallFrame* callerFrame = callFrame->callerFrame();
484 return !callerFrame->isVMEntrySentinel();
6fe7ccc8
A
485}
486
81345200 487static StackFrameCodeType getStackFrameCodeType(StackVisitor& visitor)
6fe7ccc8 488{
81345200
A
489 switch (visitor->codeType()) {
490 case StackVisitor::Frame::Eval:
6fe7ccc8 491 return StackFrameEvalCode;
81345200 492 case StackVisitor::Frame::Function:
6fe7ccc8 493 return StackFrameFunctionCode;
81345200 494 case StackVisitor::Frame::Global:
6fe7ccc8 495 return StackFrameGlobalCode;
81345200
A
496 case StackVisitor::Frame::Native:
497 ASSERT_NOT_REACHED();
498 return StackFrameNativeCode;
6fe7ccc8 499 }
93a37866 500 RELEASE_ASSERT_NOT_REACHED();
6fe7ccc8
A
501 return StackFrameGlobalCode;
502}
503
93a37866 504void StackFrame::computeLineAndColumn(unsigned& line, unsigned& column)
6fe7ccc8 505{
93a37866
A
506 if (!codeBlock) {
507 line = 0;
508 column = 0;
6fe7ccc8 509 return;
93a37866
A
510 }
511
512 int divot = 0;
513 int unusedStartOffset = 0;
514 int unusedEndOffset = 0;
515 unsigned divotLine = 0;
516 unsigned divotColumn = 0;
517 expressionInfo(divot, unusedStartOffset, unusedEndOffset, divotLine, divotColumn);
518
519 line = divotLine + lineOffset;
520 column = divotColumn + (divotLine ? 1 : firstLineColumnOffset);
521}
522
523void StackFrame::expressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column)
524{
525 codeBlock->expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column);
526 divot += characterOffset;
527}
528
529String StackFrame::toString(CallFrame* callFrame)
530{
531 StringBuilder traceBuild;
532 String functionName = friendlyFunctionName(callFrame);
533 String sourceURL = friendlySourceURL();
534 traceBuild.append(functionName);
535 if (!sourceURL.isEmpty()) {
536 if (!functionName.isEmpty())
537 traceBuild.append('@');
538 traceBuild.append(sourceURL);
539 if (codeType != StackFrameNativeCode) {
540 unsigned line;
541 unsigned column;
542 computeLineAndColumn(line, column);
543
544 traceBuild.append(':');
545 traceBuild.appendNumber(line);
546 traceBuild.append(':');
547 traceBuild.appendNumber(column);
548 }
549 }
550 return traceBuild.toString().impl();
551}
6fe7ccc8 552
81345200
A
553class GetStackTraceFunctor {
554public:
555 GetStackTraceFunctor(VM& vm, Vector<StackFrame>& results, size_t remainingCapacity)
556 : m_vm(vm)
557 , m_results(results)
558 , m_remainingCapacityForFrameCapture(remainingCapacity)
559 {
560 }
561
562 StackVisitor::Status operator()(StackVisitor& visitor)
563 {
564 VM& vm = m_vm;
565 if (m_remainingCapacityForFrameCapture) {
566 if (visitor->isJSFrame() && !visitor->codeBlock()->unlinkedCodeBlock()->isBuiltinFunction()) {
567 CodeBlock* codeBlock = visitor->codeBlock();
568 StackFrame s = {
569 Strong<JSObject>(vm, visitor->callee()),
570 getStackFrameCodeType(visitor),
571 Strong<ExecutableBase>(vm, codeBlock->ownerExecutable()),
572 Strong<UnlinkedCodeBlock>(vm, codeBlock->unlinkedCodeBlock()),
573 codeBlock->source(),
574 codeBlock->ownerExecutable()->lineNo(),
575 codeBlock->firstLineColumnOffset(),
576 codeBlock->sourceOffset(),
577 visitor->bytecodeOffset(),
578 visitor->sourceURL()
579 };
580 m_results.append(s);
581 } else {
582 StackFrame s = { Strong<JSObject>(vm, visitor->callee()), StackFrameNativeCode, Strong<ExecutableBase>(), Strong<UnlinkedCodeBlock>(), 0, 0, 0, 0, 0, String()};
583 m_results.append(s);
584 }
585
586 m_remainingCapacityForFrameCapture--;
587 return StackVisitor::Continue;
6fe7ccc8 588 }
81345200 589 return StackVisitor::Done;
6fe7ccc8 590 }
6fe7ccc8 591
81345200
A
592private:
593 VM& m_vm;
594 Vector<StackFrame>& m_results;
595 size_t m_remainingCapacityForFrameCapture;
596};
6fe7ccc8 597
81345200
A
598void Interpreter::getStackTrace(Vector<StackFrame>& results, size_t maxStackSize)
599{
600 VM& vm = m_vm;
601 ASSERT(!vm.topCallFrame->isVMEntrySentinel());
602 CallFrame* callFrame = vm.topCallFrame;
603 if (!callFrame)
6fe7ccc8 604 return;
93a37866 605
81345200
A
606 GetStackTraceFunctor functor(vm, results, maxStackSize);
607 callFrame->iterate(functor);
608}
93a37866 609
81345200
A
610JSString* Interpreter::stackTraceAsString(ExecState* exec, Vector<StackFrame> stackTrace)
611{
93a37866 612 // FIXME: JSStringJoiner could be more efficient than StringBuilder here.
6fe7ccc8
A
613 StringBuilder builder;
614 for (unsigned i = 0; i < stackTrace.size(); i++) {
81345200 615 builder.append(String(stackTrace[i].toString(exec)));
6fe7ccc8
A
616 if (i != stackTrace.size() - 1)
617 builder.append('\n');
618 }
81345200 619 return jsString(&exec->vm(), builder.toString());
6fe7ccc8
A
620}
621
81345200
A
622class GetExceptionHandlerFunctor {
623public:
624 GetExceptionHandlerFunctor()
625 : m_handler(0)
626 {
627 }
628
629 HandlerInfo* handler() { return m_handler; }
630
631 StackVisitor::Status operator()(StackVisitor& visitor)
632 {
633 CodeBlock* codeBlock = visitor->codeBlock();
634 if (!codeBlock)
635 return StackVisitor::Continue;
636
637 unsigned bytecodeOffset = visitor->bytecodeOffset();
638 m_handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset);
639 if (m_handler)
640 return StackVisitor::Done;
641
642 return StackVisitor::Continue;
643 }
644
645private:
646 HandlerInfo* m_handler;
647};
648
649class UnwindFunctor {
650public:
651 UnwindFunctor(CallFrame*& callFrame, bool isTermination, CodeBlock*& codeBlock, HandlerInfo*& handler)
652 : m_callFrame(callFrame)
653 , m_isTermination(isTermination)
654 , m_codeBlock(codeBlock)
655 , m_handler(handler)
656 {
657 }
658
659 StackVisitor::Status operator()(StackVisitor& visitor)
660 {
661 VM& vm = m_callFrame->vm();
662 m_callFrame = visitor->callFrame();
663 m_codeBlock = visitor->codeBlock();
664 unsigned bytecodeOffset = visitor->bytecodeOffset();
665
666 if (m_isTermination || !(m_handler = m_codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
667 if (!unwindCallFrame(visitor)) {
668 if (LegacyProfiler* profiler = vm.enabledProfiler())
669 profiler->exceptionUnwind(m_callFrame);
670 return StackVisitor::Done;
671 }
672 } else
673 return StackVisitor::Done;
674
675 return StackVisitor::Continue;
676 }
677
678private:
679 CallFrame*& m_callFrame;
680 bool m_isTermination;
681 CodeBlock*& m_codeBlock;
682 HandlerInfo*& m_handler;
683};
684
685NEVER_INLINE HandlerInfo* Interpreter::unwind(CallFrame*& callFrame, JSValue& exceptionValue)
14957cd0 686{
81345200
A
687 if (callFrame->isVMEntrySentinel()) {
688 // This happens when we throw stack overflow in a function that is called
689 // directly from callToJavaScript. Stack overflow throws the exception in the
690 // context of the caller. In that case the caller is the sentinel frame. The
691 // right thing to do is to pretend that the exception is uncaught so that we
692 // go to the uncaught exception handler, which returns through callToJavaScript.
693 return 0;
694 }
695
9dae56ea 696 CodeBlock* codeBlock = callFrame->codeBlock();
81345200 697 ASSERT(codeBlock);
93a37866 698 bool isTermination = false;
14957cd0 699
6fe7ccc8
A
700 ASSERT(!exceptionValue.isEmpty());
701 ASSERT(!exceptionValue.isCell() || exceptionValue.asCell());
702 // This shouldn't be possible (hence the assertions), but we're already in the slowest of
703 // slow cases, so let's harden against it anyway to be safe.
704 if (exceptionValue.isEmpty() || (exceptionValue.isCell() && !exceptionValue.asCell()))
705 exceptionValue = jsNull();
706
81345200
A
707 if (exceptionValue.isObject())
708 isTermination = isTerminatedExecutionException(asObject(exceptionValue));
709
710 ASSERT(callFrame->vm().exceptionStack().size());
711
712 Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger();
713 if (debugger && debugger->needsExceptionCallbacks()) {
714 // We need to clear the exception and the exception stack here in order to see if a new exception happens.
715 // Afterwards, the values are put back to continue processing this error.
716 ClearExceptionScope scope(&callFrame->vm());
717 // This code assumes that if the debugger is enabled then there is no inlining.
718 // If that assumption turns out to be false then we'll ignore the inlined call
719 // frames.
720 // https://bugs.webkit.org/show_bug.cgi?id=121754
721
722 bool hasHandler;
723 if (isTermination)
724 hasHandler = false;
725 else {
726 GetExceptionHandlerFunctor functor;
727 callFrame->iterate(functor);
728 hasHandler = !!functor.handler();
93a37866 729 }
9dae56ea 730
81345200
A
731 debugger->exception(callFrame, exceptionValue, hasHandler);
732 ASSERT(!callFrame->hadException());
9dae56ea
A
733 }
734
735 // Calculate an exception handler vPC, unwinding call frames as necessary.
9dae56ea 736 HandlerInfo* handler = 0;
81345200
A
737 VM& vm = callFrame->vm();
738 ASSERT(callFrame == vm.topCallFrame);
739 UnwindFunctor functor(callFrame, isTermination, codeBlock, handler);
740 callFrame->iterate(functor);
741 if (!handler)
742 return 0;
9dae56ea 743
81345200 744 if (LegacyProfiler* profiler = vm.enabledProfiler())
14957cd0 745 profiler->exceptionUnwind(callFrame);
9dae56ea 746
14957cd0 747 // Unwind the scope chain within the exception handler's call frame.
81345200
A
748 int targetScopeDepth = handler->scopeDepth;
749 if (codeBlock->needsActivation() && callFrame->hasActivation())
750 ++targetScopeDepth;
751
93a37866 752 JSScope* scope = callFrame->scope();
81345200
A
753 int scopeDelta = scope->depth() - targetScopeDepth;
754 RELEASE_ASSERT(scopeDelta >= 0);
755
9dae56ea 756 while (scopeDelta--)
93a37866
A
757 scope = scope->next();
758 callFrame->setScope(scope);
9dae56ea
A
759
760 return handler;
761}
762
14957cd0
A
763static inline JSValue checkedReturn(JSValue returnValue)
764{
765 ASSERT(returnValue);
766 return returnValue;
767}
768
769static inline JSObject* checkedReturn(JSObject* returnValue)
770{
771 ASSERT(returnValue);
772 return returnValue;
773}
774
93a37866
A
775class SamplingScope {
776public:
777 SamplingScope(Interpreter* interpreter)
778 : m_interpreter(interpreter)
779 {
780 interpreter->startSampling();
781 }
782 ~SamplingScope()
783 {
784 m_interpreter->stopSampling();
785 }
786private:
787 Interpreter* m_interpreter;
788};
789
790JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, JSObject* thisObj)
9dae56ea 791{
93a37866
A
792 SamplingScope samplingScope(this);
793
794 JSScope* scope = callFrame->scope();
795 VM& vm = *scope->vm();
796
81345200 797 ASSERT(!vm.exception());
93a37866 798 ASSERT(!vm.isCollectorBusy());
81345200 799 RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
93a37866
A
800 if (vm.isCollectorBusy())
801 return jsNull();
9dae56ea 802
81345200 803 if (!vm.isSafeToRecurse())
14957cd0
A
804 return checkedReturn(throwStackOverflowError(callFrame));
805
93a37866
A
806 // First check if the "program" is actually just a JSON object. If so,
807 // we'll handle the JSON object here. Else, we'll handle real JS code
808 // below at failedJSONP.
81345200 809
6fe7ccc8
A
810 Vector<JSONPData> JSONPData;
811 bool parseResult;
93a37866 812 const String programSource = program->source().toString();
6fe7ccc8
A
813 if (programSource.isNull())
814 return jsUndefined();
815 if (programSource.is8Bit()) {
816 LiteralParser<LChar> literalParser(callFrame, programSource.characters8(), programSource.length(), JSONP);
93a37866 817 parseResult = literalParser.tryJSONPParse(JSONPData, scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()));
6fe7ccc8
A
818 } else {
819 LiteralParser<UChar> literalParser(callFrame, programSource.characters16(), programSource.length(), JSONP);
93a37866 820 parseResult = literalParser.tryJSONPParse(JSONPData, scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()));
6fe7ccc8
A
821 }
822
823 if (parseResult) {
93a37866 824 JSGlobalObject* globalObject = scope->globalObject();
14957cd0
A
825 JSValue result;
826 for (unsigned entry = 0; entry < JSONPData.size(); entry++) {
6fe7ccc8 827 Vector<JSONPPathEntry> JSONPPath;
14957cd0
A
828 JSONPPath.swap(JSONPData[entry].m_path);
829 JSValue JSONPValue = JSONPData[entry].m_value.get();
6fe7ccc8 830 if (JSONPPath.size() == 1 && JSONPPath[0].m_type == JSONPPathEntryTypeDeclare) {
81345200
A
831 globalObject->addVar(callFrame, JSONPPath[0].m_pathEntryName);
832 PutPropertySlot slot(globalObject);
833 globalObject->methodTable()->put(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, slot);
14957cd0
A
834 result = jsUndefined();
835 continue;
836 }
837 JSValue baseObject(globalObject);
838 for (unsigned i = 0; i < JSONPPath.size() - 1; i++) {
6fe7ccc8 839 ASSERT(JSONPPath[i].m_type != JSONPPathEntryTypeDeclare);
14957cd0 840 switch (JSONPPath[i].m_type) {
6fe7ccc8 841 case JSONPPathEntryTypeDot: {
14957cd0
A
842 if (i == 0) {
843 PropertySlot slot(globalObject);
844 if (!globalObject->getPropertySlot(callFrame, JSONPPath[i].m_pathEntryName, slot)) {
845 if (entry)
81345200 846 return callFrame->vm().throwException(callFrame, createUndefinedVariableError(globalObject->globalExec(), JSONPPath[i].m_pathEntryName));
14957cd0
A
847 goto failedJSONP;
848 }
849 baseObject = slot.getValue(callFrame, JSONPPath[i].m_pathEntryName);
850 } else
851 baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathEntryName);
852 if (callFrame->hadException())
853 return jsUndefined();
854 continue;
855 }
6fe7ccc8 856 case JSONPPathEntryTypeLookup: {
14957cd0
A
857 baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathIndex);
858 if (callFrame->hadException())
859 return jsUndefined();
860 continue;
861 }
862 default:
93a37866 863 RELEASE_ASSERT_NOT_REACHED();
14957cd0
A
864 return jsUndefined();
865 }
866 }
81345200 867 PutPropertySlot slot(baseObject);
14957cd0 868 switch (JSONPPath.last().m_type) {
6fe7ccc8 869 case JSONPPathEntryTypeCall: {
14957cd0
A
870 JSValue function = baseObject.get(callFrame, JSONPPath.last().m_pathEntryName);
871 if (callFrame->hadException())
872 return jsUndefined();
873 CallData callData;
874 CallType callType = getCallData(function, callData);
875 if (callType == CallTypeNone)
81345200 876 return callFrame->vm().throwException(callFrame, createNotAFunctionError(callFrame, function));
14957cd0
A
877 MarkedArgumentBuffer jsonArg;
878 jsonArg.append(JSONPValue);
879 JSValue thisValue = JSONPPath.size() == 1 ? jsUndefined(): baseObject;
880 JSONPValue = JSC::call(callFrame, function, callType, callData, thisValue, jsonArg);
881 if (callFrame->hadException())
882 return jsUndefined();
883 break;
884 }
6fe7ccc8 885 case JSONPPathEntryTypeDot: {
14957cd0
A
886 baseObject.put(callFrame, JSONPPath.last().m_pathEntryName, JSONPValue, slot);
887 if (callFrame->hadException())
888 return jsUndefined();
889 break;
890 }
6fe7ccc8
A
891 case JSONPPathEntryTypeLookup: {
892 baseObject.putByIndex(callFrame, JSONPPath.last().m_pathIndex, JSONPValue, slot.isStrictMode());
14957cd0
A
893 if (callFrame->hadException())
894 return jsUndefined();
895 break;
896 }
897 default:
93a37866 898 RELEASE_ASSERT_NOT_REACHED();
14957cd0
A
899 return jsUndefined();
900 }
901 result = JSONPValue;
ba379fdc 902 }
14957cd0 903 return result;
9dae56ea 904 }
14957cd0 905failedJSONP:
93a37866
A
906 // If we get here, then we have already proven that the script is not a JSON
907 // object.
908
81345200
A
909 VMEntryScope entryScope(vm, scope->globalObject());
910
93a37866
A
911 // Compile source to bytecode if necessary:
912 if (JSObject* error = program->initializeGlobalProperties(vm, callFrame, scope))
81345200 913 return checkedReturn(callFrame->vm().throwException(callFrame, error));
9dae56ea 914
81345200
A
915 if (JSObject* error = program->prepareForExecution(callFrame, nullptr, &scope, CodeForCall))
916 return checkedReturn(callFrame->vm().throwException(callFrame, error));
93a37866 917
81345200 918 ProgramCodeBlock* codeBlock = program->codeBlock();
93a37866 919
81345200 920 if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(callFrame)))
93a37866 921 return throwTerminatedExecutionException(callFrame);
9dae56ea 922
6fe7ccc8 923 ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
93a37866 924
81345200
A
925 ProtoCallFrame protoCallFrame;
926 protoCallFrame.init(codeBlock, scope, 0, thisObj, 1);
9dae56ea 927
93a37866 928 if (LegacyProfiler* profiler = vm.enabledProfiler())
81345200 929 profiler->willExecute(callFrame, program->sourceURL(), program->lineNo(), program->startColumn());
9dae56ea 930
93a37866 931 // Execute the code:
ba379fdc 932 JSValue result;
9dae56ea 933 {
f9bf01c6 934 SamplingTool::CallRecord callRecord(m_sampler.get());
81345200 935 Watchdog::Scope watchdogScope(vm.watchdog.get());
9dae56ea 936
81345200 937 result = program->generatedJITCode()->execute(&vm, &protoCallFrame);
9dae56ea
A
938 }
939
93a37866 940 if (LegacyProfiler* profiler = vm.enabledProfiler())
81345200 941 profiler->didExecute(callFrame, program->sourceURL(), program->lineNo(), program->startColumn());
9dae56ea 942
14957cd0 943 return checkedReturn(result);
9dae56ea
A
944}
945
14957cd0 946JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
9dae56ea 947{
93a37866 948 VM& vm = callFrame->vm();
14957cd0 949 ASSERT(!callFrame->hadException());
93a37866
A
950 ASSERT(!vm.isCollectorBusy());
951 if (vm.isCollectorBusy())
14957cd0 952 return jsNull();
9dae56ea 953
93a37866
A
954 bool isJSCall = (callType == CallTypeJS);
955 JSScope* scope;
956 CodeBlock* newCodeBlock;
957 size_t argsCount = 1 + args.size(); // implicit "this" parameter
14957cd0 958
93a37866
A
959 if (isJSCall)
960 scope = callData.js.scope;
961 else {
962 ASSERT(callType == CallTypeHost);
963 scope = callFrame->scope();
964 }
81345200
A
965
966 VMEntryScope entryScope(vm, scope->globalObject());
967 if (!vm.isSafeToRecurse())
968 return checkedReturn(throwStackOverflowError(callFrame));
14957cd0 969
93a37866
A
970 if (isJSCall) {
971 // Compile the callee:
81345200 972 JSObject* compileError = callData.js.functionExecutable->prepareForExecution(callFrame, jsCast<JSFunction*>(function), &scope, CodeForCall);
14957cd0 973 if (UNLIKELY(!!compileError)) {
81345200 974 return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
14957cd0 975 }
81345200 976 newCodeBlock = callData.js.functionExecutable->codeBlockForCall();
93a37866 977 ASSERT(!!newCodeBlock);
81345200 978 newCodeBlock->m_shouldAlwaysBeInlined = false;
93a37866
A
979 } else
980 newCodeBlock = 0;
14957cd0 981
81345200 982 if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(callFrame)))
93a37866 983 return throwTerminatedExecutionException(callFrame);
14957cd0 984
81345200
A
985 ProtoCallFrame protoCallFrame;
986 protoCallFrame.init(newCodeBlock, scope, function, thisValue, argsCount, args.data());
9dae56ea 987
93a37866
A
988 if (LegacyProfiler* profiler = vm.enabledProfiler())
989 profiler->willExecute(callFrame, function);
9dae56ea 990
ba379fdc 991 JSValue result;
9dae56ea 992 {
93a37866 993 SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSCall);
81345200 994 Watchdog::Scope watchdogScope(vm.watchdog.get());
93a37866
A
995
996 // Execute the code:
81345200
A
997 if (isJSCall)
998 result = callData.js.functionExecutable->generatedJITCodeForCall()->execute(&vm, &protoCallFrame);
999 else {
1000 result = JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(callData.native.function), &vm, &protoCallFrame));
1001 if (callFrame->hadException())
1002 result = jsNull();
1003 }
14957cd0 1004 }
9dae56ea 1005
93a37866
A
1006 if (LegacyProfiler* profiler = vm.enabledProfiler())
1007 profiler->didExecute(callFrame, function);
14957cd0 1008
14957cd0
A
1009 return checkedReturn(result);
1010}
1011
1012JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
1013{
93a37866 1014 VM& vm = callFrame->vm();
14957cd0 1015 ASSERT(!callFrame->hadException());
93a37866 1016 ASSERT(!vm.isCollectorBusy());
14957cd0
A
1017 // We throw in this case because we have to return something "valid" but we're
1018 // already in an invalid state.
93a37866 1019 if (vm.isCollectorBusy())
14957cd0
A
1020 return checkedReturn(throwStackOverflowError(callFrame));
1021
93a37866
A
1022 bool isJSConstruct = (constructType == ConstructTypeJS);
1023 JSScope* scope;
1024 CodeBlock* newCodeBlock;
1025 size_t argsCount = 1 + args.size(); // implicit "this" parameter
14957cd0 1026
93a37866
A
1027 if (isJSConstruct)
1028 scope = constructData.js.scope;
1029 else {
1030 ASSERT(constructType == ConstructTypeHost);
1031 scope = callFrame->scope();
1032 }
14957cd0 1033
81345200
A
1034 VMEntryScope entryScope(vm, scope->globalObject());
1035 if (!vm.isSafeToRecurse())
1036 return checkedReturn(throwStackOverflowError(callFrame));
14957cd0 1037
93a37866
A
1038 if (isJSConstruct) {
1039 // Compile the callee:
81345200 1040 JSObject* compileError = constructData.js.functionExecutable->prepareForExecution(callFrame, jsCast<JSFunction*>(constructor), &scope, CodeForConstruct);
14957cd0 1041 if (UNLIKELY(!!compileError)) {
81345200 1042 return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
14957cd0 1043 }
81345200 1044 newCodeBlock = constructData.js.functionExecutable->codeBlockForConstruct();
93a37866 1045 ASSERT(!!newCodeBlock);
81345200 1046 newCodeBlock->m_shouldAlwaysBeInlined = false;
93a37866
A
1047 } else
1048 newCodeBlock = 0;
14957cd0 1049
81345200 1050 if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(callFrame)))
93a37866 1051 return throwTerminatedExecutionException(callFrame);
14957cd0 1052
81345200
A
1053 ProtoCallFrame protoCallFrame;
1054 protoCallFrame.init(newCodeBlock, scope, constructor, jsUndefined(), argsCount, args.data());
14957cd0 1055
93a37866
A
1056 if (LegacyProfiler* profiler = vm.enabledProfiler())
1057 profiler->willExecute(callFrame, constructor);
14957cd0
A
1058
1059 JSValue result;
1060 {
93a37866 1061 SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSConstruct);
81345200 1062 Watchdog::Scope watchdogScope(vm.watchdog.get());
93a37866
A
1063
1064 // Execute the code.
81345200
A
1065 if (isJSConstruct)
1066 result = constructData.js.functionExecutable->generatedJITCodeForConstruct()->execute(&vm, &protoCallFrame);
1067 else {
1068 result = JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(constructData.native.function), &vm, &protoCallFrame));
1069
1070 if (!callFrame->hadException())
1071 RELEASE_ASSERT(result.isObject());
1072 }
14957cd0
A
1073 }
1074
93a37866
A
1075 if (LegacyProfiler* profiler = vm.enabledProfiler())
1076 profiler->didExecute(callFrame, constructor);
1077
14957cd0
A
1078 if (callFrame->hadException())
1079 return 0;
1080 ASSERT(result.isObject());
1081 return checkedReturn(asObject(result));
9dae56ea
A
1082}
1083
81345200 1084CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionExecutable, CallFrame* callFrame, ProtoCallFrame* protoCallFrame, JSFunction* function, int argumentCountIncludingThis, JSScope* scope, JSValue* args)
ba379fdc 1085{
93a37866 1086 VM& vm = *scope->vm();
81345200 1087 ASSERT(!vm.exception());
ba379fdc 1088
93a37866 1089 if (vm.isCollectorBusy())
6fe7ccc8
A
1090 return CallFrameClosure();
1091
93a37866 1092 // Compile the callee:
81345200 1093 JSObject* error = functionExecutable->prepareForExecution(callFrame, function, &scope, CodeForCall);
93a37866 1094 if (error) {
81345200 1095 callFrame->vm().throwException(callFrame, error);
ba379fdc
A
1096 return CallFrameClosure();
1097 }
81345200
A
1098 CodeBlock* newCodeBlock = functionExecutable->codeBlockForCall();
1099 newCodeBlock->m_shouldAlwaysBeInlined = false;
ba379fdc 1100
93a37866
A
1101 size_t argsCount = argumentCountIncludingThis;
1102
81345200 1103 protoCallFrame->init(newCodeBlock, scope, function, jsUndefined(), argsCount, args);
93a37866 1104 // Return the successful closure:
81345200 1105 CallFrameClosure result = { callFrame, protoCallFrame, function, functionExecutable, &vm, scope, newCodeBlock->numParameters(), argumentCountIncludingThis };
ba379fdc
A
1106 return result;
1107}
1108
14957cd0 1109JSValue Interpreter::execute(CallFrameClosure& closure)
ba379fdc 1110{
93a37866
A
1111 VM& vm = *closure.vm;
1112 SamplingScope samplingScope(this);
1113
1114 ASSERT(!vm.isCollectorBusy());
81345200 1115 RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
93a37866 1116 if (vm.isCollectorBusy())
14957cd0 1117 return jsNull();
93a37866
A
1118
1119 StackStats::CheckPoint stackCheckPoint;
ba379fdc 1120 closure.resetCallFrame();
93a37866
A
1121
1122 if (LegacyProfiler* profiler = vm.enabledProfiler())
1123 profiler->willExecute(closure.oldCallFrame, closure.function);
1124
81345200 1125 if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(closure.oldCallFrame)))
93a37866 1126 return throwTerminatedExecutionException(closure.oldCallFrame);
6fe7ccc8 1127
93a37866 1128 // Execute the code:
ba379fdc
A
1129 JSValue result;
1130 {
f9bf01c6 1131 SamplingTool::CallRecord callRecord(m_sampler.get());
81345200 1132 Watchdog::Scope watchdogScope(vm.watchdog.get());
93a37866 1133
81345200 1134 result = closure.functionExecutable->generatedJITCodeForCall()->execute(&vm, closure.protoCallFrame);
ba379fdc 1135 }
6fe7ccc8 1136
93a37866
A
1137 if (LegacyProfiler* profiler = vm.enabledProfiler())
1138 profiler->didExecute(closure.oldCallFrame, closure.function);
1139
14957cd0 1140 return checkedReturn(result);
ba379fdc
A
1141}
1142
93a37866 1143JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, JSScope* scope)
9dae56ea 1144{
93a37866
A
1145 VM& vm = *scope->vm();
1146 SamplingScope samplingScope(this);
1147
1148 ASSERT(scope->vm() == &callFrame->vm());
81345200 1149 ASSERT(!vm.exception());
93a37866 1150 ASSERT(!vm.isCollectorBusy());
81345200 1151 RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
93a37866 1152 if (vm.isCollectorBusy())
14957cd0 1153 return jsNull();
9dae56ea 1154
81345200
A
1155 VMEntryScope entryScope(vm, scope->globalObject());
1156 if (!vm.isSafeToRecurse())
1157 return checkedReturn(throwStackOverflowError(callFrame));
9dae56ea 1158
81345200
A
1159 unsigned numVariables = eval->numVariables();
1160 int numFunctions = eval->numberOfFunctionDecls();
9dae56ea 1161
81345200
A
1162 JSScope* variableObject;
1163 if ((numVariables || numFunctions) && eval->isStrictMode()) {
1164 scope = StrictEvalActivation::create(callFrame);
1165 variableObject = scope;
1166 } else {
1167 for (JSScope* node = scope; ; node = node->next()) {
1168 RELEASE_ASSERT(node);
1169 if (node->isVariableObject() && !node->isNameScopeObject()) {
1170 variableObject = node;
1171 break;
1172 }
9dae56ea
A
1173 }
1174 }
1175
81345200
A
1176 JSObject* compileError = eval->prepareForExecution(callFrame, nullptr, &scope, CodeForCall);
1177 if (UNLIKELY(!!compileError))
1178 return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
1179 EvalCodeBlock* codeBlock = eval->codeBlock();
1180
4e4e5a6f 1181 if (numVariables || numFunctions) {
93a37866 1182 BatchedTransitionOptimizer optimizer(vm, variableObject);
81345200
A
1183 if (variableObject->next())
1184 variableObject->globalObject()->varInjectionWatchpoint()->fireAll();
9dae56ea 1185
f9bf01c6
A
1186 for (unsigned i = 0; i < numVariables; ++i) {
1187 const Identifier& ident = codeBlock->variable(i);
9dae56ea 1188 if (!variableObject->hasProperty(callFrame, ident)) {
81345200 1189 PutPropertySlot slot(variableObject);
6fe7ccc8 1190 variableObject->methodTable()->put(variableObject, callFrame, ident, jsUndefined(), slot);
9dae56ea
A
1191 }
1192 }
1193
f9bf01c6
A
1194 for (int i = 0; i < numFunctions; ++i) {
1195 FunctionExecutable* function = codeBlock->functionDecl(i);
81345200
A
1196 PutPropertySlot slot(variableObject);
1197 variableObject->methodTable()->put(variableObject, callFrame, function->name(), JSFunction::create(vm, function, scope), slot);
9dae56ea 1198 }
9dae56ea
A
1199 }
1200
81345200 1201 if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(callFrame)))
93a37866 1202 return throwTerminatedExecutionException(callFrame);
6fe7ccc8
A
1203
1204 ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
9dae56ea 1205
81345200
A
1206 ProtoCallFrame protoCallFrame;
1207 protoCallFrame.init(codeBlock, scope, 0, thisValue, 1);
9dae56ea 1208
93a37866 1209 if (LegacyProfiler* profiler = vm.enabledProfiler())
81345200 1210 profiler->willExecute(callFrame, eval->sourceURL(), eval->lineNo(), eval->startColumn());
9dae56ea 1211
93a37866 1212 // Execute the code:
ba379fdc 1213 JSValue result;
9dae56ea 1214 {
f9bf01c6 1215 SamplingTool::CallRecord callRecord(m_sampler.get());
81345200 1216 Watchdog::Scope watchdogScope(vm.watchdog.get());
9dae56ea 1217
81345200 1218 result = eval->generatedJITCode()->execute(&vm, &protoCallFrame);
9dae56ea
A
1219 }
1220
93a37866 1221 if (LegacyProfiler* profiler = vm.enabledProfiler())
81345200 1222 profiler->didExecute(callFrame, eval->sourceURL(), eval->lineNo(), eval->startColumn());
9dae56ea 1223
14957cd0 1224 return checkedReturn(result);
9dae56ea
A
1225}
1226
81345200 1227NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID)
9dae56ea 1228{
81345200 1229 Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger();
9dae56ea
A
1230 if (!debugger)
1231 return;
1232
81345200
A
1233 ASSERT(callFrame->codeBlock()->hasDebuggerRequests());
1234 ASSERT(!callFrame->hadException());
1235
9dae56ea
A
1236 switch (debugHookID) {
1237 case DidEnterCallFrame:
81345200
A
1238 debugger->callEvent(callFrame);
1239 break;
9dae56ea 1240 case WillLeaveCallFrame:
81345200
A
1241 debugger->returnEvent(callFrame);
1242 break;
9dae56ea 1243 case WillExecuteStatement:
81345200
A
1244 debugger->atStatement(callFrame);
1245 break;
9dae56ea 1246 case WillExecuteProgram:
81345200
A
1247 debugger->willExecuteProgram(callFrame);
1248 break;
9dae56ea 1249 case DidExecuteProgram:
81345200
A
1250 debugger->didExecuteProgram(callFrame);
1251 break;
9dae56ea 1252 case DidReachBreakpoint:
81345200
A
1253 debugger->didReachBreakpoint(callFrame);
1254 break;
9dae56ea 1255 }
81345200
A
1256 ASSERT(!callFrame->hadException());
1257}
9dae56ea 1258
f9bf01c6
A
1259void Interpreter::enableSampler()
1260{
1261#if ENABLE(OPCODE_SAMPLING)
1262 if (!m_sampler) {
6fe7ccc8 1263 m_sampler = adoptPtr(new SamplingTool(this));
f9bf01c6
A
1264 m_sampler->setup();
1265 }
1266#endif
1267}
1268void Interpreter::dumpSampleData(ExecState* exec)
1269{
1270#if ENABLE(OPCODE_SAMPLING)
1271 if (m_sampler)
1272 m_sampler->dump(exec);
1273#else
1274 UNUSED_PARAM(exec);
1275#endif
1276}
1277void Interpreter::startSampling()
1278{
1279#if ENABLE(SAMPLING_THREAD)
1280 if (!m_sampleEntryDepth)
1281 SamplingThread::start();
1282
1283 m_sampleEntryDepth++;
1284#endif
1285}
1286void Interpreter::stopSampling()
1287{
1288#if ENABLE(SAMPLING_THREAD)
1289 m_sampleEntryDepth--;
1290 if (!m_sampleEntryDepth)
1291 SamplingThread::stop();
1292#endif
1293}
1294
9dae56ea 1295} // namespace JSC