From 8e49e1e4d11423a9a6c87f2541c463839f79f053 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 10 Oct 2024 15:06:19 +0300 Subject: [PATCH] JIT support for ASSIGN_DIM[_OP] with IS_VAR op1 --- ext/opcache/jit/zend_jit.c | 4 ++-- ext/opcache/jit/zend_jit_ir.c | 11 ++++++++++- ext/opcache/jit/zend_jit_trace.c | 15 +++++++-------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 63feb78519e03..0a3f107bb89dc 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -1741,7 +1741,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op break; } if (!zend_jit_assign_dim_op(&ctx, opline, - OP1_INFO(), OP1_DEF_INFO(), OP1_REG_ADDR(), + OP1_INFO(), OP1_DEF_INFO(), OP1_REG_ADDR(), 0, OP2_INFO(), (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0, (opline->op2_type != IS_UNUSED) ? OP2_RANGE() : NULL, OP1_DATA_INFO(), OP1_DATA_REG_ADDR(), OP1_DATA_RANGE(), IS_UNKNOWN, @@ -1757,7 +1757,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op break; } if (!zend_jit_assign_dim(&ctx, opline, - OP1_INFO(), OP1_REG_ADDR(), + OP1_INFO(), OP1_REG_ADDR(), 0, OP2_INFO(), (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0, (opline->op2_type != IS_UNUSED) ? OP2_RANGE() : NULL, OP1_DATA_INFO(), OP1_DATA_REG_ADDR(), diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 73b416f959905..7846731d4204d 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -13179,6 +13179,7 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit, const zend_op *opline, uint32_t op1_info, zend_jit_addr op1_addr, + bool op1_indirect, uint32_t op2_info, zend_jit_addr op2_addr, zend_ssa_range *op2_range, @@ -13271,8 +13272,8 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit, // JIT: value = zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE); if (opline->op1_type == IS_VAR && Z_MODE(op3_addr) != IS_REG + && opline->result_type == IS_UNUSED && (res_addr == 0 || Z_MODE(res_addr) != IS_REG)) { - ZEND_ASSERT(opline->result_type == IS_UNUSED); if (!zend_jit_assign_to_variable_call(jit, opline, var_addr, var_addr, var_info, -1, (opline+1)->op1_type, op3_addr, val_info, res_addr, 0)) { return 0; } @@ -13339,6 +13340,10 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit, ir_MERGE_list(end_inputs); jit_FREE_OP(jit, opline->op2_type, opline->op2, op2_info, opline); + if (!op1_indirect) { + jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, opline); + } + if (may_throw) { zend_jit_check_exception(jit); } @@ -13351,6 +13356,7 @@ static int zend_jit_assign_dim_op(zend_jit_ctx *jit, uint32_t op1_info, uint32_t op1_def_info, zend_jit_addr op1_addr, + bool op1_indirect, uint32_t op2_info, zend_jit_addr op2_addr, zend_ssa_range *op2_range, @@ -13549,6 +13555,9 @@ static int zend_jit_assign_dim_op(zend_jit_ctx *jit, jit_FREE_OP(jit, (opline+1)->op1_type, (opline+1)->op1, op1_data_info, NULL); jit_FREE_OP(jit, opline->op2_type, opline->op2, op2_info, NULL); + if (!op1_indirect) { + jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, NULL); + } if (may_throw) { zend_jit_check_exception(jit); } diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index be4fe750541e6..02d2e62ccf4ff 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -4697,15 +4697,15 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par } op1_info = OP1_INFO(); op1_addr = OP1_REG_ADDR(); + op1_indirect = 0; if (opline->op1_type == IS_VAR) { if (orig_op1_type != IS_UNKNOWN && (orig_op1_type & IS_TRACE_INDIRECT)) { + op1_indirect = 1; if (!zend_jit_fetch_indirect_var(&ctx, opline, orig_op1_type, &op1_info, &op1_addr, !ssa->var_info[ssa_op->op1_use].indirect_reference)) { goto jit_failure; } - } else { - break; } } if (orig_op1_type != IS_UNKNOWN @@ -4727,7 +4727,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par CHECK_OP1_DATA_TRACE_TYPE(); op1_def_info = OP1_DEF_INFO(); if (!zend_jit_assign_dim_op(&ctx, opline, - op1_info, op1_def_info, op1_addr, + op1_info, op1_def_info, op1_addr, op1_indirect, op2_info, (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0, (opline->op2_type != IS_UNUSED) ? OP2_RANGE() : NULL, op1_data_info, OP1_DATA_REG_ADDR(), OP1_DATA_RANGE(), val_type, @@ -5009,6 +5009,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par case ZEND_ASSIGN_DIM: op1_info = OP1_INFO(); op1_addr = OP1_REG_ADDR(); + op1_indirect = 0; if (opline->op1_type == IS_CV && (opline+1)->op1_type == IS_CV && (opline+1)->op1.var == opline->op1.var) { @@ -5017,14 +5018,12 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par } if (opline->op1_type == IS_VAR) { if (orig_op1_type != IS_UNKNOWN - && (orig_op1_type & IS_TRACE_INDIRECT) - && opline->result_type == IS_UNUSED) { + && (orig_op1_type & IS_TRACE_INDIRECT)) { + op1_indirect = 1; if (!zend_jit_fetch_indirect_var(&ctx, opline, orig_op1_type, &op1_info, &op1_addr, !ssa->var_info[ssa_op->op1_use].indirect_reference)) { goto jit_failure; } - } else { - break; } } if (orig_op1_type != IS_UNKNOWN @@ -5045,7 +5044,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par op1_data_info = OP1_DATA_INFO(); CHECK_OP1_DATA_TRACE_TYPE(); if (!zend_jit_assign_dim(&ctx, opline, - op1_info, op1_addr, + op1_info, op1_addr, op1_indirect, op2_info, (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0, (opline->op2_type != IS_UNUSED) ? OP2_RANGE() : NULL, op1_data_info, OP1_DATA_REG_ADDR(),