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