Skip to content

Commit d08c584

Browse files
committed
Factor out array cast
1 parent d264057 commit d08c584

File tree

4 files changed

+39
-169
lines changed

4 files changed

+39
-169
lines changed

Zend/zend_ast.c

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -713,52 +713,25 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
713713
switch (ast->attr) {
714714
case _IS_BOOL:
715715
ZVAL_BOOL(result, zend_is_true(&op1));
716-
zval_ptr_dtor_nogc(&op1);
717716
break;
718717
case IS_LONG:
719718
ZVAL_LONG(result, zval_get_long_func(&op1, false));
720-
zval_ptr_dtor_nogc(&op1);
721719
break;
722720
case IS_DOUBLE:
723721
ZVAL_DOUBLE(result, zval_get_double_func(&op1));
724-
zval_ptr_dtor_nogc(&op1);
725722
break;
726723
case IS_STRING:
727724
ZVAL_STR(result, zval_get_string_func(&op1));
728-
zval_ptr_dtor_nogc(&op1);
729725
break;
730726
case IS_ARRAY:
731-
/* Adapted from VM */
732-
if (Z_TYPE(op1) != IS_OBJECT || Z_OBJCE(op1) == zend_ce_closure) {
733-
if (Z_TYPE(op1) != IS_NULL) {
734-
ZVAL_ARR(result, zend_new_array(1));
735-
zend_hash_index_add_new(Z_ARRVAL_P(result), 0, &op1);
736-
} else {
737-
ZVAL_EMPTY_ARRAY(result);
738-
}
739-
} else if (ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(&op1)) {
740-
ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ(op1)));
741-
zval_ptr_dtor_nogc(&op1);
742-
} else {
743-
HashTable *obj_ht = zend_get_properties_for(&op1, ZEND_PROP_PURPOSE_ARRAY_CAST);
744-
if (obj_ht) {
745-
ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht,
746-
(Z_OBJCE(op1)->default_properties_count ||
747-
Z_OBJ(op1)->handlers != &std_object_handlers ||
748-
GC_IS_RECURSIVE(obj_ht))));
749-
zend_release_properties(obj_ht);
750-
} else {
751-
ZVAL_EMPTY_ARRAY(result);
752-
}
753-
zval_ptr_dtor_nogc(&op1);
754-
}
727+
zend_cast_zval_to_array(result, &op1, IS_VAR);
755728
break;
756729
case IS_OBJECT:
757730
zend_cast_zval_to_object(result, &op1, IS_VAR);
758-
Z_TRY_DELREF(op1);
759731
break;
760732
EMPTY_SWITCH_DEFAULT_CASE();
761733
}
734+
zval_ptr_dtor_nogc(&op1);
762735
}
763736
break;
764737
case ZEND_AST_OR:

Zend/zend_execute.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,38 @@ static zend_always_inline void zend_cast_zval_to_object(zval *result, zval *expr
241241
}
242242
}
243243

244+
static zend_always_inline void zend_cast_zval_to_array(zval *result, zval *expr, uint8_t op1_type) {
245+
extern zend_class_entry *zend_ce_closure;
246+
if (op1_type == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) {
247+
if (Z_TYPE_P(expr) != IS_NULL) {
248+
ZVAL_ARR(result, zend_new_array(1));
249+
expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
250+
if (op1_type == IS_CONST) {
251+
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
252+
} else {
253+
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
254+
}
255+
} else {
256+
ZVAL_EMPTY_ARRAY(result);
257+
}
258+
} else if (ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(expr)) {
259+
/* Optimized version without rebuilding properties HashTable */
260+
ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr)));
261+
} else {
262+
HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST);
263+
if (obj_ht) {
264+
/* fast copy */
265+
ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht,
266+
(Z_OBJCE_P(expr)->default_properties_count ||
267+
Z_OBJ_P(expr)->handlers != &std_object_handlers ||
268+
GC_IS_RECURSIVE(obj_ht))));
269+
zend_release_properties(obj_ht);
270+
} else {
271+
ZVAL_EMPTY_ARRAY(result);
272+
}
273+
}
274+
}
275+
244276
ZEND_API zend_result ZEND_FASTCALL zval_update_constant(zval *pp);
245277
ZEND_API zend_result ZEND_FASTCALL zval_update_constant_ex(zval *pp, zend_class_entry *scope);
246278
ZEND_API zend_result ZEND_FASTCALL zval_update_constant_with_ctx(zval *pp, zend_class_entry *scope, zend_ast_evaluate_ctx *ctx);

Zend/zend_vm_def.h

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6493,34 +6493,7 @@ ZEND_VM_COLD_CONST_HANDLER(51, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE)
64936493
}
64946494

64956495
if (opline->extended_value == IS_ARRAY) {
6496-
if (OP1_TYPE == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) {
6497-
if (Z_TYPE_P(expr) != IS_NULL) {
6498-
ZVAL_ARR(result, zend_new_array(1));
6499-
expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
6500-
if (OP1_TYPE == IS_CONST) {
6501-
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
6502-
} else {
6503-
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
6504-
}
6505-
} else {
6506-
ZVAL_EMPTY_ARRAY(result);
6507-
}
6508-
} else if (ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(expr)) {
6509-
/* Optimized version without rebuilding properties HashTable */
6510-
ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr)));
6511-
} else {
6512-
HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST);
6513-
if (obj_ht) {
6514-
/* fast copy */
6515-
ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht,
6516-
(Z_OBJCE_P(expr)->default_properties_count ||
6517-
Z_OBJ_P(expr)->handlers != &std_object_handlers ||
6518-
GC_IS_RECURSIVE(obj_ht))));
6519-
zend_release_properties(obj_ht);
6520-
} else {
6521-
ZVAL_EMPTY_ARRAY(result);
6522-
}
6523-
}
6496+
zend_cast_zval_to_array(result, expr, OP1_TYPE);
65246497
} else {
65256498
ZEND_ASSERT(opline->extended_value == IS_OBJECT);
65266499
zend_cast_zval_to_object(result, expr, OP1_TYPE);

Zend/zend_vm_execute.h

Lines changed: 4 additions & 112 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)