Unreviewed, rolling out r189079.
[WebKit-https.git] / Source / JavaScriptCore / interpreter / Interpreter.cpp
index c4b1235..10501c1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2009, 2010, 2012, 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2010, 2012-2015 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
  *
  * Redistribution and use in source and binary forms, with or without
 #include "config.h"
 #include "Interpreter.h"
 
-#include "Arguments.h"
 #include "BatchedTransitionOptimizer.h"
 #include "CallFrameClosure.h"
 #include "CallFrameInlines.h"
+#include "ClonedArguments.h"
 #include "CodeBlock.h"
+#include "DirectArguments.h"
 #include "Heap.h"
 #include "Debugger.h"
 #include "DebuggerCallFrame.h"
 #include "ErrorInstance.h"
 #include "EvalCodeCache.h"
+#include "Exception.h"
 #include "ExceptionHelpers.h"
 #include "GetterSetter.h"
 #include "JSArray.h"
+#include "JSArrowFunction.h"
 #include "JSBoundFunction.h"
+#include "JSCInlines.h"
 #include "JSLexicalEnvironment.h"
-#include "JSNameScope.h"
 #include "JSNotAnObject.h"
 #include "JSStackInlines.h"
 #include "JSString.h"
 #include "LLIntThunks.h"
 #include "LegacyProfiler.h"
 #include "LiteralParser.h"
-#include "NameInstance.h"
 #include "ObjectPrototype.h"
-#include "JSCInlines.h"
 #include "Parser.h"
 #include "ProtoCallFrame.h"
 #include "RegExpObject.h"
 #include "RegExpPrototype.h"
 #include "Register.h"
 #include "SamplingTool.h"
+#include "ScopedArguments.h"
 #include "StackAlignment.h"
 #include "StackVisitor.h"
 #include "StrictEvalActivation.h"
 #include "StrongInlines.h"
+#include "Symbol.h"
 #include "VMEntryScope.h"
+#include "VMInlines.h"
 #include "VirtualRegister.h"
 
 #include <limits.h>
 #include "JIT.h"
 #endif
 
