Remove excessive headers from JavaScriptCore
[WebKit-https.git] / Source / JavaScriptCore / jsc.cpp
index a189757..6f176a9 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2004-2008, 2012-2013, 2015-2016 Apple Inc. All rights reserved.
+ *  Copyright (C) 2004-2017 Apple Inc. All rights reserved.
  *  Copyright (C) 2006 Bjoern Graf (bjoern.graf@gmail.com)
  *
  *  This library is free software; you can redistribute it and/or
 #include "ArrayBuffer.h"
 #include "ArrayPrototype.h"
 #include "BuiltinExecutableCreator.h"
+#include "BuiltinNames.h"
 #include "ButterflyInlines.h"
+#include "CatchScope.h"
 #include "CodeBlock.h"
 #include "Completion.h"
+#include "ConfigFile.h"
 #include "DOMJITGetterSetter.h"
-#include "DOMJITPatchpoint.h"
-#include "DOMJITPatchpointParams.h"
 #include "Disassembler.h"
 #include "Exception.h"
 #include "ExceptionHelpers.h"
+#include "FrameTracers.h"
 #include "GetterSetter.h"
 #include "HeapProfiler.h"
 #include "HeapSnapshotBuilder.h"
-#include "HeapStatistics.h"
 #include "InitializeThreading.h"
 #include "Interpreter.h"
 #include "JIT.h"
 #include "JSInternalPromise.h"
 #include "JSInternalPromiseDeferred.h"
 #include "JSLock.h"
+#include "JSModuleLoader.h"
 #include "JSNativeStdFunction.h"
 #include "JSONObject.h"
 #include "JSProxy.h"
+#include "JSSourceCode.h"
 #include "JSString.h"
 #include "JSTypedArrays.h"
+#include "JSWebAssemblyInstance.h"
+#include "JSWebAssemblyMemory.h"
 #include "LLIntData.h"
 #include "LLIntThunks.h"
 #include "ObjectConstructor.h"
 #include "ParserError.h"
 #include "ProfilerDatabase.h"
+#include "PromiseDeferredTimer.h"
 #include "ProtoCallFrame.h"
+#include "ReleaseHeapAccessScope.h"
 #include "SamplingProfiler.h"
 #include "ShadowChicken.h"
+#include "Snippet.h"
+#include "SnippetParams.h"
 #include "StackVisitor.h"
 #include "StructureInlines.h"
 #include "StructureRareDataInlines.h"
 #include "SuperSampler.h"
 #include "TestRunnerUtils.h"
+#include "TypeProfiler.h"
 #include "TypeProfilerLog.h"
-#include "WasmPlan.h"
+#include "WasmContext.h"
+#include "WasmFaultSignalHandler.h"
+#include "WasmMemory.h"
 #include <locale.h>
 #include <math.h>
 #include <stdio.h>
@@ -75,6 +87,7 @@
 #include <string.h>
 #include <thread>
 #include <type_traits>
+#include <wtf/CommaPrinter.h>
 #include <wtf/CurrentTime.h>
 #include <wtf/MainThread.h>
 #include <wtf/NeverDestroyed.h>
@@ -83,6 +96,7 @@
 
 #if OS(WINDOWS)
 #include <direct.h>
+#include <wtf/text/win/WCharStringExtras.h>
 #else
 #include <unistd.h>
 #endif
 #include <arm/arch.h>
 #endif
 
-#if PLATFORM(EFL)
-#include <Ecore.h>
-#endif
-
 #if !defined(PATH_MAX)
 #define PATH_MAX 4096
 #endif
@@ -160,7 +170,6 @@ public:
     }
 
     typedef JSNonFinalObject Base;
-    static const bool needsDestruction = false;
 
     Root* root() const { return m_root.get(); }
     void setRoot(VM& vm, Root* root) { m_root.set(vm, this, root); }
@@ -180,7 +189,7 @@ public:
         Element* thisObject = jsCast<Element*>(cell);
         ASSERT_GC_OBJECT_INHERITS(thisObject, info());
         Base::visitChildren(thisObject, visitor);
-        visitor.append(&thisObject->m_root);
+        visitor.append(thisObject->m_root);
     }
 
     static ElementHandleOwner* handleOwner();
@@ -198,7 +207,7 @@ private:
 
 class ElementHandleOwner : public WeakHandleOwner {
 public:
-    virtual bool isReachableFromOpaqueRoots(Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
+    bool isReachableFromOpaqueRoots(Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor) override
     {
         Element* element = jsCast<Element*>(handle.slot()->asCell());
         return visitor.containsOpaqueRoot(element->root());
@@ -261,7 +270,6 @@ public:
     typedef JSDestructibleObject Base;
 
     DECLARE_INFO;
-    static const bool needsDestruction = true;
 
     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
     {
@@ -327,7 +335,7 @@ public:
     {
         Base::visitChildren(cell, visitor);
         ImpureGetter* thisObject = jsCast<ImpureGetter*>(cell);
-        visitor.append(&thisObject->m_delegate);
+        visitor.append(thisObject->m_delegate);
     }
 
     void setDelegate(VM& vm, JSObject* delegate)
@@ -369,6 +377,12 @@ public:
             slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject->customGetter);
             return true;
         }
+        
+        if (propertyName == PropertyName(Identifier::fromString(exec, "customGetterAccessor"))) {
+            slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum | CustomAccessor, thisObject->customGetterAcessor);
+            return true;
+        }
+        
         return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
     }
 
@@ -378,7 +392,22 @@ private:
         VM& vm = exec->vm();
         auto scope = DECLARE_THROW_SCOPE(vm);
 
-        CustomGetter* thisObject = jsDynamicCast<CustomGetter*>(JSValue::decode(thisValue));
+        CustomGetter* thisObject = jsDynamicCast<CustomGetter*>(vm, JSValue::decode(thisValue));
+        if (!thisObject)
+            return throwVMTypeError(exec, scope);
+        bool shouldThrow = thisObject->get(exec, PropertyName(Identifier::fromString(exec, "shouldThrow"))).toBoolean(exec);
+        RETURN_IF_EXCEPTION(scope, encodedJSValue());
+        if (shouldThrow)
+            return throwVMTypeError(exec, scope);
+        return JSValue::encode(jsNumber(100));
+    }
+    
+    static EncodedJSValue customGetterAcessor(ExecState* exec, EncodedJSValue thisValue, PropertyName)
+    {
+        VM& vm = exec->vm();
+        auto scope = DECLARE_THROW_SCOPE(vm);
+        
+        JSObject* thisObject = jsDynamicCast<JSObject*>(vm, JSValue::decode(thisValue));
         if (!thisObject)
             return throwVMTypeError(exec, scope);
         bool shouldThrow = thisObject->get(exec, PropertyName(Identifier::fromString(exec, "shouldThrow"))).toBoolean(exec);
@@ -421,7 +450,7 @@ public:
             return true;
         }
 
-        Optional<uint32_t> index = parseIndex(propertyName);
+        std::optional<uint32_t> index = parseIndex(propertyName);
         if (index && index.value() < thisObject->getLength()) {
             slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index.value()]));
             return true;
@@ -468,8 +497,9 @@ public:
 protected:
     void finishCreation(ExecState* exec)
     {
-        Base::finishCreation(exec->vm());
-        ASSERT(inherits(info()));
+        VM& vm = exec->vm();
+        Base::finishCreation(vm);
+        ASSERT(inherits(vm, info()));
 
         for (size_t i = 0; i < exec->argumentCount(); i++)
             m_vector.append(exec->argument(i).toInt32(exec));
@@ -486,7 +516,7 @@ private:
         VM& vm = exec->vm();
         auto scope = DECLARE_THROW_SCOPE(vm);
 
-        RuntimeArray* thisObject = jsDynamicCast<RuntimeArray*>(JSValue::decode(thisValue));
+        RuntimeArray* thisObject = jsDynamicCast<RuntimeArray*>(vm, JSValue::decode(thisValue));
         if (!thisObject)
             return throwVMTypeError(exec, scope);
         return JSValue::encode(jsNumber(thisObject->getLength()));
@@ -518,7 +548,7 @@ public:
         SimpleObject* thisObject = jsCast<SimpleObject*>(cell);
         ASSERT_GC_OBJECT_INHERITS(thisObject, info());
         Base::visitChildren(thisObject, visitor);
-        visitor.append(&thisObject->m_hiddenValue);
+        visitor.append(thisObject->m_hiddenValue);
     }
 
     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
@@ -560,10 +590,10 @@ public:
     }
 
 #if ENABLE(JIT)
-    static Ref<DOMJIT::Patchpoint> checkDOMJITNode()
+    static Ref<Snippet> checkSubClassSnippet()
     {
-        Ref<DOMJIT::Patchpoint> patchpoint = DOMJIT::Patchpoint::create();
-        patchpoint->setGenerator([=](CCallHelpers& jit, DOMJIT::PatchpointParams& params) {
+        Ref<Snippet> snippet = Snippet::create();
+        snippet->setGenerator([=](CCallHelpers& jit, SnippetParams& params) {
             CCallHelpers::JumpList failureCases;
             failureCases.append(jit.branch8(
                 CCallHelpers::NotEqual,
@@ -571,7 +601,7 @@ public:
                 CCallHelpers::TrustedImm32(JSC::JSType(LastJSCObjectType + 1))));
             return failureCases;
         });
-        return patchpoint;
+        return snippet;
     }
 #endif
 
@@ -624,29 +654,24 @@ public:
         }
 
 #if ENABLE(JIT)
-        Ref<DOMJIT::Patchpoint> checkDOM() override
-        {
-            return DOMJITNode::checkDOMJITNode();
-        }
-
         static EncodedJSValue JIT_OPERATION slowCall(ExecState* exec, void* pointer)
         {
             NativeCallFrameTracer tracer(&exec->vm(), exec);
             return JSValue::encode(jsNumber(static_cast<DOMJITGetter*>(pointer)->value()));
         }
 
-        Ref<DOMJIT::CallDOMGetterPatchpoint> callDOMGetter() override
+        Ref<DOMJIT::CallDOMGetterSnippet> callDOMGetter() override
         {
-            Ref<DOMJIT::CallDOMGetterPatchpoint> patchpoint = DOMJIT::CallDOMGetterPatchpoint::create();
-            patchpoint->requireGlobalObject = false;
-            patchpoint->setGenerator([=](CCallHelpers& jit, DOMJIT::PatchpointParams& params) {
+            Ref<DOMJIT::CallDOMGetterSnippet> snippet = DOMJIT::CallDOMGetterSnippet::create();
+            snippet->requireGlobalObject = false;
+            snippet->setGenerator([=](CCallHelpers& jit, SnippetParams& params) {
                 JSValueRegs results = params[0].jsValueRegs();
                 GPRReg dom = params[1].gpr();
                 params.addSlowPathCall(jit.jump(), jit, slowCall, results, dom);
                 return CCallHelpers::JumpList();
 
             });
-            return patchpoint;
+            return snippet;
         }
 #endif
     };
@@ -671,7 +696,7 @@ private:
         VM& vm = exec->vm();
         auto scope = DECLARE_THROW_SCOPE(vm);
 
-        DOMJITNode* thisObject = jsDynamicCast<DOMJITNode*>(JSValue::decode(thisValue));
+        DOMJITNode* thisObject = jsDynamicCast<DOMJITNode*>(vm, JSValue::decode(thisValue));
         if (!thisObject)
             return throwVMTypeError(exec, scope);
         return JSValue::encode(jsNumber(thisObject->value()));
@@ -709,18 +734,13 @@ public:
         }
 
 #if ENABLE(JIT)
-        Ref<DOMJIT::Patchpoint> checkDOM() override
-        {
-            return DOMJITNode::checkDOMJITNode();
-        }
-
         static EncodedJSValue JIT_OPERATION slowCall(ExecState* exec, void* pointer)
         {
             VM& vm = exec->vm();
             NativeCallFrameTracer tracer(&vm, exec);
             auto scope = DECLARE_THROW_SCOPE(vm);
             auto* object = static_cast<DOMJITNode*>(pointer);
-            auto* domjitGetterComplex = jsDynamicCast<DOMJITGetterComplex*>(object);
+            auto* domjitGetterComplex = jsDynamicCast<DOMJITGetterComplex*>(vm, object);
             if (domjitGetterComplex) {
                 if (domjitGetterComplex->m_enableException)
                     return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("DOMJITGetterComplex slow call exception"))));
