Skip to content

Commit 8227f2e

Browse files
committed
Combine ARRAY_DUP with ARRAY_SET_PLACEHOLDER
1 parent eb6c74c commit 8227f2e

File tree

11 files changed

+902
-838
lines changed

11 files changed

+902
-838
lines changed

Zend/Optimizer/block_pass.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,8 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
911911
src->opcode != ZEND_COPY_TMP &&
912912
src->opcode != ZEND_ADD_ARRAY_ELEMENT &&
913913
src->opcode != ZEND_ADD_ARRAY_UNPACK &&
914+
/* ARRAY_DUP is ok. If it is used within a QM_ASSIGN, it
915+
* has no ARRAY_SET_PLACEHOLDER calls. */
914916
src->opcode != ZEND_ARRAY_SET_PLACEHOLDER &&
915917
(src->opcode != ZEND_DECLARE_LAMBDA_FUNCTION ||
916918
src == opline -1)) {
@@ -1570,6 +1572,7 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use
15701572
break;
15711573
case ZEND_ADD_ARRAY_ELEMENT:
15721574
case ZEND_ADD_ARRAY_UNPACK:
1575+
/* FIXME: Can we eliminate these? There's no reason for them to be added if unused. */
15731576
case ZEND_ARRAY_SET_PLACEHOLDER:
15741577
case ZEND_ROPE_ADD:
15751578
zend_bitset_incl(usage, VAR_NUM(opline->result.var));

Zend/Optimizer/escape_analysis.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -315,13 +315,18 @@ static bool is_escape_use(zend_op_array *op_array, zend_ssa *ssa, int use, int v
315315
if (opline->extended_value & ZEND_ARRAY_ELEMENT_REF) {
316316
return 1;
317317
}
318-
ZEND_FALLTHROUGH;
318+
if (OP1_INFO() & MAY_BE_OBJECT) {
319+
/* object aliasing */
320+
return 1;
321+
}
322+
/* reference dependencies processed separately */
323+
break;
324+
case ZEND_ARRAY_DUP:
319325
case ZEND_ARRAY_SET_PLACEHOLDER:
320326
if (OP2_INFO() & MAY_BE_OBJECT) {
321327
/* object aliasing */
322328
return 1;
323329
}
324-
/* reference dependencies processed separately */
325330
break;
326331
case ZEND_OP_DATA:
327332
if ((opline-1)->opcode != ZEND_ASSIGN_DIM
@@ -499,7 +504,8 @@ zend_result zend_ssa_escape_analysis(const zend_script *script, zend_op_array *o
499504
op->op1_use == i &&
500505
op->result_def >= 0) {
501506
enclosing_root = ees[op->result_def];
502-
} else if (opline->opcode == ZEND_ARRAY_SET_PLACEHOLDER
507+
} else if ((opline->opcode == ZEND_ARRAY_DUP
508+
|| opline->opcode == ZEND_ARRAY_SET_PLACEHOLDER)
503509
&& op->op2_use == i
504510
&& op->result_def >= 0) {
505511
enclosing_root = ees[op->result_def];

Zend/Optimizer/sccp.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,12 +1182,14 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
11821182
}
11831183
return;
11841184
}
1185-
case ZEND_ARRAY_DUP: {
1186-
SET_RESULT(result, op1);
1187-
return;
1188-
}
1185+
case ZEND_ARRAY_DUP:
11891186
case ZEND_ARRAY_SET_PLACEHOLDER: {
1190-
zval *result = &ctx->values[ssa_op->result_use];
1187+
zval *result;
1188+
if (opline->opcode == ZEND_ARRAY_DUP) {
1189+
result = op1;
1190+
} else {
1191+
result = &ctx->values[ssa_op->result_use];
1192+
}
11911193

11921194
SKIP_IF_TOP(result);
11931195
SKIP_IF_TOP(op2);

Zend/Optimizer/zend_dfg.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ static zend_always_inline void _zend_dfg_add_use_def_op(const zend_op_array *op_
212212
}
213213
ZEND_FALLTHROUGH;
214214
case ZEND_ARRAY_DUP:
215-
if ((build_flags & ZEND_SSA_RC_INFERENCE) && opline->op1_type == IS_CV) {
216-
goto add_op1_def;
215+
if ((build_flags & ZEND_SSA_RC_INFERENCE) && opline->op2_type == IS_CV) {
216+
zend_bitset_incl(def, EX_VAR_TO_NUM(opline->op2.var));
217217
}
218218
break;
219219
case ZEND_YIELD:

Zend/Optimizer/zend_inference.c

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3447,30 +3447,17 @@ static zend_always_inline zend_result _zend_update_type_info(
34473447
UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
34483448
}
34493449
break;
3450-
case ZEND_ARRAY_DUP: {
3451-
ZEND_ASSERT(opline->op1_type == IS_CONST);
3452-
zval *template = CRT_CONSTANT_EX(op_array, opline, opline->op1);
3453-
uint32_t tmp = zend_array_type_info(template);
3454-
tmp &= ~MAY_BE_RCN;
3455-
tmp |= MAY_BE_RC1;
3456-
if (!(tmp & MAY_BE_ARRAY_OF_ANY)) {
3457-
tmp |= MAY_BE_ARRAY_OF_ANY;
3458-
}
3459-
UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
3460-
break;
3461-
}
3450+
case ZEND_ARRAY_DUP:
34623451
case ZEND_ARRAY_SET_PLACEHOLDER: {
34633452
// FIXME: op2 RC inference
3464-
uint32_t tmp = RES_USE_INFO();
3465-
if ((tmp & MAY_BE_ARRAY_OF_ANY) == MAY_BE_ARRAY_OF_ANY) {
3466-
ZEND_ASSERT(ssa_op->result_use != -1);
3467-
zend_op *dup_op = op_array->opcodes + ssa_vars[ssa_op->result_use].definition;
3468-
if (dup_op->opcode == ZEND_ARRAY_DUP) {
3469-
zval *template = CRT_CONSTANT_EX(op_array, dup_op, dup_op->op1);
3470-
tmp = zend_array_type_info(template);
3471-
tmp &= ~MAY_BE_RCN;
3472-
tmp |= MAY_BE_RC1;
3473-
}
3453+
if (opline->opcode == ZEND_ARRAY_DUP) {
3454+
ZEND_ASSERT(opline->op1_type == IS_CONST);
3455+
zval *template = CRT_CONSTANT_EX(op_array, opline, opline->op1);
3456+
tmp = zend_array_type_info(template);
3457+
tmp &= ~MAY_BE_RCN;
3458+
tmp |= MAY_BE_RC1;
3459+
} else {
3460+
tmp = RES_USE_INFO();
34743461
}
34753462
uint32_t dim_type = ((tmp & MAY_BE_ARRAY_KEY_LONG) ? MAY_BE_LONG : 0) | ((tmp & MAY_BE_ARRAY_KEY_STRING) ? MAY_BE_STRING : 0);
34763463
tmp |= assign_dim_array_result_type(tmp, dim_type, t2, IS_CONST);

Zend/Optimizer/zend_ssa.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -730,8 +730,11 @@ static zend_always_inline int _zend_ssa_rename_op(const zend_op_array *op_array,
730730
ssa_ops[k].result_use = var[EX_VAR_TO_NUM(opline->result.var)];
731731
ZEND_FALLTHROUGH;
732732
case ZEND_ARRAY_DUP:
733-
if ((build_flags & ZEND_SSA_RC_INFERENCE) && opline->op1_type == IS_CV) {
734-
goto add_op1_def;
733+
if ((build_flags & ZEND_SSA_RC_INFERENCE) && opline->op2_type == IS_CV) {
734+
ssa_ops[k].op2_def = ssa_vars_count;
735+
var[EX_VAR_TO_NUM(opline->op2.var)] = ssa_vars_count;
736+
ssa_vars_count++;
737+
//NEW_SSA_VAR(opline->op2.var)
735738
}
736739
break;
737740
case ZEND_YIELD:

Zend/zend_compile.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10688,7 +10688,7 @@ static void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */
1068810688
zend_ast_list *list = zend_ast_get_list(ast);
1068910689
zend_op *opline;
1069010690
uint32_t i, opnum_init = -1;
10691-
bool packed = 1, use_template = false;
10691+
bool packed = 1;
1069210692

1069310693
znode template_node;
1069410694
template_node.op_type = IS_CONST;
@@ -10702,9 +10702,6 @@ static void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */
1070210702

1070310703
zend_array *template = NULL;
1070410704
if (Z_TYPE(template_node.u.constant) == IS_ARRAY) {
10705-
opnum_init = get_next_op_number();
10706-
zend_emit_op_tmp(result, ZEND_ARRAY_DUP, &template_node, NULL);
10707-
use_template = true;
1070810705
template = Z_ARRVAL(template_node.u.constant);
1070910706
}
1071010707

@@ -10720,7 +10717,7 @@ static void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */
1072010717
}
1072110718

1072210719
if (terminate_array_template(elem_ast)) {
10723-
use_template = false;
10720+
template = NULL;
1072410721
}
1072510722

1072610723
value_ast = elem_ast->child[0];
@@ -10739,7 +10736,7 @@ static void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */
1073910736
key_ast = elem_ast->child[1];
1074010737
by_ref = elem_ast->attr;
1074110738

10742-
if (key_ast && !use_template) {
10739+
if (key_ast && !template) {
1074310740
zend_compile_expr(&key_node, key_ast);
1074410741
zend_handle_numeric_op(&key_node);
1074510742
key_node_ptr = &key_node;
@@ -10752,7 +10749,7 @@ static void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */
1075210749
zend_compile_expr(&value_node, value_ast);
1075310750
}
1075410751

10755-
if (use_template) {
10752+
if (template) {
1075610753
zval *element;
1075710754
if (key_ast) {
1075810755
zval *key = zend_ast_get_zval(key_ast);
@@ -10805,15 +10802,20 @@ static void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */
1080510802
// }
1080610803
}
1080710804

10808-
if (use_template && value_ast->kind == ZEND_AST_ZVAL) {
10805+
if (value_ast->kind == ZEND_AST_ZVAL) {
1080910806
zval_ptr_dtor(&value_node.u.constant);
1081010807
if (key_node_ptr) {
1081110808
zval_ptr_dtor(&key_node_ptr->u.constant);
1081210809
}
1081310810
continue;
1081410811
}
1081510812

10816-
opline = zend_emit_op(NULL, ZEND_ARRAY_SET_PLACEHOLDER, NULL, &value_node);
10813+
if (opnum_init == -1) {
10814+
opnum_init = get_next_op_number();
10815+
opline = zend_emit_op_tmp(result, ZEND_ARRAY_DUP, &template_node, &value_node);
10816+
} else {
10817+
opline = zend_emit_op(NULL, ZEND_ARRAY_SET_PLACEHOLDER, NULL, &value_node);
10818+
}
1081710819
opline->extended_value = (uintptr_t) element - (HT_IS_PACKED(template) ? (uintptr_t) template->arPacked : (uintptr_t) template->arData);
1081810820
SET_NODE(opline->result, result);
1081910821
} else if (opnum_init == -1) {
@@ -10834,10 +10836,12 @@ static void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */
1083410836
}
1083510837

1083610838
/* Add a flag to INIT_ARRAY if we know this array cannot be packed */
10837-
if (!packed && !template) {
10839+
if (!packed) {
1083810840
ZEND_ASSERT(opnum_init != (uint32_t)-1);
1083910841
opline = &CG(active_op_array)->opcodes[opnum_init];
10840-
opline->extended_value |= ZEND_ARRAY_NOT_PACKED;
10842+
if (opline->opcode == ZEND_INIT_ARRAY) {
10843+
opline->extended_value |= ZEND_ARRAY_NOT_PACKED;
10844+
}
1084110845
}
1084210846
}
1084310847
/* }}} */

Zend/zend_vm_def.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6243,7 +6243,7 @@ ZEND_VM_C_LABEL(num_index):
62436243
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
62446244
}
62456245

6246-
ZEND_VM_HANDLER(211, ZEND_ARRAY_SET_PLACEHOLDER, UNUSED, CONST|TMP|VAR|CV, NUM)
6246+
ZEND_VM_HANDLER(211, ZEND_ARRAY_SET_PLACEHOLDER, ANY, CONST|TMP|VAR|CV, NUM)
62476247
{
62486248
USE_OPLINE
62496249
zval *expr_ptr, new_expr, *element;
@@ -6437,15 +6437,15 @@ ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|CV|UNUSED, CONST|TMPVAR|UNUSE
64376437
}
64386438
}
64396439

6440-
ZEND_VM_HANDLER(210, ZEND_ARRAY_DUP, CONST, UNUSED)
6440+
ZEND_VM_HANDLER(210, ZEND_ARRAY_DUP, CONST, CONST|TMP|VAR|CV, NUM)
64416441
{
64426442
zend_array *copy;
64436443
USE_OPLINE
64446444

64456445
copy = zend_array_dup_immutable(Z_ARRVAL_P(GET_OP1_ZVAL_PTR(BP_VAR_R)));
64466446
ZVAL_ARR(EX_VAR(opline->result.var), copy);
64476447

6448-
ZEND_VM_NEXT_OPCODE();
6448+
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ARRAY_SET_PLACEHOLDER);
64496449
}
64506450

64516451
ZEND_VM_COLD_CONST_HANDLER(51, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE)

0 commit comments

Comments
 (0)