]> granicus.if.org Git - php/commitdiff
Optimized object conversion to array without rebulding properties HashTable
authorDmitry Stogov <dmitry@zend.com>
Mon, 1 Mar 2021 19:37:37 +0000 (22:37 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 1 Mar 2021 19:37:37 +0000 (22:37 +0300)
Zend/zend_object_handlers.c
Zend/zend_object_handlers.h
Zend/zend_operators.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 94d2ff8cf4486dc6f23abd8c59420dfd7a01f7d9..f10e2c58a6bade4c14308ba78127be264aa30aa4 100644 (file)
@@ -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) {
index 71c0168372f601036b49f2f7a2cbdc6603197a0c..53eef829282ce3181e16c91f509f961190b50432 100644 (file)
@@ -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);
index a23dad9e1e1d57d447a8c7881f34de3332d9befc..db53c71317a4dfd05216c3096c37d83989698adb 100644 (file)
@@ -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) {
index 8b4a86b7452f0f903501dbddb7fd64402949a460..09dce52b68a03973ed0a6995c1469e4bb93440be 100644 (file)
@@ -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) {
index 26903f940334a5501bd9b1b411f180693234339a..385941e5952aa4e556c848a310806203b6a0b6a7 100644 (file)
@@ -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) {