Skip to content

Commit 60aab0f

Browse files
authored
Implement zend_enum_get_case_by_id() (#22402)
Avoid hash-based lookup if we already know the offset in the table anyway.
1 parent fd8eaaf commit 60aab0f

8 files changed

Lines changed: 38 additions & 34 deletions

File tree

UPGRADING.INTERNALS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ PHP 8.6 INTERNALS UPGRADE NOTES
6565
zend_enum_RoundingMode parameter.
6666
. Added Z_PARAM_ENUM().
6767
. Added zend_enum_fetch_case_id().
68+
. Added zend_enum_get_case_by_id().
6869
. ZEND_INI_GET_ADDR() is now a void* pointer instead of a char* pointer. This
6970
more correctly represents the generic nature of the returned pointer and
7071
allows to remove explicit casts, but possibly breaks pointer arithmetic

Zend/zend_enum.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,11 @@ ZEND_API zend_object *zend_enum_get_case_cstr(zend_class_entry *ce, const char *
673673
return zend_enum_case_from_class_constant(c);
674674
}
675675

676+
ZEND_API zend_object *zend_enum_get_case_by_id(zend_class_entry *ce, int id) {
677+
zend_class_constant *c = Z_PTR(CE_CONSTANTS_TABLE(ce)->arData[id - 1].val);
678+
return zend_enum_case_from_class_constant(c);
679+
}
680+
676681
void zend_enum_startup(void)
677682
{
678683
for (size_t i = 0; i < sizeof(zarginfo_class_UnitEnum_cases)/sizeof(zend_arg_info); i++) {

Zend/zend_enum.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ ZEND_API void zend_enum_add_case(zend_class_entry *ce, zend_string *case_name, z
5555
ZEND_API void zend_enum_add_case_cstr(zend_class_entry *ce, const char *name, zval *value);
5656
ZEND_API zend_object *zend_enum_get_case(zend_class_entry *ce, zend_string *name);
5757
ZEND_API zend_object *zend_enum_get_case_cstr(zend_class_entry *ce, const char *name);
58+
ZEND_API zend_object *zend_enum_get_case_by_id(zend_class_entry *ce, int id);
5859
ZEND_API zend_result zend_enum_get_case_by_value(zend_object **result, zend_class_entry *ce, zend_long long_key, zend_string *string_key, bool try_from);
5960

6061
static zend_always_inline int zend_enum_fetch_case_id(zend_object *zobj)

ext/pcntl/pcntl.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ typedef psetid_t cpu_set_t;
152152
#include "Zend/zend_max_execution_timer.h"
153153

154154
#include "pcntl_arginfo.h"
155+
#include "pcntl_decl.h"
155156
static zend_class_entry *QosClass_ce;
156157

157158
ZEND_DECLARE_MODULE_GLOBALS(pcntl)
@@ -1839,28 +1840,28 @@ static qos_class_t qos_enum_to_pthread(zend_enum_Pcntl_QosClass entry)
18391840

18401841
static zend_object *qos_lval_to_zval(qos_class_t qos_class)
18411842
{
1842-
const char *entryname;
1843+
int entry_id;
18431844
switch (qos_class)
18441845
{
18451846
case QOS_CLASS_USER_INTERACTIVE:
1846-
entryname = "UserInteractive";
1847+
entry_id = ZEND_ENUM_Pcntl_QosClass_UserInteractive;
18471848
break;
18481849
case QOS_CLASS_USER_INITIATED:
1849-
entryname = "UserInitiated";
1850+
entry_id = ZEND_ENUM_Pcntl_QosClass_UserInitiated;
18501851
break;
18511852
case QOS_CLASS_UTILITY:
1852-
entryname = "Utility";
1853+
entry_id = ZEND_ENUM_Pcntl_QosClass_Utility;
18531854
break;
18541855
case QOS_CLASS_BACKGROUND:
1855-
entryname = "Background";
1856+
entry_id = ZEND_ENUM_Pcntl_QosClass_Background;
18561857
break;
18571858
case QOS_CLASS_DEFAULT:
18581859
default:
1859-
entryname = "Default";
1860+
entry_id = ZEND_ENUM_Pcntl_QosClass_Default;
18601861
break;
18611862
}
18621863

1863-
return zend_enum_get_case_cstr(QosClass_ce, entryname);
1864+
return zend_enum_get_case_by_id(QosClass_ce, entry_id);
18641865
}
18651866

18661867
PHP_FUNCTION(pcntl_getqos_class)

ext/standard/io_poll.c

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "php_network.h"
1919
#include "php_poll.h"
2020
#include "io_poll_arginfo.h"
21+
#include "io_poll_decl.h"
2122

2223
/* Class entries */
2324
static zend_class_entry *php_io_poll_backend_class_entry;
@@ -118,38 +119,31 @@ static zend_result php_io_poll_events_to_event_enums(uint32_t events, zval *even
118119
array_init(event_enums);
119120

120121
if (events & PHP_POLL_READ) {
121-
ZVAL_OBJ(&enum_case, zend_enum_get_case_cstr(php_io_poll_event_class_entry, "Read"));
122-
GC_ADDREF(Z_OBJ(enum_case));
122+
ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_Read));
123123
add_next_index_zval(event_enums, &enum_case);
124124
}
125125
if (events & PHP_POLL_WRITE) {
126-
ZVAL_OBJ(&enum_case, zend_enum_get_case_cstr(php_io_poll_event_class_entry, "Write"));
127-
GC_ADDREF(Z_OBJ(enum_case));
126+
ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_Write));
128127
add_next_index_zval(event_enums, &enum_case);
129128
}
130129
if (events & PHP_POLL_ERROR) {
131-
ZVAL_OBJ(&enum_case, zend_enum_get_case_cstr(php_io_poll_event_class_entry, "Error"));
132-
GC_ADDREF(Z_OBJ(enum_case));
130+
ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_Error));
133131
add_next_index_zval(event_enums, &enum_case);
134132
}
135133
if (events & PHP_POLL_HUP) {
136-
ZVAL_OBJ(&enum_case, zend_enum_get_case_cstr(php_io_poll_event_class_entry, "HangUp"));
137-
GC_ADDREF(Z_OBJ(enum_case));
134+
ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_HangUp));
138135
add_next_index_zval(event_enums, &enum_case);
139136
}
140137
if (events & PHP_POLL_RDHUP) {
141-
ZVAL_OBJ(&enum_case, zend_enum_get_case_cstr(php_io_poll_event_class_entry, "ReadHangUp"));
142-
GC_ADDREF(Z_OBJ(enum_case));
138+
ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_ReadHangUp));
143139
add_next_index_zval(event_enums, &enum_case);
144140
}
145141
if (events & PHP_POLL_ONESHOT) {
146-
ZVAL_OBJ(&enum_case, zend_enum_get_case_cstr(php_io_poll_event_class_entry, "OneShot"));
147-
GC_ADDREF(Z_OBJ(enum_case));
142+
ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_OneShot));
148143
add_next_index_zval(event_enums, &enum_case);
149144
}
150145
if (events & PHP_POLL_ET) {
151-
ZVAL_OBJ(&enum_case, zend_enum_get_case_cstr(php_io_poll_event_class_entry, "EdgeTriggered"));
152-
GC_ADDREF(Z_OBJ(enum_case));
146+
ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_EdgeTriggered));
153147
add_next_index_zval(event_enums, &enum_case);
154148
}
155149