-#define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND (!defined(__llvm__))
-
 using namespace std;
 
 namespace JSC {
 
+String StackFrame::friendlySourceURL() const
+{
+    String traceLine;
+    
+    switch (codeType) {
+    case StackFrameEvalCode:
+    case StackFrameFunctionCode:
+    case StackFrameGlobalCode:
+        if (!sourceURL.isEmpty())
+            traceLine = sourceURL.impl();
+        break;
+    case StackFrameNativeCode:
+        traceLine = "[native code]";
+        break;
+    }
+    return traceLine.isNull() ? emptyString() : traceLine;
+}
+
+String StackFrame::friendlyFunctionName(CallFrame* callFrame) const
+{
+    String traceLine;
+    JSObject* stackFrameCallee = callee.get();
+
+    switch (codeType) {
+    case StackFrameEvalCode:
+        traceLine = "eval code";
+        break;
+    case StackFrameNativeCode:
+        if (callee)
+            traceLine = getCalculatedDisplayName(callFrame, stackFrameCallee).impl();
+        break;
+    case StackFrameFunctionCode:
+        traceLine = getCalculatedDisplayName(callFrame, stackFrameCallee).impl();
+        break;
+    case StackFrameGlobalCode:
+        traceLine = "global code";
+        break;
+    }
+    return traceLine.isNull() ? emptyString() : traceLine;
+}
+
 JSValue eval(CallFrame* callFrame)
 {
     if (!callFrame->argumentCount())
@@ -105,13 +148,11 @@ JSValue eval(CallFrame* callFrame)
     
     CallFrame* callerFrame = callFrame->callerFrame();
     CodeBlock* callerCodeBlock = callerFrame->codeBlock();
-    JSScope* callerScopeChain = callerFrame->scope();
+    JSScope* callerScopeChain = callerFrame->uncheckedR(callerCodeBlock->scopeRegister().offset()).Register::scope();
     EvalExecutable* eval = callerCodeBlock->evalCodeCache().tryGet(callerCodeBlock->isStrictMode(), programSource, callerScopeChain);
 
     if (!eval) {
         if (!callerCodeBlock->isStrictMode()) {
-            // FIXME: We can use the preparser in strict mode, we just need additional logic
-            // to prevent duplicates.
             if (programSource.is8Bit()) {
                 LiteralParser<LChar> preparser(callFrame, programSource.characters8(), programSource.length(), NonStrictJSON);
                 if (JSValue parsedObject = preparser.tryLiteralParse())
@@ -126,7 +167,8 @@ JSValue eval(CallFrame* callFrame)
         // If the literal parser bailed, it should not have thrown exceptions.
         ASSERT(!callFrame->vm().exception());
 
-        eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock->ownerExecutable(), callerCodeBlock->isStrictMode(), programSource, callerScopeChain);
+        ThisTDZMode thisTDZMode = callerCodeBlock->unlinkedCodeBlock()->constructorKind() == ConstructorKind::Derived ? ThisTDZMode::AlwaysCheck : ThisTDZMode::CheckIfNeeded;
+        eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock->ownerExecutable(), callerCodeBlock->isStrictMode(), thisTDZMode, programSource, callerScopeChain);
         if (!eval)
             return jsUndefined();
     }
@@ -136,147 +178,103 @@ JSValue eval(CallFrame* callFrame)
     return interpreter->execute(eval, callFrame, thisValue, callerScopeChain);
 }
 
-CallFrame* sizeFrameForVarargs(CallFrame* callFrame, JSStack* stack, JSValue arguments, int firstFreeRegister, uint32_t firstVarArgOffset)
+unsigned sizeOfVarargs(CallFrame* callFrame, JSValue arguments, uint32_t firstVarArgOffset)
 {
-    if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
-        unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
-        if (argumentCountIncludingThis > firstVarArgOffset)
-            argumentCountIncludingThis -= firstVarArgOffset;
-        else
-            argumentCountIncludingThis = 1;
-        unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister + argumentCountIncludingThis + JSStack::CallFrameHeaderSize + 1);
-        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
-        if (argumentCountIncludingThis > Arguments::MaxArguments + 1 || !stack->ensureCapacityFor(newCallFrame->registers())) {
-            throwStackOverflowError(callFrame);
-            return 0;
-        }
-        return newCallFrame;
-    }
-
-    if (arguments.isUndefinedOrNull()) {
-        unsigned argumentCountIncludingThis = 1;
-        unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(),  -firstFreeRegister + argumentCountIncludingThis + JSStack::CallFrameHeaderSize + 1);
-        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
-        if (!stack->ensureCapacityFor(newCallFrame->registers())) {
-            throwStackOverflowError(callFrame);
+    if (UNLIKELY(!arguments.isCell())) {
+        if (arguments.isUndefinedOrNull())
             return 0;
-        }
-        return newCallFrame;
-    }
-
-    if (!arguments.isObject()) {
-        callFrame->vm().throwException(callFrame, createInvalidParameterError(callFrame, "Function.prototype.apply", arguments));
+        
+        callFrame->vm().throwException(callFrame, createInvalidFunctionApplyParameterError(callFrame, arguments));
         return 0;
     }
-
-    if (asObject(arguments)->classInfo() == Arguments::info()) {
-        Arguments* argsObject = asArguments(arguments);
-        unsigned argCount = argsObject->length(callFrame);
-        if (argCount >= firstVarArgOffset)
-            argCount -= firstVarArgOffset;
-        else
-            argCount = 0;
-        unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister + CallFrame::offsetFor(argCount + 1));
-        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
-        if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
-            throwStackOverflowError(callFrame);
-            return 0;
-        }
-        return newCallFrame;
-    }
-
-    if (isJSArray(arguments)) {
-        JSArray* array = asArray(arguments);
-        unsigned argCount = array->length();
-        if (argCount >= firstVarArgOffset)
-            argCount -= firstVarArgOffset;
+    
+    JSCell* cell = arguments.asCell();
+    unsigned length;
+    switch (cell->type()) {
+    case DirectArgumentsType:
+        length = jsCast<DirectArguments*>(cell)->length(callFrame);
+        break;
+    case ScopedArgumentsType:
+        length =jsCast<ScopedArguments*>(cell)->length(callFrame);
+        break;
+    case StringType:
+        callFrame->vm().throwException(callFrame, createInvalidFunctionApplyParameterError(callFrame,  arguments));
+        return 0;
+    default:
+        ASSERT(arguments.isObject());
+        if (isJSArray(cell))
+            length = jsCast<JSArray*>(cell)->length();
         else
-            argCount = 0;
-        unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister + CallFrame::offsetFor(argCount + 1));
-        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
-        if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
-            throwStackOverflowError(callFrame);
-            return 0;
-        }
-        return newCallFrame;
+            length = jsCast<JSObject*>(cell)->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
+        break;
     }
-
-    JSObject* argObject = asObject(arguments);
-    unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
-    if (argCount >= firstVarArgOffset)
-        argCount -= firstVarArgOffset;
+    
+    if (length >= firstVarArgOffset)
+        length -= firstVarArgOffset;
     else
