Skip to content

Commit 8c9016d

Browse files
committed
Initial prototyping implicit move
1 parent c0b89e0 commit 8c9016d

File tree

5 files changed

+168
-81
lines changed

5 files changed

+168
-81
lines changed

Zend/Optimizer/dfa_pass.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,6 +1124,46 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
11241124
#endif
11251125
}
11261126

1127+
// TODO: move me to other function?
1128+
for (v = 0; v < ssa->vars_count; v++) {
1129+
if (ssa->vars[v].var >= op_array->last_var) {
1130+
continue;
1131+
}
1132+
1133+
uint32_t type = ssa->var_info[v].type;
1134+
if (!(type & (MAY_BE_ANY-(MAY_BE_RC1|MAY_BE_ARRAY|MAY_BE_ARRAY_OF_ANY|MAY_BE_STRING)))) {
1135+
continue;
1136+
}
1137+
1138+
#if 0
1139+
fprintf(stderr, "cv %d: ", v);
1140+
zend_dump_var(op_array, IS_CV, v);
1141+
fprintf(stderr, "\n");
1142+
fprintf(stderr, "type %x\n", type);
1143+
#endif
1144+
1145+
int use = ssa->vars[v].use_chain;
1146+
if (use >= 0
1147+
&& op_array->opcodes[use].opcode == ZEND_SEND_VAR
1148+
&& op_array->opcodes[use].op2_type == IS_UNUSED) {
1149+
int next_use = zend_ssa_next_use(ssa->ops, v, use);
1150+
1151+
if (next_use >= 0 && op_array->opcodes[next_use].opcode == ZEND_ASSIGN) {
1152+
fprintf(stderr, "v=%d next_use %d (%d, %d, %d)\n", v, next_use, ssa->ops[next_use].result_def, ssa->ops[next_use].result_use, ssa->ops[next_use].op1_use);
1153+
}
1154+
1155+
/* Either there is no next use which is okay, or the next use is an assignment
1156+
* which overrides the previous value, which is also okay. */
1157+
if (next_use < 0
1158+
|| (op_array->opcodes[next_use].opcode == ZEND_ASSIGN
1159+
&& ssa->ops[next_use].op1_use == v
1160+
&& zend_ssa_next_use(ssa->ops, v, next_use) < 0)) {
1161+
ZEND_ASSERT(op_array->opcodes[use].extended_value == 0);
1162+
op_array->opcodes[use].extended_value = 1;
1163+
}
1164+
}
1165+
}
1166+
11271167
for (v = op_array->last_var; v < ssa->vars_count; v++) {
11281168

11291169
op_1 = ssa->vars[v].definition;

Zend/zend_vm_def.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9874,7 +9874,7 @@ ZEND_VM_C_LABEL(fetch_dim_r_index_undef):
98749874
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
98759875
}
98769876

