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