-        argCount = 0;
-    unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister + CallFrame::offsetFor(argCount + 1));
-    CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
-    if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
+        length = 0;
+    
+    return length;
+}
+
+unsigned sizeFrameForVarargs(CallFrame* callFrame, JSStack* stack, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset)
+{
+    unsigned length = sizeOfVarargs(callFrame, arguments, firstVarArgOffset);
+    
+    CallFrame* calleeFrame = calleeFrameForVarargs(callFrame, numUsedStackSlots, length + 1);
+    if (length > maxArguments || !stack->ensureCapacityFor(calleeFrame->registers())) {
         throwStackOverflowError(callFrame);
         return 0;
     }
-    return newCallFrame;
+    
+    return length;
 }
 
-void loadVarargs(CallFrame* callFrame, CallFrame* newCallFrame, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset)
+void loadVarargs(CallFrame* callFrame, VirtualRegister firstElementDest, JSValue arguments, uint32_t offset, uint32_t length)
 {
-    if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
-        unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
-        if (argumentCountIncludingThis > firstVarArgOffset)
-            argumentCountIncludingThis -= firstVarArgOffset;
-        else
-            argumentCountIncludingThis = 1;
-        newCallFrame->setArgumentCountIncludingThis(argumentCountIncludingThis);
-        newCallFrame->setThisValue(thisValue);
-        for (size_t i = firstVarArgOffset; i < callFrame->argumentCount(); ++i)
-            newCallFrame->setArgument(i - firstVarArgOffset, callFrame->argumentAfterCapture(i));
+    if (UNLIKELY(!arguments.isCell()))
         return;
-    }
     
-    if (arguments.isUndefinedOrNull()) {
-        newCallFrame->setArgumentCountIncludingThis(1);
-        newCallFrame->setThisValue(thisValue);
+    JSCell* cell = arguments.asCell();
+    switch (cell->type()) {
+    case DirectArgumentsType:
+        jsCast<DirectArguments*>(cell)->copyToArguments(callFrame, firstElementDest, offset, length);
         return;
-    }
-    
-    if (asObject(arguments)->classInfo() == Arguments::info()) {
-        Arguments* argsObject = asArguments(arguments);
-        unsigned argCount = argsObject->length(callFrame);
-        if (argCount >= firstVarArgOffset) {
-            argCount -= firstVarArgOffset;
-            newCallFrame->setArgumentCountIncludingThis(argCount + 1);
-            argsObject->copyToArguments(callFrame, newCallFrame, argCount, firstVarArgOffset);
-        } else
-            newCallFrame->setArgumentCountIncludingThis(1);
-        newCallFrame->setThisValue(thisValue);
+    case ScopedArgumentsType:
+        jsCast<ScopedArguments*>(cell)->copyToArguments(callFrame, firstElementDest, offset, length);
         return;
-    }
-    
-    if (isJSArray(arguments)) {
-        JSArray* array = asArray(arguments);
-        unsigned argCount = array->length();
-        if (argCount >= firstVarArgOffset) {
-            argCount -= firstVarArgOffset;
-            newCallFrame->setArgumentCountIncludingThis(argCount + 1);
-            array->copyToArguments(callFrame, newCallFrame, argCount, firstVarArgOffset);
-        } else
-            newCallFrame->setArgumentCountIncludingThis(1);
-        newCallFrame->setThisValue(thisValue);
+    default: {
+        ASSERT(arguments.isObject());
+        JSObject* object = jsCast<JSObject*>(cell);
+        if (isJSArray(object)) {
+            jsCast<JSArray*>(object)->copyToArguments(callFrame, firstElementDest, offset, length);
+            return;
+        }
+        unsigned i;
+        for (i = 0; i < length && object->canGetIndexQuickly(i + offset); ++i)
+            callFrame->r(firstElementDest + i) = object->getIndexQuickly(i + offset);
+        for (; i < length; ++i)
+            callFrame->r(firstElementDest + i) = object->get(callFrame, i + offset);
         return;
-    }
+    } }
+}
+
+void setupVarargsFrame(CallFrame* callFrame, CallFrame* newCallFrame, JSValue arguments, uint32_t offset, uint32_t length)
+{
+    VirtualRegister calleeFrameOffset(newCallFrame - callFrame);
     
-    JSObject* argObject = asObject(arguments);
-    unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
-    if (argCount >= firstVarArgOffset) {
-        argCount -= firstVarArgOffset;
-        newCallFrame->setArgumentCountIncludingThis(argCount + 1);
-    } else
-        newCallFrame->setArgumentCountIncludingThis(1);
+    loadVarargs(
+        callFrame,
+        calleeFrameOffset + CallFrame::argumentOffset(0),
+        arguments, offset, length);
+    
+    newCallFrame->setArgumentCountIncludingThis(length + 1);
+}
 