@@ -728,23 +748,23 @@ public:
             return JSValue::encode(jsNumber(object->value()));
         }
 
-        Ref<DOMJIT::CallDOMGetterPatchpoint> callDOMGetter() override
+        Ref<DOMJIT::CallDOMGetterSnippet> callDOMGetter() override
         {
-            RefPtr<DOMJIT::CallDOMGetterPatchpoint> patchpoint = DOMJIT::CallDOMGetterPatchpoint::create();
+            RefPtr<DOMJIT::CallDOMGetterSnippet> snippet = DOMJIT::CallDOMGetterSnippet::create();
             static_assert(GPRInfo::numberOfRegisters >= 4, "Number of registers should be larger or equal to 4.");
-            patchpoint->numGPScratchRegisters = GPRInfo::numberOfRegisters - 4;
-            patchpoint->numFPScratchRegisters = 3;
-            patchpoint->setGenerator([=](CCallHelpers& jit, DOMJIT::PatchpointParams& params) {
+            snippet->numGPScratchRegisters = GPRInfo::numberOfRegisters - 4;
+            snippet->numFPScratchRegisters = 3;
+            snippet->setGenerator([=](CCallHelpers& jit, SnippetParams& params) {
                 JSValueRegs results = params[0].jsValueRegs();
                 GPRReg domGPR = params[1].gpr();
-                for (unsigned i = 0; i < patchpoint->numGPScratchRegisters; ++i)
+                for (unsigned i = 0; i < snippet->numGPScratchRegisters; ++i)
                     jit.move(CCallHelpers::TrustedImm32(42), params.gpScratch(i));
 
                 params.addSlowPathCall(jit.jump(), jit, slowCall, results, domGPR);
                 return CCallHelpers::JumpList();
 
             });
-            return *patchpoint.get();
+            return *snippet.get();
         }
 #endif
     };
@@ -767,7 +787,8 @@ private:
 
     static EncodedJSValue JSC_HOST_CALL functionEnableException(ExecState* exec)
     {
-        auto* object = jsDynamicCast<DOMJITGetterComplex*>(exec->thisValue());
+        VM& vm = exec->vm();
+        auto* object = jsDynamicCast<DOMJITGetterComplex*>(vm, exec->thisValue());
         if (object)
             object->m_enableException = true;
         return JSValue::encode(jsUndefined());
@@ -778,10 +799,10 @@ private:
         VM& vm = exec->vm();
         auto scope = DECLARE_THROW_SCOPE(vm);
 
-        auto* thisObject = jsDynamicCast<DOMJITNode*>(JSValue::decode(thisValue));
+        auto* thisObject = jsDynamicCast<DOMJITNode*>(vm, JSValue::decode(thisValue));
         if (!thisObject)
             return throwVMTypeError(exec, scope);
-        if (auto* domjitGetterComplex = jsDynamicCast<DOMJITGetterComplex*>(JSValue::decode(thisValue))) {
+        if (auto* domjitGetterComplex = jsDynamicCast<DOMJITGetterComplex*>(vm, JSValue::decode(thisValue))) {
             if (domjitGetterComplex->m_enableException)
                 return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("DOMJITGetterComplex slow call exception"))));
         }
@@ -820,25 +841,25 @@ public:
         VM& vm = exec->vm();
         auto scope = DECLARE_THROW_SCOPE(vm);
 
-        DOMJITNode* thisObject = jsDynamicCast<DOMJITNode*>(exec->thisValue());
+        DOMJITNode* thisObject = jsDynamicCast<DOMJITNode*>(vm, exec->thisValue());
         if (!thisObject)
             return throwVMTypeError(exec, scope);
         return JSValue::encode(jsNumber(thisObject->value()));
     }
 
-#if ENABLE(JIT)
     static EncodedJSValue JIT_OPERATION unsafeFunction(ExecState* exec, DOMJITNode* node)
     {
         NativeCallFrameTracer tracer(&exec->vm(), exec);
         return JSValue::encode(jsNumber(node->value()));
     }
 
-    static Ref<DOMJIT::Patchpoint> checkDOMJITNode()
+#if ENABLE(JIT)
+    static Ref<Snippet> checkSubClassSnippet()
     {
-        static const double value = 42.0;
-        Ref<DOMJIT::Patchpoint> patchpoint = DOMJIT::Patchpoint::create();
-        patchpoint->numFPScratchRegisters = 1;
-        patchpoint->setGenerator([=](CCallHelpers& jit, DOMJIT::PatchpointParams& params) {
+        Ref<Snippet> snippet = Snippet::create();
+        snippet->numFPScratchRegisters = 1;
+        snippet->setGenerator([=](CCallHelpers& jit, SnippetParams& params) {
+            static const double value = 42.0;
             CCallHelpers::JumpList failureCases;
             // May use scratch registers.
             jit.loadDouble(CCallHelpers::TrustedImmPtr(&value), params.fpScratch(0));
@@ -848,7 +869,7 @@ public:
                 CCallHelpers::TrustedImm32(JSC::JSType(LastJSCObjectType + 1))));
             return failureCases;
         });
-        return patchpoint;
+        return snippet;
     }
 #endif
 
@@ -856,34 +877,89 @@ private:
     void finishCreation(VM&, JSGlobalObject*);
 };
 
-#if ENABLE(JIT)
-static const DOMJIT::Signature DOMJITFunctionObjectSignature((uintptr_t)DOMJITFunctionObject::unsafeFunction, DOMJITFunctionObject::checkDOMJITNode, DOMJITFunctionObject::info(), DOMJIT::Effect::forRead(DOMJIT::HeapRange::top()), SpecInt32Only);
-#endif
+static const DOMJIT::Signature DOMJITFunctionObjectSignature((uintptr_t)DOMJITFunctionObject::unsafeFunction, DOMJITFunctionObject::info(), DOMJIT::Effect::forRead(DOMJIT::HeapRange::top()), SpecInt32Only);
 
 void DOMJITFunctionObject::finishCreation(VM& vm, JSGlobalObject* globalObject)
 {
     Base::finishCreation(vm);
-#if ENABLE(JIT)
     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "func"), 0, safeFunction, NoIntrinsic, &DOMJITFunctionObjectSignature, ReadOnly);
-#else
-    putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "func"), 0, safeFunction, NoIntrinsic, nullptr, ReadOnly);
-#endif
 }
 
+class DOMJITCheckSubClassObject : public DOMJITNode {
+public:
+    DOMJITCheckSubClassObject(VM& vm, Structure* structure)
+        : Base(vm, structure)
+    {
+    }
+
+    DECLARE_INFO;
+    typedef DOMJITNode Base;
+    static const unsigned StructureFlags = Base::StructureFlags;
+
+
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
+    }
+
+    static DOMJITCheckSubClassObject* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
+    {
+        DOMJITCheckSubClassObject* object = new (NotNull, allocateCell<DOMJITCheckSubClassObject>(vm.heap, sizeof(DOMJITCheckSubClassObject))) DOMJITCheckSubClassObject(vm, structure);
+        object->finishCreation(vm, globalObject);
+        return object;
+    }
+
+    static EncodedJSValue JSC_HOST_CALL safeFunction(ExecState* exec)
+    {
+        VM& vm = exec->vm();
+        auto scope = DECLARE_THROW_SCOPE(vm);
+
+        auto* thisObject = jsDynamicCast<DOMJITCheckSubClassObject*>(vm, exec->thisValue());
+        if (!thisObject)
+            return throwVMTypeError(exec, scope);
+        return JSValue::encode(jsNumber(thisObject->value()));
+    }
+
+    static EncodedJSValue JIT_OPERATION unsafeFunction(ExecState* exec, DOMJITNode* node)
+    {
+        NativeCallFrameTracer tracer(&exec->vm(), exec);
+        return JSValue::encode(jsNumber(node->value()));
+    }
+
+private:
+    void finishCreation(VM&, JSGlobalObject*);
+};
+
+static const DOMJIT::Signature DOMJITCheckSubClassObjectSignature((uintptr_t)DOMJITCheckSubClassObject::unsafeFunction, DOMJITCheckSubClassObject::info(), DOMJIT::Effect::forRead(DOMJIT::HeapRange::top()), SpecInt32Only);
+
+void DOMJITCheckSubClassObject::finishCreation(VM& vm, JSGlobalObject* globalObject)
+{
+    Base::finishCreation(vm);
+    putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "func"), 0, safeFunction, NoIntrinsic, &DOMJITCheckSubClassObjectSignature, ReadOnly);
+}
 
