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