Diff
Modified: branches/safari-605-branch/Source/WebCore/ChangeLog (227392 => 227393)
--- branches/safari-605-branch/Source/WebCore/ChangeLog 2018-01-23 04:08:48 UTC (rev 227392)
+++ branches/safari-605-branch/Source/WebCore/ChangeLog 2018-01-23 04:08:53 UTC (rev 227393)
@@ -1,5 +1,81 @@
2018-01-22 Jason Marcell <jmarc...@apple.com>
+ Cherry-pick r227275. rdar://problem/36745983
+
+ 2018-01-20 Brady Eidson <beid...@apple.com>
+
+ Make garbage collection of MessagePort objects be asynchronous.
+ https://bugs.webkit.org/show_bug.cgi?id=181910
+
+ Reviewed by Andy Estes.
+
+ No new tests (Covered by existing tests, including GC-specific ones).
+
+ The basic premise here is as follows:
+ - You can *always* GC a MessagePort that is closed
+ - You can *always* GC a MessagePort that has no onmessage handler, as incoming messages cannot
+ possibly revive it.
+ - You can GC a MessagePort, even if it has a message handler, as long as there are no messages
+ in flight between it and the remote port, and as long as the remote port is "maybe eligible for GC."
+
+ A MessagePort is considered "maybe eligible for GC" once hasPendingActivity is asked once.
+
+ A MessagePort loses "maybe eligible for GC" status once it is used for sending or receiving a message.
+
+ The changes to MessagePort.cpp implement the above with a tiny little bool-driven state machine.
+ * dom/MessagePort.cpp:
+ (WebCore::MessagePort::postMessage):
+ (WebCore::MessagePort::disentangle):
+ (WebCore::MessagePort::registerLocalActivity):
+ (WebCore::MessagePort::start):
+ (WebCore::MessagePort::close):
+ (WebCore::MessagePort::contextDestroyed):
+ (WebCore::MessagePort::dispatchMessages):
+ (WebCore::MessagePort::hasPendingActivity const):
+ (WebCore::MessagePort::isLocallyReachable const):
+ (WebCore::MessagePort::addEventListener):
+ (WebCore::MessagePort::removeEventListener):
+ * dom/MessagePort.h:
+
+ - Remove the lock and any background-thread code paths
+ - Add ASSERT(isMainThread())s throughout
+ * dom/messageports/MessagePortChannel.cpp:
+ (WebCore::MessagePortChannel::MessagePortChannel):
+ (WebCore::MessagePortChannel::includesPort):
+ (WebCore::MessagePortChannel::entanglePortWithProcess):
+ (WebCore::MessagePortChannel::disentanglePort):
+ (WebCore::MessagePortChannel::closePort):
+ (WebCore::MessagePortChannel::postMessageToRemote):
+ (WebCore::MessagePortChannel::takeAllMessagesForPort):
+ (WebCore::MessagePortChannel::checkRemotePortForActivity):
+ (WebCore::MessagePortChannel::hasAnyMessagesPendingOrInFlight const):
+ * dom/messageports/MessagePortChannel.h:
+
+ Add a callback for a MessagePortChannel to go ask the remote MessagePort object about local activity:
+ * dom/messageports/MessagePortChannelProvider.h:
+ * dom/messageports/MessagePortChannelProviderImpl.cpp:
+ (WebCore::MessagePortChannelProviderImpl::checkRemotePortForActivity):
+ (WebCore::MessagePortChannelProviderImpl::checkProcessLocalPortForActivity):
+ (WebCore::MessagePortChannelProviderImpl::hasMessagesForPorts_temporarySync): Deleted.
+ * dom/messageports/MessagePortChannelProviderImpl.h:
+
+ - Remove the lock and any background-thread code paths
+ - Add ASSERT(isMainThread())s throughout
+ * dom/messageports/MessagePortChannelRegistry.cpp:
+ (WebCore::MessagePortChannelRegistry::messagePortChannelCreated):
+ (WebCore::MessagePortChannelRegistry::messagePortChannelDestroyed):
+ (WebCore::MessagePortChannelRegistry::didEntangleLocalToRemote):
+ (WebCore::MessagePortChannelRegistry::didDisentangleMessagePort):
+ (WebCore::MessagePortChannelRegistry::didCloseMessagePort):
+ (WebCore::MessagePortChannelRegistry::didPostMessageToRemote):
+ (WebCore::MessagePortChannelRegistry::takeAllMessagesForPort):
+ (WebCore::MessagePortChannelRegistry::checkRemotePortForActivity):
+ (WebCore::MessagePortChannelRegistry::existingChannelContainingPort):
+ (WebCore::MessagePortChannelRegistry::hasMessagesForPorts_temporarySync): Deleted.
+ * dom/messageports/MessagePortChannelRegistry.h:
+
+2018-01-22 Jason Marcell <jmarc...@apple.com>
+
Cherry-pick r227282. rdar://problem/36746077
2018-01-21 Ryosuke Niwa <rn...@webkit.org>
Modified: branches/safari-605-branch/Source/WebCore/dom/MessagePort.cpp (227392 => 227393)
--- branches/safari-605-branch/Source/WebCore/dom/MessagePort.cpp 2018-01-23 04:08:48 UTC (rev 227392)
+++ branches/safari-605-branch/Source/WebCore/dom/MessagePort.cpp 2018-01-23 04:08:53 UTC (rev 227393)
@@ -124,6 +124,8 @@
{
LOG(MessagePorts, "Attempting to post message to port %s (to be received by port %s)", m_identifier.logString().utf8().data(), m_remoteIdentifier.logString().utf8().data());
+ registerLocalActivity();
+
Vector<RefPtr<MessagePort>> ports;
auto messageData = SerializedScriptValue::create(state, messageValue, WTFMove(transfer), ports);
if (messageData.hasException())
@@ -158,8 +160,10 @@
void MessagePort::disentangle()
{
ASSERT(m_entangled);
+ m_entangled = false;
- m_entangled = false;
+ registerLocalActivity();
+
MessagePortChannelProvider::singleton().messagePortDisentangled(m_identifier);
// We can't receive any messages or generate any events after this, so remove ourselves from the list of active ports.
@@ -171,6 +175,13 @@
m_scriptExecutionContext = nullptr;
}
+void MessagePort::registerLocalActivity()
+{
+ // Any time certain local operations happen, we dirty our own state to delay GC.
+ m_hasHadLocalActivitySinceLastCheck = true;
+ m_mightBeEligibleForGC = false;
+}
+
// Invoked to notify us that there are messages available for this port.
// This code may be called from another thread, and so should not call any non-threadsafe APIs (i.e. should not call into the entangled channel or access mutable variables).
void MessagePort::messageAvailable()
@@ -189,6 +200,8 @@
if (!isEntangled())
return;
+ registerLocalActivity();
+
ASSERT(m_scriptExecutionContext);
if (m_started)
return;
@@ -199,6 +212,7 @@
void MessagePort::close()
{
+ m_mightBeEligibleForGC = true;
if (m_closed)
return;
@@ -210,6 +224,8 @@
void MessagePort::contextDestroyed()
{
ASSERT(m_scriptExecutionContext);
+
+ m_mightBeEligibleForGC = true;
if (!m_closed)
close();
@@ -232,6 +248,9 @@
if (!m_scriptExecutionContext)
return;
+ if (!messages.isEmpty())
+ registerLocalActivity();
+
ASSERT(m_scriptExecutionContext->isContextThread());
bool contextIsWorker = is<WorkerGlobalScope>(*m_scriptExecutionContext);
@@ -266,14 +285,61 @@
bool MessagePort::hasPendingActivity() const
{
- // The spec says that entangled message ports should always be treated as if they have a strong reference.
- // We'll also stipulate that the queue needs to be open (if the app drops its reference to the port before start()-ing it, then it's not really entangled as it's unreachable).
- if (m_started && isEntangled() && MessagePortChannelProvider::singleton().hasMessagesForPorts_temporarySync(m_identifier, m_remoteIdentifier))
- return true;
+ m_mightBeEligibleForGC = true;
- return false;
+ // If the ScriptExecutionContext has been shut down on this object close()'ed, we can GC.
+ if (!m_scriptExecutionContext || m_closed)
+ return false;
+
+ // If this object has been idle since the remote port declared itself elgibile for GC, we can GC.
+ if (!m_hasHadLocalActivitySinceLastCheck && m_isRemoteEligibleForGC)
+ return false;
+
+ // If this MessagePort has no message event handler then the existence of remote activity cannot keep it alive.
+ if (!m_hasMessageEventListener)
+ return false;
+
+ // If we're not in the middle of asking the remote port about collectability, do so now.
+ if (!m_isAskingRemoteAboutGC) {
+ MessagePortChannelProvider::singleton().checkRemotePortForActivity(m_remoteIdentifier, [this, protectedThis = makeRef(*this)](MessagePortChannelProvider::HasActivity hasActivity) mutable {
+ auto innerHandler = [this, otherProtectedThis = WTFMove(protectedThis)](MessagePortChannelProvider::HasActivity hasActivity) {
+ bool hasHadLocalActivity = m_hasHadLocalActivitySinceLastCheck;
+ m_hasHadLocalActivitySinceLastCheck = false;
+
+ if (hasActivity == MessagePortChannelProvider::HasActivity::No && !hasHadLocalActivity)
+ m_isRemoteEligibleForGC = true;
+
+ if (hasActivity == MessagePortChannelProvider::HasActivity::Yes)
+ m_isRemoteEligibleForGC = false;
+
+ m_isAskingRemoteAboutGC = false;
+ };
+
+
+ if (!m_scriptExecutionContext)
+ return;
+
+ if (m_scriptExecutionContext->isContextThread()) {
+ innerHandler(hasActivity);
+ return;
+ }
+
+ m_scriptExecutionContext->postTask([innerHandler = WTFMove(innerHandler), hasActivity](ScriptExecutionContext&) mutable {
+ innerHandler(hasActivity);
+ });
+ });
+ m_isAskingRemoteAboutGC = true;
+ }
+
+ // Since we need an answer from the remote object, we have to pretend we have pending activity for now.
+ return true;
}
+bool MessagePort::isLocallyReachable() const
+{
+ return !m_mightBeEligibleForGC;
+}
+
MessagePort* MessagePort::locallyEntangledPort() const
{
// FIXME: As the header describes, this is an optional optimization.
@@ -323,11 +389,26 @@
bool MessagePort::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options)
{
- if (listener->isAttribute() && eventType == eventNames().messageEvent)
- start();
+ if (eventType == eventNames().messageEvent) {
+ if (listener->isAttribute())
+ start();
+ m_hasMessageEventListener = true;
+ registerLocalActivity();
+ }
+
return EventTargetWithInlineData::addEventListener(eventType, WTFMove(listener), options);
}
+bool MessagePort::removeEventListener(const AtomicString& eventType, EventListener& listener, const ListenerOptions& options)
+{
+ auto result = EventTargetWithInlineData::removeEventListener(eventType, listener, options);
+
+ if (!hasEventListeners(eventNames().messageEvent))
+ m_hasMessageEventListener = false;
+
+ return result;
+}
+
const char* MessagePort::activeDOMObjectName() const
{
return "MessagePort";
Modified: branches/safari-605-branch/Source/WebCore/dom/MessagePort.h (227392 => 227393)
--- branches/safari-605-branch/Source/WebCore/dom/MessagePort.h 2018-01-23 04:08:48 UTC (rev 227392)
+++ branches/safari-605-branch/Source/WebCore/dom/MessagePort.h 2018-01-23 04:08:53 UTC (rev 227393)
@@ -83,6 +83,8 @@
void stop() final { close(); }
bool hasPendingActivity() const final;
+ bool isLocallyReachable() const;
+
// EventTargetWithInlineData.
EventTargetInterface eventTargetInterface() const final { return MessagePortEventTargetInterfaceType; }
ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); }
@@ -93,9 +95,12 @@
explicit MessagePort(ScriptExecutionContext&, const MessagePortIdentifier& local, const MessagePortIdentifier& remote);
bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) final;
+ bool removeEventListener(const AtomicString& eventType, EventListener&, const ListenerOptions&) final;
void disentangle();
+ void registerLocalActivity();
+
// A port starts out its life entangled, and remains entangled until it is closed or is cloned.
bool isEntangled() const { return !m_closed && m_entangled; }
@@ -103,6 +108,13 @@
bool m_closed { false };
bool m_entangled { true };
+ // Flags to manage querying the remote port for GC purposes
+ mutable bool m_mightBeEligibleForGC { false };
+ mutable bool m_hasHadLocalActivitySinceLastCheck { false };
+ mutable bool m_isRemoteEligibleForGC { false };
+ mutable bool m_isAskingRemoteAboutGC { false };
+ bool m_hasMessageEventListener { false };
+
MessagePortIdentifier m_identifier;
MessagePortIdentifier m_remoteIdentifier;
Modified: branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannel.cpp (227392 => 227393)
--- branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannel.cpp 2018-01-23 04:08:48 UTC (rev 227392)
+++ branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannel.cpp 2018-01-23 04:08:53 UTC (rev 227393)
@@ -28,6 +28,8 @@
#include "Logging.h"
#include "MessagePortChannelRegistry.h"
+#include <wtf/CompletionHandler.h>
+#include <wtf/MainThread.h>
namespace WebCore {
@@ -39,6 +41,8 @@
MessagePortChannel::MessagePortChannel(MessagePortChannelRegistry& registry, const MessagePortIdentifier& port1, const MessagePortIdentifier& port2)
: m_registry(registry)
{
+ ASSERT(isMainThread());
+
relaxAdoptionRequirement();
m_ports[0] = port1;
@@ -58,7 +62,7 @@
bool MessagePortChannel::includesPort(const MessagePortIdentifier& port)
{
- Locker<Lock> locker(m_lock);
+ ASSERT(isMainThread());
return m_ports[0] == port || m_ports[1] == port;
}
@@ -65,7 +69,7 @@
void MessagePortChannel::entanglePortWithProcess(const MessagePortIdentifier& port, ProcessIdentifier process)
{
- Locker<Lock> locker(m_lock);
+ ASSERT(isMainThread());
LOG(MessagePorts, "MessagePortChannel %s (%p) entangling port %s", logString().utf8().data(), this, port.logString().utf8().data());
@@ -79,7 +83,7 @@
void MessagePortChannel::disentanglePort(const MessagePortIdentifier& port)
{
- Locker<Lock> locker(m_lock);
+ ASSERT(isMainThread());
LOG(MessagePorts, "MessagePortChannel %s (%p) disentangling port %s", logString().utf8().data(), this, port.logString().utf8().data());
@@ -92,12 +96,11 @@
// This set of steps is to guarantee that the lock is unlocked before the
// last ref to this object is released.
auto protectedThis = WTFMove(m_entangledToProcessProtectors[i]);
- locker.unlockEarly();
}
void MessagePortChannel::closePort(const MessagePortIdentifier& port)
{
- Locker<Lock> locker(m_lock);
+ ASSERT(isMainThread());
ASSERT(port == m_ports[0] || port == m_ports[1]);
size_t i = port == m_ports[0] ? 0 : 1;
@@ -113,13 +116,11 @@
m_pendingMessagePortTransfers[i].clear();
m_pendingMessageProtectors[i] = nullptr;
m_entangledToProcessProtectors[i] = nullptr;
-
- locker.unlockEarly();
}
bool MessagePortChannel::postMessageToRemote(MessageWithMessagePorts&& message, const MessagePortIdentifier& remoteTarget)
{
- Locker<Lock> locker(m_lock);
+ ASSERT(isMainThread());
ASSERT(remoteTarget == m_ports[0] || remoteTarget == m_ports[1]);
size_t i = remoteTarget == m_ports[0] ? 0 : 1;
@@ -156,7 +157,7 @@
void MessagePortChannel::takeAllMessagesForPort(const MessagePortIdentifier& port, Function<void(Vector<MessageWithMessagePorts>&&, Function<void()>&&)>&& callback)
{
- Locker<Lock> locker(m_lock);
+ ASSERT(isMainThread());
LOG(MessagePorts, "MessagePortChannel %p taking all messages for port %s", this, port.logString().utf8().data());
@@ -181,7 +182,6 @@
HashSet<RefPtr<MessagePortChannel>> transferredPortProtectors;
transferredPortProtectors.swap(m_pendingMessagePortTransfers[i]);
- locker.unlockEarly();
callback(WTFMove(result), [size, this, port, protectedThis = WTFMove(m_pendingMessageProtectors[i]), transferredPortProtectors = WTFMove(transferredPortProtectors)] {
UNUSED_PARAM(port);
#if LOG_DISABLED
@@ -193,10 +193,51 @@
});
}
+void MessagePortChannel::checkRemotePortForActivity(const MessagePortIdentifier& remotePort, CompletionHandler<void(MessagePortChannelProvider::HasActivity)>&& callback)
+{
+ ASSERT(isMainThread());
+ ASSERT(remotePort == m_ports[0] || remotePort == m_ports[1]);
+
+ // If the remote port is closed there is no pending activity.
+ size_t i = remotePort == m_ports[0] ? 0 : 1;
+ if (m_isClosed[i]) {
+ callback(MessagePortChannelProvider::HasActivity::No);
+ return;
+ }
+
+ // If there are any messages in flight between the ports, there is pending activity.
+ if (hasAnyMessagesPendingOrInFlight()) {
+ callback(MessagePortChannelProvider::HasActivity::Yes);
+ return;
+ }
+
+ // If the port is not currently in a process then it's being transferred as part of a postMessage.
+ // We treat these ports as if they do have activity since they will be revived when the message is delivered.
+ if (!m_processes[i]) {
+ callback(MessagePortChannelProvider::HasActivity::Yes);
+ return;
+ }
+
+ auto outerCallback = CompletionHandler<void(MessagePortChannelProvider::HasActivity)> { [this, protectedThis = makeRef(*this), callback = WTFMove(callback)] (MessagePortChannelProvider::HasActivity hasActivity) {
+ if (hasActivity == MessagePortChannelProvider::HasActivity::Yes) {
+ callback(hasActivity);
+ return;
+ }
+
+ // If the remote port said it had no activity, check again for any messages that might be in flight.
+ // This is because it might have asynchronously sent a message just before it was asked about local activity.
+ if (hasAnyMessagesPendingOrInFlight())
+ hasActivity = MessagePortChannelProvider::HasActivity::Yes;
+
+ callback(hasActivity);
+ } };
+
+ MessagePortChannelProvider::singleton().checkProcessLocalPortForActivity(remotePort, *m_processes[i], WTFMove(outerCallback));
+}
+
bool MessagePortChannel::hasAnyMessagesPendingOrInFlight() const
{
- Locker<Lock> locker(m_lock);
-
+ ASSERT(isMainThread());
return m_messageBatchesInFlight || !m_pendingMessages[0].isEmpty() || !m_pendingMessages[1].isEmpty();
}
Modified: branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannel.h (227392 => 227393)
--- branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannel.h 2018-01-23 04:08:48 UTC (rev 227392)
+++ branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannel.h 2018-01-23 04:08:53 UTC (rev 227393)
@@ -25,11 +25,11 @@
#pragma once
+#include "MessagePortChannelProvider.h"
#include "MessagePortIdentifier.h"
#include "MessageWithMessagePorts.h"
#include "Process.h"
#include <wtf/HashSet.h>
-#include <wtf/Lock.h>
#include <wtf/RefCounted.h>
#include <wtf/text/WTFString.h>
@@ -53,6 +53,7 @@
bool postMessageToRemote(MessageWithMessagePorts&&, const MessagePortIdentifier& remoteTarget);
void takeAllMessagesForPort(const MessagePortIdentifier&, Function<void(Vector<MessageWithMessagePorts>&&, Function<void()>&&)>&&);
+ void checkRemotePortForActivity(const MessagePortIdentifier&, CompletionHandler<void(MessagePortChannelProvider::HasActivity)>&& callback);
bool hasAnyMessagesPendingOrInFlight() const;
@@ -65,10 +66,6 @@
private:
MessagePortChannel(MessagePortChannelRegistry&, const MessagePortIdentifier& port1, const MessagePortIdentifier& port2);
- // FIXME: This lock is to temporarily support synchronous background-thread GC.
- // It should be removed and this class relegated to main thread only.
- mutable Lock m_lock;
-
MessagePortIdentifier m_ports[2];
bool m_isClosed[2] { false, false };
std::optional<ProcessIdentifier> m_processes[2];
Modified: branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannelProvider.h (227392 => 227393)
--- branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannelProvider.h 2018-01-23 04:08:48 UTC (rev 227392)
+++ branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannelProvider.h 2018-01-23 04:08:53 UTC (rev 227393)
@@ -25,6 +25,7 @@
#pragma once
+#include "Process.h"
#include <wtf/Function.h>
#include <wtf/Vector.h>
@@ -40,6 +41,7 @@
virtual ~MessagePortChannelProvider() { }
+ // Operations that WebProcesses perform
virtual void createNewMessagePortChannel(const MessagePortIdentifier& local, const MessagePortIdentifier& remote) = 0;
virtual void entangleLocalPortInThisProcessToRemote(const MessagePortIdentifier& local, const MessagePortIdentifier& remote) = 0;
virtual void messagePortDisentangled(const MessagePortIdentifier& local) = 0;
@@ -47,8 +49,15 @@
virtual void takeAllMessagesForPort(const MessagePortIdentifier&, Function<void(Vector<MessageWithMessagePorts>&&, Function<void()>&&)>&&) = 0;
virtual void postMessageToRemote(MessageWithMessagePorts&&, const MessagePortIdentifier& remoteTarget) = 0;
- virtual bool hasMessagesForPorts_temporarySync(const MessagePortIdentifier&, const MessagePortIdentifier&) = 0;
+ enum class HasActivity {
+ Yes,
+ No,
+ };
+ virtual void checkRemotePortForActivity(const MessagePortIdentifier& remoteTarget, CompletionHandler<void(HasActivity)>&& callback) = 0;
+ // Operations that the coordinating process performs (e.g. the UIProcess)
+ virtual void checkProcessLocalPortForActivity(const MessagePortIdentifier&, ProcessIdentifier, CompletionHandler<void(HasActivity)>&&) = 0;
+
private:
};
Modified: branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannelProviderImpl.cpp (227392 => 227393)
--- branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannelProviderImpl.cpp 2018-01-23 04:08:48 UTC (rev 227392)
+++ branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannelProviderImpl.cpp 2018-01-23 04:08:53 UTC (rev 227393)
@@ -27,6 +27,7 @@
#include "MessagePortChannelProviderImpl.h"
#include "MessagePort.h"
+#include <wtf/CompletionHandler.h>
#include <wtf/MainThread.h>
#include <wtf/RunLoop.h>
@@ -97,10 +98,30 @@
});
}
-bool MessagePortChannelProviderImpl::hasMessagesForPorts_temporarySync(const MessagePortIdentifier& port1, const MessagePortIdentifier& port2)
+void MessagePortChannelProviderImpl::checkRemotePortForActivity(const MessagePortIdentifier& remoteTarget, CompletionHandler<void(HasActivity)>&& outerCallback)
{
- // FIXME: Remove this sync function call when GC logic is made asynchronous.
- return m_registry.hasMessagesForPorts_temporarySync(port1, port2);
+ auto callback = CompletionHandler<void(HasActivity)> { [outerCallback = WTFMove(outerCallback)](HasActivity hasActivity) {
+ ASSERT(isMainThread());
+ outerCallback(hasActivity);
+ } };
+
+ performActionOnMainThread([registry = &m_registry, remoteTarget, callback = WTFMove(callback)]() mutable {
+ registry->checkRemotePortForActivity(remoteTarget, WTFMove(callback));
+ });
}
+void MessagePortChannelProviderImpl::checkProcessLocalPortForActivity(const MessagePortIdentifier& identifier, ProcessIdentifier, CompletionHandler<void(HasActivity)>&& callback)
+{
+ ASSERT(isMainThread());
+
+ auto port = MessagePort::existingMessagePortForIdentifier(identifier);
+ if (!port) {
+ callback(MessagePortChannelProvider::HasActivity::No);
+ return;
+ }
+
+ callback(port->isLocallyReachable() ? HasActivity::Yes : HasActivity::No);
+}
+
+
} // namespace WebCore
Modified: branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannelProviderImpl.h (227392 => 227393)
--- branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannelProviderImpl.h 2018-01-23 04:08:48 UTC (rev 227392)
+++ branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannelProviderImpl.h 2018-01-23 04:08:53 UTC (rev 227393)
@@ -41,8 +41,9 @@
void messagePortClosed(const MessagePortIdentifier& local) final;
void postMessageToRemote(MessageWithMessagePorts&&, const MessagePortIdentifier& remoteTarget) final;
void takeAllMessagesForPort(const MessagePortIdentifier&, Function<void(Vector<MessageWithMessagePorts>&&, Function<void()>&&)>&&) final;
+ void checkRemotePortForActivity(const MessagePortIdentifier& remoteTarget, CompletionHandler<void(HasActivity)>&& callback) final;
- bool hasMessagesForPorts_temporarySync(const MessagePortIdentifier&, const MessagePortIdentifier&) final;
+ void checkProcessLocalPortForActivity(const MessagePortIdentifier&, ProcessIdentifier, CompletionHandler<void(HasActivity)>&&) final;
void performActionOnMainThread(Function<void()>&&);
Modified: branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannelRegistry.cpp (227392 => 227393)
--- branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannelRegistry.cpp 2018-01-23 04:08:48 UTC (rev 227392)
+++ branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannelRegistry.cpp 2018-01-23 04:08:53 UTC (rev 227393)
@@ -45,7 +45,6 @@
void MessagePortChannelRegistry::messagePortChannelCreated(MessagePortChannel& channel)
{
- Locker<Lock> locker(m_openChannelsLock);
ASSERT(isMainThread());
auto result = m_openChannels.ensure(channel.port1(), [channel = &channel] {
@@ -61,7 +60,6 @@
void MessagePortChannelRegistry::messagePortChannelDestroyed(MessagePortChannel& channel)
{
- Locker<Lock> locker(m_openChannelsLock);
ASSERT(isMainThread());
ASSERT(m_openChannels.get(channel.port1()) == &channel);
@@ -76,7 +74,6 @@
void MessagePortChannelRegistry::didEntangleLocalToRemote(const MessagePortIdentifier& local, const MessagePortIdentifier& remote, ProcessIdentifier process)
{
ASSERT(isMainThread());
- Locker<Lock> locker(m_openChannelsLock);
// The channel might be gone if the remote side was closed.
auto* channel = m_openChannels.get(local);
@@ -91,7 +88,6 @@
void MessagePortChannelRegistry::didDisentangleMessagePort(const MessagePortIdentifier& port)
{
ASSERT(isMainThread());
- Locker<Lock> locker(m_openChannelsLock);
// The channel might be gone if the remote side was closed.
auto* channel = m_openChannels.get(port);
@@ -98,7 +94,6 @@
if (!channel)
return;
- locker.unlockEarly();
channel->disentanglePort(port);
}
@@ -105,7 +100,6 @@
void MessagePortChannelRegistry::didCloseMessagePort(const MessagePortIdentifier& port)
{
ASSERT(isMainThread());
- Locker<Lock> locker(m_openChannelsLock);
LOG(MessagePorts, "Registry: MessagePort %s closed in registry", port.logString().utf8().data());
@@ -118,7 +112,6 @@
LOG(MessagePorts, "Registry: (Note) The channel closed for port %s had messages pending or in flight", port.logString().utf8().data());
#endif
- locker.unlockEarly();
channel->closePort(port);
// FIXME: When making message ports be multi-process, this should probably push a notification
@@ -128,7 +121,6 @@
bool MessagePortChannelRegistry::didPostMessageToRemote(MessageWithMessagePorts&& message, const MessagePortIdentifier& remoteTarget)
{
ASSERT(isMainThread());
- Locker<Lock> locker(m_openChannelsLock);
LOG(MessagePorts, "Registry: Posting message to MessagePort %s in registry", remoteTarget.logString().utf8().data());
@@ -139,7 +131,6 @@
return false;
}
- locker.unlockEarly();
return channel->postMessageToRemote(WTFMove(message), remoteTarget);
}
@@ -146,7 +137,6 @@
void MessagePortChannelRegistry::takeAllMessagesForPort(const MessagePortIdentifier& port, Function<void(Vector<MessageWithMessagePorts>&&, Function<void()>&&)>&& callback)
{
ASSERT(isMainThread());
- Locker<Lock> locker(m_openChannelsLock);
LOG(MessagePorts, "Registry: Taking all messages for MessagePort %s", port.logString().utf8().data());
@@ -157,27 +147,21 @@
return;
}
- locker.unlockEarly();
channel->takeAllMessagesForPort(port, WTFMove(callback));
}
-bool MessagePortChannelRegistry::hasMessagesForPorts_temporarySync(const MessagePortIdentifier& port1, const MessagePortIdentifier& port2)
+void MessagePortChannelRegistry::checkRemotePortForActivity(const MessagePortIdentifier& remoteTarget, CompletionHandler<void(MessagePortChannelProvider::HasActivity)>&& callback)
{
- // FIXME: Remove this function (and the lock) with a followup patch to do async garbage collection
- Locker<Lock> locker(m_openChannelsLock);
+ ASSERT(isMainThread());
- auto* channel1 = m_openChannels.get(port1);
- if (!channel1)
- return false;
+ // The channel might be gone if the remote side was closed.
+ auto* channel = m_openChannels.get(remoteTarget);
+ if (!channel) {
+ callback(MessagePortChannelProvider::HasActivity::No);
+ return;
+ }
- auto* channel2 = m_openChannels.get(port2);
- ASSERT_UNUSED(channel2, channel2);
- if (!channel2)
- return false;
-
- ASSERT(channel1 == channel2);
-
- return channel1->hasAnyMessagesPendingOrInFlight();
+ channel->checkRemotePortForActivity(remoteTarget, WTFMove(callback));
}
MessagePortChannel* MessagePortChannelRegistry::existingChannelContainingPort(const MessagePortIdentifier& port)
@@ -184,8 +168,6 @@
{
ASSERT(isMainThread());
- Locker<Lock> locker(m_openChannelsLock);
-
return m_openChannels.get(port);
}
Modified: branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannelRegistry.h (227392 => 227393)
--- branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannelRegistry.h 2018-01-23 04:08:48 UTC (rev 227392)
+++ branches/safari-605-branch/Source/WebCore/dom/messageports/MessagePortChannelRegistry.h 2018-01-23 04:08:53 UTC (rev 227393)
@@ -26,6 +26,7 @@
#pragma once
#include "MessagePortChannel.h"
+#include "MessagePortChannelProvider.h"
#include "MessagePortIdentifier.h"
#include "Process.h"
#include <wtf/HashMap.h>
@@ -42,18 +43,14 @@
void didCloseMessagePort(const MessagePortIdentifier& local);
bool didPostMessageToRemote(MessageWithMessagePorts&&, const MessagePortIdentifier& remoteTarget);
void takeAllMessagesForPort(const MessagePortIdentifier&, Function<void(Vector<MessageWithMessagePorts>&&, Function<void()>&&)>&&);
+ void checkRemotePortForActivity(const MessagePortIdentifier& remoteTarget, CompletionHandler<void(MessagePortChannelProvider::HasActivity)>&& callback);
MessagePortChannel* existingChannelContainingPort(const MessagePortIdentifier&);
- bool hasMessagesForPorts_temporarySync(const MessagePortIdentifier&, const MessagePortIdentifier&);
void messagePortChannelCreated(MessagePortChannel&);
void messagePortChannelDestroyed(MessagePortChannel&);
private:
-
- // FIXME: The need for the open channels lock is temporary.
- // It should be removed and this class should be main-thread only.
- Lock m_openChannelsLock;
HashMap<MessagePortIdentifier, MessagePortChannel*> m_openChannels;
};