mirror of
https://github.com/php/php-src.git
synced 2024-09-23 02:47:26 +00:00
Fixed optimization patterns
This commit is contained in:
parent
d146d15003
commit
0a6bb2dfd4
@ -940,11 +940,8 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
|
||||
}
|
||||
|
||||
VAR_UNSET(opline->op1);
|
||||
if (ZEND_OP1_TYPE(src) == IS_UNUSED) {
|
||||
/* 5.3 may use IS_UNUSED as first argument to ZEND_ADD_... */
|
||||
if (opline->opcode != ZEND_CONCAT) {
|
||||
opline->opcode = ZEND_ADD_STRING;
|
||||
} else {
|
||||
opline->opcode = ZEND_CONCAT;
|
||||
}
|
||||
COPY_NODE(opline->op1, src->op1);
|
||||
old_len = Z_STRLEN(ZEND_OP2_LITERAL(src));
|
||||
@ -1039,45 +1036,47 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
|
||||
VAR_UNSET(opline->op1);
|
||||
COPY_NODE(opline->op1, src->op1);
|
||||
MAKE_NOP(src);
|
||||
} else if ((opline->opcode == ZEND_ADD_STRING ||
|
||||
opline->opcode == ZEND_ADD_CHAR ||
|
||||
opline->opcode == ZEND_ADD_VAR ||
|
||||
opline->opcode == ZEND_CONCAT) &&
|
||||
ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
|
||||
VAR_SOURCE(opline->op1) &&
|
||||
VAR_SOURCE(opline->op1)->opcode == ZEND_CONCAT &&
|
||||
ZEND_OP2_TYPE(VAR_SOURCE(opline->op1)) == IS_CONST &&
|
||||
Z_TYPE(ZEND_OP2_LITERAL(VAR_SOURCE(opline->op1))) == IS_STRING &&
|
||||
Z_STRLEN(ZEND_OP2_LITERAL(VAR_SOURCE(opline->op1))) == 0) {
|
||||
/* convert T = CONCAT(X,''), T = ADD_STRING(T, Y) to T = CONCAT(X,Y) */
|
||||
zend_op *src = VAR_SOURCE(opline->op1);
|
||||
VAR_UNSET(opline->op1);
|
||||
COPY_NODE(opline->op1, src->op1);
|
||||
if (opline->opcode == ZEND_ADD_CHAR) {
|
||||
char c = (char)Z_LVAL(ZEND_OP2_LITERAL(opline));
|
||||
ZVAL_STRINGL(&ZEND_OP2_LITERAL(opline), &c, 1);
|
||||
} else if (opline->opcode == ZEND_CONCAT) {
|
||||
if ((ZEND_OP1_TYPE(opline) & (IS_TMP_VAR|IS_VAR)) &&
|
||||
VAR_SOURCE(opline->op1) &&
|
||||
VAR_SOURCE(opline->op1)->opcode == ZEND_CAST &&
|
||||
VAR_SOURCE(opline->op1)->extended_value == IS_STRING) {
|
||||
/* convert T1 = CAST(STRING, X), T2 = CONCAT(T1, Y) to T2 = CONCAT(X,Y) */
|
||||
zend_op *src = VAR_SOURCE(opline->op1);
|
||||
VAR_UNSET(opline->op1);
|
||||
COPY_NODE(opline->op1, src->op1);
|
||||
MAKE_NOP(src);
|
||||
}
|
||||
opline->opcode = ZEND_CONCAT;
|
||||
literal_dtor(&ZEND_OP2_LITERAL(src)); /* will take care of empty_string too */
|
||||
MAKE_NOP(src);
|
||||
} else if ((opline->opcode == ZEND_ADD_STRING ||
|
||||
opline->opcode == ZEND_ADD_CHAR ||
|
||||
opline->opcode == ZEND_ADD_VAR ||
|
||||
opline->opcode == ZEND_CONCAT) &&
|
||||
(ZEND_OP1_TYPE(opline) & (IS_TMP_VAR|IS_VAR)) &&
|
||||
VAR_SOURCE(opline->op1) &&
|
||||
VAR_SOURCE(opline->op1)->opcode == ZEND_CAST &&
|
||||
VAR_SOURCE(opline->op1)->extended_value == IS_STRING) {
|
||||
/* convert T1 = CAST(STRING, X), T2 = CONCAT(T1, Y) to T2 = CONCAT(X,Y) */
|
||||
zend_op *src = VAR_SOURCE(opline->op1);
|
||||
VAR_UNSET(opline->op1);
|
||||
COPY_NODE(opline->op1, src->op1);
|
||||
if (opline->opcode == ZEND_ADD_CHAR) {
|
||||
char c = (char)Z_LVAL(ZEND_OP2_LITERAL(opline));
|
||||
ZVAL_STRINGL(&ZEND_OP2_LITERAL(opline), &c, 1);
|
||||
if ((ZEND_OP2_TYPE(opline) & (IS_TMP_VAR|IS_VAR)) &&
|
||||
VAR_SOURCE(opline->op2) &&
|
||||
VAR_SOURCE(opline->op2)->opcode == ZEND_CAST &&
|
||||
VAR_SOURCE(opline->op2)->extended_value == IS_STRING) {
|
||||
/* convert T1 = CAST(STRING, X), T2 = CONCAT(Y, T1) to T2 = CONCAT(Y,X) */
|
||||
zend_op *src = VAR_SOURCE(opline->op2);
|
||||
VAR_UNSET(opline->op2);
|
||||
COPY_NODE(opline->op2, src->op1);
|
||||
MAKE_NOP(src);
|
||||
}
|
||||
if (ZEND_OP1_TYPE(opline) == IS_CONST &&
|
||||
Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
|
||||
Z_STRLEN(ZEND_OP1_LITERAL(opline)) == 0) {
|
||||
/* convert CONCAT('', X) => CAST(STRING, X) */
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
opline->opcode = ZEND_CAST;
|
||||
opline->extended_value = IS_STRING;
|
||||
COPY_NODE(opline->op1, opline->op2);
|
||||
opline->op2_type = IS_UNUSED;
|
||||
opline->op2.var = 0;
|
||||
} else if (ZEND_OP2_TYPE(opline) == IS_CONST &&
|
||||
Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING &&
|
||||
Z_STRLEN(ZEND_OP2_LITERAL(opline)) == 0) {
|
||||
/* convert CONCAT(X, '') => CAST(STRING, X) */
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
opline->opcode = ZEND_CAST;
|
||||
opline->extended_value = IS_STRING;
|
||||
opline->op2_type = IS_UNUSED;
|
||||
opline->op2.var = 0;
|
||||
}
|
||||
opline->opcode = ZEND_CONCAT;
|
||||
MAKE_NOP(src);
|
||||
} else if (opline->opcode == ZEND_QM_ASSIGN &&
|
||||
ZEND_OP1_TYPE(opline) == ZEND_RESULT_TYPE(opline) &&
|
||||
ZEND_OP1(opline).var == ZEND_RESULT(opline).var) {
|
||||
|
@ -87,11 +87,12 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
break;
|
||||
}
|
||||
EG(error_reporting) = er;
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
|
||||
zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, tv, &result);
|
||||
if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, tv, &result)) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -124,10 +125,10 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
break;
|
||||
}
|
||||
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
|
||||
zend_optimizer_replace_by_const(op_array, opline + 1, type, tv, &res);
|
||||
if (zend_optimizer_replace_by_const(op_array, opline + 1, type, tv, &res)) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
}
|
||||
} else if (opline->extended_value == _IS_BOOL) {
|
||||
/* T = CAST(X, IS_BOOL) => T = BOOL(X) */
|
||||
opline->opcode = ZEND_BOOL;
|
||||
@ -151,10 +152,11 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
break;
|
||||
}
|
||||
EG(error_reporting) = er;
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
|
||||
zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, tv, &result);
|
||||
if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, tv, &result)) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -190,6 +192,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
last_op = next_op;
|
||||
final_length += (requires_conversion? 1 : Z_STRLEN(ZEND_OP2_LITERAL(opline)));
|
||||
str = zend_string_alloc(final_length, 0);
|
||||
str->len = final_length;
|
||||
ptr = str->val;
|
||||
ptr[final_length] = '\0';
|
||||
if (requires_conversion) { /* ZEND_ADD_CHAR */
|
||||
@ -201,11 +204,10 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
ptr++;
|
||||
} else { /* ZEND_ADD_STRING */
|
||||
memcpy(ptr, Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)));
|
||||
zend_string_release(Z_STR(ZEND_OP2_LITERAL(opline)));
|
||||
Z_STR(ZEND_OP2_LITERAL(opline)) = str;
|
||||
ptr += Z_STRLEN(ZEND_OP2_LITERAL(opline));
|
||||
zend_string_release(Z_STR(ZEND_OP2_LITERAL(opline)));
|
||||
ZVAL_NEW_STR(&ZEND_OP2_LITERAL(opline), str);
|
||||
}
|
||||
Z_STRLEN(ZEND_OP2_LITERAL(opline)) = final_length;
|
||||
next_op = opline + 1;
|
||||
while (next_op < last_op) {
|
||||
if (next_op->opcode == ZEND_ADD_STRING) {
|
||||
@ -246,9 +248,10 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) {
|
||||
uint32_t tv = ZEND_RESULT(opline).var;
|
||||
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, offset);
|
||||
if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, offset)) {
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
}
|
||||
}
|
||||
EG(current_execute_data) = orig_execute_data;
|
||||
break;
|
||||
@ -269,9 +272,10 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
if (Z_TYPE(c) == IS_CONSTANT_AST) {
|
||||
break;
|
||||
}
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &c);
|
||||
if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &c)) {
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
}
|
||||
}
|
||||
|
||||
/* class constant */
|
||||
@ -333,9 +337,10 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
} else {
|
||||
MAKE_NOP((opline - 1));
|
||||
}
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &t);
|
||||
if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &t)) {
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -559,9 +564,10 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
zval t;
|
||||
|
||||
ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline)));
|
||||
zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, ZEND_RESULT(opline).var, &t);
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, ZEND_RESULT(opline).var, &t)) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_DEFINED:
|
||||
@ -572,9 +578,10 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
break;
|
||||
}
|
||||
ZVAL_TRUE(&c);
|
||||
zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &c);
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &c)) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_DECLARE_CONST:
|
||||
|
@ -158,6 +158,9 @@ void zend_optimizer_update_op2_const(zend_op_array *op_array,
|
||||
Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->cache_size;
|
||||
op_array->cache_size += sizeof(void*);
|
||||
return;
|
||||
} else if (opline->opcode == ZEND_ADD_VAR) {
|
||||
convert_to_string(val);
|
||||
opline->opcode = ZEND_ADD_STRING;
|
||||
}
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
|
||||
if (Z_TYPE_P(val) == IS_STRING) {
|
||||
@ -306,6 +309,7 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
|
||||
case ZEND_SEND_VAR_NO_REF:
|
||||
if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) {
|
||||
if (opline->extended_value & ZEND_ARG_SEND_BY_REF) {
|
||||
zval_dtor(val);
|
||||
return 0;
|
||||
}
|
||||
opline->extended_value = 0;
|
||||
@ -374,6 +378,7 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
|
||||
ZEND_OP2(opline).var == var) {
|
||||
switch (opline->opcode) {
|
||||
case ZEND_ASSIGN_REF:
|
||||
zval_dtor(val);
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user