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