-const ClassInfo Element::s_info = { "Element", &Base::s_info, nullptr, CREATE_METHOD_TABLE(Element) };
-const ClassInfo Masquerader::s_info = { "Masquerader", &Base::s_info, nullptr, CREATE_METHOD_TABLE(Masquerader) };
-const ClassInfo Root::s_info = { "Root", &Base::s_info, nullptr, CREATE_METHOD_TABLE(Root) };
-const ClassInfo ImpureGetter::s_info = { "ImpureGetter", &Base::s_info, nullptr, CREATE_METHOD_TABLE(ImpureGetter) };
-const ClassInfo CustomGetter::s_info = { "CustomGetter", &Base::s_info, nullptr, CREATE_METHOD_TABLE(CustomGetter) };
-const ClassInfo DOMJITNode::s_info = { "DOMJITNode", &Base::s_info, nullptr, CREATE_METHOD_TABLE(DOMJITNode) };
-const ClassInfo DOMJITGetter::s_info = { "DOMJITGetter", &Base::s_info, nullptr, CREATE_METHOD_TABLE(DOMJITGetter) };
-const ClassInfo DOMJITGetterComplex::s_info = { "DOMJITGetterComplex", &Base::s_info, nullptr, CREATE_METHOD_TABLE(DOMJITGetterComplex) };
-const ClassInfo DOMJITFunctionObject::s_info = { "DOMJITFunctionObject", &Base::s_info, nullptr, CREATE_METHOD_TABLE(DOMJITFunctionObject) };
-const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, nullptr, CREATE_METHOD_TABLE(RuntimeArray) };
-const ClassInfo SimpleObject::s_info = { "SimpleObject", &Base::s_info, nullptr, CREATE_METHOD_TABLE(SimpleObject) };
-static bool test262AsyncPassed { false };
-static bool test262AsyncTest { false };
+const ClassInfo Element::s_info = { "Element", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(Element) };
+const ClassInfo Masquerader::s_info = { "Masquerader", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(Masquerader) };
+const ClassInfo Root::s_info = { "Root", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(Root) };
+const ClassInfo ImpureGetter::s_info = { "ImpureGetter", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ImpureGetter) };
+const ClassInfo CustomGetter::s_info = { "CustomGetter", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(CustomGetter) };
+#if ENABLE(JIT)
+const ClassInfo DOMJITNode::s_info = { "DOMJITNode", &Base::s_info, nullptr, &DOMJITNode::checkSubClassSnippet, CREATE_METHOD_TABLE(DOMJITNode) };
+#else
+const ClassInfo DOMJITNode::s_info = { "DOMJITNode", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITNode) };
+#endif
+const ClassInfo DOMJITGetter::s_info = { "DOMJITGetter", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITGetter) };
+const ClassInfo DOMJITGetterComplex::s_info = { "DOMJITGetterComplex", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITGetterComplex) };
+#if ENABLE(JIT)
+const ClassInfo DOMJITFunctionObject::s_info = { "DOMJITFunctionObject", &Base::s_info, nullptr, &DOMJITFunctionObject::checkSubClassSnippet, CREATE_METHOD_TABLE(DOMJITFunctionObject) };
+#else
+const ClassInfo DOMJITFunctionObject::s_info = { "DOMJITFunctionObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITFunctionObject) };
+#endif
+const ClassInfo DOMJITCheckSubClassObject::s_info = { "DOMJITCheckSubClassObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMJITCheckSubClassObject) };
+const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(RuntimeArray) };
+const ClassInfo SimpleObject::s_info = { "SimpleObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(SimpleObject) };
+static unsigned asyncTestPasses { 0 };
+static unsigned asyncTestExpectedPasses { 0 };
 
 ElementHandleOwner* Element::handleOwner()
 {
@@ -904,6 +980,67 @@ void Element::finishCreation(VM& vm, Root* root)
 
 static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer);
 
+class CommandLine;
+class GlobalObject;
+class Workers;
+
+template<typename Func>
+int runJSC(CommandLine, bool isWorker, const Func&);
+static void checkException(GlobalObject*, bool isLastFile, bool hasException, JSValue, const String& uncaughtExceptionName, bool alwaysDumpUncaughtException, bool dump, bool& success);
+
+class Message : public ThreadSafeRefCounted<Message> {
+public:
+    Message(ArrayBufferContents&&, int32_t);
+    ~Message();
+    
+    ArrayBufferContents&& releaseContents() { return WTFMove(m_contents); }
+    int32_t index() const { return m_index; }
+
+private:
+    ArrayBufferContents m_contents;
+    int32_t m_index { 0 };
+};
+
+class Worker : public BasicRawSentinelNode<Worker> {
+public:
+    Worker(Workers&);
+    ~Worker();
+    
+    void enqueue(const AbstractLocker&, RefPtr<Message>);
+    RefPtr<Message> dequeue();
+    
+    static Worker& current();
+
+private:
+    static ThreadSpecific<Worker*>& currentWorker();
+
+    Workers& m_workers;
+    Deque<RefPtr<Message>> m_messages;
+};
+
+class Workers {
+public:
+    Workers();
+    ~Workers();
+    
+    template<typename Func>
+    void broadcast(const Func&);
+    
+    void report(String);
+    String tryGetReport();
+    String getReport();
+    
+    static Workers& singleton();
+    
+private:
+    friend class Worker;
+    
+    Lock m_lock;
+    Condition m_condition;
+    SentinelLinkedList<Worker, BasicRawSentinelNode<Worker>> m_workers;
+    Deque<String> m_reports;
+};
+
 static EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState*);
@@ -912,6 +1049,7 @@ static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITNodeObject(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterObject(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterComplexObject(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITFunctionObject(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITCheckSubClassObject(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionCreateGlobalObject(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState*);
@@ -990,8 +1128,12 @@ static EncodedJSValue JSC_HOST_CALL functionStartSamplingProfiler(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionSamplingProfilerStackTraces(ExecState*);
 #endif
 
+static EncodedJSValue JSC_HOST_CALL functionMaxArguments(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionAsyncTestStart(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionAsyncTestPassed(ExecState*);
+
 #if ENABLE(WEBASSEMBLY)
-static EncodedJSValue JSC_HOST_CALL functionTestWasmModuleFunctions(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionWebAssemblyMemoryMode(ExecState*);
 #endif
 
 #if ENABLE(SAMPLING_FLAGS)
@@ -1004,6 +1146,21 @@ static EncodedJSValue JSC_HOST_CALL functionSetGlobalConstRedeclarationShouldNot
 static EncodedJSValue JSC_HOST_CALL functionGetRandomSeed(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionSetRandomSeed(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionIsRope(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionCallerSourceOrigin(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionGlobalObjectForObject(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionDollarCreateRealm(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionDollarDetachArrayBuffer(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionDollarEvalScript(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionDollarAgentStart(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionDollarAgentReceiveBroadcast(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionDollarAgentReport(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionDollarAgentSleep(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionDollarAgentBroadcast(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionDollarAgentGetReport(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionDollarAgentLeaving(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionWaitForReport(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionHeapCapacity(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionFlashHeapAccess(ExecState*);
 
 struct Script {
     enum class StrictMode {
@@ -1095,10 +1252,10 @@ static inline String stringFromUTF(const Vector& utf8)
 }
 
 template<typename Vector>
-static inline SourceCode jscSource(const Vector& utf8, const String& filename)
+static inline SourceCode jscSource(const Vector& utf8, const SourceOrigin& sourceOrigin, const String& filename)
 {
     String str = stringFromUTF(utf8);
-    return makeSource(str, filename);
+    return makeSource(str, sourceOrigin, filename);
 }
 
 class GlobalObject : public JSGlobalObject {
@@ -1112,7 +1269,6 @@ public:
     {
         GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure);
         object->finishCreation(vm, arguments);
-        vm.heap.addFinalizer(object, destroy);
         return object;
     }
 
@@ -1208,6 +1364,7 @@ protected:
         addFunction(vm, "createDOMJITGetterObject", functionCreateDOMJITGetterObject, 0);
         addFunction(vm, "createDOMJITGetterComplexObject", functionCreateDOMJITGetterComplexObject, 0);
         addFunction(vm, "createDOMJITFunctionObject", functionCreateDOMJITFunctionObject, 0);
+        addFunction(vm, "createDOMJITCheckSubClassObject", functionCreateDOMJITCheckSubClassObject, 0);
         addFunction(vm, "createBuiltin", functionCreateBuiltin, 2);
         addFunction(vm, "createGlobalObject", functionCreateGlobalObject, 0);
         addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
@@ -1227,6 +1384,9 @@ protected:
         addFunction(vm, "getRandomSeed", functionGetRandomSeed, 0);
         addFunction(vm, "setRandomSeed", functionSetRandomSeed, 1);
         addFunction(vm, "isRope", functionIsRope, 1);
+        addFunction(vm, "callerSourceOrigin", functionCallerSourceOrigin, 0);
+
+        addFunction(vm, "globalObjectForObject", functionGlobalObjectForObject, 1);
 
         addFunction(vm, "is32BitPlatform", functionIs32BitPlatform, 0);
 
@@ -1242,8 +1402,13 @@ protected:
         addFunction(vm, "samplingProfilerStackTraces", functionSamplingProfilerStackTraces, 0);
 #endif
 
+        addFunction(vm, "maxArguments", functionMaxArguments, 0);
+
+        addFunction(vm, "asyncTestStart", functionAsyncTestStart, 1);
+        addFunction(vm, "asyncTestPassed", functionAsyncTestPassed, 1);
+
 #if ENABLE(WEBASSEMBLY)
-        addFunction(vm, "testWasmModuleFunctions", functionTestWasmModuleFunctions, 0);
+        addFunction(vm, "WebAssemblyMemoryMode", functionWebAssemblyMemoryMode, 1);
 #endif
 
         if (!arguments.isEmpty()) {
@@ -1254,12 +1419,46 @@ protected:
         }
 
         putDirect(vm, Identifier::fromString(globalExec(), "console"), jsUndefined());
+        
+        Structure* plainObjectStructure = JSFinalObject::createStructure(vm, this, objectPrototype(), 0);
+        
+        JSObject* dollar = JSFinalObject::create(vm, plainObjectStructure);
+        putDirect(vm, Identifier::fromString(globalExec(), "$"), dollar);
+        
+        addFunction(vm, dollar, "createRealm", functionDollarCreateRealm, 0);
+        addFunction(vm, dollar, "detachArrayBuffer", functionDollarDetachArrayBuffer, 1);
+        addFunction(vm, dollar, "evalScript", functionDollarEvalScript, 1);
+        
+        dollar->putDirect(vm, Identifier::fromString(globalExec(), "global"), this);
+        
+        JSObject* agent = JSFinalObject::create(vm, plainObjectStructure);
+        dollar->putDirect(vm, Identifier::fromString(globalExec(), "agent"), agent);
+        
+        // The test262 INTERPRETING.md document says that some of these functions are just in the main
+        // thread and some are in the other threads. We just put them in all threads.
+        addFunction(vm, agent, "start", functionDollarAgentStart, 1);
+        addFunction(vm, agent, "receiveBroadcast", functionDollarAgentReceiveBroadcast, 1);
+        addFunction(vm, agent, "report", functionDollarAgentReport, 1);
+        addFunction(vm, agent, "sleep", functionDollarAgentSleep, 1);
+        addFunction(vm, agent, "broadcast", functionDollarAgentBroadcast, 1);
+        addFunction(vm, agent, "getReport", functionDollarAgentGetReport, 0);
+        addFunction(vm, agent, "leaving", functionDollarAgentLeaving, 0);
+        
+        addFunction(vm, "waitForReport", functionWaitForReport, 0);
+
+        addFunction(vm, "heapCapacity", functionHeapCapacity, 0);
+        addFunction(vm, "flashHeapAccess", functionFlashHeapAccess, 0);
+    }
+    
+    void addFunction(VM& vm, JSObject* object, const char* name, NativeFunction function, unsigned arguments)
+    {
+        Identifier identifier = Identifier::fromString(&vm, name);
+        object->putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function));
     }
 
     void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
     {
-        Identifier identifier = Identifier::fromString(&vm, name);
-        putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function));
+        addFunction(vm, this, name, function, arguments);
     }
     
     void addConstructableFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
@@ -1268,13 +1467,26 @@ protected:
         putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function, NoIntrinsic, function));
     }
 
+    static JSInternalPromise* moduleLoaderImportModule(JSGlobalObject*, ExecState*, JSModuleLoader*, JSString*, const SourceOrigin&);
     static JSInternalPromise* moduleLoaderResolve(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue);
     static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue);
 };
 
-const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, nullptr, CREATE_METHOD_TABLE(GlobalObject) };
-const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, 0, &shouldInterruptScriptBeforeTimeout, &moduleLoaderResolve, &moduleLoaderFetch, nullptr, nullptr, nullptr, nullptr };
-
+const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(GlobalObject) };
+const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = {
+    &supportsRichSourceInfo,
+    &shouldInterruptScript,
+    &javaScriptRuntimeFlags,
+    nullptr, // queueTaskToEventLoop
+    &shouldInterruptScriptBeforeTimeout,
+    &moduleLoaderImportModule,
+    &moduleLoaderResolve,
+    &moduleLoaderFetch,
+    nullptr, // moduleLoaderInstantiate
+    nullptr, // moduleLoaderEvaluate
+    nullptr, // promiseRejectionTracker
+    nullptr, // defaultLanguage
+};
 
 GlobalObject::GlobalObject(VM& vm, Structure* structure)
     : JSGlobalObject(vm, structure, &s_globalObjectMethodTable)
@@ -1315,11 +1527,12 @@ ModuleName::ModuleName(const String& moduleName)
     moduleName.split('/', true, queries);
 }
 
-static bool extractDirectoryName(const String& absolutePathToFile, DirectoryName& directoryName)
+static std::optional<DirectoryName> extractDirectoryName(const String& absolutePathToFile)
 {
     size_t firstSeparatorPosition = absolutePathToFile.find(pathSeparator());
     if (firstSeparatorPosition == notFound)
-        return false;
+        return std::nullopt;
+    DirectoryName directoryName;
     directoryName.rootName = absolutePathToFile.substring(0, firstSeparatorPosition + 1); // Include the separator.
     size_t lastSeparatorPosition = absolutePathToFile.reverseFind(pathSeparator());
     ASSERT_WITH_MESSAGE(lastSeparatorPosition != notFound, "If the separator is not found, this function already returns when performing the forward search.");
@@ -1330,10 +1543,10 @@ static bool extractDirectoryName(const String& absolutePathToFile, DirectoryName
         size_t queryLength = lastSeparatorPosition - queryStartPosition; // Not include the last separator.
         directoryName.queryName = absolutePathToFile.substring(queryStartPosition, queryLength);
     }
-    return true;
+    return directoryName;
 }
 
-static bool currentWorkingDirectory(DirectoryName& directoryName)
+static std::optional<DirectoryName> currentWorkingDirectory()
 {
 #if OS(WINDOWS)
     // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364934.aspx
@@ -1347,30 +1560,29 @@ static bool currentWorkingDirectory(DirectoryName& directoryName)
     // In the path utility functions inside the JSC shell, we does not handle the UNC and UNCW including the network host name.
     DWORD bufferLength = ::GetCurrentDirectoryW(0, nullptr);
     if (!bufferLength)
-        return false;
+        return std::nullopt;
     // In Windows, wchar_t is the UTF-16LE.
     // https://msdn.microsoft.com/en-us/library/dd374081.aspx
     // https://msdn.microsoft.com/en-us/library/windows/desktop/ff381407.aspx
     auto buffer = std::make_unique<wchar_t[]>(bufferLength);
     DWORD lengthNotIncludingNull = ::GetCurrentDirectoryW(bufferLength, buffer.get());
-    static_assert(sizeof(wchar_t) == sizeof(UChar), "In Windows, both are UTF-16LE");
-    String directoryString = String(reinterpret_cast<UChar*>(buffer.get()));
+    String directoryString = wcharToString(buffer.get(), lengthNotIncludingNull);
     // We don't support network path like \\host\share\<path name>.
     if (directoryString.startsWith("\\\\"))
-        return false;
+        return std::nullopt;
 #else
     auto buffer = std::make_unique<char[]>(PATH_MAX);
     if (!getcwd(buffer.get(), PATH_MAX))
-        return false;
+        return std::nullopt;
     String directoryString = String::fromUTF8(buffer.get());
 #endif
     if (directoryString.isEmpty())
-        return false;
+        return std::nullopt;
 
     if (directoryString[directoryString.length() - 1] == pathSeparator())
-        return extractDirectoryName(directoryString, directoryName);
+        return extractDirectoryName(directoryString);
     // Append the seperator to represents the file name. extractDirectoryName only accepts the absolute file name.
-    return extractDirectoryName(makeString(directoryString, pathSeparator()), directoryName);
+    return extractDirectoryName(makeString(directoryString, pathSeparator()));
 }
 
 static String resolvePath(const DirectoryName& directoryName, const ModuleName& moduleName)
@@ -1400,12 +1612,48 @@ static String resolvePath(const DirectoryName& directoryName, const ModuleName&
     return builder.toString();
 }
 
+static String absolutePath(const String& fileName)
+{
+    auto directoryName = currentWorkingDirectory();
+    if (!directoryName)
+        return fileName;
+    return resolvePath(directoryName.value(), ModuleName(fileName.impl()));
+}
+
+JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSString* moduleNameValue, const SourceOrigin& sourceOrigin)
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+
+    auto rejectPromise = [&] (JSValue error) {
+        return JSInternalPromiseDeferred::create(exec, globalObject)->reject(exec, error);
+    };
+
+    if (sourceOrigin.isNull())
+        return rejectPromise(createError(exec, ASCIILiteral("Could not resolve the module specifier.")));
+
+    auto referrer = sourceOrigin.string();
+    auto moduleName = moduleNameValue->value(exec);
+    if (UNLIKELY(scope.exception())) {
+        JSValue exception = scope.exception();
+        scope.clearException();
+        return rejectPromise(exception);
+    }
+
+    auto directoryName = extractDirectoryName(referrer.impl());
+    if (!directoryName)
+        return rejectPromise(createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
+
+    return JSC::importModule(exec, Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(moduleName))), jsUndefined());
+}
+
 JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue keyValue, JSValue referrerValue, JSValue)
 {
     VM& vm = globalObject->vm();
     auto scope = DECLARE_CATCH_SCOPE(vm);
 
     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
+    scope.releaseAssertNoException();
     const Identifier key = keyValue.toPropertyKey(exec);
     if (UNLIKELY(scope.exception())) {
         JSValue exception = scope.exception();
@@ -1416,28 +1664,34 @@ JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObjec
     if (key.isSymbol())
         return deferred->resolve(exec, keyValue);
 
-    DirectoryName directoryName;
     if (referrerValue.isUndefined()) {
-        if (!currentWorkingDirectory(directoryName))
+        auto directoryName = currentWorkingDirectory();
+        if (!directoryName)
             return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
-    } else {
-        const Identifier referrer = referrerValue.toPropertyKey(exec);
-        if (UNLIKELY(scope.exception())) {
-            JSValue exception = scope.exception();
-            scope.clearException();
-            return deferred->reject(exec, exception);
-        }
-        if (referrer.isSymbol()) {
-            if (!currentWorkingDirectory(directoryName))
-                return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
-        } else {
-            // If the referrer exists, we assume that the referrer is the correct absolute path.
-            if (!extractDirectoryName(referrer.impl(), directoryName))
-                return deferred->reject(exec, createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
-        }
+        return deferred->resolve(exec, jsString(exec, resolvePath(directoryName.value(), ModuleName(key.impl()))));
+    }
+
+    const Identifier referrer = referrerValue.toPropertyKey(exec);
+    if (UNLIKELY(scope.exception())) {
+        JSValue exception = scope.exception();
+        scope.clearException();
+        return deferred->reject(exec, exception);
     }
 
-    return deferred->resolve(exec, jsString(exec, resolvePath(directoryName, ModuleName(key.impl()))));
+    if (referrer.isSymbol()) {
+        auto directoryName = currentWorkingDirectory();
+        if (!directoryName)
+            return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
+        return deferred->resolve(exec, jsString(exec, resolvePath(directoryName.value(), ModuleName(key.impl()))));
+    }
+
+    // If the referrer exists, we assume that the referrer is the correct absolute path.
+    auto directoryName = extractDirectoryName(referrer.impl());
+    if (!directoryName)
+        return deferred->reject(exec, createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
+    auto result = deferred->resolve(exec, jsString(exec, resolvePath(directoryName.value(), ModuleName(key.impl()))));
+    scope.releaseAssertNoException();
+    return result;
 }
 
 static void convertShebangToJSComment(Vector<char>& buffer)
@@ -1489,9 +1743,7 @@ static bool fetchModuleFromLocalFileSystem(const String& fileName, Vector<char>&
     // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
     // Use long UNC to pass the long path name to the Windows APIs.
     String longUNCPathName = WTF::makeString("\\\\?\\", fileName);
-    static_assert(sizeof(wchar_t) == sizeof(UChar), "In Windows, both are UTF-16LE");
-    auto utf16Vector = longUNCPathName.charactersWithNullTermination();
-    FILE* f = _wfopen(reinterpret_cast<wchar_t*>(utf16Vector.data()), L"rb");
+    FILE* f = _wfopen(stringToNullTerminatedWChar(longUNCPathName).data(), L"rb");
 #else
     FILE* f = fopen(fileName.utf8().data(), "r");
 #endif
@@ -1525,17 +1777,23 @@ JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject,
     if (!fetchModuleFromLocalFileSystem(moduleKey, utf8))
         return deferred->reject(exec, createError(exec, makeString("Could not open file '", moduleKey, "'.")));
 
-    return deferred->resolve(exec, jsString(exec, stringFromUTF(utf8)));
+    auto result = deferred->resolve(exec, JSSourceCode::create(exec->vm(), makeSource(stringFromUTF(utf8), SourceOrigin { moduleKey }, moduleKey, TextPosition(), SourceProviderSourceType::Module)));
+    scope.releaseAssertNoException();
+    return result;
 }
 
 
 static EncodedJSValue printInternal(ExecState* exec, FILE* out)
 {
-    if (test262AsyncTest) {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    if (asyncTestExpectedPasses) {
         JSValue value = exec->argument(0);
-        if (value.isString() && WTF::equal(asString(value)->value(exec).impl(), "Test262:AsyncTestComplete"))
-            test262AsyncPassed = true;
-        return JSValue::encode(jsUndefined());
+        if (value.isString() && WTF::equal(asString(value)->value(exec).impl(), "Test262:AsyncTestComplete")) {
+            asyncTestPasses++;
+            return JSValue::encode(jsUndefined());
+        }
     }
 
     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
@@ -1543,7 +1801,9 @@ static EncodedJSValue printInternal(ExecState* exec, FILE* out)
             if (EOF == fputc(' ', out))
                 goto fail;
 
-        if (fprintf(out, "%s", exec->uncheckedArgument(i).toString(exec)->view(exec).get().utf8().data()) < 0)
+        auto viewWithString = exec->uncheckedArgument(i).toString(exec)->viewWithUnderlyingString(exec);
+        RETURN_IF_EXCEPTION(scope, encodedJSValue());
+        if (fprintf(out, "%s", viewWithString.view.utf8().data()) < 0)
             goto fail;
     }
 
@@ -1569,7 +1829,11 @@ EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
 {
-    fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->view(exec).get().utf8().data());
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    auto viewWithString = exec->argument(0).toString(exec)->viewWithUnderlyingString(exec);
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    fprintf(stderr, "--> %s\n", viewWithString.view.utf8().data());
     return JSValue::encode(jsUndefined());
 }
 
@@ -1584,7 +1848,8 @@ EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState* exec)
 {
     if (exec->argumentCount() < 1)
         return JSValue::encode(jsUndefined());
-    JSObject* object = jsDynamicCast<JSObject*>(exec->argument(0));
+    VM& vm = exec->vm();
+    JSObject* object = jsDynamicCast<JSObject*>(vm, exec->argument(0));
     if (!object)
         return JSValue::encode(jsNontrivialString(exec, ASCIILiteral("<not object>")));
     return JSValue::encode(jsNontrivialString(exec, toString("<Butterfly: ", RawPointer(object->butterfly()), "; public length: ", object->getArrayLength(), "; vector length: ", object->getVectorLength(), ">")));
@@ -1592,8 +1857,15 @@ EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL functionSleepSeconds(ExecState* exec)
 {
-    if (exec->argumentCount() >= 1)
-        sleep(exec->argument(0).toNumber(exec));
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    if (exec->argumentCount() >= 1) {
+        Seconds seconds = Seconds(exec->argument(0).toNumber(exec));
+        RETURN_IF_EXCEPTION(scope, encodedJSValue());
+        sleep(seconds);
+    }
+    
     return JSValue::encode(jsUndefined());
 }
 
@@ -1637,7 +1909,7 @@ EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState* exec)
     JSLockHolder lock(vm);
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    Root* root = jsDynamicCast<Root*>(exec->argument(0));
+    Root* root = jsDynamicCast<Root*>(vm, exec->argument(0));
     if (!root)
         return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Cannot create Element without a Root."))));
     return JSValue::encode(Element::create(vm, exec->lexicalGlobalObject(), root));
@@ -1646,7 +1918,8 @@ EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState* exec)
 EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState* exec)
 {
     JSLockHolder lock(exec);
-    Root* root = jsDynamicCast<Root*>(exec->argument(0));
+    VM& vm = exec->vm();
+    Root* root = jsDynamicCast<Root*>(vm, exec->argument(0));
     if (!root)
         return JSValue::encode(jsUndefined());
     Element* result = root->element();
@@ -1656,8 +1929,9 @@ EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState* exec)
 EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState* exec)
 {
     JSLockHolder lock(exec);
-    Element* element = jsDynamicCast<Element*>(exec->argument(0));
-    Root* root = jsDynamicCast<Root*>(exec->argument(1));
+    VM& vm = exec->vm();
+    Element* element = jsDynamicCast<Element*>(vm, exec->argument(0));
+    Root* root = jsDynamicCast<Root*>(vm, exec->argument(1));
     if (element && root)
         element->setRoot(exec->vm(), root);
     return JSValue::encode(jsUndefined());
@@ -1671,15 +1945,29 @@ EncodedJSValue JSC_HOST_CALL functionCreateSimpleObject(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL functionGetHiddenValue(ExecState* exec)
 {
-    JSLockHolder lock(exec);
-    SimpleObject* simpleObject = jsCast<SimpleObject*>(exec->argument(0).asCell());
+    VM& vm = exec->vm();
+    JSLockHolder lock(vm);
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    SimpleObject* simpleObject = jsDynamicCast<SimpleObject*>(vm, exec->argument(0));
+    if (UNLIKELY(!simpleObject)) {
+        throwTypeError(exec, scope, ASCIILiteral("Invalid use of getHiddenValue test function"));
+        return encodedJSValue();
+    }
     return JSValue::encode(simpleObject->hiddenValue());
 }
 
 EncodedJSValue JSC_HOST_CALL functionSetHiddenValue(ExecState* exec)
 {
-    JSLockHolder lock(exec);
-    SimpleObject* simpleObject = jsCast<SimpleObject*>(exec->argument(0).asCell());
+    VM& vm = exec->vm();
+    JSLockHolder lock(vm);
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    SimpleObject* simpleObject = jsDynamicCast<SimpleObject*>(vm, exec->argument(0));
+    if (UNLIKELY(!simpleObject)) {
+        throwTypeError(exec, scope, ASCIILiteral("Invalid use of setHiddenValue test function"));
+        return encodedJSValue();
+    }
     JSValue value = exec->argument(1);
     simpleObject->setHiddenValue(exec->vm(), value);
     return JSValue::encode(jsUndefined());
@@ -1756,6 +2044,14 @@ EncodedJSValue JSC_HOST_CALL functionCreateDOMJITFunctionObject(ExecState* exec)
     return JSValue::encode(result);
 }
 
+EncodedJSValue JSC_HOST_CALL functionCreateDOMJITCheckSubClassObject(ExecState* exec)
+{
+    JSLockHolder lock(exec);
+    Structure* structure = DOMJITCheckSubClassObject::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull());
+    DOMJITCheckSubClassObject* result = DOMJITCheckSubClassObject::create(exec->vm(), exec->lexicalGlobalObject(), structure);
+    return JSValue::encode(result);
+}
+
 EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec)
 {
     VM& vm = exec->vm();
@@ -1768,7 +2064,7 @@ EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec)
     JSValue delegate = exec->argument(1);
     if (!delegate.isObject())
         return JSValue::encode(jsUndefined());
-    ImpureGetter* impureGetter = jsDynamicCast<ImpureGetter*>(asObject(base.asCell()));
+    ImpureGetter* impureGetter = jsDynamicCast<ImpureGetter*>(vm, asObject(base.asCell()));
     if (UNLIKELY(!impureGetter)) {
         throwTypeError(exec, scope, ASCIILiteral("argument is not an ImpureGetter"));
         return encodedJSValue();
@@ -1780,7 +2076,7 @@ EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec)
 EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState* exec)
 {
     JSLockHolder lock(exec);
-    exec->heap()->collectAllGarbage();
+    exec->heap()->collectNow(Sync, CollectionScope::Full);
     return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastFullCollection()));
 }
 
@@ -1836,10 +2132,8 @@ static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState* exec)
     if (!property.isString())
         return JSValue::encode(jsUndefined());
 
-    Identifier ident = Identifier::fromString(&exec->vm(), property.toWTFString(exec));
-
     PropertySlot slot(value, PropertySlot::InternalMethodType::VMInquiry);
-    value.getPropertySlot(exec, ident, slot);
+    value.getPropertySlot(exec, asString(property)->toIdentifier(exec), slot);
 
     JSValue result;
     if (slot.isCacheableGetter())
@@ -1871,15 +2165,18 @@ EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
     GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
 
     JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
-    for (unsigned i = 1; i < exec->argumentCount(); ++i)
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    for (unsigned i = 1; i < exec->argumentCount(); ++i) {
         array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
+        RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    }
     globalObject->putDirect(
         vm, Identifier::fromString(globalObject->globalExec(), "arguments"), array);
 
     NakedPtr<Exception> exception;
     StopWatch stopWatch;
     stopWatch.start();
-    evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), exception);
+    evaluate(globalObject->globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), exception);
     stopWatch.stop();
 
     if (exception) {
@@ -1901,13 +2198,16 @@ EncodedJSValue JSC_HOST_CALL functionRunString(ExecState* exec)
     GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
 
     JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
-    for (unsigned i = 1; i < exec->argumentCount(); ++i)
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    for (unsigned i = 1; i < exec->argumentCount(); ++i) {
         array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
+        RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    }
     globalObject->putDirect(
         vm, Identifier::fromString(globalObject->globalExec(), "arguments"), array);
 
     NakedPtr<Exception> exception;
-    evaluate(globalObject->globalExec(), makeSource(source), JSValue(), exception);
+    evaluate(globalObject->globalExec(), makeSource(source, exec->callerSourceOrigin()), JSValue(), exception);
 
     if (exception) {
         scope.throwException(globalObject->globalExec(), exception);
@@ -1931,7 +2231,7 @@ EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     
     NakedPtr<Exception> evaluationException;
-    JSValue result = evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), evaluationException);
+    JSValue result = evaluate(globalObject->globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), evaluationException);
     if (evaluationException)
         throwException(exec, scope, evaluationException);
     return JSValue::encode(result);
@@ -1947,7 +2247,7 @@ EncodedJSValue JSC_HOST_CALL functionLoadString(ExecState* exec)
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
 
     NakedPtr<Exception> evaluationException;
-    JSValue result = evaluate(globalObject->globalExec(), makeSource(sourceCode), JSValue(), evaluationException);
+    JSValue result = evaluate(globalObject->globalExec(), makeSource(sourceCode, exec->callerSourceOrigin()), JSValue(), evaluationException);
     if (evaluationException)
         throwException(exec, scope, evaluationException);
     return JSValue::encode(result);
@@ -2002,7 +2302,7 @@ EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
     stopWatch.start();
 
     JSValue syntaxException;
-    bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script, fileName), &syntaxException);
+    bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), &syntaxException);
     stopWatch.stop();
 
     if (!validSyntax)
