Skip to content

Commit 182e462

Browse files
committed
Move slow code to C file
1 parent 6e8db20 commit 182e462

2 files changed

Lines changed: 48 additions & 45 deletions

File tree

Zend/zend_execute.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5957,3 +5957,49 @@ ZEND_API void zend_return_unwrap_ref(zend_execute_data *execute_data, zval *retu
59575957

59585958
zend_unwrap_reference(return_value);
59595959
}
5960+
5961+
static zend_always_inline bool zend_has_ctor_for_cpp_reassignment(
5962+
const zend_execute_data *ex, zend_object *obj, zend_string *property_name)
5963+
{
5964+
for (const zend_execute_data *frame = ex; frame != NULL; frame = frame->prev_execute_data) {
5965+
if (!(ZEND_CALL_INFO(frame) & ZEND_CALL_HAS_THIS) || Z_OBJ(frame->This) != obj) {
5966+
return false;
5967+
}
5968+
if (!(frame->func->common.fn_flags & ZEND_ACC_CTOR)) {
5969+
continue;
5970+
}
5971+
5972+
zend_class_entry *scope = frame->func->common.scope;
5973+
ZEND_ASSERT(scope);
5974+
5975+
zend_property_info *scope_prop = (zend_property_info *) zend_hash_find_ptr(&scope->properties_info, property_name);
5976+
ZEND_ASSERT(scope_prop);
5977+
return scope_prop->ce == scope && (scope_prop->flags & (ZEND_ACC_READONLY|ZEND_ACC_PROMOTED)) == (ZEND_ACC_READONLY|ZEND_ACC_PROMOTED);
5978+
}
5979+
5980+
return false;
5981+
}
5982+
5983+
ZEND_API ZEND_COLD zend_property_write_kind zend_verify_readonly_slow(zval *property_val, const zend_property_info *info)
5984+
{
5985+
ZEND_ASSERT(info->flags & ZEND_ACC_READONLY);
5986+
5987+
if (Z_PROP_FLAG_P(property_val) & IS_PROP_REINITABLE) {
5988+
return ZEND_PROPERTY_WRITE_READONLY_REINITABLE;
5989+
}
5990+
if (Z_PROP_FLAG_P(property_val) & IS_PROP_CTOR_REASSIGNED) {
5991+
return ZEND_PROPERTY_WRITE_FORBIDDEN;
5992+
}
5993+
zend_execute_data *execute_data = EG(current_execute_data);
5994+
if (!execute_data || !(EX_CALL_INFO() & ZEND_CALL_HAS_THIS)) {
5995+
return ZEND_PROPERTY_WRITE_FORBIDDEN;
5996+
}
5997+
const zend_op *opline = EX(opline);
5998+
zend_object *obj = zend_get_object_from_slot(property_val, info);
5999+
if (!zend_has_ctor_for_cpp_reassignment(execute_data, obj, info->name)
6000+
|| ((opline->opcode == ZEND_ASSIGN_OBJ || opline->opcode == ZEND_ASSIGN_OBJ_REF)
6001+
&& opline->extended_value & ZEND_ASSIGN_OBJ_PROMOTED_READONLY_INIT)) {
6002+
return ZEND_PROPERTY_WRITE_FORBIDDEN;
6003+
}
6004+
return ZEND_PROPERTY_WRITE_READONLY_CTOR_REASSIGNED;
6005+
}

Zend/zend_execute.h

