diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index 0340eb7a119..077088298ae 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -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; diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c index 8e8759fb586..5374a1887e4 100644 --- a/ext/opcache/Optimizer/pass1_5.c +++ b/ext/opcache/Optimizer/pass1_5.c @@ -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; diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index 966b472fdb1..bf7eb4ba621 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -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); diff --git a/ext/opcache/Optimizer/zend_optimizer_internal.h b/ext/opcache/Optimizer/zend_optimizer_internal.h index 39bf62d1a43..b5d47291003 100644 --- a/ext/opcache/Optimizer/zend_optimizer_internal.h +++ b/ext/opcache/Optimizer/zend_optimizer_internal.h @@ -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);