@@ -2064,10 +2364,27 @@ EncodedJSValue JSC_HOST_CALL functionIsRope(ExecState* exec)
     JSValue argument = exec->argument(0);
     if (!argument.isString())
         return JSValue::encode(jsBoolean(false));
-    const StringImpl* impl = jsCast<JSString*>(argument)->tryGetValueImpl();
+    const StringImpl* impl = asString(argument)->tryGetValueImpl();
     return JSValue::encode(jsBoolean(!impl));
 }
 
+EncodedJSValue JSC_HOST_CALL functionCallerSourceOrigin(ExecState* state)
+{
+    SourceOrigin sourceOrigin = state->callerSourceOrigin();
+    if (sourceOrigin.isNull())
+        return JSValue::encode(jsNull());
+    return JSValue::encode(jsString(state, sourceOrigin.string()));
+}
+
+EncodedJSValue JSC_HOST_CALL functionGlobalObjectForObject(ExecState* exec)
+{
+    JSValue value = exec->argument(0);
+    RELEASE_ASSERT(value.isObject());
+    JSGlobalObject* globalObject = jsCast<JSObject*>(value)->globalObject();
+    RELEASE_ASSERT(globalObject);
+    return JSValue::encode(globalObject);
+}
+
 EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
 {
     Vector<char, 256> line;
@@ -2099,7 +2416,8 @@ EncodedJSValue JSC_HOST_CALL functionNoDFG(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL functionNoFTL(ExecState* exec)
 {
-    if (JSFunction* function = jsDynamicCast<JSFunction*>(exec->argument(0))) {
+    VM& vm = exec->vm();
+    if (JSFunction* function = jsDynamicCast<JSFunction*>(vm, exec->argument(0))) {
         FunctionExecutable* executable = function->jsExecutable();
         executable->setNeverFTLOptimize(true);
     }
@@ -2122,6 +2440,329 @@ EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState* exec)
     return JSValue::encode(numberOfDFGCompiles(exec));
 }
 
+Message::Message(ArrayBufferContents&& contents, int32_t index)
+    : m_contents(WTFMove(contents))
+    , m_index(index)
+{
+}
+
+Message::~Message()
+{
+}
+
+Worker::Worker(Workers& workers)
+    : m_workers(workers)
+{
+    auto locker = holdLock(m_workers.m_lock);
+    m_workers.m_workers.append(this);
+    
+    *currentWorker() = this;
+}
+
+Worker::~Worker()
+{
+    auto locker = holdLock(m_workers.m_lock);
+    RELEASE_ASSERT(isOnList());
+    remove();
+}
+
+void Worker::enqueue(const AbstractLocker&, RefPtr<Message> message)
+{
+    m_messages.append(message);
+}
+
+RefPtr<Message> Worker::dequeue()
+{
+    auto locker = holdLock(m_workers.m_lock);
+    while (m_messages.isEmpty())
+        m_workers.m_condition.wait(m_workers.m_lock);
+    return m_messages.takeFirst();
+}
+
+Worker& Worker::current()
+{
+    return **currentWorker();
+}
+
+ThreadSpecific<Worker*>& Worker::currentWorker()
+{
+    static ThreadSpecific<Worker*>* result;
+    static std::once_flag flag;
+    std::call_once(
+        flag,
+        [] () {
+            result = new ThreadSpecific<Worker*>();
+        });
+    return *result;
+}
+
+Workers::Workers()
+{
+}
+
+Workers::~Workers()
+{
+    UNREACHABLE_FOR_PLATFORM();
+}
+
+template<typename Func>
+void Workers::broadcast(const Func& func)
+{
+    auto locker = holdLock(m_lock);
+    for (Worker* worker = m_workers.begin(); worker != m_workers.end(); worker = worker->next()) {
+        if (worker != &Worker::current())
+            func(locker, *worker);
+    }
+    m_condition.notifyAll();
+}
+
+void Workers::report(String string)
+{
+    auto locker = holdLock(m_lock);
+    m_reports.append(string.isolatedCopy());
+    m_condition.notifyAll();
+}
+
+String Workers::tryGetReport()
+{
+    auto locker = holdLock(m_lock);
+    if (m_reports.isEmpty())
+        return String();
+    return m_reports.takeFirst();
+}
+
+String Workers::getReport()
+{
+    auto locker = holdLock(m_lock);
+    while (m_reports.isEmpty())
+        m_condition.wait(m_lock);
+    return m_reports.takeFirst();
+}
+
+Workers& Workers::singleton()
+{
+    static Workers* result;
+    static std::once_flag flag;
+    std::call_once(
+        flag,
+        [] {
+            result = new Workers();
+        });
+    return *result;
+}
+
+EncodedJSValue JSC_HOST_CALL functionDollarCreateRealm(ExecState* exec)
+{
+    VM& vm = exec->vm();
+    GlobalObject* result = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
+    return JSValue::encode(result->getDirect(vm, Identifier::fromString(exec, "$")));
+}
+
+EncodedJSValue JSC_HOST_CALL functionDollarDetachArrayBuffer(ExecState* exec)
+{
+    return functionTransferArrayBuffer(exec);
+}
+
+EncodedJSValue JSC_HOST_CALL functionDollarEvalScript(ExecState* exec)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    String sourceCode = exec->argument(0).toWTFString(exec);
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    
+    GlobalObject* globalObject = jsDynamicCast<GlobalObject*>(vm,
+        exec->thisValue().get(exec, Identifier::fromString(exec, "global")));
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    if (!globalObject)
+        return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Expected global to point to a global object"))));
+    
+    NakedPtr<Exception> evaluationException;
+    JSValue result = evaluate(globalObject->globalExec(), makeSource(sourceCode, exec->callerSourceOrigin()), JSValue(), evaluationException);
+    if (evaluationException)
+        throwException(exec, scope, evaluationException);
+    return JSValue::encode(result);
+}
+
+EncodedJSValue JSC_HOST_CALL functionDollarAgentStart(ExecState* exec)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    String sourceCode = exec->argument(0).toWTFString(exec).isolatedCopy();
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    
+    Lock didStartLock;
+    Condition didStartCondition;
+    bool didStart = false;
+    
+    RefPtr<Thread> thread = Thread::create(
+        "JSC Agent",
+        [sourceCode, &didStartLock, &didStartCondition, &didStart] () {
+            CommandLine commandLine(0, nullptr);
+            commandLine.m_interactive = false;
+            runJSC(
+                commandLine, true,
+                [&] (VM&, GlobalObject* globalObject) {
+                    // Notify the thread that started us that we have registered a worker.
+                    {
+                        auto locker = holdLock(didStartLock);
+                        didStart = true;
+                        didStartCondition.notifyOne();
+                    }
+                    
+                    NakedPtr<Exception> evaluationException;
+                    bool success = true;
+                    JSValue result;
+                    result = evaluate(globalObject->globalExec(), makeSource(sourceCode, SourceOrigin(ASCIILiteral("worker"))), JSValue(), evaluationException);
+                    if (evaluationException)
+                        result = evaluationException->value();
+                    checkException(globalObject, true, evaluationException, result, String(), false, false, success);
+                    if (!success)
+                        exit(1);
+                    return success;
+                });
+        });
+    thread->detach();
+    
+    {
+        auto locker = holdLock(didStartLock);
+        while (!didStart)
+            didStartCondition.wait(didStartLock);
+    }
+    
+    return JSValue::encode(jsUndefined());
+}
+
+EncodedJSValue JSC_HOST_CALL functionDollarAgentReceiveBroadcast(ExecState* exec)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSValue callback = exec->argument(0);
+    CallData callData;
+    CallType callType = getCallData(callback, callData);
+    if (callType == CallType::None)
+        return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Expected callback"))));
+    
+    RefPtr<Message> message;
+    {
+        ReleaseHeapAccessScope releaseAccess(vm.heap);
+        message = Worker::current().dequeue();
+    }
+    
+    RefPtr<ArrayBuffer> nativeBuffer = ArrayBuffer::create(message->releaseContents());
+    ArrayBufferSharingMode sharingMode = nativeBuffer->sharingMode();
+    JSArrayBuffer* jsBuffer = JSArrayBuffer::create(vm, exec->lexicalGlobalObject()->arrayBufferStructure(sharingMode), WTFMove(nativeBuffer));
+    
+    MarkedArgumentBuffer args;
+    args.append(jsBuffer);
+    args.append(jsNumber(message->index()));
+    return JSValue::encode(call(exec, callback, callType, callData, jsNull(), args));
+}
+
+EncodedJSValue JSC_HOST_CALL functionDollarAgentReport(ExecState* exec)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    String report = exec->argument(0).toWTFString(exec);
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    
+    Workers::singleton().report(report);
+    
+    return JSValue::encode(jsUndefined());
+}
+
+EncodedJSValue JSC_HOST_CALL functionDollarAgentSleep(ExecState* exec)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    if (exec->argumentCount() >= 1) {
+        Seconds seconds = Seconds::fromMilliseconds(exec->argument(0).toNumber(exec));
+        RETURN_IF_EXCEPTION(scope, encodedJSValue());
+        sleep(seconds);
+    }
+    return JSValue::encode(jsUndefined());
+}
+
+EncodedJSValue JSC_HOST_CALL functionDollarAgentBroadcast(ExecState* exec)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSArrayBuffer* jsBuffer = jsDynamicCast<JSArrayBuffer*>(vm, exec->argument(0));
+    if (!jsBuffer || !jsBuffer->isShared())
+        return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Expected SharedArrayBuffer"))));
+    
+    int32_t index = exec->argument(1).toInt32(exec);
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    
+    Workers::singleton().broadcast(
+        [&] (const AbstractLocker& locker, Worker& worker) {
+            ArrayBuffer* nativeBuffer = jsBuffer->impl();
+            ArrayBufferContents contents;
+            nativeBuffer->transferTo(vm, contents); // "transferTo" means "share" if the buffer is shared.
+            RefPtr<Message> message = adoptRef(new Message(WTFMove(contents), index));
+            worker.enqueue(locker, message);
+        });
+    
+    return JSValue::encode(jsUndefined());
+}
+
+EncodedJSValue JSC_HOST_CALL functionDollarAgentGetReport(ExecState* exec)
+{
+    VM& vm = exec->vm();
+
+    String string = Workers::singleton().tryGetReport();
+    if (!string)
+        return JSValue::encode(jsNull());
+    
+    return JSValue::encode(jsString(&vm, string));
+}
+
+EncodedJSValue JSC_HOST_CALL functionDollarAgentLeaving(ExecState*)
+{
+    return JSValue::encode(jsUndefined());
+}
+
+EncodedJSValue JSC_HOST_CALL functionWaitForReport(ExecState* exec)
+{
+    VM& vm = exec->vm();
+
+    String string;
+    {
+        ReleaseHeapAccessScope releaseAccess(vm.heap);
+        string = Workers::singleton().getReport();
+    }
+    if (!string)
+        return JSValue::encode(jsNull());
+    
+    return JSValue::encode(jsString(&vm, string));
+}
+
+EncodedJSValue JSC_HOST_CALL functionHeapCapacity(ExecState* exec)
+{
+    VM& vm = exec->vm();
+    return JSValue::encode(jsNumber(vm.heap.capacity()));
+}
+
+EncodedJSValue JSC_HOST_CALL functionFlashHeapAccess(ExecState* exec)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    
+    vm.heap.releaseAccess();
+    if (exec->argumentCount() >= 1) {
+        double ms = exec->argument(0).toNumber(exec);
+        RETURN_IF_EXCEPTION(scope, encodedJSValue());
+        sleep(Seconds::fromMilliseconds(ms));
+    }
+    vm.heap.acquireAccess();
+    return JSValue::encode(jsUndefined());
+}
+
 template<typename ValueType>
 typename std::enable_if<!std::is_fundamental<ValueType>::value>::type addOption(VM&, JSObject*, Identifier, ValueType) { }
 
