From: Nikita Popov Date: Tue, 22 Oct 2019 14:20:15 +0000 (+0200) Subject: JIT: Fix handling of typed ref in assign op X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2f80fbe3aeee52ed7111f4b61f9f4df05ed0ad7a;p=php JIT: Fix handling of typed ref in assign op --- diff --git a/ext/opcache/jit/zend_jit_disasm_x86.c b/ext/opcache/jit/zend_jit_disasm_x86.c index c3b2e0210b..790c62af8f 100644 --- a/ext/opcache/jit/zend_jit_disasm_x86.c +++ b/ext/opcache/jit/zend_jit_disasm_x86.c @@ -441,6 +441,7 @@ static int zend_jit_disasm_init(void) REGISTER_HELPER(zend_jit_pre_dec_typed_ref); REGISTER_HELPER(zend_jit_post_inc_typed_ref); REGISTER_HELPER(zend_jit_post_dec_typed_ref); + REGISTER_HELPER(zend_jit_assign_op_to_typed_ref); REGISTER_HELPER(zend_jit_only_vars_by_reference); REGISTER_HELPER(zend_jit_invalid_array_access); REGISTER_HELPER(zend_runtime_jit); diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index b0d12f4d18..d2c848af77 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1340,6 +1340,7 @@ static void ZEND_FASTCALL zend_jit_assign_cv_to_typed_ref(zend_reference *ref, z zend_jit_assign_to_typed_ref(ref, value, IS_CV); } + static zend_property_info *zend_jit_get_prop_not_accepting_double(zend_reference *ref) { zend_property_info *prop; @@ -1440,6 +1441,19 @@ static void ZEND_FASTCALL zend_jit_post_dec_typed_ref(zval *var_ptr, zend_refere } } +static void ZEND_FASTCALL zend_jit_assign_op_to_typed_ref(zend_reference *ref, zval *val, binary_op_type binary_op) +{ + zval z_copy; + + binary_op(&z_copy, &ref->val, val); + if (EXPECTED(zend_verify_ref_assignable_zval(ref, &z_copy, ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data))))) { + zval_ptr_dtor(&ref->val); + ZVAL_COPY_VALUE(&ref->val, &z_copy); + } else { + zval_ptr_dtor(&z_copy); + } +} + static void ZEND_FASTCALL zend_jit_only_vars_by_reference(zval *arg) { ZVAL_NEW_REF(arg, arg); diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 79395ab6fe..33e6c19b97 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -5047,29 +5047,58 @@ static int zend_jit_assign_op(dasm_State **Dst, const zend_op *opline, const zen } if (op1_info & MAY_BE_REF) { + binary_op_type binary_op = get_binary_op(opline->extended_value); | LOAD_ZVAL_ADDR FCARG1a, op1_addr - | ZVAL_DEREF FCARG1a, op1_info + | IF_NOT_Z_TYPE, FCARG1a, IS_REFERENCE, >1 + | GET_Z_PTR FCARG1a, FCARG1a + | cmp aword [FCARG1a + offsetof(zend_reference, sources.ptr)], 0 + | jnz >2 + | add FCARG1a, offsetof(zend_reference, val) + |.cold_code + |2: + | LOAD_ZVAL_ADDR FCARG2a, op2_addr + |.if X64 + | LOAD_ADDR CARG3, binary_op + |.else + | sub r4, 12 + | PUSH_ADDR binary_op, r0 + |.endif + | SAVE_VALID_OPLINE opline + | EXT_CALL zend_jit_assign_op_to_typed_ref, r0 + |.if not(X64) + | add r4, 12 + |.endif + zend_jit_check_exception(Dst); + | jmp >9 + |.code + |1: op1_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG1a, 0); } + int result; switch (opline->extended_value) { case ZEND_ADD: case ZEND_SUB: case ZEND_MUL: case ZEND_DIV: - return zend_jit_math_helper(Dst, opline, opline->extended_value, op_array, ssa, opline->op1_type, opline->op1, op1_addr, op1_info, opline->op2_type, opline->op2, op2_addr, op2_info, opline->op1.var, op1_addr, OP1_DEF_INFO(), op1_info); + result = zend_jit_math_helper(Dst, opline, opline->extended_value, op_array, ssa, opline->op1_type, opline->op1, op1_addr, op1_info, opline->op2_type, opline->op2, op2_addr, op2_info, opline->op1.var, op1_addr, OP1_DEF_INFO(), op1_info); + break; case ZEND_BW_OR: case ZEND_BW_AND: case ZEND_BW_XOR: case ZEND_SL: case ZEND_SR: case ZEND_MOD: - return zend_jit_long_math_helper(Dst, opline, opline->extended_value, op_array, ssa, opline->op1_type, opline->op1, op1_addr, op1_info, op1_ssa_var, opline->op2_type, opline->op2, op2_addr, op2_info, op2_ssa_var, opline->op1.var, op1_addr, OP1_DEF_INFO(), op1_info); + result = zend_jit_long_math_helper(Dst, opline, opline->extended_value, op_array, ssa, opline->op1_type, opline->op1, op1_addr, op1_info, op1_ssa_var, opline->op2_type, opline->op2, op2_addr, op2_info, op2_ssa_var, opline->op1.var, op1_addr, OP1_DEF_INFO(), op1_info); + break; case ZEND_CONCAT: - return zend_jit_concat_helper(Dst, opline, op_array, ssa, opline->op1_type, opline->op1, op1_addr, op1_info, opline->op2_type, opline->op2, op2_addr, op2_info, op1_addr, OP1_DEF_INFO()); + result = zend_jit_concat_helper(Dst, opline, op_array, ssa, opline->op1_type, opline->op1, op1_addr, op1_info, opline->op2_type, opline->op2, op2_addr, op2_info, op1_addr, OP1_DEF_INFO()); + break; default: ZEND_ASSERT(0); } + |9: + return result; fallback: /* fallback to subroutine threading */