@@ -633,6 +633,24 @@ static int zend_add_class_name_literal(zend_string *name) /* {{{ */
633633}
634634/* }}} */
635635
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+
636654static int zend_add_const_name_literal (zend_string * name , bool unqualified ) /* {{{ */
637655{
638656 zend_string * tmp_name ;
@@ -1517,6 +1535,105 @@ zend_string *zend_type_to_string_resolved(zend_type type, const zend_class_entry
15171535 return zend_type_to_string_impl (type , scope , 1 );
15181536}
15191537
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+
15201637static bool is_generator_compatible_class_type (zend_string * name ) {
15211638 return zend_string_equals_ci (name , ZSTR_KNOWN (ZEND_STR_TRAVERSABLE ))
15221639 || zend_string_equals_literal_ci (name , "Iterator" )
@@ -1780,13 +1897,27 @@ static zend_name_reference *zend_compile_name_reference(
17801897 size_t alloc_size = ZEND_CLASS_REF_SIZE (num_types );
17811898 zend_name_reference * ref = zend_arena_alloc (& CG (arena ), alloc_size );
17821899 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 , '<' );
17851909 for (uint32_t i = 0 ; i < num_types ; i ++ ) {
1910+ if (i != 0 ) {
1911+ smart_str_appendc (& key , ',' );
1912+ }
17861913 zend_ast * type_ast = list -> child [i ];
17871914 ref -> args .types [i ] = zend_compile_typename (type_ast );
1915+ zend_type_to_key_impl (& key , ref -> args .types [i ]);
17881916 }
1917+ smart_str_appendc (& key , '>' );
1918+ ref -> key = zend_new_interned_string (smart_str_extract (& key ));
17891919 }
1920+ ref -> args .num_types = num_types ;
17901921 return ref ;
17911922}
17921923
@@ -4999,10 +5130,14 @@ static void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
49995130 zend_compile_class_ref_ex (& class_node , class_ast , ZEND_FETCH_CLASS_EXCEPTION );
50005131 }
50015132
5002- opline = zend_emit_op (result , ZEND_NEW , & class_node , NULL );
5133+ opline = zend_emit_op (result , ZEND_NEW , NULL , NULL );
50035134
50045135 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 ));
50055138 opline -> op2 .num = zend_alloc_cache_slot ();
5139+ } else {
5140+ SET_NODE (opline -> op1 , & class_node );
50065141 }
50075142
50085143 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)
82708405 }
82718406}
82728407
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 ) {
82748409 zend_class_reference * ref = (zend_class_reference * ) ptr ;
82758410 zend_class_entry * ce = (zend_class_entry * ) ((char * ) ptr + ZEND_CLASS_ENTRY_HEADER_SIZE );
82768411 ref -> ce = ce ;
8412+ ref -> key = key ;
82778413 ref -> args .num_types = 0 ;
82788414 return ce ;
82798415}
@@ -8287,7 +8423,6 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
82878423 zend_string * name , * lcname ;
82888424 void * ce_ref = zend_arena_alloc (& CG (arena ),
82898425 sizeof (zend_class_entry ) + ZEND_CLASS_ENTRY_HEADER_SIZE );
8290- zend_class_entry * ce = zend_init_class_entry_header (ce_ref );
82918426 zend_op * opline ;
82928427
82938428 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)
83278462 }
83288463 lcname = zend_new_interned_string (lcname );
83298464
8465+ zend_class_entry * ce = zend_init_class_entry_header (ce_ref , lcname );
8466+
83308467 ce -> type = ZEND_USER_CLASS ;
83318468 ce -> name = name ;
83328469 zend_initialize_class_data (ce , 1 );
@@ -8361,6 +8498,11 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
83618498 if (generic_params_ast ) {
83628499 zend_compile_generic_params (generic_params_ast );
83638500 }
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+ }
83648506 }
83658507
83668508 if (extends_ast ) {
0 commit comments