Title: [211509] branches/safari-603-branch

Diff

Modified: branches/safari-603-branch/JSTests/ChangeLog (211508 => 211509)


--- branches/safari-603-branch/JSTests/ChangeLog	2017-02-01 21:26:05 UTC (rev 211508)
+++ branches/safari-603-branch/JSTests/ChangeLog	2017-02-01 21:26:09 UTC (rev 211509)
@@ -1,5 +1,25 @@
 2017-01-27  Matthew Hanson  <matthew_han...@apple.com>
 
+        Merge r211194. rdar://problem/30201008
+
+    2017-01-25  Filip Pizlo  <fpi...@apple.com>
+
+            jsc.cpp should have the $.agent stuff for testing SAB
+            https://bugs.webkit.org/show_bug.cgi?id=167431
+
+            Reviewed by Saam Barati.
+
+            Add a very basic test of Atomics using $.agent. This is based on
+            LayoutTests/workers/sab/simple.html.
+
+            * stress/lars-sab-workers.js: Added.
+            (startWorker):
+            (resources):
+            (wake):
+            (else):
+
+2017-01-27  Matthew Hanson  <matthew_han...@apple.com>
+
         Rollout r211258. rdar://problem/29144126
 
 2017-01-27  Matthew Hanson  <matthew_han...@apple.com>

Added: branches/safari-603-branch/JSTests/stress/lars-sab-workers.js (0 => 211509)


--- branches/safari-603-branch/JSTests/stress/lars-sab-workers.js	                        (rev 0)
+++ branches/safari-603-branch/JSTests/stress/lars-sab-workers.js	2017-02-01 21:26:09 UTC (rev 211509)
@@ -0,0 +1,127 @@
+//@ defaultRunNoisyTest
+
+var sab = new SharedArrayBuffer(100 * 4);
+
+var memory = new Int32Array(sab);
+
+var numWorkers = 0;
+function startWorker(code)
+{
+    print("Starting worker!");
+    
+    numWorkers++;
+    $.agent.start(code);
+}
+
+resources = `
+function wait(memory, index, waitCondition, wakeCondition)
+{
+    while (memory[index] == waitCondition) {
+        var result = Atomics.wait(memory, index, waitCondition);
+        switch (result) {
+        case "not-equal":
+        case "ok":
+            break;
+        default:
+            $.agent.report("Error: bad result from wait: " + result);
+            $.agent.report("error");
+            break;
+        }
+        var value = memory[index];
+        if (value != wakeCondition) {
+            $.agent.report("Error: wait returned not-equal but the memory has a bad value: " + value);
+            $.agent.report("error");
+        }
+    }
+    var value = memory[index];
+    if (value != wakeCondition) {
+        $.agent.report("Error: done waiting but the memory has a bad value: " + value);
+        $.agent.report("error");
+    }
+}
+
+function wake(memory, index)
+{
+    var result = Atomics.wake(memory, index, 1);
+    if (result != 0 && result != 1) {
+        $.agent.report("Error: bad result from wake: " + result);
+        $.agent.report("error");
+    }
+}
+`;
+
+startWorker(
+    resources + `
+    $.agent.receiveBroadcast(sab => {
+        var memory = new Int32Array(sab);
+        var didStartIdx = 0;
+        var shouldGoIdx = 1;
+        var didEndIdx = 2;
+        
+        $.agent.report("1: Started!");
+        $.agent.report("1: Memory: " + memory);
+        
+        wait(memory, didStartIdx, 0, 1);
+        
+        $.agent.report("1: It started!");
+        
+        memory[shouldGoIdx] = 1;
+        wake(memory, shouldGoIdx);
+        
+        wait(memory, didEndIdx, 0, 1);
+        
+        $.agent.report("1: All done!");
+        $.agent.report("1: Memory: " + memory);
+        $.agent.report("done");
+    });
+    `);
+
+startWorker(
+    resources + `
+    $.agent.receiveBroadcast(sab => {
+        var memory = new Int32Array(sab);
+        var didStartIdx = 0;
+        var shouldGoIdx = 1;
+        var didEndIdx = 2;
+        
+        $.agent.report("2: Started!");
+        $.agent.report("2: Memory: " + memory);
+        
+        Atomics.store(memory, didStartIdx, 1);
+        wake(memory, didStartIdx);
+        
+        wait(memory, shouldGoIdx, 0, 1);
+        
+        Atomics.store(memory, didEndIdx, 1);
+        wake(memory, didEndIdx, 1);
+        
+        $.agent.report("2: Memory: " + memory);
+        $.agent.report("done");
+    });
+    `);
+
+$.agent.broadcast(sab);
+
+for (;;) {
+    var report = waitForReport();
+    if (report == "done") {
+        if (!--numWorkers) {
+            print("All workers done!");
+            break;
+        }
+    } else if (report == "error") {
+        print("Test failed!");
+        throw new Error("Test failed.");
+    } else
+        print("report: " + report);
+}
+
+for (var i = 0; i < 3; ++i) {
+    if (memory[i] != 1)
+        throw "Error: Bad value at memory[" + i + "]: " + memory[i];
+}
+for (var i = 3; i < memory.length; ++i) {
+    if (memory[i] != 0)
+        throw "Error: Bad value at memory[" + i + "]: " + memory[i];
+}
+print("Test passed!");

