diff options
author | Dmitry Stogov <dmitry@zend.com> | 2021-03-25 23:48:08 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2021-03-25 23:48:08 +0300 |
commit | 7b2b9b40797e3f071f653bd64706dfdcaf548f90 (patch) | |
tree | d0b4f35780f80d08911d710745d34e3504f63c17 | |
parent | aa45eedef0ded065f2f6ec33250747ad50558527 (diff) | |
download | php-git-7b2b9b40797e3f071f653bd64706dfdcaf548f90.tar.gz |
Improved JIT for TYPE_CHECK opcode
-rw-r--r-- | ext/opcache/jit/zend_jit_trace.c | 14 | ||||
-rw-r--r-- | ext/opcache/jit/zend_jit_x86.dasc | 88 |
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 |