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