Skip to content

Commit 7b0a053

Browse files
committed
JIT for ASSIGN_OBJ
1 parent e9b47df commit 7b0a053

File tree

7 files changed

+518
-31
lines changed

7 files changed

+518
-31
lines changed

Zend/zend_execute.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -919,7 +919,7 @@ static zend_always_inline zend_bool i_zend_verify_property_type(zend_property_in
919919
return 0;
920920
}
921921

922-
zend_bool zend_never_inline zend_verify_property_type(zend_property_info *info, zval *property, zend_bool strict) {
922+
ZEND_API zend_bool zend_never_inline zend_verify_property_type(zend_property_info *info, zval *property, zend_bool strict) {
923923
return i_zend_verify_property_type(info, property, strict);
924924
}
925925

Zend/zend_execute.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ ZEND_API int ZEND_FASTCALL zend_handle_undef_args(zend_execute_data *call);
418418

419419
#define ZEND_CLASS_HAS_TYPE_HINTS(ce) ((ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS) == ZEND_ACC_HAS_TYPE_HINTS)
420420

421-
zend_bool zend_verify_property_type(zend_property_info *info, zval *property, zend_bool strict);
421+
ZEND_API zend_bool zend_verify_property_type(zend_property_info *info, zval *property, zend_bool strict);
422422
ZEND_COLD void zend_verify_property_type_error(zend_property_info *info, zval *property);
423423

424424
#define ZEND_REF_ADD_TYPE_SOURCE(ref, source) \

ext/opcache/jit/zend_jit.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2457,6 +2457,49 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
24572457
goto jit_failure;
24582458
}
24592459
goto done;
2460+
case ZEND_ASSIGN_OBJ:
2461+
if (opline->op1_type == IS_VAR) {
2462+
break;
2463+
}
2464+
if (opline->op2_type != IS_CONST
2465+
|| Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
2466+
|| Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
2467+
break;
2468+
}
2469+
if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
2470+
break;
2471+
}
2472+
ce = NULL;
2473+
ce_is_instanceof = 0;
2474+
if (opline->op1_type == IS_UNUSED) {
2475+
op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
2476+
ce = op_array->scope;
2477+
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
2478+
op1_addr = 0;
2479+
} else {
2480+
op1_info = OP1_INFO();
2481+
if (!(op1_info & MAY_BE_OBJECT)) {
2482+
break;
2483+
}
2484+
op1_addr = OP1_REG_ADDR();
2485+
if (ssa->var_info && ssa->ops) {
2486+
zend_ssa_op *ssa_op = &ssa->ops[opline - op_array->opcodes];
2487+
if (ssa_op->op1_use >= 0) {
2488+
zend_ssa_var_info *op1_ssa = ssa->var_info + ssa_op->op1_use;
2489+
if (op1_ssa->ce && !op1_ssa->ce->create_object) {
2490+
ce = op1_ssa->ce;
2491+
ce_is_instanceof = op1_ssa->is_instanceof;
2492+
}
2493+
}
2494+
}
2495+
}
2496+
if (!zend_jit_assign_obj(&dasm_state, opline, op_array, ssa, ssa_op,
2497+
op1_info, op1_addr, OP1_DATA_INFO(),
2498+
0, ce, ce_is_instanceof, 0, NULL,
2499+
zend_may_throw(opline, ssa_op, op_array, ssa))) {
2500+
goto jit_failure;
2501+
}
2502+
goto done;
24602503
case ZEND_ASSIGN:
24612504
if (opline->op1_type != IS_CV) {
24622505
break;

ext/opcache/jit/zend_jit_disasm_x86.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,7 @@ static int zend_jit_disasm_init(void)
456456
REGISTER_HELPER(zend_jit_invalid_array_access);
457457
REGISTER_HELPER(zend_jit_invalid_property_read);
458458
REGISTER_HELPER(zend_jit_invalid_property_write);
459+
REGISTER_HELPER(zend_jit_invalid_property_assign);
459460
REGISTER_HELPER(zend_jit_prepare_assign_dim_ref);
460461
REGISTER_HELPER(zend_jit_pre_inc);
461462
REGISTER_HELPER(zend_jit_pre_dec);
@@ -466,6 +467,8 @@ static int zend_jit_disasm_init(void)
466467
REGISTER_HELPER(zend_jit_array_free);
467468
REGISTER_HELPER(zend_jit_zval_array_dup);
468469
REGISTER_HELPER(zend_jit_add_arrays_helper);
470+
REGISTER_HELPER(zend_jit_assign_obj_helper);
471+
REGISTER_HELPER(zend_jit_assign_to_typed_prop);
469472
#undef REGISTER_HELPER
470473

471474
#ifndef _WIN32

ext/opcache/jit/zend_jit_helpers.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,6 +1858,13 @@ static void ZEND_FASTCALL zend_jit_invalid_property_write(zval *container, const
18581858
property_name, zend_zval_type_name(container));
18591859
}
18601860

