&& 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 */
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;
}
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;
}
/* }}} */
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);
}
/* }}} */
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);
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;
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);
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;
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;
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;
}
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 */
}
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);
}
}
}
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));
}
}
- 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));
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));
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));
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));
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);
}
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);
}
}
}
-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:
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;
}
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:
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)
{