summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2021-03-01 22:37:37 +0300
committerDmitry Stogov <dmitry@zend.com>2021-03-01 22:37:37 +0300
commit9da66e6ad0f57d7ba71417731ec2586703f4d790 (patch)
tree53b6bbc0615fc2b10ec1099f65fdd3b853a307e5 /Zend
parentf9f8c1c79cac1b03279190e0c5513a51881615f9 (diff)
downloadphp-git-9da66e6ad0f57d7ba71417731ec2586703f4d790.tar.gz
Optimized object conversion to array without rebulding properties HashTable
Diffstat (limited to 'Zend')
-rw-r--r--Zend/zend_object_handlers.c32
-rw-r--r--Zend/zend_object_handlers.h2
-rw-r--r--Zend/zend_operators.c7
-rw-r--r--Zend/zend_vm_def.h5
-rw-r--r--Zend/zend_vm_execute.h20
5 files changed, 66 insertions, 0 deletions
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 94d2ff8cf4..f10e2c58a6 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -87,6 +87,38 @@ ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
}
/* }}} */
+ZEND_API HashTable *zend_std_build_object_properties_array(zend_object *zobj) /* {{{ */
+{
+ zend_property_info *prop_info;
+ zend_class_entry *ce = zobj->ce;
+ HashTable *ht;
+ zval* prop;
+ int i;
+
+ ZEND_ASSERT(!zobj->properties);
+ ht = zend_new_array(ce->default_properties_count);
+ if (ce->default_properties_count) {
+ zend_hash_real_init_mixed(ht);
+ for (i = 0; i < ce->default_properties_count; i++) {
+ prop_info = ce->properties_info_table[i];
+
+ if (!prop_info) {
+ continue;
+ }
+
+ prop = OBJ_PROP(zobj, prop_info->offset);
+ if (UNEXPECTED(Z_TYPE_P(prop) == IS_UNDEF)) {
+ continue;
+ }
+
+ Z_TRY_ADDREF_P(prop);
+ _zend_hash_append(ht, prop_info->name, prop);
+ }
+ }
+ return ht;
+}
+/* }}} */
+
ZEND_API HashTable *zend_std_get_properties(zend_object *zobj) /* {{{ */
{
if (!zobj->properties) {
diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h
index 71c0168372..53eef82928 100644
--- a/Zend/zend_object_handlers.h
+++ b/Zend/zend_object_handlers.h
@@ -225,6 +225,8 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2);
ZEND_API int zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only);
ZEND_API void rebuild_object_properties(zend_object *zobj);
+ZEND_API HashTable *zend_std_build_object_properties_array(zend_object *zobj);
+
/* Handler for objects that cannot be meaningfully compared.
* Only objects with the same identity will be considered equal. */
ZEND_API int zend_objects_not_comparable(zval *o1, zval *o2);
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index a23dad9e1e..db53c71317 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -713,6 +713,13 @@ try_again:
case IS_OBJECT:
if (Z_OBJCE_P(op) == zend_ce_closure) {
convert_scalar_to_array(op);
+ } else if (Z_OBJ_P(op)->properties == NULL
+ && Z_OBJ_HT_P(op)->get_properties_for == NULL
+ && Z_OBJ_HT_P(op)->get_properties == zend_std_get_properties) {
+ /* Optimized version without rebulding properties HashTable */
+ HashTable *ht = zend_std_build_object_properties_array(Z_OBJ_P(op));
+ OBJ_RELEASE(Z_OBJ_P(op));
+ ZVAL_ARR(op, ht);
} else {
HashTable *obj_ht = zend_get_properties_for(op, ZEND_PROP_PURPOSE_ARRAY_CAST);
if (obj_ht) {
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 8b4a86b745..09dce52b68 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -6139,6 +6139,11 @@ ZEND_VM_COLD_CONST_HANDLER(51, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE)
} else {
ZVAL_EMPTY_ARRAY(result);
}
+ } else if (Z_OBJ_P(expr)->properties == NULL
+ && Z_OBJ_HT_P(expr)->get_properties_for == NULL
+ && Z_OBJ_HT_P(expr)->get_properties == zend_std_get_properties) {
+ /* Optimized version without rebulding properties HashTable */
+ ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr)));
} else {
HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST);
if (obj_ht) {
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 26903f9403..385941e595 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -4643,6 +4643,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CONST_H
} else {
ZVAL_EMPTY_ARRAY(result);
}
+ } else if (Z_OBJ_P(expr)->properties == NULL
+ && Z_OBJ_HT_P(expr)->get_properties_for == NULL
+ && Z_OBJ_HT_P(expr)->get_properties == zend_std_get_properties) {
+ /* Optimized version without rebulding properties HashTable */
+ ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr)));
} else {
HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST);
if (obj_ht) {
@@ -18859,6 +18864,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC
} else {
ZVAL_EMPTY_ARRAY(result);
}
+ } else if (Z_OBJ_P(expr)->properties == NULL
+ && Z_OBJ_HT_P(expr)->get_properties_for == NULL
+ && Z_OBJ_HT_P(expr)->get_properties == zend_std_get_properties) {
+ /* Optimized version without rebulding properties HashTable */
+ ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr)));
} else {
HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST);
if (obj_ht) {
@@ -21469,6 +21479,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC
} else {
ZVAL_EMPTY_ARRAY(result);
}
+ } else if (Z_OBJ_P(expr)->properties == NULL
+ && Z_OBJ_HT_P(expr)->get_properties_for == NULL
+ && Z_OBJ_HT_P(expr)->get_properties == zend_std_get_properties) {
+ /* Optimized version without rebulding properties HashTable */
+ ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr)));
} else {
HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST);
if (obj_ht) {
@@ -38144,6 +38159,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCO
} else {
ZVAL_EMPTY_ARRAY(result);
}
+ } else if (Z_OBJ_P(expr)->properties == NULL
+ && Z_OBJ_HT_P(expr)->get_properties_for == NULL
+ && Z_OBJ_HT_P(expr)->get_properties == zend_std_get_properties) {
+ /* Optimized version without rebulding properties HashTable */
+ ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr)));
} else {
HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST);
if (obj_ht) {