Skip to content

Commit 89bdf18

Browse files
committed
Initial prototyping implicit move
1 parent f06da77 commit 89bdf18

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
@@ -9900,7 +9900,7 @@ ZEND_VM_C_LABEL(fetch_dim_r_index_undef):
99009900
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
99019901
}
99029902

9903-
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)
9903+
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)
99049904
{
99059905
USE_OPLINE
99069906
zval *varptr, *arg;
@@ -9917,6 +9917,20 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAR, op->op2_type == IS_UNUSED && (op1_i
99179917
ZEND_VM_NEXT_OPCODE();
99189918
}
99199919

9920+
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)
9921+
{
9922+
USE_OPLINE
9923+
zval *varptr, *arg;
9924+
9925+
varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9926+
arg = ZEND_CALL_VAR(EX(call), opline->result.var);
9927+
9928+
ZVAL_COPY_VALUE(arg, varptr);
9929+
//fprintf(stderr, "Hello world, %d\n", Z_REFCOUNTED_P(arg));
9930+
9931+
ZEND_VM_NEXT_OPCODE();
9932+
}
9933+
99209934
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)
99219935
{
99229936
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
@@ -3945,22 +3945,32 @@ static zend_always_inline void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMET
39453945

39463946
arg = args;
39473947
src = Z_ARRVAL_P(arg);
3948-
/* copy first array */
3949-
array_init_size(return_value, count);
3950-
dest = Z_ARRVAL_P(return_value);
3948+
/* copy first array if necessary */
39513949
if (HT_IS_PACKED(src)) {
3952-
zend_hash_real_init_packed(dest);
3953-
ZEND_HASH_FILL_PACKED(dest) {
3954-
ZEND_HASH_PACKED_FOREACH_VAL(src, src_entry) {
3955-
if (UNEXPECTED(Z_ISREF_P(src_entry) &&
3956-
Z_REFCOUNT_P(src_entry) == 1)) {
3957-
src_entry = Z_REFVAL_P(src_entry);
3958-
}
3959-
Z_TRY_ADDREF_P(src_entry);
3960-
ZEND_HASH_FILL_ADD(src_entry);
3961-
} ZEND_HASH_FOREACH_END();
3962-
} ZEND_HASH_FILL_END();
3950+
/* Note: If it has holes, it might get sequentialized */
3951+
if (HT_IS_WITHOUT_HOLES(src) && !(GC_FLAGS(Z_ARRVAL_P(arg)) & (IS_ARRAY_IMMUTABLE | IS_ARRAY_PERSISTENT)) && Z_REFCOUNT_P(arg) == 1) {
3952+
dest = src;
3953+
ZVAL_ARR(return_value, dest);
3954+
} else {
3955+
array_init_size(return_value, count);
3956+
dest = Z_ARRVAL_P(return_value);
3957+
3958+
zend_hash_real_init_packed(dest);
3959+
ZEND_HASH_FILL_PACKED(dest) {
3960+
ZEND_HASH_PACKED_FOREACH_VAL(src, src_entry) {
3961+
if (UNEXPECTED(Z_ISREF_P(src_entry) &&
3962+
Z_REFCOUNT_P(src_entry) == 1)) {
3963+
src_entry = Z_REFVAL_P(src_entry);
3964+
}
3965+
Z_TRY_ADDREF_P(src_entry);
3966+
ZEND_HASH_FILL_ADD(src_entry);
3967+
} ZEND_HASH_FOREACH_END();
3968+
} ZEND_HASH_FILL_END();
3969+
}
39633970
} else {
3971+
array_init_size(return_value, count);
3972+
dest = Z_ARRVAL_P(return_value);
3973+
39643974
zend_string *string_key;
39653975
zend_hash_real_init_mixed(dest);
39663976
ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(src, string_key, src_entry) {

0 commit comments

Comments
 (0)