@@ -2161,12 +2802,12 @@ EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState* exec)
     if (exec->argumentCount() < 1)
         return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Not enough arguments"))));
     
-    JSArrayBuffer* buffer = jsDynamicCast<JSArrayBuffer*>(exec->argument(0));
+    JSArrayBuffer* buffer = jsDynamicCast<JSArrayBuffer*>(vm, exec->argument(0));
     if (!buffer)
         return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Expected an array buffer"))));
     
     ArrayBufferContents dummyContents;
-    buffer->impl()->transferTo(dummyContents);
+    buffer->impl()->transferTo(vm, dummyContents);
     
     return JSValue::encode(jsUndefined());
 }
@@ -2234,15 +2875,16 @@ EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState* exec)
 {
+    VM& vm = exec->vm();
     RELEASE_ASSERT(exec->vm().typeProfiler());
-    exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionFindTypeForExpression"));
+    vm.typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionFindTypeForExpression"));
 
     JSValue functionValue = exec->argument(0);
     RELEASE_ASSERT(functionValue.isFunction());
-    FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
+    FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
 
     RELEASE_ASSERT(exec->argument(1).isString());
-    String substring = exec->argument(1).getString(exec);
+    String substring = asString(exec->argument(1))->value(exec);
     String sourceCodeText = executable->source().view().toString();
     unsigned offset = static_cast<unsigned>(sourceCodeText.find(substring) + executable->source().startOffset());
     
@@ -2252,12 +2894,13 @@ EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState* exec)
 {
+    VM& vm = exec->vm();
     RELEASE_ASSERT(exec->vm().typeProfiler());
-    exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionReturnTypeFor"));
+    vm.typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionReturnTypeFor"));
 
     JSValue functionValue = exec->argument(0);
     RELEASE_ASSERT(functionValue.isFunction());
-    FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
+    FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
 
     unsigned offset = executable->typeProfilingStartOffset();
     String jsonString = exec->vm().typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorFunctionReturn, offset, executable->sourceID(), exec->vm());
