Implement cache slot optimization for XMLReader (#17232)

This commit is contained in:
Niels Dossche 2024-12-22 13:01:45 +01:00 committed by GitHub
parent 26244c7dcd
commit d480c04be1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 80 additions and 4 deletions

View file

@ -123,10 +123,25 @@ static zval *xmlreader_get_property_ptr_ptr(zend_object *object, zend_string *na
}
/* }}} */
static xmlreader_prop_handler *xmlreader_get_prop_handler(zend_string *name, void **cache_slot)
{
/* We don't store the `ce` as that may match with how the std cache slot code works in the fallback,
* instead use the prop handlers table as `ce`. */
if (cache_slot && cache_slot[0] == &xmlreader_prop_handlers) {
return cache_slot[1];
} else {
xmlreader_prop_handler *hnd = zend_hash_find_ptr(&xmlreader_prop_handlers, name);
if (hnd != NULL && cache_slot) {
CACHE_POLYMORPHIC_PTR_EX(cache_slot, &xmlreader_prop_handlers, hnd);
}
return hnd;
}
}
static int xmlreader_has_property(zend_object *object, zend_string *name, int type, void **cache_slot)
{
xmlreader_object *obj = php_xmlreader_fetch_object(object);
xmlreader_prop_handler *hnd = zend_hash_find_ptr(&xmlreader_prop_handlers, name);
xmlreader_prop_handler *hnd = xmlreader_get_prop_handler(name, cache_slot);
if (hnd != NULL) {
if (type == ZEND_PROPERTY_EXISTS) {
@ -162,7 +177,7 @@ static zval *xmlreader_read_property(zend_object *object, zend_string *name, int
{
zval *retval = NULL;
xmlreader_object *obj = php_xmlreader_fetch_object(object);
xmlreader_prop_handler *hnd = zend_hash_find_ptr(&xmlreader_prop_handlers, name);
xmlreader_prop_handler *hnd = xmlreader_get_prop_handler(name, cache_slot);
if (hnd != NULL) {
if (xmlreader_property_reader(obj, hnd, rv) == FAILURE) {
@ -181,7 +196,7 @@ static zval *xmlreader_read_property(zend_object *object, zend_string *name, int
/* {{{ xmlreader_write_property */
static zval *xmlreader_write_property(zend_object *object, zend_string *name, zval *value, void **cache_slot)
{
xmlreader_prop_handler *hnd = zend_hash_find_ptr(&xmlreader_prop_handlers, name);
xmlreader_prop_handler *hnd = xmlreader_get_prop_handler(name, cache_slot);
if (hnd != NULL) {
zend_readonly_property_modification_error_ex(ZSTR_VAL(object->ce->name), ZSTR_VAL(name));
@ -195,7 +210,7 @@ static zval *xmlreader_write_property(zend_object *object, zend_string *name, zv
void xmlreader_unset_property(zend_object *object, zend_string *name, void **cache_slot)
{
xmlreader_prop_handler *hnd = zend_hash_find_ptr(&xmlreader_prop_handlers, name);
xmlreader_prop_handler *hnd = xmlreader_get_prop_handler(name, cache_slot);
if (hnd != NULL) {
zend_throw_error(NULL, "Cannot unset %s::$%s", ZSTR_VAL(object->ce->name), ZSTR_VAL(name));

View file

@ -0,0 +1,58 @@
--TEST--
Cache slot test
--EXTENSIONS--
xmlreader
--FILE--
<?php
class Test1 {
function __construct(public string $localName) {}
}
#[AllowDynamicProperties]
class Test2 extends XMLReader {
}
function readLocalName($obj) {
for ($i = 0; $i < 2; $i++)
var_dump($obj->localName);
}
function readTestProp($obj) {
for ($i = 0; $i < 2; $i++)
var_dump($obj->testProp);
}
$reader = XMLReader::fromString("<root/>");
$reader->read();
$test1 = new Test1("hello");
readLocalName($reader);
readLocalName($test1);
readLocalName($reader);
$test2 = new Test2;
$test2->testProp = 1;
readTestProp($test2);
readTestProp($reader);
readTestProp($test2);
?>
--EXPECTF--
string(4) "root"
string(4) "root"
string(5) "hello"
string(5) "hello"
string(4) "root"
string(4) "root"
int(1)
int(1)
Warning: Undefined property: XMLReader::$testProp in %s on line %d
NULL
Warning: Undefined property: XMLReader::$testProp in %s on line %d
NULL
int(1)
int(1)