Modified: branches/safari-603-branch/Source/_javascript_Core/ChangeLog (211508 => 211509)


--- branches/safari-603-branch/Source/_javascript_Core/ChangeLog	2017-02-01 21:26:05 UTC (rev 211508)
+++ branches/safari-603-branch/Source/_javascript_Core/ChangeLog	2017-02-01 21:26:09 UTC (rev 211509)
@@ -1,5 +1,56 @@
 2017-01-27  Matthew Hanson  <matthew_han...@apple.com>
 
+        Merge r211194. rdar://problem/30201008
+
+    2017-01-25  Filip Pizlo  <fpi...@apple.com>
+
+            jsc.cpp should have the $.agent stuff for testing SAB
+            https://bugs.webkit.org/show_bug.cgi?id=167431
+
+            Reviewed by Saam Barati.
+
+            This adds some stuff that the SAB branch of test262 needs. None of this is exposed except for our
+            own tests and the SAB branch of test262. We now pass all of the Atomics tests in the SAB branch
+            of test262.
+
+            * jsc.cpp:
+            (Message::releaseContents):
+            (Message::index):
+            (GlobalObject::finishCreation):
+            (GlobalObject::addFunction):
+            (Message::Message):
+            (Message::~Message):
+            (Worker::Worker):
+            (Worker::~Worker):
+            (Worker::send):
+            (Worker::receive):
+            (Worker::current):
+            (Worker::currentWorker):
+            (Workers::Workers):
+            (Workers::~Workers):
+            (Workers::broadcast):
+            (Workers::report):
+            (Workers::tryGetReport):
+            (Workers::getReport):
+            (Workers::singleton):
+            (functionDollarCreateRealm):
+            (functionDollarDetachArrayBuffer):
+            (functionDollarEvalScript):
+            (functionDollarAgentStart):
+            (functionDollarAgentReceiveBroadcast):
+            (functionDollarAgentReport):
+            (functionDollarAgentSleep):
+            (functionDollarAgentBroadcast):
+            (functionDollarAgentGetReport):
+            (functionWaitForReport):
+            (checkException):
+            (runWithScripts):
+            (runJSC):
+            (jscmain):
+            * runtime/JSArrayBuffer.h:
+
+2017-01-27  Matthew Hanson  <matthew_han...@apple.com>
+
         Rollout r211258. rdar://problem/29144126
 
 2017-01-27  Matthew Hanson  <matthew_han...@apple.com>

Modified: branches/safari-603-branch/Source/_javascript_Core/jsc.cpp (211508 => 211509)


--- branches/safari-603-branch/Source/_javascript_Core/jsc.cpp	2017-02-01 21:26:05 UTC (rev 211508)
+++ branches/safari-603-branch/Source/_javascript_Core/jsc.cpp	2017-02-01 21:26:09 UTC (rev 211509)
@@ -60,6 +60,7 @@
 #include "ParserError.h"
 #include "ProfilerDatabase.h"
 #include "ProtoCallFrame.h"
+#include "ReleaseHeapAccessScope.h"
 #include "SamplingProfiler.h"
 #include "ShadowChicken.h"
 #include "StackVisitor.h"
@@ -905,6 +906,67 @@
 
 static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer);
 
+class CommandLine;
+class GlobalObject;
+class Workers;
+
+template<typename Func>
+int runJSC(CommandLine, 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*);
@@ -1008,6 +1070,17 @@
 static EncodedJSValue JSC_HOST_CALL functionSetRandomSeed(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionIsRope(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*);
 
 struct Script {
     enum class StrictMode {
@@ -1262,12 +1335,43 @@
         }
 
         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);
     }