ext/uri/uri_parser_rfc3986.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -125,19 +125,19 @@ ZEND_ATTRIBUTE_NONNULL void php_uri_parser_rfc3986_uri_type_read(php_uri_parser_
125125
{
126126
const UriUriA *uriparser_uri = get_uri_for_reading(uri, PHP_URI_COMPONENT_READ_MODE_RAW);
127127

128-
const char *type;
128+
zend_object *value;
129129

130130
if (has_text_range(&uriparser_uri->scheme)) {
131-
type = "Uri";
131+
value = zend_enum_get_case_by_id(php_uri_ce_rfc3986_uri_type, ZEND_ENUM_Uri_Rfc3986_UriType_Uri);
132132
} else if (has_text_range(&uriparser_uri->hostText)) {
133-
type = "NetworkPathReference";
133+
value = zend_enum_get_case_by_id(php_uri_ce_rfc3986_uri_type, ZEND_ENUM_Uri_Rfc3986_UriType_NetworkPathReference);
134134
} else if (uriparser_uri->absolutePath) {
135-
type = "AbsolutePathReference";
135+
value = zend_enum_get_case_by_id(php_uri_ce_rfc3986_uri_type, ZEND_ENUM_Uri_Rfc3986_UriType_AbsolutePathReference);
136136
} else {
137-
type = "RelativePathReference";
137+
value = zend_enum_get_case_by_id(php_uri_ce_rfc3986_uri_type, ZEND_ENUM_Uri_Rfc3986_UriType_RelativePathReference);
138138
}
139139

140-
ZVAL_OBJ_COPY(retval, zend_enum_get_case_cstr(php_uri_ce_rfc3986_uri_type, type));
140+
ZVAL_OBJ_COPY(retval, value);
141141
}
142142

143143
ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_scheme_read(void *uri, const php_uri_component_read_mode read_mode, zval *retval)
@@ -290,19 +290,19 @@ ZEND_ATTRIBUTE_NONNULL void php_uri_parser_rfc3986_host_type_read(php_uri_parser
290290
return;
291291
}
292292

293-
const char *type;
293+
zend_object *value;
294294

295295
if (uriparser_uri->hostData.ip4 != NULL) {
296-
type = "IPv4";
296+
value = zend_enum_get_case_by_id(php_uri_ce_rfc3986_uri_host_type, ZEND_ENUM_Uri_Rfc3986_UriHostType_IPv4);
297297
} else if (uriparser_uri->hostData.ip6 != NULL) {
298-
type = "IPv6";
298+
value = zend_enum_get_case_by_id(php_uri_ce_rfc3986_uri_host_type, ZEND_ENUM_Uri_Rfc3986_UriHostType_IPv6);
299299
} else if (has_text_range(&uriparser_uri->hostData.ipFuture)) {
300-
type = "IPvFuture";
300+
value = zend_enum_get_case_by_id(php_uri_ce_rfc3986_uri_host_type, ZEND_ENUM_Uri_Rfc3986_UriHostType_IPvFuture);
301301
} else {
302-
type = "RegisteredName";
302+
value = zend_enum_get_case_by_id(php_uri_ce_rfc3986_uri_host_type, ZEND_ENUM_Uri_Rfc3986_UriHostType_RegisteredName);
303303
}
304304

305-
ZVAL_OBJ_COPY(retval, zend_enum_get_case_cstr(php_uri_ce_rfc3986_uri_host_type, type));
305+
ZVAL_OBJ_COPY(retval, value);
306306
}
307307

