JIT: Fix handling of typed ref in assign op

This commit is contained in:
Nikita Popov 2019-10-22 16:20:15 +02:00
parent 8cdbcd7d91
commit 2f80fbe3ae
3 changed files with 48 additions and 4 deletions

View 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);

View 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);

View 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 */