1
0
mirror of https://github.com/php/php-src.git synced 2026-04-01 05:02:27 +02:00

Optimize zend_handle_fetch_obj_flags()

This commit is contained in:
Dmitry Stogov
2019-01-18 01:22:14 +03:00
parent e6182bd4ea
commit 77db3d524e

View File

@@ -2624,50 +2624,7 @@ ZEND_API zend_property_info* ZEND_FASTCALL zend_check_ref_array_assignable(zend_
return i_zend_check_ref_array_assignable(ref);
}
static zend_always_inline zend_bool zend_need_to_handle_fetch_obj_flags(uint32_t flags, zval *ptr) {
return (flags == ZEND_FETCH_REF && Z_TYPE_P(ptr) != IS_REFERENCE)
|| (flags == ZEND_FETCH_DIM_WRITE && promotes_to_array(ptr))
|| (flags == ZEND_FETCH_OBJ_WRITE && promotes_to_object(ptr));
}
static zend_never_inline zend_bool zend_handle_fetch_obj_flags(
zval *result, zval *ptr, zend_property_info *prop_info, uint32_t flags)
{
ZEND_ASSERT(prop_info && prop_info->type);
switch (flags) {
case ZEND_FETCH_DIM_WRITE:
if (!check_type_array_assignable(prop_info->type)) {
zend_throw_auto_init_in_prop_error(prop_info, "array");
if (result) ZVAL_ERROR(result);
return 0;
}
break;
case ZEND_FETCH_OBJ_WRITE:
if (!check_type_stdClass_assignable(prop_info->type)) {
zend_throw_auto_init_in_prop_error(prop_info, "stdClass");
if (result) ZVAL_ERROR(result);
return 0;
}
break;
case ZEND_FETCH_REF:
if (Z_TYPE_P(ptr) == IS_UNDEF) {
if (!ZEND_TYPE_ALLOW_NULL(prop_info->type)) {
zend_throw_access_uninit_prop_by_ref_error(prop_info);
if (result) ZVAL_ERROR(result);
return 0;
}
ZVAL_NULL(ptr);
}
ZVAL_NEW_REF(ptr, ptr);
ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(ptr), prop_info);
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
return 1;
}
static zend_always_inline zend_property_info *zend_object_fetch_property_type_info(
static zend_property_info *zend_object_fetch_property_type_info(
zend_object *obj, zval *slot)
{
if (EXPECTED(!ZEND_CLASS_HAS_TYPE_HINTS(obj->ce))) {
@@ -2683,6 +2640,66 @@ static zend_always_inline zend_property_info *zend_object_fetch_property_type_in
return zend_get_typed_property_info_for_slot(obj, slot);
}
static zend_never_inline zend_bool zend_handle_fetch_obj_flags(
zval *result, zval *ptr, zend_object *obj, zend_property_info *prop_info, uint32_t flags)
{
switch (flags) {
case ZEND_FETCH_DIM_WRITE:
if (promotes_to_array(ptr)) {
if (!prop_info) {
prop_info = zend_object_fetch_property_type_info(obj, ptr);
if (!prop_info) {
break;
}
}
if (!check_type_array_assignable(prop_info->type)) {
zend_throw_auto_init_in_prop_error(prop_info, "array");
if (result) ZVAL_ERROR(result);
return 0;
}
}
break;
case ZEND_FETCH_OBJ_WRITE:
if (promotes_to_object(ptr)) {
if (!prop_info) {
prop_info = zend_object_fetch_property_type_info(obj, ptr);
if (!prop_info) {
break;
}
}
if (!check_type_stdClass_assignable(prop_info->type)) {
zend_throw_auto_init_in_prop_error(prop_info, "stdClass");
if (result) ZVAL_ERROR(result);
return 0;
}
}
break;
case ZEND_FETCH_REF:
if (Z_TYPE_P(ptr) != IS_REFERENCE) {
if (!prop_info) {
prop_info = zend_object_fetch_property_type_info(obj, ptr);
if (!prop_info) {
break;
}
}
if (Z_TYPE_P(ptr) == IS_UNDEF) {
if (!ZEND_TYPE_ALLOW_NULL(prop_info->type)) {
zend_throw_access_uninit_prop_by_ref_error(prop_info);
if (result) ZVAL_ERROR(result);
return 0;
}
ZVAL_NULL(ptr);
}
ZVAL_NEW_REF(ptr, ptr);
ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(ptr), prop_info);
}
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
return 1;
}
static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, uint32_t prop_op_type, void **cache_slot, int type, uint32_t flags, zend_bool init_undef OPLINE_DC)
{
zval *ptr;
@@ -2714,11 +2731,12 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c
if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) {
ptr = OBJ_PROP(zobj, prop_offset);
if (EXPECTED(Z_TYPE_P(ptr) != IS_UNDEF)) {
zend_property_info *prop_info;
ZVAL_INDIRECT(result, ptr);
if (flags && (prop_info = CACHED_PTR_EX(cache_slot + 2)) &&
UNEXPECTED(zend_need_to_handle_fetch_obj_flags(flags, ptr))) {
zend_handle_fetch_obj_flags(result, ptr, prop_info, flags);
if (flags) {
zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2);
if (prop_info) {
zend_handle_fetch_obj_flags(result, ptr, NULL, prop_info, flags);
}
}
return;
}
@@ -2748,11 +2766,20 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c
}
ZVAL_INDIRECT(result, ptr);
if (flags && UNEXPECTED(zend_need_to_handle_fetch_obj_flags(flags, ptr))) {
zend_property_info *prop_info =
zend_object_fetch_property_type_info(Z_OBJ_P(container), ptr);
if (prop_info && !zend_handle_fetch_obj_flags(result, ptr, prop_info, flags)) {
return;
if (flags) {
zend_property_info *prop_info;
if (prop_op_type == IS_CONST) {
prop_info = CACHED_PTR_EX(cache_slot + 2);
if (prop_info) {
if (UNEXPECTED(!zend_handle_fetch_obj_flags(result, ptr, NULL, prop_info, flags))) {
return;
}
}
} else {
if (UNEXPECTED(!zend_handle_fetch_obj_flags(result, ptr, Z_OBJ_P(container), NULL, flags))) {
return;
}
}
}
if (init_undef && UNEXPECTED(Z_TYPE_P(ptr) == IS_UNDEF)) {
@@ -2862,8 +2889,8 @@ static zend_always_inline int zend_fetch_static_property_address(zval **retval,
}
}
if (flags && property_info->type && zend_need_to_handle_fetch_obj_flags(flags, *retval)) {
zend_handle_fetch_obj_flags(NULL, *retval, property_info, flags);
if (flags && property_info->type) {
zend_handle_fetch_obj_flags(NULL, *retval, NULL, property_info, flags);
}
if (prop_info) {