9877-
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAR, op->op2_type == IS_UNUSED && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0, ZEND_SEND_VAR_SIMPLE, CV|VAR, NUM)
9877+
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAR, op->op2_type == IS_UNUSED && !op->extended_value && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0, ZEND_SEND_VAR_SIMPLE, CV|VAR, NUM)
98789878
{
98799879
USE_OPLINE
98809880
zval *varptr, *arg;
@@ -9891,6 +9891,20 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAR, op->op2_type == IS_UNUSED && (op1_i
98919891
ZEND_VM_NEXT_OPCODE();
98929892
}
98939893

9894+
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAR, op->op2_type == IS_UNUSED && op->extended_value && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0, ZEND_SEND_VAR_SIMPLE_EXT, CV, NUM)
9895+
{
9896+
USE_OPLINE
9897+
zval *varptr, *arg;
9898+
9899+
varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9900+
arg = ZEND_CALL_VAR(EX(call), opline->result.var);
9901+
9902+
ZVAL_COPY_VALUE(arg, varptr);
9903+
//fprintf(stderr, "Hello world, %d\n", Z_REFCOUNTED_P(arg));
9904+
9905+
ZEND_VM_NEXT_OPCODE();
9906+
}
9907+
98949908
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAR_EX, op->op2_type == IS_UNUSED && op->op2.num <= MAX_ARG_FLAG_NUM && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0, ZEND_SEND_VAR_EX_SIMPLE, CV|VAR, UNUSED|NUM)
98959909
{
98969910
USE_OPLINE

Zend/zend_vm_execute.h

Lines changed: 81 additions & 59 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Zend/zend_vm_handlers.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,10 +1850,11 @@
18501850
_(3455, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \
18511851
_(3458, ZEND_SEND_VAR_SIMPLE_SPEC_VAR) \
18521852
_(3460, ZEND_SEND_VAR_SIMPLE_SPEC_CV) \
1853-
_(3463, ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED) \
1854-
_(3465, ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED) \
1855-
_(3466, ZEND_SEND_VAL_SIMPLE_SPEC_CONST) \
1856-
_(3467, ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST) \
1857-
_(3468, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED) \
1858-
_(3469, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED) \
1859-
_(3469+1, ZEND_NULL)
1853+
_(3461, ZEND_SEND_VAR_SIMPLE_EXT_SPEC_CV) \
1854+
_(3464, ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED) \
1855+
_(3466, ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED) \
1856+
_(3467, ZEND_SEND_VAL_SIMPLE_SPEC_CONST) \
1857+
_(3468, ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST) \
1858+
_(3469, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED) \
1859+
_(3470, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED) \
1860+
_(3470+1, ZEND_NULL)

ext/standard/array.c

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3925,22 +3925,32 @@ static zend_always_inline void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMET
39253925

39263926
arg = args;
39273927
src = Z_ARRVAL_P(arg);
3928-
/* copy first array */
3929-
array_init_size(return_value, count);
3930-
dest = Z_ARRVAL_P(return_value);
3928+
/* copy first array if necessary */
39313929
if (HT_IS_PACKED(src)) {
3932-
zend_hash_real_init_packed(dest);
3933-
ZEND_HASH_FILL_PACKED(dest) {
3934-
ZEND_HASH_PACKED_FOREACH_VAL(src, src_entry) {
3935-
if (UNEXPECTED(Z_ISREF_P(src_entry) &&
3936-
Z_REFCOUNT_P(src_entry) == 1)) {
3937-
src_entry = Z_REFVAL_P(src_entry);
3938-
}
3939-
Z_TRY_ADDREF_P(src_entry);
3940-
ZEND_HASH_FILL_ADD(src_entry);
3941-
} ZEND_HASH_FOREACH_END();
3942-
} ZEND_HASH_FILL_END();
3930+
/* Note: If it has holes, it might get sequentialized */
3931+
if (HT_IS_WITHOUT_HOLES(src) && !(GC_FLAGS(Z_ARRVAL_P(arg)) & (IS_ARRAY_IMMUTABLE | IS_ARRAY_PERSISTENT)) && Z_REFCOUNT_P(arg) == 1) {
3932+
dest = src;
3933+
ZVAL_ARR(return_value, dest);
3934+
} else {
3935+
array_init_size(return_value, count);
3936+
dest = Z_ARRVAL_P(return_value);
3937+
3938+
zend_hash_real_init_packed(dest);
3939+
ZEND_HASH_FILL_PACKED(dest) {
3940+
ZEND_HASH_PACKED_FOREACH_VAL(src, src_entry) {
3941+
if (UNEXPECTED(Z_ISREF_P(src_entry) &&
3942+
Z_REFCOUNT_P(src_entry) == 1)) {
3943+
src_entry = Z_REFVAL_P(src_entry);
3944+
}
3945+
Z_TRY_ADDREF_P(src_entry);
3946+
ZEND_HASH_FILL_ADD(src_entry);
3947+
} ZEND_HASH_FOREACH_END();
3948+
} ZEND_HASH_FILL_END();
3949+
}
39433950
} else {
3951+
array_init_size(return_value, count);
3952+
dest = Z_ARRVAL_P(return_value);
3953+
39443954
zend_string *string_key;
39453955
zend_hash_real_init_mixed(dest);
39463956
ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(src, string_key, src_entry) {

0 commit comments

Comments
 (0)