@@ -2273,37 +2916,39 @@ EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState* ex
 
 EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState* exec)
 {
-    RELEASE_ASSERT(exec->vm().controlFlowProfiler());
+    VM& vm = exec->vm();
+    RELEASE_ASSERT(vm.controlFlowProfiler());
 
     JSValue functionValue = exec->argument(0);
     RELEASE_ASSERT(functionValue.isFunction());
-    FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
+    FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
 
     RELEASE_ASSERT(exec->argument(1).isString());
-    String substring = exec->argument(1).getString(exec);
+    String substring = asString(exec->argument(1))->value(exec);
     String sourceCodeText = executable->source().view().toString();
     RELEASE_ASSERT(sourceCodeText.contains(substring));
     int offset = sourceCodeText.find(substring) + executable->source().startOffset();
     
-    bool hasExecuted = exec->vm().controlFlowProfiler()->hasBasicBlockAtTextOffsetBeenExecuted(offset, executable->sourceID(), exec->vm());
+    bool hasExecuted = vm.controlFlowProfiler()->hasBasicBlockAtTextOffsetBeenExecuted(offset, executable->sourceID(), vm);
     return JSValue::encode(jsBoolean(hasExecuted));
 }
 
 EncodedJSValue JSC_HOST_CALL functionBasicBlockExecutionCount(ExecState* exec)
 {
-    RELEASE_ASSERT(exec->vm().controlFlowProfiler());
+    VM& vm = exec->vm();
+    RELEASE_ASSERT(vm.controlFlowProfiler());
 
     JSValue functionValue = exec->argument(0);
     RELEASE_ASSERT(functionValue.isFunction());
-    FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
+    FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
 
     RELEASE_ASSERT(exec->argument(1).isString());
-    String substring = exec->argument(1).getString(exec);
+    String substring = asString(exec->argument(1))->value(exec);
     String sourceCodeText = executable->source().view().toString();
     RELEASE_ASSERT(sourceCodeText.contains(substring));
     int offset = sourceCodeText.find(substring) + executable->source().startOffset();
     
-    size_t executionCount = exec->vm().controlFlowProfiler()->basicBlockExecutionCountAtTextOffset(offset, executable->sourceID(), exec->vm());
+    size_t executionCount = vm.controlFlowProfiler()->basicBlockExecutionCountAtTextOffset(offset, executable->sourceID(), exec->vm());
     return JSValue::encode(JSValue(executionCount));
 }
 
@@ -2349,6 +2994,7 @@ EncodedJSValue JSC_HOST_CALL functionLoadModule(ExecState* exec)
     });
 
     promise->then(exec, nullptr, errorHandler);
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     vm.drainMicrotasks();
     if (error)
         return JSValue::encode(throwException(exec, scope, error));
@@ -2363,10 +3009,10 @@ EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState* exec)
     if (exec->argumentCount() < 1 || !exec->argument(0).isString())
         return JSValue::encode(jsUndefined());
 
-    String functionText = exec->argument(0).toWTFString(exec);
+    String functionText = asString(exec->argument(0))->value(exec);
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
-    const SourceCode& source = makeSource(functionText);
+    const SourceCode& source = makeSource(functionText, { });
     JSFunction* func = JSFunction::createBuiltinFunction(vm, createBuiltinExecutable(vm, source, Identifier::fromString(&vm, "foo"), ConstructorKind::None, ConstructAbility::CannotConstruct)->link(vm, source), exec->lexicalGlobalObject());
 
     return JSValue::encode(func);
@@ -2390,7 +3036,8 @@ EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState* exec)
     stopWatch.start();
 
     ParserError error;
-    bool validSyntax = checkModuleSyntax(exec, makeSource(source, String(), TextPosition::minimumPosition(), SourceProviderSourceType::Module), error);
+    bool validSyntax = checkModuleSyntax(exec, makeSource(source, { }, String(), TextPosition(), SourceProviderSourceType::Module), error);
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     stopWatch.stop();
 
     if (!validSyntax)
@@ -2418,7 +3065,7 @@ EncodedJSValue JSC_HOST_CALL functionGenerateHeapSnapshot(ExecState* exec)
 
     String jsonString = snapshotBuilder.json();
     EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
-    RELEASE_ASSERT(!scope.exception());
+    scope.releaseAssertNoException();
     return result;
 }
 
@@ -2430,8 +3077,9 @@ EncodedJSValue JSC_HOST_CALL functionResetSuperSamplerState(ExecState*)
 
 EncodedJSValue JSC_HOST_CALL functionEnsureArrayStorage(ExecState* exec)
 {
+    VM& vm = exec->vm();
     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
-        if (JSObject* object = jsDynamicCast<JSObject*>(exec->argument(0)))
+        if (JSObject* object = jsDynamicCast<JSObject*>(vm, exec->argument(0)))
             object->ensureArrayStorage(exec->vm());
     }
     return JSValue::encode(jsUndefined());
@@ -2456,105 +3104,53 @@ EncodedJSValue JSC_HOST_CALL functionSamplingProfilerStackTraces(ExecState* exec
 
     String jsonString = vm.samplingProfiler()->stackTracesAsJSON();
     EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
-    RELEASE_ASSERT(!scope.exception());
+    scope.releaseAssertNoException();
     return result;
 }
 #endif // ENABLE(SAMPLING_PROFILER)
 
-#if ENABLE(WEBASSEMBLY)
-
-static JSValue box(ExecState* exec, VM& vm, JSValue wasmValue)
+EncodedJSValue JSC_HOST_CALL functionMaxArguments(ExecState*)
 {
-    JSString* type = jsCast<JSString*>(wasmValue.get(exec, makeIdentifier(vm, "type")));
-    JSValue value = wasmValue.get(exec, makeIdentifier(vm, "value"));
-
-    const String& typeString = type->value(exec);
-    if (typeString == "i64") {
-        RELEASE_ASSERT(value.isString());
-        int64_t result;
-        RELEASE_ASSERT(sscanf(bitwise_cast<const char*>(jsCast<JSString*>(value)->value(exec).characters8()), "%lld", &result) != EOF);
-        return JSValue::decode(result);
-    }
-    RELEASE_ASSERT(value.isNumber());
+    return JSValue::encode(jsNumber(JSC::maxArguments));
+}
 
