[php-src] master: poll: fetch method ptr directly (#22816)

Gina Peter Banyard via GitHub <[email protected]> Mon, 20 Jul 2026 13:32:32 +0000
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Gina Peter Banyard (Girgias)
Committer: GitHub (web-flow)
Pusher: Girgias
Date: 2026-07-20T14:32:29+01:00

Commit: https://github.com/php/php-src/commit/55183b9d127bb8eba2d5e4b13e0c1536ff371d30
Raw diff: https://github.com/php/php-src/commit/55183b9d127bb8eba2d5e4b13e0c1536ff371d30.diff

poll: fetch method ptr directly (#22816)

Rather than going through a whole callability check via call_user_function() we can grab the known method pointer and call it directly.

This removes some allocations

Changed paths:
  M  main/poll/poll_handle.c


Diff:

diff --git a/main/poll/poll_handle.c b/main/poll/poll_handle.c
index 0c0628ac49dc..228d44e1e420 100644
--- a/main/poll/poll_handle.c
+++ b/main/poll/poll_handle.c
@@ -19,26 +19,22 @@
 static php_socket_t php_poll_handle_default_get_fd(php_poll_handle_object *handle)
 {
 	zval retval;
-	zval obj;
-	zval func_name;
 
-	ZVAL_OBJ(&obj, &handle->std);
-
-	/* Prepare function name as zval */
-	ZVAL_STRING(&func_name, "getFileDescriptor");
+	/* Grab getFileDescriptor() method pointer which is stored in lowercase in the function table */
+	zend_function *method = zend_hash_str_find_ptr_lc(&handle->std.ce->function_table, ZEND_STRL("getfiledescriptor"));
+	ZEND_ASSERT(method && "no default method???");
 
 	/* Call getFileDescriptor() method */
-	if (EXPECTED(call_user_function(NULL, &obj, &func_name, &retval, 0, NULL) == SUCCESS)) {
-		if (Z_TYPE(retval) == IS_LONG) {
-			php_socket_t fd = Z_LVAL(retval) < 0 ? SOCK_ERR : (php_socket_t) Z_LVAL(retval);
-			zval_ptr_dtor(&retval);
-			zval_ptr_dtor(&func_name); /* Clean up function name */
-			return fd;
-		}
-		zval_ptr_dtor(&retval);
+	zend_call_known_function(method, &handle->std, handle->std.ce, &retval, 0, NULL, NULL);
+
+	/* No need to deref the return value as the class is final and thus the method cannot be changed to return by-ref */
+	if (EXPECTED(Z_TYPE(retval) == IS_LONG)) {
+		php_socket_t fd = Z_LVAL(retval) < 0 ? SOCK_ERR : (php_socket_t) Z_LVAL(retval);
+		/* No need to clean the retval as we know it is an integer, and thus it's just on the stack */
+		return fd;
 	}
 
-	zval_ptr_dtor(&func_name); /* Clean up function name */
+	zval_ptr_dtor(&retval);
 	return SOCK_ERR; /* Invalid socket */
 }