+void setupVarargsFrameAndSetThis(CallFrame* callFrame, CallFrame* newCallFrame, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length)
+{
+    setupVarargsFrame(callFrame, newCallFrame, arguments, firstVarArgOffset, length);
     newCallFrame->setThisValue(thisValue);
-    for (size_t i = 0; i < argCount; ++i) {
-        newCallFrame->setArgument(i, asObject(arguments)->get(callFrame, i + firstVarArgOffset));
-        if (UNLIKELY(callFrame->vm().exception()))
-            return;
-    }
 }
 
 Interpreter::Interpreter(VM& vm)
@@ -294,10 +292,8 @@ Interpreter::~Interpreter()
 {
 }
 
-void Interpreter::initialize(bool canUseJIT)
+void Interpreter::initialize()
 {
-    UNUSED_PARAM(canUseJIT);
-
 #if ENABLE(COMPUTED_GOTO_OPCODES)
     m_opcodeTable = LLInt::opcodeMap();
     for (int i = 0; i < numOpcodeIDs; ++i)
@@ -383,7 +379,7 @@ void Interpreter::dumpRegisters(CallFrame* callFrame)
     --it;
     dataLogF("[Callee]                   | %10p | %p \n", it, callFrame->callee());
     --it;
-    dataLogF("[ScopeChain]               | %10p | %p \n", it, callFrame->scope());
+    // FIXME: Remove the next decrement when the ScopeChain slot is removed from the call header
     --it;
 #if ENABLE(JIT)
     AbstractPC pc = callFrame->abstractReturnPC(callFrame->vm());
@@ -438,9 +434,8 @@ bool Interpreter::isOpcode(Opcode opcode)
 static bool unwindCallFrame(StackVisitor& visitor)
 {
     CallFrame* callFrame = visitor->callFrame();
-    CodeBlock* codeBlock = visitor->codeBlock();
     if (Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger()) {
-        ClearExceptionScope scope(&callFrame->vm());
+        SuspendExceptionScope scope(&callFrame->vm());
         if (jsDynamicCast<JSFunction*>(callFrame->callee()))
             debugger->returnEvent(callFrame);
         else
@@ -448,23 +443,6 @@ static bool unwindCallFrame(StackVisitor& visitor)
         ASSERT(!callFrame->hadException());
     }
 
-    if (codeBlock->codeType() == FunctionCode && codeBlock->needsActivation()) {
-#if ENABLE(DFG_JIT)
-        RELEASE_ASSERT(!visitor->isInlinedFrame());
-#endif
-    }
-
-    if (codeBlock->codeType() == FunctionCode && codeBlock->usesArguments()) {
-        if (Arguments* arguments = visitor->existingArguments()) {
-#if ENABLE(DFG_JIT)
-            if (visitor->isInlinedFrame())
-                arguments->tearOff(callFrame, visitor->inlineCallFrame());
-#endif
-            else
-                arguments->tearOff(callFrame);
-        }
-    }
-
     return !visitor->callerIsVMEntryFrame();
 }
 
@@ -502,6 +480,9 @@ void StackFrame::computeLineAndColumn(unsigned& line, unsigned& column)
 
     line = divotLine + lineOffset;
     column = divotColumn + (divotLine ? 1 : firstLineColumnOffset);
+
+    if (executable->hasOverrideLineNumber())
+        line = executable->overrideLineNumber();
 }
 
 void StackFrame::expressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column)
@@ -552,10 +533,10 @@ public:
                 StackFrame s = {
                     Strong<JSObject>(vm, visitor->callee()),
                     getStackFrameCodeType(visitor),
-                    Strong<ExecutableBase>(vm, codeBlock->ownerExecutable()),
+                    Strong<ScriptExecutable>(vm, codeBlock->ownerExecutable()),
                     Strong<UnlinkedCodeBlock>(vm, codeBlock->unlinkedCodeBlock()),
                     codeBlock->source(),
-                    codeBlock->ownerExecutable()->lineNo(),
+                    codeBlock->ownerExecutable()->firstLine(),
                     codeBlock->firstLineColumnOffset(),
                     codeBlock->sourceOffset(),
                     visitor->bytecodeOffset(),
@@ -563,7 +544,7 @@ public:
                 };
                 m_results.append(s);
             } else {
-                StackFrame s = { Strong<JSObject>(vm, visitor->callee()), StackFrameNativeCode, Strong<ExecutableBase>(), Strong<UnlinkedCodeBlock>(), 0, 0, 0, 0, 0, String()};
+                StackFrame s = { Strong<JSObject>(vm, visitor->callee()), StackFrameNativeCode, Strong<ScriptExecutable>(), Strong<UnlinkedCodeBlock>(), 0, 0, 0, 0, 0, String()};
                 m_results.append(s);
             }
     
