@@ -1041,6 +1041,19 @@ ZEND_VM_HANDLER(28, ZEND_ASSIGN_OBJ_OP, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, OP)
10411041ZEND_VM_C_LABEL (assign_op_object ):
10421042 /* here we are sure we are dealing with an object */
10431043 zobj = Z_OBJ_P (object );
1044+
1045+ // if this is a data class, we may need to CoW
1046+ if (zobj -> ce -> ce_flags & ZEND_ACC_DATA_CLASS ) {
1047+ if (GC_REFCOUNT (zobj ) > 1 ) {
1048+ // clone the object
1049+ zend_object * new_obj = zend_objects_clone_obj (zobj );
1050+ // set the object zval to the new object
1051+ ZVAL_OBJ (object , new_obj );
1052+ GC_DELREF (zobj );
1053+ zobj = new_obj ;
1054+ }
1055+ }
1056+
10441057 if (OP2_TYPE == IS_CONST ) {
10451058 name = Z_STR_P (property );
10461059 } else {
@@ -1310,6 +1323,19 @@ ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACH
13101323ZEND_VM_C_LABEL (pre_incdec_object ):
13111324 /* here we are sure we are dealing with an object */
13121325 zobj = Z_OBJ_P (object );
1326+
1327+ // if this is a data class, we may need to CoW
1328+ if (zobj -> ce -> ce_flags & ZEND_ACC_DATA_CLASS ) {
1329+ if (GC_REFCOUNT (zobj ) > 1 ) {
1330+ // clone the object
1331+ zend_object * new_obj = zend_objects_clone_obj (zobj );
1332+ // set the object zval to the new object
1333+ ZVAL_OBJ (object , new_obj );
1334+ GC_DELREF (zobj );
1335+ zobj = new_obj ;
1336+ }
1337+ }
1338+
13131339 if (OP2_TYPE == IS_CONST ) {
13141340 name = Z_STR_P (property );
13151341 } else {
@@ -1380,6 +1406,19 @@ ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CAC
13801406ZEND_VM_C_LABEL (post_incdec_object ):
13811407 /* here we are sure we are dealing with an object */
13821408 zobj = Z_OBJ_P (object );
1409+
1410+ // if this is a data class, we may need to CoW
1411+ if (zobj -> ce -> ce_flags & ZEND_ACC_DATA_CLASS ) {
1412+ if (GC_REFCOUNT (zobj ) > 1 ) {
1413+ // clone the object
1414+ zend_object * new_obj = zend_objects_clone_obj (zobj );
1415+ // set the object zval to the new object
1416+ ZVAL_OBJ (object , new_obj );
1417+ GC_DELREF (zobj );
1418+ zobj = new_obj ;
1419+ }
1420+ }
1421+
13831422 if (OP2_TYPE == IS_CONST ) {
13841423 name = Z_STR_P (property );
13851424 } else {
@@ -2560,6 +2599,22 @@ ZEND_VM_C_LABEL(fast_assign_obj):
25602599 ZVAL_DEREF (value );
25612600 }
25622601
2602+ // if this is a data class, we may need to CoW
2603+ if (zobj -> ce -> ce_flags & ZEND_ACC_DATA_CLASS ) {
2604+ // skip if in a constructor
2605+ if (EX (func )-> common .fn_flags & ZEND_ACC_CTOR ) {
2606+ // skip
2607+ } else
2608+ if (GC_REFCOUNT (zobj ) > 1 ) {
2609+ // clone the object
2610+ zend_object * new_obj = zend_objects_clone_obj (zobj );
2611+ // set the object zval to the new object
2612+ ZVAL_OBJ (object , new_obj );
2613+ GC_DELREF (zobj );
2614+ zobj = new_obj ;
2615+ }
2616+ }
2617+
25632618 value = zobj -> handlers -> write_property (zobj , name , value , (OP2_TYPE == IS_CONST ) ? CACHE_ADDR (opline -> extended_value ) : NULL );
25642619
25652620 if (OP2_TYPE != IS_CONST ) {
0 commit comments