+    
+    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)
@@ -1619,8 +1723,15 @@
 
 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());
 }
 
@@ -2170,6 +2281,307 @@
     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*>(
+        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), 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;
+    
+    ThreadIdentifier thread = createThread(
+        "JSC Agent",
+        [sourceCode, &didStartLock, &didStartCondition, &didStart] () {
+            CommandLine commandLine(0, nullptr);
+            commandLine.m_interactive = false;
+            runJSC(
+                commandLine,
+                [&] (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), JSValue(), evaluationException);
+                    if (evaluationException)
+                        result = evaluationException->value();
+                    checkException(globalObject, true, evaluationException, result, String(), false, false, success);
+                    if (!success)
+                        exit(1);
+                    return success;
+                });
+        });
+    detachThread(thread);
+    
+    {
+        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());
+    JSArrayBuffer* jsBuffer = JSArrayBuffer::create(vm, exec->lexicalGlobalObject()->arrayBufferStructure(nativeBuffer->sharingMode()), 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*>(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(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));
+}
+
 template<typename ValueType>
 typename std::enable_if<!std::is_fundamental<ValueType>::value>::type addOption(VM&, JSObject*, Identifier, ValueType) { }
 
@@ -2865,6 +3277,19 @@
     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;
@@ -2877,17 +3302,6 @@
     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
@@ -2920,12 +3334,12 @@
             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());
             });
 
@@ -2937,7 +3351,7 @@
             ASSERT(!scope.exception());
             if (evaluationException)
                 returnValue = evaluationException->value();
-            checkException(isLastFile, evaluationException, returnValue);
+            checkException(globalObject, isLastFile, evaluationException, returnValue, uncaughtExceptionName, alwaysDumpUncaughtException, dump, success);
         }
 
         scriptBuffer.clear();
@@ -3199,22 +3613,25 @@
         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, const Func& func)
 {
-    JSLockHolder locker(vm);
+    Worker worker(Workers::singleton());
+    
+    VM& vm = VM::create(LargeHeap).leakRef();
+    JSLockHolder locker(&vm);
 
     int result;
-    if (options.m_profile && !vm->m_perBytecodeProfiler)
-        vm->m_perBytecodeProfiler = std::make_unique<Profiler::Database>(*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* 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);
+    bool success = func(vm, globalObject);
     if (options.m_interactive && success)
         runInteractive(globalObject);
 
-    vm->drainMicrotasks();
+    vm.drainMicrotasks();
     result = success && (test262AsyncTest == test262AsyncPassed) ? 0 : 3;
 
     if (options.m_exitCode)
@@ -3221,7 +3638,7 @@
         printf("jsc exiting %d\n", result);
 
     if (options.m_profile) {
-        if (!vm->m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
+        if (!vm.m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
             fprintf(stderr, "could not save profiler output.\n");
     }
 
@@ -3246,6 +3663,22 @@
         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.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
+    }
+
     return result;
 }
 
@@ -3263,26 +3696,13 @@
     JSC::initializeThreading();
     startTimeoutThreadIfNeeded();
 
-    VM* vm = &VM::create(LargeHeap).leakRef();
     int result;
-    result = runJSC(vm, options);
+    result = runJSC(
+        options,
+        [&] (VM&, GlobalObject* globalObject) {
+            return runWithScripts(globalObject, options.m_scripts, options.m_uncaughtExceptionName, options.m_alwaysDumpUncaughtException, options.m_dump, options.m_module);
+        });
 
-    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
-    }
-
     printSuperSamplerState();
 
     return result;

Modified: branches/safari-603-branch/Source/_javascript_Core/runtime/JSArrayBuffer.h (211508 => 211509)


--- branches/safari-603-branch/Source/_javascript_Core/runtime/JSArrayBuffer.h	2017-02-01 21:26:05 UTC (rev 211508)
+++ branches/safari-603-branch/Source/_javascript_Core/runtime/JSArrayBuffer.h	2017-02-01 21:26:09 UTC (rev 211509)
@@ -47,7 +47,7 @@
     
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
 
-    bool isShared() const;
+    JS_EXPORT_PRIVATE bool isShared() const;
     ArrayBufferSharingMode sharingMode() const;
     
     DECLARE_EXPORT_INFO;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to