1861+
static void ZEND_FASTCALL zend_jit_invalid_property_assign(zval *container, const char *property_name)
1862+
{
1863+
zend_throw_error(NULL,
1864+
"Attempt to assign property \"%s\" on %s",
1865+
property_name, zend_zval_type_name(container));
1866+
}
1867+
18611868
static zval * ZEND_FASTCALL zend_jit_prepare_assign_dim_ref(zval *ref) {
18621869
zval *val = Z_REFVAL_P(ref);
18631870
if (Z_TYPE_P(val) <= IS_FALSE) {
@@ -1927,3 +1934,34 @@ static zend_array *ZEND_FASTCALL zend_jit_add_arrays_helper(zend_array *op1, zen
19271934
zend_hash_merge(res, op2, zval_add_ref, 0);
19281935
return res;
19291936
}
1937+
1938+
static void ZEND_FASTCALL zend_jit_assign_obj_helper(zend_object *zobj, zend_string *name, zval *value, void **cache_slot, zval *result)
1939+
{
1940+
ZVAL_DEREF(value);
1941+
value = zobj->handlers->write_property(zobj, name, value, cache_slot);
1942+
if (result) {
1943+
ZVAL_COPY_DEREF(result, value);
1944+
}
1945+
}
1946+
1947+
static void ZEND_FASTCALL zend_jit_assign_to_typed_prop(zval *property_val, zend_property_info *info, zval *value, zval *result)
1948+
{
1949+
zend_execute_data *execute_data = EG(current_execute_data);
1950+
zval tmp;
1951+
1952+
ZVAL_DEREF(value);
1953+
ZVAL_COPY(&tmp, value);
1954+
1955+
if (UNEXPECTED(!zend_verify_property_type(info, &tmp, EX_USES_STRICT_TYPES()))) {
1956+
zval_ptr_dtor(&tmp);
1957+
if (result) {
1958+
ZVAL_NULL(result);
1959+
}
1960+
return;
1961+
}
1962+
1963+
value = zend_assign_to_variable(property_val, &tmp, IS_TMP_VAR, EX_USES_STRICT_TYPES());
1964+
if (result) {
1965+
ZVAL_COPY_DEREF(result, value);
1966+
}
1967+
}

ext/opcache/jit/zend_jit_trace.c

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1426,6 +1426,15 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
14261426
ADD_OP2_TRACE_GUARD();
14271427
}
14281428
break;
1429+
case ZEND_ASSIGN_OBJ:
1430+
if (opline->op2_type != IS_CONST
1431+
|| Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
1432+
|| Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
1433+
break;
1434+
}
1435+
// ADD_OP1_DATA_TRACE_GUARD();
1436+
ADD_OP1_TRACE_GUARD();
1437+
break;
14291438
case ZEND_IS_EQUAL:
14301439
case ZEND_IS_NOT_EQUAL:
14311440
case ZEND_IS_SMALLER:
@@ -2795,7 +2804,8 @@ static zend_bool zend_jit_may_delay_fetch_this(zend_ssa *ssa, const zend_op **ss
27952804
}
27962805
} else if (opline->opcode != ZEND_FETCH_OBJ_R
27972806
&& opline->opcode != ZEND_FETCH_OBJ_IS
2798-
&& opline->opcode != ZEND_FETCH_OBJ_W) {
2807+
&& opline->opcode != ZEND_FETCH_OBJ_W
2808+
&& opline->opcode != ZEND_ASSIGN_OBJ) {
27992809
return 0;
28002810
}
28012811