@@ -602,9 +583,9 @@ JSString* Interpreter::stackTraceAsString(ExecState* exec, Vector<StackFrame> st
     return jsString(&exec->vm(), builder.toString());
 }
 
-class GetExceptionHandlerFunctor {
+class GetCatchHandlerFunctor {
 public:
-    GetExceptionHandlerFunctor()
+    GetCatchHandlerFunctor()
         : m_handler(0)
     {
     }
@@ -618,7 +599,7 @@ public:
             return StackVisitor::Continue;
 
         unsigned bytecodeOffset = visitor->bytecodeOffset();
-        m_handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset);
+        m_handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset, CodeBlock::RequiredHandler::CatchHandler);
         if (m_handler)
             return StackVisitor::Done;
 
@@ -648,7 +629,7 @@ public:
         m_codeBlock = visitor->codeBlock();
         unsigned bytecodeOffset = visitor->bytecodeOffset();
 
-        if (m_isTermination || !(m_handler = m_codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
+        if (m_isTermination || !(m_handler = m_codeBlock ? m_codeBlock->handlerForBytecodeOffset(bytecodeOffset) : nullptr)) {
             if (!unwindCallFrame(visitor)) {
                 if (LegacyProfiler* profiler = vm.enabledProfiler())
                     profiler->exceptionUnwind(m_callFrame);
@@ -668,12 +649,12 @@ private:
     HandlerInfo*& m_handler;
 };
 
-NEVER_INLINE HandlerInfo* Interpreter::unwind(VMEntryFrame*& vmEntryFrame, CallFrame*& callFrame, JSValue& exceptionValue)
+NEVER_INLINE HandlerInfo* Interpreter::unwind(VMEntryFrame*& vmEntryFrame, CallFrame*& callFrame, Exception* exception)
 {
     CodeBlock* codeBlock = callFrame->codeBlock();
-    ASSERT(codeBlock);
     bool isTermination = false;
 
+    JSValue exceptionValue = exception->value();
     ASSERT(!exceptionValue.isEmpty());
     ASSERT(!exceptionValue.isCell() || exceptionValue.asCell());
     // This shouldn't be possible (hence the assertions), but we're already in the slowest of
@@ -682,32 +663,35 @@ NEVER_INLINE HandlerInfo* Interpreter::unwind(VMEntryFrame*& vmEntryFrame, CallF
         exceptionValue = jsNull();
 
     if (exceptionValue.isObject())
-        isTermination = isTerminatedExecutionException(asObject(exceptionValue));
+        isTermination = isTerminatedExecutionException(exception);
 
-    ASSERT(callFrame->vm().exceptionStack().size());
+    ASSERT(callFrame->vm().exception() && callFrame->vm().exception()->stack().size());
 
     Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger();
-    if (debugger && debugger->needsExceptionCallbacks()) {
-        // We need to clear the exception and the exception stack here in order to see if a new exception happens.
+    if (debugger && debugger->needsExceptionCallbacks() && !exception->didNotifyInspectorOfThrow()) {
+        // We need to clear the exception here in order to see if a new exception happens.
         // Afterwards, the values are put back to continue processing this error.
-        ClearExceptionScope scope(&callFrame->vm());
+        SuspendExceptionScope scope(&callFrame->vm());
         // This code assumes that if the debugger is enabled then there is no inlining.
         // If that assumption turns out to be false then we'll ignore the inlined call
         // frames.
         // https://bugs.webkit.org/show_bug.cgi?id=121754
 
-        bool hasHandler;
+        bool hasCatchHandler;
         if (isTermination)
-            hasHandler = false;
+            hasCatchHandler = false;
         else {
-            GetExceptionHandlerFunctor functor;
+            GetCatchHandlerFunctor functor;
             callFrame->iterate(functor);
-            hasHandler = !!functor.handler();
+            HandlerInfo* handler = functor.handler();
+            ASSERT(!handler || handler->isCatchHandler());
+            hasCatchHandler = !!handler;
         }
 
-        debugger->exception(callFrame, exceptionValue, hasHandler);
+        debugger->exception(callFrame, exceptionValue, hasCatchHandler);
         ASSERT(!callFrame->hadException());
     }
+    exception->setDidNotifyInspectorOfThrow();
 
     // Calculate an exception handler vPC, unwinding call frames as necessary.
     HandlerInfo* handler = 0;
@@ -721,19 +705,6 @@ NEVER_INLINE HandlerInfo* Interpreter::unwind(VMEntryFrame*& vmEntryFrame, CallF
     if (LegacyProfiler* profiler = vm.enabledProfiler())
         profiler->exceptionUnwind(callFrame);
 
-    // Unwind the scope chain within the exception handler's call frame.
-    int targetScopeDepth = handler->scopeDepth;
-    if (codeBlock->needsActivation() && callFrame->hasActivation())
-        ++targetScopeDepth;
-
-    JSScope* scope = callFrame->scope();
-    int scopeDelta = scope->depth() - targetScopeDepth;
-    RELEASE_ASSERT(scopeDelta >= 0);
-
-    while (scopeDelta--)
-        scope = scope->next();
-    callFrame->setScope(scope);
-
     return handler;
 }
 
@@ -767,8 +738,8 @@ private:
 JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, JSObject* thisObj)
 {
     SamplingScope samplingScope(this);
-    
-    JSScope* scope = callFrame->scope();
+
+    JSScope* scope = thisObj->globalObject();
     VM& vm = *scope->vm();
 
     ASSERT(!vm.exception());
@@ -820,7 +791,7 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, J
                         PropertySlot slot(globalObject);
                         if (!globalObject->getPropertySlot(callFrame, JSONPPath[i].m_pathEntryName, slot)) {
                             if (entry)
-                                return callFrame->vm().throwException(callFrame, createUndefinedVariableError(globalObject->globalExec(), JSONPPath[i].m_pathEntryName));
+                                return callFrame->vm().throwException(callFrame, createUndefinedVariableError(callFrame, JSONPPath[i].m_pathEntryName));
                             goto failedJSONP;
                         }
                         baseObject = slot.getValue(callFrame, JSONPPath[i].m_pathEntryName);
@@ -889,33 +860,31 @@ failedJSONP:
     if (JSObject* error = program->initializeGlobalProperties(vm, callFrame, scope))
         return checkedReturn(callFrame->vm().throwException(callFrame, error));
 
-    if (JSObject* error = program->prepareForExecution(callFrame, nullptr, &scope, CodeForCall))
+    if (JSObject* error = program->prepareForExecution(callFrame, nullptr, scope, CodeForCall))
         return checkedReturn(callFrame->vm().throwException(callFrame, error));
 
     ProgramCodeBlock* codeBlock = program->codeBlock();
 
-    if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(callFrame)))
+    if (UNLIKELY(vm.shouldTriggerTermination(callFrame)))
         return throwTerminatedExecutionException(callFrame);
 
     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
 
     ProtoCallFrame protoCallFrame;
-    protoCallFrame.init(codeBlock, scope, JSCallee::create(vm, scope->globalObject(), scope), thisObj, 1);
+    protoCallFrame.init(codeBlock, JSCallee::create(vm, scope->globalObject(), scope), thisObj, 1);
 
     if (LegacyProfiler* profiler = vm.enabledProfiler())
-        profiler->willExecute(callFrame, program->sourceURL(), program->lineNo(), program->startColumn());
+        profiler->willExecute(callFrame, program->sourceURL(), program->firstLine(), program->startColumn());
 
     // Execute the code:
     JSValue result;
     {
         SamplingTool::CallRecord callRecord(m_sampler.get());
-        Watchdog::Scope watchdogScope(vm.watchdog.get());
-
         result = program->generatedJITCode()->execute(&vm, &protoCallFrame);
     }
 
     if (LegacyProfiler* profiler = vm.enabledProfiler())
-        profiler->didExecute(callFrame, program->sourceURL(), program->lineNo(), program->startColumn());
+        profiler->didExecute(callFrame, program->sourceURL(), program->firstLine(), program->startColumn());
 
     return checkedReturn(result);
 }
@@ -929,24 +898,27 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
         return jsNull();
 
     bool isJSCall = (callType == CallTypeJS);
-    JSScope* scope;
+    JSScope* scope = nullptr;
     CodeBlock* newCodeBlock;
     size_t argsCount = 1 + args.size(); // implicit "this" parameter
 
-    if (isJSCall)
+    JSGlobalObject* globalObject;
+
+    if (isJSCall) {
         scope = callData.js.scope;
-    else {
+        globalObject = scope->globalObject();
+    } else {
         ASSERT(callType == CallTypeHost);
-        scope = callFrame->scope();
+        globalObject = function->globalObject();
     }
 
-    VMEntryScope entryScope(vm, scope->globalObject());
+    VMEntryScope entryScope(vm, globalObject);
     if (!vm.isSafeToRecurse())
         return checkedReturn(throwStackOverflowError(callFrame));
 
     if (isJSCall) {
         // Compile the callee:
-        JSObject* compileError = callData.js.functionExecutable->prepareForExecution(callFrame, jsCast<JSFunction*>(function), &scope, CodeForCall);
+        JSObject* compileError = callData.js.functionExecutable->prepareForExecution(callFrame, jsCast<JSFunction*>(function), scope, CodeForCall);
         if (UNLIKELY(!!compileError)) {
             return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
         }
@@ -956,11 +928,11 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
     } else
         newCodeBlock = 0;
 
-    if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(callFrame)))
+    if (UNLIKELY(vm.shouldTriggerTermination(callFrame)))
         return throwTerminatedExecutionException(callFrame);
 
     ProtoCallFrame protoCallFrame;
-    protoCallFrame.init(newCodeBlock, scope, function, thisValue, argsCount, args.data());
+    protoCallFrame.init(newCodeBlock, function, thisValue, argsCount, args.data());
 
     if (LegacyProfiler* profiler = vm.enabledProfiler())
         profiler->willExecute(callFrame, function);
@@ -968,7 +940,6 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
     JSValue result;
     {
         SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSCall);
-        Watchdog::Scope watchdogScope(vm.watchdog.get());
 
         // Execute the code:
         if (isJSCall)
@@ -986,7 +957,7 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
     return checkedReturn(result);
 }
 
-JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
+JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args, JSValue newTarget)
 {
     VM& vm = callFrame->vm();
     ASSERT(!callFrame->hadException());
@@ -997,24 +968,27 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
         return checkedReturn(throwStackOverflowError(callFrame));
 
     bool isJSConstruct = (constructType == ConstructTypeJS);
-    JSScope* scope;
+    JSScope* scope = nullptr;
     CodeBlock* newCodeBlock;
     size_t argsCount = 1 + args.size(); // implicit "this" parameter
 
-    if (isJSConstruct)
+    JSGlobalObject* globalObject;
+
+    if (isJSConstruct) {
         scope = constructData.js.scope;
-    else {
+        globalObject = scope->globalObject();
+    } else {
         ASSERT(constructType == ConstructTypeHost);
-        scope = callFrame->scope();
+        globalObject = constructor->globalObject();
     }
 
-    VMEntryScope entryScope(vm, scope->globalObject());
+    VMEntryScope entryScope(vm, globalObject);
     if (!vm.isSafeToRecurse())
         return checkedReturn(throwStackOverflowError(callFrame));
 
     if (isJSConstruct) {
         // Compile the callee:
-        JSObject* compileError = constructData.js.functionExecutable->prepareForExecution(callFrame, jsCast<JSFunction*>(constructor), &scope, CodeForConstruct);
+        JSObject* compileError = constructData.js.functionExecutable->prepareForExecution(callFrame, jsCast<JSFunction*>(constructor), scope, CodeForConstruct);
         if (UNLIKELY(!!compileError)) {
             return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
         }
@@ -1024,11 +998,11 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
     } else
         newCodeBlock = 0;
 
-    if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(callFrame)))
+    if (UNLIKELY(vm.shouldTriggerTermination(callFrame)))
         return throwTerminatedExecutionException(callFrame);
 
     ProtoCallFrame protoCallFrame;
