diff options
author | Andrey Hristov <andrey@php.net> | 2013-11-26 20:10:30 +0200 |
---|---|---|
committer | Andrey Hristov <andrey@php.net> | 2013-11-26 20:10:30 +0200 |
commit | 0fc90b100dab0f480153e5166d31488b42c808f8 (patch) | |
tree | ac008fb92c9d719cc8c48890ef1dd7513b4e096d | |
parent | 9a6b72a05ad6be151e5952e9a5fa6e645fb17a5f (diff) | |
parent | de658171360cc480105eaf932f94c15b24687a83 (diff) | |
download | php-git-0fc90b100dab0f480153e5166d31488b42c808f8.tar.gz |
Merge branch 'PHP-5.5' of git.php.net:php-src into PHP-5.5
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | ext/opcache/Optimizer/block_pass.c | 59 | ||||
-rw-r--r-- | ext/opcache/Optimizer/pass1_5.c | 23 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_optimizer.c | 271 | ||||
-rw-r--r-- | ext/opcache/README | 6 | ||||
-rw-r--r-- | ext/opcache/ZendAccelerator.c | 13 | ||||
-rw-r--r-- | ext/opcache/ZendAccelerator.h | 1 | ||||
-rw-r--r-- | ext/opcache/tests/bug65559.phpt | 22 | ||||
-rw-r--r-- | ext/opcache/tests/bug66176.phpt | 19 | ||||
-rw-r--r-- | ext/opcache/zend_accelerator_module.c | 3 | ||||
-rwxr-xr-x | run-tests.php | 1 | ||||
-rw-r--r-- | sapi/cli/tests/php_cli_server_019.phpt | 2 |
12 files changed, 250 insertions, 173 deletions
@@ -12,7 +12,10 @@ PHP NEWS string). (Laruence) - OPCache + . Fixed bug #66176 (Invalid constant substitution). (Dmitry) . Fixed bug #65915 (Inconsistent results with require return value). (Dmitry) + . Fixed bug #65559 (Opcache: cache not cleared if changes occur while + running). (Dmitry) - readline . Fixed Bug #65714 (PHP cli forces the tty to cooked mode). (Remi) diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index 1c34cffbf7..8c4c58e493 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -643,8 +643,11 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, opline->opcode != ZEND_FREE ) { zend_op *src = VAR_SOURCE(opline->op1); + zval c = ZEND_OP1_LITERAL(src); VAR_UNSET(opline->op1); - COPY_NODE(opline->op1, src->op1); + zval_copy_ctor(&c); + update_op1_const(op_array, opline, &c TSRMLS_CC); + literal_dtor(&ZEND_OP1_LITERAL(src)); MAKE_NOP(src); } @@ -654,51 +657,12 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, VAR_SOURCE(opline->op2)->opcode == ZEND_QM_ASSIGN && ZEND_OP1_TYPE(VAR_SOURCE(opline->op2)) == IS_CONST) { zend_op *src = VAR_SOURCE(opline->op2); + zval c = ZEND_OP1_LITERAL(src); VAR_UNSET(opline->op2); - COPY_NODE(opline->op2, src->op1); + zval_copy_ctor(&c); + update_op2_const(op_array, opline, &c TSRMLS_CC); + literal_dtor(&ZEND_OP1_LITERAL(src)); MAKE_NOP(src); - -#if ZEND_EXTENSION_API_NO >= PHP_5_4_X_API_NO - /* numeric string constants used as array indeces have to be - converted to long at compile time */ - if (opline->opcode == ZEND_ADD_ARRAY_ELEMENT || - opline->opcode == ZEND_INIT_ARRAY || - opline->opcode == ZEND_UNSET_DIM || - opline->opcode == ZEND_ISSET_ISEMPTY_DIM_OBJ || - opline->opcode == ZEND_FETCH_DIM_R || - opline->opcode == ZEND_FETCH_DIM_W || - opline->opcode == ZEND_FETCH_DIM_RW || - opline->opcode == ZEND_FETCH_DIM_IS || - opline->opcode == ZEND_FETCH_DIM_FUNC_ARG || - opline->opcode == ZEND_FETCH_DIM_UNSET || - opline->opcode == ZEND_FETCH_DIM_TMP_VAR || - (opline->opcode == ZEND_OP_DATA && - ((opline-1)->opcode == ZEND_ASSIGN_DIM || - ((opline-1)->extended_value == ZEND_ASSIGN_DIM && - ((opline-1)->opcode == ZEND_ASSIGN_ADD || - (opline-1)->opcode == ZEND_ASSIGN_SUB || - (opline-1)->opcode == ZEND_ASSIGN_MUL || - (opline-1)->opcode == ZEND_ASSIGN_DIV || - (opline-1)->opcode == ZEND_ASSIGN_MOD || - (opline-1)->opcode == ZEND_ASSIGN_SL || - (opline-1)->opcode == ZEND_ASSIGN_SR || - (opline-1)->opcode == ZEND_ASSIGN_CONCAT || - (opline-1)->opcode == ZEND_ASSIGN_BW_OR || - (opline-1)->opcode == ZEND_ASSIGN_BW_AND || - (opline-1)->opcode == ZEND_ASSIGN_BW_XOR))))) { - - if (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) { - ulong index; - int numeric = 0; - - ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline))+1, index, numeric = 1); - if (numeric) { - zval_dtor(&ZEND_OP2_LITERAL(opline)); - ZVAL_LONG(&ZEND_OP2_LITERAL(opline), index); - } - } - } -#endif } /* T = PRINT(X), F(T) => ECHO(X), F(1) */ @@ -1070,10 +1034,9 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, literal_dtor(&ZEND_OP1_LITERAL(opline)); literal_dtor(&ZEND_OP2_LITERAL(opline)); - ZEND_OP1_LITERAL(opline) = result; - SET_UNUSED(opline->op2); - opline->opcode = ZEND_QM_ASSIGN; + SET_UNUSED(opline->op2); + update_op1_const(op_array, opline, &result TSRMLS_CC); } EG(error_reporting) = er; } else if ((opline->opcode == ZEND_BOOL || @@ -1097,8 +1060,8 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, } PZ_SET_REFCOUNT_P(&result, 1); PZ_UNSET_ISREF_P(&result); - ZEND_OP1_LITERAL(opline) = result; opline->opcode = ZEND_QM_ASSIGN; + update_op1_const(op_array, opline, &result TSRMLS_CC); } else if ((opline->opcode == ZEND_RETURN || opline->opcode == ZEND_EXIT) && ZEND_OP1_TYPE(opline) == IS_TMP_VAR && VAR_SOURCE(opline->op1) && diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c index 70ec6d5e2e..ca5b882901 100644 --- a/ext/opcache/Optimizer/pass1_5.c +++ b/ext/opcache/Optimizer/pass1_5.c @@ -219,15 +219,11 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { EG(in_execution) = 1; EG(active_op_array) = op_array; if (zend_get_constant("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1, &offset TSRMLS_CC)) { + zend_uint tv = ZEND_RESULT(opline).var; + literal_dtor(&ZEND_OP2_LITERAL(opline)); - ZEND_OP1_TYPE(opline) = IS_CONST; -#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO - opline->op1.constant = zend_optimizer_add_literal(op_array, &offset TSRMLS_CC); -#else - ZEND_OP1_LITERAL(opline) = offset; -#endif - SET_UNUSED(opline->op2); - opline->opcode = ZEND_QM_ASSIGN; + MAKE_NOP(opline); + replace_tmp_by_const(op_array, opline, tv, &offset TSRMLS_CC); } EG(active_op_array) = orig_op_array; EG(in_execution) = orig_in_execution; @@ -238,20 +234,15 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { ZEND_OP2_TYPE(opline) == IS_CONST && ZEND_OP2_LITERAL(opline).type == IS_STRING) { /* substitute persistent constants */ + zend_uint tv = ZEND_RESULT(opline).var; zval c; if (!zend_get_persistent_constant(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), &c, 1 TSRMLS_CC)) { break; } literal_dtor(&ZEND_OP2_LITERAL(opline)); - ZEND_OP1_TYPE(opline) = IS_CONST; -#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO - opline->op1.constant = zend_optimizer_add_literal(op_array, &c TSRMLS_CC); -#else - ZEND_OP1_LITERAL(opline) = c; -#endif - SET_UNUSED(opline->op2); - opline->opcode = ZEND_QM_ASSIGN; + MAKE_NOP(opline); + replace_tmp_by_const(op_array, opline, tv, &c TSRMLS_CC); } break; diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index 28085cb441..c932530128 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -19,6 +19,7 @@ +----------------------------------------------------------------------+
*/
+#include "php.h"
#include "Optimizer/zend_optimizer.h"
#include "Optimizer/zend_optimizer_internal.h"
#include "zend_API.h"
@@ -110,6 +111,167 @@ int zend_optimizer_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC #endif
+static void update_op1_const(zend_op_array *op_array,
+ zend_op *opline,
+ zval *val TSRMLS_DC)
+{
+ if (opline->opcode == ZEND_FREE) {
+ MAKE_NOP(opline);
+ zval_dtor(val);
+ } else {
+ ZEND_OP1_TYPE(opline) = IS_CONST;
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ if (Z_TYPE_P(val) == IS_STRING) {
+ switch (opline->opcode) {
+ case ZEND_INIT_STATIC_METHOD_CALL:
+ case ZEND_CATCH:
+ case ZEND_FETCH_CONSTANT:
+ opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
+ Z_HASH_P(&ZEND_OP1_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1);
+ op_array->literals[opline->op1.constant].cache_slot = op_array->last_cache_slot++;
+ zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
+ zend_optimizer_add_literal(op_array, val TSRMLS_CC);
+ op_array->literals[opline->op1.constant+1].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[opline->op1.constant+1].constant), Z_STRLEN(op_array->literals[opline->op1.constant+1].constant) + 1);
+ break;
+ case ZEND_DO_FCALL:
+ zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
+ opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
+ Z_HASH_P(&ZEND_OP1_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1);
+ op_array->literals[opline->op1.constant].cache_slot = op_array->last_cache_slot++;
+ break;
+ default:
+ opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
+ Z_HASH_P(&ZEND_OP1_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1);
+ break;
+ }
+ } else {
+ opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
+ }
+#else
+ ZEND_OP1_LITERAL(opline) = *val;
+#endif
+ }
+}
+
+static void update_op2_const(zend_op_array *op_array,
+ zend_op *opline,
+ zval *val TSRMLS_DC)
+{
+ ZEND_OP2_TYPE(opline) = IS_CONST;
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ opline->op2.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
+ if (Z_TYPE_P(val) == IS_STRING) {
+ Z_HASH_P(&ZEND_OP2_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)) + 1);
+ switch (opline->opcode) {
+ case ZEND_FETCH_R:
+ case ZEND_FETCH_W:
+ case ZEND_FETCH_RW:
+ case ZEND_FETCH_IS:
+ case ZEND_FETCH_UNSET:
+ case ZEND_FETCH_FUNC_ARG:
+ case ZEND_FETCH_CLASS:
+ case ZEND_INIT_FCALL_BY_NAME:
+ /*case ZEND_INIT_NS_FCALL_BY_NAME:*/
+ case ZEND_UNSET_VAR:
+ case ZEND_ISSET_ISEMPTY_VAR:
+ case ZEND_ADD_INTERFACE:
+ case ZEND_ADD_TRAIT:
+ op_array->literals[opline->op2.constant].cache_slot = op_array->last_cache_slot++;
+ zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
+ zend_optimizer_add_literal(op_array, val TSRMLS_CC);
+ op_array->literals[opline->op2.constant+1].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[opline->op2.constant+1].constant), Z_STRLEN(op_array->literals[opline->op2.constant+1].constant) + 1);
+ break;
+ case ZEND_INIT_METHOD_CALL:
+ case ZEND_INIT_STATIC_METHOD_CALL:
+ zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
+ zend_optimizer_add_literal(op_array, val TSRMLS_CC);
+ op_array->literals[opline->op2.constant+1].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[opline->op2.constant+1].constant), Z_STRLEN(op_array->literals[opline->op2.constant+1].constant) + 1);
+ /* break missing intentionally */
+ /*case ZEND_FETCH_CONSTANT:*/
+ case ZEND_ASSIGN_OBJ:
+ case ZEND_FETCH_OBJ_R:
+ case ZEND_FETCH_OBJ_W:
+ case ZEND_FETCH_OBJ_RW:
+ case ZEND_FETCH_OBJ_IS:
+ case ZEND_FETCH_OBJ_UNSET:
+ case ZEND_FETCH_OBJ_FUNC_ARG:
+ case ZEND_UNSET_OBJ:
+ case ZEND_PRE_INC_OBJ:
+ case ZEND_PRE_DEC_OBJ:
+ case ZEND_POST_INC_OBJ:
+ case ZEND_POST_DEC_OBJ:
+ case ZEND_ISSET_ISEMPTY_PROP_OBJ:
+ op_array->literals[opline->op2.constant].cache_slot = op_array->last_cache_slot;
+ op_array->last_cache_slot += 2;
+ break;
+ case ZEND_ASSIGN_ADD:
+ case ZEND_ASSIGN_SUB:
+ case ZEND_ASSIGN_MUL:
+ case ZEND_ASSIGN_DIV:
+ case ZEND_ASSIGN_MOD:
+ case ZEND_ASSIGN_SL:
+ case ZEND_ASSIGN_SR:
+ case ZEND_ASSIGN_CONCAT:
+ case ZEND_ASSIGN_BW_OR:
+ case ZEND_ASSIGN_BW_AND:
+ case ZEND_ASSIGN_BW_XOR:
+ if (opline->extended_value == ZEND_ASSIGN_OBJ) {
+ op_array->literals[opline->op2.constant].cache_slot = op_array->last_cache_slot;
+ op_array->last_cache_slot += 2;
+ }
+ break;
+#if ZEND_EXTENSION_API_NO >= PHP_5_4_X_API_NO
+ case ZEND_OP_DATA:
+ if ((opline-1)->opcode == ZEND_ASSIGN_DIM ||
+ ((opline-1)->extended_value == ZEND_ASSIGN_DIM &&
+ ((opline-1)->opcode == ZEND_ASSIGN_ADD ||
+ (opline-1)->opcode == ZEND_ASSIGN_SUB ||
+ (opline-1)->opcode == ZEND_ASSIGN_MUL ||
+ (opline-1)->opcode == ZEND_ASSIGN_DIV ||
+ (opline-1)->opcode == ZEND_ASSIGN_MOD ||
+ (opline-1)->opcode == ZEND_ASSIGN_SL ||
+ (opline-1)->opcode == ZEND_ASSIGN_SR ||
+ (opline-1)->opcode == ZEND_ASSIGN_CONCAT ||
+ (opline-1)->opcode == ZEND_ASSIGN_BW_OR ||
+ (opline-1)->opcode == ZEND_ASSIGN_BW_AND ||
+ (opline-1)->opcode == ZEND_ASSIGN_BW_XOR))) {
+ goto check_numeric;
+ }
+ break;
+ case ZEND_ISSET_ISEMPTY_DIM_OBJ:
+ case ZEND_ADD_ARRAY_ELEMENT:
+ case ZEND_INIT_ARRAY:
+ case ZEND_UNSET_DIM:
+ case ZEND_FETCH_DIM_R:
+ case ZEND_FETCH_DIM_W:
+ case ZEND_FETCH_DIM_RW:
+ case ZEND_FETCH_DIM_IS:
+ case ZEND_FETCH_DIM_FUNC_ARG:
+ case ZEND_FETCH_DIM_UNSET:
+ case ZEND_FETCH_DIM_TMP_VAR:
+check_numeric:
+ {
+ ulong index;
+ int numeric = 0;
+
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(val), Z_STRLEN_P(val)+1, index, numeric = 1);
+ if (numeric) {
+ zval_dtor(val);
+ ZVAL_LONG(val, index);
+ op_array->literals[opline->op2.constant].constant = *val;
+ }
+ }
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+#else
+ ZEND_OP2_LITERAL(opline) = *val;
+#endif
+}
+
static void replace_tmp_by_const(zend_op_array *op_array,
zend_op *opline,
zend_uint var,
@@ -122,42 +284,7 @@ static void replace_tmp_by_const(zend_op_array *op_array, if (ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
ZEND_OP1(opline).var == var) {
- if (opline->opcode == ZEND_FREE) {
- MAKE_NOP(opline);
- zval_dtor(val);
- } else {
- ZEND_OP1_TYPE(opline) = IS_CONST;
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- if (Z_TYPE_P(val) == IS_STRING) {
- switch (opline->opcode) {
- case ZEND_INIT_STATIC_METHOD_CALL:
- case ZEND_CATCH:
- case ZEND_FETCH_CONSTANT:
- opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
- Z_HASH_P(&ZEND_OP1_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1);
- op_array->literals[opline->op1.constant].cache_slot = op_array->last_cache_slot++;
- zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
- zend_optimizer_add_literal(op_array, val TSRMLS_CC);
- op_array->literals[opline->op1.constant+1].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[opline->op1.constant+1].constant), Z_STRLEN(op_array->literals[opline->op1.constant+1].constant) + 1);
- break;
- case ZEND_DO_FCALL:
- zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
- opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
- Z_HASH_P(&ZEND_OP1_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1);
- op_array->literals[opline->op1.constant].cache_slot = op_array->last_cache_slot++;
- break;
- default:
- opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
- Z_HASH_P(&ZEND_OP1_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1);
- break;
- }
- } else {
- opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
- }
-#else
- ZEND_OP1_LITERAL(opline) = *val;
-#endif
- }
+ update_op1_const(op_array, opline, val TSRMLS_CC);
/* TMP_VAR my be used only once */
break;
}
@@ -165,76 +292,8 @@ static void replace_tmp_by_const(zend_op_array *op_array, if (ZEND_OP2_TYPE(opline) == IS_TMP_VAR &&
ZEND_OP2(opline).var == var) {
- ZEND_OP2_TYPE(opline) = IS_CONST;
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- opline->op2.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
- if (Z_TYPE_P(val) == IS_STRING) {
- Z_HASH_P(&ZEND_OP2_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)) + 1);
- switch (opline->opcode) {
- case ZEND_FETCH_R:
- case ZEND_FETCH_W:
- case ZEND_FETCH_RW:
- case ZEND_FETCH_IS:
- case ZEND_FETCH_UNSET:
- case ZEND_FETCH_FUNC_ARG:
- case ZEND_FETCH_CLASS:
- case ZEND_INIT_FCALL_BY_NAME:
- /*case ZEND_INIT_NS_FCALL_BY_NAME:*/
- case ZEND_UNSET_VAR:
- case ZEND_ISSET_ISEMPTY_VAR:
- case ZEND_ADD_INTERFACE:
- case ZEND_ADD_TRAIT:
- op_array->literals[opline->op2.constant].cache_slot = op_array->last_cache_slot++;
- zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
- zend_optimizer_add_literal(op_array, val TSRMLS_CC);
- op_array->literals[opline->op2.constant+1].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[opline->op2.constant+1].constant), Z_STRLEN(op_array->literals[opline->op2.constant+1].constant) + 1);
- break;
- case ZEND_INIT_METHOD_CALL:
- case ZEND_INIT_STATIC_METHOD_CALL:
- zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
- zend_optimizer_add_literal(op_array, val TSRMLS_CC);
- op_array->literals[opline->op2.constant+1].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[opline->op2.constant+1].constant), Z_STRLEN(op_array->literals[opline->op2.constant+1].constant) + 1);
- /* break missing intentionally */
- /*case ZEND_FETCH_CONSTANT:*/
- case ZEND_ASSIGN_OBJ:
- case ZEND_FETCH_OBJ_R:
- case ZEND_FETCH_OBJ_W:
- case ZEND_FETCH_OBJ_RW:
- case ZEND_FETCH_OBJ_IS:
- case ZEND_FETCH_OBJ_UNSET:
- case ZEND_FETCH_OBJ_FUNC_ARG:
- case ZEND_UNSET_OBJ:
- case ZEND_PRE_INC_OBJ:
- case ZEND_PRE_DEC_OBJ:
- case ZEND_POST_INC_OBJ:
- case ZEND_POST_DEC_OBJ:
- case ZEND_ISSET_ISEMPTY_PROP_OBJ:
- op_array->literals[opline->op2.constant].cache_slot = op_array->last_cache_slot;
- op_array->last_cache_slot += 2;
- break;
- case ZEND_ASSIGN_ADD:
- case ZEND_ASSIGN_SUB:
- case ZEND_ASSIGN_MUL:
- case ZEND_ASSIGN_DIV:
- case ZEND_ASSIGN_MOD:
- case ZEND_ASSIGN_SL:
- case ZEND_ASSIGN_SR:
- case ZEND_ASSIGN_CONCAT:
- case ZEND_ASSIGN_BW_OR:
- case ZEND_ASSIGN_BW_AND:
- case ZEND_ASSIGN_BW_XOR:
- if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- op_array->literals[opline->op2.constant].cache_slot = op_array->last_cache_slot;
- op_array->last_cache_slot += 2;
- }
- break;
- default:
- break;
- }
- }
-#else
- ZEND_OP2_LITERAL(opline) = *val;
-#endif
+ update_op2_const(op_array, opline, val TSRMLS_CC);
+ /* TMP_VAR my be used only once */
break;
}
opline++;
diff --git a/ext/opcache/README b/ext/opcache/README index 2e30d92c00..cb6ac342c4 100644 --- a/ext/opcache/README +++ b/ext/opcache/README @@ -103,6 +103,12 @@ opcache.revalidate_freq (default "2") memory storage allocation. ("1" means validate once per second, but only once per request. "0" means always validate) +opcache.file_update_protection (default "2") + Prevents caching files that are less than this number of seconds old. + It protects from caching of incompletely updated files. In case all file + updates on your site are atomic, you may increase performance setting it + to "0". + opcache.revalidate_path (default "0") Enables or disables file search in include_path optimization If the file search is disabled and a cached file is found that uses diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 8eaa0a3778..c0edf7e477 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -1331,7 +1331,9 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han } #endif - if (ZCG(accel_directives).validate_timestamps || ZCG(accel_directives).max_file_size > 0) { + if (ZCG(accel_directives).validate_timestamps || + ZCG(accel_directives).file_update_protection || + ZCG(accel_directives).max_file_size > 0) { size_t size = 0; /* Obtain the file timestamps, *before* actually compiling them, @@ -1347,6 +1349,13 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han return NULL; } + /* check if file is too new (may be it's not written completely yet) */ + if (ZCG(accel_directives).file_update_protection && + (ZCG(request_time) - ZCG(accel_directives).file_update_protection < timestamp)) { + *op_array_p = accelerator_orig_compile_file(file_handle, type TSRMLS_CC); + return NULL; + } + if (ZCG(accel_directives).max_file_size > 0 && size > (size_t)ZCG(accel_directives).max_file_size) { ZCSG(blacklist_misses)++; *op_array_p = accelerator_orig_compile_file(file_handle, type TSRMLS_CC); @@ -2721,6 +2730,7 @@ void zend_accel_schedule_restart(zend_accel_restart_reason reason TSRMLS_DC) } zend_accel_error(ACCEL_LOG_DEBUG, "Restart Scheduled!"); + SHM_UNPROTECT(); ZCSG(restart_pending) = 1; ZCSG(restart_reason) = reason; ZCSG(cache_status_before_restart) = ZCSG(accelerator_enabled); @@ -2731,6 +2741,7 @@ void zend_accel_schedule_restart(zend_accel_restart_reason reason TSRMLS_DC) } else { ZCSG(force_restart_time) = 0; } + SHM_PROTECT(); } /* this is needed because on WIN32 lock is not decreased unless ZCG(counted) is set */ diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h index b9d7ef3470..cbc50d2b71 100644 --- a/ext/opcache/ZendAccelerator.h +++ b/ext/opcache/ZendAccelerator.h @@ -229,6 +229,7 @@ typedef struct _zend_accel_directives { zend_bool inherited_hack; zend_bool enable_cli; unsigned long revalidate_freq; + unsigned long file_update_protection; char *error_log; #ifdef ZEND_WIN32 char *mmap_base; diff --git a/ext/opcache/tests/bug65559.phpt b/ext/opcache/tests/bug65559.phpt new file mode 100644 index 0000000000..0d40cf10f8 --- /dev/null +++ b/ext/opcache/tests/bug65559.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #65559 (cache not cleared if changes occur while running) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=2 +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php +$file = __DIR__ . "/bug6559.inc.php"; +file_put_contents($file, '<?php return 1;'); +$var = include $file; +var_dump($var); +file_put_contents($file, '<?php return 2;'); +$var = include $file; +var_dump($var); +@unlink($file); +?> +--EXPECT-- +int(1) +int(2) diff --git a/ext/opcache/tests/bug66176.phpt b/ext/opcache/tests/bug66176.phpt new file mode 100644 index 0000000000..a91024a616 --- /dev/null +++ b/ext/opcache/tests/bug66176.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug #66176 (Invalid constant substitution) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +opcache.file_update_protection=0 +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php +function foo($v) { + global $a; + return $a[$v]; +} +$a = array(PHP_VERSION => 1); +var_dump(foo(PHP_VERSION)); +--EXPECT-- +int(1) diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 0914fb68dd..c3df1a68f7 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -259,7 +259,8 @@ ZEND_INI_BEGIN() STD_PHP_INI_ENTRY("opcache.consistency_checks" , "0" , PHP_INI_ALL , OnUpdateLong, accel_directives.consistency_checks, zend_accel_globals, accel_globals) STD_PHP_INI_ENTRY("opcache.force_restart_timeout" , "180" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.force_restart_timeout, zend_accel_globals, accel_globals) STD_PHP_INI_ENTRY("opcache.revalidate_freq" , "2" , PHP_INI_ALL , OnUpdateLong, accel_directives.revalidate_freq, zend_accel_globals, accel_globals) - STD_PHP_INI_ENTRY("opcache.preferred_memory_model", "" , PHP_INI_SYSTEM, OnUpdateStringUnempty, accel_directives.memory_model, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("opcache.file_update_protection", "2" , PHP_INI_ALL , OnUpdateLong, accel_directives.file_update_protection, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("opcache.preferred_memory_model", "" , PHP_INI_SYSTEM, OnUpdateStringUnempty, accel_directives.memory_model, zend_accel_globals, accel_globals) STD_PHP_INI_ENTRY("opcache.blacklist_filename" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.user_blacklist_filename, zend_accel_globals, accel_globals) STD_PHP_INI_ENTRY("opcache.max_file_size" , "0" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.max_file_size, zend_accel_globals, accel_globals) diff --git a/run-tests.php b/run-tests.php index a88d37d000..d53c3b6c5e 100755 --- a/run-tests.php +++ b/run-tests.php @@ -241,6 +241,7 @@ $ini_overwrites = array( 'precision=14', 'memory_limit=128M', 'opcache.fast_shutdown=0', + 'opcache.file_update_protection=0', ); function write_information($show_html) diff --git a/sapi/cli/tests/php_cli_server_019.phpt b/sapi/cli/tests/php_cli_server_019.phpt index cdad01ed64..2b983e5c0a 100644 --- a/sapi/cli/tests/php_cli_server_019.phpt +++ b/sapi/cli/tests/php_cli_server_019.phpt @@ -60,7 +60,7 @@ array(2) { } array(3) { ["X-Powered-By"]=> - string(13) "P%s" + string(%d) "P%s" ["Bar-Foo"]=> string(3) "Foo" ["Content-type"]=> |