op1_addr = OP1_REG_ADDR();
if (orig_op1_type != IS_UNKNOWN
&& (orig_op1_type & IS_TRACE_REFERENCE)) {
- if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr)) {
+ if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr, 1)) {
goto jit_failure;
}
} else {
op1_addr = OP1_REG_ADDR();
if (orig_op1_type != IS_UNKNOWN
&& (orig_op1_type & IS_TRACE_REFERENCE)) {
- if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr)) {
+ if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr, 1)) {
goto jit_failure;
}
} else {
CHECK_OP2_TRACE_TYPE();
op1_info = OP1_INFO();
op1_def_info = OP1_DEF_INFO();
- USE_OP1_TRACE_TYPE();
+ op1_addr = OP1_REG_ADDR();
+ op1_def_addr = OP1_DEF_REG_ADDR();
+ if (orig_op1_type != IS_UNKNOWN
+ && (orig_op1_type & IS_TRACE_REFERENCE)) {
+ if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr, 0)) {
+ goto jit_failure;
+ }
+ op1_def_addr = op1_addr;
+ } else {
+ USE_OP1_TRACE_TYPE();
+ if (orig_op1_type != IS_UNKNOWN
+ && (op1_info & MAY_BE_REF)) {
+ if (!zend_jit_noref_guard(&dasm_state, opline, op1_addr)) {
+ goto jit_failure;
+ }
+ op1_info &= ~MAY_BE_REF;
+ op1_def_info &= ~MAY_BE_REF;
+ }
+ }
if (!zend_jit_assign(&dasm_state, opline, op_array,
- op1_info, OP1_REG_ADDR(),
- op1_def_info, OP1_DEF_REG_ADDR(),
+ op1_info, op1_addr,
+ op1_def_info, op1_def_addr,
op2_info, op2_addr, op2_def_addr,
res_info, res_addr,
zend_may_throw(opline, ssa_op, op_array, ssa))) {
op1_addr = OP1_REG_ADDR();
if (orig_op1_type != IS_UNKNOWN
&& (orig_op1_type & IS_TRACE_REFERENCE)) {
- if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr)) {
+ if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr, 1)) {
goto jit_failure;
}
} else {
op1_addr = OP1_REG_ADDR();
if (orig_op1_type != IS_UNKNOWN
&& (orig_op1_type & IS_TRACE_REFERENCE)) {
- if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr)) {
+ if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr, 1)) {
goto jit_failure;
}
} else {
return 1;
}
-static zend_bool zend_jit_fetch_reference(dasm_State **Dst, const zend_op *opline, uint8_t var_type, uint32_t *var_info_ptr, zend_jit_addr *var_addr_ptr)
+static zend_bool zend_jit_noref_guard(dasm_State **Dst, const zend_op *opline, zend_jit_addr var_addr)
+{
+ int32_t exit_point = zend_jit_trace_get_exit_point(opline, opline, NULL, 0);
+ const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
+
+ if (!exit_addr) {
+ return 0;
+ }
+ | IF_ZVAL_TYPE var_addr, IS_REFERENCE, &exit_addr
+
+ return 1;
+}
+
+static zend_bool zend_jit_fetch_reference(dasm_State **Dst, const zend_op *opline, uint8_t var_type, uint32_t *var_info_ptr, zend_jit_addr *var_addr_ptr, zend_bool add_type_guard)
{
zend_jit_addr var_addr = *var_addr_ptr;
uint32_t var_info = *var_info_ptr;
*var_addr_ptr = var_addr;
var_type &= ~IS_TRACE_REFERENCE;
- if (var_type != IS_UNKNOWN
+ if (add_type_guard
+ && var_type != IS_UNKNOWN
&& (var_info & (MAY_BE_ANY|MAY_BE_UNDEF)) != (1 << var_type)) {
| IF_NOT_Z_TYPE FCARG1a, var_type, &exit_addr
var_info = MAY_BE_ARRAY | (var_info & (MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF|MAY_BE_ARRAY_KEY_ANY|MAY_BE_RC1|MAY_BE_RCN));
}
+ *var_info_ptr = var_info;
+ } else {
+ var_info &= ~MAY_BE_REF;
*var_info_ptr = var_info;
}