-    if (typeString == "i32") {
-        RELEASE_ASSERT(value.isInt32());
-        return JSValue::decode(static_cast<uint32_t>(value.asInt32()));
-    }
+EncodedJSValue JSC_HOST_CALL functionAsyncTestStart(ExecState* exec)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
 
-    if (typeString == "f32")
-        return JSValue::decode(bitwise_cast<uint32_t>(value.toFloat(exec)));
+    JSValue numberOfAsyncPasses = exec->argument(0);
+    if (!numberOfAsyncPasses.isUInt32())
+        return throwVMError(exec, scope, ASCIILiteral("Expected first argument to a uint32"));
 
-    RELEASE_ASSERT(typeString == "f64");
-    return value;
+    asyncTestExpectedPasses += numberOfAsyncPasses.asUInt32();
+    return encodedJSUndefined();
 }
 
-static JSValue callWasmFunction(VM* vm, const B3::Compilation& code, Vector<JSValue>& boxedArgs)
+EncodedJSValue JSC_HOST_CALL functionAsyncTestPassed(ExecState*)
 {
-    JSValue firstArgument;
-    int argCount = 1;
-    JSValue* remainingArgs = nullptr;
-    if (boxedArgs.size()) {
-        remainingArgs = boxedArgs.data();
-        firstArgument = *remainingArgs;
-        remainingArgs++;
-        argCount = boxedArgs.size();
-    }
-
-    ProtoCallFrame protoCallFrame;
-    protoCallFrame.init(nullptr, nullptr, firstArgument, argCount, remainingArgs);
-
-    return JSValue::decode(vmEntryToWasm(code.code().executableAddress(), vm, &protoCallFrame));
+    asyncTestPasses++;
+    return encodedJSUndefined();
 }
 
-// testWasmModule(JSArrayBufferView source, number functionCount, ...[[WasmValue, [WasmValue]]]) where the ith copy of [[result, [args]]] is a list
-// of arguments to be passed to the ith wasm function as well as the expected result. WasmValue is an object with "type" and "value" properties.
-static EncodedJSValue JSC_HOST_CALL functionTestWasmModuleFunctions(ExecState* exec)
+#if ENABLE(WEBASSEMBLY)
+
+static EncodedJSValue JSC_HOST_CALL functionWebAssemblyMemoryMode(ExecState* exec)
 {
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
-
+    
     if (!Options::useWebAssembly())
-        return throwVMTypeError(exec, scope, ASCIILiteral("testWasmModule should only be called if the useWebAssembly option is set"));
+        return throwVMTypeError(exec, scope, ASCIILiteral("WebAssemblyMemoryMode should only be called if the useWebAssembly option is set"));
 
-    JSArrayBufferView* source = jsCast<JSArrayBufferView*>(exec->argument(0));
-    uint32_t functionCount = exec->argument(1).toUInt32(exec);
-
-    if (exec->argumentCount() != functionCount + 2)
-        CRASH();
-
-    Wasm::Plan plan(&vm, static_cast<uint8_t*>(source->vector()), source->length());
-    plan.run();
-    if (plan.failed())
-        CRASH();
-
-    if (plan.compiledFunctionCount() != functionCount)
-        CRASH();
-
-    for (uint32_t i = 0; i < functionCount; ++i) {
-        if (!plan.compiledFunction(i))
-            dataLogLn("failed to compile function at index", i);
-
-        JSArray* testCases = jsCast<JSArray*>(exec->argument(i + 2));
-        for (unsigned testIndex = 0; testIndex < testCases->length(); ++testIndex) {
-            JSArray* test = jsCast<JSArray*>(testCases->getIndexQuickly(testIndex));
-            JSObject* result = jsCast<JSObject*>(test->getIndexQuickly(0));
-            JSArray* arguments = jsCast<JSArray*>(test->getIndexQuickly(1));
-
-            Vector<JSValue> boxedArgs;
-            for (unsigned argIndex = 0; argIndex < arguments->length(); ++argIndex)
-                boxedArgs.append(box(exec, vm, arguments->getIndexQuickly(argIndex)));
-
-            JSValue callResult = callWasmFunction(&vm, *plan.compiledFunction(i)->jsEntryPoint, boxedArgs);
-            JSValue expected = box(exec, vm, result);
-            if (callResult != expected) {
-                WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, toCString(" (callResult == ", RawPointer(bitwise_cast<void*>(callResult)), ", expected == ", RawPointer(bitwise_cast<void*>(expected)), ")").data());
-                CRASH();
-            }
-        }
+    if (JSObject* object = exec->argument(0).getObject()) {
+        if (auto* memory = jsDynamicCast<JSWebAssemblyMemory*>(vm, object))
+            return JSValue::encode(jsString(&vm, makeString(memory->memory().mode())));
+        if (auto* instance = jsDynamicCast<JSWebAssemblyInstance*>(vm, object))
+            return JSValue::encode(jsString(&vm, makeString(instance->memoryMode())));
     }
 
-    return encodedJSUndefined();
+    return throwVMTypeError(exec, scope, ASCIILiteral("WebAssemblyMemoryMode expects either a WebAssembly.Memory or WebAssembly.Instance"));
 }
 
 #endif // ENABLE(WEBASSEBLY)
@@ -2575,16 +3171,27 @@ static EncodedJSValue JSC_HOST_CALL functionTestWasmModuleFunctions(ExecState* e
 int jscmain(int argc, char** argv);
 
 static double s_desiredTimeout;
+static double s_timeoutMultiplier = 1.0;
 
 static NO_RETURN_DUE_TO_CRASH void timeoutThreadMain(void*)
 {
-    auto timeout = std::chrono::microseconds(static_cast<std::chrono::microseconds::rep>(s_desiredTimeout * 1000000));
-    std::this_thread::sleep_for(timeout);
-    
-    dataLog("Timed out after ", s_desiredTimeout, " seconds!\n");
+    Seconds timeoutDuration(s_desiredTimeout * s_timeoutMultiplier);
+    sleep(timeoutDuration);
+    dataLog("Timed out after ", timeoutDuration, " seconds!\n");
     CRASH();
 }
 
+static void startTimeoutThreadIfNeeded()
+{
+    if (char* timeoutString = getenv("JSCTEST_timeout")) {
+        if (sscanf(timeoutString, "%lf", &s_desiredTimeout) != 1) {
+            dataLog("WARNING: timeout string is malformed, got ", timeoutString,
+                " but expected a number. Not using a timeout.\n");
+        } else
+            Thread::create(timeoutThreadMain, 0, "jsc Timeout Thread");
+    }
+}
+
 int main(int argc, char** argv)
 {
 #if PLATFORM(IOS) && CPU(ARM_THUMB2)
@@ -2613,10 +3220,6 @@ int main(int argc, char** argv)
     timeBeginPeriod(1);
 #endif
 
-#if PLATFORM(EFL)
-    ecore_init();
-#endif
-
 #if PLATFORM(GTK)
     if (!setlocale(LC_ALL, ""))
         WTFLogAlways("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
@@ -2627,15 +3230,6 @@ int main(int argc, char** argv)
     // have a chance to parse options.
     WTF::initializeThreading();
 
-    if (char* timeoutString = getenv("JSCTEST_timeout")) {
-        if (sscanf(timeoutString, "%lf", &s_desiredTimeout) != 1) {
-            dataLog(
-                "WARNING: timeout string is malformed, got ", timeoutString,
-                " but expected a number. Not using a timeout.\n");
-        } else
-            createThread(timeoutThreadMain, 0, "jsc Timeout Thread");
-    }
-
 #if PLATFORM(IOS)
     Options::crashIfCantAllocateJITMemory() = true;
 #endif
@@ -2648,10 +3242,6 @@ int main(int argc, char** argv)
     EXCEPT(res = 3)
     finalizeStatsAtEndOfTesting();
 
-#if PLATFORM(EFL)
-    ecore_shutdown();
-#endif
-
     jscExit(res);
 }
 
@@ -2670,10 +3260,14 @@ static void dumpException(GlobalObject* globalObject, JSValue exception)
     printf("Exception: %s\n", exception.toWTFString(globalObject->globalExec()).utf8().data());
 
     Identifier nameID = Identifier::fromString(globalObject->globalExec(), "name");
+    CHECK_EXCEPTION();
     Identifier fileNameID = Identifier::fromString(globalObject->globalExec(), "sourceURL");
+    CHECK_EXCEPTION();
     Identifier lineNumberID = Identifier::fromString(globalObject->globalExec(), "line");
+    CHECK_EXCEPTION();
     Identifier stackID = Identifier::fromString(globalObject->globalExec(), "stack");
-    
+    CHECK_EXCEPTION();
+
     JSValue nameValue = exception.get(globalObject->globalExec(), nameID);
     CHECK_EXCEPTION();
     JSValue fileNameValue = exception.get(globalObject->globalExec(), fileNameID);
@@ -2691,8 +3285,11 @@ static void dumpException(GlobalObject* globalObject, JSValue exception)
             lineNumberValue.toWTFString(globalObject->globalExec()).utf8().data());
     }
     
-    if (!stackValue.isUndefinedOrNull())
-        printf("%s\n", stackValue.toWTFString(globalObject->globalExec()).utf8().data());
+    if (!stackValue.isUndefinedOrNull()) {
+        auto stackString = stackValue.toWTFString(globalObject->globalExec());
+        if (stackString.length())
+            printf("%s\n", stackString.utf8().data());
+    }
 
 #undef CHECK_EXCEPTION
 }
@@ -2729,6 +3326,19 @@ static bool checkUncaughtException(VM& vm, GlobalObject* globalObject, JSValue e
     return false;
 }
 
+static void checkException(GlobalObject* globalObject, bool isLastFile, bool hasException, JSValue value, const String& uncaughtExceptionName, bool alwaysDumpUncaughtException, bool dump, bool& success)
+{
+    VM& vm = globalObject->vm();
+    if (!uncaughtExceptionName || !isLastFile) {
+        success = success && !hasException;
+        if (dump && !hasException)
+            printf("End: %s\n", value.toWTFString(globalObject->globalExec()).utf8().data());
+        if (hasException)
+            dumpException(globalObject, value);
+    } else
+        success = success && checkUncaughtException(vm, globalObject, (hasException) ? value : JSValue(), uncaughtExceptionName, alwaysDumpUncaughtException);
+}
+
 static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, const String& uncaughtExceptionName, bool alwaysDumpUncaughtException, bool dump, bool module)
 {
     String fileName;
@@ -2741,17 +3351,6 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
     auto scope = DECLARE_CATCH_SCOPE(vm);
     bool success = true;
 
-    auto checkException = [&] (bool isLastFile, bool hasException, JSValue value) {
-        if (!uncaughtExceptionName || !isLastFile) {
-            success = success && !hasException;
-            if (dump && !hasException)
-                printf("End: %s\n", value.toWTFString(globalObject->globalExec()).utf8().data());
-            if (hasException)
-                dumpException(globalObject, value);
-        } else
-            success = success && checkUncaughtException(vm, globalObject, (hasException) ? value : JSValue(), uncaughtExceptionName, alwaysDumpUncaughtException);
-    };
-
 #if ENABLE(SAMPLING_FLAGS)
     SamplingFlags::start();
 #endif
@@ -2764,9 +3363,10 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
             if (scripts[i].strictMode == Script::StrictMode::Strict)
                 scriptBuffer.append("\"use strict\";\n", strlen("\"use strict\";\n"));
 
-            if (isModule)
+            if (isModule) {
                 promise = loadAndEvaluateModule(globalObject->globalExec(), fileName);
-            else {
+                scope.releaseAssertNoException();
+            } else {
                 if (!fetchScriptFromLocalFileSystem(fileName, scriptBuffer))
                     return false; // fail early so we can catch missing files
             }
@@ -2780,28 +3380,29 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
         bool isLastFile = i == scripts.size() - 1;
         if (isModule) {
             if (!promise)
-                promise = loadAndEvaluateModule(globalObject->globalExec(), jscSource(scriptBuffer, fileName));
+                promise = loadAndEvaluateModule(globalObject->globalExec(), makeSource(stringFromUTF(scriptBuffer), SourceOrigin { absolutePath(fileName) }, fileName, TextPosition(), SourceProviderSourceType::Module));
             scope.clearException();
 
             JSFunction* fulfillHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&, isLastFile](ExecState* exec) {
-                checkException(isLastFile, false, exec->argument(0));
+                checkException(globalObject, isLastFile, false, exec->argument(0), uncaughtExceptionName, alwaysDumpUncaughtException, dump, success);
                 return JSValue::encode(jsUndefined());
             });
 
             JSFunction* rejectHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&, isLastFile](ExecState* exec) {
-                checkException(isLastFile, true, exec->argument(0));
+                checkException(globalObject, isLastFile, true, exec->argument(0), uncaughtExceptionName, alwaysDumpUncaughtException, dump, success);
                 return JSValue::encode(jsUndefined());
             });
 
             promise->then(globalObject->globalExec(), fulfillHandler, rejectHandler);
