@@ -125,38 +125,75 @@ static zend_result zp_args_check(const zend_function *function,
125125 return SUCCESS ;
126126}
127127
128- static bool zp_name_exists (zend_string * * names , uint32_t num_names , const zend_string * name )
128+ typedef struct zp_names {
129+ zend_string * variadic_param ;
130+ zend_string * extra_named_params ;
131+ zend_string * inner_closure ;
132+ zend_string * params [1 ];
133+ } zp_names ;
134+
135+ static bool zp_name_exists (zp_names * names , uint32_t argc , const zend_string * name )
129136{
130- for (uint32_t i = 0 ; i < num_names ; i ++ ) {
131- if (names [i ] && zend_string_equals (names [i ], name )) {
137+ for (uint32_t i = 0 ; i < argc ; i ++ ) {
138+ if (names -> params [i ] && zend_string_equals (names -> params [i ], name )) {
132139 return true;
133140 }
134141 }
142+ if (names -> variadic_param && zend_string_equals (names -> variadic_param , name )) {
143+ return true;
144+ }
145+ if (names -> extra_named_params && zend_string_equals (names -> extra_named_params , name )) {
146+ return true;
147+ }
148+ if (names -> inner_closure && zend_string_equals (names -> inner_closure , name )) {
149+ return true;
150+ }
151+
135152 return false;
136153}
137154
138- static zend_string * zp_get_param_name (zend_function * function , uint32_t arg_offset )
155+ static void zp_names_dtor (zp_names * names , uint32_t argc )
156+ {
157+ for (uint32_t i = 0 ; i < argc ; i ++ ) {
158+ if (names -> params [i ]) {
159+ zend_string_release (names -> params [i ]);
160+ }
161+ }
162+ if (names -> variadic_param ) {
163+ zend_string_release (names -> variadic_param );
164+ }
165+ if (names -> extra_named_params ) {
166+ zend_string_release (names -> extra_named_params );
167+ }
168+ if (names -> inner_closure ) {
169+ zend_string_release (names -> inner_closure );
170+ }
171+ }
172+
173+ static zend_string * zp_get_func_param_name (zend_function * function , uint32_t arg_offset )
139174{
140175 return zend_string_copy (function -> common .arg_info [arg_offset ].name );
141176}
142177
143178/* Assign a name for every variable that will be used in the generated closure,
144179 * including params and used vars. */
145- static void zp_assign_names (zend_string * * names , uint32_t num_names ,
146- uint32_t argc , zval * argv ,
180+ static zp_names * zp_assign_names (uint32_t argc , zval * argv ,
147181 zend_function * function , bool variadic_partial ,
148182 zend_array * extra_named_params )
149183{
184+ zp_names * names = zend_arena_calloc (& CG (ast_arena ),
185+ 1 , XtOffsetOf (zp_names , params ) + sizeof (zend_string * ) * argc );
186+
150187 /* Assign names for params. We never rename those. */
151188 for (uint32_t offset = 0 ; offset < MIN (argc , function -> common .num_args ); offset ++ ) {
152189 if (Z_IS_PLACEHOLDER_P (& argv [offset ])) {
153- names [offset ] = zp_get_param_name (function , offset );
190+ names -> params [offset ] = zp_get_func_param_name (function , offset );
154191 }
155192 }
156193
157194 /* Assign name for the variadic param. Never renamed. */
158195 if (variadic_partial && (function -> common .fn_flags & ZEND_ACC_VARIADIC )) {
159- names [ argc ] = zp_get_param_name (function , function -> common .num_args );
196+ names -> variadic_param = zp_get_func_param_name (function , function -> common .num_args );
160197 }
161198
162199 /* Assign names for placeholders that bind to the variadic param:
@@ -172,16 +209,16 @@ static void zp_assign_names(zend_string **names, uint32_t num_names,
172209 if (!Z_IS_PLACEHOLDER_P (& argv [offset ])) {
173210 continue ;
174211 }
175- zend_string * orig_name = zp_get_param_name (function , function -> common .num_args );
212+ zend_string * orig_name = zp_get_func_param_name (function , function -> common .num_args );
176213 zend_string * new_name ;
177214 for (uint32_t n = 0 ;; n ++ ) {
178215 new_name = zend_strpprintf_unchecked (0 , "%S%" PRIu32 , orig_name , n );
179- if (!zp_name_exists (names , num_names , new_name )) {
216+ if (!zp_name_exists (names , argc , new_name )) {
180217 break ;
181218 }
182219 zend_string_release (new_name );
183220 }
184- names [offset ] = new_name ;
221+ names -> params [offset ] = new_name ;
185222 zend_string_release (orig_name );
186223 }
187224
@@ -192,40 +229,42 @@ static void zp_assign_names(zend_string **names, uint32_t num_names,
192229 continue ;
193230 }
194231 uint32_t n = 0 ;
195- zend_string * orig_name = zp_get_param_name (function , MIN (offset , function -> common .num_args ));
232+ zend_string * orig_name = zp_get_func_param_name (function , MIN (offset , function -> common .num_args ));
196233 zend_string * new_name = zend_string_copy (orig_name );
197- while (zp_name_exists (names , num_names , new_name )) {
234+ while (zp_name_exists (names , argc , new_name )) {
198235 zend_string_release (new_name );
199236 new_name = zend_strpprintf_unchecked (0 , "%S%" PRIu32 , orig_name , n );
200237 n ++ ;
201238 }
202- names [offset ] = new_name ;
239+ names -> params [offset ] = new_name ;
203240 zend_string_release (orig_name );
204241 }
205242
206243 /* Assign name for $extra_named_params */
207244 if (extra_named_params ) {
208245 uint32_t n = 1 ;
209246 zend_string * new_name = ZSTR_INIT_LITERAL ("extra_named_params" , 0 );
210- while (zp_name_exists (names , num_names , new_name )) {
247+ while (zp_name_exists (names , argc , new_name )) {
211248 zend_string_release (new_name );
212249 n ++ ;
213250 new_name = zend_strpprintf (0 , "%s%" PRIu32 , "extra_named_params" , n );
214251 }
215- names [ argc + variadic_partial ] = new_name ;
252+ names -> extra_named_params = new_name ;
216253 }
217254
218255 /* Assign name for $fn */
219256 if (function -> common .fn_flags & ZEND_ACC_CLOSURE ) {
220257 uint32_t n = 1 ;
221258 zend_string * new_name = ZSTR_INIT_LITERAL ("fn" , 0 );
222- while (zp_name_exists (names , num_names , new_name )) {
259+ while (zp_name_exists (names , argc , new_name )) {
223260 zend_string_release (new_name );
224261 n ++ ;
225262 new_name = zend_strpprintf (0 , "%s%" PRIu32 , "fn" , n );
226263 }
227- names [ argc + variadic_partial + ( extra_named_params != NULL )] = new_name ;
264+ names -> inner_closure = new_name ;
228265 }
266+
267+ return names ;
229268}
230269
231270static inline bool zp_is_power_of_two (uint32_t x )
@@ -502,7 +541,7 @@ static zend_string *zp_pfa_name(const zend_op_array *declaring_op_array,
502541static zend_ast * zp_compile_forwarding_call (
503542 zval * this_ptr , zend_function * function ,
504543 uint32_t argc , zval * argv , zend_array * extra_named_params ,
505- zend_string * * param_names , bool variadic_partial , uint32_t num_args ,
544+ zp_names * var_names , bool variadic_partial , uint32_t num_args ,
506545 zend_class_entry * called_scope , zend_type return_type ,
507546 bool forward_superfluous_args ,
508547 zend_ast * stmts_ast )
@@ -547,19 +586,19 @@ static zend_ast *zp_compile_forwarding_call(
547586 args_ast = zend_ast_list_add (args_ast , default_value_ast );
548587 } else {
549588 args_ast = zend_ast_list_add (args_ast , zend_ast_create (ZEND_AST_VAR ,
550- zend_ast_create_zval_from_str (zend_string_copy (param_names [offset ]))));
589+ zend_ast_create_zval_from_str (zend_string_copy (var_names -> params [offset ]))));
551590 }
552591 }
553592 if (extra_named_params ) {
554593 args_ast = zend_ast_list_add (args_ast , zend_ast_create (ZEND_AST_UNPACK ,
555594 zend_ast_create (ZEND_AST_VAR ,
556- zend_ast_create_zval_from_str (zend_string_copy (param_names [ argc + variadic_partial ] )))));
595+ zend_ast_create_zval_from_str (zend_string_copy (var_names -> extra_named_params )))));
557596 }
558597 if (variadic_partial ) {
559598 if (function -> common .fn_flags & ZEND_ACC_VARIADIC ) {
560599 args_ast = zend_ast_list_add (args_ast , zend_ast_create (ZEND_AST_UNPACK ,
561600 zend_ast_create (ZEND_AST_VAR ,
562- zend_ast_create_zval_from_str (zend_string_copy (param_names [ argc ] )))));
601+ zend_ast_create_zval_from_str (zend_string_copy (var_names -> variadic_param )))));
563602 } else if (forward_superfluous_args ) {
564603 /* When a '...' placeholder is used, and the underlying function is
565604 * not variadic, superfluous arguments are forwarded.
@@ -592,7 +631,7 @@ static zend_ast *zp_compile_forwarding_call(
592631 call_ast = zend_ast_create (ZEND_AST_CALL , func_name_ast , args_ast );
593632 } else if (function -> common .fn_flags & ZEND_ACC_CLOSURE ) {
594633 zend_ast * fn_ast = zend_ast_create (ZEND_AST_VAR ,
595- zend_ast_create_zval_from_str (zend_string_copy (param_names [ argc + variadic_partial + ( extra_named_params != NULL )] )));
634+ zend_ast_create_zval_from_str (zend_string_copy (var_names -> inner_closure )));
596635 call_ast = zend_ast_create (ZEND_AST_CALL , fn_ast , args_ast );
597636 } else if (Z_TYPE_P (this_ptr ) == IS_OBJECT ) {
598637 zend_ast * this_ast = zend_ast_create (ZEND_AST_VAR ,
@@ -779,11 +818,7 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function,
779818
780819 /* Assign variable names */
781820
782- uint32_t num_names = argc + uses_variadic_placeholder + (extra_named_params != NULL )
783- + ((function -> common .fn_flags & ZEND_ACC_CLOSURE ) != 0 );
784- zend_string * * param_names = zend_arena_calloc (& CG (ast_arena ),
785- num_names , sizeof (zend_string * ));
786- zp_assign_names (param_names , num_names , argc , argv , function ,
821+ zp_names * var_names = zp_assign_names (argc , argv , function ,
787822 uses_variadic_placeholder , extra_named_params );
788823
789824 /* Generate AST */
@@ -800,7 +835,7 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function,
800835 * do_closure_bind(). */
801836 if (function -> common .fn_flags & ZEND_ACC_CLOSURE ) {
802837 zend_ast * lexical_var_ast = zend_ast_create_zval_from_str (
803- zend_string_copy (param_names [ argc + uses_variadic_placeholder + ( extra_named_params != NULL )] ));
838+ zend_string_copy (var_names -> inner_closure ));
804839 lexical_vars_ast = zend_ast_list_add (lexical_vars_ast , lexical_var_ast );
805840 }
806841
@@ -834,14 +869,14 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function,
834869 params [param_offset ] = zend_ast_create_ex (ZEND_AST_PARAM ,
835870 param_flags , param_type_ast ,
836871 zend_ast_create_zval_from_str (
837- zend_string_copy (param_names [offset ])),
872+ zend_string_copy (var_names -> params [offset ])),
838873 default_value_ast , attributes_ast , NULL , NULL );
839874
840875 } else if (!Z_ISUNDEF (argv [offset ])) {
841876 // TODO: If the pre-bound parameter is a literal, it can be a
842877 // literal in the function body instead of a lexical var.
843878 zend_ast * lexical_var_ast = zend_ast_create_zval_from_str (
844- zend_string_copy (param_names [offset ]));
879+ zend_string_copy (var_names -> params [offset ]));
845880 if (zp_arg_must_be_sent_by_ref (function , offset + 1 )) {
846881 lexical_var_ast -> attr = ZEND_BIND_REF ;
847882 }
@@ -857,7 +892,7 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function,
857892
858893 if (extra_named_params ) {
859894 zend_ast * lexical_var_ast = zend_ast_create_zval_from_str (
860- zend_string_copy (param_names [ argc + uses_variadic_placeholder ] ));
895+ zend_string_copy (var_names -> extra_named_params ));
861896 lexical_vars_ast = zend_ast_list_add (lexical_vars_ast , lexical_var_ast );
862897 }
863898
@@ -875,7 +910,7 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function,
875910 params_ast = zend_ast_list_add (params_ast , zend_ast_create_ex (ZEND_AST_PARAM ,
876911 param_flags , param_type_ast ,
877912 zend_ast_create_zval_from_str (
878- zend_string_copy (param_names [ argc ] )),
913+ zend_string_copy (var_names -> variadic_param )),
879914 NULL , attributes_ast , NULL , NULL ));
880915 }
881916
@@ -906,7 +941,7 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function,
906941
907942 no_forwarding_ast = zp_compile_forwarding_call (this_ptr , function ,
908943 argc , argv , extra_named_params ,
909- param_names , uses_variadic_placeholder , num_params ,
944+ var_names , uses_variadic_placeholder , num_params ,
910945 called_scope , return_type , false, no_forwarding_ast );
911946
912947 if (!no_forwarding_ast ) {
@@ -916,7 +951,7 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function,
916951
917952 forwarding_ast = zp_compile_forwarding_call (this_ptr , function ,
918953 argc , argv , extra_named_params ,
919- param_names , uses_variadic_placeholder , num_params ,
954+ var_names , uses_variadic_placeholder , num_params ,
920955 called_scope , return_type , true, forwarding_ast );
921956
922957 if (!forwarding_ast ) {
@@ -943,7 +978,7 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function,
943978 } else {
944979 stmts_ast = zp_compile_forwarding_call (this_ptr , function ,
945980 argc , argv , extra_named_params ,
946- param_names , uses_variadic_placeholder , num_params ,
981+ var_names , uses_variadic_placeholder , num_params ,
947982 called_scope , return_type , false, stmts_ast );
948983
949984 if (!stmts_ast ) {
@@ -993,12 +1028,7 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function,
9931028 zend_ast_destroy (closure_ast );
9941029
9951030clean :
996- for (uint32_t i = 0 ; i < num_names ; i ++ ) {
997- if (param_names [i ]) {
998- zend_string_release (param_names [i ]);
999- }
1000- }
1001-
1031+ zp_names_dtor (var_names , argc );
10021032 zend_arena_destroy (CG (ast_arena ));
10031033 CG (ast_arena ) = orig_ast_arena ;
10041034 CG (zend_lineno ) = orig_lineno ;
0 commit comments