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:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user