1a662eaef66523da88e48e3ac87b27bb4d727820
[WebKit-https.git] / Source / JavaScriptCore / interpreter / Interpreter.cpp
1 /*
2  * Copyright (C) 2008-2018 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         JSObject* error = program->prepareForExecution<ProgramExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
812         EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<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         JSObject* compileError = callData.js.functionExecutable->prepareForExecution<FunctionExecutable>(vm, jsCast<JSFunction*>(function), scope, CodeForCall, newCodeBlock);
870         EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<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 (vm.isCollectorBusyOnCurrentThread())
913         return checkedReturn(throwStackOverflowError(callFrame, throwScope));
914
915     bool isJSConstruct = (constructType == ConstructType::JS);
916     JSScope* scope = nullptr;
917     CodeBlock* newCodeBlock;
918     size_t argsCount = 1 + args.size(); // implicit "this" parameter
919
920     JSGlobalObject* globalObject;
921
922     if (isJSConstruct) {
923         scope = constructData.js.scope;
924         globalObject = scope->globalObject(vm);
925     } else {
926         ASSERT(constructType == ConstructType::Host);
927         globalObject = constructor->globalObject(vm);
928     }
929
930     VMEntryScope entryScope(vm, globalObject);
931     if (UNLIKELY(!vm.isSafeToRecurseSoft()))
932         return checkedReturn(throwStackOverflowError(callFrame, throwScope));
933
934     if (isJSConstruct) {
935         // Compile the callee:
936         JSObject* compileError = constructData.js.functionExecutable->prepareForExecution<FunctionExecutable>(vm, jsCast<JSFunction*>(constructor), scope, CodeForConstruct, newCodeBlock);
937         EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(compileError));
938         if (UNLIKELY(!!compileError))
939             return checkedReturn(compileError);
940
941         ASSERT(!!newCodeBlock);
942         newCodeBlock->m_shouldAlwaysBeInlined = false;
943     } else
944         newCodeBlock = 0;
945
946     VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
947     if (UNLIKELY(vm.needTrapHandling(mask))) {
948         vm.handleTraps(callFrame, mask);
949         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
950     }
951
952     ProtoCallFrame protoCallFrame;
953     protoCallFrame.init(newCodeBlock, constructor, newTarget, argsCount, args.data());
954
955     JSValue result;
956     {
957         // Execute the code.
958         if (isJSConstruct)
959             result = constructData.js.functionExecutable->generatedJITCodeForConstruct()->execute(&vm, &protoCallFrame);
960         else {
961             result = JSValue::decode(vmEntryToNative(constructData.native.function.rawPointer(), &vm, &protoCallFrame));
962
963             if (LIKELY(!throwScope.exception()))
964                 RELEASE_ASSERT(result.isObject());
965         }
966     }
967
968     RETURN_IF_EXCEPTION(throwScope, 0);
969     ASSERT(result.isObject());
970     return checkedReturn(asObject(result));
971 }
972
973 CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionExecutable, CallFrame* callFrame, ProtoCallFrame* protoCallFrame, JSFunction* function, int argumentCountIncludingThis, JSScope* scope, const ArgList& args)
974 {
975     VM& vm = *scope->vm();
976     auto throwScope = DECLARE_THROW_SCOPE(vm);
977     throwScope.assertNoException();
978     
979     if (vm.isCollectorBusyOnCurrentThread())
980         return CallFrameClosure();
981
982     // Compile the callee:
983     CodeBlock* newCodeBlock;
984     JSObject* error = functionExecutable->prepareForExecution<FunctionExecutable>(vm, function, scope, CodeForCall, newCodeBlock);
985     EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(error));
986     if (UNLIKELY(error))
987         return CallFrameClosure();
988     newCodeBlock->m_shouldAlwaysBeInlined = false;
989
990     size_t argsCount = argumentCountIncludingThis;
991
992     protoCallFrame->init(newCodeBlock, function, jsUndefined(), argsCount, args.data());
993     // Return the successful closure:
994     CallFrameClosure result = { callFrame, protoCallFrame, function, functionExecutable, &vm, scope, newCodeBlock->numParameters(), argumentCountIncludingThis };
995     return result;
996 }
997
998 JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, JSScope* scope)
999 {
1000     VM& vm = *scope->vm();
1001     auto throwScope = DECLARE_THROW_SCOPE(vm);
1002
1003     ASSERT(&vm == &callFrame->vm());
1004     throwScope.assertNoException();
1005     ASSERT(!vm.isCollectorBusyOnCurrentThread());
1006     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
1007     if (vm.isCollectorBusyOnCurrentThread())
1008         return jsNull();
1009
1010     VMEntryScope entryScope(vm, scope->globalObject(vm));
1011     if (UNLIKELY(!vm.isSafeToRecurseSoft()))
1012         return checkedReturn(throwStackOverflowError(callFrame, throwScope));
1013
1014     unsigned numVariables = eval->numVariables();
1015     unsigned numTopLevelFunctionDecls = eval->numTopLevelFunctionDecls();
1016     unsigned numFunctionHoistingCandidates = eval->numFunctionHoistingCandidates();
1017
1018     JSScope* variableObject;
1019     if ((numVariables || numTopLevelFunctionDecls) && eval->isStrictMode()) {
1020         scope = StrictEvalActivation::create(callFrame, scope);
1021         variableObject = scope;
1022     } else {
1023         for (JSScope* node = scope; ; node = node->next()) {
1024             RELEASE_ASSERT(node);
1025             if (node->isGlobalObject()) {
1026                 variableObject = node;
1027                 break;
1028             } 
1029             if (node->isJSLexicalEnvironment()) {
1030                 JSLexicalEnvironment* lexicalEnvironment = jsCast<JSLexicalEnvironment*>(node);
1031                 if (lexicalEnvironment->symbolTable()->scopeType() == SymbolTable::ScopeType::VarScope) {
1032                     variableObject = node;
1033                     break;
1034                 }
1035             }
1036         }
1037     }
1038
1039     EvalCodeBlock* codeBlock;
1040     {
1041         CodeBlock* tempCodeBlock;
1042         JSObject* compileError = eval->prepareForExecution<EvalExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
1043         EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(compileError));
1044         if (UNLIKELY(!!compileError))
1045             return checkedReturn(compileError);
1046         codeBlock = jsCast<EvalCodeBlock*>(tempCodeBlock);
1047     }
1048     UnlinkedEvalCodeBlock* unlinkedCodeBlock = codeBlock->unlinkedEvalCodeBlock();
1049
1050     // We can't declare a "var"/"function" that overwrites a global "let"/"const"/"class" in a sloppy-mode eval.
1051     if (variableObject->isGlobalObject() && !eval->isStrictMode() && (numVariables || numTopLevelFunctionDecls)) {
1052         JSGlobalLexicalEnvironment* globalLexicalEnvironment = jsCast<JSGlobalObject*>(variableObject)->globalLexicalEnvironment();
1053         for (unsigned i = 0; i < numVariables; ++i) {
1054             const Identifier& ident = unlinkedCodeBlock->variable(i);
1055             PropertySlot slot(globalLexicalEnvironment, PropertySlot::InternalMethodType::VMInquiry);
1056             if (JSGlobalLexicalEnvironment::getOwnPropertySlot(globalLexicalEnvironment, callFrame, ident, slot)) {
1057                 return checkedReturn(throwTypeError(callFrame, throwScope, makeString("Can't create duplicate global variable in eval: '", String(ident.impl()), "'")));
1058             }
1059         }
1060
1061         for (unsigned i = 0; i < numTopLevelFunctionDecls; ++i) {
1062             FunctionExecutable* function = codeBlock->functionDecl(i);
1063             PropertySlot slot(globalLexicalEnvironment, PropertySlot::InternalMethodType::VMInquiry);
1064             if (JSGlobalLexicalEnvironment::getOwnPropertySlot(globalLexicalEnvironment, callFrame, function->name(), slot)) {
1065                 return checkedReturn(throwTypeError(callFrame, throwScope, makeString("Can't create duplicate global variable in eval: '", String(function->name().impl()), "'")));
1066             }
1067         }
1068     }
1069
1070     if (variableObject->structure(vm)->isUncacheableDictionary())
1071         variableObject->flattenDictionaryObject(vm);
1072
1073     if (numVariables || numTopLevelFunctionDecls || numFunctionHoistingCandidates) {
1074         BatchedTransitionOptimizer optimizer(vm, variableObject);
1075         if (variableObject->next() && !eval->isStrictMode())
1076             variableObject->globalObject(vm)->varInjectionWatchpoint()->fireAll(vm, "Executed eval, fired VarInjection watchpoint");
1077
1078         for (unsigned i = 0; i < numVariables; ++i) {
1079             const Identifier& ident = unlinkedCodeBlock->variable(i);
1080             bool hasProperty = variableObject->hasProperty(callFrame, ident);
1081             RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1082             if (!hasProperty) {
1083                 PutPropertySlot slot(variableObject);
1084                 if (!variableObject->isExtensible(callFrame))
1085                     return checkedReturn(throwTypeError(callFrame, throwScope, NonExtensibleObjectPropertyDefineError));
1086                 variableObject->methodTable(vm)->put(variableObject, callFrame, ident, jsUndefined(), slot);
1087                 RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1088             }
1089         }
1090         
1091         if (eval->isStrictMode()) {
1092             for (unsigned i = 0; i < numTopLevelFunctionDecls; ++i) {
1093                 FunctionExecutable* function = codeBlock->functionDecl(i);
1094                 PutPropertySlot slot(variableObject);
1095                 // We need create this variables because it will be used to emits code by bytecode generator
1096                 variableObject->methodTable(vm)->put(variableObject, callFrame, function->name(), jsUndefined(), slot);
1097                 RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1098             }
1099         } else {
1100             for (unsigned i = 0; i < numTopLevelFunctionDecls; ++i) {
1101                 FunctionExecutable* function = codeBlock->functionDecl(i);
1102                 JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(callFrame, scope, function->name());
1103                 RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1104                 if (resolvedScope.isUndefined())
1105                     return checkedReturn(throwSyntaxError(callFrame, throwScope, makeString("Can't create duplicate variable in eval: '", String(function->name().impl()), "'")));
1106                 PutPropertySlot slot(variableObject);
1107                 // We need create this variables because it will be used to emits code by bytecode generator
1108                 variableObject->methodTable(vm)->put(variableObject, callFrame, function->name(), jsUndefined(), slot);
1109                 RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1110             }
1111
1112             for (unsigned i = 0; i < numFunctionHoistingCandidates; ++i) {
1113                 const Identifier& ident = unlinkedCodeBlock->functionHoistingCandidate(i);
1114                 JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(callFrame, scope, ident);
1115                 RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1116                 if (!resolvedScope.isUndefined()) {
1117                     bool hasProperty = variableObject->hasProperty(callFrame, ident);
1118                     RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1119                     if (!hasProperty) {
1120                         PutPropertySlot slot(variableObject);
1121                         variableObject->methodTable(vm)->put(variableObject, callFrame, ident, jsUndefined(), slot);
1122                         RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1123                     }
1124                 }
1125             }
1126         }
1127     }
1128
1129     VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
1130     if (UNLIKELY(vm.needTrapHandling(mask))) {
1131         vm.handleTraps(callFrame, mask);
1132         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
1133     }
1134
1135     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
1136
1137     ProtoCallFrame protoCallFrame;
1138     protoCallFrame.init(codeBlock, JSCallee::create(vm, scope->globalObject(vm), scope), thisValue, 1);
1139
1140     // Execute the code:
1141     throwScope.release();
1142     JSValue result = eval->generatedJITCode()->execute(&vm, &protoCallFrame);
1143
1144     return checkedReturn(result);
1145 }
1146
1147 JSValue Interpreter::executeModuleProgram(ModuleProgramExecutable* executable, CallFrame* callFrame, JSModuleEnvironment* scope)
1148 {
1149     VM& vm = *scope->vm();
1150     auto throwScope = DECLARE_THROW_SCOPE(vm);
1151
1152     ASSERT(&vm == &callFrame->vm());
1153     throwScope.assertNoException();
1154     ASSERT(!vm.isCollectorBusyOnCurrentThread());
1155     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
1156     if (vm.isCollectorBusyOnCurrentThread())
1157         return jsNull();
1158
1159     VMEntryScope entryScope(vm, scope->globalObject(vm));
1160     if (UNLIKELY(!vm.isSafeToRecurseSoft()))
1161         return checkedReturn(throwStackOverflowError(callFrame, throwScope));
1162
1163     ModuleProgramCodeBlock* codeBlock;
1164     {
1165         CodeBlock* tempCodeBlock;
1166         JSObject* compileError = executable->prepareForExecution<ModuleProgramExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
1167         EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(compileError));
1168         if (UNLIKELY(!!compileError))
1169             return checkedReturn(compileError);
1170         codeBlock = jsCast<ModuleProgramCodeBlock*>(tempCodeBlock);
1171     }
1172
1173     VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
1174     if (UNLIKELY(vm.needTrapHandling(mask))) {
1175         vm.handleTraps(callFrame, mask);
1176         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
1177     }
1178
1179     if (scope->structure(vm)->isUncacheableDictionary())
1180         scope->flattenDictionaryObject(vm);
1181
1182     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
1183
1184     // The |this| of the module is always `undefined`.
1185     // http://www.ecma-international.org/ecma-262/6.0/#sec-module-environment-records-hasthisbinding
1186     // http://www.ecma-international.org/ecma-262/6.0/#sec-module-environment-records-getthisbinding
1187     ProtoCallFrame protoCallFrame;
1188     protoCallFrame.init(codeBlock, JSCallee::create(vm, scope->globalObject(vm), scope), jsUndefined(), 1);
1189
1190     // Execute the code:
1191     throwScope.release();
1192     JSValue result = executable->generatedJITCode()->execute(&vm, &protoCallFrame);
1193
1194     return checkedReturn(result);
1195 }
1196
1197 NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookType debugHookType)
1198 {
1199     VM& vm = callFrame->vm();
1200     auto scope = DECLARE_CATCH_SCOPE(vm);
1201     Debugger* debugger = vm.vmEntryGlobalObject(callFrame)->debugger();
1202     if (!debugger)
1203         return;
1204
1205     ASSERT(callFrame->codeBlock()->hasDebuggerRequests());
1206     scope.assertNoException();
1207
1208     switch (debugHookType) {
1209         case DidEnterCallFrame:
1210             debugger->callEvent(callFrame);
1211             break;
1212         case WillLeaveCallFrame:
1213             debugger->returnEvent(callFrame);
1214             break;
1215         case WillExecuteStatement:
1216             debugger->atStatement(callFrame);
1217             break;
1218         case WillExecuteExpression:
1219             debugger->atExpression(callFrame);
1220             break;
1221         case WillExecuteProgram:
1222             debugger->willExecuteProgram(callFrame);
1223             break;
1224         case DidExecuteProgram:
1225             debugger->didExecuteProgram(callFrame);
1226             break;
1227         case DidReachBreakpoint:
1228             debugger->didReachBreakpoint(callFrame);
1229             break;
1230     }
1231     scope.assertNoException();
1232 }
1233
1234 } // namespace JSC
1235
1236 namespace WTF {
1237
1238 void printInternal(PrintStream& out, JSC::DebugHookType type)
1239 {
1240     switch (type) {
1241     case JSC::WillExecuteProgram:
1242         out.print("WillExecuteProgram");
1243         return;
1244     case JSC::DidExecuteProgram:
1245         out.print("DidExecuteProgram");
1246         return;
1247     case JSC::DidEnterCallFrame:
1248         out.print("DidEnterCallFrame");
1249         return;
1250     case JSC::DidReachBreakpoint:
1251         out.print("DidReachBreakpoint");
1252         return;
1253     case JSC::WillLeaveCallFrame:
1254         out.print("WillLeaveCallFrame");
1255         return;
1256     case JSC::WillExecuteStatement:
1257         out.print("WillExecuteStatement");
1258         return;
1259     case JSC::WillExecuteExpression:
1260         out.print("WillExecuteExpression");
1261         return;
1262     }
1263 }
1264
1265 } // namespace WTF