-    protoCallFrame.init(newCodeBlock, scope, constructor, jsUndefined(), argsCount, args.data());
+    protoCallFrame.init(newCodeBlock, constructor, newTarget, argsCount, args.data());
 
     if (LegacyProfiler* profiler = vm.enabledProfiler())
         profiler->willExecute(callFrame, constructor);
@@ -1036,7 +1010,6 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
     JSValue result;
     {
         SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSConstruct);
-        Watchdog::Scope watchdogScope(vm.watchdog.get());
 
         // Execute the code.
         if (isJSConstruct)
@@ -1067,7 +1040,7 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionE
         return CallFrameClosure();
 
     // Compile the callee:
-    JSObject* error = functionExecutable->prepareForExecution(callFrame, function, &scope, CodeForCall);
+    JSObject* error = functionExecutable->prepareForExecution(callFrame, function, scope, CodeForCall);
     if (error) {
         callFrame->vm().throwException(callFrame, error);
         return CallFrameClosure();
@@ -1077,7 +1050,7 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionE
 
     size_t argsCount = argumentCountIncludingThis;
 
-    protoCallFrame->init(newCodeBlock, scope, function, jsUndefined(), argsCount, args);
+    protoCallFrame->init(newCodeBlock, function, jsUndefined(), argsCount, args);
     // Return the successful closure:
     CallFrameClosure result = { callFrame, protoCallFrame, function, functionExecutable, &vm, scope, newCodeBlock->numParameters(), argumentCountIncludingThis };
     return result;
@@ -1094,20 +1067,17 @@ JSValue Interpreter::execute(CallFrameClosure& closure)
         return jsNull();
 
     StackStats::CheckPoint stackCheckPoint;
-    closure.resetCallFrame();
 
     if (LegacyProfiler* profiler = vm.enabledProfiler())
         profiler->willExecute(closure.oldCallFrame, closure.function);
 
-    if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(closure.oldCallFrame)))
+    if (UNLIKELY(vm.shouldTriggerTermination(closure.oldCallFrame)))
         return throwTerminatedExecutionException(closure.oldCallFrame);
 
     // Execute the code:
     JSValue result;
     {
         SamplingTool::CallRecord callRecord(m_sampler.get());
-        Watchdog::Scope watchdogScope(vm.watchdog.get());
-
         result = closure.functionExecutable->generatedJITCodeForCall()->execute(&vm, closure.protoCallFrame);
     }
 