308308
static zend_result php_uri_parser_rfc3986_host_write(void *uri, const zval *value, zval *errors)

ext/zend_test/test.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "zend_mm_custom_handlers.h"
4040
#include "ext/uri/php_uri.h"
4141
#include "zend_observer.h"
42+
#include "test_decl.h"
4243

4344
#if defined(HAVE_LIBXML) && !defined(PHP_WIN32)
4445
# include <libxml/globals.h>
@@ -622,7 +623,7 @@ static ZEND_FUNCTION(zend_get_unit_enum)
622623
{
623624
ZEND_PARSE_PARAMETERS_NONE();
624625

625-
RETURN_OBJ_COPY(zend_enum_get_case_cstr(zend_test_unit_enum, "Foo"));
626+
RETURN_OBJ_COPY(zend_enum_get_case_by_id(zend_test_unit_enum, ZEND_ENUM_ZendTestUnitEnum_Foo));
626627
}
627628

628629
static ZEND_FUNCTION(zend_test_zend_ini_parse_quantity)

main/streams/stream_errors.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ static void php_stream_error_create_object(zval *zv, php_stream_error_entry *ent
4545
case_name = "Generic";
4646
}
4747

48+
/* TODO: migrate to zend_enum_get_case_by_id() */
4849
zend_object *enum_obj = zend_enum_get_case_cstr(php_ce_stream_error_code, case_name);
4950
ZEND_ASSERT(enum_obj != NULL);
5051

0 commit comments

Comments
 (0)