Lines changed: 2 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -584,65 +584,22 @@ ZEND_API zend_result ZEND_FASTCALL zend_handle_undef_args(zend_execute_data *cal
584584
#define ZEND_CLASS_HAS_TYPE_HINTS(ce) ((bool)(ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS))
585585
#define ZEND_CLASS_HAS_READONLY_PROPS(ce) ((bool)(ce->ce_flags & ZEND_ACC_HAS_READONLY_PROPS))
586586

587-
static zend_always_inline bool zend_has_active_ctor_with_promoted_property(
588-
const zend_execute_data *ex, zend_object *obj, zend_string *property_name)
589-
{
590-
for (const zend_execute_data *frame = ex; frame != NULL; frame = frame->prev_execute_data) {
591-
if (!(ZEND_CALL_INFO(frame) & ZEND_CALL_HAS_THIS) || Z_OBJ(frame->This) != obj) {
592-
return false;
593-
}
594-
if (!(frame->func->common.fn_flags & ZEND_ACC_CTOR)) {
595-
continue;
596-
}
597-
598-
zend_class_entry *scope = frame->func->common.scope;
599-
ZEND_ASSERT(scope);
600-
601-
zend_property_info *scope_prop = (zend_property_info *) zend_hash_find_ptr(&scope->properties_info, property_name);
602-
ZEND_ASSERT(scope_prop);
603-
return scope_prop->ce == scope && (scope_prop->flags & (ZEND_ACC_READONLY|ZEND_ACC_PROMOTED)) == (ZEND_ACC_READONLY|ZEND_ACC_PROMOTED);
604-
}
605-
606-
return false;
607-
}
608-
609587
typedef enum _zend_property_write_kind {
610588
ZEND_PROPERTY_WRITE_FORBIDDEN = 0, /* Write disallowed */
611589
ZEND_PROPERTY_WRITE_OK, /* Write allowed */
612590
ZEND_PROPERTY_WRITE_READONLY_REINITABLE, /* Clone reinit window: clear IS_PROP_REINITABLE after write */
613591
ZEND_PROPERTY_WRITE_READONLY_CTOR_REASSIGNED, /* CPP ctor reassignment: set IS_PROP_CTOR_REASSIGNED after write */
614592
} zend_property_write_kind;
615593

616-
static zend_always_inline zend_property_write_kind zend_get_readonly_write_kind(
617-
const zval *property_val, const zend_property_info *prop_info)
618-
{
619-
if (Z_PROP_FLAG_P(property_val) & IS_PROP_REINITABLE) {
620-
return ZEND_PROPERTY_WRITE_READONLY_REINITABLE;
621-
}
622-
if (Z_PROP_FLAG_P(property_val) & IS_PROP_CTOR_REASSIGNED) {
623-
return ZEND_PROPERTY_WRITE_FORBIDDEN;
624-
}
625-
zend_execute_data *ex = EG(current_execute_data);
626-
if (ex == NULL || !(ZEND_CALL_INFO(ex) & ZEND_CALL_HAS_THIS)) {
627-
return ZEND_PROPERTY_WRITE_FORBIDDEN;
628-
}
629-
zend_object *obj = zend_get_object_from_slot(property_val, prop_info);
630-
if (!zend_has_active_ctor_with_promoted_property(ex, obj, prop_info->name)
631-
|| (ex->opline
632-
&& (ex->opline->opcode == ZEND_ASSIGN_OBJ || ex->opline->opcode == ZEND_ASSIGN_OBJ_REF)
633-
&& (ex->opline->extended_value & ZEND_ASSIGN_OBJ_PROMOTED_READONLY_INIT))) {
634-
return ZEND_PROPERTY_WRITE_FORBIDDEN;
635-
}
636-
return ZEND_PROPERTY_WRITE_READONLY_CTOR_REASSIGNED;
637-
}
594+
ZEND_API ZEND_COLD zend_property_write_kind zend_verify_readonly_slow(zval *property_val, const zend_property_info *info);
638595

639596
static zend_always_inline zend_property_write_kind zend_verify_readonly_and_avis(
640597
zval *property_val, const zend_property_info *info, bool indirect)
641598
{
642599
if (UNEXPECTED(info->flags & (ZEND_ACC_READONLY|ZEND_ACC_PPP_SET_MASK))) {
643600
zend_property_write_kind prop_write_kind = ZEND_PROPERTY_WRITE_OK;
644601
if ((info->flags & ZEND_ACC_READONLY) && !Z_ISUNDEF_P(property_val)) {
645-
prop_write_kind = zend_get_readonly_write_kind(property_val, info);
602+
prop_write_kind = zend_verify_readonly_slow(property_val, info);
646603
if (prop_write_kind == ZEND_PROPERTY_WRITE_FORBIDDEN) {
647604
zend_readonly_property_modification_error(info);
648605
return ZEND_PROPERTY_WRITE_FORBIDDEN;

0 commit comments

Comments
 (0)