@@ -1213,39 +1213,147 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */
1213
1213
}
1214
1214
/* }}} */
1215
1215
1216
+ static zend_class_mutable_data * zend_allocate_mutable_data (zend_class_entry * class_type ) /* {{{ */
1217
+ {
1218
+ zend_class_mutable_data * mutable_data ;
1219
+
1220
+ ZEND_ASSERT (class_type -> ce_flags & ZEND_ACC_IMMUTABLE );
1221
+ ZEND_ASSERT (ZEND_MAP_PTR (class_type -> mutable_data ) != NULL );
1222
+ ZEND_ASSERT (ZEND_MAP_PTR_GET_IMM (class_type -> mutable_data ) == NULL );
1223
+
1224
+ mutable_data = zend_arena_alloc (& CG (arena ), sizeof (zend_class_mutable_data ));
1225
+ memset (mutable_data , 0 , sizeof (zend_class_mutable_data ));
1226
+ mutable_data -> ce_flags = class_type -> ce_flags ;
1227
+ ZEND_MAP_PTR_SET_IMM (class_type -> mutable_data , mutable_data );
1228
+
1229
+ return mutable_data ;
1230
+ }
1231
+ /* }}} */
1232
+
1233
+ ZEND_API HashTable * zend_separate_class_constants_table (zend_class_entry * class_type ) /* {{{ */
1234
+ {
1235
+ zend_class_mutable_data * mutable_data ;
1236
+ HashTable * constants_table ;
1237
+ zend_string * key ;
1238
+ zend_class_constant * new_c , * c ;
1239
+
1240
+ constants_table = zend_arena_alloc (& CG (arena ), sizeof (HashTable ));
1241
+ zend_hash_init (constants_table , zend_hash_num_elements (& class_type -> constants_table ), NULL , NULL , 0 );
1242
+ zend_hash_extend (constants_table , zend_hash_num_elements (& class_type -> constants_table ), 0 );
1243
+
1244
+ ZEND_HASH_FOREACH_STR_KEY_PTR (& class_type -> constants_table , key , c ) {
1245
+ if (Z_TYPE (c -> value ) == IS_CONSTANT_AST ) {
1246
+ new_c = zend_arena_alloc (& CG (arena ), sizeof (zend_class_constant ));
1247
+ memcpy (new_c , c , sizeof (zend_class_constant ));
1248
+ c = new_c ;
1249
+ }
1250
+ _zend_hash_append_ptr (constants_table , key , c );
1251
+ } ZEND_HASH_FOREACH_END ();
1252
+
1253
+ ZEND_ASSERT (class_type -> ce_flags & ZEND_ACC_IMMUTABLE );
1254
+ ZEND_ASSERT (ZEND_MAP_PTR (class_type -> mutable_data ) != NULL );
1255
+
1256
+ mutable_data = ZEND_MAP_PTR_GET_IMM (class_type -> mutable_data );
1257
+ if (!mutable_data ) {
1258
+ mutable_data = zend_allocate_mutable_data (class_type );
1259
+ }
1260
+
1261
+ mutable_data -> constants_table = constants_table ;
1262
+
1263
+ return constants_table ;
1264
+ }
1265
+
1216
1266
ZEND_API zend_result zend_update_class_constants (zend_class_entry * class_type ) /* {{{ */
1217
1267
{
1218
- if (!(class_type -> ce_flags & ZEND_ACC_CONSTANTS_UPDATED )) {
1219
- zend_class_constant * c ;
1220
- zval * val ;
1221
- zend_property_info * prop_info ;
1268
+ zend_class_mutable_data * mutable_data = NULL ;
1269
+ zval * default_properties_table = NULL ;
1270
+ zval * static_members_table = NULL ;
1271
+ zend_class_constant * c ;
1272
+ zval * val ;
1273
+ zend_property_info * prop_info ;
1274
+ uint32_t ce_flags ;
1222
1275
1223
- if (class_type -> parent ) {
1224
- if (UNEXPECTED (zend_update_class_constants (class_type -> parent ) != SUCCESS )) {
1225
- return FAILURE ;
1276
+ ce_flags = class_type -> ce_flags ;
1277
+
1278
+ if (ce_flags & ZEND_ACC_CONSTANTS_UPDATED ) {
1279
+ return SUCCESS ;
1280
+ }
1281
+
1282
+ if (ce_flags & ZEND_ACC_IMMUTABLE ) {
1283
+ mutable_data = ZEND_MAP_PTR_GET_IMM (class_type -> mutable_data );
1284
+ if (mutable_data ) {
1285
+ ce_flags = mutable_data -> ce_flags ;
1286
+ if (ce_flags & ZEND_ACC_CONSTANTS_UPDATED ) {
1287
+ return SUCCESS ;
1226
1288
}
1289
+ } else {
1290
+ mutable_data = zend_allocate_mutable_data (class_type );
1227
1291
}
1292
+ }
1228
1293
1229
- ZEND_HASH_FOREACH_PTR (& class_type -> constants_table , c ) {
1230
- val = & c -> value ;
1231
- if (Z_TYPE_P (val ) == IS_CONSTANT_AST ) {
1294
+ if (class_type -> parent ) {
1295
+ if (UNEXPECTED (zend_update_class_constants (class_type -> parent ) != SUCCESS )) {
1296
+ return FAILURE ;
1297
+ }
1298
+ }
1299
+
1300
+ if (ce_flags & ZEND_ACC_HAS_AST_CONSTANTS ) {
1301
+ HashTable * constants_table ;
1302
+
1303
+ if (ce_flags & ZEND_ACC_IMMUTABLE ) {
1304
+ constants_table = mutable_data -> constants_table ;
1305
+ if (!constants_table ) {
1306
+ constants_table = zend_separate_class_constants_table (class_type );
1307
+ }
1308
+ } else {
1309
+ constants_table = & class_type -> constants_table ;
1310
+ }
1311
+ ZEND_HASH_FOREACH_PTR (constants_table , c ) {
1312
+ if (Z_TYPE (c -> value ) == IS_CONSTANT_AST ) {
1313
+ val = & c -> value ;
1232
1314
if (UNEXPECTED (zval_update_constant_ex (val , c -> ce ) != SUCCESS )) {
1233
1315
return FAILURE ;
1234
1316
}
1235
1317
}
1236
1318
} ZEND_HASH_FOREACH_END ();
1319
+ }
1237
1320
1238
- if (class_type -> default_static_members_count && !CE_STATIC_MEMBERS (class_type )) {
1239
- if (class_type -> type == ZEND_INTERNAL_CLASS || (class_type -> ce_flags & (ZEND_ACC_IMMUTABLE |ZEND_ACC_PRELOADED ))) {
1321
+ if (class_type -> default_static_members_count ) {
1322
+ static_members_table = CE_STATIC_MEMBERS (class_type );
1323
+ if (!static_members_table ) {
1324
+ if (class_type -> type == ZEND_INTERNAL_CLASS || (ce_flags & (ZEND_ACC_IMMUTABLE |ZEND_ACC_PRELOADED ))) {
1240
1325
zend_class_init_statics (class_type );
1326
+ static_members_table = CE_STATIC_MEMBERS (class_type );
1241
1327
}
1242
1328
}
1329
+ }
1330
+
1331
+ default_properties_table = class_type -> default_properties_table ;
1332
+ if ((ce_flags & ZEND_ACC_IMMUTABLE )
1333
+ && (ce_flags & ZEND_ACC_HAS_AST_PROPERTIES )) {
1334
+ zval * src , * dst , * end ;
1335
+
1336
+ default_properties_table = mutable_data -> default_properties_table ;
1337
+ if (!default_properties_table ) {
1338
+ default_properties_table = zend_arena_alloc (& CG (arena ), sizeof (zval ) * class_type -> default_properties_count );
1339
+ src = class_type -> default_properties_table ;
1340
+ dst = default_properties_table ;
1341
+ end = dst + class_type -> default_properties_count ;
1342
+ do {
1343
+ ZVAL_COPY_VALUE_PROP (dst , src );
1344
+ src ++ ;
1345
+ dst ++ ;
1346
+ } while (dst != end );
1347
+ mutable_data -> default_properties_table = default_properties_table ;
1348
+ }
1349
+ }
1243
1350
1351
+ if (ce_flags & (ZEND_ACC_HAS_AST_PROPERTIES |ZEND_ACC_HAS_AST_STATICS )) {
1244
1352
ZEND_HASH_FOREACH_PTR (& class_type -> properties_info , prop_info ) {
1245
1353
if (prop_info -> flags & ZEND_ACC_STATIC ) {
1246
- val = CE_STATIC_MEMBERS ( class_type ) + prop_info -> offset ;
1354
+ val = static_members_table + prop_info -> offset ;
1247
1355
} else {
1248
- val = (zval * )((char * )class_type -> default_properties_table + prop_info -> offset - OBJ_PROP_TO_OFFSET (0 ));
1356
+ val = (zval * )((char * )default_properties_table + prop_info -> offset - OBJ_PROP_TO_OFFSET (0 ));
1249
1357
}
1250
1358
if (Z_TYPE_P (val ) == IS_CONSTANT_AST ) {
1251
1359
if (ZEND_TYPE_IS_SET (prop_info -> type )) {
@@ -1268,8 +1376,21 @@ ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type) /
1268
1376
}
1269
1377
}
1270
1378
} ZEND_HASH_FOREACH_END ();
1379
+ }
1271
1380
1272
- class_type -> ce_flags |= ZEND_ACC_CONSTANTS_UPDATED ;
1381
+ ce_flags |= ZEND_ACC_CONSTANTS_UPDATED ;
1382
+ ce_flags &= ~ZEND_ACC_HAS_AST_CONSTANTS ;
1383
+ ce_flags &= ~ZEND_ACC_HAS_AST_PROPERTIES ;
1384
+ if (class_type -> ce_flags & ZEND_ACC_IMMUTABLE ) {
1385
+ ce_flags &= ~ZEND_ACC_HAS_AST_STATICS ;
1386
+ if (mutable_data ) {
1387
+ mutable_data -> ce_flags = ce_flags ;
1388
+ }
1389
+ } else {
1390
+ if (!(ce_flags & ZEND_ACC_PRELOADED )) {
1391
+ ce_flags &= ~ZEND_ACC_HAS_AST_STATICS ;
1392
+ }
1393
+ class_type -> ce_flags = ce_flags ;
1273
1394
}
1274
1395
1275
1396
return SUCCESS ;
@@ -1279,7 +1400,7 @@ ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type) /
1279
1400
static zend_always_inline void _object_properties_init (zend_object * object , zend_class_entry * class_type ) /* {{{ */
1280
1401
{
1281
1402
if (class_type -> default_properties_count ) {
1282
- zval * src = class_type -> default_properties_table ;
1403
+ zval * src = CE_DEFAULT_PROPERTIES_TABLE ( class_type ) ;
1283
1404
zval * dst = object -> properties_table ;
1284
1405
zval * end = src + class_type -> default_properties_count ;
1285
1406
@@ -3809,6 +3930,11 @@ ZEND_API zend_property_info *zend_declare_typed_property(zend_class_entry *ce, z
3809
3930
property_info = zend_arena_alloc (& CG (arena ), sizeof (zend_property_info ));
3810
3931
if (Z_TYPE_P (property ) == IS_CONSTANT_AST ) {
3811
3932
ce -> ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED ;
3933
+ if (access_type & ZEND_ACC_STATIC ) {
3934
+ ce -> ce_flags |= ZEND_ACC_HAS_AST_STATICS ;
3935
+ } else {
3936
+ ce -> ce_flags |= ZEND_ACC_HAS_AST_PROPERTIES ;
3937
+ }
3812
3938
}
3813
3939
}
3814
3940
@@ -4124,6 +4250,7 @@ ZEND_API zend_class_constant *zend_declare_class_constant_ex(zend_class_entry *c
4124
4250
c -> ce = ce ;
4125
4251
if (Z_TYPE_P (value ) == IS_CONSTANT_AST ) {
4126
4252
ce -> ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED ;
4253
+ ce -> ce_flags |= ZEND_ACC_HAS_AST_CONSTANTS ;
4127
4254
}
4128
4255
4129
4256
if (!zend_hash_add_ptr (& ce -> constants_table , name , c )) {
0 commit comments