summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Hristov <andrey@php.net>2013-11-26 20:10:30 +0200
committerAndrey Hristov <andrey@php.net>2013-11-26 20:10:30 +0200
commit0fc90b100dab0f480153e5166d31488b42c808f8 (patch)
treeac008fb92c9d719cc8c48890ef1dd7513b4e096d
parent9a6b72a05ad6be151e5952e9a5fa6e645fb17a5f (diff)
parentde658171360cc480105eaf932f94c15b24687a83 (diff)
downloadphp-git-0fc90b100dab0f480153e5166d31488b42c808f8.tar.gz
Merge branch 'PHP-5.5' of git.php.net:php-src into PHP-5.5
-rw-r--r--NEWS3
-rw-r--r--ext/opcache/Optimizer/block_pass.c59
-rw-r--r--ext/opcache/Optimizer/pass1_5.c23
-rw-r--r--ext/opcache/Optimizer/zend_optimizer.c271
-rw-r--r--ext/opcache/README6
-rw-r--r--ext/opcache/ZendAccelerator.c13
-rw-r--r--ext/opcache/ZendAccelerator.h1
-rw-r--r--ext/opcache/tests/bug65559.phpt22
-rw-r--r--ext/opcache/tests/bug66176.phpt19
-rw-r--r--ext/opcache/zend_accelerator_module.c3
-rwxr-xr-xrun-tests.php1
-rw-r--r--sapi/cli/tests/php_cli_server_019.phpt2
12 files changed, 250 insertions, 173 deletions
diff --git a/NEWS b/NEWS
index e8ab470d5a..c835df3595 100644
--- a/NEWS
+++ b/NEWS
@@ -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"]=>