dc294f10e3ef540cd46aec70d40b03b0c4edf10c
[WebKit-https.git] / Source / JavaScriptCore / interpreter / Interpreter.cpp
1 /*
2  * Copyright (C) 2008-2017 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 "BatchedTransitionOptimizer.h"
34 #include "Bytecodes.h"
35 #include "CallFrameClosure.h"
36 #include "CatchScope.h"
37 #include "CodeBlock.h"
38 #include "DirectArguments.h"
39 #include "Heap.h"
40 #include "Debugger.h"
41 #include "DebuggerCallFrame.h"
42 #include "DirectEvalCodeCache.h"
43 #include "ErrorInstance.h"
44 #include "EvalCodeBlock.h"
45 #include "Exception.h"
46 #include "ExceptionHelpers.h"
47 #include "FrameTracers.h"
48 #include "FunctionCodeBlock.h"
49 #include "InterpreterInlines.h"
50 #include "JSArrayInlines.h"
51 #include "JSBoundFunction.h"
52 #include "JSCInlines.h"
53 #include "JSFixedArray.h"
54 #include "JSLexicalEnvironment.h"
55 #include "JSModuleEnvironment.h"
56 #include "JSString.h"
57 #include "JSWithScope.h"
58 #include "LLIntCLoop.h"
59 #include "LLIntThunks.h"
60 #include "LiteralParser.h"
61 #include "ModuleProgramCodeBlock.h"
62 #include "ObjectPrototype.h"
63 #include "Parser.h"
64 #include "ProgramCodeBlock.h"
65 #include "ProtoCallFrame.h"
66 #include "RegExpObject.h"
67 #include "Register.h"
68 #include "ScopedArguments.h"
69 #include "StackAlignment.h"
70 #include "StackFrame.h"
71 #include "StackVisitor.h"
72 #include "StrictEvalActivation.h"
73 #include "StrongInlines.h"
74 #include "Symbol.h"
75 #include "VMEntryScope.h"
76 #include "VMInlines.h"
77 #include "VMInspector.h"
78 #include "VirtualRegister.h"
79
80 #include <limits.h>
81 #include <stdio.h>
82 #include <wtf/NeverDestroyed.h>
83 #include <wtf/StackStats.h>
84 #include <wtf/StdLibExtras.h>
85 #include <wtf/StringPrintStream.h>
86 #include <wtf/Threading.h>
87 #include <wtf/text/StringBuilder.h>
88
89 #if ENABLE(JIT)
90 #include "JIT.h"
91 #endif
92
93 using namespace std;
94
95 namespace JSC {
96
97 JSValue eval(CallFrame* callFrame)
98 {
99     VM& vm = callFrame->vm();
100     auto scope = DECLARE_THROW_SCOPE(vm);
101
102     if (!callFrame->argumentCount())
103         return jsUndefined();
104
105     JSValue program = callFrame->argument(0);
106     if (!program.isString())
107         return program;
108
109     TopCallFrameSetter topCallFrame(vm, callFrame);
110     JSGlobalObject* globalObject = callFrame->lexicalGlobalObject();
111     if (!globalObject->evalEnabled()) {
112         throwException(callFrame, scope, createEvalError(callFrame, globalObject->evalDisabledErrorMessage()));
113         return jsUndefined();
114     }
115     String programSource = asString(program)->value(callFrame);
116     RETURN_IF_EXCEPTION(scope, JSValue());
117     
118     CallFrame* callerFrame = callFrame->callerFrame();
119     CallSiteIndex callerCallSiteIndex = callerFrame->callSiteIndex();
120     CodeBlock* callerCodeBlock = callerFrame->codeBlock();
121     JSScope* callerScopeChain = callerFrame->uncheckedR(callerCodeBlock->scopeRegister().offset()).Register::scope();
122     UnlinkedCodeBlock* callerUnlinkedCodeBlock = callerCodeBlock->unlinkedCodeBlock();
123
124     bool isArrowFunctionContext = callerUnlinkedCodeBlock->isArrowFunction() || callerUnlinkedCodeBlock->isArrowFunctionContext();
125
126     DerivedContextType derivedContextType = callerUnlinkedCodeBlock->derivedContextType();
127     if (!isArrowFunctionContext && callerUnlinkedCodeBlock->isClassContext()) {
128         derivedContextType = callerUnlinkedCodeBlock->isConstructor()
129             ? DerivedContextType::DerivedConstructorContext
130             : DerivedContextType::DerivedMethodContext;
131     }
132
133     EvalContextType evalContextType;
134     if (isFunctionParseMode(callerUnlinkedCodeBlock->parseMode()))
135         evalContextType = EvalContextType::FunctionEvalContext;
136     else if (callerUnlinkedCodeBlock->codeType() == EvalCode)
137         evalContextType = callerUnlinkedCodeBlock->evalContextType();
138     else
139         evalContextType = EvalContextType::None;
140
141     DirectEvalExecutable* eval = callerCodeBlock->directEvalCodeCache().tryGet(programSource, callerCallSiteIndex);
142     if (!eval) {
143         if (!callerCodeBlock->isStrictMode()) {
144             if (programSource.is8Bit()) {
145                 LiteralParser<LChar> preparser(callFrame, programSource.characters8(), programSource.length(), NonStrictJSON);
146                 if (JSValue parsedObject = preparser.tryLiteralParse()) {
147                     scope.release();
148                     return parsedObject;
149                 }
150             } else {
151                 LiteralParser<UChar> preparser(callFrame, programSource.characters16(), programSource.length(), NonStrictJSON);
152                 if (JSValue parsedObject = preparser.tryLiteralParse()) {
153                     scope.release();
154                     return parsedObject;
155                 }
156             }
157         }
158         
159         // If the literal parser bailed, it should not have thrown exceptions.
160         scope.assertNoException();
161
162         VariableEnvironment variablesUnderTDZ;
163         JSScope::collectClosureVariablesUnderTDZ(callerScopeChain, variablesUnderTDZ);
164         eval = DirectEvalExecutable::create(callFrame, makeSource(programSource, callerCodeBlock->source()->sourceOrigin()), callerCodeBlock->isStrictMode(), derivedContextType, isArrowFunctionContext, evalContextType, &variablesUnderTDZ);
165         EXCEPTION_ASSERT(!!scope.exception() == !eval);
166         if (!eval)
167             return jsUndefined();
168
169         callerCodeBlock->directEvalCodeCache().set(callFrame, callerCodeBlock, programSource, callerCallSiteIndex, eval);
170     }
171
172     JSValue thisValue = callerFrame->thisValue();
173     Interpreter* interpreter = vm.interpreter;
174     scope.release();
175     return interpreter->execute(eval, callFrame, thisValue, callerScopeChain);
176 }
177
178 unsigned sizeOfVarargs(CallFrame* callFrame, JSValue arguments, uint32_t firstVarArgOffset)
179 {
180     VM& vm = callFrame->vm();
181     auto scope = DECLARE_THROW_SCOPE(vm);
182
183     if (UNLIKELY(!arguments.isCell())) {
184         if (arguments.isUndefinedOrNull())
185             return 0;
186         
187         throwException(callFrame, scope, createInvalidFunctionApplyParameterError(callFrame, arguments));
188         return 0;
189     }
190     
191     JSCell* cell = arguments.asCell();
192     unsigned length;
193     switch (cell->type()) {
194     case DirectArgumentsType:
195         length = jsCast<DirectArguments*>(cell)->length(callFrame);
196         break;
197     case ScopedArgumentsType:
198         length = jsCast<ScopedArguments*>(cell)->length(callFrame);
199         break;
200     case JSFixedArrayType:
201         length = jsCast<JSFixedArray*>(cell)->size();
202         break;
203     case StringType:
204     case SymbolType:
205     case BigIntType:
206         throwException(callFrame, scope, createInvalidFunctionApplyParameterError(callFrame,  arguments));
207         return 0;
208         
209     default:
210         RELEASE_ASSERT(arguments.isObject());
211         length = clampToUnsigned(toLength(callFrame, jsCast<JSObject*>(cell)));
212         break;
213     }
214     RETURN_IF_EXCEPTION(scope, 0);
215     
216     if (length >= firstVarArgOffset)
217         length -= firstVarArgOffset;
218     else
219         length = 0;
220     
221     return length;
222 }
223
224 unsigned sizeFrameForForwardArguments(CallFrame* callFrame, VM& vm, unsigned numUsedStackSlots)
225 {
226     auto scope = DECLARE_THROW_SCOPE(vm);
227
228     unsigned length = callFrame->argumentCount();
229     CallFrame* calleeFrame = calleeFrameForVarargs(callFrame, numUsedStackSlots, length + 1);
230     if (UNLIKELY(!vm.ensureStackCapacityFor(calleeFrame->registers())))
231         throwStackOverflowError(callFrame, scope);
232
233     return length;
234 }
235
236 unsigned sizeFrameForVarargs(CallFrame* callFrame, VM& vm, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset)
237 {
238     auto scope = DECLARE_THROW_SCOPE(vm);
239
240     unsigned length = sizeOfVarargs(callFrame, arguments, firstVarArgOffset);
241     RETURN_IF_EXCEPTION(scope, 0);
242
243     CallFrame* calleeFrame = calleeFrameForVarargs(callFrame, numUsedStackSlots, length + 1);
244     if (UNLIKELY(length > maxArguments || !vm.ensureStackCapacityFor(calleeFrame->registers()))) {
245         throwStackOverflowError(callFrame, scope);
246         return 0;
247     }
248     
249     return length;
250 }
251
252 void loadVarargs(CallFrame* callFrame, VirtualRegister firstElementDest, JSValue arguments, uint32_t offset, uint32_t length)
253 {
254     if (UNLIKELY(!arguments.isCell()) || !length)
255         return;
256
257     VM& vm = callFrame->vm();
258     auto scope = DECLARE_THROW_SCOPE(vm);
259     JSCell* cell = arguments.asCell();
260
261     switch (cell->type()) {
262     case DirectArgumentsType:
263         scope.release();
264         jsCast<DirectArguments*>(cell)->copyToArguments(callFrame, firstElementDest, offset, length);
265         return;
266     case ScopedArgumentsType:
267         scope.release();
268         jsCast<ScopedArguments*>(cell)->copyToArguments(callFrame, firstElementDest, offset, length);
269         return;
270     case JSFixedArrayType:
271         scope.release();
272         jsCast<JSFixedArray*>(cell)->copyToArguments(callFrame, firstElementDest, offset, length);
273         return;
274     default: {
275         ASSERT(arguments.isObject());
276         JSObject* object = jsCast<JSObject*>(cell);
277         if (isJSArray(object)) {
278             scope.release();
279             jsCast<JSArray*>(object)->copyToArguments(callFrame, firstElementDest, offset, length);
280             return;
281         }
282         unsigned i;
283         for (i = 0; i < length && object->canGetIndexQuickly(i + offset); ++i)
284             callFrame->r(firstElementDest + i) = object->getIndexQuickly(i + offset);
285         for (; i < length; ++i) {
286             JSValue value = object->get(callFrame, i + offset);
287             RETURN_IF_EXCEPTION(scope, void());
288             callFrame->r(firstElementDest + i) = value;
289         }
290         return;
291     } }
292 }
293
294 void setupVarargsFrame(CallFrame* callFrame, CallFrame* newCallFrame, JSValue arguments, uint32_t offset, uint32_t length)
295 {
296     VirtualRegister calleeFrameOffset(newCallFrame - callFrame);
297     
298     loadVarargs(
299         callFrame,
300         calleeFrameOffset + CallFrame::argumentOffset(0),
301         arguments, offset, length);
302     
303     newCallFrame->setArgumentCountIncludingThis(length + 1);
304 }
305
306 void setupVarargsFrameAndSetThis(CallFrame* callFrame, CallFrame* newCallFrame, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length)
307 {
308     setupVarargsFrame(callFrame, newCallFrame, arguments, firstVarArgOffset, length);
309     newCallFrame->setThisValue(thisValue);
310 }
311
312 void setupForwardArgumentsFrame(CallFrame* execCaller, CallFrame* execCallee, uint32_t length)
313 {
314     ASSERT(length == execCaller->argumentCount());
315     unsigned offset = execCaller->argumentOffset(0) * sizeof(Register);
316     memcpy(reinterpret_cast<char*>(execCallee) + offset, reinterpret_cast<char*>(execCaller) + offset, length * sizeof(Register));
317     execCallee->setArgumentCountIncludingThis(length + 1);
318 }
319
320 void setupForwardArgumentsFrameAndSetThis(CallFrame* execCaller, CallFrame* execCallee, JSValue thisValue, uint32_t length)
321 {
322     setupForwardArgumentsFrame(execCaller, execCallee, length);
323     execCallee->setThisValue(thisValue);
324 }
325
326     
327
328 Interpreter::Interpreter(VM& vm)
329     : m_vm(vm)
330 #if !ENABLE(JIT)
331     , m_cloopStack(vm)
332 #endif
333 {
334 #if !ASSERT_DISABLED
335     static std::once_flag assertOnceKey;
336     std::call_once(assertOnceKey, [] {
337         for (unsigned i = 0; i < NUMBER_OF_BYTECODE_IDS; ++i) {
338             OpcodeID opcodeID = static_cast<OpcodeID>(i);
339             RELEASE_ASSERT(getOpcodeID(getOpcode(opcodeID)) == opcodeID);
340         }
341     });
342 #endif // USE(LLINT_EMBEDDED_OPCODE_ID)
343 }
344
345 Interpreter::~Interpreter()
346 {
347 }
348
349 #if ENABLE(COMPUTED_GOTO_OPCODES)
350 #if !USE(LLINT_EMBEDDED_OPCODE_ID) || !ASSERT_DISABLED
351 HashMap<Opcode, OpcodeID>& Interpreter::opcodeIDTable()
352 {
353     static NeverDestroyed<HashMap<Opcode, OpcodeID>> opcodeIDTable;
354
355     static std::once_flag initializeKey;
356     std::call_once(initializeKey, [&] {
357         const Opcode* opcodeTable = LLInt::opcodeMap();
358         for (unsigned i = 0; i < NUMBER_OF_BYTECODE_IDS; ++i)
359             opcodeIDTable.get().add(opcodeTable[i], static_cast<OpcodeID>(i));
360     });
361
362     return opcodeIDTable;
363 }
364 #endif // !USE(LLINT_EMBEDDED_OPCODE_ID) || !ASSERT_DISABLED
365 #endif // ENABLE(COMPUTED_GOTO_OPCODES)
366
367 #ifdef NDEBUG
368
369 void Interpreter::dumpCallFrame(CallFrame*)
370 {
371 }
372
373 #else
374
375 void Interpreter::dumpCallFrame(CallFrame* callFrame)
376 {
377     callFrame->codeBlock()->dumpBytecode();
378     dumpRegisters(callFrame);
379 }
380
381 class DumpReturnVirtualPCFunctor {
382 public:
383     DumpReturnVirtualPCFunctor(const Register*& it)
384         : m_hasSkippedFirstFrame(false)
385         , m_it(it)
386     {
387     }
388
389     StackVisitor::Status operator()(StackVisitor& visitor) const
390     {
391         if (!m_hasSkippedFirstFrame) {
392             m_hasSkippedFirstFrame = true;
393             return StackVisitor::Continue;
394         }
395
396         unsigned line = 0;
397         unsigned unusedColumn = 0;
398         visitor->computeLineAndColumn(line, unusedColumn);
399         dataLogF("[ReturnVPC]                | %10p | %d (line %d)\n", m_it, visitor->bytecodeOffset(), line);
400         return StackVisitor::Done;
401     }
402
403 private:
404     mutable bool m_hasSkippedFirstFrame;
405     const Register*& m_it;
406 };
407
408 void Interpreter::dumpRegisters(CallFrame* callFrame)
409 {
410     CodeBlock* codeBlock = callFrame->codeBlock();
411     if (!codeBlock) {
412         dataLog("Dumping host frame registers not supported.\n");
413         return;
414     }
415     VM& vm = *codeBlock->vm();
416
417     dataLogF("Register frame: \n\n");
418     dataLogF("-----------------------------------------------------------------------------\n");
419     dataLogF("            use            |   address  |                value               \n");
420     dataLogF("-----------------------------------------------------------------------------\n");
421
422     const Register* it;
423     const Register* end;
424
425     it = callFrame->registers() + CallFrameSlot::thisArgument + callFrame->argumentCount();
426     end = callFrame->registers() + CallFrameSlot::thisArgument - 1;
427     while (it > end) {
428         JSValue v = it->jsValue();
429         int registerNumber = it - callFrame->registers();
430         String name = codeBlock->nameForRegister(VirtualRegister(registerNumber));
431         dataLogF("[r% 3d %14s]      | %10p | %-16s 0x%lld \n", registerNumber, name.ascii().data(), it, toCString(v).data(), (long long)JSValue::encode(v));
432         --it;
433     }
434     
435     dataLogF("-----------------------------------------------------------------------------\n");
436     dataLogF("[ArgumentCount]            | %10p | %lu \n", it, (unsigned long) callFrame->argumentCount());
437     DumpReturnVirtualPCFunctor functor(it);
438     callFrame->iterate(functor);
439     --it;
440     dataLogF("[Callee]                   | %10p | %p \n", it, callFrame->jsCallee());
441     --it;
442     dataLogF("[CodeBlock]                | %10p | %p \n", it, callFrame->codeBlock());
443     --it;
444 #if ENABLE(JIT)
445     AbstractPC pc = callFrame->abstractReturnPC(callFrame->vm());
446     if (pc.hasJITReturnAddress())
447         dataLogF("[ReturnPC]                 | %10p | %p \n", it, pc.jitReturnAddress().value());
448     --it;
449 #endif
450     dataLogF("[CallerFrame]              | %10p | %p \n", it, callFrame->callerFrame());
451     --it;
452     dataLogF("-----------------------------------------------------------------------------\n");
453
454     size_t numberOfCalleeSaveSlots = codeBlock->calleeSaveSpaceAsVirtualRegisters();
455     const Register* endOfCalleeSaves = it - numberOfCalleeSaveSlots;
456
457     end = it - codeBlock->m_numVars;
458     if (it != end) {
459         do {
460             JSValue v = it->jsValue();
461             int registerNumber = it - callFrame->registers();
462             String name = (it > endOfCalleeSaves)
463                 ? "CalleeSaveReg"
464                 : codeBlock->nameForRegister(VirtualRegister(registerNumber));
465             CString valueString = (it > endOfCalleeSaves) ? "" : toCString(v);
466             dataLogF("[r% 3d %14s]      | %10p | %-16s 0x%lld \n", registerNumber, name.ascii().data(), it, valueString.data(), (long long)JSValue::encode(v));
467             --it;
468         } while (it != end);
469     }
470     dataLogF("-----------------------------------------------------------------------------\n");
471
472     end = it - codeBlock->m_numCalleeLocals + codeBlock->m_numVars;
473     if (it != end) {
474         do {
475             JSValue v = (*it).jsValue();
476             int registerNumber = it - callFrame->registers();
477             CString valueString =
478                 (v.isCell() && !VMInspector::isValidCell(&vm.heap, reinterpret_cast<JSCell*>(JSValue::encode(v))))
479                 ? "INVALID"
480                 : toCString(v);
481             dataLogF("[r% 3d]                     | %10p | %-16s 0x%lld \n", registerNumber, it, valueString.data(), (long long)JSValue::encode(v));
482             --it;
483         } while (it != end);
484     }
485     dataLogF("-----------------------------------------------------------------------------\n");
486 }
487
488 #endif
489
490 #if !ASSERT_DISABLED
491 bool Interpreter::isOpcode(Opcode opcode)
492 {
493 #if ENABLE(COMPUTED_GOTO_OPCODES)
494     return opcode != HashTraits<Opcode>::emptyValue()
495         && !HashTraits<Opcode>::isDeletedValue(opcode)
496         && opcodeIDTable().contains(opcode);
497 #else
498     return opcode >= 0 && opcode <= op_end;
499 #endif
500 }
501 #endif // !ASSERT_DISABLED
502
503 class GetStackTraceFunctor {
504 public:
505     GetStackTraceFunctor(VM& vm, JSCell* owner, Vector<StackFrame>& results, size_t framesToSkip, size_t capacity)
506         : m_vm(vm)
507         , m_owner(owner)
508         , m_results(results)
509         , m_framesToSkip(framesToSkip)
510         , m_remainingCapacityForFrameCapture(capacity)
511     {
512         m_results.reserveInitialCapacity(capacity);
513     }
514
515     StackVisitor::Status operator()(StackVisitor& visitor) const
516     {
517         if (m_framesToSkip > 0) {
518             m_framesToSkip--;
519             return StackVisitor::Continue;
520         }
521
522         if (m_remainingCapacityForFrameCapture) {
523             if (visitor->isWasmFrame()) {
524                 m_results.append(StackFrame(visitor->wasmFunctionIndexOrName()));
525             } else if (!!visitor->codeBlock() && !visitor->codeBlock()->unlinkedCodeBlock()->isBuiltinFunction()) {
526                 m_results.append(
527                     StackFrame(m_vm, m_owner, visitor->callee().asCell(), visitor->codeBlock(), visitor->bytecodeOffset()));
528             } else {
529                 m_results.append(
530                     StackFrame(m_vm, m_owner, visitor->callee().asCell()));
531             }
532     
533             m_remainingCapacityForFrameCapture--;
534             return StackVisitor::Continue;
535         }
536         return StackVisitor::Done;
537     }
538
539 private:
540     VM& m_vm;
541     JSCell* m_owner;
542     Vector<StackFrame>& m_results;
543     mutable size_t m_framesToSkip;
544     mutable size_t m_remainingCapacityForFrameCapture;
545 };
546
547 void Interpreter::getStackTrace(JSCell* owner, Vector<StackFrame>& results, size_t framesToSkip, size_t maxStackSize)
548 {
549     DisallowGC disallowGC;
550     VM& vm = m_vm;
551     CallFrame* callFrame = vm.topCallFrame;
552     if (!callFrame)
553         return;
554
555     size_t framesCount = 0;
556     StackVisitor::visit(callFrame, &vm, [&] (StackVisitor&) -> StackVisitor::Status {
557         framesCount++;
558         return StackVisitor::Continue;
559     });
560     if (framesCount <= framesToSkip)
561         return;
562
563     framesCount -= framesToSkip;
564     framesCount = std::min(maxStackSize, framesCount);
565
566     GetStackTraceFunctor functor(vm, owner, results, framesToSkip, framesCount);
567     StackVisitor::visit(callFrame, &vm, functor);
568     ASSERT(results.size() == results.capacity());
569 }
570
571 JSString* Interpreter::stackTraceAsString(VM& vm, const Vector<StackFrame>& stackTrace)
572 {
573     // FIXME: JSStringJoiner could be more efficient than StringBuilder here.
574     StringBuilder builder;
575     for (unsigned i = 0; i < stackTrace.size(); i++) {
576         builder.append(String(stackTrace[i].toString(vm)));
577         if (i != stackTrace.size() - 1)
578             builder.append('\n');
579     }
580     return jsString(&vm, builder.toString());
581 }
582
583 ALWAYS_INLINE static HandlerInfo* findExceptionHandler(StackVisitor& visitor, CodeBlock* codeBlock, RequiredHandler requiredHandler)
584 {
585     ASSERT(codeBlock);
586 #if ENABLE(DFG_JIT)
587     ASSERT(!visitor->isInlinedFrame());
588 #endif
589
590     CallFrame* callFrame = visitor->callFrame();
591     unsigned exceptionHandlerIndex;
592     if (JITCode::isOptimizingJIT(codeBlock->jitType()))
593         exceptionHandlerIndex = callFrame->callSiteIndex().bits();
594     else
595         exceptionHandlerIndex = callFrame->bytecodeOffset();
596
597     return codeBlock->handlerForIndex(exceptionHandlerIndex, requiredHandler);
598 }
599
600 class GetCatchHandlerFunctor {
601 public:
602     GetCatchHandlerFunctor()
603         : m_handler(0)
604     {
605     }
606
607     HandlerInfo* handler() { return m_handler; }
608
609     StackVisitor::Status operator()(StackVisitor& visitor) const
610     {
611         visitor.unwindToMachineCodeBlockFrame();
612
613         CodeBlock* codeBlock = visitor->codeBlock();
614         if (!codeBlock)
615             return StackVisitor::Continue;
616
617         m_handler = findExceptionHandler(visitor, codeBlock, RequiredHandler::CatchHandler);
618         if (m_handler)
619             return StackVisitor::Done;
620
621         return StackVisitor::Continue;
622     }
623
624 private:
625     mutable HandlerInfo* m_handler;
626 };
627
628 ALWAYS_INLINE static void notifyDebuggerOfUnwinding(VM& vm, CallFrame* callFrame)
629 {
630     auto catchScope = DECLARE_CATCH_SCOPE(vm);
631     if (Debugger* debugger = callFrame->vmEntryGlobalObject(vm)->debugger()) {
632         SuspendExceptionScope scope(&vm);
633         if (callFrame->isAnyWasmCallee()
634             || (callFrame->callee().isCell() && callFrame->callee().asCell()->inherits(vm, JSFunction::info())))
635             debugger->unwindEvent(callFrame);
636         else
637             debugger->didExecuteProgram(callFrame);
638         catchScope.assertNoException();
639     }
640 }
641
642 class UnwindFunctor {
643 public:
644     UnwindFunctor(VM& vm, CallFrame*& callFrame, bool isTermination, CodeBlock*& codeBlock, HandlerInfo*& handler)
645         : m_vm(vm)
646         , m_callFrame(callFrame)
647         , m_isTermination(isTermination)
648         , m_codeBlock(codeBlock)
649         , m_handler(handler)
650     {
651     }
652
653     StackVisitor::Status operator()(StackVisitor& visitor) const
654     {
655         visitor.unwindToMachineCodeBlockFrame();
656         m_callFrame = visitor->callFrame();
657         m_codeBlock = visitor->codeBlock();
658
659         m_handler = nullptr;
660         if (!m_isTermination) {
661             if (m_codeBlock) {
662                 m_handler = findExceptionHandler(visitor, m_codeBlock, RequiredHandler::AnyHandler);
663                 if (m_handler)
664                     return StackVisitor::Done;
665             }
666         }
667
668         notifyDebuggerOfUnwinding(m_vm, m_callFrame);
669
670         copyCalleeSavesToEntryFrameCalleeSavesBuffer(visitor);
671
672         bool shouldStopUnwinding = visitor->callerIsEntryFrame();
673         if (shouldStopUnwinding)
674             return StackVisitor::Done;
675
676         return StackVisitor::Continue;
677     }
678
679 private:
680     void copyCalleeSavesToEntryFrameCalleeSavesBuffer(StackVisitor& visitor) const
681     {
682 #if ENABLE(JIT) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
683         RegisterAtOffsetList* currentCalleeSaves = visitor->calleeSaveRegisters();
684
685         if (!currentCalleeSaves)
686             return;
687
688         RegisterAtOffsetList* allCalleeSaves = RegisterSet::vmCalleeSaveRegisterOffsets();
689         RegisterSet dontCopyRegisters = RegisterSet::stackRegisters();
690         intptr_t* frame = reinterpret_cast<intptr_t*>(m_callFrame->registers());
691
692         unsigned registerCount = currentCalleeSaves->size();
693         VMEntryRecord* record = vmEntryRecord(m_vm.topEntryFrame);
694         for (unsigned i = 0; i < registerCount; i++) {
695             RegisterAtOffset currentEntry = currentCalleeSaves->at(i);
696             if (dontCopyRegisters.get(currentEntry.reg()))
697                 continue;
698             RegisterAtOffset* calleeSavesEntry = allCalleeSaves->find(currentEntry.reg());
699             
700             record->calleeSaveRegistersBuffer[calleeSavesEntry->offsetAsIndex()] = *(frame + currentEntry.offsetAsIndex());
701         }
702 #else
703         UNUSED_PARAM(visitor);
704 #endif
705     }
706
707     VM& m_vm;
708     CallFrame*& m_callFrame;
709     bool m_isTermination;
710     CodeBlock*& m_codeBlock;
711     HandlerInfo*& m_handler;
712 };
713
714 NEVER_INLINE HandlerInfo* Interpreter::unwind(VM& vm, CallFrame*& callFrame, Exception* exception, UnwindStart unwindStart)
715 {
716     auto scope = DECLARE_CATCH_SCOPE(vm);
717
718     if (unwindStart == UnwindFromCallerFrame) {
719         if (callFrame->callerFrameOrEntryFrame() == vm.topEntryFrame)
720             return nullptr;
721
722         callFrame = callFrame->callerFrame();
723         vm.topCallFrame = callFrame;
724     }
725
726     CodeBlock* codeBlock = callFrame->codeBlock();
727
728     JSValue exceptionValue = exception->value();
729     ASSERT(!exceptionValue.isEmpty());
730     ASSERT(!exceptionValue.isCell() || exceptionValue.asCell());
731     // This shouldn't be possible (hence the assertions), but we're already in the slowest of
732     // slow cases, so let's harden against it anyway to be safe.
733     if (exceptionValue.isEmpty() || (exceptionValue.isCell() && !exceptionValue.asCell()))
734         exceptionValue = jsNull();
735
736     EXCEPTION_ASSERT_UNUSED(scope, scope.exception() && (!Options::exceptionStackTraceLimit() || scope.exception()->stack().size()));
737
738     // Calculate an exception handler vPC, unwinding call frames as necessary.
739     HandlerInfo* handler = nullptr;
740     UnwindFunctor functor(vm, callFrame, isTerminatedExecutionException(vm, exception), codeBlock, handler);
741     StackVisitor::visit(callFrame, &vm, functor);
742     if (!handler)
743         return nullptr;
744
745     return handler;
746 }
747
748 void Interpreter::notifyDebuggerOfExceptionToBeThrown(VM& vm, CallFrame* callFrame, Exception* exception)
749 {
750     Debugger* debugger = callFrame->vmEntryGlobalObject(vm)->debugger();
751     if (debugger && debugger->needsExceptionCallbacks() && !exception->didNotifyInspectorOfThrow()) {
752         // This code assumes that if the debugger is enabled then there is no inlining.
753         // If that assumption turns out to be false then we'll ignore the inlined call
754         // frames.
755         // https://bugs.webkit.org/show_bug.cgi?id=121754
756
757         bool hasCatchHandler;
758         bool isTermination = isTerminatedExecutionException(vm, exception);
759         if (isTermination)
760             hasCatchHandler = false;
761         else {
762             GetCatchHandlerFunctor functor;
763             StackVisitor::visit(callFrame, &vm, functor);
764             HandlerInfo* handler = functor.handler();
765             ASSERT(!handler || handler->isCatchHandler());
766             hasCatchHandler = !!handler;
767         }
768
769         debugger->exception(callFrame, exception->value(), hasCatchHandler);
770     }
771     exception->setDidNotifyInspectorOfThrow();
772 }
773
774 static inline JSValue checkedReturn(JSValue returnValue)
775 {
776     ASSERT(returnValue);
777     return returnValue;
778 }
779
780 static inline JSObject* checkedReturn(JSObject* returnValue)
781 {
782     ASSERT(returnValue);
783     return returnValue;
784 }
785
786 JSValue Interpreter::executeProgram(const SourceCode& source, CallFrame* callFrame, JSObject* thisObj)
787 {
788     JSScope* scope = thisObj->globalObject()->globalScope();
789     VM& vm = *scope->vm();
790     auto throwScope = DECLARE_THROW_SCOPE(vm);
791
792     ProgramExecutable* program = ProgramExecutable::create(callFrame, source);
793     EXCEPTION_ASSERT(throwScope.exception() || program);
794     RETURN_IF_EXCEPTION(throwScope, { });
795
796     throwScope.assertNoException();
797     ASSERT(!vm.isCollectorBusyOnCurrentThread());
798     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
799     if (vm.isCollectorBusyOnCurrentThread())
800         return jsNull();
801
802     if (UNLIKELY(!vm.isSafeToRecurseSoft()))
803         return checkedReturn(throwStackOverflowError(callFrame, throwScope));
804
805     // First check if the "program" is actually just a JSON object. If so,
806     // we'll handle the JSON object here. Else, we'll handle real JS code
807     // below at failedJSONP.
808
809     Vector<JSONPData> JSONPData;
810     bool parseResult;
811     StringView programSource = program->source().view();
812     if (programSource.isNull())
813         return jsUndefined();
814     if (programSource.is8Bit()) {
815         LiteralParser<LChar> literalParser(callFrame, programSource.characters8(), programSource.length(), JSONP);
816         parseResult = literalParser.tryJSONPParse(JSONPData, scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()));
817     } else {
818         LiteralParser<UChar> literalParser(callFrame, programSource.characters16(), programSource.length(), JSONP);
819         parseResult = literalParser.tryJSONPParse(JSONPData, scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()));
820     }
821
822     RETURN_IF_EXCEPTION(throwScope, { });
823     if (parseResult) {
824         JSGlobalObject* globalObject = scope->globalObject();
825         JSValue result;
826         for (unsigned entry = 0; entry < JSONPData.size(); entry++) {
827             Vector<JSONPPathEntry> JSONPPath;
828             JSONPPath.swap(JSONPData[entry].m_path);
829             JSValue JSONPValue = JSONPData[entry].m_value.get();
830             if (JSONPPath.size() == 1 && JSONPPath[0].m_type == JSONPPathEntryTypeDeclare) {
831                 globalObject->addVar(callFrame, JSONPPath[0].m_pathEntryName);
832                 RETURN_IF_EXCEPTION(throwScope, { });
833                 PutPropertySlot slot(globalObject);
834                 globalObject->methodTable(vm)->put(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, slot);
835                 RETURN_IF_EXCEPTION(throwScope, { });
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, PropertySlot::InternalMethodType::Get);
846                         if (!globalObject->getPropertySlot(callFrame, JSONPPath[i].m_pathEntryName, slot)) {
847                             RETURN_IF_EXCEPTION(throwScope, JSValue());
848                             if (entry)
849                                 return throwException(callFrame, throwScope, createUndefinedVariableError(callFrame, JSONPPath[i].m_pathEntryName));
850                             goto failedJSONP;
851                         }
852                         baseObject = slot.getValue(callFrame, JSONPPath[i].m_pathEntryName);
853                     } else
854                         baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathEntryName);
855                     RETURN_IF_EXCEPTION(throwScope, JSValue());
856                     continue;
857                 }
858                 case JSONPPathEntryTypeLookup: {
859                     baseObject = baseObject.get(callFrame, static_cast<unsigned>(JSONPPath[i].m_pathIndex));
860                     RETURN_IF_EXCEPTION(throwScope, JSValue());
861                     continue;
862                 }
863                 default:
864                     RELEASE_ASSERT_NOT_REACHED();
865                     return jsUndefined();
866                 }
867             }
868             PutPropertySlot slot(baseObject);
869             switch (JSONPPath.last().m_type) {
870             case JSONPPathEntryTypeCall: {
871                 JSValue function = baseObject.get(callFrame, JSONPPath.last().m_pathEntryName);
872                 RETURN_IF_EXCEPTION(throwScope, JSValue());
873                 CallData callData;
874                 CallType callType = getCallData(function, callData);
875                 if (callType == CallType::None)
876                     return throwException(callFrame, throwScope, createNotAFunctionError(callFrame, function));
877                 MarkedArgumentBuffer jsonArg;
878                 jsonArg.append(JSONPValue);
879                 ASSERT(!jsonArg.hasOverflowed());
880                 JSValue thisValue = JSONPPath.size() == 1 ? jsUndefined(): baseObject;
881                 JSONPValue = JSC::call(callFrame, function, callType, callData, thisValue, jsonArg);
882                 RETURN_IF_EXCEPTION(throwScope, JSValue());
883                 break;
884             }
885             case JSONPPathEntryTypeDot: {
886                 baseObject.put(callFrame, JSONPPath.last().m_pathEntryName, JSONPValue, slot);
887                 RETURN_IF_EXCEPTION(throwScope, JSValue());
888                 break;
889             }
890             case JSONPPathEntryTypeLookup: {
891                 baseObject.putByIndex(callFrame, JSONPPath.last().m_pathIndex, JSONPValue, slot.isStrictMode());
892                 RETURN_IF_EXCEPTION(throwScope, JSValue());
893                 break;
894             }
895             default:
896                 RELEASE_ASSERT_NOT_REACHED();
897                     return jsUndefined();
898             }
899             result = JSONPValue;
900         }
901         return result;
902     }
903 failedJSONP:
904     // If we get here, then we have already proven that the script is not a JSON
905     // object.
906
907     VMEntryScope entryScope(vm, scope->globalObject());
908
909     // Compile source to bytecode if necessary:
910     JSObject* error = program->initializeGlobalProperties(vm, callFrame, scope);
911     EXCEPTION_ASSERT(!throwScope.exception() || !error);
912     if (UNLIKELY(error))
913         return checkedReturn(throwException(callFrame, throwScope, error));
914
915     ProgramCodeBlock* codeBlock;
916     {
917         CodeBlock* tempCodeBlock;
918         JSObject* error = program->prepareForExecution<ProgramExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
919         EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(error));
920         if (UNLIKELY(error))
921             return checkedReturn(error);
922         codeBlock = jsCast<ProgramCodeBlock*>(tempCodeBlock);
923     }
924
925     VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
926     if (UNLIKELY(vm.needTrapHandling(mask))) {
927         vm.handleTraps(callFrame, mask);
928         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
929     }
930
931     if (scope->structure()->isUncacheableDictionary())
932         scope->flattenDictionaryObject(vm);
933
934     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
935
936     ProtoCallFrame protoCallFrame;
937     protoCallFrame.init(codeBlock, JSCallee::create(vm, scope->globalObject(), scope), thisObj, 1);
938
939     // Execute the code:
940     throwScope.release();
941     JSValue result = program->generatedJITCode()->execute(&vm, &protoCallFrame);
942     return checkedReturn(result);
943 }
944
945 JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
946 {
947     VM& vm = callFrame->vm();
948     auto throwScope = DECLARE_THROW_SCOPE(vm);
949
950     throwScope.assertNoException();
951     ASSERT(!vm.isCollectorBusyOnCurrentThread());
952     if (vm.isCollectorBusyOnCurrentThread())
953         return jsNull();
954
955     bool isJSCall = (callType == CallType::JS);
956     JSScope* scope = nullptr;
957     CodeBlock* newCodeBlock;
958     size_t argsCount = 1 + args.size(); // implicit "this" parameter
959
960     JSGlobalObject* globalObject;
961
962     if (isJSCall) {
963         scope = callData.js.scope;
964         globalObject = scope->globalObject();
965     } else {
966         ASSERT(callType == CallType::Host);
967         globalObject = function->globalObject();
968     }
969
970     VMEntryScope entryScope(vm, globalObject);
971     if (UNLIKELY(!vm.isSafeToRecurseSoft()))
972         return checkedReturn(throwStackOverflowError(callFrame, throwScope));
973
974     if (isJSCall) {
975         // Compile the callee:
976         JSObject* compileError = callData.js.functionExecutable->prepareForExecution<FunctionExecutable>(vm, jsCast<JSFunction*>(function), scope, CodeForCall, newCodeBlock);
977         EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(compileError));
978         if (UNLIKELY(!!compileError))
979             return checkedReturn(compileError);
980
981         ASSERT(!!newCodeBlock);
982         newCodeBlock->m_shouldAlwaysBeInlined = false;
983     } else
984         newCodeBlock = 0;
985
986     VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
987     if (UNLIKELY(vm.needTrapHandling(mask))) {
988         vm.handleTraps(callFrame, mask);
989         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
990     }
991
992     ProtoCallFrame protoCallFrame;
993     protoCallFrame.init(newCodeBlock, function, thisValue, argsCount, args.data());
994
995     JSValue result;
996     {
997         // Execute the code:
998         if (isJSCall) {
999             throwScope.release();
1000             result = callData.js.functionExecutable->generatedJITCodeForCall()->execute(&vm, &protoCallFrame);
1001         } else {
1002             result = JSValue::decode(vmEntryToNative(reinterpret_cast<void*>(callData.native.function), &vm, &protoCallFrame));
1003             RETURN_IF_EXCEPTION(throwScope, JSValue());
1004         }
1005     }
1006
1007     return checkedReturn(result);
1008 }
1009
1010 JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args, JSValue newTarget)
1011 {
1012     VM& vm = callFrame->vm();
1013     auto throwScope = DECLARE_THROW_SCOPE(vm);
1014
1015     throwScope.assertNoException();
1016     ASSERT(!vm.isCollectorBusyOnCurrentThread());
1017     // We throw in this case because we have to return something "valid" but we're
1018     // already in an invalid state.
1019     if (vm.isCollectorBusyOnCurrentThread())
1020         return checkedReturn(throwStackOverflowError(callFrame, throwScope));
1021
1022     bool isJSConstruct = (constructType == ConstructType::JS);
1023     JSScope* scope = nullptr;
1024     CodeBlock* newCodeBlock;
1025     size_t argsCount = 1 + args.size(); // implicit "this" parameter
1026
1027     JSGlobalObject* globalObject;
1028
1029     if (isJSConstruct) {
1030         scope = constructData.js.scope;
1031         globalObject = scope->globalObject();
1032     } else {
1033         ASSERT(constructType == ConstructType::Host);
1034         globalObject = constructor->globalObject();
1035     }
1036
1037     VMEntryScope entryScope(vm, globalObject);
1038     if (UNLIKELY(!vm.isSafeToRecurseSoft()))
1039         return checkedReturn(throwStackOverflowError(callFrame, throwScope));
1040
1041     if (isJSConstruct) {
1042         // Compile the callee:
1043         JSObject* compileError = constructData.js.functionExecutable->prepareForExecution<FunctionExecutable>(vm, jsCast<JSFunction*>(constructor), scope, CodeForConstruct, newCodeBlock);
1044         EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(compileError));
1045         if (UNLIKELY(!!compileError))
1046             return checkedReturn(compileError);
1047
1048         ASSERT(!!newCodeBlock);
1049         newCodeBlock->m_shouldAlwaysBeInlined = false;
1050     } else
1051         newCodeBlock = 0;
1052
1053     VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
1054     if (UNLIKELY(vm.needTrapHandling(mask))) {
1055         vm.handleTraps(callFrame, mask);
1056         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
1057     }
1058
1059     ProtoCallFrame protoCallFrame;
1060     protoCallFrame.init(newCodeBlock, constructor, newTarget, argsCount, args.data());
1061
1062     JSValue result;
1063     {
1064         // Execute the code.
1065         if (isJSConstruct)
1066             result = constructData.js.functionExecutable->generatedJITCodeForConstruct()->execute(&vm, &protoCallFrame);
1067         else {
1068             result = JSValue::decode(vmEntryToNative(reinterpret_cast<void*>(constructData.native.function), &vm, &protoCallFrame));
1069
1070             if (LIKELY(!throwScope.exception()))
1071                 RELEASE_ASSERT(result.isObject());
1072         }
1073     }
1074
1075     RETURN_IF_EXCEPTION(throwScope, 0);
1076     ASSERT(result.isObject());
1077     return checkedReturn(asObject(result));
1078 }
1079
1080 CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionExecutable, CallFrame* callFrame, ProtoCallFrame* protoCallFrame, JSFunction* function, int argumentCountIncludingThis, JSScope* scope, const ArgList& args)
1081 {
1082     VM& vm = *scope->vm();
1083     auto throwScope = DECLARE_THROW_SCOPE(vm);
1084     throwScope.assertNoException();
1085     
1086     if (vm.isCollectorBusyOnCurrentThread())
1087         return CallFrameClosure();
1088
1089     // Compile the callee:
1090     CodeBlock* newCodeBlock;
1091     JSObject* error = functionExecutable->prepareForExecution<FunctionExecutable>(vm, function, scope, CodeForCall, newCodeBlock);
1092     EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(error));
1093     if (UNLIKELY(error))
1094         return CallFrameClosure();
1095     newCodeBlock->m_shouldAlwaysBeInlined = false;
1096
1097     size_t argsCount = argumentCountIncludingThis;
1098
1099     protoCallFrame->init(newCodeBlock, function, jsUndefined(), argsCount, args.data());
1100     // Return the successful closure:
1101     CallFrameClosure result = { callFrame, protoCallFrame, function, functionExecutable, &vm, scope, newCodeBlock->numParameters(), argumentCountIncludingThis };
1102     return result;
1103 }
1104
1105 JSValue Interpreter::execute(CallFrameClosure& closure) 
1106 {
1107     VM& vm = *closure.vm;
1108     auto throwScope = DECLARE_THROW_SCOPE(vm);
1109
1110     ASSERT(!vm.isCollectorBusyOnCurrentThread());
1111     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
1112     if (vm.isCollectorBusyOnCurrentThread())
1113         return jsNull();
1114
1115     StackStats::CheckPoint stackCheckPoint;
1116
1117     VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
1118     if (UNLIKELY(vm.needTrapHandling(mask))) {
1119         vm.handleTraps(closure.oldCallFrame, mask);
1120         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
1121     }
1122
1123     // Execute the code:
1124     throwScope.release();
1125     JSValue result = closure.functionExecutable->generatedJITCodeForCall()->execute(&vm, closure.protoCallFrame);
1126
1127     return checkedReturn(result);
1128 }
1129
1130 JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, JSScope* scope)
1131 {
1132     VM& vm = *scope->vm();
1133     auto throwScope = DECLARE_THROW_SCOPE(vm);
1134
1135     ASSERT(&vm == &callFrame->vm());
1136     throwScope.assertNoException();
1137     ASSERT(!vm.isCollectorBusyOnCurrentThread());
1138     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
1139     if (vm.isCollectorBusyOnCurrentThread())
1140         return jsNull();
1141
1142     VMEntryScope entryScope(vm, scope->globalObject());
1143     if (UNLIKELY(!vm.isSafeToRecurseSoft()))
1144         return checkedReturn(throwStackOverflowError(callFrame, throwScope));
1145
1146     unsigned numVariables = eval->numVariables();
1147     unsigned numTopLevelFunctionDecls = eval->numTopLevelFunctionDecls();
1148     unsigned numFunctionHoistingCandidates = eval->numFunctionHoistingCandidates();
1149
1150     JSScope* variableObject;
1151     if ((numVariables || numTopLevelFunctionDecls) && eval->isStrictMode()) {
1152         scope = StrictEvalActivation::create(callFrame, scope);
1153         variableObject = scope;
1154     } else {
1155         for (JSScope* node = scope; ; node = node->next()) {
1156             RELEASE_ASSERT(node);
1157             if (node->isGlobalObject()) {
1158                 variableObject = node;
1159                 break;
1160             } 
1161             if (node->isJSLexicalEnvironment()) {
1162                 JSLexicalEnvironment* lexicalEnvironment = jsCast<JSLexicalEnvironment*>(node);
1163                 if (lexicalEnvironment->symbolTable()->scopeType() == SymbolTable::ScopeType::VarScope) {
1164                     variableObject = node;
1165                     break;
1166                 }
1167             }
1168         }
1169     }
1170
1171     EvalCodeBlock* codeBlock;
1172     {
1173         CodeBlock* tempCodeBlock;
1174         JSObject* compileError = eval->prepareForExecution<EvalExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
1175         EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(compileError));
1176         if (UNLIKELY(!!compileError))
1177             return checkedReturn(compileError);
1178         codeBlock = jsCast<EvalCodeBlock*>(tempCodeBlock);
1179     }
1180
1181     // We can't declare a "var"/"function" that overwrites a global "let"/"const"/"class" in a sloppy-mode eval.
1182     if (variableObject->isGlobalObject() && !eval->isStrictMode() && (numVariables || numTopLevelFunctionDecls)) {
1183         JSGlobalLexicalEnvironment* globalLexicalEnvironment = jsCast<JSGlobalObject*>(variableObject)->globalLexicalEnvironment();
1184         for (unsigned i = 0; i < numVariables; ++i) {
1185             const Identifier& ident = codeBlock->variable(i);
1186             PropertySlot slot(globalLexicalEnvironment, PropertySlot::InternalMethodType::VMInquiry);
1187             if (JSGlobalLexicalEnvironment::getOwnPropertySlot(globalLexicalEnvironment, callFrame, ident, slot)) {
1188                 return checkedReturn(throwTypeError(callFrame, throwScope, makeString("Can't create duplicate global variable in eval: '", String(ident.impl()), "'")));
1189             }
1190         }
1191
1192         for (unsigned i = 0; i < numTopLevelFunctionDecls; ++i) {
1193             FunctionExecutable* function = codeBlock->functionDecl(i);
1194             PropertySlot slot(globalLexicalEnvironment, PropertySlot::InternalMethodType::VMInquiry);
1195             if (JSGlobalLexicalEnvironment::getOwnPropertySlot(globalLexicalEnvironment, callFrame, function->name(), slot)) {
1196                 return checkedReturn(throwTypeError(callFrame, throwScope, makeString("Can't create duplicate global variable in eval: '", String(function->name().impl()), "'")));
1197             }
1198         }
1199     }
1200
1201     if (variableObject->structure()->isUncacheableDictionary())
1202         variableObject->flattenDictionaryObject(vm);
1203
1204     if (numVariables || numTopLevelFunctionDecls || numFunctionHoistingCandidates) {
1205         BatchedTransitionOptimizer optimizer(vm, variableObject);
1206         if (variableObject->next() && !eval->isStrictMode())
1207             variableObject->globalObject()->varInjectionWatchpoint()->fireAll(vm, "Executed eval, fired VarInjection watchpoint");
1208
1209         for (unsigned i = 0; i < numVariables; ++i) {
1210             const Identifier& ident = codeBlock->variable(i);
1211             bool hasProperty = variableObject->hasProperty(callFrame, ident);
1212             RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1213             if (!hasProperty) {
1214                 PutPropertySlot slot(variableObject);
1215                 if (!variableObject->isExtensible(callFrame))
1216                     return checkedReturn(throwTypeError(callFrame, throwScope, ASCIILiteral(NonExtensibleObjectPropertyDefineError)));
1217                 variableObject->methodTable(vm)->put(variableObject, callFrame, ident, jsUndefined(), slot);
1218                 RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1219             }
1220         }
1221         
1222         if (eval->isStrictMode()) {
1223             for (unsigned i = 0; i < numTopLevelFunctionDecls; ++i) {
1224                 FunctionExecutable* function = codeBlock->functionDecl(i);
1225                 PutPropertySlot slot(variableObject);
1226                 // We need create this variables because it will be used to emits code by bytecode generator
1227                 variableObject->methodTable(vm)->put(variableObject, callFrame, function->name(), jsUndefined(), slot);
1228                 RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1229             }
1230         } else {
1231             for (unsigned i = 0; i < numTopLevelFunctionDecls; ++i) {
1232                 FunctionExecutable* function = codeBlock->functionDecl(i);
1233                 JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(callFrame, scope, function->name());
1234                 RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1235                 if (resolvedScope.isUndefined())
1236                     return checkedReturn(throwSyntaxError(callFrame, throwScope, makeString("Can't create duplicate variable in eval: '", String(function->name().impl()), "'")));
1237                 PutPropertySlot slot(variableObject);
1238                 // We need create this variables because it will be used to emits code by bytecode generator
1239                 variableObject->methodTable(vm)->put(variableObject, callFrame, function->name(), jsUndefined(), slot);
1240                 RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1241             }
1242
1243             for (unsigned i = 0; i < numFunctionHoistingCandidates; ++i) {
1244                 const Identifier& ident = codeBlock->functionHoistingCandidate(i);
1245                 JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(callFrame, scope, ident);
1246                 RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1247                 if (!resolvedScope.isUndefined()) {
1248                     bool hasProperty = variableObject->hasProperty(callFrame, ident);
1249                     RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1250                     if (!hasProperty) {
1251                         PutPropertySlot slot(variableObject);
1252                         variableObject->methodTable(vm)->put(variableObject, callFrame, ident, jsUndefined(), slot);
1253                         RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1254                     }
1255                 }
1256             }
1257         }
1258     }
1259
1260     VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
1261     if (UNLIKELY(vm.needTrapHandling(mask))) {
1262         vm.handleTraps(callFrame, mask);
1263         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
1264     }
1265
1266     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
1267
1268     ProtoCallFrame protoCallFrame;
1269     protoCallFrame.init(codeBlock, JSCallee::create(vm, scope->globalObject(), scope), thisValue, 1);
1270
1271     // Execute the code:
1272     throwScope.release();
1273     JSValue result = eval->generatedJITCode()->execute(&vm, &protoCallFrame);
1274
1275     return checkedReturn(result);
1276 }
1277
1278 JSValue Interpreter::executeModuleProgram(ModuleProgramExecutable* executable, CallFrame* callFrame, JSModuleEnvironment* scope)
1279 {
1280     VM& vm = *scope->vm();
1281     auto throwScope = DECLARE_THROW_SCOPE(vm);
1282
1283     ASSERT(&vm == &callFrame->vm());
1284     throwScope.assertNoException();
1285     ASSERT(!vm.isCollectorBusyOnCurrentThread());
1286     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
1287     if (vm.isCollectorBusyOnCurrentThread())
1288         return jsNull();
1289
1290     VMEntryScope entryScope(vm, scope->globalObject());
1291     if (UNLIKELY(!vm.isSafeToRecurseSoft()))
1292         return checkedReturn(throwStackOverflowError(callFrame, throwScope));
1293
1294     ModuleProgramCodeBlock* codeBlock;
1295     {
1296         CodeBlock* tempCodeBlock;
1297         JSObject* compileError = executable->prepareForExecution<ModuleProgramExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
1298         EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(compileError));
1299         if (UNLIKELY(!!compileError))
1300             return checkedReturn(compileError);
1301         codeBlock = jsCast<ModuleProgramCodeBlock*>(tempCodeBlock);
1302     }
1303
1304     VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
1305     if (UNLIKELY(vm.needTrapHandling(mask))) {
1306         vm.handleTraps(callFrame, mask);
1307         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
1308     }
1309
1310     if (scope->structure()->isUncacheableDictionary())
1311         scope->flattenDictionaryObject(vm);
1312
1313     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
1314
1315     // The |this| of the module is always `undefined`.
1316     // http://www.ecma-international.org/ecma-262/6.0/#sec-module-environment-records-hasthisbinding
1317     // http://www.ecma-international.org/ecma-262/6.0/#sec-module-environment-records-getthisbinding
1318     ProtoCallFrame protoCallFrame;
1319     protoCallFrame.init(codeBlock, JSCallee::create(vm, scope->globalObject(), scope), jsUndefined(), 1);
1320
1321     // Execute the code:
1322     throwScope.release();
1323     JSValue result = executable->generatedJITCode()->execute(&vm, &protoCallFrame);
1324
1325     return checkedReturn(result);
1326 }
1327
1328 NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookType debugHookType)
1329 {
1330     VM& vm = callFrame->vm();
1331     auto scope = DECLARE_CATCH_SCOPE(vm);
1332     Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger();
1333     if (!debugger)
1334         return;
1335
1336     ASSERT(callFrame->codeBlock()->hasDebuggerRequests());
1337     scope.assertNoException();
1338
1339     switch (debugHookType) {
1340         case DidEnterCallFrame:
1341             debugger->callEvent(callFrame);
1342             break;
1343         case WillLeaveCallFrame:
1344             debugger->returnEvent(callFrame);
1345             break;
1346         case WillExecuteStatement:
1347             debugger->atStatement(callFrame);
1348             break;
1349         case WillExecuteExpression:
1350             debugger->atExpression(callFrame);
1351             break;
1352         case WillExecuteProgram:
1353             debugger->willExecuteProgram(callFrame);
1354             break;
1355         case DidExecuteProgram:
1356             debugger->didExecuteProgram(callFrame);
1357             break;
1358         case DidReachBreakpoint:
1359             debugger->didReachBreakpoint(callFrame);
1360             break;
1361     }
1362     scope.assertNoException();
1363 }
1364
1365 } // namespace JSC