]> git.saurik.com Git - apple/javascriptcore.git/blob - interpreter/Interpreter.cpp
87a9c2b56aa24d69f376858274db4a8a189bfc57
[apple/javascriptcore.git] / interpreter / Interpreter.cpp
1 /*
2 * Copyright (C) 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
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.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
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"
35 #include "CallFrame.h"
36 #include "CallFrameClosure.h"
37 #include "CodeBlock.h"
38 #include "Heap.h"
39 #include "Debugger.h"
40 #include "DebuggerCallFrame.h"
41 #include "ErrorInstance.h"
42 #include "EvalCodeCache.h"
43 #include "ExceptionHelpers.h"
44 #include "GetterSetter.h"
45 #include "JSActivation.h"
46 #include "JSArray.h"
47 #include "JSBoundFunction.h"
48 #include "JSNameScope.h"
49 #include "JSNotAnObject.h"
50 #include "JSPropertyNameIterator.h"
51 #include "JSStackInlines.h"
52 #include "JSString.h"
53 #include "JSWithScope.h"
54 #include "LLIntCLoop.h"
55 #include "LegacyProfiler.h"
56 #include "LiteralParser.h"
57 #include "NameInstance.h"
58 #include "ObjectPrototype.h"
59 #include "Operations.h"
60 #include "Parser.h"
61 #include "RegExpObject.h"
62 #include "RegExpPrototype.h"
63 #include "Register.h"
64 #include "SamplingTool.h"
65 #include "StrictEvalActivation.h"
66 #include "StrongInlines.h"
67 #include <limits.h>
68 #include <stdio.h>
69 #include <wtf/StackStats.h>
70 #include <wtf/StringPrintStream.h>
71 #include <wtf/Threading.h>
72 #include <wtf/WTFThreadData.h>
73 #include <wtf/text/StringBuilder.h>
74
75 #if ENABLE(JIT)
76 #include "JIT.h"
77 #endif
78
79 #define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND (ENABLE(LLINT) && !defined(__llvm__))
80
81 using namespace std;
82
83 namespace JSC {
84
85 Interpreter::ErrorHandlingMode::ErrorHandlingMode(ExecState *exec)
86 : m_interpreter(*exec->interpreter())
87 {
88 if (!m_interpreter.m_errorHandlingModeReentry)
89 m_interpreter.stack().enableErrorStackReserve();
90 m_interpreter.m_errorHandlingModeReentry++;
91 }
92
93 Interpreter::ErrorHandlingMode::~ErrorHandlingMode()
94 {
95 m_interpreter.m_errorHandlingModeReentry--;
96 ASSERT(m_interpreter.m_errorHandlingModeReentry >= 0);
97 if (!m_interpreter.m_errorHandlingModeReentry)
98 m_interpreter.stack().disableErrorStackReserve();
99 }
100
101
102 // The Interpreter::StackPolicy class is used to compute a stack capacity
103 // requirement to ensure that we have enough room on the native stack for:
104 // 1. the max cumulative stack used by the interpreter and all code
105 // paths sub of it up till leaf functions.
106 // 2. the max cumulative stack used by the interpreter before it reaches
107 // the next checkpoint (execute...() function) in the interpreter.
108 //
109 // The interpreter can be run on different threads and hence, different
110 // native stacks (with different sizes) before exiting out of the first
111 // frame. Hence, the required capacity needs to be re-computed on every
112 // entry into the interpreter.
113 //
114 // Currently the requiredStack is computed based on a policy. See comments
115 // in StackPolicy::StackPolicy() for details.
116
117 Interpreter::StackPolicy::StackPolicy(Interpreter& interpreter, const StackBounds& stack)
118 : m_interpreter(interpreter)
119 {
120 const size_t size = stack.size();
121
122 // We have two separate stack limits, one for regular JS execution, and one
123 // for when we're handling errors. We need the error stack to be smaller
124 // otherwise there would obviously not be any stack left to execute JS in when
125 // there's a stack overflow.
126 //
127 // These sizes were derived from the stack usage of a number of sites when
128 // layout occurs when we've already consumed most of the C stack.
129 const size_t requiredStack = 256 * KB;
130 const size_t errorModeRequiredStack = 64 * KB;
131
132 size_t requiredCapacity = m_interpreter.m_errorHandlingModeReentry ? errorModeRequiredStack : requiredStack;
133
134 RELEASE_ASSERT(size > requiredCapacity);
135
136 m_requiredCapacity = requiredCapacity;
137 }
138
139
140 static CallFrame* getCallerInfo(VM*, CallFrame*, unsigned& bytecodeOffset, CodeBlock*& callerOut);
141
142 // Returns the depth of the scope chain within a given call frame.
143 static int depth(CodeBlock* codeBlock, JSScope* sc)
144 {
145 if (!codeBlock->needsFullScopeChain())
146 return 0;
147 return sc->localDepth();
148 }
149
150 JSValue eval(CallFrame* callFrame)
151 {
152 if (!callFrame->argumentCount())
153 return jsUndefined();
154
155 JSValue program = callFrame->argument(0);
156 if (!program.isString())
157 return program;
158
159 TopCallFrameSetter topCallFrame(callFrame->vm(), callFrame);
160 String programSource = asString(program)->value(callFrame);
161 if (callFrame->hadException())
162 return JSValue();
163
164 CallFrame* callerFrame = callFrame->callerFrame();
165 CodeBlock* callerCodeBlock = callerFrame->codeBlock();
166 JSScope* callerScopeChain = callerFrame->scope();
167 EvalExecutable* eval = callerCodeBlock->evalCodeCache().tryGet(callerCodeBlock->isStrictMode(), programSource, callerScopeChain);
168
169 if (!eval) {
170 if (!callerCodeBlock->isStrictMode()) {
171 // FIXME: We can use the preparser in strict mode, we just need additional logic
172 // to prevent duplicates.
173 if (programSource.is8Bit()) {
174 LiteralParser<LChar> preparser(callFrame, programSource.characters8(), programSource.length(), NonStrictJSON);
175 if (JSValue parsedObject = preparser.tryLiteralParse())
176 return parsedObject;
177 } else {
178 LiteralParser<UChar> preparser(callFrame, programSource.characters16(), programSource.length(), NonStrictJSON);
179 if (JSValue parsedObject = preparser.tryLiteralParse())
180 return parsedObject;
181 }
182 }
183
184 // If the literal parser bailed, it should not have thrown exceptions.
185 ASSERT(!callFrame->vm().exception);
186
187 JSValue exceptionValue;
188 eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock->unlinkedCodeBlock()->codeCacheForEval().get(), callerCodeBlock->ownerExecutable(), callerCodeBlock->isStrictMode(), programSource, callerScopeChain, exceptionValue);
189
190 ASSERT(!eval == exceptionValue);
191 if (UNLIKELY(!eval))
192 return throwError(callFrame, exceptionValue);
193 }
194
195 JSValue thisValue = callerFrame->thisValue();
196 ASSERT(isValidThisObject(thisValue, callFrame));
197 Interpreter* interpreter = callFrame->vm().interpreter;
198 return interpreter->execute(eval, callFrame, thisValue, callerScopeChain);
199 }
200
201 CallFrame* loadVarargs(CallFrame* callFrame, JSStack* stack, JSValue thisValue, JSValue arguments, int firstFreeRegister)
202 {
203 if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
204 unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
205 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + argumentCountIncludingThis + JSStack::CallFrameHeaderSize);
206 if (argumentCountIncludingThis > Arguments::MaxArguments + 1 || !stack->grow(newCallFrame->registers())) {
207 callFrame->vm().exception = createStackOverflowError(callFrame);
208 return 0;
209 }
210
211 newCallFrame->setArgumentCountIncludingThis(argumentCountIncludingThis);
212 newCallFrame->setThisValue(thisValue);
213 for (size_t i = 0; i < callFrame->argumentCount(); ++i)
214 newCallFrame->setArgument(i, callFrame->argumentAfterCapture(i));
215 return newCallFrame;
216 }
217
218 if (arguments.isUndefinedOrNull()) {
219 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + 1 + JSStack::CallFrameHeaderSize);
220 if (!stack->grow(newCallFrame->registers())) {
221 callFrame->vm().exception = createStackOverflowError(callFrame);
222 return 0;
223 }
224 newCallFrame->setArgumentCountIncludingThis(1);
225 newCallFrame->setThisValue(thisValue);
226 return newCallFrame;
227 }
228
229 if (!arguments.isObject()) {
230 callFrame->vm().exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
231 return 0;
232 }
233
234 if (asObject(arguments)->classInfo() == &Arguments::s_info) {
235 Arguments* argsObject = asArguments(arguments);
236 unsigned argCount = argsObject->length(callFrame);
237 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
238 if (argCount > Arguments::MaxArguments || !stack->grow(newCallFrame->registers())) {
239 callFrame->vm().exception = createStackOverflowError(callFrame);
240 return 0;
241 }
242 newCallFrame->setArgumentCountIncludingThis(argCount + 1);
243 newCallFrame->setThisValue(thisValue);
244 argsObject->copyToArguments(callFrame, newCallFrame, argCount);
245 return newCallFrame;
246 }
247
248 if (isJSArray(arguments)) {
249 JSArray* array = asArray(arguments);
250 unsigned argCount = array->length();
251 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
252 if (argCount > Arguments::MaxArguments || !stack->grow(newCallFrame->registers())) {
253 callFrame->vm().exception = createStackOverflowError(callFrame);
254 return 0;
255 }
256 newCallFrame->setArgumentCountIncludingThis(argCount + 1);
257 newCallFrame->setThisValue(thisValue);
258 array->copyToArguments(callFrame, newCallFrame, argCount);
259 return newCallFrame;
260 }
261
262 JSObject* argObject = asObject(arguments);
263 unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
264 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
265 if (argCount > Arguments::MaxArguments || !stack->grow(newCallFrame->registers())) {
266 callFrame->vm().exception = createStackOverflowError(callFrame);
267 return 0;
268 }
269 newCallFrame->setArgumentCountIncludingThis(argCount + 1);
270 newCallFrame->setThisValue(thisValue);
271 for (size_t i = 0; i < argCount; ++i) {
272 newCallFrame->setArgument(i, asObject(arguments)->get(callFrame, i));
273 if (UNLIKELY(callFrame->vm().exception))
274 return 0;
275 }
276 return newCallFrame;
277 }
278
279 Interpreter::Interpreter(VM& vm)
280 : m_sampleEntryDepth(0)
281 , m_stack(vm)
282 , m_errorHandlingModeReentry(0)
283 #if !ASSERT_DISABLED
284 , m_initialized(false)
285 #endif
286 {
287 }
288
289 Interpreter::~Interpreter()
290 {
291 }
292
293 void Interpreter::initialize(bool canUseJIT)
294 {
295 UNUSED_PARAM(canUseJIT);
296
297 #if ENABLE(COMPUTED_GOTO_OPCODES) && ENABLE(LLINT)
298 m_opcodeTable = LLInt::opcodeMap();
299 for (int i = 0; i < numOpcodeIDs; ++i)
300 m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
301 #endif
302
303 #if !ASSERT_DISABLED
304 m_initialized = true;
305 #endif
306
307 #if ENABLE(OPCODE_SAMPLING)
308 enableSampler();
309 #endif
310 }
311
312 #ifdef NDEBUG
313
314 void Interpreter::dumpCallFrame(CallFrame*)
315 {
316 }
317
318 #else
319
320 void Interpreter::dumpCallFrame(CallFrame* callFrame)
321 {
322 callFrame->codeBlock()->dumpBytecode();
323 dumpRegisters(callFrame);
324 }
325
326 void Interpreter::dumpRegisters(CallFrame* callFrame)
327 {
328 dataLogF("Register frame: \n\n");
329 dataLogF("-----------------------------------------------------------------------------\n");
330 dataLogF(" use | address | value \n");
331 dataLogF("-----------------------------------------------------------------------------\n");
332
333 CodeBlock* codeBlock = callFrame->codeBlock();
334 const Register* it;
335 const Register* end;
336
337 it = callFrame->registers() - JSStack::CallFrameHeaderSize - callFrame->argumentCountIncludingThis();
338 end = callFrame->registers() - JSStack::CallFrameHeaderSize;
339 while (it < end) {
340 JSValue v = it->jsValue();
341 int registerNumber = it - callFrame->registers();
342 String name = codeBlock->nameForRegister(registerNumber);
343 dataLogF("[r% 3d %14s] | %10p | %-16s 0x%lld \n", registerNumber, name.ascii().data(), it, toCString(v).data(), (long long)JSValue::encode(v));
344 it++;
345 }
346
347 dataLogF("-----------------------------------------------------------------------------\n");
348 dataLogF("[ArgumentCount] | %10p | %lu \n", it, (unsigned long) callFrame->argumentCount());
349 ++it;
350 dataLogF("[CallerFrame] | %10p | %p \n", it, callFrame->callerFrame());
351 ++it;
352 dataLogF("[Callee] | %10p | %p \n", it, callFrame->callee());
353 ++it;
354 dataLogF("[ScopeChain] | %10p | %p \n", it, callFrame->scope());
355 ++it;
356 #if ENABLE(JIT)
357 AbstractPC pc = callFrame->abstractReturnPC(callFrame->vm());
358 if (pc.hasJITReturnAddress())
359 dataLogF("[ReturnJITPC] | %10p | %p \n", it, pc.jitReturnAddress().value());
360 #endif
361 unsigned bytecodeOffset = 0;
362 int line = 0;
363 CodeBlock* callerCodeBlock = 0;
364 getCallerInfo(&callFrame->vm(), callFrame, bytecodeOffset, callerCodeBlock);
365 line = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset);
366 dataLogF("[ReturnVPC] | %10p | %d (line %d)\n", it, bytecodeOffset, line);
367 ++it;
368 dataLogF("[CodeBlock] | %10p | %p \n", it, callFrame->codeBlock());
369 ++it;
370 dataLogF("-----------------------------------------------------------------------------\n");
371
372 int registerCount = 0;
373
374 end = it + codeBlock->m_numVars;
375 if (it != end) {
376 do {
377 JSValue v = it->jsValue();
378 int registerNumber = it - callFrame->registers();
379 String name = codeBlock->nameForRegister(registerNumber);
380 dataLogF("[r% 3d %14s] | %10p | %-16s 0x%lld \n", registerNumber, name.ascii().data(), it, toCString(v).data(), (long long)JSValue::encode(v));
381 ++it;
382 ++registerCount;
383 } while (it != end);
384 }
385 dataLogF("-----------------------------------------------------------------------------\n");
386
387 end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numVars;
388 if (it != end) {
389 do {
390 JSValue v = (*it).jsValue();
391 dataLogF("[r% 3d] | %10p | %-16s 0x%lld \n", registerCount, it, toCString(v).data(), (long long)JSValue::encode(v));
392 ++it;
393 ++registerCount;
394 } while (it != end);
395 }
396 dataLogF("-----------------------------------------------------------------------------\n");
397 }
398
399 #endif
400
401 bool Interpreter::isOpcode(Opcode opcode)
402 {
403 #if ENABLE(COMPUTED_GOTO_OPCODES)
404 #if !ENABLE(LLINT)
405 return static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode)) <= op_end;
406 #else
407 return opcode != HashTraits<Opcode>::emptyValue()
408 && !HashTraits<Opcode>::isDeletedValue(opcode)
409 && m_opcodeIDTable.contains(opcode);
410 #endif
411 #else
412 return opcode >= 0 && opcode <= op_end;
413 #endif
414 }
415
416 NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock)
417 {
418 CodeBlock* oldCodeBlock = codeBlock;
419 JSScope* scope = callFrame->scope();
420
421 if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
422 DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
423 if (callFrame->callee())
424 debugger->returnEvent(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine(), 0);
425 else
426 debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine(), 0);
427 }
428
429 JSValue activation;
430 if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsActivation()) {
431 activation = callFrame->uncheckedR(oldCodeBlock->activationRegister()).jsValue();
432 if (activation)
433 jsCast<JSActivation*>(activation)->tearOff(*scope->vm());
434 }
435
436 if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->usesArguments()) {
437 if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) {
438 if (activation)
439 jsCast<Arguments*>(arguments)->didTearOffActivation(callFrame, jsCast<JSActivation*>(activation));
440 else
441 jsCast<Arguments*>(arguments)->tearOff(callFrame);
442 }
443 }
444
445 CallFrame* callerFrame = callFrame->callerFrame();
446 callFrame->vm().topCallFrame = callerFrame;
447 if (callerFrame->hasHostCallFrameFlag())
448 return false;
449 callFrame = getCallerInfo(&callFrame->vm(), callFrame, bytecodeOffset, codeBlock);
450 return true;
451 }
452
453 static void appendSourceToError(CallFrame* callFrame, ErrorInstance* exception, unsigned bytecodeOffset)
454 {
455 exception->clearAppendSourceToMessage();
456
457 if (!callFrame->codeBlock()->hasExpressionInfo())
458 return;
459
460 int startOffset = 0;
461 int endOffset = 0;
462 int divotPoint = 0;
463 unsigned line = 0;
464 unsigned column = 0;
465
466 CodeBlock* codeBlock = callFrame->codeBlock();
467 codeBlock->expressionRangeForBytecodeOffset(bytecodeOffset, divotPoint, startOffset, endOffset, line, column);
468
469 int expressionStart = divotPoint - startOffset;
470 int expressionStop = divotPoint + endOffset;
471
472 const String& sourceString = codeBlock->source()->source();
473 if (!expressionStop || expressionStart > static_cast<int>(sourceString.length()))
474 return;
475
476 VM* vm = &callFrame->vm();
477 JSValue jsMessage = exception->getDirect(*vm, vm->propertyNames->message);
478 if (!jsMessage || !jsMessage.isString())
479 return;
480
481 String message = asString(jsMessage)->value(callFrame);
482
483 if (expressionStart < expressionStop)
484 message = makeString(message, " (evaluating '", codeBlock->source()->getRange(expressionStart, expressionStop), "')");
485 else {
486 // No range information, so give a few characters of context
487 const StringImpl* data = sourceString.impl();
488 int dataLength = sourceString.length();
489 int start = expressionStart;
490 int stop = expressionStart;
491 // Get up to 20 characters of context to the left and right of the divot, clamping to the line.
492 // then strip whitespace.
493 while (start > 0 && (expressionStart - start < 20) && (*data)[start - 1] != '\n')
494 start--;
495 while (start < (expressionStart - 1) && isStrWhiteSpace((*data)[start]))
496 start++;
497 while (stop < dataLength && (stop - expressionStart < 20) && (*data)[stop] != '\n')
498 stop++;
499 while (stop > expressionStart && isStrWhiteSpace((*data)[stop - 1]))
500 stop--;
501 message = makeString(message, " (near '...", codeBlock->source()->getRange(start, stop), "...')");
502 }
503
504 exception->putDirect(*vm, vm->propertyNames->message, jsString(vm, message));
505 }
506
507 static unsigned getBytecodeOffsetForCallFrame(CallFrame* callFrame)
508 {
509 callFrame = callFrame->removeHostCallFrameFlag();
510 CodeBlock* codeBlock = callFrame->codeBlock();
511 if (!codeBlock)
512 return 0;
513 #if ENABLE(DFG_JIT)
514 if (codeBlock->getJITType() == JITCode::DFGJIT)
515 return codeBlock->codeOrigin(callFrame->codeOriginIndexForDFG()).bytecodeIndex;
516 #endif
517 return callFrame->bytecodeOffsetForNonDFGCode();
518 }
519
520 static CallFrame* getCallerInfo(VM* vm, CallFrame* callFrame, unsigned& bytecodeOffset, CodeBlock*& caller)
521 {
522 ASSERT_UNUSED(vm, vm);
523 bytecodeOffset = 0;
524 ASSERT(!callFrame->hasHostCallFrameFlag());
525 CallFrame* trueCallerFrame = callFrame->trueCallerFrame();
526 bool wasCalledByHost = callFrame->callerFrame()->hasHostCallFrameFlag();
527 ASSERT(!trueCallerFrame->hasHostCallFrameFlag());
528
529 if (trueCallerFrame == CallFrame::noCaller() || !trueCallerFrame || !trueCallerFrame->codeBlock()) {
530 caller = 0;
531 return trueCallerFrame;
532 }
533
534 CodeBlock* callerCodeBlock = trueCallerFrame->codeBlock();
535
536 if (!callFrame->hasReturnPC())
537 wasCalledByHost = true;
538
539 if (wasCalledByHost) {
540 #if ENABLE(DFG_JIT)
541 if (callerCodeBlock && callerCodeBlock->getJITType() == JITCode::DFGJIT) {
542 unsigned codeOriginIndex = callFrame->callerFrame()->removeHostCallFrameFlag()->codeOriginIndexForDFG();
543 CodeOrigin origin = callerCodeBlock->codeOrigin(codeOriginIndex);
544 bytecodeOffset = origin.bytecodeIndex;
545 if (InlineCallFrame* inlineCallFrame = origin.inlineCallFrame)
546 callerCodeBlock = inlineCallFrame->baselineCodeBlock();
547 } else
548 #endif
549 bytecodeOffset = trueCallerFrame->bytecodeOffsetForNonDFGCode();
550 } else {
551 #if ENABLE(DFG_JIT)
552 if (callFrame->isInlineCallFrame()) {
553 InlineCallFrame* icf = callFrame->inlineCallFrame();
554 bytecodeOffset = icf->caller.bytecodeIndex;
555 if (InlineCallFrame* parentCallFrame = icf->caller.inlineCallFrame) {
556 FunctionExecutable* executable = static_cast<FunctionExecutable*>(parentCallFrame->executable.get());
557 CodeBlock* newCodeBlock = executable->baselineCodeBlockFor(parentCallFrame->isCall ? CodeForCall : CodeForConstruct);
558 ASSERT(newCodeBlock);
559 ASSERT(newCodeBlock->instructionCount() > bytecodeOffset);
560 callerCodeBlock = newCodeBlock;
561 }
562 } else if (callerCodeBlock && callerCodeBlock->getJITType() == JITCode::DFGJIT) {
563 CodeOrigin origin;
564 if (!callerCodeBlock->codeOriginForReturn(callFrame->returnPC(), origin)) {
565 // This should not be possible, but we're seeing cases where it does happen
566 // CallFrame already has robustness against bogus stack walks, so
567 // we'll extend that to here as well.
568 ASSERT_NOT_REACHED();
569 caller = 0;
570 return 0;
571 }
572 bytecodeOffset = origin.bytecodeIndex;
573 if (InlineCallFrame* icf = origin.inlineCallFrame) {
574 FunctionExecutable* executable = static_cast<FunctionExecutable*>(icf->executable.get());
575 CodeBlock* newCodeBlock = executable->baselineCodeBlockFor(icf->isCall ? CodeForCall : CodeForConstruct);
576 ASSERT(newCodeBlock);
577 ASSERT(newCodeBlock->instructionCount() > bytecodeOffset);
578 callerCodeBlock = newCodeBlock;
579 }
580 } else
581 #endif
582 {
583 RELEASE_ASSERT(callerCodeBlock);
584 bytecodeOffset = callerCodeBlock->bytecodeOffset(trueCallerFrame, callFrame->returnPC());
585 }
586 }
587
588 RELEASE_ASSERT(callerCodeBlock);
589 caller = callerCodeBlock;
590 return trueCallerFrame;
591 }
592
593 static ALWAYS_INLINE const String getSourceURLFromCallFrame(CallFrame* callFrame)
594 {
595 ASSERT(!callFrame->hasHostCallFrameFlag());
596 return callFrame->codeBlock()->ownerExecutable()->sourceURL();
597 }
598
599 static StackFrameCodeType getStackFrameCodeType(CallFrame* callFrame)
600 {
601 ASSERT(!callFrame->hasHostCallFrameFlag());
602
603 switch (callFrame->codeBlock()->codeType()) {
604 case EvalCode:
605 return StackFrameEvalCode;
606 case FunctionCode:
607 return StackFrameFunctionCode;
608 case GlobalCode:
609 return StackFrameGlobalCode;
610 }
611 RELEASE_ASSERT_NOT_REACHED();
612 return StackFrameGlobalCode;
613 }
614
615 void StackFrame::computeLineAndColumn(unsigned& line, unsigned& column)
616 {
617 if (!codeBlock) {
618 line = 0;
619 column = 0;
620 return;
621 }
622
623 int divot = 0;
624 int unusedStartOffset = 0;
625 int unusedEndOffset = 0;
626 unsigned divotLine = 0;
627 unsigned divotColumn = 0;
628 expressionInfo(divot, unusedStartOffset, unusedEndOffset, divotLine, divotColumn);
629
630 line = divotLine + lineOffset;
631 column = divotColumn + (divotLine ? 1 : firstLineColumnOffset);
632 }
633
634 void StackFrame::expressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column)
635 {
636 codeBlock->expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column);
637 divot += characterOffset;
638 }
639
640 String StackFrame::toString(CallFrame* callFrame)
641 {
642 StringBuilder traceBuild;
643 String functionName = friendlyFunctionName(callFrame);
644 String sourceURL = friendlySourceURL();
645 traceBuild.append(functionName);
646 if (!sourceURL.isEmpty()) {
647 if (!functionName.isEmpty())
648 traceBuild.append('@');
649 traceBuild.append(sourceURL);
650 if (codeType != StackFrameNativeCode) {
651 unsigned line;
652 unsigned column;
653 computeLineAndColumn(line, column);
654
655 traceBuild.append(':');
656 traceBuild.appendNumber(line);
657 traceBuild.append(':');
658 traceBuild.appendNumber(column);
659 }
660 }
661 return traceBuild.toString().impl();
662 }
663
664 void Interpreter::getStackTrace(VM* vm, Vector<StackFrame>& results, size_t maxStackSize)
665 {
666 CallFrame* callFrame = vm->topCallFrame->removeHostCallFrameFlag();
667 if (!callFrame || callFrame == CallFrame::noCaller())
668 return;
669 unsigned bytecodeOffset = getBytecodeOffsetForCallFrame(callFrame);
670 callFrame = callFrame->trueCallFrameFromVMCode();
671 if (!callFrame)
672 return;
673 CodeBlock* callerCodeBlock = callFrame->codeBlock();
674
675 while (callFrame && callFrame != CallFrame::noCaller() && maxStackSize--) {
676 String sourceURL;
677 if (callerCodeBlock) {
678 sourceURL = getSourceURLFromCallFrame(callFrame);
679 StackFrame s = {
680 Strong<JSObject>(*vm, callFrame->callee()),
681 getStackFrameCodeType(callFrame),
682 Strong<ExecutableBase>(*vm, callerCodeBlock->ownerExecutable()),
683 Strong<UnlinkedCodeBlock>(*vm, callerCodeBlock->unlinkedCodeBlock()),
684 callerCodeBlock->source(),
685 callerCodeBlock->ownerExecutable()->lineNo(),
686 callerCodeBlock->firstLineColumnOffset(),
687 callerCodeBlock->sourceOffset(),
688 bytecodeOffset,
689 sourceURL
690 };
691
692 results.append(s);
693 } else {
694 StackFrame s = { Strong<JSObject>(*vm, callFrame->callee()), StackFrameNativeCode, Strong<ExecutableBase>(), Strong<UnlinkedCodeBlock>(), 0, 0, 0, 0, 0, String()};
695 results.append(s);
696 }
697 callFrame = getCallerInfo(vm, callFrame, bytecodeOffset, callerCodeBlock);
698 }
699 }
700
701 void Interpreter::addStackTraceIfNecessary(CallFrame* callFrame, JSValue error)
702 {
703 VM* vm = &callFrame->vm();
704 ASSERT(callFrame == vm->topCallFrame || callFrame == callFrame->lexicalGlobalObject()->globalExec() || callFrame == callFrame->dynamicGlobalObject()->globalExec());
705
706 Vector<StackFrame> stackTrace;
707 getStackTrace(&callFrame->vm(), stackTrace);
708 vm->exceptionStack() = RefCountedArray<StackFrame>(stackTrace);
709 if (stackTrace.isEmpty() || !error.isObject())
710 return;
711
712 JSObject* errorObject = asObject(error);
713 JSGlobalObject* globalObject = 0;
714 if (isTerminatedExecutionException(error))
715 globalObject = vm->dynamicGlobalObject;
716 else
717 globalObject = errorObject->globalObject();
718
719 // FIXME: JSStringJoiner could be more efficient than StringBuilder here.
720 StringBuilder builder;
721 for (unsigned i = 0; i < stackTrace.size(); i++) {
722 builder.append(String(stackTrace[i].toString(globalObject->globalExec()).impl()));
723 if (i != stackTrace.size() - 1)
724 builder.append('\n');
725 }
726
727 if (errorObject->hasProperty(callFrame, vm->propertyNames->stack))
728 return;
729 errorObject->putDirect(*vm, vm->propertyNames->stack, jsString(vm, builder.toString()), ReadOnly | DontDelete);
730 }
731
732 NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset)
733 {
734 CodeBlock* codeBlock = callFrame->codeBlock();
735 bool isTermination = false;
736
737 ASSERT(!exceptionValue.isEmpty());
738 ASSERT(!exceptionValue.isCell() || exceptionValue.asCell());
739 // This shouldn't be possible (hence the assertions), but we're already in the slowest of
740 // slow cases, so let's harden against it anyway to be safe.
741 if (exceptionValue.isEmpty() || (exceptionValue.isCell() && !exceptionValue.asCell()))
742 exceptionValue = jsNull();
743
744 // Set up the exception object
745 if (exceptionValue.isObject()) {
746 JSObject* exception = asObject(exceptionValue);
747
748 if (exception->isErrorInstance() && static_cast<ErrorInstance*>(exception)->appendSourceToMessage())
749 appendSourceToError(callFrame, static_cast<ErrorInstance*>(exception), bytecodeOffset);
750
751 if (!hasErrorInfo(callFrame, exception)) {
752 // FIXME: should only really be adding these properties to VM generated exceptions,
753 // but the inspector currently requires these for all thrown objects.
754 addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source());
755 }
756
757 isTermination = isTerminatedExecutionException(exception);
758 } else {
759 if (!callFrame->vm().exceptionStack().size()) {
760 Vector<StackFrame> stack;
761 Interpreter::getStackTrace(&callFrame->vm(), stack);
762 callFrame->vm().exceptionStack() = RefCountedArray<StackFrame>(stack);
763 }
764 }
765
766 if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
767 DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
768 bool hasHandler = codeBlock->handlerForBytecodeOffset(bytecodeOffset);
769 debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), 0, hasHandler);
770 }
771
772 // Calculate an exception handler vPC, unwinding call frames as necessary.
773 HandlerInfo* handler = 0;
774 while (isTermination || !(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
775 if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
776 if (LegacyProfiler* profiler = callFrame->vm().enabledProfiler())
777 profiler->exceptionUnwind(callFrame);
778 return 0;
779 }
780 }
781
782 if (LegacyProfiler* profiler = callFrame->vm().enabledProfiler())
783 profiler->exceptionUnwind(callFrame);
784
785 // Unwind the scope chain within the exception handler's call frame.
786 JSScope* scope = callFrame->scope();
787 int scopeDelta = 0;
788 if (!codeBlock->needsFullScopeChain() || codeBlock->codeType() != FunctionCode
789 || callFrame->uncheckedR(codeBlock->activationRegister()).jsValue()) {
790 int currentDepth = depth(codeBlock, scope);
791 int targetDepth = handler->scopeDepth;
792 scopeDelta = currentDepth - targetDepth;
793 RELEASE_ASSERT(scopeDelta >= 0);
794 }
795 while (scopeDelta--)
796 scope = scope->next();
797 callFrame->setScope(scope);
798
799 return handler;
800 }
801
802 static inline JSValue checkedReturn(JSValue returnValue)
803 {
804 ASSERT(returnValue);
805 return returnValue;
806 }
807
808 static inline JSObject* checkedReturn(JSObject* returnValue)
809 {
810 ASSERT(returnValue);
811 return returnValue;
812 }
813
814 class SamplingScope {
815 public:
816 SamplingScope(Interpreter* interpreter)
817 : m_interpreter(interpreter)
818 {
819 interpreter->startSampling();
820 }
821 ~SamplingScope()
822 {
823 m_interpreter->stopSampling();
824 }
825 private:
826 Interpreter* m_interpreter;
827 };
828
829 JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, JSObject* thisObj)
830 {
831 SamplingScope samplingScope(this);
832
833 JSScope* scope = callFrame->scope();
834 VM& vm = *scope->vm();
835
836 ASSERT(isValidThisObject(thisObj, callFrame));
837 ASSERT(!vm.exception);
838 ASSERT(!vm.isCollectorBusy());
839 if (vm.isCollectorBusy())
840 return jsNull();
841
842 StackStats::CheckPoint stackCheckPoint;
843 const StackBounds& nativeStack = wtfThreadData().stack();
844 StackPolicy policy(*this, nativeStack);
845 if (!nativeStack.isSafeToRecurse(policy.requiredCapacity()))
846 return checkedReturn(throwStackOverflowError(callFrame));
847
848 // First check if the "program" is actually just a JSON object. If so,
849 // we'll handle the JSON object here. Else, we'll handle real JS code
850 // below at failedJSONP.
851 DynamicGlobalObjectScope globalObjectScope(vm, scope->globalObject());
852 Vector<JSONPData> JSONPData;
853 bool parseResult;
854 const String programSource = program->source().toString();
855 if (programSource.isNull())
856 return jsUndefined();
857 if (programSource.is8Bit()) {
858 LiteralParser<LChar> literalParser(callFrame, programSource.characters8(), programSource.length(), JSONP);
859 parseResult = literalParser.tryJSONPParse(JSONPData, scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()));
860 } else {
861 LiteralParser<UChar> literalParser(callFrame, programSource.characters16(), programSource.length(), JSONP);
862 parseResult = literalParser.tryJSONPParse(JSONPData, scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()));
863 }
864
865 if (parseResult) {
866 JSGlobalObject* globalObject = scope->globalObject();
867 JSValue result;
868 for (unsigned entry = 0; entry < JSONPData.size(); entry++) {
869 Vector<JSONPPathEntry> JSONPPath;
870 JSONPPath.swap(JSONPData[entry].m_path);
871 JSValue JSONPValue = JSONPData[entry].m_value.get();
872 if (JSONPPath.size() == 1 && JSONPPath[0].m_type == JSONPPathEntryTypeDeclare) {
873 if (globalObject->hasProperty(callFrame, JSONPPath[0].m_pathEntryName)) {
874 PutPropertySlot slot;
875 globalObject->methodTable()->put(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, slot);
876 } else
877 globalObject->methodTable()->putDirectVirtual(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, DontEnum | DontDelete);
878 // var declarations return undefined
879 result = jsUndefined();
880 continue;
881 }
882 JSValue baseObject(globalObject);
883 for (unsigned i = 0; i < JSONPPath.size() - 1; i++) {
884 ASSERT(JSONPPath[i].m_type != JSONPPathEntryTypeDeclare);
885 switch (JSONPPath[i].m_type) {
886 case JSONPPathEntryTypeDot: {
887 if (i == 0) {
888 PropertySlot slot(globalObject);
889 if (!globalObject->getPropertySlot(callFrame, JSONPPath[i].m_pathEntryName, slot)) {
890 if (entry)
891 return throwError(callFrame, createUndefinedVariableError(globalObject->globalExec(), JSONPPath[i].m_pathEntryName));
892 goto failedJSONP;
893 }
894 baseObject = slot.getValue(callFrame, JSONPPath[i].m_pathEntryName);
895 } else
896 baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathEntryName);
897 if (callFrame->hadException())
898 return jsUndefined();
899 continue;
900 }
901 case JSONPPathEntryTypeLookup: {
902 baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathIndex);
903 if (callFrame->hadException())
904 return jsUndefined();
905 continue;
906 }
907 default:
908 RELEASE_ASSERT_NOT_REACHED();
909 return jsUndefined();
910 }
911 }
912 PutPropertySlot slot;
913 switch (JSONPPath.last().m_type) {
914 case JSONPPathEntryTypeCall: {
915 JSValue function = baseObject.get(callFrame, JSONPPath.last().m_pathEntryName);
916 if (callFrame->hadException())
917 return jsUndefined();
918 CallData callData;
919 CallType callType = getCallData(function, callData);
920 if (callType == CallTypeNone)
921 return throwError(callFrame, createNotAFunctionError(callFrame, function));
922 MarkedArgumentBuffer jsonArg;
923 jsonArg.append(JSONPValue);
924 JSValue thisValue = JSONPPath.size() == 1 ? jsUndefined(): baseObject;
925 JSONPValue = JSC::call(callFrame, function, callType, callData, thisValue, jsonArg);
926 if (callFrame->hadException())
927 return jsUndefined();
928 break;
929 }
930 case JSONPPathEntryTypeDot: {
931 baseObject.put(callFrame, JSONPPath.last().m_pathEntryName, JSONPValue, slot);
932 if (callFrame->hadException())
933 return jsUndefined();
934 break;
935 }
936 case JSONPPathEntryTypeLookup: {
937 baseObject.putByIndex(callFrame, JSONPPath.last().m_pathIndex, JSONPValue, slot.isStrictMode());
938 if (callFrame->hadException())
939 return jsUndefined();
940 break;
941 }
942 default:
943 RELEASE_ASSERT_NOT_REACHED();
944 return jsUndefined();
945 }
946 result = JSONPValue;
947 }
948 return result;
949 }
950 failedJSONP:
951 // If we get here, then we have already proven that the script is not a JSON
952 // object.
953
954 // Compile source to bytecode if necessary:
955 if (JSObject* error = program->initializeGlobalProperties(vm, callFrame, scope))
956 return checkedReturn(throwError(callFrame, error));
957
958 if (JSObject* error = program->compile(callFrame, scope))
959 return checkedReturn(throwError(callFrame, error));
960
961 ProgramCodeBlock* codeBlock = &program->generatedBytecode();
962
963 if (UNLIKELY(vm.watchdog.didFire(callFrame)))
964 return throwTerminatedExecutionException(callFrame);
965
966 // Push the call frame for this invocation:
967 ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
968 CallFrame* newCallFrame = m_stack.pushFrame(callFrame, codeBlock, scope, 1, 0);
969 if (UNLIKELY(!newCallFrame))
970 return checkedReturn(throwStackOverflowError(callFrame));
971
972 // Set the arguments for the callee:
973 newCallFrame->setThisValue(thisObj);
974
975 if (LegacyProfiler* profiler = vm.enabledProfiler())
976 profiler->willExecute(callFrame, program->sourceURL(), program->lineNo());
977
978 // Execute the code:
979 JSValue result;
980 {
981 SamplingTool::CallRecord callRecord(m_sampler.get());
982 Watchdog::Scope watchdogScope(vm.watchdog);
983
984 #if ENABLE(LLINT_C_LOOP)
985 result = LLInt::CLoop::execute(newCallFrame, llint_program_prologue);
986 #elif ENABLE(JIT)
987 result = program->generatedJITCode().execute(&m_stack, newCallFrame, &vm);
988 #endif // ENABLE(JIT)
989 }
990
991 if (LegacyProfiler* profiler = vm.enabledProfiler())
992 profiler->didExecute(callFrame, program->sourceURL(), program->lineNo());
993
994 m_stack.popFrame(newCallFrame);
995
996 return checkedReturn(result);
997 }
998
999 JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
1000 {
1001 VM& vm = callFrame->vm();
1002 ASSERT(isValidThisObject(thisValue, callFrame));
1003 ASSERT(!callFrame->hadException());
1004 ASSERT(!vm.isCollectorBusy());
1005 if (vm.isCollectorBusy())
1006 return jsNull();
1007
1008 StackStats::CheckPoint stackCheckPoint;
1009 const StackBounds& nativeStack = wtfThreadData().stack();
1010 StackPolicy policy(*this, nativeStack);
1011 if (!nativeStack.isSafeToRecurse(policy.requiredCapacity()))
1012 return checkedReturn(throwStackOverflowError(callFrame));
1013
1014 bool isJSCall = (callType == CallTypeJS);
1015 JSScope* scope;
1016 CodeBlock* newCodeBlock;
1017 size_t argsCount = 1 + args.size(); // implicit "this" parameter
1018
1019 if (isJSCall)
1020 scope = callData.js.scope;
1021 else {
1022 ASSERT(callType == CallTypeHost);
1023 scope = callFrame->scope();
1024 }
1025 DynamicGlobalObjectScope globalObjectScope(vm, scope->globalObject());
1026
1027 if (isJSCall) {
1028 // Compile the callee:
1029 JSObject* compileError = callData.js.functionExecutable->compileForCall(callFrame, scope);
1030 if (UNLIKELY(!!compileError)) {
1031 return checkedReturn(throwError(callFrame, compileError));
1032 }
1033 newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
1034 ASSERT(!!newCodeBlock);
1035 } else
1036 newCodeBlock = 0;
1037
1038 if (UNLIKELY(vm.watchdog.didFire(callFrame)))
1039 return throwTerminatedExecutionException(callFrame);
1040
1041 CallFrame* newCallFrame = m_stack.pushFrame(callFrame, newCodeBlock, scope, argsCount, function);
1042 if (UNLIKELY(!newCallFrame))
1043 return checkedReturn(throwStackOverflowError(callFrame));
1044
1045 // Set the arguments for the callee:
1046 newCallFrame->setThisValue(thisValue);
1047 for (size_t i = 0; i < args.size(); ++i)
1048 newCallFrame->setArgument(i, args.at(i));
1049
1050 if (LegacyProfiler* profiler = vm.enabledProfiler())
1051 profiler->willExecute(callFrame, function);
1052
1053 JSValue result;
1054 {
1055 SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSCall);
1056 Watchdog::Scope watchdogScope(vm.watchdog);
1057
1058 // Execute the code:
1059 if (isJSCall) {
1060 #if ENABLE(LLINT_C_LOOP)
1061 result = LLInt::CLoop::execute(newCallFrame, llint_function_for_call_prologue);
1062 #elif ENABLE(JIT)
1063 result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_stack, newCallFrame, &vm);
1064 #endif // ENABLE(JIT)
1065 } else
1066 result = JSValue::decode(callData.native.function(newCallFrame));
1067 }
1068
1069 if (LegacyProfiler* profiler = vm.enabledProfiler())
1070 profiler->didExecute(callFrame, function);
1071
1072 m_stack.popFrame(newCallFrame);
1073 return checkedReturn(result);
1074 }
1075
1076 JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
1077 {
1078 VM& vm = callFrame->vm();
1079 ASSERT(!callFrame->hadException());
1080 ASSERT(!vm.isCollectorBusy());
1081 // We throw in this case because we have to return something "valid" but we're
1082 // already in an invalid state.
1083 if (vm.isCollectorBusy())
1084 return checkedReturn(throwStackOverflowError(callFrame));
1085
1086 StackStats::CheckPoint stackCheckPoint;
1087 const StackBounds& nativeStack = wtfThreadData().stack();
1088 StackPolicy policy(*this, nativeStack);
1089 if (!nativeStack.isSafeToRecurse(policy.requiredCapacity()))
1090 return checkedReturn(throwStackOverflowError(callFrame));
1091
1092 bool isJSConstruct = (constructType == ConstructTypeJS);
1093 JSScope* scope;
1094 CodeBlock* newCodeBlock;
1095 size_t argsCount = 1 + args.size(); // implicit "this" parameter
1096
1097 if (isJSConstruct)
1098 scope = constructData.js.scope;
1099 else {
1100 ASSERT(constructType == ConstructTypeHost);
1101 scope = callFrame->scope();
1102 }
1103
1104 DynamicGlobalObjectScope globalObjectScope(vm, scope->globalObject());
1105
1106 if (isJSConstruct) {
1107 // Compile the callee:
1108 JSObject* compileError = constructData.js.functionExecutable->compileForConstruct(callFrame, scope);
1109 if (UNLIKELY(!!compileError)) {
1110 return checkedReturn(throwError(callFrame, compileError));
1111 }
1112 newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
1113 ASSERT(!!newCodeBlock);
1114 } else
1115 newCodeBlock = 0;
1116
1117 if (UNLIKELY(vm.watchdog.didFire(callFrame)))
1118 return throwTerminatedExecutionException(callFrame);
1119
1120 CallFrame* newCallFrame = m_stack.pushFrame(callFrame, newCodeBlock, scope, argsCount, constructor);
1121 if (UNLIKELY(!newCallFrame))
1122 return checkedReturn(throwStackOverflowError(callFrame));
1123
1124 // Set the arguments for the callee:
1125 newCallFrame->setThisValue(jsUndefined());
1126 for (size_t i = 0; i < args.size(); ++i)
1127 newCallFrame->setArgument(i, args.at(i));
1128
1129 if (LegacyProfiler* profiler = vm.enabledProfiler())
1130 profiler->willExecute(callFrame, constructor);
1131
1132 JSValue result;
1133 {
1134 SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSConstruct);
1135 Watchdog::Scope watchdogScope(vm.watchdog);
1136
1137 // Execute the code.
1138 if (isJSConstruct) {
1139 #if ENABLE(LLINT_C_LOOP)
1140 result = LLInt::CLoop::execute(newCallFrame, llint_function_for_construct_prologue);
1141 #elif ENABLE(JIT)
1142 result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_stack, newCallFrame, &vm);
1143 #endif // ENABLE(JIT)
1144 } else
1145 result = JSValue::decode(constructData.native.function(newCallFrame));
1146 }
1147
1148 if (LegacyProfiler* profiler = vm.enabledProfiler())
1149 profiler->didExecute(callFrame, constructor);
1150
1151 m_stack.popFrame(newCallFrame);
1152
1153 if (callFrame->hadException())
1154 return 0;
1155 ASSERT(result.isObject());
1156 return checkedReturn(asObject(result));
1157 }
1158
1159 CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionExecutable, CallFrame* callFrame, JSFunction* function, int argumentCountIncludingThis, JSScope* scope)
1160 {
1161 VM& vm = *scope->vm();
1162 ASSERT(!vm.exception);
1163
1164 if (vm.isCollectorBusy())
1165 return CallFrameClosure();
1166
1167 StackStats::CheckPoint stackCheckPoint;
1168 const StackBounds& nativeStack = wtfThreadData().stack();
1169 StackPolicy policy(*this, nativeStack);
1170 if (!nativeStack.isSafeToRecurse(policy.requiredCapacity())) {
1171 throwStackOverflowError(callFrame);
1172 return CallFrameClosure();
1173 }
1174
1175 // Compile the callee:
1176 JSObject* error = functionExecutable->compileForCall(callFrame, scope);
1177 if (error) {
1178 throwError(callFrame, error);
1179 return CallFrameClosure();
1180 }
1181 CodeBlock* newCodeBlock = &functionExecutable->generatedBytecodeForCall();
1182
1183 size_t argsCount = argumentCountIncludingThis;
1184
1185 CallFrame* newCallFrame = m_stack.pushFrame(callFrame, newCodeBlock, scope, argsCount, function);
1186 if (UNLIKELY(!newCallFrame)) {
1187 throwStackOverflowError(callFrame);
1188 return CallFrameClosure();
1189 }
1190
1191 if (UNLIKELY(!newCallFrame)) {
1192 throwStackOverflowError(callFrame);
1193 return CallFrameClosure();
1194 }
1195
1196 // Return the successful closure:
1197 CallFrameClosure result = { callFrame, newCallFrame, function, functionExecutable, &vm, scope, newCodeBlock->numParameters(), argumentCountIncludingThis };
1198 return result;
1199 }
1200
1201 JSValue Interpreter::execute(CallFrameClosure& closure)
1202 {
1203 VM& vm = *closure.vm;
1204 SamplingScope samplingScope(this);
1205
1206 ASSERT(!vm.isCollectorBusy());
1207 if (vm.isCollectorBusy())
1208 return jsNull();
1209
1210 StackStats::CheckPoint stackCheckPoint;
1211 m_stack.validateFence(closure.newCallFrame, "BEFORE");
1212 closure.resetCallFrame();
1213 m_stack.validateFence(closure.newCallFrame, "STEP 1");
1214
1215 if (LegacyProfiler* profiler = vm.enabledProfiler())
1216 profiler->willExecute(closure.oldCallFrame, closure.function);
1217
1218 if (UNLIKELY(vm.watchdog.didFire(closure.oldCallFrame)))
1219 return throwTerminatedExecutionException(closure.oldCallFrame);
1220
1221 // The code execution below may push more frames and point the topCallFrame
1222 // to those newer frames, or it may pop to the top frame to the caller of
1223 // the current repeat frame, or it may leave the top frame pointing to the
1224 // current repeat frame.
1225 //
1226 // Hence, we need to preserve the topCallFrame here ourselves before
1227 // repeating this call on a second callback function.
1228
1229 TopCallFrameSetter topCallFrame(vm, closure.newCallFrame);
1230
1231 // Execute the code:
1232 JSValue result;
1233 {
1234 SamplingTool::CallRecord callRecord(m_sampler.get());
1235 Watchdog::Scope watchdogScope(vm.watchdog);
1236
1237 #if ENABLE(LLINT_C_LOOP)
1238 result = LLInt::CLoop::execute(closure.newCallFrame, llint_function_for_call_prologue);
1239 #elif ENABLE(JIT)
1240 result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_stack, closure.newCallFrame, &vm);
1241 #endif // ENABLE(JIT)
1242 }
1243
1244 if (LegacyProfiler* profiler = vm.enabledProfiler())
1245 profiler->didExecute(closure.oldCallFrame, closure.function);
1246
1247 m_stack.validateFence(closure.newCallFrame, "AFTER");
1248 return checkedReturn(result);
1249 }
1250
1251 void Interpreter::endRepeatCall(CallFrameClosure& closure)
1252 {
1253 m_stack.popFrame(closure.newCallFrame);
1254 }
1255
1256 JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, JSScope* scope)
1257 {
1258 VM& vm = *scope->vm();
1259 SamplingScope samplingScope(this);
1260
1261 ASSERT(scope->vm() == &callFrame->vm());
1262 ASSERT(isValidThisObject(thisValue, callFrame));
1263 ASSERT(!vm.exception);
1264 ASSERT(!vm.isCollectorBusy());
1265 if (vm.isCollectorBusy())
1266 return jsNull();
1267
1268 DynamicGlobalObjectScope globalObjectScope(vm, scope->globalObject());
1269
1270 StackStats::CheckPoint stackCheckPoint;
1271 const StackBounds& nativeStack = wtfThreadData().stack();
1272 StackPolicy policy(*this, nativeStack);
1273 if (!nativeStack.isSafeToRecurse(policy.requiredCapacity()))
1274 return checkedReturn(throwStackOverflowError(callFrame));
1275
1276 // Compile the callee:
1277 JSObject* compileError = eval->compile(callFrame, scope);
1278 if (UNLIKELY(!!compileError))
1279 return checkedReturn(throwError(callFrame, compileError));
1280 EvalCodeBlock* codeBlock = &eval->generatedBytecode();
1281
1282 JSObject* variableObject;
1283 for (JSScope* node = scope; ; node = node->next()) {
1284 RELEASE_ASSERT(node);
1285 if (node->isVariableObject() && !node->isNameScopeObject()) {
1286 variableObject = node;
1287 break;
1288 }
1289 }
1290
1291 unsigned numVariables = codeBlock->numVariables();
1292 int numFunctions = codeBlock->numberOfFunctionDecls();
1293 if (numVariables || numFunctions) {
1294 if (codeBlock->isStrictMode()) {
1295 scope = StrictEvalActivation::create(callFrame);
1296 variableObject = scope;
1297 }
1298 // Scope for BatchedTransitionOptimizer
1299 BatchedTransitionOptimizer optimizer(vm, variableObject);
1300
1301 for (unsigned i = 0; i < numVariables; ++i) {
1302 const Identifier& ident = codeBlock->variable(i);
1303 if (!variableObject->hasProperty(callFrame, ident)) {
1304 PutPropertySlot slot;
1305 variableObject->methodTable()->put(variableObject, callFrame, ident, jsUndefined(), slot);
1306 }
1307 }
1308
1309 for (int i = 0; i < numFunctions; ++i) {
1310 FunctionExecutable* function = codeBlock->functionDecl(i);
1311 PutPropertySlot slot;
1312 variableObject->methodTable()->put(variableObject, callFrame, function->name(), JSFunction::create(callFrame, function, scope), slot);
1313 }
1314 }
1315
1316 if (UNLIKELY(vm.watchdog.didFire(callFrame)))
1317 return throwTerminatedExecutionException(callFrame);
1318
1319 // Push the frame:
1320 ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
1321 CallFrame* newCallFrame = m_stack.pushFrame(callFrame, codeBlock, scope, 1, 0);
1322 if (UNLIKELY(!newCallFrame))
1323 return checkedReturn(throwStackOverflowError(callFrame));
1324
1325 // Set the arguments for the callee:
1326 newCallFrame->setThisValue(thisValue);
1327
1328 if (LegacyProfiler* profiler = vm.enabledProfiler())
1329 profiler->willExecute(callFrame, eval->sourceURL(), eval->lineNo());
1330
1331 // Execute the code:
1332 JSValue result;
1333 {
1334 SamplingTool::CallRecord callRecord(m_sampler.get());
1335 Watchdog::Scope watchdogScope(vm.watchdog);
1336
1337 #if ENABLE(LLINT_C_LOOP)
1338 result = LLInt::CLoop::execute(newCallFrame, llint_eval_prologue);
1339 #elif ENABLE(JIT)
1340 result = eval->generatedJITCode().execute(&m_stack, newCallFrame, &vm);
1341 #endif // ENABLE(JIT)
1342 }
1343
1344 if (LegacyProfiler* profiler = vm.enabledProfiler())
1345 profiler->didExecute(callFrame, eval->sourceURL(), eval->lineNo());
1346
1347 m_stack.popFrame(newCallFrame);
1348 return checkedReturn(result);
1349 }
1350
1351 NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine, int column)
1352 {
1353 Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
1354 if (!debugger)
1355 return;
1356
1357 switch (debugHookID) {
1358 case DidEnterCallFrame:
1359 debugger->callEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine, column);
1360 return;
1361 case WillLeaveCallFrame:
1362 debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine, column);
1363 return;
1364 case WillExecuteStatement:
1365 debugger->atStatement(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine, column);
1366 return;
1367 case WillExecuteProgram:
1368 debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine, column);
1369 return;
1370 case DidExecuteProgram:
1371 debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine, column);
1372 return;
1373 case DidReachBreakpoint:
1374 debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine, column);
1375 return;
1376 }
1377 }
1378
1379 JSValue Interpreter::retrieveArgumentsFromVMCode(CallFrame* callFrame, JSFunction* function) const
1380 {
1381 CallFrame* functionCallFrame = findFunctionCallFrameFromVMCode(callFrame, function);
1382 if (!functionCallFrame)
1383 return jsNull();
1384
1385 Arguments* arguments = Arguments::create(functionCallFrame->vm(), functionCallFrame);
1386 arguments->tearOff(functionCallFrame);
1387 return JSValue(arguments);
1388 }
1389
1390 JSValue Interpreter::retrieveCallerFromVMCode(CallFrame* callFrame, JSFunction* function) const
1391 {
1392 CallFrame* functionCallFrame = findFunctionCallFrameFromVMCode(callFrame, function);
1393
1394 if (!functionCallFrame)
1395 return jsNull();
1396
1397 unsigned bytecodeOffset;
1398 CodeBlock* unusedCallerCodeBlock = 0;
1399 CallFrame* callerFrame = getCallerInfo(&callFrame->vm(), functionCallFrame, bytecodeOffset, unusedCallerCodeBlock);
1400 if (!callerFrame)
1401 return jsNull();
1402 JSValue caller = callerFrame->callee();
1403 if (!caller)
1404 return jsNull();
1405
1406 // Skip over function bindings.
1407 ASSERT(caller.isObject());
1408 while (asObject(caller)->inherits(&JSBoundFunction::s_info)) {
1409 callerFrame = getCallerInfo(&callFrame->vm(), callerFrame, bytecodeOffset, unusedCallerCodeBlock);
1410 if (!callerFrame)
1411 return jsNull();
1412 caller = callerFrame->callee();
1413 if (!caller)
1414 return jsNull();
1415 }
1416
1417 return caller;
1418 }
1419
1420 void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t& sourceID, String& sourceURL, JSValue& function) const
1421 {
1422 function = JSValue();
1423 lineNumber = -1;
1424 sourceURL = String();
1425
1426 CallFrame* callerFrame = callFrame->callerFrame();
1427 if (callerFrame->hasHostCallFrameFlag())
1428 return;
1429
1430 CodeBlock* callerCodeBlock = callerFrame->codeBlock();
1431 if (!callerCodeBlock)
1432 return;
1433 unsigned bytecodeOffset = 0;
1434 bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
1435 lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
1436 sourceID = callerCodeBlock->ownerExecutable()->sourceID();
1437 sourceURL = callerCodeBlock->ownerExecutable()->sourceURL();
1438 function = callerFrame->callee();
1439 }
1440
1441 CallFrame* Interpreter::findFunctionCallFrameFromVMCode(CallFrame* callFrame, JSFunction* function)
1442 {
1443 for (CallFrame* candidate = callFrame->trueCallFrameFromVMCode(); candidate; candidate = candidate->trueCallerFrame()) {
1444 if (candidate->callee() == function)
1445 return candidate;
1446 }
1447 return 0;
1448 }
1449
1450 void Interpreter::enableSampler()
1451 {
1452 #if ENABLE(OPCODE_SAMPLING)
1453 if (!m_sampler) {
1454 m_sampler = adoptPtr(new SamplingTool(this));
1455 m_sampler->setup();
1456 }
1457 #endif
1458 }
1459 void Interpreter::dumpSampleData(ExecState* exec)
1460 {
1461 #if ENABLE(OPCODE_SAMPLING)
1462 if (m_sampler)
1463 m_sampler->dump(exec);
1464 #else
1465 UNUSED_PARAM(exec);
1466 #endif
1467 }
1468 void Interpreter::startSampling()
1469 {
1470 #if ENABLE(SAMPLING_THREAD)
1471 if (!m_sampleEntryDepth)
1472 SamplingThread::start();
1473
1474 m_sampleEntryDepth++;
1475 #endif
1476 }
1477 void Interpreter::stopSampling()
1478 {
1479 #if ENABLE(SAMPLING_THREAD)
1480 m_sampleEntryDepth--;
1481 if (!m_sampleEntryDepth)
1482 SamplingThread::stop();
1483 #endif
1484 }
1485
1486 } // namespace JSC