mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
Separate constants propagation code shatred between "first" and "block" passes into helper functions.
This commit is contained in:
parent
816669af0c
commit
6276268b77
@ -194,6 +194,8 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
|
||||
VAR_SOURCE(op1) = NULL;
|
||||
literal_dtor(&ZEND_OP1_LITERAL(src));
|
||||
MAKE_NOP(src);
|
||||
} else {
|
||||
zval_ptr_dtor_nogc(&c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -215,6 +217,8 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
|
||||
VAR_SOURCE(op2) = NULL;
|
||||
literal_dtor(&ZEND_OP1_LITERAL(src));
|
||||
MAKE_NOP(src);
|
||||
} else {
|
||||
zval_ptr_dtor_nogc(&c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -390,10 +394,6 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
|
||||
Tsource[VAR_NUM(opline->op1.var)] = NULL;
|
||||
break;
|
||||
}
|
||||
if (opline->op1_type == IS_CONST &&
|
||||
opline->op2_type == IS_CONST) {
|
||||
break;
|
||||
}
|
||||
/* break missing intentionally */
|
||||
|
||||
case ZEND_IS_EQUAL:
|
||||
@ -723,59 +723,56 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
|
||||
if (opline->op1_type == IS_CONST &&
|
||||
opline->op2_type == IS_CONST) {
|
||||
/* evaluate constant expressions */
|
||||
binary_op_type binary_op;
|
||||
zval result;
|
||||
int er;
|
||||
|
||||
optimize_constant_binary_op:
|
||||
binary_op = get_binary_op(opline->opcode);
|
||||
if ((opline->opcode == ZEND_DIV || opline->opcode == ZEND_MOD) &&
|
||||
zval_get_long(&ZEND_OP2_LITERAL(opline)) == 0) {
|
||||
SET_VAR_SOURCE(opline);
|
||||
opline++;
|
||||
continue;
|
||||
} else if ((opline->opcode == ZEND_SL || opline->opcode == ZEND_SR) &&
|
||||
zval_get_long(&ZEND_OP2_LITERAL(opline)) < 0) {
|
||||
SET_VAR_SOURCE(opline);
|
||||
opline++;
|
||||
continue;
|
||||
} else if (zend_binary_op_produces_numeric_string_error(opline->opcode, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline))) {
|
||||
SET_VAR_SOURCE(opline);
|
||||
opline++;
|
||||
continue;
|
||||
}
|
||||
er = EG(error_reporting);
|
||||
EG(error_reporting) = 0;
|
||||
if (binary_op(&result, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)) == SUCCESS) {
|
||||
if (zend_optimizer_eval_binary_op(&result, opline->opcode, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)) == SUCCESS) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
SET_UNUSED(opline->op2);
|
||||
zend_optimizer_update_op1_const(op_array, opline, &result);
|
||||
}
|
||||
EG(error_reporting) = er;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_BW_NOT:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
/* evaluate constant unary ops */
|
||||
unary_op_type unary_op;
|
||||
zval result;
|
||||
|
||||
optimize_const_unary_op:
|
||||
unary_op = get_unary_op(opline->opcode);
|
||||
if (unary_op) {
|
||||
unary_op(&result, &ZEND_OP1_LITERAL(opline));
|
||||
if (zend_optimizer_eval_unary_op(&result, opline->opcode, &ZEND_OP1_LITERAL(opline)) == SUCCESS) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
} else {
|
||||
/* BOOL */
|
||||
ZVAL_COPY_VALUE(&result, &ZEND_OP1_LITERAL(opline));
|
||||
convert_to_boolean(&result);
|
||||
ZVAL_NULL(&ZEND_OP1_LITERAL(opline));
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
zend_optimizer_update_op1_const(op_array, opline, &result);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_CAST:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
/* cast of constant operand */
|
||||
zval result;
|
||||
|
||||
if (zend_optimizer_eval_cast(&result, opline->extended_value, &ZEND_OP1_LITERAL(opline)) == SUCCESS) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
opline->extended_value = 0;
|
||||
zend_optimizer_update_op1_const(op_array, opline, &result);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_STRLEN:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
zval result;
|
||||
|
||||
if (zend_optimizer_eval_strlen(&result, &ZEND_OP1_LITERAL(opline)) == SUCCESS) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
zend_optimizer_update_op1_const(op_array, opline, &result);
|
||||
}
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
zend_optimizer_update_op1_const(op_array, opline, &result);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -68,79 +68,45 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
case ZEND_BW_XOR:
|
||||
case ZEND_BOOL_XOR:
|
||||
case ZEND_SPACESHIP:
|
||||
case ZEND_CASE:
|
||||
if (opline->op1_type == IS_CONST &&
|
||||
opline->op2_type == IS_CONST) {
|
||||
/* binary operation with constant operands */
|
||||
binary_op_type binary_op = get_binary_op(opline->opcode);
|
||||
uint32_t tv = opline->result.var; /* temporary variable */
|
||||
zval result;
|
||||
int er;
|
||||
|
||||
if ((opline->opcode == ZEND_DIV || opline->opcode == ZEND_MOD) &&
|
||||
zval_get_long(&ZEND_OP2_LITERAL(opline)) == 0) {
|
||||
/* div by 0 */
|
||||
break;
|
||||
} else if ((opline->opcode == ZEND_SL || opline->opcode == ZEND_SR) &&
|
||||
zval_get_long(&ZEND_OP2_LITERAL(opline)) < 0) {
|
||||
/* shift by negative number */
|
||||
break;
|
||||
} else if (zend_binary_op_produces_numeric_string_error(opline->opcode, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline))) {
|
||||
/* produces numeric string E_NOTICE/E_WARNING */
|
||||
break;
|
||||
}
|
||||
er = EG(error_reporting);
|
||||
EG(error_reporting) = 0;
|
||||
/* evaluate constant expression */
|
||||
if (binary_op(&result, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)) != SUCCESS) {
|
||||
EG(error_reporting) = er;
|
||||
break;
|
||||
}
|
||||
EG(error_reporting) = er;
|
||||
|
||||
if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, tv, &result)) {
|
||||
if (zend_optimizer_eval_binary_op(&result, opline->opcode, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)) == SUCCESS) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, opline->result.var, &result)) {
|
||||
MAKE_NOP(opline);
|
||||
} else {
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
SET_UNUSED(opline->op2);
|
||||
zend_optimizer_update_op1_const(op_array, opline, &result);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_CAST:
|
||||
if (opline->op1_type == IS_CONST &&
|
||||
opline->extended_value != IS_ARRAY &&
|
||||
opline->extended_value != IS_OBJECT &&
|
||||
opline->extended_value != IS_RESOURCE &&
|
||||
(opline->extended_value != IS_STRING
|
||||
|| Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_ARRAY)) {
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
/* cast of constant operand */
|
||||
zend_uchar type = opline->result_type;
|
||||
uint32_t tv = opline->result.var; /* temporary variable */
|
||||
zval res;
|
||||
res = ZEND_OP1_LITERAL(opline);
|
||||
zval_copy_ctor(&res);
|
||||
switch (opline->extended_value) {
|
||||
case IS_NULL:
|
||||
convert_to_null(&res);
|
||||
break;
|
||||
case _IS_BOOL:
|
||||
convert_to_boolean(&res);
|
||||
break;
|
||||
case IS_LONG:
|
||||
convert_to_long(&res);
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
convert_to_double(&res);
|
||||
break;
|
||||
case IS_STRING:
|
||||
convert_to_string(&res);
|
||||
break;
|
||||
}
|
||||
zval result;
|
||||
|
||||
if (zend_optimizer_replace_by_const(op_array, opline + 1, type, tv, &res)) {
|
||||
if (zend_optimizer_eval_cast(&result, opline->extended_value, &ZEND_OP1_LITERAL(opline)) == SUCCESS) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
if (zend_optimizer_replace_by_const(op_array, opline + 1, opline->result_type, opline->result.var, &result)) {
|
||||
MAKE_NOP(opline);
|
||||
} else {
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
opline->extended_value = 0;
|
||||
zend_optimizer_update_op1_const(op_array, opline, &result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (opline->extended_value == _IS_BOOL) {
|
||||
}
|
||||
|
||||
if (opline->extended_value == _IS_BOOL) {
|
||||
/* T = CAST(X, IS_BOOL) => T = BOOL(X) */
|
||||
opline->opcode = ZEND_BOOL;
|
||||
opline->extended_value = 0;
|
||||
@ -149,24 +115,19 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
|
||||
case ZEND_BW_NOT:
|
||||
case ZEND_BOOL_NOT:
|
||||
case ZEND_BOOL:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
/* unary operation on constant operand */
|
||||
unary_op_type unary_op = get_unary_op(opline->opcode);
|
||||
zval result;
|
||||
uint32_t tv = opline->result.var; /* temporary variable */
|
||||
int er;
|
||||
|
||||
er = EG(error_reporting);
|
||||
EG(error_reporting) = 0;
|
||||
if (unary_op(&result, &ZEND_OP1_LITERAL(opline)) != SUCCESS) {
|
||||
EG(error_reporting) = er;
|
||||
break;
|
||||
}
|
||||
EG(error_reporting) = er;
|
||||
|
||||
if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, tv, &result)) {
|
||||
if (zend_optimizer_eval_unary_op(&result, opline->opcode, &ZEND_OP1_LITERAL(opline)) == SUCCESS) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, opline->result.var, &result)) {
|
||||
MAKE_NOP(opline);
|
||||
} else {
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
zend_optimizer_update_op1_const(op_array, opline, &result);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -258,11 +219,15 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
fake_execute_data.func = (zend_function*)op_array;
|
||||
EG(current_execute_data) = &fake_execute_data;
|
||||
if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) {
|
||||
uint32_t tv = opline->result.var;
|
||||
|
||||
if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, offset)) {
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, opline->result.var, offset)) {
|
||||
MAKE_NOP(opline);
|
||||
} else {
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
opline->extended_value = 0;
|
||||
SET_UNUSED(opline->op2);
|
||||
zend_optimizer_update_op1_const(op_array, opline, offset);
|
||||
}
|
||||
}
|
||||
EG(current_execute_data) = orig_execute_data;
|
||||
@ -272,7 +237,6 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
if (opline->op2_type == IS_CONST &&
|
||||
Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
|
||||
/* substitute persistent constants */
|
||||
uint32_t tv = opline->result.var;
|
||||
zval c;
|
||||
|
||||
if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP2_LITERAL(opline)), &c, 1)) {
|
||||
@ -283,9 +247,14 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
if (Z_TYPE(c) == IS_CONSTANT_AST) {
|
||||
break;
|
||||
}
|
||||
if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &c)) {
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, opline->result.var, &c)) {
|
||||
MAKE_NOP(opline);
|
||||
} else {
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
opline->extended_value = 0;
|
||||
SET_UNUSED(opline->op2);
|
||||
zend_optimizer_update_op1_const(op_array, opline, &c);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -329,7 +298,6 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
}
|
||||
|
||||
if (ce) {
|
||||
uint32_t tv = opline->result.var;
|
||||
zend_class_constant *cc;
|
||||
zval *c, t;
|
||||
|
||||
@ -350,14 +318,20 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
zval_copy_ctor(&t);
|
||||
}
|
||||
|
||||
if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &t)) {
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
} else if (opline->op1_type == IS_VAR) {
|
||||
MAKE_NOP((opline - 1));
|
||||
}
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
} else if (opline->op1_type == IS_VAR) {
|
||||
MAKE_NOP((opline - 1));
|
||||
}
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
|
||||
if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, opline->result.var, &t)) {
|
||||
MAKE_NOP(opline);
|
||||
} else {
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
opline->extended_value = 0;
|
||||
SET_UNUSED(opline->op2);
|
||||
zend_optimizer_update_op1_const(op_array, opline, &t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -469,17 +443,21 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
} else {
|
||||
ZVAL_FALSE(&t);
|
||||
}
|
||||
literal_dtor(&ZEND_OP2_LITERAL(init_opline));
|
||||
MAKE_NOP(init_opline);
|
||||
literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
|
||||
MAKE_NOP(send1_opline);
|
||||
if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, opline->result.var, &t)) {
|
||||
literal_dtor(&ZEND_OP2_LITERAL(init_opline));
|
||||
MAKE_NOP(init_opline);
|
||||
literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
|
||||
MAKE_NOP(send1_opline);
|
||||
MAKE_NOP(opline);
|
||||
zend_string_release(lc_name);
|
||||
break;
|
||||
} else {
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
opline->extended_value = 0;
|
||||
SET_UNUSED(opline->op2);
|
||||
zend_optimizer_update_op1_const(op_array, opline, &t);
|
||||
}
|
||||
}
|
||||
zend_string_release(lc_name);
|
||||
break;
|
||||
} else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("extension_loaded")-1 &&
|
||||
!memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
|
||||
"extension_loaded", sizeof("extension_loaded")-1) &&
|
||||
@ -509,14 +487,19 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
literal_dtor(&ZEND_OP2_LITERAL(init_opline));
|
||||
MAKE_NOP(init_opline);
|
||||
literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
|
||||
MAKE_NOP(send1_opline);
|
||||
if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, opline->result.var, &t)) {
|
||||
literal_dtor(&ZEND_OP2_LITERAL(init_opline));
|
||||
MAKE_NOP(init_opline);
|
||||
literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
|
||||
MAKE_NOP(send1_opline);
|
||||
MAKE_NOP(opline);
|
||||
break;
|
||||
} else {
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
opline->extended_value = 0;
|
||||
SET_UNUSED(opline->op2);
|
||||
zend_optimizer_update_op1_const(op_array, opline, &t);
|
||||
}
|
||||
break;
|
||||
} else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("constant")-1 &&
|
||||
!memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
|
||||
"constant", sizeof("constant")-1) &&
|
||||
@ -524,15 +507,20 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
zval t;
|
||||
|
||||
if (zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(send1_opline)), &t, 1)) {
|
||||
literal_dtor(&ZEND_OP2_LITERAL(init_opline));
|
||||
MAKE_NOP(init_opline);
|
||||
literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
|
||||
MAKE_NOP(send1_opline);
|
||||
if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, opline->result.var, &t)) {
|
||||
literal_dtor(&ZEND_OP2_LITERAL(init_opline));
|
||||
MAKE_NOP(init_opline);
|
||||
literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
|
||||
MAKE_NOP(send1_opline);
|
||||
MAKE_NOP(opline);
|
||||
break;
|
||||
} else {
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
opline->extended_value = 0;
|
||||
SET_UNUSED(opline->op2);
|
||||
zend_optimizer_update_op1_const(op_array, opline, &t);
|
||||
}
|
||||
}
|
||||
break;
|
||||
/* dirname(IS_CONST/IS_STRING) -> IS_CONST/IS_STRING */
|
||||
} else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("dirname")-1 &&
|
||||
!memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
|
||||
@ -545,17 +533,22 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
zval t;
|
||||
|
||||
ZVAL_STR(&t, dirname);
|
||||
literal_dtor(&ZEND_OP2_LITERAL(init_opline));
|
||||
MAKE_NOP(init_opline);
|
||||
literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
|
||||
MAKE_NOP(send1_opline);
|
||||
if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, opline->result.var, &t)) {
|
||||
literal_dtor(&ZEND_OP2_LITERAL(init_opline));
|
||||
MAKE_NOP(init_opline);
|
||||
literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
|
||||
MAKE_NOP(send1_opline);
|
||||
MAKE_NOP(opline);
|
||||
break;
|
||||
} else {
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
opline->extended_value = 0;
|
||||
SET_UNUSED(opline->op2);
|
||||
zend_optimizer_update_op1_const(op_array, opline, &t);
|
||||
}
|
||||
} else {
|
||||
zend_string_release(dirname);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* don't colllect constants after any other function call */
|
||||
@ -563,28 +556,33 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
break;
|
||||
}
|
||||
case ZEND_STRLEN:
|
||||
if (opline->op1_type == IS_CONST &&
|
||||
Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
zval t;
|
||||
|
||||
ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline)));
|
||||
if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, opline->result.var, &t)) {
|
||||
if (zend_optimizer_eval_strlen(&t, &ZEND_OP1_LITERAL(opline)) == SUCCESS) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, opline->result.var, &t)) {
|
||||
MAKE_NOP(opline);
|
||||
} else {
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
zend_optimizer_update_op1_const(op_array, opline, &t);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_DEFINED:
|
||||
{
|
||||
zval c;
|
||||
uint32_t tv = opline->result.var;
|
||||
if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline)), &c, 0)) {
|
||||
break;
|
||||
}
|
||||
ZVAL_TRUE(&c);
|
||||
if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &c)) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, opline->result.var, &c)) {
|
||||
MAKE_NOP(opline);
|
||||
} else {
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
zend_optimizer_update_op1_const(op_array, opline, &c);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -53,6 +53,86 @@ void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, zval *name, zval*
|
||||
zend_hash_add(ctx->constants, Z_STR_P(name), &val);
|
||||
}
|
||||
|
||||
int zend_optimizer_eval_binary_op(zval *result, zend_uchar opcode, zval *op1, zval *op2) /* {{{ */
|
||||
{
|
||||
binary_op_type binary_op = get_binary_op(opcode);
|
||||
int er, ret;
|
||||
|
||||
if ((opcode == ZEND_DIV || opcode == ZEND_MOD) &&
|
||||
zval_get_long(op2) == 0) {
|
||||
/* div by 0 */
|
||||
return FAILURE;
|
||||
} else if ((opcode == ZEND_SL || opcode == ZEND_SR) &&
|
||||
zval_get_long(op2) < 0) {
|
||||
/* shift by negative number */
|
||||
return FAILURE;
|
||||
} else if (zend_binary_op_produces_numeric_string_error(opcode, op1, op2)) {
|
||||
/* produces numeric string E_NOTICE/E_WARNING */
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
er = EG(error_reporting);
|
||||
EG(error_reporting) = 0;
|
||||
ret = binary_op(result, op1, op2);
|
||||
EG(error_reporting) = er;
|
||||
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int zend_optimizer_eval_unary_op(zval *result, zend_uchar opcode, zval *op1) /* {{{ */
|
||||
{
|
||||
unary_op_type unary_op = get_unary_op(opcode);
|
||||
|
||||
if (unary_op) {
|
||||
return unary_op(result, op1);
|
||||
} else { /* ZEND_BOOL */
|
||||
ZVAL_BOOL(result, zend_is_true(op1));
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int zend_optimizer_eval_cast(zval *result, uint32_t type, zval *op1) /* {{{ */
|
||||
{
|
||||
switch (type) {
|
||||
case IS_NULL:
|
||||
ZVAL_NULL(result);
|
||||
return SUCCESS;
|
||||
case _IS_BOOL:
|
||||
ZVAL_BOOL(result, zval_is_true(op1));
|
||||
return SUCCESS;
|
||||
case IS_LONG:
|
||||
ZVAL_LONG(result, zval_get_long(op1));
|
||||
return SUCCESS;
|
||||
case IS_DOUBLE:
|
||||
ZVAL_DOUBLE(result, zval_get_double(op1));
|
||||
return SUCCESS;
|
||||
case IS_STRING:
|
||||
if (Z_TYPE_P(op1) != IS_ARRAY) {
|
||||
ZVAL_STR(result, zval_get_string(op1));
|
||||
return SUCCESS;
|
||||
}
|
||||
break;
|
||||
case IS_ARRAY:
|
||||
ZVAL_COPY(result, op1);
|
||||
convert_to_array(result);
|
||||
return SUCCESS;
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int zend_optimizer_eval_strlen(zval *result, zval *op1) /* {{{ */
|
||||
{
|
||||
if (Z_TYPE_P(op1) != IS_STRING) {
|
||||
return FAILURE;
|
||||
}
|
||||
ZVAL_LONG(result, Z_STRLEN_P(op1));
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int zend_optimizer_get_collected_constant(HashTable *constants, zval *name, zval* value)
|
||||
{
|
||||
zval *val;
|
||||
@ -158,16 +238,13 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array,
|
||||
case ZEND_SEPARATE:
|
||||
case ZEND_SEND_VAR_NO_REF:
|
||||
case ZEND_SEND_VAR_NO_REF_EX:
|
||||
zval_ptr_dtor_nogc(val);
|
||||
return 0;
|
||||
case ZEND_VERIFY_RETURN_TYPE:
|
||||
/* This would require a non-local change.
|
||||
* zend_optimizer_replace_by_const() supports this. */
|
||||
zval_ptr_dtor_nogc(val);
|
||||
return 0;
|
||||
case ZEND_CASE:
|
||||
case ZEND_FETCH_LIST:
|
||||
zval_ptr_dtor_nogc(val);
|
||||
return 0;
|
||||
case ZEND_CONCAT:
|
||||
case ZEND_FAST_CONCAT:
|
||||
@ -198,7 +275,6 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
|
||||
switch (opline->opcode) {
|
||||
case ZEND_ASSIGN_REF:
|
||||
case ZEND_FAST_CALL:
|
||||
zval_ptr_dtor_nogc(val);
|
||||
return 0;
|
||||
case ZEND_FETCH_CLASS:
|
||||
case ZEND_INIT_FCALL_BY_NAME:
|
||||
@ -229,14 +305,12 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
|
||||
case ZEND_INIT_DYNAMIC_CALL:
|
||||
if (Z_TYPE_P(val) == IS_STRING) {
|
||||
if (zend_memrchr(Z_STRVAL_P(val), ':', Z_STRLEN_P(val))) {
|
||||
zval_ptr_dtor_nogc(val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (zend_optimizer_classify_function(Z_STR_P(val), opline->extended_value)) {
|
||||
/* Dynamic call to various special functions must stay dynamic,
|
||||
* otherwise would drop a warning */
|
||||
zval_ptr_dtor_nogc(val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -394,7 +468,6 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
|
||||
case ZEND_ASSIGN_DIM:
|
||||
case ZEND_SEPARATE:
|
||||
case ZEND_RETURN_BY_REF:
|
||||
zval_ptr_dtor_nogc(val);
|
||||
return 0;
|
||||
case ZEND_SEND_VAR:
|
||||
opline->extended_value = 0;
|
||||
@ -405,7 +478,6 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
|
||||
opline->opcode = ZEND_SEND_VAL_EX;
|
||||
break;
|
||||
case ZEND_SEND_VAR_NO_REF:
|
||||
zval_ptr_dtor_nogc(val);
|
||||
return 0;
|
||||
case ZEND_SEND_VAR_NO_REF_EX:
|
||||
opline->opcode = ZEND_SEND_VAL;
|
||||
@ -507,7 +579,6 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
|
||||
|| ZEND_TYPE_CODE(ret_info->type) == IS_CALLABLE
|
||||
|| !ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(ret_info->type), Z_TYPE_P(val))
|
||||
|| (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
|
||||
zval_ptr_dtor_nogc(val);
|
||||
return 0;
|
||||
}
|
||||
MAKE_NOP(opline);
|
||||
|
@ -74,6 +74,10 @@ int zend_optimizer_add_literal(zend_op_array *op_array, zval *zv);
|
||||
int zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int copy);
|
||||
void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, zval *name, zval* value);
|
||||
int zend_optimizer_get_collected_constant(HashTable *constants, zval *name, zval* value);
|
||||
int zend_optimizer_eval_binary_op(zval *result, zend_uchar opcode, zval *op1, zval *op2);
|
||||
int zend_optimizer_eval_unary_op(zval *result, zend_uchar opcode, zval *op1);
|
||||
int zend_optimizer_eval_cast(zval *result, uint32_t type, zval *op1);
|
||||
int zend_optimizer_eval_strlen(zval *result, zval *op1);
|
||||
int zend_optimizer_update_op1_const(zend_op_array *op_array,
|
||||
zend_op *opline,
|
||||
zval *val);
|
||||
|
Loading…
Reference in New Issue
Block a user