summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2021-03-25 23:48:08 +0300
committerDmitry Stogov <dmitry@zend.com>2021-03-25 23:48:08 +0300
commit7b2b9b40797e3f071f653bd64706dfdcaf548f90 (patch)
treed0b4f35780f80d08911d710745d34e3504f63c17
parentaa45eedef0ded065f2f6ec33250747ad50558527 (diff)
downloadphp-git-7b2b9b40797e3f071f653bd64706dfdcaf548f90.tar.gz
Improved JIT for TYPE_CHECK opcode
-rw-r--r--ext/opcache/jit/zend_jit_trace.c14
-rw-r--r--ext/opcache/jit/zend_jit_x86.dasc88
2 files changed, 76 insertions, 26 deletions
diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c
index ff52edad49..009b33f627 100644
--- a/ext/opcache/jit/zend_jit_trace.c
+++ b/ext/opcache/jit/zend_jit_trace.c
@@ -1843,6 +1843,19 @@ propagate_arg:
case ZEND_CHECK_UNDEF_ARGS:
case ZEND_INCLUDE_OR_EVAL:
max_used_stack = used_stack = -1;
+ break;
+ case ZEND_TYPE_CHECK:
+ if (opline->extended_value == MAY_BE_RESOURCE) {
+ // TODO: support for is_resource() ???
+ break;
+ }
+ if (op1_type != IS_UNKNOWN
+ && (opline->extended_value == (1 << op1_type)
+ || opline->extended_value == MAY_BE_ANY - (1 << op1_type))) {
+ /* add guards only for exact checks, to avoid code duplication */
+ ADD_OP1_TRACE_GUARD();
+ }
+ break;
default:
break;
}
@@ -4900,6 +4913,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
break;
}
op1_info = OP1_INFO();
+ CHECK_OP1_TRACE_TYPE();
if ((opline->result_type & (IS_SMART_BRANCH_JMPZ|IS_SMART_BRANCH_JMPNZ)) != 0) {
bool exit_if_true = 0;
const zend_op *exit_opline = zend_jit_trace_get_exit_opline(p + 1, opline + 1, &exit_if_true);
diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc
index d7686f57b3..41ac95b28e 100644
--- a/ext/opcache/jit/zend_jit_x86.dasc
+++ b/ext/opcache/jit/zend_jit_x86.dasc
@@ -10908,7 +10908,6 @@ static int zend_jit_defined(dasm_State **Dst, const zend_op *opline, zend_uchar
static int zend_jit_type_check(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, zend_uchar smart_branch_opcode, uint32_t target_label, uint32_t target_label2, const void *exit_addr)
{
uint32_t mask;
- zend_uchar type;
zend_jit_addr op1_addr = OP1_ADDR();
// TODO: support for is_resource() ???
@@ -10952,19 +10951,6 @@ static int zend_jit_type_check(dasm_State **Dst, const zend_op *opline, uint32_t
if (op1_info & (MAY_BE_ANY|MAY_BE_REF)) {
mask = opline->extended_value;
- switch (mask) {
- case MAY_BE_NULL: type = IS_NULL; break;
- case MAY_BE_FALSE: type = IS_FALSE; break;
- case MAY_BE_TRUE: type = IS_TRUE; break;
- case MAY_BE_LONG: type = IS_LONG; break;
- case MAY_BE_DOUBLE: type = IS_DOUBLE; break;
- case MAY_BE_STRING: type = IS_STRING; break;
- case MAY_BE_ARRAY: type = IS_ARRAY; break;
- case MAY_BE_OBJECT: type = IS_OBJECT; break;
- default:
- type = 0;
- }
-
if (!(op1_info & MAY_BE_GUARD) && !(op1_info & (MAY_BE_ANY - mask))) {
| FREE_OP opline->op1_type, opline->op1, op1_info, 1, opline
if (exit_addr) {
@@ -10984,6 +10970,31 @@ static int zend_jit_type_check(dasm_State **Dst, const zend_op *opline, uint32_t
return 0;
}
} else {
+ bool invert = 0;
+ zend_uchar type;
+
+ switch (mask) {
+ case MAY_BE_NULL: type = IS_NULL; break;
+ case MAY_BE_FALSE: type = IS_FALSE; break;
+ case MAY_BE_TRUE: type = IS_TRUE; break;
+ case MAY_BE_LONG: type = IS_LONG; break;
+ case MAY_BE_DOUBLE: type = IS_DOUBLE; break;
+ case MAY_BE_STRING: type = IS_STRING; break;
+ case MAY_BE_ARRAY: type = IS_ARRAY; break;
+ case MAY_BE_OBJECT: type = IS_OBJECT; break;
+ case MAY_BE_ANY - MAY_BE_NULL: type = IS_NULL; invert = 1; break;
+ case MAY_BE_ANY - MAY_BE_FALSE: type = IS_FALSE; invert = 1; break;
+ case MAY_BE_ANY - MAY_BE_TRUE: type = IS_TRUE; invert = 1; break;
+ case MAY_BE_ANY - MAY_BE_LONG: type = IS_LONG; invert = 1; break;
+ case MAY_BE_ANY - MAY_BE_DOUBLE: type = IS_DOUBLE; invert = 1; break;
+ case MAY_BE_ANY - MAY_BE_STRING: type = IS_STRING; invert = 1; break;
+ case MAY_BE_ANY - MAY_BE_ARRAY: type = IS_ARRAY; invert = 1; break;
+ case MAY_BE_ANY - MAY_BE_OBJECT: type = IS_OBJECT; invert = 1; break;
+ case MAY_BE_ANY - MAY_BE_RESOURCE: type = IS_OBJECT; invert = 1; break;
+ default:
+ type = 0;
+ }
+
if (op1_info & MAY_BE_REF) {
| LOAD_ZVAL_ADDR r0, op1_addr
| ZVAL_DEREF r0, op1_info
@@ -11115,26 +11126,51 @@ static int zend_jit_type_check(dasm_State **Dst, const zend_op *opline, uint32_t
}
}
if (exit_addr) {
- if (smart_branch_opcode == ZEND_JMPNZ) {
- | je &exit_addr
+ if (invert) {
+ if (smart_branch_opcode == ZEND_JMPNZ) {
+ | jne &exit_addr
+ } else {
+ | je &exit_addr
+ }
} else {
- | jne &exit_addr
+ if (smart_branch_opcode == ZEND_JMPNZ) {
+ | je &exit_addr
+ } else {
+ | jne &exit_addr
+ }
}
} else if (smart_branch_opcode) {
- if (smart_branch_opcode == ZEND_JMPZ) {
- | jne =>target_label
- } else if (smart_branch_opcode == ZEND_JMPNZ) {
- | je =>target_label
- } else if (smart_branch_opcode == ZEND_JMPZNZ) {
- | jne =>target_label
- | jmp =>target_label2
+ if (invert) {
+ if (smart_branch_opcode == ZEND_JMPZ) {
+ | je =>target_label
+ } else if (smart_branch_opcode == ZEND_JMPNZ) {
+ | jne =>target_label
+ } else if (smart_branch_opcode == ZEND_JMPZNZ) {
+ | je =>target_label
+ | jmp =>target_label2
+ } else {
+ ZEND_UNREACHABLE();
+ }
} else {
- ZEND_UNREACHABLE();
+ if (smart_branch_opcode == ZEND_JMPZ) {
+ | jne =>target_label
+ } else if (smart_branch_opcode == ZEND_JMPNZ) {
+ | je =>target_label
+ } else if (smart_branch_opcode == ZEND_JMPZNZ) {
+ | jne =>target_label
+ | jmp =>target_label2
+ } else {
+ ZEND_UNREACHABLE();
+ }
}
} else {
zend_jit_addr res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
- | sete al
+ if (invert) {
+ | setne al
+ } else {
+ | sete al
+ }
| movzx eax, al
| add eax, 2
| SET_ZVAL_TYPE_INFO res_addr, eax