Skip to content

Commit ed2c408

Browse files
committed
Organize names in a struct
1 parent a0e136b commit ed2c408

File tree

1 file changed

+72
-42
lines changed

1 file changed

+72
-42
lines changed

Zend/zend_partial.c

Lines changed: 72 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -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

231270
static 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,
502541
static 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

9951030
clean:
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

Comments
 (0)