@@ -1138,19 +1108,26 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
 
     JSScope* variableObject;
     if ((numVariables || numFunctions) && eval->isStrictMode()) {
-        scope = StrictEvalActivation::create(callFrame);
+        scope = StrictEvalActivation::create(callFrame, scope);
         variableObject = scope;
     } else {
         for (JSScope* node = scope; ; node = node->next()) {
             RELEASE_ASSERT(node);
-            if (node->isVariableObject() && !node->isNameScopeObject()) {
+            if (node->isGlobalObject()) {
                 variableObject = node;
                 break;
+            } 
+            if (JSLexicalEnvironment* lexicalEnvironment = jsDynamicCast<JSLexicalEnvironment*>(node)) {
+                if (lexicalEnvironment->symbolTable()->scopeType() == SymbolTable::ScopeType::VarScope) {
+                    variableObject = node;
+                    break;
+                }
             }
         }
+        ASSERT(!variableObject->isNameScopeObject());
     }
 
-    JSObject* compileError = eval->prepareForExecution(callFrame, nullptr, &scope, CodeForCall);
+    JSObject* compileError = eval->prepareForExecution(callFrame, nullptr, scope, CodeForCall);
     if (UNLIKELY(!!compileError))
         return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
     EvalCodeBlock* codeBlock = eval->codeBlock();
@@ -1175,28 +1152,26 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
         }
     }
 
