2222#include "zend_globals.h"
2323
2424ZEND_API zend_string * (* zend_new_interned_string )(zend_string * str );
25+ ZEND_API zend_string * (* zend_string_init_interned )(const char * str , size_t size , int permanent );
2526
2627static zend_string * zend_new_interned_string_permanent (zend_string * str );
2728static zend_string * zend_new_interned_string_request (zend_string * str );
29+ static zend_string * zend_string_init_interned_permanent (const char * str , size_t size , int permanent );
30+ static zend_string * zend_string_init_interned_request (const char * str , size_t size , int permanent );
2831
2932/* Any strings interned in the startup phase. Common to all the threads,
3033 won't be free'd until process exit. If we want an ability to
@@ -33,6 +36,7 @@ static zend_string *zend_new_interned_string_request(zend_string *str);
3336static HashTable interned_strings_permanent ;
3437
3538static zend_new_interned_string_func_t interned_string_request_handler = zend_new_interned_string_request ;
39+ static zend_string_init_interned_func_t interned_string_init_request_handler = zend_string_init_interned_request ;
3640static zend_string_copy_storage_func_t interned_string_copy_storage = NULL ;
3741
3842ZEND_API zend_string * zend_empty_string = NULL ;
@@ -72,6 +76,7 @@ ZEND_API void zend_interned_strings_init(void)
7276 zend_init_interned_strings_ht (& interned_strings_permanent , 1 );
7377
7478 zend_new_interned_string = zend_new_interned_string_permanent ;
79+ zend_string_init_interned = zend_string_init_interned_permanent ;
7580
7681 /* interned empty string */
7782 str = zend_string_alloc (sizeof ("" )- 1 , 1 );
@@ -100,20 +105,18 @@ ZEND_API void zend_interned_strings_dtor(void)
100105 zend_known_strings = NULL ;
101106}
102107
103- static zend_always_inline zend_string * zend_interned_string_ht_lookup ( zend_string * str , HashTable * interned_strings )
108+ static zend_always_inline zend_string * zend_interned_string_ht_lookup_ex ( zend_ulong h , const char * str , size_t size , HashTable * interned_strings )
104109{
105- zend_ulong h ;
106110 uint32_t nIndex ;
107111 uint32_t idx ;
108112 Bucket * p ;
109113
110- h = zend_string_hash_val (str );
111114 nIndex = h | interned_strings -> nTableMask ;
112115 idx = HT_HASH (interned_strings , nIndex );
113116 while (idx != HT_INVALID_IDX ) {
114117 p = HT_HASH_TO_BUCKET (interned_strings , idx );
115- if ((p -> h == h ) && (ZSTR_LEN (p -> key ) == ZSTR_LEN ( str ) )) {
116- if (!memcmp (ZSTR_VAL (p -> key ), ZSTR_VAL ( str ), ZSTR_LEN ( str ) )) {
118+ if ((p -> h == h ) && (ZSTR_LEN (p -> key ) == size )) {
119+ if (!memcmp (ZSTR_VAL (p -> key ), str , size )) {
117120 return p -> key ;
118121 }
119122 }
@@ -123,6 +126,11 @@ static zend_always_inline zend_string *zend_interned_string_ht_lookup(zend_strin
123126 return NULL ;
124127}
125128
129+ static zend_always_inline zend_string * zend_interned_string_ht_lookup (zend_string * str , HashTable * interned_strings )
130+ {
131+ return zend_interned_string_ht_lookup_ex (ZSTR_H (str ), ZSTR_VAL (str ), ZSTR_LEN (str ), interned_strings );
132+ }
133+
126134/* This function might be not thread safe at least because it would update the
127135 hash val in the passed string. Be sure it is called in the appropriate context. */
128136static zend_always_inline zend_string * zend_add_interned_string (zend_string * str , HashTable * interned_strings , uint32_t flags )
@@ -141,10 +149,10 @@ static zend_always_inline zend_string *zend_add_interned_string(zend_string *str
141149
142150ZEND_API zend_string * zend_interned_string_find_permanent (zend_string * str )
143151{
152+ zend_string_hash_val (str );
144153 return zend_interned_string_ht_lookup (str , & interned_strings_permanent );
145154}
146155
147-
148156static zend_string * zend_new_interned_string_permanent (zend_string * str )
149157{
150158 zend_string * ret ;
@@ -153,6 +161,7 @@ static zend_string *zend_new_interned_string_permanent(zend_string *str)
153161 return str ;
154162 }
155163
164+ zend_string_hash_val (str );
156165 ret = zend_interned_string_ht_lookup (str , & interned_strings_permanent );
157166 if (ret ) {
158167 zend_string_release (str );
@@ -170,6 +179,8 @@ static zend_string *zend_new_interned_string_request(zend_string *str)
170179 return str ;
171180 }
172181
182+ zend_string_hash_val (str );
183+
173184 /* Check for permanent strings, the table is readonly at this point. */
174185 ret = zend_interned_string_ht_lookup (str , & interned_strings_permanent );
175186 if (ret ) {
@@ -189,6 +200,44 @@ static zend_string *zend_new_interned_string_request(zend_string *str)
189200 return ret ;
190201}
191202
203+ static zend_string * zend_string_init_interned_permanent (const char * str , size_t size , int permanent )
204+ {
205+ zend_string * ret ;
206+ zend_long h = zend_inline_hash_func (str , size );
207+
208+ ret = zend_interned_string_ht_lookup_ex (h , str , size , & interned_strings_permanent );
209+ if (ret ) {
210+ return ret ;
211+ }
212+
213+ ret = zend_string_init (str , size , permanent );
214+ ZSTR_H (ret ) = h ;
215+ return zend_add_interned_string (ret , & interned_strings_permanent , IS_STR_PERMANENT );
216+ }
217+
218+ static zend_string * zend_string_init_interned_request (const char * str , size_t size , int permanent )
219+ {
220+ zend_string * ret ;
221+ zend_long h = zend_inline_hash_func (str , size );
222+
223+ /* Check for permanent strings, the table is readonly at this point. */
224+ ret = zend_interned_string_ht_lookup_ex (h , str , size , & interned_strings_permanent );
225+ if (ret ) {
226+ return ret ;
227+ }
228+
229+ ret = zend_interned_string_ht_lookup_ex (h , str , size , & CG (interned_strings ));
230+ if (ret ) {
231+ return ret ;
232+ }
233+
234+ ret = zend_string_init (str , size , permanent );
235+ ZSTR_H (ret ) = h ;
236+
237+ /* Create a short living interned, freed after the request. */
238+ return zend_add_interned_string (ret , & CG (interned_strings ), 0 );
239+ }
240+
192241ZEND_API void zend_interned_strings_activate (void )
193242{
194243 zend_init_interned_strings_ht (& CG (interned_strings ), 0 );
@@ -199,9 +248,10 @@ ZEND_API void zend_interned_strings_deactivate(void)
199248 zend_hash_destroy (& CG (interned_strings ));
200249}
201250
202- ZEND_API void zend_interned_strings_set_request_storage_handler (zend_new_interned_string_func_t handler )
251+ ZEND_API void zend_interned_strings_set_request_storage_handlers (zend_new_interned_string_func_t handler , zend_string_init_interned_func_t init_handler )
203252{
204253 interned_string_request_handler = handler ;
254+ interned_string_init_request_handler = init_handler ;
205255}
206256
207257ZEND_API void zend_interned_strings_set_permanent_storage_copy_handler (zend_string_copy_storage_func_t handler )
@@ -215,6 +265,7 @@ ZEND_API void zend_interned_strings_switch_storage(void)
215265 interned_string_copy_storage ();
216266 }
217267 zend_new_interned_string = interned_string_request_handler ;
268+ zend_string_init_interned = interned_string_init_request_handler ;
218269}
219270
220271/*
0 commit comments