@@ -1345,6 +1345,193 @@ static void ZEND_FASTCALL zend_jit_fetch_obj_is_dynamic(zend_object *zobj, intpt
1345
1345
zend_jit_fetch_obj_is_slow (zobj , offset , result , cache_slot );
1346
1346
}
1347
1347
1348
+ static zend_always_inline zend_bool promotes_to_array (zval * val ) {
1349
+ return Z_TYPE_P (val ) <= IS_FALSE
1350
+ || (Z_ISREF_P (val ) && Z_TYPE_P (Z_REFVAL_P (val )) <= IS_FALSE );
1351
+ }
1352
+
1353
+ static zend_always_inline zend_bool check_type_array_assignable (zend_type type ) {
1354
+ if (!ZEND_TYPE_IS_SET (type )) {
1355
+ return 1 ;
1356
+ }
1357
+ return (ZEND_TYPE_FULL_MASK (type ) & (MAY_BE_ITERABLE |MAY_BE_ARRAY )) != 0 ;
1358
+ }
1359
+
1360
+ static zend_property_info * zend_object_fetch_property_type_info (
1361
+ zend_object * obj , zval * slot )
1362
+ {
1363
+ if (EXPECTED (!ZEND_CLASS_HAS_TYPE_HINTS (obj -> ce ))) {
1364
+ return NULL ;
1365
+ }
1366
+
1367
+ /* Not a declared property */
1368
+ if (UNEXPECTED (slot < obj -> properties_table ||
1369
+ slot >= obj -> properties_table + obj -> ce -> default_properties_count )) {
1370
+ return NULL ;
1371
+ }
1372
+
1373
+ return zend_get_typed_property_info_for_slot (obj , slot );
1374
+ }
1375
+
1376
+ static zend_never_inline ZEND_COLD void zend_throw_auto_init_in_prop_error (zend_property_info * prop , const char * type ) {
1377
+ zend_string * type_str = zend_type_to_string (prop -> type );
1378
+ zend_type_error (
1379
+ "Cannot auto-initialize an %s inside property %s::$%s of type %s" ,
1380
+ type ,
1381
+ ZSTR_VAL (prop -> ce -> name ), zend_get_unmangled_property_name (prop -> name ),
1382
+ ZSTR_VAL (type_str )
1383
+ );
1384
+ zend_string_release (type_str );
1385
+ }
1386
+
1387
+ static zend_never_inline ZEND_COLD void zend_throw_access_uninit_prop_by_ref_error (
1388
+ zend_property_info * prop ) {
1389
+ zend_throw_error (NULL ,
1390
+ "Cannot access uninitialized non-nullable property %s::$%s by reference" ,
1391
+ ZSTR_VAL (prop -> ce -> name ),
1392
+ zend_get_unmangled_property_name (prop -> name ));
1393
+ }
1394
+
1395
+ static zend_never_inline zend_bool zend_handle_fetch_obj_flags (
1396
+ zval * result , zval * ptr , zend_object * obj , zend_property_info * prop_info , uint32_t flags )
1397
+ {
1398
+ switch (flags ) {
1399
+ case ZEND_FETCH_DIM_WRITE :
1400
+ if (promotes_to_array (ptr )) {
1401
+ if (!prop_info ) {
1402
+ prop_info = zend_object_fetch_property_type_info (obj , ptr );
1403
+ if (!prop_info ) {
1404
+ break ;
1405
+ }
1406
+ }
1407
+ if (!check_type_array_assignable (prop_info -> type )) {
1408
+ zend_throw_auto_init_in_prop_error (prop_info , "array" );
1409
+ if (result ) ZVAL_ERROR (result );
1410
+ return 0 ;
1411
+ }
1412
+ }
1413
+ break ;
1414
+ case ZEND_FETCH_REF :
1415
+ if (Z_TYPE_P (ptr ) != IS_REFERENCE ) {
1416
+ if (!prop_info ) {
1417
+ prop_info = zend_object_fetch_property_type_info (obj , ptr );
1418
+ if (!prop_info ) {
1419
+ break ;
1420
+ }
1421
+ }
1422
+ if (Z_TYPE_P (ptr ) == IS_UNDEF ) {
1423
+ if (!ZEND_TYPE_ALLOW_NULL (prop_info -> type )) {
1424
+ zend_throw_access_uninit_prop_by_ref_error (prop_info );
1425
+ if (result ) ZVAL_ERROR (result );
1426
+ return 0 ;
1427
+ }
1428
+ ZVAL_NULL (ptr );
1429
+ }
1430
+
1431
+ ZVAL_NEW_REF (ptr , ptr );
1432
+ ZEND_REF_ADD_TYPE_SOURCE (Z_REF_P (ptr ), prop_info );
1433
+ }
1434
+ break ;
1435
+ EMPTY_SWITCH_DEFAULT_CASE ()
1436
+ }
1437
+ return 1 ;
1438
+ }
1439
+
1440
+ static void ZEND_FASTCALL zend_jit_fetch_obj_w_slow (zend_object * zobj , zval * offset , zval * result , uint32_t cache_slot )
1441
+ {
1442
+ zval * retval ;
1443
+ zend_execute_data * execute_data = EG (current_execute_data );
1444
+ const zend_op * opline = execute_data -> opline ;
1445
+ zend_string * name , * tmp_name ;
1446
+
1447
+ name = zval_get_tmp_string (offset , & tmp_name );
1448
+ retval = zobj -> handlers -> get_property_ptr_ptr (zobj , name , BP_VAR_W , CACHE_ADDR (cache_slot ));
1449
+ if (NULL == retval ) {
1450
+ retval = zobj -> handlers -> read_property (zobj , name , BP_VAR_W , CACHE_ADDR (cache_slot ), result );
1451
+ if (retval == result ) {
1452
+ if (UNEXPECTED (Z_ISREF_P (retval ) && Z_REFCOUNT_P (retval ) == 1 )) {
1453
+ ZVAL_UNREF (retval );
1454
+ }
1455
+ goto end ;
1456
+ }
1457
+ } else if (UNEXPECTED (Z_ISERROR_P (retval ))) {
1458
+ ZVAL_ERROR (result );
1459
+ goto end ;
1460
+ }
1461
+
1462
+ ZVAL_INDIRECT (result , retval );
1463
+
1464
+ /* Support for typed properties */
1465
+ do {
1466
+ uint32_t flags = opline -> extended_value & ZEND_FETCH_OBJ_FLAGS ;
1467
+
1468
+ if (flags ) {
1469
+ zend_property_info * prop_info = NULL ;
1470
+
1471
+ if (opline -> op2_type == IS_CONST ) {
1472
+ prop_info = CACHED_PTR_EX (CACHE_ADDR (cache_slot ) + 2 );
1473
+ if (!prop_info ) {
1474
+ break ;
1475
+ }
1476
+ }
1477
+ if (UNEXPECTED (!zend_handle_fetch_obj_flags (result , retval , zobj , prop_info , flags ))) {
1478
+ goto end ;
1479
+ }
1480
+ }
1481
+ } while (0 );
1482
+
1483
+ if (UNEXPECTED (Z_TYPE_P (retval ) == IS_UNDEF )) {
1484
+ ZVAL_NULL (retval );
1485
+ }
1486
+
1487
+ end :
1488
+ zend_tmp_string_release (tmp_name );
1489
+ }
1490
+
1491
+ static void ZEND_FASTCALL zend_jit_check_array_promotion (zval * val , zend_property_info * prop )
1492
+ {
1493
+ zend_execute_data * execute_data = EG (current_execute_data );
1494
+ const zend_op * opline = execute_data -> opline ;
1495
+ zval * result = EX_VAR (opline -> result .var );
1496
+
1497
+ if (((Z_TYPE_P (val ) <= IS_FALSE
1498
+ || (Z_ISREF_P (val ) && Z_TYPE_P (Z_REFVAL_P (val )) <= IS_FALSE ))
1499
+ && ZEND_TYPE_IS_SET (prop -> type )
1500
+ && ZEND_TYPE_FULL_MASK (prop -> type ) & (MAY_BE_ITERABLE |MAY_BE_ARRAY )) == 0 ) {
1501
+ zend_string * type_str = zend_type_to_string (prop -> type );
1502
+ zend_type_error (
1503
+ "Cannot auto-initialize an array inside property %s::$%s of type %s" ,
1504
+ ZSTR_VAL (prop -> ce -> name ), zend_get_unmangled_property_name (prop -> name ),
1505
+ ZSTR_VAL (type_str )
1506
+ );
1507
+ zend_string_release (type_str );
1508
+ ZVAL_ERROR (result );
1509
+ } else {
1510
+ ZVAL_INDIRECT (result , val );
1511
+ }
1512
+ }
1513
+
1514
+ static void ZEND_FASTCALL zend_jit_create_typed_ref (zval * val , zend_property_info * prop , zval * result )
1515
+ {
1516
+ if (!Z_ISREF_P (val )) {
1517
+ ZVAL_NEW_REF (val , val );
1518
+ ZEND_REF_ADD_TYPE_SOURCE (Z_REF_P (val ), prop );
1519
+ }
1520
+ ZVAL_INDIRECT (result , val );
1521
+ }
1522
+
1523
+ static void ZEND_FASTCALL zend_jit_extract_helper (zend_refcounted * garbage )
1524
+ {
1525
+ zend_execute_data * execute_data = EG (current_execute_data );
1526
+ const zend_op * opline = execute_data -> opline ;
1527
+ zval * zv = EX_VAR (opline -> result .var );
1528
+
1529
+ if (EXPECTED (Z_TYPE_P (zv ) == IS_INDIRECT )) {
1530
+ ZVAL_COPY (zv , Z_INDIRECT_P (zv ));
1531
+ }
1532
+ rc_dtor_func (garbage );
1533
+ }
1534
+
1348
1535
static void ZEND_FASTCALL zend_jit_vm_stack_free_args_helper (zend_execute_data * call )
1349
1536
{
1350
1537
zend_vm_stack_free_args (call );
@@ -1508,6 +1695,13 @@ static void ZEND_FASTCALL zend_jit_invalid_property_read(zval *container, const
1508
1695
zend_error (E_WARNING , "Attempt to read property '%s' on %s" , property_name , zend_zval_type_name (container ));
1509
1696
}
1510
1697
1698
+ static void ZEND_FASTCALL zend_jit_invalid_property_write (zval * container , const char * property_name )
1699
+ {
1700
+ zend_throw_error (NULL ,
1701
+ "Attempt to modify property '%s' on %s" ,
1702
+ property_name , zend_zval_type_name (container ));
1703
+ }
1704
+
1511
1705
static zval * ZEND_FASTCALL zend_jit_prepare_assign_dim_ref (zval * ref ) {
1512
1706
zval * val = Z_REFVAL_P (ref );
1513
1707
if (Z_TYPE_P (val ) <= IS_FALSE ) {
0 commit comments