@@ -3708,6 +3718,72 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
37083718
goto jit_failure;
37093719
}
37103720
goto done;
3721+
case ZEND_ASSIGN_OBJ:
3722+
if (opline->op2_type != IS_CONST
3723+
|| Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
3724+
|| Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
3725+
break;
3726+
}
3727+
ce = NULL;
3728+
ce_is_instanceof = 0;
3729+
delayed_fetch_this = 0;
3730+
op1_indirect = 0;
3731+
if (opline->op1_type == IS_UNUSED) {
3732+
op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
3733+
ce = op_array->scope;
3734+
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
3735+
op1_addr = 0;
3736+
} else {
3737+
if (ssa_op->op1_use >= 0) {
3738+
delayed_fetch_this = ssa->var_info[ssa_op->op1_use].delayed_fetch_this;
3739+
}
3740+
op1_info = OP1_INFO();
3741+
if (!(op1_info & MAY_BE_OBJECT)) {
3742+
break;
3743+
}
3744+
op1_addr = OP1_REG_ADDR();
3745+
if (opline->op1_type == IS_VAR) {
3746+
if (orig_op1_type != IS_UNKNOWN
3747+
&& (orig_op1_type & IS_TRACE_INDIRECT)) {
3748+
op1_indirect = 1;
3749+
if (!zend_jit_fetch_indirect_var(&dasm_state, opline, orig_op1_type,
3750+
&op1_info, &op1_addr, !ssa->var_info[ssa_op->op1_use].indirect_reference)) {
3751+
goto jit_failure;
3752+
}
3753+
}
3754+
}
3755+
if (orig_op1_type != IS_UNKNOWN
3756+
&& (orig_op1_type & IS_TRACE_REFERENCE)) {
3757+
if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
3758+
!ssa->var_info[ssa_op->op1_use].guarded_reference, 1)) {
3759+
goto jit_failure;
3760+
}
3761+
if (opline->op1_type == IS_CV
3762+
&& zend_jit_var_may_alias(op_array, op_array_ssa, EX_VAR_TO_NUM(opline->op1.var)) == NO_ALIAS) {
3763+
ssa->var_info[ssa_op->op1_use].guarded_reference = 1;
3764+
}
3765+
} else {
3766+
CHECK_OP1_TRACE_TYPE();
3767+
}
3768+
if (ssa->var_info && ssa->ops) {
3769+
if (ssa_op->op1_use >= 0) {
3770+
zend_ssa_var_info *op1_ssa = ssa->var_info + ssa_op->op1_use;
3771+
if (op1_ssa->ce && !op1_ssa->ce->create_object) {
3772+
ce = op1_ssa->ce;
3773+
ce_is_instanceof = op1_ssa->is_instanceof;
3774+
}
3775+
}
3776+
}
3777+
}
3778+
op1_data_info = OP1_DATA_INFO();
3779+
CHECK_OP1_DATA_TRACE_TYPE();
3780+
if (!zend_jit_assign_obj(&dasm_state, opline, op_array, ssa, ssa_op,
3781+
op1_info, op1_addr, op1_data_info,
3782+
op1_indirect, ce, ce_is_instanceof, delayed_fetch_this, op1_ce,
3783+
zend_may_throw(opline, ssa_op, op_array, ssa))) {
3784+
goto jit_failure;
3785+
}
3786+
goto done;
37113787
case ZEND_ASSIGN_DIM:
37123788
op1_info = OP1_INFO();
37133789
op1_addr = OP1_REG_ADDR();

0 commit comments

Comments
 (0)