-    if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(callFrame)))
+    if (UNLIKELY(vm.shouldTriggerTermination(callFrame)))
         return throwTerminatedExecutionException(callFrame);
 
     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
 
     ProtoCallFrame protoCallFrame;
-    protoCallFrame.init(codeBlock, scope, JSCallee::create(vm, scope->globalObject(), scope), thisValue, 1);
+    protoCallFrame.init(codeBlock, JSCallee::create(vm, scope->globalObject(), scope), thisValue, 1);
 
     if (LegacyProfiler* profiler = vm.enabledProfiler())
-        profiler->willExecute(callFrame, eval->sourceURL(), eval->lineNo(), eval->startColumn());
+        profiler->willExecute(callFrame, eval->sourceURL(), eval->firstLine(), eval->startColumn());
 
     // Execute the code:
     JSValue result;
     {
         SamplingTool::CallRecord callRecord(m_sampler.get());
-        Watchdog::Scope watchdogScope(vm.watchdog.get());
-
         result = eval->generatedJITCode()->execute(&vm, &protoCallFrame);
     }
 
     if (LegacyProfiler* profiler = vm.enabledProfiler())
-        profiler->didExecute(callFrame, eval->sourceURL(), eval->lineNo(), eval->startColumn());
+        profiler->didExecute(callFrame, eval->sourceURL(), eval->firstLine(), eval->startColumn());
 
     return checkedReturn(result);
 }
@@ -1237,7 +1212,7 @@ void Interpreter::enableSampler()
 {
 #if ENABLE(OPCODE_SAMPLING)
     if (!m_sampler) {
-        m_sampler = adoptPtr(new SamplingTool(this));
+        m_sampler = std::make_unique<SamplingTool>(this);
         m_sampler->setup();
     }
 #endif