Refactor event handlers in socket_patch to avoid dynamic calls.
Change-Id: I704da875a956cbf80793c7d4f9a755e718446cb2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/264896
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Kallen Tu <kallentu@google.com>
diff --git a/sdk/lib/_internal/vm/bin/socket_patch.dart b/sdk/lib/_internal/vm/bin/socket_patch.dart
index 0ade390..48549ea 100644
--- a/sdk/lib/_internal/vm/bin/socket_patch.dart
+++ b/sdk/lib/_internal/vm/bin/socket_patch.dart
@@ -460,7 +460,12 @@
Completer closeCompleter = new Completer.sync();
// Handlers and receive port for socket events from the event handler.
- final List eventHandlers = new List.filled(eventCount + 1, null);
+ void Function()? readEventHandler;
+ void Function()? writeEventHandler;
+ void Function(Object e, StackTrace? st)? errorEventHandler;
+ void Function()? closedEventHandler;
+ void Function()? destroyedEventHandler;
+
RawReceivePort? eventPort;
bool flagsSent = false;
@@ -1316,14 +1321,14 @@
if (stopRead()) {
if (isClosedRead && !closedReadEventSent) {
if (isClosedWrite) close();
- var handler = eventHandlers[closedEvent];
+ var handler = closedEventHandler;
if (handler == null) return;
closedReadEventSent = true;
handler();
}
return;
}
- var handler = eventHandlers[readEvent];
+ var handler = readEventHandler;
if (handler == null) return;
readEventIssued = true;
handler();
@@ -1350,7 +1355,7 @@
if (isClosing) return;
if (!sendWriteEvents) return;
sendWriteEvents = false;
- var handler = eventHandlers[writeEvent];
+ var handler = writeEventHandler;
if (handler == null) return;
handler();
}
@@ -1370,62 +1375,68 @@
int events = eventsObj as int;
for (int i = firstEvent; i <= lastEvent; i++) {
if (((events & (1 << i)) != 0)) {
- if ((i == closedEvent || i == readEvent) && isClosedRead) continue;
if (isClosing && i != destroyedEvent) continue;
- if (i == closedEvent && !isListening && !isClosing && !isClosed) {
- isClosedRead = true;
- issueReadEvent();
- continue;
- }
-
- if (i == writeEvent) {
- writeAvailable = true;
- issueWriteEvent(delayed: false);
- continue;
- }
-
- if (i == readEvent) {
- if (isListening) {
- connections++;
- } else {
- if (isUdp) {
- _availableDatagram = nativeAvailableDatagram();
+ switch (i) {
+ case readEvent:
+ if (isClosedRead) continue;
+ if (isListening) {
+ connections++;
+ if (!isClosed) {
+ // If the connection is closed right after it's accepted, there's a
+ // chance the close-handler is not set.
+ var handler = readEventHandler;
+ if (handler != null) handler();
+ }
} else {
- available = nativeAvailable();
+ if (isUdp) {
+ _availableDatagram = nativeAvailableDatagram();
+ } else {
+ available = nativeAvailable();
+ }
+ issueReadEvent();
+ continue;
}
- issueReadEvent();
+ break;
+ case writeEvent:
+ writeAvailable = true;
+ issueWriteEvent(delayed: false);
continue;
- }
- }
-
- var handler = eventHandlers[i];
- if (i == destroyedEvent) {
- assert(isClosing);
- assert(!isClosed);
- isClosed = true;
- closeCompleter.complete();
- disconnectFromEventHandler();
- if (handler != null) handler();
- continue;
- }
-
- if (i == errorEvent) {
- if (!isClosing) {
- final osError = nativeGetError();
- if (osError != null) {
- reportError(osError, null, osError.message);
- } else {
- reportError(
- Error(),
- StackTrace.current,
- "Error event raised in event handler : "
- "error condition has been reset");
+ case errorEvent:
+ if (!isClosing) {
+ final osError = nativeGetError();
+ if (osError != null) {
+ reportError(osError, null, osError.message);
+ } else {
+ reportError(
+ Error(),
+ StackTrace.current,
+ "Error event raised in event handler : "
+ "error condition has been reset");
+ }
}
- }
- } else if (!isClosed) {
- // If the connection is closed right after it's accepted, there's a
- // chance the close-handler is not set.
- if (handler != null) handler();
+ break;
+ case closedEvent:
+ if (isClosedRead) continue;
+ if (!isListening && !isClosing && !isClosed) {
+ isClosedRead = true;
+ issueReadEvent();
+ continue;
+ } else if (!isClosed) {
+ // If the connection is closed right after it's accepted, there's a
+ // chance the close-handler is not set.
+ var handler = closedEventHandler;
+ if (handler != null) handler();
+ }
+ break;
+ case destroyedEvent:
+ assert(isClosing);
+ assert(!isClosed);
+ isClosed = true;
+ closeCompleter.complete();
+ disconnectFromEventHandler();
+ var handler = destroyedEventHandler;
+ if (handler != null) handler();
+ continue;
}
}
}
@@ -1447,12 +1458,17 @@
}
}
- void setHandlers({read, write, error, closed, destroyed}) {
- eventHandlers[readEvent] = read;
- eventHandlers[writeEvent] = write;
- eventHandlers[errorEvent] = error;
- eventHandlers[closedEvent] = closed;
- eventHandlers[destroyedEvent] = destroyed;
+ void setHandlers(
+ {void Function()? read,
+ void Function()? write,
+ void Function(Object e, StackTrace? st)? error,
+ void Function()? closed,
+ void Function()? destroyed}) {
+ readEventHandler = read;
+ writeEventHandler = write;
+ errorEventHandler = error;
+ closedEventHandler = closed;
+ destroyedEventHandler = destroyed;
}
void setListening({bool read = true, bool write = true}) {
@@ -1573,8 +1589,9 @@
var e =
createError(error, message, isUdp || isTcp ? address : null, localPort);
// Invoke the error handler if any.
- if (eventHandlers[errorEvent] != null) {
- eventHandlers[errorEvent](e, st);
+ var handler = errorEventHandler;
+ if (handler != null) {
+ handler(e, st);
}
// For all errors we close the socket
close();