Skip to content

Commit

Permalink
JIT: Combine type guard with overflow detection
Browse files Browse the repository at this point in the history
  • Loading branch information
dstogov committed Oct 5, 2021
1 parent 20a784e commit a5e502e
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 6 deletions.
19 changes: 16 additions & 3 deletions ext/opcache/jit/zend_jit_arm64.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -12505,6 +12505,7 @@ static int zend_jit_incdec_obj(dasm_State **Dst,
bool needs_slow_path = 0;
bool use_prop_guard = 0;
bool may_throw = 0;
uint32_t res_info = (opline->result_type != IS_UNDEF) ? RES_INFO() : 0;

ZEND_ASSERT(opline->op2_type == IS_CONST);
ZEND_ASSERT(op1_info & MAY_BE_OBJECT);
Expand Down Expand Up @@ -12820,9 +12821,21 @@ static int zend_jit_incdec_obj(dasm_State **Dst,
| SET_ZVAL_TYPE_INFO res_addr, IS_DOUBLE, TMP1w, TMP2
}
}
| b >4
|.code
|4:
if (opline->result_type != IS_UNUSED
&& (opline->opcode == ZEND_PRE_INC_OBJ || opline->opcode == ZEND_PRE_DEC_OBJ)
&& (res_info & MAY_BE_GUARD)
&& (res_info & MAY_BE_LONG)) {
int32_t exit_point = zend_jit_trace_get_exit_point(opline + 1, 0);
const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);

ssa->var_info[ssa_op->result_def].type = res_info & ~MAY_BE_GUARD;
| b &exit_addr
|.code
} else {
| b >4
|.code
|4:
}
}
}

Expand Down
19 changes: 16 additions & 3 deletions ext/opcache/jit/zend_jit_x86.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -13209,6 +13209,7 @@ static int zend_jit_incdec_obj(dasm_State **Dst,
bool needs_slow_path = 0;
bool use_prop_guard = 0;
bool may_throw = 0;
uint32_t res_info = (opline->result_type != IS_UNDEF) ? RES_INFO() : 0;

ZEND_ASSERT(opline->op2_type == IS_CONST);
ZEND_ASSERT(op1_info & MAY_BE_OBJECT);
Expand Down Expand Up @@ -13546,9 +13547,21 @@ static int zend_jit_incdec_obj(dasm_State **Dst,
}
|.endif
}
| jmp >4
|.code
|4:
if (opline->result_type != IS_UNUSED
&& (opline->opcode == ZEND_PRE_INC_OBJ || opline->opcode == ZEND_PRE_DEC_OBJ)
&& (res_info & MAY_BE_GUARD)
&& (res_info & MAY_BE_LONG)) {
int32_t exit_point = zend_jit_trace_get_exit_point(opline + 1, 0);
const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);

ssa->var_info[ssa_op->result_def].type = res_info & ~MAY_BE_GUARD;
| jmp &exit_addr
|.code
} else {
| jmp >4
|.code
|4:
}
}
}

Expand Down

2 comments on commit a5e502e

@nikic
Copy link
Member

@nikic nikic commented on a5e502e Oct 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this change has broken overflow handling:

<?php
class Test {
    function foo() {
        $this->prop = PHP_INT_MAX - 5;
        for ($i = 0; $i < 10; $i++) {
            var_dump(++$this->prop);
        }
    }
}
$test = new Test;
$test->foo();

Without tracing jit it overflows to float(9.223372036854776E+18), with tracing jit it overflows to int(4890909195324358656). Which is the correct value (interpreted as double), but with the wrong zval type.

@dstogov
Copy link
Member Author

@dstogov dstogov commented on a5e502e Oct 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be fixed now

Please sign in to comment.