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