+            scope.releaseAssertNoException();
             vm.drainMicrotasks();
         } else {
             NakedPtr<Exception> evaluationException;
-            JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(scriptBuffer, fileName), JSValue(), evaluationException);
-            ASSERT(!scope.exception());
+            JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(scriptBuffer, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), evaluationException);
+            scope.assertNoException();
             if (evaluationException)
                 returnValue = evaluationException->value();
-            checkException(isLastFile, evaluationException, returnValue);
+            checkException(globalObject, isLastFile, evaluationException, returnValue, uncaughtExceptionName, alwaysDumpUncaughtException, dump, success);
         }
 
         scriptBuffer.clear();
@@ -2821,7 +3422,10 @@ static void runInteractive(GlobalObject* globalObject)
     VM& vm = globalObject->vm();
     auto scope = DECLARE_CATCH_SCOPE(vm);
 
-    String interpreterName(ASCIILiteral("Interpreter"));
+    std::optional<DirectoryName> directoryName = currentWorkingDirectory();
+    if (!directoryName)
+        return;
+    SourceOrigin sourceOrigin(resolvePath(directoryName.value(), ModuleName("interpreter")));
     
     bool shouldQuit = false;
     while (!shouldQuit) {
@@ -2836,7 +3440,7 @@ static void runInteractive(GlobalObject* globalObject)
                 break;
             source = source + line;
             source = source + '\n';
-            checkSyntax(globalObject->vm(), makeSource(source, interpreterName), error);
+            checkSyntax(globalObject->vm(), makeSource(source, sourceOrigin), error);
             if (!line[0]) {
                 free(line);
                 break;
@@ -2852,7 +3456,7 @@ static void runInteractive(GlobalObject* globalObject)
         
         
         NakedPtr<Exception> evaluationException;
-        JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, interpreterName), JSValue(), evaluationException);
+        JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, sourceOrigin), JSValue(), evaluationException);
 #else
         printf("%s", interactivePrompt);
         Vector<char, 256> line;
@@ -2867,7 +3471,7 @@ static void runInteractive(GlobalObject* globalObject)
             break;
 
         NakedPtr<Exception> evaluationException;
-        JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line, interpreterName), JSValue(), evaluationException);
+        JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line, sourceOrigin, sourceOrigin.string()), JSValue(), evaluationException);
 #endif
         if (evaluationException)
             printf("Exception: %s\n", evaluationException->value().toWTFString(globalObject->globalExec()).utf8().data());
@@ -2987,8 +3591,17 @@ void CommandLine::parseArguments(int argc, char** argv)
             continue;
         }
 
+        static const char* timeoutMultiplierOptStr = "--timeoutMultiplier=";
+        static const unsigned timeoutMultiplierOptStrLength = strlen(timeoutMultiplierOptStr);
+        if (!strncmp(arg, timeoutMultiplierOptStr, timeoutMultiplierOptStrLength)) {
+            const char* valueStr = &arg[timeoutMultiplierOptStrLength];
+            if (sscanf(valueStr, "%lf", &s_timeoutMultiplier) != 1)
+                dataLog("WARNING: --timeoutMultiplier=", valueStr, " is invalid. Expects a numeric ratio.\n");
+            continue;
+        }
+
         if (!strcmp(arg, "--test262-async")) {
-            test262AsyncTest = true;
+            asyncTestExpectedPasses++;
             continue;
         }
 
@@ -3054,85 +3667,121 @@ void CommandLine::parseArguments(int argc, char** argv)
         jscExit(EXIT_SUCCESS);
 }
 
-// We make this function no inline so that globalObject won't be on the stack if we do a GC in jscmain.
-static int NEVER_INLINE runJSC(VM* vm, CommandLine options)
+template<typename Func>
+int runJSC(CommandLine options, bool isWorker, const Func& func)
 {
-    JSLockHolder locker(vm);
-
+    Worker worker(Workers::singleton());
+    
+    VM& vm = VM::create(LargeHeap).leakRef();
     int result;
-    if (options.m_profile && !vm->m_perBytecodeProfiler)
-        vm->m_perBytecodeProfiler = std::make_unique<Profiler::Database>(*vm);
+    bool success;
+    {
+        JSLockHolder locker(vm);
+
+        if (options.m_profile && !vm.m_perBytecodeProfiler)
+            vm.m_perBytecodeProfiler = std::make_unique<Profiler::Database>(vm);
 
-    GlobalObject* globalObject = GlobalObject::create(*vm, GlobalObject::createStructure(*vm, jsNull()), options.m_arguments);
-    globalObject->setRemoteDebuggingEnabled(options.m_enableRemoteDebugging);
-    bool success = runWithScripts(globalObject, options.m_scripts, options.m_uncaughtExceptionName, options.m_alwaysDumpUncaughtException, options.m_dump, options.m_module);
-    if (options.m_interactive && success)
-        runInteractive(globalObject);
+        GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), options.m_arguments);
+        globalObject->setRemoteDebuggingEnabled(options.m_enableRemoteDebugging);
+        success = func(vm, globalObject);
+        if (options.m_interactive && success)
+            runInteractive(globalObject);
 
-    vm->drainMicrotasks();
-    result = success && (test262AsyncTest == test262AsyncPassed) ? 0 : 3;
+        vm.drainMicrotasks();
+    }
+    vm.promiseDeferredTimer->runRunLoop();
+
+    result = success && (asyncTestExpectedPasses == asyncTestPasses) ? 0 : 3;
 
-    if (options.m_exitCode)
-        printf("jsc exiting %d\n", result);
+    if (options.m_exitCode) {
+        printf("jsc exiting %d", result);
+        if (asyncTestExpectedPasses != asyncTestPasses)
+            printf(" because expected: %d async test passes but got: %d async test passes", asyncTestExpectedPasses, asyncTestPasses);
+        printf("\n");
+    }
 
     if (options.m_profile) {
-        if (!vm->m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
+        JSLockHolder locker(vm);
+        if (!vm.m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
             fprintf(stderr, "could not save profiler output.\n");
     }
 
 #if ENABLE(JIT)
-    if (Options::useExceptionFuzz())
-        printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks());
-    bool fireAtEnabled =
-    Options::fireExecutableAllocationFuzzAt() || Options::fireExecutableAllocationFuzzAtOrAfter();
-    if (Options::useExecutableAllocationFuzz() && (!fireAtEnabled || Options::verboseExecutableAllocationFuzz()))
-        printf("JSC EXECUTABLE ALLOCATION FUZZ: encountered %u checks.\n", numberOfExecutableAllocationFuzzChecks());
-    if (Options::useOSRExitFuzz()) {
-        printf("JSC OSR EXIT FUZZ: encountered %u static checks.\n", numberOfStaticOSRExitFuzzChecks());
-        printf("JSC OSR EXIT FUZZ: encountered %u dynamic checks.\n", numberOfOSRExitFuzzChecks());
-    }
-
-    auto compileTimeStats = JIT::compileTimeStats();
-    Vector<CString> compileTimeKeys;
-    for (auto& entry : compileTimeStats)
-        compileTimeKeys.append(entry.key);
-    std::sort(compileTimeKeys.begin(), compileTimeKeys.end());
-    for (CString key : compileTimeKeys)
-        printf("%40s: %.3lf ms\n", key.data(), compileTimeStats.get(key));
+    {
+        JSLockHolder locker(vm);
+        if (Options::useExceptionFuzz())
+            printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks());
+        bool fireAtEnabled =
+        Options::fireExecutableAllocationFuzzAt() || Options::fireExecutableAllocationFuzzAtOrAfter();
+        if (Options::useExecutableAllocationFuzz() && (!fireAtEnabled || Options::verboseExecutableAllocationFuzz()))
+            printf("JSC EXECUTABLE ALLOCATION FUZZ: encountered %u checks.\n", numberOfExecutableAllocationFuzzChecks());
+        if (Options::useOSRExitFuzz()) {
+            printf("JSC OSR EXIT FUZZ: encountered %u static checks.\n", numberOfStaticOSRExitFuzzChecks());
+            printf("JSC OSR EXIT FUZZ: encountered %u dynamic checks.\n", numberOfOSRExitFuzzChecks());
+        }
+
+        
+        auto compileTimeStats = JIT::compileTimeStats();
+        Vector<CString> compileTimeKeys;
+        for (auto& entry : compileTimeStats)
+            compileTimeKeys.append(entry.key);
+        std::sort(compileTimeKeys.begin(), compileTimeKeys.end());
+        for (CString key : compileTimeKeys)
+            printf("%40s: %.3lf ms\n", key.data(), compileTimeStats.get(key));
+    }
+#endif
+
+    if (Options::gcAtEnd()) {
+        // We need to hold the API lock to do a GC.
+        JSLockHolder locker(&vm);
+        vm.heap.collectNow(Sync, CollectionScope::Full);
+    }
+
+    if (options.m_dumpSamplingProfilerData) {
+#if ENABLE(SAMPLING_PROFILER)
+        JSLockHolder locker(&vm);
+        vm.samplingProfiler()->reportTopFunctions();
+        vm.samplingProfiler()->reportTopBytecodes();
+#else
+        dataLog("Sampling profiler is not enabled on this platform\n");
 #endif
+    }
+
+    if (isWorker) {
+        JSLockHolder locker(vm);
+        // This is needed because we don't want the worker's main
+        // thread to die before its compilation threads finish.
+        vm.deref();
+    }
 
     return result;
 }
 
 int jscmain(int argc, char** argv)
 {
+    // Need to override and enable restricted options before we start parsing options below.
+    Options::enableRestrictedOptions(true);
+
     // Note that the options parsing can affect VM creation, and thus
     // comes first.
     CommandLine options(argc, argv);
 
+    processConfigFile(Options::configFile(), "jsc");
+
     // Initialize JSC before getting VM.
     WTF::initializeMainThread();
     JSC::initializeThreading();
+    startTimeoutThreadIfNeeded();
+#if ENABLE(WEBASSEMBLY)
+    JSC::Wasm::enableFastMemory();
+#endif
 
-    VM* vm = &VM::create(LargeHeap).leakRef();
     int result;
-    result = runJSC(vm, options);
-
-    if (Options::gcAtEnd()) {
-        // We need to hold the API lock to do a GC.
-        JSLockHolder locker(vm);
-        vm->heap.collectAllGarbage();
-    }
-
-    if (options.m_dumpSamplingProfilerData) {
-#if ENABLE(SAMPLING_PROFILER)
-        JSLockHolder locker(vm);
-        vm->samplingProfiler()->reportTopFunctions();
-        vm->samplingProfiler()->reportTopBytecodes();
-#else
-        dataLog("Sampling profiler is not enabled on this platform\n");
-#endif
-    }
+    result = runJSC(
+        options, false,
+        [&] (VM&, GlobalObject* globalObject) {
+            return runWithScripts(globalObject, options.m_scripts, options.m_uncaughtExceptionName, options.m_alwaysDumpUncaughtException, options.m_dump, options.m_module);
+        });
 
     printSuperSamplerState();