summaryrefslogtreecommitdiff
path: root/ext/opcache/jit/zend_jit_trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/opcache/jit/zend_jit_trace.c')
-rw-r--r--ext/opcache/jit/zend_jit_trace.c92
1 files changed, 90 insertions, 2 deletions
diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c
index 30aa0a71fc..3612a60b3a 100644
--- a/ext/opcache/jit/zend_jit_trace.c
+++ b/ext/opcache/jit/zend_jit_trace.c
@@ -1422,17 +1422,31 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
} else if (orig_op1_type != IS_UNKNOWN
&& (orig_op1_type & IS_TRACE_INDIRECT)
&& opline->result_type == IS_UNUSED) {
-// ADD_OP1_DATA_TRACE_GUARD();
+ if (opline->opcode == ZEND_ASSIGN_DIM_OP) {
+ ADD_OP1_DATA_TRACE_GUARD();
+ }
ADD_OP2_TRACE_GUARD();
}
break;
+ case ZEND_ASSIGN_OBJ_OP:
+ if (opline->extended_value == ZEND_POW
+ || opline->extended_value == ZEND_DIV) {
+ // TODO: check for division by zero ???
+ break;
+ }
+ if (opline->result_type != IS_UNUSED) {
+ break;
+ }
+ /* break missing intentionally */
case ZEND_ASSIGN_OBJ:
if (opline->op2_type != IS_CONST
|| Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
|| Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
break;
}
-// ADD_OP1_DATA_TRACE_GUARD();
+ if (opline->opcode == ZEND_ASSIGN_OBJ_OP) {
+ ADD_OP1_DATA_TRACE_GUARD();
+ }
ADD_OP1_TRACE_GUARD();
break;
case ZEND_IS_EQUAL:
@@ -3718,6 +3732,80 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
goto jit_failure;
}
goto done;
+ case ZEND_ASSIGN_OBJ_OP:
+ if (opline->extended_value == ZEND_POW
+ || opline->extended_value == ZEND_DIV) {
+ // TODO: check for division by zero ???
+ break;
+ }
+ if (opline->result_type != IS_UNUSED) {
+ break;
+ }
+ if (opline->op2_type != IS_CONST
+ || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
+ || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
+ break;
+ }
+ ce = NULL;
+ ce_is_instanceof = 0;
+ delayed_fetch_this = 0;
+ op1_indirect = 0;
+ if (opline->op1_type == IS_UNUSED) {
+ op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
+ ce = op_array->scope;
+ ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
+ op1_addr = 0;
+ } else {
+ if (ssa_op->op1_use >= 0) {
+ delayed_fetch_this = ssa->var_info[ssa_op->op1_use].delayed_fetch_this;
+ }
+ op1_info = OP1_INFO();
+ if (!(op1_info & MAY_BE_OBJECT)) {
+ break;
+ }
+ op1_addr = OP1_REG_ADDR();
+ 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(&dasm_state, opline, orig_op1_type,
+ &op1_info, &op1_addr, !ssa->var_info[ssa_op->op1_use].indirect_reference)) {
+ goto jit_failure;
+ }
+ }
+ }
+ if (orig_op1_type != IS_UNKNOWN
+ && (orig_op1_type & IS_TRACE_REFERENCE)) {
+ if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
+ !ssa->var_info[ssa_op->op1_use].guarded_reference, 1)) {
+ goto jit_failure;
+ }
+ if (opline->op1_type == IS_CV
+ && zend_jit_var_may_alias(op_array, op_array_ssa, EX_VAR_TO_NUM(opline->op1.var)) == NO_ALIAS) {
+ ssa->var_info[ssa_op->op1_use].guarded_reference = 1;
+ }
+ } else {
+ CHECK_OP1_TRACE_TYPE();
+ }
+ if (ssa->var_info && ssa->ops) {
+ if (ssa_op->op1_use >= 0) {
+ zend_ssa_var_info *op1_ssa = ssa->var_info + ssa_op->op1_use;
+ if (op1_ssa->ce && !op1_ssa->ce->create_object) {
+ ce = op1_ssa->ce;
+ ce_is_instanceof = op1_ssa->is_instanceof;
+ }
+ }
+ }
+ }
+ op1_data_info = OP1_DATA_INFO();
+ CHECK_OP1_DATA_TRACE_TYPE();
+ if (!zend_jit_assign_obj_op(&dasm_state, opline, op_array, ssa, ssa_op,
+ op1_info, op1_addr, op1_data_info, OP1_DATA_RANGE(),
+ op1_indirect, ce, ce_is_instanceof, delayed_fetch_this, op1_ce,
+ zend_may_throw(opline, ssa_op, op_array, ssa))) {
+ goto jit_failure;
+ }
+ goto done;
case ZEND_ASSIGN_OBJ:
if (opline->op2_type != IS_CONST
|| Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING