From: Dmitry Stogov Date: Wed, 2 Sep 2020 21:51:43 +0000 (+0300) Subject: JIT for FETCH_CONSTANT X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=91edb907676805bc4fad3ebc758dd6d797c92a63;p=php JIT for FETCH_CONSTANT --- diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index ea5bbfb339..56260c9105 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -2982,6 +2982,11 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op goto jit_failure; } goto done; + case ZEND_FETCH_CONSTANT: + if (!zend_jit_fetch_constant(&dasm_state, opline)) { + goto jit_failure; + } + goto done; default: break; } diff --git a/ext/opcache/jit/zend_jit_disasm_x86.c b/ext/opcache/jit/zend_jit_disasm_x86.c index ce8eec6ebf..bd737fa669 100644 --- a/ext/opcache/jit/zend_jit_disasm_x86.c +++ b/ext/opcache/jit/zend_jit_disasm_x86.c @@ -459,6 +459,7 @@ static int zend_jit_disasm_init(void) REGISTER_HELPER(zend_runtime_jit); REGISTER_HELPER(zend_jit_hot_func); REGISTER_HELPER(zend_jit_check_constant); + REGISTER_HELPER(zend_jit_get_constant); REGISTER_HELPER(zend_jit_array_free); REGISTER_HELPER(zend_jit_zval_array_dup); REGISTER_HELPER(zend_jit_add_arrays_helper); diff --git a/ext/opcache/jit/zend_jit_internal.h b/ext/opcache/jit/zend_jit_internal.h index 1f4b36cb62..bcbafad147 100644 --- a/ext/opcache/jit/zend_jit_internal.h +++ b/ext/opcache/jit/zend_jit_internal.h @@ -130,8 +130,8 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_counter_helper(ZEND_OPCODE_H void ZEND_FASTCALL zend_jit_copy_extra_args_helper(EXECUTE_DATA_D); zend_bool ZEND_FASTCALL zend_jit_deprecated_helper(OPLINE_D); -void ZEND_FASTCALL zend_jit_get_constant(const zval *key, uint32_t flags); -int ZEND_FASTCALL zend_jit_check_constant(const zval *key); +int ZEND_FASTCALL zend_jit_get_constant(const zval *key, uint32_t flags); +int ZEND_FASTCALL zend_jit_check_constant(const zval *key); /* Tracer */ #define zend_jit_opline_hash(opline) \ diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 66183d97cd..7d3c7be1aa 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -4574,6 +4574,11 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par goto jit_failure; } goto done; + case ZEND_FETCH_CONSTANT: + if (!zend_jit_fetch_constant(&dasm_state, opline)) { + goto jit_failure; + } + goto done; case ZEND_INIT_METHOD_CALL: case ZEND_INIT_DYNAMIC_CALL: if (!zend_jit_trace_handler(&dasm_state, op_array, opline, zend_may_throw(opline, ssa_op, op_array, ssa), p + 1)) { diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index 729c64073d..09a9981184 100644 --- a/ext/opcache/jit/zend_jit_vm_helpers.c +++ b/ext/opcache/jit/zend_jit_vm_helpers.c @@ -278,9 +278,9 @@ static zend_always_inline int _zend_quick_get_constant( return SUCCESS; } -void ZEND_FASTCALL zend_jit_get_constant(const zval *key, uint32_t flags) +int ZEND_FASTCALL zend_jit_get_constant(const zval *key, uint32_t flags) { - _zend_quick_get_constant(key, flags, 0); + return _zend_quick_get_constant(key, flags, 0); } int ZEND_FASTCALL zend_jit_check_constant(const zval *key) diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index f19777ab3c..a863fed69e 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -12651,15 +12651,50 @@ static int zend_jit_fe_fetch(dasm_State **Dst, const zend_op *opline, const zend } else { | // ZVAL_COPY(res, value); | ZVAL_COPY_VALUE var_addr, -1, val_addr, val_info, ZREG_R0, ZREG_FCARG1a - if (val_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) { - | TRY_ADDREF op1_info, ah, FCARG1a - } + | TRY_ADDREF val_info, ah, FCARG1a } } return 1; } +static int zend_jit_fetch_constant(dasm_State **Dst, const zend_op *opline) +{ + zval *zv = RT_CONSTANT(opline, opline->op2) + 1; + zend_jit_addr res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var); + zend_jit_addr const_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG1a, 0); + + | // c = CACHED_PTR(opline->extended_value); + | mov FCARG1a, EX->run_time_cache + | mov FCARG1a, aword [FCARG1a + opline->extended_value] + | // if (c != NULL) + | test FCARG1a, FCARG1a + | jz >9 + | // if (!IS_SPECIAL_CACHE_VAL(c)) + | test FCARG1a, CACHE_SPECIAL + | jnz >9 + | // ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value); (no dup) + | ZVAL_COPY_VALUE res_addr, MAY_BE_ANY, const_addr, MAY_BE_ANY, ZREG_R0, ZREG_FCARG2a + | TRY_ADDREF MAY_BE_ANY, ah, FCARG2a + |8: + + |.cold_code + |9: + | // SAVE_OPLINE(); + | SAVE_VALID_OPLINE opline, r0 + | // zend_quick_get_constant(RT_CONSTANT(opline, opline->op2) + 1, opline->op1.num OPLINE_CC EXECUTE_DATA_CC); + | LOAD_ADDR FCARG1a, zv + | mov FCARG2a, opline->op1.num + | EXT_CALL zend_jit_get_constant, r0 + | // ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + | test r0, r0 + | jz <8 + | jmp ->exception_handler + |.code + + return 1; +} + 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, 0);