Teach Call ICs how to call Wasm
[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 #if ENABLE(WEBASSEMBLY)
553         if (visitor->callee().isCell()) {
554             if (auto* jsToWasmICCallee = jsDynamicCast<JSToWasmICCallee*>(m_vm, visitor->callee().asCell()))
555                 m_vm.wasmContext.store(jsToWasmICCallee->function()->previousInstance(m_callFrame), m_vm.softStackLimit());
556         }
557 #endif
558
559         notifyDebuggerOfUnwinding(m_vm, m_callFrame);
560
561         copyCalleeSavesToEntryFrameCalleeSavesBuffer(visitor);
562
563         bool shouldStopUnwinding = visitor->callerIsEntryFrame();
564         if (shouldStopUnwinding)
565             return StackVisitor::Done;
566
567         return StackVisitor::Continue;
568     }
569
570 private:
571     void copyCalleeSavesToEntryFrameCalleeSavesBuffer(StackVisitor& visitor) const
572     {
573 #if !ENABLE(C_LOOP) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
574         Optional<RegisterAtOffsetList> currentCalleeSaves = visitor->calleeSaveRegistersForUnwinding();
575
576         if (!currentCalleeSaves)
577             return;
578
579         RegisterAtOffsetList* allCalleeSaves = RegisterSet::vmCalleeSaveRegisterOffsets();
580         RegisterSet dontCopyRegisters = RegisterSet::stackRegisters();
581         CPURegister* frame = reinterpret_cast<CPURegister*>(m_callFrame->registers());
582
583         unsigned registerCount = currentCalleeSaves->size();
584         VMEntryRecord* record = vmEntryRecord(m_vm.topEntryFrame);
585         for (unsigned i = 0; i < registerCount; i++) {
586             RegisterAtOffset currentEntry = currentCalleeSaves->at(i);
587             if (dontCopyRegisters.get(currentEntry.reg()))
588                 continue;
589             RegisterAtOffset* calleeSavesEntry = allCalleeSaves->find(currentEntry.reg());
590             
591             record->calleeSaveRegistersBuffer[calleeSavesEntry->offsetAsIndex()] = *(frame + currentEntry.offsetAsIndex());
592         }
593 #else
594         UNUSED_PARAM(visitor);
595 #endif
596     }
597
598     VM& m_vm;
599     CallFrame*& m_callFrame;
600     bool m_isTermination;
601     CodeBlock*& m_codeBlock;
602     HandlerInfo*& m_handler;
603 };
604
605 NEVER_INLINE HandlerInfo* Interpreter::unwind(VM& vm, CallFrame*& callFrame, Exception* exception)
606 {
607     auto scope = DECLARE_CATCH_SCOPE(vm);
608
609     ASSERT(reinterpret_cast<void*>(callFrame) != vm.topEntryFrame);
610     CodeBlock* codeBlock = callFrame->codeBlock();
611
612     JSValue exceptionValue = exception->value();
613     ASSERT(!exceptionValue.isEmpty());
614     ASSERT(!exceptionValue.isCell() || exceptionValue.asCell());
615     // This shouldn't be possible (hence the assertions), but we're already in the slowest of
616     // slow cases, so let's harden against it anyway to be safe.
617     if (exceptionValue.isEmpty() || (exceptionValue.isCell() && !exceptionValue.asCell()))
618         exceptionValue = jsNull();
619
620     EXCEPTION_ASSERT_UNUSED(scope, scope.exception());
621
622     // Calculate an exception handler vPC, unwinding call frames as necessary.
623     HandlerInfo* handler = nullptr;
624     UnwindFunctor functor(vm, callFrame, isTerminatedExecutionException(vm, exception), codeBlock, handler);
625     StackVisitor::visit<StackVisitor::TerminateIfTopEntryFrameIsEmpty>(callFrame, &vm, functor);
626     if (!handler)
627         return nullptr;
628
629     return handler;
630 }
631
632 void Interpreter::notifyDebuggerOfExceptionToBeThrown(VM& vm, CallFrame* callFrame, Exception* exception)
633 {
634     Debugger* debugger = vm.vmEntryGlobalObject(callFrame)->debugger();
635     if (debugger && debugger->needsExceptionCallbacks() && !exception->didNotifyInspectorOfThrow()) {
636         // This code assumes that if the debugger is enabled then there is no inlining.
637         // If that assumption turns out to be false then we'll ignore the inlined call
638         // frames.
639         // https://bugs.webkit.org/show_bug.cgi?id=121754
640
641         bool hasCatchHandler;
642         bool isTermination = isTerminatedExecutionException(vm, exception);
643         if (isTermination)
644             hasCatchHandler = false;
645         else {
646             GetCatchHandlerFunctor functor;
647             StackVisitor::visit(callFrame, &vm, functor);
648             HandlerInfo* handler = functor.handler();
649             ASSERT(!handler || handler->isCatchHandler());
650             hasCatchHandler = !!handler;
651         }
652
653         debugger->exception(callFrame, exception->value(), hasCatchHandler);
654     }
655     exception->setDidNotifyInspectorOfThrow();
656 }
657
658 JSValue Interpreter::executeProgram(const SourceCode& source, CallFrame* callFrame, JSObject* thisObj)
659 {
660     JSScope* scope = thisObj->globalObject()->globalScope();
661     VM& vm = *scope->vm();
662     auto throwScope = DECLARE_THROW_SCOPE(vm);
663
664     ProgramExecutable* program = ProgramExecutable::create(callFrame, source);
665     EXCEPTION_ASSERT(throwScope.exception() || program);
666     RETURN_IF_EXCEPTION(throwScope, { });
667
668     throwScope.assertNoException();
669     ASSERT(!vm.isCollectorBusyOnCurrentThread());
670     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
671     if (vm.isCollectorBusyOnCurrentThread())
672         return jsNull();
673
674     if (UNLIKELY(!vm.isSafeToRecurseSoft()))
675         return checkedReturn(throwStackOverflowError(callFrame, throwScope));
676
677     // First check if the "program" is actually just a JSON object. If so,
678     // we'll handle the JSON object here. Else, we'll handle real JS code
679     // below at failedJSONP.
680
681     JSGlobalObject* globalObject = scope->globalObject(vm);
682     Vector<JSONPData> JSONPData;
683     bool parseResult;
684     StringView programSource = program->source().view();
685     if (programSource.isNull())
686         return jsUndefined();
687     if (programSource.is8Bit()) {
688         LiteralParser<LChar> literalParser(callFrame, programSource.characters8(), programSource.length(), JSONP);
689         parseResult = literalParser.tryJSONPParse(JSONPData, globalObject->globalObjectMethodTable()->supportsRichSourceInfo(globalObject));
690     } else {
691         LiteralParser<UChar> literalParser(callFrame, programSource.characters16(), programSource.length(), JSONP);
692         parseResult = literalParser.tryJSONPParse(JSONPData, globalObject->globalObjectMethodTable()->supportsRichSourceInfo(globalObject));
693     }
694
695     RETURN_IF_EXCEPTION(throwScope, { });
696     if (parseResult) {
697         JSValue result;
698         for (unsigned entry = 0; entry < JSONPData.size(); entry++) {
699             Vector<JSONPPathEntry> JSONPPath;
700             JSONPPath.swap(JSONPData[entry].m_path);
701             JSValue JSONPValue = JSONPData[entry].m_value.get();
702             if (JSONPPath.size() == 1 && JSONPPath[0].m_type == JSONPPathEntryTypeDeclareVar) {
703                 globalObject->addVar(callFrame, JSONPPath[0].m_pathEntryName);
704                 RETURN_IF_EXCEPTION(throwScope, { });
705                 PutPropertySlot slot(globalObject);
706                 globalObject->methodTable(vm)->put(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, slot);
707                 RETURN_IF_EXCEPTION(throwScope, { });
708                 result = jsUndefined();
709                 continue;
710             }
711             JSValue baseObject(globalObject);
712             for (unsigned i = 0; i < JSONPPath.size() - 1; i++) {
713                 ASSERT(JSONPPath[i].m_type != JSONPPathEntryTypeDeclareVar);
714                 switch (JSONPPath[i].m_type) {
715                 case JSONPPathEntryTypeDot: {
716                     if (i == 0) {
717                         RELEASE_ASSERT(baseObject == globalObject);
718
719                         auto doGet = [&] (JSSegmentedVariableObject* scope) {
720                             PropertySlot slot(scope, PropertySlot::InternalMethodType::Get);
721                             if (scope->getPropertySlot(callFrame, JSONPPath[i].m_pathEntryName, slot))
722                                 return slot.getValue(callFrame, JSONPPath[i].m_pathEntryName);
723                             return JSValue();
724                         };
725
726                         JSValue result = doGet(globalObject->globalLexicalEnvironment());
727                         RETURN_IF_EXCEPTION(throwScope, JSValue());
728                         if (result) {
729                             baseObject = result;
730                             continue;
731                         }
732
733                         result = doGet(globalObject);
734                         RETURN_IF_EXCEPTION(throwScope, JSValue());
735                         if (result) {
736                             baseObject = result;
737                             continue;
738                         }
739
740                         if (entry)
741                             return throwException(callFrame, throwScope, createUndefinedVariableError(callFrame, JSONPPath[i].m_pathEntryName));
742                         goto failedJSONP;
743                     }
744
745                     baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathEntryName);
746                     RETURN_IF_EXCEPTION(throwScope, JSValue());
747                     continue;
748                 }
749                 case JSONPPathEntryTypeLookup: {
750                     baseObject = baseObject.get(callFrame, static_cast<unsigned>(JSONPPath[i].m_pathIndex));
751                     RETURN_IF_EXCEPTION(throwScope, JSValue());
752                     continue;
753                 }
754                 default:
755                     RELEASE_ASSERT_NOT_REACHED();
756                     return jsUndefined();
757                 }
758             }
759
760             if (JSONPPath.size() == 1 && JSONPPath.last().m_type != JSONPPathEntryTypeLookup) {
761                 RELEASE_ASSERT(baseObject == globalObject);
762                 JSGlobalLexicalEnvironment* scope = globalObject->globalLexicalEnvironment();
763                 if (scope->hasProperty(callFrame, JSONPPath.last().m_pathEntryName))
764                     baseObject = scope;
765                 RETURN_IF_EXCEPTION(throwScope, JSValue());
766             }
767
768             PutPropertySlot slot(baseObject);
769             switch (JSONPPath.last().m_type) {
770             case JSONPPathEntryTypeCall: {
771                 JSValue function = baseObject.get(callFrame, JSONPPath.last().m_pathEntryName);
772                 RETURN_IF_EXCEPTION(throwScope, JSValue());
773                 CallData callData;
774                 CallType callType = getCallData(vm, function, callData);
775                 if (callType == CallType::None)
776                     return throwException(callFrame, throwScope, createNotAFunctionError(callFrame, function));
777                 MarkedArgumentBuffer jsonArg;
778                 jsonArg.append(JSONPValue);
779                 ASSERT(!jsonArg.hasOverflowed());
780                 JSValue thisValue = JSONPPath.size() == 1 ? jsUndefined() : baseObject;
781                 JSONPValue = JSC::call(callFrame, function, callType, callData, thisValue, jsonArg);
782                 RETURN_IF_EXCEPTION(throwScope, JSValue());
783                 break;
784             }
785             case JSONPPathEntryTypeDot: {
786                 baseObject.put(callFrame, JSONPPath.last().m_pathEntryName, JSONPValue, slot);
787                 RETURN_IF_EXCEPTION(throwScope, JSValue());
788                 break;
789             }
790             case JSONPPathEntryTypeLookup: {
791                 baseObject.putByIndex(callFrame, JSONPPath.last().m_pathIndex, JSONPValue, slot.isStrictMode());
792                 RETURN_IF_EXCEPTION(throwScope, JSValue());
793                 break;
794             }
795             default:
796                 RELEASE_ASSERT_NOT_REACHED();
797                 return jsUndefined();
798             }
799             result = JSONPValue;
800         }
801         return result;
802     }
803 failedJSONP:
804     // If we get here, then we have already proven that the script is not a JSON
805     // object.
806
807     VMEntryScope entryScope(vm, globalObject);
808
809     // Compile source to bytecode if necessary:
810     JSObject* error = program->initializeGlobalProperties(vm, callFrame, scope);
811     EXCEPTION_ASSERT(!throwScope.exception() || !error);
812     if (UNLIKELY(error))
813         return checkedReturn(throwException(callFrame, throwScope, error));
814
815     ProgramCodeBlock* codeBlock;
816     {
817         CodeBlock* tempCodeBlock;
818         Exception* error = program->prepareForExecution<ProgramExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
819         EXCEPTION_ASSERT(throwScope.exception() == error);
820         if (UNLIKELY(error))
821             return checkedReturn(error);
822         codeBlock = jsCast<ProgramCodeBlock*>(tempCodeBlock);
823     }
824
825     VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
826     if (UNLIKELY(vm.needTrapHandling(mask))) {
827         vm.handleTraps(callFrame, mask);
828         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
829     }
830
831     if (scope->structure(vm)->isUncacheableDictionary())
832         scope->flattenDictionaryObject(vm);
833
834     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
835
836     ProtoCallFrame protoCallFrame;
837     protoCallFrame.init(codeBlock, JSCallee::create(vm, globalObject, scope), thisObj, 1);
838
839     // Execute the code:
840     throwScope.release();
841     JSValue result = program->generatedJITCode()->execute(&vm, &protoCallFrame);
842     return checkedReturn(result);
843 }
844
845 JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
846 {
847     VM& vm = callFrame->vm();
848     auto throwScope = DECLARE_THROW_SCOPE(vm);
849
850     throwScope.assertNoException();
851     ASSERT(!vm.isCollectorBusyOnCurrentThread());
852     if (vm.isCollectorBusyOnCurrentThread())
853         return jsNull();
854
855     bool isJSCall = (callType == CallType::JS);
856     JSScope* scope = nullptr;
857     CodeBlock* newCodeBlock;
858     size_t argsCount = 1 + args.size(); // implicit "this" parameter
859
860     JSGlobalObject* globalObject;
861
862     if (isJSCall) {
863         scope = callData.js.scope;
864         globalObject = scope->globalObject(vm);
865     } else {
866         ASSERT(callType == CallType::Host);
867         globalObject = function->globalObject(vm);
868     }
869
870     VMEntryScope entryScope(vm, globalObject);
871     if (UNLIKELY(!vm.isSafeToRecurseSoft()))
872         return checkedReturn(throwStackOverflowError(callFrame, throwScope));
873
874     if (isJSCall) {
875         // Compile the callee:
876         Exception* compileError = callData.js.functionExecutable->prepareForExecution<FunctionExecutable>(vm, jsCast<JSFunction*>(function), scope, CodeForCall, newCodeBlock);
877         EXCEPTION_ASSERT(throwScope.exception() == compileError);
878         if (UNLIKELY(!!compileError))
879             return checkedReturn(compileError);
880
881         ASSERT(!!newCodeBlock);
882         newCodeBlock->m_shouldAlwaysBeInlined = false;
883     } else
884         newCodeBlock = 0;
885
886     VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
887     if (UNLIKELY(vm.needTrapHandling(mask))) {
888         vm.handleTraps(callFrame, mask);
889         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
890     }
891
892     ProtoCallFrame protoCallFrame;
893     protoCallFrame.init(newCodeBlock, function, thisValue, argsCount, args.data());
894
895     JSValue result;
896     {
897         // Execute the code:
898         if (isJSCall) {
899             throwScope.release();
900             result = callData.js.functionExecutable->generatedJITCodeForCall()->execute(&vm, &protoCallFrame);
901         } else {
902             result = JSValue::decode(vmEntryToNative(callData.native.function.rawPointer(), &vm, &protoCallFrame));
903             RETURN_IF_EXCEPTION(throwScope, JSValue());
904         }
905     }
906
907     return checkedReturn(result);
908 }
909
910 JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args, JSValue newTarget)
911 {
912     VM& vm = callFrame->vm();
913     auto throwScope = DECLARE_THROW_SCOPE(vm);
914
915     throwScope.assertNoException();
916     ASSERT(!vm.isCollectorBusyOnCurrentThread());
917     // We throw in this case because we have to return something "valid" but we're
918     // already in an invalid state.
919     if (UNLIKELY(vm.isCollectorBusyOnCurrentThread())) {
920         throwStackOverflowError(callFrame, throwScope);
921         return nullptr;
922     }
923
924     bool isJSConstruct = (constructType == ConstructType::JS);
925     JSScope* scope = nullptr;
926     CodeBlock* newCodeBlock;
927     size_t argsCount = 1 + args.size(); // implicit "this" parameter
928
929     JSGlobalObject* globalObject;
930
931     if (isJSConstruct) {
932         scope = constructData.js.scope;
933         globalObject = scope->globalObject(vm);
934     } else {
935         ASSERT(constructType == ConstructType::Host);
936         globalObject = constructor->globalObject(vm);
937     }
938
939     VMEntryScope entryScope(vm, globalObject);
940     if (UNLIKELY(!vm.isSafeToRecurseSoft())) {
941         throwStackOverflowError(callFrame, throwScope);
942         return nullptr;
943     }
944
945     if (isJSConstruct) {
946         // Compile the callee:
947         Exception* compileError = constructData.js.functionExecutable->prepareForExecution<FunctionExecutable>(vm, jsCast<JSFunction*>(constructor), scope, CodeForConstruct, newCodeBlock);
948         EXCEPTION_ASSERT(throwScope.exception() == compileError);
949         if (UNLIKELY(!!compileError))
950             return nullptr;
951
952         ASSERT(!!newCodeBlock);
953         newCodeBlock->m_shouldAlwaysBeInlined = false;
954     } else
955         newCodeBlock = 0;
956
957     VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
958     if (UNLIKELY(vm.needTrapHandling(mask))) {
959         vm.handleTraps(callFrame, mask);
960         RETURN_IF_EXCEPTION(throwScope, nullptr);
961     }
962
963     ProtoCallFrame protoCallFrame;
964     protoCallFrame.init(newCodeBlock, constructor, newTarget, argsCount, args.data());
965
966     JSValue result;
967     {
968         // Execute the code.
969         if (isJSConstruct)
970             result = constructData.js.functionExecutable->generatedJITCodeForConstruct()->execute(&vm, &protoCallFrame);
971         else {
972             result = JSValue::decode(vmEntryToNative(constructData.native.function.rawPointer(), &vm, &protoCallFrame));
973
974             if (LIKELY(!throwScope.exception()))
975                 RELEASE_ASSERT(result.isObject());
976         }
977     }
978
979     RETURN_IF_EXCEPTION(throwScope, 0);
980     ASSERT(result.isObject());
981     return checkedReturn(asObject(result));
982 }
983
984 CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionExecutable, CallFrame* callFrame, ProtoCallFrame* protoCallFrame, JSFunction* function, int argumentCountIncludingThis, JSScope* scope, const ArgList& args)
985 {
986     VM& vm = *scope->vm();
987     auto throwScope = DECLARE_THROW_SCOPE(vm);
988     throwScope.assertNoException();
989     
990     if (vm.isCollectorBusyOnCurrentThread())
991         return CallFrameClosure();
992
993     // Compile the callee:
994     CodeBlock* newCodeBlock;
995     Exception* error = functionExecutable->prepareForExecution<FunctionExecutable>(vm, function, scope, CodeForCall, newCodeBlock);
996     EXCEPTION_ASSERT(throwScope.exception() == error);
997     if (UNLIKELY(error))
998         return CallFrameClosure();
999     newCodeBlock->m_shouldAlwaysBeInlined = false;
1000
1001     size_t argsCount = argumentCountIncludingThis;
1002
1003     protoCallFrame->init(newCodeBlock, function, jsUndefined(), argsCount, args.data());
1004     // Return the successful closure:
1005     CallFrameClosure result = { callFrame, protoCallFrame, function, functionExecutable, &vm, scope, newCodeBlock->numParameters(), argumentCountIncludingThis };
1006     return result;
1007 }
1008
1009 JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, JSScope* scope)
1010 {
1011     VM& vm = *scope->vm();
1012     auto throwScope = DECLARE_THROW_SCOPE(vm);
1013
1014     ASSERT(&vm == &callFrame->vm());
1015     throwScope.assertNoException();
1016     ASSERT(!vm.isCollectorBusyOnCurrentThread());
1017     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
1018     if (vm.isCollectorBusyOnCurrentThread())
1019         return jsNull();
1020
1021     VMEntryScope entryScope(vm, scope->globalObject(vm));
1022     if (UNLIKELY(!vm.isSafeToRecurseSoft()))
1023         return checkedReturn(throwStackOverflowError(callFrame, throwScope));
1024
1025     unsigned numVariables = eval->numVariables();
1026     unsigned numTopLevelFunctionDecls = eval->numTopLevelFunctionDecls();
1027     unsigned numFunctionHoistingCandidates = eval->numFunctionHoistingCandidates();
1028
1029     JSScope* variableObject;
1030     if ((numVariables || numTopLevelFunctionDecls) && eval->isStrictMode()) {
1031         scope = StrictEvalActivation::create(vm, callFrame->lexicalGlobalObject()->strictEvalActivationStructure(), scope);
1032         variableObject = scope;
1033     } else {
1034         for (JSScope* node = scope; ; node = node->next()) {
1035             RELEASE_ASSERT(node);
1036             if (node->isGlobalObject()) {
1037                 variableObject = node;
1038                 break;
1039             } 
1040             if (node->isJSLexicalEnvironment()) {
1041                 JSLexicalEnvironment* lexicalEnvironment = jsCast<JSLexicalEnvironment*>(node);
1042                 if (lexicalEnvironment->symbolTable()->scopeType() == SymbolTable::ScopeType::VarScope) {
1043                     variableObject = node;
1044                     break;
1045                 }
1046             }
1047         }
1048     }
1049
1050     EvalCodeBlock* codeBlock;
1051     {
1052         CodeBlock* tempCodeBlock;
1053         Exception* compileError = eval->prepareForExecution<EvalExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
1054         EXCEPTION_ASSERT(throwScope.exception() == compileError);
1055         if (UNLIKELY(!!compileError))
1056             return checkedReturn(compileError);
1057         codeBlock = jsCast<EvalCodeBlock*>(tempCodeBlock);
1058     }
1059     UnlinkedEvalCodeBlock* unlinkedCodeBlock = codeBlock->unlinkedEvalCodeBlock();
1060
1061     // We can't declare a "var"/"function" that overwrites a global "let"/"const"/"class" in a sloppy-mode eval.
1062     if (variableObject->isGlobalObject() && !eval->isStrictMode() && (numVariables || numTopLevelFunctionDecls)) {
1063         JSGlobalLexicalEnvironment* globalLexicalEnvironment = jsCast<JSGlobalObject*>(variableObject)->globalLexicalEnvironment();
1064         for (unsigned i = 0; i < numVariables; ++i) {
1065             const Identifier& ident = unlinkedCodeBlock->variable(i);
1066             PropertySlot slot(globalLexicalEnvironment, PropertySlot::InternalMethodType::VMInquiry);
1067             if (JSGlobalLexicalEnvironment::getOwnPropertySlot(globalLexicalEnvironment, callFrame, ident, slot)) {
1068                 return checkedReturn(throwTypeError(callFrame, throwScope, makeString("Can't create duplicate global variable in eval: '", String(ident.impl()), "'")));
1069             }
1070         }
1071
1072         for (unsigned i = 0; i < numTopLevelFunctionDecls; ++i) {
1073             FunctionExecutable* function = codeBlock->functionDecl(i);
1074             PropertySlot slot(globalLexicalEnvironment, PropertySlot::InternalMethodType::VMInquiry);
1075             if (JSGlobalLexicalEnvironment::getOwnPropertySlot(globalLexicalEnvironment, callFrame, function->name(), slot)) {
1076                 return checkedReturn(throwTypeError(callFrame, throwScope, makeString("Can't create duplicate global variable in eval: '", String(function->name().impl()), "'")));
1077             }
1078         }
1079     }
1080
1081     if (variableObject->structure(vm)->isUncacheableDictionary())
1082         variableObject->flattenDictionaryObject(vm);
1083
1084     if (numVariables || numTopLevelFunctionDecls || numFunctionHoistingCandidates) {
1085         BatchedTransitionOptimizer optimizer(vm, variableObject);
1086         if (variableObject->next() && !eval->isStrictMode())
1087             variableObject->globalObject(vm)->varInjectionWatchpoint()->fireAll(vm, "Executed eval, fired VarInjection watchpoint");
1088
1089         for (unsigned i = 0; i < numVariables; ++i) {
1090             const Identifier& ident = unlinkedCodeBlock->variable(i);
1091             bool hasProperty = variableObject->hasProperty(callFrame, ident);
1092             RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1093             if (!hasProperty) {
1094                 PutPropertySlot slot(variableObject);
1095                 if (!variableObject->isExtensible(callFrame))
1096                     return checkedReturn(throwTypeError(callFrame, throwScope, NonExtensibleObjectPropertyDefineError));
1097                 variableObject->methodTable(vm)->put(variableObject, callFrame, ident, jsUndefined(), slot);
1098                 RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1099             }
1100         }
1101         
1102         if (eval->isStrictMode()) {
1103             for (unsigned i = 0; i < numTopLevelFunctionDecls; ++i) {
1104                 FunctionExecutable* function = codeBlock->functionDecl(i);
1105                 PutPropertySlot slot(variableObject);
1106                 // We need create this variables because it will be used to emits code by bytecode generator
1107                 variableObject->methodTable(vm)->put(variableObject, callFrame, function->name(), jsUndefined(), slot);
1108                 RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1109             }
1110         } else {
1111             for (unsigned i = 0; i < numTopLevelFunctionDecls; ++i) {
1112                 FunctionExecutable* function = codeBlock->functionDecl(i);
1113                 JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(callFrame, scope, function->name());
1114                 RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1115                 if (resolvedScope.isUndefined())
1116                     return checkedReturn(throwSyntaxError(callFrame, throwScope, makeString("Can't create duplicate variable in eval: '", String(function->name().impl()), "'")));
1117                 PutPropertySlot slot(variableObject);
1118                 // We need create this variables because it will be used to emits code by bytecode generator
1119                 variableObject->methodTable(vm)->put(variableObject, callFrame, function->name(), jsUndefined(), slot);
1120                 RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1121             }
1122
1123             for (unsigned i = 0; i < numFunctionHoistingCandidates; ++i) {
1124                 const Identifier& ident = unlinkedCodeBlock->functionHoistingCandidate(i);
1125                 JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(callFrame, scope, ident);
1126                 RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1127                 if (!resolvedScope.isUndefined()) {
1128                     bool hasProperty = variableObject->hasProperty(callFrame, ident);
1129                     RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1130                     if (!hasProperty) {
1131                         PutPropertySlot slot(variableObject);
1132                         variableObject->methodTable(vm)->put(variableObject, callFrame, ident, jsUndefined(), slot);
1133                         RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
1134                     }
1135                 }
1136             }
1137         }
1138     }
1139
1140     VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
1141     if (UNLIKELY(vm.needTrapHandling(mask))) {
1142         vm.handleTraps(callFrame, mask);
1143         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
1144     }
1145
1146     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
1147
1148     ProtoCallFrame protoCallFrame;
1149     protoCallFrame.init(codeBlock, JSCallee::create(vm, scope->globalObject(vm), scope), thisValue, 1);
1150
1151     // Execute the code:
1152     throwScope.release();
1153     JSValue result = eval->generatedJITCode()->execute(&vm, &protoCallFrame);
1154
1155     return checkedReturn(result);
1156 }
1157
1158 JSValue Interpreter::executeModuleProgram(ModuleProgramExecutable* executable, CallFrame* callFrame, JSModuleEnvironment* scope)
1159 {
1160     VM& vm = *scope->vm();
1161     auto throwScope = DECLARE_THROW_SCOPE(vm);
1162
1163     ASSERT(&vm == &callFrame->vm());
1164     throwScope.assertNoException();
1165     ASSERT(!vm.isCollectorBusyOnCurrentThread());
1166     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
1167     if (vm.isCollectorBusyOnCurrentThread())
1168         return jsNull();
1169
1170     VMEntryScope entryScope(vm, scope->globalObject(vm));
1171     if (UNLIKELY(!vm.isSafeToRecurseSoft()))
1172         return checkedReturn(throwStackOverflowError(callFrame, throwScope));
1173
1174     ModuleProgramCodeBlock* codeBlock;
1175     {
1176         CodeBlock* tempCodeBlock;
1177         Exception* compileError = executable->prepareForExecution<ModuleProgramExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
1178         EXCEPTION_ASSERT(throwScope.exception() == compileError);
1179         if (UNLIKELY(!!compileError))
1180             return checkedReturn(compileError);
1181         codeBlock = jsCast<ModuleProgramCodeBlock*>(tempCodeBlock);
1182     }
1183
1184     VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
1185     if (UNLIKELY(vm.needTrapHandling(mask))) {
1186         vm.handleTraps(callFrame, mask);
1187         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
1188     }
1189
1190     if (scope->structure(vm)->isUncacheableDictionary())
1191         scope->flattenDictionaryObject(vm);
1192
1193     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
1194
1195     // The |this| of the module is always `undefined`.
1196     // http://www.ecma-international.org/ecma-262/6.0/#sec-module-environment-records-hasthisbinding
1197     // http://www.ecma-international.org/ecma-262/6.0/#sec-module-environment-records-getthisbinding
1198     ProtoCallFrame protoCallFrame;
1199     protoCallFrame.init(codeBlock, JSCallee::create(vm, scope->globalObject(vm), scope), jsUndefined(), 1);
1200
1201     // Execute the code:
1202     throwScope.release();
1203     JSValue result = executable->generatedJITCode()->execute(&vm, &protoCallFrame);
1204
1205     return checkedReturn(result);
1206 }
1207
1208 NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookType debugHookType)
1209 {
1210     VM& vm = callFrame->vm();
1211     auto scope = DECLARE_CATCH_SCOPE(vm);
1212     Debugger* debugger = vm.vmEntryGlobalObject(callFrame)->debugger();
1213     if (!debugger)
1214         return;
1215
1216     ASSERT(callFrame->codeBlock()->hasDebuggerRequests());
1217     scope.assertNoException();
1218
1219     switch (debugHookType) {
1220         case DidEnterCallFrame:
1221             debugger->callEvent(callFrame);
1222             break;
1223         case WillLeaveCallFrame:
1224             debugger->returnEvent(callFrame);
1225             break;
1226         case WillExecuteStatement:
1227             debugger->atStatement(callFrame);
1228             break;
1229         case WillExecuteExpression:
1230             debugger->atExpression(callFrame);
1231             break;
1232         case WillExecuteProgram:
1233             debugger->willExecuteProgram(callFrame);
1234             break;
1235         case DidExecuteProgram:
1236             debugger->didExecuteProgram(callFrame);
1237             break;
1238         case DidReachBreakpoint:
1239             debugger->didReachBreakpoint(callFrame);
1240             break;
1241     }
1242     scope.assertNoException();
1243 }
1244
1245 } // namespace JSC
1246
1247 namespace WTF {
1248
1249 void printInternal(PrintStream& out, JSC::DebugHookType type)
1250 {
1251     switch (type) {
1252     case JSC::WillExecuteProgram:
1253         out.print("WillExecuteProgram");
1254         return;
1255     case JSC::DidExecuteProgram:
1256         out.print("DidExecuteProgram");
1257         return;
1258     case JSC::DidEnterCallFrame:
1259         out.print("DidEnterCallFrame");
1260         return;
1261     case JSC::DidReachBreakpoint:
1262         out.print("DidReachBreakpoint");
1263         return;
1264     case JSC::WillLeaveCallFrame:
1265         out.print("WillLeaveCallFrame");
1266         return;
1267     case JSC::WillExecuteStatement:
1268         out.print("WillExecuteStatement");
1269         return;
1270     case JSC::WillExecuteExpression:
1271         out.print("WillExecuteExpression");
1272         return;
1273     }
1274 }
1275
1276 } // namespace WTF