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