]> granicus.if.org Git - php/commitdiff
JIT: Fix handling of typed ref in assign op
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 22 Oct 2019 14:20:15 +0000 (16:20 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Wed, 23 Oct 2019 08:08:09 +0000 (10:08 +0200)
ext/opcache/jit/zend_jit_disasm_x86.c
ext/opcache/jit/zend_jit_helpers.c
ext/opcache/jit/zend_jit_x86.dasc

index c3b2e0210b16606e68a1b7c12506ebdb6cf4e8ea..790c62af8f87cd5d28bbe34020ffaf5c8c27649d 100644 (file)
@@ -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);
index b0d12f4d18d7eae79f23e8df31fbc186a3803aa5..d2c848af775364f5acd9657fe62904f7032948fa 100644 (file)
@@ -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);
index 79395ab6febda9ce32401de60d12f5a0ea15ff3a..33e6c19b974ffeedcb42c3e54f3324081c3c7cc5 100644 (file)
@@ -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 */