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