@@ -633,6 +633,24 @@ static int zend_add_class_name_literal(zend_string *name) /* {{{ */
633
633
}
634
634
/* }}} */
635
635
636
+ static int zend_add_pnr_literal (zend_packed_name_reference pnr ) /* {{{ */
637
+ {
638
+ zend_string * name = ZEND_PNR_GET_NAME (pnr );
639
+
640
+ zval zpnr ;
641
+ ZVAL_PNR (& zpnr , pnr );
642
+
643
+ /* Original PNR */
644
+ int ret = zend_add_literal (& zpnr );
645
+
646
+ /* Lowercased name */
647
+ zend_string * lc_name = zend_string_tolower (name );
648
+ zend_add_literal_string (& lc_name );
649
+
650
+ return ret ;
651
+ }
652
+ /* }}} */
653
+
636
654
static int zend_add_const_name_literal (zend_string * name , bool unqualified ) /* {{{ */
637
655
{
638
656
zend_string * tmp_name ;
@@ -1517,6 +1535,105 @@ zend_string *zend_type_to_string_resolved(zend_type type, const zend_class_entry
1517
1535
return zend_type_to_string_impl (type , scope , 1 );
1518
1536
}
1519
1537
1538
+ #define zend_type_to_key_append_separator () \
1539
+ if (smart_str_get_len(key) != orig_len) { \
1540
+ smart_str_appendc(key, '|'); \
1541
+ }
1542
+
1543
+ static void zend_type_to_key_impl (smart_str * key , zend_type type ) {
1544
+ size_t orig_len = smart_str_get_len (key );
1545
+
1546
+ if (ZEND_TYPE_IS_INTERSECTION (type )) {
1547
+ zend_type * list_type ;
1548
+ ZEND_TYPE_LIST_FOREACH (ZEND_TYPE_LIST (type ), list_type ) {
1549
+ smart_str_appendc (key , '&' );
1550
+ zend_type_to_key_impl (key , * list_type );
1551
+ } ZEND_TYPE_LIST_FOREACH_END ();
1552
+ ZEND_ASSERT (!ZEND_TYPE_PURE_MASK (type ));
1553
+ return ;
1554
+ } else if (ZEND_TYPE_HAS_LIST (type )) {
1555
+ /* A union type might not be a list */
1556
+ zend_type * list_type ;
1557
+ ZEND_TYPE_LIST_FOREACH (ZEND_TYPE_LIST (type ), list_type ) {
1558
+ smart_str_appendc (key , '|' );
1559
+ zend_type_to_key_impl (key , * list_type );
1560
+ } ZEND_TYPE_LIST_FOREACH_END ();
1561
+ } else if (ZEND_TYPE_HAS_PNR (type )) {
1562
+ zend_packed_name_reference pnr = ZEND_TYPE_PNR (type );
1563
+ if (ZEND_PNR_IS_SIMPLE (pnr )) {
1564
+ zend_string * lcname = zend_string_tolower (ZEND_PNR_SIMPLE_GET_NAME (pnr ));
1565
+ smart_str_append (key , lcname );
1566
+ zend_string_release (lcname );
1567
+ } else {
1568
+ smart_str_append (key , ZEND_PNR_COMPLEX_GET_KEY (pnr ));
1569
+ }
1570
+ } else if (ZEND_TYPE_HAS_CLASS_REF (type )) {
1571
+ zend_class_reference * ce_ref = ZEND_TYPE_CLASS_REF (type );
1572
+ smart_str_append (key , ce_ref -> key );
1573
+ } else if (ZEND_TYPE_HAS_GENERIC_PARAM (type )) {
1574
+ uint32_t generic_param_id = ZEND_TYPE_GENERIC_PARAM_ID (type );
1575
+ smart_str_appendc (key , 0 );
1576
+ smart_str_appendl (key , (char * )& generic_param_id , sizeof (generic_param_id ));
1577
+ }
1578
+
1579
+ uint32_t type_mask = ZEND_TYPE_PURE_MASK (type );
1580
+
1581
+ if (type_mask == MAY_BE_ANY ) {
1582
+ smart_str_setl (key , ZSTR_VAL (ZSTR_KNOWN (ZEND_STR_MIXED )), ZSTR_LEN (ZSTR_KNOWN (ZEND_STR_MIXED )));
1583
+ return ;
1584
+ }
1585
+ if (type_mask & MAY_BE_STATIC ) {
1586
+ ZEND_ASSERT (0 && "Unsupported yet" );
1587
+ }
1588
+ if (type_mask & MAY_BE_CALLABLE ) {
1589
+ zend_type_to_key_append_separator ();
1590
+ smart_str_append (key , ZSTR_KNOWN (ZEND_STR_CALLABLE ));
1591
+ }
1592
+ if (type_mask & MAY_BE_OBJECT ) {
1593
+ zend_type_to_key_append_separator ();
1594
+ smart_str_append (key , ZSTR_KNOWN (ZEND_STR_OBJECT ));
1595
+ }
1596
+ if (type_mask & MAY_BE_ARRAY ) {
1597
+ zend_type_to_key_append_separator ();
1598
+ smart_str_append (key , ZSTR_KNOWN (ZEND_STR_ARRAY ));
1599
+ }
1600
+ if (type_mask & MAY_BE_STRING ) {
1601
+ zend_type_to_key_append_separator ();
1602
+ smart_str_append (key , ZSTR_KNOWN (ZEND_STR_STRING ));
1603
+ }
1604
+ if (type_mask & MAY_BE_LONG ) {
1605
+ zend_type_to_key_append_separator ();
1606
+ smart_str_append (key , ZSTR_KNOWN (ZEND_STR_INT ));
1607
+ }
1608
+ if (type_mask & MAY_BE_DOUBLE ) {
1609
+ zend_type_to_key_append_separator ();
1610
+ smart_str_append (key , ZSTR_KNOWN (ZEND_STR_FLOAT ));
1611
+ }
1612
+ if ((type_mask & MAY_BE_BOOL ) == MAY_BE_BOOL ) {
1613
+ zend_type_to_key_append_separator ();
1614
+ smart_str_append (key , ZSTR_KNOWN (ZEND_STR_BOOL ));
1615
+ } else if (type_mask & MAY_BE_FALSE ) {
1616
+ zend_type_to_key_append_separator ();
1617
+ smart_str_append (key , ZSTR_KNOWN (ZEND_STR_FALSE ));
1618
+ } else if (type_mask & MAY_BE_TRUE ) {
1619
+ zend_type_to_key_append_separator ();
1620
+ smart_str_append (key , ZSTR_KNOWN (ZEND_STR_TRUE ));
1621
+ }
1622
+ if (type_mask & MAY_BE_VOID ) {
1623
+ zend_type_to_key_append_separator ();
1624
+ smart_str_append (key , ZSTR_KNOWN (ZEND_STR_VOID ));
1625
+ }
1626
+ if (type_mask & MAY_BE_NEVER ) {
1627
+ zend_type_to_key_append_separator ();
1628
+ smart_str_append (key , ZSTR_KNOWN (ZEND_STR_NEVER ));
1629
+ }
1630
+
1631
+ if (type_mask & MAY_BE_NULL ) {
1632
+ zend_type_to_key_append_separator ();
1633
+ smart_str_append (key , ZSTR_KNOWN (ZEND_STR_NULL_LOWERCASE ));
1634
+ }
1635
+ }
1636
+
1520
1637
static bool is_generator_compatible_class_type (zend_string * name ) {
1521
1638
return zend_string_equals_ci (name , ZSTR_KNOWN (ZEND_STR_TRAVERSABLE ))
1522
1639
|| zend_string_equals_literal_ci (name , "Iterator" )
@@ -1780,13 +1897,27 @@ static zend_name_reference *zend_compile_name_reference(
1780
1897
size_t alloc_size = ZEND_CLASS_REF_SIZE (num_types );
1781
1898
zend_name_reference * ref = zend_arena_alloc (& CG (arena ), alloc_size );
1782
1899
ref -> name = name ;
1783
- ref -> args .num_types = num_types ;
1784
- if (list ) {
1900
+ if (num_types == 0 ) {
1901
+ ref -> key = zend_new_interned_string (zend_string_tolower (name ));
1902
+ } else {
1903
+ ZEND_ASSERT (list );
1904
+ smart_str key = {0 };
1905
+ zend_string * lcname = zend_string_tolower (name );
1906
+ smart_str_append (& key , lcname );
1907
+ zend_string_release (lcname );
1908
+ smart_str_appendc (& key , '<' );
1785
1909
for (uint32_t i = 0 ; i < num_types ; i ++ ) {
1910
+ if (i != 0 ) {
1911
+ smart_str_appendc (& key , ',' );
1912
+ }
1786
1913
zend_ast * type_ast = list -> child [i ];
1787
1914
ref -> args .types [i ] = zend_compile_typename (type_ast );
1915
+ zend_type_to_key_impl (& key , ref -> args .types [i ]);
1788
1916
}
1917
+ smart_str_appendc (& key , '>' );
1918
+ ref -> key = zend_new_interned_string (smart_str_extract (& key ));
1789
1919
}
1920
+ ref -> args .num_types = num_types ;
1790
1921
return ref ;
1791
1922
}
1792
1923
@@ -4999,10 +5130,14 @@ static void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
4999
5130
zend_compile_class_ref_ex (& class_node , class_ast , ZEND_FETCH_CLASS_EXCEPTION );
5000
5131
}
5001
5132
5002
- opline = zend_emit_op (result , ZEND_NEW , & class_node , NULL );
5133
+ opline = zend_emit_op (result , ZEND_NEW , NULL , NULL );
5003
5134
5004
5135
if (class_node .op_type == IS_CONST ) {
5136
+ opline -> op1_type = IS_CONST ;
5137
+ opline -> op1 .constant = zend_add_pnr_literal (Z_PNR (class_node .u .constant ));
5005
5138
opline -> op2 .num = zend_alloc_cache_slot ();
5139
+ } else {
5140
+ SET_NODE (opline -> op1 , & class_node );
5006
5141
}
5007
5142
5008
5143
zend_compile_call_common (& ctor_result , args_ast , NULL , ast -> lineno );
@@ -8270,10 +8405,11 @@ static void zend_compile_generic_params(zend_ast *params_ast)
8270
8405
}
8271
8406
}
8272
8407
8273
- zend_class_entry * zend_init_class_entry_header (zend_class_entry_storage * ptr ) {
8408
+ zend_class_entry * zend_init_class_entry_header (zend_class_entry_storage * ptr , zend_string * key ) {
8274
8409
zend_class_reference * ref = (zend_class_reference * ) ptr ;
8275
8410
zend_class_entry * ce = (zend_class_entry * ) ((char * ) ptr + ZEND_CLASS_ENTRY_HEADER_SIZE );
8276
8411
ref -> ce = ce ;
8412
+ ref -> key = key ;
8277
8413
ref -> args .num_types = 0 ;
8278
8414
return ce ;
8279
8415
}
@@ -8287,7 +8423,6 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
8287
8423
zend_string * name , * lcname ;
8288
8424
void * ce_ref = zend_arena_alloc (& CG (arena ),
8289
8425
sizeof (zend_class_entry ) + ZEND_CLASS_ENTRY_HEADER_SIZE );
8290
- zend_class_entry * ce = zend_init_class_entry_header (ce_ref );
8291
8426
zend_op * opline ;
8292
8427
8293
8428
zend_class_entry * original_ce = CG (active_class_entry );
@@ -8327,6 +8462,8 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
8327
8462
}
8328
8463
lcname = zend_new_interned_string (lcname );
8329
8464
8465
+ zend_class_entry * ce = zend_init_class_entry_header (ce_ref , lcname );
8466
+
8330
8467
ce -> type = ZEND_USER_CLASS ;
8331
8468
ce -> name = name ;
8332
8469
zend_initialize_class_data (ce , 1 );
@@ -8361,6 +8498,11 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
8361
8498
if (generic_params_ast ) {
8362
8499
zend_compile_generic_params (generic_params_ast );
8363
8500
}
8501
+
8502
+ if (!(decl -> flags & ZEND_ACC_ANON_CLASS ) &&
8503
+ ce -> num_generic_params > 0 && ce -> num_required_generic_params == 0 ) {
8504
+ zend_alloc_ce_cache (ZEND_CE_TO_REF (ce )-> key );
8505
+ }
8364
8506
}
8365
8507
8366
8508
if (extends_ast ) {
0 commit comments