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