From: Dmitry Stogov Date: Tue, 23 Sep 2014 21:57:40 +0000 (+0400) Subject: Make QM_ASSIGN, JMP_SET and CAST return IS_TMP_VAR. X-Git-Tag: PRE_NATIVE_TLS_MERGE~158^2~48 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=58a41cf7957d63cb0ce398828ba7c1acc34bcd1f;p=php Make QM_ASSIGN, JMP_SET and CAST return IS_TMP_VAR. --- diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 3714b94a8f..8ad65587ca 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -483,8 +483,7 @@ void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */ && opline->result.var == op1->u.op.var) { if (opline->opcode == ZEND_FETCH_R || opline->opcode == ZEND_FETCH_DIM_R || - opline->opcode == ZEND_FETCH_OBJ_R || - opline->opcode == ZEND_QM_ASSIGN) { + opline->opcode == ZEND_FETCH_OBJ_R) { /* It's very rare and useless case. It's better to use additional FREE opcode and simplify the FETCH handlers their selves */ @@ -1708,7 +1707,9 @@ static zend_op *zend_emit_op_tmp(znode *result, zend_uchar opcode, znode *op1, z SET_NODE(opline->op2, op2); } - zend_make_tmp_result(result, opline TSRMLS_CC); + if (result) { + zend_make_tmp_result(result, opline TSRMLS_CC); + } return opline; } @@ -5259,7 +5260,7 @@ void zend_compile_cast(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC); - opline = zend_emit_op(result, ZEND_CAST, &expr_node, NULL TSRMLS_CC); + opline = zend_emit_op_tmp(result, ZEND_CAST, &expr_node, NULL TSRMLS_CC); opline->extended_value = ast->attr; } /* }}} */ @@ -5278,13 +5279,13 @@ static void zend_compile_shorthand_conditional(znode *result, zend_ast *ast TSRM zend_compile_expr(&cond_node, cond_ast TSRMLS_CC); opnum_jmp_set = get_next_op_number(CG(active_op_array)); - zend_emit_op(result, ZEND_JMP_SET, &cond_node, NULL TSRMLS_CC); + zend_emit_op_tmp(result, ZEND_JMP_SET, &cond_node, NULL TSRMLS_CC); zend_compile_expr(&false_node, false_ast TSRMLS_CC); opline_jmp_set = &CG(active_op_array)->opcodes[opnum_jmp_set]; opline_jmp_set->op2.opline_num = get_next_op_number(CG(active_op_array)) + 1; - opline_qm_assign = zend_emit_op(NULL, ZEND_QM_ASSIGN, &false_node, NULL TSRMLS_CC); + opline_qm_assign = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &false_node, NULL TSRMLS_CC); SET_NODE(opline_qm_assign->result, result); } /* }}} */ @@ -5311,7 +5312,7 @@ void zend_compile_conditional(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ zend_compile_expr(&true_node, true_ast TSRMLS_CC); opnum_qm_assign1 = get_next_op_number(CG(active_op_array)); - zend_emit_op(result, ZEND_QM_ASSIGN, &true_node, NULL TSRMLS_CC); + zend_emit_op_tmp(result, ZEND_QM_ASSIGN, &true_node, NULL TSRMLS_CC); opnum_jmp = zend_emit_jump(0 TSRMLS_CC); diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c index 3f3e72dc31..6a3f4e504d 100644 --- a/ext/opcache/Optimizer/pass1_5.c +++ b/ext/opcache/Optimizer/pass1_5.c @@ -91,7 +91,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRML literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); - zend_optimizer_replace_tmp_by_const(op_array, opline + 1, tv, &result TSRMLS_CC); + zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, tv, &result TSRMLS_CC); } break; @@ -101,6 +101,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRML opline->extended_value != IS_OBJECT && opline->extended_value != IS_RESOURCE) { /* cast of constant operand */ + zend_uchar type = opline->result_type; uint32_t tv = ZEND_RESULT(opline).var; /* temporary variable */ zval res; res = ZEND_OP1_LITERAL(opline); @@ -126,11 +127,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRML literal_dtor(&ZEND_OP1_LITERAL(opline)); MAKE_NOP(opline); - if (opline->result_type == IS_TMP_VAR) { - zend_optimizer_replace_tmp_by_const(op_array, opline + 1, tv, &res TSRMLS_CC); - } else /* if (opline->result_type == IS_VAR) */ { - zend_optimizer_replace_var_by_const(op_array, opline + 1, tv, &res TSRMLS_CC); - } + zend_optimizer_replace_by_const(op_array, opline + 1, type, tv, &res TSRMLS_CC); } else if (opline->extended_value == _IS_BOOL) { /* T = CAST(X, IS_BOOL) => T = BOOL(X) */ opline->opcode = ZEND_BOOL; @@ -157,7 +154,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRML literal_dtor(&ZEND_OP1_LITERAL(opline)); MAKE_NOP(opline); - zend_optimizer_replace_tmp_by_const(op_array, opline + 1, tv, &result TSRMLS_CC); + zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, tv, &result TSRMLS_CC); } break; @@ -251,7 +248,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRML literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); - zend_optimizer_replace_tmp_by_const(op_array, opline, tv, offset TSRMLS_CC); + zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, offset TSRMLS_CC); } EG(current_execute_data) = orig_execute_data; break; @@ -271,7 +268,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRML } literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); - zend_optimizer_replace_tmp_by_const(op_array, opline, tv, &c TSRMLS_CC); + zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &c TSRMLS_CC); } /* class constant */ @@ -332,7 +329,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRML } literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); - zend_optimizer_replace_tmp_by_const(op_array, opline, tv, &t TSRMLS_CC); + zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &t TSRMLS_CC); } } } @@ -388,7 +385,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRML func->module->type == MODULE_PERSISTENT) { zval t; ZVAL_BOOL(&t, 1); - if (zend_optimizer_replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) { + if (zend_optimizer_replace_by_const(op_array, opline + 3, IS_VAR, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) { literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); literal_dtor(&ZEND_OP1_LITERAL(opline + 1)); @@ -421,7 +418,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRML } } - if (zend_optimizer_replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) { + if (zend_optimizer_replace_by_const(op_array, opline + 3, IS_VAR, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) { literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); literal_dtor(&ZEND_OP1_LITERAL(opline + 1)); @@ -436,7 +433,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRML if (zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline + 1)), &t, 0 TSRMLS_CC)) { ZVAL_BOOL(&t, 1); - if (zend_optimizer_replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) { + if (zend_optimizer_replace_by_const(op_array, opline + 3, IS_VAR, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) { literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); literal_dtor(&ZEND_OP1_LITERAL(opline + 1)); @@ -450,7 +447,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRML zval t; if (zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline + 1)), &t, 1 TSRMLS_CC)) { - if (zend_optimizer_replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) { + if (zend_optimizer_replace_by_const(op_array, opline + 3, IS_VAR, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) { literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); literal_dtor(&ZEND_OP1_LITERAL(opline + 1)); @@ -465,7 +462,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRML zval t; ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline + 1))); - if (zend_optimizer_replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) { + if (zend_optimizer_replace_by_const(op_array, opline + 3, IS_VAR, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) { literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); literal_dtor(&ZEND_OP1_LITERAL(opline + 1)); @@ -481,7 +478,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRML zval t; ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline))); - zend_optimizer_replace_tmp_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC); + zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, ZEND_RESULT(opline).var, &t TSRMLS_CC); literal_dtor(&ZEND_OP1_LITERAL(opline)); MAKE_NOP(opline); } @@ -494,7 +491,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRML break; } ZVAL_TRUE(&c); - zend_optimizer_replace_tmp_by_const(op_array, opline, tv, &c TSRMLS_CC); + zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &c TSRMLS_CC); literal_dtor(&ZEND_OP1_LITERAL(opline)); MAKE_NOP(opline); } diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index f31ce38cfe..98030611ee 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -262,15 +262,16 @@ check_numeric: } } -int zend_optimizer_replace_var_by_const(zend_op_array *op_array, - zend_op *opline, - uint32_t var, - zval *val TSRMLS_DC) +int zend_optimizer_replace_by_const(zend_op_array *op_array, + zend_op *opline, + zend_uchar type, + uint32_t var, + zval *val TSRMLS_DC) { zend_op *end = op_array->opcodes + op_array->last; while (opline < end) { - if (ZEND_OP1_TYPE(opline) == IS_VAR && + if (ZEND_OP1_TYPE(opline) == type && ZEND_OP1(opline).var == var) { switch (opline->opcode) { case ZEND_FETCH_DIM_W: @@ -292,6 +293,25 @@ int zend_optimizer_replace_var_by_const(zend_op_array *op_array, opline->opcode = ZEND_SEND_VAL; } break; + /* In most cases IS_TMP_VAR operand may be used only once. + * The operands are usually destroyed by the opcode handler. + * ZEND_CASE is an exception, that keeps operand unchanged, + * and allows its reuse. The number of ZEND_CASE instructions + * usually terminated by ZEND_FREE that finally kills the value. + */ + case ZEND_CASE: { + zval old_val; + ZVAL_COPY_VALUE(&old_val, val); + zval_copy_ctor(val); + zend_optimizer_update_op1_const(op_array, opline, val TSRMLS_CC); + zval_dtor(&old_val); + opline++; + continue; + } + case ZEND_FREE: + MAKE_NOP(opline); + zval_dtor(val); + return 1; default: break; } @@ -299,7 +319,7 @@ int zend_optimizer_replace_var_by_const(zend_op_array *op_array, break; } - if (ZEND_OP2_TYPE(opline) == IS_VAR && + if (ZEND_OP2_TYPE(opline) == type && ZEND_OP2(opline).var == var) { switch (opline->opcode) { case ZEND_ASSIGN_REF: @@ -316,55 +336,6 @@ int zend_optimizer_replace_var_by_const(zend_op_array *op_array, return 1; } -void zend_optimizer_replace_tmp_by_const(zend_op_array *op_array, - zend_op *opline, - uint32_t var, - zval *val - TSRMLS_DC) -{ - zend_op *end = op_array->opcodes + op_array->last; - - while (opline < end) { - if (ZEND_OP1_TYPE(opline) == IS_TMP_VAR && - ZEND_OP1(opline).var == var) { - - /* In most cases IS_TMP_VAR operand may be used only once. - * The operands are usually destroyed by the opcode handler. - * ZEND_CASE is an exception, that keeps operand unchanged, - * and allows its reuse. The number of ZEND_CASE instructions - * usually terminated by ZEND_FREE that finally kills the value. - */ - if (opline->opcode == ZEND_CASE) { - zval old_val; - ZVAL_COPY_VALUE(&old_val, val); - zval_copy_ctor(val); - zend_optimizer_update_op1_const(op_array, opline, val TSRMLS_CC); - ZVAL_COPY_VALUE(val, &old_val); - } else if (opline->opcode == ZEND_FREE) { - MAKE_NOP(opline); - break; - } else { - zend_optimizer_update_op1_const(op_array, opline, val TSRMLS_CC); - val = NULL; - break; - } - } - - if (ZEND_OP2_TYPE(opline) == IS_TMP_VAR && - ZEND_OP2(opline).var == var) { - - zend_optimizer_update_op2_const(op_array, opline, val TSRMLS_CC); - /* TMP_VAR may be used only once */ - val = NULL; - break; - } - opline++; - } - if (val) { - zval_dtor(val); - } -} - static void zend_optimize(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS_DC) { diff --git a/ext/opcache/Optimizer/zend_optimizer_internal.h b/ext/opcache/Optimizer/zend_optimizer_internal.h index ac87cf9f35..ba91b147c9 100644 --- a/ext/opcache/Optimizer/zend_optimizer_internal.h +++ b/ext/opcache/Optimizer/zend_optimizer_internal.h @@ -112,14 +112,11 @@ void zend_optimizer_update_op1_const(zend_op_array *op_array, void zend_optimizer_update_op2_const(zend_op_array *op_array, zend_op *opline, zval *val TSRMLS_DC); -int zend_optimizer_replace_var_by_const(zend_op_array *op_array, - zend_op *opline, - uint32_t var, - zval *val TSRMLS_DC); -void zend_optimizer_replace_tmp_by_const(zend_op_array *op_array, - zend_op *opline, - uint32_t var, - zval *val TSRMLS_DC); +int zend_optimizer_replace_by_const(zend_op_array *op_array, + zend_op *opline, + zend_uchar type, + uint32_t var, + zval *val TSRMLS_DC); void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS_DC); void zend_optimizer_pass2(zend_op_array *op_array TSRMLS_DC);