From 9035a1ed246d4d2d867edc01616ca96b40a7cd11 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Fri, 13 Apr 2012 23:17:56 -0500 Subject: [PATCH 001/276] Implement new array function array_column() array_column() returns the values of the specified column from a multi-dimensional array. --- ext/standard/array.c | 81 ++++++++++++ ext/standard/basic_functions.c | 6 + ext/standard/php_array.h | 1 + ext/standard/tests/array/array_column.phpt | 138 +++++++++++++++++++++ 4 files changed, 226 insertions(+) create mode 100644 ext/standard/tests/array/array_column.phpt diff --git a/ext/standard/array.c b/ext/standard/array.c index d1397a5f0f0..b707301bd85 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2563,6 +2563,87 @@ PHP_FUNCTION(array_count_values) } /* }}} */ +/* {{{ proto array array_column(array input, mixed key) + Return the values from a single column in the input array, identified by the key */ +PHP_FUNCTION(array_column) +{ + zval *zarray, *zoffset, **data, **zvalue; + HashTable *arr_hash; + HashPosition pointer; + long index = 0; + char *key = NULL; + int key_len = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az", &zarray, &zoffset) == FAILURE) { + return; + } + + arr_hash = Z_ARRVAL_P(zarray); + array_init(return_value); + + switch (Z_TYPE_P(zoffset)) { + case IS_NULL: + index = 0; + break; + case IS_DOUBLE: + index = (long)Z_DVAL_P(zoffset); + break; + case IS_BOOL: + case IS_LONG: + case IS_RESOURCE: + index = Z_LVAL_P(zoffset); + break; + case IS_STRING: + key = Z_STRVAL_P(zoffset); + key_len = Z_STRLEN_P(zoffset); + break; + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The key should be either a string or an integer"); + return; + } + + for (zend_hash_internal_pointer_reset_ex(arr_hash, &pointer); + zend_hash_get_current_data_ex(arr_hash, (void**)&data, &pointer) == SUCCESS; + zend_hash_move_forward_ex(arr_hash, &pointer)) { + + if (Z_TYPE_PP(data) == IS_ARRAY) { + if (key && zend_hash_find(Z_ARRVAL_PP(data), key, key_len + 1, (void**)&zvalue) == FAILURE) { + continue; + } else if (!key && zend_hash_index_find(Z_ARRVAL_PP(data), index, (void**)&zvalue) == FAILURE) { + continue; + } + + switch (Z_TYPE_PP(zvalue)) { + case IS_NULL: + add_next_index_null(return_value); + break; + case IS_LONG: + add_next_index_long(return_value, Z_LVAL_PP(zvalue)); + break; + case IS_DOUBLE: + add_next_index_double(return_value, Z_DVAL_PP(zvalue)); + break; + case IS_BOOL: + add_next_index_bool(return_value, Z_BVAL_PP(zvalue)); + break; + case IS_OBJECT: + zval_add_ref(zvalue); + add_next_index_zval(return_value, *zvalue); + break; + case IS_STRING: + add_next_index_stringl(return_value, Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue), 1); + break; + case IS_RESOURCE: + zval_add_ref(zvalue); + add_next_index_resource(return_value, Z_RESVAL_PP(zvalue)); + break; + } + } + + } +} +/* }}} */ + /* {{{ proto array array_reverse(array input [, bool preserve keys]) Return input as a new array with the order of the entries reversed */ PHP_FUNCTION(array_reverse) diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 61e2f39049a..2e441508716 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -433,6 +433,11 @@ ZEND_BEGIN_ARG_INFO(arginfo_array_count_values, 0) ZEND_ARG_INFO(0, arg) /* ARRAY_INFO(0, arg, 0) */ ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_array_column, 0, 0, 2) + ZEND_ARG_INFO(0, arg) /* ARRAY_INFO(0, arg, 0) */ + ZEND_ARG_INFO(0, key) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_array_reverse, 0, 0, 1) ZEND_ARG_INFO(0, input) /* ARRAY_INFO(0, arg, 0) */ ZEND_ARG_INFO(0, preserve_keys) @@ -3299,6 +3304,7 @@ const zend_function_entry basic_functions[] = { /* {{{ */ PHP_FE(array_keys, arginfo_array_keys) PHP_FE(array_values, arginfo_array_values) PHP_FE(array_count_values, arginfo_array_count_values) + PHP_FE(array_column, arginfo_array_column) PHP_FE(array_reverse, arginfo_array_reverse) PHP_FE(array_reduce, arginfo_array_reduce) PHP_FE(array_pad, arginfo_array_pad) diff --git a/ext/standard/php_array.h b/ext/standard/php_array.h index 90990172907..2126c09d0bd 100644 --- a/ext/standard/php_array.h +++ b/ext/standard/php_array.h @@ -71,6 +71,7 @@ PHP_FUNCTION(array_replace_recursive); PHP_FUNCTION(array_keys); PHP_FUNCTION(array_values); PHP_FUNCTION(array_count_values); +PHP_FUNCTION(array_column); PHP_FUNCTION(array_reverse); PHP_FUNCTION(array_reduce); PHP_FUNCTION(array_pad); diff --git a/ext/standard/tests/array/array_column.phpt b/ext/standard/tests/array/array_column.phpt new file mode 100644 index 00000000000..08df3b8df9c --- /dev/null +++ b/ext/standard/tests/array/array_column.phpt @@ -0,0 +1,138 @@ +--TEST-- +Test array_column_values() function +--FILE-- + 1, + 'first_name' => 'John', + 'last_name' => 'Doe' + ), + array( + 'id' => 2, + 'first_name' => 'Sally', + 'last_name' => 'Smith' + ), + array( + 'id' => 3, + 'first_name' => 'Jane', + 'last_name' => 'Jones' + ) +); + +echo "-- first_name column from recordset --\n"; +var_dump(array_column($records, 'first_name')); + +echo "-- id column from recordset --\n"; +var_dump(array_column($records, 'id')); + +echo "\n*** Testing multiple data types ***\n"; +$file = basename(__FILE__); +$fh = fopen($file, 'r', true); +$values = array( + array( + 'id' => 1, + 'value' => new stdClass + ), + array( + 'id' => 2, + 'value' => 34.2345 + ), + array( + 'id' => 3, + 'value' => true + ), + array( + 'id' => 4, + 'value' => false + ), + array( + 'id' => 5, + 'value' => null + ), + array( + 'id' => 6, + 'value' => 1234 + ), + array( + 'id' => 7, + 'value' => 'Foo' + ), + array( + 'id' => 8, + 'value' => $fh + ) +); +var_dump(array_column($values, 'value')); + +echo "\n*** Testing numeric column keys ***\n"; +$numericCols = array( + array('aaa', '111'), + array('bbb', '222'), + array('ccc', '333') +); +var_dump(array_column($numericCols, 1)); + +echo "Done\n"; +?> +--EXPECTF-- +*** Testing basic functionalities *** +-- first_name column from recordset -- +array(3) { + [0]=> + string(4) "John" + [1]=> + string(5) "Sally" + [2]=> + string(4) "Jane" +} +-- id column from recordset -- +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} + +*** Testing multiple data types *** +array(8) { + [0]=> + object(stdClass)#1 (0) { + } + [1]=> + float(34.2345) + [2]=> + bool(true) + [3]=> + bool(false) + [4]=> + NULL + [5]=> + int(1234) + [6]=> + string(3) "Foo" + [7]=> + resource(5) of type (stream) +} + +*** Testing numeric column keys *** +array(3) { + [0]=> + string(3) "111" + [1]=> + string(3) "222" + [2]=> + string(3) "333" +} +Done From a811e5b6f78dfd56074758fa17d37816628d928f Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Fri, 13 Apr 2012 23:43:04 -0500 Subject: [PATCH 002/276] Adding tests for the negative results of array_column() --- ext/standard/tests/array/array_column.phpt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ext/standard/tests/array/array_column.phpt b/ext/standard/tests/array/array_column.phpt index 08df3b8df9c..8beb0c23c01 100644 --- a/ext/standard/tests/array/array_column.phpt +++ b/ext/standard/tests/array/array_column.phpt @@ -82,6 +82,14 @@ $numericCols = array( ); var_dump(array_column($numericCols, 1)); +echo "\n*** Testing failure to find specified column ***\n"; +var_dump(array_column($numericCols, 2)); +var_dump(array_column($numericCols, 'foo')); + +echo "\n*** Testing single dimensional array ***\n"; +$singleDimension = array('foo', 'bar', 'baz'); +var_dump(array_column($singleDimension, 1)); + echo "Done\n"; ?> --EXPECTF-- @@ -135,4 +143,14 @@ array(3) { [2]=> string(3) "333" } + +*** Testing failure to find specified column *** +array(0) { +} +array(0) { +} + +*** Testing single dimensional array *** +array(0) { +} Done From dc4dfe8ae019ec1fddc05ac340ed612a9c3f6d34 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Fri, 13 Apr 2012 23:57:12 -0500 Subject: [PATCH 003/276] Adding test for columns not present in all rows for array_column(). --- ext/standard/tests/array/array_column.phpt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ext/standard/tests/array/array_column.phpt b/ext/standard/tests/array/array_column.phpt index 8beb0c23c01..030435a20cc 100644 --- a/ext/standard/tests/array/array_column.phpt +++ b/ext/standard/tests/array/array_column.phpt @@ -90,6 +90,13 @@ echo "\n*** Testing single dimensional array ***\n"; $singleDimension = array('foo', 'bar', 'baz'); var_dump(array_column($singleDimension, 1)); +echo "\n*** Testing columns not present in all rows ***\n"; +$mismatchedColumns = array( + array('a' => 'foo', 'b' => 'bar'), + array('a' => 'baz', 'c' => 'qux'), +); +var_dump(array_column($mismatchedColumns, 'c')); + echo "Done\n"; ?> --EXPECTF-- @@ -153,4 +160,10 @@ array(0) { *** Testing single dimensional array *** array(0) { } + +*** Testing columns not present in all rows *** +array(1) { + [0]=> + string(3) "qux" +} Done From 6a27b890e6d643f17072e561a5d4f87211195a7c Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Sat, 14 Apr 2012 02:39:25 -0500 Subject: [PATCH 004/276] Simplify the code and use zend_hash_next_index_insert() --- ext/standard/array.c | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index b707301bd85..c5d0fa77475 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2613,31 +2613,8 @@ PHP_FUNCTION(array_column) continue; } - switch (Z_TYPE_PP(zvalue)) { - case IS_NULL: - add_next_index_null(return_value); - break; - case IS_LONG: - add_next_index_long(return_value, Z_LVAL_PP(zvalue)); - break; - case IS_DOUBLE: - add_next_index_double(return_value, Z_DVAL_PP(zvalue)); - break; - case IS_BOOL: - add_next_index_bool(return_value, Z_BVAL_PP(zvalue)); - break; - case IS_OBJECT: - zval_add_ref(zvalue); - add_next_index_zval(return_value, *zvalue); - break; - case IS_STRING: - add_next_index_stringl(return_value, Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue), 1); - break; - case IS_RESOURCE: - zval_add_ref(zvalue); - add_next_index_resource(return_value, Z_RESVAL_PP(zvalue)); - break; - } + Z_ADDREF_PP(zvalue); + zend_hash_next_index_insert(HASH_OF(return_value), (void **)zvalue, sizeof(zval *), NULL); } } From 10da6f00b8d0fa573b3c44f685377a98a816af51 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Sat, 14 Apr 2012 02:39:46 -0500 Subject: [PATCH 005/276] Fixing typo in test for array_column() --- ext/standard/tests/array/array_column.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/tests/array/array_column.phpt b/ext/standard/tests/array/array_column.phpt index 030435a20cc..a7a1b450528 100644 --- a/ext/standard/tests/array/array_column.phpt +++ b/ext/standard/tests/array/array_column.phpt @@ -1,5 +1,5 @@ --TEST-- -Test array_column_values() function +Test array_column() function --FILE-- Date: Sat, 14 Apr 2012 08:23:51 -0500 Subject: [PATCH 006/276] array_column: Cleaning up, as recommended in pull request #56 comments --- ext/standard/array.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index c5d0fa77475..b5d8275de7f 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2578,19 +2578,11 @@ PHP_FUNCTION(array_column) return; } - arr_hash = Z_ARRVAL_P(zarray); - array_init(return_value); - switch (Z_TYPE_P(zoffset)) { case IS_NULL: index = 0; break; - case IS_DOUBLE: - index = (long)Z_DVAL_P(zoffset); - break; - case IS_BOOL: case IS_LONG: - case IS_RESOURCE: index = Z_LVAL_P(zoffset); break; case IS_STRING: @@ -2599,9 +2591,12 @@ PHP_FUNCTION(array_column) break; default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "The key should be either a string or an integer"); - return; + RETURN_FALSE; } + arr_hash = Z_ARRVAL_P(zarray); + array_init(return_value); + for (zend_hash_internal_pointer_reset_ex(arr_hash, &pointer); zend_hash_get_current_data_ex(arr_hash, (void**)&data, &pointer) == SUCCESS; zend_hash_move_forward_ex(arr_hash, &pointer)) { From 5f6b20a44d833ede5e47b3b09c98678522347de1 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Sat, 14 Apr 2012 11:19:55 -0500 Subject: [PATCH 007/276] array_column: Improved tests --- ...ay_column.phpt => array_column_basic.phpt} | 6 +- .../tests/array/array_column_error.phpt | 82 +++++++++++++++++++ 2 files changed, 85 insertions(+), 3 deletions(-) rename ext/standard/tests/array/{array_column.phpt => array_column_basic.phpt} (94%) create mode 100644 ext/standard/tests/array/array_column_error.phpt diff --git a/ext/standard/tests/array/array_column.phpt b/ext/standard/tests/array/array_column_basic.phpt similarity index 94% rename from ext/standard/tests/array/array_column.phpt rename to ext/standard/tests/array/array_column_basic.phpt index a7a1b450528..efa98cef96e 100644 --- a/ext/standard/tests/array/array_column.phpt +++ b/ext/standard/tests/array/array_column_basic.phpt @@ -1,5 +1,5 @@ --TEST-- -Test array_column() function +Test array_column() function: basic functionality --FILE-- --EXPECTF-- -*** Testing basic functionalities *** +*** Testing array_column() : basic functionality *** -- first_name column from recordset -- array(3) { [0]=> diff --git a/ext/standard/tests/array/array_column_error.phpt b/ext/standard/tests/array/array_column_error.phpt new file mode 100644 index 00000000000..d409d3b12e0 --- /dev/null +++ b/ext/standard/tests/array/array_column_error.phpt @@ -0,0 +1,82 @@ +--TEST-- +Test array_column() function: error conditions +--FILE-- + +--EXPECTF-- +*** Testing array_column() : error conditions *** + +-- Testing array_column() function with Zero arguments -- + +Warning: array_column() expects exactly 2 parameters, 0 given in %s on line %d +NULL + +-- Testing array_column() function with One argument -- + +Warning: array_column() expects exactly 2 parameters, 1 given in %s on line %d +NULL + +-- Testing array_column() function with more than expected no. of arguments -- + +Warning: array_column() expects exactly 2 parameters, 3 given in %s on line %d +NULL + +-- Testing array_column() function with string as first parameter -- + +Warning: array_column() expects parameter 1 to be array, string given in %s on line %d +NULL + +-- Testing array_column() function with int as first parameter -- + +Warning: array_column() expects parameter 1 to be array, integer given in %s on line %d +NULL + +-- Testing array_column() key parameter should be a string or an integer (testing bool) -- + +Warning: array_column(): The key should be either a string or an integer in %s on line %d +bool(false) + +-- Testing array_column() key parameter should be a string or integer (testing float) -- + +Warning: array_column(): The key should be either a string or an integer in %s on line %d +bool(false) + +-- Testing array_column() key parameter should be a string or integer (testing array) -- + +Warning: array_column(): The key should be either a string or an integer in %s on line %d +bool(false) +Done From 66a02eb25e1533c2ace47f8d934b193ebe317cde Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Sat, 14 Apr 2012 11:36:58 -0500 Subject: [PATCH 008/276] array_column: Using add_next_index_zval() at nikic's recommendation. --- ext/standard/array.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index b5d8275de7f..40ee947fa58 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2609,7 +2609,7 @@ PHP_FUNCTION(array_column) } Z_ADDREF_PP(zvalue); - zend_hash_next_index_insert(HASH_OF(return_value), (void **)zvalue, sizeof(zval *), NULL); + add_next_index_zval(return_value, *zvalue); } } From 20ab30339d9731dd6e85ea5029280148f519cdc7 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Sun, 15 Apr 2012 21:40:45 -0500 Subject: [PATCH 009/276] array_column: Adding test for IS_OBJECT and converting object to string --- ext/standard/array.c | 5 +++++ .../tests/array/array_column_basic.phpt | 21 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/ext/standard/array.c b/ext/standard/array.c index 40ee947fa58..00850ba49ab 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2589,6 +2589,11 @@ PHP_FUNCTION(array_column) key = Z_STRVAL_P(zoffset); key_len = Z_STRLEN_P(zoffset); break; + case IS_OBJECT: + convert_to_string_ex(&zoffset); + key = Z_STRVAL_P(zoffset); + key_len = Z_STRLEN_P(zoffset); + break; default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "The key should be either a string or an integer"); RETURN_FALSE; diff --git a/ext/standard/tests/array/array_column_basic.phpt b/ext/standard/tests/array/array_column_basic.phpt index efa98cef96e..fa8fe2fb5a4 100644 --- a/ext/standard/tests/array/array_column_basic.phpt +++ b/ext/standard/tests/array/array_column_basic.phpt @@ -97,6 +97,17 @@ $mismatchedColumns = array( ); var_dump(array_column($mismatchedColumns, 'c')); +echo "\n*** Testing use of object converted to string ***\n"; +class Foo +{ + public function __toString() + { + return 'last_name'; + } +} +$f = new Foo(); +var_dump(array_column($records, $f)); + echo "Done\n"; ?> --EXPECTF-- @@ -166,4 +177,14 @@ array(1) { [0]=> string(3) "qux" } + +*** Testing use of object converted to string *** +array(3) { + [0]=> + string(3) "Doe" + [1]=> + string(5) "Smith" + [2]=> + string(5) "Jones" +} Done From 94d5b2519aa6790e603cec7a054900941ffe07a9 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Thu, 21 Jun 2012 12:47:54 -0500 Subject: [PATCH 010/276] Cleaning up a memory leak. --- ext/standard/array.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 00850ba49ab..91a8833347d 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2590,7 +2590,7 @@ PHP_FUNCTION(array_column) key_len = Z_STRLEN_P(zoffset); break; case IS_OBJECT: - convert_to_string_ex(&zoffset); + convert_to_string(zoffset); key = Z_STRVAL_P(zoffset); key_len = Z_STRLEN_P(zoffset); break; From 5bc2854b37778d7f402db8bb9be9fe33df64258e Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Fri, 11 Jan 2013 16:57:11 -0600 Subject: [PATCH 011/276] array_column: Implement ability to specify an index column --- ext/standard/array.c | 97 +++++++++++--- ext/standard/basic_functions.c | 3 +- .../tests/array/array_column_basic.phpt | 123 +++++++++++++++++- .../tests/array/array_column_error.phpt | 56 +++++--- 4 files changed, 235 insertions(+), 44 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 91a8833347d..fa197375228 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2563,42 +2563,66 @@ PHP_FUNCTION(array_count_values) } /* }}} */ -/* {{{ proto array array_column(array input, mixed key) - Return the values from a single column in the input array, identified by the key */ +/* {{{ proto array array_column(array input, mixed column_key[, mixed index_key]) + Return the values from a single column in the input array, identified by the + value_key and optionally indexed by the index_key */ PHP_FUNCTION(array_column) { - zval *zarray, *zoffset, **data, **zvalue; + zval *zarray, *zcolumn, *zkey = NULL, **data, **zcolval, **zkeyval; HashTable *arr_hash; HashPosition pointer; - long index = 0; - char *key = NULL; - int key_len = 0; + ulong column_idx = 0, key_idx = 0, keyval_idx = 0; + char *column = NULL, *key = NULL, *keyval = NULL; + int column_len = 0, key_len = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az", &zarray, &zoffset) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az|z", &zarray, &zcolumn, &zkey) == FAILURE) { return; } - switch (Z_TYPE_P(zoffset)) { + switch (Z_TYPE_P(zcolumn)) { case IS_NULL: - index = 0; + column_idx = 0; break; case IS_LONG: - index = Z_LVAL_P(zoffset); + column_idx = Z_LVAL_P(zcolumn); break; case IS_STRING: - key = Z_STRVAL_P(zoffset); - key_len = Z_STRLEN_P(zoffset); + column = Z_STRVAL_P(zcolumn); + column_len = Z_STRLEN_P(zcolumn); break; case IS_OBJECT: - convert_to_string(zoffset); - key = Z_STRVAL_P(zoffset); - key_len = Z_STRLEN_P(zoffset); + convert_to_string(zcolumn); + column = Z_STRVAL_P(zcolumn); + column_len = Z_STRLEN_P(zcolumn); break; default: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The key should be either a string or an integer"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The column key should be either a string or an integer"); RETURN_FALSE; } + if (zkey) { + switch (Z_TYPE_P(zkey)) { + case IS_NULL: + key_idx = 0; + break; + case IS_LONG: + key_idx = Z_LVAL_P(zkey); + break; + case IS_STRING: + key = Z_STRVAL_P(zkey); + key_len = Z_STRLEN_P(zkey); + break; + case IS_OBJECT: + convert_to_string(zkey); + key = Z_STRVAL_P(zkey); + key_len = Z_STRLEN_P(zkey); + break; + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The index key should be either a string or an integer"); + RETURN_FALSE; + } + } + arr_hash = Z_ARRVAL_P(zarray); array_init(return_value); @@ -2607,14 +2631,47 @@ PHP_FUNCTION(array_column) zend_hash_move_forward_ex(arr_hash, &pointer)) { if (Z_TYPE_PP(data) == IS_ARRAY) { - if (key && zend_hash_find(Z_ARRVAL_PP(data), key, key_len + 1, (void**)&zvalue) == FAILURE) { + if (column && zend_hash_find(Z_ARRVAL_PP(data), column, column_len + 1, (void**)&zcolval) == FAILURE) { continue; - } else if (!key && zend_hash_index_find(Z_ARRVAL_PP(data), index, (void**)&zvalue) == FAILURE) { + } else if (!column && zend_hash_index_find(Z_ARRVAL_PP(data), column_idx, (void**)&zcolval) == FAILURE) { continue; } - Z_ADDREF_PP(zvalue); - add_next_index_zval(return_value, *zvalue); + Z_ADDREF_PP(zcolval); + + keyval = NULL; + keyval_idx = NULL; + + if (zkey) { + if (key && zend_hash_find(Z_ARRVAL_PP(data), key, key_len + 1, (void**)&zkeyval) == FAILURE) { + keyval_idx = NULL; + } else if (!key && zend_hash_index_find(Z_ARRVAL_PP(data), key_idx, (void**)&zkeyval) == FAILURE) { + keyval_idx = NULL; + } else { + switch (Z_TYPE_PP(zkeyval)) { + case IS_LONG: + keyval_idx = Z_LVAL_PP(zkeyval); + break; + case IS_STRING: + keyval = Z_STRVAL_PP(zkeyval); + break; + case IS_OBJECT: + convert_to_string(*zkeyval); + keyval = Z_STRVAL_PP(zkeyval); + break; + default: + keyval_idx = NULL; + } + } + } + + if (keyval) { + add_assoc_zval(return_value, keyval, *zcolval); + } else if (keyval_idx != NULL) { + add_index_zval(return_value, keyval_idx, *zcolval); + } else { + add_next_index_zval(return_value, *zcolval); + } } } diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 2e441508716..5e123528c32 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -435,7 +435,8 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_array_column, 0, 0, 2) ZEND_ARG_INFO(0, arg) /* ARRAY_INFO(0, arg, 0) */ - ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, column_key) + ZEND_ARG_INFO(0, index_key) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_array_reverse, 0, 0, 1) diff --git a/ext/standard/tests/array/array_column_basic.phpt b/ext/standard/tests/array/array_column_basic.phpt index fa8fe2fb5a4..70ce2136b44 100644 --- a/ext/standard/tests/array/array_column_basic.phpt +++ b/ext/standard/tests/array/array_column_basic.phpt @@ -3,7 +3,7 @@ Test array_column() function: basic functionality --FILE-- 'foo', 'b' => 'bar'), - array('a' => 'baz', 'c' => 'qux'), + array('a' => 'foo', 'b' => 'bar', 'e' => 'bbb'), + array('a' => 'baz', 'c' => 'qux', 'd' => 'aaa'), + array('a' => 'eee', 'b' => 'fff', 'e' => 'ggg'), ); var_dump(array_column($mismatchedColumns, 'c')); +var_dump(array_column($mismatchedColumns, 'c', 'a')); +var_dump(array_column($mismatchedColumns, 'a', 'd')); +var_dump(array_column($mismatchedColumns, 'a', 'e')); +var_dump(array_column($mismatchedColumns, 'b')); +var_dump(array_column($mismatchedColumns, 'b', 'a')); echo "\n*** Testing use of object converted to string ***\n"; class Foo @@ -105,8 +120,17 @@ class Foo return 'last_name'; } } +class Bar +{ + public function __toString() + { + return 'first_name'; + } +} $f = new Foo(); +$b = new Bar(); var_dump(array_column($records, $f)); +var_dump(array_column($records, $f, $b)); echo "Done\n"; ?> @@ -130,6 +154,24 @@ array(3) { [2]=> int(3) } +-- last_name column from recordset, keyed by value from id column -- +array(3) { + [1]=> + string(3) "Doe" + [2]=> + string(5) "Smith" + [3]=> + string(5) "Jones" +} +-- last_name column from recordset, keyed by value from first_name column -- +array(3) { + ["John"]=> + string(3) "Doe" + ["Sally"]=> + string(5) "Smith" + ["Jane"]=> + string(5) "Jones" +} *** Testing multiple data types *** array(8) { @@ -151,6 +193,25 @@ array(8) { [7]=> resource(5) of type (stream) } +array(8) { + [1]=> + object(stdClass)#1 (0) { + } + [2]=> + float(34.2345) + [3]=> + bool(true) + [4]=> + bool(false) + [5]=> + NULL + [6]=> + int(1234) + [7]=> + string(3) "Foo" + [8]=> + resource(5) of type (stream) +} *** Testing numeric column keys *** array(3) { @@ -161,12 +222,28 @@ array(3) { [2]=> string(3) "333" } +array(3) { + ["aaa"]=> + string(3) "111" + ["bbb"]=> + string(3) "222" + ["ccc"]=> + string(3) "333" +} *** Testing failure to find specified column *** array(0) { } array(0) { } +array(3) { + [0]=> + string(3) "aaa" + [1]=> + string(3) "bbb" + [2]=> + string(3) "ccc" +} *** Testing single dimensional array *** array(0) { @@ -177,6 +254,38 @@ array(1) { [0]=> string(3) "qux" } +array(1) { + ["baz"]=> + string(3) "qux" +} +array(3) { + [0]=> + string(3) "foo" + ["aaa"]=> + string(3) "baz" + [1]=> + string(3) "eee" +} +array(3) { + ["bbb"]=> + string(3) "foo" + [0]=> + string(3) "baz" + ["ggg"]=> + string(3) "eee" +} +array(2) { + [0]=> + string(3) "bar" + [1]=> + string(3) "fff" +} +array(2) { + ["foo"]=> + string(3) "bar" + ["eee"]=> + string(3) "fff" +} *** Testing use of object converted to string *** array(3) { @@ -187,4 +296,12 @@ array(3) { [2]=> string(5) "Jones" } +array(3) { + ["John"]=> + string(3) "Doe" + ["Sally"]=> + string(5) "Smith" + ["Jane"]=> + string(5) "Jones" +} Done diff --git a/ext/standard/tests/array/array_column_error.phpt b/ext/standard/tests/array/array_column_error.phpt index d409d3b12e0..1aec1acc636 100644 --- a/ext/standard/tests/array/array_column_error.phpt +++ b/ext/standard/tests/array/array_column_error.phpt @@ -3,7 +3,7 @@ Test array_column() function: error conditions --FILE-- --EXPECTF-- @@ -42,17 +48,12 @@ echo "Done\n"; -- Testing array_column() function with Zero arguments -- -Warning: array_column() expects exactly 2 parameters, 0 given in %s on line %d +Warning: array_column() expects at least 2 parameters, 0 given in %s on line %d NULL -- Testing array_column() function with One argument -- -Warning: array_column() expects exactly 2 parameters, 1 given in %s on line %d -NULL - --- Testing array_column() function with more than expected no. of arguments -- - -Warning: array_column() expects exactly 2 parameters, 3 given in %s on line %d +Warning: array_column() expects at least 2 parameters, 1 given in %s on line %d NULL -- Testing array_column() function with string as first parameter -- @@ -65,18 +66,33 @@ NULL Warning: array_column() expects parameter 1 to be array, integer given in %s on line %d NULL --- Testing array_column() key parameter should be a string or an integer (testing bool) -- +-- Testing array_column() column key parameter should be a string or an integer (testing bool) -- -Warning: array_column(): The key should be either a string or an integer in %s on line %d +Warning: array_column(): The column key should be either a string or an integer in %s on line %d bool(false) --- Testing array_column() key parameter should be a string or integer (testing float) -- +-- Testing array_column() column key parameter should be a string or integer (testing float) -- -Warning: array_column(): The key should be either a string or an integer in %s on line %d +Warning: array_column(): The column key should be either a string or an integer in %s on line %d bool(false) --- Testing array_column() key parameter should be a string or integer (testing array) -- +-- Testing array_column() column key parameter should be a string or integer (testing array) -- -Warning: array_column(): The key should be either a string or an integer in %s on line %d +Warning: array_column(): The column key should be either a string or an integer in %s on line %d +bool(false) + +-- Testing array_column() index key parameter should be a string or an integer (testing bool) -- + +Warning: array_column(): The index key should be either a string or an integer in %s on line %d +bool(false) + +-- Testing array_column() index key parameter should be a string or integer (testing float) -- + +Warning: array_column(): The index key should be either a string or an integer in %s on line %d +bool(false) + +-- Testing array_column() index key parameter should be a string or integer (testing array) -- + +Warning: array_column(): The index key should be either a string or an integer in %s on line %d bool(false) Done From a1876b6846898724f564208f78281dfd8ce07112 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Fri, 11 Jan 2013 17:09:34 -0600 Subject: [PATCH 012/276] array_column: Set array_pluck as an alias for array_column --- ext/standard/basic_functions.c | 1 + .../tests/array/array_column_pluck_alias.phpt | 307 ++++++++++++++++++ .../array/array_column_pluck_alias_error.phpt | 98 ++++++ 3 files changed, 406 insertions(+) create mode 100644 ext/standard/tests/array/array_column_pluck_alias.phpt create mode 100644 ext/standard/tests/array/array_column_pluck_alias_error.phpt diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 5e123528c32..6e1835dc603 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -3306,6 +3306,7 @@ const zend_function_entry basic_functions[] = { /* {{{ */ PHP_FE(array_values, arginfo_array_values) PHP_FE(array_count_values, arginfo_array_count_values) PHP_FE(array_column, arginfo_array_column) + PHP_FALIAS(array_pluck, array_column, arginfo_array_column) PHP_FE(array_reverse, arginfo_array_reverse) PHP_FE(array_reduce, arginfo_array_reduce) PHP_FE(array_pad, arginfo_array_pad) diff --git a/ext/standard/tests/array/array_column_pluck_alias.phpt b/ext/standard/tests/array/array_column_pluck_alias.phpt new file mode 100644 index 00000000000..4bd251a7f26 --- /dev/null +++ b/ext/standard/tests/array/array_column_pluck_alias.phpt @@ -0,0 +1,307 @@ +--TEST-- +Test array_pluck() function: basic functionality +--FILE-- + 1, + 'first_name' => 'John', + 'last_name' => 'Doe' + ), + array( + 'id' => 2, + 'first_name' => 'Sally', + 'last_name' => 'Smith' + ), + array( + 'id' => 3, + 'first_name' => 'Jane', + 'last_name' => 'Jones' + ) +); + +echo "-- first_name column from recordset --\n"; +var_dump(array_pluck($records, 'first_name')); + +echo "-- id column from recordset --\n"; +var_dump(array_pluck($records, 'id')); + +echo "-- last_name column from recordset, keyed by value from id column --\n"; +var_dump(array_pluck($records, 'last_name', 'id')); + +echo "-- last_name column from recordset, keyed by value from first_name column --\n"; +var_dump(array_pluck($records, 'last_name', 'first_name')); + +echo "\n*** Testing multiple data types ***\n"; +$file = basename(__FILE__); +$fh = fopen($file, 'r', true); +$values = array( + array( + 'id' => 1, + 'value' => new stdClass + ), + array( + 'id' => 2, + 'value' => 34.2345 + ), + array( + 'id' => 3, + 'value' => true + ), + array( + 'id' => 4, + 'value' => false + ), + array( + 'id' => 5, + 'value' => null + ), + array( + 'id' => 6, + 'value' => 1234 + ), + array( + 'id' => 7, + 'value' => 'Foo' + ), + array( + 'id' => 8, + 'value' => $fh + ) +); +var_dump(array_pluck($values, 'value')); +var_dump(array_pluck($values, 'value', 'id')); + +echo "\n*** Testing numeric column keys ***\n"; +$numericCols = array( + array('aaa', '111'), + array('bbb', '222'), + array('ccc', '333') +); +var_dump(array_pluck($numericCols, 1)); +var_dump(array_pluck($numericCols, 1, 0)); + +echo "\n*** Testing failure to find specified column ***\n"; +var_dump(array_pluck($numericCols, 2)); +var_dump(array_pluck($numericCols, 'foo')); +var_dump(array_pluck($numericCols, 0, 'foo')); + +echo "\n*** Testing single dimensional array ***\n"; +$singleDimension = array('foo', 'bar', 'baz'); +var_dump(array_pluck($singleDimension, 1)); + +echo "\n*** Testing columns not present in all rows ***\n"; +$mismatchedColumns = array( + array('a' => 'foo', 'b' => 'bar', 'e' => 'bbb'), + array('a' => 'baz', 'c' => 'qux', 'd' => 'aaa'), + array('a' => 'eee', 'b' => 'fff', 'e' => 'ggg'), +); +var_dump(array_pluck($mismatchedColumns, 'c')); +var_dump(array_pluck($mismatchedColumns, 'c', 'a')); +var_dump(array_pluck($mismatchedColumns, 'a', 'd')); +var_dump(array_pluck($mismatchedColumns, 'a', 'e')); +var_dump(array_pluck($mismatchedColumns, 'b')); +var_dump(array_pluck($mismatchedColumns, 'b', 'a')); + +echo "\n*** Testing use of object converted to string ***\n"; +class Foo +{ + public function __toString() + { + return 'last_name'; + } +} +class Bar +{ + public function __toString() + { + return 'first_name'; + } +} +$f = new Foo(); +$b = new Bar(); +var_dump(array_pluck($records, $f)); +var_dump(array_pluck($records, $f, $b)); + +echo "Done\n"; +?> +--EXPECTF-- +*** Testing array_pluck() : basic functionality *** +-- first_name column from recordset -- +array(3) { + [0]=> + string(4) "John" + [1]=> + string(5) "Sally" + [2]=> + string(4) "Jane" +} +-- id column from recordset -- +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +-- last_name column from recordset, keyed by value from id column -- +array(3) { + [1]=> + string(3) "Doe" + [2]=> + string(5) "Smith" + [3]=> + string(5) "Jones" +} +-- last_name column from recordset, keyed by value from first_name column -- +array(3) { + ["John"]=> + string(3) "Doe" + ["Sally"]=> + string(5) "Smith" + ["Jane"]=> + string(5) "Jones" +} + +*** Testing multiple data types *** +array(8) { + [0]=> + object(stdClass)#1 (0) { + } + [1]=> + float(34.2345) + [2]=> + bool(true) + [3]=> + bool(false) + [4]=> + NULL + [5]=> + int(1234) + [6]=> + string(3) "Foo" + [7]=> + resource(5) of type (stream) +} +array(8) { + [1]=> + object(stdClass)#1 (0) { + } + [2]=> + float(34.2345) + [3]=> + bool(true) + [4]=> + bool(false) + [5]=> + NULL + [6]=> + int(1234) + [7]=> + string(3) "Foo" + [8]=> + resource(5) of type (stream) +} + +*** Testing numeric column keys *** +array(3) { + [0]=> + string(3) "111" + [1]=> + string(3) "222" + [2]=> + string(3) "333" +} +array(3) { + ["aaa"]=> + string(3) "111" + ["bbb"]=> + string(3) "222" + ["ccc"]=> + string(3) "333" +} + +*** Testing failure to find specified column *** +array(0) { +} +array(0) { +} +array(3) { + [0]=> + string(3) "aaa" + [1]=> + string(3) "bbb" + [2]=> + string(3) "ccc" +} + +*** Testing single dimensional array *** +array(0) { +} + +*** Testing columns not present in all rows *** +array(1) { + [0]=> + string(3) "qux" +} +array(1) { + ["baz"]=> + string(3) "qux" +} +array(3) { + [0]=> + string(3) "foo" + ["aaa"]=> + string(3) "baz" + [1]=> + string(3) "eee" +} +array(3) { + ["bbb"]=> + string(3) "foo" + [0]=> + string(3) "baz" + ["ggg"]=> + string(3) "eee" +} +array(2) { + [0]=> + string(3) "bar" + [1]=> + string(3) "fff" +} +array(2) { + ["foo"]=> + string(3) "bar" + ["eee"]=> + string(3) "fff" +} + +*** Testing use of object converted to string *** +array(3) { + [0]=> + string(3) "Doe" + [1]=> + string(5) "Smith" + [2]=> + string(5) "Jones" +} +array(3) { + ["John"]=> + string(3) "Doe" + ["Sally"]=> + string(5) "Smith" + ["Jane"]=> + string(5) "Jones" +} +Done diff --git a/ext/standard/tests/array/array_column_pluck_alias_error.phpt b/ext/standard/tests/array/array_column_pluck_alias_error.phpt new file mode 100644 index 00000000000..2f98ff5cadd --- /dev/null +++ b/ext/standard/tests/array/array_column_pluck_alias_error.phpt @@ -0,0 +1,98 @@ +--TEST-- +Test array_pluck() function: error conditions +--FILE-- + +--EXPECTF-- +*** Testing array_pluck() : error conditions *** + +-- Testing array_pluck() function with Zero arguments -- + +Warning: array_pluck() expects at least 2 parameters, 0 given in %s on line %d +NULL + +-- Testing array_pluck() function with One argument -- + +Warning: array_pluck() expects at least 2 parameters, 1 given in %s on line %d +NULL + +-- Testing array_pluck() function with string as first parameter -- + +Warning: array_pluck() expects parameter 1 to be array, string given in %s on line %d +NULL + +-- Testing array_pluck() function with int as first parameter -- + +Warning: array_pluck() expects parameter 1 to be array, integer given in %s on line %d +NULL + +-- Testing array_pluck() column key parameter should be a string or an integer (testing bool) -- + +Warning: array_pluck(): The column key should be either a string or an integer in %s on line %d +bool(false) + +-- Testing array_pluck() column key parameter should be a string or integer (testing float) -- + +Warning: array_pluck(): The column key should be either a string or an integer in %s on line %d +bool(false) + +-- Testing array_pluck() column key parameter should be a string or integer (testing array) -- + +Warning: array_pluck(): The column key should be either a string or an integer in %s on line %d +bool(false) + +-- Testing array_pluck() index key parameter should be a string or an integer (testing bool) -- + +Warning: array_pluck(): The index key should be either a string or an integer in %s on line %d +bool(false) + +-- Testing array_pluck() index key parameter should be a string or integer (testing float) -- + +Warning: array_pluck(): The index key should be either a string or an integer in %s on line %d +bool(false) + +-- Testing array_pluck() index key parameter should be a string or integer (testing array) -- + +Warning: array_pluck(): The index key should be either a string or an integer in %s on line %d +bool(false) +Done From 3439a098a0b646ff05d4da9748996214cac39d12 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Mon, 14 Jan 2013 10:04:14 -0600 Subject: [PATCH 013/276] array_column: Removed array_pluck() alias --- ext/standard/basic_functions.c | 1 - .../tests/array/array_column_pluck_alias.phpt | 307 ------------------ .../array/array_column_pluck_alias_error.phpt | 98 ------ 3 files changed, 406 deletions(-) delete mode 100644 ext/standard/tests/array/array_column_pluck_alias.phpt delete mode 100644 ext/standard/tests/array/array_column_pluck_alias_error.phpt diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 6e1835dc603..5e123528c32 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -3306,7 +3306,6 @@ const zend_function_entry basic_functions[] = { /* {{{ */ PHP_FE(array_values, arginfo_array_values) PHP_FE(array_count_values, arginfo_array_count_values) PHP_FE(array_column, arginfo_array_column) - PHP_FALIAS(array_pluck, array_column, arginfo_array_column) PHP_FE(array_reverse, arginfo_array_reverse) PHP_FE(array_reduce, arginfo_array_reduce) PHP_FE(array_pad, arginfo_array_pad) diff --git a/ext/standard/tests/array/array_column_pluck_alias.phpt b/ext/standard/tests/array/array_column_pluck_alias.phpt deleted file mode 100644 index 4bd251a7f26..00000000000 --- a/ext/standard/tests/array/array_column_pluck_alias.phpt +++ /dev/null @@ -1,307 +0,0 @@ ---TEST-- -Test array_pluck() function: basic functionality ---FILE-- - 1, - 'first_name' => 'John', - 'last_name' => 'Doe' - ), - array( - 'id' => 2, - 'first_name' => 'Sally', - 'last_name' => 'Smith' - ), - array( - 'id' => 3, - 'first_name' => 'Jane', - 'last_name' => 'Jones' - ) -); - -echo "-- first_name column from recordset --\n"; -var_dump(array_pluck($records, 'first_name')); - -echo "-- id column from recordset --\n"; -var_dump(array_pluck($records, 'id')); - -echo "-- last_name column from recordset, keyed by value from id column --\n"; -var_dump(array_pluck($records, 'last_name', 'id')); - -echo "-- last_name column from recordset, keyed by value from first_name column --\n"; -var_dump(array_pluck($records, 'last_name', 'first_name')); - -echo "\n*** Testing multiple data types ***\n"; -$file = basename(__FILE__); -$fh = fopen($file, 'r', true); -$values = array( - array( - 'id' => 1, - 'value' => new stdClass - ), - array( - 'id' => 2, - 'value' => 34.2345 - ), - array( - 'id' => 3, - 'value' => true - ), - array( - 'id' => 4, - 'value' => false - ), - array( - 'id' => 5, - 'value' => null - ), - array( - 'id' => 6, - 'value' => 1234 - ), - array( - 'id' => 7, - 'value' => 'Foo' - ), - array( - 'id' => 8, - 'value' => $fh - ) -); -var_dump(array_pluck($values, 'value')); -var_dump(array_pluck($values, 'value', 'id')); - -echo "\n*** Testing numeric column keys ***\n"; -$numericCols = array( - array('aaa', '111'), - array('bbb', '222'), - array('ccc', '333') -); -var_dump(array_pluck($numericCols, 1)); -var_dump(array_pluck($numericCols, 1, 0)); - -echo "\n*** Testing failure to find specified column ***\n"; -var_dump(array_pluck($numericCols, 2)); -var_dump(array_pluck($numericCols, 'foo')); -var_dump(array_pluck($numericCols, 0, 'foo')); - -echo "\n*** Testing single dimensional array ***\n"; -$singleDimension = array('foo', 'bar', 'baz'); -var_dump(array_pluck($singleDimension, 1)); - -echo "\n*** Testing columns not present in all rows ***\n"; -$mismatchedColumns = array( - array('a' => 'foo', 'b' => 'bar', 'e' => 'bbb'), - array('a' => 'baz', 'c' => 'qux', 'd' => 'aaa'), - array('a' => 'eee', 'b' => 'fff', 'e' => 'ggg'), -); -var_dump(array_pluck($mismatchedColumns, 'c')); -var_dump(array_pluck($mismatchedColumns, 'c', 'a')); -var_dump(array_pluck($mismatchedColumns, 'a', 'd')); -var_dump(array_pluck($mismatchedColumns, 'a', 'e')); -var_dump(array_pluck($mismatchedColumns, 'b')); -var_dump(array_pluck($mismatchedColumns, 'b', 'a')); - -echo "\n*** Testing use of object converted to string ***\n"; -class Foo -{ - public function __toString() - { - return 'last_name'; - } -} -class Bar -{ - public function __toString() - { - return 'first_name'; - } -} -$f = new Foo(); -$b = new Bar(); -var_dump(array_pluck($records, $f)); -var_dump(array_pluck($records, $f, $b)); - -echo "Done\n"; -?> ---EXPECTF-- -*** Testing array_pluck() : basic functionality *** --- first_name column from recordset -- -array(3) { - [0]=> - string(4) "John" - [1]=> - string(5) "Sally" - [2]=> - string(4) "Jane" -} --- id column from recordset -- -array(3) { - [0]=> - int(1) - [1]=> - int(2) - [2]=> - int(3) -} --- last_name column from recordset, keyed by value from id column -- -array(3) { - [1]=> - string(3) "Doe" - [2]=> - string(5) "Smith" - [3]=> - string(5) "Jones" -} --- last_name column from recordset, keyed by value from first_name column -- -array(3) { - ["John"]=> - string(3) "Doe" - ["Sally"]=> - string(5) "Smith" - ["Jane"]=> - string(5) "Jones" -} - -*** Testing multiple data types *** -array(8) { - [0]=> - object(stdClass)#1 (0) { - } - [1]=> - float(34.2345) - [2]=> - bool(true) - [3]=> - bool(false) - [4]=> - NULL - [5]=> - int(1234) - [6]=> - string(3) "Foo" - [7]=> - resource(5) of type (stream) -} -array(8) { - [1]=> - object(stdClass)#1 (0) { - } - [2]=> - float(34.2345) - [3]=> - bool(true) - [4]=> - bool(false) - [5]=> - NULL - [6]=> - int(1234) - [7]=> - string(3) "Foo" - [8]=> - resource(5) of type (stream) -} - -*** Testing numeric column keys *** -array(3) { - [0]=> - string(3) "111" - [1]=> - string(3) "222" - [2]=> - string(3) "333" -} -array(3) { - ["aaa"]=> - string(3) "111" - ["bbb"]=> - string(3) "222" - ["ccc"]=> - string(3) "333" -} - -*** Testing failure to find specified column *** -array(0) { -} -array(0) { -} -array(3) { - [0]=> - string(3) "aaa" - [1]=> - string(3) "bbb" - [2]=> - string(3) "ccc" -} - -*** Testing single dimensional array *** -array(0) { -} - -*** Testing columns not present in all rows *** -array(1) { - [0]=> - string(3) "qux" -} -array(1) { - ["baz"]=> - string(3) "qux" -} -array(3) { - [0]=> - string(3) "foo" - ["aaa"]=> - string(3) "baz" - [1]=> - string(3) "eee" -} -array(3) { - ["bbb"]=> - string(3) "foo" - [0]=> - string(3) "baz" - ["ggg"]=> - string(3) "eee" -} -array(2) { - [0]=> - string(3) "bar" - [1]=> - string(3) "fff" -} -array(2) { - ["foo"]=> - string(3) "bar" - ["eee"]=> - string(3) "fff" -} - -*** Testing use of object converted to string *** -array(3) { - [0]=> - string(3) "Doe" - [1]=> - string(5) "Smith" - [2]=> - string(5) "Jones" -} -array(3) { - ["John"]=> - string(3) "Doe" - ["Sally"]=> - string(5) "Smith" - ["Jane"]=> - string(5) "Jones" -} -Done diff --git a/ext/standard/tests/array/array_column_pluck_alias_error.phpt b/ext/standard/tests/array/array_column_pluck_alias_error.phpt deleted file mode 100644 index 2f98ff5cadd..00000000000 --- a/ext/standard/tests/array/array_column_pluck_alias_error.phpt +++ /dev/null @@ -1,98 +0,0 @@ ---TEST-- -Test array_pluck() function: error conditions ---FILE-- - ---EXPECTF-- -*** Testing array_pluck() : error conditions *** - --- Testing array_pluck() function with Zero arguments -- - -Warning: array_pluck() expects at least 2 parameters, 0 given in %s on line %d -NULL - --- Testing array_pluck() function with One argument -- - -Warning: array_pluck() expects at least 2 parameters, 1 given in %s on line %d -NULL - --- Testing array_pluck() function with string as first parameter -- - -Warning: array_pluck() expects parameter 1 to be array, string given in %s on line %d -NULL - --- Testing array_pluck() function with int as first parameter -- - -Warning: array_pluck() expects parameter 1 to be array, integer given in %s on line %d -NULL - --- Testing array_pluck() column key parameter should be a string or an integer (testing bool) -- - -Warning: array_pluck(): The column key should be either a string or an integer in %s on line %d -bool(false) - --- Testing array_pluck() column key parameter should be a string or integer (testing float) -- - -Warning: array_pluck(): The column key should be either a string or an integer in %s on line %d -bool(false) - --- Testing array_pluck() column key parameter should be a string or integer (testing array) -- - -Warning: array_pluck(): The column key should be either a string or an integer in %s on line %d -bool(false) - --- Testing array_pluck() index key parameter should be a string or an integer (testing bool) -- - -Warning: array_pluck(): The index key should be either a string or an integer in %s on line %d -bool(false) - --- Testing array_pluck() index key parameter should be a string or integer (testing float) -- - -Warning: array_pluck(): The index key should be either a string or an integer in %s on line %d -bool(false) - --- Testing array_pluck() index key parameter should be a string or integer (testing array) -- - -Warning: array_pluck(): The index key should be either a string or an integer in %s on line %d -bool(false) -Done From 528006a3b49fd45d6b2803c7b7843b2e7d6929d6 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 13 Feb 2013 16:26:47 +0400 Subject: [PATCH 014/276] Open Source Release --- .gitignore | 87 + Optimizer/block_pass.c | 1967 +++++++++++++++++++++ Optimizer/nop_removal.c | 126 ++ Optimizer/optimize_temp_vars_5.c | 222 +++ Optimizer/pass10.c | 3 + Optimizer/pass1_5.c | 391 +++++ Optimizer/pass2.c | 210 +++ Optimizer/pass3.c | 443 +++++ Optimizer/pass5.c | 3 + Optimizer/pass9.c | 8 + Optimizer/zend_optimizer.c | 139 ++ Optimizer/zend_optimizer.h | 49 + Optimizer/zend_optimizer_internal.h | 76 + README | 171 ++ ZendAccelerator.c | 2510 +++++++++++++++++++++++++++ ZendAccelerator.h | 364 ++++ config.m4 | 345 ++++ config.w32 | 28 + shared_alloc_mmap.c | 70 + shared_alloc_posix.c | 90 + shared_alloc_shm.c | 137 ++ shared_alloc_win32.c | 315 ++++ zend_accelerator_blacklist.c | 241 +++ zend_accelerator_blacklist.h | 49 + zend_accelerator_debug.c | 101 ++ zend_accelerator_debug.h | 33 + zend_accelerator_hash.c | 222 +++ zend_accelerator_hash.h | 98 ++ zend_accelerator_module.c | 574 ++++++ zend_accelerator_module.h | 28 + zend_accelerator_util_funcs.c | 1079 ++++++++++++ zend_accelerator_util_funcs.h | 49 + zend_persist.c | 680 ++++++++ zend_persist.h | 29 + zend_persist_calc.c | 343 ++++ zend_shared_alloc.c | 473 +++++ zend_shared_alloc.h | 166 ++ 37 files changed, 11919 insertions(+) create mode 100644 .gitignore create mode 100644 Optimizer/block_pass.c create mode 100644 Optimizer/nop_removal.c create mode 100644 Optimizer/optimize_temp_vars_5.c create mode 100644 Optimizer/pass10.c create mode 100644 Optimizer/pass1_5.c create mode 100644 Optimizer/pass2.c create mode 100644 Optimizer/pass3.c create mode 100644 Optimizer/pass5.c create mode 100644 Optimizer/pass9.c create mode 100644 Optimizer/zend_optimizer.c create mode 100644 Optimizer/zend_optimizer.h create mode 100644 Optimizer/zend_optimizer_internal.h create mode 100644 README create mode 100644 ZendAccelerator.c create mode 100644 ZendAccelerator.h create mode 100644 config.m4 create mode 100644 config.w32 create mode 100644 shared_alloc_mmap.c create mode 100644 shared_alloc_posix.c create mode 100644 shared_alloc_shm.c create mode 100644 shared_alloc_win32.c create mode 100644 zend_accelerator_blacklist.c create mode 100644 zend_accelerator_blacklist.h create mode 100644 zend_accelerator_debug.c create mode 100644 zend_accelerator_debug.h create mode 100644 zend_accelerator_hash.c create mode 100644 zend_accelerator_hash.h create mode 100644 zend_accelerator_module.c create mode 100644 zend_accelerator_module.h create mode 100644 zend_accelerator_util_funcs.c create mode 100644 zend_accelerator_util_funcs.h create mode 100644 zend_persist.c create mode 100644 zend_persist.h create mode 100644 zend_persist_calc.c create mode 100644 zend_shared_alloc.c create mode 100644 zend_shared_alloc.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..8f2bec9d3ab --- /dev/null +++ b/.gitignore @@ -0,0 +1,87 @@ +# General Ignores +*~ +.#* +*. +*.slo +*.mk +*.mem +*.gcda +*.gcno +*.la +*.lo +*.o +*.a +*.ncb +*.opt +*.plg +*swp +*.patch +*.tgz +*.tar.gz +*.tar.bz2 +.FBCIndex +.FBCLockFolder +.deps +.libs +phpt.* +core +dynlib.m4 +Debug +Debug_TS +Makefile +Makefile.fragments +Makefile.objects +Makefile.global +Release +Release_TS +Release_TSDbg +Release_TS_inline +Release_inline +ZendEngine1 +_libs +acconfig.h +aclocal.m4 +acinclude.m4 +autom4te.cache +bsd_converted +buildconf.stamp +buildmk.stamp +confdefs.h +config.h +config.guess +config.cache +config.h.in +config.log +config.nice +config.nice.bat +config.status +config.sub +config_vars.mk +configuration-parser.c +configuration-parser.h +configuration-parser.output +configuration-scanner.c +configure +configure.in +configure.bat +configure.js +conftest +conftest.c +debug.log +diff +generated_lists +include +install-sh +internal_functions.c +lcov_data +lcov_html +libs +libtool +ltmain.sh +meta_cc +meta_ccld +missing +mkinstalldirs +modules +build +run-tests.php diff --git a/Optimizer/block_pass.c b/Optimizer/block_pass.c new file mode 100644 index 00000000000..2481b25475e --- /dev/null +++ b/Optimizer/block_pass.c @@ -0,0 +1,1967 @@ +#define DEBUG_BLOCKPASS 0 + +/* Checks if a constant (like "true") may be relaced by its value */ +static int zend_get_persistent_constant(char *name, uint name_len, zval *result, int copy TSRMLS_DC ELS_DC) +{ + zend_constant *c; + char *lookup_name; + int retval = 1; + ALLOCA_FLAG(use_heap); + + if (zend_hash_find(EG(zend_constants), name, name_len+1, (void **) &c) == FAILURE) { + lookup_name = DO_ALLOCA(name_len+1); + memcpy(lookup_name, name, name_len+1); + zend_str_tolower(lookup_name, name_len); + + if (zend_hash_find(EG(zend_constants), lookup_name, name_len+1, (void **) &c)==SUCCESS) { + if (!(c->flags & CONST_CT_SUBST) || (c->flags & CONST_CS)) { + retval=0; + } + } else { + retval=0; + } + FREE_ALLOCA(lookup_name); + } + + if (retval) { + if(c->flags & CONST_PERSISTENT) { + *result = c->value; + if(copy) { + zval_copy_ctor(result); + } + } else { + retval = 0; + } + } + + return retval; +} + +#if DEBUG_BLOCKPASS +# define BLOCK_REF(b) b?op_array->opcodes-b->start_opline:-1 + +static inline void print_block(zend_code_block *block, zend_op *opcodes, char *txt) +{ + fprintf(stderr, "%sBlock: %d-%d (%d)", txt, block->start_opline - opcodes, block->start_opline - opcodes+block->len-1, block->len); + if(!block->access) { + fprintf(stderr, " unused"); + } + if(block->op1_to) { + fprintf(stderr, " 1: %d", block->op1_to->start_opline - opcodes); + } + if(block->op2_to) { + fprintf(stderr, " 2: %d", block->op2_to->start_opline - opcodes); + } + if(block->ext_to) { + fprintf(stderr, " e: %d", block->ext_to->start_opline - opcodes); + } + if(block->follow_to) { + fprintf(stderr, " f: %d", block->follow_to->start_opline - opcodes); + } + + if(block->sources) { + zend_block_source *bs = block->sources; + fprintf(stderr, " s:"); + while(bs) { + fprintf(stderr, " %d", bs->from->start_opline - opcodes); + bs = bs->next; + } + } + + fprintf(stderr, "\n"); + fflush(stderr); +} +#else +#define print_block(a,b,c) +#endif + +#define START_BLOCK_OP(opno) blocks[opno].start_opline = &op_array->opcodes[opno]; blocks[opno].start_opline_no = opno; blocks[opno].access = 1 + +/* find code blocks in op_array + code block is a set of opcodes with single flow of control, i.e. without jmps, + branches, etc. */ +static zend_code_block *find_code_blocks(zend_op_array *op_array) +{ + zend_op *opline; + zend_op *end = op_array->opcodes+op_array->last; + zend_code_block *blocks = ecalloc(op_array->last+2, sizeof(zend_code_block)); + zend_code_block *cur_block; + zend_uint opno = 0; + + opline = op_array->opcodes; + blocks[0].start_opline = opline; + blocks[0].start_opline_no = 0; + /* first find block start points */ + if(op_array->last_try_catch) { + int i; + blocks->try = ecalloc(op_array->last_try_catch, sizeof(zend_code_block *)); + blocks->catch = ecalloc(op_array->last_try_catch, sizeof(zend_code_block *)); + for(i=0; i< op_array->last_try_catch; i++) { + blocks->try[i] = &blocks[op_array->try_catch_array[i].try_op]; + blocks->catch[i] = &blocks[op_array->try_catch_array[i].catch_op]; + START_BLOCK_OP(op_array->try_catch_array[i].try_op); + START_BLOCK_OP(op_array->try_catch_array[i].catch_op); + blocks[op_array->try_catch_array[i].try_op].is_try = 1; + } + } + while (oplineopcode) { + case ZEND_BRK: + case ZEND_CONT: +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + case ZEND_GOTO: +#endif + /* would not optimize non-optimized BRK/CONTs - we cannot + really know where it jumps, so these optimizations are + too dangerous */ + efree(blocks); + return NULL; +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + case ZEND_FAST_CALL: + START_BLOCK_OP(ZEND_OP1(opline).opline_num); + break; +#endif + case ZEND_JMP: + START_BLOCK_OP(ZEND_OP1(opline).opline_num); + /* break missing intentionally */ + case ZEND_RETURN: +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + case ZEND_RETURN_BY_REF: +#endif +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + case ZEND_FAST_RET: +#endif + case ZEND_EXIT: + case ZEND_THROW: + /* start new block from this+1 */ + START_BLOCK_OP(opno+1); + break; + /* TODO: if conditional jmp depends on constant, + don't start block that won't be executed */ + case ZEND_CATCH: + START_BLOCK_OP(opline->extended_value); + START_BLOCK_OP(opno+1); + break; + case ZEND_JMPZNZ: + START_BLOCK_OP(opline->extended_value); + case ZEND_JMPZ: + case ZEND_JMPNZ: + case ZEND_JMPZ_EX: + case ZEND_JMPNZ_EX: + case ZEND_FE_FETCH: + case ZEND_FE_RESET: + case ZEND_NEW: +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + case ZEND_JMP_SET: +#endif +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + case ZEND_JMP_SET_VAR: +#endif + START_BLOCK_OP(ZEND_OP2(opline).opline_num); + START_BLOCK_OP(opno+1); + break; + + } + opno++; + opline++; + } + + /* Build CFG (Control Flow Graph) */ + cur_block = blocks; + for(opno = 1; opno < op_array->last; opno++) { + if(blocks[opno].start_opline) { + /* found new block start */ + cur_block->len = blocks[opno].start_opline - cur_block->start_opline; + cur_block->next = &blocks[opno]; + /* what is the last OP of previous block? */ + opline = blocks[opno].start_opline-1; + switch((unsigned)opline->opcode) { + case ZEND_RETURN: +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + case ZEND_RETURN_BY_REF: +#endif +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + case ZEND_FAST_RET: +#endif + case ZEND_EXIT: + case ZEND_THROW: + break; +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + case ZEND_FAST_CALL: +#endif + case ZEND_JMP: + cur_block->op1_to = &blocks[ZEND_OP1(opline).opline_num]; + break; + case ZEND_JMPZNZ: + cur_block->op2_to = &blocks[ZEND_OP2(opline).opline_num]; + cur_block->ext_to = &blocks[opline->extended_value]; + break; + case ZEND_CATCH: + cur_block->ext_to = &blocks[opline->extended_value]; + cur_block->follow_to = &blocks[opno]; + break; + case ZEND_JMPZ: + case ZEND_JMPNZ: + case ZEND_JMPZ_EX: + case ZEND_JMPNZ_EX: + case ZEND_FE_RESET: + case ZEND_NEW: +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + case ZEND_JMP_SET: +#endif +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + case ZEND_JMP_SET_VAR: +#endif + case ZEND_FE_FETCH: + cur_block->op2_to = &blocks[ZEND_OP2(opline).opline_num]; + /* break missing intentionally */ + default: + /* next block follows this */ + cur_block->follow_to = &blocks[opno]; + break; + } + print_block(cur_block, op_array->opcodes, ""); + cur_block = cur_block->next; + } + } + cur_block->len = end - cur_block->start_opline; + cur_block->next = &blocks[op_array->last+1]; + print_block(cur_block, op_array->opcodes, ""); + + /* The op_array desn't have BRK, CONT, GOTO opcodes anyway */ + if(op_array->brk_cont_array) { + efree(op_array->brk_cont_array); + } + op_array->brk_cont_array = NULL; + op_array->last_brk_cont = 0; + + return blocks; +} + +/* CFG back references management */ + +#define ADD_SOURCE(fromb, tob) { \ + zend_block_source *__s = tob->sources; \ + while(__s && __s->from != fromb) __s = __s->next; \ + if(__s == NULL) { \ + zend_block_source *__t = emalloc(sizeof(zend_block_source)); \ + __t->next = tob->sources; \ + tob->sources = __t; \ + __t->from = fromb; \ + } \ +} + +#define DEL_SOURCE(cs) { \ + zend_block_source *__ns = (*cs)->next; \ + efree(*cs); \ + *cs = __ns; \ +} + + +static inline void replace_source(zend_block_source *list, zend_code_block *old, zend_code_block *new) +{ + /* replace all references to 'old' in 'list' with 'new' */ + zend_block_source **cs; + int found = 0; + + for(cs = &list; *cs; cs = &((*cs)->next)) { + if((*cs)->from == new) { + if(found) { + DEL_SOURCE(cs); + } else { + found = 1; + } + } + + if((*cs)->from == old) { + if(found) { + DEL_SOURCE(cs); + } else { + (*cs)->from = new; + found = 1; + } + } + } +} + +static inline void del_source(zend_code_block *from, zend_code_block *to) +{ + /* delete source 'from' from 'to'-s sources list */ + zend_block_source **cs = &to->sources; + + if(to->sources == NULL) { + to->access = 0; + return; + } + + while(*cs) { + if((*cs)->from == from) { + DEL_SOURCE(cs); + break; + } + cs = &((*cs)->next); + } + + if(to->sources == NULL) { + /* 'to' has no more sources - it's unused, will be stripped */ + to->access = 0; + return; + } + + if(to->sources->next == NULL) { + /* source to only one block */ + zend_code_block *from_block = to->sources->from; + + if(from_block->access && from_block->follow_to == to && + from_block->op1_to == NULL && + from_block->op2_to == NULL && + from_block->ext_to == NULL + ) { + /* this block follows it's only predecessor - we can join them */ + zend_op *new_to = from_block->start_opline + from_block->len; + if(new_to != to->start_opline) { + /* move block to new location */ + memmove(new_to, to->start_opline, sizeof(zend_op)*to->len); + } + /* join blocks' lengthes */ + from_block->len += to->len; + /* move 'to'`s references to 'from' */ + to->start_opline = NULL; + to->access = 0; + efree(to->sources); + to->sources = NULL; + from_block->follow_to = to->follow_to; + if(to->op1_to) { + from_block->op1_to = to->op1_to; + replace_source(to->op1_to->sources, to, from_block); + } + if(to->op2_to) { + from_block->op2_to = to->op2_to; + replace_source(to->op2_to->sources, to, from_block); + } + if(to->ext_to) { + from_block->ext_to = to->ext_to; + replace_source(to->ext_to->sources, to, from_block); + } + if(to->follow_to) { + replace_source(to->follow_to->sources, to, from_block); + } + /* remove "to" from list */ + } + } +} + +static void delete_code_block(zend_code_block *block) +{ + if(block->follow_to) { + zend_block_source *bs = block->sources; + while(bs) { + zend_code_block *from_block = bs->from; + zend_code_block *to = block->follow_to; + if(from_block->op1_to == block) { + from_block->op1_to = to; + ADD_SOURCE(from_block, to); + } + if(from_block->op2_to == block) { + from_block->op2_to = to; + ADD_SOURCE(from_block, to); + } + if(from_block->ext_to == block) { + from_block->ext_to = to; + ADD_SOURCE(from_block, to); + } + if(from_block->follow_to == block) { + from_block->follow_to = to; + ADD_SOURCE(from_block, to); + } + bs = bs->next; + } + } + block->access = 0; +} + +static void zend_access_path(zend_code_block *block) +{ + if(block->access) { + return; + } + + block->access = 1; + if(block->op1_to) { + zend_access_path(block->op1_to); + ADD_SOURCE(block, block->op1_to); + } + if(block->op2_to) { + zend_access_path(block->op2_to); + ADD_SOURCE(block, block->op2_to); + } + if(block->ext_to) { + zend_access_path(block->ext_to); + ADD_SOURCE(block, block->ext_to); + } + if(block->follow_to) { + zend_access_path(block->follow_to); + ADD_SOURCE(block, block->follow_to); + } +} + +/* Traverse CFG, mark reachable basic blocks and build back references */ +static void zend_rebuild_access_path(zend_code_block *blocks, zend_op_array *op_array, int find_start) +{ + zend_code_block *start = find_start?NULL:blocks; + zend_code_block *b; + + /* Mark all blocks as unaccessable and destroy back references */ + b = blocks; + while (b != NULL) { + zend_block_source *cs; + if (!start && b->access) { + start = b; + } + b->access = 0; + cs = b->sources; + while(cs) { + zend_block_source *n = cs->next; + efree(cs); + cs = n; + } + b->sources = NULL; + b = b->next; + } + + /* Walk thorough all pathes */ + zend_access_path(start); + + /* Add exception pathes */ + if (op_array->last_try_catch) { + int i; + for(i=0; i< op_array->last_try_catch; i++) { + if(!blocks->catch[i]->access) { + zend_access_path(blocks->catch[i]); + } + } + } +} + +/* Data dependencies macros */ + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + +# define VAR_NUM_EX(op) ((op ## _type & (IS_TMP_VAR|IS_VAR))?VAR_NUM((op).var):(op).var) + +# define VAR_SOURCE(op) Tsource[VAR_NUM(op.var)] +# define SET_VAR_SOURCE(opline) Tsource[VAR_NUM(opline->result.var)] = opline + +# define VAR_UNSET(op) do { if (op ## _type & (IS_TMP_VAR|IS_VAR)) {VAR_SOURCE(op) = NULL;}} while (0) + +#else + +# define VAR_NUM_EX(op) ((op).op_type==IS_TMP_VAR||(op).op_type==IS_VAR?VAR_NUM((op).u.var):(op).u.var) + +# define VAR_SOURCE(op) Tsource[VAR_NUM(op.u.var)] +# define SET_VAR_SOURCE(opline) Tsource[VAR_NUM(ZEND_RESULT(opline).var)] = opline + +# define VAR_UNSET(op) do { if ((op).op_type==IS_TMP_VAR||(op).op_type==IS_VAR) {VAR_SOURCE(op) = NULL;}} while (0) + +#endif + +#define convert_to_string_safe(v) \ + if(Z_TYPE_P((v)) == IS_NULL) { \ + ZVAL_STRINGL((v), "", 0, 1); \ + } else { \ + convert_to_string((v)); \ + } + +static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, char *used_ext TSRMLS_DC) +{ + zend_op *opline = block->start_opline; + zend_op *end, *last_op = NULL; + zend_op **Tsource = NULL; + + print_block(block, op_array->opcodes, "Opt "); + + /* remove leading NOPs */ + while(block->start_opline->opcode == ZEND_NOP) { + if(block->len == 1) { + /* this block is all NOPs, join with following block */ + if(block->follow_to) { + delete_code_block(block); + } + return; + } + block->start_opline++; + block->start_opline_no++; + block->len--; + } + + /* we track data dependencies only insight a single basic block */ + if(op_array->T){ + Tsource = ecalloc(op_array->T, sizeof(zend_op *)); + } + opline = block->start_opline; + end = opline+block->len; + while((op_array->T)&&(oplineop1) && + VAR_SOURCE(opline->op1)->opcode == ZEND_QM_ASSIGN && + ZEND_OP1_TYPE(VAR_SOURCE(opline->op1)) == IS_CONST && + opline->opcode != ZEND_CASE && /* CASE _always_ expects variable */ + opline->opcode != ZEND_FETCH_DIM_TMP_VAR && /* in 5.1, FETCH_DIM_TMP_VAR expects T */ + opline->opcode != ZEND_FE_RESET && + opline->opcode != ZEND_FREE + ) { + zend_op *src = VAR_SOURCE(opline->op1); + VAR_UNSET(opline->op1); + COPY_NODE(opline->op1, src->op1); + MAKE_NOP(src); + } + + /* T = QM_ASSIGN(C), F(T) => NOP, F(C) */ + if(ZEND_OP2_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op2) && + VAR_SOURCE(opline->op2)->opcode == ZEND_QM_ASSIGN && + ZEND_OP1_TYPE(VAR_SOURCE(opline->op2)) == IS_CONST) { + zend_op *src = VAR_SOURCE(opline->op2); + VAR_UNSET(opline->op2); + COPY_NODE(opline->op2, src->op1); + MAKE_NOP(src); + } + + /* T = PRINT(X), F(T) => ECHO(X), F(1) */ + if(ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + VAR_SOURCE(opline->op1)->opcode == ZEND_PRINT && + opline->opcode != ZEND_CASE && opline->opcode != ZEND_FREE) { + ZEND_OP1_TYPE(opline) = IS_CONST; + LITERAL_LONG(opline->op1, 1); + } + + if(ZEND_OP2_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op2) && + VAR_SOURCE(opline->op2)->opcode == ZEND_PRINT) { + ZEND_OP2_TYPE(opline) = IS_CONST; + LITERAL_LONG(opline->op2, 1); + } + + /* T = CAST(X, String), ECHO(T) => NOP, ECHO(X) */ + if((opline->opcode == ZEND_ECHO || opline->opcode == ZEND_PRINT) && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + VAR_SOURCE(opline->op1)->opcode == ZEND_CAST && + VAR_SOURCE(opline->op1)->extended_value == IS_STRING) { + zend_op *src = VAR_SOURCE(opline->op1); + COPY_NODE(opline->op1, src->op1); + MAKE_NOP(src); + } + + /* T = PRINT(X), FREE(T) => ECHO(X) */ + if(opline->opcode == ZEND_FREE && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1)) { + zend_op *src = VAR_SOURCE(opline->op1); + if(src->opcode == ZEND_PRINT) { + src->opcode = ZEND_ECHO; + ZEND_RESULT_TYPE(src) = IS_UNUSED; + MAKE_NOP(opline); + } + } + + /* T = BOOL(X), FREE(T) => NOP */ + if(opline->opcode == ZEND_FREE && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1)) { + zend_op *src = VAR_SOURCE(opline->op1); + if (src->opcode == ZEND_BOOL) { + if (ZEND_OP1_TYPE(src) == IS_CONST) { + literal_dtor(&ZEND_OP1_LITERAL(src)); + } + MAKE_NOP(src); + MAKE_NOP(opline); + } + } + +#if 0 + /* pre-evaluate functions: + constant(x) + defined(x) + function_exists(x) + extension_loaded(x) + BAD: interacts badly with Accelerator + */ + if((ZEND_OP1_TYPE(opline) & IS_VAR) && + VAR_SOURCE(opline->op1) && VAR_SOURCE(opline->op1)->opcode == ZEND_DO_CF_FCALL && + VAR_SOURCE(opline->op1)->extended_value == 1) { + zend_op *fcall = VAR_SOURCE(opline->op1); + zend_op *sv = fcall-1; + if(sv >= block->start_opline && sv->opcode == ZEND_SEND_VAL && + ZEND_OP1_TYPE(sv) == IS_CONST && Z_TYPE(OPLINE_OP1_LITERAL(sv)) == IS_STRING && + Z_LVAL(OPLINE_OP2_LITERAL(sv)) == 1 + ) { + zval *arg = &OPLINE_OP1_LITERAL(sv); + char *fname = FUNCTION_CACHE->funcs[Z_LVAL(ZEND_OP1_LITERAL(fcall))].function_name; + int flen = FUNCTION_CACHE->funcs[Z_LVAL(ZEND_OP1_LITERAL(fcall))].name_len; + if(flen == sizeof("defined")-1 && zend_binary_strcasecmp(fname, flen, "defined", sizeof("defined")-1) == 0) { + zval c; + if(zend_get_persistent_constant(Z_STRVAL_P(arg), Z_STRLEN_P(arg), &c, 0 TSRMLS_CC ELS_CC) != 0) { + literal_dtor(arg); + MAKE_NOP(sv); + MAKE_NOP(fcall); + LITERAL_BOOL(opline->op1, 1); + ZEND_OP1_TYPE(opline) = IS_CONST; + } + } else if((flen == sizeof("function_exists")-1 && zend_binary_strcasecmp(fname, flen, "function_exists", sizeof("function_exists")-1) == 0) || + (flen == sizeof("is_callable")-1 && zend_binary_strcasecmp(fname, flen, "is_callable", sizeof("is_callable")-1) == 0) + ) { + zend_function *function; + if(zend_hash_find(EG(function_table), Z_STRVAL_P(arg), Z_STRLEN_P(arg)+1, (void **)&function) == SUCCESS) { + literal_dtor(arg); + MAKE_NOP(sv); + MAKE_NOP(fcall); + LITERAL_BOOL(opline->op1, 1); + ZEND_OP1_TYPE(opline) = IS_CONST; + } + } else if(flen == sizeof("constant")-1 && zend_binary_strcasecmp(fname, flen, "constant", sizeof("constant")-1) == 0) { + zval c; + if(zend_get_persistent_constant(Z_STRVAL_P(arg), Z_STRLEN_P(arg), &c, 1 TSRMLS_CC ELS_CC) != 0) { + literal_dtor(arg); + MAKE_NOP(sv); + MAKE_NOP(fcall); + ZEND_OP1_LITERAL(opline) = zend_add_literal(op_array, &c TSRMLS_CC); + /* no copy ctor - get already copied it */ + ZEND_OP1_TYPE(opline) = IS_CONST; + } + } else if(flen == sizeof("extension_loaded")-1 && zend_binary_strcasecmp(fname, flen, "extension_loaded", sizeof("extension_loaded")-1) == 0) { + if(zend_hash_exists(&module_registry, Z_STRVAL_P(arg), Z_STRLEN_P(arg)+1)) { + literal_dtor(arg); + MAKE_NOP(sv); + MAKE_NOP(fcall); + LITERAL_BOOL(opline->op1, 1); + ZEND_OP1_TYPE(opline) = IS_CONST; + } + } + } + } +#endif + + /* IS_EQ(TRUE, X) => BOOL(X) + * IS_EQ(FALSE, X) => BOOL_NOT(X) + * IS_NOT_EQ(TRUE, X) => BOOL_NOT(X) + * IS_NOT_EQ(FALSE, X) => BOOL(X) + */ + if(opline->opcode == ZEND_IS_EQUAL || + opline->opcode == ZEND_IS_NOT_EQUAL) { + if (ZEND_OP1_TYPE(opline) == IS_CONST && + Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_BOOL) { + opline->opcode = + ((opline->opcode == ZEND_IS_EQUAL) == Z_LVAL(ZEND_OP1_LITERAL(opline)))? + ZEND_BOOL:ZEND_BOOL_NOT; + COPY_NODE(opline->op1, opline->op2); + SET_UNUSED(opline->op2); + } else if (ZEND_OP2_TYPE(opline) == IS_CONST && + Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_BOOL) { + opline->opcode = + ((opline->opcode == ZEND_IS_EQUAL) == Z_LVAL(ZEND_OP2_LITERAL(opline)))? + ZEND_BOOL:ZEND_BOOL_NOT; + SET_UNUSED(opline->op2); + } + } + + if((opline->opcode == ZEND_BOOL || + opline->opcode == ZEND_BOOL_NOT || + opline->opcode == ZEND_JMPZ || + opline->opcode == ZEND_JMPNZ || + opline->opcode == ZEND_JMPZNZ) && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) != NULL && + !used_ext[VAR_NUM(ZEND_OP1(opline).var)] && + VAR_SOURCE(opline->op1)->opcode == ZEND_BOOL_NOT + ) { + /* T = BOOL_NOT(X) + JMPZ(T) -> NOP, JMPNZ(X) */ + zend_op *src = VAR_SOURCE(opline->op1); + + COPY_NODE(opline->op1, src->op1); + + switch(opline->opcode) { + case ZEND_BOOL: + /* T = BOOL_NOT(X) + BOOL(T) -> NOP, BOOL_NOT(X) */ + opline->opcode = ZEND_BOOL_NOT; + break; + case ZEND_BOOL_NOT: + /* T = BOOL_NOT(X) + BOOL_BOOL(T) -> NOP, BOOL(X) */ + opline->opcode = ZEND_BOOL; + break; + case ZEND_JMPZ: + /* T = BOOL_NOT(X) + JMPZ(T,L) -> NOP, JMPNZ(X,L) */ + opline->opcode = ZEND_JMPNZ; + break; + case ZEND_JMPNZ: + /* T = BOOL_NOT(X) + JMPNZ(T,L) -> NOP, JMPZ(X,L) */ + opline->opcode = ZEND_JMPZ; + break; + case ZEND_JMPZNZ: + { + /* T = BOOL_NOT(X) + JMPZNZ(T,L1,L2) -> NOP, JMPZNZ(X,L2,L1) */ + int op_t; + zend_code_block *op_b; + + op_t = opline->extended_value; + opline->extended_value = ZEND_OP2(opline).opline_num; + ZEND_OP2(opline).opline_num = op_t; + + op_b = block->ext_to; + block->ext_to = block->op2_to; + block->op2_to = op_b; + } + break; + } + + VAR_UNSET(opline->op1); + MAKE_NOP(src); + continue; + } else +#if 0 + /* T = BOOL_NOT(X) + T = JMPZ_EX(T, X) -> T = BOOL_NOT(X), JMPNZ(X) */ + if(0 && (opline->opcode == ZEND_JMPZ_EX || + opline->opcode == ZEND_JMPNZ_EX) && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) != NULL && + VAR_SOURCE(opline->op1)->opcode == ZEND_BOOL_NOT && + ZEND_OP1(opline).var == ZEND_RESULT(opline).var + ) { + zend_op *src = VAR_SOURCE(opline->op1); + if(opline->opcode == ZEND_JMPZ_EX) { + opline->opcode = ZEND_JMPNZ; + } else { + opline->opcode = ZEND_JMPZ; + } + COPY_NODE(opline->op1, src->op1); + SET_UNUSED(opline->result); + continue; + } else +#endif + /* T = BOOL(X) + JMPZ(T) -> NOP, JMPZ(X) */ + if((opline->opcode == ZEND_BOOL || + opline->opcode == ZEND_BOOL_NOT || + opline->opcode == ZEND_JMPZ || + opline->opcode == ZEND_JMPZ_EX || + opline->opcode == ZEND_JMPNZ_EX || + opline->opcode == ZEND_JMPNZ || + opline->opcode == ZEND_JMPZNZ) && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) != NULL && + (!used_ext[VAR_NUM(ZEND_OP1(opline).var)] || + (ZEND_RESULT_TYPE(opline) == IS_TMP_VAR && + ZEND_RESULT(opline).var == ZEND_OP1(opline).var)) && + (VAR_SOURCE(opline->op1)->opcode == ZEND_BOOL || + VAR_SOURCE(opline->op1)->opcode == ZEND_QM_ASSIGN) + ) { + zend_op *src = VAR_SOURCE(opline->op1); + COPY_NODE(opline->op1, src->op1); + + VAR_UNSET(opline->op1); + MAKE_NOP(src); + continue; + } else if(last_op && opline->opcode == ZEND_ECHO && + last_op->opcode == ZEND_ECHO && + ZEND_OP1_TYPE(opline) == IS_CONST && + Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_DOUBLE && + ZEND_OP1_TYPE(last_op) == IS_CONST && + Z_TYPE(ZEND_OP1_LITERAL(last_op)) != IS_DOUBLE) { + /* compress consecutive ECHO's. + * Float to string conversion may be affected by current + * locale setting. + */ + int l; + + if(Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_STRING) { + convert_to_string_safe(&ZEND_OP1_LITERAL(opline)); + } + if(Z_TYPE(ZEND_OP1_LITERAL(last_op)) != IS_STRING) { + convert_to_string_safe(&ZEND_OP1_LITERAL(last_op)); + } + l = Z_STRLEN(ZEND_OP1_LITERAL(opline)) + Z_STRLEN(ZEND_OP1_LITERAL(last_op)); + if (IS_INTERNED(Z_STRVAL(ZEND_OP1_LITERAL(last_op)))) { + char *tmp = emalloc(l + 1); + memcpy(tmp, Z_STRVAL(ZEND_OP1_LITERAL(last_op)), l + 1); + Z_STRVAL(ZEND_OP1_LITERAL(last_op)) = tmp; + } else { + Z_STRVAL(ZEND_OP1_LITERAL(last_op)) = erealloc(Z_STRVAL(ZEND_OP1_LITERAL(last_op)), l+1); + } + memcpy(Z_STRVAL(ZEND_OP1_LITERAL(last_op))+Z_STRLEN(ZEND_OP1_LITERAL(last_op)), Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline))); + Z_STRVAL(ZEND_OP1_LITERAL(last_op))[l] = '\0'; + zval_dtor(&ZEND_OP1_LITERAL(opline)); +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + Z_STRVAL(ZEND_OP1_LITERAL(opline)) = (char*)zend_new_interned_string(Z_STRVAL(ZEND_OP1_LITERAL(last_op)), l + 1, 1 TSRMLS_CC); + Z_TYPE(ZEND_OP1_LITERAL(last_op)) = IS_NULL; +#else + Z_STRVAL(ZEND_OP1_LITERAL(opline)) = Z_STRVAL(ZEND_OP1_LITERAL(last_op)); +#endif + Z_STRLEN(ZEND_OP1_LITERAL(opline)) = l; + MAKE_NOP(last_op); + } else if(opline->opcode == ZEND_CONCAT && + ZEND_OP2_TYPE(opline) == IS_CONST && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + (VAR_SOURCE(opline->op1)->opcode == ZEND_CONCAT || + VAR_SOURCE(opline->op1)->opcode == ZEND_ADD_STRING) && + ZEND_OP2_TYPE(VAR_SOURCE(opline->op1)) == IS_CONST && + ZEND_RESULT(VAR_SOURCE(opline->op1)).var == ZEND_OP1(opline).var + ) { + /* compress consecutive CONCATs */ + zend_op *src = VAR_SOURCE(opline->op1); + int l; + + if(Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) { + convert_to_string_safe(&ZEND_OP2_LITERAL(opline)); + } + if(Z_TYPE(ZEND_OP2_LITERAL(src)) != IS_STRING) { + convert_to_string_safe(&ZEND_OP2_LITERAL(src)); + } + + VAR_UNSET(opline->op1); + if (ZEND_OP1_TYPE(src) == IS_UNUSED) { + /* 5.3 may use IS_UNUSED as first argument to ZEND_ADD_... */ + opline->opcode = ZEND_ADD_STRING; + } + COPY_NODE(opline->op1, src->op1); + l = Z_STRLEN(ZEND_OP2_LITERAL(opline)) + Z_STRLEN(ZEND_OP2_LITERAL(src)); + if (IS_INTERNED(Z_STRVAL(ZEND_OP2_LITERAL(src)))) { + char *tmp = emalloc(l + 1); + memcpy(tmp, Z_STRVAL(ZEND_OP2_LITERAL(src)), l + 1); + Z_STRVAL(ZEND_OP2_LITERAL(src)) = tmp; + } else { + Z_STRVAL(ZEND_OP2_LITERAL(src)) = erealloc(Z_STRVAL(ZEND_OP2_LITERAL(src)), l+1); + } + memcpy(Z_STRVAL(ZEND_OP2_LITERAL(src))+Z_STRLEN(ZEND_OP2_LITERAL(src)), Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline))); + Z_STRVAL(ZEND_OP2_LITERAL(src))[l] = '\0'; + if (!IS_INTERNED(Z_STRVAL(ZEND_OP2_LITERAL(opline)))) { + efree(Z_STRVAL(ZEND_OP2_LITERAL(opline))); + } +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + Z_STRVAL(ZEND_OP2_LITERAL(opline)) = (char*)zend_new_interned_string(Z_STRVAL(ZEND_OP2_LITERAL(src)), l + 1, 1 TSRMLS_CC); + Z_TYPE(ZEND_OP2_LITERAL(src)) = IS_NULL; +#else + Z_STRVAL(ZEND_OP2_LITERAL(opline)) = Z_STRVAL(ZEND_OP2_LITERAL(src)); +#endif + Z_STRLEN(ZEND_OP2_LITERAL(opline)) = l; + MAKE_NOP(src); + } else if((opline->opcode == ZEND_ADD_STRING || + opline->opcode == ZEND_ADD_VAR) && + ZEND_OP1_TYPE(opline) == IS_CONST) { + /* convert ADD_STRING(C1, C2) to CONCAT(C1, C2) */ + opline->opcode = ZEND_CONCAT; + continue; + } else if(opline->opcode == ZEND_ADD_CHAR && ZEND_OP1_TYPE(opline) == IS_CONST && ZEND_OP2_TYPE(opline) == IS_CONST) { + /* convert ADD_CHAR(C1, C2) to CONCAT(C1, C2) */ + char c = (char)Z_LVAL(ZEND_OP2_LITERAL(opline)); + ZVAL_STRINGL(&ZEND_OP2_LITERAL(opline), &c, 1, 1); + opline->opcode = ZEND_CONCAT; + continue; + } else if( + (opline->opcode == ZEND_ADD || + opline->opcode == ZEND_SUB || + opline->opcode == ZEND_MUL || + opline->opcode == ZEND_DIV || + opline->opcode == ZEND_MOD || + opline->opcode == ZEND_SL || + opline->opcode == ZEND_SR || + opline->opcode == ZEND_CONCAT || + opline->opcode == ZEND_IS_EQUAL || + opline->opcode == ZEND_IS_NOT_EQUAL || + opline->opcode == ZEND_IS_SMALLER || + opline->opcode == ZEND_IS_SMALLER_OR_EQUAL || + opline->opcode == ZEND_IS_IDENTICAL || + opline->opcode == ZEND_IS_NOT_IDENTICAL || + opline->opcode == ZEND_BOOL_XOR || + opline->opcode == ZEND_BW_OR || + opline->opcode == ZEND_BW_AND || + opline->opcode == ZEND_BW_XOR) && + ZEND_OP1_TYPE(opline)==IS_CONST && + ZEND_OP2_TYPE(opline)==IS_CONST) { + /* evaluate constant expressions */ + int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC) = get_binary_op(opline->opcode); + zval result; + int er; + + if ((opline->opcode == ZEND_DIV || + opline->opcode == ZEND_MOD) && + ((Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_LONG && + Z_LVAL(ZEND_OP2_LITERAL(opline)) == 0) || + (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_DOUBLE && + Z_DVAL(ZEND_OP2_LITERAL(opline)) == 0.0))) { + if(RESULT_USED(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) TSRMLS_CC) == SUCCESS) { + PZ_SET_REFCOUNT_P(&result, 1); + PZ_UNSET_ISREF_P(&result); + + 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; + } + EG(error_reporting) = er; + } else if((opline->opcode == ZEND_BOOL || + opline->opcode == ZEND_BOOL_NOT || + opline->opcode == ZEND_BW_NOT) && ZEND_OP1_TYPE(opline)==IS_CONST + ) { + /* evaluate constant unary ops */ + unary_op_type unary_op = get_unary_op(opline->opcode); + zval result; + + if(unary_op) { + unary_op(&result, &ZEND_OP1_LITERAL(opline) TSRMLS_CC); + literal_dtor(&ZEND_OP1_LITERAL(opline)); + } else { + /* BOOL */ + result = ZEND_OP1_LITERAL(opline); + convert_to_boolean(&result); + } + PZ_SET_REFCOUNT_P(&result, 1); + PZ_UNSET_ISREF_P(&result); + ZEND_OP1_LITERAL(opline) = result; + opline->opcode = ZEND_QM_ASSIGN; + } else if((opline->opcode == ZEND_RETURN || opline->opcode == ZEND_EXIT) && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + VAR_SOURCE(opline->op1)->opcode == ZEND_QM_ASSIGN + ) { + /* T = QM_ASSIGN(X), RETURN(T) to RETURN(X) */ + zend_op *src = VAR_SOURCE(opline->op1); + VAR_UNSET(opline->op1); + COPY_NODE(opline->op1, src->op1); + MAKE_NOP(src); + } else if((opline->opcode == ZEND_ADD_STRING || + opline->opcode == ZEND_ADD_CHAR) && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + VAR_SOURCE(opline->op1)->opcode == ZEND_INIT_STRING) { + /* convert T = INIT_STRING(), T = ADD_STRING(T, X) to T = QM_ASSIGN(X) */ + /* CHECKME: Remove ZEND_ADD_VAR optimizsation, since some conversions - + namely, BOOL(false)->string - don't allocate memory but use empty_string + and ADD_CHAR fails */ + zend_op *src = VAR_SOURCE(opline->op1); + VAR_UNSET(opline->op1); + COPY_NODE(opline->op1, opline->op2); + if(opline->opcode == ZEND_ADD_CHAR) { + char c = (char)Z_LVAL(ZEND_OP2_LITERAL(opline)); + ZVAL_STRINGL(&ZEND_OP1_LITERAL(opline), &c, 1, 1); + } + SET_UNUSED(opline->op2); + MAKE_NOP(src); + opline->opcode = ZEND_QM_ASSIGN; + } else if((opline->opcode == ZEND_ADD_STRING || + opline->opcode == ZEND_ADD_CHAR || + opline->opcode == ZEND_ADD_VAR || + opline->opcode == ZEND_CONCAT) && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + VAR_SOURCE(opline->op1)->opcode == ZEND_CONCAT && + ZEND_OP2_TYPE(VAR_SOURCE(opline->op1)) == IS_CONST && + Z_TYPE(ZEND_OP2_LITERAL(VAR_SOURCE(opline->op1))) == IS_STRING && + Z_STRLEN(ZEND_OP2_LITERAL(VAR_SOURCE(opline->op1))) == 0) { + /* convert T = CONCAT(X,''), T = ADD_STRING(T, Y) to T = CONCAT(X,Y) */ + zend_op *src = VAR_SOURCE(opline->op1); + VAR_UNSET(opline->op1); + COPY_NODE(opline->op1, src->op1); + if(opline->opcode == ZEND_ADD_CHAR) { + char c = (char)Z_LVAL(ZEND_OP2_LITERAL(opline)); + ZVAL_STRINGL(&ZEND_OP2_LITERAL(opline), &c, 1, 1); + } + opline->opcode = ZEND_CONCAT; + literal_dtor(&ZEND_OP2_LITERAL(src)); /* will take care of empty_string too */ + MAKE_NOP(src); + } else if(opline->opcode == ZEND_ADD_VAR && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + VAR_SOURCE(opline->op1)->opcode == ZEND_INIT_STRING) { + /* convert T = INIT_STRING(), T = ADD_VAR(T, X) to T = CAST(STRING, X) */ + zend_op *src = VAR_SOURCE(opline->op1); + VAR_UNSET(opline->op1); + COPY_NODE(opline->op1, opline->op2); + SET_UNUSED(opline->op2); + MAKE_NOP(src); + opline->opcode = ZEND_CAST; + opline->extended_value = IS_STRING; + } else if((opline->opcode == ZEND_ADD_STRING || + opline->opcode == ZEND_ADD_CHAR || + opline->opcode == ZEND_ADD_VAR || + opline->opcode == ZEND_CONCAT) && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + VAR_SOURCE(opline->op1)->opcode == ZEND_CAST && + VAR_SOURCE(opline->op1)->extended_value == IS_STRING) { + /* convert T1 = CAST(STRING, X), T2 = CONCAT(T1, Y) to T2 = CONCAT(X,Y) */ + zend_op *src = VAR_SOURCE(opline->op1); + VAR_UNSET(opline->op1); + COPY_NODE(opline->op1, src->op1); + if(opline->opcode == ZEND_ADD_CHAR) { + char c = (char)Z_LVAL(ZEND_OP2_LITERAL(opline)); + ZVAL_STRINGL(&ZEND_OP2_LITERAL(opline), &c, 1, 1); + } + opline->opcode = ZEND_CONCAT; + MAKE_NOP(src); + } else if(opline->opcode == ZEND_QM_ASSIGN && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + ZEND_RESULT_TYPE(opline) == IS_TMP_VAR && + ZEND_OP1(opline).var == ZEND_RESULT(opline).var) { + /* strip T = QM_ASSIGN(T) */ + MAKE_NOP(opline); + } else if(opline->opcode == ZEND_BOOL && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + (VAR_SOURCE(opline->op1)->opcode == ZEND_IS_EQUAL || + VAR_SOURCE(opline->op1)->opcode == ZEND_IS_NOT_EQUAL || + VAR_SOURCE(opline->op1)->opcode == ZEND_IS_SMALLER || + VAR_SOURCE(opline->op1)->opcode == ZEND_IS_SMALLER_OR_EQUAL || + VAR_SOURCE(opline->op1)->opcode == ZEND_BOOL || + VAR_SOURCE(opline->op1)->opcode == ZEND_IS_IDENTICAL || + VAR_SOURCE(opline->op1)->opcode == ZEND_IS_NOT_IDENTICAL || + VAR_SOURCE(opline->op1)->opcode == ZEND_ISSET_ISEMPTY_VAR || + VAR_SOURCE(opline->op1)->opcode == ZEND_ISSET_ISEMPTY_DIM_OBJ + ) && !used_ext[VAR_NUM(ZEND_OP1(opline).var)] + ) { + /* T = IS_SMALLER(X, Y), T1 = BOOL(T) => T = IS_SMALLER(X, Y), T1 = QM_ASSIGN(T) */ + zend_op *src = VAR_SOURCE(opline->op1); + COPY_NODE(src->result, opline->result); + SET_VAR_SOURCE(src); + MAKE_NOP(opline); + } + /* get variable source */ + if(RESULT_USED(opline)) { + SET_VAR_SOURCE(opline); + } + if(opline->opcode != ZEND_NOP) { + last_op = opline; + } + opline++; + } + + /* remove leading NOPs */ + while(block->start_opline->opcode == ZEND_NOP) { + if(block->len == 1) { + /* this block is all NOPs, join with following block */ + if(block->follow_to) { + delete_code_block(block); + } + if(op_array->T){ + efree(Tsource); + } + return; + } + block->start_opline++; + block->start_opline_no++; + block->len--; + } + + /* strip the inside NOPs */ + opline = block->start_opline; + end = opline+block->len; + while(oplineopcode == ZEND_NOP) { + zend_op *nop = opline+1; + int noplen; + while(nopopcode == ZEND_NOP) { + nop++; + } + noplen = nop-opline; + if(noplen -= noplen; + end = block->start_opline + block->len; + } + opline++; + } + + if(op_array->T){ + efree(Tsource); + } +} + +/* Rebuild plain (optimized) op_array from CFG */ +static void assemble_code_blocks(zend_code_block *blocks, zend_op_array *op_array) +{ + zend_op *new_opcodes = emalloc(op_array->last*sizeof(zend_op)); + zend_op *opline = new_opcodes; + zend_code_block *cur_block = blocks; + + /* Copy code of reachable blocks into a single buffer */ + while(cur_block) { + if(cur_block->access) { + memcpy(opline, cur_block->start_opline, cur_block->len*sizeof(zend_op)); + cur_block->start_opline = opline; + opline += cur_block->len; + if((opline-1)->opcode == ZEND_JMP) { + zend_code_block *next; + next = cur_block->next; + while(next && !next->access) { + next = next->next; + } + if(next && next == cur_block->op1_to) { + /* JMP to the next block - strip it */ + cur_block->follow_to = cur_block->op1_to; + cur_block->op1_to = NULL; + MAKE_NOP((opline-1)); + opline--; + cur_block->len--; + } + } + } else { + /* this block will not be used, delete all constants there */ + zend_op *_opl; + zend_op *end = cur_block->start_opline+cur_block->len; + for(_opl = cur_block->start_opline; _opl && _opl < end; _opl++) { + if(ZEND_OP1_TYPE(_opl) == IS_CONST) { + literal_dtor(&ZEND_OP1_LITERAL(_opl)); + } + if(ZEND_OP2_TYPE(_opl) == IS_CONST) { + literal_dtor(&ZEND_OP2_LITERAL(_opl)); + } + } + } + cur_block = cur_block->next; + } +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + if(opline[-1].opcode == ZEND_THROW) { + /* if we finished with THROW, we need to add space between THROW and HANDLE to not confuse + zend_throw_internal */ + MAKE_NOP(opline); + opline->lineno = opline[-1].lineno; + opline++; + } + MAKE_NOP(opline); + opline->opcode = ZEND_HANDLE_EXCEPTION; + opline->lineno = opline[-1].lineno; + opline++; +#endif + + op_array->last = opline-new_opcodes; + + /* adjust exception jump targets */ + if(op_array->last_try_catch) { + int i; + for(i=0; i< op_array->last_try_catch; i++) { + op_array->try_catch_array[i].try_op = blocks->try[i]->start_opline - new_opcodes; + op_array->try_catch_array[i].catch_op = blocks->catch[i]->start_opline - new_opcodes; + } + efree(blocks->try); + efree(blocks->catch); + } + + /* adjust jump targets */ + for(cur_block = blocks; cur_block; cur_block = cur_block->next) { + if(!cur_block->access) { + continue; + } + if(cur_block->op1_to) { + ZEND_OP1(&cur_block->start_opline[cur_block->len-1]).opline_num = cur_block->op1_to->start_opline - new_opcodes; + } + if(cur_block->op2_to) { + ZEND_OP2(&cur_block->start_opline[cur_block->len-1]).opline_num = cur_block->op2_to->start_opline - new_opcodes; + } + if(cur_block->ext_to) { + cur_block->start_opline[cur_block->len-1].extended_value = cur_block->ext_to->start_opline - new_opcodes; + } + print_block(cur_block, new_opcodes, "Out "); + } + efree(op_array->opcodes); + op_array->opcodes = erealloc(new_opcodes, op_array->last*sizeof(zend_op)); + +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + /* adjust early binding list */ + if (op_array->early_binding != -1) { + zend_uint *opline_num = &op_array->early_binding; + zend_op *end; + + opline = op_array->opcodes; + end = opline + op_array->last; + while (opline < end) { + if (opline->opcode == ZEND_DECLARE_INHERITED_CLASS_DELAYED) { + *opline_num = opline - op_array->opcodes; + opline_num = &ZEND_RESULT(opline).opline_num; + } + ++opline; + } + *opline_num = -1; + } +#endif +} + +static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_array, zend_code_block *blocks) +{ + /* last_op is the last opcode of the current block */ + zend_op *last_op = (block->start_opline+block->len-1); + + switch(last_op->opcode) { + case ZEND_JMP: + { + zend_op *target = block->op1_to->start_opline; + zend_code_block *next = block->next; + + while (next && !next->access) { + /* find used one */ + next = next->next; + } + + /* JMP(next) -> NOP */ + if(block->op1_to == next) { + block->follow_to = block->op1_to; + block->op1_to = NULL; + MAKE_NOP(last_op); + block->len--; + if(block->len == 0) { + /* this block is nothing but NOP now */ + delete_code_block(block); + } + break; + } + + if(((target->opcode == ZEND_JMP && + block->op1_to != block->op1_to->op1_to) || + target->opcode == ZEND_JMPZNZ) && + !block->op1_to->is_try) { + /* JMP L, L: JMP L1 -> JMP L1 */ + /* JMP L, L: JMPZNZ L1,L2 -> JMPZNZ L1,L2 */ + *last_op = *target; + if(ZEND_OP1_TYPE(last_op) == IS_CONST) { + zval_copy_ctor(&ZEND_OP1_LITERAL(last_op)); + } + del_source(block, block->op1_to); + if (block->op1_to->op2_to) { + block->op2_to = block->op1_to->op2_to; + ADD_SOURCE(block, block->op2_to); + } + if (block->op1_to->ext_to) { + block->ext_to = block->op1_to->ext_to; + ADD_SOURCE(block, block->ext_to); + } + if (block->op1_to->op1_to) { + block->op1_to = block->op1_to->op1_to; + ADD_SOURCE(block, block->op1_to); + } else { + block->op1_to = NULL; + } + } else if(target->opcode == ZEND_RETURN || +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + target->opcode == ZEND_RETURN_BY_REF || +#endif +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + target->opcode == ZEND_FAST_RET || +#endif + target->opcode == ZEND_EXIT) { + /* JMP L, L: RETURN to immediate RETURN */ + *last_op = *target; + if(ZEND_OP1_TYPE(last_op) == IS_CONST) { + zval_copy_ctor(&ZEND_OP1_LITERAL(last_op)); + } + del_source(block, block->op1_to); + block->op1_to = NULL; +#if 0 + /* Temporarily disabled - see bug #0025274 */ + } else if (0&& block->op1_to != block && + block->op1_to != blocks && + op_array->last_try_catch == 0 && + target->opcode != ZEND_FREE && + target->opcode != ZEND_SWITCH_FREE) { + /* Block Reordering (saves one JMP on each "for" loop iteration) + * It is disabled for some cases (ZEND_FREE/ZEND_SWITCH_FREE) + * which may break register allocation. + */ + zend_bool can_reorder = 0; + zend_block_source *cs = block->op1_to->sources; + + /* the "target" block doesn't had any followed block */ + while(cs) { + if (cs->from->follow_to == block->op1_to) { + can_reorder = 0; + break; + } + cs = cs->next; + } + if (can_reorder) { + next = block->op1_to; + /* the "target" block is not followed by current "block" */ + while (next->follow_to != NULL) { + if (next->follow_to == block) { + can_reorder = 0; + break; + } + next = next->follow_to; + } + if (can_reorder) { + zend_code_block *prev = blocks; + + while (prev->next != block->op1_to) { + prev = prev->next; + } + prev->next = next->next; + next->next = block->next; + block->next = block->op1_to; + + block->follow_to = block->op1_to; + block->op1_to = NULL; + MAKE_NOP(last_op); + block->len--; + if(block->len == 0) { + /* this block is nothing but NOP now */ + delete_code_block(block); + } + break; + } + } +#endif + } + } + break; + + case ZEND_JMPZ: + case ZEND_JMPNZ: + /* constant conditional JMPs */ + if(ZEND_OP1_TYPE(last_op) == IS_CONST) { + int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(last_op)); + if (last_op->opcode == ZEND_JMPZ) { + should_jmp = !should_jmp; + } + literal_dtor(&ZEND_OP1_LITERAL(last_op)); + ZEND_OP1_TYPE(last_op) = IS_UNUSED; + if (should_jmp) { + /* JMPNZ(true) -> JMP */ + last_op->opcode = ZEND_JMP; + COPY_NODE(last_op->op1, last_op->op2); + block->op1_to = block->op2_to; + del_source(block, block->follow_to); + block->op2_to = NULL; + block->follow_to = NULL; + } else { + /* JMPNZ(false) -> NOP */ + MAKE_NOP(last_op); + del_source(block, block->op2_to); + block->op2_to = NULL; + } + break; + } + + if(block->op2_to) { + zend_uchar same_type = ZEND_OP1_TYPE(last_op); + zend_uint same_var = VAR_NUM_EX(last_op->op1); + zend_op *target; + zend_op *target_end; + zend_code_block *target_block = block->op2_to;; + +next_target: + target = target_block->start_opline; + target_end = target_block->start_opline + target_block->len; + while(target < target_end && target->opcode == ZEND_NOP) { + target++; + } + + /* next block is only NOP's */ + if(target == target_end) { + target_block = target_block->follow_to; + goto next_target; + } else + /* JMPZ(X, L), L: JMPNZ(X, L2) -> JMPZ(X, L+1) */ + if(target->opcode == INV_COND(last_op->opcode) && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + same_type == ZEND_OP1_TYPE(target) && + same_var == VAR_NUM_EX(target->op1) && + target_block->follow_to && + !target_block->is_try + ) { + del_source(block, block->op2_to); + block->op2_to = target_block->follow_to; + ADD_SOURCE(block, block->op2_to); + } + /* JMPZ(X, L), L: X = JMPNZ_EX(X, L2) -> JMPZ(X, L+1) */ + else if(target->opcode == INV_COND_EX(last_op->opcode) && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + same_type == ZEND_OP1_TYPE(target) && + same_var == VAR_NUM_EX(target->op1) && + target_block->follow_to && + !target_block->is_try + ) { + last_op->opcode += 3; + last_op->result = target->result; + del_source(block, block->op2_to); + block->op2_to = target_block->follow_to; + ADD_SOURCE(block, block->op2_to); + } + /* JMPZ(X, L), L: JMPZ(X, L2) -> JMPZ(X, L2) */ + else if(target_block->op2_to && + target->opcode == last_op->opcode && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + same_type == ZEND_OP1_TYPE(target) && + same_var == VAR_NUM_EX(target->op1) && + !target_block->is_try + ) { + del_source(block, block->op2_to); + block->op2_to = target_block->op2_to; + ADD_SOURCE(block, block->op2_to); + } + /* JMPZ(X, L), L: JMP(L2) -> JMPZ(X, L2) */ + else if(target_block->op1_to && + target->opcode == ZEND_JMP && + !target_block->is_try + ) { + del_source(block, block->op2_to); + block->op2_to = target_block->op1_to; + ADD_SOURCE(block, block->op2_to); + } + /* JMPZ(X, L), L: JMPZNZ(X, L2, L3) -> JMPZ(X, L2) */ + else if(target_block->op2_to && + target_block->ext_to && + target->opcode == ZEND_JMPZNZ && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + same_type == ZEND_OP1_TYPE(target) && + same_var == VAR_NUM_EX(target->op1) && + ! target_block->is_try + ) { + del_source(block, block->op2_to); + if (last_op->opcode == ZEND_JMPZ) { + block->op2_to = target_block->op2_to; + } else { + block->op2_to = target_block->ext_to; + } + ADD_SOURCE(block, block->op2_to); + } + } + + if (block->follow_to && + (last_op->opcode == ZEND_JMPZ || last_op->opcode == ZEND_JMPNZ)) { + zend_op *target; + zend_op *target_end; + + while (1) { + target = block->follow_to->start_opline; + target_end = block->follow_to->start_opline + block->follow_to->len; + while (target < target_end && target->opcode == ZEND_NOP) { + target++; + } + + /* next block is only NOP's */ + if(target == target_end) { + del_source(block, block->follow_to); + block->follow_to = block->follow_to->follow_to; + ADD_SOURCE(block, block->follow_to); + } else { + break; + } + } + /* JMPZ(X,L1), JMP(L2) -> JMPZNZ(X,L1,L2) */ + if (target->opcode == ZEND_JMP && + block->follow_to->op1_to && + !block->follow_to->is_try) { + del_source(block, block->follow_to); + if (last_op->opcode == ZEND_JMPZ) { + block->ext_to = block->follow_to->op1_to; + ADD_SOURCE(block, block->ext_to); + } else { + block->ext_to = block->op2_to; + block->op2_to = block->follow_to->op1_to; + ADD_SOURCE(block, block->op2_to); + } + block->follow_to = NULL; + last_op->opcode = ZEND_JMPZNZ; + } + } + break; + + case ZEND_JMPNZ_EX: + case ZEND_JMPZ_EX: + /* constant conditional JMPs */ + if(ZEND_OP1_TYPE(last_op) == IS_CONST) { + int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(last_op)); + if (last_op->opcode == ZEND_JMPZ_EX) { + should_jmp = !should_jmp; + } + if (!should_jmp) { + /* T = JMPZ_EX(true,L) -> T = QM_ASSIGN(true) + * T = JMPNZ_EX(false,L) -> T = QM_ASSIGN(false) + */ + last_op->opcode = ZEND_QM_ASSIGN; + SET_UNUSED(last_op->op2); + del_source(block, block->op2_to); + block->op2_to = NULL; + } + break; + } + + if(block->op2_to) { + zend_op *target, *target_end; + char *same_t=NULL; + zend_code_block *target_block; + int var_num = 0; + if(op_array->T >= (zend_uint)op_array->last_var){ + var_num = op_array->T; + } else { + var_num = op_array->last_var; + } + if( var_num <= 0 ) { + return; + } + same_t = ecalloc(var_num, sizeof(char)); + if(same_t == NULL){ + return; + } + same_t[VAR_NUM_EX(last_op->op1)] |= ZEND_OP1_TYPE(last_op); + same_t[VAR_NUM_EX(last_op->result)] |= ZEND_RESULT_TYPE(last_op); + target_block = block->op2_to; +next_target_ex: + target = target_block->start_opline; + target_end = target_block->start_opline + target_block->len; + while(target < target_end && target->opcode == ZEND_NOP) { + target++; + } + /* next block is only NOP's */ + if(target == target_end) { + target_block = target_block->follow_to; + goto next_target_ex; + } else + /* T = JMPZ_EX(X, L1), L1: JMPZ({X|T}, L2) -> T = JMPZ_EX(X, L2) */ + if(target_block->op2_to && + target->opcode == last_op->opcode-3 && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && + !target_block->is_try + ) { + del_source(block, block->op2_to); + block->op2_to = target_block->op2_to; + ADD_SOURCE(block, block->op2_to); + /* T = JMPZ_EX(X, L1), L1: JMPNZ({X|T1}, L2) -> T = JMPZ_EX(X, L1+1) */ + } else if(target_block->op2_to && + target->opcode == INV_EX_COND(last_op->opcode) && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && + !target_block->is_try + ) { + del_source(block, block->op2_to); + block->op2_to = target_block->follow_to; + ADD_SOURCE(block, block->op2_to); + /* T = JMPZ_EX(X, L1), L1: T = JMPNZ_EX(T, L2) -> T = JMPZ_EX(X, L1+1) */ + } else if(target_block->op2_to && + target->opcode == INV_EX_COND_EX(last_op->opcode) && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && + (same_t[VAR_NUM_EX(target->result)] & ZEND_RESULT_TYPE(target)) != 0 && + !target_block->is_try) { + del_source(block, block->op2_to); + block->op2_to = target_block->follow_to; + ADD_SOURCE(block, block->op2_to); + /* T = JMPZ_EX(X, L1), L1: T = JMPZ({X|T}, L2) -> T = JMPZ_EX(X, L2) */ + } else if(target_block->op2_to && + target->opcode == last_op->opcode && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && + (same_t[VAR_NUM_EX(target->result)] & ZEND_RESULT_TYPE(target)) != 0 && + !target_block->is_try) { + del_source(block, block->op2_to); + block->op2_to = target_block->op2_to; + ADD_SOURCE(block, block->op2_to); + /* T = JMPZ_EX(X, L), L: JMP(L2) -> T = JMPZ(X, L2) */ + } else if(target_block->op1_to && + target->opcode == ZEND_JMP && + !target_block->is_try) { + del_source(block, block->op2_to); + block->op2_to = target_block->op1_to; + ADD_SOURCE(block, block->op2_to); + /* T = JMPZ_EX(X, L), L: JMPZNZ({X|T}, L2, L3) -> T = JMPZ_EX(X, L2) */ + } else if(target_block->op2_to && + target_block->ext_to && + target->opcode == ZEND_JMPZNZ && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && + !target_block->is_try + ) { + del_source(block, block->op2_to); + if (last_op->opcode == ZEND_JMPZ_EX) { + block->op2_to = target_block->op2_to; + } else { + block->op2_to = target_block->ext_to; + } + ADD_SOURCE(block, block->op2_to); + } + if(same_t != NULL){ + efree(same_t); + } + } + break; + + case ZEND_JMPZNZ: { + zend_code_block *next = block->next; + + while (next && !next->access) { + /* find first accessed one */ + next = next->next; + } + + if(ZEND_OP1_TYPE(last_op) == IS_CONST) { + if (!zend_is_true(&ZEND_OP1_LITERAL(last_op))) { + /* JMPZNZ(false,L1,L2) -> JMP(L1) */ + zend_code_block *todel; + + literal_dtor(&ZEND_OP1_LITERAL(last_op)); + last_op->opcode = ZEND_JMP; + SET_UNUSED(last_op->op1); + SET_UNUSED(last_op->op2); + block->op1_to = block->op2_to; + todel = block->ext_to; + block->op2_to = NULL; + block->ext_to = NULL; + del_source(block, todel); + } else { + /* JMPZNZ(true,L1,L2) -> JMP(L2) */ + zend_code_block *todel; + + literal_dtor(&ZEND_OP1_LITERAL(last_op)); + last_op->opcode = ZEND_JMP; + SET_UNUSED(last_op->op1); + SET_UNUSED(last_op->op2); + block->op1_to = block->ext_to; + todel = block->op2_to; + block->op2_to = NULL; + block->ext_to = NULL; + del_source(block, todel); + } + } else if (block->op2_to == block->ext_to) { + /* both goto the same one - it's JMP */ + /* JMPZNZ(?,L,L) -> JMP(L) */ + last_op->opcode = ZEND_JMP; + SET_UNUSED(last_op->op1); + SET_UNUSED(last_op->op2); + block->op1_to = block->op2_to; + block->op2_to = NULL; + block->ext_to = NULL; + } else if (block->op2_to == next) { + /* jumping to next on Z - can follow to it and jump only on NZ */ + /* JMPZNZ(X,L1,L2) L1: -> JMPNZ(X,L2) */ + last_op->opcode = ZEND_JMPNZ; + block->op2_to = block->ext_to; + block->follow_to = next; + block->ext_to = NULL; + /* no need to add source - it's block->op2_to */ + } else if (block->ext_to == next) { + /* jumping to next on NZ - can follow to it and jump only on Z */ + /* JMPZNZ(X,L1,L2) L2: -> JMPZ(X,L1) */ + last_op->opcode = ZEND_JMPZ; + block->follow_to = next; + block->ext_to = NULL; + /* no need to add source - it's block->ext_to */ + } + + if(last_op->opcode == ZEND_JMPZNZ && block->op2_to) { + zend_uchar same_type = ZEND_OP1_TYPE(last_op); + zend_uchar same_var = VAR_NUM_EX(last_op->op1); + zend_op *target; + zend_op *target_end; + zend_code_block *target_block = block->op2_to; + +next_target_znz: + target = target_block->start_opline; + target_end = target_block->start_opline + target_block->len; + while(target < target_end && target->opcode == ZEND_NOP) { + target++; + } + /* next block is only NOP's */ + if(target == target_end) { + target_block = target_block->follow_to; + goto next_target_znz; + /* JMPZNZ(X, L1, L2), L1: JMPZ(X, L3) -> JMPZNZ(X, L3, L2) */ + } else if(target_block->op2_to && + (target->opcode == ZEND_JMPZ || target->opcode == ZEND_JMPZNZ) && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + same_type == ZEND_OP1_TYPE(target) && + same_var == VAR_NUM_EX(target->op1) && + !target_block->is_try) { + del_source(block, block->op2_to); + block->op2_to = target_block->op2_to; + ADD_SOURCE(block, block->op2_to); + } + /* JMPZNZ(X, L1, L2), L1: X = JMPNZ(X, L3) -> JMPZNZ(X, L1+1, L2) */ + else if(target->opcode == ZEND_JMPNZ && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + same_type == ZEND_OP1_TYPE(target) && + same_var == VAR_NUM_EX(target->op1) && + target_block->follow_to && + !target_block->is_try) { + del_source(block, block->op2_to); + block->op2_to = target_block->follow_to; + ADD_SOURCE(block, block->op2_to); + } + /* JMPZNZ(X, L1, L2), L1: JMP(L3) -> JMPZNZ(X, L3, L2) */ + else if(target_block->op1_to && + target->opcode == ZEND_JMP && + !target_block->is_try) { + del_source(block, block->op2_to); + block->op2_to = target_block->op1_to; + ADD_SOURCE(block, block->op2_to); + } + } + break; + } + } +} + +/* Global data dependencies */ + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + +# define T_USAGE(op) do { \ + if((op ## _type & (IS_VAR | IS_TMP_VAR)) && \ + !defined_here[VAR_NUM(op.var)] && !used_ext[VAR_NUM(op.var)]) { \ + used_ext[VAR_NUM(op.var)] = 1; \ + } \ + } while (0) + +# define NEVER_USED(op) ((op ## _type & (IS_VAR | IS_TMP_VAR)) && !usage[VAR_NUM(op.var)]) /* !used_ext[op.var] && */ +# define RES_NEVER_USED(opline) (opline->result_type == IS_UNUSED || NEVER_USED(opline->result)) + +#else + +# define T_USAGE(op) do { \ + if((op.op_type == IS_VAR || op.op_type == IS_TMP_VAR) && \ + !defined_here[VAR_NUM(op.u.var)] && !used_ext[VAR_NUM(op.u.var)]) { \ + used_ext[VAR_NUM(op.u.var)] = 1; \ + } \ + } while (0) + +# define NEVER_USED(op) ((op.op_type == IS_VAR || op.op_type == IS_TMP_VAR) && !usage[VAR_NUM(op.u.var)]) /* !used_ext[op.u.var] && */ +# define RES_NEVER_USED(opline) (ZEND_RESULT_TYPE(opline) == IS_UNUSED || NEVER_USED(opline->result)) + +#endif + +/* Find a set of variables which are used outside of the block where they are + * defined. We won't apply some optimization patterns for sush variables. */ +static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *used_ext) +{ + zend_code_block *next_block = block->next; + char *usage; + char *defined_here; + + if(op_array->T == 0) { + /* shortcut - if no Ts, nothing to do */ + return; + } + + usage = ecalloc(op_array->T, 1); + defined_here = emalloc(op_array->T); + + while(next_block) { + zend_op *opline = next_block->start_opline; + zend_op *end = opline+next_block->len; + + if(!next_block->access) { + next_block = next_block->next; + continue; + } + memset(defined_here, 0, op_array->T); + + while(oplineop1); + T_USAGE(opline->op2); + + if(RESULT_USED(opline)) { + if(!defined_here[VAR_NUM(ZEND_RESULT(opline).var)] && !used_ext[VAR_NUM(ZEND_RESULT(opline).var)] && + (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT || + (opline->opcode == ZEND_OP_DATA && ZEND_RESULT_TYPE(opline) == IS_TMP_VAR) || + opline->opcode == ZEND_ADD_ARRAY_ELEMENT)) { + /* these opcodes use the result as argument */ + used_ext[VAR_NUM(ZEND_RESULT(opline).var)] = 1; + } + defined_here[VAR_NUM(ZEND_RESULT(opline).var)] = 1; + } + opline++; + } + next_block = next_block->next; + } + +#if DEBUG_BLOCKPASS + { + int i; + for(i=0; i< op_array->T; i++) { + fprintf(stderr, "T%d: %c\n", i, used_ext[i]+'0'); + } + } +#endif + + while(block) { + zend_op *opline = block->start_opline+block->len-1; + + if(!block->access) { + block = block->next; + continue; + } + + memcpy(usage, used_ext, op_array->T); + + while(opline>=block->start_opline) { + /* usage checks */ + if(RES_NEVER_USED(opline)) { + switch(opline->opcode) { + 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: + case ZEND_PRE_INC: + case ZEND_PRE_DEC: + case ZEND_POST_INC: + case ZEND_POST_DEC: + case ZEND_ASSIGN: + case ZEND_ASSIGN_REF: + case ZEND_DO_FCALL: + case ZEND_DO_FCALL_BY_NAME: + if(ZEND_RESULT_TYPE(opline) == IS_VAR) { +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + ZEND_RESULT_TYPE(opline) |= EXT_TYPE_UNUSED; +#else + ZEND_RESULT(opline).EA.type |= EXT_TYPE_UNUSED; +#endif + } + break; + case ZEND_QM_ASSIGN: + case ZEND_BOOL: + case ZEND_BOOL_NOT: + if(ZEND_OP1_TYPE(opline) == IS_CONST) { + literal_dtor(&ZEND_OP1_LITERAL(opline)); + } + MAKE_NOP(opline); + break; + case ZEND_PRINT: + opline->opcode = ZEND_ECHO; + ZEND_RESULT_TYPE(opline) = IS_UNUSED; + break; + case ZEND_JMPZ_EX: + case ZEND_JMPNZ_EX: + opline->opcode -= 3; + SET_UNUSED(opline->result); + break; + } + } + + if(opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT || + opline->opcode == ZEND_ADD_ARRAY_ELEMENT) { + if(ZEND_OP1_TYPE(opline) == IS_VAR || ZEND_OP1_TYPE(opline) == IS_TMP_VAR) { + usage[VAR_NUM(ZEND_RESULT(opline).var)] = 1; + } + } else { + if(RESULT_USED(opline)) { + usage[VAR_NUM(ZEND_RESULT(opline).var)] = 0; + } + } + + if(ZEND_OP1_TYPE(opline) == IS_VAR || ZEND_OP1_TYPE(opline) == IS_TMP_VAR) { + usage[VAR_NUM(ZEND_OP1(opline).var)] = 1; + } + if(ZEND_OP2_TYPE(opline) == IS_VAR || ZEND_OP2_TYPE(opline) == IS_TMP_VAR) { + usage[VAR_NUM(ZEND_OP2(opline).var)] = 1; + } + + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if((ZEND_RESULT_TYPE(opline) & IS_VAR) && + (ZEND_RESULT_TYPE(opline) & EXT_TYPE_UNUSED) && + usage[VAR_NUM(ZEND_RESULT(opline).var)]) { + ZEND_RESULT_TYPE(opline) &= ~EXT_TYPE_UNUSED; + } +#else + if(ZEND_RESULT_TYPE(opline) == IS_VAR && + usage[VAR_NUM(ZEND_RESULT(opline).var)] && + (ZEND_RESULT(opline).EA.type & EXT_TYPE_UNUSED) != 0) { + ZEND_RESULT(opline).EA.type &= ~EXT_TYPE_UNUSED; + } +#endif + + opline--; + } + block = block->next; + } /* end blocks */ + efree(defined_here); + efree(usage); +} + +#define PASSES 3 + +static void zend_block_optimization(zend_op_array *op_array TSRMLS_DC) +{ + zend_code_block *blocks, *cur_block; + int pass; + char *usage; + +#if DEBUG_BLOCKPASS + fprintf(stderr, "File %s func %s\n", op_array->filename, op_array->function_name?op_array->function_name:"main"); + fflush(stderr); +#endif + +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + if (op_array->has_finally_block) { + return; + } +#endif + + /* Build CFG */ + blocks = find_code_blocks(op_array); + if(!blocks) { + return; + } + + zend_rebuild_access_path(blocks, op_array, 0); + /* full rebuild here to produce correct sources! */ + usage = emalloc(op_array->T); + for(pass=0; pass< PASSES; pass++) { + /* Compute data dependencies */ + memset(usage, 0, op_array->T); + zend_t_usage(blocks, op_array, usage); + + /* optimize each basic block separately */ + for(cur_block = blocks; cur_block; cur_block = cur_block->next) { + if(!cur_block->access) { + continue; + } + zend_optimize_block(cur_block, op_array, usage TSRMLS_CC); + } + + /* Jump optimization for each block */ + for(cur_block = blocks; cur_block; cur_block = cur_block->next) { + if(!cur_block->access) { + continue; + } + zend_jmp_optimization(cur_block, op_array, blocks); + } + + /* Eliminate unreachable basic blocks */ + zend_rebuild_access_path(blocks, op_array, 1); + } + + assemble_code_blocks(blocks, op_array); + efree(usage); + + /* Destroy CFG */ + for(cur_block = blocks; cur_block; cur_block = cur_block->next) { + zend_block_source *cs = cur_block->sources; + while(cs) { + zend_block_source *n = cs->next; + efree(cs); + cs = n; + } + } + efree(blocks); +} diff --git a/Optimizer/nop_removal.c b/Optimizer/nop_removal.c new file mode 100644 index 00000000000..49ffe0e6e50 --- /dev/null +++ b/Optimizer/nop_removal.c @@ -0,0 +1,126 @@ +/* pass 10: + * - remove NOPs + */ + +static void nop_removal(zend_op_array *op_array) +{ + zend_op *end, *opline; + zend_uint new_count, i, shift; + int j; + zend_uint *shiftlist; + ALLOCA_FLAG(use_heap); + + shiftlist = (zend_uint *)DO_ALLOCA(sizeof(zend_uint) * op_array->last); + i = new_count = shift = 0; + end = op_array->opcodes+op_array->last; + for (opline = op_array->opcodes; opline < end; opline++) { + +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + /* GOTO target is unresolved yet. We can't optimize. */ + if (opline->opcode == ZEND_GOTO && + Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_LONG) { + /* TODO: in general we can avoid this restriction */ + FREE_ALLOCA(shiftlist); + return; + } +#endif + + /* Kill JMP-over-NOP-s */ + if (opline->opcode == ZEND_JMP && ZEND_OP1(opline).opline_num > i) { + /* check if there are only NOPs under the branch */ + zend_op *target = op_array->opcodes + ZEND_OP1(opline).opline_num - 1; + + while (target->opcode == ZEND_NOP) { + target--; + } + if (target == opline) { + /* only NOPs */ + opline->opcode = ZEND_NOP; + } + } + + shiftlist[i++] = shift; + if (opline->opcode == ZEND_NOP) { + shift++; + } else { + if (shift) { + op_array->opcodes[new_count] = *opline; + } + new_count++; + } + } + + if (shift) { + op_array->last = new_count; + end = op_array->opcodes + op_array->last; + + /* update JMPs */ + for (opline = op_array->opcodes; oplineopcode) { + case ZEND_JMP: +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + case ZEND_GOTO: +#endif +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + case ZEND_FAST_CALL: +#endif + ZEND_OP1(opline).opline_num -= shiftlist[ZEND_OP1(opline).opline_num]; + break; + case ZEND_JMPZ: + case ZEND_JMPNZ: + case ZEND_JMPZ_EX: + case ZEND_JMPNZ_EX: + case ZEND_FE_FETCH: + case ZEND_FE_RESET: + case ZEND_NEW: +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + case ZEND_JMP_SET: +#endif +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + case ZEND_JMP_SET_VAR: +#endif + ZEND_OP2(opline).opline_num -= shiftlist[ZEND_OP2(opline).opline_num]; + break; + case ZEND_JMPZNZ: + ZEND_OP2(opline).opline_num -= shiftlist[ZEND_OP2(opline).opline_num]; + opline->extended_value -= shiftlist[opline->extended_value]; + break; + case ZEND_CATCH: + opline->extended_value -= shiftlist[opline->extended_value]; + break; + } + } + + /* update brk/cont array */ + for (i=0; ilast_brk_cont; i++) { + op_array->brk_cont_array[i].brk -= shiftlist[op_array->brk_cont_array[i].brk]; + op_array->brk_cont_array[i].cont -= shiftlist[op_array->brk_cont_array[i].cont]; + op_array->brk_cont_array[i].start -= shiftlist[op_array->brk_cont_array[i].start]; + } + + /* update try/catch array */ + for (j=0; jlast_try_catch; j++) { + op_array->try_catch_array[j].try_op -= shiftlist[op_array->try_catch_array[j].try_op]; + op_array->try_catch_array[j].catch_op -= shiftlist[op_array->try_catch_array[j].catch_op]; +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + if (op_array->try_catch_array[j].finally_op) { + op_array->try_catch_array[j].finally_op -= shiftlist[op_array->try_catch_array[j].finally_op]; + op_array->try_catch_array[j].finally_end -= shiftlist[op_array->try_catch_array[j].finally_end]; + } +#endif + } + +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + /* update early binding list */ + if (op_array->early_binding != -1) { + zend_uint *opline_num = &op_array->early_binding; + + do { + *opline_num -= shiftlist[*opline_num]; + opline_num = &ZEND_RESULT(&op_array->opcodes[*opline_num]).opline_num; + } while (*opline_num != -1); + } +#endif + } + FREE_ALLOCA(shiftlist); +} diff --git a/Optimizer/optimize_temp_vars_5.c b/Optimizer/optimize_temp_vars_5.c new file mode 100644 index 00000000000..4e2865ead44 --- /dev/null +++ b/Optimizer/optimize_temp_vars_5.c @@ -0,0 +1,222 @@ +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + +/* ops that use CLs: +op1: +ZEND_FETCH_CONSTANT: +ZEND_INIT_CTOR_CALL: +ZEND_INIT_STATIC_METHOD_CALL: +ZEND_INIT_METHOD_CALL: +ZEND_IMPORT_CLASS: +ZEND_IMPORT_FUNCTION: +ZEND_IMPORT_CONST: +ZEND_ADD_INTERFACE: +ZEND_VERIFY_ABSTRACT_CLASS: +ZEND_NEW: +ZEND_CATCH: +ZEND_INIT_FCALL_BY_NAME: + +op2: +ZEND_UNSET_VAR: +ZEND_ISSET_ISEMPTY_VAR: +ZEND_FETCH_UNSET: +ZEND_FETCH_IS: +ZEND_FETCH_R: +ZEND_FETCH_W: +ZEND_FETCH_RW: +ZEND_FETCH_FUNC_ARG: +ZEND_ADD_INTERFACE: +ZEND_INSTANCEOF: + +extended_value: +ZEND_DECLARE_INHERITED_CLASS: + +ignore result +INIT_METHOD_CALL: +*/ + +#define OP1_CONST_IS_CLASS 1 +#define OP2_CONST_IS_CLASS 2 +#define EXT_CONST_IS_CLASS 4 +#define RESULT_IS_UNUSED 8 + +static const char op_const_means_class[256] = { + /* 0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 32 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + /* 64 */ + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, + /* 96 */ + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 9, 1, 2, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 128 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 160 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 192 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 224 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +#endif + +#define GET_AVAILABLE_T() \ + for (i=0; i max) { \ + max = i; \ + } + +static void optimize_temporary_variables(zend_op_array *op_array) +{ + int T = op_array->T; + char *taken_T; /* T index in use */ + zend_op **start_of_T; /* opline where T is first used */ + char *valid_T; /* Is the map_T valid */ + int *map_T; /* Map's the T to its new index */ + zend_op *opline, *end; + int currT; + int i; + int max = -1; + int var_to_free = -1; + + taken_T = (char *) emalloc(T); + start_of_T = (zend_op **) emalloc(T*sizeof(zend_op *)); + valid_T = (char *) emalloc(T); + map_T = (int *) emalloc(T*sizeof(int)); + + end = op_array->opcodes; + opline = &op_array->opcodes[op_array->last-1]; + + /* Find T definition points */ + while (opline >= end) { +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR | IS_CONST)) { + if (!(op_const_means_class[opline->opcode] & RESULT_IS_UNUSED)) { + start_of_T[VAR_NUM(ZEND_RESULT(opline).var)] = opline; + } + } +#else + if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR)) { + start_of_T[VAR_NUM(ZEND_RESULT(opline).var)] = opline; + } +#endif + opline--; + } + + memset(valid_T, 0, T); + memset(taken_T, 0, T); + + end = op_array->opcodes; + opline = &op_array->opcodes[op_array->last-1]; + + while (opline >= end) { + if ((ZEND_OP1_TYPE(opline) & (IS_VAR | IS_TMP_VAR)) +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + || ((op_const_means_class[opline->opcode] & OP1_CONST_IS_CLASS) && ZEND_OP1_TYPE(opline) == IS_CONST) +#endif + ) { + currT = VAR_NUM(ZEND_OP1(opline).var); + if (!valid_T[currT]) { + GET_AVAILABLE_T(); + map_T[currT] = i; + valid_T[currT] = 1; + } + ZEND_OP1(opline).var = NUM_VAR(map_T[currT]); + } + + /* Skip OP_DATA */ + if (opline->opcode == ZEND_OP_DATA && + (opline-1)->opcode == ZEND_ASSIGN_DIM) { + opline--; + continue; + } + + if ((ZEND_OP2_TYPE(opline) & (IS_VAR | IS_TMP_VAR)) +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + || ((op_const_means_class[opline->opcode] & OP2_CONST_IS_CLASS) && ZEND_OP2_TYPE(opline) == IS_CONST) +#endif + ) { + currT = VAR_NUM(ZEND_OP2(opline).var); + if (!valid_T[currT]) { + GET_AVAILABLE_T(); + map_T[currT] = i; + valid_T[currT] = 1; + } + ZEND_OP2(opline).var = NUM_VAR(map_T[currT]); + } + +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + if ((op_const_means_class[opline->opcode] & EXT_CONST_IS_CLASS)) { +#else + if (opline->opcode == ZEND_DECLARE_INHERITED_CLASS || + opline->opcode == ZEND_DECLARE_INHERITED_CLASS_DELAYED) { +#endif + currT = VAR_NUM(opline->extended_value); + if (!valid_T[currT]) { + GET_AVAILABLE_T(); + map_T[currT] = i; + valid_T[currT] = 1; + } + opline->extended_value = NUM_VAR(map_T[currT]); + } + + /* Allocate OP_DATA->op2 after "opernds", but before "result" */ + if (opline->opcode == ZEND_ASSIGN_DIM && + (opline+1)->opcode == ZEND_OP_DATA && + ZEND_OP2_TYPE(opline+1) & (IS_VAR | IS_TMP_VAR)) { + currT = VAR_NUM(ZEND_OP2(opline+1).var); + GET_AVAILABLE_T(); + map_T[currT] = i; + valid_T[currT] = 1; + taken_T[i] = 0; + ZEND_OP2(opline+1).var = NUM_VAR(i); + var_to_free = i; + } + +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR | IS_CONST)) { + if (!(op_const_means_class[opline->opcode] & RESULT_IS_UNUSED)) { +#else + if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR)) { +#endif + currT = VAR_NUM(ZEND_RESULT(opline).var); + if (valid_T[currT]) { + if (start_of_T[currT] == opline) { + taken_T[map_T[currT]] = 0; + } + ZEND_RESULT(opline).var = NUM_VAR(map_T[currT]); + } else { /* Au still needs to be assigned a T which is a bit dumb. Should consider changing Zend */ + GET_AVAILABLE_T(); + + if (RESULT_UNUSED(opline)) { + taken_T[i] = 0; + } else { + /* Code which gets here is using a wrongly built opcode such as RECV() */ + map_T[currT] = i; + valid_T[currT] = 1; + } + ZEND_RESULT(opline).var = NUM_VAR(i); + } +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + } +#endif + } + + if (var_to_free >= 0) { + taken_T[var_to_free] = 0; + var_to_free = -1; + } + + opline--; + } + + efree(taken_T); + efree(start_of_T); + efree(valid_T); + efree(map_T); + op_array->T = max+1; +} diff --git a/Optimizer/pass10.c b/Optimizer/pass10.c new file mode 100644 index 00000000000..3bfcec643a6 --- /dev/null +++ b/Optimizer/pass10.c @@ -0,0 +1,3 @@ +if (((ZEND_OPTIMIZER_PASS_10|ZEND_OPTIMIZER_PASS_5) & OPTIMIZATION_LEVEL) == ZEND_OPTIMIZER_PASS_10) { + nop_removal(op_array); +} diff --git a/Optimizer/pass1_5.c b/Optimizer/pass1_5.c new file mode 100644 index 00000000000..247b1b8632f --- /dev/null +++ b/Optimizer/pass1_5.c @@ -0,0 +1,391 @@ +/* pass 1 + * - substitute persistent constants (true, false, null, etc) + * - perform compile-time evaluation of constant binary and unary operations + * - optimize series of ADD_STRING and/or ADD_CHAR + * - convert CAST(IS_BOOL,x) into BOOL(x) + * - convert INTI_FCALL_BY_NAME, DO_FCALL_BY_NAME into DO_FCALL + */ + +if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { + int i=0; + zend_op *opline = op_array->opcodes; + zend_op *end = opline + op_array->last; + + while (oplineopcode) { + case ZEND_ADD: + case ZEND_SUB: + case ZEND_MUL: + case ZEND_DIV: + case ZEND_MOD: + case ZEND_SL: + case ZEND_SR: + case ZEND_CONCAT: + case ZEND_IS_EQUAL: + case ZEND_IS_NOT_EQUAL: + case ZEND_IS_SMALLER: + case ZEND_IS_SMALLER_OR_EQUAL: + case ZEND_IS_IDENTICAL: + case ZEND_IS_NOT_IDENTICAL: + case ZEND_BW_OR: + case ZEND_BW_AND: + case ZEND_BW_XOR: + case ZEND_BOOL_XOR: + if (ZEND_OP1_TYPE(opline)==IS_CONST + && ZEND_OP2_TYPE(opline)==IS_CONST) { + /* binary operation wheit constant operands */ + int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC) = get_binary_op(opline->opcode); + zend_uint tv = ZEND_RESULT(opline).var; /* temporary variable */ + zval result; + zend_op *tmp_opline; + int er; + + if (opline->opcode == ZEND_DIV && + Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_LONG && + Z_LVAL(ZEND_OP2_LITERAL(opline)) == 0) { + /* div by 0 */ + break; + } + er = EG(error_reporting); + EG(error_reporting) = 0; + /* evaluate constant expression */ + if (binary_op(&result, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline) TSRMLS_CC) != SUCCESS) { + EG(error_reporting) = er; + break; + } + EG(error_reporting) = er; + PZ_SET_REFCOUNT_P(&result, 1); + PZ_UNSET_ISREF_P(&result); + + literal_dtor(&ZEND_OP1_LITERAL(opline)); + literal_dtor(&ZEND_OP2_LITERAL(opline)); + MAKE_NOP(opline); + + /* substitute the following TMP_VAR usage with constant */ + for (tmp_opline=opline+1; tmp_oplineopcode==ZEND_FREE) { + MAKE_NOP(tmp_opline); + zval_dtor(&result); + } else { + ZEND_OP1_TYPE(tmp_opline) = IS_CONST; +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + tmp_opline->op1.constant = zend_add_literal(op_array, &result TSRMLS_CC); + if (Z_TYPE(result) == IS_STRING) { + Z_HASH_P(&ZEND_OP1_LITERAL(tmp_opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(tmp_opline)), Z_STRLEN(ZEND_OP1_LITERAL(tmp_opline))+1); + if (tmp_opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + tmp_opline->opcode == ZEND_DO_FCALL || + tmp_opline->opcode == ZEND_CATCH || + tmp_opline->opcode == ZEND_FETCH_CONSTANT) { + op_array->literals[tmp_opline->op1.constant].cache_slot = op_array->last_cache_slot++; + } + } +#else + ZEND_OP1_LITERAL(tmp_opline) = result; +#endif + } + /* TMP_VAR my be used only once */ + break; + } + if (ZEND_OP2_TYPE(tmp_opline)== IS_TMP_VAR + && ZEND_OP2(tmp_opline).var == tv) { + ZEND_OP2_TYPE(tmp_opline) = IS_CONST; +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + tmp_opline->op2.constant = zend_add_literal(op_array, &result TSRMLS_CC); + if (Z_TYPE(result) == IS_STRING) { + Z_HASH_P(&ZEND_OP2_LITERAL(tmp_opline)) = zend_hash_func(Z_STRVAL(ZEND_OP2_LITERAL(tmp_opline)), Z_STRLEN(ZEND_OP2_LITERAL(tmp_opline))+1); + if (tmp_opline->opcode == ZEND_FETCH_R || + tmp_opline->opcode == ZEND_FETCH_W || + tmp_opline->opcode == ZEND_FETCH_RW || + tmp_opline->opcode == ZEND_FETCH_IS || + tmp_opline->opcode == ZEND_FETCH_UNSET || + tmp_opline->opcode == ZEND_FETCH_FUNC_ARG || + tmp_opline->opcode == ZEND_FETCH_CLASS || + tmp_opline->opcode == ZEND_INIT_FCALL_BY_NAME || + tmp_opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + tmp_opline->opcode == ZEND_UNSET_VAR || + tmp_opline->opcode == ZEND_ISSET_ISEMPTY_VAR || + tmp_opline->opcode == ZEND_ADD_INTERFACE || + tmp_opline->opcode == ZEND_ADD_TRAIT) { + op_array->literals[tmp_opline->op2.constant].cache_slot = op_array->last_cache_slot++; + } else if (tmp_opline->opcode == ZEND_INIT_METHOD_CALL || + tmp_opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + tmp_opline->opcode == ZEND_FETCH_CONSTANT || + tmp_opline->opcode == ZEND_ASSIGN_OBJ || + tmp_opline->opcode == ZEND_FETCH_OBJ_R || + tmp_opline->opcode == ZEND_FETCH_OBJ_W || + tmp_opline->opcode == ZEND_FETCH_OBJ_RW || + tmp_opline->opcode == ZEND_FETCH_OBJ_IS || + tmp_opline->opcode == ZEND_FETCH_OBJ_UNSET || + tmp_opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG || + tmp_opline->opcode == ZEND_UNSET_OBJ || + tmp_opline->opcode == ZEND_PRE_INC_OBJ || + tmp_opline->opcode == ZEND_PRE_DEC_OBJ || + tmp_opline->opcode == ZEND_POST_INC_OBJ || + tmp_opline->opcode == ZEND_POST_DEC_OBJ || + tmp_opline->opcode == ZEND_ISSET_ISEMPTY_PROP_OBJ) { + op_array->literals[tmp_opline->op2.constant].cache_slot = op_array->last_cache_slot; + op_array->last_cache_slot += 2; + } else if (tmp_opline->opcode == ZEND_ASSIGN_ADD || + tmp_opline->opcode == ZEND_ASSIGN_SUB || + tmp_opline->opcode == ZEND_ASSIGN_MUL || + tmp_opline->opcode == ZEND_ASSIGN_DIV || + tmp_opline->opcode == ZEND_ASSIGN_MOD || + tmp_opline->opcode == ZEND_ASSIGN_SL || + tmp_opline->opcode == ZEND_ASSIGN_SR || + tmp_opline->opcode == ZEND_ASSIGN_CONCAT || + tmp_opline->opcode == ZEND_ASSIGN_BW_OR || + tmp_opline->opcode == ZEND_ASSIGN_BW_AND || + tmp_opline->opcode == ZEND_ASSIGN_BW_XOR) { + if (tmp_opline->extended_value == ZEND_ASSIGN_OBJ) { + op_array->literals[tmp_opline->op2.constant].cache_slot = op_array->last_cache_slot; + op_array->last_cache_slot += 2; + } + } + } +#else + ZEND_OP2_LITERAL(tmp_opline) = result; +#endif + break; + } + } + } + break; + + case ZEND_CAST: + if (ZEND_OP1_TYPE(opline)==IS_CONST && + opline->extended_value != IS_ARRAY && + opline->extended_value != IS_OBJECT && + opline->extended_value != IS_RESOURCE) { + /* cast of constant operand */ + 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; + } + literal_dtor(&ZEND_OP1_LITERAL(opline)); + opline->opcode = ZEND_QM_ASSIGN; + opline->extended_value = 0; + ZEND_OP1_LITERAL(opline) = res; + SET_UNUSED(opline->op2); + } else if (opline->extended_value == IS_BOOL) { + /* T = CAST(X, IS_BOOL) => T = BOOL(X) */ + opline->opcode = ZEND_BOOL; + opline->extended_value = 0; + } + break; + + case ZEND_BW_NOT: + case ZEND_BOOL_NOT: + if (ZEND_OP1_TYPE(opline)==IS_CONST) { + /* unary operation on constant operand */ + unary_op_type unary_op = get_unary_op(opline->opcode); + zval result; + zend_op *tmp_opline; + zend_uint tv = ZEND_RESULT(opline).var; /* temporary variable */ + int er; + + er = EG(error_reporting); + EG(error_reporting) = 0; + if (unary_op(&result, &ZEND_OP1_LITERAL(opline) TSRMLS_CC) != SUCCESS) { + EG(error_reporting) = er; + break; + } + EG(error_reporting) = er; + PZ_SET_REFCOUNT_P(&result, 1); + PZ_UNSET_ISREF_P(&result); + + literal_dtor(&ZEND_OP1_LITERAL(opline)); + MAKE_NOP(opline); + + /* substitute the following TMP_VAR usage with constant */ + for (tmp_opline=opline+1; tmp_oplineopcode==ZEND_FREE) { + MAKE_NOP(tmp_opline); + zval_dtor(&result); + } else { + ZEND_OP1_TYPE(tmp_opline) = IS_CONST; +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + tmp_opline->op1.constant = zend_add_literal(op_array, &result TSRMLS_CC); +#else + ZEND_OP1_LITERAL(tmp_opline) = result; +#endif + } + break; + } + if (ZEND_OP2_TYPE(tmp_opline)== IS_TMP_VAR + && ZEND_OP2(tmp_opline).var == tv) { + ZEND_OP2_TYPE(tmp_opline) = IS_CONST; +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + tmp_opline->op2.constant = zend_add_literal(op_array, &result TSRMLS_CC); +#else + ZEND_OP2_LITERAL(tmp_opline) = result; +#endif + break; + } + } + } + break; + + case ZEND_ADD_STRING: + case ZEND_ADD_CHAR: + { + zend_op *next_op = opline+1; + int requires_conversion = (opline->opcode==ZEND_ADD_CHAR?1:0); + size_t final_length = 0; + char *ptr; + zend_op *last_op; + + /* There is always a ZEND_RETURN at the end + if (next_op>=end) { + break; + } + */ + while (next_op->opcode == ZEND_ADD_STRING || next_op->opcode == ZEND_ADD_CHAR) { + if (ZEND_RESULT(opline).var != ZEND_RESULT(next_op).var) { + break; + } + if (next_op->opcode == ZEND_ADD_CHAR) { + final_length += 1; + } else { /* ZEND_ADD_STRING */ + final_length += ZEND_OP2_LITERAL(next_op).value.str.len; + } + next_op++; + } + if (final_length == 0) { + break; + } + last_op = next_op; + final_length += (requires_conversion ? 1 : ZEND_OP2_LITERAL(opline).value.str.len); + ptr = (char *) emalloc(final_length+1); + ptr[final_length] = '\0'; + if (requires_conversion) { /* ZEND_ADD_CHAR */ + char chval = (char)ZEND_OP2_LITERAL(opline).value.lval; + + ZEND_OP2_LITERAL(opline).value.str.val = ptr; + ptr[0] = chval; + ZEND_OP2_LITERAL(opline).type = IS_STRING; + opline->opcode = ZEND_ADD_STRING; + ptr++; + } else { /* ZEND_ADD_STRING */ + memcpy(ptr, Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline))); + if (!IS_INTERNED(Z_STRVAL(ZEND_OP2_LITERAL(opline)))) { + efree(Z_STRVAL(ZEND_OP2_LITERAL(opline))); + } + Z_STRVAL(ZEND_OP2_LITERAL(opline)) = ptr; + ptr += Z_STRLEN(ZEND_OP2_LITERAL(opline)); + } + ZEND_OP2_LITERAL(opline).value.str.len = final_length; + next_op = opline+1; + while (next_op < last_op) { + if (next_op->opcode == ZEND_ADD_STRING) { + memcpy(ptr, ZEND_OP2_LITERAL(next_op).value.str.val, ZEND_OP2_LITERAL(next_op).value.str.len); + ptr += ZEND_OP2_LITERAL(next_op).value.str.len; + literal_dtor(&ZEND_OP2_LITERAL(next_op)); + } else { /* ZEND_ADD_CHAR */ + *ptr = (char)ZEND_OP2_LITERAL(next_op).value.lval; + ptr++; + } + MAKE_NOP(next_op); + next_op++; + } + if (!((ZEND_OPTIMIZER_PASS_5|ZEND_OPTIMIZER_PASS_10) & OPTIMIZATION_LEVEL)) { + /* NOP removel is disabled => insert JMP over NOPs */ + if (last_op-opline >= 3) { /* If we have more than 2 NOPS then JMP over them */ + (opline+1)->opcode = ZEND_JMP; + ZEND_OP1(opline+1).opline_num = last_op - op_array->opcodes; /* that's OK even for ZE2, since opline_num's are resolved in pass 2 later */ + } + } + } + break; + + case ZEND_FETCH_CONSTANT: + if (ZEND_OP1_TYPE(opline) == IS_UNUSED && + ZEND_OP2_TYPE(opline) == IS_CONST && + Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING && + Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("__COMPILER_HALT_OFFSET__")-1 && + memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1) == 0) { + /* substitute __COMPILER_HALT_OFFSET__ constant */ + zend_bool orig_in_execution = EG(in_execution); + zend_op_array *orig_op_array = EG(active_op_array); + zval offset; + + 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)) { + 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_add_literal(op_array, &offset TSRMLS_CC); +#else + ZEND_OP1_LITERAL(opline) = offset; +#endif + SET_UNUSED(opline->op2); + opline->opcode = ZEND_QM_ASSIGN; + } + EG(active_op_array) = orig_op_array; + EG(in_execution) = orig_in_execution; + break; + } + + if (ZEND_OP1_TYPE(opline) == IS_UNUSED && + ZEND_OP2_TYPE(opline) == IS_CONST && + ZEND_OP2_LITERAL(opline).type == IS_STRING) { + /* substitute persistent constants */ + zval c; + + if(zend_get_persistent_constant(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), &c, 1 TSRMLS_CC) == 0) { + 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_add_literal(op_array, &c TSRMLS_CC); +#else + ZEND_OP1_LITERAL(opline) = c; +#endif + SET_UNUSED(opline->op2); + opline->opcode = ZEND_QM_ASSIGN; + } + break; + + case ZEND_INIT_FCALL_BY_NAME: + if(opline->extended_value == 0 /* not method */ && + ZEND_OP1_TYPE(opline) == IS_UNUSED && + ZEND_OP2_TYPE(opline) == IS_CONST) { + if((opline+1)->opcode == ZEND_DO_FCALL_BY_NAME && + (opline+1)->extended_value == 0) { + (opline+1)->opcode = ZEND_DO_FCALL; + COPY_NODE((opline+1)->op1, opline->op2); + zend_str_tolower(Z_STRVAL(ZEND_OP1_LITERAL(opline+1)), Z_STRLEN(ZEND_OP1_LITERAL(opline+1))); +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + Z_HASH_P(&ZEND_OP1_LITERAL(opline+1)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline+1)), Z_STRLEN(ZEND_OP1_LITERAL(opline+1))+1); + op_array->literals[(opline+1)->op1.constant].cache_slot = op_array->last_cache_slot++; +#endif + MAKE_NOP(opline); + } + } + break; + } + opline++; + i++; + } +} diff --git a/Optimizer/pass2.c b/Optimizer/pass2.c new file mode 100644 index 00000000000..ef6c5ac0c3e --- /dev/null +++ b/Optimizer/pass2.c @@ -0,0 +1,210 @@ +/* pass 2: + * - convert non-numeric constants to numeric constants in numeric operators + * - optimize constant conditional JMPs + * - optimize static BRKs and CONTs + */ + +if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) { + zend_op *opline; + zend_op *end = op_array->opcodes+op_array->last; + + opline = op_array->opcodes; + while (oplineopcode) { + case ZEND_ADD: + case ZEND_SUB: + case ZEND_MUL: + case ZEND_DIV: + if (ZEND_OP1_TYPE(opline) == IS_CONST) { + if (ZEND_OP1_LITERAL(opline).type == IS_STRING) { + convert_scalar_to_number(&ZEND_OP1_LITERAL(opline) TSRMLS_CC); + } + } + /* break missing *intentionally* - the assign_op's may only optimize op2 */ + case ZEND_ASSIGN_ADD: + case ZEND_ASSIGN_SUB: + case ZEND_ASSIGN_MUL: + case ZEND_ASSIGN_DIV: + if(opline->extended_value != 0) { + /* object tristate op - don't attempt to optimize it! */ + break; + } + if (ZEND_OP2_TYPE(opline) == IS_CONST) { + if (ZEND_OP2_LITERAL(opline).type == IS_STRING) { + convert_scalar_to_number(&ZEND_OP2_LITERAL(opline) TSRMLS_CC); + } + } + break; + + case ZEND_MOD: + case ZEND_SL: + case ZEND_SR: + if (ZEND_OP1_TYPE(opline) == IS_CONST) { + if (ZEND_OP1_LITERAL(opline).type != IS_LONG) { + convert_to_long(&ZEND_OP1_LITERAL(opline)); + } + } + /* break missing *intentionally - the assign_op's may only optimize op2 */ + case ZEND_ASSIGN_MOD: + case ZEND_ASSIGN_SL: + case ZEND_ASSIGN_SR: + if(opline->extended_value != 0) { + /* object tristate op - don't attempt to optimize it! */ + break; + } + if (ZEND_OP2_TYPE(opline) == IS_CONST) { + if (ZEND_OP2_LITERAL(opline).type != IS_LONG) { + convert_to_long(&ZEND_OP2_LITERAL(opline)); + } + } + break; + + case ZEND_CONCAT: + if (ZEND_OP1_TYPE(opline) == IS_CONST) { + if (ZEND_OP1_LITERAL(opline).type != IS_STRING) { + convert_to_string(&ZEND_OP1_LITERAL(opline)); + } + } + /* break missing *intentionally - the assign_op's may only optimize op2 */ + case ZEND_ASSIGN_CONCAT: + if(opline->extended_value != 0) { + /* object tristate op - don't attempt to optimize it! */ + break; + } + if (ZEND_OP2_TYPE(opline) == IS_CONST) { + if (ZEND_OP2_LITERAL(opline).type != IS_STRING) { + convert_to_string(&ZEND_OP2_LITERAL(opline)); + } + } + break; + + case ZEND_JMPZ_EX: + case ZEND_JMPNZ_EX: + /* convert Ti = JMPZ_EX(Ti, L) to JMPZ(Ti, L) */ + if (ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + ZEND_RESULT_TYPE(opline) == IS_TMP_VAR && + ZEND_OP1(opline).var == ZEND_RESULT(opline).var) { + opline->opcode -= 3; + /* convert Ti = JMPZ_EX(C, L) => Ti = QM_ASSIGN(C) + in case we know it wouldn't jump */ + } else if (ZEND_OP1_TYPE(opline) == IS_CONST) { + int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(opline)); + if (opline->opcode == ZEND_JMPZ_EX) { + should_jmp = !should_jmp; + } + if (!should_jmp) { + opline->opcode = ZEND_QM_ASSIGN; + SET_UNUSED(opline->op2); + } + } + break; + + case ZEND_JMPZ: + case ZEND_JMPNZ: + if (ZEND_OP1_TYPE(opline) == IS_CONST) { + int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(opline)); + + if (opline->opcode == ZEND_JMPZ) { + should_jmp = !should_jmp; + } + literal_dtor(&ZEND_OP1_LITERAL(opline)); + ZEND_OP1_TYPE(opline) = IS_UNUSED; + if (should_jmp) { + opline->opcode = ZEND_JMP; + COPY_NODE(opline->op1, opline->op2); + } else { + MAKE_NOP(opline); + } + break; + } + if ((opline+1)->opcode == ZEND_JMP) { + /* JMPZ(X, L1), JMP(L2) => JMPZNZ(X, L1, L2) */ + /* JMPNZ(X, L1), JMP(L2) => JMPZNZ(X, L2, L1) */ + if (ZEND_OP2(opline).opline_num == ZEND_OP1(opline+1).opline_num) { + /* JMPZ(X, L1), JMP(L1) => NOP, JMP(L1) */ + MAKE_NOP(opline); + } else { + if (opline->opcode == ZEND_JMPZ) { + opline->extended_value = ZEND_OP1(opline+1).opline_num; + } else { + opline->extended_value = ZEND_OP2(opline).opline_num; + COPY_NODE(opline->op2, (opline+1)->op1); + } + opline->opcode = ZEND_JMPZNZ; + } + } + break; + + case ZEND_JMPZNZ: + if (ZEND_OP1_TYPE(opline) == IS_CONST) { + int opline_num; + + if (zend_is_true(&ZEND_OP1_LITERAL(opline))) { + opline_num = opline->extended_value; /* JMPNZ */ + } else { + opline_num = ZEND_OP2(opline).opline_num; /* JMPZ */ + } + literal_dtor(&ZEND_OP1_LITERAL(opline)); + ZEND_OP1(opline).opline_num = opline_num; + ZEND_OP1_TYPE(opline) = IS_UNUSED; + opline->opcode = ZEND_JMP; + } + break; + + case ZEND_BRK: + case ZEND_CONT: + { + zend_brk_cont_element *jmp_to; + int array_offset; + int nest_levels; + int dont_optimize=0; + + if (ZEND_OP2_TYPE(opline) != IS_CONST) { + break; + } + convert_to_long(&ZEND_OP2_LITERAL(opline)); + nest_levels = ZEND_OP2_LITERAL(opline).value.lval; + + array_offset = ZEND_OP1(opline).opline_num; + while (1) { + if (array_offset==-1) { + dont_optimize=1; /* don't optimize this bogus break/continue, let the executor shout */ + break; + } + jmp_to = &op_array->brk_cont_array[array_offset]; + array_offset = jmp_to->parent; + if (--nest_levels > 0) { + if (opline->opcode == ZEND_BRK && + (op_array->opcodes[jmp_to->brk].opcode == ZEND_FREE || + op_array->opcodes[jmp_to->brk].opcode == ZEND_SWITCH_FREE)) { + dont_optimize=1; + break; + } + } else { + break; + } + } + + if (dont_optimize) { + break; + } + + /* optimize - convert to a JMP */ + switch (opline->opcode) { + case ZEND_BRK: + MAKE_NOP(opline); + ZEND_OP1(opline).opline_num = jmp_to->brk; + break; + case ZEND_CONT: + MAKE_NOP(opline); + ZEND_OP1(opline).opline_num = jmp_to->cont; + break; + } + opline->opcode = ZEND_JMP; + /* MAKE_NOP() already set op1 and op2 to IS_UNUSED */ + } + break; + } + opline++; + } +} diff --git a/Optimizer/pass3.c b/Optimizer/pass3.c new file mode 100644 index 00000000000..95a6aad9bff --- /dev/null +++ b/Optimizer/pass3.c @@ -0,0 +1,443 @@ +/* pass 3: + * - optimize $i = $i+expr to $i+=expr + * - optimize series of JMPs + * - change $i++ to ++$i where possible + */ + +/* compares opcodes with allowing oc1 be _EX of oc2 */ +#define SAME_OPCODE_EX(oc1, oc2) ((oc1 == oc2) || (oc1 == ZEND_JMPZ_EX && oc2 == ZEND_JMPZ) || (oc1 == ZEND_JMPNZ_EX && oc2 == ZEND_JMPNZ)) + +/* we use "jmp_hitlist" to avoid infinity loops during jmp optimization */ +#define CHECK_JMP(target, label) \ + for (i=0; iopcodes[target]).opline_num) { \ + goto label; \ + } \ + } \ + jmp_hitlist[jmp_hitlist_count++] = ZEND_OP1(&op_array->opcodes[target]).opline_num; + +#define CHECK_JMP2(target, label) \ + for (i=0; iopcodes[target]).opline_num) { \ + goto label; \ + } \ + } \ + jmp_hitlist[jmp_hitlist_count++] = ZEND_OP2(&op_array->opcodes[target]).opline_num; + +if(ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) { + zend_op *opline; + zend_op *end = op_array->opcodes+op_array->last; + zend_uint *jmp_hitlist; + int jmp_hitlist_count; + int i; + zend_uint opline_num = 0; + ALLOCA_FLAG(use_heap); + + jmp_hitlist = (zend_uint *) DO_ALLOCA(sizeof(zend_uint)*op_array->last); + opline = op_array->opcodes; + + while (oplineopcode) { + case ZEND_ADD: + case ZEND_SUB: + case ZEND_MUL: + case ZEND_DIV: + case ZEND_MOD: + case ZEND_CONCAT: + case ZEND_SL: + case ZEND_SR: + case ZEND_BW_OR: + case ZEND_BW_AND: + case ZEND_BW_XOR: + { + zend_op *next_opline = opline+1; + + while (next_opline < end && next_opline->opcode == ZEND_NOP) { + ++next_opline; + } + + if (next_opline >= end || next_opline->opcode != ZEND_ASSIGN) { + break; + } + + if ((ZEND_OP2_TYPE(opline)==IS_VAR || ZEND_OP2_TYPE(opline)==IS_CV) + && ZEND_OP2(opline).var == ZEND_OP1(next_opline).var && + (opline->opcode == ZEND_ADD || + opline->opcode == ZEND_MUL || + opline->opcode == ZEND_BW_OR || + opline->opcode == ZEND_BW_AND || + opline->opcode == ZEND_BW_XOR)) { + /* change $i=expr+$i to $i=$i+expr so that the next + * optimization works on it + */ +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + zend_uchar tmp_type=opline->op1_type; + znode_op tmp=opline->op1; +#else + znode tmp=opline->op1; +#endif + + if(opline->opcode != ZEND_ADD || ZEND_OP1_TYPE(opline) == IS_CONST) { + /* protection from array add: $a = array + $a is not commutative! */ + COPY_NODE(opline->op1, opline->op2); + COPY_NODE(opline->op2, tmp); + } + } + if ((ZEND_OP1_TYPE(opline)==IS_VAR || ZEND_OP1_TYPE(opline)==IS_CV) + && ZEND_OP1(opline).var == ZEND_OP1(next_opline).var + && ZEND_OP1_TYPE(opline) == ZEND_OP1_TYPE(next_opline)) { + switch (opline->opcode) { + case ZEND_ADD: + opline->opcode = ZEND_ASSIGN_ADD; + break; + case ZEND_SUB: + opline->opcode = ZEND_ASSIGN_SUB; + break; + case ZEND_MUL: + opline->opcode = ZEND_ASSIGN_MUL; + break; + case ZEND_DIV: + opline->opcode = ZEND_ASSIGN_DIV; + break; + case ZEND_MOD: + opline->opcode = ZEND_ASSIGN_MOD; + break; + case ZEND_CONCAT: + opline->opcode = ZEND_ASSIGN_CONCAT; + break; + case ZEND_SL: + opline->opcode = ZEND_ASSIGN_SL; + break; + case ZEND_SR: + opline->opcode = ZEND_ASSIGN_SR; + break; + case ZEND_BW_OR: + opline->opcode = ZEND_ASSIGN_BW_OR; + break; + case ZEND_BW_AND: + opline->opcode = ZEND_ASSIGN_BW_AND; + break; + case ZEND_BW_XOR: + opline->opcode = ZEND_ASSIGN_BW_XOR; + break; + } + COPY_NODE(opline->result, next_opline->result); + MAKE_NOP(next_opline); + opline++; + opline_num++; + } + } + break; + + case ZEND_JMP: +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + if (op_array->has_finally_block) { + break; + } +#endif + + /* convert L: JMP L+1 to NOP */ + if(ZEND_OP1(opline).opline_num == opline_num + 1) { + MAKE_NOP(opline); + goto done_jmp_optimization; + } + + /* convert JMP L1 ... L1: JMP L2 to JMP L2 .. L1: JMP L2 */ + while (ZEND_OP1(opline).opline_numlast + && op_array->opcodes[ZEND_OP1(opline).opline_num].opcode == ZEND_JMP) { + int target = ZEND_OP1(opline).opline_num; + CHECK_JMP(target, done_jmp_optimization); + ZEND_OP1(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num; + } + break; + +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + case ZEND_JMP_SET: +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + case ZEND_JMP_SET_VAR: +#endif + +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + if (op_array->has_finally_block) { + break; + } +#endif + + while (ZEND_OP2(opline).opline_numlast) { + int target = ZEND_OP2(opline).opline_num; + if (op_array->opcodes[target].opcode == ZEND_JMP) { + ZEND_OP2(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num; + } else { + break; + } + } + break; +#endif + + case ZEND_JMPZ: + case ZEND_JMPNZ: +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + if (op_array->has_finally_block) { + break; + } +#endif + + /* convert L: JMPZ L+1 to NOP */ + if(ZEND_OP2(opline).opline_num == opline_num + 1) { + MAKE_NOP(opline); + goto done_jmp_optimization; + } + + while (ZEND_OP2(opline).opline_numlast) { + int target = ZEND_OP2(opline).opline_num; + + if (op_array->opcodes[target].opcode == ZEND_JMP) { + /* plain JMP */ + /* JMPZ(X,L1), L1: JMP(L2) => JMPZ(X,L2), L1: JMP(L2) */ + CHECK_JMP(target, done_jmp_optimization); + ZEND_OP2(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num; + } else if (op_array->opcodes[target].opcode == opline->opcode && + SAME_VAR(opline->op1, op_array->opcodes[target].op1)) { + /* same opcode and same var as this opcode */ + /* JMPZ(X,L1), L1: JMPZ(X,L2) => JMPZ(X,L2), L1: JMPZ(X,L2) */ + CHECK_JMP2(target, done_jmp_optimization); + ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num; + } else if (op_array->opcodes[target].opcode == opline->opcode+3 && + SAME_VAR(opline->op1, op_array->opcodes[target].op1)) { + /* convert JMPZ(X,L1), L1: T JMPZ_EX(X,L2) to + T = JMPZ_EX(X, L2) */ + ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num;opline->opcode += 3; + COPY_NODE(opline->result, op_array->opcodes[target].result); + break; + } else if (op_array->opcodes[target].opcode == INV_COND(opline->opcode) && + SAME_VAR(opline->op1, op_array->opcodes[target].op1)) { + /* convert JMPZ(X,L1), L1: JMPNZ(X,L2) to + JMPZ(X,L1+1) */ + ZEND_OP2(opline).opline_num = target+1; + break; + } else if (op_array->opcodes[target].opcode == INV_COND_EX(opline->opcode) && + SAME_VAR(opline->op1, op_array->opcodes[target].op1)) { + /* convert JMPZ(X,L1), L1: T = JMPNZ_EX(X,L2) to + T = JMPZ_EX(X,L1+1) */ + ZEND_OP2(opline).opline_num = target+1; + opline->opcode += 3; + COPY_NODE(opline->result, op_array->opcodes[target].result); + break; + } else { + break; + } + } + break; + + case ZEND_JMPZ_EX: + case ZEND_JMPNZ_EX: { +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + zend_uchar T_type = opline->result_type; + znode_op T = opline->result; +#else + znode T = opline->result; +#endif +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + if (op_array->has_finally_block) { + break; + } +#endif + /* convert L: T = JMPZ_EX X,L+1 to T = BOOL(X) */ + /* convert L: T = JMPZ_EX T,L+1 to NOP */ + if(ZEND_OP2(opline).opline_num == opline_num + 1) { + if(ZEND_OP1(opline).var == ZEND_RESULT(opline).var) { + MAKE_NOP(opline); + } else { + opline->opcode = ZEND_BOOL; + SET_UNUSED(opline->op2); + } + goto done_jmp_optimization; + } + + while (ZEND_OP2(opline).opline_numlast) { + int target = ZEND_OP2(opline).opline_num; + if(SAME_OPCODE_EX(opline->opcode, op_array->opcodes[target].opcode) && + SAME_VAR(op_array->opcodes[target].op1, T)) { + /* Check for JMPZ_EX to JMPZ[_EX] with the same condition, either with _EX or not */ + if(op_array->opcodes[target].opcode == opline->opcode) { + /* change T only if we have _EX opcode there */ + COPY_NODE(T, op_array->opcodes[target].result); + } + CHECK_JMP2(target, continue_jmp_ex_optimization); + ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num; + } else if(op_array->opcodes[target].opcode == ZEND_JMPZNZ && + SAME_VAR(op_array->opcodes[target].op1, T)) { + /* Check for JMPZNZ with same cond variable */ + int new_target; + CHECK_JMP2(target, continue_jmp_ex_optimization); + if(opline->opcode == ZEND_JMPZ_EX) { + new_target = ZEND_OP2(&op_array->opcodes[target]).opline_num; + } else { + /* JMPNZ_EX */ + new_target = op_array->opcodes[target].extended_value; + } + ZEND_OP2(opline).opline_num = new_target; + } else if((op_array->opcodes[target].opcode == INV_EX_COND_EX(opline->opcode) || + op_array->opcodes[target].opcode == INV_EX_COND(opline->opcode) + ) && + SAME_VAR(opline->op1, op_array->opcodes[target].op1)) { + /* convert JMPZ_EX(X,L1), L1: JMPNZ_EX(X,L2) to + JMPZ_EX(X,L1+1) */ + ZEND_OP2(opline).opline_num = target+1; + break; + } else { + break; + } + } /* while */ +continue_jmp_ex_optimization: + break; +#if 0 + /* If Ti = JMPZ_EX(X, L) and Ti is not used, convert to JMPZ(X, L) */ + { + zend_op *op; + for(op = opline+1; opopcode == ZEND_JMP || + op->opcode == ZEND_JMPZ || + op->opcode == ZEND_JMPZ_EX || + op->opcode == ZEND_JMPNZ || + op->opcode == ZEND_JMPNZ_EX || + op->opcode == ZEND_JMPZNZ || + op->opcode == ZEND_BRK || + op->opcode == ZEND_CONT || + op->opcode == ZEND_CASE || + op->opcode == ZEND_RETURN || +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + op->opcode == ZEND_RETURN_BY_REF || +#endif +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + op->opcode == ZEND_FAST_RET || +#endif + op->opcode == ZEND_FE_FETCH || + op->opcode == ZEND_EXIT) { + break; + } + + if(ZEND_OP1_TYPE(op) == IS_TMP_VAR && + ZEND_OP1(op).var == ZEND_RESULT(opline).var) { + goto done_jmp_optimization; + } + + if(ZEND_OP2_TYPE(op) == IS_TMP_VAR && + ZEND_OP2(op).var == ZEND_RESULT(opline).var) { + goto done_jmp_optimization; + } + } /* for */ + + for(op = &op_array->opcodes[ZEND_OP2(opline).opline_num]; opopcode == ZEND_JMP || + op->opcode == ZEND_JMPZ || + op->opcode == ZEND_JMPZ_EX || + op->opcode == ZEND_JMPNZ || + op->opcode == ZEND_JMPNZ_EX || + op->opcode == ZEND_JMPZNZ || + op->opcode == ZEND_BRK || + op->opcode == ZEND_CONT || + op->opcode == ZEND_CASE || + op->opcode == ZEND_RETURN || +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + op->opcode == ZEND_RETURN_BY_REF || +#endif +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + op->opcode == ZEND_FAST_RET || +#endif + op->opcode == ZEND_FE_FETCH || + op->opcode == ZEND_EXIT) { + break; + } + + if(ZEND_OP1_TYPE(op) == IS_TMP_VAR && + ZEND_OP1(op).var == ZEND_RESULT(opline).var) { + goto done_jmp_optimization; + } + + if(ZEND_OP2_TYPE(op) == IS_TMP_VAR && + ZEND_OP2(op).var == ZEND_RESULT(opline).var) { + goto done_jmp_optimization; + } + } + + opline->opcode = opline->opcode-3; /* JMP_EX -> JMP */ + SET_UNUSED(opline->result); + break; + } +#endif + } + break; + + case ZEND_JMPZNZ: +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + if (op_array->has_finally_block) { + break; + } +#endif + /* JMPZNZ(X,L1,L2), L1: JMP(L3) => JMPZNZ(X,L3,L2), L1: JMP(L3) */ + while (ZEND_OP2(opline).opline_num < op_array->last + && op_array->opcodes[ZEND_OP2(opline).opline_num].opcode == ZEND_JMP) { + int target = ZEND_OP2(opline).opline_num; + CHECK_JMP(target, continue_jmpznz_optimization); + ZEND_OP2(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num; + } +continue_jmpznz_optimization: + /* JMPZNZ(X,L1,L2), L2: JMP(L3) => JMPZNZ(X,L1,L3), L2: JMP(L3) */ + while (opline->extended_value < op_array->last + && op_array->opcodes[opline->extended_value].opcode == ZEND_JMP) { + int target = opline->extended_value; + CHECK_JMP(target, done_jmp_optimization); + opline->extended_value = ZEND_OP1(&op_array->opcodes[target]).opline_num; + } + break; + + case ZEND_POST_INC: + case ZEND_POST_DEC: { + /* POST_INC, FREE => PRE_INC */ + zend_op *next_op = opline+1; + + if (next_op>=end) { + break; + } + if (next_op->opcode == ZEND_FREE + && ZEND_OP1(next_op).var == ZEND_RESULT(opline).var) { + MAKE_NOP(next_op); + switch (opline->opcode) { + case ZEND_POST_INC: + opline->opcode = ZEND_PRE_INC; + break; + case ZEND_POST_DEC: + opline->opcode = ZEND_PRE_DEC; + break; + } +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + ZEND_RESULT_TYPE(opline) = IS_VAR | EXT_TYPE_UNUSED; +#else + ZEND_RESULT_TYPE(opline) = IS_VAR; + ZEND_RESULT(opline).EA.type = 0; + ZEND_RESULT(opline).EA.type |= EXT_TYPE_UNUSED; +#endif + } + } + break; + } +done_jmp_optimization: + opline++; + opline_num++; + } + FREE_ALLOCA(jmp_hitlist); +} diff --git a/Optimizer/pass5.c b/Optimizer/pass5.c new file mode 100644 index 00000000000..b0d651a5fcf --- /dev/null +++ b/Optimizer/pass5.c @@ -0,0 +1,3 @@ +if (ZEND_OPTIMIZER_PASS_5 & OPTIMIZATION_LEVEL) { + zend_block_optimization(op_array TSRMLS_CC); +} diff --git a/Optimizer/pass9.c b/Optimizer/pass9.c new file mode 100644 index 00000000000..586160c14d1 --- /dev/null +++ b/Optimizer/pass9.c @@ -0,0 +1,8 @@ +/* pass 9 + * + * - optimize usage of temporary variables + */ + +if (ZEND_OPTIMIZER_PASS_9 & OPTIMIZATION_LEVEL) { + optimize_temporary_variables(op_array); +} diff --git a/Optimizer/zend_optimizer.c b/Optimizer/zend_optimizer.c new file mode 100644 index 00000000000..b2b0c8878c7 --- /dev/null +++ b/Optimizer/zend_optimizer.c @@ -0,0 +1,139 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#include "Optimizer/zend_optimizer.h" +#include "Optimizer/zend_optimizer_internal.h" +#include "zend_API.h" +#include "zend_constants.h" +#include "zend_execute.h" + +#define OPTIMIZATION_LEVEL \ + ZCG(accel_directives).optimization_level + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO +int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) +{ + int i = op_array->last_literal; + op_array->last_literal++; +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + { + if (i >= CG(context).literals_size) { + CG(context).literals_size += 16; /* FIXME */ + op_array->literals = (zend_literal*)erealloc(op_array->literals, CG(context).literals_size * sizeof(zend_literal)); + } + } +#else + if (i >= op_array->size_literal) { + op_array->size_literal += 16; /* FIXME */ + op_array->literals = (zend_literal*)erealloc(op_array->literals, op_array->size_literal * sizeof(zend_literal)); + } +#endif + op_array->literals[i].constant = *zv; + Z_SET_REFCOUNT(op_array->literals[i].constant, 2); + Z_SET_ISREF(op_array->literals[i].constant); + return i; +} + +# define LITERAL_LONG(op, val) do { \ + zval _c; \ + ZVAL_LONG(&_c, val); \ + op.constant = zend_add_literal(op_array, &_c TSRMLS_CC); \ + } while (0) + +# define LITERAL_BOOL(op, val) do { \ + zval _c; \ + ZVAL_BOOL(&_c, val); \ + op.constant = zend_add_literal(op_array, &_c TSRMLS_CC); \ + } while (0) + +# define literal_dtor(zv) do { \ + zval_dtor(zv); \ + Z_TYPE_P(zv) = IS_NULL; \ + } while (0) + +#define COPY_NODE(target, src) do { \ + target ## _type = src ## _type; \ + target = src; \ + } while (0) + +#else + +# define LITERAL_LONG(op, val) ZVAL_LONG(&op.u.constant, val) + +# define LITERAL_BOOL(op, val) ZVAL_BOOL(&op.u.constant, val) + +# define literal_dtor(zv) zval_dtor(zv) + +#define COPY_NODE(target, src) do { \ + target = src; \ + } while (0) + +#endif + +#include "Optimizer/nop_removal.c" +#include "Optimizer/block_pass.c" +#include "Optimizer/optimize_temp_vars_5.c" + +void zend_optimizer(zend_op_array *op_array TSRMLS_DC) +{ + if (op_array->type == ZEND_EVAL_CODE || + (op_array->fn_flags & ZEND_ACC_INTERACTIVE)) { + return; + } + + /* pass 1 + * - substitute persistent constants (true, false, null, etc) + * - perform compile-time evaluation of constant binary and unary operations + * - optimize series of ADD_STRING and/or ADD_CHAR + * - convert CAST(IS_BOOL,x) into BOOL(x) + * - convert INTI_FCALL_BY_NAME + DO_FCALL_BY_NAME into DO_FCALL + */ +#include "Optimizer/pass1_5.c" + + /* pass 2: + * - convert non-numeric constants to numeric constants in numeric operators + * - optimize constant conditional JMPs + * - optimize static BRKs and CONTs + */ +#include "Optimizer/pass2.c" + + /* pass 3: + * - optimize $i = $i+expr to $i+=expr + * - optimize series of JMPs + * - change $i++ to ++$i where possible + */ +#include "Optimizer/pass3.c" + + /* pass 5: + * - CFG optimization + */ +#include "Optimizer/pass5.c" + + /* pass 9: + * - Optimize temp variables usage + */ +#include "Optimizer/pass9.c" + + /* pass 10: + * - remove NOPs + */ +#include "Optimizer/pass10.c" +} diff --git a/Optimizer/zend_optimizer.h b/Optimizer/zend_optimizer.h new file mode 100644 index 00000000000..0c069168740 --- /dev/null +++ b/Optimizer/zend_optimizer.h @@ -0,0 +1,49 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_OPTIMIZER_H +#define ZEND_OPTIMIZER_H + +#include "zend.h" +#include "zend_compile.h" + +#define ZEND_OPTIMIZER_PASS_1 (1<<0) /* CSE, STRING construction */ +#define ZEND_OPTIMIZER_PASS_2 (1<<1) /* Constant conversion and jums */ +#define ZEND_OPTIMIZER_PASS_3 (1<<2) /* ++, +=, series of jumps */ +#define ZEND_OPTIMIZER_PASS_4 (1<<3) +#define ZEND_OPTIMIZER_PASS_5 (1<<4) /* CFG based optimization */ +#define ZEND_OPTIMIZER_PASS_6 (1<<5) +#define ZEND_OPTIMIZER_PASS_7 (1<<6) +#define ZEND_OPTIMIZER_PASS_8 (1<<7) +#define ZEND_OPTIMIZER_PASS_9 (1<<8) /* TMP VAR usage */ +#define ZEND_OPTIMIZER_PASS_10 (1<<9) /* NOP removal */ +#define ZEND_OPTIMIZER_PASS_11 (1<<10) +#define ZEND_OPTIMIZER_PASS_12 (1<<11) +#define ZEND_OPTIMIZER_PASS_13 (1<<12) +#define ZEND_OPTIMIZER_PASS_14 (1<<13) + +#define ZEND_OPTIMIZER_ALL_PASSES 0xFFFFFFFF + +#define DEFAULT_OPTIMIZATION_LEVEL "0xFFFFFFFF" + +void zend_optimizer(zend_op_array *op_array TSRMLS_DC); + +#endif diff --git a/Optimizer/zend_optimizer_internal.h b/Optimizer/zend_optimizer_internal.h new file mode 100644 index 00000000000..113cbe98267 --- /dev/null +++ b/Optimizer/zend_optimizer_internal.h @@ -0,0 +1,76 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_OPTIMIZER_INTERNAL_H +#define ZEND_OPTIMIZER_INTERNAL_H + +#include "ZendAccelerator.h" + +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO +# define VAR_NUM(v) (EX_TMP_VAR_NUM(0, 0) - EX_TMP_VAR(0, v)) +# define NUM_VAR(v) ((zend_uint)EX_TMP_VAR_NUM(0, v)) +#else +# define VAR_NUM(v) ((v)/(sizeof(temp_variable))) +# define NUM_VAR(v) ((v)*(sizeof(temp_variable))) +#endif + +#define INV_COND(op) ((op) == ZEND_JMPZ ? ZEND_JMPNZ : ZEND_JMPZ) +#define INV_EX_COND(op) ((op) == ZEND_JMPZ_EX ? ZEND_JMPNZ : ZEND_JMPZ) +#define INV_COND_EX(op) ((op) == ZEND_JMPZ ? ZEND_JMPNZ_EX : ZEND_JMPZ_EX) +#define INV_EX_COND_EX(op) ((op) == ZEND_JMPZ_EX ? ZEND_JMPNZ_EX : ZEND_JMPZ_EX) + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO +# define MAKE_NOP(opline) { opline->opcode = ZEND_NOP; memset(&opline->result,0,sizeof(opline->result)); memset(&opline->op1,0,sizeof(opline->op1)); memset(&opline->op2,0,sizeof(opline->op2)); opline->result_type=opline->op1_type=opline->op2_type=IS_UNUSED; opline->handler = zend_opcode_handlers[ZEND_NOP]; } +# define RESULT_USED(op) (((op->result_type & IS_VAR) && !(op->result_type & EXT_TYPE_UNUSED)) || op->result_type == IS_TMP_VAR) +# define RESULT_UNUSED(op) ((op->result_type & EXT_TYPE_UNUSED) != 0) +# define SAME_VAR(op1, op2) ((((op1 ## _type & IS_VAR) && (op2 ## _type & IS_VAR)) || (op1 ## _type == IS_TMP_VAR && op2 ## _type == IS_TMP_VAR)) && op1.var == op2.var) +#else +# define MAKE_NOP(opline) { opline->opcode = ZEND_NOP; memset(&opline->result,0,sizeof(znode)); memset(&opline->op1,0,sizeof(znode)); memset(&opline->op2,0,sizeof(znode)); opline->result.op_type=opline->op1.op_type=opline->op2.op_type=IS_UNUSED; opline->handler = zend_opcode_handlers[ZEND_NOP]; } +# define RESULT_USED(op) ((op->result.op_type == IS_VAR && (op->result.u.EA.type & EXT_TYPE_UNUSED) == 0) || (op->result.op_type == IS_TMP_VAR)) +# define RESULT_UNUSED(op) ((op->result.op_type == IS_VAR) && (op->result.u.EA.type == EXT_TYPE_UNUSED)) +# define SAME_VAR(op1, op2) (((op1.op_type == IS_VAR && op2.op_type == IS_VAR) || (op1.op_type == IS_TMP_VAR && op2.op_type == IS_TMP_VAR)) && op1.u.var == op2.u.var) +#endif + +typedef struct _zend_code_block zend_code_block; +typedef struct _zend_block_source zend_block_source; + +struct _zend_code_block { + int access; + zend_op *start_opline; + int start_opline_no; + int len; + zend_code_block *op1_to; + zend_code_block *op2_to; + zend_code_block *ext_to; + zend_code_block *follow_to; + zend_code_block *next; + zend_block_source *sources; + zend_code_block **try; + zend_code_block **catch; + zend_bool is_try; +}; + +struct _zend_block_source { + zend_code_block *from; + zend_block_source *next; +}; + +#endif diff --git a/README b/README new file mode 100644 index 00000000000..69273d0624c --- /dev/null +++ b/README @@ -0,0 +1,171 @@ +The Zend Optimizer+ +=================== + +The Zend Optimizer+ provides faster PHP execution through opcode caching and +optimization. It improves PHP performance by storing precompiled script +bytecode in the shared memory. This eliminates the stages of reading code from +the disk and compiling it on future access. In addition it applies a few +bytecode optimization patterns that make code execution faster. + +Compatibility +------------- + +This version of Zend Optimizer+ is compatible with PHP 5.2.*, 5.3.*, 5.4.* +and PHP-5.5 development branch. PHP 5.2 support may be removed in the future. + +Quick Install +------------- + +- Compile + +export PHP_DIR=/usr/local/php5.5 +PHP_AUTOCONF=autoconf $PHP_DIR/bin/phpize +./configure \ + --enable-optimizer-plus \ + --with-php-config=$PHP_DIR/bin/php-config +make + +- Install + +cp .libs/ZendOptimizerPlus.so $PHP_DIR/lib/ZendOptimizerPlus.so + +- Edit php.ini + +zend_extensin=/...full path.../ZendOptimizerPlus.so + +- Restart PHP + +Speed Tunning +------------- + +We reccomend the following configuration options for best performance. + +zend_optimizerplus.memory_consumption=128 +zend_optimizerplus.interned_strings_buffer=8 +zend_optimizerplus.max_accelerated_files=4000 +zend_optimizerplus.revalidate_freq=60 +zend_optimizerplus.save_comments=0 +zend_optimizerplus.fast_shutdown=1 +zend_optimizerplus.enable_file_override=1 +zend_optimizerplus.enable_cli=1 + +In some cases you may like to prefer enabling/disabling some features +to avoid incompatibilities at the cost of some performance degradation. + +Configuration Directives +------------------------ + +zend_optimizerplus.enable (default "1") + Optimizer+ On/Off switch. When set to Off, code is not optimized. + +zend_optimizerplus.memory_consumption (default "64") + The Optimizer+ shared memory storage size. The amount of memory for storing + precompiled PHP code in Mbytes. + +zend_optimizerplus.interned_strings_buffer (default "4") + The amount of memory for interned strings in Mbytes. + +zend_optimizerplus.max_accelerated_files (default "2000") + The maximum number of keys (scripts) in the Optimizer+ hash table. + The number is actually the the first one in the following set of prime + numbers that is bigger than the one supplied: { 223, 463, 983, 1979, 3907, + 7963, 16229, 32531, 65407, 130987 }. Only numbers between 200 and 100000 + are allowed. + +zend_optimizerplus.max_wasted_percentage (default "5") + The maximum percentage of "wasted" memory until a restart is scheduled + +zend_optimizerplus.use_cwd (default "1") + When this directive is enabled, the Optimizer+ appends the current working + directory to the script key, thus elminating possible collisions between + files with the same name (basename). Disablingthe directive improves + performance, but may break existing applications. + +zend_optimizerplus.validate_timestamps (default "1") + When disabled, you must reset the Optimizer+ manually or restart the + webserver for changes to the filesystem to take effect. + The frequancy of the check is controlled by the directive + "zend_optimizerplus.revalidate_freq" + +zend_optimizerplus.revalidate_freq (default "2") + How often (in seconds) to check file timestamps for changes to the shared + memory storage allocation. + +zend_optimizerplus.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 + the same include_path, the file is not searched again. Thus, if a file + with the same name appears somewhere else in include_path, it + won't be found. Enable this directive if this optimization has an effect on + your applications. The default for this directive is disabled, which means + that optimization is active. + +zend_optimizerplus.save_comments (default "1") + If disabled, all PHPDoc comments are dropped from the code to reduce the + size of the optimized code. + +zend_optimizerplus.fast_shutdown (default "0") + If enabled, a fast shutdown sequence is used for the accelerated code + The fast shutdown sequence doesn't free each allocated block, but lets + the Zend Engine Memory Manager do the work. + +zend_optimizerplus.enable_file_override (default "0") + Allow file existance override (file_exists, etc.) performance feature + +zend_optimizerplus.optimization_level (default "0xffffffff") + A bitmask, where each bit enables or disables the appropriate Optimizer+ + passes + +zend_optimizerplus.inherited_hack (default "1") + Enable this hack as a workaround for "can't redeclare class" errors. + The Optimizer+ stores the places where DECLARE_CLASS opcodes use + inheritance (These are the only opcodes that can be executed by PHP, + but which may not be executed because the parent class is missing due to + optimization). When the file is loaded, Optimizer+ tries to bind the + inherited classes by using the current environment. The problem with this + scenario is that, while the DECLARE_CLASS opcode may not be needed for the + current script, if the script requires that the opcode at least be defined, + it may not run. The default for this directive is disabled, which means + that optimization is active. In php-5.3 and above this hack is not needed + anymore and this setting has no effect. + +zend_optimizerplus.dups_fix (default "0") + Enable this hack as a workaround for "duplicate definition" errors + +zend_optimizerplus.blacklist_filename + The location of the Optimizer+ blacklist file + The Optimizer+ blacklist file is a text file that holds the names of files + that should not be accelerated. The file format is to add each filename + to a new line. The filename may be a full path or just a file prefix + (i.e., /var/www/x blacklists all the files and directories in /var/www + that start with 'x'). Files are usually triggered by one of the following + three reasons: + 1) Directories that contain auto generated code, like Smarty or ZFW cache. + 2) Code that does not work well when accelerated, due to some delayed + compile time evaluation. + 3) Code that triggers an Optimizer+ bug. + +zend_optimizerplus.consistency_checks (default "0") + Check the cache checksum each N requests. + The default value of "0" means that the checks are disabled. + Because calculating the checksum impairs performance, this directive should + be enabled only as part of a debugging process. + +zend_optimizerplus.force_restart_timeout (default "180") + How long to wait (in seconds) for a scheduled restart to begin if the cache + is not being accessed. + The Optimizer+ uses this directive to identify a situation where there may + be a problem with a process. After this time period has passed, the + Optimizer+ assumes that something has happened and starts killing the + processes that still hold the locks that are preventing a restart. + If the log level is 3 or above, a "killed locker" error is recorded + in the Apache logs when this happens. + +zend_optimizerplus.error_log + Optimizer+ error_log file name. Empty string assumes "stderr" + +zend_optimizerplus.log_verbosity_level (default "1") + Alll Optimizer+ errors go to the Web server log. + By default, only fatal errors (level 0) or errors (level 1) are logged. + You can also enable warnings (level 2), info messages (level 3) or + debug messesges (level 4). diff --git a/ZendAccelerator.c b/ZendAccelerator.c new file mode 100644 index 00000000000..8b2a6ae48e7 --- /dev/null +++ b/ZendAccelerator.c @@ -0,0 +1,2510 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#include "main/php.h" +#include "main/php_globals.h" +#include "zend.h" +#include "zend_extensions.h" +#include "zend_compile.h" +#include "ZendAccelerator.h" +#include "zend_persist.h" +#include "zend_shared_alloc.h" +#include "zend_accelerator_module.h" +#include "zend_accelerator_blacklist.h" +#include "zend_list.h" +#include "zend_execute.h" +#include "main/SAPI.h" +#include "main/php_streams.h" +#include "main/php_open_temporary_file.h" +#include "zend_API.h" +#include "zend_ini.h" +#include "TSRM/tsrm_virtual_cwd.h" +#include "zend_accelerator_util_funcs.h" +#include "zend_accelerator_hash.h" + +#ifndef ZEND_WIN32 +#include +#endif + +#ifdef ZEND_WIN32 +typedef int uid_t; +typedef int gid_t; +#include +#endif + +#ifndef ZEND_WIN32 +# include +#else +# include +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include + +#ifndef ZEND_WIN32 +# include +# include +#endif + +#include +#include + +#define MIN_FREE_MEMORY 64*1024 + +#define SHM_PROTECT() \ + do { \ + if (ZCG(accel_directives).protect_memory) { \ + zend_accel_shared_protect(1 TSRMLS_CC); \ + } \ + } while (0) +#define SHM_UNPROTECT() \ + do { \ + if (ZCG(accel_directives).protect_memory) { \ + zend_accel_shared_protect(0 TSRMLS_CC); \ + } \ + } while (0) + +ZEND_EXTENSION(); + +#ifndef ZTS +zend_accel_globals accel_globals; +#else +int accel_globals_id; +#endif + +/* Points to the structure shared across all PHP processes */ +zend_accel_shared_globals *accel_shared_globals = NULL; + +/* true globals, no need for thread safety */ +static char *zps_failure_reason = NULL; +char *zps_api_failure_reason = NULL; + +static zend_op_array *(*accelerator_orig_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC); +static int (*accelerator_orig_zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC); +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO +static char *(*accelerator_orig_zend_resolve_path)(const char *filename, int filename_len TSRMLS_DC); +#endif +static void (*orig_chdir)(INTERNAL_FUNCTION_PARAMETERS) = NULL; +static ZEND_INI_MH((*orig_include_path_on_modify)) = NULL; + +#ifdef ZEND_WIN32 +# define INCREMENT(v) InterlockedIncrement(&ZCSG(v)) +# define DECREMENT(v) InterlockedDecrement(&ZCSG(v)) +# define LOCKVAL(v) (ZCSG(v)) +#endif + +#ifdef ZEND_WIN32 +static time_t zend_accel_get_time(void) +{ + FILETIME now; + GetSystemTimeAsFileTime(&now); + + return (time_t) ((((((__int64)now.dwHighDateTime) << 32)|now.dwLowDateTime) - 116444736000000000L)/10000000); +} +#else +# define zend_accel_get_time() time(NULL) +#endif + +static inline int is_stream_path(const char *filename) +{ + const char *p; + + for (p = filename; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++); + return ((*p == ':') && (p - filename > 1) && (p[1] == '/') && (p[2] == '/')); +} + +/* O+ overrides PHP chdir() function and remembers the current working directory + * in ZCG(cwd) and ZCG(cwd_len). Later accel_getcwd() can use stored value and + * avoid getcwd() call. + */ +static ZEND_FUNCTION(accel_chdir) +{ + char cwd[MAXPATHLEN]; + + orig_chdir(INTERNAL_FUNCTION_PARAM_PASSTHRU); + if (VCWD_GETCWD(cwd, MAXPATHLEN)) { + ZCG(cwd_len) = strlen(cwd); + ZCG(cwd) = estrndup(cwd, ZCG(cwd_len)); + } else { + if (ZCG(cwd)) { + efree(ZCG(cwd)); + ZCG(cwd) = NULL; + } + } +} + +static inline char* accel_getcwd(int *cwd_len TSRMLS_DC) +{ + if (ZCG(cwd)) { + *cwd_len = ZCG(cwd_len); + return ZCG(cwd); + } else { + char cwd[MAXPATHLEN + 1]; + + if (!VCWD_GETCWD(cwd, MAXPATHLEN)) { + return NULL; + } + *cwd_len = ZCG(cwd_len) = strlen(cwd); + ZCG(cwd) = estrndup(cwd, ZCG(cwd_len)); + return ZCG(cwd); + } +} + +/* O+ traks changes of "include_path" directive. It stores all the requested + * values in ZCG(include_paths) shared hash table, current value in + * ZCG(include_path)/ZCG(include_path_len) and one letter "path key" in + * ZCG(include_path_key). + */ +static ZEND_INI_MH(accel_include_path_on_modify) +{ + int ret = orig_include_path_on_modify(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); + + ZCG(include_path_key) = NULL; + if (ret == SUCCESS) { + ZCG(include_path) = new_value; + if (ZCG(include_path) && *ZCG(include_path)) { + ZCG(include_path_len) = new_value_length; + + if (ZCG(startup_ok) && + (ZCG(counted) || ZCSG(accelerator_enabled)) && + !zend_accel_hash_is_full(&ZCSG(include_paths))) { + + SHM_UNPROTECT(); + zend_shared_alloc_lock(TSRMLS_C); + + ZCG(include_path_key) = zend_accel_hash_find(&ZCSG(include_paths), ZCG(include_path), ZCG(include_path_len) + 1); + if (!ZCG(include_path_key) && + !zend_accel_hash_is_full(&ZCSG(include_paths))) { + char *key; + + key = zend_shared_alloc(ZCG(include_path_len) + 2); + if (key) { + memcpy(key, ZCG(include_path), ZCG(include_path_len) + 1); + key[ZCG(include_path_len) + 1] = 'A' + ZCSG(include_paths).num_entries; + ZCG(include_path_key) = key + ZCG(include_path_len) + 1; + zend_accel_hash_update(&ZCSG(include_paths), key, ZCG(include_path_len) + 1, 0, ZCG(include_path_key)); + } + } + + zend_shared_alloc_unlock(TSRMLS_C); + SHM_PROTECT(); + } else { + ZCG(include_path_check) = 1; + } + } else { + ZCG(include_path) = ""; + ZCG(include_path_len) = 0; + } + } + return ret; +} + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO +/* Interned strings support */ +static char *orig_interned_strings_start; +static char *orig_interned_strings_end; +static const char *(*orig_new_interned_string)(const char *str, int len, int free_src TSRMLS_DC); +static void (*orig_interned_strings_snapshot)(TSRMLS_D); +static void (*orig_interned_strings_restore)(TSRMLS_D); + +/* O+ disables creation of interned strings by regular PHP compiler, instead, + * it creates interned strings in shared memory when saves a script. + * Such interned strings are shatred across all PHP processes + */ +static const char *accel_new_interned_string_for_php(const char *str, int len, int free_src TSRMLS_DC) +{ + return str; +} + +static void accel_interned_strings_snapshot_for_php(TSRMLS_D) +{ +} + +static void accel_interned_strings_restore_for_php(TSRMLS_D) +{ +} + +#ifndef ZTS +static void accel_interned_strings_restore_state(TSRMLS_D) +{ + unsigned int i; + + for (i = 0; i < ZCSG(interned_strings).nTableSize; i++) { + ZCSG(interned_strings).arBuckets[i] = ZCSG(interned_strings_saved_state).arBuckets[i]; + if (ZCSG(interned_strings).arBuckets[i]) { + ZCSG(interned_strings).arBuckets[i]->pLast = NULL; + } + } + ZCSG(interned_strings).pListHead = ZCSG(interned_strings_saved_state).pListHead; + ZCSG(interned_strings).pListTail = ZCSG(interned_strings_saved_state).pListTail; + if (ZCSG(interned_strings).pListHead) { + ZCSG(interned_strings).pListHead->pListLast = NULL; + } + if (ZCSG(interned_strings).pListTail) { + ZCSG(interned_strings).pListTail->pListNext = NULL; + } + ZCSG(interned_strings_top) = ZCSG(interned_strings_saved_state).top; +} + +static void accel_interned_strings_save_state(TSRMLS_D) +{ + ZCSG(interned_strings_saved_state).arBuckets = (Bucket**)zend_shared_alloc(ZCSG(interned_strings).nTableSize * sizeof(Bucket *)); + if (!ZCSG(interned_strings_saved_state).arBuckets) { + zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!"); + } + memcpy(ZCSG(interned_strings_saved_state).arBuckets, ZCSG(interned_strings).arBuckets, ZCSG(interned_strings).nTableSize * sizeof(Bucket *)); + ZCSG(interned_strings_saved_state).pListHead = ZCSG(interned_strings).pListHead; + ZCSG(interned_strings_saved_state).pListTail = ZCSG(interned_strings).pListTail; + ZCSG(interned_strings_saved_state).top = ZCSG(interned_strings_top); +} +#endif + +const char *accel_new_interned_string(const char *arKey, int nKeyLength, int free_src TSRMLS_DC) +{ +/* for now interned strings are supported only for non-ZTS build */ +#ifndef ZTS + ulong h; + uint nIndex; + Bucket *p; + + if (arKey >= ZCSG(interned_strings_start) && arKey < ZCSG(interned_strings_end)) { + /* this is already an interned string */ + return arKey; + } + + h = zend_inline_hash_func(arKey, nKeyLength); + nIndex = h & ZCSG(interned_strings).nTableMask; + + /* check for existing interned string */ + p = ZCSG(interned_strings).arBuckets[nIndex]; + while (p != NULL) { + if ((p->h == h) && (p->nKeyLength == (uint)nKeyLength)) { + if (!memcmp(p->arKey, arKey, nKeyLength)) { + if (free_src) { + efree((char*)arKey); + } + return p->arKey; + } + } + p = p->pNext; + } + + if (ZCSG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength) >= + ZCSG(interned_strings_end)) { + /* no memory, return the same non-interned string */ + return arKey; + } + + /* create new interning string in shared interned strings buffer */ + p = (Bucket *) ZCSG(interned_strings_top); + ZCSG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength); + + p->arKey = (char*)(p+1); + memcpy((char*)p->arKey, arKey, nKeyLength); + p->nKeyLength = nKeyLength; + p->h = h; + p->pData = &p->pDataPtr; + p->pDataPtr = p; + + p->pNext = ZCSG(interned_strings).arBuckets[nIndex]; + p->pLast = NULL; + if (p->pNext) { + p->pNext->pLast = p; + } + ZCSG(interned_strings).arBuckets[nIndex] = p; + + p->pListLast = ZCSG(interned_strings).pListTail; + ZCSG(interned_strings).pListTail = p; + p->pListNext = NULL; + if (p->pListLast != NULL) { + p->pListLast->pListNext = p; + } + if (!ZCSG(interned_strings).pListHead) { + ZCSG(interned_strings).pListHead = p; + } + + ZCSG(interned_strings).nNumOfElements++; + + if (free_src) { + efree((char*)arKey); + } + + return p->arKey; +#else + return arKey; +#endif +} + +#ifndef ZTS +/* Copy PHP interned strings from PHP process memory into the shared memory */ +static void accel_use_shm_interned_strings(TSRMLS_D) +{ + Bucket *p, *q; + + /* function table hash keys */ + p = CG(function_table)->pListHead; + while (p) { + if (p->nKeyLength) { + p->arKey = accel_new_interned_string(p->arKey, p->nKeyLength, 0 TSRMLS_CC); + } + p = p->pListNext; + } + + /* class table hash keys, class names, properties, methods, constants, etc */ + p = CG(class_table)->pListHead; + while (p) { + zend_class_entry *ce = (zend_class_entry*)(p->pDataPtr); + + if (p->nKeyLength) { + p->arKey = accel_new_interned_string(p->arKey, p->nKeyLength, 0 TSRMLS_CC); + } + + if (ce->name) { + ce->name = accel_new_interned_string(ce->name, ce->name_length+1, 0 TSRMLS_CC); + } + + q = ce->properties_info.pListHead; + while (q) { + zend_property_info *info = (zend_property_info*)(q->pData); + + if (q->nKeyLength) { + q->arKey = accel_new_interned_string(q->arKey, q->nKeyLength, 0 TSRMLS_CC); + } + + if (info->name) { + info->name = accel_new_interned_string(info->name, info->name_length+1, 0 TSRMLS_CC); + } + + q = q->pListNext; + } + + q = ce->function_table.pListHead; + while (q) { + if (q->nKeyLength) { + q->arKey = accel_new_interned_string(q->arKey, q->nKeyLength, 0 TSRMLS_CC); + } + q = q->pListNext; + } + + q = ce->constants_table.pListHead; + while (q) { + if (q->nKeyLength) { + q->arKey = accel_new_interned_string(q->arKey, q->nKeyLength, 0 TSRMLS_CC); + } + q = q->pListNext; + } + + p = p->pListNext; + } + + /* constant hash keys */ + p = EG(zend_constants)->pListHead; + while (p) { + if (p->nKeyLength) { + p->arKey = accel_new_interned_string(p->arKey, p->nKeyLength, 0 TSRMLS_CC); + } + p = p->pListNext; + } + + /* auto globals hash keys and names */ + p = CG(auto_globals)->pListHead; + while (p) { + zend_auto_global *auto_global = (zend_auto_global*)p->pData; + + auto_global->name = accel_new_interned_string(auto_global->name, auto_global->name_len + 1, 0 TSRMLS_CC); + if (p->nKeyLength) { + p->arKey = accel_new_interned_string(p->arKey, p->nKeyLength, 0 TSRMLS_CC); + } + p = p->pListNext; + } +} +#endif +#endif + +static inline void accel_restart_enter(TSRMLS_D) +{ +#ifdef ZEND_WIN32 + INCREMENT(restart_in); +#else + static const FLOCK_STRUCTURE(restart_in_progress, F_WRLCK, SEEK_SET, 2, 1); + + if (fcntl(lock_file, F_SETLK, &restart_in_progress)==-1) { + zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(+1): %s (%d)", strerror(errno), errno); + } +#endif + ZCSG(restart_in_progress) = 1; +} + +static inline void accel_restart_leave(TSRMLS_D) +{ + ZCSG(restart_in_progress) = 0; +#ifdef ZEND_WIN32 + DECREMENT(restart_in); +#else + static const FLOCK_STRUCTURE(restart_finished, F_UNLCK, SEEK_SET, 2, 1); + + if (fcntl(lock_file, F_SETLK, &restart_finished)==-1) { + zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(-1): %s (%d)", strerror(errno), errno); + } +#endif +} + +static inline int accel_restart_is_active(TSRMLS_D) +{ + if(ZCSG(restart_in_progress)) { +#ifndef ZEND_WIN32 + FLOCK_STRUCTURE(restart_check, F_WRLCK, SEEK_SET, 2, 1); + + if (fcntl(lock_file, F_GETLK, &restart_check) == -1) { + zend_accel_error(ACCEL_LOG_DEBUG, "RestartC: %s (%d)", strerror(errno), errno); + return FAILURE; + } + if (restart_check.l_type == F_UNLCK) { + ZCSG(restart_in_progress) = 0; + return 0; + } else { + return 1; + } +#else + return LOCKVAL(restart_in) != 0; +#endif + } + return 0; +} + +/* Creates a read lock for SHM access */ +static inline void accel_activate_add(TSRMLS_D) +{ +#ifdef ZEND_WIN32 + INCREMENT(mem_usage); +#else + static const FLOCK_STRUCTURE(mem_usage_lock, F_RDLCK, SEEK_SET, 1, 1); + + if (fcntl(lock_file, F_SETLK, &mem_usage_lock)==-1) { + zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(+1): %s (%d)", strerror(errno), errno); + } +#endif +} + +/* Releases a lock for SHM access */ +static inline void accel_deactivate_sub(TSRMLS_D) +{ +#ifdef ZEND_WIN32 + if (ZCG(counted)) { + DECREMENT(mem_usage); + ZCG(counted) = 0; + } +#else + static const FLOCK_STRUCTURE(mem_usage_unlock, F_UNLCK, SEEK_SET, 1, 1); + + if (fcntl(lock_file, F_SETLK, &mem_usage_unlock)==-1) { + zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(-1): %s (%d)", strerror(errno), errno); + } +#endif +} + +static inline void accel_unlock_all(TSRMLS_D) +{ +#ifdef ZEND_WIN32 + accel_deactivate_sub(TSRMLS_C); +#else + static const FLOCK_STRUCTURE(mem_usage_unlock_all, F_UNLCK, SEEK_SET, 0, 0); + + if (fcntl(lock_file, F_SETLK, &mem_usage_unlock_all)==-1) { + zend_accel_error(ACCEL_LOG_DEBUG, "UnlockAll: %s (%d)", strerror(errno), errno); + } +#endif +} + +#ifndef ZEND_WIN32 +static inline void kill_all_lockers(struct flock *mem_usage_check) +{ + int tries = 10; + + /* so that other process won't try to force while we are busy cleaning up */ + ZCSG(force_restart_time) = 0; + while (mem_usage_check->l_pid > 0) { + while (tries--) { + zend_accel_error(ACCEL_LOG_INFO, "Killed locker %d", mem_usage_check->l_pid); + if (kill(mem_usage_check->l_pid, SIGKILL)) { + break; + } + /* give it a chance to die */ + usleep(20000); + if (kill(mem_usage_check->l_pid, 0)) { + /* can't kill it */ + break; + } + usleep(10000); + } + if (!tries) { + zend_accel_error(ACCEL_LOG_INFO, "Can't kill %d after 20 tries!", mem_usage_check->l_pid); + ZCSG(force_restart_time) = time(NULL); /* restore forced restart request */ + } + + mem_usage_check->l_type = F_WRLCK; + mem_usage_check->l_whence = SEEK_SET; + mem_usage_check->l_start = 1; + mem_usage_check->l_len = 1; + mem_usage_check->l_pid = -1; + if (fcntl(lock_file, F_GETLK, mem_usage_check) == -1) { + zend_accel_error(ACCEL_LOG_DEBUG, "KLockers: %s (%d)", strerror(errno), errno); + break; + } + + if (mem_usage_check->l_type == F_UNLCK || mem_usage_check->l_pid <= 0) { + break; + } + } +} +#endif + +static inline int accel_is_inactive(TSRMLS_D) +{ +#ifdef ZEND_WIN32 + if (LOCKVAL(mem_usage) == 0) { + return SUCCESS; + } +#else + FLOCK_STRUCTURE(mem_usage_check, F_WRLCK, SEEK_SET, 1, 1); + + mem_usage_check.l_pid = -1; + if (fcntl(lock_file, F_GETLK, &mem_usage_check) == -1) { + zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC: %s (%d)", strerror(errno), errno); + return FAILURE; + } + if (mem_usage_check.l_type == F_UNLCK) { + return SUCCESS; + } + + if (ZCG(accel_directives).force_restart_timeout + && ZCSG(force_restart_time) + && time(NULL)>=ZCSG(force_restart_time)) { + zend_accel_error(ACCEL_LOG_WARNING, "Forced restart at %d (after %d seconds), locked by %d", time(NULL), ZCG(accel_directives).force_restart_timeout, mem_usage_check.l_pid); + kill_all_lockers(&mem_usage_check); + + return FAILURE; /* next request should be able to restart it */ + } +#endif + + return FAILURE; +} + +static int zend_get_stream_timestamp(const char *filename, struct stat *statbuf TSRMLS_DC) +{ + php_stream_wrapper *wrapper; + php_stream_statbuf stream_statbuf; + + if(!filename) { + return FAILURE; + } + + wrapper = php_stream_locate_url_wrapper(filename, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC); + if(!wrapper) { + + return FAILURE; + } + if(!wrapper->wops || !wrapper->wops->url_stat) { + + statbuf->st_mtime = 1; + return SUCCESS; /* anything other than 0 is considered to be a valid timestamp */ + } + + if(wrapper->wops->url_stat(wrapper, (char*)filename, PHP_STREAM_URL_STAT_QUIET, &stream_statbuf, NULL TSRMLS_CC) != 0) { + return FAILURE; + } + *statbuf = stream_statbuf.sb; + return SUCCESS; +} + +#if ZEND_WIN32 +static accel_time_t zend_get_file_handle_timestamp_win(zend_file_handle *file_handle) +{ + static unsigned __int64 utc_base = 0; + static FILETIME utc_base_ft; + WIN32_FILE_ATTRIBUTE_DATA fdata; + + if(!file_handle->opened_path) { + return 0; + } + + if (!utc_base) { + SYSTEMTIME st; + + st.wYear = 1970; + st.wMonth = 1; + st.wDay = 1; + st.wHour = 0; + st.wMinute = 0; + st.wSecond = 0; + st.wMilliseconds = 0; + + SystemTimeToFileTime (&st, &utc_base_ft); + utc_base = (((unsigned __int64)utc_base_ft.dwHighDateTime) << 32) + utc_base_ft.dwLowDateTime; + } + + if(GetFileAttributesEx(file_handle->opened_path, GetFileExInfoStandard, &fdata) != 0) { + unsigned __int64 ftime; + + if (CompareFileTime (&fdata.ftLastWriteTime, &utc_base_ft) < 0) + return 0; + + ftime = (((unsigned __int64)fdata.ftLastWriteTime.dwHighDateTime) << 32) + fdata.ftLastWriteTime.dwLowDateTime - utc_base; + ftime /= 10000000L; + + return (accel_time_t)ftime; + } + return 0; +} +#endif + +static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle TSRMLS_DC) +{ + struct stat statbuf; + +#ifdef ZEND_WIN32 + accel_time_t res; + + res = zend_get_file_handle_timestamp_win(file_handle); + if(res) { + return res; + } +#endif + + switch (file_handle->type) { + case ZEND_HANDLE_FD: + if (fstat(file_handle->handle.fd, &statbuf)==-1) { + return 0; + } + break; + case ZEND_HANDLE_FP: + if (fstat(fileno(file_handle->handle.fp), &statbuf) == -1) { + if (zend_get_stream_timestamp(file_handle->filename, &statbuf TSRMLS_CC) != SUCCESS) { + return 0; + } + } + break; + case ZEND_HANDLE_FILENAME: +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + case ZEND_HANDLE_MAPPED: +#endif + { + char *file_path = file_handle->opened_path; + + if(file_path) { + if (is_stream_path(file_path)) { + if (zend_get_stream_timestamp(file_path, &statbuf TSRMLS_CC) == SUCCESS) { + break; + } + } + if (VCWD_STAT(file_path, &statbuf) !=-1) { + break; + } + } + + if (zend_get_stream_timestamp(file_handle->filename, &statbuf TSRMLS_CC) != SUCCESS) { + return 0; + } + break; + } + case ZEND_HANDLE_STREAM: + { + php_stream *stream = (php_stream *)file_handle->handle.stream.handle; + php_stream_statbuf sb; + int er = EG(error_reporting); + + EG(error_reporting) = 0; + if (!stream || + !stream->ops || + !stream->ops->stat || + stream->ops->stat(stream, &sb TSRMLS_CC) != 0) { + EG(error_reporting) = er; + return 0; + } + EG(error_reporting) = er; + statbuf = sb.sb; + } + break; + + default: + return 0; + } + + return statbuf.st_mtime; +} + +static inline int do_validate_timestamps(zend_persistent_script *persistent_script, zend_file_handle *file_handle TSRMLS_DC) +{ + zend_file_handle ps_handle; + + /** check that the persistant script is indeed the same file we cached + * (if part of the path is a symlink than it possible that the user will change it) + * See bug #15140 + */ + if (file_handle->opened_path) { + if (strcmp(persistent_script->full_path,file_handle->opened_path)!=0) { + return FAILURE; + } + } else { + char actualpath [MAXPATHLEN+1]; + char *full_path_ptr; + + full_path_ptr = VCWD_REALPATH(file_handle->filename, actualpath); + if (full_path_ptr && strcmp(persistent_script->full_path,full_path_ptr)!=0) { + return FAILURE; + } + } + + if (persistent_script->timestamp == 0) { + return FAILURE; + } + + if (zend_get_file_handle_timestamp(file_handle TSRMLS_CC) == persistent_script->timestamp) { + return SUCCESS; + } + + ps_handle.type = ZEND_HANDLE_FILENAME; + ps_handle.filename = persistent_script->full_path; + ps_handle.opened_path = persistent_script->full_path; + + if (zend_get_file_handle_timestamp(&ps_handle TSRMLS_CC) == persistent_script->timestamp) { + return SUCCESS; + } + + return FAILURE; +} + +static void zend_accel_schedule_restart_if_necessary(TSRMLS_D) +{ + if ((((double) ZSMMG(wasted_shared_memory)) / ZCG(accel_directives).memory_consumption) >= ZCG(accel_directives).max_wasted_percentage) { + zend_accel_schedule_restart(TSRMLS_C); + } +} + +static inline int validate_timestamp_and_record(zend_persistent_script *persistent_script, zend_file_handle *file_handle TSRMLS_DC) +{ + if (persistent_script->dynamic_members.revalidate >= ZCSG(revalidate_at)) { + return SUCCESS; + } else if (do_validate_timestamps(persistent_script, file_handle TSRMLS_CC)==FAILURE) { + return FAILURE; + } else { + persistent_script->dynamic_members.revalidate = ZCSG(revalidate_at); + return SUCCESS; + } +} + +static unsigned int zend_accel_script_checksum(zend_persistent_script *persistent_script) +{ + signed char *mem = (signed char*)persistent_script->mem; + size_t size = persistent_script->size; + size_t persistent_script_check_block_size = ((char *)&(persistent_script->dynamic_members)) - (char *)persistent_script; + unsigned int checksum = ADLER32_INIT; + + if (mem < (signed char*)persistent_script) { + checksum = zend_adler32(checksum, mem, (signed char*)persistent_script - mem); + size -= (signed char*)persistent_script - mem; + mem += (signed char*)persistent_script - mem; + } + + zend_adler32(checksum, mem, persistent_script_check_block_size); + mem += sizeof(*persistent_script); + size -= sizeof(*persistent_script); + + if (size > 0) { + checksum = zend_adler32(checksum, mem, size); + } + return checksum; +} + +/* Instead of resolving full real path name each time we need to identify file, + * we create a key that consist from requested file name, current working + * directory, current include_path, etc */ +char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_length, int *key_len TSRMLS_DC) +{ + int key_length; + + /* CWD and include_path don't matter for absolute file names and streams */ + if (ZCG(accel_directives).use_cwd && + !IS_ABSOLUTE_PATH(file_handle->filename, path_length) && + !is_stream_path(file_handle->filename)) { + char *include_path=NULL; + int include_path_len=0; + const char *parent_script = NULL; + int parent_script_len=0; + int cur_len=0; + int cwd_len; + char *cwd; + + if ((cwd = accel_getcwd(&cwd_len TSRMLS_CC)) == NULL) { + /* we don't handle this well for now. */ + zend_accel_error(ACCEL_LOG_INFO, "getcwd() failed for '%s' (%d), please try to set zend_optimizerplus.use_cwd to 0 in ini file", file_handle->filename, errno); + if(file_handle->opened_path) { + cwd = file_handle->opened_path; + cwd_len = strlen(cwd); + } else { + ZCG(key_len) = 0; + return NULL; + } + } + + if (ZCG(include_path_key)) { + include_path = ZCG(include_path_key); + include_path_len = 1; + } else { + include_path = ZCG(include_path); + include_path_len = ZCG(include_path_len); + if (ZCG(include_path_check) && + ZCG(startup_ok) && + (ZCG(counted) || ZCSG(accelerator_enabled)) && + !zend_accel_hash_is_full(&ZCSG(include_paths))) { + + SHM_UNPROTECT(); + zend_shared_alloc_lock(TSRMLS_C); + + ZCG(include_path_key) = zend_accel_hash_find(&ZCSG(include_paths), ZCG(include_path), ZCG(include_path_len) + 1); + if (ZCG(include_path_key)) { + include_path = ZCG(include_path_key); + include_path_len = 1; + } else if (!zend_accel_hash_is_full(&ZCSG(include_paths))) { + char *key; + + key = zend_shared_alloc(ZCG(include_path_len) + 2); + if (key) { + memcpy(key, ZCG(include_path), ZCG(include_path_len) + 1); + key[ZCG(include_path_len) + 1] = 'A' + ZCSG(include_paths).num_entries; + ZCG(include_path_key) = key + ZCG(include_path_len) + 1; + zend_accel_hash_update(&ZCSG(include_paths), key, ZCG(include_path_len) + 1, 0, ZCG(include_path_key)); + include_path = ZCG(include_path_key); + include_path_len = 1; + } + } + + zend_shared_alloc_unlock(TSRMLS_C); + SHM_PROTECT(); + } + } + + /* Here we add to the key the parent script directory, + since fopen_wrappers from version 4.0.7 use current script's path + in include path too. + */ + if (EG(in_execution) && + (parent_script = zend_get_executed_filename(TSRMLS_C)) != NULL && + parent_script[0] != '[') { + + parent_script_len = strlen(parent_script); + while ((--parent_script_len > 0) && !IS_SLASH(parent_script[parent_script_len])); + } + + /* Calculate key length */ + key_length = cwd_len+path_length+include_path_len+2; + if (parent_script_len) { + key_length += parent_script_len+1; + } + + /* Generate key + * Note - the include_path must be the last element in the key, + * since in itself, it may include colons (which we use to separate + * different components of the key) + */ + if ((size_t)key_length >= sizeof(ZCG(key))) { + ZCG(key_len) = 0; + return NULL; + } + memcpy(ZCG(key), cwd, cwd_len); + ZCG(key)[cwd_len] = ':'; + + memcpy(ZCG(key)+cwd_len+1, file_handle->filename, path_length); + + ZCG(key)[cwd_len+1+path_length] = ':'; + + cur_len = cwd_len+1+path_length+1; + + if (parent_script_len) { + memcpy(ZCG(key)+cur_len, parent_script, parent_script_len); + cur_len += parent_script_len; + ZCG(key)[cur_len] = ':'; + cur_len++; + } + memcpy(ZCG(key)+cur_len, include_path, include_path_len); + ZCG(key)[key_length] = '\0'; + } else { + /* not use_cwd */ + key_length = path_length; + if ((size_t)key_length >= sizeof(ZCG(key))) { + ZCG(key_len) = 0; + return NULL; + } + memcpy(ZCG(key), file_handle->filename, key_length+1); + } + + *key_len = ZCG(key_len) = key_length; + return ZCG(key); +} + +static inline char *accel_make_persistent_key(zend_file_handle *file_handle, int *key_len TSRMLS_DC) +{ + return accel_make_persistent_key_ex(file_handle, strlen(file_handle->filename), key_len TSRMLS_CC); +} + +/* Adds another key for existing cached script */ +static void zend_accel_add_key(char *key, unsigned int key_length, zend_accel_hash_entry *bucket TSRMLS_DC) +{ + if (!zend_accel_hash_find(&ZCSG(hash), key, key_length+1)) { + if (zend_accel_hash_is_full(&ZCSG(hash))) { + zend_accel_error(ACCEL_LOG_DEBUG,"No more entries in hash table!"); + ZSMMG(memory_exhausted) = 1; + } else { + char *new_key = zend_shared_alloc(key_length+1); + if (new_key) { + memcpy(new_key, key, key_length+1); + zend_accel_hash_update(&ZCSG(hash), new_key, key_length+1, 1, bucket); + } else { + zend_accel_error(ACCEL_LOG_DEBUG,"No more memory!"); + ZSMMG(memory_exhausted) = 1; + } + } + } +} + +static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_script *new_persistent_script, char *key, unsigned int key_length, int *from_shared_memory TSRMLS_DC) +{ + zend_accel_hash_entry *bucket; + uint memory_used; + + /* Check if script may be stored in shared memory */ + if(!zend_accel_script_persistable(new_persistent_script)) { + return new_persistent_script; + } + + /* exclusive lock */ + zend_shared_alloc_lock(TSRMLS_C); + + if (zend_accel_hash_is_full(&ZCSG(hash))) { + zend_accel_error(ACCEL_LOG_DEBUG,"No more entries in hash table!"); + ZSMMG(memory_exhausted) = 1; + zend_accel_schedule_restart_if_necessary(TSRMLS_C); + zend_shared_alloc_unlock(TSRMLS_C); + return new_persistent_script; + } + + /* Check if we still need to put the file into the cache (may be it was + * already stored by another process. This final check is done under + * exclusive lock) */ + bucket = zend_accel_hash_find_entry(&ZCSG(hash), new_persistent_script->full_path, new_persistent_script->full_path_len+1); + if (bucket) { + zend_persistent_script *existing_persistent_script = (zend_persistent_script *)bucket->data; + + if (!existing_persistent_script->corrupted) { + if (!ZCG(accel_directives).validate_timestamps || + (new_persistent_script->timestamp == existing_persistent_script->timestamp)) { + zend_accel_add_key(key, key_length, bucket TSRMLS_CC); + } + zend_shared_alloc_unlock(TSRMLS_C); + return new_persistent_script; + } + } + + /* Calculate the required memory size */ + memory_used = zend_accel_script_persist_calc(new_persistent_script, key, key_length TSRMLS_CC); + + /* Allocate shared memory */ + ZCG(mem) = zend_shared_alloc(memory_used); + if (!ZCG(mem)) { + zend_accel_error(ACCEL_LOG_DEBUG, "No more memory!"); + zend_accel_schedule_restart_if_necessary(TSRMLS_C); + if (zend_shared_alloc_get_largest_free_block() < MIN_FREE_MEMORY) { + ZSMMG(memory_exhausted) = 1; + } + zend_shared_alloc_unlock(TSRMLS_C); + return new_persistent_script; + } + + /* cleanup after calculation */ + new_persistent_script->mem = ZCG(mem); + new_persistent_script->size = memory_used; + + /* Copy into shared memory */ + new_persistent_script = zend_accel_script_persist(new_persistent_script, &key, key_length TSRMLS_CC); + + /* Consistency check */ + if ((char*)new_persistent_script->mem + new_persistent_script->size != (char*)ZCG(mem)) { + zend_accel_error( + ((char*)new_persistent_script->mem + new_persistent_script->size < (char*)ZCG(mem)) ? ACCEL_LOG_ERROR : ACCEL_LOG_WARNING, + "Internal error: wrong size calculation: %s start=0x%08x, end=0x%08x, real=0x%08x\n", + new_persistent_script->full_path, + new_persistent_script->mem, + (char *)new_persistent_script->mem + new_persistent_script->size, + ZCG(mem)); + } + + new_persistent_script->dynamic_members.checksum = zend_accel_script_checksum(new_persistent_script); + + /* store script structure in the hash table */ + bucket = zend_accel_hash_update(&ZCSG(hash), new_persistent_script->full_path, new_persistent_script->full_path_len+1, 0, new_persistent_script); + if (bucket && + (new_persistent_script->full_path_len != key_length || + memcmp(new_persistent_script->full_path, key, key_length) != 0)) { + /* link key to the same persistent script in hash table */ + if (!zend_accel_hash_update(&ZCSG(hash), key, key_length+1, 1, bucket)) { + zend_accel_error(ACCEL_LOG_DEBUG,"No more entries in hash table!"); + ZSMMG(memory_exhausted) = 1; + } + } + + new_persistent_script->dynamic_members.memory_consumption = ZEND_ALIGNED_SIZE(new_persistent_script->size); + + zend_shared_alloc_unlock(TSRMLS_C); + + *from_shared_memory = 1; + return new_persistent_script; +} + +static const struct jit_auto_global_info +{ + const char *name; + size_t len; +} jit_auto_globals_info[] = { + { "_SERVER", sizeof("_SERVER")}, + { "_ENV", sizeof("_ENV")}, + { "_REQUEST", sizeof("_REQUEST")}, +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + { "GLOBALS", sizeof("GLOBALS")}, +#endif +}; + +static int zend_accel_get_auto_globals(TSRMLS_D) +{ + int i, ag_size = (sizeof(jit_auto_globals_info) / sizeof(jit_auto_globals_info[0])); + int n = 1; + zval **res; + int mask = 0; + + for (i = 0; i < ag_size ; i++) { + if (zend_hash_find(&EG(symbol_table), jit_auto_globals_info[i].name, jit_auto_globals_info[i].len, (void *)&res) == SUCCESS) { + mask |= n; + } + n += n; + } + return mask; +} + +static void zend_accel_set_auto_globals(int mask TSRMLS_DC) +{ + int i, ag_size = (sizeof(jit_auto_globals_info) / sizeof(jit_auto_globals_info[0])); + int n = 1; + + for (i = 0; i < ag_size ; i++) { + if (mask & n) { + zend_is_auto_global(jit_auto_globals_info[i].name, jit_auto_globals_info[i].len - 1 TSRMLS_CC); + } + n += n; + } +} + +static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_handle, int type, char *key, unsigned int key_length, zend_op_array **op_array_p, int *from_shared_memory TSRMLS_DC) +{ + zend_persistent_script *new_persistent_script; + zend_op_array *orig_active_op_array; + HashTable *orig_function_table, *orig_class_table; + zval *orig_user_error_handler; + zend_op_array *op_array; + int do_bailout = 0; +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + zend_uint orig_compiler_options = 0; +#endif + + /* Try to open file */ + if (file_handle->type == ZEND_HANDLE_FILENAME) { + if (accelerator_orig_zend_stream_open_function(file_handle->filename, file_handle TSRMLS_CC) == SUCCESS) { + /* key may be changed by zend_stream_open_function() */ + if (key == ZCG(key)) { + key_length = ZCG(key_len); + } + } else { + *op_array_p = NULL; + if (type==ZEND_REQUIRE) { + zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC); + zend_bailout(); + } else { + zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC); + } + return NULL; + } + } + + /* check blacklist right after ensuring that file was opened */ + if (file_handle->opened_path && zend_accel_blacklist_is_blacklisted(&accel_blacklist, file_handle->opened_path)) { + ZCSG(blacklist_misses)++; + *op_array_p = accelerator_orig_compile_file(file_handle, type TSRMLS_CC); + return NULL; + } + + new_persistent_script = create_persistent_script(); + + /* Save the original values for the op_array, function table and class table */ + orig_active_op_array = CG(active_op_array); + orig_function_table = CG(function_table); + orig_class_table = CG(class_table); + orig_user_error_handler = EG(user_error_handler); + + /* Override them with ours */ + CG(function_table) = &ZCG(function_table); + EG(class_table) = CG(class_table) = &new_persistent_script->class_table; + EG(user_error_handler) = NULL; + + zend_try { +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + orig_compiler_options = CG(compiler_options); + CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY; + CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES; + CG(compiler_options) |= ZEND_COMPILE_DELAYED_BINDING; + CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION; +#endif + op_array = *op_array_p = accelerator_orig_compile_file(file_handle, type TSRMLS_CC); +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + CG(compiler_options) = orig_compiler_options; +#endif + } zend_catch { + op_array = NULL; + do_bailout = 1; +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + CG(compiler_options) = orig_compiler_options; +#endif + } zend_end_try(); + + /* Restore originals */ + CG(active_op_array) = orig_active_op_array; + CG(function_table) = orig_function_table; + EG(class_table) = CG(class_table) = orig_class_table; + EG(user_error_handler) = orig_user_error_handler; + + if (!op_array) { + /* compilation failed */ + free_persistent_script(new_persistent_script, 1); + zend_accel_free_user_functions(&ZCG(function_table) TSRMLS_CC); + if(do_bailout) { + zend_bailout(); + } + return NULL; + } + + /* Build the persistent_script structure. + Here we aren't sure we would store it, but we will need it + further anyway. + */ + zend_accel_move_user_functions(&ZCG(function_table), &new_persistent_script->function_table TSRMLS_CC); + new_persistent_script->main_op_array = *op_array; + + efree(op_array); /* we have valid persistent_script, so it's safe to free op_array */ + + /* Fill in the ping_auto_globals_mask for the new script. If jit for auto globals is enabled we + will have to ping the used auto global varaibles before execution */ +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (PG(auto_globals_jit)) { +#else + if ((PG(auto_globals_jit) && !PG(register_globals) && !PG(register_long_arrays))) { +#endif + new_persistent_script->ping_auto_globals_mask = zend_accel_get_auto_globals(TSRMLS_C); + } + + if (ZCG(accel_directives).validate_timestamps) { + /* Obtain the file timestamps, *before* actually compiling them, + * otherwise we have a race-condition. + */ + new_persistent_script->timestamp = zend_get_file_handle_timestamp(file_handle TSRMLS_CC); + + /* If we can't obtain a timestamp (that means file is possibly socket) + * we return it but do not persist it + */ + if (new_persistent_script->timestamp == 0) { + return new_persistent_script; + } + new_persistent_script->dynamic_members.revalidate = ZCSG(revalidate_at); + } + + if (file_handle->opened_path) { + new_persistent_script->full_path_len = strlen(file_handle->opened_path); + new_persistent_script->full_path = estrndup(file_handle->opened_path, new_persistent_script->full_path_len); + } else { + new_persistent_script->full_path_len = strlen(file_handle->filename); + new_persistent_script->full_path = estrndup(file_handle->filename, new_persistent_script->full_path_len); + } + new_persistent_script->hash_value = zend_hash_func(new_persistent_script->full_path, new_persistent_script->full_path_len + 1); + + /* Now persistent_script structure is ready in process memory */ + return cache_script_in_shared_memory(new_persistent_script, key, key_length, from_shared_memory TSRMLS_CC); +} + +/* zend_compile() replacement */ +static zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) +{ + zend_persistent_script *persistent_script = NULL; + char *key = NULL; + int key_length; + int from_shared_memory; /* if the script we've got is stored in SHM */ + + if (!file_handle->filename || + !ZCG(startup_ok) || + (!ZCG(counted) && !ZCSG(accelerator_enabled)) || + CG(interactive) || + (ZCSG(restart_in_progress) && accel_restart_is_active(TSRMLS_C))) { + /* The Accelerator is disabled, act as if without the Accelerator */ + return accelerator_orig_compile_file(file_handle, type TSRMLS_CC); + } + + /* Make sure we only increase the currently running processes semaphore + * once each execution (this function can be called more than once on + * each execution) + */ + if (!ZCG(counted)) { + ZCG(counted) = 1; + accel_activate_add(TSRMLS_C); + } + + /* In case this callback is called from include_once, require_once or it's + * a main FastCGI request, the key must be already calculated, and cached + * persistent script already found */ + if ((EG(opline_ptr) == NULL && + ZCG(cache_opline) == NULL && + file_handle->filename == SG(request_info).path_translated && + ZCG(cache_persistent_script)) || + (EG(opline_ptr) && *EG(opline_ptr) && + *EG(opline_ptr) == ZCG(cache_opline) && + (*EG(opline_ptr))->opcode == ZEND_INCLUDE_OR_EVAL && +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + ((*EG(opline_ptr))->extended_value == ZEND_INCLUDE_ONCE || + (*EG(opline_ptr))->extended_value == ZEND_REQUIRE_ONCE))) { +#else + ((*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_INCLUDE_ONCE || + (*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_REQUIRE_ONCE))) { +#endif + if (!ZCG(key_len)) { + return accelerator_orig_compile_file(file_handle, type TSRMLS_CC); + } + /* persistent script was already found by overrifen open() or + * resolve_path() callbacks */ + persistent_script = ZCG(cache_persistent_script); + key = ZCG(key); + key_length = ZCG(key_len); + } else { + /* try to find cached script by key */ + if ((key = accel_make_persistent_key(file_handle, &key_length TSRMLS_CC)) == NULL) { + return accelerator_orig_compile_file(file_handle, type TSRMLS_CC); + } + persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length+1); + if (!persistent_script) { + /* try to find cached script by full real path */ + zend_accel_hash_entry *bucket; + + /* open file to resolve the path */ + if (file_handle->type == ZEND_HANDLE_FILENAME && +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + accelerator_orig_zend_stream_open_function(file_handle->filename, file_handle TSRMLS_CC) == FAILURE) { +#else + zend_stream_open(file_handle->filename, file_handle TSRMLS_CC) == FAILURE) { +#endif + if (type==ZEND_REQUIRE) { + zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC); + zend_bailout(); + } else { + zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC); + } + return NULL; + } + + if (file_handle->opened_path && + (bucket = zend_accel_hash_find_entry(&ZCSG(hash), file_handle->opened_path, strlen(file_handle->opened_path)+1)) != NULL) { + + persistent_script = (zend_persistent_script *)bucket->data; + if (!ZCG(accel_directives).revalidate_path && + !persistent_script->corrupted) { + SHM_UNPROTECT(); + zend_shared_alloc_lock(TSRMLS_C); + zend_accel_add_key(key, key_length, bucket TSRMLS_CC); + zend_shared_alloc_unlock(TSRMLS_C); + SHM_PROTECT(); + } + } + } + } + + /* clear cache */ + ZCG(cache_opline) = NULL; + ZCG(cache_persistent_script) = NULL; + + if (persistent_script && persistent_script->corrupted) { + persistent_script = NULL; + } + + SHM_UNPROTECT(); + + /* If script is found then validate_timestamps if option is enabled */ + if (persistent_script && ZCG(accel_directives).validate_timestamps) { + if (validate_timestamp_and_record(persistent_script, file_handle TSRMLS_CC)==FAILURE) { + zend_shared_alloc_lock(TSRMLS_C); + if (!persistent_script->corrupted) { + persistent_script->corrupted = 1; + persistent_script->timestamp = 0; + ZSMMG(wasted_shared_memory) += persistent_script->dynamic_members.memory_consumption; + } + zend_shared_alloc_unlock(TSRMLS_C); + persistent_script = NULL; + } + } + + /* if turned on - check the compiled script ADLER32 checksum */ + if (persistent_script && ZCG(accel_directives).consistency_checks + && persistent_script->dynamic_members.hits % ZCG(accel_directives).consistency_checks == 0) { + + unsigned int checksum = zend_accel_script_checksum(persistent_script); + if (checksum != persistent_script->dynamic_members.checksum ) { + /* The checksum is wrong */ + zend_accel_error(ACCEL_LOG_INFO, "Checksum failed for '%s': expected=0x%0.8X, found=0x%0.8X", + persistent_script->full_path, persistent_script->dynamic_members.checksum, checksum); + zend_shared_alloc_lock(TSRMLS_C); + if (!persistent_script->corrupted) { + persistent_script->corrupted = 1; + persistent_script->timestamp = 0; + ZSMMG(wasted_shared_memory) += persistent_script->dynamic_members.memory_consumption; + } + zend_shared_alloc_unlock(TSRMLS_C); + persistent_script = NULL; + } + } + + /* If script was not found or invalidated by validate_timestamps */ + if (!persistent_script) { + zend_op_array *op_array; + + /* Cache miss.. */ + ZCSG(misses)++; + + /* No memory left. Behave like without the Accelerator */ + if (ZSMMG(memory_exhausted)) { + SHM_PROTECT(); + return accelerator_orig_compile_file(file_handle, type TSRMLS_CC); + } + + /* Try and cache the script and assume that it is returned from_shared_memory. + * If it isn't compile_and_cache_file() changes the flag to 0 + */ + from_shared_memory = 0; + persistent_script = compile_and_cache_file(file_handle, type, key, key_length, &op_array, &from_shared_memory TSRMLS_CC); + + /* Something went wrong during compilation, returning NULL */ + if (!persistent_script) { + SHM_PROTECT(); + return op_array; /* Presently always NULL, but not necessary in the future */ + } + } else { + +#if !ZEND_WIN32 + ZCSG(hits)++; /* TBFixed: may lose one hit */ + persistent_script->dynamic_members.hits++; /* see above */ +#else + InterlockedIncrement(&ZCSG(hits)); + InterlockedIncrement(&persistent_script->dynamic_members.hits); +#endif + + /* see bug #15471 (old BTS) */ + if (persistent_script->full_path) { + if (!EG(opline_ptr) || !*EG(opline_ptr) || + (*EG(opline_ptr))->opcode != ZEND_INCLUDE_OR_EVAL || +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + ((*EG(opline_ptr))->extended_value != ZEND_INCLUDE_ONCE && + (*EG(opline_ptr))->extended_value != ZEND_REQUIRE_ONCE)) { +#else + ((*EG(opline_ptr))->op2.u.constant.value.lval != ZEND_INCLUDE_ONCE && + (*EG(opline_ptr))->op2.u.constant.value.lval != ZEND_REQUIRE_ONCE)) { +#endif + void *dummy = (void *) 1; + + zend_hash_quick_add(&EG(included_files), persistent_script->full_path, persistent_script->full_path_len+1, persistent_script->hash_value, &dummy, sizeof(void *), NULL); + } + } + zend_file_handle_dtor(file_handle TSRMLS_CC); + from_shared_memory = 1; + } + + persistent_script->dynamic_members.last_used = ZCG(request_time); + + SHM_PROTECT(); + + /* Fetch jit auto globals used in the script before execution */ + if (persistent_script->ping_auto_globals_mask) { + zend_accel_set_auto_globals(persistent_script->ping_auto_globals_mask TSRMLS_CC); + } + + return zend_accel_load_script(persistent_script, from_shared_memory TSRMLS_CC); +} + +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + +/* Taken from php-5.2.5 because early versions don't have correct version */ +static char *accel_tsrm_realpath(const char *path, int path_len TSRMLS_DC) +{ + cwd_state new_state; + char *real_path; + char *cwd; + int cwd_len; + + /* realpath("") returns CWD */ + if (!*path) { + new_state.cwd = (char*)malloc(1); + new_state.cwd[0] = '\0'; + new_state.cwd_length = 0; + if ((cwd = accel_getcwd(&cwd_len TSRMLS_CC)) != NULL) { + path = cwd; + } + } else if (!IS_ABSOLUTE_PATH(path, path_len) && + (cwd = accel_getcwd(&cwd_len TSRMLS_CC)) != NULL) { + new_state.cwd = zend_strndup(cwd, cwd_len); + new_state.cwd_length = cwd_len; + } else { + new_state.cwd = (char*)malloc(1); + new_state.cwd[0] = '\0'; + new_state.cwd_length = 0; + } + +#ifndef CWD_REALPATH +# define CWD_REALPATH 2 +#endif + if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) { + free(new_state.cwd); + return NULL; + } + + real_path = emalloc(new_state.cwd_length+1); + memcpy(real_path, new_state.cwd, new_state.cwd_length+1); + free(new_state.cwd); + return real_path; +} + +static char *accel_php_resolve_path(const char *filename, int filename_length, const char *path TSRMLS_DC) +{ + char *resolved_path; + char trypath[MAXPATHLEN]; + const char *ptr, *end; + int len; + + if (!filename) { + return NULL; + } + + if (*filename == '.' || + IS_ABSOLUTE_PATH(filename, filename_length) || + !path || + !*path) { + return accel_tsrm_realpath(filename, filename_length TSRMLS_CC); + } + + ptr = path; + while (*ptr) { + for (end = ptr; *end && *end != DEFAULT_DIR_SEPARATOR; end++); + len = end-ptr; + if (*end) end++; + if (len + 1 + filename_length + 1 >= MAXPATHLEN) { + ptr = end; + continue; + } + memcpy(trypath, ptr, len); + trypath[len] = '/'; + memcpy(trypath+len+1, filename, filename_length+1); + ptr = end; + if ((resolved_path = accel_tsrm_realpath(trypath, len+1+filename_length TSRMLS_CC)) != NULL) { + return resolved_path; + } + } /* end provided path */ + + /* check in calling scripts' current working directory as a fall back case + */ + if (EG(in_execution)) { + char *exec_fname = zend_get_executed_filename(TSRMLS_C); + int exec_fname_length = strlen(exec_fname); + + while ((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length])); + if (exec_fname && exec_fname[0] != '[' && + exec_fname_length > 0 && + exec_fname_length + 1 + filename_length + 1 < MAXPATHLEN) { + memcpy(trypath, exec_fname, exec_fname_length + 1); + memcpy(trypath+exec_fname_length + 1, filename, filename_length+1); + return accel_tsrm_realpath(trypath, exec_fname_length+1+filename_length TSRMLS_CC); + } + } + + return NULL; +} + +/* zend_stream_open_function() replacement for PHP 5.2 */ +static int persistent_stream_open_function(const char *filename, zend_file_handle *handle TSRMLS_DC) +{ + if (ZCG(startup_ok) && + (ZCG(counted) || ZCSG(accelerator_enabled)) && + !CG(interactive) && + !ZCSG(restart_in_progress)) { + + if (EG(opline_ptr) && *EG(opline_ptr)) { + zend_op *opline = *EG(opline_ptr); + + if (opline->opcode == ZEND_INCLUDE_OR_EVAL && + (opline->op2.u.constant.value.lval == ZEND_INCLUDE_ONCE || + opline->op2.u.constant.value.lval == ZEND_REQUIRE_ONCE)) { + /* we are in include_once */ + char *key = NULL; + int key_length; + char *resolved_path; + zend_accel_hash_entry *bucket; + zend_persistent_script *persistent_script; + int filename_len; + + if (opline->op1.op_type == IS_CONST) { + filename_len = Z_STRLEN(opline->op1.u.constant); + } else { + filename_len = strlen(filename); + } + handle->filename = (char*)filename; + handle->free_filename = 0; + handle->opened_path = NULL; + + /* Check if requestd file already cached (by full name) */ + if (IS_ABSOLUTE_PATH(filename, filename_len) && + (persistent_script = zend_accel_hash_find(&ZCSG(hash), (char*)filename, filename_len+1)) != NULL && + !persistent_script->corrupted) { + + handle->opened_path = estrndup(persistent_script->full_path, persistent_script->full_path_len); + handle->type = ZEND_HANDLE_FILENAME; + memcpy(ZCG(key), persistent_script->full_path, persistent_script->full_path_len+1); + ZCG(key_len) = persistent_script->full_path_len; + ZCG(cache_opline) = opline; + ZCG(cache_persistent_script) = persistent_script; + return SUCCESS; + } + + /* Check if requestd file already cached (by key) */ + key = accel_make_persistent_key_ex(handle, filename_len, &key_length TSRMLS_CC); + if (!ZCG(accel_directives).revalidate_path && + key && + (persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length+1)) != NULL && + !persistent_script->corrupted) { + + handle->opened_path = estrndup(persistent_script->full_path, persistent_script->full_path_len); + handle->type = ZEND_HANDLE_FILENAME; + ZCG(cache_opline) = opline; + ZCG(cache_persistent_script) = persistent_script; + return SUCCESS; + } + + /* find the full real path */ + resolved_path = accel_php_resolve_path(filename, filename_len, ZCG(include_path) TSRMLS_CC); + + /* Check if requestd file already cached (by real name) */ + if (resolved_path && + (bucket = zend_accel_hash_find_entry(&ZCSG(hash), resolved_path, strlen(resolved_path)+1)) != NULL) { + + persistent_script = (zend_persistent_script *)bucket->data; + if (persistent_script && !persistent_script->corrupted) { + handle->opened_path = resolved_path; + handle->type = ZEND_HANDLE_FILENAME; + if (key && !ZCG(accel_directives).revalidate_path) { + /* add another "key" for the same bucket */ + SHM_UNPROTECT(); + zend_shared_alloc_lock(TSRMLS_C); + zend_accel_add_key(key, key_length, bucket TSRMLS_CC); + zend_shared_alloc_unlock(TSRMLS_C); + SHM_PROTECT(); + } + ZCG(cache_opline) = opline; + ZCG(cache_persistent_script) = persistent_script; + return SUCCESS; + } + } + if (resolved_path) { + efree(resolved_path); + } + } + } + } + ZCG(cache_opline) = NULL; + ZCG(cache_persistent_script) = NULL; + return accelerator_orig_zend_stream_open_function(filename, handle TSRMLS_CC); +} + +#else + +/* zend_stream_open_function() replacement for PHP 5.3 and above */ +static int persistent_stream_open_function(const char *filename, zend_file_handle *handle TSRMLS_DC) +{ + if (ZCG(startup_ok) && + (ZCG(counted) || ZCSG(accelerator_enabled)) && + !CG(interactive) && + !ZCSG(restart_in_progress)) { + + /* check if callback is called from include_once or it's a main request */ + if ((!EG(opline_ptr) && + filename == SG(request_info).path_translated) || + (EG(opline_ptr) && + *EG(opline_ptr) && + (*EG(opline_ptr))->opcode == ZEND_INCLUDE_OR_EVAL && +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + ((*EG(opline_ptr))->extended_value == ZEND_INCLUDE_ONCE || + (*EG(opline_ptr))->extended_value == ZEND_REQUIRE_ONCE))) { +#else + ((*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_INCLUDE_ONCE || + (*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_REQUIRE_ONCE))) { +#endif + + /* we are in include_once or FastCGI request */ + zend_persistent_script *persistent_script; + + handle->filename = (char*)filename; + handle->free_filename = 0; + + /* check if cached script was already found by resolve_path() */ + if ((EG(opline_ptr) == NULL && + ZCG(cache_opline) == NULL && + ZCG(cache_persistent_script) != NULL) || + (EG(opline_ptr) && + (ZCG(cache_opline) == *EG(opline_ptr)))) { + persistent_script = ZCG(cache_persistent_script); + handle->opened_path = estrndup(persistent_script->full_path, persistent_script->full_path_len); + handle->type = ZEND_HANDLE_FILENAME; + return SUCCESS; +#if 0 + } else { + /* FIXME: It looks like this part is not needed any more */ + int filename_len = strlen(filename); + + if ((IS_ABSOLUTE_PATH(filename, filename_len) || + is_stream_path(filename)) && + (persistent_script = zend_accel_hash_find(&ZCSG(hash), (char*)filename, filename_len+1)) != NULL && + !persistent_script->corrupted) { + + handle->opened_path = estrndup(persistent_script->full_path, persistent_script->full_path_len); + handle->type = ZEND_HANDLE_FILENAME; + memcpy(ZCG(key), persistent_script->full_path, persistent_script->full_path_len+1); + ZCG(key_len) = persistent_script->full_path_len; + ZCG(cache_opline) = EG(opline_ptr) ? *EG(opline_ptr) : NULL; + ZCG(cache_persistent_script) = EG(opline_ptr) ? persistent_script : NULL; + return SUCCESS; + } +#endif + } + } + } + ZCG(cache_opline) = NULL; + ZCG(cache_persistent_script) = NULL; + return accelerator_orig_zend_stream_open_function(filename, handle TSRMLS_CC); +} + +/* zend_resolve_path() replacement for PHP 5.3 and above */ +static char* persistent_zend_resolve_path(const char *filename, int filename_len TSRMLS_DC) +{ + if (ZCG(startup_ok) && + (ZCG(counted) || ZCSG(accelerator_enabled)) && + !CG(interactive) && + !ZCSG(restart_in_progress)) { + + /* check if callback is called from include_once or it's a main request */ + if ((!EG(opline_ptr) && + filename == SG(request_info).path_translated) || + (EG(opline_ptr) && + *EG(opline_ptr) && + (*EG(opline_ptr))->opcode == ZEND_INCLUDE_OR_EVAL && +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + ((*EG(opline_ptr))->extended_value == ZEND_INCLUDE_ONCE || + (*EG(opline_ptr))->extended_value == ZEND_REQUIRE_ONCE))) { +#else + ((*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_INCLUDE_ONCE || + (*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_REQUIRE_ONCE))) { +#endif + + /* we are in include_once or FastCGI request */ + zend_file_handle handle; + char *key = NULL; + int key_length; + char *resolved_path; + zend_accel_hash_entry *bucket; + zend_persistent_script *persistent_script; + + /* Check if requestd file already cached (by full name) */ + if ((IS_ABSOLUTE_PATH(filename, filename_len) || + is_stream_path(filename)) && + (bucket = zend_accel_hash_find_entry(&ZCSG(hash), (char*)filename, filename_len+1)) != NULL) { + persistent_script = (zend_persistent_script *)bucket->data; + if (persistent_script && !persistent_script->corrupted) { + memcpy(ZCG(key), persistent_script->full_path, persistent_script->full_path_len+1); + ZCG(key_len) = persistent_script->full_path_len; + ZCG(cache_opline) = EG(opline_ptr) ? *EG(opline_ptr) : NULL; + ZCG(cache_persistent_script) = persistent_script; + return estrndup(persistent_script->full_path, persistent_script->full_path_len); + } + } + + /* Check if requestd file already cached (by key) */ + handle.filename = (char*)filename; + handle.free_filename = 0; + handle.opened_path = NULL; + key = accel_make_persistent_key_ex(&handle, filename_len, &key_length TSRMLS_CC); + if (!ZCG(accel_directives).revalidate_path && + key && + (persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length+1)) != NULL && + !persistent_script->corrupted) { + + /* we have persistent script */ + ZCG(cache_opline) = EG(opline_ptr) ? *EG(opline_ptr) : NULL; + ZCG(cache_persistent_script) = persistent_script; + return estrndup(persistent_script->full_path, persistent_script->full_path_len); + } + + /* find the full real path */ + resolved_path = accelerator_orig_zend_resolve_path(filename, filename_len TSRMLS_CC); + + /* Check if requestd file already cached (by real path) */ + if (resolved_path && + (bucket = zend_accel_hash_find_entry(&ZCSG(hash), resolved_path, strlen(resolved_path)+1)) != NULL) { + persistent_script = (zend_persistent_script *)bucket->data; + + if (persistent_script && !persistent_script->corrupted) { + if (key && !ZCG(accel_directives).revalidate_path) { + /* add another "key" for the same bucket */ + SHM_UNPROTECT(); + zend_shared_alloc_lock(TSRMLS_C); + zend_accel_add_key(key, key_length, bucket TSRMLS_CC); + zend_shared_alloc_unlock(TSRMLS_C); + SHM_PROTECT(); + } + ZCG(cache_opline) = (EG(opline_ptr) && key) ? *EG(opline_ptr): NULL; + ZCG(cache_persistent_script) = key ? persistent_script : NULL; + return resolved_path; + } + } + ZCG(cache_opline) = NULL; + ZCG(cache_persistent_script) = NULL; + return resolved_path; + } + } + ZCG(cache_opline) = NULL; + ZCG(cache_persistent_script) = NULL; + return accelerator_orig_zend_resolve_path(filename, filename_len TSRMLS_CC); +} + +#endif + +static void zend_reset_cache_vars(TSRMLS_D) +{ + ZSMMG(memory_exhausted) = 0; + ZCSG(hits) = 0; + ZCSG(misses) = 0; + ZCSG(blacklist_misses) = 0; + ZSMMG(wasted_shared_memory) = 0; + ZCSG(restart_pending) = 0; + ZCSG(force_restart_time) = 0; +} + +static void accel_activate(void) +{ + TSRMLS_FETCH(); + + if (!ZCG(startup_ok)) { + return; + } + + SHM_UNPROTECT(); + ZCG(request_time) = sapi_get_request_time(TSRMLS_C); + ZCG(cache_opline) = NULL; + ZCG(cache_persistent_script) = NULL; + ZCG(include_path_check) = !ZCG(include_path_key); + + if (ZCG(counted)) { +#ifdef ZTS + zend_accel_error(ACCEL_LOG_WARNING, "Stuck count for thread id %d", tsrm_thread_id()); +#else + zend_accel_error(ACCEL_LOG_WARNING, "Stuck count for pid %d", getpid()); +#endif + accel_unlock_all(TSRMLS_C); + ZCG(counted) = 0; + } + + if (ZCSG(restart_pending)) { + zend_shared_alloc_lock(TSRMLS_C); + if (ZCSG(restart_pending) != 0) { /* check again, to ensure that the cache wasn't already cleaned by another process */ + if (accel_is_inactive(TSRMLS_C) == SUCCESS) { + zend_accel_error(ACCEL_LOG_DEBUG, "Restarting!"); + ZCSG(restart_pending) = 0; + accel_restart_enter(TSRMLS_C); + + zend_reset_cache_vars(TSRMLS_C); + zend_accel_hash_clean(&ZCSG(hash)); + + /* include_paths keeps only the first path */ + if (ZCSG(include_paths).num_entries > 1) { + ZCSG(include_paths).num_entries = 1; + ZCSG(include_paths).num_direct_entries = 1; + memset(ZCSG(include_paths).hash_table, 0, sizeof(zend_accel_hash_entry*) * ZCSG(include_paths).max_num_entries); + ZCSG(include_paths).hash_table[zend_inline_hash_func(ZCSG(include_paths).hash_entries[0].key, ZCSG(include_paths).hash_entries[0].key_length) % ZCSG(include_paths).max_num_entries] = &ZCSG(include_paths).hash_entries[0]; + } + +#if (ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO) && !defined(ZTS) + accel_interned_strings_restore_state(TSRMLS_C); +#endif + + zend_shared_alloc_restore_state(); + ZCSG(accelerator_enabled) = ZCSG(cache_status_before_restart); + ZCSG(last_restart_time) = ZCG(request_time); + accel_restart_leave(TSRMLS_C); + } + } + zend_shared_alloc_unlock(TSRMLS_C); + } + + /* check if ZCG(function_table) wasn't somehow polluted on the way */ + if(ZCG(internal_functions_count) != zend_hash_num_elements(&ZCG(function_table))) { + zend_accel_error(ACCEL_LOG_WARNING, "Internal functions count changed - was %d, now %d", ZCG(internal_functions_count), zend_hash_num_elements(&ZCG(function_table))); + } + + if (ZCG(accel_directives).validate_timestamps) { + time_t now = ZCG(request_time); + if (now > ZCSG(revalidate_at) + (time_t)ZCG(accel_directives).revalidate_freq) { + ZCSG(revalidate_at) = now; + } + } + + ZCG(cwd) = NULL; + + SHM_PROTECT(); +} + +#if !ZEND_DEBUG + +/* Fast Request Shutdown + * ===================== + * Zend Memory Manager frees memory by its own. We don't have to free each + * allocated block separately, but we like to call all the destructors and + * callbacks in exactly the same order. + */ + +static void accel_fast_hash_destroy(HashTable *ht) +{ + Bucket *p = ht->pListHead; + + while (p != NULL) { + ht->pDestructor(p->pData); + p = p->pListNext; + } +} + +static void accel_fast_zval_ptr_dtor(zval **zval_ptr) +{ + zval *zvalue = *zval_ptr; + + if (Z_DELREF_P(zvalue)==0) { +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) { +#else + switch (Z_TYPE_P(zvalue) & ~IS_CONSTANT_INDEX) { +#endif + case IS_ARRAY: + case IS_CONSTANT_ARRAY: { + TSRMLS_FETCH(); + + if (zvalue->value.ht && (zvalue->value.ht != &EG(symbol_table))) { + zvalue->value.ht->pDestructor = (dtor_func_t)accel_fast_zval_ptr_dtor; + accel_fast_hash_destroy(zvalue->value.ht); + } + } + break; + case IS_OBJECT: + { + TSRMLS_FETCH(); + + Z_OBJ_HT_P(zvalue)->del_ref(zvalue TSRMLS_CC); + } + break; + case IS_RESOURCE: + { + TSRMLS_FETCH(); + + /* destroy resource */ + zend_list_delete(zvalue->value.lval); + } + break; + case IS_LONG: + case IS_DOUBLE: + case IS_BOOL: + case IS_NULL: + case IS_STRING: + case IS_CONSTANT: + default: + return; + break; + } + } +} + +static int accel_clean_non_persistent_function(zend_function *function TSRMLS_DC) +{ + if (function->type == ZEND_INTERNAL_FUNCTION) { + return ZEND_HASH_APPLY_STOP; + } else { + if (function->op_array.static_variables) { + function->op_array.static_variables->pDestructor = (dtor_func_t)accel_fast_zval_ptr_dtor; + accel_fast_hash_destroy(function->op_array.static_variables); + function->op_array.static_variables = NULL; + } + return (--(*function->op_array.refcount) <= 0) ? + ZEND_HASH_APPLY_REMOVE : + ZEND_HASH_APPLY_KEEP; + } +} + +static int accel_cleanup_function_data(zend_function *function TSRMLS_DC) +{ + if (function->type == ZEND_USER_FUNCTION) { + if (function->op_array.static_variables) { + function->op_array.static_variables->pDestructor = (dtor_func_t)accel_fast_zval_ptr_dtor; + accel_fast_hash_destroy(function->op_array.static_variables); + function->op_array.static_variables = NULL; + } + } + return 0; +} + +static int accel_clean_non_persistent_class(zend_class_entry **pce TSRMLS_DC) +{ + zend_class_entry *ce = *pce; + + if (ce->type == ZEND_INTERNAL_CLASS) { + return ZEND_HASH_APPLY_STOP; + } else { +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) { + zend_hash_apply(&ce->function_table, (apply_func_t) accel_cleanup_function_data TSRMLS_CC); + } + if (ce->static_members_table) { + int i; + + for (i = 0; i < ce->default_static_members_count; i++) { + if (ce->static_members_table[i]) { + accel_fast_zval_ptr_dtor(&ce->static_members_table[i]); + ce->static_members_table[i] = NULL; + } + } + ce->static_members_table = NULL; + } +#else + zend_hash_apply(&ce->function_table, (apply_func_t) accel_cleanup_function_data TSRMLS_CC); + if (ce->static_members) { + ce->static_members->pDestructor = (dtor_func_t)accel_fast_zval_ptr_dtor; + accel_fast_hash_destroy(ce->static_members); + ce->static_members = NULL; + } +#endif + return ZEND_HASH_APPLY_REMOVE; + } +} + +static int accel_clean_non_persistent_constant(zend_constant *c TSRMLS_DC) +{ + if (c->flags & CONST_PERSISTENT) { + return ZEND_HASH_APPLY_STOP; + } else { + interned_free(c->name); + return ZEND_HASH_APPLY_REMOVE; + } +} + +static void zend_accel_fast_shutdown(TSRMLS_D) +{ + if (EG(full_tables_cleanup)) { + EG(symbol_table).pDestructor = (dtor_func_t)accel_fast_zval_ptr_dtor; + } else { + dtor_func_t old_destructor; + + if (EG(objects_store).top > 1 || zend_hash_num_elements(&EG(regular_list)) > 0) { + /* We don't have to destroy all zvals if they cannot call any destructors */ + + old_destructor = EG(symbol_table).pDestructor; + EG(symbol_table).pDestructor = (dtor_func_t)accel_fast_zval_ptr_dtor; + zend_try { + zend_hash_graceful_reverse_destroy(&EG(symbol_table)); + } zend_end_try(); + EG(symbol_table).pDestructor = old_destructor; + } + zend_hash_init(&EG(symbol_table), 0, NULL, NULL, 0); + old_destructor = EG(function_table)->pDestructor; + EG(function_table)->pDestructor = NULL; + zend_hash_reverse_apply(EG(function_table), (apply_func_t) accel_clean_non_persistent_function TSRMLS_CC); + EG(function_table)->pDestructor = old_destructor; + old_destructor = EG(class_table)->pDestructor; + EG(class_table)->pDestructor = NULL; + zend_hash_reverse_apply(EG(class_table), (apply_func_t) accel_clean_non_persistent_class TSRMLS_CC); + EG(class_table)->pDestructor = old_destructor; + old_destructor = EG(zend_constants)->pDestructor; + EG(zend_constants)->pDestructor = NULL; + zend_hash_reverse_apply(EG(zend_constants), (apply_func_t) accel_clean_non_persistent_constant TSRMLS_CC); + EG(zend_constants)->pDestructor = old_destructor; + } + CG(unclean_shutdown) = 1; +} +#endif + +static void accel_deactivate(void) +{ + /* ensure that we restore function_table and class_table + * In general, they're restored by persistent_compile_file(), but in case + * the script is aborted abnormally, they may become messed up. + */ + TSRMLS_FETCH(); + + if (!ZCG(startup_ok)) { + return; + } + + zend_shared_alloc_safe_unlock(TSRMLS_C); /* be sure we didn't leave cache locked */ + accel_unlock_all(TSRMLS_C); + ZCG(counted) = 0; + +#if !ZEND_DEBUG + if (ZCG(accel_directives).fast_shutdown) { + zend_accel_fast_shutdown(TSRMLS_C); + } +#endif + + if (ZCG(cwd)) { + efree(ZCG(cwd)); + ZCG(cwd) = NULL; + } + +} + +static int accelerator_remove_cb(zend_extension *element1, zend_extension *element2) +{ + (void)element2; /* keep the compiler happy */ + + if (!strcmp(element1->name, ACCELERATOR_PRODUCT_NAME )) { + element1->startup = NULL; +#if 0 + /* We have to call shutdown callback it to free TS resources */ + element1->shutdown = NULL; +#endif + element1->activate = NULL; + element1->deactivate = NULL; + element1->op_array_handler = NULL; + +#ifdef __DEBUG_MESSAGES__ + fprintf(stderr, ACCELERATOR_PRODUCT_NAME " is disabled: %s\n", (zps_failure_reason ? zps_failure_reason : "unknown error")); + fflush(stderr); +#endif + } + + return 0; +} + +static void zps_startup_failure(char *reason, char *api_reason, int (*cb)(zend_extension *, zend_extension *) TSRMLS_DC) +{ + ZCG(startup_ok) = 0; + zps_failure_reason = reason; + zps_api_failure_reason = api_reason?api_reason:reason; + zend_llist_del_element(&zend_extensions, NULL, (int (*)(void *, void *))cb); +} + +static inline int accel_find_sapi(TSRMLS_D) +{ + static const char *supported_sapis[] = { + "apache", + "fastcgi", + "cgi-fcgi", + "fpm-fcgi", + "isapi", + "apache2filter", + "apache2handler", + NULL + }; + const char **sapi_name; + + if (sapi_module.name) { + for (sapi_name=supported_sapis; *sapi_name; sapi_name++) { + if (strcmp(sapi_module.name, *sapi_name)==0) { + return SUCCESS; + } + } + if (ZCG(accel_directives).enable_cli && + strcmp(sapi_module.name, "cli")==0) { + return SUCCESS; + } + } + + return FAILURE; +} + +static void zend_accel_init_shm(TSRMLS_D) +{ + zend_shared_alloc_lock(TSRMLS_C); + + accel_shared_globals = zend_shared_alloc(sizeof(zend_accel_shared_globals)); + if (!accel_shared_globals) { + zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!"); + } + ZSMMG(app_shared_globals) = accel_shared_globals; + + zend_accel_hash_init(&ZCSG(hash), ZCG(accel_directives).max_accelerated_files); + zend_accel_hash_init(&ZCSG(include_paths), 32); + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + +# ifndef ZTS + zend_hash_init(&ZCSG(interned_strings), (ZCG(accel_directives).interned_strings_buffer * 1024 * 1024) / (sizeof(Bucket) + sizeof(Bucket*) + 8 /* average string length */), NULL, NULL, 1); + ZCSG(interned_strings).nTableMask = ZCSG(interned_strings).nTableSize - 1; + ZCSG(interned_strings).arBuckets = zend_shared_alloc(ZCSG(interned_strings).nTableSize * sizeof(Bucket *)); + ZCSG(interned_strings_start) = zend_shared_alloc((ZCG(accel_directives).interned_strings_buffer * 1024 * 1024)); + if (!ZCSG(interned_strings).arBuckets || !ZCSG(interned_strings_start)) { + zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " cannot allocate buffer for interned strings"); + } + ZCSG(interned_strings_end) = ZCSG(interned_strings_start) + (ZCG(accel_directives).interned_strings_buffer * 1024 * 1024); + ZCSG(interned_strings_top) = ZCSG(interned_strings_start); +# else + ZCSG(interned_strings_start) = ZCSG(interned_strings_end) = NULL; +# endif + + orig_interned_strings_start = CG(interned_strings_start); + orig_interned_strings_end = CG(interned_strings_end); + orig_new_interned_string = zend_new_interned_string; + orig_interned_strings_snapshot = zend_interned_strings_snapshot; + orig_interned_strings_restore = zend_interned_strings_restore; + + CG(interned_strings_start) = ZCSG(interned_strings_start); + CG(interned_strings_end) = ZCSG(interned_strings_end); + zend_new_interned_string = accel_new_interned_string_for_php; + zend_interned_strings_snapshot = accel_interned_strings_snapshot_for_php; + zend_interned_strings_restore = accel_interned_strings_restore_for_php; + +# ifndef ZTS + accel_use_shm_interned_strings(TSRMLS_C); + accel_interned_strings_save_state(TSRMLS_C); +# endif + +#endif + + zend_reset_cache_vars(TSRMLS_C); + + ZCSG(accelerator_enabled) = 1; + ZCSG(last_restart_time) = 0; + ZCSG(restart_in_progress) = 0; + + zend_shared_alloc_unlock(TSRMLS_C); +} + +static void accel_globals_ctor(zend_accel_globals *accel_globals TSRMLS_DC) +{ + memset(accel_globals, 0, sizeof(zend_accel_globals)); + zend_hash_init(&accel_globals->function_table, zend_hash_num_elements(CG(function_table)), NULL, ZEND_FUNCTION_DTOR, 1); + zend_accel_copy_internal_functions(TSRMLS_C); +} + +static void accel_globals_dtor(zend_accel_globals *accel_globals TSRMLS_DC) +{ + accel_globals->function_table.pDestructor = NULL; + zend_hash_destroy(&accel_globals->function_table); +} + +static int accel_startup(zend_extension *extension) +{ + zend_function *func; + zend_ini_entry *ini_entry; + TSRMLS_FETCH(); + +#ifdef ZTS + accel_globals_id = ts_allocate_id(&accel_globals_id, sizeof(zend_accel_globals), (ts_allocate_ctor) accel_globals_ctor, (ts_allocate_dtor) accel_globals_dtor); +#else + accel_globals_ctor(&accel_globals); +#endif + +#ifdef ZEND_WIN32 + _setmaxstdio(2048); /* The default configuration is limited to 512 stdio files */ +#endif + + if (start_accel_module(0) == FAILURE) { + ZCG(startup_ok) = 0; + zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": module registration failed!"); + return FAILURE; + } + + /* no supported SAPI found - disable acceleration and stop initalization */ + if( accel_find_sapi(TSRMLS_C) == FAILURE ){ + ZCG(startup_ok) = 0; + zps_startup_failure("Opcode Caching is only supported in Apache, ISAPI and FastCGI SAPIs", NULL, accelerator_remove_cb TSRMLS_CC); + return SUCCESS; + } + + if (ZCG(enabled) == 0) { + return SUCCESS ; + } +/********************************************/ +/* End of non-SHM dependent initializations */ +/********************************************/ + switch (zend_shared_alloc_startup(ZCG(accel_directives).memory_consumption)) { + case ALLOC_SUCCESS: + zend_accel_init_shm(TSRMLS_C); + break; + case ALLOC_FAILURE: + ZCG(startup_ok) = 0; + zend_accel_error(ACCEL_LOG_FATAL,"Failure to initialize shared memory structures - probably not enough shared memory."); + return SUCCESS; + case SUCCESSFULLY_REATTACHED: + accel_shared_globals = (zend_accel_shared_globals *) ZSMMG(app_shared_globals); +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + zend_shared_alloc_lock(TSRMLS_C); + orig_interned_strings_start = CG(interned_strings_start); + orig_interned_strings_end = CG(interned_strings_end); + orig_new_interned_string = zend_new_interned_string; + orig_interned_strings_snapshot = zend_interned_strings_snapshot; + orig_interned_strings_restore = zend_interned_strings_restore; + + CG(interned_strings_start) = ZCSG(interned_strings_start); + CG(interned_strings_end) = ZCSG(interned_strings_end); + zend_new_interned_string = accel_new_interned_string_for_php; + zend_interned_strings_snapshot = accel_interned_strings_snapshot_for_php; + zend_interned_strings_restore = accel_interned_strings_restore_for_php; + +# ifndef ZTS + accel_use_shm_interned_strings(TSRMLS_C); +# endif + + zend_shared_alloc_unlock(TSRMLS_C); +#endif + + break; + case FAILED_REATTACHED: + ZCG(startup_ok) = 0; + zend_accel_error(ACCEL_LOG_FATAL,"Failure to initialize shared memory structures - can not reattach to exiting shared memory."); + return SUCCESS; + break; + } + + /* from this point further, shared memory is supposed to be OK */ + + /* Override compiler */ + accelerator_orig_compile_file = zend_compile_file; + zend_compile_file = persistent_compile_file; + + /* Override stream opener function (to eliminate open() call caused by + * include/require statements ) */ + accelerator_orig_zend_stream_open_function = zend_stream_open_function; + zend_stream_open_function = persistent_stream_open_function; + +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + /* Override path resolver function (to eliminate stat() calls caused by + * include_once/require_once statements */ + accelerator_orig_zend_resolve_path = zend_resolve_path; + zend_resolve_path = persistent_zend_resolve_path; +#endif + + if(ZCG(accel_directives).validate_timestamps) { + ZCSG(revalidate_at) = zend_accel_get_time() + ZCG(accel_directives).revalidate_freq; + } + + /* Override chdir() function */ + if (zend_hash_find(CG(function_table), "chdir", sizeof("chdir"), (void**)&func) == SUCCESS && + func->type == ZEND_INTERNAL_FUNCTION) { + orig_chdir = func->internal_function.handler; + func->internal_function.handler = ZEND_FN(accel_chdir); + } + ZCG(cwd) = NULL; + + /* Override "include_path" modifier callback */ + if (zend_hash_find(EG(ini_directives), "include_path", sizeof("include_path"), (void **) &ini_entry)==SUCCESS) { + ZCG(include_path) = INI_STR("include_path"); + ZCG(include_path_key) = NULL; + if (ZCG(include_path) && *ZCG(include_path)) { + ZCG(include_path_len) = strlen(ZCG(include_path)); + if (!zend_accel_hash_is_full(&ZCSG(include_paths))) { + char *key; + + zend_shared_alloc_lock(TSRMLS_C); + key = zend_shared_alloc(ZCG(include_path_len) + 2); + if (key) { + memcpy(key, ZCG(include_path), ZCG(include_path_len) + 1); + key[ZCG(include_path_len) + 1] = 'A' + ZCSG(include_paths).num_entries; + ZCG(include_path_key) = key + ZCG(include_path_len) + 1; + zend_accel_hash_update(&ZCSG(include_paths), key, ZCG(include_path_len) + 1, 0, ZCG(include_path_key)); + } + zend_shared_alloc_unlock(TSRMLS_C); + } + } else { + ZCG(include_path) = ""; + ZCG(include_path_len) = 0; + } + orig_include_path_on_modify = ini_entry->on_modify; + ini_entry->on_modify = accel_include_path_on_modify; + } + + zend_shared_alloc_lock(TSRMLS_C); + zend_shared_alloc_save_state(); + zend_shared_alloc_unlock(TSRMLS_C); + + SHM_PROTECT(); + + ZCG(startup_ok) = 1; + + /* Override file_exists(), is_file() and is_readable() */ + zend_accel_override_file_functions(TSRMLS_C); + +#if 0 + /* FIXME: We probably don't need it here */ + zend_accel_copy_internal_functions(TSRMLS_C); +#endif + + return SUCCESS; +} + +static void accel_free_ts_resources() +{ +#ifndef ZTS + accel_globals_dtor(&accel_globals); +#else + ts_free_id(accel_globals_id); +#endif +} + +static void accel_shutdown(zend_extension *extension) +{ + zend_ini_entry *ini_entry; + TSRMLS_FETCH(); + + (void)extension; /* keep the compiler happy */ + + zend_accel_blacklist_shutdown(&accel_blacklist); + + if (!ZCG(startup_ok)) { + accel_free_ts_resources(); + return; + } + + accel_free_ts_resources(); + zend_shared_alloc_shutdown(); + zend_compile_file = accelerator_orig_compile_file; + + if (zend_hash_find(EG(ini_directives), "include_path", sizeof("include_path"), (void **) &ini_entry)==SUCCESS) { + ini_entry->on_modify = orig_include_path_on_modify; + } + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + CG(interned_strings_start) = orig_interned_strings_start; + CG(interned_strings_end) = orig_interned_strings_end; + zend_new_interned_string = orig_new_interned_string; + zend_interned_strings_snapshot = orig_interned_strings_snapshot; + zend_interned_strings_restore = orig_interned_strings_restore; +#endif + +} + +void zend_accel_schedule_restart(TSRMLS_D) +{ + if (ZCSG(restart_pending)) { + /* don't schedule twice */ + return; + } + zend_accel_error(ACCEL_LOG_DEBUG, "Restart Scheduled!"); + + ZCSG(restart_pending) = 1; + ZCSG(cache_status_before_restart) = ZCSG(accelerator_enabled); + ZCSG(accelerator_enabled) = 0; + + if (ZCG(accel_directives).force_restart_timeout) { + ZCSG(force_restart_time) = zend_accel_get_time() + ZCG(accel_directives).force_restart_timeout; + } else { + ZCSG(force_restart_time) = 0; + } +} + +/* this is needed because on WIN32 lock is not decreased unless ZCG(counted) is set */ +#ifdef ZEND_WIN32 +#define accel_deactivate_now() ZCG(counted) = 1; accel_deactivate_sub(TSRMLS_C) +#else +#define accel_deactivate_now() accel_deactivate_sub(TSRMLS_C) +#endif + +/* ensures it is OK to read SHM + if it's not OK (restart in progress) returns FAILURE + if OK returns SUCCESS + MUST call accelerator_shm_read_unlock after done lock operationss +*/ +int accelerator_shm_read_lock(TSRMLS_D) +{ + if(ZCG(counted)) { + /* counted means we are holding read lock for SHM, so that nothing bad can happen */ + return SUCCESS; + } else { + /* here accelerator is active but we do not hold SHM lock. This means restart was scheduled + or is in progress now */ + accel_activate_add(TSRMLS_C); /* acquire usage lock */ + /* Now if we weren't inside restart, restart would not begin until we remove usage lock */ + if(ZCSG(restart_in_progress)) { + /* we already were inside restart this means it's not safe to touch shm */ + accel_deactivate_now(); /* drop usage lock */ + return FAILURE; + } + } + return SUCCESS; +} + +/* must be called ONLY after SUCCESSFUL accelerator_shm_read_lock */ +void accelerator_shm_read_unlock(TSRMLS_D) +{ + if(!ZCG(counted)) { + /* counted is 0 - meaning we had to readlock manually, release readlock now */ + accel_deactivate_now(); + } +} + +static void accel_op_array_handler(zend_op_array *op_array) +{ + TSRMLS_FETCH(); + + if (ZCG(startup_ok) && ZCSG(accelerator_enabled)) { + zend_optimizer(op_array TSRMLS_CC); + } +} + +ZEND_EXT_API zend_extension zend_extension_entry = { + ACCELERATOR_PRODUCT_NAME, /* name */ + ACCELERATOR_VERSION, /* version */ + "Zend Technologies", /* author */ + "http://www.zend.com/", /* URL */ + "Copyright (c) 1999-2013", /* copyright */ + accel_startup, /* startup */ + accel_shutdown, /* shutdown */ + accel_activate, /* per-script activation */ + accel_deactivate, /* per-script deactivation */ + NULL, /* message handler */ + accel_op_array_handler, /* op_array handler */ + NULL, /* extended statement handler */ + NULL, /* extended fcall begin handler */ + NULL, /* extended fcall end handler */ + NULL, /* op_array ctor */ + NULL, /* op_array dtor */ + STANDARD_ZEND_EXTENSION_PROPERTIES +}; diff --git a/ZendAccelerator.h b/ZendAccelerator.h new file mode 100644 index 00000000000..68afad38f4c --- /dev/null +++ b/ZendAccelerator.h @@ -0,0 +1,364 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_ACCELERATOR_H +#define ZEND_ACCELERATOR_H + +#ifdef HAVE_CONFIG_H +# include +#endif + +#define ACCELERATOR_PRODUCT_NAME "Zend Optimizer+" +#define ACCELERATOR_VERSION "7.0.0" +/* 2 - added Profiler support, on 20010712 */ +/* 3 - added support for Optimizer's encoded-only-files mode */ +/* 4 - works with the new Optimizer, that supports the file format with licenses */ +/* 5 - API 4 didn't really work with the license-enabled file format. v5 does. */ +/* 6 - Monitor was removed from ZendPlatform.so, to a module of its own */ +/* 7 - Optimizer was embeded into Accelerator */ +/* 8 - Standalone Open Source OptimizerPlus */ +#define ACCELERATOR_API_NO 8 + +#if ZEND_WIN32 +# include "zend_config.w32.h" +#else +#include "zend_config.h" +# include +# include +#endif + +#if HAVE_UNISTD_H +# include "unistd.h" +#endif + +#include "zend_extensions.h" +#include "zend_compile.h" + +#include "Optimizer/zend_optimizer.h" +#include "zend_accelerator_hash.h" +#include "zend_accelerator_debug.h" + +#ifndef PHPAPI +# ifdef ZEND_WIN32 +# define PHPAPI __declspec(dllimport) +# else +# define PHPAPI +# endif +#endif + +#ifndef ZEND_EXT_API +# if WIN32|WINNT +# define ZEND_EXT_API __declspec(dllexport) +# else +# define ZEND_EXT_API +# endif +#endif + +#ifdef ZEND_WIN32 +# ifndef MAXPATHLEN +# define MAXPATHLEN _MAX_PATH +# endif +# include +#else +# include +#endif + +#define PHP_5_0_X_API_NO 220040412 +#define PHP_5_1_X_API_NO 220051025 +#define PHP_5_2_X_API_NO 220060519 +#define PHP_5_3_X_API_NO 220090626 +#define PHP_5_4_X_API_NO 220100525 + +/*** file locking ***/ +#ifndef ZEND_WIN32 +extern int lock_file; + +# if defined(__FreeBSD__) || (defined(__APPLE__) && defined(__MACH__)/* Darwin */) || defined(__OpenBSD__) || defined(__NetBSD__) +# define FLOCK_STRUCTURE(name, type, whence, start, len) \ + struct flock name = {start, len, -1, type, whence} +# elif defined(__svr4__) +# define FLOCK_STRUCTURE(name, type, whence, start, len) \ + struct flock name = {type, whence, start, len} +# elif defined(__linux__) || defined(__hpux) +# define FLOCK_STRUCTURE(name, type, whence, start, len) \ + struct flock name = {type, whence, start, len, 0} +# elif defined(_AIX) +# if defined(_LARGE_FILES) || defined(__64BIT__) +# define FLOCK_STRUCTURE(name, type, whence, start, len) \ + struct flock name = {type, whence, 0, 0, 0, start, len } +# else +# define FLOCK_STRUCTURE(name, type, whence, start, len) \ + struct flock name = {type, whence, start, len} +# endif +# else +# error "Don't know how to define struct flock" +# endif +#endif + +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + #define Z_REFCOUNT_P(pz) (pz)->refcount + #define Z_SET_REFCOUNT_P(pz, v) (pz)->refcount = (v) + #define Z_ADDREF_P(pz) ++((pz)->refcount) + #define Z_DELREF_P(pz) --((pz)->refcount) + #define Z_ISREF_P(pz) (pz)->is_ref + #define Z_SET_ISREF_P(pz) Z_SET_ISREF_TO_P(pz, 1) + #define Z_UNSET_ISREF_P(pz) Z_SET_ISREF_TO_P(pz, 0) + #define Z_SET_ISREF_TO_P(pz, isref) (pz)->is_ref = (isref) + #define PZ_REFCOUNT_P(pz) (pz)->refcount + #define PZ_SET_REFCOUNT_P(pz, v) (pz)->refcount = (v) + #define PZ_ADDREF_P(pz) ++((pz)->refcount) + #define PZ_DELREF_P(pz) --((pz)->refcount) + #define PZ_ISREF_P(pz) (pz)->is_ref + #define PZ_SET_ISREF_P(pz) Z_SET_ISREF_TO_P(pz, 1) + #define PZ_UNSET_ISREF_P(pz) Z_SET_ISREF_TO_P(pz, 0) + #define PZ_SET_ISREF_TO_P(pz, isref) (pz)->is_ref = (isref) +#else + #define PZ_REFCOUNT_P(pz) (pz)->refcount__gc + #define PZ_SET_REFCOUNT_P(pz, v) (pz)->refcount__gc = (v) + #define PZ_ADDREF_P(pz) ++((pz)->refcount__gc) + #define PZ_DELREF_P(pz) --((pz)->refcount__gc) + #define PZ_ISREF_P(pz) (pz)->is_ref__gc + #define PZ_SET_ISREF_P(pz) Z_SET_ISREF_TO_P(pz, 1) + #define PZ_UNSET_ISREF_P(pz) Z_SET_ISREF_TO_P(pz, 0) + #define PZ_SET_ISREF_TO_P(pz, isref) (pz)->is_ref__gc = (isref) +#endif + +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO +# ifdef ALLOCA_FLAG + #define DO_ALLOCA(x) do_alloca_with_limit(x,use_heap) + #define FREE_ALLOCA(x) free_alloca_with_limit(x,use_heap) +# else + #define ALLOCA_FLAG(x) + #define DO_ALLOCA(x) do_alloca(x) + #define FREE_ALLOCA(x) free_alloca(x) +# endif +#else + #define DO_ALLOCA(x) do_alloca(x,use_heap) + #define FREE_ALLOCA(x) free_alloca(x,use_heap) +#endif + + +#if ZEND_WIN32 +typedef unsigned __int64 accel_time_t; +#else +typedef time_t accel_time_t; +#endif + +typedef struct _zend_persistent_script { + ulong hash_value; + char *full_path; /* full real path with resolved symlinks */ + int full_path_len; + zend_op_array main_op_array; + HashTable function_table; + HashTable class_table; + long compiler_halt_offset; /* position of __HALT_COMPILER or -1 */ + int ping_auto_globals_mask; /* which autoglobals are used by the script */ + accel_time_t timestamp; /* the script modification time */ + zend_bool corrupted; +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + zend_uint early_binding; /* the linked list of delayed declarations */ +#endif + + void *mem; /* shared memory area used by script structures */ + size_t size; /* size of used shared memory */ + + /* All entries that shouldn't be counted in the ADLER32 + * checksum must be declared in this struct + */ + struct zend_persistent_script_dynamic_members { + time_t last_used; + ulong hits; + unsigned int memory_consumption; + unsigned int checksum; + time_t revalidate; + } dynamic_members; +} zend_persistent_script; + +typedef struct _zend_accel_directives { + long memory_consumption; + long max_accelerated_files; + double max_wasted_percentage; + char *user_blacklist_filename; + long consistency_checks; + long force_restart_timeout; + zend_bool use_cwd; + zend_bool ignore_dups; + zend_bool validate_timestamps; + zend_bool revalidate_path; + zend_bool save_comments; + zend_bool fast_shutdown; + zend_bool protect_memory; + zend_bool file_override_enabled; + zend_bool inherited_hack; + zend_bool enable_cli; + unsigned long revalidate_freq; + char *error_log; +#ifdef ZEND_WIN32 + char *mmap_base; +#endif + char *memory_model; + long log_verbosity_level; + + long optimization_level; +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + long interned_strings_buffer; +#endif +} zend_accel_directives; + +typedef struct _zend_accel_globals { + /* copy of CG(function_table) used for compilation scripts into cashe */ + /* imitially it contains only internal functions */ + HashTable function_table; + int internal_functions_count; + int counted; /* the process uses shatred memory */ + zend_bool enabled; + HashTable bind_hash; /* prototype and zval lookup table */ + zend_accel_directives accel_directives; + char *cwd; /* current working directory or NULL */ + int cwd_len; /* "cwd" string lenght */ + char *include_path_key; /* one letter key of current "include_path" */ + char *include_path; /* current settion of "include_path" directive */ + int include_path_len; /* "include_path" string lenght */ + int include_path_check; + time_t request_time; + zend_bool startup_ok; + /* preallocated shared-memory block to save current script */ + void *mem; + /* cache to save hash lookup on the same INCLUDE opcode */ + zend_op *cache_opline; + zend_persistent_script *cache_persistent_script; + /* preallocated buffer for keys */ + int key_len; + char key[MAXPATHLEN * 8]; +} zend_accel_globals; + +typedef struct _zend_accel_shared_globals { + /* Cache Data Structures */ + unsigned long hits; + unsigned long misses; + unsigned long blacklist_misses; + zend_accel_hash hash; /* hash table for cached scripts */ + zend_accel_hash include_paths; /* used "include_path" values */ + + /* Directives & Maintenance */ + time_t last_restart_time; + time_t force_restart_time; + zend_bool accelerator_enabled; + zend_bool restart_pending; + zend_bool cache_status_before_restart; +#ifdef ZEND_WIN32 + unsigned long mem_usage; + unsigned long restart_in; +#endif + zend_bool restart_in_progress; + time_t revalidate_at; +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + /* Interned Strings Support */ + char *interned_strings_start; + char *interned_strings_top; + char *interned_strings_end; + HashTable interned_strings; + struct { + Bucket **arBuckets; + Bucket *pListHead; + Bucket *pListTail; + char *top; + } interned_strings_saved_state; +#endif +} zend_accel_shared_globals; + +extern zend_accel_shared_globals *accel_shared_globals; +#define ZCSG(element) (accel_shared_globals->element) + +#ifdef ZTS +# define ZCG(v) TSRMG(accel_globals_id, zend_accel_globals *, v) +extern int accel_globals_id; +#else +# define ZCG(v) (accel_globals.v) +extern zend_accel_globals accel_globals; +#endif + +extern char *zps_api_failure_reason; + +void zend_accel_schedule_restart(TSRMLS_D); +int accelerator_shm_read_lock(TSRMLS_D); +void accelerator_shm_read_unlock(TSRMLS_D); + +char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_length, int *key_len TSRMLS_DC); + +#if !defined(ZEND_DECLARE_INHERITED_CLASS_DELAYED) +# define ZEND_DECLARE_INHERITED_CLASS_DELAYED 145 +#endif + +#define ZEND_DECLARE_INHERITED_CLASS_DELAYED_FLAG 0x80 + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + +const char *accel_new_interned_string(const char *arKey, int nKeyLength, int free_src TSRMLS_DC); + +# define interned_free(s) do { \ + if (!IS_INTERNED(s)) { \ + free(s); \ + } \ + } while (0) +# define interned_efree(s) do { \ + if (!IS_INTERNED(s)) { \ + efree(s); \ + } \ + } while (0) +# define interned_estrndup(s, n) \ + (IS_INTERNED(s) ? (s) : estrndup(s, n)) +# define ZEND_RESULT_TYPE(opline) (opline)->result_type +# define ZEND_RESULT(opline) (opline)->result +# define ZEND_OP1_TYPE(opline) (opline)->op1_type +# define ZEND_OP1(opline) (opline)->op1 +# define ZEND_OP1_CONST(opline) (*(opline)->op1.zv) +# define ZEND_OP1_LITERAL(opline) (op_array)->literals[(opline)->op1.constant].constant +# define ZEND_OP2_TYPE(opline) (opline)->op2_type +# define ZEND_OP2(opline) (opline)->op2 +# define ZEND_OP2_CONST(opline) (*(opline)->op2.zv) +# define ZEND_OP2_LITERAL(opline) (op_array)->literals[(opline)->op2.constant].constant +# define ZEND_DONE_PASS_TWO(op_array) (((op_array)->fn_flags & ZEND_ACC_DONE_PASS_TWO) != 0) +# define ZEND_CE_FILENAME(ce) (ce)->info.user.filename +# define ZEND_CE_DOC_COMMENT(ce) (ce)->info.user.doc_comment +# define ZEND_CE_DOC_COMMENT_LEN(ce) (ce)->info.user.doc_comment_len +#else +# define IS_INTERNED(s) 0 +# define interned_free(s) free(s) +# define interned_efree(s) efree(s) +# define interned_estrndup(s, n) estrndup(s, n) +# define ZEND_RESULT_TYPE(opline) (opline)->result.op_type +# define ZEND_RESULT(opline) (opline)->result.u +# define ZEND_OP1_TYPE(opline) (opline)->op1.op_type +# define ZEND_OP1(opline) (opline)->op1.u +# define ZEND_OP1_CONST(opline) (opline)->op1.u.constant +# define ZEND_OP1_LITERAL(opline) (opline)->op1.u.constant +# define ZEND_OP2_TYPE(opline) (opline)->op2.op_type +# define ZEND_OP2(opline) (opline)->op2.u +# define ZEND_OP2_CONST(opline) (opline)->op2.u.constant +# define ZEND_OP2_LITERAL(opline) (opline)->op2.u.constant +# define ZEND_DONE_PASS_TWO(op_array) ((op_array)->done_pass_two != 0) +# define ZEND_CE_FILENAME(ce) (ce)->filename +# define ZEND_CE_DOC_COMMENT(ce) (ce)->doc_comment +# define ZEND_CE_DOC_COMMENT_LEN(ce) (ce)->doc_comment_len +#endif + +#endif /* ZEND_ACCELERATOR_H */ diff --git a/config.m4 b/config.m4 new file mode 100644 index 00000000000..6e178c1123e --- /dev/null +++ b/config.m4 @@ -0,0 +1,345 @@ +dnl +dnl $Id$ +dnl + +PHP_ARG_ENABLE(optimizer-plus, whether to enable Zend OptimizerPlus support, +[ --enable-optimizer-plus Enable Zend OptimizerPlus support]) + +if test "$PHP_OPTIMIZER_PLUS" != "no"; then + AC_DEFINE(HAVE_OPTIMIZER_PLUS, 1, [ ]) + + AC_CHECK_FUNC(mprotect,[ + AC_DEFINE(HAVE_MPROTECT, 1, [Define if you have mprotect() function]) + ]) + + AC_MSG_CHECKING(for sysvipc shared memory support) + AC_TRY_RUN([ +#include +#include +#include +#include +#include +#include + +int main() { + pid_t pid; + int status; + int ipc_id; + char *shm; + struct shmid_ds shmbuf; + + ipc_id = shmget(IPC_PRIVATE, 4096, (IPC_CREAT | SHM_R | SHM_W)); + if (ipc_id == -1) { + return 1; + } + + shm = shmat(ipc_id, NULL, 0); + if (shm == (void *)-1) { + shmctl(ipc_id, IPC_RMID, NULL); + return 2; + } + + if (shmctl(ipc_id, IPC_STAT, &shmbuf) != 0) { + shmdt(shm); + shmctl(ipc_id, IPC_RMID, NULL); + return 3; + } + + shmbuf.shm_perm.uid = getuid(); + shmbuf.shm_perm.gid = getgid(); + shmbuf.shm_perm.mode = 0600; + + if (shmctl(ipc_id, IPC_SET, &shmbuf) != 0) { + shmdt(shm); + shmctl(ipc_id, IPC_RMID, NULL); + return 4; + } + + shmctl(ipc_id, IPC_RMID, NULL); + + strcpy(shm, "hello"); + + pid = fork(); + if (pid < 0) { + return 5; + } else if (pid == 0) { + strcpy(shm, "bye"); + return 6; + } + if (wait(&status) != pid) { + return 7; + } + if (!WIFEXITED(status) || WEXITSTATUS(status) != 6) { + return 8; + } + if (strcmp(shm, "bye") != 0) { + return 9; + } + return 0; +} +],dnl + AC_DEFINE(HAVE_SHM_IPC, 1, [Define if you have SysV IPC SHM support]) + msg=yes,msg=no,msg=no) + AC_MSG_RESULT([$msg]) + + AC_MSG_CHECKING(for mmap() using MAP_ANON shared memory support) + AC_TRY_RUN([ +#include +#include +#include +#include +#include + +#ifndef MAP_ANON +# ifdef MAP_ANONYMOUS +# define MAP_ANON MAP_ANONYMOUS +# endif +#endif +#ifndef MAP_FAILED +# define MAP_FAILED ((void*)-1) +#endif + +int main() { + pid_t pid; + int status; + char *shm; + + shm = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); + if (shm == MAP_FAILED) { + return 1; + } + + strcpy(shm, "hello"); + + pid = fork(); + if (pid < 0) { + return 5; + } else if (pid == 0) { + strcpy(shm, "bye"); + return 6; + } + if (wait(&status) != pid) { + return 7; + } + if (!WIFEXITED(status) || WEXITSTATUS(status) != 6) { + return 8; + } + if (strcmp(shm, "bye") != 0) { + return 9; + } + return 0; +} +],dnl + AC_DEFINE(HAVE_SHM_MMAP_ANON, 1, [Define if you have mmap(MAP_ANON) SHM support]) + msg=yes,msg=no,msg=no) + AC_MSG_RESULT([$msg]) + + AC_MSG_CHECKING(for mmap() using /dev/zero shared memory support) + AC_TRY_RUN([ +#include +#include +#include +#include +#include +#include +#include + +#ifndef MAP_FAILED +# define MAP_FAILED ((void*)-1) +#endif + +int main() { + pid_t pid; + int status; + int fd; + char *shm; + + fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR); + if (fd == -1) { + return 1; + } + + shm = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (shm == MAP_FAILED) { + return 2; + } + + strcpy(shm, "hello"); + + pid = fork(); + if (pid < 0) { + return 5; + } else if (pid == 0) { + strcpy(shm, "bye"); + return 6; + } + if (wait(&status) != pid) { + return 7; + } + if (!WIFEXITED(status) || WEXITSTATUS(status) != 6) { + return 8; + } + if (strcmp(shm, "bye") != 0) { + return 9; + } + return 0; +} +],dnl + AC_DEFINE(HAVE_SHM_MMAP_ZERO, 1, [Define if you have mmap("/dev/zero") SHM support]) + msg=yes,msg=no,msg=no) + AC_MSG_RESULT([$msg]) + + AC_MSG_CHECKING(for mmap() using shm_open() shared memory support) + AC_TRY_RUN([ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef MAP_FAILED +# define MAP_FAILED ((void*)-1) +#endif + +int main() { + pid_t pid; + int status; + int fd; + char *shm; + char tmpname[4096]; + + sprintf(tmpname,"test.shm.%dXXXXXX", getpid()); + if (mktemp(tmpname) == NULL) { + return 1; + } + fd = shm_open(tmpname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (fd == -1) { + return 2; + } + if (ftruncate(fd, 4096) < 0) { + close(fd); + shm_unlink(tmpname); + return 3; + } + + shm = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (shm == MAP_FAILED) { + return 4; + } + shm_unlink(tmpname); + close(fd); + + strcpy(shm, "hello"); + + pid = fork(); + if (pid < 0) { + return 5; + } else if (pid == 0) { + strcpy(shm, "bye"); + return 6; + } + if (wait(&status) != pid) { + return 7; + } + if (!WIFEXITED(status) || WEXITSTATUS(status) != 6) { + return 8; + } + if (strcmp(shm, "bye") != 0) { + return 9; + } + return 0; +} +],dnl + AC_DEFINE(HAVE_SHM_MMAP_POSIX, 1, [Define if you have POSIX mmap() SHM support]) + msg=yes,msg=no,msg=no) + AC_MSG_RESULT([$msg]) + + AC_MSG_CHECKING(for mmap() using regular file shared memory support) + AC_TRY_RUN([ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef MAP_FAILED +# define MAP_FAILED ((void*)-1) +#endif + +int main() { + pid_t pid; + int status; + int fd; + char *shm; + char tmpname[4096]; + + sprintf(tmpname,"test.shm.%dXXXXXX", getpid()); + if (mktemp(tmpname) == NULL) { + return 1; + } + fd = open(tmpname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (fd == -1) { + return 2; + } + if (ftruncate(fd, 4096) < 0) { + close(fd); + unlink(tmpname); + return 3; + } + + shm = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (shm == MAP_FAILED) { + return 4; + } + unlink(tmpname); + close(fd); + + strcpy(shm, "hello"); + + pid = fork(); + if (pid < 0) { + return 5; + } else if (pid == 0) { + strcpy(shm, "bye"); + return 6; + } + if (wait(&status) != pid) { + return 7; + } + if (!WIFEXITED(status) || WEXITSTATUS(status) != 6) { + return 8; + } + if (strcmp(shm, "bye") != 0) { + return 9; + } + return 0; +} +],dnl + AC_DEFINE(HAVE_SHM_MMAP_FILE, 1, [Define if you have mmap() SHM support]) + msg=yes,msg=no,msg=no) + AC_MSG_RESULT([$msg]) + + PHP_NEW_EXTENSION(ZendOptimizerPlus, + ZendAccelerator.c \ + zend_accelerator_blacklist.c \ + zend_accelerator_debug.c \ + zend_accelerator_hash.c \ + zend_accelerator_module.c \ + zend_persist.c \ + zend_persist_calc.c \ + zend_shared_alloc.c \ + zend_accelerator_util_funcs.c \ + shared_alloc_shm.c \ + shared_alloc_mmap.c \ + shared_alloc_posix.c \ + Optimizer/zend_optimizer.c, + $ext_shared) +fi diff --git a/config.w32 b/config.w32 new file mode 100644 index 00000000000..6f3c89c135d --- /dev/null +++ b/config.w32 @@ -0,0 +1,28 @@ +ARG_ENABLE("optimizer-plus", "whether to enable Zend OptimizerPlus support", "yes"); + +if (PHP_OPTIMIZER_PLUS != "no") { + + PHP_PGI = "no"; // workaround + PHP_PGO = "no"; // workaround + + EXTENSION('ZendOptimizerPlus', "\ + ZendAccelerator.c \ + zend_accelerator_blacklist.c \ + zend_accelerator_debug.c \ + zend_accelerator_hash.c \ + zend_accelerator_module.c \ + zend_accelerator_util_funcs.c \ + zend_persist.c \ + zend_persist_calc.c \ + zend_shared_alloc.c \ + shared_alloc_win32.c", true); + + ADD_SOURCES("Optimizer", "zend_optimizer.c", "ZendOptimizerPlus", "OptimizerObj"); + + + ADD_FLAG('CFLAGS_ZENDOPTIMIZERPLUS', "/I ."); + ADD_FLAG('CFLAGS_ZENDOPTIMIZERPLUS', "/D HAVE_OPTIMIZER_PLUS=1"); + + ADD_FLAG('CFLAGS_ZENDOPTIMIZERPLUS', "/Dregexec=php_regexec /Dregerror=php_regerror /Dregfree=php_regfree /Dregcomp=php_regcomp /Iext/ereg/regex"); + +} diff --git a/shared_alloc_mmap.c b/shared_alloc_mmap.c new file mode 100644 index 00000000000..7e23d4ea8d9 --- /dev/null +++ b/shared_alloc_mmap.c @@ -0,0 +1,70 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#include +#include +#include +#include +#include + +#include "zend_shared_alloc.h" + +#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) +# define MAP_ANONYMOUS MAP_ANON +#endif + +static int create_segments(size_t requested_size, zend_shared_segment ***shared_segments_p, int *shared_segments_count, char **error_in) +{ + zend_shared_segment *shared_segment; + + *shared_segments_count = 1; + *shared_segments_p = (zend_shared_segment **) calloc(1, sizeof(zend_shared_segment)+sizeof(void *)); + shared_segment = (zend_shared_segment *)((char *)(*shared_segments_p) + sizeof(void *)); + (*shared_segments_p)[0] = shared_segment; + + shared_segment->p = mmap(0, requested_size, PROT_READ | PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); + if(shared_segment->p == MAP_FAILED) { + *error_in = "mmap"; + return ALLOC_FAILURE; + } + + shared_segment->pos = 0; + shared_segment->size = requested_size; + + return ALLOC_SUCCESS; +} + +static int detach_segment(zend_shared_segment *shared_segment) +{ + munmap(shared_segment->p, shared_segment->size); + return 0; +} + +static size_t segment_type_size(void) +{ + return sizeof(zend_shared_segment); +} + +zend_shared_memory_handlers zend_alloc_mmap_handlers = { + create_segments, + detach_segment, + segment_type_size +}; diff --git a/shared_alloc_posix.c b/shared_alloc_posix.c new file mode 100644 index 00000000000..5a0111c797a --- /dev/null +++ b/shared_alloc_posix.c @@ -0,0 +1,90 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "zend_shared_alloc.h" + +typedef struct { + zend_shared_segment common; + int shm_fd; +} zend_shared_segment_posix; + +static int create_segments(size_t requested_size, zend_shared_segment_posix ***shared_segments_p, int *shared_segments_count, char **error_in) +{ + zend_shared_segment_posix *shared_segment; + char shared_segment_name[sizeof("/ZendAccelerator.")+20]; + + *shared_segments_count = 1; + *shared_segments_p = (zend_shared_segment_posix **) calloc(1, sizeof(zend_shared_segment_posix)+sizeof(void *)); + shared_segment = (zend_shared_segment_posix *)((char *)(*shared_segments_p) + sizeof(void *)); + (*shared_segments_p)[0] = shared_segment; + + sprintf(shared_segment_name, "/ZendAccelerator.%d", getpid()); + shared_segment->shm_fd = shm_open(shared_segment_name, O_RDWR|O_CREAT|O_TRUNC, 0600); + if(shared_segment->shm_fd == -1) { + *error_in = "shm_open"; + return ALLOC_FAILURE; + } + + if(ftruncate(shared_segment->shm_fd, requested_size) != 0) { + *error_in = "ftruncate"; + shm_unlink(shared_segment_name); + return ALLOC_FAILURE; + } + + shared_segment->common.p = mmap(0, requested_size, PROT_READ | PROT_WRITE, MAP_SHARED, shared_segment->shm_fd, 0); + if(shared_segment->common.p == MAP_FAILED) { + *error_in = "mmap"; + shm_unlink(shared_segment_name); + return ALLOC_FAILURE; + } + shm_unlink(shared_segment_name); + + shared_segment->common.pos = 0; + shared_segment->common.size = requested_size; + + return ALLOC_SUCCESS; +} + +static int detach_segment(zend_shared_segment_posix *shared_segment) +{ + munmap(shared_segment->common.p, shared_segment->common.size); + close(shared_segment->shm_fd); + return 0; +} + +static size_t segment_type_size(void) +{ + return sizeof(zend_shared_segment_posix); +} + +zend_shared_memory_handlers zend_alloc_posix_handlers = { + (create_segments_t)create_segments, + (detach_segment_t)detach_segment, + segment_type_size +}; diff --git a/shared_alloc_shm.c b/shared_alloc_shm.c new file mode 100644 index 00000000000..45fab7c4a31 --- /dev/null +++ b/shared_alloc_shm.c @@ -0,0 +1,137 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#if defined(__FreeBSD__) +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "zend_shared_alloc.h" + +#ifndef MIN +# define MIN(x, y) ((x) > (y)? (y) : (x)) +#endif + +#define SEG_ALLOC_SIZE_MAX 32*1024*1024 +#define SEG_ALLOC_SIZE_MIN 2*1024*1024 + +typedef struct { + zend_shared_segment common; + int shm_id; +} zend_shared_segment_shm; + +static int create_segments(size_t requested_size, zend_shared_segment_shm ***shared_segments_p, int *shared_segments_count, char **error_in) +{ + int i; + unsigned int allocate_size=0, remaining_bytes=requested_size, seg_allocate_size; + int first_segment_id=-1; + key_t first_segment_key = -1; + struct shmid_ds sds; + int shmget_flags; + zend_shared_segment_shm *shared_segments; + + seg_allocate_size = SEG_ALLOC_SIZE_MAX; + /* determine segment size we _really_ need: + * no more than to include requested_size + */ + while (requested_size*2 <= seg_allocate_size && seg_allocate_size > SEG_ALLOC_SIZE_MIN) { + seg_allocate_size >>= 1; + } + + shmget_flags = IPC_CREAT|SHM_R|SHM_W|IPC_EXCL; + + /* try allocating this much, if not - try shrinking */ + while (seg_allocate_size >= SEG_ALLOC_SIZE_MIN) { + allocate_size = MIN(requested_size, seg_allocate_size); + first_segment_id = shmget(first_segment_key, allocate_size, shmget_flags); + if (first_segment_id != -1) { + break; + } + seg_allocate_size >>= 1; /* shrink the allocated block */ + } + + if (first_segment_id == -1) { + *error_in = "shmget"; + return ALLOC_FAILURE; + } + + *shared_segments_count = ((requested_size-1)/seg_allocate_size) + 1; + *shared_segments_p = (zend_shared_segment_shm **) calloc(1, (*shared_segments_count)*sizeof(zend_shared_segment_shm)+sizeof(void *)*(*shared_segments_count)); + shared_segments = (zend_shared_segment_shm *)((char *)(*shared_segments_p) + sizeof(void *)*(*shared_segments_count)); + for(i=0; i<*shared_segments_count; i++) { + (*shared_segments_p)[i] = shared_segments+i; + } + + remaining_bytes = requested_size; + for (i=0; i<*shared_segments_count; i++) { + allocate_size = MIN(remaining_bytes, seg_allocate_size); + if (i != 0) { + shared_segments[i].shm_id = shmget(IPC_PRIVATE, allocate_size, shmget_flags); + } else { + shared_segments[i].shm_id = first_segment_id; + } + + if (shared_segments[i].shm_id==-1) { + return ALLOC_FAILURE; + } + + shared_segments[i].common.p = shmat(shared_segments[i].shm_id, NULL, 0); + if (((int) shared_segments[i].common.p) == -1) { + *error_in = "shmat"; + shmctl(shared_segments[i].shm_id, IPC_RMID, &sds); + return ALLOC_FAILURE; + } + shmctl(shared_segments[i].shm_id, IPC_RMID, &sds); + + shared_segments[i].common.pos = 0; + shared_segments[i].common.size = allocate_size; + remaining_bytes -= allocate_size; + } + return ALLOC_SUCCESS; +} + +static int detach_segment(zend_shared_segment_shm *shared_segment) +{ + shmdt(shared_segment->common.p); + return 0; +} + +static size_t segment_type_size(void) +{ + return sizeof(zend_shared_segment_shm); +} + +zend_shared_memory_handlers zend_alloc_shm_handlers = { + (create_segments_t)create_segments, + (detach_segment_t)detach_segment, + segment_type_size +}; diff --git a/shared_alloc_win32.c b/shared_alloc_win32.c new file mode 100644 index 00000000000..5388ce1ec57 --- /dev/null +++ b/shared_alloc_win32.c @@ -0,0 +1,315 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#include "ZendAccelerator.h" +#include "zend_shared_alloc.h" +#include "zend_accelerator_util_funcs.h" +#include +#include +#include + +#define ACCEL_FILEMAP_NAME "ZendOptimizer+.SharedMemoryArea" +#define ACCEL_MUTEX_NAME "ZendOptimizer+.SharedMemoryMutex" +#define ACCEL_FILEMAP_BASE_DEFAULT 0x01000000 +#define ACCEL_FILEMAP_BASE "ZendOptimizer+.MemoryBase" +#define ACCEL_EVENT_SOURCE "Zend Optimizer+" + +static HANDLE memfile = NULL, memory_mutex = NULL; +static void *mapping_base; + +#define MAX_MAP_RETRIES 25 + +static void zend_win_error_message(int type, char *msg, int err) +{ + LPVOID lpMsgBuf; + FILE *fp; + HANDLE h; + char *ev_msgs[2]; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + + h = RegisterEventSource(NULL, TEXT(ACCEL_EVENT_SOURCE)); + ev_msgs[0] = msg; + ev_msgs[1] = lpMsgBuf; + ReportEvent(h, // event log handle + EVENTLOG_ERROR_TYPE, // event type + 0, // category zero + err, // event identifier + NULL, // no user security identifier + 2, // one substitution string + 0, // no data + ev_msgs, // pointer to string array + NULL); // pointer to data + DeregisterEventSource(h); + + LocalFree( lpMsgBuf ); + + zend_accel_error(type, msg); +} + +static char *create_name_with_username(char *name) +{ + static char newname[MAXPATHLEN+UNLEN+4]; + char uname[UNLEN+1]; + DWORD unsize = UNLEN; + + GetUserName(uname, &unsize); + snprintf(newname, sizeof(newname)-1, "%s@%s", name, uname); + return newname; +} + +static char *get_mmap_base_file() +{ + static char windir[MAXPATHLEN+UNLEN+3+sizeof("\\\\@")]; + char uname[UNLEN+1]; + DWORD unsize = UNLEN; + int l; + + GetTempPath(MAXPATHLEN, windir); + GetUserName(uname, &unsize); + l = strlen(windir); + snprintf(windir+l, sizeof(windir)-l-1, "\\%s@%s", ACCEL_FILEMAP_BASE, uname); + return windir; +} + +void zend_shared_alloc_create_lock(void) +{ + memory_mutex = CreateMutex(NULL, FALSE, create_name_with_username(ACCEL_MUTEX_NAME)); + ReleaseMutex(memory_mutex); +} + +void zend_shared_alloc_lock_win32() +{ + DWORD waitRes = WaitForSingleObject(memory_mutex, INFINITE); + + if(waitRes == WAIT_FAILED) { + zend_accel_error(ACCEL_LOG_ERROR, "Cannot lock mutex"); + } +} + +void zend_shared_alloc_unlock_win32(TSRMLS_D) +{ + ReleaseMutex(memory_mutex); +} + +static int zend_shared_alloc_reattach(size_t requested_size, char **error_in) +{ + int err; + void *wanted_mapping_base; + char *mmap_base_file = get_mmap_base_file(); + FILE *fp = fopen(mmap_base_file, "r"); + MEMORY_BASIC_INFORMATION info; + + err = GetLastError(); + if(!fp) { + zend_win_error_message(ACCEL_LOG_WARNING, mmap_base_file, err); + zend_win_error_message(ACCEL_LOG_FATAL, "Unable to open base address file", err); + *error_in="fopen"; + return ALLOC_FAILURE; + } + if(!fscanf(fp, "%p", &wanted_mapping_base)) { + err = GetLastError(); + zend_win_error_message(ACCEL_LOG_FATAL, "Unable to read base address", err); + *error_in="read mapping base"; + return ALLOC_FAILURE; + } + fclose(fp); + + /* Check if the requested address space is free */ + if (VirtualQuery(wanted_mapping_base, &info, sizeof(info)) == 0 || + info.State != MEM_FREE || + info.RegionSize < requested_size) { + err = ERROR_INVALID_ADDRESS; + zend_win_error_message(ACCEL_LOG_FATAL, "Unable to reattach to base address", err); + return ALLOC_FAILURE; + } + + mapping_base = MapViewOfFileEx(memfile, FILE_MAP_ALL_ACCESS, 0, 0, 0, wanted_mapping_base); + err = GetLastError(); + + if(mapping_base == NULL) { + if (err == ERROR_INVALID_ADDRESS) { + zend_win_error_message(ACCEL_LOG_FATAL, "Unable to reattach to base address", err); + return ALLOC_FAILURE; + } + return ALLOC_FAIL_MAPPING; + } + smm_shared_globals = (zend_smm_shared_globals *) (((char *) mapping_base) + sizeof(zend_shared_memory_block_header)); + + return SUCCESSFULLY_REATTACHED; +} + +static int create_segments(size_t requested_size, zend_shared_segment ***shared_segments_p, int *shared_segments_count, char **error_in) +{ + int err, ret; + zend_shared_segment *shared_segment; + int map_retries = 0; + void *default_mapping_base_set[] = { 0, 0 }; + void *vista_mapping_base_set[] = { (void *)0x20000000, (void *)0x21000000, (void *)0x30000000, (void *)0x31000000, (void *)0x50000000, 0 }; + void **wanted_mapping_base = default_mapping_base_set; + TSRMLS_FETCH(); + + /* Mapping retries: When Apache2 restarts, the parent process startup routine + can be called before the child process is killed. In this case, the map will fail + and we have to sleep some time (until the child releases the mapping object) and retry.*/ + do { + memfile = OpenFileMapping(FILE_MAP_WRITE, 0, create_name_with_username(ACCEL_FILEMAP_NAME)); + err = GetLastError(); + if (memfile == NULL) + break; + + ret = zend_shared_alloc_reattach(requested_size, error_in); + err = GetLastError(); + if (ret == ALLOC_FAIL_MAPPING) { + /* Mapping failed, wait for mapping object to get freed and retry */ + CloseHandle(memfile); + memfile = NULL; + Sleep(1000*(map_retries+1)); + } else { + return ret; + } + } while(++map_retries < MAX_MAP_RETRIES); + + if(map_retries == MAX_MAP_RETRIES) { + zend_win_error_message(ACCEL_LOG_FATAL, "Unable to open file mapping", err); + *error_in = "OpenFileMapping"; + return ALLOC_FAILURE; + } + + /* creating segment here */ + *shared_segments_count = 1; + *shared_segments_p = (zend_shared_segment **) calloc(1, sizeof(zend_shared_segment)+sizeof(void *)); + shared_segment = (zend_shared_segment *)((char *)(*shared_segments_p) + sizeof(void *)); + (*shared_segments_p)[0] = shared_segment; + + memfile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, requested_size, + create_name_with_username(ACCEL_FILEMAP_NAME)); + err = GetLastError(); + if(memfile == NULL) { + zend_win_error_message(ACCEL_LOG_FATAL, "Unable to create file mapping", err); + *error_in = "CreateFileMapping"; + return ALLOC_FAILURE; + } + + /* Starting from windows Vista, heap randomization occurs which might cause our mapping base to + be taken (fail to map). So under Vista, we try to map into a hard coded predefined addresses + in high memory. */ + if (!ZCG(accel_directives).mmap_base || !*ZCG(accel_directives).mmap_base) { + do { + OSVERSIONINFOEX osvi; + SYSTEM_INFO si; + + ZeroMemory(&si, sizeof(SYSTEM_INFO)); + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + if (! GetVersionEx ((OSVERSIONINFO *) &osvi)) { + osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) + break; + } + + GetSystemInfo(&si); + + /* Are we running Vista ? */ + if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion == 6 ) { + /* Assert that platform is 32 bit (for 64 bit we need to test a different set */ + if(si.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL) + DebugBreak(); + + wanted_mapping_base = vista_mapping_base_set; + } + } while (0); + } else { + char *s = ZCG(accel_directives).mmap_base; + + /* skip leading 0x, %p assumes hexdeciaml format anyway */ + if (*s == '0' && *(s+1) == 'x') { + s += 2; + } + if (sscanf(s, "%p", &default_mapping_base_set[0]) != 1) { + zend_win_error_message(ACCEL_LOG_FATAL, "Bad mapping address specified in zend_optimizerplus.mmap_base", err); + return ALLOC_FAILURE; + } + } + + do { + shared_segment->p = mapping_base = MapViewOfFileEx(memfile, FILE_MAP_ALL_ACCESS, 0, 0, 0, *wanted_mapping_base); + if(*wanted_mapping_base == NULL) /* Auto address (NULL) is the last option on the array */ + break; + wanted_mapping_base++; + } while (!mapping_base); + + err = GetLastError(); + if(mapping_base == NULL) { + zend_win_error_message(ACCEL_LOG_FATAL, "Unable to create view for file mapping", err); + *error_in = "MapViewOfFile"; + return ALLOC_FAILURE; + } else { + char *mmap_base_file = get_mmap_base_file(); + FILE *fp = fopen(mmap_base_file, "w"); + err = GetLastError(); + if(!fp) { + zend_win_error_message(ACCEL_LOG_WARNING, mmap_base_file, err); + zend_win_error_message(ACCEL_LOG_FATAL, "Unable to write base address", err); + } + fprintf(fp, "%p\n", mapping_base); + fclose(fp); + } + + shared_segment->pos = 0; + shared_segment->size = requested_size; + + return ALLOC_SUCCESS; +} + +static int detach_segment(zend_shared_segment *shared_segment) +{ + if(mapping_base) { + UnmapViewOfFile(mapping_base); + } + CloseHandle(memfile); + ReleaseMutex(memory_mutex); + CloseHandle(memory_mutex); + return 0; +} + +static size_t segment_type_size(void) +{ + return sizeof(zend_shared_segment); +} + +zend_shared_memory_handlers zend_alloc_win32_handlers = { + create_segments, + detach_segment, + segment_type_size +}; diff --git a/zend_accelerator_blacklist.c b/zend_accelerator_blacklist.c new file mode 100644 index 00000000000..7ceadeacf39 --- /dev/null +++ b/zend_accelerator_blacklist.c @@ -0,0 +1,241 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#include "main/php.h" +#include "main/fopen_wrappers.h" +#include "ZendAccelerator.h" +#include "zend_accelerator_blacklist.h" + +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO +# include "ext/ereg/php_regex.h" +#else +# include "main/php_regex.h" +#endif + +#ifdef ZEND_WIN32 +# define REGEX_MODE (REG_EXTENDED|REG_NOSUB|REG_ICASE) +#else +# define REGEX_MODE (REG_EXTENDED|REG_NOSUB) +#endif + +#define ZEND_BLACKLIST_BLOCK_SIZE 32 + +struct _zend_regexp_list { + regex_t comp_regex; + zend_regexp_list *next; +}; + +zend_blacklist accel_blacklist; + +void zend_accel_blacklist_init(zend_blacklist *blacklist) +{ + blacklist->pos = 0; + blacklist->size = ZEND_BLACKLIST_BLOCK_SIZE; + + if( blacklist->entries != NULL ){ + zend_accel_blacklist_shutdown(blacklist); + } + + blacklist->entries = (zend_blacklist_entry *) calloc(sizeof(zend_blacklist_entry), blacklist->size); + blacklist->regexp_list = NULL; +} + +static void blacklist_report_regexp_error(regex_t *comp_regex, int reg_err) +{ + char *errbuf; + int errsize = regerror(reg_err, comp_regex, NULL, 0); + errbuf = malloc(errsize); + + regerror(reg_err, comp_regex, errbuf, errsize); + zend_accel_error(ACCEL_LOG_ERROR, "Blacklist compilation: %s\n", errbuf); + free(errbuf); +} + +static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist) +{ + int i, end=0, j, rlen=6, clen, reg_err; + char *regexp; + zend_regexp_list **regexp_list_it; + + if (blacklist->pos == 0) { + /* we have no blacklist to talk about */ + return; + } + + regexp_list_it = &(blacklist->regexp_list); + for (i=0; ipos; i++) { + rlen += blacklist->entries[i].path_length*2+2; + + /* don't create a regexp buffer bigger than 12K)*/ + if((i+1 == blacklist->pos) || ((rlen+blacklist->entries[i+1].path_length*2+2)>(12*1024) ) ) { + regexp = (char *)malloc(rlen); + regexp[0] = '^'; + regexp[1] = '('; + + clen=2; + for (j=end; j<=i ;j++) { + + int c; + if (j!=end) { + regexp[clen++] = '|'; + } + /* copy mangled filename */ + for(c=0; centries[j].path_length; c++) { + if(strchr("^.[]$()|*+?{}\\", blacklist->entries[j].path[c])) { + regexp[clen++] = '\\'; + } + regexp[clen++] = blacklist->entries[j].path[c]; + } + } + regexp[clen++] = ')'; + regexp[clen] = '\0'; + + (*regexp_list_it) = malloc(sizeof(zend_regexp_list)); + (*regexp_list_it)->next = NULL; + + if ((reg_err = regcomp(&((*regexp_list_it)->comp_regex), regexp, REGEX_MODE)) != 0) { + blacklist_report_regexp_error(&((*regexp_list_it)->comp_regex), reg_err); + } + /* prepare for the next iteration */ + free(regexp); + end = i+1; + rlen = 6; + regexp_list_it = &((*regexp_list_it)->next); + } + } +} + +void zend_accel_blacklist_shutdown(zend_blacklist *blacklist) +{ + zend_blacklist_entry *p = blacklist->entries, *end = blacklist->entries + blacklist->pos; + + while (ppath); + p++; + } + free(blacklist->entries); + blacklist->entries = NULL; + if (blacklist->regexp_list) { + zend_regexp_list *temp, *it = blacklist->regexp_list; + while( it ){ + regfree(&it->comp_regex); + temp = it; + it = it->next; + free(temp); + } + } +} + +static inline void zend_accel_blacklist_allocate(zend_blacklist *blacklist) +{ + if (blacklist->pos==blacklist->size) { + blacklist->size += ZEND_BLACKLIST_BLOCK_SIZE; + blacklist->entries = (zend_blacklist_entry *) realloc(blacklist->entries, sizeof(zend_blacklist_entry)*blacklist->size); + } +} + +void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename) +{ + char buf[MAXPATHLEN+1], real_path[MAXPATHLEN+1]; + FILE *fp; + int path_length; + TSRMLS_FETCH(); + + if ((fp=fopen(filename, "r"))==NULL) { + zend_accel_error(ACCEL_LOG_WARNING, "Cannot load blacklist file: %s\n", filename); + return; + } + + zend_accel_error(ACCEL_LOG_DEBUG,"Loading blacklist file: '%s'", filename); + + memset(buf, 0, sizeof(buf)); + memset(real_path, 0, sizeof(real_path)); + + while (fgets(buf, MAXPATHLEN, fp)!=NULL) { + char *path_dup, *pbuf; + path_length = strlen(buf); + if (buf[path_length-1]=='\n') { + buf[--path_length] = 0; + if (buf[path_length-1]=='\r') { + buf[--path_length] = 0; + } + } + + /* Strip ctrl-m prefix */ + pbuf = &buf[0]; + while(*pbuf == '\r') { + *pbuf++ = 0; + path_length--; + } + + /* strip \" */ + if( pbuf[0] == '\"' && pbuf[path_length-1]== '\"' ){ + *pbuf++ = 0; + path_length-=2; + } + + if (path_length==0) { + continue; + } + + path_dup = zend_strndup(pbuf, path_length); + expand_filepath(path_dup, real_path TSRMLS_CC); + path_length = strlen(real_path); + + free(path_dup); + + zend_accel_blacklist_allocate(blacklist); + blacklist->entries[blacklist->pos].path_length = path_length; + blacklist->entries[blacklist->pos].path = (char *) malloc(path_length+1); + blacklist->entries[blacklist->pos].id = blacklist->pos; + memcpy(blacklist->entries[blacklist->pos].path, real_path, path_length+1); + blacklist->pos++; + } + fclose(fp); + zend_accel_blacklist_update_regexp(blacklist); +} + +zend_bool zend_accel_blacklist_is_blacklisted(zend_blacklist *blacklist, char *verify_path) +{ + int ret = 0; + zend_regexp_list *regexp_list_it = blacklist->regexp_list; + + if (regexp_list_it == NULL) { + return 0; + } + while (regexp_list_it != NULL) { + if (regexec(&(regexp_list_it->comp_regex), verify_path, 0, NULL, 0) == 0) { + ret = 1; + break; + } + regexp_list_it = regexp_list_it->next; + } + return ret; +} + +void zend_accel_blacklist_apply(zend_blacklist *blacklist, apply_func_arg_t func, void *argument TSRMLS_DC) +{ + int i; + + for(i=0; ipos; i++) { + func(&blacklist->entries[i], argument TSRMLS_CC); + } +} diff --git a/zend_accelerator_blacklist.h b/zend_accelerator_blacklist.h new file mode 100644 index 00000000000..5d7730f4701 --- /dev/null +++ b/zend_accelerator_blacklist.h @@ -0,0 +1,49 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_ACCELERATOR_BLACKLIST_H +#define ZEND_ACCELERATOR_BLACKLIST_H + +typedef struct _zend_regexp_list zend_regexp_list; + +typedef struct _zend_blacklist_entry { + char *path; + int path_length; + int id; +} zend_blacklist_entry; + +typedef struct _zend_blacklist { + zend_blacklist_entry *entries; + int size; + int pos; + zend_regexp_list *regexp_list; +} zend_blacklist; + +extern zend_blacklist accel_blacklist; + +void zend_accel_blacklist_init(zend_blacklist *blacklist); +void zend_accel_blacklist_shutdown(zend_blacklist *blacklist); + +void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename); +zend_bool zend_accel_blacklist_is_blacklisted(zend_blacklist *blacklist, char *verify_path); +void zend_accel_blacklist_apply(zend_blacklist *blacklist, apply_func_arg_t func, void *argument TSRMLS_DC); + +#endif /* ZEND_ACCELERATOR_BLACKLIST_H */ diff --git a/zend_accelerator_debug.c b/zend_accelerator_debug.c new file mode 100644 index 00000000000..8b2bd6241c8 --- /dev/null +++ b/zend_accelerator_debug.c @@ -0,0 +1,101 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#include +#include +#include +#include +#ifdef ZEND_WIN32 +# include +#endif +#include "ZendAccelerator.h" + +void zend_accel_error(int type, const char *format, ...) +{ + va_list args; + time_t timestamp; + char *time_string; + FILE * fLog = NULL; + TSRMLS_FETCH(); + + if (type > ZCG(accel_directives).log_verbosity_level) { + return; + } + + timestamp = time(NULL); + time_string = asctime(localtime(×tamp)); + time_string[24] = 0; + + if (!ZCG(accel_directives).error_log || + !*ZCG(accel_directives).error_log || + strcmp(ZCG(accel_directives).error_log, "stderr") == 0) { + + fLog = stderr; + } else { + fLog = fopen(ZCG(accel_directives).error_log, "a+"); + if (!fLog) { + fLog = stderr; + } + } + + fprintf(fLog, "%s (%d): ", time_string, +#ifdef ZTS + tsrm_thread_id() +#else + getpid() +#endif + ); + + switch (type) { + case ACCEL_LOG_FATAL: + fprintf(fLog, "Fatal Error "); + break; + case ACCEL_LOG_ERROR: + fprintf(fLog, "Error "); + break; + case ACCEL_LOG_WARNING: + fprintf(fLog, "Warning "); + break; + case ACCEL_LOG_INFO: + fprintf(fLog, "Message "); + break; + case ACCEL_LOG_DEBUG: + fprintf(fLog, "Debug "); + break; + } + + va_start(args, format); + vfprintf(fLog, format, args); + va_end(args); + fprintf(fLog, "\n"); + switch (type) { + case ACCEL_LOG_ERROR: + zend_bailout(); + break; + case ACCEL_LOG_FATAL: + exit(-2); + break; + } + fflush(fLog); + if (fLog != stderr) { + fclose(fLog); + } +} diff --git a/zend_accelerator_debug.h b/zend_accelerator_debug.h new file mode 100644 index 00000000000..8d0d7320bf5 --- /dev/null +++ b/zend_accelerator_debug.h @@ -0,0 +1,33 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_ACCELERATOR_DEBUG_H +#define ZEND_ACCELERATOR_DEBUG_H + +#define ACCEL_LOG_FATAL 0 +#define ACCEL_LOG_ERROR 1 +#define ACCEL_LOG_WARNING 2 +#define ACCEL_LOG_INFO 3 +#define ACCEL_LOG_DEBUG 4 + +void zend_accel_error(int type, const char *format, ...); + +#endif /* _ZEND_ACCELERATOR_DEBUG_H */ diff --git a/zend_accelerator_hash.c b/zend_accelerator_hash.c new file mode 100644 index 00000000000..8257ac2e52d --- /dev/null +++ b/zend_accelerator_hash.c @@ -0,0 +1,222 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#include "ZendAccelerator.h" +#include "zend_accelerator_hash.h" +#include "zend_hash.h" +#include "zend_shared_alloc.h" + +/* Generated on an Octa-ALPHA 300MHz CPU & 2.5GB RAM monster */ +static uint prime_numbers[] = + {5, 11, 19, 53, 107, 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987, 262237, 524521, 1048793 }; +static uint num_prime_numbers = sizeof(prime_numbers) / sizeof(uint); + +void zend_accel_hash_clean(zend_accel_hash *accel_hash) +{ + accel_hash->num_entries = 0; + accel_hash->num_direct_entries = 0; + memset(accel_hash->hash_table, 0, sizeof(zend_accel_hash_entry *)*accel_hash->max_num_entries); +} + +void zend_accel_hash_init(zend_accel_hash *accel_hash, zend_uint hash_size) +{ + uint i; + + for (i=0; inum_entries = 0; + accel_hash->num_direct_entries = 0; + accel_hash->max_num_entries = hash_size; + + /* set up hash pointers table */ + accel_hash->hash_table = zend_shared_alloc(sizeof(zend_accel_hash_entry *)*accel_hash->max_num_entries); + if (!accel_hash->hash_table) { + zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!"); + } + + /* set up hash values table */ + accel_hash->hash_entries = zend_shared_alloc(sizeof(zend_accel_hash_entry)*accel_hash->max_num_entries); + if (!accel_hash->hash_entries) { + zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!"); + } + memset(accel_hash->hash_table, 0, sizeof(zend_accel_hash_entry *)*accel_hash->max_num_entries); +} + +/* Returns NULL if hash is full + * Returns pointer the actual hash entry on success + * key needs to be already allocated as it is not copied + */ +zend_accel_hash_entry* zend_accel_hash_update(zend_accel_hash *accel_hash, char *key, zend_uint key_length, zend_bool indirect, void *data) +{ + zend_ulong hash_value; + zend_ulong index; + zend_accel_hash_entry *entry; + zend_accel_hash_entry *indirect_bucket = NULL; + + if (indirect) { + indirect_bucket = (zend_accel_hash_entry*)data; + while (indirect_bucket->indirect) { + indirect_bucket = (zend_accel_hash_entry*)indirect_bucket->data; + } + } + + hash_value = zend_inline_hash_func(key, key_length); + index = hash_value % accel_hash->max_num_entries; + + /* try to see if the element already exists in the hash */ + entry = accel_hash->hash_table[index]; + while (entry) { + if (entry->hash_value == hash_value + && entry->key_length == key_length + && !memcmp(entry->key, key, key_length)) { + + if (entry->indirect) { + if (indirect_bucket) { + entry->data = indirect_bucket; + } else { + ((zend_accel_hash_entry*)entry->data)->data = data; + } + } else { + if (indirect_bucket) { + accel_hash->num_direct_entries--; + entry->data = indirect_bucket; + entry->indirect = 1; + } else { + entry->data = data; + } + } + return entry; + } + entry = entry->next; + } + + /* Does not exist, add a new entry */ + if (accel_hash->num_entries == accel_hash->max_num_entries) { + return NULL; + } + + entry = &accel_hash->hash_entries[accel_hash->num_entries++]; + if (indirect) { + entry->data = indirect_bucket; + entry->indirect = 1; + } else { + accel_hash->num_direct_entries++; + entry->data = data; + entry->indirect = 0; + } + entry->hash_value = hash_value; + entry->key = key; + entry->key_length = key_length; + entry->next = accel_hash->hash_table[index]; + accel_hash->hash_table[index] = entry; + return entry; +} + +/* Returns the data associated with key on success + * Returns NULL if data doesn't exist + */ +void* zend_accel_hash_find(zend_accel_hash *accel_hash, char *key, zend_uint key_length) +{ + zend_ulong hash_value; + zend_ulong index; + zend_accel_hash_entry *entry; + + hash_value = zend_inline_hash_func(key, key_length); + index = hash_value % accel_hash->max_num_entries; + + entry = accel_hash->hash_table[index]; + while (entry) { + if (entry->hash_value == hash_value + && entry->key_length == key_length + && !memcmp(entry->key, key, key_length)) { + if (entry->indirect) { + return ((zend_accel_hash_entry *) entry->data)->data; + } else { + return entry->data; + } + } + entry = entry->next; + } + return NULL; +} + +/* Returns the hash entry associated with key on success + * Returns NULL if it doesn't exist + */ +zend_accel_hash_entry* zend_accel_hash_find_entry(zend_accel_hash *accel_hash, char *key, zend_uint key_length) +{ + zend_ulong hash_value; + zend_ulong index; + zend_accel_hash_entry *entry; + + hash_value = zend_inline_hash_func(key, key_length); + index = hash_value % accel_hash->max_num_entries; + + entry = accel_hash->hash_table[index]; + while (entry) { + if (entry->hash_value == hash_value + && entry->key_length == key_length + && !memcmp(entry->key, key, key_length)) { + if (entry->indirect) { + return (zend_accel_hash_entry *) entry->data; + } else { + return entry; + } + } + entry = entry->next; + } + return NULL; +} + +int zend_accel_hash_unlink(zend_accel_hash *accel_hash, char *key, zend_uint key_length) +{ + zend_ulong hash_value; + zend_ulong index; + zend_accel_hash_entry *entry, *last_entry=NULL; + + hash_value = zend_inline_hash_func(key, key_length); + index = hash_value % accel_hash->max_num_entries; + + entry = accel_hash->hash_table[index]; + while (entry) { + if (entry->hash_value == hash_value + && entry->key_length == key_length + && !memcmp(entry->key, key, key_length)) { + if (!entry->indirect) { + accel_hash->num_direct_entries--; + } + if (last_entry) { + last_entry->next = entry->next; + } else { + accel_hash->hash_table[index] = entry->next; + } + return SUCCESS; + } + last_entry = entry; + entry = entry->next; + } + return FAILURE; +} diff --git a/zend_accelerator_hash.h b/zend_accelerator_hash.h new file mode 100644 index 00000000000..4673a5e425a --- /dev/null +++ b/zend_accelerator_hash.h @@ -0,0 +1,98 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_ACCELERATOR_HASH_H +#define ZEND_ACCELERATOR_HASH_H + +#include "zend.h" + +/* + zend_accel_hash - is a hash table allocated in shared memory and + distributed across simultaneously running processes. The hash tables have + fixed sizen selected during construction by zend_accel_hash_init(). All the + hash entries are preallocated in the 'hash_entries' array. 'num_entries' is + initialized by zero and grows when new data is added. + zend_accel_hash_update() just takes the next entry from 'hash_entries' + array and puts it into appropriate place of 'hash_table'. + Hash collisions are resolved by separate chaining with linked lists, + however, entries are still taken from the same 'hash_entries' array. + 'key' and 'data' passed to zend_accel_hash_update() must be already + allocated in shared memory. Few keys may be resolved to the same data. + using 'indirect' emtries, that point to other entries ('data' is actually + a pointer to another zend_accel_hash_entry). + zend_accel_hash_update() requires exclusive lock, however, + zend_accel_hash_find() does not. +*/ + +typedef struct _zend_accel_hash_entry zend_accel_hash_entry; + +struct _zend_accel_hash_entry { + zend_ulong hash_value; + char *key; + zend_uint key_length; + zend_accel_hash_entry *next; + void *data; + zend_bool indirect; +}; + +typedef struct _zend_accel_hash { + zend_accel_hash_entry **hash_table; + zend_accel_hash_entry *hash_entries; + zend_uint num_entries; + zend_uint max_num_entries; + zend_uint num_direct_entries; +} zend_accel_hash; + +void zend_accel_hash_init(zend_accel_hash *accel_hash, zend_uint hash_size); +void zend_accel_hash_clean(zend_accel_hash *accel_hash); + +zend_accel_hash_entry* zend_accel_hash_update( + zend_accel_hash *accel_hash, + char *key, + zend_uint key_length, + zend_bool indirect, + void *data); + +void* zend_accel_hash_find( + zend_accel_hash *accel_hash, + char *key, + zend_uint key_length); + +zend_accel_hash_entry* zend_accel_hash_find_entry( + zend_accel_hash *accel_hash, + char *key, + zend_uint key_length); + +int zend_accel_hash_unlink( + zend_accel_hash *accel_hash, + char *key, + zend_uint key_length); + +static inline zend_bool zend_accel_hash_is_full(zend_accel_hash *accel_hash) +{ + if (accel_hash->num_entries == accel_hash->max_num_entries) { + return 1; + } else { + return 0; + } +} + +#endif /* ZEND_ACCELERATOR_HASH_H */ diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c new file mode 100644 index 00000000000..b1c90a0eace --- /dev/null +++ b/zend_accelerator_module.c @@ -0,0 +1,574 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#include + +#include "php.h" +#include "ZendAccelerator.h" +#include "zend_API.h" +#include "zend_shared_alloc.h" +#include "zend_accelerator_blacklist.h" +#include "php_ini.h" +#include "SAPI.h" +#include "TSRM/tsrm_virtual_cwd.h" +#include "ext/standard/info.h" +#include "ext/standard/php_filestat.h" + +#define STRING_NOT_NULL(s) (NULL == (s)?"":s) +#define MIN_ACCEL_FILES 200 +#define MAX_ACCEL_FILES 100000 +#define TOKENTOSTR(X) #X + +/* User functions */ +static ZEND_FUNCTION(accelerator_reset); + +/* Private functions */ +static ZEND_FUNCTION(accelerator_get_status); +static ZEND_FUNCTION(accelerator_get_configuration); + +static zend_function_entry accel_functions[] = { + /* User functions */ + ZEND_FE(accelerator_reset, NULL) + /* Private functions */ + ZEND_FE(accelerator_get_configuration, NULL) + ZEND_FE(accelerator_get_status, NULL) + { NULL, NULL, NULL, 0, 0 } +}; + +static ZEND_INI_MH(OnUpdateMemoryConsumption) +{ + long *p; + long memsize; +#ifndef ZTS + char *base = (char *) mh_arg2; +#else + char *base = (char *) ts_resource(*((int *) mh_arg2)); +#endif + + /* keep the compiler happy */ + (void)entry; (void)new_value_length; (void)mh_arg2; (void)mh_arg3; (void)stage; + + p = (long *) (base+(size_t) mh_arg1); + memsize = atoi(new_value); + /* sanity check we must use at least 8 MB */ + if (memsize < 8) { + const char *new_new_value = "8"; + zend_ini_entry *ini_entry; + + memsize = 8; + zend_accel_error(ACCEL_LOG_WARNING,"zend_optimizerplus.memory_consumption is set below the required 8MB.\n" ); + zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the minimal 8MB cofiguration.\n" ); + + if (zend_hash_find(EG(ini_directives), + "zend_optimizerplus.memory_consumption", + sizeof("zend_optimizerplus.memory_consumption"), + (void *) &ini_entry)==FAILURE) { + return FAILURE; + } + + ini_entry->value = strdup(new_new_value); + ini_entry->value_length = strlen(new_new_value); + } + *p = memsize * (1024 * 1024); + return SUCCESS; +} + +static ZEND_INI_MH(OnUpdateMaxAcceleratedFiles) +{ + long *p; + long size; +#ifndef ZTS + char *base = (char *) mh_arg2; +#else + char *base = (char *) ts_resource(*((int *) mh_arg2)); +#endif + + /* keep the compiler happy */ + (void)entry; (void)new_value_length; (void)mh_arg2; (void)mh_arg3; (void)stage; + + p = (long *) (base+(size_t) mh_arg1); + size = atoi(new_value); + /* sanity check we must use a value between MIN_ACCEL_FILES and MAX_ACCEL_FILES */ + + if (size < MIN_ACCEL_FILES || size > MAX_ACCEL_FILES) { + const char *new_new_value; + zend_ini_entry *ini_entry; + + if(size < MIN_ACCEL_FILES){ + size = MIN_ACCEL_FILES; + new_new_value = TOKENTOSTR(MIN_ACCEL_FILES); + zend_accel_error(ACCEL_LOG_WARNING,"zend_optimizerplus.max_accelerated_files is set below the required minimum (%d).\n", MIN_ACCEL_FILES ); + zend_accel_error(ACCEL_LOG_WARNING,ACCELERATOR_PRODUCT_NAME " will use the minimal cofiguration.\n" ); + } + if(size > MAX_ACCEL_FILES){ + size = MAX_ACCEL_FILES; + new_new_value = TOKENTOSTR(MAX_ACCEL_FILES); + zend_accel_error(ACCEL_LOG_WARNING,"zend_optimizerplus.max_accelerated_files is set above the limit (%d).\n", MAX_ACCEL_FILES ); + zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the maximal cofiguration.\n" ); + } + if (zend_hash_find(EG(ini_directives), + "zend_optimizerplus.max_accelerated_files", + sizeof("zend_optimizerplus.max_accelerated_files"), + (void *) &ini_entry)==FAILURE) { + return FAILURE; + } + ini_entry->value = strdup(new_new_value); + ini_entry->value_length = strlen(new_new_value); + } + *p = size; + return SUCCESS; +} + +static ZEND_INI_MH(OnUpdateMaxWastedPercentage) +{ + double *p; + long percentage; +#ifndef ZTS + char *base = (char *) mh_arg2; +#else + char *base = (char *) ts_resource(*((int *) mh_arg2)); +#endif + + /* keep the compiler happy */ + (void)entry; (void)new_value_length; (void)mh_arg2; (void)mh_arg3; (void)stage; + + p = (double *) (base+(size_t) mh_arg1); + percentage = atoi(new_value); + + if (percentage <= 0 || percentage > 50) { + const char *new_new_value = "5"; + zend_ini_entry *ini_entry; + + percentage = 5; + zend_accel_error(ACCEL_LOG_WARNING,"zend_optimizerplus.max_wasted_percentage must be ser netweeb 1 and 50.\n"); + zend_accel_error(ACCEL_LOG_WARNING,ACCELERATOR_PRODUCT_NAME " will use 5%.\n" ); + if (zend_hash_find(EG(ini_directives), + "zend_optimizerplus.max_wasted_percentage", + sizeof("zend_optimizerplus.max_wasted_percentage"), + (void *) &ini_entry)==FAILURE) { + return FAILURE; + } + ini_entry->value = strdup(new_new_value); + ini_entry->value_length = strlen(new_new_value); + } + *p = (double)percentage / 100.0; + return SUCCESS; +} + +static ZEND_INI_MH(OnUpdateAccelBlacklist) +{ + char **p; +#ifndef ZTS + char *base = (char *) mh_arg2; +#else + char *base = (char *) ts_resource(*((int *) mh_arg2)); +#endif + + /* keep the compiler happy */ + (void)entry; (void)new_value_length; (void)mh_arg2; (void)mh_arg3; (void)stage; + + if (new_value && !new_value[0]) { + return FAILURE; + } + + p = (char **) (base+(size_t) mh_arg1); + *p = new_value; + + zend_accel_blacklist_init(&accel_blacklist); + zend_accel_blacklist_load(&accel_blacklist, *p); + + return SUCCESS; +} + +ZEND_INI_BEGIN() + STD_PHP_INI_BOOLEAN("zend_optimizerplus.enable" ,"1", PHP_INI_SYSTEM, OnUpdateBool, enabled , zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("zend_optimizerplus.use_cwd" ,"1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.use_cwd , zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("zend_optimizerplus.validate_timestamps","1", PHP_INI_ALL , OnUpdateBool, accel_directives.validate_timestamps, zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("zend_optimizerplus.inherited_hack" ,"1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.inherited_hack , zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("zend_optimizerplus.dups_fix" ,"0", PHP_INI_ALL , OnUpdateBool, accel_directives.ignore_dups , zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("zend_optimizerplus.revalidate_path" ,"0", PHP_INI_ALL , OnUpdateBool, accel_directives.revalidate_path , zend_accel_globals, accel_globals) + + STD_PHP_INI_ENTRY("zend_optimizerplus.log_verbosity_level" , "1" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.log_verbosity_level, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("zend_optimizerplus.memory_consumption" , "64" , PHP_INI_SYSTEM, OnUpdateMemoryConsumption, accel_directives.memory_consumption, zend_accel_globals, accel_globals) +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + STD_PHP_INI_ENTRY("zend_optimizerplus.interned_strings_buffer", "4" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.interned_strings_buffer, zend_accel_globals, accel_globals) +#endif + STD_PHP_INI_ENTRY("zend_optimizerplus.max_accelerated_files" , "2000", PHP_INI_SYSTEM, OnUpdateMaxAcceleratedFiles, accel_directives.max_accelerated_files, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("zend_optimizerplus.max_wasted_percentage" , "5" , PHP_INI_SYSTEM, OnUpdateMaxWastedPercentage, accel_directives.max_wasted_percentage, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("zend_optimizerplus.consistency_checks" , "0" , PHP_INI_ALL , OnUpdateLong, accel_directives.consistency_checks, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("zend_optimizerplus.force_restart_timeout" , "180" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.force_restart_timeout, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("zend_optimizerplus.revalidate_freq" , "2" , PHP_INI_ALL , OnUpdateLong, accel_directives.revalidate_freq, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("zend_optimizerplus.preferred_memory_model", "" , PHP_INI_SYSTEM, OnUpdateStringUnempty, accel_directives.memory_model, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("zend_optimizerplus.blacklist_filename" , "" , PHP_INI_SYSTEM, OnUpdateAccelBlacklist, accel_directives.user_blacklist_filename, zend_accel_globals, accel_globals) + + STD_PHP_INI_ENTRY("zend_optimizerplus.protect_memory" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.protect_memory, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("zend_optimizerplus.save_comments" , "1" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.save_comments, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("zend_optimizerplus.fast_shutdown" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.fast_shutdown, zend_accel_globals, accel_globals) + + STD_PHP_INI_ENTRY("zend_optimizerplus.optimization_level" , DEFAULT_OPTIMIZATION_LEVEL , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.optimization_level, zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("zend_optimizerplus.enable_file_override" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.file_override_enabled, zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("zend_optimizerplus.enable_cli" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.enable_cli, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("zend_optimizerplus.error_log" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.error_log, zend_accel_globals, accel_globals) + +#ifdef ZEND_WIN32 + STD_PHP_INI_ENTRY("zend_optimizerplus.mmap_base", NULL, PHP_INI_SYSTEM, OnUpdateString, accel_directives.mmap_base, zend_accel_globals, accel_globals) +#endif +ZEND_INI_END() + +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + +#undef EX +#define EX(element) execute_data->element +#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset)) + +static int ZEND_DECLARE_INHERITED_CLASS_DELAYED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_class_entry **pce, **pce_orig; + + if (zend_hash_find(EG(class_table), Z_STRVAL(EX(opline)->op2.u.constant), Z_STRLEN(EX(opline)->op2.u.constant)+1, (void **)&pce) == FAILURE || + (zend_hash_find(EG(class_table), Z_STRVAL(EX(opline)->op1.u.constant), Z_STRLEN(EX(opline)->op1.u.constant), (void**)&pce_orig) == SUCCESS && + *pce != *pce_orig)) { + do_bind_inherited_class(EX(opline), EG(class_table), EX_T(EX(opline)->extended_value).class_entry, 0 TSRMLS_CC); + } + EX(opline)++; + return ZEND_USER_OPCODE_CONTINUE; +} +#endif + +static int filename_is_in_cache(char *filename, int filename_len TSRMLS_DC) +{ + char *key; + int key_length; + zend_file_handle handle = {0}; + zend_persistent_script *persistent_script; + + handle.filename = filename; + handle.type = ZEND_HANDLE_FILENAME; + + if (IS_ABSOLUTE_PATH(filename, filename_len)) { + persistent_script = zend_accel_hash_find(&ZCSG(hash), filename, filename_len+1); + if (persistent_script) { + return !persistent_script->corrupted; + } + } + + if((key = accel_make_persistent_key_ex(&handle, filename_len, &key_length TSRMLS_CC)) != NULL) { + persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length+1); + return persistent_script && !persistent_script->corrupted; + } + + return 0; +} + +static void accel_file_in_cache(int type, INTERNAL_FUNCTION_PARAMETERS) +{ + char *filename; + int filename_len; +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + zval **zfilename; + + if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &zfilename) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string_ex(zfilename); + filename = Z_STRVAL_PP(zfilename); + filename_len = Z_STRLEN_PP(zfilename); +#else + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) { + return; + } +#endif + if(filename_len > 0) { + if(filename_is_in_cache(filename, filename_len TSRMLS_CC)) { + RETURN_TRUE; + } + } + + php_stat(filename, filename_len, type, return_value TSRMLS_CC); +} + +static void accel_file_exists(INTERNAL_FUNCTION_PARAMETERS) +{ + accel_file_in_cache(FS_EXISTS, INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static void accel_is_file(INTERNAL_FUNCTION_PARAMETERS) +{ + accel_file_in_cache(FS_IS_FILE, INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static void accel_is_readable(INTERNAL_FUNCTION_PARAMETERS) +{ + accel_file_in_cache(FS_IS_R, INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static ZEND_MINIT_FUNCTION(zend_accelerator) +{ + (void)type; /* keep the compiler happy */ + + /* must be 0 before the ini entry OnUpdate function is called */ + accel_blacklist.entries = NULL; + + REGISTER_INI_ENTRIES(); +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + zend_set_user_opcode_handler(ZEND_DECLARE_INHERITED_CLASS_DELAYED, ZEND_DECLARE_INHERITED_CLASS_DELAYED_HANDLER); +#endif + return SUCCESS; +} + +void zend_accel_override_file_functions(TSRMLS_D) +{ + zend_function *old_function; + if(ZCG(startup_ok) && ZCG(accel_directives).file_override_enabled) { + /* override file_exists */ + if(zend_hash_find(CG(function_table), "file_exists", sizeof("file_exists"), (void **)&old_function) == SUCCESS) { + old_function->internal_function.handler = accel_file_exists; + } + if(zend_hash_find(CG(function_table), "is_file", sizeof("is_file"), (void **)&old_function) == SUCCESS) { + old_function->internal_function.handler = accel_is_file; + } + if(zend_hash_find(CG(function_table), "is_readable", sizeof("is_readable"), (void **)&old_function) == SUCCESS) { + old_function->internal_function.handler = accel_is_readable; + } + } +} + +static ZEND_MSHUTDOWN_FUNCTION(zend_accelerator) +{ + (void)type; /* keep the compiler happy */ + + UNREGISTER_INI_ENTRIES(); + return SUCCESS; +} + +void zend_accel_info(ZEND_MODULE_INFO_FUNC_ARGS) +{ + php_info_print_table_start(); + + if (ZCG(startup_ok) && ZCSG(accelerator_enabled)) { + php_info_print_table_row(2, "Opcode Caching", "Up and Running"); + } else { + php_info_print_table_row(2, "Opcode Caching", "Disabled"); + } + if (ZCG(enabled) && ZCG(accel_directives).optimization_level) { + php_info_print_table_row(2, "Optimization", "Enabled"); + } else { + php_info_print_table_row(2, "Optimization", "Disabled"); + } + if (!ZCG(startup_ok) || zps_api_failure_reason) { + php_info_print_table_row(2, "Startup Failed", zps_api_failure_reason); + } else { + php_info_print_table_row(2, "Startup", "OK"); + php_info_print_table_row(2, "Shared memory model", zend_accel_get_shared_model()); + } + + php_info_print_table_end(); + DISPLAY_INI_ENTRIES(); +} + +static zend_module_entry accel_module_entry = { + STANDARD_MODULE_HEADER, + ACCELERATOR_PRODUCT_NAME, + accel_functions, + ZEND_MINIT(zend_accelerator), + ZEND_MSHUTDOWN(zend_accelerator), + NULL, + NULL, + zend_accel_info, + ACCELERATOR_VERSION "FE", + STANDARD_MODULE_PROPERTIES +}; + +int start_accel_module() +{ + return zend_startup_module(&accel_module_entry); +} + +/* {{{ proto array accelerator_get_scripts() + Get the scripts which are accelerated by ZendAccelerator */ +static zval* accelerator_get_scripts(TSRMLS_D) +{ + uint i; + zval *return_value,*persistent_script_report; + zend_accel_hash_entry *cache_entry; + struct tm *ta; + struct timeval exec_time; + struct timeval fetch_time; + + if (!ZCG(startup_ok) || !ZCSG(accelerator_enabled) || accelerator_shm_read_lock(TSRMLS_C) != SUCCESS) { + return 0; + } + + MAKE_STD_ZVAL(return_value); + array_init(return_value); + for (i=0; inext) { + zend_persistent_script *script; + + if (cache_entry->indirect) continue; + + script = (zend_persistent_script *)cache_entry->data; + + MAKE_STD_ZVAL(persistent_script_report); + array_init(persistent_script_report); + add_assoc_stringl(persistent_script_report, "full_path", script->full_path, script->full_path_len, 1); + add_assoc_long(persistent_script_report, "hits", script->dynamic_members.hits); + add_assoc_long(persistent_script_report, "memory_consumption", script->dynamic_members.memory_consumption); + ta = localtime(&script->dynamic_members.last_used); + add_assoc_string(persistent_script_report, "last_used", asctime(ta), 1); + add_assoc_long(persistent_script_report, "last_used_timestamp", script->dynamic_members.last_used); + if (ZCG(accel_directives).validate_timestamps) { + add_assoc_long(persistent_script_report, "timestamp", (long)script->timestamp); + } + timerclear(&exec_time); + timerclear(&fetch_time); + + zend_hash_update(return_value->value.ht, cache_entry->key, cache_entry->key_length, &persistent_script_report, sizeof(zval *), NULL); + } + } + accelerator_shm_read_unlock(TSRMLS_C); + + return return_value; +} + +/* {{{ proto array accelerator_get_status() + Obtain statistics information regarding code acceleration in the Zend Performance Suite */ +static ZEND_FUNCTION(accelerator_get_status) +{ + long reqs; + zval *memory_usage,*statistics,*scripts; + + /* keep the compiler happy */ + (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; + + if (!ZCG(startup_ok) || !ZCSG(accelerator_enabled)) { + RETURN_FALSE; + } + + array_init(return_value); + + /* Trivia */ + add_assoc_long(return_value, "accelerator_enabled", ZCG(startup_ok) && ZCSG(accelerator_enabled)); + add_assoc_bool(return_value, "cache_full", ZSMMG(memory_exhausted)); + + /* Memory usage statistics */ + MAKE_STD_ZVAL(memory_usage); + array_init(memory_usage); + add_assoc_long(memory_usage, "used_memory", ZCG(accel_directives).memory_consumption-zend_shared_alloc_get_free_memory()-ZSMMG(wasted_shared_memory)); + add_assoc_long(memory_usage, "free_memory", zend_shared_alloc_get_free_memory()); + add_assoc_long(memory_usage, "wasted_memory", ZSMMG(wasted_shared_memory)); + add_assoc_double(memory_usage, "current_wasted_percentage", (((double) ZSMMG(wasted_shared_memory))/ZCG(accel_directives).memory_consumption)*100.0); + add_assoc_zval(return_value, "memory_usage",memory_usage); + + /* Accelerator statistics */ + MAKE_STD_ZVAL(statistics); + array_init(statistics); + add_assoc_long(statistics, "num_cached_scripts", ZCSG(hash).num_direct_entries); + add_assoc_long(statistics, "max_cached_scripts", ZCSG(hash).max_num_entries); + add_assoc_long(statistics, "hits", ZCSG(hits)); + add_assoc_long(statistics, "last_restart_time", ZCSG(last_restart_time)); + add_assoc_long(statistics, "misses", ZSMMG(memory_exhausted)?ZCSG(misses):ZCSG(misses)-ZCSG(blacklist_misses)); + add_assoc_long(statistics, "blacklist_misses", ZCSG(blacklist_misses)); + reqs = ZCSG(hits)+ZCSG(misses); + add_assoc_double(statistics, "blacklist_miss_ratio", reqs?(((double) ZCSG(blacklist_misses))/reqs)*100.0:0); + add_assoc_double(statistics, "accelerator_hit_rate", reqs?(((double) ZCSG(hits))/reqs)*100.0:0); + add_assoc_zval(return_value, "accelerator_statistics",statistics); + + /* acceleratred scripts */ + scripts=accelerator_get_scripts(TSRMLS_C); + if( scripts ){ + add_assoc_zval(return_value, "scripts",scripts); + } +} + +static int add_blacklist_path(zend_blacklist_entry *p, zval *return_value TSRMLS_DC) +{ + add_next_index_stringl(return_value, p->path, p->path_length, 1); + return 0; +} + +/* {{{ proto array accelerator_get_configuration() + Obtain configuration information for the Zend Performance Suite */ +static ZEND_FUNCTION(accelerator_get_configuration) +{ + zval *directives,*version,*blacklist; + + /* keep the compiler happy */ + (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; + + array_init(return_value); + + /* directives */ + MAKE_STD_ZVAL(directives); + array_init(directives); + add_assoc_bool(directives, "zend_optimizerplus.enable", ZCG(enabled)); + add_assoc_bool(directives, "zend_optimizerplus.use_cwd", ZCG(accel_directives).use_cwd); + add_assoc_bool(directives, "zend_optimizerplus.validate_timestamps", ZCG(accel_directives).validate_timestamps); + add_assoc_bool(directives, "zend_optimizerplus.inherited_hack", ZCG(accel_directives).inherited_hack); + add_assoc_bool(directives, "zend_optimizerplus.dups_fix", ZCG(accel_directives).ignore_dups); + add_assoc_bool(directives, "zend_optimizerplus.revalidate_path", ZCG(accel_directives).revalidate_path); + + add_assoc_long(directives, "zend_optimizerplus.log_verbosity_level", ZCG(accel_directives).log_verbosity_level); + add_assoc_long(directives, "zend_optimizerplus.memory_consumption", ZCG(accel_directives).memory_consumption); + add_assoc_long(directives, "zend_optimizerplus.max_accelerated_files", ZCG(accel_directives).max_accelerated_files); + add_assoc_double(directives, "zend_optimizerplus.max_wasted_percentage", ZCG(accel_directives).max_wasted_percentage); + add_assoc_long(directives, "zend_optimizerplus.consistency_checks", ZCG(accel_directives).consistency_checks); + add_assoc_long(directives, "zend_optimizerplus.force_restart_timeout", ZCG(accel_directives).force_restart_timeout); + add_assoc_long(directives, "zend_optimizerplus.revalidate_freq", ZCG(accel_directives).revalidate_freq); + add_assoc_string(directives, "zend_optimizerplus.preferred_memory_model", STRING_NOT_NULL(ZCG(accel_directives).memory_model), 1); + add_assoc_string(directives, "zend_optimizerplus.blacklist_filename", STRING_NOT_NULL(ZCG(accel_directives).user_blacklist_filename), 1); + + add_assoc_bool(directives, "zend_optimizerplus.protect_memory", ZCG(accel_directives).protect_memory); + add_assoc_bool(directives, "zend_optimizerplus.save_comments", ZCG(accel_directives).save_comments); + add_assoc_bool(directives, "zend_optimizerplus.fast_shutdown", ZCG(accel_directives).fast_shutdown); + + add_assoc_long(directives, "zend_optimizerplus.optimization_level", ZCG(accel_directives).optimization_level); + + add_assoc_zval(return_value,"directives",directives); + + /*version */ + MAKE_STD_ZVAL(version); + array_init(version); + add_assoc_string(version, "version", ACCELERATOR_VERSION, 1); + add_assoc_string(version, "accelerator_product_name", ACCELERATOR_PRODUCT_NAME, 1); + add_assoc_zval(return_value,"version",version); + + /* blacklist */ + MAKE_STD_ZVAL(blacklist); + array_init(blacklist); + zend_accel_blacklist_apply(&accel_blacklist, (apply_func_arg_t) add_blacklist_path, blacklist TSRMLS_CC); + add_assoc_zval(return_value,"blacklist",blacklist); +} + +/* {{{ proto void accelerator_reset() + Request that the contents of the Accelerator module in the ZPS be reset */ +static ZEND_FUNCTION(accelerator_reset) +{ + /* keep the compiler happy */ + (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; + + if (!ZCG(startup_ok) || !ZCSG(accelerator_enabled)) { + RETURN_FALSE; + } + + zend_accel_schedule_restart(TSRMLS_C); + RETURN_TRUE; +} diff --git a/zend_accelerator_module.h b/zend_accelerator_module.h new file mode 100644 index 00000000000..25ad4ae3fa8 --- /dev/null +++ b/zend_accelerator_module.h @@ -0,0 +1,28 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_ACCELERAROR_MODULE_H +#define ZEND_ACCELERATOR_MODULE_H + +int start_accel_module(); +void zend_accel_override_file_functions(TSRMLS_D); + +#endif /* _ZEND_ACCELERATOR_MODULE_H */ diff --git a/zend_accelerator_util_funcs.c b/zend_accelerator_util_funcs.c new file mode 100644 index 00000000000..275642bd218 --- /dev/null +++ b/zend_accelerator_util_funcs.c @@ -0,0 +1,1079 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#include "zend_API.h" +#include "zend_constants.h" +#include "zend_accelerator_util_funcs.h" +#include "zend_persist.h" +#include "zend_shared_alloc.h" + +#define ZEND_PROTECTED_REFCOUNT (1<<30) + +static zend_uint zend_accel_refcount = ZEND_PROTECTED_REFCOUNT; + +#if SIZEOF_SIZE_T <= SIZEOF_LONG +/* If sizeof(void*) == sizeof(ulong) we can use zend_hash index functions */ +# define accel_xlat_set(old, new) zend_hash_index_update(&ZCG(bind_hash), (ulong)(zend_uintptr_t)(old), &(new), sizeof(void*), NULL) +# define accel_xlat_get(old, new) zend_hash_index_find(&ZCG(bind_hash), (ulong)(zend_uintptr_t)(old), (void**)&(new)) +#else +# define accel_xlat_set(old, new) zend_hash_quick_add(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (ulong)(zend_uintptr_t)(old), (void**)&(new), sizeof(void*), NULL) +# define accel_xlat_get(old, new) zend_hash_quick_find(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (ulong)(zend_uintptr_t)(old), (void**)&(new)) +#endif + +typedef int (*id_function_t)(void *, void *); +typedef void (*unique_copy_ctor_func_t)(void *pElement); + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO +static const Bucket *uninitialized_bucket = NULL; +#endif + +static int zend_prepare_function_for_execution(zend_op_array *op_array); +static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind); + +static void zend_accel_destroy_zend_function(zend_function *function) +{ + TSRMLS_FETCH(); + + if (function->type == ZEND_USER_FUNCTION) { + if (function->op_array.static_variables) { + + efree(function->op_array.static_variables); + function->op_array.static_variables = NULL; + } + } + + destroy_zend_function(function TSRMLS_CC); +} + +static void zend_accel_destroy_zend_class(zend_class_entry **pce) +{ + zend_class_entry *ce = *pce; + + ce->function_table.pDestructor = (dtor_func_t) zend_accel_destroy_zend_function; + destroy_zend_class(pce); +} + +zend_persistent_script* create_persistent_script(void) +{ + zend_persistent_script *persistent_script = (zend_persistent_script *) emalloc(sizeof(zend_persistent_script)); + memset(persistent_script, 0, sizeof(zend_persistent_script)); + + zend_hash_init(&persistent_script->function_table, 100, NULL, (dtor_func_t) zend_accel_destroy_zend_function, 0); + /* class_table is usualy destroyed by free_persistent_script() that + * overrides destructor. ZEND_CLASS_DTOR may be used by standard + * PHP compiler + */ + zend_hash_init(&persistent_script->class_table, 10, NULL, ZEND_CLASS_DTOR, 0); + + return persistent_script; +} + +void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements) +{ + if (destroy_elements) { + persistent_script->function_table.pDestructor = (dtor_func_t)zend_accel_destroy_zend_function; + persistent_script->class_table.pDestructor = (dtor_func_t)zend_accel_destroy_zend_class; + } else { + persistent_script->function_table.pDestructor = NULL; + persistent_script->class_table.pDestructor = NULL; + } + + zend_hash_destroy(&persistent_script->function_table); + zend_hash_destroy(&persistent_script->class_table); + + if (persistent_script->full_path) { + efree(persistent_script->full_path); + } + + efree(persistent_script); +} + +static int is_not_internal_function(zend_function *function) +{ + return(function->type != ZEND_INTERNAL_FUNCTION); +} + +void zend_accel_free_user_functions(HashTable *ht TSRMLS_DC) +{ + dtor_func_t orig_dtor = ht->pDestructor; + + ht->pDestructor = NULL; + zend_hash_apply(ht, (apply_func_t) is_not_internal_function TSRMLS_CC); + ht->pDestructor = orig_dtor; +} + +static int move_user_function(zend_function *function TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) +{ + HashTable *function_table = va_arg(args, HashTable *); + (void)num_args; /* keep the compiler happy */ + + if (function->type==ZEND_USER_FUNCTION) { + zend_hash_quick_update(function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, function, sizeof(zend_function), NULL); + return 1; + } else { + return 0; + } +} + +void zend_accel_move_user_functions(HashTable *src, HashTable *dst TSRMLS_DC) +{ + dtor_func_t orig_dtor = src->pDestructor; + + src->pDestructor = NULL; + zend_hash_apply_with_arguments(src TSRMLS_CC, (apply_func_args_t)move_user_function, 1, dst); + src->pDestructor = orig_dtor; +} + +static int copy_internal_function(zend_function *function, HashTable *function_table TSRMLS_DC) +{ + if (function->type==ZEND_INTERNAL_FUNCTION) { + zend_hash_update(function_table, function->common.function_name, strlen(function->common.function_name)+1, function, sizeof(zend_function), NULL); + } + return 0; +} + +void zend_accel_copy_internal_functions(TSRMLS_D) +{ + zend_hash_apply_with_argument(CG(function_table), (apply_func_arg_t)copy_internal_function, &ZCG(function_table) TSRMLS_CC); + ZCG(internal_functions_count) = zend_hash_num_elements(&ZCG(function_table)); +} + +static void zend_destroy_property_info(zend_property_info *property_info) +{ + interned_efree((char*)property_info->name); + if(property_info->doc_comment){ + efree((char*)property_info->doc_comment); + } +} + +static inline zval* zend_clone_zval(zval *src, int bind TSRMLS_DC) +{ + zval *ret, **ret_ptr; + + if (!bind) { + ALLOC_ZVAL(ret); + *ret = *src; + INIT_PZVAL(ret); + } else if (Z_REFCOUNT_P(src) == 1) { + ALLOC_ZVAL(ret); + *ret = *src; + } else if (accel_xlat_get(src, ret_ptr) != SUCCESS) { + ALLOC_ZVAL(ret); + *ret = *src; + accel_xlat_set(src, ret); + } else { + return *ret_ptr; + } + +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + if ((Z_TYPE_P(ret) & IS_CONSTANT_TYPE_MASK) >= IS_ARRAY) { + switch ((Z_TYPE_P(ret) & IS_CONSTANT_TYPE_MASK)) { +#else + if ((Z_TYPE_P(ret) & ~IS_CONSTANT_INDEX) >= IS_ARRAY) { + switch ((Z_TYPE_P(ret) & ~IS_CONSTANT_INDEX)) { +#endif + case IS_STRING: + case IS_CONSTANT: + Z_STRVAL_P(ret) = (char *) interned_estrndup(Z_STRVAL_P(ret), Z_STRLEN_P(ret)); + break; + case IS_ARRAY: + case IS_CONSTANT_ARRAY: + if (ret->value.ht && ret->value.ht != &EG(symbol_table)) { + ALLOC_HASHTABLE(ret->value.ht); + zend_hash_clone_zval(ret->value.ht, src->value.ht, 0); + } + break; + } + } + return ret; +} + +static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind) +{ + Bucket *p, *q, **prev; + ulong nIndex; + zval *ppz; + TSRMLS_FETCH(); + + ht->nTableSize = source->nTableSize; + ht->nTableMask = source->nTableMask; + ht->nNumOfElements = source->nNumOfElements; + ht->nNextFreeElement = source->nNextFreeElement; + ht->pDestructor = ZVAL_PTR_DTOR; +#if ZEND_DEBUG + ht->inconsistent = 0; +#endif + ht->persistent = 0; + ht->arBuckets = NULL; + ht->pListHead = NULL; + ht->pListTail = NULL; + ht->pInternalPointer = NULL; + ht->nApplyCount = 0; + ht->bApplyProtection = 1; + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (!ht->nTableMask) { + ht->arBuckets = (Bucket**)&uninitialized_bucket; + return; + } +#endif + + ht->arBuckets = (Bucket **) ecalloc(ht->nTableSize, sizeof(Bucket *)); + + prev = &ht->pListHead; + p = source->pListHead; + while (p) { + nIndex = p->h & ht->nTableMask; + + /* Create bucket and initialize key */ +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (!p->nKeyLength) { + q = (Bucket *) emalloc(sizeof(Bucket)); + q->arKey = NULL; + } else if (IS_INTERNED(p->arKey)) { + q = (Bucket *) emalloc(sizeof(Bucket)); + q->arKey = p->arKey; + } else { + q = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength); + q->arKey = ((char*)q) + sizeof(Bucket); + memcpy((char*)q->arKey, p->arKey, p->nKeyLength); + } +#else + q = (Bucket *) emalloc(sizeof(Bucket) - 1 + p->nKeyLength); + if (p->nKeyLength) { + memcpy(q->arKey, p->arKey, p->nKeyLength); + } +#endif + q->h = p->h; + q->nKeyLength = p->nKeyLength; + + /* Insert into hash collision list */ + q->pNext = ht->arBuckets[nIndex]; + q->pLast = NULL; + if (q->pNext) { + q->pNext->pLast = q; + } + ht->arBuckets[nIndex] = q; + + /* Insert into global list */ + q->pListLast = ht->pListTail; + ht->pListTail = q; + q->pListNext = NULL; + *prev = q; + prev = &q->pListNext; + + /* Copy data */ + q->pData = &q->pDataPtr; + if (!bind) { + ALLOC_ZVAL(ppz); + *ppz = *((zval*)p->pDataPtr); + INIT_PZVAL(ppz); + } else if (Z_REFCOUNT_P((zval*)p->pDataPtr) == 1) { + ALLOC_ZVAL(ppz); + *ppz = *((zval*)p->pDataPtr); + } else if (accel_xlat_get(p->pDataPtr, ppz) != SUCCESS) { + ALLOC_ZVAL(ppz); + *ppz = *((zval*)p->pDataPtr); + accel_xlat_set(p->pDataPtr, ppz); + } else { + q->pDataPtr = *(void**)ppz; + p = p->pListNext; + continue; + } + q->pDataPtr = (void*)ppz; + +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + if ((Z_TYPE_P((zval*)p->pDataPtr) & IS_CONSTANT_TYPE_MASK) >= IS_ARRAY) { + switch ((Z_TYPE_P((zval*)p->pDataPtr) & IS_CONSTANT_TYPE_MASK)) { +#else + if ((Z_TYPE_P((zval*)p->pDataPtr) & ~IS_CONSTANT_INDEX) >= IS_ARRAY) { + switch ((Z_TYPE_P((zval*)p->pDataPtr) & ~IS_CONSTANT_INDEX)) { +#endif + case IS_STRING: + case IS_CONSTANT: + Z_STRVAL_P(ppz) = (char *) interned_estrndup(Z_STRVAL_P((zval*)p->pDataPtr), Z_STRLEN_P((zval*)p->pDataPtr)); + break; + case IS_ARRAY: + case IS_CONSTANT_ARRAY: + if (((zval*)p->pDataPtr)->value.ht && ((zval*)p->pDataPtr)->value.ht != &EG(symbol_table)) { + ALLOC_HASHTABLE(ppz->value.ht); + zend_hash_clone_zval(ppz->value.ht, ((zval*)p->pDataPtr)->value.ht, 0); + } + break; + } + } + + p = p->pListNext; + } + ht->pInternalPointer = ht->pListHead; +} + +static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce TSRMLS_DC) +{ + Bucket *p, *q, **prev; + ulong nIndex; + zend_class_entry **new_ce; + zend_function** new_prototype; + zend_op_array *new_entry; + + ht->nTableSize = source->nTableSize; + ht->nTableMask = source->nTableMask; + ht->nNumOfElements = source->nNumOfElements; + ht->nNextFreeElement = source->nNextFreeElement; + ht->pDestructor = ZEND_FUNCTION_DTOR; +#if ZEND_DEBUG + ht->inconsistent = 0; +#endif + ht->persistent = 0; + ht->pListHead = NULL; + ht->pListTail = NULL; + ht->pInternalPointer = NULL; + ht->nApplyCount = 0; + ht->bApplyProtection = 1; + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (!ht->nTableMask) { + ht->arBuckets = (Bucket**)&uninitialized_bucket; + return; + } +#endif + + ht->arBuckets = (Bucket **) ecalloc(ht->nTableSize, sizeof(Bucket *)); + + prev = &ht->pListHead; + p = source->pListHead; + while (p) { + nIndex = p->h & ht->nTableMask; + + /* Create bucket and initialize key */ +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (!p->nKeyLength) { + q = (Bucket *) emalloc(sizeof(Bucket)); + q->arKey = NULL; + } else if (IS_INTERNED(p->arKey)) { + q = (Bucket *) emalloc(sizeof(Bucket)); + q->arKey = p->arKey; + } else { + q = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength); + q->arKey = ((char*)q) + sizeof(Bucket); + memcpy((char*)q->arKey, p->arKey, p->nKeyLength); + } +#else + q = (Bucket *) emalloc(sizeof(Bucket) - 1 + p->nKeyLength); + if (p->nKeyLength) { + memcpy(q->arKey, p->arKey, p->nKeyLength); + } +#endif + q->h = p->h; + q->nKeyLength = p->nKeyLength; + + /* Insert into hash collision list */ + q->pNext = ht->arBuckets[nIndex]; + q->pLast = NULL; + if (q->pNext) { + q->pNext->pLast = q; + } + ht->arBuckets[nIndex] = q; + + /* Insert into global list */ + q->pListLast = ht->pListTail; + ht->pListTail = q; + q->pListNext = NULL; + *prev = q; + prev = &q->pListNext; + + /* Copy data */ + q->pData = (void *) emalloc(sizeof(zend_function)); + new_entry = (zend_op_array*)q->pData; + *new_entry = *(zend_op_array*)p->pData; + q->pDataPtr=NULL; + + /* Copy constructor */ + /* we use refcount to show that op_array is referenced from several places */ + if (new_entry->refcount != NULL) { + accel_xlat_set(p->pData, new_entry); + } + + zend_prepare_function_for_execution(new_entry); + + if(old_ce == new_entry->scope) { + new_entry->scope = ce; + } else { + if(accel_xlat_get(new_entry->scope, new_ce) == SUCCESS) { + new_entry->scope = *new_ce; + } else { + zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s. Please call Zend Support", ce->name, new_entry->function_name); + } + } + + /* update prototype */ + if (new_entry->prototype ){ + if(accel_xlat_get(new_entry->prototype, new_prototype)==SUCCESS) { + new_entry->prototype = *new_prototype; + } else { + zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s. Please call Zend Support", ce->name, new_entry->function_name); + } + } + + p = p->pListNext; + } + ht->pInternalPointer = ht->pListHead; +} + +static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce TSRMLS_DC) +{ + Bucket *p, *q, **prev; + ulong nIndex; + zend_class_entry **new_ce; + zend_property_info *prop_info; + + ht->nTableSize = source->nTableSize; + ht->nTableMask = source->nTableMask; + ht->nNumOfElements = source->nNumOfElements; + ht->nNextFreeElement = source->nNextFreeElement; + ht->pDestructor = (dtor_func_t) zend_destroy_property_info; +#if ZEND_DEBUG + ht->inconsistent = 0; +#endif + ht->persistent = 0; + ht->pListHead = NULL; + ht->pListTail = NULL; + ht->pInternalPointer = NULL; + ht->nApplyCount = 0; + ht->bApplyProtection = 1; + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (!ht->nTableMask) { + ht->arBuckets = (Bucket**)&uninitialized_bucket; + return; + } +#endif + + ht->arBuckets = (Bucket **) ecalloc(ht->nTableSize, sizeof(Bucket *)); + + prev = &ht->pListHead; + p = source->pListHead; + while (p) { + nIndex = p->h & ht->nTableMask; + + /* Create bucket and initialize key */ +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (!p->nKeyLength) { + q = (Bucket *) emalloc(sizeof(Bucket)); + q->arKey = NULL; + } else if (IS_INTERNED(p->arKey)) { + q = (Bucket *) emalloc(sizeof(Bucket)); + q->arKey = p->arKey; + } else { + q = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength); + q->arKey = ((char*)q) + sizeof(Bucket); + memcpy((char*)q->arKey, p->arKey, p->nKeyLength); + } +#else + q = (Bucket *) emalloc(sizeof(Bucket) - 1 + p->nKeyLength); + if (p->nKeyLength) { + memcpy(q->arKey, p->arKey, p->nKeyLength); + } +#endif + q->h = p->h; + q->nKeyLength = p->nKeyLength; + + /* Insert into hash collision list */ + q->pNext = ht->arBuckets[nIndex]; + q->pLast = NULL; + if (q->pNext) { + q->pNext->pLast = q; + } + ht->arBuckets[nIndex] = q; + + /* Insert into global list */ + q->pListLast = ht->pListTail; + ht->pListTail = q; + q->pListNext = NULL; + *prev = q; + prev = &q->pListNext; + + /* Copy data */ + q->pData = (void *) emalloc(sizeof(zend_property_info)); + prop_info = q->pData; + *prop_info = *(zend_property_info*)p->pData; + q->pDataPtr=NULL; + + /* Copy constructor */ + prop_info->name = interned_estrndup(prop_info->name, prop_info->name_length); + if(prop_info->doc_comment) { + prop_info->doc_comment = estrndup(prop_info->doc_comment, prop_info->doc_comment_len); + } + if(prop_info->ce == old_ce) { + prop_info->ce = ce; + } else if(accel_xlat_get(prop_info->ce, new_ce) == SUCCESS) { + prop_info->ce = *new_ce; + } else { + zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s, property %s. Please call Zend Support", ce->name, prop_info->name); + } + + p = p->pListNext; + } + ht->pInternalPointer = ht->pListHead; +} + +/* protects reference count, creates copy of statics */ +static int zend_prepare_function_for_execution(zend_op_array *op_array) +{ + HashTable *shared_statics = op_array->static_variables; + + /* protect reference count */ + op_array->refcount = &zend_accel_refcount; + (*op_array->refcount) = ZEND_PROTECTED_REFCOUNT; + + /* copy statics */ + if (shared_statics) { + ALLOC_HASHTABLE(op_array->static_variables); + zend_hash_clone_zval(op_array->static_variables, shared_statics, 0); + } + + return 0; +} + +#define zend_update_inherited_handler(handler) \ +{ \ + if(ce->handler != NULL) { \ + if(accel_xlat_get(ce->handler, new_func)==SUCCESS) { \ + ce->handler = *new_func; \ + } else { \ + zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s. Please call Zend Support", ce->name); \ + } \ + } \ +} + +/* Protects class' refcount, copies default properties, functions and class name */ +static void zend_class_copy_ctor(zend_class_entry **pce) +{ + zend_class_entry *ce = *pce; + zend_class_entry *old_ce = ce; + zend_class_entry **new_ce; + zend_function **new_func; + TSRMLS_FETCH(); + + *pce = ce = emalloc(sizeof(zend_class_entry)); + *ce = *old_ce; + ce->refcount = 1; + + if (old_ce->refcount != 1) { + /* this class is not used as a parent for any other classes */ + accel_xlat_set(old_ce, ce); + } + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (old_ce->default_properties_table) { + int i; + + ce->default_properties_table = emalloc(sizeof(zval*) * old_ce->default_properties_count); + for (i = 0; i < old_ce->default_properties_count; i++) { + if (old_ce->default_properties_table[i]) { + ce->default_properties_table[i] = zend_clone_zval(old_ce->default_properties_table[i], 0 TSRMLS_CC); + } else { + ce->default_properties_table[i] = NULL; + } + } + } +#else + zend_hash_clone_zval(&ce->default_properties, &old_ce->default_properties, 0); +#endif + + zend_hash_clone_methods(&ce->function_table, &old_ce->function_table, old_ce, ce TSRMLS_CC); + + /* static members */ +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (old_ce->default_static_members_table) { + int i; + + ce->default_static_members_table = emalloc(sizeof(zval*) * old_ce->default_static_members_count); + for (i = 0; i < old_ce->default_static_members_count; i++) { + if (old_ce->default_static_members_table[i]) { + ce->default_static_members_table[i] = zend_clone_zval(old_ce->default_static_members_table[i], 1 TSRMLS_CC); + } else { + ce->default_static_members_table[i] = NULL; + } + } + } + ce->static_members_table = ce->default_static_members_table; +#else + zend_hash_clone_zval(&ce->default_static_members, &old_ce->default_static_members, 1); + ce->static_members = &ce->default_static_members; +#endif + + /* properties_info */ + zend_hash_clone_prop_info(&ce->properties_info, &old_ce->properties_info, old_ce, ce TSRMLS_CC); + + /* constants table */ + zend_hash_clone_zval(&ce->constants_table, &old_ce->constants_table, 0); + + ce->name = interned_estrndup(ce->name, ce->name_length); + + /* interfaces aren't really implemented, so we create a new table */ + if(ce->num_interfaces) { + ce->interfaces = emalloc(sizeof(zend_class_entry *) * ce->num_interfaces); + memset(ce->interfaces, 0, sizeof(zend_class_entry *) * ce->num_interfaces); + } else { + ce->interfaces = NULL; + } + if (ZEND_CE_DOC_COMMENT(ce)) { + ZEND_CE_DOC_COMMENT(ce) = estrndup(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT_LEN(ce)); + } + + if(ce->parent) { + if(accel_xlat_get(ce->parent, new_ce)==SUCCESS) { + ce->parent = *new_ce; + } else { + zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s. Please call Zend Support", ce->name); + } + } + + zend_update_inherited_handler(constructor); + zend_update_inherited_handler(destructor); + zend_update_inherited_handler(clone); + zend_update_inherited_handler(__get); + zend_update_inherited_handler(__set); + zend_update_inherited_handler(__call); +/* 5.1 stuff */ + zend_update_inherited_handler(serialize_func); + zend_update_inherited_handler(unserialize_func); + zend_update_inherited_handler(__isset); + zend_update_inherited_handler(__unset); +/* 5.2 stuff */ + zend_update_inherited_handler(__tostring); + +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO +/* 5.3 stuff */ + zend_update_inherited_handler(__callstatic); +#endif + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO +/* 5.4 traits */ + if (ce->trait_aliases) { + zend_trait_alias **trait_aliases; + int i = 0; + + while (ce->trait_aliases[i]) { + i++; + } + trait_aliases = emalloc(sizeof(zend_trait_alias*) * (i+1)); + i = 0; + while (ce->trait_aliases[i]) { + trait_aliases[i] = emalloc(sizeof(zend_trait_alias)); + memcpy(trait_aliases[i], ce->trait_aliases[i], sizeof(zend_trait_alias)); + trait_aliases[i]->trait_method = emalloc(sizeof(zend_trait_method_reference)); + memcpy(trait_aliases[i]->trait_method, ce->trait_aliases[i]->trait_method, sizeof(zend_trait_method_reference)); + if (trait_aliases[i]->trait_method) { + if (trait_aliases[i]->trait_method->method_name) { + trait_aliases[i]->trait_method->method_name = + estrndup(trait_aliases[i]->trait_method->method_name, + trait_aliases[i]->trait_method->mname_len); + } + if (trait_aliases[i]->trait_method->class_name) { + trait_aliases[i]->trait_method->class_name = + estrndup(trait_aliases[i]->trait_method->class_name, + trait_aliases[i]->trait_method->cname_len); + } + } + + if (trait_aliases[i]->alias) { + trait_aliases[i]->alias = + estrndup(trait_aliases[i]->alias, + trait_aliases[i]->alias_len); + } + i++; + } + trait_aliases[i] = NULL; + ce->trait_aliases = trait_aliases; + } + + if (ce->trait_precedences) { + zend_trait_precedence **trait_precedences; + int i = 0; + + while (ce->trait_precedences[i]) { + i++; + } + trait_precedences = emalloc(sizeof(zend_trait_precedence*) * (i+1)); + i = 0; + while (ce->trait_precedences[i]) { + trait_precedences[i] = emalloc(sizeof(zend_trait_precedence)); + memcpy(trait_precedences[i], ce->trait_precedences[i], sizeof(zend_trait_precedence)); + trait_precedences[i]->trait_method = emalloc(sizeof(zend_trait_method_reference)); + memcpy(trait_precedences[i]->trait_method, ce->trait_precedences[i]->trait_method, sizeof(zend_trait_method_reference)); + + trait_precedences[i]->trait_method->method_name = + estrndup(trait_precedences[i]->trait_method->method_name, + trait_precedences[i]->trait_method->mname_len); + trait_precedences[i]->trait_method->class_name = + estrndup(trait_precedences[i]->trait_method->class_name, + trait_precedences[i]->trait_method->cname_len); + + if (trait_precedences[i]->exclude_from_classes) { + zend_class_entry **exclude_from_classes; + int j = 0; + + while (trait_precedences[i]->exclude_from_classes[j]) { + j++; + } + exclude_from_classes = emalloc(sizeof(zend_class_entry*) * (j+1)); + j = 0; + while (trait_precedences[i]->exclude_from_classes[j]) { + exclude_from_classes[j] = (zend_class_entry*)estrndup( + (char*)trait_precedences[i]->exclude_from_classes[j], + strlen((char*)trait_precedences[i]->exclude_from_classes[j])); + j++; + } + exclude_from_classes[j] = NULL; + trait_precedences[i]->exclude_from_classes = exclude_from_classes; + } + i++; + } + trait_precedences[i] = NULL; + ce->trait_precedences = trait_precedences; + } +#endif +} + +static int zend_accel_same_function(void *f1, void *f2) +{ + zend_function *func1 = (zend_function *)f1, *func2 = (zend_function *)f2; + zend_op_array *op1 = (zend_op_array *)func1; + zend_op_array *op2 = (zend_op_array *)func2; + + if(func1->type != ZEND_USER_FUNCTION || func2->type != ZEND_USER_FUNCTION) { + return 0; + } + + if(func1 == func2) { + return 1; + } + + if(op1->function_name != op2->function_name && (!op1->function_name || !op2->function_name || strcmp(op1->function_name, op2->function_name))) { + /* compare filenames */ + return 0; + } + + if(op1->filename != op2->filename && (!op1->filename || !op2->filename || strcmp(op1->filename, op2->filename))) { + /* compare filenames */ + return 0; + } + + if(!op1->opcodes || !op2->opcodes || op1->opcodes[0].lineno != op2->opcodes[0].lineno) { + /* compare first lines */ + return 0; + } + + /* if everything matches - we are OK */ + return 1; +} + +static int zend_accel_same_class(void *f1, void *f2) +{ + zend_class_entry *ce1 = *(zend_class_entry **)f1; + zend_class_entry *ce2 = *(zend_class_entry **)f2; + + if(ce1->type != ZEND_USER_CLASS || ce2->type != ZEND_USER_CLASS) { + return 0; + } + + if(ce1 == ce2) { + return 1; + } + + if(!ce1->name || !ce2->name || zend_binary_strcmp(ce1->name, ce1->name_length, ce2->name, ce2->name_length)) { + return 0; + } + + if (zend_hash_num_elements(&ce1->function_table) != zend_hash_num_elements(&ce2->function_table) +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + || ce1->default_properties_count != ce2->default_properties_count) { +#else + || zend_hash_num_elements(&ce1->default_properties) != zend_hash_num_elements(&ce2->default_properties)) { +#endif + return 0; + } + + if(zend_hash_num_elements(&ce1->function_table)) { + HashPosition pos; + zend_function *func1, *func2; + + zend_hash_internal_pointer_reset_ex(&ce1->function_table, &pos); + zend_hash_get_current_data_ex(&ce1->function_table, (void **)&func1, &pos); + zend_hash_internal_pointer_reset_ex(&ce2->function_table, &pos); + zend_hash_get_current_data_ex(&ce2->function_table, (void **)&func2, &pos); + if(!zend_accel_same_function(func1, func2)) { + return 0; + } + } + + return 1; +} + +static int zend_hash_unique_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor, uint size, const char **key_fail, ulong *key_fail_l, id_function_t pIdFunc) +{ + Bucket *p; + void *t; + + p = source->pListHead; + while (p) { + if (p->nKeyLength>0) { + if (zend_hash_quick_add(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &t) ==SUCCESS) { + if(pCopyConstructor) { + pCopyConstructor(t); + } + } else { + if(p->nKeyLength>0 && p->arKey[0]==0) { + /* Mangled key, ignore and wait for runtime */ + } else if(zend_hash_quick_find(target, p->arKey, p->nKeyLength, p->h, &t) == SUCCESS && + (!pIdFunc || pIdFunc(p->pData, t))) { + /* same one, ignore it */ + } else { + if(key_fail) { + *key_fail = p->arKey; + } + if(key_fail_l) { + *key_fail_l = p->nKeyLength; + } + return FAILURE; + } + } + } else { + if (!zend_hash_index_exists(target, p->h) && zend_hash_index_update(target, p->h, p->pData, size, &t) == SUCCESS) { + if(pCopyConstructor) { + pCopyConstructor(t); + } + } else { + if(key_fail) { + *key_fail = NULL; + } + if(key_fail_l) { + *key_fail_l = p->h; + } + return FAILURE; + } + } + p = p->pListNext; + } + target->pInternalPointer = target->pListHead; + + return SUCCESS; +} + +static void zend_accel_function_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor) { + const char *name; + ulong name_len; + zend_function *function; + TSRMLS_FETCH(); + + if(zend_hash_unique_copy(target, source, pCopyConstructor, sizeof(zend_function), &name, &name_len, ZCG(accel_directives).ignore_dups?NULL:zend_accel_same_function) != SUCCESS) { + if (zend_hash_find(target, name, name_len, (void *) &function)==SUCCESS + && function->type==ZEND_USER_FUNCTION + && ((zend_op_array *) function)->last>0) { + zend_error(E_ERROR, "Cannot redeclare function %.*s() (previously declared in %s:%d). If this code worked without the " ACCELERATOR_PRODUCT_NAME ", please set zend_optimizerplus.dups_fix=1 in your ini file", + (int)name_len, name, + ((zend_op_array *) function)->filename, + (int)((zend_op_array *) function)->opcodes[0].lineno); + } else { + + zend_error(E_ERROR, "Cannot redeclare function %.*s(). If this code worked without the " ACCELERATOR_PRODUCT_NAME ", please set zend_optimizerplus.dups_fix=1 in your ini file", (int)name_len, name); + } + } +} + +static void zend_accel_class_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor TSRMLS_DC) { + const char *name; + ulong name_len; + uint size; + + size = sizeof(zend_class_entry*); + if(zend_hash_unique_copy(target, source, pCopyConstructor, size, &name, &name_len, ZCG(accel_directives).ignore_dups?NULL:zend_accel_same_class) != SUCCESS) { + zend_error(E_ERROR, "Cannot redeclare class %.*s. If this code worked without the " ACCELERATOR_PRODUCT_NAME ", please set zend_optimizerplus.dups_fix=1 in your php.ini", (int)name_len, name); + } +} + +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO +static void zend_do_delayed_early_binding(zend_op_array *op_array, zend_uint early_binding TSRMLS_DC) +{ + zend_uint opline_num = early_binding; + + if ((int)opline_num != -1) { + zend_bool orig_in_compilation = CG(in_compilation); + char *orig_compiled_filename = zend_set_compiled_filename(op_array->filename TSRMLS_CC); + zend_class_entry **pce; + + CG(in_compilation) = 1; + while ((int)opline_num != -1) { + if (zend_lookup_class(Z_STRVAL(op_array->opcodes[opline_num-1].op2.u.constant), Z_STRLEN(op_array->opcodes[opline_num-1].op2.u.constant), &pce TSRMLS_CC) == SUCCESS) { + do_bind_inherited_class(&op_array->opcodes[opline_num], EG(class_table), *pce, 1 TSRMLS_CC); + } + opline_num = op_array->opcodes[opline_num].result.u.opline_num; + } + zend_restore_compiled_filename(orig_compiled_filename); + CG(in_compilation) = orig_in_compilation; + } +} +#endif + +zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory TSRMLS_DC) +{ + zend_op_array *op_array; + + op_array = (zend_op_array *) emalloc(sizeof(zend_op_array)); + *op_array = persistent_script->main_op_array; + + if (from_shared_memory) { + /* Copy all the necessary stuff from shared memory to regular memory, and protect the shared script */ + if (zend_hash_num_elements(&persistent_script->class_table) > 0) { + zend_hash_init(&ZCG(bind_hash), 10, NULL, NULL, 0); + zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, (unique_copy_ctor_func_t) zend_class_copy_ctor TSRMLS_CC); + zend_hash_destroy(&ZCG(bind_hash)); + } + /* we must first to copy all classes and then prepare functions, since functions may try to bind + classes - which depend on pre-bind class entries existant in the class table */ + if (zend_hash_num_elements(&persistent_script->function_table) > 0) { + zend_accel_function_hash_copy(CG(function_table), &persistent_script->function_table, (unique_copy_ctor_func_t)zend_prepare_function_for_execution); + } + + zend_prepare_function_for_execution(op_array); + + /* Register __COMPILER_HALT_OFFSET__ constant */ + if (persistent_script->compiler_halt_offset != 0 && + persistent_script->full_path) { + char *name, *cfilename; + char haltoff[] = "__COMPILER_HALT_OFFSET__"; + int len, clen; + + cfilename = persistent_script->full_path; + clen = strlen(cfilename); + zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, cfilename, clen, 0); + if (!zend_hash_exists(EG(zend_constants), name, len+1)) { + zend_register_long_constant(name, len+1, persistent_script->compiler_halt_offset, CONST_CS, 0 TSRMLS_CC); + } + efree(name); + } + +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + if ((int)persistent_script->early_binding != -1) { + zend_do_delayed_early_binding(op_array, persistent_script->early_binding TSRMLS_CC); + } +#endif + + } else /* if (!from_shared_memory) */ { + if (zend_hash_num_elements(&persistent_script->function_table) > 0) { + zend_accel_function_hash_copy(CG(function_table), &persistent_script->function_table, NULL); + } + if (zend_hash_num_elements(&persistent_script->class_table) > 0) { + zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, NULL TSRMLS_CC); + } + free_persistent_script(persistent_script, 0); /* free only hashes */ + } + +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + if (op_array->early_binding != (zend_uint)-1) { + char *orig_compiled_filename = CG(compiled_filename); + CG(compiled_filename) = persistent_script->full_path; + zend_do_delayed_early_binding(op_array TSRMLS_CC); + CG(compiled_filename) = orig_compiled_filename; + } +#endif + + return op_array; +} + +/* + * zend_adler32() is based on zlib implementation + * Computes the Adler-32 checksum of a data stream + * + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + */ + +#define ADLER32_BASE 65521 /* largest prime smaller than 65536 */ +#define ADLER32_NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define ADLER32_DO1(buf) {s1 += *(buf); s2 += s1;} +#define ADLER32_DO2(buf,i) ADLER32_DO1(buf+i); ADLER32_DO1(buf+i+1); +#define ADLER32_DO4(buf,i) ADLER32_DO2(buf,i); ADLER32_DO2(buf,i+2); +#define ADLER32_DO8(buf,i) ADLER32_DO4(buf,i); ADLER32_DO4(buf,i+4); +#define ADLER32_DO16(buf) ADLER32_DO8(buf,0); ADLER32_DO8(buf,8); + +unsigned int zend_adler32(unsigned int checksum, signed char *buf, uint len) +{ + unsigned int s1 = checksum & 0xffff; + unsigned int s2 = (checksum >> 16) & 0xffff; + signed char *end; + + while (len >= ADLER32_NMAX) { + len -= ADLER32_NMAX; + end = buf + ADLER32_NMAX; + do { + ADLER32_DO16(buf); + buf += 16; + } while (buf != end); + s1 %= ADLER32_BASE; + s2 %= ADLER32_BASE; + } + + if (len) { + if (len >= 16) { + end = buf + (len & 0xfff0); + len &= 0xf; + do { + ADLER32_DO16(buf); + buf += 16; + } while (buf != end); + } + if (len) { + end = buf + len; + do { + ADLER32_DO1(buf); + buf++; + } while (buf != end); + } + s1 %= ADLER32_BASE; + s2 %= ADLER32_BASE; + } + + return (s2 << 16) | s1; +} diff --git a/zend_accelerator_util_funcs.h b/zend_accelerator_util_funcs.h new file mode 100644 index 00000000000..804e0f786b3 --- /dev/null +++ b/zend_accelerator_util_funcs.h @@ -0,0 +1,49 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_ACCELERATOR_UTIL_FUNCS_H +#define ZEND_ACCELERATOR_UTIL_FUNCS_H + +#include "zend.h" +#include "ZendAccelerator.h" + +void zend_accel_copy_internal_functions(TSRMLS_D); + +zend_persistent_script* create_persistent_script(void); +void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements); + +void zend_accel_free_user_functions(HashTable *ht TSRMLS_DC); +void zend_accel_move_user_functions(HashTable *str, HashTable *dst TSRMLS_DC); + +zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory TSRMLS_DC); + +#define ADLER32_INIT 1 /* initial Adler-32 value */ + +unsigned int zend_adler32(unsigned int checksum, signed char *buf, uint len); + +#endif /* ZEND_ACCELERATOR_UTIL_FUNCS_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/zend_persist.c b/zend_persist.c new file mode 100644 index 00000000000..44a9809322e --- /dev/null +++ b/zend_persist.c @@ -0,0 +1,680 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#include "zend.h" +#include "ZendAccelerator.h" +#include "zend_persist.h" +#include "zend_extensions.h" +#include "zend_shared_alloc.h" +#include "zend_vm.h" +#include "zend_constants.h" +#include "zend_operators.h" + +#define zend_accel_store(p, size) \ + (p = _zend_shared_memdup((void*)p, size, 1 TSRMLS_CC)) +#define zend_accel_memdup(p, size) \ + _zend_shared_memdup((void*)p, size, 0 TSRMLS_CC) + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO +# define zend_accel_memdup_interned_string(str, len) \ + IS_INTERNED(str) ? str : zend_accel_memdup(str, len) + +# define zend_accel_store_interned_string(str, len) do { \ + if (!IS_INTERNED(str)) { zend_accel_store(str, len); } \ + } while (0) +#else +# define zend_accel_memdup_interned_string(str, len) \ + zend_accel_memdup(str, len) + +# define zend_accel_store_interned_string(str, len) \ + zend_accel_store(str, len) +#endif + +typedef void (*zend_persist_func_t)(void * TSRMLS_DC); + +static void zend_persist_zval_ptr(zval **zp TSRMLS_DC); + +static void zend_hash_persist(HashTable *ht, void (*pPersistElement)(void *pElement TSRMLS_DC), size_t el_size TSRMLS_DC) +{ + Bucket *p = ht->pListHead; + uint i; + + while (p) { + Bucket *q = p; + + /* persist bucket and key */ +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + p = zend_accel_memdup(p, sizeof(Bucket)); + if (p->nKeyLength) { + p->arKey = zend_accel_memdup_interned_string(p->arKey, p->nKeyLength); + } +#else + p = zend_accel_memdup(p, sizeof(Bucket) - 1 + p->nKeyLength); +#endif + + /* persist data pointer in bucket */ + if (!p->pDataPtr) { + zend_accel_store(p->pData, el_size); + } else { + /* Update p->pData to point to the new p->pDataPtr address, after the bucket relocation */ + p->pData = &p->pDataPtr; + } + + /* persist the data itself */ + if (pPersistElement) { + pPersistElement(p->pData TSRMLS_CC); + } + + /* update linked lists */ + if (p->pLast) { + p->pLast->pNext = p; + } + if (p->pNext) { + p->pNext->pLast = p; + } + if (p->pListLast) { + p->pListLast->pListNext = p; + } + if (p->pListNext) { + p->pListNext->pListLast = p; + } + + p = p->pListNext; + + /* delete the old non-persistent bucket */ + efree(q); + } + + /* update linked lists */ + if (ht->pListHead) { + ht->pListHead = zend_shared_alloc_get_xlat_entry(ht->pListHead); + } + if (ht->pListTail) { + ht->pListTail = zend_shared_alloc_get_xlat_entry(ht->pListTail); + } + if (ht->pInternalPointer) { + ht->pInternalPointer = zend_shared_alloc_get_xlat_entry(ht->pInternalPointer); + } + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + /* Check if HastTable is initialized */ + if (ht->nTableMask) { +#endif + if (ht->nNumOfElements) { + /* update hash table */ + for (i = 0; i < ht->nTableSize; i++) { + if (ht->arBuckets[i]) { + ht->arBuckets[i] = zend_shared_alloc_get_xlat_entry(ht->arBuckets[i]); + } + } + } + zend_accel_store(ht->arBuckets, sizeof(Bucket*) * ht->nTableSize); +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + } else { + ht->arBuckets = NULL; + } +#endif +} + +static void zend_persist_zval(zval *z TSRMLS_DC) +{ +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + switch (z->type & IS_CONSTANT_TYPE_MASK) { +#else + switch (z->type & ~IS_CONSTANT_INDEX) { +#endif + case IS_STRING: + case IS_CONSTANT: + zend_accel_store_interned_string(z->value.str.val, z->value.str.len + 1); + break; + case IS_ARRAY: + case IS_CONSTANT_ARRAY: + zend_accel_store(z->value.ht, sizeof(HashTable)); + zend_hash_persist(z->value.ht, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC); + break; + } +} + +static void zend_persist_zval_ptr(zval **zp TSRMLS_DC) +{ + zval *new_ptr = zend_shared_alloc_get_xlat_entry(*zp); + + if (new_ptr) { + *zp = new_ptr; + } else { + /* Attempt to store only if we didn't store this zval_ptr yet */ + zend_accel_store(*zp, sizeof(zval)); + zend_persist_zval(*zp TSRMLS_CC); + } +} + +static void zend_protect_zval(zval *z TSRMLS_DC) +{ + PZ_SET_ISREF_P(z); + PZ_SET_REFCOUNT_P(z,2); +} + +static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_script* main_persistent_script TSRMLS_DC) +{ + zend_op *persist_ptr; +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + int has_jmp = 0; +#endif +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + zend_literal *orig_literals = NULL; +#endif + + if (op_array->type != ZEND_USER_FUNCTION) { + return; + } + +#if ZEND_EXTENSION_API_NO <= PHP_5_3_X_API_NO + op_array->size = op_array->last; +#endif + + if (--(*op_array->refcount) == 0) { + efree(op_array->refcount); + } + op_array->refcount = NULL; + + if (op_array->filename) { + /* do not free! PHP has centralized filename storage, compiler will free it */ + op_array->filename = zend_accel_memdup(op_array->filename, strlen(op_array->filename) + 1); + } + + if (main_persistent_script) { + zend_bool orig_in_execution = EG(in_execution); + zend_op_array *orig_op_array = EG(active_op_array); + zval offset; + +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + main_persistent_script->early_binding = -1; +#endif + 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)) { + main_persistent_script->compiler_halt_offset = Z_LVAL(offset); + } + EG(active_op_array) = orig_op_array; + EG(in_execution) = orig_in_execution; + } + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (op_array->literals) { + orig_literals = zend_shared_alloc_get_xlat_entry(op_array->literals); + if (orig_literals) { + op_array->literals = orig_literals; + } else { + zend_literal *p = zend_accel_memdup(op_array->literals, sizeof(zend_literal) * op_array->last_literal); + zend_literal *end = p + op_array->last_literal; + orig_literals = op_array->literals; + op_array->literals = p; + while (p < end) { + zend_persist_zval(&p->constant TSRMLS_CC); + zend_protect_zval(&p->constant TSRMLS_CC); + p++; + } + efree(orig_literals); + } + } +#endif + + if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->opcodes))) { + op_array->opcodes = persist_ptr; + } else { + zend_op *new_opcodes = zend_accel_memdup(op_array->opcodes, sizeof(zend_op) * op_array->last); + zend_op *opline = new_opcodes; + zend_op *end = new_opcodes + op_array->last; + int offset = 0; + + for (;opline PHP_5_3_X_API_NO + opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals)); +#else + zend_persist_zval(&opline->op1.u.constant TSRMLS_CC); + zend_protect_zval(&opline->op1.u.constant TSRMLS_CC); +#endif + } + if (ZEND_OP2_TYPE(opline)==IS_CONST) { +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + opline->op2.zv = (zval*)((char*)opline->op2.zv + ((char*)op_array->literals - (char*)orig_literals)); +#else + zend_persist_zval(&opline->op2.u.constant TSRMLS_CC); + zend_protect_zval(&opline->op2.u.constant TSRMLS_CC); +#endif + } + +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + switch (opline->opcode) { + case ZEND_JMP: + has_jmp = 1; + if (ZEND_DONE_PASS_TWO(op_array)) { + ZEND_OP1(opline).jmp_addr = &new_opcodes[ZEND_OP1(opline).jmp_addr - op_array->opcodes]; + } + break; + case ZEND_JMPZ: + case ZEND_JMPNZ: + case ZEND_JMPZ_EX: + case ZEND_JMPNZ_EX: + has_jmp = 1; + if (ZEND_DONE_PASS_TWO(op_array)) { + ZEND_OP2(opline).jmp_addr = &new_opcodes[ZEND_OP2(opline).jmp_addr - op_array->opcodes]; + } + break; + case ZEND_JMPZNZ: + case ZEND_BRK: + case ZEND_CONT: + has_jmp = 1; + break; + case ZEND_DECLARE_INHERITED_CLASS: + if (main_persistent_script && ZCG(accel_directives).inherited_hack) { + if (!has_jmp && + ((opline+2) >= end || + (opline+1)->opcode != ZEND_FETCH_CLASS || + (opline+2)->opcode != ZEND_ADD_INTERFACE)) { + + zend_uint *opline_num = &main_persistent_script->early_binding; + + while ((int)*opline_num != -1) { + opline_num = &new_opcodes[*opline_num].result.u.opline_num; + } + *opline_num = opline - new_opcodes; + opline->result.op_type = IS_UNUSED; + opline->result.u.opline_num = -1; + opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED; + ZEND_VM_SET_OPCODE_HANDLER(opline); + } + break; + } + } + +#else /* if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO */ + + if (ZEND_DONE_PASS_TWO(op_array)) { + /* fix jmps to point to new array */ + switch (opline->opcode) { + case ZEND_JMP: + case ZEND_GOTO: +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + case ZEND_FAST_CALL: +#endif + ZEND_OP1(opline).jmp_addr = &new_opcodes[ZEND_OP1(opline).jmp_addr - op_array->opcodes]; + break; + case ZEND_JMPZ: + case ZEND_JMPNZ: + case ZEND_JMPZ_EX: + case ZEND_JMPNZ_EX: + case ZEND_JMP_SET: +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + case ZEND_JMP_SET_VAR: +#endif + ZEND_OP2(opline).jmp_addr = &new_opcodes[ZEND_OP2(opline).jmp_addr - op_array->opcodes]; + break; + } + } +#endif /* if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO */ + } + + efree(op_array->opcodes); + op_array->opcodes = new_opcodes; + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (op_array->run_time_cache) { + efree(op_array->run_time_cache); + op_array->run_time_cache = NULL; + } +#endif + } + + if (op_array->function_name) { + char *new_name; + if ((new_name = zend_shared_alloc_get_xlat_entry(op_array->function_name))) { + op_array->function_name = new_name; + } else { + zend_accel_store(op_array->function_name, strlen(op_array->function_name)+1); + } + } + + if (op_array->arg_info) { + zend_arg_info *new_ptr; + if((new_ptr = zend_shared_alloc_get_xlat_entry(op_array->arg_info))) { + op_array->arg_info = new_ptr; + } else { + zend_uint i; + + zend_accel_store(op_array->arg_info, sizeof(zend_arg_info) * op_array->num_args); + for(i=0;inum_args;i++) { + if(op_array->arg_info[i].name) { + zend_accel_store_interned_string(op_array->arg_info[i].name, op_array->arg_info[i].name_len + 1); + } + if(op_array->arg_info[i].class_name) { + zend_accel_store_interned_string(op_array->arg_info[i].class_name, op_array->arg_info[i].class_name_len + 1); + } + } + } + } + + if (op_array->brk_cont_array) { + zend_accel_store(op_array->brk_cont_array, sizeof(zend_brk_cont_element) * op_array->last_brk_cont); + } + + if (op_array->static_variables) { + zend_hash_persist(op_array->static_variables, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC); + zend_accel_store(op_array->static_variables, sizeof(HashTable)); + } + + if(op_array->scope) { + op_array->scope = zend_shared_alloc_get_xlat_entry(op_array->scope); + } + + if(op_array->doc_comment) { + if (ZCG(accel_directives).save_comments) { + zend_accel_store(op_array->doc_comment, op_array->doc_comment_len + 1); + } else { + if(!zend_shared_alloc_get_xlat_entry(op_array->doc_comment)) { + zend_shared_alloc_register_xlat_entry(op_array->doc_comment, op_array->doc_comment); + efree((char*)op_array->doc_comment); + } + op_array->doc_comment = NULL; + op_array->doc_comment_len = 0; + } + } + + if(op_array->try_catch_array) { + zend_accel_store(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch); + } + + if(op_array->vars) { + if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->vars))) { + op_array->vars = (zend_compiled_variable*)persist_ptr; + } else { + int i; + zend_accel_store(op_array->vars, sizeof(zend_compiled_variable) * op_array->last_var); + for(i=0; ilast_var; i++) { + zend_accel_store_interned_string(op_array->vars[i].name, op_array->vars[i].name_len + 1); + } + } + } + + /* "prototype" may be undefined if "scope" isn't set */ + if(op_array->scope && op_array->prototype) { + if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype))) { + op_array->prototype = (union _zend_function*)persist_ptr; + /* we use refcount to show that op_array is referenced from several places */ + op_array->prototype->op_array.refcount++; + } + } else { + op_array->prototype = NULL; + } +} + +static void zend_persist_op_array(zend_op_array *op_array TSRMLS_DC) +{ + zend_persist_op_array_ex(op_array, NULL TSRMLS_CC); +} + +static void zend_persist_property_info(zend_property_info *prop TSRMLS_DC) +{ + zend_accel_store_interned_string(prop->name, prop->name_length + 1); + if(prop->doc_comment) { + if (ZCG(accel_directives).save_comments) { + zend_accel_store(prop->doc_comment, prop->doc_comment_len + 1); + } else { + if(!zend_shared_alloc_get_xlat_entry(prop->doc_comment)) { + zend_shared_alloc_register_xlat_entry(prop->doc_comment, prop->doc_comment); + efree((char*)prop->doc_comment); + } + prop->doc_comment = NULL; + prop->doc_comment_len = 0; + } + } +} + +static void zend_persist_class_entry(zend_class_entry **pce TSRMLS_DC) +{ + zend_class_entry *ce = *pce; + + if (ce->type == ZEND_USER_CLASS) { + *pce = zend_accel_store(ce, sizeof(zend_class_entry)); + zend_accel_store_interned_string(ce->name, ce->name_length + 1); + zend_hash_persist(&ce->function_table, (zend_persist_func_t) zend_persist_op_array, sizeof(zend_op_array) TSRMLS_CC); +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (ce->default_properties_table) { + int i; + + zend_accel_store(ce->default_properties_table, sizeof(zval*) * ce->default_properties_count); + for (i = 0; i < ce->default_properties_count; i++) { + if (ce->default_properties_table[i]) { + zend_persist_zval_ptr(&ce->default_properties_table[i] TSRMLS_CC); + } + } + } + if (ce->default_static_members_table) { + int i; + + zend_accel_store(ce->default_static_members_table, sizeof(zval*) * ce->default_static_members_count); + for (i = 0; i < ce->default_static_members_count; i++) { + if (ce->default_static_members_table[i]) { + zend_persist_zval_ptr(&ce->default_static_members_table[i] TSRMLS_CC); + } + } + } + ce->static_members_table = NULL; +#else + zend_hash_persist(&ce->default_properties, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC); + zend_hash_persist(&ce->default_static_members, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC); + ce->static_members = NULL; +#endif + zend_hash_persist(&ce->constants_table, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC); + + if(ZEND_CE_FILENAME(ce)) { + /* do not free! PHP has centralized filename storage, compiler will free it */ + ZEND_CE_FILENAME(ce) = zend_accel_memdup(ZEND_CE_FILENAME(ce), strlen(ZEND_CE_FILENAME(ce)) + 1); + } + if(ZEND_CE_DOC_COMMENT(ce)) { + if (ZCG(accel_directives).save_comments) { + zend_accel_store(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT_LEN(ce) + 1); + } else { + if(!zend_shared_alloc_get_xlat_entry(ZEND_CE_DOC_COMMENT(ce))) { + zend_shared_alloc_register_xlat_entry(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT(ce)); + efree((char*)ZEND_CE_DOC_COMMENT(ce)); + } + ZEND_CE_DOC_COMMENT(ce) = NULL; + ZEND_CE_DOC_COMMENT_LEN(ce) = 0; + } + } + zend_hash_persist(&ce->properties_info, (zend_persist_func_t) zend_persist_property_info, sizeof(zend_property_info) TSRMLS_CC); + if(ce->num_interfaces && ce->interfaces) { + efree(ce->interfaces); + } + ce->interfaces = NULL; /* will be filled in on fetch */ + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (ce->num_traits && ce->traits) { + efree(ce->traits); + } + ce->traits = NULL; + + if (ce->trait_aliases) { + int i = 0; + while (ce->trait_aliases[i]) { + if (ce->trait_aliases[i]->trait_method) { + if (ce->trait_aliases[i]->trait_method->method_name) { + zend_accel_store(ce->trait_aliases[i]->trait_method->method_name, + ce->trait_aliases[i]->trait_method->mname_len+1); + } + if (ce->trait_aliases[i]->trait_method->class_name) { + zend_accel_store(ce->trait_aliases[i]->trait_method->class_name, + ce->trait_aliases[i]->trait_method->cname_len+1); + } + ce->trait_aliases[i]->trait_method->ce = NULL; + zend_accel_store(ce->trait_aliases[i]->trait_method, + sizeof(zend_trait_method_reference)); + } + + if (ce->trait_aliases[i]->alias) { + zend_accel_store(ce->trait_aliases[i]->alias, + ce->trait_aliases[i]->alias_len+1); + } + +#if ZEND_EXTENSION_API_NO <= PHP_5_4_X_API_NO + ce->trait_aliases[i]->function = NULL; +#endif + zend_accel_store(ce->trait_aliases[i], sizeof(zend_trait_alias)); + i++; + } + + zend_accel_store(ce->trait_aliases, sizeof(zend_trait_alias*) * (i + 1)); + } + + if (ce->trait_precedences) { + int i = 0; + + while (ce->trait_precedences[i]) { + zend_accel_store(ce->trait_precedences[i]->trait_method->method_name, + ce->trait_precedences[i]->trait_method->mname_len+1); + zend_accel_store(ce->trait_precedences[i]->trait_method->class_name, + ce->trait_precedences[i]->trait_method->cname_len+1); + ce->trait_precedences[i]->trait_method->ce = NULL; + zend_accel_store(ce->trait_precedences[i]->trait_method, + sizeof(zend_trait_method_reference)); + + if (ce->trait_precedences[i]->exclude_from_classes) { + int j = 0; + + while (ce->trait_precedences[i]->exclude_from_classes[j]) { + zend_accel_store(ce->trait_precedences[i]->exclude_from_classes[j], + strlen((char*)ce->trait_precedences[i]->exclude_from_classes[j]) + 1); + j++; + } + zend_accel_store(ce->trait_precedences[i]->exclude_from_classes, + sizeof(zend_class_entry*) * (j+1)); + } + +#if ZEND_EXTENSION_API_NO <= PHP_5_4_X_API_NO + ce->trait_precedences[i]->function = NULL; +#endif + zend_accel_store(ce->trait_precedences[i], sizeof(zend_trait_precedence)); + i++; + } + zend_accel_store( + ce->trait_precedences, sizeof(zend_trait_precedence*) * (i+1)); + } +#endif + } +} + +static int zend_update_property_info_ce(zend_property_info *prop TSRMLS_DC) +{ + prop->ce = zend_shared_alloc_get_xlat_entry(prop->ce); + return 0; +} + +static int zend_update_parent_ce(zend_class_entry **pce TSRMLS_DC) +{ + zend_class_entry *ce = *pce; + + if (ce->parent) { + ce->parent = zend_shared_alloc_get_xlat_entry(ce->parent); + /* We use refcount to show if the class is used as a parent */ + ce->parent->refcount++; + } + + /* update methods */ + if(ce->constructor) { + ce->constructor = zend_shared_alloc_get_xlat_entry(ce->constructor); + /* we use refcount to show that op_array is referenced from several places */ + ce->constructor->op_array.refcount++; + } + if(ce->destructor) { + ce->destructor = zend_shared_alloc_get_xlat_entry(ce->destructor); + ce->destructor->op_array.refcount++; + } + if(ce->clone) { + ce->clone = zend_shared_alloc_get_xlat_entry(ce->clone); + ce->clone->op_array.refcount++; + } + if(ce->__get) { + ce->__get = zend_shared_alloc_get_xlat_entry(ce->__get); + ce->__get->op_array.refcount++; + } + if(ce->__set) { + ce->__set = zend_shared_alloc_get_xlat_entry(ce->__set); + ce->__set->op_array.refcount++; + } + if(ce->__call) { + ce->__call = zend_shared_alloc_get_xlat_entry(ce->__call); + ce->__call->op_array.refcount++; + } + if(ce->serialize_func) { + ce->serialize_func = zend_shared_alloc_get_xlat_entry(ce->serialize_func); + ce->serialize_func->op_array.refcount++; + } + if(ce->unserialize_func) { + ce->unserialize_func = zend_shared_alloc_get_xlat_entry(ce->unserialize_func); + ce->unserialize_func->op_array.refcount++; + } + if(ce->__isset) { + ce->__isset = zend_shared_alloc_get_xlat_entry(ce->__isset); + ce->__isset->op_array.refcount++; + } + if(ce->__unset) { + ce->__unset = zend_shared_alloc_get_xlat_entry(ce->__unset); + ce->__unset->op_array.refcount++; + } + if(ce->__tostring) { + ce->__tostring = zend_shared_alloc_get_xlat_entry(ce->__tostring); + ce->__tostring->op_array.refcount++; + } +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + if(ce->__callstatic) { + ce->__callstatic = zend_shared_alloc_get_xlat_entry(ce->__callstatic); + ce->__callstatic->op_array.refcount++; + } +#endif + zend_hash_apply(&ce->properties_info, (apply_func_t) zend_update_property_info_ce TSRMLS_CC); + return 0; +} + +static void zend_accel_persist_class_table(HashTable *class_table TSRMLS_DC) +{ + zend_hash_persist(class_table, (zend_persist_func_t) zend_persist_class_entry, sizeof(zend_class_entry*) TSRMLS_CC); + zend_hash_apply(class_table, (apply_func_t) zend_update_parent_ce TSRMLS_CC); +} + +zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, char **key, unsigned int key_length TSRMLS_DC) +{ + zend_shared_alloc_clear_xlat_table(); + zend_hash_persist(&script->function_table, (zend_persist_func_t) zend_persist_op_array, sizeof(zend_op_array) TSRMLS_CC); + zend_accel_persist_class_table(&script->class_table TSRMLS_CC); + zend_persist_op_array_ex(&script->main_op_array, script TSRMLS_CC); + *key = zend_accel_memdup(*key, key_length + 1); + zend_accel_store(script->full_path, script->full_path_len + 1); + zend_accel_store(script, sizeof(zend_persistent_script)); + + return script; +} + +int zend_accel_script_persistable(zend_persistent_script *script) +{ + return 1; +} diff --git a/zend_persist.h b/zend_persist.h new file mode 100644 index 00000000000..ffb990ae751 --- /dev/null +++ b/zend_persist.h @@ -0,0 +1,29 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_PERSIST_H +#define ZEND_PERSIST_H + +int zend_accel_script_persistable(zend_persistent_script *script); +uint zend_accel_script_persist_calc(zend_persistent_script *script, char *key, unsigned int key_length TSRMLS_DC); +zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, char **key, unsigned int key_length TSRMLS_DC); + +#endif /* ZEND_PERSIST_H */ diff --git a/zend_persist_calc.c b/zend_persist_calc.c new file mode 100644 index 00000000000..36ec05b7283 --- /dev/null +++ b/zend_persist_calc.c @@ -0,0 +1,343 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#include "zend.h" +#include "ZendAccelerator.h" +#include "zend_persist.h" +#include "zend_extensions.h" +#include "zend_shared_alloc.h" +#include "zend_operators.h" + +#define START_SIZE() uint memory_used = 0 +#define ADD_DUP_SIZE(m,s) memory_used += zend_shared_memdup_size((void*)m, s) +#define ADD_SIZE(m) memory_used += ZEND_ALIGNED_SIZE(m) +#define RETURN_SIZE() return memory_used + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO +# define ADD_INTERNED_STRING(str, len) do { \ + const char *tmp = accel_new_interned_string((str), (len), !IS_INTERNED((str)) TSRMLS_CC); \ + if (tmp != (str)) { \ + (str) = (char*)tmp; \ + } else { \ + ADD_DUP_SIZE((str), (len)); \ + } \ + } while (0) +#else +# define ADD_INTERNED_STRING(str, len) ADD_DUP_SIZE((str), (len)) +#endif + +static uint zend_persist_zval_ptr_calc(zval **zp TSRMLS_DC); + +static uint zend_hash_persist_calc(HashTable *ht, int (*pPersistElement)(void *pElement TSRMLS_DC), size_t el_size TSRMLS_DC) +{ + Bucket *p = ht->pListHead; + START_SIZE(); + + while (p) { + /* persist bucket and key */ +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + ADD_DUP_SIZE(p, sizeof(Bucket)); + if (p->nKeyLength) { + const char *tmp = accel_new_interned_string(p->arKey, p->nKeyLength, 0 TSRMLS_CC); + if (tmp != p->arKey) { + p->arKey = tmp; + } else { + ADD_DUP_SIZE(p->arKey, p->nKeyLength); + } + } +#else + ADD_DUP_SIZE(p, sizeof(Bucket) - 1 + p->nKeyLength); +#endif + + /* persist data pointer in bucket */ + if (!p->pDataPtr) { + ADD_DUP_SIZE(p->pData, el_size); + } + + /* persist the data itself */ + if (pPersistElement) { + ADD_SIZE(pPersistElement(p->pData TSRMLS_CC)); + } + + p = p->pListNext; + } + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (ht->nTableMask) { + ADD_DUP_SIZE(ht->arBuckets, sizeof(Bucket*) * ht->nTableSize); + } +#else + ADD_DUP_SIZE(ht->arBuckets, sizeof(Bucket*) * ht->nTableSize); +#endif + + RETURN_SIZE(); +} + +static uint zend_persist_zval_calc(zval *z TSRMLS_DC) +{ + START_SIZE(); + +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + switch (z->type & IS_CONSTANT_TYPE_MASK) { +#else + switch (z->type & ~IS_CONSTANT_INDEX) { +#endif + case IS_STRING: + case IS_CONSTANT: + ADD_INTERNED_STRING(Z_STRVAL_P(z), Z_STRLEN_P(z) + 1); + break; + case IS_ARRAY: + case IS_CONSTANT_ARRAY: + ADD_DUP_SIZE(z->value.ht, sizeof(HashTable)); + ADD_SIZE(zend_hash_persist_calc(z->value.ht, (int (*)(void* TSRMLS_DC)) zend_persist_zval_ptr_calc, sizeof(zval**) TSRMLS_CC)); + break; + } + RETURN_SIZE(); +} + +static uint zend_persist_zval_ptr_calc(zval **zp TSRMLS_DC) +{ + START_SIZE(); + zval *new_ptr = zend_shared_alloc_get_xlat_entry(*zp); + + if (!new_ptr) { + ADD_DUP_SIZE(*zp, sizeof(zval)); + ADD_SIZE(zend_persist_zval_calc(*zp TSRMLS_CC)); + } + RETURN_SIZE(); +} + +static uint zend_persist_op_array_calc(zend_op_array *op_array TSRMLS_DC) +{ + START_SIZE(); + + if (op_array->type != ZEND_USER_FUNCTION) { + return 0; + } + + if (op_array->filename) { + ADD_DUP_SIZE(op_array->filename, strlen(op_array->filename) + 1); + } + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (op_array->literals && !zend_shared_alloc_get_xlat_entry(op_array->literals)) { + zend_literal *p = op_array->literals; + zend_literal *end = p + op_array->last_literal; + ADD_DUP_SIZE(op_array->literals, sizeof(zend_literal) * op_array->last_literal); + while (p < end) { + ADD_SIZE(zend_persist_zval_calc(&p->constant TSRMLS_CC)); + p++; + } + } +#endif + + if (!zend_shared_alloc_get_xlat_entry(op_array->opcodes)) { +#if ZEND_EXTENSION_API_NO <= PHP_5_3_X_API_NO + zend_op *opline = op_array->opcodes; + zend_op *end = op_array->opcodes+op_array->last; + + ADD_DUP_SIZE(op_array->opcodes, sizeof(zend_op) * op_array->last); + while (oplineop1.op_type==IS_CONST) { + ADD_SIZE(zend_persist_zval_calc(&opline->op1.u.constant TSRMLS_CC)); + } + if (opline->op2.op_type==IS_CONST) { + ADD_SIZE(zend_persist_zval_calc(&opline->op2.u.constant TSRMLS_CC)); + } + opline++; + } +#else + ADD_DUP_SIZE(op_array->opcodes, sizeof(zend_op) * op_array->last); +#endif + } + + if (op_array->function_name) { + ADD_DUP_SIZE(op_array->function_name, strlen(op_array->function_name) + 1); + } + + if (op_array->arg_info && + !zend_shared_alloc_get_xlat_entry(op_array->arg_info)) { + zend_uint i; + + ADD_DUP_SIZE(op_array->arg_info, sizeof(zend_arg_info) * op_array->num_args); + for(i=0;inum_args;i++) { + if(op_array->arg_info[i].name) { + ADD_INTERNED_STRING(op_array->arg_info[i].name, op_array->arg_info[i].name_len + 1); + } + if(op_array->arg_info[i].class_name) { + ADD_INTERNED_STRING(op_array->arg_info[i].class_name, op_array->arg_info[i].class_name_len + 1); + } + + } + } + + if (op_array->brk_cont_array) { + ADD_DUP_SIZE(op_array->brk_cont_array, sizeof(zend_brk_cont_element) * op_array->last_brk_cont); + } + + if (op_array->static_variables) { + ADD_DUP_SIZE(op_array->static_variables, sizeof(HashTable)); + ADD_SIZE(zend_hash_persist_calc(op_array->static_variables, (int (*)(void* TSRMLS_DC)) zend_persist_zval_ptr_calc, sizeof(zval**) TSRMLS_CC)); + } + + if(ZCG(accel_directives).save_comments && op_array->doc_comment) { + ADD_DUP_SIZE(op_array->doc_comment, op_array->doc_comment_len + 1); + } + + if(op_array->try_catch_array) { + ADD_DUP_SIZE(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch); + } + + if(op_array->vars && !zend_shared_alloc_get_xlat_entry(op_array->vars)) { + int i; + + ADD_DUP_SIZE(op_array->vars, sizeof(zend_compiled_variable) * op_array->last_var); + for(i=0; ilast_var; i++) { + ADD_INTERNED_STRING(op_array->vars[i].name, op_array->vars[i].name_len + 1); + } + } + + RETURN_SIZE(); +} + +static uint zend_persist_property_info_calc(zend_property_info *prop TSRMLS_DC) +{ + START_SIZE(); + ADD_INTERNED_STRING(prop->name, prop->name_length + 1); + if(ZCG(accel_directives).save_comments && prop->doc_comment) { + ADD_DUP_SIZE(prop->doc_comment, prop->doc_comment_len + 1); + } + RETURN_SIZE(); +} + +static uint zend_persist_class_entry_calc(zend_class_entry **pce TSRMLS_DC) +{ + zend_class_entry *ce = *pce; + START_SIZE(); + + if (ce->type == ZEND_USER_CLASS) { + ADD_DUP_SIZE(ce, sizeof(zend_class_entry)); + ADD_INTERNED_STRING(ce->name, ce->name_length + 1); + ADD_SIZE(zend_hash_persist_calc(&ce->function_table, (int (*)(void* TSRMLS_DC)) zend_persist_op_array_calc, sizeof(zend_op_array) TSRMLS_CC)); +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (ce->default_properties_table) { + int i; + + ADD_SIZE(sizeof(zval*) * ce->default_properties_count); + for (i = 0; i < ce->default_properties_count; i++) { + if (ce->default_properties_table[i]) { + ADD_SIZE(zend_persist_zval_ptr_calc(&ce->default_properties_table[i] TSRMLS_CC)); + } + } + } + if (ce->default_static_members_table) { + int i; + + ADD_SIZE(sizeof(zval*) * ce->default_static_members_count); + for (i = 0; i < ce->default_static_members_count; i++) { + if (ce->default_static_members_table[i]) { + ADD_SIZE(zend_persist_zval_ptr_calc(&ce->default_static_members_table[i] TSRMLS_CC)); + } + } + } +#else + ADD_SIZE(zend_hash_persist_calc(&ce->default_properties, (int (*)(void* TSRMLS_DC)) zend_persist_zval_ptr_calc, sizeof(zval**) TSRMLS_CC)); + ADD_SIZE(zend_hash_persist_calc(&ce->default_static_members, (int (*)(void* TSRMLS_DC)) zend_persist_zval_ptr_calc, sizeof(zval**) TSRMLS_CC)); +#endif + ADD_SIZE(zend_hash_persist_calc(&ce->constants_table, (int (*)(void* TSRMLS_DC)) zend_persist_zval_ptr_calc, sizeof(zval**) TSRMLS_CC)); + + if (ZEND_CE_FILENAME(ce)) { + ADD_DUP_SIZE(ZEND_CE_FILENAME(ce), strlen(ZEND_CE_FILENAME(ce)) + 1); + } + if(ZCG(accel_directives).save_comments && ZEND_CE_DOC_COMMENT(ce)) { + ADD_DUP_SIZE(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT_LEN(ce) + 1); + } + + ADD_SIZE(zend_hash_persist_calc(&ce->properties_info, (int (*)(void* TSRMLS_DC)) zend_persist_property_info_calc, sizeof(zend_property_info) TSRMLS_CC)); + +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + if (ce->trait_aliases) { + int i = 0; + while (ce->trait_aliases[i]) { + if (ce->trait_aliases[i]->trait_method) { + if (ce->trait_aliases[i]->trait_method->method_name) { + ADD_SIZE(ce->trait_aliases[i]->trait_method->mname_len+1); + } + if (ce->trait_aliases[i]->trait_method->class_name) { + ADD_SIZE(ce->trait_aliases[i]->trait_method->cname_len+1); + } + ADD_SIZE(sizeof(zend_trait_method_reference)); + } + + if (ce->trait_aliases[i]->alias) { + ADD_SIZE(ce->trait_aliases[i]->alias_len+1); + } + ADD_SIZE(sizeof(zend_trait_alias)); + i++; + } + ADD_SIZE(sizeof(zend_trait_alias*) * (i + 1)); + } + + if (ce->trait_precedences) { + int i = 0; + + while (ce->trait_precedences[i]) { + ADD_SIZE(ce->trait_precedences[i]->trait_method->mname_len+1); + ADD_SIZE(ce->trait_precedences[i]->trait_method->cname_len+1); + ADD_SIZE(sizeof(zend_trait_method_reference)); + + if (ce->trait_precedences[i]->exclude_from_classes) { + int j = 0; + + while (ce->trait_precedences[i]->exclude_from_classes[j]) { + ADD_SIZE(strlen((char*)ce->trait_precedences[i]->exclude_from_classes[j]) + 1); + j++; + } + ADD_SIZE(sizeof(zend_class_entry*) * (j+1)); + } + ADD_SIZE(sizeof(zend_trait_precedence)); + i++; + } + ADD_SIZE(sizeof(zend_trait_precedence*) * (i+1)); + } +#endif + } + RETURN_SIZE(); +} + +static uint zend_accel_persist_class_table_calc(HashTable *class_table TSRMLS_DC) +{ + return zend_hash_persist_calc(class_table, (int (*)(void* TSRMLS_DC)) zend_persist_class_entry_calc, sizeof(zend_class_entry*) TSRMLS_CC); +} + +uint zend_accel_script_persist_calc(zend_persistent_script *new_persistent_script, char *key, unsigned int key_length TSRMLS_DC) +{ + START_SIZE(); + + ADD_SIZE(zend_hash_persist_calc(&new_persistent_script->function_table, (int (*)(void* TSRMLS_DC)) zend_persist_op_array_calc, sizeof(zend_op_array) TSRMLS_CC)); + ADD_SIZE(zend_accel_persist_class_table_calc(&new_persistent_script->class_table TSRMLS_CC)); + ADD_SIZE(zend_persist_op_array_calc(&new_persistent_script->main_op_array TSRMLS_CC)); + ADD_DUP_SIZE(key, key_length + 1); + ADD_DUP_SIZE(new_persistent_script->full_path, new_persistent_script->full_path_len + 1); + ADD_DUP_SIZE(new_persistent_script, sizeof(zend_persistent_script)); + + RETURN_SIZE(); +} diff --git a/zend_shared_alloc.c b/zend_shared_alloc.c new file mode 100644 index 00000000000..c0024c66660 --- /dev/null +++ b/zend_shared_alloc.c @@ -0,0 +1,473 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#include +#include "ZendAccelerator.h" +#include "zend_shared_alloc.h" +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#ifndef ZEND_WIN32 +# include +# include +# include +# include +# include +#endif + +#ifdef HAVE_MPROTECT +# include "sys/mman.h" +#endif + +#define TMP_DIR "/tmp" +#define SEM_FILENAME_PREFIX ".ZendSem." +#define S_H(s) g_shared_alloc_handler->s + +/* True globals */ +static zend_bool locked; +/* old/new mapping. We can use true global even for ZTS because its usage + is wrapped with exclusive lock anyway */ +static HashTable xlat_table; +static const zend_shared_memory_handlers *g_shared_alloc_handler = NULL; +static const char *g_shared_model; +/* pointer to globals allocated in SHM and shared across processes */ +zend_smm_shared_globals *smm_shared_globals; + +#ifndef ZEND_WIN32 +int lock_file; +static char lockfile_name[sizeof(TMP_DIR)+sizeof(SEM_FILENAME_PREFIX)+8]; +#endif + +static const zend_shared_memory_handler_entry handler_table[] = { +#if USE_MMAP + { "mmap", &zend_alloc_mmap_handlers }, +#endif +#if USE_SHM + { "shm", &zend_alloc_shm_handlers }, +#endif +#if USE_SHM_OPEN + { "posix", &zend_alloc_posix_handlers }, +#endif +#ifdef ZEND_WIN32 + { "win32", &zend_alloc_win32_handlers }, +#endif + { NULL, NULL} +}; + +#ifndef ZEND_WIN32 +void zend_shared_alloc_create_lock(void) +{ + int val; + + sprintf(lockfile_name, "%s/%sXXXXXX", TMP_DIR, SEM_FILENAME_PREFIX); + lock_file = mkstemp(lockfile_name); + fchmod(lock_file, 0666); + + if (lock_file == -1) { + zend_accel_error(ACCEL_LOG_FATAL, "Unable to create lock file: %s (%d)", strerror(errno), errno); + } + val = fcntl(lock_file, F_GETFD, 0); + val |= FD_CLOEXEC; + fcntl(lock_file, F_SETFD, val); + + unlink(lockfile_name); +} +#endif + +static void no_memory_bailout(int allocate_size, char *error) +{ + zend_accel_error(ACCEL_LOG_FATAL, "Unable to allocate shared memory segment of %d bytes: %s: %s (%d)", allocate_size, error?error:"unknown", strerror(errno), errno ); +} + +static void copy_shared_segments(void *to, void *from, int count, int size) +{ + zend_shared_segment **shared_segments_v = (zend_shared_segment **)to; + void *shared_segments_to_p = ((char *)to + count*(sizeof(void *))); + void *shared_segments_from_p = from; + int i; + + for(i=0;ihandler; + g_shared_model = he->name; + ZSMMG(shared_segments) = NULL; + ZSMMG(shared_segments_count) = 0; + + res = S_H(create_segments)(requested_size, shared_segments_p, shared_segments_count, error_in); + + if( res ) { + /* this model works! */ + return res; + } + if(*shared_segments_p) { + int i; + /* cleanup */ + for(i=0;i<*shared_segments_count;i++) { + if((*shared_segments_p)[i]->p && (int)(*shared_segments_p)[i]->p != -1) { + S_H(detach_segment)((*shared_segments_p)[i]); + } + } + free(*shared_segments_p); + *shared_segments_p = NULL; + } + g_shared_alloc_handler = NULL; + return ALLOC_FAILURE; +} + +int zend_shared_alloc_startup(int requested_size) +{ + zend_shared_segment **tmp_shared_segments; + size_t shared_segments_array_size; + zend_smm_shared_globals tmp_shared_globals, *p_tmp_shared_globals; + char *error_in = NULL; + const zend_shared_memory_handler_entry *he; + int res = ALLOC_FAILURE; + + TSRMLS_FETCH(); + + /* shared_free must be valid before we call zend_shared_alloc() + * - make it temporarily point to a local variable + */ + smm_shared_globals = &tmp_shared_globals; + ZSMMG(shared_free) = requested_size; /* goes to tmp_shared_globals.shared_free */ + + zend_shared_alloc_create_lock(); + + if(ZCG(accel_directives).memory_model && ZCG(accel_directives).memory_model[0]) { + char* model = ZCG(accel_directives).memory_model; + /* "cgi" is really "shm"... */ + if( strncmp(ZCG(accel_directives).memory_model,"cgi",4) == 0 ){ + model = "shm"; + } + + for(he = handler_table; he->name; he++) { + if(strcmp(model, he->name) == 0) { + res=zend_shared_alloc_try(he, requested_size, &ZSMMG(shared_segments), &ZSMMG(shared_segments_count), &error_in); + if( res ) { + /* this model works! */ + } + break; + } + } + } + + if( res == FAILED_REATTACHED ){ + smm_shared_globals = NULL; + return res; + } + + if(!g_shared_alloc_handler) { + /* try memory handlers in order */ + for(he = handler_table; he->name; he++) { + res=zend_shared_alloc_try(he, requested_size, &ZSMMG(shared_segments), &ZSMMG(shared_segments_count), &error_in); + if( res ) { + /* this model works! */ + break; + } + } + } + + if(!g_shared_alloc_handler) { + no_memory_bailout(requested_size, error_in); + return ALLOC_FAILURE; + } + + if( res == SUCCESSFULLY_REATTACHED ){ + return res; + } + + shared_segments_array_size = ZSMMG(shared_segments_count)*S_H(segment_type_size)(); + + /* move shared_segments and shared_free to shared memory */ + locked = 1; /* no need to perform a real lock at this point */ + p_tmp_shared_globals = (zend_smm_shared_globals *) zend_shared_alloc(sizeof(zend_smm_shared_globals)); + + tmp_shared_segments = zend_shared_alloc(shared_segments_array_size+ZSMMG(shared_segments_count)*sizeof(void *)); + copy_shared_segments(tmp_shared_segments, ZSMMG(shared_segments)[0], ZSMMG(shared_segments_count), S_H(segment_type_size)()); + + *p_tmp_shared_globals = tmp_shared_globals; + smm_shared_globals = p_tmp_shared_globals; + + free(ZSMMG(shared_segments)); + ZSMMG(shared_segments) = tmp_shared_segments; + + ZSMMG(shared_memory_state).positions = (int *) zend_shared_alloc(sizeof(int)*ZSMMG(shared_segments_count)); + locked = 0; + + return res; +} + +void zend_shared_alloc_shutdown(void) +{ + zend_shared_segment **tmp_shared_segments; + size_t shared_segments_array_size; + zend_smm_shared_globals tmp_shared_globals; + int i; + + tmp_shared_globals = *smm_shared_globals; + smm_shared_globals = &tmp_shared_globals; + shared_segments_array_size = ZSMMG(shared_segments_count)*(S_H(segment_type_size)()+sizeof(void *)); + tmp_shared_segments = emalloc(shared_segments_array_size); + copy_shared_segments(tmp_shared_segments, ZSMMG(shared_segments)[0], ZSMMG(shared_segments_count), S_H(segment_type_size)()); + ZSMMG(shared_segments) = tmp_shared_segments; + + for(i=0; i ZSMMG(shared_free)) { /* No hope to find a big-enough block */ + SHARED_ALLOC_FAILED(); + return NULL; + } + for (i=0; isize-ZSMMG(shared_segments)[i]->pos >= block_size) { /* found a valid block */ + zend_shared_memory_block_header *p = (zend_shared_memory_block_header *) (((char *) ZSMMG(shared_segments)[i]->p)+ZSMMG(shared_segments)[i]->pos); + int remainder = block_size % PLATFORM_ALIGNMENT; + void *retval; + + if (remainder!=0) { + size += PLATFORM_ALIGNMENT-remainder; + block_size += PLATFORM_ALIGNMENT-remainder; + } + ZSMMG(shared_segments)[i]->pos += block_size; + ZSMMG(shared_free) -= block_size; + p->size = size; + retval = ((char *) p)+sizeof(zend_shared_memory_block_header); + memset(retval, 0, size); + return retval; + } + } + SHARED_ALLOC_FAILED(); + return NULL; +} + +int zend_shared_memdup_size(void *source, size_t size) +{ + void **old_p; + + if (zend_hash_index_find(&xlat_table, (ulong) source, (void **) &old_p)==SUCCESS) { + /* we already duplicated this pointer */ + return 0; + } + zend_shared_alloc_register_xlat_entry(source, source); + return ZEND_ALIGNED_SIZE(size); +} + +void *_zend_shared_memdup(void *source, size_t size, zend_bool free_source TSRMLS_DC) +{ + void **old_p, *retval; + + if (zend_hash_index_find(&xlat_table, (ulong) source, (void **) &old_p)==SUCCESS) { + /* we already duplicated this pointer */ + return *old_p; + } + retval = ZCG(mem);; + ZCG(mem) = (void*)(((char*)ZCG(mem)) + ZEND_ALIGNED_SIZE(size)); + memcpy(retval, source, size); + if (free_source) { + interned_efree((char*)source); + } + zend_shared_alloc_register_xlat_entry(source, retval); + return retval; +} + +void zend_shared_alloc_safe_unlock(TSRMLS_D) +{ + if (locked) { + zend_shared_alloc_unlock(TSRMLS_C); + } +} + +#ifndef ZEND_WIN32 +/* name l_type l_whence l_start l_len */ +static FLOCK_STRUCTURE(mem_write_lock, F_WRLCK, SEEK_SET, 0, 1); +static FLOCK_STRUCTURE(mem_write_unlock, F_UNLCK, SEEK_SET, 0, 1); +#endif + +void zend_shared_alloc_lock(TSRMLS_D) +{ +#ifndef ZEND_WIN32 +#if 0 + /* this will happen once per process, and will un-globalize mem_write_lock */ + if (mem_write_lock.l_pid == -1) { + mem_write_lock.l_pid = getpid(); + } +#endif + + while (1) { + if (fcntl(lock_file, F_SETLKW, &mem_write_lock) == -1) { + if (errno == EINTR) { + continue; + } + zend_accel_error(ACCEL_LOG_ERROR, "Cannot create lock - %s (%d)", strerror(errno), errno); + } + break; + } +#else + zend_shared_alloc_lock_win32(); +#endif + + locked=1; + + /* Prepare translation table + * + * Make it persistent so that it uses malloc() and allocated blocks + * won't be taken from space which is freed by efree in memdup. + * Otherwise it leads to false matches in memdup check. + */ + zend_hash_init(&xlat_table, 100, NULL, NULL, 1); +} + +void zend_shared_alloc_unlock(TSRMLS_D) +{ + /* Destroy translation table */ + zend_hash_destroy(&xlat_table); + + locked=0; + +#ifndef ZEND_WIN32 + if (fcntl(lock_file, F_SETLK, &mem_write_unlock) == -1) { + zend_accel_error(ACCEL_LOG_ERROR, "Cannot remove lock - %s (%d)", strerror(errno), errno); + } +#else + zend_shared_alloc_unlock_win32(); +#endif +} + +void zend_shared_alloc_clear_xlat_table(void) +{ + zend_hash_clean(&xlat_table); +} + +void zend_shared_alloc_register_xlat_entry(const void *old, const void *new) +{ + zend_hash_index_update(&xlat_table, (ulong) old, (void*)&new, sizeof(void *), NULL); +} + +void *zend_shared_alloc_get_xlat_entry(const void *old) +{ + void **retval; + + if (zend_hash_index_find(&xlat_table, (ulong) old, (void **) &retval)==FAILURE) { + return NULL; + } + return *retval; +} + +size_t zend_shared_alloc_get_free_memory(void) +{ + return ZSMMG(shared_free); +} + +size_t zend_shared_alloc_get_largest_free_block(void) +{ + int i; + size_t largest_block_size=0; + + for (i=0; isize - ZSMMG(shared_segments)[i]->pos; + + if (block_size>largest_block_size) { + largest_block_size = block_size; + } + } + return largest_block_size; +} + +void zend_shared_alloc_save_state(void) +{ + int i; + + for (i=0; ipos; + } + ZSMMG(shared_memory_state).shared_free = ZSMMG(shared_free); +} + +void zend_shared_alloc_restore_state(void) +{ + int i; + + for (i=0; ipos = ZSMMG(shared_memory_state).positions[i]; + } + ZSMMG(shared_free) = ZSMMG(shared_memory_state).shared_free; + ZSMMG(memory_exhausted) = 0; + ZSMMG(wasted_shared_memory) = 0; +} + +const char *zend_accel_get_shared_model() +{ + return g_shared_model; +} + +void zend_accel_shared_protect(int mode TSRMLS_DC) +{ +#ifdef HAVE_MPROTECT + int i; + + if (mode) { + mode = PROT_READ; + } else { + mode = PROT_READ|PROT_WRITE; + } + + for(i=0; i < ZSMMG(shared_segments_count); i++) { + mprotect(ZSMMG(shared_segments)[i]->p, ZSMMG(shared_segments)[i]->size, mode); + } +#endif +} diff --git a/zend_shared_alloc.h b/zend_shared_alloc.h new file mode 100644 index 00000000000..aa615144524 --- /dev/null +++ b/zend_shared_alloc.h @@ -0,0 +1,166 @@ +/* + +----------------------------------------------------------------------+ + | Zend Optimizer+ | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + | Stanislav Malyshev | + | Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_SHARED_ALLOC_H +#define ZEND_SHARED_ALLOC_H + +#include "zend.h" + +#if defined(__APPLE__) && defined(__MACH__) /* darwin */ +# define USE_SHM_OPEN 1 +# define USE_MMAP 1 +#elif defined(__linux__) || defined(_AIX) +# define USE_SHM 1 +# define USE_MMAP 1 +#elif defined(__FreeBSD__) +# define USE_SHM_OPEN 1 +# define USE_MMAP 1 +# define USE_SHM 1 +#elif defined(__sparc) || defined(__sun) +# define USE_SHM_OPEN 1 +# define USE_SHM 1 +# if defined(__i386) +# define USE_MMAP 1 +# endif +#endif + +#define ALLOC_FAILURE 0 +#define ALLOC_SUCCESS 1 +#define FAILED_REATTACHED 2 +#define SUCCESSFULLY_REATTACHED 4 +#define ALLOC_FAIL_MAPPING 8 + +typedef struct _zend_shared_segment { + size_t size; + size_t pos; /* position for simple stack allocator */ + void *p; +} zend_shared_segment; + +typedef int (*create_segments_t)(size_t requested_size, zend_shared_segment ***shared_segments, int *shared_segment_count, char **error_in); +typedef int (*detach_segment_t)(zend_shared_segment *shared_segment); + +typedef struct { + create_segments_t create_segments; + detach_segment_t detach_segment; + size_t (*segment_type_size)(void); +} zend_shared_memory_handlers; + +typedef struct _handler_entry { + const char *name; + zend_shared_memory_handlers *handler; +} zend_shared_memory_handler_entry; + +typedef struct _zend_shared_memory_block_header { + int size; +} zend_shared_memory_block_header; + +typedef struct _zend_shared_memory_state { + int *positions; /* current positions for each segment */ + int shared_free; /* amount of free shared memory */ +} zend_shared_memory_state; + +typedef struct _zend_smm_shared_globals { + /* Shared Memory Manager */ + zend_shared_segment **shared_segments; + /* Number of allocated shared segments */ + int shared_segments_count; + /* Amount of free shared memory */ + size_t shared_free; + /* Amount of shared memory allocated by garbage */ + int wasted_shared_memory; + /* No more shared memory flag */ + zend_bool memory_exhausted; + /* Saved Shared Allocator State */ + zend_shared_memory_state shared_memory_state; + /* Pointer to the application's shared data structures */ + void *app_shared_globals; +} zend_smm_shared_globals; + +extern zend_smm_shared_globals *smm_shared_globals; + +#define ZSMMG(element) (smm_shared_globals->element) + +#define SHARED_ALLOC_REATTACHED (SUCCESS+1) + +int zend_shared_alloc_startup(int requested_size); +void zend_shared_alloc_shutdown(void); + +/* allocate shared memory block */ +void *zend_shared_alloc(size_t size); + +/* copy into shared memory */ +void *_zend_shared_memdup(void *p, size_t size, zend_bool free_source TSRMLS_DC); +int zend_shared_memdup_size(void *p, size_t size); + +typedef union _align_test { + void *ptr; + double dbl; + long lng; +} align_test; + +#if ZEND_GCC_VERSION >= 2000 +# define PLATFORM_ALIGNMENT (__alignof__ (align_test)) +#else +# define PLATFORM_ALIGNMENT (sizeof(align_test)) +#endif + +#define ZEND_ALIGNED_SIZE(size) \ + ((size + PLATFORM_ALIGNMENT - 1) & ~(PLATFORM_ALIGNMENT - 1)) + +/* exclusive locking */ +void zend_shared_alloc_lock(TSRMLS_D); +void zend_shared_alloc_unlock(TSRMLS_D); /* returns the allocated size during lock..unlock */ +void zend_shared_alloc_safe_unlock(TSRMLS_D); + +/* old/new mapping functions */ +void zend_shared_alloc_clear_xlat_table(void); +void zend_shared_alloc_register_xlat_entry(const void *old, const void *new); +void *zend_shared_alloc_get_xlat_entry(const void *old); + +size_t zend_shared_alloc_get_free_memory(void); +void zend_shared_alloc_save_state(void); +void zend_shared_alloc_restore_state(void); +size_t zend_shared_alloc_get_largest_free_block(void); +const char *zend_accel_get_shared_model(); + +/* memory write protection */ +void zend_accel_shared_protect(int mode TSRMLS_DC); + +#ifdef USE_MMAP +extern zend_shared_memory_handlers zend_alloc_mmap_handlers; +#endif + +#ifdef USE_SHM +extern zend_shared_memory_handlers zend_alloc_shm_handlers; +#endif + +#ifdef USE_SHM_OPEN +extern zend_shared_memory_handlers zend_alloc_posix_handlers; +#endif + +#ifdef ZEND_WIN32 +extern zend_shared_memory_handlers zend_alloc_win32_handlers; +void zend_shared_alloc_create_lock(); +void zend_shared_alloc_lock_win32(); +void zend_shared_alloc_unlock_win32(); +#endif + +#endif /* ZEND_SHARED_ALLOC_H */ From aafc1456b0ae7212321250ca7915c8da076e7f6e Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 13 Feb 2013 16:33:14 +0400 Subject: [PATCH 015/276] spelling --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 69273d0624c..a284dd31b5c 100644 --- a/README +++ b/README @@ -31,7 +31,7 @@ cp .libs/ZendOptimizerPlus.so $PHP_DIR/lib/ZendOptimizerPlus.so - Edit php.ini -zend_extensin=/...full path.../ZendOptimizerPlus.so +zend_extension=/...full path.../ZendOptimizerPlus.so - Restart PHP From 7c0e3ccdb6acc569964c3e904e30e9d3dc97ff04 Mon Sep 17 00:00:00 2001 From: Damien Tournoud Date: Wed, 13 Feb 2013 16:08:19 +0100 Subject: [PATCH 016/276] Fix typos and grammar issues in README. --- README | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/README b/README index a284dd31b5c..224ebe3f284 100644 --- a/README +++ b/README @@ -4,7 +4,7 @@ The Zend Optimizer+ The Zend Optimizer+ provides faster PHP execution through opcode caching and optimization. It improves PHP performance by storing precompiled script bytecode in the shared memory. This eliminates the stages of reading code from -the disk and compiling it on future access. In addition it applies a few +the disk and compiling it on future access. In addition, it applies a few bytecode optimization patterns that make code execution faster. Compatibility @@ -35,10 +35,10 @@ zend_extension=/...full path.../ZendOptimizerPlus.so - Restart PHP -Speed Tunning +Speed Tuning ------------- -We reccomend the following configuration options for best performance. +We recommend the following configuration options for best performance. zend_optimizerplus.memory_consumption=128 zend_optimizerplus.interned_strings_buffer=8 @@ -73,19 +73,19 @@ zend_optimizerplus.max_accelerated_files (default "2000") are allowed. zend_optimizerplus.max_wasted_percentage (default "5") - The maximum percentage of "wasted" memory until a restart is scheduled + The maximum percentage of "wasted" memory until a restart is scheduled. zend_optimizerplus.use_cwd (default "1") When this directive is enabled, the Optimizer+ appends the current working - directory to the script key, thus elminating possible collisions between - files with the same name (basename). Disablingthe directive improves + directory to the script key, thus eliminating possible collisions between + files with the same name (basename). Disabling the directive improves performance, but may break existing applications. zend_optimizerplus.validate_timestamps (default "1") When disabled, you must reset the Optimizer+ manually or restart the webserver for changes to the filesystem to take effect. - The frequancy of the check is controlled by the directive - "zend_optimizerplus.revalidate_freq" + The frequency of the check is controlled by the directive + "zend_optimizerplus.revalidate_freq". zend_optimizerplus.revalidate_freq (default "2") How often (in seconds) to check file timestamps for changes to the shared @@ -110,7 +110,7 @@ zend_optimizerplus.fast_shutdown (default "0") the Zend Engine Memory Manager do the work. zend_optimizerplus.enable_file_override (default "0") - Allow file existance override (file_exists, etc.) performance feature + Allow file existence override (file_exists, etc.) performance feature. zend_optimizerplus.optimization_level (default "0xffffffff") A bitmask, where each bit enables or disables the appropriate Optimizer+ @@ -130,10 +130,10 @@ zend_optimizerplus.inherited_hack (default "1") anymore and this setting has no effect. zend_optimizerplus.dups_fix (default "0") - Enable this hack as a workaround for "duplicate definition" errors + Enable this hack as a workaround for "duplicate definition" errors. zend_optimizerplus.blacklist_filename - The location of the Optimizer+ blacklist file + The location of the Optimizer+ blacklist file. The Optimizer+ blacklist file is a text file that holds the names of files that should not be accelerated. The file format is to add each filename to a new line. The filename may be a full path or just a file prefix @@ -162,10 +162,10 @@ zend_optimizerplus.force_restart_timeout (default "180") in the Apache logs when this happens. zend_optimizerplus.error_log - Optimizer+ error_log file name. Empty string assumes "stderr" + Optimizer+ error_log file name. Empty string assumes "stderr". zend_optimizerplus.log_verbosity_level (default "1") - Alll Optimizer+ errors go to the Web server log. + All Optimizer+ errors go to the Web server log. By default, only fatal errors (level 0) or errors (level 1) are logged. You can also enable warnings (level 2), info messages (level 3) or - debug messesges (level 4). + debug messages (level 4). From 2ba47175cff2f93b166b526bf942dfb8aaa406bf Mon Sep 17 00:00:00 2001 From: sasezaki Date: Thu, 14 Feb 2013 00:48:18 +0900 Subject: [PATCH 017/276] typo at Optimizer/block_pass.c --- Optimizer/block_pass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Optimizer/block_pass.c b/Optimizer/block_pass.c index 2481b25475e..aeb8f18707c 100644 --- a/Optimizer/block_pass.c +++ b/Optimizer/block_pass.c @@ -228,7 +228,7 @@ static zend_code_block *find_code_blocks(zend_op_array *op_array) cur_block->next = &blocks[op_array->last+1]; print_block(cur_block, op_array->opcodes, ""); - /* The op_array desn't have BRK, CONT, GOTO opcodes anyway */ + /* The op_array doesn't have BRK, CONT, GOTO opcodes anyway */ if(op_array->brk_cont_array) { efree(op_array->brk_cont_array); } From 7334835143cf3a3907337e5f8b718252d870ea74 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 13 Feb 2013 21:41:07 +0400 Subject: [PATCH 018/276] Fixed zend_optimizerplus.enable_file_override=1 compatibility with PHP-5.3 --- zend_accelerator_module.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index b1c90a0eace..41ae4268990 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -291,6 +291,10 @@ static void accel_file_in_cache(int type, INTERNAL_FUNCTION_PARAMETERS) convert_to_string_ex(zfilename); filename = Z_STRVAL_PP(zfilename); filename_len = Z_STRLEN_PP(zfilename); +#elif ZEND_EXTENSION_API_NO == PHP_5_3_X_API_NO + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { + return; + } #else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) { return; From 54da28b015c5b36d41e16c7262c61b31775ea422 Mon Sep 17 00:00:00 2001 From: John Leach Date: Wed, 13 Feb 2013 18:47:31 +0000 Subject: [PATCH 019/276] Added LICENSE from http://www.php.net/license/3_01.txt Closes #2 --- LICENSE | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000000..42536af3206 --- /dev/null +++ b/LICENSE @@ -0,0 +1,68 @@ +-------------------------------------------------------------------- + The PHP License, version 3.01 +Copyright (c) 1999 - 2012 The PHP Group. All rights reserved. +-------------------------------------------------------------------- + +Redistribution and use in source and binary forms, with or without +modification, is permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + 3. The name "PHP" must not be used to endorse or promote products + derived from this software without prior written permission. For + written permission, please contact group@php.net. + + 4. Products derived from this software may not be called "PHP", nor + may "PHP" appear in their name, without prior written permission + from group@php.net. You may indicate that your software works in + conjunction with PHP by saying "Foo for PHP" instead of calling + it "PHP Foo" or "phpfoo" + + 5. The PHP Group may publish revised and/or new versions of the + license from time to time. Each version will be given a + distinguishing version number. + Once covered code has been published under a particular version + of the license, you may always continue to use it under the terms + of that version. You may also choose to use such covered code + under the terms of any subsequent version of the license + published by the PHP Group. No one other than the PHP Group has + the right to modify the terms applicable to covered code created + under this License. + + 6. Redistributions of any form whatsoever must retain the following + acknowledgment: + "This product includes PHP software, freely available from + ". + +THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND +ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP +DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------- + +This software consists of voluntary contributions made by many +individuals on behalf of the PHP Group. + +The PHP Group can be contacted via Email at group@php.net. + +For more information on the PHP Group and the PHP project, +please see . + +PHP includes the Zend Engine, freely available at +. From 8847f9107b231ed872429537f01ff442a2eb3378 Mon Sep 17 00:00:00 2001 From: Thomas Lallement Date: Wed, 13 Feb 2013 19:56:44 +0100 Subject: [PATCH 020/276] Fix typo --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 224ebe3f284..05c4c606813 100644 --- a/README +++ b/README @@ -67,7 +67,7 @@ zend_optimizerplus.interned_strings_buffer (default "4") zend_optimizerplus.max_accelerated_files (default "2000") The maximum number of keys (scripts) in the Optimizer+ hash table. - The number is actually the the first one in the following set of prime + The number is actually the first one in the following set of prime numbers that is bigger than the one supplied: { 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987 }. Only numbers between 200 and 100000 are allowed. From 30c3a59668e4def67d29c86d5a43eda134714857 Mon Sep 17 00:00:00 2001 From: Pierrick Charron Date: Wed, 13 Feb 2013 14:25:38 -0500 Subject: [PATCH 021/276] Avoid unnecessary code and change the type of accelerator_enabled accelerator_enabled will always be true when accelerator_get_status returns an array. Also the accelerator_enabled should be a boolean and not a long --- zend_accelerator_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index 41ae4268990..807c2446a45 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -470,7 +470,7 @@ static ZEND_FUNCTION(accelerator_get_status) array_init(return_value); /* Trivia */ - add_assoc_long(return_value, "accelerator_enabled", ZCG(startup_ok) && ZCSG(accelerator_enabled)); + add_assoc_bool(return_value, "accelerator_enabled", 1); add_assoc_bool(return_value, "cache_full", ZSMMG(memory_exhausted)); /* Memory usage statistics */ From bfcbe7849b4b5a7cd4a3a5c8a950de621b67e9c3 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 14 Feb 2013 10:01:29 +0400 Subject: [PATCH 022/276] Avoid compilation of unsupported SHM backends --- shared_alloc_mmap.c | 8 ++++++-- shared_alloc_posix.c | 8 ++++++-- shared_alloc_shm.c | 8 ++++++-- zend_shared_alloc.c | 6 +++--- zend_shared_alloc.h | 47 ++++++++++++++++++++++++++++++++------------ 5 files changed, 55 insertions(+), 22 deletions(-) diff --git a/shared_alloc_mmap.c b/shared_alloc_mmap.c index 7e23d4ea8d9..2a389c072cb 100644 --- a/shared_alloc_mmap.c +++ b/shared_alloc_mmap.c @@ -19,14 +19,16 @@ +----------------------------------------------------------------------+ */ +#include "zend_shared_alloc.h" + +#ifdef USE_MMAP + #include #include #include #include #include -#include "zend_shared_alloc.h" - #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) # define MAP_ANONYMOUS MAP_ANON #endif @@ -68,3 +70,5 @@ zend_shared_memory_handlers zend_alloc_mmap_handlers = { detach_segment, segment_type_size }; + +#endif /* USE_MMAP */ diff --git a/shared_alloc_posix.c b/shared_alloc_posix.c index 5a0111c797a..75ea176f41d 100644 --- a/shared_alloc_posix.c +++ b/shared_alloc_posix.c @@ -19,6 +19,10 @@ +----------------------------------------------------------------------+ */ +#include "zend_shared_alloc.h" + +#ifdef USE_SHM_OPEN + #include #include #include @@ -27,8 +31,6 @@ #include #include -#include "zend_shared_alloc.h" - typedef struct { zend_shared_segment common; int shm_fd; @@ -88,3 +90,5 @@ zend_shared_memory_handlers zend_alloc_posix_handlers = { (detach_segment_t)detach_segment, segment_type_size }; + +#endif /* USE_SHM_OPEN */ diff --git a/shared_alloc_shm.c b/shared_alloc_shm.c index 45fab7c4a31..9d0256e4de6 100644 --- a/shared_alloc_shm.c +++ b/shared_alloc_shm.c @@ -19,6 +19,10 @@ +----------------------------------------------------------------------+ */ +#include "zend_shared_alloc.h" + +#ifdef USE_SHM + #if defined(__FreeBSD__) # include #endif @@ -35,8 +39,6 @@ #include #include -#include "zend_shared_alloc.h" - #ifndef MIN # define MIN(x, y) ((x) > (y)? (y) : (x)) #endif @@ -135,3 +137,5 @@ zend_shared_memory_handlers zend_alloc_shm_handlers = { (detach_segment_t)detach_segment, segment_type_size }; + +#endif /* USE_SHM */ diff --git a/zend_shared_alloc.c b/zend_shared_alloc.c index c0024c66660..3b93d041618 100644 --- a/zend_shared_alloc.c +++ b/zend_shared_alloc.c @@ -58,13 +58,13 @@ static char lockfile_name[sizeof(TMP_DIR)+sizeof(SEM_FILENAME_PREFIX)+8]; #endif static const zend_shared_memory_handler_entry handler_table[] = { -#if USE_MMAP +#ifdef USE_MMAP { "mmap", &zend_alloc_mmap_handlers }, #endif -#if USE_SHM +#ifdef USE_SHM { "shm", &zend_alloc_shm_handlers }, #endif -#if USE_SHM_OPEN +#ifdef USE_SHM_OPEN { "posix", &zend_alloc_posix_handlers }, #endif #ifdef ZEND_WIN32 diff --git a/zend_shared_alloc.h b/zend_shared_alloc.h index aa615144524..12df673cf3c 100644 --- a/zend_shared_alloc.h +++ b/zend_shared_alloc.h @@ -23,23 +23,44 @@ #define ZEND_SHARED_ALLOC_H #include "zend.h" +#include "ZendAccelerator.h" #if defined(__APPLE__) && defined(__MACH__) /* darwin */ -# define USE_SHM_OPEN 1 -# define USE_MMAP 1 -#elif defined(__linux__) || defined(_AIX) -# define USE_SHM 1 -# define USE_MMAP 1 -#elif defined(__FreeBSD__) -# define USE_SHM_OPEN 1 -# define USE_MMAP 1 -# define USE_SHM 1 -#elif defined(__sparc) || defined(__sun) -# define USE_SHM_OPEN 1 -# define USE_SHM 1 -# if defined(__i386) +# ifdef HAVE_SHM_MMAP_POSIX +# define USE_SHM_OPEN 1 +# endif +# ifdef HAVE_SHM_MMAP_ANON # define USE_MMAP 1 # endif +#elif defined(__linux__) || defined(_AIX) +# ifdef HAVE_SHM_IPC +# define USE_SHM 1 +# endif +# ifdef HAVE_SHM_MMAP_ANON +# define USE_MMAP 1 +# endif +#elif defined(__sparc) || defined(__sun) +# ifdef HAVE_SHM_MMAP_POSIX +# define USE_SHM_OPEN 1 +# endif +# ifdef HAVE_SHM_IPC +# define USE_SHM 1 +# endif +# if defined(__i386) +# ifdef HAVE_SHM_MMAP_ANON +# define USE_MMAP 1 +# endif +# endif +#else +# ifdef HAVE_SHM_MMAP_POSIX +# define USE_SHM_OPEN 1 +# endif +# ifdef HAVE_SHM_MMAP_ANON +# define USE_MMAP 1 +# endif +# ifdef HAVE_SHM_IPC +# define USE_SHM 1 +# endif #endif #define ALLOC_FAILURE 0 From f74c938c950de1b0fcdb0ef2bd66760832b57a53 Mon Sep 17 00:00:00 2001 From: Pierre Joye Date: Thu, 14 Feb 2013 07:24:26 +0100 Subject: [PATCH 023/276] - fix windows build --- config.w32 | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/config.w32 b/config.w32 index 6f3c89c135d..feebe41afd3 100644 --- a/config.w32 +++ b/config.w32 @@ -2,27 +2,27 @@ ARG_ENABLE("optimizer-plus", "whether to enable Zend OptimizerPlus support", "ye if (PHP_OPTIMIZER_PLUS != "no") { - PHP_PGI = "no"; // workaround - PHP_PGO = "no"; // workaround + PHP_PGI = "no"; // workaround + PHP_PGO = "no"; // workaround - EXTENSION('ZendOptimizerPlus', "\ - ZendAccelerator.c \ - zend_accelerator_blacklist.c \ - zend_accelerator_debug.c \ - zend_accelerator_hash.c \ - zend_accelerator_module.c \ - zend_accelerator_util_funcs.c \ - zend_persist.c \ - zend_persist_calc.c \ - zend_shared_alloc.c \ - shared_alloc_win32.c", true); + EXTENSION('ZendOptimizerPlus', "\ + ZendAccelerator.c \ + zend_accelerator_blacklist.c \ + zend_accelerator_debug.c \ + zend_accelerator_hash.c \ + zend_accelerator_module.c \ + zend_accelerator_util_funcs.c \ + zend_persist.c \ + zend_persist_calc.c \ + zend_shared_alloc.c \ + shared_alloc_win32.c", true); - ADD_SOURCES("Optimizer", "zend_optimizer.c", "ZendOptimizerPlus", "OptimizerObj"); + ADD_SOURCES(configure_module_dirname + "/Optimizer", "zend_optimizer.c", "ZendOptimizerPlus", "OptimizerObj"); - ADD_FLAG('CFLAGS_ZENDOPTIMIZERPLUS', "/I ."); - ADD_FLAG('CFLAGS_ZENDOPTIMIZERPLUS', "/D HAVE_OPTIMIZER_PLUS=1"); + ADD_FLAG('CFLAGS_ZENDOPTIMIZERPLUS', "/I " + configure_module_dirname); + ADD_FLAG('CFLAGS_ZENDOPTIMIZERPLUS', "/D HAVE_OPTIMIZER_PLUS=1"); - ADD_FLAG('CFLAGS_ZENDOPTIMIZERPLUS', "/Dregexec=php_regexec /Dregerror=php_regerror /Dregfree=php_regfree /Dregcomp=php_regcomp /Iext/ereg/regex"); + ADD_FLAG('CFLAGS_ZENDOPTIMIZERPLUS', "/Dregexec=php_regexec /Dregerror=php_regerror /Dregfree=php_regfree /Dregcomp=php_regcomp /Iext/ereg/regex"); } From 219decd8ec4d6ec4fe35812d319871db62037d7e Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 14 Feb 2013 10:38:20 +0400 Subject: [PATCH 024/276] This is a development version yet --- ZendAccelerator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZendAccelerator.h b/ZendAccelerator.h index 68afad38f4c..2aa2248cd32 100644 --- a/ZendAccelerator.h +++ b/ZendAccelerator.h @@ -27,7 +27,7 @@ #endif #define ACCELERATOR_PRODUCT_NAME "Zend Optimizer+" -#define ACCELERATOR_VERSION "7.0.0" +#define ACCELERATOR_VERSION "7.0.0-dev" /* 2 - added Profiler support, on 20010712 */ /* 3 - added support for Optimizer's encoded-only-files mode */ /* 4 - works with the new Optimizer, that supports the file format with licenses */ From dfcd77341daa0cf102bd09effd720d262e4a234e Mon Sep 17 00:00:00 2001 From: Pierre Joye Date: Thu, 14 Feb 2013 07:41:18 +0100 Subject: [PATCH 025/276] - nuke unused variable --- shared_alloc_win32.c | 1 - 1 file changed, 1 deletion(-) diff --git a/shared_alloc_win32.c b/shared_alloc_win32.c index 5388ce1ec57..4abf23de8f0 100644 --- a/shared_alloc_win32.c +++ b/shared_alloc_win32.c @@ -40,7 +40,6 @@ static void *mapping_base; static void zend_win_error_message(int type, char *msg, int err) { LPVOID lpMsgBuf; - FILE *fp; HANDLE h; char *ev_msgs[2]; From 54a90b691f83c21ded23b52ad7699e493a577779 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 14 Feb 2013 11:00:04 +0400 Subject: [PATCH 026/276] Don't completely delete the "enabled condition". --- zend_accelerator_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index 807c2446a45..be0655adf34 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -470,7 +470,7 @@ static ZEND_FUNCTION(accelerator_get_status) array_init(return_value); /* Trivia */ - add_assoc_bool(return_value, "accelerator_enabled", 1); + add_assoc_bool(return_value, "accelerator_enabled", 1 /*ZCG(startup_ok) && ZCSG(accelerator_enabled)*/); add_assoc_bool(return_value, "cache_full", ZSMMG(memory_exhausted)); /* Memory usage statistics */ From 37de7567b1dedbdf61786ee87f3336eb81653c3b Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 14 Feb 2013 11:09:36 +0400 Subject: [PATCH 027/276] Renamed README into README.md --- README => README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename README => README.md (100%) diff --git a/README b/README.md similarity index 100% rename from README rename to README.md From 4bc28ae783eb5c8205b53df4edf581d05a8662ae Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 14 Feb 2013 11:13:51 +0400 Subject: [PATCH 028/276] Revert renaming (md needs additional formatting tags) --- README.md => README | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename README.md => README (100%) diff --git a/README.md b/README similarity index 100% rename from README.md rename to README From afb43f5650da2d24f03ce893bcd5123c12aba3fd Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 14 Feb 2013 11:59:23 +0400 Subject: [PATCH 029/276] - Added zend_optimizerplus.load_comments configuration durective, so "Doc comments" may be always stored in SHM, but restored only by applicaions that really need them. - Added note, that zend_optimizerplus.save_comments is dangerous and may break applications and frameworks. --- README | 17 ++++++++++++++--- ZendAccelerator.h | 1 + zend_accelerator_module.c | 1 + zend_accelerator_util_funcs.c | 12 ++++++++++-- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/README b/README index 05c4c606813..5b25a7aa399 100644 --- a/README +++ b/README @@ -44,11 +44,16 @@ zend_optimizerplus.memory_consumption=128 zend_optimizerplus.interned_strings_buffer=8 zend_optimizerplus.max_accelerated_files=4000 zend_optimizerplus.revalidate_freq=60 -zend_optimizerplus.save_comments=0 zend_optimizerplus.fast_shutdown=1 -zend_optimizerplus.enable_file_override=1 zend_optimizerplus.enable_cli=1 +You also may add the following, but it may break some applications and +frameworks. Please, read description of these directives and add them on your +own risk. + +zend_optimizerplus.save_comments=0 +zend_optimizerplus.enable_file_override=1 + In some cases you may like to prefer enabling/disabling some features to avoid incompatibilities at the cost of some performance degradation. @@ -102,7 +107,13 @@ zend_optimizerplus.revalidate_path (default "0") zend_optimizerplus.save_comments (default "1") If disabled, all PHPDoc comments are dropped from the code to reduce the - size of the optimized code. + size of the optimized code. Disabling "Doc Comments" may break some + existing applications and frameworks (e.g. Doctrine, ZF2, PHPUnit) + +zend_optimizerplus.load_comments (default "1") + If disabled, PHPDoc comments are not loaded from SHM, so "Doc Comments" + may be always stored (save_comments=1), but not loaded by applications + that don't need them anyway. zend_optimizerplus.fast_shutdown (default "0") If enabled, a fast shutdown sequence is used for the accelerated code diff --git a/ZendAccelerator.h b/ZendAccelerator.h index 2aa2248cd32..d7ac0ed3884 100644 --- a/ZendAccelerator.h +++ b/ZendAccelerator.h @@ -204,6 +204,7 @@ typedef struct _zend_accel_directives { zend_bool validate_timestamps; zend_bool revalidate_path; zend_bool save_comments; + zend_bool load_comments; zend_bool fast_shutdown; zend_bool protect_memory; zend_bool file_override_enabled; diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index be0655adf34..e64ad19e3c8 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -221,6 +221,7 @@ ZEND_INI_BEGIN() STD_PHP_INI_ENTRY("zend_optimizerplus.protect_memory" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.protect_memory, zend_accel_globals, accel_globals) STD_PHP_INI_ENTRY("zend_optimizerplus.save_comments" , "1" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.save_comments, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("zend_optimizerplus.load_comments" , "1" , PHP_INI_ALL, OnUpdateBool, accel_directives.load_comments, zend_accel_globals, accel_globals) STD_PHP_INI_ENTRY("zend_optimizerplus.fast_shutdown" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.fast_shutdown, zend_accel_globals, accel_globals) STD_PHP_INI_ENTRY("zend_optimizerplus.optimization_level" , DEFAULT_OPTIMIZATION_LEVEL , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.optimization_level, zend_accel_globals, accel_globals) diff --git a/zend_accelerator_util_funcs.c b/zend_accelerator_util_funcs.c index 275642bd218..c41080fbd34 100644 --- a/zend_accelerator_util_funcs.c +++ b/zend_accelerator_util_funcs.c @@ -520,7 +520,11 @@ static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_cla /* Copy constructor */ prop_info->name = interned_estrndup(prop_info->name, prop_info->name_length); if(prop_info->doc_comment) { - prop_info->doc_comment = estrndup(prop_info->doc_comment, prop_info->doc_comment_len); + if (ZCG(accel_directives).load_comments) { + prop_info->doc_comment = estrndup(prop_info->doc_comment, prop_info->doc_comment_len); + } else { + prop_info->doc_comment = NULL; + } } if(prop_info->ce == old_ce) { prop_info->ce = ce; @@ -637,7 +641,11 @@ static void zend_class_copy_ctor(zend_class_entry **pce) ce->interfaces = NULL; } if (ZEND_CE_DOC_COMMENT(ce)) { - ZEND_CE_DOC_COMMENT(ce) = estrndup(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT_LEN(ce)); + if (ZCG(accel_directives).load_comments) { + ZEND_CE_DOC_COMMENT(ce) = estrndup(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT_LEN(ce)); + } else { + ZEND_CE_DOC_COMMENT(ce) = NULL; + } } if(ce->parent) { From d30b98501531ab1eae65cdd6e2b93f35d7d50e8e Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 14 Feb 2013 08:51:05 +0100 Subject: [PATCH 030/276] missing directive in README (need doc) --- README | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README b/README index 5b25a7aa399..5f84c59183d 100644 --- a/README +++ b/README @@ -180,3 +180,9 @@ zend_optimizerplus.log_verbosity_level (default "1") By default, only fatal errors (level 0) or errors (level 1) are logged. You can also enable warnings (level 2), info messages (level 3) or debug messages (level 4). + +zend_optimizerplus.preferred_memory_model + (default "") + +zend_optimizerplus.protect_memory + (default 0) From 92df8e208f8594d387c0a5053b5773be6d89b54a Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 14 Feb 2013 09:10:00 +0100 Subject: [PATCH 031/276] missing directives in accelerator_get_configuration --- zend_accelerator_module.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index e64ad19e3c8..659ebcc82b2 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -525,6 +525,7 @@ static ZEND_FUNCTION(accelerator_get_configuration) MAKE_STD_ZVAL(directives); array_init(directives); add_assoc_bool(directives, "zend_optimizerplus.enable", ZCG(enabled)); + add_assoc_bool(directives, "zend_optimizerplus.enable_cli", ZCG(accel_directives).enable_cli); add_assoc_bool(directives, "zend_optimizerplus.use_cwd", ZCG(accel_directives).use_cwd); add_assoc_bool(directives, "zend_optimizerplus.validate_timestamps", ZCG(accel_directives).validate_timestamps); add_assoc_bool(directives, "zend_optimizerplus.inherited_hack", ZCG(accel_directives).inherited_hack); @@ -533,6 +534,7 @@ static ZEND_FUNCTION(accelerator_get_configuration) add_assoc_long(directives, "zend_optimizerplus.log_verbosity_level", ZCG(accel_directives).log_verbosity_level); add_assoc_long(directives, "zend_optimizerplus.memory_consumption", ZCG(accel_directives).memory_consumption); + add_assoc_long(directives, "zend_optimizerplus.interned_strings_buffer",ZCG(accel_directives).interned_strings_buffer); add_assoc_long(directives, "zend_optimizerplus.max_accelerated_files", ZCG(accel_directives).max_accelerated_files); add_assoc_double(directives, "zend_optimizerplus.max_wasted_percentage", ZCG(accel_directives).max_wasted_percentage); add_assoc_long(directives, "zend_optimizerplus.consistency_checks", ZCG(accel_directives).consistency_checks); @@ -540,11 +542,12 @@ static ZEND_FUNCTION(accelerator_get_configuration) add_assoc_long(directives, "zend_optimizerplus.revalidate_freq", ZCG(accel_directives).revalidate_freq); add_assoc_string(directives, "zend_optimizerplus.preferred_memory_model", STRING_NOT_NULL(ZCG(accel_directives).memory_model), 1); add_assoc_string(directives, "zend_optimizerplus.blacklist_filename", STRING_NOT_NULL(ZCG(accel_directives).user_blacklist_filename), 1); + add_assoc_string(directives, "zend_optimizerplus.error_log", STRING_NOT_NULL(ZCG(accel_directives).error_log), 1); add_assoc_bool(directives, "zend_optimizerplus.protect_memory", ZCG(accel_directives).protect_memory); add_assoc_bool(directives, "zend_optimizerplus.save_comments", ZCG(accel_directives).save_comments); add_assoc_bool(directives, "zend_optimizerplus.fast_shutdown", ZCG(accel_directives).fast_shutdown); - + add_assoc_bool(directives, "zend_optimizerplus.enable_file_override", ZCG(accel_directives).file_override_enabled); add_assoc_long(directives, "zend_optimizerplus.optimization_level", ZCG(accel_directives).optimization_level); add_assoc_zval(return_value,"directives",directives); From 071ab3cf3712e021a710362da30ff3918c361195 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 14 Feb 2013 09:24:11 +0100 Subject: [PATCH 032/276] also add load_comments --- zend_accelerator_module.c | 1 + 1 file changed, 1 insertion(+) diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index 659ebcc82b2..71d42ef58b2 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -546,6 +546,7 @@ static ZEND_FUNCTION(accelerator_get_configuration) add_assoc_bool(directives, "zend_optimizerplus.protect_memory", ZCG(accel_directives).protect_memory); add_assoc_bool(directives, "zend_optimizerplus.save_comments", ZCG(accel_directives).save_comments); + add_assoc_bool(directives, "zend_optimizerplus.load_comments", ZCG(accel_directives).save_comments); add_assoc_bool(directives, "zend_optimizerplus.fast_shutdown", ZCG(accel_directives).fast_shutdown); add_assoc_bool(directives, "zend_optimizerplus.enable_file_override", ZCG(accel_directives).file_override_enabled); add_assoc_long(directives, "zend_optimizerplus.optimization_level", ZCG(accel_directives).optimization_level); From 91e775df1b04a1da9292ef06a4fd0e56bc3a8cc6 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 14 Feb 2013 13:06:30 +0400 Subject: [PATCH 033/276] Disabled unsafe optimization pattern --- Optimizer/pass2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Optimizer/pass2.c b/Optimizer/pass2.c index ef6c5ac0c3e..b600e6b40b0 100644 --- a/Optimizer/pass2.c +++ b/Optimizer/pass2.c @@ -81,7 +81,8 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) { case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: /* convert Ti = JMPZ_EX(Ti, L) to JMPZ(Ti, L) */ - if (ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + if (0 && /* FIXME: temorary disable unsafe pattern */ + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && ZEND_RESULT_TYPE(opline) == IS_TMP_VAR && ZEND_OP1(opline).var == ZEND_RESULT(opline).var) { opline->opcode -= 3; From ded12158ccf112860864d390d96913426a9debe7 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 14 Feb 2013 13:19:06 +0400 Subject: [PATCH 034/276] Fixed phpinfo() output when O+ is not enabled for CLI --- ZendAccelerator.c | 7 ++++++- zend_accelerator_module.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index 8b2a6ae48e7..3e9ea12e7a4 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -2255,7 +2255,12 @@ static int accel_startup(zend_extension *extension) /* no supported SAPI found - disable acceleration and stop initalization */ if( accel_find_sapi(TSRMLS_C) == FAILURE ){ ZCG(startup_ok) = 0; - zps_startup_failure("Opcode Caching is only supported in Apache, ISAPI and FastCGI SAPIs", NULL, accelerator_remove_cb TSRMLS_CC); + if (!ZCG(accel_directives).enable_cli && + strcmp(sapi_module.name, "cli")==0) { + zps_startup_failure("Opcode Caching is disabled for CLI", NULL, accelerator_remove_cb TSRMLS_CC); + } else { + zps_startup_failure("Opcode Caching is only supported in Apache, ISAPI, FPM and FastCGI SAPIs", NULL, accelerator_remove_cb TSRMLS_CC); + } return SUCCESS; } diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index e64ad19e3c8..d26a773bbf8 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -373,7 +373,7 @@ void zend_accel_info(ZEND_MODULE_INFO_FUNC_ARGS) } else { php_info_print_table_row(2, "Opcode Caching", "Disabled"); } - if (ZCG(enabled) && ZCG(accel_directives).optimization_level) { + if (ZCG(enabled) && ZCG(startup_ok) && ZCSG(accelerator_enabled) && ZCG(accel_directives).optimization_level) { php_info_print_table_row(2, "Optimization", "Enabled"); } else { php_info_print_table_row(2, "Optimization", "Disabled"); From 8eb38dacac34671a8f6ad28b66e0ef2334f12db5 Mon Sep 17 00:00:00 2001 From: Thomas Bley Date: Thu, 14 Feb 2013 12:20:50 +0100 Subject: [PATCH 035/276] added travis-ci config (make + load extension) --- .travis.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000000..b876f57d30f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,14 @@ +language: php +php: + - 5.2 + - 5.3 + - 5.4 + - 5.5 + +before_script: + - phpize + - ./configure --enable-optimizer-plus + - make + +script: + - php -d zend_extension=`pwd`/modules/ZendOptimizerPlus.so -m | grep "Zend Optimizer+" \ No newline at end of file From f0aa77a44d622b23ff0bcb18efc24a202f89f501 Mon Sep 17 00:00:00 2001 From: Thomas Bley Date: Thu, 14 Feb 2013 12:24:48 +0100 Subject: [PATCH 036/276] Update README --- README | 1 + 1 file changed, 1 insertion(+) diff --git a/README b/README index 5b25a7aa399..f7f68dedb11 100644 --- a/README +++ b/README @@ -18,6 +18,7 @@ Quick Install - Compile +phpize export PHP_DIR=/usr/local/php5.5 PHP_AUTOCONF=autoconf $PHP_DIR/bin/phpize ./configure \ From a9ff713a56d8618ae9ba60e6168169358e19343b Mon Sep 17 00:00:00 2001 From: Thomas Bley Date: Thu, 14 Feb 2013 12:44:07 +0100 Subject: [PATCH 037/276] phpize is already in README --- README | 1 - 1 file changed, 1 deletion(-) diff --git a/README b/README index f7f68dedb11..5b25a7aa399 100644 --- a/README +++ b/README @@ -18,7 +18,6 @@ Quick Install - Compile -phpize export PHP_DIR=/usr/local/php5.5 PHP_AUTOCONF=autoconf $PHP_DIR/bin/phpize ./configure \ From 5cd7c775452d53300cc84c1fc3274cd1e89c5c2f Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 14 Feb 2013 18:20:34 +0400 Subject: [PATCH 038/276] Added Xdebug compatibility note --- README | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README b/README index 2f45af11b23..cab29ddb9f5 100644 --- a/README +++ b/README @@ -33,6 +33,10 @@ cp .libs/ZendOptimizerPlus.so $PHP_DIR/lib/ZendOptimizerPlus.so zend_extension=/...full path.../ZendOptimizerPlus.so +NOTE: In case you are going to use Zend Optimizer+ together with Xdebug, +be sure that Xdebug is loaded afer Optimizer+. "php -v" must show Xdebug +after Optimizer+. + - Restart PHP Speed Tuning From aef92d22d591026c259abc125bd8f390fc78efca Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 14 Feb 2013 18:36:07 +0400 Subject: [PATCH 039/276] Fixed compatibility with 5.2 and 5.3 --- zend_accelerator_module.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index 658dba6b849..1e3f589dc98 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -534,7 +534,9 @@ static ZEND_FUNCTION(accelerator_get_configuration) add_assoc_long(directives, "zend_optimizerplus.log_verbosity_level", ZCG(accel_directives).log_verbosity_level); add_assoc_long(directives, "zend_optimizerplus.memory_consumption", ZCG(accel_directives).memory_consumption); +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO add_assoc_long(directives, "zend_optimizerplus.interned_strings_buffer",ZCG(accel_directives).interned_strings_buffer); +#endif add_assoc_long(directives, "zend_optimizerplus.max_accelerated_files", ZCG(accel_directives).max_accelerated_files); add_assoc_double(directives, "zend_optimizerplus.max_wasted_percentage", ZCG(accel_directives).max_wasted_percentage); add_assoc_long(directives, "zend_optimizerplus.consistency_checks", ZCG(accel_directives).consistency_checks); From ddbe1b66edab5c3824166459da4b872919951727 Mon Sep 17 00:00:00 2001 From: Daniel Gimenes Date: Fri, 15 Feb 2013 00:00:40 -0200 Subject: [PATCH 040/276] Fix typo in README --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index cab29ddb9f5..71b5af6a084 100644 --- a/README +++ b/README @@ -34,7 +34,7 @@ cp .libs/ZendOptimizerPlus.so $PHP_DIR/lib/ZendOptimizerPlus.so zend_extension=/...full path.../ZendOptimizerPlus.so NOTE: In case you are going to use Zend Optimizer+ together with Xdebug, -be sure that Xdebug is loaded afer Optimizer+. "php -v" must show Xdebug +be sure that Xdebug is loaded after Optimizer+. "php -v" must show Xdebug after Optimizer+. - Restart PHP From 4fec381b3a0f947b15d0f73bda513cb79a113581 Mon Sep 17 00:00:00 2001 From: Reeze Xia Date: Fri, 15 Feb 2013 13:48:37 +0800 Subject: [PATCH 041/276] Typo fix --- ZendAccelerator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index 3e9ea12e7a4..174ba754865 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -231,7 +231,7 @@ static void (*orig_interned_strings_restore)(TSRMLS_D); /* O+ disables creation of interned strings by regular PHP compiler, instead, * it creates interned strings in shared memory when saves a script. - * Such interned strings are shatred across all PHP processes + * Such interned strings are shared across all PHP processes */ static const char *accel_new_interned_string_for_php(const char *str, int len, int free_src TSRMLS_DC) { From bde294f8ebaf95bba51c4951f02cf0acc08b3184 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 15 Feb 2013 13:45:42 +0400 Subject: [PATCH 042/276] Renamed ZCG(startup_ok) into "accel_startup_ok". It must be a "true" global to make ZTS work. (ZTS starts work, but ZTS O+ is not stable anyway) --- ZendAccelerator.c | 33 +++++++++++++++++---------------- ZendAccelerator.h | 3 ++- zend_accelerator_module.c | 16 ++++++++-------- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index 174ba754865..19dd5c89892 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -98,6 +98,7 @@ int accel_globals_id; zend_accel_shared_globals *accel_shared_globals = NULL; /* true globals, no need for thread safety */ +zend_bool accel_startup_ok = 0; static char *zps_failure_reason = NULL; char *zps_api_failure_reason = NULL; @@ -187,7 +188,7 @@ static ZEND_INI_MH(accel_include_path_on_modify) if (ZCG(include_path) && *ZCG(include_path)) { ZCG(include_path_len) = new_value_length; - if (ZCG(startup_ok) && + if (accel_startup_ok && (ZCG(counted) || ZCSG(accelerator_enabled)) && !zend_accel_hash_is_full(&ZCSG(include_paths))) { @@ -876,7 +877,7 @@ char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_lengt include_path = ZCG(include_path); include_path_len = ZCG(include_path_len); if (ZCG(include_path_check) && - ZCG(startup_ok) && + accel_startup_ok && (ZCG(counted) || ZCSG(accelerator_enabled)) && !zend_accel_hash_is_full(&ZCSG(include_paths))) { @@ -1267,7 +1268,7 @@ static zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int int from_shared_memory; /* if the script we've got is stored in SHM */ if (!file_handle->filename || - !ZCG(startup_ok) || + !accel_startup_ok || (!ZCG(counted) && !ZCSG(accelerator_enabled)) || CG(interactive) || (ZCSG(restart_in_progress) && accel_restart_is_active(TSRMLS_C))) { @@ -1561,7 +1562,7 @@ static char *accel_php_resolve_path(const char *filename, int filename_length, c /* zend_stream_open_function() replacement for PHP 5.2 */ static int persistent_stream_open_function(const char *filename, zend_file_handle *handle TSRMLS_DC) { - if (ZCG(startup_ok) && + if (accel_startup_ok && (ZCG(counted) || ZCSG(accelerator_enabled)) && !CG(interactive) && !ZCSG(restart_in_progress)) { @@ -1657,7 +1658,7 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl /* zend_stream_open_function() replacement for PHP 5.3 and above */ static int persistent_stream_open_function(const char *filename, zend_file_handle *handle TSRMLS_DC) { - if (ZCG(startup_ok) && + if (accel_startup_ok && (ZCG(counted) || ZCSG(accelerator_enabled)) && !CG(interactive) && !ZCSG(restart_in_progress)) { @@ -1722,7 +1723,7 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl /* zend_resolve_path() replacement for PHP 5.3 and above */ static char* persistent_zend_resolve_path(const char *filename, int filename_len TSRMLS_DC) { - if (ZCG(startup_ok) && + if (accel_startup_ok && (ZCG(counted) || ZCSG(accelerator_enabled)) && !CG(interactive) && !ZCSG(restart_in_progress)) { @@ -1828,7 +1829,7 @@ static void accel_activate(void) { TSRMLS_FETCH(); - if (!ZCG(startup_ok)) { + if (!accel_startup_ok) { return; } @@ -2079,7 +2080,7 @@ static void accel_deactivate(void) */ TSRMLS_FETCH(); - if (!ZCG(startup_ok)) { + if (!accel_startup_ok) { return; } @@ -2125,7 +2126,7 @@ static int accelerator_remove_cb(zend_extension *element1, zend_extension *eleme static void zps_startup_failure(char *reason, char *api_reason, int (*cb)(zend_extension *, zend_extension *) TSRMLS_DC) { - ZCG(startup_ok) = 0; + accel_startup_ok = 0; zps_failure_reason = reason; zps_api_failure_reason = api_reason?api_reason:reason; zend_llist_del_element(&zend_extensions, NULL, (int (*)(void *, void *))cb); @@ -2247,14 +2248,14 @@ static int accel_startup(zend_extension *extension) #endif if (start_accel_module(0) == FAILURE) { - ZCG(startup_ok) = 0; + accel_startup_ok = 0; zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": module registration failed!"); return FAILURE; } /* no supported SAPI found - disable acceleration and stop initalization */ if( accel_find_sapi(TSRMLS_C) == FAILURE ){ - ZCG(startup_ok) = 0; + accel_startup_ok = 0; if (!ZCG(accel_directives).enable_cli && strcmp(sapi_module.name, "cli")==0) { zps_startup_failure("Opcode Caching is disabled for CLI", NULL, accelerator_remove_cb TSRMLS_CC); @@ -2275,7 +2276,7 @@ static int accel_startup(zend_extension *extension) zend_accel_init_shm(TSRMLS_C); break; case ALLOC_FAILURE: - ZCG(startup_ok) = 0; + accel_startup_ok = 0; zend_accel_error(ACCEL_LOG_FATAL,"Failure to initialize shared memory structures - probably not enough shared memory."); return SUCCESS; case SUCCESSFULLY_REATTACHED: @@ -2303,7 +2304,7 @@ static int accel_startup(zend_extension *extension) break; case FAILED_REATTACHED: - ZCG(startup_ok) = 0; + accel_startup_ok = 0; zend_accel_error(ACCEL_LOG_FATAL,"Failure to initialize shared memory structures - can not reattach to exiting shared memory."); return SUCCESS; break; @@ -2372,7 +2373,7 @@ static int accel_startup(zend_extension *extension) SHM_PROTECT(); - ZCG(startup_ok) = 1; + accel_startup_ok = 1; /* Override file_exists(), is_file() and is_readable() */ zend_accel_override_file_functions(TSRMLS_C); @@ -2403,7 +2404,7 @@ static void accel_shutdown(zend_extension *extension) zend_accel_blacklist_shutdown(&accel_blacklist); - if (!ZCG(startup_ok)) { + if (!accel_startup_ok) { accel_free_ts_resources(); return; } @@ -2489,7 +2490,7 @@ static void accel_op_array_handler(zend_op_array *op_array) { TSRMLS_FETCH(); - if (ZCG(startup_ok) && ZCSG(accelerator_enabled)) { + if (accel_startup_ok && ZCSG(accelerator_enabled)) { zend_optimizer(op_array TSRMLS_CC); } } diff --git a/ZendAccelerator.h b/ZendAccelerator.h index d7ac0ed3884..918e48fa146 100644 --- a/ZendAccelerator.h +++ b/ZendAccelerator.h @@ -240,7 +240,6 @@ typedef struct _zend_accel_globals { int include_path_len; /* "include_path" string lenght */ int include_path_check; time_t request_time; - zend_bool startup_ok; /* preallocated shared-memory block to save current script */ void *mem; /* cache to save hash lookup on the same INCLUDE opcode */ @@ -286,6 +285,8 @@ typedef struct _zend_accel_shared_globals { #endif } zend_accel_shared_globals; +extern zend_bool accel_startup_ok; + extern zend_accel_shared_globals *accel_shared_globals; #define ZCSG(element) (accel_shared_globals->element) diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index 1e3f589dc98..057ae57b42e 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -342,7 +342,7 @@ static ZEND_MINIT_FUNCTION(zend_accelerator) void zend_accel_override_file_functions(TSRMLS_D) { zend_function *old_function; - if(ZCG(startup_ok) && ZCG(accel_directives).file_override_enabled) { + if(accel_startup_ok && ZCG(accel_directives).file_override_enabled) { /* override file_exists */ if(zend_hash_find(CG(function_table), "file_exists", sizeof("file_exists"), (void **)&old_function) == SUCCESS) { old_function->internal_function.handler = accel_file_exists; @@ -368,17 +368,17 @@ void zend_accel_info(ZEND_MODULE_INFO_FUNC_ARGS) { php_info_print_table_start(); - if (ZCG(startup_ok) && ZCSG(accelerator_enabled)) { + if (accel_startup_ok && ZCSG(accelerator_enabled)) { php_info_print_table_row(2, "Opcode Caching", "Up and Running"); } else { php_info_print_table_row(2, "Opcode Caching", "Disabled"); } - if (ZCG(enabled) && ZCG(startup_ok) && ZCSG(accelerator_enabled) && ZCG(accel_directives).optimization_level) { + if (ZCG(enabled) && accel_startup_ok && ZCSG(accelerator_enabled) && ZCG(accel_directives).optimization_level) { php_info_print_table_row(2, "Optimization", "Enabled"); } else { php_info_print_table_row(2, "Optimization", "Disabled"); } - if (!ZCG(startup_ok) || zps_api_failure_reason) { + if (!accel_startup_ok || zps_api_failure_reason) { php_info_print_table_row(2, "Startup Failed", zps_api_failure_reason); } else { php_info_print_table_row(2, "Startup", "OK"); @@ -418,7 +418,7 @@ static zval* accelerator_get_scripts(TSRMLS_D) struct timeval exec_time; struct timeval fetch_time; - if (!ZCG(startup_ok) || !ZCSG(accelerator_enabled) || accelerator_shm_read_lock(TSRMLS_C) != SUCCESS) { + if (!accel_startup_ok || !ZCSG(accelerator_enabled) || accelerator_shm_read_lock(TSRMLS_C) != SUCCESS) { return 0; } @@ -464,14 +464,14 @@ static ZEND_FUNCTION(accelerator_get_status) /* keep the compiler happy */ (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; - if (!ZCG(startup_ok) || !ZCSG(accelerator_enabled)) { + if (!accel_startup_ok || !ZCSG(accelerator_enabled)) { RETURN_FALSE; } array_init(return_value); /* Trivia */ - add_assoc_bool(return_value, "accelerator_enabled", 1 /*ZCG(startup_ok) && ZCSG(accelerator_enabled)*/); + add_assoc_bool(return_value, "accelerator_enabled", 1 /*accel_startup_ok && ZCSG(accelerator_enabled)*/); add_assoc_bool(return_value, "cache_full", ZSMMG(memory_exhausted)); /* Memory usage statistics */ @@ -576,7 +576,7 @@ static ZEND_FUNCTION(accelerator_reset) /* keep the compiler happy */ (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; - if (!ZCG(startup_ok) || !ZCSG(accelerator_enabled)) { + if (!accel_startup_ok || !ZCSG(accelerator_enabled)) { RETURN_FALSE; } From d70ed26aaac1d3f613026f61d115a0ce05190315 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 15 Feb 2013 15:08:51 +0400 Subject: [PATCH 043/276] Added ZTS lock --- zend_shared_alloc.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/zend_shared_alloc.c b/zend_shared_alloc.c index 3b93d041618..12bfef20af5 100644 --- a/zend_shared_alloc.c +++ b/zend_shared_alloc.c @@ -53,6 +53,9 @@ static const char *g_shared_model; zend_smm_shared_globals *smm_shared_globals; #ifndef ZEND_WIN32 +#ifdef ZTS +static MUTEX_T zts_lock; +#endif int lock_file; static char lockfile_name[sizeof(TMP_DIR)+sizeof(SEM_FILENAME_PREFIX)+8]; #endif @@ -78,6 +81,10 @@ void zend_shared_alloc_create_lock(void) { int val; +#ifdef ZTS + zts_lock = tsrm_mutex_alloc(); +#endif + sprintf(lockfile_name, "%s/%sXXXXXX", TMP_DIR, SEM_FILENAME_PREFIX); lock_file = mkstemp(lockfile_name); fchmod(lock_file, 0666); @@ -341,6 +348,11 @@ static FLOCK_STRUCTURE(mem_write_unlock, F_UNLCK, SEEK_SET, 0, 1); void zend_shared_alloc_lock(TSRMLS_D) { #ifndef ZEND_WIN32 + +#ifdef ZTS + tsrm_mutex_lock(zts_lock); +#endif + #if 0 /* this will happen once per process, and will un-globalize mem_write_lock */ if (mem_write_lock.l_pid == -1) { @@ -383,6 +395,9 @@ void zend_shared_alloc_unlock(TSRMLS_D) if (fcntl(lock_file, F_SETLK, &mem_write_unlock) == -1) { zend_accel_error(ACCEL_LOG_ERROR, "Cannot remove lock - %s (%d)", strerror(errno), errno); } +#ifdef ZTS + tsrm_mutex_unlock(zts_lock); +#endif #else zend_shared_alloc_unlock_win32(); #endif From 4c97b6c8cf7e9ff56be6511c9e4f40af1562b835 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 15 Feb 2013 17:35:58 +0400 Subject: [PATCH 044/276] "locked" must be a "module" global (local to thread) --- ZendAccelerator.h | 1 + zend_shared_alloc.c | 15 +++++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ZendAccelerator.h b/ZendAccelerator.h index 918e48fa146..36f1b548fdf 100644 --- a/ZendAccelerator.h +++ b/ZendAccelerator.h @@ -231,6 +231,7 @@ typedef struct _zend_accel_globals { int internal_functions_count; int counted; /* the process uses shatred memory */ zend_bool enabled; + zend_bool locked; /* thread obtained exclusive lock */ HashTable bind_hash; /* prototype and zval lookup table */ zend_accel_directives accel_directives; char *cwd; /* current working directory or NULL */ diff --git a/zend_shared_alloc.c b/zend_shared_alloc.c index 12bfef20af5..c4e0e55c795 100644 --- a/zend_shared_alloc.c +++ b/zend_shared_alloc.c @@ -43,7 +43,6 @@ #define S_H(s) g_shared_alloc_handler->s /* True globals */ -static zend_bool locked; /* old/new mapping. We can use true global even for ZTS because its usage is wrapped with exclusive lock anyway */ static HashTable xlat_table; @@ -214,7 +213,7 @@ int zend_shared_alloc_startup(int requested_size) shared_segments_array_size = ZSMMG(shared_segments_count)*S_H(segment_type_size)(); /* move shared_segments and shared_free to shared memory */ - locked = 1; /* no need to perform a real lock at this point */ + ZCG(locked) = 1; /* no need to perform a real lock at this point */ p_tmp_shared_globals = (zend_smm_shared_globals *) zend_shared_alloc(sizeof(zend_smm_shared_globals)); tmp_shared_segments = zend_shared_alloc(shared_segments_array_size+ZSMMG(shared_segments_count)*sizeof(void *)); @@ -227,7 +226,7 @@ int zend_shared_alloc_startup(int requested_size) ZSMMG(shared_segments) = tmp_shared_segments; ZSMMG(shared_memory_state).positions = (int *) zend_shared_alloc(sizeof(int)*ZSMMG(shared_segments_count)); - locked = 0; + ZCG(locked) = 0; return res; } @@ -255,7 +254,6 @@ void zend_shared_alloc_shutdown(void) #ifndef ZEND_WIN32 close(lock_file); #endif - locked = 0; } #define SHARED_ALLOC_FAILED() { \ @@ -270,9 +268,10 @@ void *zend_shared_alloc(size_t size) { int i; unsigned int block_size = size+sizeof(zend_shared_memory_block_header); + TSRMLS_FETCH(); #if 1 - if (!locked) { + if (!ZCG(locked)) { zend_accel_error(ACCEL_LOG_ERROR, "Shared memory lock not obtained"); } #endif @@ -334,7 +333,7 @@ void *_zend_shared_memdup(void *source, size_t size, zend_bool free_source TSRML void zend_shared_alloc_safe_unlock(TSRMLS_D) { - if (locked) { + if (ZCG(locked)) { zend_shared_alloc_unlock(TSRMLS_C); } } @@ -373,7 +372,7 @@ void zend_shared_alloc_lock(TSRMLS_D) zend_shared_alloc_lock_win32(); #endif - locked=1; + ZCG(locked) = 1; /* Prepare translation table * @@ -389,7 +388,7 @@ void zend_shared_alloc_unlock(TSRMLS_D) /* Destroy translation table */ zend_hash_destroy(&xlat_table); - locked=0; + ZCG(locked) = 0; #ifndef ZEND_WIN32 if (fcntl(lock_file, F_SETLK, &mem_write_unlock) == -1) { From bee06002d0fee1c440a5c5d04220a587416fdfb4 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 15 Feb 2013 17:46:38 +0400 Subject: [PATCH 045/276] Fixed possible resource leak --- shared_alloc_win32.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shared_alloc_win32.c b/shared_alloc_win32.c index 4abf23de8f0..32b7c3a845e 100644 --- a/shared_alloc_win32.c +++ b/shared_alloc_win32.c @@ -138,6 +138,7 @@ static int zend_shared_alloc_reattach(size_t requested_size, char **error_in) err = GetLastError(); zend_win_error_message(ACCEL_LOG_FATAL, "Unable to read base address", err); *error_in="read mapping base"; + fclose(fp); return ALLOC_FAILURE; } fclose(fp); @@ -280,6 +281,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ if(!fp) { zend_win_error_message(ACCEL_LOG_WARNING, mmap_base_file, err); zend_win_error_message(ACCEL_LOG_FATAL, "Unable to write base address", err); + return ALLOC_FAILURE; } fprintf(fp, "%p\n", mapping_base); fclose(fp); From 6693f1854d45b763ce21e53183c38ddad2ac0a20 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 15 Feb 2013 17:59:36 +0400 Subject: [PATCH 046/276] Wrong value --- zend_accelerator_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index 057ae57b42e..299f3186977 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -548,7 +548,7 @@ static ZEND_FUNCTION(accelerator_get_configuration) add_assoc_bool(directives, "zend_optimizerplus.protect_memory", ZCG(accel_directives).protect_memory); add_assoc_bool(directives, "zend_optimizerplus.save_comments", ZCG(accel_directives).save_comments); - add_assoc_bool(directives, "zend_optimizerplus.load_comments", ZCG(accel_directives).save_comments); + add_assoc_bool(directives, "zend_optimizerplus.load_comments", ZCG(accel_directives).load_comments); add_assoc_bool(directives, "zend_optimizerplus.fast_shutdown", ZCG(accel_directives).fast_shutdown); add_assoc_bool(directives, "zend_optimizerplus.enable_file_override", ZCG(accel_directives).file_override_enabled); add_assoc_long(directives, "zend_optimizerplus.optimization_level", ZCG(accel_directives).optimization_level); From 2b6eede1d3e2fa7151a5cb07c20cf66504e6e066 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 15 Feb 2013 18:06:48 +0400 Subject: [PATCH 047/276] Fixed warning about uninitialized variable (actually, it doesn't have to be initialized). --- zend_accelerator_util_funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zend_accelerator_util_funcs.c b/zend_accelerator_util_funcs.c index c41080fbd34..a234461405a 100644 --- a/zend_accelerator_util_funcs.c +++ b/zend_accelerator_util_funcs.c @@ -166,7 +166,7 @@ static void zend_destroy_property_info(zend_property_info *property_info) static inline zval* zend_clone_zval(zval *src, int bind TSRMLS_DC) { - zval *ret, **ret_ptr; + zval *ret, **ret_ptr = NULL; if (!bind) { ALLOC_ZVAL(ret); From 996485e0b2709c46bb07085b88498c88cbc89512 Mon Sep 17 00:00:00 2001 From: krakjoe Date: Sun, 17 Feb 2013 15:48:31 +0000 Subject: [PATCH 048/276] bug #29 enable cli-server support --- ZendAccelerator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index 19dd5c89892..20ee110b6d4 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -2137,6 +2137,7 @@ static inline int accel_find_sapi(TSRMLS_D) static const char *supported_sapis[] = { "apache", "fastcgi", + "cli-server", "cgi-fcgi", "fpm-fcgi", "isapi", From 908fc9dcc46118f22c9ee840909f19dab98b0556 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 18 Feb 2013 11:04:58 +0400 Subject: [PATCH 049/276] Fixed inconsistent start_accel_module() prototype and usage --- ZendAccelerator.c | 2 +- zend_accelerator_module.c | 2 +- zend_accelerator_module.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index 20ee110b6d4..5a0f1cef0ae 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -2248,7 +2248,7 @@ static int accel_startup(zend_extension *extension) _setmaxstdio(2048); /* The default configuration is limited to 512 stdio files */ #endif - if (start_accel_module(0) == FAILURE) { + if (start_accel_module() == FAILURE) { accel_startup_ok = 0; zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": module registration failed!"); return FAILURE; diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index 299f3186977..b39c52d8426 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -402,7 +402,7 @@ static zend_module_entry accel_module_entry = { STANDARD_MODULE_PROPERTIES }; -int start_accel_module() +int start_accel_module(void) { return zend_startup_module(&accel_module_entry); } diff --git a/zend_accelerator_module.h b/zend_accelerator_module.h index 25ad4ae3fa8..112ab0fc571 100644 --- a/zend_accelerator_module.h +++ b/zend_accelerator_module.h @@ -22,7 +22,7 @@ #ifndef ZEND_ACCELERAROR_MODULE_H #define ZEND_ACCELERATOR_MODULE_H -int start_accel_module(); +int start_accel_module(void); void zend_accel_override_file_functions(TSRMLS_D); #endif /* _ZEND_ACCELERATOR_MODULE_H */ From 6d999b4379e9b7b4052534a068809d1297bb738d Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 18 Feb 2013 11:12:20 +0400 Subject: [PATCH 050/276] Added check for CreateMutex() failure --- shared_alloc_win32.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/shared_alloc_win32.c b/shared_alloc_win32.c index 32b7c3a845e..fad75be77de 100644 --- a/shared_alloc_win32.c +++ b/shared_alloc_win32.c @@ -102,6 +102,10 @@ static char *get_mmap_base_file() void zend_shared_alloc_create_lock(void) { memory_mutex = CreateMutex(NULL, FALSE, create_name_with_username(ACCEL_MUTEX_NAME)); + if (!memory_mutex) { + zend_accel_error(ACCEL_LOG_FATAL, "Cannot create mutex"); + return; + } ReleaseMutex(memory_mutex); } From a1201785208cc953ed0d9bd793976ab722848649 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 18 Feb 2013 11:34:10 +0400 Subject: [PATCH 051/276] Added checks for malloc() failures --- ZendAccelerator.c | 12 ++++++++++++ zend_accelerator_blacklist.c | 17 ++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index 5a0f1cef0ae..033c7af9406 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -1475,6 +1475,10 @@ static char *accel_tsrm_realpath(const char *path, int path_len TSRMLS_DC) /* realpath("") returns CWD */ if (!*path) { new_state.cwd = (char*)malloc(1); + if (!new_state.cwd) { + zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed"); + return NULL; + } new_state.cwd[0] = '\0'; new_state.cwd_length = 0; if ((cwd = accel_getcwd(&cwd_len TSRMLS_CC)) != NULL) { @@ -1483,9 +1487,17 @@ static char *accel_tsrm_realpath(const char *path, int path_len TSRMLS_DC) } else if (!IS_ABSOLUTE_PATH(path, path_len) && (cwd = accel_getcwd(&cwd_len TSRMLS_CC)) != NULL) { new_state.cwd = zend_strndup(cwd, cwd_len); + if (!new_state.cwd) { + zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed"); + return NULL; + } new_state.cwd_length = cwd_len; } else { new_state.cwd = (char*)malloc(1); + if (!new_state.cwd) { + zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed"); + return NULL; + } new_state.cwd[0] = '\0'; new_state.cwd_length = 0; } diff --git a/zend_accelerator_blacklist.c b/zend_accelerator_blacklist.c index 7ceadeacf39..52f4216a644 100644 --- a/zend_accelerator_blacklist.c +++ b/zend_accelerator_blacklist.c @@ -63,7 +63,10 @@ static void blacklist_report_regexp_error(regex_t *comp_regex, int reg_err) char *errbuf; int errsize = regerror(reg_err, comp_regex, NULL, 0); errbuf = malloc(errsize); - + if (!errbuf) { + zend_accel_error(ACCEL_LOG_ERROR, "Blacklist compilation: no memory\n"); + return; + } regerror(reg_err, comp_regex, errbuf, errsize); zend_accel_error(ACCEL_LOG_ERROR, "Blacklist compilation: %s\n", errbuf); free(errbuf); @@ -87,6 +90,10 @@ static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist) /* don't create a regexp buffer bigger than 12K)*/ if((i+1 == blacklist->pos) || ((rlen+blacklist->entries[i+1].path_length*2+2)>(12*1024) ) ) { regexp = (char *)malloc(rlen); + if (!regexp) { + zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n"); + return; + } regexp[0] = '^'; regexp[1] = '('; @@ -109,6 +116,10 @@ static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist) regexp[clen] = '\0'; (*regexp_list_it) = malloc(sizeof(zend_regexp_list)); + if (!*regexp_list_it) { + zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n"); + return; + } (*regexp_list_it)->next = NULL; if ((reg_err = regcomp(&((*regexp_list_it)->comp_regex), regexp, REGEX_MODE)) != 0) { @@ -205,6 +216,10 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename) zend_accel_blacklist_allocate(blacklist); blacklist->entries[blacklist->pos].path_length = path_length; blacklist->entries[blacklist->pos].path = (char *) malloc(path_length+1); + if (!blacklist->entries[blacklist->pos].path) { + zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n"); + return; + } blacklist->entries[blacklist->pos].id = blacklist->pos; memcpy(blacklist->entries[blacklist->pos].path, real_path, path_length+1); blacklist->pos++; From d9ba147e5c460dcc9d8f6ed2330c816e748a98a7 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 18 Feb 2013 12:33:58 +0400 Subject: [PATCH 052/276] Avoid mixing declarations and code --- ZendAccelerator.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index 033c7af9406..2fb87551aaf 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -460,12 +460,13 @@ static inline void accel_restart_enter(TSRMLS_D) static inline void accel_restart_leave(TSRMLS_D) { - ZCSG(restart_in_progress) = 0; #ifdef ZEND_WIN32 + ZCSG(restart_in_progress) = 0; DECREMENT(restart_in); #else static const FLOCK_STRUCTURE(restart_finished, F_UNLCK, SEEK_SET, 2, 1); + ZCSG(restart_in_progress) = 0; if (fcntl(lock_file, F_SETLK, &restart_finished)==-1) { zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(-1): %s (%d)", strerror(errno), errno); } From e708dce6742dcc4c06aea63ae8929923ad896dbf Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 18 Feb 2013 12:42:56 +0400 Subject: [PATCH 053/276] Lenght is unsigned --- ZendAccelerator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZendAccelerator.h b/ZendAccelerator.h index 36f1b548fdf..230ee865441 100644 --- a/ZendAccelerator.h +++ b/ZendAccelerator.h @@ -165,7 +165,7 @@ typedef time_t accel_time_t; typedef struct _zend_persistent_script { ulong hash_value; char *full_path; /* full real path with resolved symlinks */ - int full_path_len; + unsigned int full_path_len; zend_op_array main_op_array; HashTable function_table; HashTable class_table; From f18678bbcf79e4ecdb4bd0f48cab8f614d284ac2 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 18 Feb 2013 13:03:29 +0400 Subject: [PATCH 054/276] Fixed signed/unsigned comparison warnings --- Optimizer/block_pass.c | 2 +- Optimizer/nop_removal.c | 12 ++++++------ Optimizer/zend_optimizer_internal.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Optimizer/block_pass.c b/Optimizer/block_pass.c index aeb8f18707c..966cf26fbc4 100644 --- a/Optimizer/block_pass.c +++ b/Optimizer/block_pass.c @@ -1182,7 +1182,7 @@ static void assemble_code_blocks(zend_code_block *blocks, zend_op_array *op_arra #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO /* adjust early binding list */ - if (op_array->early_binding != -1) { + if (op_array->early_binding != (zend_uint)-1) { zend_uint *opline_num = &op_array->early_binding; zend_op *end; diff --git a/Optimizer/nop_removal.c b/Optimizer/nop_removal.c index 49ffe0e6e50..6c22bcf6fd5 100644 --- a/Optimizer/nop_removal.c +++ b/Optimizer/nop_removal.c @@ -92,10 +92,10 @@ static void nop_removal(zend_op_array *op_array) } /* update brk/cont array */ - for (i=0; ilast_brk_cont; i++) { - op_array->brk_cont_array[i].brk -= shiftlist[op_array->brk_cont_array[i].brk]; - op_array->brk_cont_array[i].cont -= shiftlist[op_array->brk_cont_array[i].cont]; - op_array->brk_cont_array[i].start -= shiftlist[op_array->brk_cont_array[i].start]; + for (j=0; jlast_brk_cont; j++) { + op_array->brk_cont_array[j].brk -= shiftlist[op_array->brk_cont_array[j].brk]; + op_array->brk_cont_array[j].cont -= shiftlist[op_array->brk_cont_array[j].cont]; + op_array->brk_cont_array[j].start -= shiftlist[op_array->brk_cont_array[j].start]; } /* update try/catch array */ @@ -112,13 +112,13 @@ static void nop_removal(zend_op_array *op_array) #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO /* update early binding list */ - if (op_array->early_binding != -1) { + if (op_array->early_binding != (zend_uint)-1) { zend_uint *opline_num = &op_array->early_binding; do { *opline_num -= shiftlist[*opline_num]; opline_num = &ZEND_RESULT(&op_array->opcodes[*opline_num]).opline_num; - } while (*opline_num != -1); + } while (*opline_num != (zend_uint)-1); } #endif } diff --git a/Optimizer/zend_optimizer_internal.h b/Optimizer/zend_optimizer_internal.h index 113cbe98267..198ec20c499 100644 --- a/Optimizer/zend_optimizer_internal.h +++ b/Optimizer/zend_optimizer_internal.h @@ -25,7 +25,7 @@ #include "ZendAccelerator.h" #if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO -# define VAR_NUM(v) (EX_TMP_VAR_NUM(0, 0) - EX_TMP_VAR(0, v)) +# define VAR_NUM(v) ((zend_uint)(EX_TMP_VAR_NUM(0, 0) - EX_TMP_VAR(0, v))) # define NUM_VAR(v) ((zend_uint)EX_TMP_VAR_NUM(0, v)) #else # define VAR_NUM(v) ((v)/(sizeof(temp_variable))) From 53d4abb16c78a7c35c7df0d7e2f8c51baa01ca8f Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 18 Feb 2013 13:13:25 +0400 Subject: [PATCH 055/276] Avoid static analyzer warning --- zend_accelerator_hash.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zend_accelerator_hash.c b/zend_accelerator_hash.c index 8257ac2e52d..dbdc2ef1405 100644 --- a/zend_accelerator_hash.c +++ b/zend_accelerator_hash.c @@ -55,12 +55,14 @@ void zend_accel_hash_init(zend_accel_hash *accel_hash, zend_uint hash_size) accel_hash->hash_table = zend_shared_alloc(sizeof(zend_accel_hash_entry *)*accel_hash->max_num_entries); if (!accel_hash->hash_table) { zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!"); + return; } /* set up hash values table */ accel_hash->hash_entries = zend_shared_alloc(sizeof(zend_accel_hash_entry)*accel_hash->max_num_entries); if (!accel_hash->hash_entries) { zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!"); + return; } memset(accel_hash->hash_table, 0, sizeof(zend_accel_hash_entry *)*accel_hash->max_num_entries); } From 40107aa6dac533695d1784f66f79683caaf6d3c8 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 18 Feb 2013 13:19:24 +0400 Subject: [PATCH 056/276] Use proper format specifier --- zend_accelerator_debug.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/zend_accelerator_debug.c b/zend_accelerator_debug.c index 8b2bd6241c8..1234c0fc93c 100644 --- a/zend_accelerator_debug.c +++ b/zend_accelerator_debug.c @@ -56,13 +56,11 @@ void zend_accel_error(int type, const char *format, ...) } } - fprintf(fLog, "%s (%d): ", time_string, #ifdef ZTS - tsrm_thread_id() + fprintf(fLog, "%s (%lu): ", time_string, (unsigned long)tsrm_thread_id()); #else - getpid() + fprintf(fLog, "%s (%d): ", time_string, getpid()); #endif - ); switch (type) { case ACCEL_LOG_FATAL: From 511b33ccdf290b4833dbaeff96df984abe157a47 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 18 Feb 2013 13:27:42 +0400 Subject: [PATCH 057/276] Avoid warning about possible precision loss --- ZendAccelerator.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index 2fb87551aaf..79eb7f4a344 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -1847,7 +1847,8 @@ static void accel_activate(void) } SHM_UNPROTECT(); - ZCG(request_time) = sapi_get_request_time(TSRMLS_C); + /* PHP-5.4 and above return "double", but we use 1 sec precision */ + ZCG(request_time) = (time_t)sapi_get_request_time(TSRMLS_C); ZCG(cache_opline) = NULL; ZCG(cache_persistent_script) = NULL; ZCG(include_path_check) = !ZCG(include_path_key); From 2d87dce1edb5cfd4699accf2e8e238c5a6ca074d Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 19 Feb 2013 18:00:49 +0400 Subject: [PATCH 058/276] Avoid buffer overrun --- zend_accelerator_blacklist.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zend_accelerator_blacklist.c b/zend_accelerator_blacklist.c index 52f4216a644..804124bce06 100644 --- a/zend_accelerator_blacklist.c +++ b/zend_accelerator_blacklist.c @@ -183,9 +183,9 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename) while (fgets(buf, MAXPATHLEN, fp)!=NULL) { char *path_dup, *pbuf; path_length = strlen(buf); - if (buf[path_length-1]=='\n') { + if (path_length > 0 && buf[path_length-1]=='\n') { buf[--path_length] = 0; - if (buf[path_length-1]=='\r') { + if (path_length > 0 && buf[path_length-1]=='\r') { buf[--path_length] = 0; } } From 3af305cc504f265b373ccfff9f0d0211ae73e85b Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 19 Feb 2013 18:04:40 +0400 Subject: [PATCH 059/276] Removed redundand TSRMLS_FETCH() --- zend_shared_alloc.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/zend_shared_alloc.c b/zend_shared_alloc.c index c4e0e55c795..abdc195d796 100644 --- a/zend_shared_alloc.c +++ b/zend_shared_alloc.c @@ -256,13 +256,11 @@ void zend_shared_alloc_shutdown(void) #endif } -#define SHARED_ALLOC_FAILED() { \ - TSRMLS_FETCH(); \ - \ - zend_accel_error(ACCEL_LOG_WARNING, "Not enough free shared space to allocate %ld bytes (%ld bytes free)", (long)size, (long)ZSMMG(shared_free)); \ - ZSMMG(memory_exhausted) = 1; \ - zend_accel_schedule_restart(TSRMLS_C); \ -} +#define SHARED_ALLOC_FAILED() do { \ + zend_accel_error(ACCEL_LOG_WARNING, "Not enough free shared space to allocate %ld bytes (%ld bytes free)", (long)size, (long)ZSMMG(shared_free)); \ + ZSMMG(memory_exhausted) = 1; \ + zend_accel_schedule_restart(TSRMLS_C); \ + } while (0) void *zend_shared_alloc(size_t size) { From 4813a711749df756088f049cadb58f13fe60721d Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 19 Feb 2013 18:07:23 +0400 Subject: [PATCH 060/276] Fixed static analyser warning --- ZendAccelerator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index 79eb7f4a344..f9b39fc63ca 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -2183,6 +2183,7 @@ static void zend_accel_init_shm(TSRMLS_D) accel_shared_globals = zend_shared_alloc(sizeof(zend_accel_shared_globals)); if (!accel_shared_globals) { zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!"); + return; } ZSMMG(app_shared_globals) = accel_shared_globals; From 6ee260231741085f204ea79248c21d3e66dc4c93 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 19 Feb 2013 18:15:11 +0400 Subject: [PATCH 061/276] Simplification --- zend_accelerator_blacklist.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/zend_accelerator_blacklist.c b/zend_accelerator_blacklist.c index 804124bce06..666304becf0 100644 --- a/zend_accelerator_blacklist.c +++ b/zend_accelerator_blacklist.c @@ -76,7 +76,7 @@ static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist) { int i, end=0, j, rlen=6, clen, reg_err; char *regexp; - zend_regexp_list **regexp_list_it; + zend_regexp_list **regexp_list_it, *it; if (blacklist->pos == 0) { /* we have no blacklist to talk about */ @@ -115,21 +115,22 @@ static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist) regexp[clen++] = ')'; regexp[clen] = '\0'; - (*regexp_list_it) = malloc(sizeof(zend_regexp_list)); - if (!*regexp_list_it) { + it = (zend_regexp_list*)malloc(sizeof(zend_regexp_list)); + if (!it) { zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n"); return; } - (*regexp_list_it)->next = NULL; + it->next = NULL; - if ((reg_err = regcomp(&((*regexp_list_it)->comp_regex), regexp, REGEX_MODE)) != 0) { - blacklist_report_regexp_error(&((*regexp_list_it)->comp_regex), reg_err); + if ((reg_err = regcomp(&it->comp_regex, regexp, REGEX_MODE)) != 0) { + blacklist_report_regexp_error(&it->comp_regex, reg_err); } /* prepare for the next iteration */ free(regexp); end = i+1; rlen = 6; - regexp_list_it = &((*regexp_list_it)->next); + *regexp_list_it = it; + regexp_list_it = &it->next; } } } From 1fcdd25e83e2193854cd80c314af8e8bcd38fcda Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 19 Feb 2013 18:21:31 +0400 Subject: [PATCH 062/276] Added check for calloc() failure --- shared_alloc_win32.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/shared_alloc_win32.c b/shared_alloc_win32.c index fad75be77de..61dbd80c6a1 100644 --- a/shared_alloc_win32.c +++ b/shared_alloc_win32.c @@ -211,6 +211,11 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ /* creating segment here */ *shared_segments_count = 1; *shared_segments_p = (zend_shared_segment **) calloc(1, sizeof(zend_shared_segment)+sizeof(void *)); + if (!*shared_segments_p) { + zend_win_error_message(ACCEL_LOG_FATAL, "calloc() failed"); + *error_in = "calloc"; + return ALLOC_FAILURE; + } shared_segment = (zend_shared_segment *)((char *)(*shared_segments_p) + sizeof(void *)); (*shared_segments_p)[0] = shared_segment; From b95964535cfa9561a3d18c3573d8afe47a8b7343 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 20 Feb 2013 11:21:15 +0400 Subject: [PATCH 063/276] Fixed compilation error --- shared_alloc_win32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared_alloc_win32.c b/shared_alloc_win32.c index 61dbd80c6a1..f275c64336c 100644 --- a/shared_alloc_win32.c +++ b/shared_alloc_win32.c @@ -212,7 +212,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ *shared_segments_count = 1; *shared_segments_p = (zend_shared_segment **) calloc(1, sizeof(zend_shared_segment)+sizeof(void *)); if (!*shared_segments_p) { - zend_win_error_message(ACCEL_LOG_FATAL, "calloc() failed"); + zend_win_error_message(ACCEL_LOG_FATAL, "calloc() failed", GetLastError()); *error_in = "calloc"; return ALLOC_FAILURE; } From 280bbaf30178e4955afe34639955d736ecbb3173 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 20 Feb 2013 18:04:07 +0400 Subject: [PATCH 064/276] Avoid unexpected warning messages (ext/standard/tests/file/fopencookie.phpt) --- ZendAccelerator.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index f9b39fc63ca..1ddc2a92424 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -618,6 +618,7 @@ static int zend_get_stream_timestamp(const char *filename, struct stat *statbuf { php_stream_wrapper *wrapper; php_stream_statbuf stream_statbuf; + int ret, er; if(!filename) { return FAILURE; @@ -634,9 +635,20 @@ static int zend_get_stream_timestamp(const char *filename, struct stat *statbuf return SUCCESS; /* anything other than 0 is considered to be a valid timestamp */ } - if(wrapper->wops->url_stat(wrapper, (char*)filename, PHP_STREAM_URL_STAT_QUIET, &stream_statbuf, NULL TSRMLS_CC) != 0) { + + er = EG(error_reporting); + EG(error_reporting) = 0; + zend_try { + ret = wrapper->wops->url_stat(wrapper, (char*)filename, PHP_STREAM_URL_STAT_QUIET, &stream_statbuf, NULL TSRMLS_CC); + } zend_catch { + ret = -1; + } zend_end_try(); + EG(error_reporting) = er; + + if (ret != 0) { return FAILURE; } + *statbuf = stream_statbuf.sb; return SUCCESS; } @@ -735,17 +747,26 @@ static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle { php_stream *stream = (php_stream *)file_handle->handle.stream.handle; php_stream_statbuf sb; - int er = EG(error_reporting); + int ret, er; - EG(error_reporting) = 0; if (!stream || !stream->ops || - !stream->ops->stat || - stream->ops->stat(stream, &sb TSRMLS_CC) != 0) { - EG(error_reporting) = er; + !stream->ops->stat) { return 0; } + + er = EG(error_reporting); + EG(error_reporting) = 0; + zend_try { + ret = stream->ops->stat(stream, &sb TSRMLS_CC); + } zend_catch { + ret = -1; + } zend_end_try(); EG(error_reporting) = er; + if (ret != 0) { + return 0; + } + statbuf = sb.sb; } break; From 3a06991ffda1ed6baa1c6004e2f113347955a3e1 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 21 Feb 2013 12:11:03 +0400 Subject: [PATCH 065/276] Added ability to always validate cached script timestamps using zend_optimizerplus.revalidate_freq=0 --- README | 3 ++- ZendAccelerator.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README b/README index 71b5af6a084..38549152425 100644 --- a/README +++ b/README @@ -98,7 +98,8 @@ zend_optimizerplus.validate_timestamps (default "1") zend_optimizerplus.revalidate_freq (default "2") How often (in seconds) to check file timestamps for changes to the shared - memory storage allocation. + memory storage allocation. ("1" means validate once per second, but only + once per request. "0" means always validate) zend_optimizerplus.revalidate_path (default "0") Enables or disables file search in include_path optimization diff --git a/ZendAccelerator.c b/ZendAccelerator.c index 1ddc2a92424..2d84b37a30b 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -828,7 +828,8 @@ static void zend_accel_schedule_restart_if_necessary(TSRMLS_D) static inline int validate_timestamp_and_record(zend_persistent_script *persistent_script, zend_file_handle *file_handle TSRMLS_DC) { - if (persistent_script->dynamic_members.revalidate >= ZCSG(revalidate_at)) { + if (ZCG(accel_directives).revalidate_freq && + (persistent_script->dynamic_members.revalidate >= ZCSG(revalidate_at))) { return SUCCESS; } else if (do_validate_timestamps(persistent_script, file_handle TSRMLS_CC)==FAILURE) { return FAILURE; From cddc2c35d9f367b121e8c3b29fdfa45497ff834d Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Fri, 22 Feb 2013 14:56:05 +0800 Subject: [PATCH 066/276] Codes style improve --- Optimizer/block_pass.c | 806 +++++++++++++++---------------- Optimizer/nop_removal.c | 4 +- Optimizer/optimize_temp_vars_5.c | 6 +- Optimizer/pass1_5.c | 180 +++---- Optimizer/pass2.c | 34 +- Optimizer/pass3.c | 65 ++- ZendAccelerator.c | 179 ++++--- shared_alloc_mmap.c | 4 +- shared_alloc_posix.c | 10 +- shared_alloc_shm.c | 20 +- shared_alloc_win32.c | 26 +- zend_accelerator_blacklist.c | 50 +- zend_accelerator_module.c | 58 +-- zend_accelerator_util_funcs.c | 112 ++--- zend_persist.c | 88 ++-- zend_persist_calc.c | 38 +- zend_shared_alloc.c | 84 ++-- 17 files changed, 868 insertions(+), 896 deletions(-) diff --git a/Optimizer/block_pass.c b/Optimizer/block_pass.c index 966cf26fbc4..f72cc582891 100644 --- a/Optimizer/block_pass.c +++ b/Optimizer/block_pass.c @@ -8,25 +8,25 @@ static int zend_get_persistent_constant(char *name, uint name_len, zval *result, int retval = 1; ALLOCA_FLAG(use_heap); - if (zend_hash_find(EG(zend_constants), name, name_len+1, (void **) &c) == FAILURE) { - lookup_name = DO_ALLOCA(name_len+1); - memcpy(lookup_name, name, name_len+1); + if (zend_hash_find(EG(zend_constants), name, name_len + 1, (void **) &c) == FAILURE) { + lookup_name = DO_ALLOCA(name_len + 1); + memcpy(lookup_name, name, name_len + 1); zend_str_tolower(lookup_name, name_len); - if (zend_hash_find(EG(zend_constants), lookup_name, name_len+1, (void **) &c)==SUCCESS) { + if (zend_hash_find(EG(zend_constants), lookup_name, name_len + 1, (void **) &c) == SUCCESS) { if (!(c->flags & CONST_CT_SUBST) || (c->flags & CONST_CS)) { - retval=0; + retval = 0; } } else { - retval=0; + retval = 0; } FREE_ALLOCA(lookup_name); } if (retval) { - if(c->flags & CONST_PERSISTENT) { + if (c->flags & CONST_PERSISTENT) { *result = c->value; - if(copy) { + if (copy) { zval_copy_ctor(result); } } else { @@ -43,26 +43,26 @@ static int zend_get_persistent_constant(char *name, uint name_len, zval *result, static inline void print_block(zend_code_block *block, zend_op *opcodes, char *txt) { fprintf(stderr, "%sBlock: %d-%d (%d)", txt, block->start_opline - opcodes, block->start_opline - opcodes+block->len-1, block->len); - if(!block->access) { + if (!block->access) { fprintf(stderr, " unused"); } - if(block->op1_to) { + if (block->op1_to) { fprintf(stderr, " 1: %d", block->op1_to->start_opline - opcodes); } - if(block->op2_to) { + if (block->op2_to) { fprintf(stderr, " 2: %d", block->op2_to->start_opline - opcodes); } - if(block->ext_to) { + if (block->ext_to) { fprintf(stderr, " e: %d", block->ext_to->start_opline - opcodes); } - if(block->follow_to) { + if (block->follow_to) { fprintf(stderr, " f: %d", block->follow_to->start_opline - opcodes); } - if(block->sources) { + if (block->sources) { zend_block_source *bs = block->sources; fprintf(stderr, " s:"); - while(bs) { + while (bs) { fprintf(stderr, " %d", bs->from->start_opline - opcodes); bs = bs->next; } @@ -83,8 +83,8 @@ static inline void print_block(zend_code_block *block, zend_op *opcodes, char *t static zend_code_block *find_code_blocks(zend_op_array *op_array) { zend_op *opline; - zend_op *end = op_array->opcodes+op_array->last; - zend_code_block *blocks = ecalloc(op_array->last+2, sizeof(zend_code_block)); + zend_op *end = op_array->opcodes + op_array->last; + zend_code_block *blocks = ecalloc(op_array->last + 2, sizeof(zend_code_block)); zend_code_block *cur_block; zend_uint opno = 0; @@ -92,11 +92,11 @@ static zend_code_block *find_code_blocks(zend_op_array *op_array) blocks[0].start_opline = opline; blocks[0].start_opline_no = 0; /* first find block start points */ - if(op_array->last_try_catch) { - int i; + if (op_array->last_try_catch) { + int i = 0; blocks->try = ecalloc(op_array->last_try_catch, sizeof(zend_code_block *)); blocks->catch = ecalloc(op_array->last_try_catch, sizeof(zend_code_block *)); - for(i=0; i< op_array->last_try_catch; i++) { + for (; i< op_array->last_try_catch; i++) { blocks->try[i] = &blocks[op_array->try_catch_array[i].try_op]; blocks->catch[i] = &blocks[op_array->try_catch_array[i].catch_op]; START_BLOCK_OP(op_array->try_catch_array[i].try_op); @@ -104,7 +104,7 @@ static zend_code_block *find_code_blocks(zend_op_array *op_array) blocks[op_array->try_catch_array[i].try_op].is_try = 1; } } - while (oplineopcode) { case ZEND_BRK: case ZEND_CONT: @@ -134,13 +134,13 @@ static zend_code_block *find_code_blocks(zend_op_array *op_array) case ZEND_EXIT: case ZEND_THROW: /* start new block from this+1 */ - START_BLOCK_OP(opno+1); + START_BLOCK_OP(opno + 1); break; /* TODO: if conditional jmp depends on constant, don't start block that won't be executed */ case ZEND_CATCH: START_BLOCK_OP(opline->extended_value); - START_BLOCK_OP(opno+1); + START_BLOCK_OP(opno + 1); break; case ZEND_JMPZNZ: START_BLOCK_OP(opline->extended_value); @@ -158,7 +158,7 @@ static zend_code_block *find_code_blocks(zend_op_array *op_array) case ZEND_JMP_SET_VAR: #endif START_BLOCK_OP(ZEND_OP2(opline).opline_num); - START_BLOCK_OP(opno+1); + START_BLOCK_OP(opno + 1); break; } @@ -168,13 +168,13 @@ static zend_code_block *find_code_blocks(zend_op_array *op_array) /* Build CFG (Control Flow Graph) */ cur_block = blocks; - for(opno = 1; opno < op_array->last; opno++) { - if(blocks[opno].start_opline) { + for (opno = 1; opno < op_array->last; opno++) { + if (blocks[opno].start_opline) { /* found new block start */ cur_block->len = blocks[opno].start_opline - cur_block->start_opline; cur_block->next = &blocks[opno]; /* what is the last OP of previous block? */ - opline = blocks[opno].start_opline-1; + opline = blocks[opno].start_opline - 1; switch((unsigned)opline->opcode) { case ZEND_RETURN: #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO @@ -229,7 +229,7 @@ static zend_code_block *find_code_blocks(zend_op_array *op_array) print_block(cur_block, op_array->opcodes, ""); /* The op_array doesn't have BRK, CONT, GOTO opcodes anyway */ - if(op_array->brk_cont_array) { + if (op_array->brk_cont_array) { efree(op_array->brk_cont_array); } op_array->brk_cont_array = NULL; @@ -242,8 +242,8 @@ static zend_code_block *find_code_blocks(zend_op_array *op_array) #define ADD_SOURCE(fromb, tob) { \ zend_block_source *__s = tob->sources; \ - while(__s && __s->from != fromb) __s = __s->next; \ - if(__s == NULL) { \ + while (__s && __s->from != fromb) __s = __s->next; \ + if (__s == NULL) { \ zend_block_source *__t = emalloc(sizeof(zend_block_source)); \ __t->next = tob->sources; \ tob->sources = __t; \ @@ -264,17 +264,17 @@ static inline void replace_source(zend_block_source *list, zend_code_block *old, zend_block_source **cs; int found = 0; - for(cs = &list; *cs; cs = &((*cs)->next)) { - if((*cs)->from == new) { - if(found) { + for (cs = &list; *cs; cs = &((*cs)->next)) { + if ((*cs)->from == new) { + if (found) { DEL_SOURCE(cs); } else { found = 1; } } - if((*cs)->from == old) { - if(found) { + if ((*cs)->from == old) { + if (found) { DEL_SOURCE(cs); } else { (*cs)->from = new; @@ -289,37 +289,36 @@ static inline void del_source(zend_code_block *from, zend_code_block *to) /* delete source 'from' from 'to'-s sources list */ zend_block_source **cs = &to->sources; - if(to->sources == NULL) { + if (to->sources == NULL) { to->access = 0; return; } - while(*cs) { - if((*cs)->from == from) { - DEL_SOURCE(cs); + while (*cs) { + if ((*cs)->from == from) { + DEL_SOURCE(cs); break; } cs = &((*cs)->next); } - if(to->sources == NULL) { + if (to->sources == NULL) { /* 'to' has no more sources - it's unused, will be stripped */ to->access = 0; return; } - if(to->sources->next == NULL) { + if (to->sources->next == NULL) { /* source to only one block */ zend_code_block *from_block = to->sources->from; - - if(from_block->access && from_block->follow_to == to && - from_block->op1_to == NULL && - from_block->op2_to == NULL && - from_block->ext_to == NULL - ) { + + if (from_block->access && from_block->follow_to == to && + from_block->op1_to == NULL && + from_block->op2_to == NULL && + from_block->ext_to == NULL) { /* this block follows it's only predecessor - we can join them */ zend_op *new_to = from_block->start_opline + from_block->len; - if(new_to != to->start_opline) { + if (new_to != to->start_opline) { /* move block to new location */ memmove(new_to, to->start_opline, sizeof(zend_op)*to->len); } @@ -331,19 +330,19 @@ static inline void del_source(zend_code_block *from, zend_code_block *to) efree(to->sources); to->sources = NULL; from_block->follow_to = to->follow_to; - if(to->op1_to) { + if (to->op1_to) { from_block->op1_to = to->op1_to; replace_source(to->op1_to->sources, to, from_block); } - if(to->op2_to) { + if (to->op2_to) { from_block->op2_to = to->op2_to; replace_source(to->op2_to->sources, to, from_block); } - if(to->ext_to) { + if (to->ext_to) { from_block->ext_to = to->ext_to; replace_source(to->ext_to->sources, to, from_block); } - if(to->follow_to) { + if (to->follow_to) { replace_source(to->follow_to->sources, to, from_block); } /* remove "to" from list */ @@ -353,24 +352,24 @@ static inline void del_source(zend_code_block *from, zend_code_block *to) static void delete_code_block(zend_code_block *block) { - if(block->follow_to) { + if (block->follow_to) { zend_block_source *bs = block->sources; - while(bs) { + while (bs) { zend_code_block *from_block = bs->from; zend_code_block *to = block->follow_to; - if(from_block->op1_to == block) { + if (from_block->op1_to == block) { from_block->op1_to = to; ADD_SOURCE(from_block, to); } - if(from_block->op2_to == block) { + if (from_block->op2_to == block) { from_block->op2_to = to; ADD_SOURCE(from_block, to); } - if(from_block->ext_to == block) { + if (from_block->ext_to == block) { from_block->ext_to = to; ADD_SOURCE(from_block, to); } - if(from_block->follow_to == block) { + if (from_block->follow_to == block) { from_block->follow_to = to; ADD_SOURCE(from_block, to); } @@ -382,24 +381,24 @@ static void delete_code_block(zend_code_block *block) static void zend_access_path(zend_code_block *block) { - if(block->access) { + if (block->access) { return; } block->access = 1; - if(block->op1_to) { + if (block->op1_to) { zend_access_path(block->op1_to); ADD_SOURCE(block, block->op1_to); } - if(block->op2_to) { + if (block->op2_to) { zend_access_path(block->op2_to); ADD_SOURCE(block, block->op2_to); } - if(block->ext_to) { + if (block->ext_to) { zend_access_path(block->ext_to); ADD_SOURCE(block, block->ext_to); } - if(block->follow_to) { + if (block->follow_to) { zend_access_path(block->follow_to); ADD_SOURCE(block, block->follow_to); } @@ -408,7 +407,7 @@ static void zend_access_path(zend_code_block *block) /* Traverse CFG, mark reachable basic blocks and build back references */ static void zend_rebuild_access_path(zend_code_block *blocks, zend_op_array *op_array, int find_start) { - zend_code_block *start = find_start?NULL:blocks; + zend_code_block *start = find_start? NULL : blocks; zend_code_block *b; /* Mark all blocks as unaccessable and destroy back references */ @@ -420,7 +419,7 @@ static void zend_rebuild_access_path(zend_code_block *blocks, zend_op_array *op_ } b->access = 0; cs = b->sources; - while(cs) { + while (cs) { zend_block_source *n = cs->next; efree(cs); cs = n; @@ -435,8 +434,8 @@ static void zend_rebuild_access_path(zend_code_block *blocks, zend_op_array *op_ /* Add exception pathes */ if (op_array->last_try_catch) { int i; - for(i=0; i< op_array->last_try_catch; i++) { - if(!blocks->catch[i]->access) { + for (i=0; i< op_array->last_try_catch; i++) { + if (!blocks->catch[i]->access) { zend_access_path(blocks->catch[i]); } } @@ -456,17 +455,17 @@ static void zend_rebuild_access_path(zend_code_block *blocks, zend_op_array *op_ #else -# define VAR_NUM_EX(op) ((op).op_type==IS_TMP_VAR||(op).op_type==IS_VAR?VAR_NUM((op).u.var):(op).u.var) +# define VAR_NUM_EX(op) ((op).op_type == IS_TMP_VAR || (op).op_type == IS_VAR? VAR_NUM((op).u.var) : (op).u.var) # define VAR_SOURCE(op) Tsource[VAR_NUM(op.u.var)] # define SET_VAR_SOURCE(opline) Tsource[VAR_NUM(ZEND_RESULT(opline).var)] = opline -# define VAR_UNSET(op) do { if ((op).op_type==IS_TMP_VAR||(op).op_type==IS_VAR) {VAR_SOURCE(op) = NULL;}} while (0) +# define VAR_UNSET(op) do { if ((op).op_type == IS_TMP_VAR || (op).op_type == IS_VAR) {VAR_SOURCE(op) = NULL;}} while (0) #endif #define convert_to_string_safe(v) \ - if(Z_TYPE_P((v)) == IS_NULL) { \ + if (Z_TYPE_P((v)) == IS_NULL) { \ ZVAL_STRINGL((v), "", 0, 1); \ } else { \ convert_to_string((v)); \ @@ -481,10 +480,10 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, print_block(block, op_array->opcodes, "Opt "); /* remove leading NOPs */ - while(block->start_opline->opcode == ZEND_NOP) { - if(block->len == 1) { + while (block->start_opline->opcode == ZEND_NOP) { + if (block->len == 1) { /* this block is all NOPs, join with following block */ - if(block->follow_to) { + if (block->follow_to) { delete_code_block(block); } return; @@ -495,22 +494,22 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, } /* we track data dependencies only insight a single basic block */ - if(op_array->T){ + if (op_array->T) { Tsource = ecalloc(op_array->T, sizeof(zend_op *)); } opline = block->start_opline; - end = opline+block->len; - while((op_array->T)&&(oplinelen; + while ((op_array->T) && (opline < end)) { /* strip X = QM_ASSIGN(const) */ - if(ZEND_OP1_TYPE(opline) == IS_TMP_VAR && - VAR_SOURCE(opline->op1) && - VAR_SOURCE(opline->op1)->opcode == ZEND_QM_ASSIGN && - ZEND_OP1_TYPE(VAR_SOURCE(opline->op1)) == IS_CONST && - opline->opcode != ZEND_CASE && /* CASE _always_ expects variable */ - opline->opcode != ZEND_FETCH_DIM_TMP_VAR && /* in 5.1, FETCH_DIM_TMP_VAR expects T */ - opline->opcode != ZEND_FE_RESET && - opline->opcode != ZEND_FREE - ) { + if (ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + VAR_SOURCE(opline->op1)->opcode == ZEND_QM_ASSIGN && + ZEND_OP1_TYPE(VAR_SOURCE(opline->op1)) == IS_CONST && + opline->opcode != ZEND_CASE && /* CASE _always_ expects variable */ + opline->opcode != ZEND_FETCH_DIM_TMP_VAR && /* in 5.1, FETCH_DIM_TMP_VAR expects T */ + opline->opcode != ZEND_FE_RESET && + opline->opcode != ZEND_FREE + ) { zend_op *src = VAR_SOURCE(opline->op1); VAR_UNSET(opline->op1); COPY_NODE(opline->op1, src->op1); @@ -518,10 +517,10 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, } /* T = QM_ASSIGN(C), F(T) => NOP, F(C) */ - if(ZEND_OP2_TYPE(opline) == IS_TMP_VAR && - VAR_SOURCE(opline->op2) && - VAR_SOURCE(opline->op2)->opcode == ZEND_QM_ASSIGN && - ZEND_OP1_TYPE(VAR_SOURCE(opline->op2)) == IS_CONST) { + if (ZEND_OP2_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op2) && + VAR_SOURCE(opline->op2)->opcode == ZEND_QM_ASSIGN && + ZEND_OP1_TYPE(VAR_SOURCE(opline->op2)) == IS_CONST) { zend_op *src = VAR_SOURCE(opline->op2); VAR_UNSET(opline->op2); COPY_NODE(opline->op2, src->op1); @@ -529,38 +528,38 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, } /* T = PRINT(X), F(T) => ECHO(X), F(1) */ - if(ZEND_OP1_TYPE(opline) == IS_TMP_VAR && - VAR_SOURCE(opline->op1) && - VAR_SOURCE(opline->op1)->opcode == ZEND_PRINT && - opline->opcode != ZEND_CASE && opline->opcode != ZEND_FREE) { + if (ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + VAR_SOURCE(opline->op1)->opcode == ZEND_PRINT && + opline->opcode != ZEND_CASE && opline->opcode != ZEND_FREE) { ZEND_OP1_TYPE(opline) = IS_CONST; LITERAL_LONG(opline->op1, 1); } - if(ZEND_OP2_TYPE(opline) == IS_TMP_VAR && - VAR_SOURCE(opline->op2) && - VAR_SOURCE(opline->op2)->opcode == ZEND_PRINT) { + if (ZEND_OP2_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op2) && + VAR_SOURCE(opline->op2)->opcode == ZEND_PRINT) { ZEND_OP2_TYPE(opline) = IS_CONST; LITERAL_LONG(opline->op2, 1); } /* T = CAST(X, String), ECHO(T) => NOP, ECHO(X) */ - if((opline->opcode == ZEND_ECHO || opline->opcode == ZEND_PRINT) && - ZEND_OP1_TYPE(opline) == IS_TMP_VAR && - VAR_SOURCE(opline->op1) && - VAR_SOURCE(opline->op1)->opcode == ZEND_CAST && - VAR_SOURCE(opline->op1)->extended_value == IS_STRING) { + if ((opline->opcode == ZEND_ECHO || opline->opcode == ZEND_PRINT) && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + VAR_SOURCE(opline->op1)->opcode == ZEND_CAST && + VAR_SOURCE(opline->op1)->extended_value == IS_STRING) { zend_op *src = VAR_SOURCE(opline->op1); COPY_NODE(opline->op1, src->op1); MAKE_NOP(src); } /* T = PRINT(X), FREE(T) => ECHO(X) */ - if(opline->opcode == ZEND_FREE && + if (opline->opcode == ZEND_FREE && ZEND_OP1_TYPE(opline) == IS_TMP_VAR && - VAR_SOURCE(opline->op1)) { + VAR_SOURCE(opline->op1)) { zend_op *src = VAR_SOURCE(opline->op1); - if(src->opcode == ZEND_PRINT) { + if (src->opcode == ZEND_PRINT) { src->opcode = ZEND_ECHO; ZEND_RESULT_TYPE(src) = IS_UNUSED; MAKE_NOP(opline); @@ -568,9 +567,9 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, } /* T = BOOL(X), FREE(T) => NOP */ - if(opline->opcode == ZEND_FREE && - ZEND_OP1_TYPE(opline) == IS_TMP_VAR && - VAR_SOURCE(opline->op1)) { + if (opline->opcode == ZEND_FREE && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1)) { zend_op *src = VAR_SOURCE(opline->op1); if (src->opcode == ZEND_BOOL) { if (ZEND_OP1_TYPE(src) == IS_CONST) { @@ -649,40 +648,39 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, * IS_NOT_EQ(TRUE, X) => BOOL_NOT(X) * IS_NOT_EQ(FALSE, X) => BOOL(X) */ - if(opline->opcode == ZEND_IS_EQUAL || - opline->opcode == ZEND_IS_NOT_EQUAL) { + if (opline->opcode == ZEND_IS_EQUAL || + opline->opcode == ZEND_IS_NOT_EQUAL) { if (ZEND_OP1_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_BOOL) { opline->opcode = ((opline->opcode == ZEND_IS_EQUAL) == Z_LVAL(ZEND_OP1_LITERAL(opline)))? - ZEND_BOOL:ZEND_BOOL_NOT; + ZEND_BOOL : ZEND_BOOL_NOT; COPY_NODE(opline->op1, opline->op2); SET_UNUSED(opline->op2); } else if (ZEND_OP2_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_BOOL) { opline->opcode = ((opline->opcode == ZEND_IS_EQUAL) == Z_LVAL(ZEND_OP2_LITERAL(opline)))? - ZEND_BOOL:ZEND_BOOL_NOT; + ZEND_BOOL : ZEND_BOOL_NOT; SET_UNUSED(opline->op2); } } - if((opline->opcode == ZEND_BOOL || + if ((opline->opcode == ZEND_BOOL || opline->opcode == ZEND_BOOL_NOT || opline->opcode == ZEND_JMPZ || opline->opcode == ZEND_JMPNZ || opline->opcode == ZEND_JMPZNZ) && - ZEND_OP1_TYPE(opline) == IS_TMP_VAR && - VAR_SOURCE(opline->op1) != NULL && - !used_ext[VAR_NUM(ZEND_OP1(opline).var)] && - VAR_SOURCE(opline->op1)->opcode == ZEND_BOOL_NOT - ) { + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) != NULL && + !used_ext[VAR_NUM(ZEND_OP1(opline).var)] && + VAR_SOURCE(opline->op1)->opcode == ZEND_BOOL_NOT) { /* T = BOOL_NOT(X) + JMPZ(T) -> NOP, JMPNZ(X) */ zend_op *src = VAR_SOURCE(opline->op1); COPY_NODE(opline->op1, src->op1); - switch(opline->opcode) { + switch (opline->opcode) { case ZEND_BOOL: /* T = BOOL_NOT(X) + BOOL(T) -> NOP, BOOL_NOT(X) */ opline->opcode = ZEND_BOOL_NOT; @@ -741,28 +739,27 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, } else #endif /* T = BOOL(X) + JMPZ(T) -> NOP, JMPZ(X) */ - if((opline->opcode == ZEND_BOOL || + if ((opline->opcode == ZEND_BOOL || opline->opcode == ZEND_BOOL_NOT || opline->opcode == ZEND_JMPZ || opline->opcode == ZEND_JMPZ_EX || opline->opcode == ZEND_JMPNZ_EX || opline->opcode == ZEND_JMPNZ || opline->opcode == ZEND_JMPZNZ) && - ZEND_OP1_TYPE(opline) == IS_TMP_VAR && - VAR_SOURCE(opline->op1) != NULL && - (!used_ext[VAR_NUM(ZEND_OP1(opline).var)] || + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) != NULL && + (!used_ext[VAR_NUM(ZEND_OP1(opline).var)] || (ZEND_RESULT_TYPE(opline) == IS_TMP_VAR && ZEND_RESULT(opline).var == ZEND_OP1(opline).var)) && - (VAR_SOURCE(opline->op1)->opcode == ZEND_BOOL || - VAR_SOURCE(opline->op1)->opcode == ZEND_QM_ASSIGN) - ) { + (VAR_SOURCE(opline->op1)->opcode == ZEND_BOOL || + VAR_SOURCE(opline->op1)->opcode == ZEND_QM_ASSIGN)) { zend_op *src = VAR_SOURCE(opline->op1); COPY_NODE(opline->op1, src->op1); VAR_UNSET(opline->op1); MAKE_NOP(src); continue; - } else if(last_op && opline->opcode == ZEND_ECHO && + } else if (last_op && opline->opcode == ZEND_ECHO && last_op->opcode == ZEND_ECHO && ZEND_OP1_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_DOUBLE && @@ -774,10 +771,10 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, */ int l; - if(Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_STRING) { + if (Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_STRING) { convert_to_string_safe(&ZEND_OP1_LITERAL(opline)); } - if(Z_TYPE(ZEND_OP1_LITERAL(last_op)) != IS_STRING) { + if (Z_TYPE(ZEND_OP1_LITERAL(last_op)) != IS_STRING) { convert_to_string_safe(&ZEND_OP1_LITERAL(last_op)); } l = Z_STRLEN(ZEND_OP1_LITERAL(opline)) + Z_STRLEN(ZEND_OP1_LITERAL(last_op)); @@ -799,23 +796,22 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, #endif Z_STRLEN(ZEND_OP1_LITERAL(opline)) = l; MAKE_NOP(last_op); - } else if(opline->opcode == ZEND_CONCAT && + } else if (opline->opcode == ZEND_CONCAT && ZEND_OP2_TYPE(opline) == IS_CONST && ZEND_OP1_TYPE(opline) == IS_TMP_VAR && VAR_SOURCE(opline->op1) && (VAR_SOURCE(opline->op1)->opcode == ZEND_CONCAT || VAR_SOURCE(opline->op1)->opcode == ZEND_ADD_STRING) && ZEND_OP2_TYPE(VAR_SOURCE(opline->op1)) == IS_CONST && - ZEND_RESULT(VAR_SOURCE(opline->op1)).var == ZEND_OP1(opline).var - ) { + ZEND_RESULT(VAR_SOURCE(opline->op1)).var == ZEND_OP1(opline).var) { /* compress consecutive CONCATs */ zend_op *src = VAR_SOURCE(opline->op1); int l; - if(Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) { + if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) { convert_to_string_safe(&ZEND_OP2_LITERAL(opline)); } - if(Z_TYPE(ZEND_OP2_LITERAL(src)) != IS_STRING) { + if (Z_TYPE(ZEND_OP2_LITERAL(src)) != IS_STRING) { convert_to_string_safe(&ZEND_OP2_LITERAL(src)); } @@ -831,7 +827,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, memcpy(tmp, Z_STRVAL(ZEND_OP2_LITERAL(src)), l + 1); Z_STRVAL(ZEND_OP2_LITERAL(src)) = tmp; } else { - Z_STRVAL(ZEND_OP2_LITERAL(src)) = erealloc(Z_STRVAL(ZEND_OP2_LITERAL(src)), l+1); + Z_STRVAL(ZEND_OP2_LITERAL(src)) = erealloc(Z_STRVAL(ZEND_OP2_LITERAL(src)), l + 1); } memcpy(Z_STRVAL(ZEND_OP2_LITERAL(src))+Z_STRLEN(ZEND_OP2_LITERAL(src)), Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline))); Z_STRVAL(ZEND_OP2_LITERAL(src))[l] = '\0'; @@ -846,51 +842,47 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, #endif Z_STRLEN(ZEND_OP2_LITERAL(opline)) = l; MAKE_NOP(src); - } else if((opline->opcode == ZEND_ADD_STRING || - opline->opcode == ZEND_ADD_VAR) && - ZEND_OP1_TYPE(opline) == IS_CONST) { + } else if ((opline->opcode == ZEND_ADD_STRING || opline->opcode == ZEND_ADD_VAR) && ZEND_OP1_TYPE(opline) == IS_CONST) { /* convert ADD_STRING(C1, C2) to CONCAT(C1, C2) */ opline->opcode = ZEND_CONCAT; continue; - } else if(opline->opcode == ZEND_ADD_CHAR && ZEND_OP1_TYPE(opline) == IS_CONST && ZEND_OP2_TYPE(opline) == IS_CONST) { + } else if (opline->opcode == ZEND_ADD_CHAR && ZEND_OP1_TYPE(opline) == IS_CONST && ZEND_OP2_TYPE(opline) == IS_CONST) { /* convert ADD_CHAR(C1, C2) to CONCAT(C1, C2) */ char c = (char)Z_LVAL(ZEND_OP2_LITERAL(opline)); ZVAL_STRINGL(&ZEND_OP2_LITERAL(opline), &c, 1, 1); opline->opcode = ZEND_CONCAT; continue; - } else if( - (opline->opcode == ZEND_ADD || - opline->opcode == ZEND_SUB || - opline->opcode == ZEND_MUL || - opline->opcode == ZEND_DIV || - opline->opcode == ZEND_MOD || - opline->opcode == ZEND_SL || - opline->opcode == ZEND_SR || - opline->opcode == ZEND_CONCAT || - opline->opcode == ZEND_IS_EQUAL || - opline->opcode == ZEND_IS_NOT_EQUAL || - opline->opcode == ZEND_IS_SMALLER || - opline->opcode == ZEND_IS_SMALLER_OR_EQUAL || - opline->opcode == ZEND_IS_IDENTICAL || - opline->opcode == ZEND_IS_NOT_IDENTICAL || - opline->opcode == ZEND_BOOL_XOR || - opline->opcode == ZEND_BW_OR || - opline->opcode == ZEND_BW_AND || - opline->opcode == ZEND_BW_XOR) && - ZEND_OP1_TYPE(opline)==IS_CONST && - ZEND_OP2_TYPE(opline)==IS_CONST) { + } else if ((opline->opcode == ZEND_ADD || + opline->opcode == ZEND_SUB || + opline->opcode == ZEND_MUL || + opline->opcode == ZEND_DIV || + opline->opcode == ZEND_MOD || + opline->opcode == ZEND_SL || + opline->opcode == ZEND_SR || + opline->opcode == ZEND_CONCAT || + opline->opcode == ZEND_IS_EQUAL || + opline->opcode == ZEND_IS_NOT_EQUAL || + opline->opcode == ZEND_IS_SMALLER || + opline->opcode == ZEND_IS_SMALLER_OR_EQUAL || + opline->opcode == ZEND_IS_IDENTICAL || + opline->opcode == ZEND_IS_NOT_IDENTICAL || + opline->opcode == ZEND_BOOL_XOR || + opline->opcode == ZEND_BW_OR || + opline->opcode == ZEND_BW_AND || + opline->opcode == ZEND_BW_XOR) && + ZEND_OP1_TYPE(opline)==IS_CONST && + ZEND_OP2_TYPE(opline)==IS_CONST) { /* evaluate constant expressions */ int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC) = get_binary_op(opline->opcode); zval result; int er; - if ((opline->opcode == ZEND_DIV || - opline->opcode == ZEND_MOD) && + if ((opline->opcode == ZEND_DIV || opline->opcode == ZEND_MOD) && ((Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_LONG && Z_LVAL(ZEND_OP2_LITERAL(opline)) == 0) || (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_DOUBLE && Z_DVAL(ZEND_OP2_LITERAL(opline)) == 0.0))) { - if(RESULT_USED(opline)) { + if (RESULT_USED(opline)) { SET_VAR_SOURCE(opline); } opline++; @@ -898,7 +890,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, } er = EG(error_reporting); EG(error_reporting) = 0; - if(binary_op(&result, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline) TSRMLS_CC) == SUCCESS) { + if (binary_op(&result, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline) TSRMLS_CC) == SUCCESS) { PZ_SET_REFCOUNT_P(&result, 1); PZ_UNSET_ISREF_P(&result); @@ -910,15 +902,14 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, opline->opcode = ZEND_QM_ASSIGN; } EG(error_reporting) = er; - } else if((opline->opcode == ZEND_BOOL || - opline->opcode == ZEND_BOOL_NOT || - opline->opcode == ZEND_BW_NOT) && ZEND_OP1_TYPE(opline)==IS_CONST - ) { + } else if ((opline->opcode == ZEND_BOOL || + opline->opcode == ZEND_BOOL_NOT || + opline->opcode == ZEND_BW_NOT) && ZEND_OP1_TYPE(opline) == IS_CONST) { /* evaluate constant unary ops */ unary_op_type unary_op = get_unary_op(opline->opcode); zval result; - if(unary_op) { + if (unary_op) { unary_op(&result, &ZEND_OP1_LITERAL(opline) TSRMLS_CC); literal_dtor(&ZEND_OP1_LITERAL(opline)); } else { @@ -930,21 +921,20 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, PZ_UNSET_ISREF_P(&result); ZEND_OP1_LITERAL(opline) = result; opline->opcode = ZEND_QM_ASSIGN; - } else if((opline->opcode == ZEND_RETURN || opline->opcode == ZEND_EXIT) && - ZEND_OP1_TYPE(opline) == IS_TMP_VAR && - VAR_SOURCE(opline->op1) && - VAR_SOURCE(opline->op1)->opcode == ZEND_QM_ASSIGN - ) { + } else if ((opline->opcode == ZEND_RETURN || opline->opcode == ZEND_EXIT) && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + VAR_SOURCE(opline->op1)->opcode == ZEND_QM_ASSIGN) { /* T = QM_ASSIGN(X), RETURN(T) to RETURN(X) */ zend_op *src = VAR_SOURCE(opline->op1); VAR_UNSET(opline->op1); COPY_NODE(opline->op1, src->op1); MAKE_NOP(src); - } else if((opline->opcode == ZEND_ADD_STRING || - opline->opcode == ZEND_ADD_CHAR) && - ZEND_OP1_TYPE(opline) == IS_TMP_VAR && - VAR_SOURCE(opline->op1) && - VAR_SOURCE(opline->op1)->opcode == ZEND_INIT_STRING) { + } else if ((opline->opcode == ZEND_ADD_STRING || + opline->opcode == ZEND_ADD_CHAR) && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + VAR_SOURCE(opline->op1)->opcode == ZEND_INIT_STRING) { /* convert T = INIT_STRING(), T = ADD_STRING(T, X) to T = QM_ASSIGN(X) */ /* CHECKME: Remove ZEND_ADD_VAR optimizsation, since some conversions - namely, BOOL(false)->string - don't allocate memory but use empty_string @@ -952,38 +942,38 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, zend_op *src = VAR_SOURCE(opline->op1); VAR_UNSET(opline->op1); COPY_NODE(opline->op1, opline->op2); - if(opline->opcode == ZEND_ADD_CHAR) { + if (opline->opcode == ZEND_ADD_CHAR) { char c = (char)Z_LVAL(ZEND_OP2_LITERAL(opline)); ZVAL_STRINGL(&ZEND_OP1_LITERAL(opline), &c, 1, 1); } SET_UNUSED(opline->op2); MAKE_NOP(src); opline->opcode = ZEND_QM_ASSIGN; - } else if((opline->opcode == ZEND_ADD_STRING || - opline->opcode == ZEND_ADD_CHAR || - opline->opcode == ZEND_ADD_VAR || - opline->opcode == ZEND_CONCAT) && - ZEND_OP1_TYPE(opline) == IS_TMP_VAR && - VAR_SOURCE(opline->op1) && - VAR_SOURCE(opline->op1)->opcode == ZEND_CONCAT && - ZEND_OP2_TYPE(VAR_SOURCE(opline->op1)) == IS_CONST && - Z_TYPE(ZEND_OP2_LITERAL(VAR_SOURCE(opline->op1))) == IS_STRING && - Z_STRLEN(ZEND_OP2_LITERAL(VAR_SOURCE(opline->op1))) == 0) { + } else if ((opline->opcode == ZEND_ADD_STRING || + opline->opcode == ZEND_ADD_CHAR || + opline->opcode == ZEND_ADD_VAR || + opline->opcode == ZEND_CONCAT) && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + VAR_SOURCE(opline->op1)->opcode == ZEND_CONCAT && + ZEND_OP2_TYPE(VAR_SOURCE(opline->op1)) == IS_CONST && + Z_TYPE(ZEND_OP2_LITERAL(VAR_SOURCE(opline->op1))) == IS_STRING && + Z_STRLEN(ZEND_OP2_LITERAL(VAR_SOURCE(opline->op1))) == 0) { /* convert T = CONCAT(X,''), T = ADD_STRING(T, Y) to T = CONCAT(X,Y) */ zend_op *src = VAR_SOURCE(opline->op1); VAR_UNSET(opline->op1); COPY_NODE(opline->op1, src->op1); - if(opline->opcode == ZEND_ADD_CHAR) { + if (opline->opcode == ZEND_ADD_CHAR) { char c = (char)Z_LVAL(ZEND_OP2_LITERAL(opline)); ZVAL_STRINGL(&ZEND_OP2_LITERAL(opline), &c, 1, 1); } opline->opcode = ZEND_CONCAT; literal_dtor(&ZEND_OP2_LITERAL(src)); /* will take care of empty_string too */ MAKE_NOP(src); - } else if(opline->opcode == ZEND_ADD_VAR && - ZEND_OP1_TYPE(opline) == IS_TMP_VAR && - VAR_SOURCE(opline->op1) && - VAR_SOURCE(opline->op1)->opcode == ZEND_INIT_STRING) { + } else if (opline->opcode == ZEND_ADD_VAR && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + VAR_SOURCE(opline->op1)->opcode == ZEND_INIT_STRING) { /* convert T = INIT_STRING(), T = ADD_VAR(T, X) to T = CAST(STRING, X) */ zend_op *src = VAR_SOURCE(opline->op1); VAR_UNSET(opline->op1); @@ -992,44 +982,43 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, MAKE_NOP(src); opline->opcode = ZEND_CAST; opline->extended_value = IS_STRING; - } else if((opline->opcode == ZEND_ADD_STRING || - opline->opcode == ZEND_ADD_CHAR || - opline->opcode == ZEND_ADD_VAR || - opline->opcode == ZEND_CONCAT) && - ZEND_OP1_TYPE(opline) == IS_TMP_VAR && - VAR_SOURCE(opline->op1) && - VAR_SOURCE(opline->op1)->opcode == ZEND_CAST && - VAR_SOURCE(opline->op1)->extended_value == IS_STRING) { + } else if ((opline->opcode == ZEND_ADD_STRING || + opline->opcode == ZEND_ADD_CHAR || + opline->opcode == ZEND_ADD_VAR || + opline->opcode == ZEND_CONCAT) && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + VAR_SOURCE(opline->op1)->opcode == ZEND_CAST && + VAR_SOURCE(opline->op1)->extended_value == IS_STRING) { /* convert T1 = CAST(STRING, X), T2 = CONCAT(T1, Y) to T2 = CONCAT(X,Y) */ zend_op *src = VAR_SOURCE(opline->op1); VAR_UNSET(opline->op1); COPY_NODE(opline->op1, src->op1); - if(opline->opcode == ZEND_ADD_CHAR) { + if (opline->opcode == ZEND_ADD_CHAR) { char c = (char)Z_LVAL(ZEND_OP2_LITERAL(opline)); ZVAL_STRINGL(&ZEND_OP2_LITERAL(opline), &c, 1, 1); } opline->opcode = ZEND_CONCAT; MAKE_NOP(src); - } else if(opline->opcode == ZEND_QM_ASSIGN && - ZEND_OP1_TYPE(opline) == IS_TMP_VAR && - ZEND_RESULT_TYPE(opline) == IS_TMP_VAR && - ZEND_OP1(opline).var == ZEND_RESULT(opline).var) { + } else if (opline->opcode == ZEND_QM_ASSIGN && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + ZEND_RESULT_TYPE(opline) == IS_TMP_VAR && + ZEND_OP1(opline).var == ZEND_RESULT(opline).var) { /* strip T = QM_ASSIGN(T) */ MAKE_NOP(opline); - } else if(opline->opcode == ZEND_BOOL && - ZEND_OP1_TYPE(opline) == IS_TMP_VAR && - VAR_SOURCE(opline->op1) && - (VAR_SOURCE(opline->op1)->opcode == ZEND_IS_EQUAL || - VAR_SOURCE(opline->op1)->opcode == ZEND_IS_NOT_EQUAL || - VAR_SOURCE(opline->op1)->opcode == ZEND_IS_SMALLER || - VAR_SOURCE(opline->op1)->opcode == ZEND_IS_SMALLER_OR_EQUAL || - VAR_SOURCE(opline->op1)->opcode == ZEND_BOOL || - VAR_SOURCE(opline->op1)->opcode == ZEND_IS_IDENTICAL || - VAR_SOURCE(opline->op1)->opcode == ZEND_IS_NOT_IDENTICAL || - VAR_SOURCE(opline->op1)->opcode == ZEND_ISSET_ISEMPTY_VAR || - VAR_SOURCE(opline->op1)->opcode == ZEND_ISSET_ISEMPTY_DIM_OBJ - ) && !used_ext[VAR_NUM(ZEND_OP1(opline).var)] - ) { + } else if (opline->opcode == ZEND_BOOL && + ZEND_OP1_TYPE(opline) == IS_TMP_VAR && + VAR_SOURCE(opline->op1) && + (VAR_SOURCE(opline->op1)->opcode == ZEND_IS_EQUAL || + VAR_SOURCE(opline->op1)->opcode == ZEND_IS_NOT_EQUAL || + VAR_SOURCE(opline->op1)->opcode == ZEND_IS_SMALLER || + VAR_SOURCE(opline->op1)->opcode == ZEND_IS_SMALLER_OR_EQUAL || + VAR_SOURCE(opline->op1)->opcode == ZEND_BOOL || + VAR_SOURCE(opline->op1)->opcode == ZEND_IS_IDENTICAL || + VAR_SOURCE(opline->op1)->opcode == ZEND_IS_NOT_IDENTICAL || + VAR_SOURCE(opline->op1)->opcode == ZEND_ISSET_ISEMPTY_VAR || + VAR_SOURCE(opline->op1)->opcode == ZEND_ISSET_ISEMPTY_DIM_OBJ) && + !used_ext[VAR_NUM(ZEND_OP1(opline).var)]) { /* T = IS_SMALLER(X, Y), T1 = BOOL(T) => T = IS_SMALLER(X, Y), T1 = QM_ASSIGN(T) */ zend_op *src = VAR_SOURCE(opline->op1); COPY_NODE(src->result, opline->result); @@ -1037,23 +1026,23 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, MAKE_NOP(opline); } /* get variable source */ - if(RESULT_USED(opline)) { + if (RESULT_USED(opline)) { SET_VAR_SOURCE(opline); } - if(opline->opcode != ZEND_NOP) { + if (opline->opcode != ZEND_NOP) { last_op = opline; } opline++; } /* remove leading NOPs */ - while(block->start_opline->opcode == ZEND_NOP) { - if(block->len == 1) { + while (block->start_opline->opcode == ZEND_NOP) { + if (block->len == 1) { /* this block is all NOPs, join with following block */ - if(block->follow_to) { + if (block->follow_to) { delete_code_block(block); } - if(op_array->T){ + if (op_array->T) { efree(Tsource); } return; @@ -1066,15 +1055,15 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, /* strip the inside NOPs */ opline = block->start_opline; end = opline+block->len; - while(oplineopcode == ZEND_NOP) { - zend_op *nop = opline+1; + while (opline < end) { + if (opline->opcode == ZEND_NOP) { + zend_op *nop = opline + 1; int noplen; - while(nopopcode == ZEND_NOP) { + while (nop < end && nop->opcode == ZEND_NOP) { nop++; } noplen = nop-opline; - if(nopT){ + if (op_array->T) { efree(Tsource); } } @@ -1099,18 +1088,18 @@ static void assemble_code_blocks(zend_code_block *blocks, zend_op_array *op_arra zend_code_block *cur_block = blocks; /* Copy code of reachable blocks into a single buffer */ - while(cur_block) { - if(cur_block->access) { + while (cur_block) { + if (cur_block->access) { memcpy(opline, cur_block->start_opline, cur_block->len*sizeof(zend_op)); cur_block->start_opline = opline; opline += cur_block->len; - if((opline-1)->opcode == ZEND_JMP) { + if ((opline-1)->opcode == ZEND_JMP) { zend_code_block *next; next = cur_block->next; - while(next && !next->access) { + while (next && !next->access) { next = next->next; } - if(next && next == cur_block->op1_to) { + if (next && next == cur_block->op1_to) { /* JMP to the next block - strip it */ cur_block->follow_to = cur_block->op1_to; cur_block->op1_to = NULL; @@ -1123,11 +1112,11 @@ static void assemble_code_blocks(zend_code_block *blocks, zend_op_array *op_arra /* this block will not be used, delete all constants there */ zend_op *_opl; zend_op *end = cur_block->start_opline+cur_block->len; - for(_opl = cur_block->start_opline; _opl && _opl < end; _opl++) { - if(ZEND_OP1_TYPE(_opl) == IS_CONST) { + for (_opl = cur_block->start_opline; _opl && _opl < end; _opl++) { + if (ZEND_OP1_TYPE(_opl) == IS_CONST) { literal_dtor(&ZEND_OP1_LITERAL(_opl)); } - if(ZEND_OP2_TYPE(_opl) == IS_CONST) { + if (ZEND_OP2_TYPE(_opl) == IS_CONST) { literal_dtor(&ZEND_OP2_LITERAL(_opl)); } } @@ -1135,7 +1124,7 @@ static void assemble_code_blocks(zend_code_block *blocks, zend_op_array *op_arra cur_block = cur_block->next; } #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO - if(opline[-1].opcode == ZEND_THROW) { + if (opline[-1].opcode == ZEND_THROW) { /* if we finished with THROW, we need to add space between THROW and HANDLE to not confuse zend_throw_internal */ MAKE_NOP(opline); @@ -1151,9 +1140,9 @@ static void assemble_code_blocks(zend_code_block *blocks, zend_op_array *op_arra op_array->last = opline-new_opcodes; /* adjust exception jump targets */ - if(op_array->last_try_catch) { + if (op_array->last_try_catch) { int i; - for(i=0; i< op_array->last_try_catch; i++) { + for (i=0; i< op_array->last_try_catch; i++) { op_array->try_catch_array[i].try_op = blocks->try[i]->start_opline - new_opcodes; op_array->try_catch_array[i].catch_op = blocks->catch[i]->start_opline - new_opcodes; } @@ -1162,17 +1151,17 @@ static void assemble_code_blocks(zend_code_block *blocks, zend_op_array *op_arra } /* adjust jump targets */ - for(cur_block = blocks; cur_block; cur_block = cur_block->next) { - if(!cur_block->access) { + for (cur_block = blocks; cur_block; cur_block = cur_block->next) { + if (!cur_block->access) { continue; } - if(cur_block->op1_to) { + if (cur_block->op1_to) { ZEND_OP1(&cur_block->start_opline[cur_block->len-1]).opline_num = cur_block->op1_to->start_opline - new_opcodes; } - if(cur_block->op2_to) { + if (cur_block->op2_to) { ZEND_OP2(&cur_block->start_opline[cur_block->len-1]).opline_num = cur_block->op2_to->start_opline - new_opcodes; } - if(cur_block->ext_to) { + if (cur_block->ext_to) { cur_block->start_opline[cur_block->len-1].extended_value = cur_block->ext_to->start_opline - new_opcodes; } print_block(cur_block, new_opcodes, "Out "); @@ -1203,9 +1192,9 @@ static void assemble_code_blocks(zend_code_block *blocks, zend_op_array *op_arra static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_array, zend_code_block *blocks) { /* last_op is the last opcode of the current block */ - zend_op *last_op = (block->start_opline+block->len-1); + zend_op *last_op = (block->start_opline + block->len - 1); - switch(last_op->opcode) { + switch (last_op->opcode) { case ZEND_JMP: { zend_op *target = block->op1_to->start_opline; @@ -1217,26 +1206,26 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra } /* JMP(next) -> NOP */ - if(block->op1_to == next) { + if (block->op1_to == next) { block->follow_to = block->op1_to; block->op1_to = NULL; MAKE_NOP(last_op); block->len--; - if(block->len == 0) { + if (block->len == 0) { /* this block is nothing but NOP now */ delete_code_block(block); } break; } - if(((target->opcode == ZEND_JMP && - block->op1_to != block->op1_to->op1_to) || - target->opcode == ZEND_JMPZNZ) && - !block->op1_to->is_try) { + if (((target->opcode == ZEND_JMP && + block->op1_to != block->op1_to->op1_to) || + target->opcode == ZEND_JMPZNZ) && + !block->op1_to->is_try) { /* JMP L, L: JMP L1 -> JMP L1 */ /* JMP L, L: JMPZNZ L1,L2 -> JMPZNZ L1,L2 */ *last_op = *target; - if(ZEND_OP1_TYPE(last_op) == IS_CONST) { + if (ZEND_OP1_TYPE(last_op) == IS_CONST) { zval_copy_ctor(&ZEND_OP1_LITERAL(last_op)); } del_source(block, block->op1_to); @@ -1254,7 +1243,7 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra } else { block->op1_to = NULL; } - } else if(target->opcode == ZEND_RETURN || + } else if (target->opcode == ZEND_RETURN || #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO target->opcode == ZEND_RETURN_BY_REF || #endif @@ -1264,7 +1253,7 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra target->opcode == ZEND_EXIT) { /* JMP L, L: RETURN to immediate RETURN */ *last_op = *target; - if(ZEND_OP1_TYPE(last_op) == IS_CONST) { + if (ZEND_OP1_TYPE(last_op) == IS_CONST) { zval_copy_ctor(&ZEND_OP1_LITERAL(last_op)); } del_source(block, block->op1_to); @@ -1330,7 +1319,7 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra case ZEND_JMPZ: case ZEND_JMPNZ: /* constant conditional JMPs */ - if(ZEND_OP1_TYPE(last_op) == IS_CONST) { + if (ZEND_OP1_TYPE(last_op) == IS_CONST) { int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(last_op)); if (last_op->opcode == ZEND_JMPZ) { should_jmp = !should_jmp; @@ -1354,7 +1343,7 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra break; } - if(block->op2_to) { + if (block->op2_to) { zend_uchar same_type = ZEND_OP1_TYPE(last_op); zend_uint same_var = VAR_NUM_EX(last_op->op1); zend_op *target; @@ -1364,17 +1353,16 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra next_target: target = target_block->start_opline; target_end = target_block->start_opline + target_block->len; - while(target < target_end && target->opcode == ZEND_NOP) { + while (target < target_end && target->opcode == ZEND_NOP) { target++; } /* next block is only NOP's */ - if(target == target_end) { + if (target == target_end) { target_block = target_block->follow_to; goto next_target; - } else - /* JMPZ(X, L), L: JMPNZ(X, L2) -> JMPZ(X, L+1) */ - if(target->opcode == INV_COND(last_op->opcode) && + } else if (target->opcode == INV_COND(last_op->opcode) && + /* JMPZ(X, L), L: JMPNZ(X, L2) -> JMPZ(X, L+1) */ (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && same_type == ZEND_OP1_TYPE(target) && same_var == VAR_NUM_EX(target->op1) && @@ -1384,51 +1372,43 @@ next_target: del_source(block, block->op2_to); block->op2_to = target_block->follow_to; ADD_SOURCE(block, block->op2_to); - } - /* JMPZ(X, L), L: X = JMPNZ_EX(X, L2) -> JMPZ(X, L+1) */ - else if(target->opcode == INV_COND_EX(last_op->opcode) && - (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && - same_type == ZEND_OP1_TYPE(target) && - same_var == VAR_NUM_EX(target->op1) && - target_block->follow_to && - !target_block->is_try - ) { + } else if (target->opcode == INV_COND_EX(last_op->opcode) && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + same_type == ZEND_OP1_TYPE(target) && + same_var == VAR_NUM_EX(target->op1) && + target_block->follow_to && + !target_block->is_try) { + /* JMPZ(X, L), L: X = JMPNZ_EX(X, L2) -> JMPZ(X, L+1) */ last_op->opcode += 3; last_op->result = target->result; del_source(block, block->op2_to); block->op2_to = target_block->follow_to; ADD_SOURCE(block, block->op2_to); - } - /* JMPZ(X, L), L: JMPZ(X, L2) -> JMPZ(X, L2) */ - else if(target_block->op2_to && - target->opcode == last_op->opcode && - (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && - same_type == ZEND_OP1_TYPE(target) && - same_var == VAR_NUM_EX(target->op1) && - !target_block->is_try - ) { + } else if (target_block->op2_to && + target->opcode == last_op->opcode && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + same_type == ZEND_OP1_TYPE(target) && + same_var == VAR_NUM_EX(target->op1) && + !target_block->is_try) { + /* JMPZ(X, L), L: JMPZ(X, L2) -> JMPZ(X, L2) */ del_source(block, block->op2_to); block->op2_to = target_block->op2_to; ADD_SOURCE(block, block->op2_to); - } - /* JMPZ(X, L), L: JMP(L2) -> JMPZ(X, L2) */ - else if(target_block->op1_to && - target->opcode == ZEND_JMP && - !target_block->is_try - ) { + } else if (target_block->op1_to && + target->opcode == ZEND_JMP && + !target_block->is_try) { + /* JMPZ(X, L), L: JMP(L2) -> JMPZ(X, L2) */ del_source(block, block->op2_to); block->op2_to = target_block->op1_to; ADD_SOURCE(block, block->op2_to); - } - /* JMPZ(X, L), L: JMPZNZ(X, L2, L3) -> JMPZ(X, L2) */ - else if(target_block->op2_to && - target_block->ext_to && - target->opcode == ZEND_JMPZNZ && - (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && - same_type == ZEND_OP1_TYPE(target) && - same_var == VAR_NUM_EX(target->op1) && - ! target_block->is_try - ) { + } else if (target_block->op2_to && + target_block->ext_to && + target->opcode == ZEND_JMPZNZ && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + same_type == ZEND_OP1_TYPE(target) && + same_var == VAR_NUM_EX(target->op1) && + !target_block->is_try) { + /* JMPZ(X, L), L: JMPZNZ(X, L2, L3) -> JMPZ(X, L2) */ del_source(block, block->op2_to); if (last_op->opcode == ZEND_JMPZ) { block->op2_to = target_block->op2_to; @@ -1452,7 +1432,7 @@ next_target: } /* next block is only NOP's */ - if(target == target_end) { + if (target == target_end) { del_source(block, block->follow_to); block->follow_to = block->follow_to->follow_to; ADD_SOURCE(block, block->follow_to); @@ -1482,7 +1462,7 @@ next_target: case ZEND_JMPNZ_EX: case ZEND_JMPZ_EX: /* constant conditional JMPs */ - if(ZEND_OP1_TYPE(last_op) == IS_CONST) { + if (ZEND_OP1_TYPE(last_op) == IS_CONST) { int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(last_op)); if (last_op->opcode == ZEND_JMPZ_EX) { should_jmp = !should_jmp; @@ -1499,21 +1479,21 @@ next_target: break; } - if(block->op2_to) { + if (block->op2_to) { zend_op *target, *target_end; char *same_t=NULL; zend_code_block *target_block; int var_num = 0; - if(op_array->T >= (zend_uint)op_array->last_var){ + if (op_array->T >= (zend_uint)op_array->last_var) { var_num = op_array->T; } else { var_num = op_array->last_var; } - if( var_num <= 0 ) { + if (var_num <= 0) { return; } same_t = ecalloc(var_num, sizeof(char)); - if(same_t == NULL){ + if (same_t == NULL) { return; } same_t[VAR_NUM_EX(last_op->op1)] |= ZEND_OP1_TYPE(last_op); @@ -1522,69 +1502,65 @@ next_target: next_target_ex: target = target_block->start_opline; target_end = target_block->start_opline + target_block->len; - while(target < target_end && target->opcode == ZEND_NOP) { + while (target < target_end && target->opcode == ZEND_NOP) { target++; } /* next block is only NOP's */ - if(target == target_end) { + if (target == target_end) { target_block = target_block->follow_to; goto next_target_ex; - } else - /* T = JMPZ_EX(X, L1), L1: JMPZ({X|T}, L2) -> T = JMPZ_EX(X, L2) */ - if(target_block->op2_to && - target->opcode == last_op->opcode-3 && - (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && - (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && - !target_block->is_try - ) { + } else if (target_block->op2_to && + target->opcode == last_op->opcode-3 && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && + !target_block->is_try) { + /* T = JMPZ_EX(X, L1), L1: JMPZ({X|T}, L2) -> T = JMPZ_EX(X, L2) */ del_source(block, block->op2_to); block->op2_to = target_block->op2_to; ADD_SOURCE(block, block->op2_to); + } else if (target_block->op2_to && + target->opcode == INV_EX_COND(last_op->opcode) && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && + !target_block->is_try) { /* T = JMPZ_EX(X, L1), L1: JMPNZ({X|T1}, L2) -> T = JMPZ_EX(X, L1+1) */ - } else if(target_block->op2_to && - target->opcode == INV_EX_COND(last_op->opcode) && - (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && - (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && - !target_block->is_try - ) { del_source(block, block->op2_to); block->op2_to = target_block->follow_to; ADD_SOURCE(block, block->op2_to); + } else if (target_block->op2_to && + target->opcode == INV_EX_COND_EX(last_op->opcode) && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && + (same_t[VAR_NUM_EX(target->result)] & ZEND_RESULT_TYPE(target)) != 0 && + !target_block->is_try) { /* T = JMPZ_EX(X, L1), L1: T = JMPNZ_EX(T, L2) -> T = JMPZ_EX(X, L1+1) */ - } else if(target_block->op2_to && - target->opcode == INV_EX_COND_EX(last_op->opcode) && - (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && - (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && - (same_t[VAR_NUM_EX(target->result)] & ZEND_RESULT_TYPE(target)) != 0 && - !target_block->is_try) { del_source(block, block->op2_to); block->op2_to = target_block->follow_to; ADD_SOURCE(block, block->op2_to); - /* T = JMPZ_EX(X, L1), L1: T = JMPZ({X|T}, L2) -> T = JMPZ_EX(X, L2) */ - } else if(target_block->op2_to && - target->opcode == last_op->opcode && - (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && - (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && - (same_t[VAR_NUM_EX(target->result)] & ZEND_RESULT_TYPE(target)) != 0 && - !target_block->is_try) { + } else if (target_block->op2_to && + target->opcode == last_op->opcode && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && + (same_t[VAR_NUM_EX(target->result)] & ZEND_RESULT_TYPE(target)) != 0 && + !target_block->is_try) { + /* T = JMPZ_EX(X, L1), L1: T = JMPZ({X|T}, L2) -> T = JMPZ_EX(X, L2) */ del_source(block, block->op2_to); block->op2_to = target_block->op2_to; ADD_SOURCE(block, block->op2_to); - /* T = JMPZ_EX(X, L), L: JMP(L2) -> T = JMPZ(X, L2) */ - } else if(target_block->op1_to && - target->opcode == ZEND_JMP && - !target_block->is_try) { + } else if (target_block->op1_to && + target->opcode == ZEND_JMP && + !target_block->is_try) { + /* T = JMPZ_EX(X, L), L: JMP(L2) -> T = JMPZ(X, L2) */ del_source(block, block->op2_to); block->op2_to = target_block->op1_to; ADD_SOURCE(block, block->op2_to); - /* T = JMPZ_EX(X, L), L: JMPZNZ({X|T}, L2, L3) -> T = JMPZ_EX(X, L2) */ - } else if(target_block->op2_to && - target_block->ext_to && - target->opcode == ZEND_JMPZNZ && - (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && - (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && - !target_block->is_try - ) { + } else if (target_block->op2_to && + target_block->ext_to && + target->opcode == ZEND_JMPZNZ && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && + !target_block->is_try) { + /* T = JMPZ_EX(X, L), L: JMPZNZ({X|T}, L2, L3) -> T = JMPZ_EX(X, L2) */ del_source(block, block->op2_to); if (last_op->opcode == ZEND_JMPZ_EX) { block->op2_to = target_block->op2_to; @@ -1593,7 +1569,7 @@ next_target_ex: } ADD_SOURCE(block, block->op2_to); } - if(same_t != NULL){ + if (same_t != NULL) { efree(same_t); } } @@ -1607,11 +1583,11 @@ next_target_ex: next = next->next; } - if(ZEND_OP1_TYPE(last_op) == IS_CONST) { + if (ZEND_OP1_TYPE(last_op) == IS_CONST) { if (!zend_is_true(&ZEND_OP1_LITERAL(last_op))) { /* JMPZNZ(false,L1,L2) -> JMP(L1) */ zend_code_block *todel; - + literal_dtor(&ZEND_OP1_LITERAL(last_op)); last_op->opcode = ZEND_JMP; SET_UNUSED(last_op->op1); @@ -1624,7 +1600,7 @@ next_target_ex: } else { /* JMPZNZ(true,L1,L2) -> JMP(L2) */ zend_code_block *todel; - + literal_dtor(&ZEND_OP1_LITERAL(last_op)); last_op->opcode = ZEND_JMP; SET_UNUSED(last_op->op1); @@ -1661,7 +1637,7 @@ next_target_ex: /* no need to add source - it's block->ext_to */ } - if(last_op->opcode == ZEND_JMPZNZ && block->op2_to) { + if (last_op->opcode == ZEND_JMPZNZ && block->op2_to) { zend_uchar same_type = ZEND_OP1_TYPE(last_op); zend_uchar same_var = VAR_NUM_EX(last_op->op1); zend_op *target; @@ -1671,39 +1647,37 @@ next_target_ex: next_target_znz: target = target_block->start_opline; target_end = target_block->start_opline + target_block->len; - while(target < target_end && target->opcode == ZEND_NOP) { + while (target < target_end && target->opcode == ZEND_NOP) { target++; } /* next block is only NOP's */ - if(target == target_end) { + if (target == target_end) { target_block = target_block->follow_to; goto next_target_znz; - /* JMPZNZ(X, L1, L2), L1: JMPZ(X, L3) -> JMPZNZ(X, L3, L2) */ - } else if(target_block->op2_to && - (target->opcode == ZEND_JMPZ || target->opcode == ZEND_JMPZNZ) && - (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && - same_type == ZEND_OP1_TYPE(target) && - same_var == VAR_NUM_EX(target->op1) && - !target_block->is_try) { + } else if (target_block->op2_to && + (target->opcode == ZEND_JMPZ || target->opcode == ZEND_JMPZNZ) && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + same_type == ZEND_OP1_TYPE(target) && + same_var == VAR_NUM_EX(target->op1) && + !target_block->is_try) { + /* JMPZNZ(X, L1, L2), L1: JMPZ(X, L3) -> JMPZNZ(X, L3, L2) */ del_source(block, block->op2_to); block->op2_to = target_block->op2_to; ADD_SOURCE(block, block->op2_to); - } - /* JMPZNZ(X, L1, L2), L1: X = JMPNZ(X, L3) -> JMPZNZ(X, L1+1, L2) */ - else if(target->opcode == ZEND_JMPNZ && - (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && - same_type == ZEND_OP1_TYPE(target) && - same_var == VAR_NUM_EX(target->op1) && - target_block->follow_to && - !target_block->is_try) { + } else if (target->opcode == ZEND_JMPNZ && + (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && + same_type == ZEND_OP1_TYPE(target) && + same_var == VAR_NUM_EX(target->op1) && + target_block->follow_to && + !target_block->is_try) { + /* JMPZNZ(X, L1, L2), L1: X = JMPNZ(X, L3) -> JMPZNZ(X, L1+1, L2) */ del_source(block, block->op2_to); block->op2_to = target_block->follow_to; ADD_SOURCE(block, block->op2_to); - } - /* JMPZNZ(X, L1, L2), L1: JMP(L3) -> JMPZNZ(X, L3, L2) */ - else if(target_block->op1_to && - target->opcode == ZEND_JMP && - !target_block->is_try) { + } else if (target_block->op1_to && + target->opcode == ZEND_JMP && + !target_block->is_try) { + /* JMPZNZ(X, L1, L2), L1: JMP(L3) -> JMPZNZ(X, L3, L2) */ del_source(block, block->op2_to); block->op2_to = target_block->op1_to; ADD_SOURCE(block, block->op2_to); @@ -1719,7 +1693,7 @@ next_target_znz: #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO # define T_USAGE(op) do { \ - if((op ## _type & (IS_VAR | IS_TMP_VAR)) && \ + if ((op ## _type & (IS_VAR | IS_TMP_VAR)) && \ !defined_here[VAR_NUM(op.var)] && !used_ext[VAR_NUM(op.var)]) { \ used_ext[VAR_NUM(op.var)] = 1; \ } \ @@ -1731,7 +1705,7 @@ next_target_znz: #else # define T_USAGE(op) do { \ - if((op.op_type == IS_VAR || op.op_type == IS_TMP_VAR) && \ + if ((op.op_type == IS_VAR || op.op_type == IS_TMP_VAR) && \ !defined_here[VAR_NUM(op.u.var)] && !used_ext[VAR_NUM(op.u.var)]) { \ used_ext[VAR_NUM(op.u.var)] = 1; \ } \ @@ -1750,7 +1724,7 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char * char *usage; char *defined_here; - if(op_array->T == 0) { + if (op_array->T == 0) { /* shortcut - if no Ts, nothing to do */ return; } @@ -1758,23 +1732,23 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char * usage = ecalloc(op_array->T, 1); defined_here = emalloc(op_array->T); - while(next_block) { + while (next_block) { zend_op *opline = next_block->start_opline; zend_op *end = opline+next_block->len; - if(!next_block->access) { + if (!next_block->access) { next_block = next_block->next; continue; } memset(defined_here, 0, op_array->T); - while(oplineop1); T_USAGE(opline->op2); - if(RESULT_USED(opline)) { - if(!defined_here[VAR_NUM(ZEND_RESULT(opline).var)] && !used_ext[VAR_NUM(ZEND_RESULT(opline).var)] && - (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT || + if (RESULT_USED(opline)) { + if (!defined_here[VAR_NUM(ZEND_RESULT(opline).var)] && !used_ext[VAR_NUM(ZEND_RESULT(opline).var)] && + (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT || (opline->opcode == ZEND_OP_DATA && ZEND_RESULT_TYPE(opline) == IS_TMP_VAR) || opline->opcode == ZEND_ADD_ARRAY_ELEMENT)) { /* these opcodes use the result as argument */ @@ -1790,26 +1764,26 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char * #if DEBUG_BLOCKPASS { int i; - for(i=0; i< op_array->T; i++) { - fprintf(stderr, "T%d: %c\n", i, used_ext[i]+'0'); + for (i=0; i< op_array->T; i++) { + fprintf(stderr, "T%d: %c\n", i, used_ext[i] + '0'); } } #endif - while(block) { - zend_op *opline = block->start_opline+block->len-1; + while (block) { + zend_op *opline = block->start_opline+block->len - 1; - if(!block->access) { + if (!block->access) { block = block->next; continue; } memcpy(usage, used_ext, op_array->T); - while(opline>=block->start_opline) { + while (opline >= block->start_opline) { /* usage checks */ - if(RES_NEVER_USED(opline)) { - switch(opline->opcode) { + if (RES_NEVER_USED(opline)) { + switch (opline->opcode) { case ZEND_ASSIGN_ADD: case ZEND_ASSIGN_SUB: case ZEND_ASSIGN_MUL: @@ -1829,7 +1803,7 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char * case ZEND_ASSIGN_REF: case ZEND_DO_FCALL: case ZEND_DO_FCALL_BY_NAME: - if(ZEND_RESULT_TYPE(opline) == IS_VAR) { + if (ZEND_RESULT_TYPE(opline) == IS_VAR) { #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO ZEND_RESULT_TYPE(opline) |= EXT_TYPE_UNUSED; #else @@ -1840,7 +1814,7 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char * case ZEND_QM_ASSIGN: case ZEND_BOOL: case ZEND_BOOL_NOT: - if(ZEND_OP1_TYPE(opline) == IS_CONST) { + if (ZEND_OP1_TYPE(opline) == IS_CONST) { literal_dtor(&ZEND_OP1_LITERAL(opline)); } MAKE_NOP(opline); @@ -1857,35 +1831,36 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char * } } - if(opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT || - opline->opcode == ZEND_ADD_ARRAY_ELEMENT) { - if(ZEND_OP1_TYPE(opline) == IS_VAR || ZEND_OP1_TYPE(opline) == IS_TMP_VAR) { + if (opline->opcode == ZEND_RECV || + opline->opcode == ZEND_RECV_INIT || + opline->opcode == ZEND_ADD_ARRAY_ELEMENT) { + if (ZEND_OP1_TYPE(opline) == IS_VAR || ZEND_OP1_TYPE(opline) == IS_TMP_VAR) { usage[VAR_NUM(ZEND_RESULT(opline).var)] = 1; } } else { - if(RESULT_USED(opline)) { + if (RESULT_USED(opline)) { usage[VAR_NUM(ZEND_RESULT(opline).var)] = 0; } } - if(ZEND_OP1_TYPE(opline) == IS_VAR || ZEND_OP1_TYPE(opline) == IS_TMP_VAR) { + if (ZEND_OP1_TYPE(opline) == IS_VAR || ZEND_OP1_TYPE(opline) == IS_TMP_VAR) { usage[VAR_NUM(ZEND_OP1(opline).var)] = 1; } - if(ZEND_OP2_TYPE(opline) == IS_VAR || ZEND_OP2_TYPE(opline) == IS_TMP_VAR) { + if (ZEND_OP2_TYPE(opline) == IS_VAR || ZEND_OP2_TYPE(opline) == IS_TMP_VAR) { usage[VAR_NUM(ZEND_OP2(opline).var)] = 1; } #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO - if((ZEND_RESULT_TYPE(opline) & IS_VAR) && - (ZEND_RESULT_TYPE(opline) & EXT_TYPE_UNUSED) && - usage[VAR_NUM(ZEND_RESULT(opline).var)]) { + if ((ZEND_RESULT_TYPE(opline) & IS_VAR) && + (ZEND_RESULT_TYPE(opline) & EXT_TYPE_UNUSED) && + usage[VAR_NUM(ZEND_RESULT(opline).var)]) { ZEND_RESULT_TYPE(opline) &= ~EXT_TYPE_UNUSED; } #else - if(ZEND_RESULT_TYPE(opline) == IS_VAR && - usage[VAR_NUM(ZEND_RESULT(opline).var)] && - (ZEND_RESULT(opline).EA.type & EXT_TYPE_UNUSED) != 0) { + if (ZEND_RESULT_TYPE(opline) == IS_VAR && + usage[VAR_NUM(ZEND_RESULT(opline).var)] && + (ZEND_RESULT(opline).EA.type & EXT_TYPE_UNUSED) != 0) { ZEND_RESULT(opline).EA.type &= ~EXT_TYPE_UNUSED; } #endif @@ -1894,6 +1869,7 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char * } block = block->next; } /* end blocks */ + efree(defined_here); efree(usage); } @@ -1907,7 +1883,7 @@ static void zend_block_optimization(zend_op_array *op_array TSRMLS_DC) char *usage; #if DEBUG_BLOCKPASS - fprintf(stderr, "File %s func %s\n", op_array->filename, op_array->function_name?op_array->function_name:"main"); + fprintf(stderr, "File %s func %s\n", op_array->filename, op_array->function_name? op_array->function_name : "main"); fflush(stderr); #endif @@ -1919,29 +1895,29 @@ static void zend_block_optimization(zend_op_array *op_array TSRMLS_DC) /* Build CFG */ blocks = find_code_blocks(op_array); - if(!blocks) { + if (!blocks) { return; } zend_rebuild_access_path(blocks, op_array, 0); /* full rebuild here to produce correct sources! */ usage = emalloc(op_array->T); - for(pass=0; pass< PASSES; pass++) { + for (pass = 0; pass < PASSES; pass++) { /* Compute data dependencies */ memset(usage, 0, op_array->T); zend_t_usage(blocks, op_array, usage); /* optimize each basic block separately */ - for(cur_block = blocks; cur_block; cur_block = cur_block->next) { - if(!cur_block->access) { + for (cur_block = blocks; cur_block; cur_block = cur_block->next) { + if (!cur_block->access) { continue; } zend_optimize_block(cur_block, op_array, usage TSRMLS_CC); } /* Jump optimization for each block */ - for(cur_block = blocks; cur_block; cur_block = cur_block->next) { - if(!cur_block->access) { + for (cur_block = blocks; cur_block; cur_block = cur_block->next) { + if (!cur_block->access) { continue; } zend_jmp_optimization(cur_block, op_array, blocks); @@ -1955,9 +1931,9 @@ static void zend_block_optimization(zend_op_array *op_array TSRMLS_DC) efree(usage); /* Destroy CFG */ - for(cur_block = blocks; cur_block; cur_block = cur_block->next) { + for (cur_block = blocks; cur_block; cur_block = cur_block->next) { zend_block_source *cs = cur_block->sources; - while(cs) { + while (cs) { zend_block_source *n = cs->next; efree(cs); cs = n; diff --git a/Optimizer/nop_removal.c b/Optimizer/nop_removal.c index 6c22bcf6fd5..ccac6f4540a 100644 --- a/Optimizer/nop_removal.c +++ b/Optimizer/nop_removal.c @@ -92,14 +92,14 @@ static void nop_removal(zend_op_array *op_array) } /* update brk/cont array */ - for (j=0; jlast_brk_cont; j++) { + for (j = 0; j < op_array->last_brk_cont; j++) { op_array->brk_cont_array[j].brk -= shiftlist[op_array->brk_cont_array[j].brk]; op_array->brk_cont_array[j].cont -= shiftlist[op_array->brk_cont_array[j].cont]; op_array->brk_cont_array[j].start -= shiftlist[op_array->brk_cont_array[j].start]; } /* update try/catch array */ - for (j=0; jlast_try_catch; j++) { + for (j = 0; j < op_array->last_try_catch; j++) { op_array->try_catch_array[j].try_op -= shiftlist[op_array->try_catch_array[j].try_op]; op_array->try_catch_array[j].catch_op -= shiftlist[op_array->try_catch_array[j].catch_op]; #if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO diff --git a/Optimizer/optimize_temp_vars_5.c b/Optimizer/optimize_temp_vars_5.c index 4e2865ead44..7cf43bf11e8 100644 --- a/Optimizer/optimize_temp_vars_5.c +++ b/Optimizer/optimize_temp_vars_5.c @@ -60,7 +60,7 @@ static const char op_const_means_class[256] = { #endif #define GET_AVAILABLE_T() \ - for (i=0; iopcode == ZEND_OP_DATA && + if (opline->opcode == ZEND_OP_DATA && (opline-1)->opcode == ZEND_ASSIGN_DIM) { opline--; continue; @@ -218,5 +218,5 @@ static void optimize_temporary_variables(zend_op_array *op_array) efree(start_of_T); efree(valid_T); efree(map_T); - op_array->T = max+1; + op_array->T = max + 1; } diff --git a/Optimizer/pass1_5.c b/Optimizer/pass1_5.c index 247b1b8632f..65e934efcdf 100644 --- a/Optimizer/pass1_5.c +++ b/Optimizer/pass1_5.c @@ -7,11 +7,11 @@ */ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { - int i=0; + int i = 0; zend_op *opline = op_array->opcodes; zend_op *end = opline + op_array->last; - while (oplineopcode) { case ZEND_ADD: case ZEND_SUB: @@ -31,18 +31,18 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { case ZEND_BW_AND: case ZEND_BW_XOR: case ZEND_BOOL_XOR: - if (ZEND_OP1_TYPE(opline)==IS_CONST - && ZEND_OP2_TYPE(opline)==IS_CONST) { - /* binary operation wheit constant operands */ + if (ZEND_OP1_TYPE(opline) == IS_CONST && + ZEND_OP2_TYPE(opline) == IS_CONST) { + /* binary operation with constant operands */ int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC) = get_binary_op(opline->opcode); zend_uint tv = ZEND_RESULT(opline).var; /* temporary variable */ zval result; zend_op *tmp_opline; int er; - if (opline->opcode == ZEND_DIV && - Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_LONG && - Z_LVAL(ZEND_OP2_LITERAL(opline)) == 0) { + if (opline->opcode == ZEND_DIV && + Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_LONG && + Z_LVAL(ZEND_OP2_LITERAL(opline)) == 0) { /* div by 0 */ break; } @@ -62,10 +62,10 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { MAKE_NOP(opline); /* substitute the following TMP_VAR usage with constant */ - for (tmp_opline=opline+1; tmp_oplineopcode==ZEND_FREE) { + for (tmp_opline = opline + 1; tmp_opline < end; tmp_opline++) { + if (ZEND_OP1_TYPE(tmp_opline) == IS_TMP_VAR && + ZEND_OP1(tmp_opline).var == tv) { + if (tmp_opline->opcode == ZEND_FREE) { MAKE_NOP(tmp_opline); zval_dtor(&result); } else { @@ -73,11 +73,11 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO tmp_opline->op1.constant = zend_add_literal(op_array, &result TSRMLS_CC); if (Z_TYPE(result) == IS_STRING) { - Z_HASH_P(&ZEND_OP1_LITERAL(tmp_opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(tmp_opline)), Z_STRLEN(ZEND_OP1_LITERAL(tmp_opline))+1); + Z_HASH_P(&ZEND_OP1_LITERAL(tmp_opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(tmp_opline)), Z_STRLEN(ZEND_OP1_LITERAL(tmp_opline)) + 1); if (tmp_opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - tmp_opline->opcode == ZEND_DO_FCALL || - tmp_opline->opcode == ZEND_CATCH || - tmp_opline->opcode == ZEND_FETCH_CONSTANT) { + tmp_opline->opcode == ZEND_DO_FCALL || + tmp_opline->opcode == ZEND_CATCH || + tmp_opline->opcode == ZEND_FETCH_CONSTANT) { op_array->literals[tmp_opline->op1.constant].cache_slot = op_array->last_cache_slot++; } } @@ -88,56 +88,56 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { /* TMP_VAR my be used only once */ break; } - if (ZEND_OP2_TYPE(tmp_opline)== IS_TMP_VAR - && ZEND_OP2(tmp_opline).var == tv) { + if (ZEND_OP2_TYPE(tmp_opline) == IS_TMP_VAR && + ZEND_OP2(tmp_opline).var == tv) { ZEND_OP2_TYPE(tmp_opline) = IS_CONST; #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO tmp_opline->op2.constant = zend_add_literal(op_array, &result TSRMLS_CC); if (Z_TYPE(result) == IS_STRING) { - Z_HASH_P(&ZEND_OP2_LITERAL(tmp_opline)) = zend_hash_func(Z_STRVAL(ZEND_OP2_LITERAL(tmp_opline)), Z_STRLEN(ZEND_OP2_LITERAL(tmp_opline))+1); + Z_HASH_P(&ZEND_OP2_LITERAL(tmp_opline)) = zend_hash_func(Z_STRVAL(ZEND_OP2_LITERAL(tmp_opline)), Z_STRLEN(ZEND_OP2_LITERAL(tmp_opline)) + 1); if (tmp_opline->opcode == ZEND_FETCH_R || - tmp_opline->opcode == ZEND_FETCH_W || - tmp_opline->opcode == ZEND_FETCH_RW || - tmp_opline->opcode == ZEND_FETCH_IS || - tmp_opline->opcode == ZEND_FETCH_UNSET || - tmp_opline->opcode == ZEND_FETCH_FUNC_ARG || - tmp_opline->opcode == ZEND_FETCH_CLASS || - tmp_opline->opcode == ZEND_INIT_FCALL_BY_NAME || - tmp_opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - tmp_opline->opcode == ZEND_UNSET_VAR || - tmp_opline->opcode == ZEND_ISSET_ISEMPTY_VAR || - tmp_opline->opcode == ZEND_ADD_INTERFACE || - tmp_opline->opcode == ZEND_ADD_TRAIT) { + tmp_opline->opcode == ZEND_FETCH_W || + tmp_opline->opcode == ZEND_FETCH_RW || + tmp_opline->opcode == ZEND_FETCH_IS || + tmp_opline->opcode == ZEND_FETCH_UNSET || + tmp_opline->opcode == ZEND_FETCH_FUNC_ARG || + tmp_opline->opcode == ZEND_FETCH_CLASS || + tmp_opline->opcode == ZEND_INIT_FCALL_BY_NAME || + tmp_opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + tmp_opline->opcode == ZEND_UNSET_VAR || + tmp_opline->opcode == ZEND_ISSET_ISEMPTY_VAR || + tmp_opline->opcode == ZEND_ADD_INTERFACE || + tmp_opline->opcode == ZEND_ADD_TRAIT) { op_array->literals[tmp_opline->op2.constant].cache_slot = op_array->last_cache_slot++; } else if (tmp_opline->opcode == ZEND_INIT_METHOD_CALL || - tmp_opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - tmp_opline->opcode == ZEND_FETCH_CONSTANT || - tmp_opline->opcode == ZEND_ASSIGN_OBJ || - tmp_opline->opcode == ZEND_FETCH_OBJ_R || - tmp_opline->opcode == ZEND_FETCH_OBJ_W || - tmp_opline->opcode == ZEND_FETCH_OBJ_RW || - tmp_opline->opcode == ZEND_FETCH_OBJ_IS || - tmp_opline->opcode == ZEND_FETCH_OBJ_UNSET || - tmp_opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG || - tmp_opline->opcode == ZEND_UNSET_OBJ || - tmp_opline->opcode == ZEND_PRE_INC_OBJ || - tmp_opline->opcode == ZEND_PRE_DEC_OBJ || - tmp_opline->opcode == ZEND_POST_INC_OBJ || - tmp_opline->opcode == ZEND_POST_DEC_OBJ || - tmp_opline->opcode == ZEND_ISSET_ISEMPTY_PROP_OBJ) { + tmp_opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + tmp_opline->opcode == ZEND_FETCH_CONSTANT || + tmp_opline->opcode == ZEND_ASSIGN_OBJ || + tmp_opline->opcode == ZEND_FETCH_OBJ_R || + tmp_opline->opcode == ZEND_FETCH_OBJ_W || + tmp_opline->opcode == ZEND_FETCH_OBJ_RW || + tmp_opline->opcode == ZEND_FETCH_OBJ_IS || + tmp_opline->opcode == ZEND_FETCH_OBJ_UNSET || + tmp_opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG || + tmp_opline->opcode == ZEND_UNSET_OBJ || + tmp_opline->opcode == ZEND_PRE_INC_OBJ || + tmp_opline->opcode == ZEND_PRE_DEC_OBJ || + tmp_opline->opcode == ZEND_POST_INC_OBJ || + tmp_opline->opcode == ZEND_POST_DEC_OBJ || + tmp_opline->opcode == ZEND_ISSET_ISEMPTY_PROP_OBJ) { op_array->literals[tmp_opline->op2.constant].cache_slot = op_array->last_cache_slot; op_array->last_cache_slot += 2; } else if (tmp_opline->opcode == ZEND_ASSIGN_ADD || - tmp_opline->opcode == ZEND_ASSIGN_SUB || - tmp_opline->opcode == ZEND_ASSIGN_MUL || - tmp_opline->opcode == ZEND_ASSIGN_DIV || - tmp_opline->opcode == ZEND_ASSIGN_MOD || - tmp_opline->opcode == ZEND_ASSIGN_SL || - tmp_opline->opcode == ZEND_ASSIGN_SR || - tmp_opline->opcode == ZEND_ASSIGN_CONCAT || - tmp_opline->opcode == ZEND_ASSIGN_BW_OR || - tmp_opline->opcode == ZEND_ASSIGN_BW_AND || - tmp_opline->opcode == ZEND_ASSIGN_BW_XOR) { + tmp_opline->opcode == ZEND_ASSIGN_SUB || + tmp_opline->opcode == ZEND_ASSIGN_MUL || + tmp_opline->opcode == ZEND_ASSIGN_DIV || + tmp_opline->opcode == ZEND_ASSIGN_MOD || + tmp_opline->opcode == ZEND_ASSIGN_SL || + tmp_opline->opcode == ZEND_ASSIGN_SR || + tmp_opline->opcode == ZEND_ASSIGN_CONCAT || + tmp_opline->opcode == ZEND_ASSIGN_BW_OR || + tmp_opline->opcode == ZEND_ASSIGN_BW_AND || + tmp_opline->opcode == ZEND_ASSIGN_BW_XOR) { if (tmp_opline->extended_value == ZEND_ASSIGN_OBJ) { op_array->literals[tmp_opline->op2.constant].cache_slot = op_array->last_cache_slot; op_array->last_cache_slot += 2; @@ -154,7 +154,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { break; case ZEND_CAST: - if (ZEND_OP1_TYPE(opline)==IS_CONST && + if (ZEND_OP1_TYPE(opline) == IS_CONST && opline->extended_value != IS_ARRAY && opline->extended_value != IS_OBJECT && opline->extended_value != IS_RESOURCE) { @@ -193,7 +193,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { case ZEND_BW_NOT: case ZEND_BOOL_NOT: - if (ZEND_OP1_TYPE(opline)==IS_CONST) { + if (ZEND_OP1_TYPE(opline) == IS_CONST) { /* unary operation on constant operand */ unary_op_type unary_op = get_unary_op(opline->opcode); zval result; @@ -215,10 +215,10 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { MAKE_NOP(opline); /* substitute the following TMP_VAR usage with constant */ - for (tmp_opline=opline+1; tmp_oplineopcode==ZEND_FREE) { + for (tmp_opline = opline + 1; tmp_opline < end; tmp_opline++) { + if (ZEND_OP1_TYPE(tmp_opline) == IS_TMP_VAR && + ZEND_OP1(tmp_opline).var == tv) { + if (tmp_opline->opcode == ZEND_FREE) { MAKE_NOP(tmp_opline); zval_dtor(&result); } else { @@ -231,8 +231,8 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { } break; } - if (ZEND_OP2_TYPE(tmp_opline)== IS_TMP_VAR - && ZEND_OP2(tmp_opline).var == tv) { + if (ZEND_OP2_TYPE(tmp_opline) == IS_TMP_VAR && + ZEND_OP2(tmp_opline).var == tv) { ZEND_OP2_TYPE(tmp_opline) = IS_CONST; #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO tmp_opline->op2.constant = zend_add_literal(op_array, &result TSRMLS_CC); @@ -248,15 +248,15 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { case ZEND_ADD_STRING: case ZEND_ADD_CHAR: { - zend_op *next_op = opline+1; - int requires_conversion = (opline->opcode==ZEND_ADD_CHAR?1:0); + zend_op *next_op = opline + 1; + int requires_conversion = (opline->opcode == ZEND_ADD_CHAR? 1 : 0); size_t final_length = 0; char *ptr; zend_op *last_op; /* There is always a ZEND_RETURN at the end if (next_op>=end) { - break; + break; } */ while (next_op->opcode == ZEND_ADD_STRING || next_op->opcode == ZEND_ADD_CHAR) { @@ -275,7 +275,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { } last_op = next_op; final_length += (requires_conversion ? 1 : ZEND_OP2_LITERAL(opline).value.str.len); - ptr = (char *) emalloc(final_length+1); + ptr = (char *)emalloc(final_length+1); ptr[final_length] = '\0'; if (requires_conversion) { /* ZEND_ADD_CHAR */ char chval = (char)ZEND_OP2_LITERAL(opline).value.lval; @@ -294,7 +294,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { ptr += Z_STRLEN(ZEND_OP2_LITERAL(opline)); } ZEND_OP2_LITERAL(opline).value.str.len = final_length; - next_op = opline+1; + next_op = opline + 1; while (next_op < last_op) { if (next_op->opcode == ZEND_ADD_STRING) { memcpy(ptr, ZEND_OP2_LITERAL(next_op).value.str.val, ZEND_OP2_LITERAL(next_op).value.str.len); @@ -310,8 +310,8 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { if (!((ZEND_OPTIMIZER_PASS_5|ZEND_OPTIMIZER_PASS_10) & OPTIMIZATION_LEVEL)) { /* NOP removel is disabled => insert JMP over NOPs */ if (last_op-opline >= 3) { /* If we have more than 2 NOPS then JMP over them */ - (opline+1)->opcode = ZEND_JMP; - ZEND_OP1(opline+1).opline_num = last_op - op_array->opcodes; /* that's OK even for ZE2, since opline_num's are resolved in pass 2 later */ + (opline + 1)->opcode = ZEND_JMP; + ZEND_OP1(opline + 1).opline_num = last_op - op_array->opcodes; /* that's OK even for ZE2, since opline_num's are resolved in pass 2 later */ } } } @@ -319,11 +319,11 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { case ZEND_FETCH_CONSTANT: if (ZEND_OP1_TYPE(opline) == IS_UNUSED && - ZEND_OP2_TYPE(opline) == IS_CONST && - Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING && - Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("__COMPILER_HALT_OFFSET__")-1 && - memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1) == 0) { - /* substitute __COMPILER_HALT_OFFSET__ constant */ + ZEND_OP2_TYPE(opline) == IS_CONST && + Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING && + Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("__COMPILER_HALT_OFFSET__")-1 && + memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1) == 0) { + /* substitute __COMPILER_HALT_OFFSET__ constant */ zend_bool orig_in_execution = EG(in_execution); zend_op_array *orig_op_array = EG(active_op_array); zval offset; @@ -347,12 +347,12 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { } if (ZEND_OP1_TYPE(opline) == IS_UNUSED && - ZEND_OP2_TYPE(opline) == IS_CONST && - ZEND_OP2_LITERAL(opline).type == IS_STRING) { - /* substitute persistent constants */ + ZEND_OP2_TYPE(opline) == IS_CONST && + ZEND_OP2_LITERAL(opline).type == IS_STRING) { + /* substitute persistent constants */ zval c; - if(zend_get_persistent_constant(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), &c, 1 TSRMLS_CC) == 0) { + 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)); @@ -368,17 +368,17 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { break; case ZEND_INIT_FCALL_BY_NAME: - if(opline->extended_value == 0 /* not method */ && - ZEND_OP1_TYPE(opline) == IS_UNUSED && - ZEND_OP2_TYPE(opline) == IS_CONST) { - if((opline+1)->opcode == ZEND_DO_FCALL_BY_NAME && - (opline+1)->extended_value == 0) { - (opline+1)->opcode = ZEND_DO_FCALL; - COPY_NODE((opline+1)->op1, opline->op2); - zend_str_tolower(Z_STRVAL(ZEND_OP1_LITERAL(opline+1)), Z_STRLEN(ZEND_OP1_LITERAL(opline+1))); + if (opline->extended_value == 0 /* not method */ && + ZEND_OP1_TYPE(opline) == IS_UNUSED && + ZEND_OP2_TYPE(opline) == IS_CONST) { + if ((opline + 1)->opcode == ZEND_DO_FCALL_BY_NAME && + (opline + 1)->extended_value == 0) { + (opline + 1)->opcode = ZEND_DO_FCALL; + COPY_NODE((opline + 1)->op1, opline->op2); + zend_str_tolower(Z_STRVAL(ZEND_OP1_LITERAL(opline + 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline + 1))); #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO - Z_HASH_P(&ZEND_OP1_LITERAL(opline+1)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline+1)), Z_STRLEN(ZEND_OP1_LITERAL(opline+1))+1); - op_array->literals[(opline+1)->op1.constant].cache_slot = op_array->last_cache_slot++; + Z_HASH_P(&ZEND_OP1_LITERAL(opline + 1)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline + 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)) + 1); + op_array->literals[(opline + 1)->op1.constant].cache_slot = op_array->last_cache_slot++; #endif MAKE_NOP(opline); } diff --git a/Optimizer/pass2.c b/Optimizer/pass2.c index b600e6b40b0..da56dcfa52d 100644 --- a/Optimizer/pass2.c +++ b/Optimizer/pass2.c @@ -6,10 +6,10 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) { zend_op *opline; - zend_op *end = op_array->opcodes+op_array->last; + zend_op *end = op_array->opcodes + op_array->last; opline = op_array->opcodes; - while (oplineopcode) { case ZEND_ADD: case ZEND_SUB: @@ -25,7 +25,7 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) { case ZEND_ASSIGN_SUB: case ZEND_ASSIGN_MUL: case ZEND_ASSIGN_DIV: - if(opline->extended_value != 0) { + if (opline->extended_value != 0) { /* object tristate op - don't attempt to optimize it! */ break; } @@ -48,7 +48,7 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) { case ZEND_ASSIGN_MOD: case ZEND_ASSIGN_SL: case ZEND_ASSIGN_SR: - if(opline->extended_value != 0) { + if (opline->extended_value != 0) { /* object tristate op - don't attempt to optimize it! */ break; } @@ -58,7 +58,7 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) { } } break; - + case ZEND_CONCAT: if (ZEND_OP1_TYPE(opline) == IS_CONST) { if (ZEND_OP1_LITERAL(opline).type != IS_STRING) { @@ -67,7 +67,7 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) { } /* break missing *intentionally - the assign_op's may only optimize op2 */ case ZEND_ASSIGN_CONCAT: - if(opline->extended_value != 0) { + if (opline->extended_value != 0) { /* object tristate op - don't attempt to optimize it! */ break; } @@ -77,7 +77,7 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) { } } break; - + case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: /* convert Ti = JMPZ_EX(Ti, L) to JMPZ(Ti, L) */ @@ -118,18 +118,18 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) { } break; } - if ((opline+1)->opcode == ZEND_JMP) { + if ((opline + 1)->opcode == ZEND_JMP) { /* JMPZ(X, L1), JMP(L2) => JMPZNZ(X, L1, L2) */ /* JMPNZ(X, L1), JMP(L2) => JMPZNZ(X, L2, L1) */ - if (ZEND_OP2(opline).opline_num == ZEND_OP1(opline+1).opline_num) { + if (ZEND_OP2(opline).opline_num == ZEND_OP1(opline + 1).opline_num) { /* JMPZ(X, L1), JMP(L1) => NOP, JMP(L1) */ MAKE_NOP(opline); } else { if (opline->opcode == ZEND_JMPZ) { - opline->extended_value = ZEND_OP1(opline+1).opline_num; + opline->extended_value = ZEND_OP1(opline + 1).opline_num; } else { opline->extended_value = ZEND_OP2(opline).opline_num; - COPY_NODE(opline->op2, (opline+1)->op1); + COPY_NODE(opline->op2, (opline + 1)->op1); } opline->opcode = ZEND_JMPZNZ; } @@ -151,14 +151,14 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) { opline->opcode = ZEND_JMP; } break; - + case ZEND_BRK: case ZEND_CONT: { zend_brk_cont_element *jmp_to; int array_offset; int nest_levels; - int dont_optimize=0; + int dont_optimize = 0; if (ZEND_OP2_TYPE(opline) != IS_CONST) { break; @@ -168,8 +168,8 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) { array_offset = ZEND_OP1(opline).opline_num; while (1) { - if (array_offset==-1) { - dont_optimize=1; /* don't optimize this bogus break/continue, let the executor shout */ + if (array_offset == -1) { + dont_optimize = 1; /* don't optimize this bogus break/continue, let the executor shout */ break; } jmp_to = &op_array->brk_cont_array[array_offset]; @@ -178,7 +178,7 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) { if (opline->opcode == ZEND_BRK && (op_array->opcodes[jmp_to->brk].opcode == ZEND_FREE || op_array->opcodes[jmp_to->brk].opcode == ZEND_SWITCH_FREE)) { - dont_optimize=1; + dont_optimize = 1; break; } } else { @@ -189,7 +189,7 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) { if (dont_optimize) { break; } - + /* optimize - convert to a JMP */ switch (opline->opcode) { case ZEND_BRK: diff --git a/Optimizer/pass3.c b/Optimizer/pass3.c index 95a6aad9bff..269f523e981 100644 --- a/Optimizer/pass3.c +++ b/Optimizer/pass3.c @@ -24,7 +24,7 @@ } \ jmp_hitlist[jmp_hitlist_count++] = ZEND_OP2(&op_array->opcodes[target]).opline_num; -if(ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) { +if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) { zend_op *opline; zend_op *end = op_array->opcodes+op_array->last; zend_uint *jmp_hitlist; @@ -33,10 +33,10 @@ if(ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) { zend_uint opline_num = 0; ALLOCA_FLAG(use_heap); - jmp_hitlist = (zend_uint *) DO_ALLOCA(sizeof(zend_uint)*op_array->last); + jmp_hitlist = (zend_uint *)DO_ALLOCA(sizeof(zend_uint)*op_array->last); opline = op_array->opcodes; - while (oplineopcode) { @@ -52,7 +52,7 @@ if(ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) { case ZEND_BW_AND: case ZEND_BW_XOR: { - zend_op *next_opline = opline+1; + zend_op *next_opline = opline + 1; while (next_opline < end && next_opline->opcode == ZEND_NOP) { ++next_opline; @@ -62,7 +62,7 @@ if(ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) { break; } - if ((ZEND_OP2_TYPE(opline)==IS_VAR || ZEND_OP2_TYPE(opline)==IS_CV) + if ((ZEND_OP2_TYPE(opline) == IS_VAR || ZEND_OP2_TYPE(opline) == IS_CV) && ZEND_OP2(opline).var == ZEND_OP1(next_opline).var && (opline->opcode == ZEND_ADD || opline->opcode == ZEND_MUL || @@ -73,19 +73,19 @@ if(ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) { * optimization works on it */ #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO - zend_uchar tmp_type=opline->op1_type; - znode_op tmp=opline->op1; + zend_uchar tmp_type = opline->op1_type; + znode_op tmp = opline->op1; #else - znode tmp=opline->op1; + znode tmp = opline->op1; #endif - if(opline->opcode != ZEND_ADD || ZEND_OP1_TYPE(opline) == IS_CONST) { + if (opline->opcode != ZEND_ADD || ZEND_OP1_TYPE(opline) == IS_CONST) { /* protection from array add: $a = array + $a is not commutative! */ COPY_NODE(opline->op1, opline->op2); COPY_NODE(opline->op2, tmp); } } - if ((ZEND_OP1_TYPE(opline)==IS_VAR || ZEND_OP1_TYPE(opline)==IS_CV) + if ((ZEND_OP1_TYPE(opline) == IS_VAR || ZEND_OP1_TYPE(opline) == IS_CV) && ZEND_OP1(opline).var == ZEND_OP1(next_opline).var && ZEND_OP1_TYPE(opline) == ZEND_OP1_TYPE(next_opline)) { switch (opline->opcode) { @@ -139,13 +139,13 @@ if(ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) { #endif /* convert L: JMP L+1 to NOP */ - if(ZEND_OP1(opline).opline_num == opline_num + 1) { + if (ZEND_OP1(opline).opline_num == opline_num + 1) { MAKE_NOP(opline); goto done_jmp_optimization; } /* convert JMP L1 ... L1: JMP L2 to JMP L2 .. L1: JMP L2 */ - while (ZEND_OP1(opline).opline_numlast + while (ZEND_OP1(opline).opline_num < op_array->last && op_array->opcodes[ZEND_OP1(opline).opline_num].opcode == ZEND_JMP) { int target = ZEND_OP1(opline).opline_num; CHECK_JMP(target, done_jmp_optimization); @@ -165,7 +165,7 @@ if(ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) { } #endif - while (ZEND_OP2(opline).opline_numlast) { + while (ZEND_OP2(opline).opline_num < op_array->last) { int target = ZEND_OP2(opline).opline_num; if (op_array->opcodes[target].opcode == ZEND_JMP) { ZEND_OP2(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num; @@ -185,24 +185,24 @@ if(ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) { #endif /* convert L: JMPZ L+1 to NOP */ - if(ZEND_OP2(opline).opline_num == opline_num + 1) { + if (ZEND_OP2(opline).opline_num == opline_num + 1) { MAKE_NOP(opline); goto done_jmp_optimization; } - while (ZEND_OP2(opline).opline_numlast) { + while (ZEND_OP2(opline).opline_num < op_array->last) { int target = ZEND_OP2(opline).opline_num; if (op_array->opcodes[target].opcode == ZEND_JMP) { /* plain JMP */ /* JMPZ(X,L1), L1: JMP(L2) => JMPZ(X,L2), L1: JMP(L2) */ - CHECK_JMP(target, done_jmp_optimization); + CHECK_JMP(target, done_jmp_optimization); ZEND_OP2(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num; } else if (op_array->opcodes[target].opcode == opline->opcode && SAME_VAR(opline->op1, op_array->opcodes[target].op1)) { /* same opcode and same var as this opcode */ /* JMPZ(X,L1), L1: JMPZ(X,L2) => JMPZ(X,L2), L1: JMPZ(X,L2) */ - CHECK_JMP2(target, done_jmp_optimization); + CHECK_JMP2(target, done_jmp_optimization); ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num; } else if (op_array->opcodes[target].opcode == opline->opcode+3 && SAME_VAR(opline->op1, op_array->opcodes[target].op1)) { @@ -246,8 +246,8 @@ if(ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) { #endif /* convert L: T = JMPZ_EX X,L+1 to T = BOOL(X) */ /* convert L: T = JMPZ_EX T,L+1 to NOP */ - if(ZEND_OP2(opline).opline_num == opline_num + 1) { - if(ZEND_OP1(opline).var == ZEND_RESULT(opline).var) { + if (ZEND_OP2(opline).opline_num == opline_num + 1) { + if (ZEND_OP1(opline).var == ZEND_RESULT(opline).var) { MAKE_NOP(opline); } else { opline->opcode = ZEND_BOOL; @@ -256,33 +256,32 @@ if(ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) { goto done_jmp_optimization; } - while (ZEND_OP2(opline).opline_numlast) { + while (ZEND_OP2(opline).opline_num < op_array->last) { int target = ZEND_OP2(opline).opline_num; - if(SAME_OPCODE_EX(opline->opcode, op_array->opcodes[target].opcode) && - SAME_VAR(op_array->opcodes[target].op1, T)) { + if (SAME_OPCODE_EX(opline->opcode, op_array->opcodes[target].opcode) && + SAME_VAR(op_array->opcodes[target].op1, T)) { /* Check for JMPZ_EX to JMPZ[_EX] with the same condition, either with _EX or not */ - if(op_array->opcodes[target].opcode == opline->opcode) { + if (op_array->opcodes[target].opcode == opline->opcode) { /* change T only if we have _EX opcode there */ COPY_NODE(T, op_array->opcodes[target].result); } CHECK_JMP2(target, continue_jmp_ex_optimization); ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num; - } else if(op_array->opcodes[target].opcode == ZEND_JMPZNZ && + } else if (op_array->opcodes[target].opcode == ZEND_JMPZNZ && SAME_VAR(op_array->opcodes[target].op1, T)) { /* Check for JMPZNZ with same cond variable */ int new_target; CHECK_JMP2(target, continue_jmp_ex_optimization); - if(opline->opcode == ZEND_JMPZ_EX) { + if (opline->opcode == ZEND_JMPZ_EX) { new_target = ZEND_OP2(&op_array->opcodes[target]).opline_num; } else { /* JMPNZ_EX */ new_target = op_array->opcodes[target].extended_value; } ZEND_OP2(opline).opline_num = new_target; - } else if((op_array->opcodes[target].opcode == INV_EX_COND_EX(opline->opcode) || - op_array->opcodes[target].opcode == INV_EX_COND(opline->opcode) - ) && - SAME_VAR(opline->op1, op_array->opcodes[target].op1)) { + } else if ((op_array->opcodes[target].opcode == INV_EX_COND_EX(opline->opcode) || + op_array->opcodes[target].opcode == INV_EX_COND(opline->opcode)) && + SAME_VAR(opline->op1, op_array->opcodes[target].op1)) { /* convert JMPZ_EX(X,L1), L1: JMPNZ_EX(X,L2) to JMPZ_EX(X,L1+1) */ ZEND_OP2(opline).opline_num = target+1; @@ -408,13 +407,13 @@ continue_jmpznz_optimization: case ZEND_POST_INC: case ZEND_POST_DEC: { /* POST_INC, FREE => PRE_INC */ - zend_op *next_op = opline+1; + zend_op *next_op = opline + 1; - if (next_op>=end) { + if (next_op >= end) { break; } - if (next_op->opcode == ZEND_FREE - && ZEND_OP1(next_op).var == ZEND_RESULT(opline).var) { + if (next_op->opcode == ZEND_FREE && + ZEND_OP1(next_op).var == ZEND_RESULT(opline).var) { MAKE_NOP(next_op); switch (opline->opcode) { case ZEND_POST_INC: diff --git a/ZendAccelerator.c b/ZendAccelerator.c index 2d84b37a30b..d3c3b14e9d8 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -322,7 +322,7 @@ const char *accel_new_interned_string(const char *arKey, int nKeyLength, int fre p = (Bucket *) ZCSG(interned_strings_top); ZCSG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength); - p->arKey = (char*)(p+1); + p->arKey = (char*)(p + 1); memcpy((char*)p->arKey, arKey, nKeyLength); p->nKeyLength = nKeyLength; p->h = h; @@ -383,7 +383,7 @@ static void accel_use_shm_interned_strings(TSRMLS_D) } if (ce->name) { - ce->name = accel_new_interned_string(ce->name, ce->name_length+1, 0 TSRMLS_CC); + ce->name = accel_new_interned_string(ce->name, ce->name_length + 1, 0 TSRMLS_CC); } q = ce->properties_info.pListHead; @@ -395,7 +395,7 @@ static void accel_use_shm_interned_strings(TSRMLS_D) } if (info->name) { - info->name = accel_new_interned_string(info->name, info->name_length+1, 0 TSRMLS_CC); + info->name = accel_new_interned_string(info->name, info->name_length + 1, 0 TSRMLS_CC); } q = q->pListNext; @@ -451,7 +451,7 @@ static inline void accel_restart_enter(TSRMLS_D) #else static const FLOCK_STRUCTURE(restart_in_progress, F_WRLCK, SEEK_SET, 2, 1); - if (fcntl(lock_file, F_SETLK, &restart_in_progress)==-1) { + if (fcntl(lock_file, F_SETLK, &restart_in_progress) == -1) { zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(+1): %s (%d)", strerror(errno), errno); } #endif @@ -467,7 +467,7 @@ static inline void accel_restart_leave(TSRMLS_D) static const FLOCK_STRUCTURE(restart_finished, F_UNLCK, SEEK_SET, 2, 1); ZCSG(restart_in_progress) = 0; - if (fcntl(lock_file, F_SETLK, &restart_finished)==-1) { + if (fcntl(lock_file, F_SETLK, &restart_finished) == -1) { zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(-1): %s (%d)", strerror(errno), errno); } #endif @@ -475,7 +475,7 @@ static inline void accel_restart_leave(TSRMLS_D) static inline int accel_restart_is_active(TSRMLS_D) { - if(ZCSG(restart_in_progress)) { + if (ZCSG(restart_in_progress)) { #ifndef ZEND_WIN32 FLOCK_STRUCTURE(restart_check, F_WRLCK, SEEK_SET, 2, 1); @@ -504,7 +504,7 @@ static inline void accel_activate_add(TSRMLS_D) #else static const FLOCK_STRUCTURE(mem_usage_lock, F_RDLCK, SEEK_SET, 1, 1); - if (fcntl(lock_file, F_SETLK, &mem_usage_lock)==-1) { + if (fcntl(lock_file, F_SETLK, &mem_usage_lock) == -1) { zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(+1): %s (%d)", strerror(errno), errno); } #endif @@ -521,7 +521,7 @@ static inline void accel_deactivate_sub(TSRMLS_D) #else static const FLOCK_STRUCTURE(mem_usage_unlock, F_UNLCK, SEEK_SET, 1, 1); - if (fcntl(lock_file, F_SETLK, &mem_usage_unlock)==-1) { + if (fcntl(lock_file, F_SETLK, &mem_usage_unlock) == -1) { zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(-1): %s (%d)", strerror(errno), errno); } #endif @@ -534,7 +534,7 @@ static inline void accel_unlock_all(TSRMLS_D) #else static const FLOCK_STRUCTURE(mem_usage_unlock_all, F_UNLCK, SEEK_SET, 0, 0); - if (fcntl(lock_file, F_SETLK, &mem_usage_unlock_all)==-1) { + if (fcntl(lock_file, F_SETLK, &mem_usage_unlock_all) == -1) { zend_accel_error(ACCEL_LOG_DEBUG, "UnlockAll: %s (%d)", strerror(errno), errno); } #endif @@ -603,7 +603,7 @@ static inline int accel_is_inactive(TSRMLS_D) if (ZCG(accel_directives).force_restart_timeout && ZCSG(force_restart_time) - && time(NULL)>=ZCSG(force_restart_time)) { + && time(NULL) >= ZCSG(force_restart_time)) { zend_accel_error(ACCEL_LOG_WARNING, "Forced restart at %d (after %d seconds), locked by %d", time(NULL), ZCG(accel_directives).force_restart_timeout, mem_usage_check.l_pid); kill_all_lockers(&mem_usage_check); @@ -620,22 +620,19 @@ static int zend_get_stream_timestamp(const char *filename, struct stat *statbuf php_stream_statbuf stream_statbuf; int ret, er; - if(!filename) { + if (!filename) { return FAILURE; } wrapper = php_stream_locate_url_wrapper(filename, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC); - if(!wrapper) { - + if (!wrapper) { return FAILURE; } - if(!wrapper->wops || !wrapper->wops->url_stat) { - + if (!wrapper->wops || !wrapper->wops->url_stat) { statbuf->st_mtime = 1; return SUCCESS; /* anything other than 0 is considered to be a valid timestamp */ } - er = EG(error_reporting); EG(error_reporting) = 0; zend_try { @@ -660,7 +657,7 @@ static accel_time_t zend_get_file_handle_timestamp_win(zend_file_handle *file_ha static FILETIME utc_base_ft; WIN32_FILE_ATTRIBUTE_DATA fdata; - if(!file_handle->opened_path) { + if (!file_handle->opened_path) { return 0; } @@ -679,7 +676,7 @@ static accel_time_t zend_get_file_handle_timestamp_win(zend_file_handle *file_ha utc_base = (((unsigned __int64)utc_base_ft.dwHighDateTime) << 32) + utc_base_ft.dwLowDateTime; } - if(GetFileAttributesEx(file_handle->opened_path, GetFileExInfoStandard, &fdata) != 0) { + if (GetFileAttributesEx(file_handle->opened_path, GetFileExInfoStandard, &fdata) != 0) { unsigned __int64 ftime; if (CompareFileTime (&fdata.ftLastWriteTime, &utc_base_ft) < 0) @@ -702,14 +699,14 @@ static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle accel_time_t res; res = zend_get_file_handle_timestamp_win(file_handle); - if(res) { + if (res) { return res; } #endif switch (file_handle->type) { case ZEND_HANDLE_FD: - if (fstat(file_handle->handle.fd, &statbuf)==-1) { + if (fstat(file_handle->handle.fd, &statbuf) == -1) { return 0; } break; @@ -727,13 +724,13 @@ static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle { char *file_path = file_handle->opened_path; - if(file_path) { + if (file_path) { if (is_stream_path(file_path)) { if (zend_get_stream_timestamp(file_path, &statbuf TSRMLS_CC) == SUCCESS) { break; } } - if (VCWD_STAT(file_path, &statbuf) !=-1) { + if (VCWD_STAT(file_path, &statbuf) != -1) { break; } } @@ -787,15 +784,15 @@ static inline int do_validate_timestamps(zend_persistent_script *persistent_scri * See bug #15140 */ if (file_handle->opened_path) { - if (strcmp(persistent_script->full_path,file_handle->opened_path)!=0) { + if (strcmp(persistent_script->full_path, file_handle->opened_path) != 0) { return FAILURE; } } else { - char actualpath [MAXPATHLEN+1]; + char actualpath [MAXPATHLEN + 1]; char *full_path_ptr; full_path_ptr = VCWD_REALPATH(file_handle->filename, actualpath); - if (full_path_ptr && strcmp(persistent_script->full_path,full_path_ptr)!=0) { + if (full_path_ptr && strcmp(persistent_script->full_path, full_path_ptr) != 0) { return FAILURE; } } @@ -831,7 +828,7 @@ static inline int validate_timestamp_and_record(zend_persistent_script *persiste if (ZCG(accel_directives).revalidate_freq && (persistent_script->dynamic_members.revalidate >= ZCSG(revalidate_at))) { return SUCCESS; - } else if (do_validate_timestamps(persistent_script, file_handle TSRMLS_CC)==FAILURE) { + } else if (do_validate_timestamps(persistent_script, file_handle TSRMLS_CC) == FAILURE) { return FAILURE; } else { persistent_script->dynamic_members.revalidate = ZCSG(revalidate_at); @@ -873,18 +870,18 @@ char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_lengt if (ZCG(accel_directives).use_cwd && !IS_ABSOLUTE_PATH(file_handle->filename, path_length) && !is_stream_path(file_handle->filename)) { - char *include_path=NULL; - int include_path_len=0; + char *include_path = NULL; + int include_path_len = 0; const char *parent_script = NULL; - int parent_script_len=0; - int cur_len=0; + int parent_script_len = 0; + int cur_len = 0; int cwd_len; char *cwd; if ((cwd = accel_getcwd(&cwd_len TSRMLS_CC)) == NULL) { /* we don't handle this well for now. */ zend_accel_error(ACCEL_LOG_INFO, "getcwd() failed for '%s' (%d), please try to set zend_optimizerplus.use_cwd to 0 in ini file", file_handle->filename, errno); - if(file_handle->opened_path) { + if (file_handle->opened_path) { cwd = file_handle->opened_path; cwd_len = strlen(cwd); } else { @@ -943,9 +940,9 @@ char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_lengt } /* Calculate key length */ - key_length = cwd_len+path_length+include_path_len+2; + key_length = cwd_len + path_length+include_path_len + 2; if (parent_script_len) { - key_length += parent_script_len+1; + key_length += parent_script_len + 1; } /* Generate key @@ -960,19 +957,19 @@ char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_lengt memcpy(ZCG(key), cwd, cwd_len); ZCG(key)[cwd_len] = ':'; - memcpy(ZCG(key)+cwd_len+1, file_handle->filename, path_length); + memcpy(ZCG(key) + cwd_len + 1, file_handle->filename, path_length); - ZCG(key)[cwd_len+1+path_length] = ':'; + ZCG(key)[cwd_len + 1 + path_length] = ':'; - cur_len = cwd_len+1+path_length+1; + cur_len = cwd_len + 1 + path_length + 1; if (parent_script_len) { - memcpy(ZCG(key)+cur_len, parent_script, parent_script_len); + memcpy(ZCG(key) + cur_len, parent_script, parent_script_len); cur_len += parent_script_len; ZCG(key)[cur_len] = ':'; cur_len++; } - memcpy(ZCG(key)+cur_len, include_path, include_path_len); + memcpy(ZCG(key) + cur_len, include_path, include_path_len); ZCG(key)[key_length] = '\0'; } else { /* not use_cwd */ @@ -981,7 +978,7 @@ char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_lengt ZCG(key_len) = 0; return NULL; } - memcpy(ZCG(key), file_handle->filename, key_length+1); + memcpy(ZCG(key), file_handle->filename, key_length + 1); } *key_len = ZCG(key_len) = key_length; @@ -996,17 +993,17 @@ static inline char *accel_make_persistent_key(zend_file_handle *file_handle, int /* Adds another key for existing cached script */ static void zend_accel_add_key(char *key, unsigned int key_length, zend_accel_hash_entry *bucket TSRMLS_DC) { - if (!zend_accel_hash_find(&ZCSG(hash), key, key_length+1)) { + if (!zend_accel_hash_find(&ZCSG(hash), key, key_length + 1)) { if (zend_accel_hash_is_full(&ZCSG(hash))) { - zend_accel_error(ACCEL_LOG_DEBUG,"No more entries in hash table!"); + zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!"); ZSMMG(memory_exhausted) = 1; } else { - char *new_key = zend_shared_alloc(key_length+1); + char *new_key = zend_shared_alloc(key_length + 1); if (new_key) { - memcpy(new_key, key, key_length+1); - zend_accel_hash_update(&ZCSG(hash), new_key, key_length+1, 1, bucket); + memcpy(new_key, key, key_length + 1); + zend_accel_hash_update(&ZCSG(hash), new_key, key_length + 1, 1, bucket); } else { - zend_accel_error(ACCEL_LOG_DEBUG,"No more memory!"); + zend_accel_error(ACCEL_LOG_DEBUG, "No more memory!"); ZSMMG(memory_exhausted) = 1; } } @@ -1019,7 +1016,7 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr uint memory_used; /* Check if script may be stored in shared memory */ - if(!zend_accel_script_persistable(new_persistent_script)) { + if (!zend_accel_script_persistable(new_persistent_script)) { return new_persistent_script; } @@ -1027,7 +1024,7 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr zend_shared_alloc_lock(TSRMLS_C); if (zend_accel_hash_is_full(&ZCSG(hash))) { - zend_accel_error(ACCEL_LOG_DEBUG,"No more entries in hash table!"); + zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!"); ZSMMG(memory_exhausted) = 1; zend_accel_schedule_restart_if_necessary(TSRMLS_C); zend_shared_alloc_unlock(TSRMLS_C); @@ -1037,7 +1034,7 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr /* Check if we still need to put the file into the cache (may be it was * already stored by another process. This final check is done under * exclusive lock) */ - bucket = zend_accel_hash_find_entry(&ZCSG(hash), new_persistent_script->full_path, new_persistent_script->full_path_len+1); + bucket = zend_accel_hash_find_entry(&ZCSG(hash), new_persistent_script->full_path, new_persistent_script->full_path_len + 1); if (bucket) { zend_persistent_script *existing_persistent_script = (zend_persistent_script *)bucket->data; @@ -1087,13 +1084,13 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr new_persistent_script->dynamic_members.checksum = zend_accel_script_checksum(new_persistent_script); /* store script structure in the hash table */ - bucket = zend_accel_hash_update(&ZCSG(hash), new_persistent_script->full_path, new_persistent_script->full_path_len+1, 0, new_persistent_script); + bucket = zend_accel_hash_update(&ZCSG(hash), new_persistent_script->full_path, new_persistent_script->full_path_len + 1, 0, new_persistent_script); if (bucket && (new_persistent_script->full_path_len != key_length || memcmp(new_persistent_script->full_path, key, key_length) != 0)) { /* link key to the same persistent script in hash table */ - if (!zend_accel_hash_update(&ZCSG(hash), key, key_length+1, 1, bucket)) { - zend_accel_error(ACCEL_LOG_DEBUG,"No more entries in hash table!"); + if (!zend_accel_hash_update(&ZCSG(hash), key, key_length + 1, 1, bucket)) { + zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!"); ZSMMG(memory_exhausted) = 1; } } @@ -1169,7 +1166,7 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han } } else { *op_array_p = NULL; - if (type==ZEND_REQUIRE) { + if (type == ZEND_REQUIRE) { zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC); zend_bailout(); } else { @@ -1229,7 +1226,7 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han /* compilation failed */ free_persistent_script(new_persistent_script, 1); zend_accel_free_user_functions(&ZCG(function_table) TSRMLS_CC); - if(do_bailout) { + if (do_bailout) { zend_bailout(); } return NULL; @@ -1338,7 +1335,7 @@ static zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int if ((key = accel_make_persistent_key(file_handle, &key_length TSRMLS_CC)) == NULL) { return accelerator_orig_compile_file(file_handle, type TSRMLS_CC); } - persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length+1); + persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length + 1); if (!persistent_script) { /* try to find cached script by full real path */ zend_accel_hash_entry *bucket; @@ -1350,7 +1347,7 @@ static zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int #else zend_stream_open(file_handle->filename, file_handle TSRMLS_CC) == FAILURE) { #endif - if (type==ZEND_REQUIRE) { + if (type == ZEND_REQUIRE) { zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC); zend_bailout(); } else { @@ -1360,7 +1357,7 @@ static zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int } if (file_handle->opened_path && - (bucket = zend_accel_hash_find_entry(&ZCSG(hash), file_handle->opened_path, strlen(file_handle->opened_path)+1)) != NULL) { + (bucket = zend_accel_hash_find_entry(&ZCSG(hash), file_handle->opened_path, strlen(file_handle->opened_path) + 1)) != NULL) { persistent_script = (zend_persistent_script *)bucket->data; if (!ZCG(accel_directives).revalidate_path && @@ -1387,7 +1384,7 @@ static zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int /* If script is found then validate_timestamps if option is enabled */ if (persistent_script && ZCG(accel_directives).validate_timestamps) { - if (validate_timestamp_and_record(persistent_script, file_handle TSRMLS_CC)==FAILURE) { + if (validate_timestamp_and_record(persistent_script, file_handle TSRMLS_CC) == FAILURE) { zend_shared_alloc_lock(TSRMLS_C); if (!persistent_script->corrupted) { persistent_script->corrupted = 1; @@ -1466,7 +1463,7 @@ static zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int #endif void *dummy = (void *) 1; - zend_hash_quick_add(&EG(included_files), persistent_script->full_path, persistent_script->full_path_len+1, persistent_script->hash_value, &dummy, sizeof(void *), NULL); + zend_hash_quick_add(&EG(included_files), persistent_script->full_path, persistent_script->full_path_len + 1, persistent_script->hash_value, &dummy, sizeof(void *), NULL); } } zend_file_handle_dtor(file_handle TSRMLS_CC); @@ -1533,8 +1530,8 @@ static char *accel_tsrm_realpath(const char *path, int path_len TSRMLS_DC) return NULL; } - real_path = emalloc(new_state.cwd_length+1); - memcpy(real_path, new_state.cwd, new_state.cwd_length+1); + real_path = emalloc(new_state.cwd_length + 1); + memcpy(real_path, new_state.cwd, new_state.cwd_length + 1); free(new_state.cwd); return real_path; } @@ -1560,7 +1557,7 @@ static char *accel_php_resolve_path(const char *filename, int filename_length, c ptr = path; while (*ptr) { for (end = ptr; *end && *end != DEFAULT_DIR_SEPARATOR; end++); - len = end-ptr; + len = end - ptr; if (*end) end++; if (len + 1 + filename_length + 1 >= MAXPATHLEN) { ptr = end; @@ -1568,9 +1565,9 @@ static char *accel_php_resolve_path(const char *filename, int filename_length, c } memcpy(trypath, ptr, len); trypath[len] = '/'; - memcpy(trypath+len+1, filename, filename_length+1); + memcpy(trypath + len + 1, filename, filename_length + 1); ptr = end; - if ((resolved_path = accel_tsrm_realpath(trypath, len+1+filename_length TSRMLS_CC)) != NULL) { + if ((resolved_path = accel_tsrm_realpath(trypath, len + 1 + filename_length TSRMLS_CC)) != NULL) { return resolved_path; } } /* end provided path */ @@ -1586,8 +1583,8 @@ static char *accel_php_resolve_path(const char *filename, int filename_length, c exec_fname_length > 0 && exec_fname_length + 1 + filename_length + 1 < MAXPATHLEN) { memcpy(trypath, exec_fname, exec_fname_length + 1); - memcpy(trypath+exec_fname_length + 1, filename, filename_length+1); - return accel_tsrm_realpath(trypath, exec_fname_length+1+filename_length TSRMLS_CC); + memcpy(trypath + exec_fname_length + 1, filename, filename_length + 1); + return accel_tsrm_realpath(trypath, exec_fname_length + 1 + filename_length TSRMLS_CC); } } @@ -1627,12 +1624,12 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl /* Check if requestd file already cached (by full name) */ if (IS_ABSOLUTE_PATH(filename, filename_len) && - (persistent_script = zend_accel_hash_find(&ZCSG(hash), (char*)filename, filename_len+1)) != NULL && + (persistent_script = zend_accel_hash_find(&ZCSG(hash), (char*)filename, filename_len + 1)) != NULL && !persistent_script->corrupted) { handle->opened_path = estrndup(persistent_script->full_path, persistent_script->full_path_len); handle->type = ZEND_HANDLE_FILENAME; - memcpy(ZCG(key), persistent_script->full_path, persistent_script->full_path_len+1); + memcpy(ZCG(key), persistent_script->full_path, persistent_script->full_path_len + 1); ZCG(key_len) = persistent_script->full_path_len; ZCG(cache_opline) = opline; ZCG(cache_persistent_script) = persistent_script; @@ -1643,7 +1640,7 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl key = accel_make_persistent_key_ex(handle, filename_len, &key_length TSRMLS_CC); if (!ZCG(accel_directives).revalidate_path && key && - (persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length+1)) != NULL && + (persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length + 1)) != NULL && !persistent_script->corrupted) { handle->opened_path = estrndup(persistent_script->full_path, persistent_script->full_path_len); @@ -1658,7 +1655,7 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl /* Check if requestd file already cached (by real name) */ if (resolved_path && - (bucket = zend_accel_hash_find_entry(&ZCSG(hash), resolved_path, strlen(resolved_path)+1)) != NULL) { + (bucket = zend_accel_hash_find_entry(&ZCSG(hash), resolved_path, strlen(resolved_path) + 1)) != NULL) { persistent_script = (zend_persistent_script *)bucket->data; if (persistent_script && !persistent_script->corrupted) { @@ -1735,12 +1732,12 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl if ((IS_ABSOLUTE_PATH(filename, filename_len) || is_stream_path(filename)) && - (persistent_script = zend_accel_hash_find(&ZCSG(hash), (char*)filename, filename_len+1)) != NULL && + (persistent_script = zend_accel_hash_find(&ZCSG(hash), (char*)filename, filename_len + 1)) != NULL && !persistent_script->corrupted) { handle->opened_path = estrndup(persistent_script->full_path, persistent_script->full_path_len); handle->type = ZEND_HANDLE_FILENAME; - memcpy(ZCG(key), persistent_script->full_path, persistent_script->full_path_len+1); + memcpy(ZCG(key), persistent_script->full_path, persistent_script->full_path_len + 1); ZCG(key_len) = persistent_script->full_path_len; ZCG(cache_opline) = EG(opline_ptr) ? *EG(opline_ptr) : NULL; ZCG(cache_persistent_script) = EG(opline_ptr) ? persistent_script : NULL; @@ -1784,14 +1781,14 @@ static char* persistent_zend_resolve_path(const char *filename, int filename_len char *resolved_path; zend_accel_hash_entry *bucket; zend_persistent_script *persistent_script; - + /* Check if requestd file already cached (by full name) */ if ((IS_ABSOLUTE_PATH(filename, filename_len) || is_stream_path(filename)) && - (bucket = zend_accel_hash_find_entry(&ZCSG(hash), (char*)filename, filename_len+1)) != NULL) { + (bucket = zend_accel_hash_find_entry(&ZCSG(hash), (char*)filename, filename_len + 1)) != NULL) { persistent_script = (zend_persistent_script *)bucket->data; if (persistent_script && !persistent_script->corrupted) { - memcpy(ZCG(key), persistent_script->full_path, persistent_script->full_path_len+1); + memcpy(ZCG(key), persistent_script->full_path, persistent_script->full_path_len + 1); ZCG(key_len) = persistent_script->full_path_len; ZCG(cache_opline) = EG(opline_ptr) ? *EG(opline_ptr) : NULL; ZCG(cache_persistent_script) = persistent_script; @@ -1806,7 +1803,7 @@ static char* persistent_zend_resolve_path(const char *filename, int filename_len key = accel_make_persistent_key_ex(&handle, filename_len, &key_length TSRMLS_CC); if (!ZCG(accel_directives).revalidate_path && key && - (persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length+1)) != NULL && + (persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length + 1)) != NULL && !persistent_script->corrupted) { /* we have persistent script */ @@ -1820,7 +1817,7 @@ static char* persistent_zend_resolve_path(const char *filename, int filename_len /* Check if requestd file already cached (by real path) */ if (resolved_path && - (bucket = zend_accel_hash_find_entry(&ZCSG(hash), resolved_path, strlen(resolved_path)+1)) != NULL) { + (bucket = zend_accel_hash_find_entry(&ZCSG(hash), resolved_path, strlen(resolved_path) + 1)) != NULL) { persistent_script = (zend_persistent_script *)bucket->data; if (persistent_script && !persistent_script->corrupted) { @@ -1918,7 +1915,7 @@ static void accel_activate(void) } /* check if ZCG(function_table) wasn't somehow polluted on the way */ - if(ZCG(internal_functions_count) != zend_hash_num_elements(&ZCG(function_table))) { + if (ZCG(internal_functions_count) != zend_hash_num_elements(&ZCG(function_table))) { zend_accel_error(ACCEL_LOG_WARNING, "Internal functions count changed - was %d, now %d", ZCG(internal_functions_count), zend_hash_num_elements(&ZCG(function_table))); } @@ -1957,7 +1954,7 @@ static void accel_fast_zval_ptr_dtor(zval **zval_ptr) { zval *zvalue = *zval_ptr; - if (Z_DELREF_P(zvalue)==0) { + if (Z_DELREF_P(zvalue) == 0) { #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) { #else @@ -2184,13 +2181,13 @@ static inline int accel_find_sapi(TSRMLS_D) const char **sapi_name; if (sapi_module.name) { - for (sapi_name=supported_sapis; *sapi_name; sapi_name++) { - if (strcmp(sapi_module.name, *sapi_name)==0) { + for (sapi_name = supported_sapis; *sapi_name; sapi_name++) { + if (strcmp(sapi_module.name, *sapi_name) == 0) { return SUCCESS; } } if (ZCG(accel_directives).enable_cli && - strcmp(sapi_module.name, "cli")==0) { + strcmp(sapi_module.name, "cli") == 0) { return SUCCESS; } } @@ -2292,10 +2289,10 @@ static int accel_startup(zend_extension *extension) } /* no supported SAPI found - disable acceleration and stop initalization */ - if( accel_find_sapi(TSRMLS_C) == FAILURE ){ + if (accel_find_sapi(TSRMLS_C) == FAILURE) { accel_startup_ok = 0; if (!ZCG(accel_directives).enable_cli && - strcmp(sapi_module.name, "cli")==0) { + strcmp(sapi_module.name, "cli") == 0) { zps_startup_failure("Opcode Caching is disabled for CLI", NULL, accelerator_remove_cb TSRMLS_CC); } else { zps_startup_failure("Opcode Caching is only supported in Apache, ISAPI, FPM and FastCGI SAPIs", NULL, accelerator_remove_cb TSRMLS_CC); @@ -2315,7 +2312,7 @@ static int accel_startup(zend_extension *extension) break; case ALLOC_FAILURE: accel_startup_ok = 0; - zend_accel_error(ACCEL_LOG_FATAL,"Failure to initialize shared memory structures - probably not enough shared memory."); + zend_accel_error(ACCEL_LOG_FATAL, "Failure to initialize shared memory structures - probably not enough shared memory."); return SUCCESS; case SUCCESSFULLY_REATTACHED: accel_shared_globals = (zend_accel_shared_globals *) ZSMMG(app_shared_globals); @@ -2343,7 +2340,7 @@ static int accel_startup(zend_extension *extension) break; case FAILED_REATTACHED: accel_startup_ok = 0; - zend_accel_error(ACCEL_LOG_FATAL,"Failure to initialize shared memory structures - can not reattach to exiting shared memory."); + zend_accel_error(ACCEL_LOG_FATAL, "Failure to initialize shared memory structures - can not reattach to exiting shared memory."); return SUCCESS; break; } @@ -2366,7 +2363,7 @@ static int accel_startup(zend_extension *extension) zend_resolve_path = persistent_zend_resolve_path; #endif - if(ZCG(accel_directives).validate_timestamps) { + if (ZCG(accel_directives).validate_timestamps) { ZCSG(revalidate_at) = zend_accel_get_time() + ZCG(accel_directives).revalidate_freq; } @@ -2379,7 +2376,7 @@ static int accel_startup(zend_extension *extension) ZCG(cwd) = NULL; /* Override "include_path" modifier callback */ - if (zend_hash_find(EG(ini_directives), "include_path", sizeof("include_path"), (void **) &ini_entry)==SUCCESS) { + if (zend_hash_find(EG(ini_directives), "include_path", sizeof("include_path"), (void **) &ini_entry) == SUCCESS) { ZCG(include_path) = INI_STR("include_path"); ZCG(include_path_key) = NULL; if (ZCG(include_path) && *ZCG(include_path)) { @@ -2451,7 +2448,7 @@ static void accel_shutdown(zend_extension *extension) zend_shared_alloc_shutdown(); zend_compile_file = accelerator_orig_compile_file; - if (zend_hash_find(EG(ini_directives), "include_path", sizeof("include_path"), (void **) &ini_entry)==SUCCESS) { + if (zend_hash_find(EG(ini_directives), "include_path", sizeof("include_path"), (void **) &ini_entry) == SUCCESS) { ini_entry->on_modify = orig_include_path_on_modify; } @@ -2498,7 +2495,7 @@ void zend_accel_schedule_restart(TSRMLS_D) */ int accelerator_shm_read_lock(TSRMLS_D) { - if(ZCG(counted)) { + if (ZCG(counted)) { /* counted means we are holding read lock for SHM, so that nothing bad can happen */ return SUCCESS; } else { @@ -2506,7 +2503,7 @@ int accelerator_shm_read_lock(TSRMLS_D) or is in progress now */ accel_activate_add(TSRMLS_C); /* acquire usage lock */ /* Now if we weren't inside restart, restart would not begin until we remove usage lock */ - if(ZCSG(restart_in_progress)) { + if (ZCSG(restart_in_progress)) { /* we already were inside restart this means it's not safe to touch shm */ accel_deactivate_now(); /* drop usage lock */ return FAILURE; @@ -2518,7 +2515,7 @@ int accelerator_shm_read_lock(TSRMLS_D) /* must be called ONLY after SUCCESSFUL accelerator_shm_read_lock */ void accelerator_shm_read_unlock(TSRMLS_D) { - if(!ZCG(counted)) { + if (!ZCG(counted)) { /* counted is 0 - meaning we had to readlock manually, release readlock now */ accel_deactivate_now(); } diff --git a/shared_alloc_mmap.c b/shared_alloc_mmap.c index 2a389c072cb..a13d3730f0a 100644 --- a/shared_alloc_mmap.c +++ b/shared_alloc_mmap.c @@ -38,12 +38,12 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ zend_shared_segment *shared_segment; *shared_segments_count = 1; - *shared_segments_p = (zend_shared_segment **) calloc(1, sizeof(zend_shared_segment)+sizeof(void *)); + *shared_segments_p = (zend_shared_segment **) calloc(1, sizeof(zend_shared_segment) + sizeof(void *)); shared_segment = (zend_shared_segment *)((char *)(*shared_segments_p) + sizeof(void *)); (*shared_segments_p)[0] = shared_segment; shared_segment->p = mmap(0, requested_size, PROT_READ | PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); - if(shared_segment->p == MAP_FAILED) { + if (shared_segment->p == MAP_FAILED) { *error_in = "mmap"; return ALLOC_FAILURE; } diff --git a/shared_alloc_posix.c b/shared_alloc_posix.c index 75ea176f41d..06441e4e0fb 100644 --- a/shared_alloc_posix.c +++ b/shared_alloc_posix.c @@ -39,28 +39,28 @@ typedef struct { static int create_segments(size_t requested_size, zend_shared_segment_posix ***shared_segments_p, int *shared_segments_count, char **error_in) { zend_shared_segment_posix *shared_segment; - char shared_segment_name[sizeof("/ZendAccelerator.")+20]; + char shared_segment_name[sizeof("/ZendAccelerator.") + 20]; *shared_segments_count = 1; - *shared_segments_p = (zend_shared_segment_posix **) calloc(1, sizeof(zend_shared_segment_posix)+sizeof(void *)); + *shared_segments_p = (zend_shared_segment_posix **) calloc(1, sizeof(zend_shared_segment_posix) + sizeof(void *)); shared_segment = (zend_shared_segment_posix *)((char *)(*shared_segments_p) + sizeof(void *)); (*shared_segments_p)[0] = shared_segment; sprintf(shared_segment_name, "/ZendAccelerator.%d", getpid()); shared_segment->shm_fd = shm_open(shared_segment_name, O_RDWR|O_CREAT|O_TRUNC, 0600); - if(shared_segment->shm_fd == -1) { + if (shared_segment->shm_fd == -1) { *error_in = "shm_open"; return ALLOC_FAILURE; } - if(ftruncate(shared_segment->shm_fd, requested_size) != 0) { + if (ftruncate(shared_segment->shm_fd, requested_size) != 0) { *error_in = "ftruncate"; shm_unlink(shared_segment_name); return ALLOC_FAILURE; } shared_segment->common.p = mmap(0, requested_size, PROT_READ | PROT_WRITE, MAP_SHARED, shared_segment->shm_fd, 0); - if(shared_segment->common.p == MAP_FAILED) { + if (shared_segment->common.p == MAP_FAILED) { *error_in = "mmap"; shm_unlink(shared_segment_name); return ALLOC_FAILURE; diff --git a/shared_alloc_shm.c b/shared_alloc_shm.c index 9d0256e4de6..c9a31b07b40 100644 --- a/shared_alloc_shm.c +++ b/shared_alloc_shm.c @@ -54,8 +54,8 @@ typedef struct { static int create_segments(size_t requested_size, zend_shared_segment_shm ***shared_segments_p, int *shared_segments_count, char **error_in) { int i; - unsigned int allocate_size=0, remaining_bytes=requested_size, seg_allocate_size; - int first_segment_id=-1; + unsigned int allocate_size = 0, remaining_bytes = requested_size, seg_allocate_size; + int first_segment_id = -1; key_t first_segment_key = -1; struct shmid_ds sds; int shmget_flags; @@ -65,7 +65,7 @@ static int create_segments(size_t requested_size, zend_shared_segment_shm ***sha /* determine segment size we _really_ need: * no more than to include requested_size */ - while (requested_size*2 <= seg_allocate_size && seg_allocate_size > SEG_ALLOC_SIZE_MIN) { + while (requested_size * 2 <= seg_allocate_size && seg_allocate_size > SEG_ALLOC_SIZE_MIN) { seg_allocate_size >>= 1; } @@ -86,15 +86,15 @@ static int create_segments(size_t requested_size, zend_shared_segment_shm ***sha return ALLOC_FAILURE; } - *shared_segments_count = ((requested_size-1)/seg_allocate_size) + 1; - *shared_segments_p = (zend_shared_segment_shm **) calloc(1, (*shared_segments_count)*sizeof(zend_shared_segment_shm)+sizeof(void *)*(*shared_segments_count)); - shared_segments = (zend_shared_segment_shm *)((char *)(*shared_segments_p) + sizeof(void *)*(*shared_segments_count)); - for(i=0; i<*shared_segments_count; i++) { - (*shared_segments_p)[i] = shared_segments+i; + *shared_segments_count = ((requested_size - 1) / seg_allocate_size) + 1; + *shared_segments_p = (zend_shared_segment_shm **) calloc(1, (*shared_segments_count) * sizeof(zend_shared_segment_shm) + sizeof(void *) * (*shared_segments_count)); + shared_segments = (zend_shared_segment_shm *)((char *)(*shared_segments_p) + sizeof(void *) * (*shared_segments_count)); + for (i = 0; i < *shared_segments_count; i++) { + (*shared_segments_p)[i] = shared_segments + i; } remaining_bytes = requested_size; - for (i=0; i<*shared_segments_count; i++) { + for (i = 0; i < *shared_segments_count; i++) { allocate_size = MIN(remaining_bytes, seg_allocate_size); if (i != 0) { shared_segments[i].shm_id = shmget(IPC_PRIVATE, allocate_size, shmget_flags); @@ -102,7 +102,7 @@ static int create_segments(size_t requested_size, zend_shared_segment_shm ***sha shared_segments[i].shm_id = first_segment_id; } - if (shared_segments[i].shm_id==-1) { + if (shared_segments[i].shm_id == -1) { return ALLOC_FAILURE; } diff --git a/shared_alloc_win32.c b/shared_alloc_win32.c index f275c64336c..40f941d1c01 100644 --- a/shared_alloc_win32.c +++ b/shared_alloc_win32.c @@ -113,7 +113,7 @@ void zend_shared_alloc_lock_win32() { DWORD waitRes = WaitForSingleObject(memory_mutex, INFINITE); - if(waitRes == WAIT_FAILED) { + if (waitRes == WAIT_FAILED) { zend_accel_error(ACCEL_LOG_ERROR, "Cannot lock mutex"); } } @@ -132,13 +132,13 @@ static int zend_shared_alloc_reattach(size_t requested_size, char **error_in) MEMORY_BASIC_INFORMATION info; err = GetLastError(); - if(!fp) { + if (!fp) { zend_win_error_message(ACCEL_LOG_WARNING, mmap_base_file, err); zend_win_error_message(ACCEL_LOG_FATAL, "Unable to open base address file", err); *error_in="fopen"; return ALLOC_FAILURE; } - if(!fscanf(fp, "%p", &wanted_mapping_base)) { + if (!fscanf(fp, "%p", &wanted_mapping_base)) { err = GetLastError(); zend_win_error_message(ACCEL_LOG_FATAL, "Unable to read base address", err); *error_in="read mapping base"; @@ -159,7 +159,7 @@ static int zend_shared_alloc_reattach(size_t requested_size, char **error_in) mapping_base = MapViewOfFileEx(memfile, FILE_MAP_ALL_ACCESS, 0, 0, 0, wanted_mapping_base); err = GetLastError(); - if(mapping_base == NULL) { + if (mapping_base == NULL) { if (err == ERROR_INVALID_ADDRESS) { zend_win_error_message(ACCEL_LOG_FATAL, "Unable to reattach to base address", err); return ALLOC_FAILURE; @@ -200,9 +200,9 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ } else { return ret; } - } while(++map_retries < MAX_MAP_RETRIES); + } while (++map_retries < MAX_MAP_RETRIES); - if(map_retries == MAX_MAP_RETRIES) { + if (map_retries == MAX_MAP_RETRIES) { zend_win_error_message(ACCEL_LOG_FATAL, "Unable to open file mapping", err); *error_in = "OpenFileMapping"; return ALLOC_FAILURE; @@ -222,7 +222,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ memfile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, requested_size, create_name_with_username(ACCEL_FILEMAP_NAME)); err = GetLastError(); - if(memfile == NULL) { + if (memfile == NULL) { zend_win_error_message(ACCEL_LOG_FATAL, "Unable to create file mapping", err); *error_in = "CreateFileMapping"; return ALLOC_FAILURE; @@ -250,9 +250,9 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ GetSystemInfo(&si); /* Are we running Vista ? */ - if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion == 6 ) { + if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion == 6) { /* Assert that platform is 32 bit (for 64 bit we need to test a different set */ - if(si.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL) + if (si.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL) DebugBreak(); wanted_mapping_base = vista_mapping_base_set; @@ -273,13 +273,13 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ do { shared_segment->p = mapping_base = MapViewOfFileEx(memfile, FILE_MAP_ALL_ACCESS, 0, 0, 0, *wanted_mapping_base); - if(*wanted_mapping_base == NULL) /* Auto address (NULL) is the last option on the array */ + if (*wanted_mapping_base == NULL) /* Auto address (NULL) is the last option on the array */ break; wanted_mapping_base++; } while (!mapping_base); err = GetLastError(); - if(mapping_base == NULL) { + if (mapping_base == NULL) { zend_win_error_message(ACCEL_LOG_FATAL, "Unable to create view for file mapping", err); *error_in = "MapViewOfFile"; return ALLOC_FAILURE; @@ -287,7 +287,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ char *mmap_base_file = get_mmap_base_file(); FILE *fp = fopen(mmap_base_file, "w"); err = GetLastError(); - if(!fp) { + if (!fp) { zend_win_error_message(ACCEL_LOG_WARNING, mmap_base_file, err); zend_win_error_message(ACCEL_LOG_FATAL, "Unable to write base address", err); return ALLOC_FAILURE; @@ -304,7 +304,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ static int detach_segment(zend_shared_segment *shared_segment) { - if(mapping_base) { + if (mapping_base) { UnmapViewOfFile(mapping_base); } CloseHandle(memfile); diff --git a/zend_accelerator_blacklist.c b/zend_accelerator_blacklist.c index 666304becf0..f3fd91236eb 100644 --- a/zend_accelerator_blacklist.c +++ b/zend_accelerator_blacklist.c @@ -50,7 +50,7 @@ void zend_accel_blacklist_init(zend_blacklist *blacklist) blacklist->pos = 0; blacklist->size = ZEND_BLACKLIST_BLOCK_SIZE; - if( blacklist->entries != NULL ){ + if (blacklist->entries != NULL) { zend_accel_blacklist_shutdown(blacklist); } @@ -74,8 +74,8 @@ static void blacklist_report_regexp_error(regex_t *comp_regex, int reg_err) static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist) { - int i, end=0, j, rlen=6, clen, reg_err; char *regexp; + int i, j, clen, reg_err, end = 0, rlen = 6; zend_regexp_list **regexp_list_it, *it; if (blacklist->pos == 0) { @@ -84,11 +84,11 @@ static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist) } regexp_list_it = &(blacklist->regexp_list); - for (i=0; ipos; i++) { - rlen += blacklist->entries[i].path_length*2+2; + for (i = 0; i < blacklist->pos; i++) { + rlen += blacklist->entries[i].path_length * 2 + 2; /* don't create a regexp buffer bigger than 12K)*/ - if((i+1 == blacklist->pos) || ((rlen+blacklist->entries[i+1].path_length*2+2)>(12*1024) ) ) { + if ((i + 1 == blacklist->pos) || ((rlen + blacklist->entries[i + 1].path_length * 2 + 2) > (12 * 1024))) { regexp = (char *)malloc(rlen); if (!regexp) { zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n"); @@ -97,16 +97,16 @@ static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist) regexp[0] = '^'; regexp[1] = '('; - clen=2; - for (j=end; j<=i ;j++) { + clen = 2; + for (j = end; j <= i ;j++) { int c; - if (j!=end) { + if (j != end) { regexp[clen++] = '|'; } /* copy mangled filename */ - for(c=0; centries[j].path_length; c++) { - if(strchr("^.[]$()|*+?{}\\", blacklist->entries[j].path[c])) { + for (c = 0; c < blacklist->entries[j].path_length; c++) { + if (strchr("^.[]$()|*+?{}\\", blacklist->entries[j].path[c])) { regexp[clen++] = '\\'; } regexp[clen++] = blacklist->entries[j].path[c]; @@ -127,7 +127,7 @@ static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist) } /* prepare for the next iteration */ free(regexp); - end = i+1; + end = i + 1; rlen = 6; *regexp_list_it = it; regexp_list_it = &it->next; @@ -147,7 +147,7 @@ void zend_accel_blacklist_shutdown(zend_blacklist *blacklist) blacklist->entries = NULL; if (blacklist->regexp_list) { zend_regexp_list *temp, *it = blacklist->regexp_list; - while( it ){ + while (it) { regfree(&it->comp_regex); temp = it; it = it->next; @@ -158,7 +158,7 @@ void zend_accel_blacklist_shutdown(zend_blacklist *blacklist) static inline void zend_accel_blacklist_allocate(zend_blacklist *blacklist) { - if (blacklist->pos==blacklist->size) { + if (blacklist->pos == blacklist->size) { blacklist->size += ZEND_BLACKLIST_BLOCK_SIZE; blacklist->entries = (zend_blacklist_entry *) realloc(blacklist->entries, sizeof(zend_blacklist_entry)*blacklist->size); } @@ -166,12 +166,12 @@ static inline void zend_accel_blacklist_allocate(zend_blacklist *blacklist) void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename) { - char buf[MAXPATHLEN+1], real_path[MAXPATHLEN+1]; + char buf[MAXPATHLEN + 1], real_path[MAXPATHLEN + 1]; FILE *fp; int path_length; TSRMLS_FETCH(); - if ((fp=fopen(filename, "r"))==NULL) { + if ((fp = fopen(filename, "r")) == NULL) { zend_accel_error(ACCEL_LOG_WARNING, "Cannot load blacklist file: %s\n", filename); return; } @@ -181,30 +181,30 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename) memset(buf, 0, sizeof(buf)); memset(real_path, 0, sizeof(real_path)); - while (fgets(buf, MAXPATHLEN, fp)!=NULL) { + while (fgets(buf, MAXPATHLEN, fp) != NULL) { char *path_dup, *pbuf; path_length = strlen(buf); - if (path_length > 0 && buf[path_length-1]=='\n') { + if (path_length > 0 && buf[path_length - 1] == '\n') { buf[--path_length] = 0; - if (path_length > 0 && buf[path_length-1]=='\r') { + if (path_length > 0 && buf[path_length - 1] == '\r') { buf[--path_length] = 0; } } /* Strip ctrl-m prefix */ pbuf = &buf[0]; - while(*pbuf == '\r') { + while (*pbuf == '\r') { *pbuf++ = 0; path_length--; } /* strip \" */ - if( pbuf[0] == '\"' && pbuf[path_length-1]== '\"' ){ + if (pbuf[0] == '\"' && pbuf[path_length - 1]== '\"') { *pbuf++ = 0; - path_length-=2; + path_length -= 2; } - if (path_length==0) { + if (path_length == 0) { continue; } @@ -216,13 +216,13 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename) zend_accel_blacklist_allocate(blacklist); blacklist->entries[blacklist->pos].path_length = path_length; - blacklist->entries[blacklist->pos].path = (char *) malloc(path_length+1); + blacklist->entries[blacklist->pos].path = (char *)malloc(path_length + 1); if (!blacklist->entries[blacklist->pos].path) { zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n"); return; } blacklist->entries[blacklist->pos].id = blacklist->pos; - memcpy(blacklist->entries[blacklist->pos].path, real_path, path_length+1); + memcpy(blacklist->entries[blacklist->pos].path, real_path, path_length + 1); blacklist->pos++; } fclose(fp); @@ -251,7 +251,7 @@ void zend_accel_blacklist_apply(zend_blacklist *blacklist, apply_func_arg_t func { int i; - for(i=0; ipos; i++) { + for (i = 0; i < blacklist->pos; i++) { func(&blacklist->entries[i], argument TSRMLS_CC); } } diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index b39c52d8426..45ed12a9af6 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -74,13 +74,13 @@ static ZEND_INI_MH(OnUpdateMemoryConsumption) zend_ini_entry *ini_entry; memsize = 8; - zend_accel_error(ACCEL_LOG_WARNING,"zend_optimizerplus.memory_consumption is set below the required 8MB.\n" ); + zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.memory_consumption is set below the required 8MB.\n" ); zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the minimal 8MB cofiguration.\n" ); if (zend_hash_find(EG(ini_directives), "zend_optimizerplus.memory_consumption", sizeof("zend_optimizerplus.memory_consumption"), - (void *) &ini_entry)==FAILURE) { + (void *) &ini_entry) == FAILURE) { return FAILURE; } @@ -112,22 +112,22 @@ static ZEND_INI_MH(OnUpdateMaxAcceleratedFiles) const char *new_new_value; zend_ini_entry *ini_entry; - if(size < MIN_ACCEL_FILES){ + if (size < MIN_ACCEL_FILES) { size = MIN_ACCEL_FILES; new_new_value = TOKENTOSTR(MIN_ACCEL_FILES); - zend_accel_error(ACCEL_LOG_WARNING,"zend_optimizerplus.max_accelerated_files is set below the required minimum (%d).\n", MIN_ACCEL_FILES ); + zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.max_accelerated_files is set below the required minimum (%d).\n", MIN_ACCEL_FILES ); zend_accel_error(ACCEL_LOG_WARNING,ACCELERATOR_PRODUCT_NAME " will use the minimal cofiguration.\n" ); } - if(size > MAX_ACCEL_FILES){ + if (size > MAX_ACCEL_FILES) { size = MAX_ACCEL_FILES; new_new_value = TOKENTOSTR(MAX_ACCEL_FILES); - zend_accel_error(ACCEL_LOG_WARNING,"zend_optimizerplus.max_accelerated_files is set above the limit (%d).\n", MAX_ACCEL_FILES ); + zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.max_accelerated_files is set above the limit (%d).\n", MAX_ACCEL_FILES ); zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the maximal cofiguration.\n" ); } if (zend_hash_find(EG(ini_directives), "zend_optimizerplus.max_accelerated_files", sizeof("zend_optimizerplus.max_accelerated_files"), - (void *) &ini_entry)==FAILURE) { + (void *) &ini_entry) == FAILURE) { return FAILURE; } ini_entry->value = strdup(new_new_value); @@ -158,12 +158,12 @@ static ZEND_INI_MH(OnUpdateMaxWastedPercentage) zend_ini_entry *ini_entry; percentage = 5; - zend_accel_error(ACCEL_LOG_WARNING,"zend_optimizerplus.max_wasted_percentage must be ser netweeb 1 and 50.\n"); + zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.max_wasted_percentage must be ser netweeb 1 and 50.\n"); zend_accel_error(ACCEL_LOG_WARNING,ACCELERATOR_PRODUCT_NAME " will use 5%.\n" ); if (zend_hash_find(EG(ini_directives), "zend_optimizerplus.max_wasted_percentage", sizeof("zend_optimizerplus.max_wasted_percentage"), - (void *) &ini_entry)==FAILURE) { + (void *) &ini_entry) == FAILURE) { return FAILURE; } ini_entry->value = strdup(new_new_value); @@ -199,12 +199,12 @@ static ZEND_INI_MH(OnUpdateAccelBlacklist) } ZEND_INI_BEGIN() - STD_PHP_INI_BOOLEAN("zend_optimizerplus.enable" ,"1", PHP_INI_SYSTEM, OnUpdateBool, enabled , zend_accel_globals, accel_globals) - STD_PHP_INI_BOOLEAN("zend_optimizerplus.use_cwd" ,"1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.use_cwd , zend_accel_globals, accel_globals) - STD_PHP_INI_BOOLEAN("zend_optimizerplus.validate_timestamps","1", PHP_INI_ALL , OnUpdateBool, accel_directives.validate_timestamps, zend_accel_globals, accel_globals) - STD_PHP_INI_BOOLEAN("zend_optimizerplus.inherited_hack" ,"1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.inherited_hack , zend_accel_globals, accel_globals) - STD_PHP_INI_BOOLEAN("zend_optimizerplus.dups_fix" ,"0", PHP_INI_ALL , OnUpdateBool, accel_directives.ignore_dups , zend_accel_globals, accel_globals) - STD_PHP_INI_BOOLEAN("zend_optimizerplus.revalidate_path" ,"0", PHP_INI_ALL , OnUpdateBool, accel_directives.revalidate_path , zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("zend_optimizerplus.enable" , "1", PHP_INI_SYSTEM, OnUpdateBool, enabled , zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("zend_optimizerplus.use_cwd" , "1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.use_cwd , zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("zend_optimizerplus.validate_timestamps", "1", PHP_INI_ALL , OnUpdateBool, accel_directives.validate_timestamps, zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("zend_optimizerplus.inherited_hack" , "1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.inherited_hack , zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("zend_optimizerplus.dups_fix" , "0", PHP_INI_ALL , OnUpdateBool, accel_directives.ignore_dups , zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("zend_optimizerplus.revalidate_path" , "0", PHP_INI_ALL , OnUpdateBool, accel_directives.revalidate_path , zend_accel_globals, accel_globals) STD_PHP_INI_ENTRY("zend_optimizerplus.log_verbosity_level" , "1" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.log_verbosity_level, zend_accel_globals, accel_globals) STD_PHP_INI_ENTRY("zend_optimizerplus.memory_consumption" , "64" , PHP_INI_SYSTEM, OnUpdateMemoryConsumption, accel_directives.memory_consumption, zend_accel_globals, accel_globals) @@ -271,7 +271,7 @@ static int filename_is_in_cache(char *filename, int filename_len TSRMLS_DC) } } - if((key = accel_make_persistent_key_ex(&handle, filename_len, &key_length TSRMLS_CC)) != NULL) { + if ((key = accel_make_persistent_key_ex(&handle, filename_len, &key_length TSRMLS_CC)) != NULL) { persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length+1); return persistent_script && !persistent_script->corrupted; } @@ -301,8 +301,8 @@ static void accel_file_in_cache(int type, INTERNAL_FUNCTION_PARAMETERS) return; } #endif - if(filename_len > 0) { - if(filename_is_in_cache(filename, filename_len TSRMLS_CC)) { + if (filename_len > 0) { + if (filename_is_in_cache(filename, filename_len TSRMLS_CC)) { RETURN_TRUE; } } @@ -342,15 +342,15 @@ static ZEND_MINIT_FUNCTION(zend_accelerator) void zend_accel_override_file_functions(TSRMLS_D) { zend_function *old_function; - if(accel_startup_ok && ZCG(accel_directives).file_override_enabled) { + if (accel_startup_ok && ZCG(accel_directives).file_override_enabled) { /* override file_exists */ - if(zend_hash_find(CG(function_table), "file_exists", sizeof("file_exists"), (void **)&old_function) == SUCCESS) { + if (zend_hash_find(CG(function_table), "file_exists", sizeof("file_exists"), (void **)&old_function) == SUCCESS) { old_function->internal_function.handler = accel_file_exists; } - if(zend_hash_find(CG(function_table), "is_file", sizeof("is_file"), (void **)&old_function) == SUCCESS) { + if (zend_hash_find(CG(function_table), "is_file", sizeof("is_file"), (void **)&old_function) == SUCCESS) { old_function->internal_function.handler = accel_is_file; } - if(zend_hash_find(CG(function_table), "is_readable", sizeof("is_readable"), (void **)&old_function) == SUCCESS) { + if (zend_hash_find(CG(function_table), "is_readable", sizeof("is_readable"), (void **)&old_function) == SUCCESS) { old_function->internal_function.handler = accel_is_readable; } } @@ -424,8 +424,8 @@ static zval* accelerator_get_scripts(TSRMLS_D) MAKE_STD_ZVAL(return_value); array_init(return_value); - for (i=0; inext) { + for (i = 0; inext) { zend_persistent_script *script; if (cache_entry->indirect) continue; @@ -498,8 +498,8 @@ static ZEND_FUNCTION(accelerator_get_status) add_assoc_zval(return_value, "accelerator_statistics",statistics); /* acceleratred scripts */ - scripts=accelerator_get_scripts(TSRMLS_C); - if( scripts ){ + scripts = accelerator_get_scripts(TSRMLS_C); + if (scripts) { add_assoc_zval(return_value, "scripts",scripts); } } @@ -553,20 +553,20 @@ static ZEND_FUNCTION(accelerator_get_configuration) add_assoc_bool(directives, "zend_optimizerplus.enable_file_override", ZCG(accel_directives).file_override_enabled); add_assoc_long(directives, "zend_optimizerplus.optimization_level", ZCG(accel_directives).optimization_level); - add_assoc_zval(return_value,"directives",directives); + add_assoc_zval(return_value, "directives",directives); /*version */ MAKE_STD_ZVAL(version); array_init(version); add_assoc_string(version, "version", ACCELERATOR_VERSION, 1); add_assoc_string(version, "accelerator_product_name", ACCELERATOR_PRODUCT_NAME, 1); - add_assoc_zval(return_value,"version",version); + add_assoc_zval(return_value, "version",version); /* blacklist */ MAKE_STD_ZVAL(blacklist); array_init(blacklist); zend_accel_blacklist_apply(&accel_blacklist, (apply_func_arg_t) add_blacklist_path, blacklist TSRMLS_CC); - add_assoc_zval(return_value,"blacklist",blacklist); + add_assoc_zval(return_value, "blacklist",blacklist); } /* {{{ proto void accelerator_reset() diff --git a/zend_accelerator_util_funcs.c b/zend_accelerator_util_funcs.c index a234461405a..e8ed57c2444 100644 --- a/zend_accelerator_util_funcs.c +++ b/zend_accelerator_util_funcs.c @@ -125,7 +125,7 @@ static int move_user_function(zend_function *function TSRMLS_DC, int num_args, v HashTable *function_table = va_arg(args, HashTable *); (void)num_args; /* keep the compiler happy */ - if (function->type==ZEND_USER_FUNCTION) { + if (function->type == ZEND_USER_FUNCTION) { zend_hash_quick_update(function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, function, sizeof(zend_function), NULL); return 1; } else { @@ -144,8 +144,8 @@ void zend_accel_move_user_functions(HashTable *src, HashTable *dst TSRMLS_DC) static int copy_internal_function(zend_function *function, HashTable *function_table TSRMLS_DC) { - if (function->type==ZEND_INTERNAL_FUNCTION) { - zend_hash_update(function_table, function->common.function_name, strlen(function->common.function_name)+1, function, sizeof(zend_function), NULL); + if (function->type == ZEND_INTERNAL_FUNCTION) { + zend_hash_update(function_table, function->common.function_name, strlen(function->common.function_name) + 1, function, sizeof(zend_function), NULL); } return 0; } @@ -159,7 +159,7 @@ void zend_accel_copy_internal_functions(TSRMLS_D) static void zend_destroy_property_info(zend_property_info *property_info) { interned_efree((char*)property_info->name); - if(property_info->doc_comment){ + if (property_info->doc_comment) { efree((char*)property_info->doc_comment); } } @@ -404,7 +404,7 @@ static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class q->pData = (void *) emalloc(sizeof(zend_function)); new_entry = (zend_op_array*)q->pData; *new_entry = *(zend_op_array*)p->pData; - q->pDataPtr=NULL; + q->pDataPtr = NULL; /* Copy constructor */ /* we use refcount to show that op_array is referenced from several places */ @@ -414,10 +414,10 @@ static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class zend_prepare_function_for_execution(new_entry); - if(old_ce == new_entry->scope) { + if (old_ce == new_entry->scope) { new_entry->scope = ce; } else { - if(accel_xlat_get(new_entry->scope, new_ce) == SUCCESS) { + if (accel_xlat_get(new_entry->scope, new_ce) == SUCCESS) { new_entry->scope = *new_ce; } else { zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s. Please call Zend Support", ce->name, new_entry->function_name); @@ -425,8 +425,8 @@ static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class } /* update prototype */ - if (new_entry->prototype ){ - if(accel_xlat_get(new_entry->prototype, new_prototype)==SUCCESS) { + if (new_entry->prototype) { + if (accel_xlat_get(new_entry->prototype, new_prototype) == SUCCESS) { new_entry->prototype = *new_prototype; } else { zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s. Please call Zend Support", ce->name, new_entry->function_name); @@ -515,20 +515,20 @@ static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_cla q->pData = (void *) emalloc(sizeof(zend_property_info)); prop_info = q->pData; *prop_info = *(zend_property_info*)p->pData; - q->pDataPtr=NULL; + q->pDataPtr = NULL; /* Copy constructor */ prop_info->name = interned_estrndup(prop_info->name, prop_info->name_length); - if(prop_info->doc_comment) { + if (prop_info->doc_comment) { if (ZCG(accel_directives).load_comments) { prop_info->doc_comment = estrndup(prop_info->doc_comment, prop_info->doc_comment_len); } else { prop_info->doc_comment = NULL; } } - if(prop_info->ce == old_ce) { + if (prop_info->ce == old_ce) { prop_info->ce = ce; - } else if(accel_xlat_get(prop_info->ce, new_ce) == SUCCESS) { + } else if (accel_xlat_get(prop_info->ce, new_ce) == SUCCESS) { prop_info->ce = *new_ce; } else { zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s, property %s. Please call Zend Support", ce->name, prop_info->name); @@ -559,8 +559,8 @@ static int zend_prepare_function_for_execution(zend_op_array *op_array) #define zend_update_inherited_handler(handler) \ { \ - if(ce->handler != NULL) { \ - if(accel_xlat_get(ce->handler, new_func)==SUCCESS) { \ + if (ce->handler != NULL) { \ + if (accel_xlat_get(ce->handler, new_func) == SUCCESS) { \ ce->handler = *new_func; \ } else { \ zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s. Please call Zend Support", ce->name); \ @@ -634,7 +634,7 @@ static void zend_class_copy_ctor(zend_class_entry **pce) ce->name = interned_estrndup(ce->name, ce->name_length); /* interfaces aren't really implemented, so we create a new table */ - if(ce->num_interfaces) { + if (ce->num_interfaces) { ce->interfaces = emalloc(sizeof(zend_class_entry *) * ce->num_interfaces); memset(ce->interfaces, 0, sizeof(zend_class_entry *) * ce->num_interfaces); } else { @@ -648,8 +648,8 @@ static void zend_class_copy_ctor(zend_class_entry **pce) } } - if(ce->parent) { - if(accel_xlat_get(ce->parent, new_ce)==SUCCESS) { + if (ce->parent) { + if (accel_xlat_get(ce->parent, new_ce) == SUCCESS) { ce->parent = *new_ce; } else { zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s. Please call Zend Support", ce->name); @@ -684,7 +684,7 @@ static void zend_class_copy_ctor(zend_class_entry **pce) while (ce->trait_aliases[i]) { i++; } - trait_aliases = emalloc(sizeof(zend_trait_alias*) * (i+1)); + trait_aliases = emalloc(sizeof(zend_trait_alias*) * (i + 1)); i = 0; while (ce->trait_aliases[i]) { trait_aliases[i] = emalloc(sizeof(zend_trait_alias)); @@ -722,7 +722,7 @@ static void zend_class_copy_ctor(zend_class_entry **pce) while (ce->trait_precedences[i]) { i++; } - trait_precedences = emalloc(sizeof(zend_trait_precedence*) * (i+1)); + trait_precedences = emalloc(sizeof(zend_trait_precedence*) * (i + 1)); i = 0; while (ce->trait_precedences[i]) { trait_precedences[i] = emalloc(sizeof(zend_trait_precedence)); @@ -744,7 +744,7 @@ static void zend_class_copy_ctor(zend_class_entry **pce) while (trait_precedences[i]->exclude_from_classes[j]) { j++; } - exclude_from_classes = emalloc(sizeof(zend_class_entry*) * (j+1)); + exclude_from_classes = emalloc(sizeof(zend_class_entry*) * (j + 1)); j = 0; while (trait_precedences[i]->exclude_from_classes[j]) { exclude_from_classes[j] = (zend_class_entry*)estrndup( @@ -769,25 +769,25 @@ static int zend_accel_same_function(void *f1, void *f2) zend_op_array *op1 = (zend_op_array *)func1; zend_op_array *op2 = (zend_op_array *)func2; - if(func1->type != ZEND_USER_FUNCTION || func2->type != ZEND_USER_FUNCTION) { + if (func1->type != ZEND_USER_FUNCTION || func2->type != ZEND_USER_FUNCTION) { return 0; } - if(func1 == func2) { + if (func1 == func2) { return 1; } - if(op1->function_name != op2->function_name && (!op1->function_name || !op2->function_name || strcmp(op1->function_name, op2->function_name))) { + if (op1->function_name != op2->function_name && (!op1->function_name || !op2->function_name || strcmp(op1->function_name, op2->function_name))) { /* compare filenames */ return 0; } - if(op1->filename != op2->filename && (!op1->filename || !op2->filename || strcmp(op1->filename, op2->filename))) { + if (op1->filename != op2->filename && (!op1->filename || !op2->filename || strcmp(op1->filename, op2->filename))) { /* compare filenames */ return 0; } - if(!op1->opcodes || !op2->opcodes || op1->opcodes[0].lineno != op2->opcodes[0].lineno) { + if (!op1->opcodes || !op2->opcodes || op1->opcodes[0].lineno != op2->opcodes[0].lineno) { /* compare first lines */ return 0; } @@ -801,15 +801,15 @@ static int zend_accel_same_class(void *f1, void *f2) zend_class_entry *ce1 = *(zend_class_entry **)f1; zend_class_entry *ce2 = *(zend_class_entry **)f2; - if(ce1->type != ZEND_USER_CLASS || ce2->type != ZEND_USER_CLASS) { + if (ce1->type != ZEND_USER_CLASS || ce2->type != ZEND_USER_CLASS) { return 0; } - if(ce1 == ce2) { + if (ce1 == ce2) { return 1; } - if(!ce1->name || !ce2->name || zend_binary_strcmp(ce1->name, ce1->name_length, ce2->name, ce2->name_length)) { + if (!ce1->name || !ce2->name || zend_binary_strcmp(ce1->name, ce1->name_length, ce2->name, ce2->name_length)) { return 0; } @@ -822,7 +822,7 @@ static int zend_accel_same_class(void *f1, void *f2) return 0; } - if(zend_hash_num_elements(&ce1->function_table)) { + if (zend_hash_num_elements(&ce1->function_table)) { HashPosition pos; zend_function *func1, *func2; @@ -830,7 +830,7 @@ static int zend_accel_same_class(void *f1, void *f2) zend_hash_get_current_data_ex(&ce1->function_table, (void **)&func1, &pos); zend_hash_internal_pointer_reset_ex(&ce2->function_table, &pos); zend_hash_get_current_data_ex(&ce2->function_table, (void **)&func2, &pos); - if(!zend_accel_same_function(func1, func2)) { + if (!zend_accel_same_function(func1, func2)) { return 0; } } @@ -843,24 +843,24 @@ static int zend_hash_unique_copy(HashTable *target, HashTable *source, unique_co Bucket *p; void *t; - p = source->pListHead; + p = source->pListHead; while (p) { - if (p->nKeyLength>0) { - if (zend_hash_quick_add(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &t) ==SUCCESS) { - if(pCopyConstructor) { + if (p->nKeyLength > 0) { + if (zend_hash_quick_add(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &t) == SUCCESS) { + if (pCopyConstructor) { pCopyConstructor(t); } } else { - if(p->nKeyLength>0 && p->arKey[0]==0) { + if (p->nKeyLength > 0 && p->arKey[0] == 0) { /* Mangled key, ignore and wait for runtime */ - } else if(zend_hash_quick_find(target, p->arKey, p->nKeyLength, p->h, &t) == SUCCESS && + } else if (zend_hash_quick_find(target, p->arKey, p->nKeyLength, p->h, &t) == SUCCESS && (!pIdFunc || pIdFunc(p->pData, t))) { /* same one, ignore it */ } else { - if(key_fail) { + if (key_fail) { *key_fail = p->arKey; } - if(key_fail_l) { + if (key_fail_l) { *key_fail_l = p->nKeyLength; } return FAILURE; @@ -868,14 +868,14 @@ static int zend_hash_unique_copy(HashTable *target, HashTable *source, unique_co } } else { if (!zend_hash_index_exists(target, p->h) && zend_hash_index_update(target, p->h, p->pData, size, &t) == SUCCESS) { - if(pCopyConstructor) { + if (pCopyConstructor) { pCopyConstructor(t); } } else { - if(key_fail) { + if (key_fail) { *key_fail = NULL; } - if(key_fail_l) { + if (key_fail_l) { *key_fail_l = p->h; } return FAILURE; @@ -894,10 +894,10 @@ static void zend_accel_function_hash_copy(HashTable *target, HashTable *source, zend_function *function; TSRMLS_FETCH(); - if(zend_hash_unique_copy(target, source, pCopyConstructor, sizeof(zend_function), &name, &name_len, ZCG(accel_directives).ignore_dups?NULL:zend_accel_same_function) != SUCCESS) { - if (zend_hash_find(target, name, name_len, (void *) &function)==SUCCESS - && function->type==ZEND_USER_FUNCTION - && ((zend_op_array *) function)->last>0) { + if (zend_hash_unique_copy(target, source, pCopyConstructor, sizeof(zend_function), &name, &name_len, ZCG(accel_directives).ignore_dups?NULL:zend_accel_same_function) != SUCCESS) { + if (zend_hash_find(target, name, name_len, (void *) &function) == SUCCESS + && function->type == ZEND_USER_FUNCTION + && ((zend_op_array *) function)->last > 0) { zend_error(E_ERROR, "Cannot redeclare function %.*s() (previously declared in %s:%d). If this code worked without the " ACCELERATOR_PRODUCT_NAME ", please set zend_optimizerplus.dups_fix=1 in your ini file", (int)name_len, name, ((zend_op_array *) function)->filename, @@ -915,7 +915,7 @@ static void zend_accel_class_hash_copy(HashTable *target, HashTable *source, uni uint size; size = sizeof(zend_class_entry*); - if(zend_hash_unique_copy(target, source, pCopyConstructor, size, &name, &name_len, ZCG(accel_directives).ignore_dups?NULL:zend_accel_same_class) != SUCCESS) { + if (zend_hash_unique_copy(target, source, pCopyConstructor, size, &name, &name_len, ZCG(accel_directives).ignore_dups? NULL : zend_accel_same_class) != SUCCESS) { zend_error(E_ERROR, "Cannot redeclare class %.*s. If this code worked without the " ACCELERATOR_PRODUCT_NAME ", please set zend_optimizerplus.dups_fix=1 in your php.ini", (int)name_len, name); } } @@ -932,7 +932,7 @@ static void zend_do_delayed_early_binding(zend_op_array *op_array, zend_uint ear CG(in_compilation) = 1; while ((int)opline_num != -1) { - if (zend_lookup_class(Z_STRVAL(op_array->opcodes[opline_num-1].op2.u.constant), Z_STRLEN(op_array->opcodes[opline_num-1].op2.u.constant), &pce TSRMLS_CC) == SUCCESS) { + if (zend_lookup_class(Z_STRVAL(op_array->opcodes[opline_num - 1].op2.u.constant), Z_STRLEN(op_array->opcodes[opline_num - 1].op2.u.constant), &pce TSRMLS_CC) == SUCCESS) { do_bind_inherited_class(&op_array->opcodes[opline_num], EG(class_table), *pce, 1 TSRMLS_CC); } opline_num = op_array->opcodes[opline_num].result.u.opline_num; @@ -975,8 +975,8 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, cfilename = persistent_script->full_path; clen = strlen(cfilename); zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, cfilename, clen, 0); - if (!zend_hash_exists(EG(zend_constants), name, len+1)) { - zend_register_long_constant(name, len+1, persistent_script->compiler_halt_offset, CONST_CS, 0 TSRMLS_CC); + if (!zend_hash_exists(EG(zend_constants), name, len + 1)) { + zend_register_long_constant(name, len + 1, persistent_script->compiler_halt_offset, CONST_CS, 0 TSRMLS_CC); } efree(name); } @@ -1040,11 +1040,11 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, #define ADLER32_NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ -#define ADLER32_DO1(buf) {s1 += *(buf); s2 += s1;} -#define ADLER32_DO2(buf,i) ADLER32_DO1(buf+i); ADLER32_DO1(buf+i+1); -#define ADLER32_DO4(buf,i) ADLER32_DO2(buf,i); ADLER32_DO2(buf,i+2); -#define ADLER32_DO8(buf,i) ADLER32_DO4(buf,i); ADLER32_DO4(buf,i+4); -#define ADLER32_DO16(buf) ADLER32_DO8(buf,0); ADLER32_DO8(buf,8); +#define ADLER32_DO1(buf) {s1 += *(buf); s2 += s1;} +#define ADLER32_DO2(buf, i) ADLER32_DO1(buf + i); ADLER32_DO1(buf + i + 1); +#define ADLER32_DO4(buf, i) ADLER32_DO2(buf, i); ADLER32_DO2(buf, i + 2); +#define ADLER32_DO8(buf, i) ADLER32_DO4(buf, i); ADLER32_DO4(buf, i + 4); +#define ADLER32_DO16(buf) ADLER32_DO8(buf, 0); ADLER32_DO8(buf, 8); unsigned int zend_adler32(unsigned int checksum, signed char *buf, uint len) { @@ -1081,7 +1081,7 @@ unsigned int zend_adler32(unsigned int checksum, signed char *buf, uint len) } s1 %= ADLER32_BASE; s2 %= ADLER32_BASE; - } + } return (s2 << 16) | s1; } diff --git a/zend_persist.c b/zend_persist.c index 44a9809322e..f3438a05bf4 100644 --- a/zend_persist.c +++ b/zend_persist.c @@ -210,7 +210,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc #endif 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)) { + if (zend_get_constant("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1, &offset TSRMLS_CC)) { main_persistent_script->compiler_halt_offset = Z_LVAL(offset); } EG(active_op_array) = orig_op_array; @@ -246,7 +246,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc int offset = 0; for (;opline PHP_5_3_X_API_NO opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals)); #else @@ -254,7 +254,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc zend_protect_zval(&opline->op1.u.constant TSRMLS_CC); #endif } - if (ZEND_OP2_TYPE(opline)==IS_CONST) { + if (ZEND_OP2_TYPE(opline) == IS_CONST) { #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO opline->op2.zv = (zval*)((char*)opline->op2.zv + ((char*)op_array->literals - (char*)orig_literals)); #else @@ -288,9 +288,9 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc case ZEND_DECLARE_INHERITED_CLASS: if (main_persistent_script && ZCG(accel_directives).inherited_hack) { if (!has_jmp && - ((opline+2) >= end || - (opline+1)->opcode != ZEND_FETCH_CLASS || - (opline+2)->opcode != ZEND_ADD_INTERFACE)) { + ((opline + 2) >= end || + (opline + 1)->opcode != ZEND_FETCH_CLASS || + (opline + 2)->opcode != ZEND_ADD_INTERFACE)) { zend_uint *opline_num = &main_persistent_script->early_binding; @@ -331,7 +331,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc break; } } -#endif /* if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO */ +#endif /* if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO */ } efree(op_array->opcodes); @@ -350,23 +350,23 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc if ((new_name = zend_shared_alloc_get_xlat_entry(op_array->function_name))) { op_array->function_name = new_name; } else { - zend_accel_store(op_array->function_name, strlen(op_array->function_name)+1); + zend_accel_store(op_array->function_name, strlen(op_array->function_name) + 1); } } if (op_array->arg_info) { zend_arg_info *new_ptr; - if((new_ptr = zend_shared_alloc_get_xlat_entry(op_array->arg_info))) { + if ((new_ptr = zend_shared_alloc_get_xlat_entry(op_array->arg_info))) { op_array->arg_info = new_ptr; } else { zend_uint i; zend_accel_store(op_array->arg_info, sizeof(zend_arg_info) * op_array->num_args); - for(i=0;inum_args;i++) { - if(op_array->arg_info[i].name) { + for (i = 0; i < op_array->num_args; i++) { + if (op_array->arg_info[i].name) { zend_accel_store_interned_string(op_array->arg_info[i].name, op_array->arg_info[i].name_len + 1); } - if(op_array->arg_info[i].class_name) { + if (op_array->arg_info[i].class_name) { zend_accel_store_interned_string(op_array->arg_info[i].class_name, op_array->arg_info[i].class_name_len + 1); } } @@ -382,15 +382,15 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc zend_accel_store(op_array->static_variables, sizeof(HashTable)); } - if(op_array->scope) { + if (op_array->scope) { op_array->scope = zend_shared_alloc_get_xlat_entry(op_array->scope); } - if(op_array->doc_comment) { + if (op_array->doc_comment) { if (ZCG(accel_directives).save_comments) { zend_accel_store(op_array->doc_comment, op_array->doc_comment_len + 1); } else { - if(!zend_shared_alloc_get_xlat_entry(op_array->doc_comment)) { + if (!zend_shared_alloc_get_xlat_entry(op_array->doc_comment)) { zend_shared_alloc_register_xlat_entry(op_array->doc_comment, op_array->doc_comment); efree((char*)op_array->doc_comment); } @@ -399,24 +399,24 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc } } - if(op_array->try_catch_array) { + if (op_array->try_catch_array) { zend_accel_store(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch); } - if(op_array->vars) { + if (op_array->vars) { if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->vars))) { op_array->vars = (zend_compiled_variable*)persist_ptr; } else { int i; zend_accel_store(op_array->vars, sizeof(zend_compiled_variable) * op_array->last_var); - for(i=0; ilast_var; i++) { + for (i = 0; i < op_array->last_var; i++) { zend_accel_store_interned_string(op_array->vars[i].name, op_array->vars[i].name_len + 1); } } } /* "prototype" may be undefined if "scope" isn't set */ - if(op_array->scope && op_array->prototype) { + if (op_array->scope && op_array->prototype) { if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype))) { op_array->prototype = (union _zend_function*)persist_ptr; /* we use refcount to show that op_array is referenced from several places */ @@ -435,11 +435,11 @@ static void zend_persist_op_array(zend_op_array *op_array TSRMLS_DC) static void zend_persist_property_info(zend_property_info *prop TSRMLS_DC) { zend_accel_store_interned_string(prop->name, prop->name_length + 1); - if(prop->doc_comment) { + if (prop->doc_comment) { if (ZCG(accel_directives).save_comments) { zend_accel_store(prop->doc_comment, prop->doc_comment_len + 1); } else { - if(!zend_shared_alloc_get_xlat_entry(prop->doc_comment)) { + if (!zend_shared_alloc_get_xlat_entry(prop->doc_comment)) { zend_shared_alloc_register_xlat_entry(prop->doc_comment, prop->doc_comment); efree((char*)prop->doc_comment); } @@ -486,15 +486,15 @@ static void zend_persist_class_entry(zend_class_entry **pce TSRMLS_DC) #endif zend_hash_persist(&ce->constants_table, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC); - if(ZEND_CE_FILENAME(ce)) { + if (ZEND_CE_FILENAME(ce)) { /* do not free! PHP has centralized filename storage, compiler will free it */ ZEND_CE_FILENAME(ce) = zend_accel_memdup(ZEND_CE_FILENAME(ce), strlen(ZEND_CE_FILENAME(ce)) + 1); } - if(ZEND_CE_DOC_COMMENT(ce)) { + if (ZEND_CE_DOC_COMMENT(ce)) { if (ZCG(accel_directives).save_comments) { zend_accel_store(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT_LEN(ce) + 1); } else { - if(!zend_shared_alloc_get_xlat_entry(ZEND_CE_DOC_COMMENT(ce))) { + if (!zend_shared_alloc_get_xlat_entry(ZEND_CE_DOC_COMMENT(ce))) { zend_shared_alloc_register_xlat_entry(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT(ce)); efree((char*)ZEND_CE_DOC_COMMENT(ce)); } @@ -503,7 +503,7 @@ static void zend_persist_class_entry(zend_class_entry **pce TSRMLS_DC) } } zend_hash_persist(&ce->properties_info, (zend_persist_func_t) zend_persist_property_info, sizeof(zend_property_info) TSRMLS_CC); - if(ce->num_interfaces && ce->interfaces) { + if (ce->num_interfaces && ce->interfaces) { efree(ce->interfaces); } ce->interfaces = NULL; /* will be filled in on fetch */ @@ -520,11 +520,11 @@ static void zend_persist_class_entry(zend_class_entry **pce TSRMLS_DC) if (ce->trait_aliases[i]->trait_method) { if (ce->trait_aliases[i]->trait_method->method_name) { zend_accel_store(ce->trait_aliases[i]->trait_method->method_name, - ce->trait_aliases[i]->trait_method->mname_len+1); + ce->trait_aliases[i]->trait_method->mname_len + 1); } if (ce->trait_aliases[i]->trait_method->class_name) { zend_accel_store(ce->trait_aliases[i]->trait_method->class_name, - ce->trait_aliases[i]->trait_method->cname_len+1); + ce->trait_aliases[i]->trait_method->cname_len + 1); } ce->trait_aliases[i]->trait_method->ce = NULL; zend_accel_store(ce->trait_aliases[i]->trait_method, @@ -533,7 +533,7 @@ static void zend_persist_class_entry(zend_class_entry **pce TSRMLS_DC) if (ce->trait_aliases[i]->alias) { zend_accel_store(ce->trait_aliases[i]->alias, - ce->trait_aliases[i]->alias_len+1); + ce->trait_aliases[i]->alias_len + 1); } #if ZEND_EXTENSION_API_NO <= PHP_5_4_X_API_NO @@ -551,9 +551,9 @@ static void zend_persist_class_entry(zend_class_entry **pce TSRMLS_DC) while (ce->trait_precedences[i]) { zend_accel_store(ce->trait_precedences[i]->trait_method->method_name, - ce->trait_precedences[i]->trait_method->mname_len+1); + ce->trait_precedences[i]->trait_method->mname_len + 1); zend_accel_store(ce->trait_precedences[i]->trait_method->class_name, - ce->trait_precedences[i]->trait_method->cname_len+1); + ce->trait_precedences[i]->trait_method->cname_len + 1); ce->trait_precedences[i]->trait_method->ce = NULL; zend_accel_store(ce->trait_precedences[i]->trait_method, sizeof(zend_trait_method_reference)); @@ -567,7 +567,7 @@ static void zend_persist_class_entry(zend_class_entry **pce TSRMLS_DC) j++; } zend_accel_store(ce->trait_precedences[i]->exclude_from_classes, - sizeof(zend_class_entry*) * (j+1)); + sizeof(zend_class_entry*) * (j + 1)); } #if ZEND_EXTENSION_API_NO <= PHP_5_4_X_API_NO @@ -577,7 +577,7 @@ static void zend_persist_class_entry(zend_class_entry **pce TSRMLS_DC) i++; } zend_accel_store( - ce->trait_precedences, sizeof(zend_trait_precedence*) * (i+1)); + ce->trait_precedences, sizeof(zend_trait_precedence*) * (i + 1)); } #endif } @@ -600,53 +600,53 @@ static int zend_update_parent_ce(zend_class_entry **pce TSRMLS_DC) } /* update methods */ - if(ce->constructor) { + if (ce->constructor) { ce->constructor = zend_shared_alloc_get_xlat_entry(ce->constructor); /* we use refcount to show that op_array is referenced from several places */ ce->constructor->op_array.refcount++; } - if(ce->destructor) { + if (ce->destructor) { ce->destructor = zend_shared_alloc_get_xlat_entry(ce->destructor); ce->destructor->op_array.refcount++; } - if(ce->clone) { + if (ce->clone) { ce->clone = zend_shared_alloc_get_xlat_entry(ce->clone); ce->clone->op_array.refcount++; } - if(ce->__get) { + if (ce->__get) { ce->__get = zend_shared_alloc_get_xlat_entry(ce->__get); ce->__get->op_array.refcount++; } - if(ce->__set) { + if (ce->__set) { ce->__set = zend_shared_alloc_get_xlat_entry(ce->__set); ce->__set->op_array.refcount++; } - if(ce->__call) { + if (ce->__call) { ce->__call = zend_shared_alloc_get_xlat_entry(ce->__call); ce->__call->op_array.refcount++; } - if(ce->serialize_func) { + if (ce->serialize_func) { ce->serialize_func = zend_shared_alloc_get_xlat_entry(ce->serialize_func); ce->serialize_func->op_array.refcount++; } - if(ce->unserialize_func) { + if (ce->unserialize_func) { ce->unserialize_func = zend_shared_alloc_get_xlat_entry(ce->unserialize_func); ce->unserialize_func->op_array.refcount++; } - if(ce->__isset) { + if (ce->__isset) { ce->__isset = zend_shared_alloc_get_xlat_entry(ce->__isset); ce->__isset->op_array.refcount++; } - if(ce->__unset) { + if (ce->__unset) { ce->__unset = zend_shared_alloc_get_xlat_entry(ce->__unset); ce->__unset->op_array.refcount++; } - if(ce->__tostring) { + if (ce->__tostring) { ce->__tostring = zend_shared_alloc_get_xlat_entry(ce->__tostring); ce->__tostring->op_array.refcount++; } #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO - if(ce->__callstatic) { + if (ce->__callstatic) { ce->__callstatic = zend_shared_alloc_get_xlat_entry(ce->__callstatic); ce->__callstatic->op_array.refcount++; } diff --git a/zend_persist_calc.c b/zend_persist_calc.c index 36ec05b7283..72755325bfc 100644 --- a/zend_persist_calc.c +++ b/zend_persist_calc.c @@ -152,14 +152,14 @@ static uint zend_persist_op_array_calc(zend_op_array *op_array TSRMLS_DC) if (!zend_shared_alloc_get_xlat_entry(op_array->opcodes)) { #if ZEND_EXTENSION_API_NO <= PHP_5_3_X_API_NO zend_op *opline = op_array->opcodes; - zend_op *end = op_array->opcodes+op_array->last; + zend_op *end = op_array->opcodes + op_array->last; ADD_DUP_SIZE(op_array->opcodes, sizeof(zend_op) * op_array->last); while (oplineop1.op_type==IS_CONST) { + if (opline->op1.op_type == IS_CONST) { ADD_SIZE(zend_persist_zval_calc(&opline->op1.u.constant TSRMLS_CC)); } - if (opline->op2.op_type==IS_CONST) { + if (opline->op2.op_type == IS_CONST) { ADD_SIZE(zend_persist_zval_calc(&opline->op2.u.constant TSRMLS_CC)); } opline++; @@ -178,11 +178,11 @@ static uint zend_persist_op_array_calc(zend_op_array *op_array TSRMLS_DC) zend_uint i; ADD_DUP_SIZE(op_array->arg_info, sizeof(zend_arg_info) * op_array->num_args); - for(i=0;inum_args;i++) { - if(op_array->arg_info[i].name) { + for (i = 0;i < op_array->num_args; i++) { + if (op_array->arg_info[i].name) { ADD_INTERNED_STRING(op_array->arg_info[i].name, op_array->arg_info[i].name_len + 1); } - if(op_array->arg_info[i].class_name) { + if (op_array->arg_info[i].class_name) { ADD_INTERNED_STRING(op_array->arg_info[i].class_name, op_array->arg_info[i].class_name_len + 1); } @@ -198,19 +198,19 @@ static uint zend_persist_op_array_calc(zend_op_array *op_array TSRMLS_DC) ADD_SIZE(zend_hash_persist_calc(op_array->static_variables, (int (*)(void* TSRMLS_DC)) zend_persist_zval_ptr_calc, sizeof(zval**) TSRMLS_CC)); } - if(ZCG(accel_directives).save_comments && op_array->doc_comment) { + if (ZCG(accel_directives).save_comments && op_array->doc_comment) { ADD_DUP_SIZE(op_array->doc_comment, op_array->doc_comment_len + 1); } - if(op_array->try_catch_array) { + if (op_array->try_catch_array) { ADD_DUP_SIZE(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch); } - if(op_array->vars && !zend_shared_alloc_get_xlat_entry(op_array->vars)) { + if (op_array->vars && !zend_shared_alloc_get_xlat_entry(op_array->vars)) { int i; ADD_DUP_SIZE(op_array->vars, sizeof(zend_compiled_variable) * op_array->last_var); - for(i=0; ilast_var; i++) { + for (i = 0; i < op_array->last_var; i++) { ADD_INTERNED_STRING(op_array->vars[i].name, op_array->vars[i].name_len + 1); } } @@ -222,7 +222,7 @@ static uint zend_persist_property_info_calc(zend_property_info *prop TSRMLS_DC) { START_SIZE(); ADD_INTERNED_STRING(prop->name, prop->name_length + 1); - if(ZCG(accel_directives).save_comments && prop->doc_comment) { + if (ZCG(accel_directives).save_comments && prop->doc_comment) { ADD_DUP_SIZE(prop->doc_comment, prop->doc_comment_len + 1); } RETURN_SIZE(); @@ -267,7 +267,7 @@ static uint zend_persist_class_entry_calc(zend_class_entry **pce TSRMLS_DC) if (ZEND_CE_FILENAME(ce)) { ADD_DUP_SIZE(ZEND_CE_FILENAME(ce), strlen(ZEND_CE_FILENAME(ce)) + 1); } - if(ZCG(accel_directives).save_comments && ZEND_CE_DOC_COMMENT(ce)) { + if (ZCG(accel_directives).save_comments && ZEND_CE_DOC_COMMENT(ce)) { ADD_DUP_SIZE(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT_LEN(ce) + 1); } @@ -279,16 +279,16 @@ static uint zend_persist_class_entry_calc(zend_class_entry **pce TSRMLS_DC) while (ce->trait_aliases[i]) { if (ce->trait_aliases[i]->trait_method) { if (ce->trait_aliases[i]->trait_method->method_name) { - ADD_SIZE(ce->trait_aliases[i]->trait_method->mname_len+1); + ADD_SIZE(ce->trait_aliases[i]->trait_method->mname_len + 1); } if (ce->trait_aliases[i]->trait_method->class_name) { - ADD_SIZE(ce->trait_aliases[i]->trait_method->cname_len+1); + ADD_SIZE(ce->trait_aliases[i]->trait_method->cname_len + 1); } ADD_SIZE(sizeof(zend_trait_method_reference)); } if (ce->trait_aliases[i]->alias) { - ADD_SIZE(ce->trait_aliases[i]->alias_len+1); + ADD_SIZE(ce->trait_aliases[i]->alias_len + 1); } ADD_SIZE(sizeof(zend_trait_alias)); i++; @@ -300,8 +300,8 @@ static uint zend_persist_class_entry_calc(zend_class_entry **pce TSRMLS_DC) int i = 0; while (ce->trait_precedences[i]) { - ADD_SIZE(ce->trait_precedences[i]->trait_method->mname_len+1); - ADD_SIZE(ce->trait_precedences[i]->trait_method->cname_len+1); + ADD_SIZE(ce->trait_precedences[i]->trait_method->mname_len + 1); + ADD_SIZE(ce->trait_precedences[i]->trait_method->cname_len + 1); ADD_SIZE(sizeof(zend_trait_method_reference)); if (ce->trait_precedences[i]->exclude_from_classes) { @@ -311,12 +311,12 @@ static uint zend_persist_class_entry_calc(zend_class_entry **pce TSRMLS_DC) ADD_SIZE(strlen((char*)ce->trait_precedences[i]->exclude_from_classes[j]) + 1); j++; } - ADD_SIZE(sizeof(zend_class_entry*) * (j+1)); + ADD_SIZE(sizeof(zend_class_entry*) * (j + 1)); } ADD_SIZE(sizeof(zend_trait_precedence)); i++; } - ADD_SIZE(sizeof(zend_trait_precedence*) * (i+1)); + ADD_SIZE(sizeof(zend_trait_precedence*) * (i + 1)); } #endif } diff --git a/zend_shared_alloc.c b/zend_shared_alloc.c index abdc195d796..3e867d13613 100644 --- a/zend_shared_alloc.c +++ b/zend_shared_alloc.c @@ -56,7 +56,7 @@ zend_smm_shared_globals *smm_shared_globals; static MUTEX_T zts_lock; #endif int lock_file; -static char lockfile_name[sizeof(TMP_DIR)+sizeof(SEM_FILENAME_PREFIX)+8]; +static char lockfile_name[sizeof(TMP_DIR) + sizeof(SEM_FILENAME_PREFIX) + 8]; #endif static const zend_shared_memory_handler_entry handler_table[] = { @@ -111,7 +111,7 @@ static void copy_shared_segments(void *to, void *from, int count, int size) void *shared_segments_from_p = from; int i; - for(i=0;ip && (int)(*shared_segments_p)[i]->p != -1) { + for (i = 0; i < *shared_segments_count; i++) { + if ((*shared_segments_p)[i]->p && (int)(*shared_segments_p)[i]->p != -1) { S_H(detach_segment)((*shared_segments_p)[i]); } } @@ -167,17 +167,17 @@ int zend_shared_alloc_startup(int requested_size) zend_shared_alloc_create_lock(); - if(ZCG(accel_directives).memory_model && ZCG(accel_directives).memory_model[0]) { - char* model = ZCG(accel_directives).memory_model; + if (ZCG(accel_directives).memory_model && ZCG(accel_directives).memory_model[0]) { + char *model = ZCG(accel_directives).memory_model; /* "cgi" is really "shm"... */ - if( strncmp(ZCG(accel_directives).memory_model,"cgi",4) == 0 ){ + if (strncmp(ZCG(accel_directives).memory_model, "cgi", sizeof("cgi")) == 0) { model = "shm"; } - for(he = handler_table; he->name; he++) { - if(strcmp(model, he->name) == 0) { - res=zend_shared_alloc_try(he, requested_size, &ZSMMG(shared_segments), &ZSMMG(shared_segments_count), &error_in); - if( res ) { + for (he = handler_table; he->name; he++) { + if (strcmp(model, he->name) == 0) { + res = zend_shared_alloc_try(he, requested_size, &ZSMMG(shared_segments), &ZSMMG(shared_segments_count), &error_in); + if (res) { /* this model works! */ } break; @@ -185,38 +185,38 @@ int zend_shared_alloc_startup(int requested_size) } } - if( res == FAILED_REATTACHED ){ + if (res == FAILED_REATTACHED) { smm_shared_globals = NULL; return res; } - if(!g_shared_alloc_handler) { + if (!g_shared_alloc_handler) { /* try memory handlers in order */ - for(he = handler_table; he->name; he++) { - res=zend_shared_alloc_try(he, requested_size, &ZSMMG(shared_segments), &ZSMMG(shared_segments_count), &error_in); - if( res ) { + for (he = handler_table; he->name; he++) { + res = zend_shared_alloc_try(he, requested_size, &ZSMMG(shared_segments), &ZSMMG(shared_segments_count), &error_in); + if (res) { /* this model works! */ break; } } } - if(!g_shared_alloc_handler) { + if (!g_shared_alloc_handler) { no_memory_bailout(requested_size, error_in); return ALLOC_FAILURE; } - if( res == SUCCESSFULLY_REATTACHED ){ + if (res == SUCCESSFULLY_REATTACHED) { return res; } - shared_segments_array_size = ZSMMG(shared_segments_count)*S_H(segment_type_size)(); + shared_segments_array_size = ZSMMG(shared_segments_count) * S_H(segment_type_size)(); /* move shared_segments and shared_free to shared memory */ ZCG(locked) = 1; /* no need to perform a real lock at this point */ p_tmp_shared_globals = (zend_smm_shared_globals *) zend_shared_alloc(sizeof(zend_smm_shared_globals)); - tmp_shared_segments = zend_shared_alloc(shared_segments_array_size+ZSMMG(shared_segments_count)*sizeof(void *)); + tmp_shared_segments = zend_shared_alloc(shared_segments_array_size + ZSMMG(shared_segments_count) * sizeof(void *)); copy_shared_segments(tmp_shared_segments, ZSMMG(shared_segments)[0], ZSMMG(shared_segments_count), S_H(segment_type_size)()); *p_tmp_shared_globals = tmp_shared_globals; @@ -225,7 +225,7 @@ int zend_shared_alloc_startup(int requested_size) free(ZSMMG(shared_segments)); ZSMMG(shared_segments) = tmp_shared_segments; - ZSMMG(shared_memory_state).positions = (int *) zend_shared_alloc(sizeof(int)*ZSMMG(shared_segments_count)); + ZSMMG(shared_memory_state).positions = (int *)zend_shared_alloc(sizeof(int) * ZSMMG(shared_segments_count)); ZCG(locked) = 0; return res; @@ -240,12 +240,12 @@ void zend_shared_alloc_shutdown(void) tmp_shared_globals = *smm_shared_globals; smm_shared_globals = &tmp_shared_globals; - shared_segments_array_size = ZSMMG(shared_segments_count)*(S_H(segment_type_size)()+sizeof(void *)); + shared_segments_array_size = ZSMMG(shared_segments_count) * (S_H(segment_type_size)() + sizeof(void *)); tmp_shared_segments = emalloc(shared_segments_array_size); copy_shared_segments(tmp_shared_segments, ZSMMG(shared_segments)[0], ZSMMG(shared_segments_count), S_H(segment_type_size)()); ZSMMG(shared_segments) = tmp_shared_segments; - for(i=0; isize-ZSMMG(shared_segments)[i]->pos >= block_size) { /* found a valid block */ - zend_shared_memory_block_header *p = (zend_shared_memory_block_header *) (((char *) ZSMMG(shared_segments)[i]->p)+ZSMMG(shared_segments)[i]->pos); + for (i = 0; i < ZSMMG(shared_segments_count); i++) { + if (ZSMMG(shared_segments)[i]->size - ZSMMG(shared_segments)[i]->pos >= block_size) { /* found a valid block */ + zend_shared_memory_block_header *p = (zend_shared_memory_block_header *) (((char *) ZSMMG(shared_segments)[i]->p) + ZSMMG(shared_segments)[i]->pos); int remainder = block_size % PLATFORM_ALIGNMENT; void *retval; - if (remainder!=0) { - size += PLATFORM_ALIGNMENT-remainder; - block_size += PLATFORM_ALIGNMENT-remainder; + if (remainder != 0) { + size += PLATFORM_ALIGNMENT - remainder; + block_size += PLATFORM_ALIGNMENT - remainder; } ZSMMG(shared_segments)[i]->pos += block_size; ZSMMG(shared_free) -= block_size; p->size = size; - retval = ((char *) p)+sizeof(zend_shared_memory_block_header); + retval = ((char *) p) + sizeof(zend_shared_memory_block_header); memset(retval, 0, size); return retval; } @@ -303,7 +303,7 @@ int zend_shared_memdup_size(void *source, size_t size) { void **old_p; - if (zend_hash_index_find(&xlat_table, (ulong) source, (void **) &old_p)==SUCCESS) { + if (zend_hash_index_find(&xlat_table, (ulong)source, (void **)&old_p) == SUCCESS) { /* we already duplicated this pointer */ return 0; } @@ -315,7 +315,7 @@ void *_zend_shared_memdup(void *source, size_t size, zend_bool free_source TSRML { void **old_p, *retval; - if (zend_hash_index_find(&xlat_table, (ulong) source, (void **) &old_p)==SUCCESS) { + if (zend_hash_index_find(&xlat_table, (ulong)source, (void **)&old_p) == SUCCESS) { /* we already duplicated this pointer */ return *old_p; } @@ -407,14 +407,14 @@ void zend_shared_alloc_clear_xlat_table(void) void zend_shared_alloc_register_xlat_entry(const void *old, const void *new) { - zend_hash_index_update(&xlat_table, (ulong) old, (void*)&new, sizeof(void *), NULL); + zend_hash_index_update(&xlat_table, (ulong)old, (void*)&new, sizeof(void *), NULL); } void *zend_shared_alloc_get_xlat_entry(const void *old) { void **retval; - if (zend_hash_index_find(&xlat_table, (ulong) old, (void **) &retval)==FAILURE) { + if (zend_hash_index_find(&xlat_table, (ulong)old, (void **)&retval) == FAILURE) { return NULL; } return *retval; @@ -428,9 +428,9 @@ size_t zend_shared_alloc_get_free_memory(void) size_t zend_shared_alloc_get_largest_free_block(void) { int i; - size_t largest_block_size=0; + size_t largest_block_size = 0; - for (i=0; isize - ZSMMG(shared_segments)[i]->pos; if (block_size>largest_block_size) { @@ -444,7 +444,7 @@ void zend_shared_alloc_save_state(void) { int i; - for (i=0; ipos; } ZSMMG(shared_memory_state).shared_free = ZSMMG(shared_free); @@ -454,7 +454,7 @@ void zend_shared_alloc_restore_state(void) { int i; - for (i=0; ipos = ZSMMG(shared_memory_state).positions[i]; } ZSMMG(shared_free) = ZSMMG(shared_memory_state).shared_free; @@ -478,7 +478,7 @@ void zend_accel_shared_protect(int mode TSRMLS_DC) mode = PROT_READ|PROT_WRITE; } - for(i=0; i < ZSMMG(shared_segments_count); i++) { + for (i = 0; i < ZSMMG(shared_segments_count); i++) { mprotect(ZSMMG(shared_segments)[i]->p, ZSMMG(shared_segments)[i]->size, mode); } #endif From f1b76342d8f222f3b8c44756f6b35586ab48d1af Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 22 Feb 2013 13:38:32 +0400 Subject: [PATCH 067/276] We build a zend_extension (not a regular PHP module). --- config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index 6e178c1123e..e536bfc0bee 100644 --- a/config.m4 +++ b/config.m4 @@ -341,5 +341,5 @@ int main() { shared_alloc_mmap.c \ shared_alloc_posix.c \ Optimizer/zend_optimizer.c, - $ext_shared) + $ext_shared,,,,yes) fi From 56818541c791a35d666711eaddaa9b34fd7c84d8 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 22 Feb 2013 14:06:02 +0400 Subject: [PATCH 068/276] Started Test Suite --- tests/001_cli.phpt | 19 +++++++++++++++++++ tests/skipif.inc | 3 +++ 2 files changed, 22 insertions(+) create mode 100644 tests/001_cli.phpt create mode 100644 tests/skipif.inc diff --git a/tests/001_cli.phpt b/tests/001_cli.phpt new file mode 100644 index 00000000000..6c42049038c --- /dev/null +++ b/tests/001_cli.phpt @@ -0,0 +1,19 @@ +--TEST-- +001: O+ works in CLI +--INI-- +zend_optimizerplus.enable=1 +zend_optimizerplus.enable_cli=1 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +bool(true) +bool(true) +bool(true) diff --git a/tests/skipif.inc b/tests/skipif.inc new file mode 100644 index 00000000000..8652a94de74 --- /dev/null +++ b/tests/skipif.inc @@ -0,0 +1,3 @@ + From f2e8465017868f9f983afbf5eac6a4cc01ad0a48 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 22 Feb 2013 17:10:34 +0400 Subject: [PATCH 069/276] Fixed memory leak --- Optimizer/block_pass.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Optimizer/block_pass.c b/Optimizer/block_pass.c index f72cc582891..a65554c4ab7 100644 --- a/Optimizer/block_pass.c +++ b/Optimizer/block_pass.c @@ -114,6 +114,10 @@ static zend_code_block *find_code_blocks(zend_op_array *op_array) /* would not optimize non-optimized BRK/CONTs - we cannot really know where it jumps, so these optimizations are too dangerous */ + if (op_array->last_try_catch) { + efree(blocks->try); + efree(blocks->catch); + } efree(blocks); return NULL; #if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO From 4fe4b0d593de9ed192eb8bc09d0089a56aebda43 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 22 Feb 2013 17:22:43 +0400 Subject: [PATCH 070/276] Fixed memory leak --- ZendAccelerator.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index d3c3b14e9d8..c7ed4965d76 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -146,6 +146,9 @@ static ZEND_FUNCTION(accel_chdir) orig_chdir(INTERNAL_FUNCTION_PARAM_PASSTHRU); if (VCWD_GETCWD(cwd, MAXPATHLEN)) { + if (ZCG(cwd)) { + efree(ZCG(cwd)); + } ZCG(cwd_len) = strlen(cwd); ZCG(cwd) = estrndup(cwd, ZCG(cwd_len)); } else { From a9910f3ce21905ddb125edb18f490529ea18adfc Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 22 Feb 2013 18:09:26 +0400 Subject: [PATCH 071/276] white spaces --- ZendAccelerator.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index c7ed4965d76..eeb82deb308 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -145,18 +145,18 @@ static ZEND_FUNCTION(accel_chdir) char cwd[MAXPATHLEN]; orig_chdir(INTERNAL_FUNCTION_PARAM_PASSTHRU); - if (VCWD_GETCWD(cwd, MAXPATHLEN)) { - if (ZCG(cwd)) { - efree(ZCG(cwd)); + if (VCWD_GETCWD(cwd, MAXPATHLEN)) { + if (ZCG(cwd)) { + efree(ZCG(cwd)); } - ZCG(cwd_len) = strlen(cwd); - ZCG(cwd) = estrndup(cwd, ZCG(cwd_len)); - } else { - if (ZCG(cwd)) { - efree(ZCG(cwd)); - ZCG(cwd) = NULL; - } - } + ZCG(cwd_len) = strlen(cwd); + ZCG(cwd) = estrndup(cwd, ZCG(cwd_len)); + } else { + if (ZCG(cwd)) { + efree(ZCG(cwd)); + ZCG(cwd) = NULL; + } + } } static inline char* accel_getcwd(int *cwd_len TSRMLS_DC) @@ -165,12 +165,12 @@ static inline char* accel_getcwd(int *cwd_len TSRMLS_DC) *cwd_len = ZCG(cwd_len); return ZCG(cwd); } else { - char cwd[MAXPATHLEN + 1]; + char cwd[MAXPATHLEN + 1]; if (!VCWD_GETCWD(cwd, MAXPATHLEN)) { return NULL; } - *cwd_len = ZCG(cwd_len) = strlen(cwd); + *cwd_len = ZCG(cwd_len) = strlen(cwd); ZCG(cwd) = estrndup(cwd, ZCG(cwd_len)); return ZCG(cwd); } From a1afc0a1398ee1d18dab76c5c97c0a6da98531f3 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 23 Feb 2013 15:21:48 +0800 Subject: [PATCH 072/276] Simplify the install instructions --- README | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README b/README index 38549152425..16854be7661 100644 --- a/README +++ b/README @@ -18,20 +18,19 @@ Quick Install - Compile -export PHP_DIR=/usr/local/php5.5 -PHP_AUTOCONF=autoconf $PHP_DIR/bin/phpize -./configure \ + $PHP_DIR/phpize + ./configure \ --enable-optimizer-plus \ --with-php-config=$PHP_DIR/bin/php-config -make + make - Install -cp .libs/ZendOptimizerPlus.so $PHP_DIR/lib/ZendOptimizerPlus.so + make install - Edit php.ini -zend_extension=/...full path.../ZendOptimizerPlus.so + zend_extension=/...full path.../ZendOptimizerPlus.so NOTE: In case you are going to use Zend Optimizer+ together with Xdebug, be sure that Xdebug is loaded after Optimizer+. "php -v" must show Xdebug From 0d73c20d8757b7db40350251f5accb5de6e390b1 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 25 Feb 2013 09:59:39 +0400 Subject: [PATCH 073/276] Fixed compilation, when compiling right into PHP (Ilia Alshanetsky) --- Optimizer/block_pass.c | 2 +- Optimizer/pass1_5.c | 12 ++++++------ Optimizer/zend_optimizer.c | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Optimizer/block_pass.c b/Optimizer/block_pass.c index a65554c4ab7..acd149eeef1 100644 --- a/Optimizer/block_pass.c +++ b/Optimizer/block_pass.c @@ -630,7 +630,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, literal_dtor(arg); MAKE_NOP(sv); MAKE_NOP(fcall); - ZEND_OP1_LITERAL(opline) = zend_add_literal(op_array, &c TSRMLS_CC); + ZEND_OP1_LITERAL(opline) = zend_optimizer_add_literal(op_array, &c TSRMLS_CC); /* no copy ctor - get already copied it */ ZEND_OP1_TYPE(opline) = IS_CONST; } diff --git a/Optimizer/pass1_5.c b/Optimizer/pass1_5.c index 65e934efcdf..a2287ea3f94 100644 --- a/Optimizer/pass1_5.c +++ b/Optimizer/pass1_5.c @@ -71,7 +71,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { } else { ZEND_OP1_TYPE(tmp_opline) = IS_CONST; #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO - tmp_opline->op1.constant = zend_add_literal(op_array, &result TSRMLS_CC); + tmp_opline->op1.constant = zend_optimizer_add_literal(op_array, &result TSRMLS_CC); if (Z_TYPE(result) == IS_STRING) { Z_HASH_P(&ZEND_OP1_LITERAL(tmp_opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(tmp_opline)), Z_STRLEN(ZEND_OP1_LITERAL(tmp_opline)) + 1); if (tmp_opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || @@ -92,7 +92,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { ZEND_OP2(tmp_opline).var == tv) { ZEND_OP2_TYPE(tmp_opline) = IS_CONST; #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO - tmp_opline->op2.constant = zend_add_literal(op_array, &result TSRMLS_CC); + tmp_opline->op2.constant = zend_optimizer_add_literal(op_array, &result TSRMLS_CC); if (Z_TYPE(result) == IS_STRING) { Z_HASH_P(&ZEND_OP2_LITERAL(tmp_opline)) = zend_hash_func(Z_STRVAL(ZEND_OP2_LITERAL(tmp_opline)), Z_STRLEN(ZEND_OP2_LITERAL(tmp_opline)) + 1); if (tmp_opline->opcode == ZEND_FETCH_R || @@ -224,7 +224,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { } else { ZEND_OP1_TYPE(tmp_opline) = IS_CONST; #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO - tmp_opline->op1.constant = zend_add_literal(op_array, &result TSRMLS_CC); + tmp_opline->op1.constant = zend_optimizer_add_literal(op_array, &result TSRMLS_CC); #else ZEND_OP1_LITERAL(tmp_opline) = result; #endif @@ -235,7 +235,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { ZEND_OP2(tmp_opline).var == tv) { ZEND_OP2_TYPE(tmp_opline) = IS_CONST; #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO - tmp_opline->op2.constant = zend_add_literal(op_array, &result TSRMLS_CC); + tmp_opline->op2.constant = zend_optimizer_add_literal(op_array, &result TSRMLS_CC); #else ZEND_OP2_LITERAL(tmp_opline) = result; #endif @@ -334,7 +334,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { 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_add_literal(op_array, &offset TSRMLS_CC); + opline->op1.constant = zend_optimizer_add_literal(op_array, &offset TSRMLS_CC); #else ZEND_OP1_LITERAL(opline) = offset; #endif @@ -358,7 +358,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { 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_add_literal(op_array, &c TSRMLS_CC); + opline->op1.constant = zend_optimizer_add_literal(op_array, &c TSRMLS_CC); #else ZEND_OP1_LITERAL(opline) = c; #endif diff --git a/Optimizer/zend_optimizer.c b/Optimizer/zend_optimizer.c index b2b0c8878c7..e46e5a2ecec 100644 --- a/Optimizer/zend_optimizer.c +++ b/Optimizer/zend_optimizer.c @@ -29,7 +29,7 @@ ZCG(accel_directives).optimization_level #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO -int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) +int zend_optimizer_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) { int i = op_array->last_literal; op_array->last_literal++; @@ -55,13 +55,13 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) # define LITERAL_LONG(op, val) do { \ zval _c; \ ZVAL_LONG(&_c, val); \ - op.constant = zend_add_literal(op_array, &_c TSRMLS_CC); \ + op.constant = zend_optimizer_add_literal(op_array, &_c TSRMLS_CC); \ } while (0) # define LITERAL_BOOL(op, val) do { \ zval _c; \ ZVAL_BOOL(&_c, val); \ - op.constant = zend_add_literal(op_array, &_c TSRMLS_CC); \ + op.constant = zend_optimizer_add_literal(op_array, &_c TSRMLS_CC); \ } while (0) # define literal_dtor(zv) do { \ From 0c220d6fb3a9865a37eabbbc1ed5588c0aad5674 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 25 Feb 2013 10:04:03 +0400 Subject: [PATCH 074/276] Fixed build in a separate directory (Ilia Alshanetsky) --- config.m4 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config.m4 b/config.m4 index e536bfc0bee..19c8e9464c5 100644 --- a/config.m4 +++ b/config.m4 @@ -342,4 +342,6 @@ int main() { shared_alloc_posix.c \ Optimizer/zend_optimizer.c, $ext_shared,,,,yes) + + PHP_ADD_BUILD_DIR([$ext_builddir/Optimizer], 1) fi From ce69b869279d11e176ad19f361bf1dccfcdad5af Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 25 Feb 2013 10:35:59 +0400 Subject: [PATCH 075/276] Ability to disable O+ per process (or process pool) --- ZendAccelerator.c | 20 ++++++++++---------- zend_accelerator_module.c | 24 +++++++++++++----------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index eeb82deb308..eb540eddeb9 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -191,7 +191,7 @@ static ZEND_INI_MH(accel_include_path_on_modify) if (ZCG(include_path) && *ZCG(include_path)) { ZCG(include_path_len) = new_value_length; - if (accel_startup_ok && + if (ZCG(enabled) && accel_startup_ok && (ZCG(counted) || ZCSG(accelerator_enabled)) && !zend_accel_hash_is_full(&ZCSG(include_paths))) { @@ -900,7 +900,7 @@ char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_lengt include_path = ZCG(include_path); include_path_len = ZCG(include_path_len); if (ZCG(include_path_check) && - accel_startup_ok && + ZCG(enabled) && accel_startup_ok && (ZCG(counted) || ZCSG(accelerator_enabled)) && !zend_accel_hash_is_full(&ZCSG(include_paths))) { @@ -1291,7 +1291,7 @@ static zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int int from_shared_memory; /* if the script we've got is stored in SHM */ if (!file_handle->filename || - !accel_startup_ok || + !ZCG(enabled) || !accel_startup_ok || (!ZCG(counted) && !ZCSG(accelerator_enabled)) || CG(interactive) || (ZCSG(restart_in_progress) && accel_restart_is_active(TSRMLS_C))) { @@ -1597,7 +1597,7 @@ static char *accel_php_resolve_path(const char *filename, int filename_length, c /* zend_stream_open_function() replacement for PHP 5.2 */ static int persistent_stream_open_function(const char *filename, zend_file_handle *handle TSRMLS_DC) { - if (accel_startup_ok && + if (ZCG(enabled) && accel_startup_ok && (ZCG(counted) || ZCSG(accelerator_enabled)) && !CG(interactive) && !ZCSG(restart_in_progress)) { @@ -1693,7 +1693,7 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl /* zend_stream_open_function() replacement for PHP 5.3 and above */ static int persistent_stream_open_function(const char *filename, zend_file_handle *handle TSRMLS_DC) { - if (accel_startup_ok && + if (ZCG(enabled) && accel_startup_ok && (ZCG(counted) || ZCSG(accelerator_enabled)) && !CG(interactive) && !ZCSG(restart_in_progress)) { @@ -1758,7 +1758,7 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl /* zend_resolve_path() replacement for PHP 5.3 and above */ static char* persistent_zend_resolve_path(const char *filename, int filename_len TSRMLS_DC) { - if (accel_startup_ok && + if (ZCG(enabled) && accel_startup_ok && (ZCG(counted) || ZCSG(accelerator_enabled)) && !CG(interactive) && !ZCSG(restart_in_progress)) { @@ -1864,7 +1864,7 @@ static void accel_activate(void) { TSRMLS_FETCH(); - if (!accel_startup_ok) { + if (!ZCG(enabled) || !accel_startup_ok) { return; } @@ -2116,7 +2116,7 @@ static void accel_deactivate(void) */ TSRMLS_FETCH(); - if (!accel_startup_ok) { + if (!ZCG(enabled) || !accel_startup_ok) { return; } @@ -2442,7 +2442,7 @@ static void accel_shutdown(zend_extension *extension) zend_accel_blacklist_shutdown(&accel_blacklist); - if (!accel_startup_ok) { + if (!ZCG(enabled) || !accel_startup_ok) { accel_free_ts_resources(); return; } @@ -2528,7 +2528,7 @@ static void accel_op_array_handler(zend_op_array *op_array) { TSRMLS_FETCH(); - if (accel_startup_ok && ZCSG(accelerator_enabled)) { + if (ZCG(enabled) && accel_startup_ok && ZCSG(accelerator_enabled)) { zend_optimizer(op_array TSRMLS_CC); } } diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index 45ed12a9af6..58fc48d030d 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -342,7 +342,7 @@ static ZEND_MINIT_FUNCTION(zend_accelerator) void zend_accel_override_file_functions(TSRMLS_D) { zend_function *old_function; - if (accel_startup_ok && ZCG(accel_directives).file_override_enabled) { + if (ZCG(enabled) && accel_startup_ok && ZCG(accel_directives).file_override_enabled) { /* override file_exists */ if (zend_hash_find(CG(function_table), "file_exists", sizeof("file_exists"), (void **)&old_function) == SUCCESS) { old_function->internal_function.handler = accel_file_exists; @@ -368,7 +368,7 @@ void zend_accel_info(ZEND_MODULE_INFO_FUNC_ARGS) { php_info_print_table_start(); - if (accel_startup_ok && ZCSG(accelerator_enabled)) { + if (ZCG(enabled) && accel_startup_ok && ZCSG(accelerator_enabled)) { php_info_print_table_row(2, "Opcode Caching", "Up and Running"); } else { php_info_print_table_row(2, "Opcode Caching", "Disabled"); @@ -378,11 +378,13 @@ void zend_accel_info(ZEND_MODULE_INFO_FUNC_ARGS) } else { php_info_print_table_row(2, "Optimization", "Disabled"); } - if (!accel_startup_ok || zps_api_failure_reason) { - php_info_print_table_row(2, "Startup Failed", zps_api_failure_reason); - } else { - php_info_print_table_row(2, "Startup", "OK"); - php_info_print_table_row(2, "Shared memory model", zend_accel_get_shared_model()); + if (ZCG(enabled)) { + if (!accel_startup_ok || zps_api_failure_reason) { + php_info_print_table_row(2, "Startup Failed", zps_api_failure_reason); + } else { + php_info_print_table_row(2, "Startup", "OK"); + php_info_print_table_row(2, "Shared memory model", zend_accel_get_shared_model()); + } } php_info_print_table_end(); @@ -418,7 +420,7 @@ static zval* accelerator_get_scripts(TSRMLS_D) struct timeval exec_time; struct timeval fetch_time; - if (!accel_startup_ok || !ZCSG(accelerator_enabled) || accelerator_shm_read_lock(TSRMLS_C) != SUCCESS) { + if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled) || accelerator_shm_read_lock(TSRMLS_C) != SUCCESS) { return 0; } @@ -464,14 +466,14 @@ static ZEND_FUNCTION(accelerator_get_status) /* keep the compiler happy */ (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; - if (!accel_startup_ok || !ZCSG(accelerator_enabled)) { + if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled)) { RETURN_FALSE; } array_init(return_value); /* Trivia */ - add_assoc_bool(return_value, "accelerator_enabled", 1 /*accel_startup_ok && ZCSG(accelerator_enabled)*/); + add_assoc_bool(return_value, "accelerator_enabled", 1 /*ZCG(enabled) && accel_startup_ok && ZCSG(accelerator_enabled)*/); add_assoc_bool(return_value, "cache_full", ZSMMG(memory_exhausted)); /* Memory usage statistics */ @@ -576,7 +578,7 @@ static ZEND_FUNCTION(accelerator_reset) /* keep the compiler happy */ (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; - if (!accel_startup_ok || !ZCSG(accelerator_enabled)) { + if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled)) { RETURN_FALSE; } From c58b89947079606cd3937333a89bee4599941d69 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 25 Feb 2013 14:45:03 +0800 Subject: [PATCH 076/276] remove useless configure option --- README | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README b/README index 16854be7661..b2c060c58f3 100644 --- a/README +++ b/README @@ -20,13 +20,12 @@ Quick Install $PHP_DIR/phpize ./configure \ - --enable-optimizer-plus \ --with-php-config=$PHP_DIR/bin/php-config make - Install - make install + make install # this will copy ZendOptimizerPlus.so into PHP extension directory - Edit php.ini From 3da5b830c2233da590ae2ccd0ab4d82e37009c7c Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 25 Feb 2013 15:29:54 +0800 Subject: [PATCH 077/276] coding style improve --- Optimizer/block_pass.c | 32 ++++++++++++------------- Optimizer/nop_removal.c | 2 +- Optimizer/optimize_temp_vars_5.c | 16 ++++++------- Optimizer/pass1_5.c | 10 ++++---- Optimizer/pass3.c | 10 ++++---- ZendAccelerator.c | 5 ++-- ZendAccelerator.h | 8 +++---- shared_alloc_win32.c | 30 +++++++++++++----------- zend_accelerator_blacklist.c | 2 +- zend_accelerator_module.c | 40 ++++++++++++++++---------------- zend_persist.c | 4 ++-- zend_persist_calc.c | 2 +- 12 files changed, 83 insertions(+), 78 deletions(-) diff --git a/Optimizer/block_pass.c b/Optimizer/block_pass.c index acd149eeef1..77af8d70cb6 100644 --- a/Optimizer/block_pass.c +++ b/Optimizer/block_pass.c @@ -42,7 +42,7 @@ static int zend_get_persistent_constant(char *name, uint name_len, zval *result, static inline void print_block(zend_code_block *block, zend_op *opcodes, char *txt) { - fprintf(stderr, "%sBlock: %d-%d (%d)", txt, block->start_opline - opcodes, block->start_opline - opcodes+block->len-1, block->len); + fprintf(stderr, "%sBlock: %d-%d (%d)", txt, block->start_opline - opcodes, block->start_opline - opcodes + block->len - 1, block->len); if (!block->access) { fprintf(stderr, " unused"); } @@ -229,7 +229,7 @@ static zend_code_block *find_code_blocks(zend_op_array *op_array) } } cur_block->len = end - cur_block->start_opline; - cur_block->next = &blocks[op_array->last+1]; + cur_block->next = &blocks[op_array->last + 1]; print_block(cur_block, op_array->opcodes, ""); /* The op_array doesn't have BRK, CONT, GOTO opcodes anyway */ @@ -787,7 +787,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, memcpy(tmp, Z_STRVAL(ZEND_OP1_LITERAL(last_op)), l + 1); Z_STRVAL(ZEND_OP1_LITERAL(last_op)) = tmp; } else { - Z_STRVAL(ZEND_OP1_LITERAL(last_op)) = erealloc(Z_STRVAL(ZEND_OP1_LITERAL(last_op)), l+1); + Z_STRVAL(ZEND_OP1_LITERAL(last_op)) = erealloc(Z_STRVAL(ZEND_OP1_LITERAL(last_op)), l + 1); } memcpy(Z_STRVAL(ZEND_OP1_LITERAL(last_op))+Z_STRLEN(ZEND_OP1_LITERAL(last_op)), Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline))); Z_STRVAL(ZEND_OP1_LITERAL(last_op))[l] = '\0'; @@ -1058,7 +1058,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, /* strip the inside NOPs */ opline = block->start_opline; - end = opline+block->len; + end = opline + block->len; while (opline < end) { if (opline->opcode == ZEND_NOP) { zend_op *nop = opline + 1; @@ -1087,17 +1087,17 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, /* Rebuild plain (optimized) op_array from CFG */ static void assemble_code_blocks(zend_code_block *blocks, zend_op_array *op_array) { - zend_op *new_opcodes = emalloc(op_array->last*sizeof(zend_op)); + zend_op *new_opcodes = emalloc(op_array->last * sizeof(zend_op)); zend_op *opline = new_opcodes; zend_code_block *cur_block = blocks; /* Copy code of reachable blocks into a single buffer */ while (cur_block) { if (cur_block->access) { - memcpy(opline, cur_block->start_opline, cur_block->len*sizeof(zend_op)); + memcpy(opline, cur_block->start_opline, cur_block->len * sizeof(zend_op)); cur_block->start_opline = opline; opline += cur_block->len; - if ((opline-1)->opcode == ZEND_JMP) { + if ((opline - 1)->opcode == ZEND_JMP) { zend_code_block *next; next = cur_block->next; while (next && !next->access) { @@ -1107,7 +1107,7 @@ static void assemble_code_blocks(zend_code_block *blocks, zend_op_array *op_arra /* JMP to the next block - strip it */ cur_block->follow_to = cur_block->op1_to; cur_block->op1_to = NULL; - MAKE_NOP((opline-1)); + MAKE_NOP((opline - 1)); opline--; cur_block->len--; } @@ -1115,7 +1115,7 @@ static void assemble_code_blocks(zend_code_block *blocks, zend_op_array *op_arra } else { /* this block will not be used, delete all constants there */ zend_op *_opl; - zend_op *end = cur_block->start_opline+cur_block->len; + zend_op *end = cur_block->start_opline + cur_block->len; for (_opl = cur_block->start_opline; _opl && _opl < end; _opl++) { if (ZEND_OP1_TYPE(_opl) == IS_CONST) { literal_dtor(&ZEND_OP1_LITERAL(_opl)); @@ -1160,18 +1160,18 @@ static void assemble_code_blocks(zend_code_block *blocks, zend_op_array *op_arra continue; } if (cur_block->op1_to) { - ZEND_OP1(&cur_block->start_opline[cur_block->len-1]).opline_num = cur_block->op1_to->start_opline - new_opcodes; + ZEND_OP1(&cur_block->start_opline[cur_block->len - 1]).opline_num = cur_block->op1_to->start_opline - new_opcodes; } if (cur_block->op2_to) { - ZEND_OP2(&cur_block->start_opline[cur_block->len-1]).opline_num = cur_block->op2_to->start_opline - new_opcodes; + ZEND_OP2(&cur_block->start_opline[cur_block->len - 1]).opline_num = cur_block->op2_to->start_opline - new_opcodes; } if (cur_block->ext_to) { - cur_block->start_opline[cur_block->len-1].extended_value = cur_block->ext_to->start_opline - new_opcodes; + cur_block->start_opline[cur_block->len - 1].extended_value = cur_block->ext_to->start_opline - new_opcodes; } print_block(cur_block, new_opcodes, "Out "); } efree(op_array->opcodes); - op_array->opcodes = erealloc(new_opcodes, op_array->last*sizeof(zend_op)); + op_array->opcodes = erealloc(new_opcodes, op_array->last * sizeof(zend_op)); #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO /* adjust early binding list */ @@ -1738,7 +1738,7 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char * while (next_block) { zend_op *opline = next_block->start_opline; - zend_op *end = opline+next_block->len; + zend_op *end = opline + next_block->len; if (!next_block->access) { next_block = next_block->next; @@ -1768,14 +1768,14 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char * #if DEBUG_BLOCKPASS { int i; - for (i=0; i< op_array->T; i++) { + for (i = 0; i< op_array->T; i++) { fprintf(stderr, "T%d: %c\n", i, used_ext[i] + '0'); } } #endif while (block) { - zend_op *opline = block->start_opline+block->len - 1; + zend_op *opline = block->start_opline + block->len - 1; if (!block->access) { block = block->next; diff --git a/Optimizer/nop_removal.c b/Optimizer/nop_removal.c index ccac6f4540a..b2fb667ed55 100644 --- a/Optimizer/nop_removal.c +++ b/Optimizer/nop_removal.c @@ -12,7 +12,7 @@ static void nop_removal(zend_op_array *op_array) shiftlist = (zend_uint *)DO_ALLOCA(sizeof(zend_uint) * op_array->last); i = new_count = shift = 0; - end = op_array->opcodes+op_array->last; + end = op_array->opcodes + op_array->last; for (opline = op_array->opcodes; opline < end; opline++) { #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO diff --git a/Optimizer/optimize_temp_vars_5.c b/Optimizer/optimize_temp_vars_5.c index 7cf43bf11e8..976a7b21acc 100644 --- a/Optimizer/optimize_temp_vars_5.c +++ b/Optimizer/optimize_temp_vars_5.c @@ -84,12 +84,12 @@ static void optimize_temporary_variables(zend_op_array *op_array) int var_to_free = -1; taken_T = (char *) emalloc(T); - start_of_T = (zend_op **) emalloc(T*sizeof(zend_op *)); + start_of_T = (zend_op **) emalloc(T * sizeof(zend_op *)); valid_T = (char *) emalloc(T); - map_T = (int *) emalloc(T*sizeof(int)); + map_T = (int *) emalloc(T * sizeof(int)); end = op_array->opcodes; - opline = &op_array->opcodes[op_array->last-1]; + opline = &op_array->opcodes[op_array->last - 1]; /* Find T definition points */ while (opline >= end) { @@ -111,7 +111,7 @@ static void optimize_temporary_variables(zend_op_array *op_array) memset(taken_T, 0, T); end = op_array->opcodes; - opline = &op_array->opcodes[op_array->last-1]; + opline = &op_array->opcodes[op_array->last - 1]; while (opline >= end) { if ((ZEND_OP1_TYPE(opline) & (IS_VAR | IS_TMP_VAR)) @@ -166,14 +166,14 @@ static void optimize_temporary_variables(zend_op_array *op_array) /* Allocate OP_DATA->op2 after "opernds", but before "result" */ if (opline->opcode == ZEND_ASSIGN_DIM && - (opline+1)->opcode == ZEND_OP_DATA && - ZEND_OP2_TYPE(opline+1) & (IS_VAR | IS_TMP_VAR)) { - currT = VAR_NUM(ZEND_OP2(opline+1).var); + (opline + 1)->opcode == ZEND_OP_DATA && + ZEND_OP2_TYPE(opline + 1) & (IS_VAR | IS_TMP_VAR)) { + currT = VAR_NUM(ZEND_OP2(opline + 1).var); GET_AVAILABLE_T(); map_T[currT] = i; valid_T[currT] = 1; taken_T[i] = 0; - ZEND_OP2(opline+1).var = NUM_VAR(i); + ZEND_OP2(opline + 1).var = NUM_VAR(i); var_to_free = i; } diff --git a/Optimizer/pass1_5.c b/Optimizer/pass1_5.c index a2287ea3f94..7a69689fa73 100644 --- a/Optimizer/pass1_5.c +++ b/Optimizer/pass1_5.c @@ -274,8 +274,8 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { break; } last_op = next_op; - final_length += (requires_conversion ? 1 : ZEND_OP2_LITERAL(opline).value.str.len); - ptr = (char *)emalloc(final_length+1); + final_length += (requires_conversion? 1 : ZEND_OP2_LITERAL(opline).value.str.len); + ptr = (char *)emalloc(final_length + 1); ptr[final_length] = '\0'; if (requires_conversion) { /* ZEND_ADD_CHAR */ char chval = (char)ZEND_OP2_LITERAL(opline).value.lval; @@ -321,8 +321,8 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { if (ZEND_OP1_TYPE(opline) == IS_UNUSED && ZEND_OP2_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING && - Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("__COMPILER_HALT_OFFSET__")-1 && - memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1) == 0) { + Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("__COMPILER_HALT_OFFSET__") - 1 && + memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) { /* substitute __COMPILER_HALT_OFFSET__ constant */ zend_bool orig_in_execution = EG(in_execution); zend_op_array *orig_op_array = EG(active_op_array); @@ -330,7 +330,7 @@ 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)) { + if (zend_get_constant("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1, &offset TSRMLS_CC)) { literal_dtor(&ZEND_OP2_LITERAL(opline)); ZEND_OP1_TYPE(opline) = IS_CONST; #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO diff --git a/Optimizer/pass3.c b/Optimizer/pass3.c index 269f523e981..fd2a1900097 100644 --- a/Optimizer/pass3.c +++ b/Optimizer/pass3.c @@ -26,7 +26,7 @@ if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) { zend_op *opline; - zend_op *end = op_array->opcodes+op_array->last; + zend_op *end = op_array->opcodes + op_array->last; zend_uint *jmp_hitlist; int jmp_hitlist_count; int i; @@ -204,7 +204,7 @@ if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) { /* JMPZ(X,L1), L1: JMPZ(X,L2) => JMPZ(X,L2), L1: JMPZ(X,L2) */ CHECK_JMP2(target, done_jmp_optimization); ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num; - } else if (op_array->opcodes[target].opcode == opline->opcode+3 && + } else if (op_array->opcodes[target].opcode == opline->opcode + 3 && SAME_VAR(opline->op1, op_array->opcodes[target].op1)) { /* convert JMPZ(X,L1), L1: T JMPZ_EX(X,L2) to T = JMPZ_EX(X, L2) */ @@ -215,13 +215,13 @@ if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) { SAME_VAR(opline->op1, op_array->opcodes[target].op1)) { /* convert JMPZ(X,L1), L1: JMPNZ(X,L2) to JMPZ(X,L1+1) */ - ZEND_OP2(opline).opline_num = target+1; + ZEND_OP2(opline).opline_num = target + 1; break; } else if (op_array->opcodes[target].opcode == INV_COND_EX(opline->opcode) && SAME_VAR(opline->op1, op_array->opcodes[target].op1)) { /* convert JMPZ(X,L1), L1: T = JMPNZ_EX(X,L2) to T = JMPZ_EX(X,L1+1) */ - ZEND_OP2(opline).opline_num = target+1; + ZEND_OP2(opline).opline_num = target + 1; opline->opcode += 3; COPY_NODE(opline->result, op_array->opcodes[target].result); break; @@ -284,7 +284,7 @@ if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) { SAME_VAR(opline->op1, op_array->opcodes[target].op1)) { /* convert JMPZ_EX(X,L1), L1: JMPNZ_EX(X,L2) to JMPZ_EX(X,L1+1) */ - ZEND_OP2(opline).opline_num = target+1; + ZEND_OP2(opline).opline_num = target + 1; break; } else { break; diff --git a/ZendAccelerator.c b/ZendAccelerator.c index eb540eddeb9..7f1c8f84b2b 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -682,8 +682,9 @@ static accel_time_t zend_get_file_handle_timestamp_win(zend_file_handle *file_ha if (GetFileAttributesEx(file_handle->opened_path, GetFileExInfoStandard, &fdata) != 0) { unsigned __int64 ftime; - if (CompareFileTime (&fdata.ftLastWriteTime, &utc_base_ft) < 0) + if (CompareFileTime (&fdata.ftLastWriteTime, &utc_base_ft) < 0) { return 0; + } ftime = (((unsigned __int64)fdata.ftLastWriteTime.dwHighDateTime) << 32) + fdata.ftLastWriteTime.dwLowDateTime - utc_base; ftime /= 10000000L; @@ -943,7 +944,7 @@ char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_lengt } /* Calculate key length */ - key_length = cwd_len + path_length+include_path_len + 2; + key_length = cwd_len + path_length + include_path_len + 2; if (parent_script_len) { key_length += parent_script_len + 1; } diff --git a/ZendAccelerator.h b/ZendAccelerator.h index 230ee865441..83e7cd185ed 100644 --- a/ZendAccelerator.h +++ b/ZendAccelerator.h @@ -143,16 +143,16 @@ extern int lock_file; #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO # ifdef ALLOCA_FLAG - #define DO_ALLOCA(x) do_alloca_with_limit(x,use_heap) - #define FREE_ALLOCA(x) free_alloca_with_limit(x,use_heap) + #define DO_ALLOCA(x) do_alloca_with_limit(x, use_heap) + #define FREE_ALLOCA(x) free_alloca_with_limit(x, use_heap) # else #define ALLOCA_FLAG(x) #define DO_ALLOCA(x) do_alloca(x) #define FREE_ALLOCA(x) free_alloca(x) # endif #else - #define DO_ALLOCA(x) do_alloca(x,use_heap) - #define FREE_ALLOCA(x) free_alloca(x,use_heap) + #define DO_ALLOCA(x) do_alloca(x, use_heap) + #define FREE_ALLOCA(x) free_alloca(x, use_heap) #endif diff --git a/shared_alloc_win32.c b/shared_alloc_win32.c index 40f941d1c01..819ef5cc3cd 100644 --- a/shared_alloc_win32.c +++ b/shared_alloc_win32.c @@ -76,26 +76,26 @@ static void zend_win_error_message(int type, char *msg, int err) static char *create_name_with_username(char *name) { - static char newname[MAXPATHLEN+UNLEN+4]; - char uname[UNLEN+1]; + static char newname[MAXPATHLEN + UNLEN + 4]; + char uname[UNLEN + 1]; DWORD unsize = UNLEN; GetUserName(uname, &unsize); - snprintf(newname, sizeof(newname)-1, "%s@%s", name, uname); + snprintf(newname, sizeof(newname) - 1, "%s@%s", name, uname); return newname; } static char *get_mmap_base_file() { - static char windir[MAXPATHLEN+UNLEN+3+sizeof("\\\\@")]; - char uname[UNLEN+1]; + static char windir[MAXPATHLEN+UNLEN + 3 + sizeof("\\\\@")]; + char uname[UNLEN + 1]; DWORD unsize = UNLEN; int l; GetTempPath(MAXPATHLEN, windir); GetUserName(uname, &unsize); l = strlen(windir); - snprintf(windir+l, sizeof(windir)-l-1, "\\%s@%s", ACCEL_FILEMAP_BASE, uname); + snprintf(windir + l, sizeof(windir) - l - 1, "\\%s@%s", ACCEL_FILEMAP_BASE, uname); return windir; } @@ -187,8 +187,9 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ do { memfile = OpenFileMapping(FILE_MAP_WRITE, 0, create_name_with_username(ACCEL_FILEMAP_NAME)); err = GetLastError(); - if (memfile == NULL) + if (memfile == NULL) { break; + } ret = zend_shared_alloc_reattach(requested_size, error_in); err = GetLastError(); @@ -196,7 +197,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ /* Mapping failed, wait for mapping object to get freed and retry */ CloseHandle(memfile); memfile = NULL; - Sleep(1000*(map_retries+1)); + Sleep(1000 * (map_retries + 1)); } else { return ret; } @@ -242,9 +243,10 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); if (! GetVersionEx ((OSVERSIONINFO *) &osvi)) { - osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); - if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (!GetVersionEx((OSVERSIONINFO *)&osvi)) { break; + } } GetSystemInfo(&si); @@ -252,8 +254,9 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ /* Are we running Vista ? */ if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion == 6) { /* Assert that platform is 32 bit (for 64 bit we need to test a different set */ - if (si.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL) + if (si.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL) { DebugBreak(); + } wanted_mapping_base = vista_mapping_base_set; } @@ -262,7 +265,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ char *s = ZCG(accel_directives).mmap_base; /* skip leading 0x, %p assumes hexdeciaml format anyway */ - if (*s == '0' && *(s+1) == 'x') { + if (*s == '0' && *(s + 1) == 'x') { s += 2; } if (sscanf(s, "%p", &default_mapping_base_set[0]) != 1) { @@ -273,8 +276,9 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ do { shared_segment->p = mapping_base = MapViewOfFileEx(memfile, FILE_MAP_ALL_ACCESS, 0, 0, 0, *wanted_mapping_base); - if (*wanted_mapping_base == NULL) /* Auto address (NULL) is the last option on the array */ + if (*wanted_mapping_base == NULL) { /* Auto address (NULL) is the last option on the array */ break; + } wanted_mapping_base++; } while (!mapping_base); diff --git a/zend_accelerator_blacklist.c b/zend_accelerator_blacklist.c index f3fd91236eb..5191fdb0209 100644 --- a/zend_accelerator_blacklist.c +++ b/zend_accelerator_blacklist.c @@ -98,7 +98,7 @@ static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist) regexp[1] = '('; clen = 2; - for (j = end; j <= i ;j++) { + for (j = end; j <= i; j++) { int c; if (j != end) { diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index 58fc48d030d..04133f64b65 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -66,7 +66,7 @@ static ZEND_INI_MH(OnUpdateMemoryConsumption) /* keep the compiler happy */ (void)entry; (void)new_value_length; (void)mh_arg2; (void)mh_arg3; (void)stage; - p = (long *) (base+(size_t) mh_arg1); + p = (long *) (base + (size_t)mh_arg1); memsize = atoi(new_value); /* sanity check we must use at least 8 MB */ if (memsize < 8) { @@ -74,8 +74,8 @@ static ZEND_INI_MH(OnUpdateMemoryConsumption) zend_ini_entry *ini_entry; memsize = 8; - zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.memory_consumption is set below the required 8MB.\n" ); - zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the minimal 8MB cofiguration.\n" ); + zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.memory_consumption is set below the required 8MB.\n"); + zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the minimal 8MB cofiguration.\n"); if (zend_hash_find(EG(ini_directives), "zend_optimizerplus.memory_consumption", @@ -104,7 +104,7 @@ static ZEND_INI_MH(OnUpdateMaxAcceleratedFiles) /* keep the compiler happy */ (void)entry; (void)new_value_length; (void)mh_arg2; (void)mh_arg3; (void)stage; - p = (long *) (base+(size_t) mh_arg1); + p = (long *) (base + (size_t)mh_arg1); size = atoi(new_value); /* sanity check we must use a value between MIN_ACCEL_FILES and MAX_ACCEL_FILES */ @@ -115,14 +115,14 @@ static ZEND_INI_MH(OnUpdateMaxAcceleratedFiles) if (size < MIN_ACCEL_FILES) { size = MIN_ACCEL_FILES; new_new_value = TOKENTOSTR(MIN_ACCEL_FILES); - zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.max_accelerated_files is set below the required minimum (%d).\n", MIN_ACCEL_FILES ); - zend_accel_error(ACCEL_LOG_WARNING,ACCELERATOR_PRODUCT_NAME " will use the minimal cofiguration.\n" ); + zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.max_accelerated_files is set below the required minimum (%d).\n", MIN_ACCEL_FILES); + zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the minimal cofiguration.\n"); } if (size > MAX_ACCEL_FILES) { size = MAX_ACCEL_FILES; new_new_value = TOKENTOSTR(MAX_ACCEL_FILES); - zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.max_accelerated_files is set above the limit (%d).\n", MAX_ACCEL_FILES ); - zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the maximal cofiguration.\n" ); + zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.max_accelerated_files is set above the limit (%d).\n", MAX_ACCEL_FILES); + zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the maximal cofiguration.\n"); } if (zend_hash_find(EG(ini_directives), "zend_optimizerplus.max_accelerated_files", @@ -150,7 +150,7 @@ static ZEND_INI_MH(OnUpdateMaxWastedPercentage) /* keep the compiler happy */ (void)entry; (void)new_value_length; (void)mh_arg2; (void)mh_arg3; (void)stage; - p = (double *) (base+(size_t) mh_arg1); + p = (double *) (base + (size_t)mh_arg1); percentage = atoi(new_value); if (percentage <= 0 || percentage > 50) { @@ -159,7 +159,7 @@ static ZEND_INI_MH(OnUpdateMaxWastedPercentage) percentage = 5; zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.max_wasted_percentage must be ser netweeb 1 and 50.\n"); - zend_accel_error(ACCEL_LOG_WARNING,ACCELERATOR_PRODUCT_NAME " will use 5%.\n" ); + zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use 5%.\n"); if (zend_hash_find(EG(ini_directives), "zend_optimizerplus.max_wasted_percentage", sizeof("zend_optimizerplus.max_wasted_percentage"), @@ -189,7 +189,7 @@ static ZEND_INI_MH(OnUpdateAccelBlacklist) return FAILURE; } - p = (char **) (base+(size_t) mh_arg1); + p = (char **) (base + (size_t)mh_arg1); *p = new_value; zend_accel_blacklist_init(&accel_blacklist); @@ -244,7 +244,7 @@ static int ZEND_DECLARE_INHERITED_CLASS_DELAYED_HANDLER(ZEND_OPCODE_HANDLER_ARGS { zend_class_entry **pce, **pce_orig; - if (zend_hash_find(EG(class_table), Z_STRVAL(EX(opline)->op2.u.constant), Z_STRLEN(EX(opline)->op2.u.constant)+1, (void **)&pce) == FAILURE || + if (zend_hash_find(EG(class_table), Z_STRVAL(EX(opline)->op2.u.constant), Z_STRLEN(EX(opline)->op2.u.constant) + 1, (void **)&pce) == FAILURE || (zend_hash_find(EG(class_table), Z_STRVAL(EX(opline)->op1.u.constant), Z_STRLEN(EX(opline)->op1.u.constant), (void**)&pce_orig) == SUCCESS && *pce != *pce_orig)) { do_bind_inherited_class(EX(opline), EG(class_table), EX_T(EX(opline)->extended_value).class_entry, 0 TSRMLS_CC); @@ -265,14 +265,14 @@ static int filename_is_in_cache(char *filename, int filename_len TSRMLS_DC) handle.type = ZEND_HANDLE_FILENAME; if (IS_ABSOLUTE_PATH(filename, filename_len)) { - persistent_script = zend_accel_hash_find(&ZCSG(hash), filename, filename_len+1); + persistent_script = zend_accel_hash_find(&ZCSG(hash), filename, filename_len + 1); if (persistent_script) { return !persistent_script->corrupted; } } if ((key = accel_make_persistent_key_ex(&handle, filename_len, &key_length TSRMLS_CC)) != NULL) { - persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length+1); + persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length + 1); return persistent_script && !persistent_script->corrupted; } @@ -483,7 +483,7 @@ static ZEND_FUNCTION(accelerator_get_status) add_assoc_long(memory_usage, "free_memory", zend_shared_alloc_get_free_memory()); add_assoc_long(memory_usage, "wasted_memory", ZSMMG(wasted_shared_memory)); add_assoc_double(memory_usage, "current_wasted_percentage", (((double) ZSMMG(wasted_shared_memory))/ZCG(accel_directives).memory_consumption)*100.0); - add_assoc_zval(return_value, "memory_usage",memory_usage); + add_assoc_zval(return_value, "memory_usage", memory_usage); /* Accelerator statistics */ MAKE_STD_ZVAL(statistics); @@ -497,12 +497,12 @@ static ZEND_FUNCTION(accelerator_get_status) reqs = ZCSG(hits)+ZCSG(misses); add_assoc_double(statistics, "blacklist_miss_ratio", reqs?(((double) ZCSG(blacklist_misses))/reqs)*100.0:0); add_assoc_double(statistics, "accelerator_hit_rate", reqs?(((double) ZCSG(hits))/reqs)*100.0:0); - add_assoc_zval(return_value, "accelerator_statistics",statistics); + add_assoc_zval(return_value, "accelerator_statistics", statistics); /* acceleratred scripts */ scripts = accelerator_get_scripts(TSRMLS_C); if (scripts) { - add_assoc_zval(return_value, "scripts",scripts); + add_assoc_zval(return_value, "scripts", scripts); } } @@ -555,20 +555,20 @@ static ZEND_FUNCTION(accelerator_get_configuration) add_assoc_bool(directives, "zend_optimizerplus.enable_file_override", ZCG(accel_directives).file_override_enabled); add_assoc_long(directives, "zend_optimizerplus.optimization_level", ZCG(accel_directives).optimization_level); - add_assoc_zval(return_value, "directives",directives); + add_assoc_zval(return_value, "directives", directives); /*version */ MAKE_STD_ZVAL(version); array_init(version); add_assoc_string(version, "version", ACCELERATOR_VERSION, 1); add_assoc_string(version, "accelerator_product_name", ACCELERATOR_PRODUCT_NAME, 1); - add_assoc_zval(return_value, "version",version); + add_assoc_zval(return_value, "version", version); /* blacklist */ MAKE_STD_ZVAL(blacklist); array_init(blacklist); zend_accel_blacklist_apply(&accel_blacklist, (apply_func_arg_t) add_blacklist_path, blacklist TSRMLS_CC); - add_assoc_zval(return_value, "blacklist",blacklist); + add_assoc_zval(return_value, "blacklist", blacklist); } /* {{{ proto void accelerator_reset() diff --git a/zend_persist.c b/zend_persist.c index f3438a05bf4..9efd028e99b 100644 --- a/zend_persist.c +++ b/zend_persist.c @@ -169,7 +169,7 @@ static void zend_persist_zval_ptr(zval **zp TSRMLS_DC) static void zend_protect_zval(zval *z TSRMLS_DC) { PZ_SET_ISREF_P(z); - PZ_SET_REFCOUNT_P(z,2); + PZ_SET_REFCOUNT_P(z, 2); } static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_script* main_persistent_script TSRMLS_DC) @@ -245,7 +245,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc zend_op *end = new_opcodes + op_array->last; int offset = 0; - for (;opline PHP_5_3_X_API_NO opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals)); diff --git a/zend_persist_calc.c b/zend_persist_calc.c index 72755325bfc..00c8784a84b 100644 --- a/zend_persist_calc.c +++ b/zend_persist_calc.c @@ -178,7 +178,7 @@ static uint zend_persist_op_array_calc(zend_op_array *op_array TSRMLS_DC) zend_uint i; ADD_DUP_SIZE(op_array->arg_info, sizeof(zend_arg_info) * op_array->num_args); - for (i = 0;i < op_array->num_args; i++) { + for (i = 0; i < op_array->num_args; i++) { if (op_array->arg_info[i].name) { ADD_INTERNED_STRING(op_array->arg_info[i].name, op_array->arg_info[i].name_len + 1); } From cf102333a2d150d029ddea8fb6bf4939d075ee91 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 25 Feb 2013 14:18:07 +0400 Subject: [PATCH 078/276] op_array->brk_count_array has to be kept even if op_array doesn't have BRK/CONT/GOTO opcodes. It might be used to unlock "loop" or "switch" variable in case of exception. --- Optimizer/block_pass.c | 189 ++++++++++++++++++---------- Optimizer/zend_optimizer_internal.h | 11 +- 2 files changed, 132 insertions(+), 68 deletions(-) diff --git a/Optimizer/block_pass.c b/Optimizer/block_pass.c index acd149eeef1..7c37da4fc0a 100644 --- a/Optimizer/block_pass.c +++ b/Optimizer/block_pass.c @@ -80,30 +80,18 @@ static inline void print_block(zend_code_block *block, zend_op *opcodes, char *t /* find code blocks in op_array code block is a set of opcodes with single flow of control, i.e. without jmps, branches, etc. */ -static zend_code_block *find_code_blocks(zend_op_array *op_array) +static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg) { zend_op *opline; zend_op *end = op_array->opcodes + op_array->last; - zend_code_block *blocks = ecalloc(op_array->last + 2, sizeof(zend_code_block)); - zend_code_block *cur_block; + zend_code_block *blocks, *cur_block; zend_uint opno = 0; + memset(cfg, 0, sizeof(zend_cfg)); + blocks = cfg->blocks = ecalloc(op_array->last + 2, sizeof(zend_code_block)); opline = op_array->opcodes; blocks[0].start_opline = opline; blocks[0].start_opline_no = 0; - /* first find block start points */ - if (op_array->last_try_catch) { - int i = 0; - blocks->try = ecalloc(op_array->last_try_catch, sizeof(zend_code_block *)); - blocks->catch = ecalloc(op_array->last_try_catch, sizeof(zend_code_block *)); - for (; i< op_array->last_try_catch; i++) { - blocks->try[i] = &blocks[op_array->try_catch_array[i].try_op]; - blocks->catch[i] = &blocks[op_array->try_catch_array[i].catch_op]; - START_BLOCK_OP(op_array->try_catch_array[i].try_op); - START_BLOCK_OP(op_array->try_catch_array[i].catch_op); - blocks[op_array->try_catch_array[i].try_op].is_try = 1; - } - } while (opline < end) { switch((unsigned)opline->opcode) { case ZEND_BRK: @@ -114,12 +102,8 @@ static zend_code_block *find_code_blocks(zend_op_array *op_array) /* would not optimize non-optimized BRK/CONTs - we cannot really know where it jumps, so these optimizations are too dangerous */ - if (op_array->last_try_catch) { - efree(blocks->try); - efree(blocks->catch); - } efree(blocks); - return NULL; + return 0; #if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO case ZEND_FAST_CALL: START_BLOCK_OP(ZEND_OP1(opline).opline_num); @@ -170,6 +154,71 @@ static zend_code_block *find_code_blocks(zend_op_array *op_array) opline++; } + /* first find block start points */ + if (op_array->last_try_catch) { + int i; + cfg->try = ecalloc(op_array->last_try_catch, sizeof(zend_code_block *)); + cfg->catch = ecalloc(op_array->last_try_catch, sizeof(zend_code_block *)); + for (i = 0; i< op_array->last_try_catch; i++) { + cfg->try[i] = &blocks[op_array->try_catch_array[i].try_op]; + cfg->catch[i] = &blocks[op_array->try_catch_array[i].catch_op]; + START_BLOCK_OP(op_array->try_catch_array[i].try_op); + START_BLOCK_OP(op_array->try_catch_array[i].catch_op); + blocks[op_array->try_catch_array[i].try_op].protected = 1; + } + } + /* Currentrly, we don't optimize op_arrays with BRK/CONT/GOTO opcodes, + * but, we have to keep brk_cont_array to avoid memory leaks during + * exception handling */ + if (op_array->last_brk_cont) { + int i, j; + cfg->loop_start = ecalloc(op_array->last_brk_cont, sizeof(zend_code_block *)); + cfg->loop_cont = ecalloc(op_array->last_brk_cont, sizeof(zend_code_block *)); + cfg->loop_brk = ecalloc(op_array->last_brk_cont, sizeof(zend_code_block *)); + j = 0; + for (i = 0; i< op_array->last_brk_cont; i++) { + if (op_array->brk_cont_array[i].start >= 0) { + int parent = op_array->brk_cont_array[i].parent; + + while (parent >= 0 && op_array->brk_cont_array[parent].start < 0) { + parent = op_array->brk_cont_array[parent].parent; + } + op_array->brk_cont_array[i].parent = parent; + j++; + } + } + if (j) { + j = 0; + for (i = 0; i< op_array->last_brk_cont; i++) { + if (op_array->brk_cont_array[i].start >= 0) { + if (i != j) { + op_array->brk_cont_array[j] = op_array->brk_cont_array[i]; + } + cfg->loop_start[j] = &blocks[op_array->brk_cont_array[j].start]; + cfg->loop_cont[j] = &blocks[op_array->brk_cont_array[j].cont]; + cfg->loop_brk[j] = &blocks[op_array->brk_cont_array[j].brk]; + START_BLOCK_OP(op_array->brk_cont_array[j].start); + START_BLOCK_OP(op_array->brk_cont_array[j].cont); + START_BLOCK_OP(op_array->brk_cont_array[j].brk); + blocks[op_array->brk_cont_array[j].start].protected = 1; + blocks[op_array->brk_cont_array[j].brk].protected = 1; + j++; + } + } + op_array->last_brk_cont = j; + } else { + efree(cfg->loop_start); + efree(cfg->loop_cont); + efree(cfg->loop_brk); + efree(op_array->brk_cont_array); + cfg->loop_start = NULL; + cfg->loop_cont = NULL; + cfg->loop_brk = NULL; + op_array->brk_cont_array = NULL; + op_array->last_brk_cont = 0; + } + } + /* Build CFG (Control Flow Graph) */ cur_block = blocks; for (opno = 1; opno < op_array->last; opno++) { @@ -232,14 +281,7 @@ static zend_code_block *find_code_blocks(zend_op_array *op_array) cur_block->next = &blocks[op_array->last+1]; print_block(cur_block, op_array->opcodes, ""); - /* The op_array doesn't have BRK, CONT, GOTO opcodes anyway */ - if (op_array->brk_cont_array) { - efree(op_array->brk_cont_array); - } - op_array->brk_cont_array = NULL; - op_array->last_brk_cont = 0; - - return blocks; + return 1; } /* CFG back references management */ @@ -409,8 +451,9 @@ static void zend_access_path(zend_code_block *block) } /* Traverse CFG, mark reachable basic blocks and build back references */ -static void zend_rebuild_access_path(zend_code_block *blocks, zend_op_array *op_array, int find_start) +static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int find_start) { + zend_code_block *blocks = cfg->blocks; zend_code_block *start = find_start? NULL : blocks; zend_code_block *b; @@ -439,8 +482,8 @@ static void zend_rebuild_access_path(zend_code_block *blocks, zend_op_array *op_ if (op_array->last_try_catch) { int i; for (i=0; i< op_array->last_try_catch; i++) { - if (!blocks->catch[i]->access) { - zend_access_path(blocks->catch[i]); + if (!cfg->catch[i]->access) { + zend_access_path(cfg->catch[i]); } } } @@ -1085,8 +1128,9 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, } /* Rebuild plain (optimized) op_array from CFG */ -static void assemble_code_blocks(zend_code_block *blocks, zend_op_array *op_array) +static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array) { + zend_code_block *blocks = cfg->blocks; zend_op *new_opcodes = emalloc(op_array->last*sizeof(zend_op)); zend_op *opline = new_opcodes; zend_code_block *cur_block = blocks; @@ -1146,12 +1190,25 @@ static void assemble_code_blocks(zend_code_block *blocks, zend_op_array *op_arra /* adjust exception jump targets */ if (op_array->last_try_catch) { int i; - for (i=0; i< op_array->last_try_catch; i++) { - op_array->try_catch_array[i].try_op = blocks->try[i]->start_opline - new_opcodes; - op_array->try_catch_array[i].catch_op = blocks->catch[i]->start_opline - new_opcodes; + for (i = 0; i< op_array->last_try_catch; i++) { + op_array->try_catch_array[i].try_op = cfg->try[i]->start_opline - new_opcodes; + op_array->try_catch_array[i].catch_op = cfg->catch[i]->start_opline - new_opcodes; } - efree(blocks->try); - efree(blocks->catch); + efree(cfg->try); + efree(cfg->catch); + } + + /* adjust loop jump targets */ + if (op_array->last_brk_cont) { + int i; + for (i = 0; i< op_array->last_brk_cont; i++) { + op_array->brk_cont_array[i].start = cfg->loop_start[i]->start_opline - new_opcodes; + op_array->brk_cont_array[i].cont = cfg->loop_cont[i]->start_opline - new_opcodes; + op_array->brk_cont_array[i].brk = cfg->loop_brk[i]->start_opline - new_opcodes; + } + efree(cfg->loop_start); + efree(cfg->loop_cont); + efree(cfg->loop_brk); } /* adjust jump targets */ @@ -1225,7 +1282,7 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra if (((target->opcode == ZEND_JMP && block->op1_to != block->op1_to->op1_to) || target->opcode == ZEND_JMPZNZ) && - !block->op1_to->is_try) { + !block->op1_to->protected) { /* JMP L, L: JMP L1 -> JMP L1 */ /* JMP L, L: JMPZNZ L1,L2 -> JMPZNZ L1,L2 */ *last_op = *target; @@ -1371,7 +1428,7 @@ next_target: same_type == ZEND_OP1_TYPE(target) && same_var == VAR_NUM_EX(target->op1) && target_block->follow_to && - !target_block->is_try + !target_block->protected ) { del_source(block, block->op2_to); block->op2_to = target_block->follow_to; @@ -1381,7 +1438,7 @@ next_target: same_type == ZEND_OP1_TYPE(target) && same_var == VAR_NUM_EX(target->op1) && target_block->follow_to && - !target_block->is_try) { + !target_block->protected) { /* JMPZ(X, L), L: X = JMPNZ_EX(X, L2) -> JMPZ(X, L+1) */ last_op->opcode += 3; last_op->result = target->result; @@ -1393,14 +1450,14 @@ next_target: (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && same_type == ZEND_OP1_TYPE(target) && same_var == VAR_NUM_EX(target->op1) && - !target_block->is_try) { + !target_block->protected) { /* JMPZ(X, L), L: JMPZ(X, L2) -> JMPZ(X, L2) */ del_source(block, block->op2_to); block->op2_to = target_block->op2_to; ADD_SOURCE(block, block->op2_to); } else if (target_block->op1_to && target->opcode == ZEND_JMP && - !target_block->is_try) { + !target_block->protected) { /* JMPZ(X, L), L: JMP(L2) -> JMPZ(X, L2) */ del_source(block, block->op2_to); block->op2_to = target_block->op1_to; @@ -1411,7 +1468,7 @@ next_target: (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && same_type == ZEND_OP1_TYPE(target) && same_var == VAR_NUM_EX(target->op1) && - !target_block->is_try) { + !target_block->protected) { /* JMPZ(X, L), L: JMPZNZ(X, L2, L3) -> JMPZ(X, L2) */ del_source(block, block->op2_to); if (last_op->opcode == ZEND_JMPZ) { @@ -1447,7 +1504,7 @@ next_target: /* JMPZ(X,L1), JMP(L2) -> JMPZNZ(X,L1,L2) */ if (target->opcode == ZEND_JMP && block->follow_to->op1_to && - !block->follow_to->is_try) { + !block->follow_to->protected) { del_source(block, block->follow_to); if (last_op->opcode == ZEND_JMPZ) { block->ext_to = block->follow_to->op1_to; @@ -1517,7 +1574,7 @@ next_target_ex: target->opcode == last_op->opcode-3 && (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && - !target_block->is_try) { + !target_block->protected) { /* T = JMPZ_EX(X, L1), L1: JMPZ({X|T}, L2) -> T = JMPZ_EX(X, L2) */ del_source(block, block->op2_to); block->op2_to = target_block->op2_to; @@ -1526,7 +1583,7 @@ next_target_ex: target->opcode == INV_EX_COND(last_op->opcode) && (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && - !target_block->is_try) { + !target_block->protected) { /* T = JMPZ_EX(X, L1), L1: JMPNZ({X|T1}, L2) -> T = JMPZ_EX(X, L1+1) */ del_source(block, block->op2_to); block->op2_to = target_block->follow_to; @@ -1536,7 +1593,7 @@ next_target_ex: (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && (same_t[VAR_NUM_EX(target->result)] & ZEND_RESULT_TYPE(target)) != 0 && - !target_block->is_try) { + !target_block->protected) { /* T = JMPZ_EX(X, L1), L1: T = JMPNZ_EX(T, L2) -> T = JMPZ_EX(X, L1+1) */ del_source(block, block->op2_to); block->op2_to = target_block->follow_to; @@ -1546,14 +1603,14 @@ next_target_ex: (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && (same_t[VAR_NUM_EX(target->result)] & ZEND_RESULT_TYPE(target)) != 0 && - !target_block->is_try) { + !target_block->protected) { /* T = JMPZ_EX(X, L1), L1: T = JMPZ({X|T}, L2) -> T = JMPZ_EX(X, L2) */ del_source(block, block->op2_to); block->op2_to = target_block->op2_to; ADD_SOURCE(block, block->op2_to); } else if (target_block->op1_to && target->opcode == ZEND_JMP && - !target_block->is_try) { + !target_block->protected) { /* T = JMPZ_EX(X, L), L: JMP(L2) -> T = JMPZ(X, L2) */ del_source(block, block->op2_to); block->op2_to = target_block->op1_to; @@ -1563,7 +1620,7 @@ next_target_ex: target->opcode == ZEND_JMPZNZ && (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && (same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 && - !target_block->is_try) { + !target_block->protected) { /* T = JMPZ_EX(X, L), L: JMPZNZ({X|T}, L2, L3) -> T = JMPZ_EX(X, L2) */ del_source(block, block->op2_to); if (last_op->opcode == ZEND_JMPZ_EX) { @@ -1663,7 +1720,7 @@ next_target_znz: (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) && same_type == ZEND_OP1_TYPE(target) && same_var == VAR_NUM_EX(target->op1) && - !target_block->is_try) { + !target_block->protected) { /* JMPZNZ(X, L1, L2), L1: JMPZ(X, L3) -> JMPZNZ(X, L3, L2) */ del_source(block, block->op2_to); block->op2_to = target_block->op2_to; @@ -1673,14 +1730,14 @@ next_target_znz: same_type == ZEND_OP1_TYPE(target) && same_var == VAR_NUM_EX(target->op1) && target_block->follow_to && - !target_block->is_try) { + !target_block->protected) { /* JMPZNZ(X, L1, L2), L1: X = JMPNZ(X, L3) -> JMPZNZ(X, L1+1, L2) */ del_source(block, block->op2_to); block->op2_to = target_block->follow_to; ADD_SOURCE(block, block->op2_to); } else if (target_block->op1_to && target->opcode == ZEND_JMP && - !target_block->is_try) { + !target_block->protected) { /* JMPZNZ(X, L1, L2), L1: JMP(L3) -> JMPZNZ(X, L3, L2) */ del_source(block, block->op2_to); block->op2_to = target_block->op1_to; @@ -1882,7 +1939,8 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char * static void zend_block_optimization(zend_op_array *op_array TSRMLS_DC) { - zend_code_block *blocks, *cur_block; + zend_cfg cfg; + zend_code_block *cur_block; int pass; char *usage; @@ -1898,21 +1956,20 @@ static void zend_block_optimization(zend_op_array *op_array TSRMLS_DC) #endif /* Build CFG */ - blocks = find_code_blocks(op_array); - if (!blocks) { + if (!find_code_blocks(op_array, &cfg)) { return; } - zend_rebuild_access_path(blocks, op_array, 0); + zend_rebuild_access_path(&cfg, op_array, 0); /* full rebuild here to produce correct sources! */ usage = emalloc(op_array->T); for (pass = 0; pass < PASSES; pass++) { /* Compute data dependencies */ memset(usage, 0, op_array->T); - zend_t_usage(blocks, op_array, usage); + zend_t_usage(cfg.blocks, op_array, usage); /* optimize each basic block separately */ - for (cur_block = blocks; cur_block; cur_block = cur_block->next) { + for (cur_block = cfg.blocks; cur_block; cur_block = cur_block->next) { if (!cur_block->access) { continue; } @@ -1920,22 +1977,22 @@ static void zend_block_optimization(zend_op_array *op_array TSRMLS_DC) } /* Jump optimization for each block */ - for (cur_block = blocks; cur_block; cur_block = cur_block->next) { + for (cur_block = cfg.blocks; cur_block; cur_block = cur_block->next) { if (!cur_block->access) { continue; } - zend_jmp_optimization(cur_block, op_array, blocks); + zend_jmp_optimization(cur_block, op_array, cfg.blocks); } /* Eliminate unreachable basic blocks */ - zend_rebuild_access_path(blocks, op_array, 1); + zend_rebuild_access_path(&cfg, op_array, 1); } - assemble_code_blocks(blocks, op_array); + assemble_code_blocks(&cfg, op_array); efree(usage); /* Destroy CFG */ - for (cur_block = blocks; cur_block; cur_block = cur_block->next) { + for (cur_block = cfg.blocks; cur_block; cur_block = cur_block->next) { zend_block_source *cs = cur_block->sources; while (cs) { zend_block_source *n = cs->next; @@ -1943,5 +2000,5 @@ static void zend_block_optimization(zend_op_array *op_array TSRMLS_DC) cs = n; } } - efree(blocks); + efree(cfg.blocks); } diff --git a/Optimizer/zend_optimizer_internal.h b/Optimizer/zend_optimizer_internal.h index 198ec20c499..6f853641fac 100644 --- a/Optimizer/zend_optimizer_internal.h +++ b/Optimizer/zend_optimizer_internal.h @@ -63,10 +63,17 @@ struct _zend_code_block { zend_code_block *follow_to; zend_code_block *next; zend_block_source *sources; + zend_bool protected; /* don't merge this block with others */ +}; + +typedef struct _zend_cfg { + zend_code_block *blocks; zend_code_block **try; zend_code_block **catch; - zend_bool is_try; -}; + zend_code_block **loop_start; + zend_code_block **loop_cont; + zend_code_block **loop_brk; +} zend_cfg; struct _zend_block_source { zend_code_block *from; From f463abc5082dcc3e11da45bfe7e04dd90b3ac426 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 25 Feb 2013 16:06:38 +0400 Subject: [PATCH 079/276] Fixed function prototypes --- shared_alloc_win32.c | 6 +++--- zend_shared_alloc.c | 2 +- zend_shared_alloc.h | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/shared_alloc_win32.c b/shared_alloc_win32.c index 819ef5cc3cd..2b6548743b5 100644 --- a/shared_alloc_win32.c +++ b/shared_alloc_win32.c @@ -85,7 +85,7 @@ static char *create_name_with_username(char *name) return newname; } -static char *get_mmap_base_file() +static char *get_mmap_base_file(void) { static char windir[MAXPATHLEN+UNLEN + 3 + sizeof("\\\\@")]; char uname[UNLEN + 1]; @@ -109,7 +109,7 @@ void zend_shared_alloc_create_lock(void) ReleaseMutex(memory_mutex); } -void zend_shared_alloc_lock_win32() +void zend_shared_alloc_lock_win32(void) { DWORD waitRes = WaitForSingleObject(memory_mutex, INFINITE); @@ -118,7 +118,7 @@ void zend_shared_alloc_lock_win32() } } -void zend_shared_alloc_unlock_win32(TSRMLS_D) +void zend_shared_alloc_unlock_win32(void) { ReleaseMutex(memory_mutex); } diff --git a/zend_shared_alloc.c b/zend_shared_alloc.c index 3e867d13613..b6040cf0ad8 100644 --- a/zend_shared_alloc.c +++ b/zend_shared_alloc.c @@ -462,7 +462,7 @@ void zend_shared_alloc_restore_state(void) ZSMMG(wasted_shared_memory) = 0; } -const char *zend_accel_get_shared_model() +const char *zend_accel_get_shared_model(void) { return g_shared_model; } diff --git a/zend_shared_alloc.h b/zend_shared_alloc.h index 12df673cf3c..77ef723fbba 100644 --- a/zend_shared_alloc.h +++ b/zend_shared_alloc.h @@ -160,7 +160,7 @@ size_t zend_shared_alloc_get_free_memory(void); void zend_shared_alloc_save_state(void); void zend_shared_alloc_restore_state(void); size_t zend_shared_alloc_get_largest_free_block(void); -const char *zend_accel_get_shared_model(); +const char *zend_accel_get_shared_model(void); /* memory write protection */ void zend_accel_shared_protect(int mode TSRMLS_DC); @@ -179,9 +179,9 @@ extern zend_shared_memory_handlers zend_alloc_posix_handlers; #ifdef ZEND_WIN32 extern zend_shared_memory_handlers zend_alloc_win32_handlers; -void zend_shared_alloc_create_lock(); -void zend_shared_alloc_lock_win32(); -void zend_shared_alloc_unlock_win32(); +void zend_shared_alloc_create_lock(void); +void zend_shared_alloc_lock_win32(void); +void zend_shared_alloc_unlock_win32(void); #endif #endif /* ZEND_SHARED_ALLOC_H */ From 70f1cd9dc52b8b2b3e69274e4acee9448e3fdfb4 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 25 Feb 2013 16:35:44 +0400 Subject: [PATCH 080/276] Execute shared memory initialization/deinitialization under exclusive lock --- shared_alloc_win32.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/shared_alloc_win32.c b/shared_alloc_win32.c index 2b6548743b5..dc2bfd7a13b 100644 --- a/shared_alloc_win32.c +++ b/shared_alloc_win32.c @@ -181,6 +181,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ void **wanted_mapping_base = default_mapping_base_set; TSRMLS_FETCH(); + zend_shared_alloc_lock_win32(); /* Mapping retries: When Apache2 restarts, the parent process startup routine can be called before the child process is killed. In this case, the map will fail and we have to sleep some time (until the child releases the mapping object) and retry.*/ @@ -199,11 +200,13 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ memfile = NULL; Sleep(1000 * (map_retries + 1)); } else { + zend_shared_alloc_unlock_win32(); return ret; } } while (++map_retries < MAX_MAP_RETRIES); if (map_retries == MAX_MAP_RETRIES) { + zend_shared_alloc_unlock_win32(); zend_win_error_message(ACCEL_LOG_FATAL, "Unable to open file mapping", err); *error_in = "OpenFileMapping"; return ALLOC_FAILURE; @@ -213,6 +216,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ *shared_segments_count = 1; *shared_segments_p = (zend_shared_segment **) calloc(1, sizeof(zend_shared_segment)+sizeof(void *)); if (!*shared_segments_p) { + zend_shared_alloc_unlock_win32(); zend_win_error_message(ACCEL_LOG_FATAL, "calloc() failed", GetLastError()); *error_in = "calloc"; return ALLOC_FAILURE; @@ -224,6 +228,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ create_name_with_username(ACCEL_FILEMAP_NAME)); err = GetLastError(); if (memfile == NULL) { + zend_shared_alloc_unlock_win32(); zend_win_error_message(ACCEL_LOG_FATAL, "Unable to create file mapping", err); *error_in = "CreateFileMapping"; return ALLOC_FAILURE; @@ -269,6 +274,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ s += 2; } if (sscanf(s, "%p", &default_mapping_base_set[0]) != 1) { + zend_shared_alloc_unlock_win32(); zend_win_error_message(ACCEL_LOG_FATAL, "Bad mapping address specified in zend_optimizerplus.mmap_base", err); return ALLOC_FAILURE; } @@ -284,6 +290,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ err = GetLastError(); if (mapping_base == NULL) { + zend_shared_alloc_unlock_win32(); zend_win_error_message(ACCEL_LOG_FATAL, "Unable to create view for file mapping", err); *error_in = "MapViewOfFile"; return ALLOC_FAILURE; @@ -292,6 +299,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ FILE *fp = fopen(mmap_base_file, "w"); err = GetLastError(); if (!fp) { + zend_shared_alloc_unlock_win32(); zend_win_error_message(ACCEL_LOG_WARNING, mmap_base_file, err); zend_win_error_message(ACCEL_LOG_FATAL, "Unable to write base address", err); return ALLOC_FAILURE; @@ -303,16 +311,19 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ shared_segment->pos = 0; shared_segment->size = requested_size; + zend_shared_alloc_unlock_win32(); + return ALLOC_SUCCESS; } static int detach_segment(zend_shared_segment *shared_segment) { + zend_shared_alloc_lock_win32(); if (mapping_base) { UnmapViewOfFile(mapping_base); } CloseHandle(memfile); - ReleaseMutex(memory_mutex); + zend_shared_alloc_unlock_win32(); CloseHandle(memory_mutex); return 0; } From a7a355c741de119dc7b3823751cf005023adf9d9 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 26 Feb 2013 01:32:24 +0400 Subject: [PATCH 081/276] Fixed memory leaks (avoid generation of unused results) --- Optimizer/block_pass.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Optimizer/block_pass.c b/Optimizer/block_pass.c index af2f1589188..4ee89326a0e 100644 --- a/Optimizer/block_pass.c +++ b/Optimizer/block_pass.c @@ -1988,6 +1988,8 @@ static void zend_block_optimization(zend_op_array *op_array TSRMLS_DC) zend_rebuild_access_path(&cfg, op_array, 1); } + memset(usage, 0, op_array->T); + zend_t_usage(cfg.blocks, op_array, usage); assemble_code_blocks(&cfg, op_array); efree(usage); From 443a177b349d56ff33f0506a2a9abdcc58d4b93c Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 26 Feb 2013 01:34:11 +0400 Subject: [PATCH 082/276] Emit the same error messages as without O+ (use "dups_fix" hack only for classes) --- README | 2 +- zend_accelerator_util_funcs.c | 152 ++++++++-------------------------- 2 files changed, 37 insertions(+), 117 deletions(-) diff --git a/README b/README index b2c060c58f3..83a30f26803 100644 --- a/README +++ b/README @@ -144,7 +144,7 @@ zend_optimizerplus.inherited_hack (default "1") anymore and this setting has no effect. zend_optimizerplus.dups_fix (default "0") - Enable this hack as a workaround for "duplicate definition" errors. + Enable this hack as a workaround for "Cannot redecalre class" errors. zend_optimizerplus.blacklist_filename The location of the Optimizer+ blacklist file. diff --git a/zend_accelerator_util_funcs.c b/zend_accelerator_util_funcs.c index e8ed57c2444..7c3c9ae86cc 100644 --- a/zend_accelerator_util_funcs.c +++ b/zend_accelerator_util_funcs.c @@ -763,82 +763,7 @@ static void zend_class_copy_ctor(zend_class_entry **pce) #endif } -static int zend_accel_same_function(void *f1, void *f2) -{ - zend_function *func1 = (zend_function *)f1, *func2 = (zend_function *)f2; - zend_op_array *op1 = (zend_op_array *)func1; - zend_op_array *op2 = (zend_op_array *)func2; - - if (func1->type != ZEND_USER_FUNCTION || func2->type != ZEND_USER_FUNCTION) { - return 0; - } - - if (func1 == func2) { - return 1; - } - - if (op1->function_name != op2->function_name && (!op1->function_name || !op2->function_name || strcmp(op1->function_name, op2->function_name))) { - /* compare filenames */ - return 0; - } - - if (op1->filename != op2->filename && (!op1->filename || !op2->filename || strcmp(op1->filename, op2->filename))) { - /* compare filenames */ - return 0; - } - - if (!op1->opcodes || !op2->opcodes || op1->opcodes[0].lineno != op2->opcodes[0].lineno) { - /* compare first lines */ - return 0; - } - - /* if everything matches - we are OK */ - return 1; -} - -static int zend_accel_same_class(void *f1, void *f2) -{ - zend_class_entry *ce1 = *(zend_class_entry **)f1; - zend_class_entry *ce2 = *(zend_class_entry **)f2; - - if (ce1->type != ZEND_USER_CLASS || ce2->type != ZEND_USER_CLASS) { - return 0; - } - - if (ce1 == ce2) { - return 1; - } - - if (!ce1->name || !ce2->name || zend_binary_strcmp(ce1->name, ce1->name_length, ce2->name, ce2->name_length)) { - return 0; - } - - if (zend_hash_num_elements(&ce1->function_table) != zend_hash_num_elements(&ce2->function_table) -#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO - || ce1->default_properties_count != ce2->default_properties_count) { -#else - || zend_hash_num_elements(&ce1->default_properties) != zend_hash_num_elements(&ce2->default_properties)) { -#endif - return 0; - } - - if (zend_hash_num_elements(&ce1->function_table)) { - HashPosition pos; - zend_function *func1, *func2; - - zend_hash_internal_pointer_reset_ex(&ce1->function_table, &pos); - zend_hash_get_current_data_ex(&ce1->function_table, (void **)&func1, &pos); - zend_hash_internal_pointer_reset_ex(&ce2->function_table, &pos); - zend_hash_get_current_data_ex(&ce2->function_table, (void **)&func2, &pos); - if (!zend_accel_same_function(func1, func2)) { - return 0; - } - } - - return 1; -} - -static int zend_hash_unique_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor, uint size, const char **key_fail, ulong *key_fail_l, id_function_t pIdFunc) +static int zend_hash_unique_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor, uint size, int ignore_dups, void **fail_data, void **conflict_data) { Bucket *p; void *t; @@ -853,31 +778,20 @@ static int zend_hash_unique_copy(HashTable *target, HashTable *source, unique_co } else { if (p->nKeyLength > 0 && p->arKey[0] == 0) { /* Mangled key, ignore and wait for runtime */ - } else if (zend_hash_quick_find(target, p->arKey, p->nKeyLength, p->h, &t) == SUCCESS && - (!pIdFunc || pIdFunc(p->pData, t))) { - /* same one, ignore it */ - } else { - if (key_fail) { - *key_fail = p->arKey; - } - if (key_fail_l) { - *key_fail_l = p->nKeyLength; - } + } else if (!ignore_dups && zend_hash_quick_find(target, p->arKey, p->nKeyLength, p->h, &t) == SUCCESS) { + *fail_data = p->pData; + *conflict_data = t; return FAILURE; } } } else { if (!zend_hash_index_exists(target, p->h) && zend_hash_index_update(target, p->h, p->pData, size, &t) == SUCCESS) { - if (pCopyConstructor) { - pCopyConstructor(t); - } - } else { - if (key_fail) { - *key_fail = NULL; - } - if (key_fail_l) { - *key_fail_l = p->h; + if (pCopyConstructor) { + pCopyConstructor(t); } + } else if (!ignore_dups && zend_hash_index_find(target,p->h, &t) == SUCCESS) { + *fail_data = p->pData; + *conflict_data = t; return FAILURE; } } @@ -888,35 +802,41 @@ static int zend_hash_unique_copy(HashTable *target, HashTable *source, unique_co return SUCCESS; } -static void zend_accel_function_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor) { - const char *name; - ulong name_len; - zend_function *function; +static void zend_accel_function_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor) +{ + zend_function *function1, *function2; TSRMLS_FETCH(); - if (zend_hash_unique_copy(target, source, pCopyConstructor, sizeof(zend_function), &name, &name_len, ZCG(accel_directives).ignore_dups?NULL:zend_accel_same_function) != SUCCESS) { - if (zend_hash_find(target, name, name_len, (void *) &function) == SUCCESS - && function->type == ZEND_USER_FUNCTION - && ((zend_op_array *) function)->last > 0) { - zend_error(E_ERROR, "Cannot redeclare function %.*s() (previously declared in %s:%d). If this code worked without the " ACCELERATOR_PRODUCT_NAME ", please set zend_optimizerplus.dups_fix=1 in your ini file", - (int)name_len, name, - ((zend_op_array *) function)->filename, - (int)((zend_op_array *) function)->opcodes[0].lineno); + if (zend_hash_unique_copy(target, source, pCopyConstructor, sizeof(zend_function), 0, (void**)&function1, (void**)&function2) != SUCCESS) { + CG(in_compilation) = 1; + zend_set_compiled_filename(function1->op_array.filename TSRMLS_CC); + CG(zend_lineno) = function1->op_array.opcodes[0].lineno; + if (function2->type == ZEND_USER_FUNCTION + && function2->op_array.last > 0) { + zend_error(E_ERROR, "Cannot redeclare %s() (previously declared in %s:%d)", + function1->common.function_name, + function2->op_array.filename, + (int)function2->op_array.opcodes[0].lineno); } else { - - zend_error(E_ERROR, "Cannot redeclare function %.*s(). If this code worked without the " ACCELERATOR_PRODUCT_NAME ", please set zend_optimizerplus.dups_fix=1 in your ini file", (int)name_len, name); + zend_error(E_ERROR, "Cannot redeclare %s()", function1->common.function_name); } } } -static void zend_accel_class_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor TSRMLS_DC) { - const char *name; - ulong name_len; - uint size; +static void zend_accel_class_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor TSRMLS_DC) +{ + zend_class_entry **pce1, **pce2; - size = sizeof(zend_class_entry*); - if (zend_hash_unique_copy(target, source, pCopyConstructor, size, &name, &name_len, ZCG(accel_directives).ignore_dups? NULL : zend_accel_same_class) != SUCCESS) { - zend_error(E_ERROR, "Cannot redeclare class %.*s. If this code worked without the " ACCELERATOR_PRODUCT_NAME ", please set zend_optimizerplus.dups_fix=1 in your php.ini", (int)name_len, name); + if (zend_hash_unique_copy(target, source, pCopyConstructor, sizeof(zend_class_entry*), ZCG(accel_directives).ignore_dups, (void**)&pce1, (void**)&pce2) != SUCCESS) { + CG(in_compilation) = 1; +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + zend_set_compiled_filename((*pce1)->info.user.filename TSRMLS_CC); + CG(zend_lineno) = (*pce1)->info.user.line_start; +#else + zend_set_compiled_filename((*pce1)->filename TSRMLS_CC); + CG(zend_lineno) = (*pce1)->line_start; +#endif + zend_error(E_ERROR, "Cannot redeclare class %s", (*pce1)->name); } } From 616214f929f74c6f0e19515959925466646e1194 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 26 Feb 2013 11:26:51 +0400 Subject: [PATCH 083/276] Fixed build instruction --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 83a30f26803..34c8bcaf912 100644 --- a/README +++ b/README @@ -18,7 +18,7 @@ Quick Install - Compile - $PHP_DIR/phpize + $PHP_DIR/bin/phpize ./configure \ --with-php-config=$PHP_DIR/bin/php-config make From a6e115e94e1f84335c75860317bad696c77aad94 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 26 Feb 2013 23:05:24 +0400 Subject: [PATCH 084/276] Fixed typo --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 34c8bcaf912..27005048b0e 100644 --- a/README +++ b/README @@ -144,7 +144,7 @@ zend_optimizerplus.inherited_hack (default "1") anymore and this setting has no effect. zend_optimizerplus.dups_fix (default "0") - Enable this hack as a workaround for "Cannot redecalre class" errors. + Enable this hack as a workaround for "Cannot redeclare class" errors. zend_optimizerplus.blacklist_filename The location of the Optimizer+ blacklist file. From e1fb6ce3657f0397261e95e8dc910a305e50ae1a Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Wed, 27 Feb 2013 10:13:01 -0500 Subject: [PATCH 085/276] Added missing calloc() result checks --- shared_alloc_mmap.c | 4 ++++ shared_alloc_posix.c | 4 ++++ shared_alloc_shm.c | 3 +++ zend_accelerator_blacklist.c | 4 ++++ 4 files changed, 15 insertions(+) diff --git a/shared_alloc_mmap.c b/shared_alloc_mmap.c index a13d3730f0a..961f4fea9af 100644 --- a/shared_alloc_mmap.c +++ b/shared_alloc_mmap.c @@ -39,6 +39,10 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ *shared_segments_count = 1; *shared_segments_p = (zend_shared_segment **) calloc(1, sizeof(zend_shared_segment) + sizeof(void *)); + if (!*shared_segments_p) { + *error_in = "calloc"; + return ALLOC_FAILURE; + } shared_segment = (zend_shared_segment *)((char *)(*shared_segments_p) + sizeof(void *)); (*shared_segments_p)[0] = shared_segment; diff --git a/shared_alloc_posix.c b/shared_alloc_posix.c index 06441e4e0fb..418280a45ac 100644 --- a/shared_alloc_posix.c +++ b/shared_alloc_posix.c @@ -43,6 +43,10 @@ static int create_segments(size_t requested_size, zend_shared_segment_posix ***s *shared_segments_count = 1; *shared_segments_p = (zend_shared_segment_posix **) calloc(1, sizeof(zend_shared_segment_posix) + sizeof(void *)); + if (!*shared_segments_p) { + *error_in = "calloc"; + rerurn ALLOC_FAILURE; + } shared_segment = (zend_shared_segment_posix *)((char *)(*shared_segments_p) + sizeof(void *)); (*shared_segments_p)[0] = shared_segment; diff --git a/shared_alloc_shm.c b/shared_alloc_shm.c index c9a31b07b40..21a4005571d 100644 --- a/shared_alloc_shm.c +++ b/shared_alloc_shm.c @@ -88,6 +88,9 @@ static int create_segments(size_t requested_size, zend_shared_segment_shm ***sha *shared_segments_count = ((requested_size - 1) / seg_allocate_size) + 1; *shared_segments_p = (zend_shared_segment_shm **) calloc(1, (*shared_segments_count) * sizeof(zend_shared_segment_shm) + sizeof(void *) * (*shared_segments_count)); + if (!*shared_segments_p) { + return ALLOC_FAILURE; + } shared_segments = (zend_shared_segment_shm *)((char *)(*shared_segments_p) + sizeof(void *) * (*shared_segments_count)); for (i = 0; i < *shared_segments_count; i++) { (*shared_segments_p)[i] = shared_segments + i; diff --git a/zend_accelerator_blacklist.c b/zend_accelerator_blacklist.c index 5191fdb0209..48fe958432a 100644 --- a/zend_accelerator_blacklist.c +++ b/zend_accelerator_blacklist.c @@ -55,6 +55,10 @@ void zend_accel_blacklist_init(zend_blacklist *blacklist) } blacklist->entries = (zend_blacklist_entry *) calloc(sizeof(zend_blacklist_entry), blacklist->size); + if (!blacklist->entries) { + zend_accel_error(ACCEL_LOG_ERROR, "Blacklist initialization: no memory\n"); + return; + } blacklist->regexp_list = NULL; } From d39a49a5340643483f6a94f391328b2d46a24d3b Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 27 Feb 2013 21:35:24 +0400 Subject: [PATCH 086/276] Correction --- shared_alloc_shm.c | 1 + zend_accelerator_blacklist.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/shared_alloc_shm.c b/shared_alloc_shm.c index 21a4005571d..a8b244aac15 100644 --- a/shared_alloc_shm.c +++ b/shared_alloc_shm.c @@ -89,6 +89,7 @@ static int create_segments(size_t requested_size, zend_shared_segment_shm ***sha *shared_segments_count = ((requested_size - 1) / seg_allocate_size) + 1; *shared_segments_p = (zend_shared_segment_shm **) calloc(1, (*shared_segments_count) * sizeof(zend_shared_segment_shm) + sizeof(void *) * (*shared_segments_count)); if (!*shared_segments_p) { + *error_in = "calloc"; return ALLOC_FAILURE; } shared_segments = (zend_shared_segment_shm *)((char *)(*shared_segments_p) + sizeof(void *) * (*shared_segments_count)); diff --git a/zend_accelerator_blacklist.c b/zend_accelerator_blacklist.c index 48fe958432a..87dc4744574 100644 --- a/zend_accelerator_blacklist.c +++ b/zend_accelerator_blacklist.c @@ -56,7 +56,7 @@ void zend_accel_blacklist_init(zend_blacklist *blacklist) blacklist->entries = (zend_blacklist_entry *) calloc(sizeof(zend_blacklist_entry), blacklist->size); if (!blacklist->entries) { - zend_accel_error(ACCEL_LOG_ERROR, "Blacklist initialization: no memory\n"); + zend_accel_error(ACCEL_LOG_FATAL, "Blacklist initialization: no memory\n"); return; } blacklist->regexp_list = NULL; From 0039f160f259dc230fa1979a3fd1c01248b309ad Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Wed, 27 Feb 2013 13:53:03 -0500 Subject: [PATCH 087/276] Make the functions validate input parameters (or lack thereof) --- zend_accelerator_module.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index 04133f64b65..ba989429a28 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -466,6 +466,10 @@ static ZEND_FUNCTION(accelerator_get_status) /* keep the compiler happy */ (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; + if (zend_parse_parameters_none() == FAILURE) { + return; + } + if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled)) { RETURN_FALSE; } @@ -521,6 +525,10 @@ static ZEND_FUNCTION(accelerator_get_configuration) /* keep the compiler happy */ (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; + if (zend_parse_parameters_none() == FAILURE) { + return; + } + array_init(return_value); /* directives */ @@ -578,6 +586,10 @@ static ZEND_FUNCTION(accelerator_reset) /* keep the compiler happy */ (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; + if (zend_parse_parameters_none() == FAILURE) { + return; + } + if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled)) { RETURN_FALSE; } From 23daa95d10ddc91ad8b4d846d8aadb0ad9748cc1 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Wed, 27 Feb 2013 13:54:56 -0500 Subject: [PATCH 088/276] return false to be consistent --- zend_accelerator_module.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index ba989429a28..1bf16e5035c 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -467,7 +467,7 @@ static ZEND_FUNCTION(accelerator_get_status) (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; if (zend_parse_parameters_none() == FAILURE) { - return; + RETURN_FALSE; } if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled)) { @@ -526,7 +526,7 @@ static ZEND_FUNCTION(accelerator_get_configuration) (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; if (zend_parse_parameters_none() == FAILURE) { - return; + RETURN_FALSE; } array_init(return_value); @@ -587,7 +587,7 @@ static ZEND_FUNCTION(accelerator_reset) (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; if (zend_parse_parameters_none() == FAILURE) { - return; + RETURN_FALSE; } if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled)) { From 171843a4e0b4fe55af74893f91e4432eb7b5ec58 Mon Sep 17 00:00:00 2001 From: Patrick Allaert Date: Thu, 28 Feb 2013 15:44:58 +0100 Subject: [PATCH 089/276] Fixed typo --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 27005048b0e..d56d4502a97 100644 --- a/README +++ b/README @@ -185,7 +185,7 @@ zend_optimizerplus.log_verbosity_level (default "1") debug messages (level 4). zend_optimizerplus.preferred_memory_model - Preffered Shared Memory back-end. Leave empty and let the system decide. + Preferred Shared Memory back-end. Leave empty and let the system decide. zend_optimizerplus.protect_memory (default "0") Protect the shared memory from unexpected writing during script execution. From 0a29c8de7ae1b721296c58f2d51a1dae205edbd3 Mon Sep 17 00:00:00 2001 From: Ferenc Kovacs Date: Thu, 28 Feb 2013 22:38:09 +0100 Subject: [PATCH 090/276] adding the package.xml for pecl --- package.xml | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 package.xml diff --git a/package.xml b/package.xml new file mode 100644 index 00000000000..114d0ba8ccb --- /dev/null +++ b/package.xml @@ -0,0 +1,116 @@ + + + zendoptimizerplus + pecl.php.net + The Zend Optimizer+ provides faster PHP execution through opcode caching and +optimization. + +The Zend Optimizer+ provides faster PHP execution through opcode caching and +optimization. It improves PHP performance by storing precompiled script +bytecode in the shared memory. This eliminates the stages of reading code from +the disk and compiling it on future access. In addition, it applies a few +bytecode optimization patterns that make code execution faster. + + + + Dmitry Stogov + dmitry + dmitry@zend.com + yes + + 2013-02-28 + + + 0.1.0 + 0.1.0 + + + alpha + alpha + + PHP License + +Initial release + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5.2.0 + + + 1.4.0b1 + + + + zendoptimizerplus + + + + + 0.1.0 + 0.1.0 + + + alpha + alpha + + 2013-02-28 + PHP License + +Initial release. + + + + From 28cd079adb2b6abbfbeb19382971302eb1efd92c Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 1 Mar 2013 10:17:41 +0400 Subject: [PATCH 091/276] Added info anout zend_optimizerplus.mmap_base directice --- README | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README b/README index d56d4502a97..b44386e87a0 100644 --- a/README +++ b/README @@ -190,3 +190,9 @@ zend_optimizerplus.preferred_memory_model zend_optimizerplus.protect_memory (default "0") Protect the shared memory from unexpected writing during script execution. Useful for internal debugging only. + +zend_optimizerplus.mmap_base + Mapping base of shared memory segments (for Windows only). All the PHP + processes have to map shared memory into the same address space. This + directive allows to manually fix the "Unable to reattach to base address" + errors. From 68c265ce372860a09f6111f99684ff012dbbc602 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 1 Mar 2013 22:57:53 +0400 Subject: [PATCH 092/276] typo --- shared_alloc_posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared_alloc_posix.c b/shared_alloc_posix.c index 418280a45ac..46f0257bb3a 100644 --- a/shared_alloc_posix.c +++ b/shared_alloc_posix.c @@ -45,7 +45,7 @@ static int create_segments(size_t requested_size, zend_shared_segment_posix ***s *shared_segments_p = (zend_shared_segment_posix **) calloc(1, sizeof(zend_shared_segment_posix) + sizeof(void *)); if (!*shared_segments_p) { *error_in = "calloc"; - rerurn ALLOC_FAILURE; + return ALLOC_FAILURE; } shared_segment = (zend_shared_segment_posix *)((char *)(*shared_segments_p) + sizeof(void *)); (*shared_segments_p)[0] = shared_segment; From 3b0da73d325858e6c8259262c216a62020482865 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 4 Mar 2013 15:26:40 +0400 Subject: [PATCH 093/276] Preparaton for pecl release --- ZendAccelerator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZendAccelerator.h b/ZendAccelerator.h index 83e7cd185ed..5ec75f18f8d 100644 --- a/ZendAccelerator.h +++ b/ZendAccelerator.h @@ -27,7 +27,7 @@ #endif #define ACCELERATOR_PRODUCT_NAME "Zend Optimizer+" -#define ACCELERATOR_VERSION "7.0.0-dev" +#define ACCELERATOR_VERSION "7.0.0" /* 2 - added Profiler support, on 20010712 */ /* 3 - added support for Optimizer's encoded-only-files mode */ /* 4 - works with the new Optimizer, that supports the file format with licenses */ From 2c9583413540d099e48bba4fccd59e4bcf1a07ea Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 4 Mar 2013 15:29:02 +0400 Subject: [PATCH 094/276] Increased version number --- ZendAccelerator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZendAccelerator.h b/ZendAccelerator.h index 5ec75f18f8d..268d86faaa4 100644 --- a/ZendAccelerator.h +++ b/ZendAccelerator.h @@ -27,7 +27,7 @@ #endif #define ACCELERATOR_PRODUCT_NAME "Zend Optimizer+" -#define ACCELERATOR_VERSION "7.0.0" +#define ACCELERATOR_VERSION "7.0.1-dev" /* 2 - added Profiler support, on 20010712 */ /* 3 - added support for Optimizer's encoded-only-files mode */ /* 4 - works with the new Optimizer, that supports the file format with licenses */ From a293bd1c4af6c7fbdabaeb7d0cd12a6ce6cdcfac Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 4 Mar 2013 19:49:53 +0800 Subject: [PATCH 095/276] release 7.0.0 --- package.xml | 126 ++++++++++++++++++++++++++-------------------------- 1 file changed, 62 insertions(+), 64 deletions(-) diff --git a/package.xml b/package.xml index 114d0ba8ccb..05d9dcbffec 100644 --- a/package.xml +++ b/package.xml @@ -7,15 +7,13 @@ xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> zendoptimizerplus pecl.php.net - The Zend Optimizer+ provides faster PHP execution through opcode caching and -optimization. + The Zend Optimizer+ provides faster PHP execution through opcode caching and optimization. -The Zend Optimizer+ provides faster PHP execution through opcode caching and -optimization. It improves PHP performance by storing precompiled script -bytecode in the shared memory. This eliminates the stages of reading code from -the disk and compiling it on future access. In addition, it applies a few -bytecode optimization patterns that make code execution faster. - + The Zend Optimizer+ provides faster PHP execution through opcode caching and + optimization. It improves PHP performance by storing precompiled script + bytecode in the shared memory. This eliminates the stages of reading code from + the disk and compiling it on future access. In addition, it applies a few + bytecode optimization patterns that make code execution faster. Dmitry Stogov @@ -23,65 +21,65 @@ bytecode optimization patterns that make code execution faster. dmitry@zend.com yes - 2013-02-28 - + 2013-03-04 + - 0.1.0 - 0.1.0 + 7.0.0 + 7.0.0 - alpha - alpha + beta + beta PHP License -Initial release + - Initial release - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -99,17 +97,17 @@ Initial release - 0.1.0 - 0.1.0 + 7.0.0 + 7.0.0 - alpha - alpha + beta + beta - 2013-02-28 + 2013-03-04 PHP License -Initial release. + - Initial release. From 3b78c87a36fbdb13b9bf5c4f6914b5d4aab2ab5e Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Tue, 5 Mar 2013 13:37:49 +0800 Subject: [PATCH 096/276] Fixed #54 (PECL install adds extension= instead of zend_extension= to php.ini) --- package.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 05d9dcbffec..d085cf6bd81 100644 --- a/package.xml +++ b/package.xml @@ -93,7 +93,7 @@ zendoptimizerplus - + From 9c5039eabb54bbdd45376c7c79d83bc6e2fd71ba Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 5 Mar 2013 12:17:18 +0400 Subject: [PATCH 097/276] Save a stat() call by calling sapi_module.get_stat() --- ZendAccelerator.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index 7f1c8f84b2b..e0576b8a0ca 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -699,6 +699,17 @@ static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle { struct stat statbuf; + if (sapi_module.get_stat && + !EG(opline_ptr) && + file_handle->filename == SG(request_info).path_translated) { + + struct stat *tmpbuf = sapi_module.get_stat(TSRMLS_C); + + if (tmpbuf) { + return tmpbuf->st_mtime; + } + } + #ifdef ZEND_WIN32 accel_time_t res; @@ -782,6 +793,8 @@ static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle static inline int do_validate_timestamps(zend_persistent_script *persistent_script, zend_file_handle *file_handle TSRMLS_DC) { zend_file_handle ps_handle; + char actualpath [MAXPATHLEN + 1]; + char *full_path_ptr = NULL; /** check that the persistant script is indeed the same file we cached * (if part of the path is a symlink than it possible that the user will change it) @@ -792,22 +805,29 @@ static inline int do_validate_timestamps(zend_persistent_script *persistent_scri return FAILURE; } } else { - char actualpath [MAXPATHLEN + 1]; - char *full_path_ptr; - full_path_ptr = VCWD_REALPATH(file_handle->filename, actualpath); if (full_path_ptr && strcmp(persistent_script->full_path, full_path_ptr) != 0) { return FAILURE; } + file_handle->opened_path = full_path_ptr; } if (persistent_script->timestamp == 0) { + if (full_path_ptr) { + file_handle->opened_path = NULL; + } return FAILURE; } if (zend_get_file_handle_timestamp(file_handle TSRMLS_CC) == persistent_script->timestamp) { + if (full_path_ptr) { + file_handle->opened_path = NULL; + } return SUCCESS; } + if (full_path_ptr) { + file_handle->opened_path = NULL; + } ps_handle.type = ZEND_HANDLE_FILENAME; ps_handle.filename = persistent_script->full_path; From fae0a738df8542d909c4e56b4af89abcfbc2f99e Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 5 Mar 2013 14:57:50 +0400 Subject: [PATCH 098/276] Fixed bug #64353 (Built-in classes can be unavailable with dynamic includes and Optimizer+) --- ZendAccelerator.c | 14 ++++++++++++++ tests/bug64353.phpt | 29 +++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 tests/bug64353.phpt diff --git a/ZendAccelerator.c b/ZendAccelerator.c index e0576b8a0ca..aa226706ec1 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -1207,6 +1207,20 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han return NULL; } +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + if (file_handle->type == ZEND_HANDLE_STREAM) { + char *buf; + size_t size, offset = 0; + + /* Stream callbacks needs to be called in context of original + * function and class tables (see: https://bugs.php.net/bug.php?id=64353) + */ + if (zend_stream_fixup(file_handle, &buf, &size TSRMLS_CC) == FAILURE) { + return NULL; + } + } +#endif + new_persistent_script = create_persistent_script(); /* Save the original values for the op_array, function table and class table */ diff --git a/tests/bug64353.phpt b/tests/bug64353.phpt new file mode 100644 index 00000000000..32e70cc35ea --- /dev/null +++ b/tests/bug64353.phpt @@ -0,0 +1,29 @@ +--TEST-- +Bug #64353 (Built-in classes can be unavailable with dynamic includes and Optimizer+) +--INI-- +zend_optimizerplus.enable=1 +zend_optimizerplus.enable_cli=1 +--SKIPIF-- + +--FILE-- +data = strtoupper($bucket->data); + $consumed += $bucket->datalen; +// stream_bucket_append($out, $bucket); + } + return PSFS_PASS_ON; + } +} + +stream_filter_register('bug.test', 'BugLoader'); +include "php://filter/read=bug.test/resource=test.php"; +echo "OK\n"; +?> +--EXPECT-- +OK From 6ab1759369d16d46bf20b175c6158f38fd816893 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 5 Mar 2013 15:46:21 +0400 Subject: [PATCH 099/276] Fixed uninitialized variable --- ZendAccelerator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index aa226706ec1..9690bb8122f 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -1216,6 +1216,7 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han * function and class tables (see: https://bugs.php.net/bug.php?id=64353) */ if (zend_stream_fixup(file_handle, &buf, &size TSRMLS_CC) == FAILURE) { + *op_array_p = NULL; return NULL; } } From c3c244af811d7288fad407ce61aa2f719dbbef44 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 5 Mar 2013 22:49:31 +0400 Subject: [PATCH 100/276] Fixed test --- tests/bug64353.phpt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/bug64353.phpt b/tests/bug64353.phpt index 32e70cc35ea..a4e1dabc250 100644 --- a/tests/bug64353.phpt +++ b/tests/bug64353.phpt @@ -1,6 +1,7 @@ --TEST-- Bug #64353 (Built-in classes can be unavailable with dynamic includes and Optimizer+) --INI-- +allow_url_include=1 zend_optimizerplus.enable=1 zend_optimizerplus.enable_cli=1 --SKIPIF-- @@ -13,16 +14,15 @@ class BugLoader extends php_user_filter { eval("class Test extends ArrayObject {}"); } while ($bucket = stream_bucket_make_writeable($in)) { - $bucket->data = strtoupper($bucket->data); $consumed += $bucket->datalen; -// stream_bucket_append($out, $bucket); + stream_bucket_append($out, $bucket); } return PSFS_PASS_ON; } } stream_filter_register('bug.test', 'BugLoader'); -include "php://filter/read=bug.test/resource=test.php"; +include "php://filter/read=bug.test/resource=data://text/plain, --EXPECT-- From bfb8b9153b752e5ed22ed2a621c5dc9f77df008d Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 5 Mar 2013 20:24:58 +0100 Subject: [PATCH 101/276] fix ANSI C90 compat --- ZendAccelerator.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index 9690bb8122f..06469f5c025 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -698,6 +698,9 @@ static accel_time_t zend_get_file_handle_timestamp_win(zend_file_handle *file_ha static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle TSRMLS_DC) { struct stat statbuf; +#ifdef ZEND_WIN32 + accel_time_t res; +#endif if (sapi_module.get_stat && !EG(opline_ptr) && @@ -711,8 +714,6 @@ static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle } #ifdef ZEND_WIN32 - accel_time_t res; - res = zend_get_file_handle_timestamp_win(file_handle); if (res) { return res; From be5369be5930c5d00be1f2cbb90471049bedb322 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 6 Mar 2013 11:22:20 +0800 Subject: [PATCH 102/276] Add maintainers inot package.xml otherwise, when doing release, pecl net will sync the maintianers info form package.xml --- package.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/package.xml b/package.xml index d085cf6bd81..11c4684d729 100644 --- a/package.xml +++ b/package.xml @@ -21,6 +21,24 @@ dmitry@zend.com yes + + Zeev Suraski + zeev + zeev@zend.com + yes + + + Hannes Magnusson + bjori + bjori@php.net + yes + + + Xinchen Hui + laruence + laruence@php.net + yes + 2013-03-04 From 08bfdc75a4c6656192706cd153fc28ab89a821bc Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 6 Mar 2013 09:41:59 +0400 Subject: [PATCH 103/276] Allows exclusion of large files from being cached --- README | 4 +++ ZendAccelerator.c | 54 +++++++++++++++++++++++++++++---------- ZendAccelerator.h | 1 + zend_accelerator_module.c | 2 ++ 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/README b/README index b44386e87a0..c0304a73abf 100644 --- a/README +++ b/README @@ -159,6 +159,10 @@ zend_optimizerplus.blacklist_filename compile time evaluation. 3) Code that triggers an Optimizer+ bug. +zend_optimizerplus.max_file_size (default "0") + Allows exclusion of large files from being cached. By default all files + are cached. + zend_optimizerplus.consistency_checks (default "0") Check the cache checksum each N requests. The default value of "0" means that the checks are disabled. diff --git a/ZendAccelerator.c b/ZendAccelerator.c index 06469f5c025..ed942265604 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -654,7 +654,7 @@ static int zend_get_stream_timestamp(const char *filename, struct stat *statbuf } #if ZEND_WIN32 -static accel_time_t zend_get_file_handle_timestamp_win(zend_file_handle *file_handle) +static accel_time_t zend_get_file_handle_timestamp_win(zend_file_handle *file_handle, size_t *size) { static unsigned __int64 utc_base = 0; static FILETIME utc_base_ft; @@ -689,13 +689,16 @@ static accel_time_t zend_get_file_handle_timestamp_win(zend_file_handle *file_ha ftime = (((unsigned __int64)fdata.ftLastWriteTime.dwHighDateTime) << 32) + fdata.ftLastWriteTime.dwLowDateTime - utc_base; ftime /= 10000000L; + if (size) { + *size = (size_t)(((unsigned __int64)fdata.nFileSizeHigh) << 32 + (unsigned __int64)fdata.nFileSizeLow); + } return (accel_time_t)ftime; } return 0; } #endif -static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle TSRMLS_DC) +static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle, size_t *size TSRMLS_DC) { struct stat statbuf; #ifdef ZEND_WIN32 @@ -709,12 +712,15 @@ static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle struct stat *tmpbuf = sapi_module.get_stat(TSRMLS_C); if (tmpbuf) { + if (size) { + *size = tmpbuf->st_size; + } return tmpbuf->st_mtime; } } #ifdef ZEND_WIN32 - res = zend_get_file_handle_timestamp_win(file_handle); + res = zend_get_file_handle_timestamp_win(file_handle, size); if (res) { return res; } @@ -788,6 +794,9 @@ static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle return 0; } + if (size) { + *size = statbuf.st_size; + } return statbuf.st_mtime; } @@ -820,7 +829,7 @@ static inline int do_validate_timestamps(zend_persistent_script *persistent_scri return FAILURE; } - if (zend_get_file_handle_timestamp(file_handle TSRMLS_CC) == persistent_script->timestamp) { + if (zend_get_file_handle_timestamp(file_handle, NULL TSRMLS_CC) == persistent_script->timestamp) { if (full_path_ptr) { file_handle->opened_path = NULL; } @@ -834,7 +843,7 @@ static inline int do_validate_timestamps(zend_persistent_script *persistent_scri ps_handle.filename = persistent_script->full_path; ps_handle.opened_path = persistent_script->full_path; - if (zend_get_file_handle_timestamp(&ps_handle TSRMLS_CC) == persistent_script->timestamp) { + if (zend_get_file_handle_timestamp(&ps_handle, NULL TSRMLS_CC) == persistent_script->timestamp) { return SUCCESS; } @@ -1178,6 +1187,7 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han zval *orig_user_error_handler; zend_op_array *op_array; int do_bailout = 0; + accel_time_t timestamp = 0; #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO zend_uint orig_compiler_options = 0; #endif @@ -1211,7 +1221,7 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO if (file_handle->type == ZEND_HANDLE_STREAM) { char *buf; - size_t size, offset = 0; + size_t size; /* Stream callbacks needs to be called in context of original * function and class tables (see: https://bugs.php.net/bug.php?id=64353) @@ -1223,6 +1233,29 @@ 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) { + size_t size = 0; + + /* Obtain the file timestamps, *before* actually compiling them, + * otherwise we have a race-condition. + */ + timestamp = zend_get_file_handle_timestamp(file_handle, ZCG(accel_directives).max_file_size > 0 ? &size : NULL TSRMLS_CC); + + /* If we can't obtain a timestamp (that means file is possibly socket) + * we won't cache it + */ + if (timestamp == 0) { + *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); + return NULL; + } + } + new_persistent_script = create_persistent_script(); /* Save the original values for the op_array, function table and class table */ @@ -1295,14 +1328,7 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han /* Obtain the file timestamps, *before* actually compiling them, * otherwise we have a race-condition. */ - new_persistent_script->timestamp = zend_get_file_handle_timestamp(file_handle TSRMLS_CC); - - /* If we can't obtain a timestamp (that means file is possibly socket) - * we return it but do not persist it - */ - if (new_persistent_script->timestamp == 0) { - return new_persistent_script; - } + new_persistent_script->timestamp = timestamp; new_persistent_script->dynamic_members.revalidate = ZCSG(revalidate_at); } diff --git a/ZendAccelerator.h b/ZendAccelerator.h index 268d86faaa4..310605b878b 100644 --- a/ZendAccelerator.h +++ b/ZendAccelerator.h @@ -219,6 +219,7 @@ typedef struct _zend_accel_directives { long log_verbosity_level; long optimization_level; + long max_file_size; #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO long interned_strings_buffer; #endif diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index 1bf16e5035c..5f7c32b594e 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -218,6 +218,7 @@ ZEND_INI_BEGIN() STD_PHP_INI_ENTRY("zend_optimizerplus.revalidate_freq" , "2" , PHP_INI_ALL , OnUpdateLong, accel_directives.revalidate_freq, zend_accel_globals, accel_globals) STD_PHP_INI_ENTRY("zend_optimizerplus.preferred_memory_model", "" , PHP_INI_SYSTEM, OnUpdateStringUnempty, accel_directives.memory_model, zend_accel_globals, accel_globals) STD_PHP_INI_ENTRY("zend_optimizerplus.blacklist_filename" , "" , PHP_INI_SYSTEM, OnUpdateAccelBlacklist, accel_directives.user_blacklist_filename, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("zend_optimizerplus.max_file_size" , "0" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.max_file_size, zend_accel_globals, accel_globals) STD_PHP_INI_ENTRY("zend_optimizerplus.protect_memory" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.protect_memory, zend_accel_globals, accel_globals) STD_PHP_INI_ENTRY("zend_optimizerplus.save_comments" , "1" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.save_comments, zend_accel_globals, accel_globals) @@ -554,6 +555,7 @@ static ZEND_FUNCTION(accelerator_get_configuration) add_assoc_long(directives, "zend_optimizerplus.revalidate_freq", ZCG(accel_directives).revalidate_freq); add_assoc_string(directives, "zend_optimizerplus.preferred_memory_model", STRING_NOT_NULL(ZCG(accel_directives).memory_model), 1); add_assoc_string(directives, "zend_optimizerplus.blacklist_filename", STRING_NOT_NULL(ZCG(accel_directives).user_blacklist_filename), 1); + add_assoc_long(directives, "zend_optimizerplus.max_file_size", ZCG(accel_directives).max_file_size); add_assoc_string(directives, "zend_optimizerplus.error_log", STRING_NOT_NULL(ZCG(accel_directives).error_log), 1); add_assoc_bool(directives, "zend_optimizerplus.protect_memory", ZCG(accel_directives).protect_memory); From b34e50cc78b29f713ac4c4ecd93c069f24001cba Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 6 Mar 2013 17:49:47 +0400 Subject: [PATCH 104/276] Fixed issue #58 (PHP-5.2 compatibility) --- zend_accelerator_module.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index 5f7c32b594e..b3aac5f0027 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -467,9 +467,11 @@ static ZEND_FUNCTION(accelerator_get_status) /* keep the compiler happy */ (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO if (zend_parse_parameters_none() == FAILURE) { RETURN_FALSE; } +#endif if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled)) { RETURN_FALSE; @@ -526,9 +528,11 @@ static ZEND_FUNCTION(accelerator_get_configuration) /* keep the compiler happy */ (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO if (zend_parse_parameters_none() == FAILURE) { RETURN_FALSE; } +#endif array_init(return_value); @@ -588,9 +592,11 @@ static ZEND_FUNCTION(accelerator_reset) /* keep the compiler happy */ (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO if (zend_parse_parameters_none() == FAILURE) { RETURN_FALSE; } +#endif if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled)) { RETURN_FALSE; From 1143d3b1d012ded505bf3e4525ae86f95b729dd9 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 6 Mar 2013 22:32:21 +0400 Subject: [PATCH 105/276] Fixed Issue #57 (segfaults in drupal7) --- Optimizer/block_pass.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/Optimizer/block_pass.c b/Optimizer/block_pass.c index 4ee89326a0e..9922cbdb486 100644 --- a/Optimizer/block_pass.c +++ b/Optimizer/block_pass.c @@ -180,7 +180,10 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg) if (op_array->brk_cont_array[i].start >= 0) { int parent = op_array->brk_cont_array[i].parent; - while (parent >= 0 && op_array->brk_cont_array[parent].start < 0) { + while (parent >= 0 && + op_array->brk_cont_array[parent].start < 0 && + op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_FREE && + op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_SWITCH_FREE) { parent = op_array->brk_cont_array[parent].parent; } op_array->brk_cont_array[i].parent = parent; @@ -190,7 +193,9 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg) if (j) { j = 0; for (i = 0; i< op_array->last_brk_cont; i++) { - if (op_array->brk_cont_array[i].start >= 0) { + if (op_array->brk_cont_array[i].start >= 0 && + (op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FREE || + op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_SWITCH_FREE)) { if (i != j) { op_array->brk_cont_array[j] = op_array->brk_cont_array[i]; } @@ -398,6 +403,9 @@ static inline void del_source(zend_code_block *from, zend_code_block *to) static void delete_code_block(zend_code_block *block) { + if (block->protected) { + return; + } if (block->follow_to) { zend_block_source *bs = block->sources; while (bs) { @@ -478,6 +486,16 @@ static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int /* Walk thorough all pathes */ zend_access_path(start); + /* Add brk/cont pathes */ + if (op_array->last_brk_cont) { + int i; + for (i=0; i< op_array->last_brk_cont; i++) { + zend_access_path(cfg->loop_start[i]); + zend_access_path(cfg->loop_cont[i]); + zend_access_path(cfg->loop_brk[i]); + } + } + /* Add exception pathes */ if (op_array->last_try_catch) { int i; @@ -527,7 +545,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, print_block(block, op_array->opcodes, "Opt "); /* remove leading NOPs */ - while (block->start_opline->opcode == ZEND_NOP) { + while (block->len > 0 && block->start_opline->opcode == ZEND_NOP) { if (block->len == 1) { /* this block is all NOPs, join with following block */ if (block->follow_to) { @@ -1083,7 +1101,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, } /* remove leading NOPs */ - while (block->start_opline->opcode == ZEND_NOP) { + while (block->len > 0 && block->start_opline->opcode == ZEND_NOP) { if (block->len == 1) { /* this block is all NOPs, join with following block */ if (block->follow_to) { @@ -1255,6 +1273,9 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra /* last_op is the last opcode of the current block */ zend_op *last_op = (block->start_opline + block->len - 1); + if (!block->len) { + return; + } switch (last_op->opcode) { case ZEND_JMP: { From b54351134314737374721a3f5d1d043a86f067aa Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 7 Mar 2013 08:13:58 +0400 Subject: [PATCH 106/276] fixed memory leaks --- Optimizer/block_pass.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/Optimizer/block_pass.c b/Optimizer/block_pass.c index 9922cbdb486..a1fc760e73f 100644 --- a/Optimizer/block_pass.c +++ b/Optimizer/block_pass.c @@ -172,12 +172,12 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg) * exception handling */ if (op_array->last_brk_cont) { int i, j; - cfg->loop_start = ecalloc(op_array->last_brk_cont, sizeof(zend_code_block *)); - cfg->loop_cont = ecalloc(op_array->last_brk_cont, sizeof(zend_code_block *)); - cfg->loop_brk = ecalloc(op_array->last_brk_cont, sizeof(zend_code_block *)); + j = 0; for (i = 0; i< op_array->last_brk_cont; i++) { - if (op_array->brk_cont_array[i].start >= 0) { + if (op_array->brk_cont_array[i].start >= 0 && + (op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FREE || + op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_SWITCH_FREE)) { int parent = op_array->brk_cont_array[i].parent; while (parent >= 0 && @@ -191,6 +191,9 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg) } } if (j) { + cfg->loop_start = ecalloc(op_array->last_brk_cont, sizeof(zend_code_block *)); + cfg->loop_cont = ecalloc(op_array->last_brk_cont, sizeof(zend_code_block *)); + cfg->loop_brk = ecalloc(op_array->last_brk_cont, sizeof(zend_code_block *)); j = 0; for (i = 0; i< op_array->last_brk_cont; i++) { if (op_array->brk_cont_array[i].start >= 0 && @@ -212,13 +215,7 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg) } op_array->last_brk_cont = j; } else { - efree(cfg->loop_start); - efree(cfg->loop_cont); - efree(cfg->loop_brk); efree(op_array->brk_cont_array); - cfg->loop_start = NULL; - cfg->loop_cont = NULL; - cfg->loop_brk = NULL; op_array->brk_cont_array = NULL; op_array->last_brk_cont = 0; } From bc926f2fbb260f220a1e19bd4f17d71c9be7a344 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Thu, 7 Mar 2013 12:19:30 +0800 Subject: [PATCH 107/276] Add test script for #57 (segfaults in drupal7) --- tests/issue0057.phpt | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/issue0057.phpt diff --git a/tests/issue0057.phpt b/tests/issue0057.phpt new file mode 100644 index 00000000000..1ef3cbb8e26 --- /dev/null +++ b/tests/issue0057.phpt @@ -0,0 +1,38 @@ +--TEST-- +ISSUE #57 (segfaults in drupal7) +--INI-- +zend_optimizerplus.enable=1 +zend_optimizerplus.enable_cli=1 +zend_optimizerplus.optimization_level=-1 +--SKIPIF-- + +--FILE-- +getMessage(); +} + +?> +--EXPECT-- +exception From d2f9804e1f1dcaf44a66f198b70b1f27959ca775 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Thu, 7 Mar 2013 14:53:22 +0800 Subject: [PATCH 108/276] add tests into package --- package.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.xml b/package.xml index 11c4684d729..b890a2dda7e 100644 --- a/package.xml +++ b/package.xml @@ -97,6 +97,8 @@ + + From 01049ca7aed40a5f1081d0303c69a40dae0f982e Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Fri, 8 Mar 2013 10:34:17 +0800 Subject: [PATCH 109/276] Fixed bug #61025 (__invoke() visibility not honored) --- NEWS | 1 + NEWS-5.5 | 1 + Zend/tests/bug61025.phpt | 27 +++++++++++++++++++++++++++ Zend/zend_closures.c | 1 - Zend/zend_closures.h | 2 -- Zend/zend_compile.c | 8 ++++++++ Zend/zend_compile.h | 1 + 7 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 Zend/tests/bug61025.phpt diff --git a/NEWS b/NEWS index a82e9a26d92..a1c0aea21f7 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,7 @@ PHP NEWS 07 Mar 2013, PHP 5.5.0 Alpha 6 - Core: + . Fixed bug #61025 (__invoke() visibility not honored). (Laruence) . Fixed bug #49348 (Uninitialized ++$foo->bar; does not cause a notice). (Stas) diff --git a/NEWS-5.5 b/NEWS-5.5 index a5b11c0d326..d5acd617b43 100644 --- a/NEWS-5.5 +++ b/NEWS-5.5 @@ -3,6 +3,7 @@ PHP NEWS ?? ??? 201?, PHP 5.5.0 Beta 1 - Core: + . Fixed bug #61025 (__invoke() visibility not honored). (Laruence) . Fixed bug #49348 (Uninitialized ++$foo->bar; does not cause a notice). (Stas) diff --git a/Zend/tests/bug61025.phpt b/Zend/tests/bug61025.phpt new file mode 100644 index 00000000000..0709c28fbc5 --- /dev/null +++ b/Zend/tests/bug61025.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #61025 (__invoke() visibility not honored) +--FILE-- +__invoke(); + +?> +--EXPECTF-- +Warning: The magic method __invoke() must have public visibility and cannot be static in %sbug61025.php on line %d + +Warning: The magic method __invoke() must have public visibility and cannot be static in %sbug61025.php on line %d +Bar +Fatal error: Call to private method Bar::__invoke() from context '' in %sbug61025.php on line %d diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 0de92833377..5faefbd2241 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -291,7 +291,6 @@ static zend_object_value zend_closure_clone(zval *zobject TSRMLS_DC) /* {{{ */ } /* }}} */ - int zend_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC) /* {{{ */ { zend_closure *closure; diff --git a/Zend/zend_closures.h b/Zend/zend_closures.h index c41cf475603..9d50641d219 100644 --- a/Zend/zend_closures.h +++ b/Zend/zend_closures.h @@ -24,8 +24,6 @@ BEGIN_EXTERN_C() -#define ZEND_INVOKE_FUNC_NAME "__invoke" - void zend_register_closure_ce(TSRMLS_D); extern ZEND_API zend_class_entry *zend_ce_closure; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index e45419d3f0c..aa1df99ea95 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1621,6 +1621,10 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) { zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static"); } + } else if ((name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1))) { + if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) { + zend_error(E_WARNING, "The magic method __invoke() must have public visibility and cannot be static"); + } } } else { char *class_lcname; @@ -1677,6 +1681,10 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static"); } CG(active_class_entry)->__tostring = (zend_function *) CG(active_op_array); + } else if ((name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1))) { + if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) { + zend_error(E_WARNING, "The magic method __invoke() must have public visibility and cannot be static"); + } } else if (!(fn_flags & ZEND_ACC_STATIC)) { CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC; } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 8042dd54eee..2295cffab94 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -856,6 +856,7 @@ END_EXTERN_C() #define ZEND_CALLSTATIC_FUNC_NAME "__callstatic" #define ZEND_TOSTRING_FUNC_NAME "__tostring" #define ZEND_AUTOLOAD_FUNC_NAME "__autoload" +#define ZEND_INVOKE_FUNC_NAME "__invoke" /* The following constants may be combined in CG(compiler_options) * to change the default compiler behavior */ From 6824dc6b333c69384677d6f37c48d7f57228de13 Mon Sep 17 00:00:00 2001 From: David Soria Parra Date: Fri, 8 Mar 2013 11:12:35 +0100 Subject: [PATCH 110/276] use NEWS only --- NEWS-5.5 | 345 ------------------------------------------------------- 1 file changed, 345 deletions(-) delete mode 100644 NEWS-5.5 diff --git a/NEWS-5.5 b/NEWS-5.5 deleted file mode 100644 index d5acd617b43..00000000000 --- a/NEWS-5.5 +++ /dev/null @@ -1,345 +0,0 @@ -PHP NEWS -||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? 201?, PHP 5.5.0 Beta 1 - -- Core: - . Fixed bug #61025 (__invoke() visibility not honored). (Laruence) - . Fixed bug #49348 (Uninitialized ++$foo->bar; does not cause a notice). - (Stas) - -- Sockets: - . Fixed bug #64287 (sendmsg/recvmsg shutdown handler causes segfault). - (Gustavo) - -- PCRE: - . Merged PCRE 8.32. (Anatol) - -21 Feb 2013, PHP 5.5.0 Alpha 5 - -- Core: - . Implemented FR #64175 (Added HTTP codes as of RFC 6585). (Jonh Wendell) - . Fixed bug #64135 (Exceptions from set_error_handler are not always - propagated). (Laruence) - . Fixed bug #63830 (Segfault on undefined function call in nested generator). - (Nikita Popov) - . Fixed bug #60833 (self, parent, static behave inconsistently - case-sensitive). (Stas, mario at include-once dot org) - . Implemented FR #60524 (specify temp dir by php.ini). (ALeX Kazik). - . Fixed bug #64142 (dval to lval different behavior on ppc64). (Remi) - . Added ARMv7/v8 versions of various Zend arithmetic functions that are - implemented using inline assembler (Ard Biesheuvel) - . Fix undefined behavior when converting double variables to integers. - The double is now always rounded towards zero, the remainder of its division - by 2^32 or 2^64 (depending on sizeof(long)) is calculated and it's made - signed assuming a two's complement representation. (Gustavo) - -- CLI server: - . Fixed bug #64128 (buit-in web server is broken on ppc64). (Remi) - -- cURL: - . Implemented FR #46439 - added CURLFile for safer file uploads. - (Stas) - -- Intl: - . Cherry-picked UConverter wrapper, which had accidentaly been committed only - to master. - -- mysqli - . Added mysqli_begin_transaction()/mysqli::begin_transaction(). Implemented - all options, per MySQL 5.6, which can be used with START TRANSACTION, COMMIT - and ROLLBACK through options to mysqli_commit()/mysqli_rollback() and their - respective OO counterparts. They work in libmysql and mysqlnd mode. (Andrey) - . Added mysqli_savepoint(), mysqli_release_savepoint(). (Andrey) - -- mysqlnd - . Add new begin_transaction() call to the connection object. Implemented all - options, per MySQL 5.6, which can be used with START TRANSACTION, COMMIT - and ROLLBACK. (Andrey) - . Added mysqlnd_savepoint(), mysqlnd_release_savepoint(). (Andrey) - -- Sockets: - . Added recvmsg() and sendmsg() wrappers. (Gustavo) - See https://wiki.php.net/rfc/sendrecvmsg - -- Filter: - . Implemented FR #49180 - added MAC address validation. (Martin) - -- Phar: - . Fixed timestamp update on Phar contents modification. (Dmitry) - -- SPL: - . Fixed bug #64264 (SPLFixedArray toArray problem). (Laruence) - . Fixed bug #64228 (RecursiveDirectoryIterator always assumes SKIP_DOTS). - (patch by kriss@krizalys.com, Laruence) - . Fixed bug #64106 (Segfault on SplFixedArray[][x] = y when extended). - (Nikita Popov) - . Fixed bug #52861 (unset fails with ArrayObject and deep arrays). - (Mike Willbanks) - -- SNMP: - . Fixed bug #64124 (IPv6 malformed). (Boris Lytochkin) - -24 Jan 2013, PHP 5.5.0 Alpha 4 - -- Core: - . Fixed bug #63980 (object members get trimmed by zero bytes). (Laruence) - . Implemented RFC for Class Name Resolution As Scalar Via "class" Keyword. - (Ralph Schindler, Nikita Popov, Lars) - -- DateTime - . Added DateTimeImmutable - a variant of DateTime that only returns the - modified state instead of changing itself. (Derick) - -- FPM: - . Fixed bug #63999 (php with fpm fails to build on Solaris 10 or 11). (Adam) - -- pgsql: - . Bug #46408: Locale number format settings can cause pg_query_params to - break with numerics. (asmecher, Lars) - -- dba: - . Bug #62489: dba_insert not working as expected. - (marc-bennewitz at arcor dot de, Lars) - -- Reflection: - . Fixed bug #64007 (There is an ability to create instance of Generator by - hand). (Laruence) - -10 Jan 2013, PHP 5.5.0 Alpha 3 - -- General improvements: - . Fixed bug #63874 (Segfault if php_strip_whitespace has heredoc). (Pierrick) - . Fixed bug #63822 (Crash when using closures with ArrayAccess). - (Nikita Popov) - . Add Generator::throw() method. (Nikita Popov) - . Bug #23955: allow specifying Max-Age attribute in setcookie() (narfbg, Lars) - . Bug #52126: timestamp for mail.log (Martin Jansen, Lars) - -- mysqlnd - . Fixed return value of mysqli_stmt_affected_rows() in the time after - prepare() and before execute(). (Andrey) - -- cURL: - . Added new functions curl_escape, curl_multi_setopt, curl_multi_strerror - curl_pause, curl_reset, curl_share_close, curl_share_init, - curl_share_setopt curl_strerror and curl_unescape. (Pierrick) - . Addes new curl options CURLOPT_TELNETOPTIONS, CURLOPT_GSSAPI_DELEGATION, - CURLOPT_ACCEPTTIMEOUT_MS, CURLOPT_SSL_OPTIONS, CURLOPT_TCP_KEEPALIVE, - CURLOPT_TCP_KEEPIDLE and CURLOPT_TCP_KEEPINTVL. (Pierrick) - -18 Dec 2012, PHP 5.5.0 Alpha 2 - -- General improvements: - . Added systemtap support by enabling systemtap compatible dtrace probes on - linux. (David Soria Parra) - . Added support for using empty() on the result of function calls and - other expressions (https://wiki.php.net/rfc/empty_isset_exprs). - (Nikita Popov) - . Optimized access to temporary and compiled VM variables. 8% less memory - reads. (Dmitry) - . The VM stacks for passing function arguments and syntaticaly nested calls - were merged into a single stack. The stack size needed for op_array - execution is calculated at compile time and preallocated at once. As result - all the stack push operatins don't require checks for stack overflow - any more. (Dmitry) - -- MySQL - . This extension is now deprecated, and deprecation warnings will be generated - when connections are established to databases via mysql_connect(), - mysql_pconnect(), or through implicit connection: use MySQLi or PDO_MySQL - instead (https://wiki.php.net/rfc/mysql_deprecation). (Adam) - -- Fileinfo: - . Fixed bug #63590 (Different results in TS and NTS under Windows). - (Anatoliy) - -- Apache2 Handler SAPI: - . Enabled Apache 2.4 configure option for Windows (Pierre, Anatoliy) - -13 Nov 2012, PHP 5.5.0 Alpha 1 - -- General improvements: - . Added generators and coroutines (https://wiki.php.net/rfc/generators). - (Nikita Popov) - . Added "finally" keyword (https://wiki.php.net/rfc/finally). (Laruence) - . Add simplified password hashing API - (https://wiki.php.net/rfc/password_hash). (Anthony Ferrara) - . Added support for list in foreach (https://wiki.php.net/rfc/foreachlist). - (Laruence) - . Added support for using empty() on the result of function calls and - other expressions (https://wiki.php.net/rfc/empty_isset_exprs). - (Nikita Popov) - . Added support for constant array/string dereferencing. (Laruence) - . Improve set_exception_handler while doing reset.(Laruence) - . Remove php_logo_guid(), php_egg_logo_guid(), php_real_logo_guid(), - zend_logo_guid(). (Adnrew Faulds) - . Drop Windows XP and 2003 support. (Pierre) - -- Calendar: - . Fixed bug #54254 (cal_from_jd returns month = 6 when there is only one Adar) - (Stas, Eitan Mosenkis) - -- Core: - . Added boolval(). (Jille Timmermans) - . Added "Z" option to pack/unpack. (Gustavo) - . Implemented FR #60738 (Allow 'set_error_handler' to handle NULL). - (Laruence, Nikita Popov) - . Added optional second argument for assert() to specify custom message. Patch - by Lonny Kapelushnik (lonny@lonnylot.com). (Lars) - . Fixed bug #18556 (Engine uses locale rules to handle class names). (Stas) - . Fixed bug #61681 (Malformed grammar). (Nikita Popov, Etienne, Laruence) - . Fixed bug #61038 (unpack("a5", "str\0\0") does not work as expected). - (srgoogleguy, Gustavo) - . Return previous handler when passing NULL to set_error_handler and - set_exception_handler. (Nikita Popov) - -- cURL: - . Added support for CURLOPT_FTP_RESPONSE_TIMEOUT, CURLOPT_APPEND, - CURLOPT_DIRLISTONLY, CURLOPT_NEW_DIRECTORY_PERMS, CURLOPT_NEW_FILE_PERMS, - CURLOPT_NETRC_FILE, CURLOPT_PREQUOTE, CURLOPT_KRBLEVEL, CURLOPT_MAXFILESIZE, - CURLOPT_FTP_ACCOUNT, CURLOPT_COOKIELIST, CURLOPT_IGNORE_CONTENT_LENGTH, - CURLOPT_CONNECT_ONLY, CURLOPT_LOCALPORT, CURLOPT_LOCALPORTRANGE, - CURLOPT_FTP_ALTERNATIVE_TO_USER, CURLOPT_SSL_SESSIONID_CACHE, - CURLOPT_FTP_SSL_CCC, CURLOPT_HTTP_CONTENT_DECODING, - CURLOPT_HTTP_TRANSFER_DECODING, CURLOPT_PROXY_TRANSFER_MODE, - CURLOPT_ADDRESS_SCOPE, CURLOPT_CRLFILE, CURLOPT_ISSUERCERT, - CURLOPT_USERNAME, CURLOPT_PASSWORD, CURLOPT_PROXYUSERNAME, - CURLOPT_PROXYPASSWORD, CURLOPT_NOPROXY, CURLOPT_SOCKS5_GSSAPI_NEC, - CURLOPT_SOCKS5_GSSAPI_SERVICE, CURLOPT_TFTP_BLKSIZE, - CURLOPT_SSH_KNOWNHOSTS, CURLOPT_FTP_USE_PRET, CURLOPT_MAIL_FROM, - CURLOPT_MAIL_RCPT, CURLOPT_RTSP_CLIENT_CSEQ, CURLOPT_RTSP_SERVER_CSEQ, - CURLOPT_RTSP_SESSION_ID, CURLOPT_RTSP_STREAM_URI, CURLOPT_RTSP_TRANSPORT, - CURLOPT_RTSP_REQUEST, CURLOPT_RESOLVE, CURLOPT_ACCEPT_ENCODING, - CURLOPT_TRANSFER_ENCODING, CURLOPT_DNS_SERVERS and CURLOPT_USE_SSL. - (Pierrick) - . Fixed bug #55635 (CURLOPT_BINARYTRANSFER no longer used. The constant - still exists for backward compatibility but is doing nothing). (Pierrick) - . Fixed bug #54995 (Missing CURLINFO_RESPONSE_CODE support). (Pierrick) - -- Datetime - . Fixed bug #61642 (modify("+5 weekdays") returns Sunday). - (Dmitri Iouchtchenko) - -- Hash - . Added support for PBKDF2 via hash_pbkdf2(). (Anthony Ferrara) - -- Intl - . The intl extension now requires ICU 4.0+. - . Added intl.use_exceptions INI directive, which controls what happens when - global errors are set together with intl.error_level. (Gustavo) - . MessageFormatter::format() and related functions now accepted named - arguments and mixed numeric/named arguments in ICU 4.8+. (Gustavo) - . MessageFormatter::format() and related functions now don't error out when - an insufficient argument count is provided. Instead, the placeholders will - remain unsubstituted. (Gustavo) - . MessageFormatter::parse() and MessageFormat::format() (and their static - equivalents) don't throw away better than second precision in the arguments. - (Gustavo) - . IntlDateFormatter::__construct and datefmt_create() now accept for the - $timezone argument time zone identifiers, IntlTimeZone objects, DateTimeZone - objects and NULL. (Gustavo) - . IntlDateFormatter::__construct and datefmt_create() no longer accept invalid - timezone identifiers or empty strings. (Gustavo) - . The default time zone used in IntlDateFormatter::__construct and - datefmt_create() (when the corresponding argument is not passed or NULL is - passed) is now the one given by date_default_timezone_get(), not the - default ICU time zone. (Gustavo) - . The time zone passed to the IntlDateFormatter is ignored if it is NULL and - if the calendar passed is an IntlCalendar object -- in this case, the - IntlCalendar's time zone will be used instead. Otherwise, the time zone - specified in the $timezone argument is used instead. This does not affect - old code, as IntlCalendar was introduced in this version. (Gustavo) - . IntlDateFormatter::__construct and datefmt_create() now accept for the - $calendar argument also IntlCalendar objects. (Gustavo) - . IntlDateFormatter::getCalendar() and datefmt_get_calendar() return false - if the IntlDateFormatter was set up with an IntlCalendar instead of the - constants IntlDateFormatter::GREGORIAN/TRADITIONAL. IntlCalendar did not - exist before this version. (Gustavo) - . IntlDateFormatter::setCalendar() and datefmt_set_calendar() now also accept - an IntlCalendar object, in which case its time zone is taken. Passing a - constant is still allowed, and still keeps the time zone. (Gustavo) - . IntlDateFormatter::setTimeZoneID() and datefmt_set_timezone_id() are - deprecated. Use IntlDateFormatter::setTimeZone() or datefmt_set_timezone() - instead. (Gustavo) - . IntlDateFormatter::format() and datefmt_format() now also accept an - IntlCalendar object for formatting. (Gustavo) - . Added the classes: IntlCalendar, IntlGregorianCalendar, IntlTimeZone, - IntlBreakIterator, IntlRuleBasedBreakIterator and - IntlCodePointBreakIterator. (Gustavo) - . Added the functions: intlcal_get_keyword_values_for_locale(), - intlcal_get_now(), intlcal_get_available_locales(), intlcal_get(), - intlcal_get_time(), intlcal_set_time(), intlcal_add(), - intlcal_set_time_zone(), intlcal_after(), intlcal_before(), intlcal_set(), - intlcal_roll(), intlcal_clear(), intlcal_field_difference(), - intlcal_get_actual_maximum(), intlcal_get_actual_minimum(), - intlcal_get_day_of_week_type(), intlcal_get_first_day_of_week(), - intlcal_get_greatest_minimum(), intlcal_get_least_maximum(), - intlcal_get_locale(), intlcal_get_maximum(), - intlcal_get_minimal_days_in_first_week(), intlcal_get_minimum(), - intlcal_get_time_zone(), intlcal_get_type(), - intlcal_get_weekend_transition(), intlcal_in_daylight_time(), - intlcal_is_equivalent_to(), intlcal_is_lenient(), intlcal_is_set(), - intlcal_is_weekend(), intlcal_set_first_day_of_week(), - intlcal_set_lenient(), intlcal_equals(), - intlcal_get_repeated_wall_time_option(), - intlcal_get_skipped_wall_time_option(), - intlcal_set_repeated_wall_time_option(), - intlcal_set_skipped_wall_time_option(), intlcal_from_date_time(), - intlcal_to_date_time(), intlcal_get_error_code(), - intlcal_get_error_message(), intlgregcal_create_instance(), - intlgregcal_set_gregorian_change(), intlgregcal_get_gregorian_change() and - intlgregcal_is_leap_year(). (Gustavo) - . Added the functions: intltz_create_time_zone(), intltz_create_default(), - intltz_get_id(), intltz_get_gmt(), intltz_get_unknown(), - intltz_create_enumeration(), intltz_count_equivalent_ids(), - intltz_create_time_zone_id_enumeration(), intltz_get_canonical_id(), - intltz_get_region(), intltz_get_tz_data_version(), - intltz_get_equivalent_id(), intltz_use_daylight_time(), intltz_get_offset(), - intltz_get_raw_offset(), intltz_has_same_rules(), intltz_get_display_name(), - intltz_get_dst_savings(), intltz_from_date_time_zone(), - intltz_to_date_time_zone(), intltz_get_error_code(), - intltz_get_error_message(). (Gustavo) - . Added the methods: IntlDateFormatter::formatObject(), - IntlDateFormatter::getCalendarObject(), IntlDateFormatter::getTimeZone(), - IntlDateFormatter::setTimeZone(). (Gustavo) - . Added the functions: datefmt_format_object(), datefmt_get_calendar_object(), - datefmt_get_timezone(), datefmt_set_timezone(), - datefmt_get_calendar_object(), intlcal_create_instance(). (Gustavo) - -- MCrypt - . mcrypt_ecb(), mcrypt_cbc(), mcrypt_cfb() and mcrypt_ofb() now throw - E_DEPRECATED. (GoogleGuy) - -- MySQLi - . Dropped support for LOAD DATA LOCAL INFILE handlers when using libmysql. - Known for stability problems. (Andrey) - . Added support for SHA256 authentication available with MySQL 5.6.6+. - (Andrey) - -- PCRE: - . Deprecated the /e modifier - (https://wiki.php.net/rfc/remove_preg_replace_eval_modifier). (Nikita Popov) - . Fixed bug #63284 (Upgrade PCRE to 8.31). (Anatoliy) - -- pgsql - . Added pg_escape_literal() and pg_escape_identifier() (Yasuo) - -- SPL - . Fix bug #60560 (SplFixedArray un-/serialize, getSize(), count() return 0, - keys are strings). (Adam) - -- Tokenizer: - . Fixed bug #60097 (token_get_all fails to lex nested heredoc). (Nikita Popov) - -- Zip: - . Upgraded libzip to 0.10.1 (Anatoliy) - -- Fileinfo: - . Fixed bug #63248 (Load multiple magic files from a directory under Windows). - (Anatoliy) - -- General improvements: - . Implemented FR #46487 (Dereferencing process-handles no longer waits on - those processes). (Jille Timmermans) - -<<< NOTE: Insert NEWS from last stable release here prior to actual release! >>> From 6fece94369bdef32ce0307bd124803c8e8bf54cf Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 9 Mar 2013 11:37:41 +0800 Subject: [PATCH 111/276] Fix date --- NEWS | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 17ecbe5670a..f8a43f6501a 100644 --- a/NEWS +++ b/NEWS @@ -1,10 +1,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? 2012, PHP 5.4.14 +?? ??? 2013, PHP 5.4.14 - PCRE: . Merged PCRE 8.32. (Anatol) -?? ??? 2012, PHP 5.4.13 +?? ??? 2013, PHP 5.4.13 - Core: . Fixed bug #64235 (Insteadof not work for class method in 5.4.11). @@ -54,7 +54,7 @@ PHP NEWS - SNMP: . Fixed bug #64124 (IPv6 malformed). (Boris Lytochkin) -21 Feb 2012, PHP 5.4.12 +21 Feb 2013, PHP 5.4.12 - Core: . Fixed bug #64099 (Wrong TSRM usage in zend_Register_class alias). (Johannes) @@ -99,7 +99,7 @@ PHP NEWS . Fixed bug #63916 (PDO::PARAM_INT casts to 32bit int internally even on 64bit builds in pdo_sqlite). (srgoogleguy, Lars) -17 Jan 2012, PHP 5.4.11 +17 Jan 2013, PHP 5.4.11 - Core: . Fixed bug #63762 (Sigsegv when Exception::$trace is changed by user). From f52b2e6a6572018eb61ad830206ed172b033232a Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 9 Mar 2013 23:00:58 +0800 Subject: [PATCH 112/276] Fixed bug #64354 (Unserialize array of objects whose class can't be autoloaded fail) about the __sleep one, since php_serialize_* are all void function, so,,only check exception at the very begining --- NEWS | 2 + ext/standard/tests/serialize/bug64354_1.phpt | 25 ++++++ ext/standard/tests/serialize/bug64354_2.phpt | 24 ++++++ ext/standard/tests/serialize/bug64354_3.phpt | 29 +++++++ ext/standard/var.c | 22 ++++- ext/standard/var_unserializer.c | 90 +++++++++++++------- ext/standard/var_unserializer.re | 28 +++++- 7 files changed, 185 insertions(+), 35 deletions(-) create mode 100644 ext/standard/tests/serialize/bug64354_1.phpt create mode 100644 ext/standard/tests/serialize/bug64354_2.phpt create mode 100644 ext/standard/tests/serialize/bug64354_3.phpt diff --git a/NEWS b/NEWS index f8a43f6501a..1fbd5a28589 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,8 @@ PHP NEWS ?? ??? 2013, PHP 5.4.13 - Core: + . Fixed bug #64354 (Unserialize array of objects whose class can't + be autoloaded fail). (Laruence) . Fixed bug #64235 (Insteadof not work for class method in 5.4.11). (Laruence) . Fixed bug #64197 (_Offsetof() macro used but not defined on ARM/Clang). diff --git a/ext/standard/tests/serialize/bug64354_1.phpt b/ext/standard/tests/serialize/bug64354_1.phpt new file mode 100644 index 00000000000..e85749bcbef --- /dev/null +++ b/ext/standard/tests/serialize/bug64354_1.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #64354 (Unserialize array of objects whose class can't be autoloaded fail) +--FILE-- +getMessage()); +} + +try { + var_dump(unserialize('a:2:{i:0;O:1:"A":0:{}i:1;O:1:"A":0:{}}')); +} catch (Exception $e) { + var_dump($e->getMessage()); +} +?> +--EXPECTF-- +string(6) "Failed" +string(6) "Failed" diff --git a/ext/standard/tests/serialize/bug64354_2.phpt b/ext/standard/tests/serialize/bug64354_2.phpt new file mode 100644 index 00000000000..41a455b54a6 --- /dev/null +++ b/ext/standard/tests/serialize/bug64354_2.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #64354 (Unserialize array of objects whose class can't be autoloaded fail) +--FILE-- +getMessage()); +} +?> +--EXPECTF-- +string(6) "Failed" diff --git a/ext/standard/tests/serialize/bug64354_3.phpt b/ext/standard/tests/serialize/bug64354_3.phpt new file mode 100644 index 00000000000..3ce61152d64 --- /dev/null +++ b/ext/standard/tests/serialize/bug64354_3.phpt @@ -0,0 +1,29 @@ +--TEST-- +Bug #64354 (Unserialize array of objects whose class can't be autoloaded fail) +--FILE-- +getMessage()); +} +?> +--EXPECTF-- +string(6) "Failed" diff --git a/ext/standard/var.c b/ext/standard/var.c index b13edf6615c..f76a14cfa66 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -714,6 +714,10 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var ulong *var_already; HashTable *myht; + if (EG(exception)) { + return; + } + if (var_hash && php_add_var_hash(var_hash, struc, (void *) &var_already TSRMLS_CC) == FAILURE) { if (Z_ISREF_P(struc)) { smart_str_appendl(buf, "R:", 2); @@ -800,8 +804,15 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var BG(serialize_lock)++; res = call_user_function_ex(CG(function_table), &struc, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC); BG(serialize_lock)--; + + if (EG(exception)) { + if (retval_ptr) { + zval_ptr_dtor(&retval_ptr); + } + return; + } - if (res == SUCCESS && !EG(exception)) { + if (res == SUCCESS) { if (retval_ptr) { if (HASH_OF(retval_ptr)) { php_var_serialize_class(buf, struc, retval_ptr, var_hash TSRMLS_CC); @@ -921,6 +932,11 @@ PHP_FUNCTION(serialize) php_var_serialize(&buf, struc, &var_hash TSRMLS_CC); PHP_VAR_SERIALIZE_DESTROY(var_hash); + if (EG(exception)) { + smart_str_free(&buf); + RETURN_FALSE; + } + if (buf.c) { RETURN_STRINGL(buf.c, buf.len, 0); } else { @@ -951,7 +967,9 @@ PHP_FUNCTION(unserialize) if (!php_var_unserialize(&return_value, &p, p + buf_len, &var_hash TSRMLS_CC)) { PHP_VAR_UNSERIALIZE_DESTROY(var_hash); zval_dtor(return_value); - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len); + if (!EG(exception)) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len); + } RETURN_FALSE; } PHP_VAR_UNSERIALIZE_DESTROY(var_hash); diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index bd0b2f66958..d8bae08d2a5 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.13.5 on Mon Jan 21 11:34:03 2013 */ +/* Generated by re2c 0.13.5 on Sat Mar 9 22:33:09 2013 */ #line 1 "ext/standard/var_unserializer.re" /* +----------------------------------------------------------------------+ @@ -396,8 +396,13 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) BG(serialize_lock)--; } - if (retval_ptr) + if (retval_ptr) { zval_ptr_dtor(&retval_ptr); + } + + if (EG(exception)) { + return 0; + } return finish_nested_data(UNSERIALIZE_PASSTHRU); @@ -427,7 +432,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) -#line 431 "ext/standard/var_unserializer.c" +#line 436 "ext/standard/var_unserializer.c" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -487,9 +492,9 @@ yy2: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy95; yy3: -#line 759 "ext/standard/var_unserializer.re" +#line 785 "ext/standard/var_unserializer.re" { return 0; } -#line 493 "ext/standard/var_unserializer.c" +#line 498 "ext/standard/var_unserializer.c" yy4: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy89; @@ -532,13 +537,13 @@ yy13: goto yy3; yy14: ++YYCURSOR; -#line 753 "ext/standard/var_unserializer.re" +#line 779 "ext/standard/var_unserializer.re" { /* this is the case where we have less data than planned */ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data"); return 0; /* not sure if it should be 0 or 1 here? */ } -#line 542 "ext/standard/var_unserializer.c" +#line 547 "ext/standard/var_unserializer.c" yy16: yych = *++YYCURSOR; goto yy3; @@ -568,7 +573,7 @@ yy20: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 630 "ext/standard/var_unserializer.re" +#line 635 "ext/standard/var_unserializer.re" { size_t len, len2, len3, maxlen; long elements; @@ -623,10 +628,19 @@ yy20: BG(serialize_lock) = 1; if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) { BG(serialize_lock) = 0; + if (EG(exception)) { + efree(class_name); + return 0; + } ce = *pce; break; } BG(serialize_lock) = 0; + + if (EG(exception)) { + efree(class_name); + return 0; + } /* Check for unserialize callback */ if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) { @@ -644,6 +658,12 @@ yy20: BG(serialize_lock) = 1; if (call_user_function_ex(CG(function_table), NULL, user_func, &retval_ptr, 1, args, 0, NULL TSRMLS_CC) != SUCCESS) { BG(serialize_lock) = 0; + if (EG(exception)) { + efree(class_name); + zval_ptr_dtor(&user_func); + zval_ptr_dtor(&arg_func_name); + return 0; + } php_error_docref(NULL TSRMLS_CC, E_WARNING, "defined (%s) but not found", user_func->value.str.val); incomplete_class = 1; ce = PHP_IC_ENTRY; @@ -655,6 +675,12 @@ yy20: if (retval_ptr) { zval_ptr_dtor(&retval_ptr); } + if (EG(exception)) { + efree(class_name); + zval_ptr_dtor(&user_func); + zval_ptr_dtor(&arg_func_name); + return 0; + } /* The callback function may have defined the class */ if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) { @@ -691,7 +717,7 @@ yy20: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 695 "ext/standard/var_unserializer.c" +#line 721 "ext/standard/var_unserializer.c" yy25: yych = *++YYCURSOR; if (yych <= ',') { @@ -716,7 +742,7 @@ yy27: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 622 "ext/standard/var_unserializer.re" +#line 627 "ext/standard/var_unserializer.re" { INIT_PZVAL(*rval); @@ -724,7 +750,7 @@ yy27: return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -#line 728 "ext/standard/var_unserializer.c" +#line 754 "ext/standard/var_unserializer.c" yy32: yych = *++YYCURSOR; if (yych == '+') goto yy33; @@ -745,7 +771,7 @@ yy34: yych = *++YYCURSOR; if (yych != '{') goto yy18; ++YYCURSOR; -#line 602 "ext/standard/var_unserializer.re" +#line 607 "ext/standard/var_unserializer.re" { long elements = parse_iv(start + 2); /* use iv() not uiv() in order to check data range */ @@ -765,7 +791,7 @@ yy34: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 769 "ext/standard/var_unserializer.c" +#line 795 "ext/standard/var_unserializer.c" yy39: yych = *++YYCURSOR; if (yych == '+') goto yy40; @@ -786,7 +812,7 @@ yy41: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 573 "ext/standard/var_unserializer.re" +#line 578 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -815,7 +841,7 @@ yy41: ZVAL_STRINGL(*rval, str, len, 0); return 1; } -#line 819 "ext/standard/var_unserializer.c" +#line 845 "ext/standard/var_unserializer.c" yy46: yych = *++YYCURSOR; if (yych == '+') goto yy47; @@ -836,7 +862,7 @@ yy48: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 545 "ext/standard/var_unserializer.re" +#line 550 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -864,7 +890,7 @@ yy48: ZVAL_STRINGL(*rval, str, len, 1); return 1; } -#line 868 "ext/standard/var_unserializer.c" +#line 894 "ext/standard/var_unserializer.c" yy53: yych = *++YYCURSOR; if (yych <= '/') { @@ -952,7 +978,7 @@ yy61: } yy63: ++YYCURSOR; -#line 535 "ext/standard/var_unserializer.re" +#line 540 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 use_double: @@ -962,7 +988,7 @@ use_double: ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 966 "ext/standard/var_unserializer.c" +#line 992 "ext/standard/var_unserializer.c" yy65: yych = *++YYCURSOR; if (yych <= ',') { @@ -1021,7 +1047,7 @@ yy73: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 520 "ext/standard/var_unserializer.re" +#line 525 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); @@ -1036,7 +1062,7 @@ yy73: return 1; } -#line 1040 "ext/standard/var_unserializer.c" +#line 1066 "ext/standard/var_unserializer.c" yy76: yych = *++YYCURSOR; if (yych == 'N') goto yy73; @@ -1063,7 +1089,7 @@ yy79: if (yych <= '9') goto yy79; if (yych != ';') goto yy18; ++YYCURSOR; -#line 493 "ext/standard/var_unserializer.re" +#line 498 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 int digits = YYCURSOR - start - 3; @@ -1090,7 +1116,7 @@ yy79: ZVAL_LONG(*rval, parse_iv(start + 2)); return 1; } -#line 1094 "ext/standard/var_unserializer.c" +#line 1120 "ext/standard/var_unserializer.c" yy83: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1098,24 +1124,24 @@ yy83: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 486 "ext/standard/var_unserializer.re" +#line 491 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_BOOL(*rval, parse_iv(start + 2)); return 1; } -#line 1109 "ext/standard/var_unserializer.c" +#line 1135 "ext/standard/var_unserializer.c" yy87: ++YYCURSOR; -#line 479 "ext/standard/var_unserializer.re" +#line 484 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_NULL(*rval); return 1; } -#line 1119 "ext/standard/var_unserializer.c" +#line 1145 "ext/standard/var_unserializer.c" yy89: yych = *++YYCURSOR; if (yych <= ',') { @@ -1138,7 +1164,7 @@ yy91: if (yych <= '9') goto yy91; if (yych != ';') goto yy18; ++YYCURSOR; -#line 456 "ext/standard/var_unserializer.re" +#line 461 "ext/standard/var_unserializer.re" { long id; @@ -1161,7 +1187,7 @@ yy91: return 1; } -#line 1165 "ext/standard/var_unserializer.c" +#line 1191 "ext/standard/var_unserializer.c" yy95: yych = *++YYCURSOR; if (yych <= ',') { @@ -1184,7 +1210,7 @@ yy97: if (yych <= '9') goto yy97; if (yych != ';') goto yy18; ++YYCURSOR; -#line 435 "ext/standard/var_unserializer.re" +#line 440 "ext/standard/var_unserializer.re" { long id; @@ -1205,9 +1231,9 @@ yy97: return 1; } -#line 1209 "ext/standard/var_unserializer.c" +#line 1235 "ext/standard/var_unserializer.c" } -#line 761 "ext/standard/var_unserializer.re" +#line 787 "ext/standard/var_unserializer.re" return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 204995783fe..4d99cbfd789 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -400,8 +400,13 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) BG(serialize_lock)--; } - if (retval_ptr) + if (retval_ptr) { zval_ptr_dtor(&retval_ptr); + } + + if (EG(exception)) { + return 0; + } return finish_nested_data(UNSERIALIZE_PASSTHRU); @@ -681,10 +686,19 @@ object ":" uiv ":" ["] { BG(serialize_lock) = 1; if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) { BG(serialize_lock) = 0; + if (EG(exception)) { + efree(class_name); + return 0; + } ce = *pce; break; } BG(serialize_lock) = 0; + + if (EG(exception)) { + efree(class_name); + return 0; + } /* Check for unserialize callback */ if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) { @@ -702,6 +716,12 @@ object ":" uiv ":" ["] { BG(serialize_lock) = 1; if (call_user_function_ex(CG(function_table), NULL, user_func, &retval_ptr, 1, args, 0, NULL TSRMLS_CC) != SUCCESS) { BG(serialize_lock) = 0; + if (EG(exception)) { + efree(class_name); + zval_ptr_dtor(&user_func); + zval_ptr_dtor(&arg_func_name); + return 0; + } php_error_docref(NULL TSRMLS_CC, E_WARNING, "defined (%s) but not found", user_func->value.str.val); incomplete_class = 1; ce = PHP_IC_ENTRY; @@ -713,6 +733,12 @@ object ":" uiv ":" ["] { if (retval_ptr) { zval_ptr_dtor(&retval_ptr); } + if (EG(exception)) { + efree(class_name); + zval_ptr_dtor(&user_func); + zval_ptr_dtor(&arg_func_name); + return 0; + } /* The callback function may have defined the class */ if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) { From 7197f0ffccea7f195bc28571e30c389eadda874b Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 9 Mar 2013 23:08:14 +0800 Subject: [PATCH 113/276] Fixed confused exception message while user threw exception --- Zend/tests/bug64354.phpt | 24 ++++++++++++++++++++++++ Zend/zend_interfaces.c | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/bug64354.phpt diff --git a/Zend/tests/bug64354.phpt b/Zend/tests/bug64354.phpt new file mode 100644 index 00000000000..03a4b80b4bc --- /dev/null +++ b/Zend/tests/bug64354.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #64354 (Unserialize array of objects whose class can't be autoloaded fail) +--FILE-- +getMessage()); +} +?> +--EXPECTF-- +string(9) "serialize" diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index 384b66da4b5..e2e81ed326a 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -452,7 +452,7 @@ ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, zend_uint zval_ptr_dtor(&retval); } - if (result == FAILURE) { + if (result == FAILURE && !EG(exception)) { zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "%s::serialize() must return a string or NULL", ce->name); } return result; From 9d816ba1d3df25969c2a9f6e659201d2caaf8af3 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 9 Mar 2013 23:11:48 +0800 Subject: [PATCH 114/276] Update NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index a1c0aea21f7..f1df09d6c20 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 20??, PHP 5.5.0 Beta 1 +- Core: + . Fixed bug #64354 (Unserialize array of objects whose class can't + be autoloaded fail). (Laruence) + 07 Mar 2013, PHP 5.5.0 Alpha 6 From a59b211b2ddc84a2cca572409c4a66b2ed487e0e Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 9 Mar 2013 20:15:00 +0100 Subject: [PATCH 115/276] Fix get_property_ptr_ptr declaration in simplexml A new parameter was added to the API and simplexml wasn't adjusted, thus causing crashes. --- ext/simplexml/simplexml.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 692516840b2..baae3842c26 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -694,7 +694,7 @@ static void sxe_dimension_write(zval *object, zval *offset, zval *value TSRMLS_D } /* }}} */ -static zval** sxe_property_get_adr(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */ +static zval** sxe_property_get_adr(zval *object, zval *member, int fetch_type, const zend_literal *key TSRMLS_DC) /* {{{ */ { php_sxe_object *sxe; xmlNodePtr node; From 9490118fdb66eb6148dc74b24399eb72dc55aec1 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 9 Mar 2013 20:21:33 +0100 Subject: [PATCH 116/276] Fix tests after laruence unserialize change --- Zend/tests/generators/errors/serialize_unserialize_error.phpt | 2 -- 1 file changed, 2 deletions(-) diff --git a/Zend/tests/generators/errors/serialize_unserialize_error.phpt b/Zend/tests/generators/errors/serialize_unserialize_error.phpt index a8470b0a63a..aa2d4693f78 100644 --- a/Zend/tests/generators/errors/serialize_unserialize_error.phpt +++ b/Zend/tests/generators/errors/serialize_unserialize_error.phpt @@ -38,8 +38,6 @@ Stack trace: #1 %s(%d): unserialize('O:9:"Generator"...') #2 {main} - -Notice: unserialize(): Error at offset 19 of 20 bytes in %s on line %d exception 'Exception' with message 'Unserialization of 'Generator' is not allowed' in %s:%d Stack trace: #0 %s(%d): unserialize('C:9:"Generator"...') From c7ad92fac72a11efcfa9b70cb19d9feae87936d6 Mon Sep 17 00:00:00 2001 From: Keyur Govande Date: Mon, 11 Mar 2013 00:20:57 +0000 Subject: [PATCH 117/276] Adding in NEWS/UPGRADING about process title change support. --- NEWS | 3 +++ UPGRADING | 2 ++ 2 files changed, 5 insertions(+) diff --git a/NEWS b/NEWS index f1df09d6c20..4ef3a55bc1a 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,9 @@ PHP NEWS - Core: . Fixed bug #64354 (Unserialize array of objects whose class can't be autoloaded fail). (Laruence) + . Added support for changing the process's title in CLI/CLI-Server SAPIs. + The implementation is more robust that the proctitle PECL module. More + details here: https://wiki.php.net/rfc/cli_process_title. (Keyur) 07 Mar 2013, PHP 5.5.0 Alpha 6 diff --git a/UPGRADING b/UPGRADING index ee1ff67c856..76d6f4fb839 100755 --- a/UPGRADING +++ b/UPGRADING @@ -79,6 +79,8 @@ PHP 5.5 UPGRADE NOTES (https://wiki.php.net/rfc/generators) - ClassName::class syntax returning full class name for a class as a string constant. (https://wiki.php.net/rfc/class_name_scalars) +- Support for changing the process's title in CLI/CLI-Server SAPIs. (Keyur) + (https://wiki.php.net/rfc/cli_process_title) ======================================== 2. Changes in SAPI modules From 0444708c5cd665179a936b86369f84b9dad8effe Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 11 Mar 2013 15:15:22 +0800 Subject: [PATCH 118/276] Disable zend_always_inline in debug build it will be much more easier for debuging --- Zend/zend.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Zend/zend.h b/Zend/zend.h index b6c1a5b8a6f..e1d1fad4276 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -350,6 +350,10 @@ struct _zval_struct { #define Z_UNSET_ISREF(z) Z_UNSET_ISREF_P(&(z)) #define Z_SET_ISREF_TO(z, isref) Z_SET_ISREF_TO_P(&(z), isref) +#if ZEND_DEBUG +#define zend_always_inline inline +#define zend_never_inline +#else #if defined(__GNUC__) #if __GNUC__ >= 3 #define zend_always_inline inline __attribute__((always_inline)) @@ -358,7 +362,6 @@ struct _zval_struct { #define zend_always_inline inline #define zend_never_inline #endif - #elif defined(_MSC_VER) #define zend_always_inline __forceinline #define zend_never_inline @@ -366,6 +369,7 @@ struct _zval_struct { #define zend_always_inline inline #define zend_never_inline #endif +#endif /* ZEND_DEBUG */ #if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX) # define EXPECTED(condition) __builtin_expect(condition, 1) From 8aaa09636a3efee7d6e92103dad1ae2c1d137e72 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Mon, 11 Mar 2013 16:04:37 +0100 Subject: [PATCH 119/276] Fixed bug #64370 (microtime(true) less than $_SERVER['REQUEST_TIME_FLOAT']) --- NEWS | 2 + ext/standard/tests/bug64370_var1.phpt | 18 ++++ ext/standard/tests/bug64370_var2.phpt | 23 +++++ win32/globals.c | 2 - win32/php_win32_globals.h | 4 - win32/time.c | 129 ++++++++------------------ 6 files changed, 83 insertions(+), 95 deletions(-) create mode 100644 ext/standard/tests/bug64370_var1.phpt create mode 100644 ext/standard/tests/bug64370_var2.phpt diff --git a/NEWS b/NEWS index 4ef3a55bc1a..291ec52e405 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,8 @@ PHP NEWS . Added support for changing the process's title in CLI/CLI-Server SAPIs. The implementation is more robust that the proctitle PECL module. More details here: https://wiki.php.net/rfc/cli_process_title. (Keyur) + . Fixed bug #64370 (microtime(true) less than $_SERVER['REQUEST_TIME_FLOAT']). + (Anatol) 07 Mar 2013, PHP 5.5.0 Alpha 6 diff --git a/ext/standard/tests/bug64370_var1.phpt b/ext/standard/tests/bug64370_var1.phpt new file mode 100644 index 00000000000..3f25f534bab --- /dev/null +++ b/ext/standard/tests/bug64370_var1.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test bug #64370 microtime(true) less than $_SERVER['REQUEST_TIME_FLOAT'] +--FILE-- + +===DONE=== +--EXPECTF-- +$_SERVER['REQUEST_TIME']: %d +$_SERVER['REQUEST_TIME_FLOAT']: %f +time(): %d +microtime(true): %f +created in %f ms +===DONE=== diff --git a/ext/standard/tests/bug64370_var2.phpt b/ext/standard/tests/bug64370_var2.phpt new file mode 100644 index 00000000000..d0d3590ea7b --- /dev/null +++ b/ext/standard/tests/bug64370_var2.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test bug #64370 sequential microtime(true) calls +--FILE-- + $i++) { + $m0 = microtime(true); + $m1 = microtime(true); + $d = $m1 - $m0; + + /*echo "$d\n";*/ + + if ($d < 0) { + die("failed in {$i}th iteration"); + } +} +echo "ok\n"; +?> +===DONE=== +--EXPECT-- +ok +===DONE=== diff --git a/win32/globals.c b/win32/globals.c index 1bbb3b4481d..b381cc12371 100644 --- a/win32/globals.c +++ b/win32/globals.c @@ -65,8 +65,6 @@ PHP_RSHUTDOWN_FUNCTION(win32_core_globals) ; closelog(); - wg->starttime.tv_sec = 0; - wg->lasttime = 0; return SUCCESS; } diff --git a/win32/php_win32_globals.h b/win32/php_win32_globals.h index 1686e5df63e..b2b07f68e18 100644 --- a/win32/php_win32_globals.h +++ b/win32/php_win32_globals.h @@ -38,10 +38,6 @@ struct _php_win32_core_globals { char *log_header; HANDLE log_source; - /* time */ - struct timeval starttime; - __int64 lasttime, freq; - HKEY registry_key; HANDLE registry_event; HashTable *registry_directories; diff --git a/win32/time.c b/win32/time.c index 391a8a81e99..77e4504cd12 100644 --- a/win32/time.c +++ b/win32/time.c @@ -12,13 +12,6 @@ /* $Id$ */ - /** - * - * 04-Feb-2001 - * - Added patch by "Vanhanen, Reijo" - * Improves accuracy of msec - */ - /* Include stuff ************************************************************ */ #include @@ -32,98 +25,56 @@ #include #include "php_win32_globals.h" -int getfilesystemtime(struct timeval *time_Info) +typedef VOID (WINAPI *MyGetSystemTimeAsFileTime)(LPFILETIME lpSystemTimeAsFileTime); + +static MyGetSystemTimeAsFileTime get_time_func(void) { - FILETIME ft; - __int64 ff; - ULARGE_INTEGER convFromft; + MyGetSystemTimeAsFileTime timefunc = NULL; + HMODULE hMod = LoadLibrary("kernel32.dll"); - GetSystemTimeAsFileTime(&ft); /* 100 ns blocks since 01-Jan-1641 */ - /* resolution seems to be 0.01 sec */ - /* - * Do not cast a pointer to a FILETIME structure to either a - * ULARGE_INTEGER* or __int64* value because it can cause alignment faults on 64-bit Windows. - * via http://technet.microsoft.com/en-us/library/ms724284(v=vs.85).aspx - */ - convFromft.HighPart = ft.dwHighDateTime; - convFromft.LowPart = ft.dwLowDateTime; - ff = convFromft.QuadPart; + if (hMod) { + /* Max possible resolution <1us, win8/server2012 */ + timefunc = (MyGetSystemTimeAsFileTime)GetProcAddress(hMod, "GetSystemTimePreciseAsFileTime"); - time_Info->tv_sec = (int)(ff/(__int64)10000000-(__int64)11644473600); - time_Info->tv_usec = (int)(ff % 10000000)/10; - return 0; + if(!timefunc) { + /* 100ns blocks since 01-Jan-1641 */ + timefunc = (MyGetSystemTimeAsFileTime)GetProcAddress(hMod, "GetSystemTimeAsFileTime"); + } + } + + return timefunc; } - +int getfilesystemtime(struct timeval *tv) +{ + FILETIME ft; + unsigned __int64 ff = 0; + MyGetSystemTimeAsFileTime timefunc; + + timefunc = get_time_func(); + if (timefunc) { + timefunc(&ft); + } else { + GetSystemTimeAsFileTime(&ft); + } + + ff |= ft.dwHighDateTime; + ff <<= 32; + ff |= ft.dwLowDateTime; + ff /= 10; /* convert to microseconds */ + ff -= 11644473600000000Ui64; /* convert to unix epoch */ + + tv->tv_sec = (long)(ff / 1000000UL); + tv->tv_usec = (long)(ff % 1000000UL); + + return 0; +} PHPAPI int gettimeofday(struct timeval *time_Info, struct timezone *timezone_Info) { - __int64 timer; - LARGE_INTEGER li; - BOOL b; - double dt; - TSRMLS_FETCH(); - /* Get the time, if they want it */ if (time_Info != NULL) { - if (PW32G(starttime).tv_sec == 0) { - b = QueryPerformanceFrequency(&li); - if (!b) { - PW32G(starttime).tv_sec = -1; - } - else { - PW32G(freq) = li.QuadPart; - b = QueryPerformanceCounter(&li); - if (!b) { - PW32G(starttime).tv_sec = -1; - } - else { - getfilesystemtime(&PW32G(starttime)); - timer = li.QuadPart; - dt = (double)timer/PW32G(freq); - PW32G(starttime).tv_usec -= (int)((dt-(int)dt)*1000000); - if (PW32G(starttime).tv_usec < 0) { - PW32G(starttime).tv_usec += 1000000; - --PW32G(starttime).tv_sec; - } - PW32G(starttime).tv_sec -= (int)dt; - } - } - } - if (PW32G(starttime).tv_sec > 0) { - b = QueryPerformanceCounter(&li); - if (!b) { - PW32G(starttime).tv_sec = -1; - } - else { - timer = li.QuadPart; - if (timer < PW32G(lasttime)) { - getfilesystemtime(time_Info); - dt = (double)timer/PW32G(freq); - PW32G(starttime) = *time_Info; - PW32G(starttime).tv_usec -= (int)((dt-(int)dt)*1000000); - if (PW32G(starttime).tv_usec < 0) { - PW32G(starttime).tv_usec += 1000000; - --PW32G(starttime).tv_sec; - } - PW32G(starttime).tv_sec -= (int)dt; - } - else { - PW32G(lasttime) = timer; - dt = (double)timer/PW32G(freq); - time_Info->tv_sec = PW32G(starttime).tv_sec + (int)dt; - time_Info->tv_usec = PW32G(starttime).tv_usec + (int)((dt-(int)dt)*1000000); - if (time_Info->tv_usec >= 1000000) { - time_Info->tv_usec -= 1000000; - ++time_Info->tv_sec; - } - } - } - } - if (PW32G(starttime).tv_sec < 0) { - getfilesystemtime(time_Info); - } - + getfilesystemtime(time_Info); } /* Get the timezone, if they want it */ if (timezone_Info != NULL) { From 278c4097c61ff258525bb11c680ffc8dce22fcaa Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Mon, 11 Mar 2013 16:14:39 +0100 Subject: [PATCH 120/276] fixed the test --- ext/standard/tests/bug64370_var1.phpt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ext/standard/tests/bug64370_var1.phpt b/ext/standard/tests/bug64370_var1.phpt index 3f25f534bab..aca46a594d1 100644 --- a/ext/standard/tests/bug64370_var1.phpt +++ b/ext/standard/tests/bug64370_var1.phpt @@ -6,7 +6,9 @@ echo "\$_SERVER['REQUEST_TIME']: {$_SERVER['REQUEST_TIME']}\n"; echo "\$_SERVER['REQUEST_TIME_FLOAT']: {$_SERVER['REQUEST_TIME_FLOAT']}\n"; echo "time(): " . time() . "\n"; echo "microtime(true): " . microtime(true) . "\n"; -echo "created in " . ((microtime(true)-$_SERVER['REQUEST_TIME_FLOAT'])*1000) . " ms\n"; +$d = (microtime(true)-$_SERVER['REQUEST_TIME_FLOAT'])*1000; +echo "created in $d ms\n"; +echo ((bool)($d >= 0)) . "\n"; ?> ===DONE=== --EXPECTF-- @@ -15,4 +17,5 @@ $_SERVER['REQUEST_TIME_FLOAT']: %f time(): %d microtime(true): %f created in %f ms +1 ===DONE=== From 4c5517623c1c2c53288951525fedd57c33ebe826 Mon Sep 17 00:00:00 2001 From: Pascal Borreli Date: Mon, 11 Mar 2013 18:49:05 +0000 Subject: [PATCH 121/276] Fixed typos --- Optimizer/block_pass.c | 16 ++++++++-------- Optimizer/optimize_temp_vars_5.c | 2 +- Optimizer/pass1_5.c | 2 +- Optimizer/pass2.c | 2 +- Optimizer/zend_optimizer.h | 2 +- ZendAccelerator.c | 22 +++++++++++----------- ZendAccelerator.h | 14 +++++++------- zend_accelerator_hash.h | 2 +- zend_accelerator_module.c | 10 +++++----- zend_accelerator_module.h | 2 +- zend_accelerator_util_funcs.c | 2 +- zend_persist.c | 2 +- 12 files changed, 39 insertions(+), 39 deletions(-) diff --git a/Optimizer/block_pass.c b/Optimizer/block_pass.c index a1fc760e73f..3d4bb0c1d27 100644 --- a/Optimizer/block_pass.c +++ b/Optimizer/block_pass.c @@ -1,6 +1,6 @@ #define DEBUG_BLOCKPASS 0 -/* Checks if a constant (like "true") may be relaced by its value */ +/* Checks if a constant (like "true") may be replaced by its value */ static int zend_get_persistent_constant(char *name, uint name_len, zval *result, int copy TSRMLS_DC ELS_DC) { zend_constant *c; @@ -167,7 +167,7 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg) blocks[op_array->try_catch_array[i].try_op].protected = 1; } } - /* Currentrly, we don't optimize op_arrays with BRK/CONT/GOTO opcodes, + /* Currently, we don't optimize op_arrays with BRK/CONT/GOTO opcodes, * but, we have to keep brk_cont_array to avoid memory leaks during * exception handling */ if (op_array->last_brk_cont) { @@ -370,7 +370,7 @@ static inline void del_source(zend_code_block *from, zend_code_block *to) /* move block to new location */ memmove(new_to, to->start_opline, sizeof(zend_op)*to->len); } - /* join blocks' lengthes */ + /* join blocks' lengths */ from_block->len += to->len; /* move 'to'`s references to 'from' */ to->start_opline = NULL; @@ -462,7 +462,7 @@ static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int zend_code_block *start = find_start? NULL : blocks; zend_code_block *b; - /* Mark all blocks as unaccessable and destroy back references */ + /* Mark all blocks as unaccessible and destroy back references */ b = blocks; while (b != NULL) { zend_block_source *cs; @@ -480,10 +480,10 @@ static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int b = b->next; } - /* Walk thorough all pathes */ + /* Walk thorough all paths */ zend_access_path(start); - /* Add brk/cont pathes */ + /* Add brk/cont paths */ if (op_array->last_brk_cont) { int i; for (i=0; i< op_array->last_brk_cont; i++) { @@ -493,7 +493,7 @@ static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int } } - /* Add exception pathes */ + /* Add exception paths */ if (op_array->last_try_catch) { int i; for (i=0; i< op_array->last_try_catch; i++) { @@ -998,7 +998,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, VAR_SOURCE(opline->op1) && VAR_SOURCE(opline->op1)->opcode == ZEND_INIT_STRING) { /* convert T = INIT_STRING(), T = ADD_STRING(T, X) to T = QM_ASSIGN(X) */ - /* CHECKME: Remove ZEND_ADD_VAR optimizsation, since some conversions - + /* CHECKME: Remove ZEND_ADD_VAR optimization, since some conversions - namely, BOOL(false)->string - don't allocate memory but use empty_string and ADD_CHAR fails */ zend_op *src = VAR_SOURCE(opline->op1); diff --git a/Optimizer/optimize_temp_vars_5.c b/Optimizer/optimize_temp_vars_5.c index 976a7b21acc..dc630733faa 100644 --- a/Optimizer/optimize_temp_vars_5.c +++ b/Optimizer/optimize_temp_vars_5.c @@ -164,7 +164,7 @@ static void optimize_temporary_variables(zend_op_array *op_array) opline->extended_value = NUM_VAR(map_T[currT]); } - /* Allocate OP_DATA->op2 after "opernds", but before "result" */ + /* Allocate OP_DATA->op2 after "operands", but before "result" */ if (opline->opcode == ZEND_ASSIGN_DIM && (opline + 1)->opcode == ZEND_OP_DATA && ZEND_OP2_TYPE(opline + 1) & (IS_VAR | IS_TMP_VAR)) { diff --git a/Optimizer/pass1_5.c b/Optimizer/pass1_5.c index 7a69689fa73..8938e148ce5 100644 --- a/Optimizer/pass1_5.c +++ b/Optimizer/pass1_5.c @@ -308,7 +308,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { next_op++; } if (!((ZEND_OPTIMIZER_PASS_5|ZEND_OPTIMIZER_PASS_10) & OPTIMIZATION_LEVEL)) { - /* NOP removel is disabled => insert JMP over NOPs */ + /* NOP removal is disabled => insert JMP over NOPs */ if (last_op-opline >= 3) { /* If we have more than 2 NOPS then JMP over them */ (opline + 1)->opcode = ZEND_JMP; ZEND_OP1(opline + 1).opline_num = last_op - op_array->opcodes; /* that's OK even for ZE2, since opline_num's are resolved in pass 2 later */ diff --git a/Optimizer/pass2.c b/Optimizer/pass2.c index da56dcfa52d..30708a0935b 100644 --- a/Optimizer/pass2.c +++ b/Optimizer/pass2.c @@ -81,7 +81,7 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) { case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: /* convert Ti = JMPZ_EX(Ti, L) to JMPZ(Ti, L) */ - if (0 && /* FIXME: temorary disable unsafe pattern */ + if (0 && /* FIXME: temporary disable unsafe pattern */ ZEND_OP1_TYPE(opline) == IS_TMP_VAR && ZEND_RESULT_TYPE(opline) == IS_TMP_VAR && ZEND_OP1(opline).var == ZEND_RESULT(opline).var) { diff --git a/Optimizer/zend_optimizer.h b/Optimizer/zend_optimizer.h index 0c069168740..ff848535d30 100644 --- a/Optimizer/zend_optimizer.h +++ b/Optimizer/zend_optimizer.h @@ -26,7 +26,7 @@ #include "zend_compile.h" #define ZEND_OPTIMIZER_PASS_1 (1<<0) /* CSE, STRING construction */ -#define ZEND_OPTIMIZER_PASS_2 (1<<1) /* Constant conversion and jums */ +#define ZEND_OPTIMIZER_PASS_2 (1<<1) /* Constant conversion and jumps */ #define ZEND_OPTIMIZER_PASS_3 (1<<2) /* ++, +=, series of jumps */ #define ZEND_OPTIMIZER_PASS_4 (1<<3) #define ZEND_OPTIMIZER_PASS_5 (1<<4) /* CFG based optimization */ diff --git a/ZendAccelerator.c b/ZendAccelerator.c index ed942265604..e6029cf4543 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -176,7 +176,7 @@ static inline char* accel_getcwd(int *cwd_len TSRMLS_DC) } } -/* O+ traks changes of "include_path" directive. It stores all the requested +/* O+ tracks changes of "include_path" directive. It stores all the requested * values in ZCG(include_paths) shared hash table, current value in * ZCG(include_path)/ZCG(include_path_len) and one letter "path key" in * ZCG(include_path_key). @@ -1315,7 +1315,7 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han efree(op_array); /* we have valid persistent_script, so it's safe to free op_array */ /* Fill in the ping_auto_globals_mask for the new script. If jit for auto globals is enabled we - will have to ping the used auto global varaibles before execution */ + will have to ping the used auto global variables before execution */ #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO if (PG(auto_globals_jit)) { #else @@ -1391,7 +1391,7 @@ static zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int if (!ZCG(key_len)) { return accelerator_orig_compile_file(file_handle, type TSRMLS_CC); } - /* persistent script was already found by overrifen open() or + /* persistent script was already found by overridden open() or * resolve_path() callbacks */ persistent_script = ZCG(cache_persistent_script); key = ZCG(key); @@ -1688,7 +1688,7 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl handle->free_filename = 0; handle->opened_path = NULL; - /* Check if requestd file already cached (by full name) */ + /* Check if requested file already cached (by full name) */ if (IS_ABSOLUTE_PATH(filename, filename_len) && (persistent_script = zend_accel_hash_find(&ZCSG(hash), (char*)filename, filename_len + 1)) != NULL && !persistent_script->corrupted) { @@ -1702,7 +1702,7 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl return SUCCESS; } - /* Check if requestd file already cached (by key) */ + /* Check if requested file already cached (by key) */ key = accel_make_persistent_key_ex(handle, filename_len, &key_length TSRMLS_CC); if (!ZCG(accel_directives).revalidate_path && key && @@ -1719,7 +1719,7 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl /* find the full real path */ resolved_path = accel_php_resolve_path(filename, filename_len, ZCG(include_path) TSRMLS_CC); - /* Check if requestd file already cached (by real name) */ + /* Check if requested file already cached (by real name) */ if (resolved_path && (bucket = zend_accel_hash_find_entry(&ZCSG(hash), resolved_path, strlen(resolved_path) + 1)) != NULL) { @@ -1848,7 +1848,7 @@ static char* persistent_zend_resolve_path(const char *filename, int filename_len zend_accel_hash_entry *bucket; zend_persistent_script *persistent_script; - /* Check if requestd file already cached (by full name) */ + /* Check if requested file already cached (by full name) */ if ((IS_ABSOLUTE_PATH(filename, filename_len) || is_stream_path(filename)) && (bucket = zend_accel_hash_find_entry(&ZCSG(hash), (char*)filename, filename_len + 1)) != NULL) { @@ -1862,7 +1862,7 @@ static char* persistent_zend_resolve_path(const char *filename, int filename_len } } - /* Check if requestd file already cached (by key) */ + /* Check if requested file already cached (by key) */ handle.filename = (char*)filename; handle.free_filename = 0; handle.opened_path = NULL; @@ -1881,7 +1881,7 @@ static char* persistent_zend_resolve_path(const char *filename, int filename_len /* find the full real path */ resolved_path = accelerator_orig_zend_resolve_path(filename, filename_len TSRMLS_CC); - /* Check if requestd file already cached (by real path) */ + /* Check if requested file already cached (by real path) */ if (resolved_path && (bucket = zend_accel_hash_find_entry(&ZCSG(hash), resolved_path, strlen(resolved_path) + 1)) != NULL) { persistent_script = (zend_persistent_script *)bucket->data; @@ -2354,7 +2354,7 @@ static int accel_startup(zend_extension *extension) return FAILURE; } - /* no supported SAPI found - disable acceleration and stop initalization */ + /* no supported SAPI found - disable acceleration and stop initialization */ if (accel_find_sapi(TSRMLS_C) == FAILURE) { accel_startup_ok = 0; if (!ZCG(accel_directives).enable_cli && @@ -2557,7 +2557,7 @@ void zend_accel_schedule_restart(TSRMLS_D) /* ensures it is OK to read SHM if it's not OK (restart in progress) returns FAILURE if OK returns SUCCESS - MUST call accelerator_shm_read_unlock after done lock operationss + MUST call accelerator_shm_read_unlock after done lock operations */ int accelerator_shm_read_lock(TSRMLS_D) { diff --git a/ZendAccelerator.h b/ZendAccelerator.h index 310605b878b..87736ec839c 100644 --- a/ZendAccelerator.h +++ b/ZendAccelerator.h @@ -33,7 +33,7 @@ /* 4 - works with the new Optimizer, that supports the file format with licenses */ /* 5 - API 4 didn't really work with the license-enabled file format. v5 does. */ /* 6 - Monitor was removed from ZendPlatform.so, to a module of its own */ -/* 7 - Optimizer was embeded into Accelerator */ +/* 7 - Optimizer was embedded into Accelerator */ /* 8 - Standalone Open Source OptimizerPlus */ #define ACCELERATOR_API_NO 8 @@ -226,20 +226,20 @@ typedef struct _zend_accel_directives { } zend_accel_directives; typedef struct _zend_accel_globals { - /* copy of CG(function_table) used for compilation scripts into cashe */ - /* imitially it contains only internal functions */ + /* copy of CG(function_table) used for compilation scripts into cache */ + /* initially it contains only internal functions */ HashTable function_table; int internal_functions_count; - int counted; /* the process uses shatred memory */ + int counted; /* the process uses shared memory */ zend_bool enabled; zend_bool locked; /* thread obtained exclusive lock */ HashTable bind_hash; /* prototype and zval lookup table */ zend_accel_directives accel_directives; char *cwd; /* current working directory or NULL */ - int cwd_len; /* "cwd" string lenght */ + int cwd_len; /* "cwd" string length */ char *include_path_key; /* one letter key of current "include_path" */ - char *include_path; /* current settion of "include_path" directive */ - int include_path_len; /* "include_path" string lenght */ + char *include_path; /* current section of "include_path" directive */ + int include_path_len; /* "include_path" string length */ int include_path_check; time_t request_time; /* preallocated shared-memory block to save current script */ diff --git a/zend_accelerator_hash.h b/zend_accelerator_hash.h index 4673a5e425a..a1a836c03c3 100644 --- a/zend_accelerator_hash.h +++ b/zend_accelerator_hash.h @@ -36,7 +36,7 @@ however, entries are still taken from the same 'hash_entries' array. 'key' and 'data' passed to zend_accel_hash_update() must be already allocated in shared memory. Few keys may be resolved to the same data. - using 'indirect' emtries, that point to other entries ('data' is actually + using 'indirect' entries, that point to other entries ('data' is actually a pointer to another zend_accel_hash_entry). zend_accel_hash_update() requires exclusive lock, however, zend_accel_hash_find() does not. diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index b3aac5f0027..701820f228e 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -75,7 +75,7 @@ static ZEND_INI_MH(OnUpdateMemoryConsumption) memsize = 8; zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.memory_consumption is set below the required 8MB.\n"); - zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the minimal 8MB cofiguration.\n"); + zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the minimal 8MB configuration.\n"); if (zend_hash_find(EG(ini_directives), "zend_optimizerplus.memory_consumption", @@ -116,13 +116,13 @@ static ZEND_INI_MH(OnUpdateMaxAcceleratedFiles) size = MIN_ACCEL_FILES; new_new_value = TOKENTOSTR(MIN_ACCEL_FILES); zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.max_accelerated_files is set below the required minimum (%d).\n", MIN_ACCEL_FILES); - zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the minimal cofiguration.\n"); + zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the minimal configuration.\n"); } if (size > MAX_ACCEL_FILES) { size = MAX_ACCEL_FILES; new_new_value = TOKENTOSTR(MAX_ACCEL_FILES); zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.max_accelerated_files is set above the limit (%d).\n", MAX_ACCEL_FILES); - zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the maximal cofiguration.\n"); + zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the maximal configuration.\n"); } if (zend_hash_find(EG(ini_directives), "zend_optimizerplus.max_accelerated_files", @@ -158,7 +158,7 @@ static ZEND_INI_MH(OnUpdateMaxWastedPercentage) zend_ini_entry *ini_entry; percentage = 5; - zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.max_wasted_percentage must be ser netweeb 1 and 50.\n"); + zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.max_wasted_percentage must be set between 1 and 50.\n"); zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use 5%.\n"); if (zend_hash_find(EG(ini_directives), "zend_optimizerplus.max_wasted_percentage", @@ -506,7 +506,7 @@ static ZEND_FUNCTION(accelerator_get_status) add_assoc_double(statistics, "accelerator_hit_rate", reqs?(((double) ZCSG(hits))/reqs)*100.0:0); add_assoc_zval(return_value, "accelerator_statistics", statistics); - /* acceleratred scripts */ + /* accelerated scripts */ scripts = accelerator_get_scripts(TSRMLS_C); if (scripts) { add_assoc_zval(return_value, "scripts", scripts); diff --git a/zend_accelerator_module.h b/zend_accelerator_module.h index 112ab0fc571..5ac5716ca7c 100644 --- a/zend_accelerator_module.h +++ b/zend_accelerator_module.h @@ -19,7 +19,7 @@ +----------------------------------------------------------------------+ */ -#ifndef ZEND_ACCELERAROR_MODULE_H +#ifndef ZEND_ACCELERATOR_MODULE_H #define ZEND_ACCELERATOR_MODULE_H int start_accel_module(void); diff --git a/zend_accelerator_util_funcs.c b/zend_accelerator_util_funcs.c index 7c3c9ae86cc..06299d8a0bf 100644 --- a/zend_accelerator_util_funcs.c +++ b/zend_accelerator_util_funcs.c @@ -77,7 +77,7 @@ zend_persistent_script* create_persistent_script(void) memset(persistent_script, 0, sizeof(zend_persistent_script)); zend_hash_init(&persistent_script->function_table, 100, NULL, (dtor_func_t) zend_accel_destroy_zend_function, 0); - /* class_table is usualy destroyed by free_persistent_script() that + /* class_table is usually destroyed by free_persistent_script() that * overrides destructor. ZEND_CLASS_DTOR may be used by standard * PHP compiler */ diff --git a/zend_persist.c b/zend_persist.c index 9efd028e99b..6f9678e2850 100644 --- a/zend_persist.c +++ b/zend_persist.c @@ -310,7 +310,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc #else /* if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO */ if (ZEND_DONE_PASS_TWO(op_array)) { - /* fix jmps to point to new array */ + /* fix jumps to point to new array */ switch (opline->opcode) { case ZEND_JMP: case ZEND_GOTO: From 50ad2af503e9021d70bd3de92998806c018dea2b Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Mon, 11 Mar 2013 21:36:36 +0000 Subject: [PATCH 122/276] - Updated to version 2013.2 (2013b) --- ext/date/lib/timezonedb.h | 1211 +++++++++++++++++++------------------ 1 file changed, 616 insertions(+), 595 deletions(-) diff --git a/ext/date/lib/timezonedb.h b/ext/date/lib/timezonedb.h index ba34c75b206..7bf9a9d220b 100644 --- a/ext/date/lib/timezonedb.h +++ b/ext/date/lib/timezonedb.h @@ -14,573 +14,573 @@ const timelib_tzdb_index_entry timezonedb_idx_builtin[579] = { { "Africa/Bujumbura" , 0x000571 }, { "Africa/Cairo" , 0x0005B5 }, { "Africa/Casablanca" , 0x000878 }, - { "Africa/Ceuta" , 0x000A76 }, - { "Africa/Conakry" , 0x000D7D }, - { "Africa/Dakar" , 0x000DE8 }, - { "Africa/Dar_es_Salaam" , 0x000E4E }, - { "Africa/Djibouti" , 0x000EBB }, - { "Africa/Douala" , 0x000F10 }, - { "Africa/El_Aaiun" , 0x000F65 }, - { "Africa/Freetown" , 0x000FCB }, - { "Africa/Gaborone" , 0x0010DA }, - { "Africa/Harare" , 0x001147 }, - { "Africa/Johannesburg" , 0x00119C }, - { "Africa/Juba" , 0x00120A }, - { "Africa/Kampala" , 0x00131D }, - { "Africa/Khartoum" , 0x00139C }, - { "Africa/Kigali" , 0x0014AF }, - { "Africa/Kinshasa" , 0x001504 }, - { "Africa/Lagos" , 0x00155F }, - { "Africa/Libreville" , 0x0015B4 }, - { "Africa/Lome" , 0x001609 }, - { "Africa/Luanda" , 0x00164D }, - { "Africa/Lubumbashi" , 0x0016A2 }, - { "Africa/Lusaka" , 0x0016FD }, - { "Africa/Malabo" , 0x001752 }, - { "Africa/Maputo" , 0x0017B8 }, - { "Africa/Maseru" , 0x00180D }, - { "Africa/Mbabane" , 0x001875 }, - { "Africa/Mogadishu" , 0x0018CB }, - { "Africa/Monrovia" , 0x001926 }, - { "Africa/Nairobi" , 0x00198C }, - { "Africa/Ndjamena" , 0x001A0B }, - { "Africa/Niamey" , 0x001A77 }, - { "Africa/Nouakchott" , 0x001AEA }, - { "Africa/Ouagadougou" , 0x001B55 }, - { "Africa/Porto-Novo" , 0x001BAA }, - { "Africa/Sao_Tome" , 0x001C10 }, - { "Africa/Timbuktu" , 0x001C65 }, - { "Africa/Tripoli" , 0x001CD0 }, - { "Africa/Tunis" , 0x001EC9 }, - { "Africa/Windhoek" , 0x001FDB }, - { "America/Adak" , 0x002222 }, - { "America/Anchorage" , 0x002598 }, - { "America/Anguilla" , 0x00290C }, - { "America/Antigua" , 0x002961 }, - { "America/Araguaina" , 0x0029C7 }, - { "America/Argentina/Buenos_Aires" , 0x002C21 }, - { "America/Argentina/Catamarca" , 0x002DCF }, - { "America/Argentina/ComodRivadavia" , 0x002F90 }, - { "America/Argentina/Cordoba" , 0x003136 }, - { "America/Argentina/Jujuy" , 0x00330B }, - { "America/Argentina/La_Rioja" , 0x0034BF }, - { "America/Argentina/Mendoza" , 0x003677 }, - { "America/Argentina/Rio_Gallegos" , 0x003837 }, - { "America/Argentina/Salta" , 0x0039EC }, - { "America/Argentina/San_Juan" , 0x003B98 }, - { "America/Argentina/San_Luis" , 0x003D50 }, - { "America/Argentina/Tucuman" , 0x003F16 }, - { "America/Argentina/Ushuaia" , 0x0040D2 }, - { "America/Aruba" , 0x00428D }, - { "America/Asuncion" , 0x0042F3 }, - { "America/Atikokan" , 0x0045D8 }, - { "America/Atka" , 0x0046AE }, - { "America/Bahia" , 0x004A14 }, - { "America/Bahia_Banderas" , 0x004BA7 }, - { "America/Barbados" , 0x004E20 }, - { "America/Belem" , 0x004EBA }, - { "America/Belize" , 0x004FB5 }, - { "America/Blanc-Sablon" , 0x005131 }, - { "America/Boa_Vista" , 0x0051E5 }, - { "America/Bogota" , 0x0052EE }, - { "America/Boise" , 0x00535A }, - { "America/Buenos_Aires" , 0x0056F1 }, - { "America/Cambridge_Bay" , 0x00588A }, - { "America/Campo_Grande" , 0x005BB2 }, - { "America/Cancun" , 0x005EA1 }, - { "America/Caracas" , 0x0060E3 }, - { "America/Catamarca" , 0x00614A }, - { "America/Cayenne" , 0x0062F0 }, - { "America/Cayman" , 0x006352 }, - { "America/Chicago" , 0x0063A7 }, - { "America/Chihuahua" , 0x0068BE }, - { "America/Coral_Harbour" , 0x006B29 }, - { "America/Cordoba" , 0x006BBB }, - { "America/Costa_Rica" , 0x006D61 }, - { "America/Creston" , 0x006DEB }, - { "America/Cuiaba" , 0x006E77 }, - { "America/Curacao" , 0x007155 }, - { "America/Danmarkshavn" , 0x0071BB }, - { "America/Dawson" , 0x0072FF }, - { "America/Dawson_Creek" , 0x00761C }, - { "America/Denver" , 0x0077F6 }, - { "America/Detroit" , 0x007B7C }, - { "America/Dominica" , 0x007EDB }, - { "America/Edmonton" , 0x007F30 }, - { "America/Eirunepe" , 0x0082E8 }, - { "America/El_Salvador" , 0x0083FB }, - { "America/Ensenada" , 0x008470 }, - { "America/Fort_Wayne" , 0x008917 }, - { "America/Fortaleza" , 0x0087D9 }, - { "America/Glace_Bay" , 0x008B81 }, - { "America/Godthab" , 0x008EF8 }, - { "America/Goose_Bay" , 0x0091BC }, - { "America/Grand_Turk" , 0x009679 }, - { "America/Grenada" , 0x009928 }, - { "America/Guadeloupe" , 0x00997D }, - { "America/Guatemala" , 0x0099D2 }, - { "America/Guayaquil" , 0x009A5B }, - { "America/Guyana" , 0x009AB8 }, - { "America/Halifax" , 0x009B39 }, - { "America/Havana" , 0x00A04F }, - { "America/Hermosillo" , 0x00A3C2 }, - { "America/Indiana/Indianapolis" , 0x00A4A0 }, - { "America/Indiana/Knox" , 0x00A731 }, - { "America/Indiana/Marengo" , 0x00AAC8 }, - { "America/Indiana/Petersburg" , 0x00AD6E }, - { "America/Indiana/Tell_City" , 0x00B2BB }, - { "America/Indiana/Vevay" , 0x00B554 }, - { "America/Indiana/Vincennes" , 0x00B78F }, - { "America/Indiana/Winamac" , 0x00BA43 }, - { "America/Indianapolis" , 0x00B051 }, - { "America/Inuvik" , 0x00BCFC }, - { "America/Iqaluit" , 0x00BFF3 }, - { "America/Jamaica" , 0x00C315 }, - { "America/Jujuy" , 0x00C3DA }, - { "America/Juneau" , 0x00C584 }, - { "America/Kentucky/Louisville" , 0x00C902 }, - { "America/Kentucky/Monticello" , 0x00CD20 }, - { "America/Knox_IN" , 0x00D0A5 }, - { "America/Kralendijk" , 0x00D416 }, - { "America/La_Paz" , 0x00D47C }, - { "America/Lima" , 0x00D4E3 }, - { "America/Los_Angeles" , 0x00D58B }, - { "America/Louisville" , 0x00D99C }, - { "America/Lower_Princes" , 0x00DD91 }, - { "America/Maceio" , 0x00DDF7 }, - { "America/Managua" , 0x00DF31 }, - { "America/Manaus" , 0x00DFE4 }, - { "America/Marigot" , 0x00E0E6 }, - { "America/Martinique" , 0x00E13B }, - { "America/Matamoros" , 0x00E1A7 }, - { "America/Mazatlan" , 0x00E400 }, - { "America/Mendoza" , 0x00E66D }, - { "America/Menominee" , 0x00E821 }, - { "America/Merida" , 0x00EBA2 }, - { "America/Metlakatla" , 0x00EDDD }, - { "America/Mexico_City" , 0x00EF17 }, - { "America/Miquelon" , 0x00F192 }, - { "America/Moncton" , 0x00F404 }, - { "America/Monterrey" , 0x00F89B }, - { "America/Montevideo" , 0x00FAFE }, - { "America/Montreal" , 0x00FE10 }, - { "America/Montserrat" , 0x010326 }, - { "America/Nassau" , 0x01037B }, - { "America/New_York" , 0x0106C0 }, - { "America/Nipigon" , 0x010BCB }, - { "America/Nome" , 0x010F1C }, - { "America/Noronha" , 0x01129A }, - { "America/North_Dakota/Beulah" , 0x0113CA }, - { "America/North_Dakota/Center" , 0x01175E }, - { "America/North_Dakota/New_Salem" , 0x011AF2 }, - { "America/Ojinaga" , 0x011E9B }, - { "America/Panama" , 0x0120FC }, - { "America/Pangnirtung" , 0x012151 }, - { "America/Paramaribo" , 0x012487 }, - { "America/Phoenix" , 0x012519 }, - { "America/Port-au-Prince" , 0x0125C7 }, - { "America/Port_of_Spain" , 0x0127EC }, - { "America/Porto_Acre" , 0x0126ED }, - { "America/Porto_Velho" , 0x012841 }, - { "America/Puerto_Rico" , 0x012937 }, - { "America/Rainy_River" , 0x0129A2 }, - { "America/Rankin_Inlet" , 0x012CDA }, - { "America/Recife" , 0x012FC0 }, - { "America/Regina" , 0x0130EA }, - { "America/Resolute" , 0x0132A8 }, - { "America/Rio_Branco" , 0x013599 }, - { "America/Rosario" , 0x01369C }, - { "America/Santa_Isabel" , 0x013842 }, - { "America/Santarem" , 0x013BE5 }, - { "America/Santiago" , 0x013CEA }, - { "America/Santo_Domingo" , 0x014093 }, - { "America/Sao_Paulo" , 0x014159 }, - { "America/Scoresbysund" , 0x014468 }, - { "America/Shiprock" , 0x014756 }, - { "America/Sitka" , 0x014AE5 }, - { "America/St_Barthelemy" , 0x014E6D }, - { "America/St_Johns" , 0x014EC2 }, - { "America/St_Kitts" , 0x015415 }, - { "America/St_Lucia" , 0x01546A }, - { "America/St_Thomas" , 0x0154BF }, - { "America/St_Vincent" , 0x015514 }, - { "America/Swift_Current" , 0x015569 }, - { "America/Tegucigalpa" , 0x01568A }, - { "America/Thule" , 0x015709 }, - { "America/Thunder_Bay" , 0x015950 }, - { "America/Tijuana" , 0x015C99 }, - { "America/Toronto" , 0x016032 }, - { "America/Tortola" , 0x016549 }, - { "America/Vancouver" , 0x01659E }, - { "America/Virgin" , 0x0169DB }, - { "America/Whitehorse" , 0x016A30 }, - { "America/Winnipeg" , 0x016D4D }, - { "America/Yakutat" , 0x01718D }, - { "America/Yellowknife" , 0x0174F8 }, - { "Antarctica/Casey" , 0x017808 }, - { "Antarctica/Davis" , 0x0178A5 }, - { "Antarctica/DumontDUrville" , 0x017946 }, - { "Antarctica/Macquarie" , 0x0179D8 }, - { "Antarctica/Mawson" , 0x017C52 }, - { "Antarctica/McMurdo" , 0x017CCE }, - { "Antarctica/Palmer" , 0x017FD0 }, - { "Antarctica/Rothera" , 0x0182EC }, - { "Antarctica/South_Pole" , 0x018362 }, - { "Antarctica/Syowa" , 0x01866A }, - { "Antarctica/Vostok" , 0x0186D8 }, - { "Arctic/Longyearbyen" , 0x018749 }, - { "Asia/Aden" , 0x018A7B }, - { "Asia/Almaty" , 0x018AD0 }, - { "Asia/Amman" , 0x018C4F }, - { "Asia/Anadyr" , 0x018F05 }, - { "Asia/Aqtau" , 0x0190EA }, - { "Asia/Aqtobe" , 0x0192E9 }, - { "Asia/Ashgabat" , 0x0194A1 }, - { "Asia/Ashkhabad" , 0x0195BE }, - { "Asia/Baghdad" , 0x0196DB }, - { "Asia/Bahrain" , 0x019850 }, - { "Asia/Baku" , 0x0198B6 }, - { "Asia/Bangkok" , 0x019B9E }, - { "Asia/Beirut" , 0x019BF3 }, - { "Asia/Bishkek" , 0x019F00 }, - { "Asia/Brunei" , 0x01A0AC }, - { "Asia/Calcutta" , 0x01A10E }, - { "Asia/Choibalsan" , 0x01A187 }, - { "Asia/Chongqing" , 0x01A300 }, - { "Asia/Chungking" , 0x01A3EF }, - { "Asia/Colombo" , 0x01A49E }, - { "Asia/Dacca" , 0x01A53A }, - { "Asia/Damascus" , 0x01A5E0 }, - { "Asia/Dhaka" , 0x01A930 }, - { "Asia/Dili" , 0x01A9D6 }, - { "Asia/Dubai" , 0x01AA5F }, - { "Asia/Dushanbe" , 0x01AAB4 }, - { "Asia/Gaza" , 0x01ABB7 }, - { "Asia/Harbin" , 0x01AE10 }, - { "Asia/Hebron" , 0x01AEF7 }, - { "Asia/Ho_Chi_Minh" , 0x01B159 }, - { "Asia/Hong_Kong" , 0x01B1D1 }, - { "Asia/Hovd" , 0x01B393 }, - { "Asia/Irkutsk" , 0x01B50B }, - { "Asia/Istanbul" , 0x01B6F1 }, - { "Asia/Jakarta" , 0x01BADE }, - { "Asia/Jayapura" , 0x01BB88 }, - { "Asia/Jerusalem" , 0x01BC24 }, - { "Asia/Kabul" , 0x01BF53 }, - { "Asia/Kamchatka" , 0x01BFA4 }, - { "Asia/Karachi" , 0x01C180 }, - { "Asia/Kashgar" , 0x01C235 }, - { "Asia/Kathmandu" , 0x01C306 }, - { "Asia/Katmandu" , 0x01C36C }, - { "Asia/Khandyga" , 0x01C3D2 }, - { "Asia/Kolkata" , 0x01C5F7 }, - { "Asia/Krasnoyarsk" , 0x01C670 }, - { "Asia/Kuala_Lumpur" , 0x01C858 }, - { "Asia/Kuching" , 0x01C915 }, - { "Asia/Kuwait" , 0x01CA03 }, - { "Asia/Macao" , 0x01CA58 }, - { "Asia/Macau" , 0x01CB93 }, - { "Asia/Magadan" , 0x01CCCE }, - { "Asia/Makassar" , 0x01CEB0 }, - { "Asia/Manila" , 0x01CF74 }, - { "Asia/Muscat" , 0x01CFF9 }, - { "Asia/Nicosia" , 0x01D04E }, - { "Asia/Novokuznetsk" , 0x01D336 }, - { "Asia/Novosibirsk" , 0x01D538 }, - { "Asia/Omsk" , 0x01D723 }, - { "Asia/Oral" , 0x01D90A }, - { "Asia/Phnom_Penh" , 0x01DADA }, - { "Asia/Pontianak" , 0x01DB52 }, - { "Asia/Pyongyang" , 0x01DC13 }, - { "Asia/Qatar" , 0x01DC80 }, - { "Asia/Qyzylorda" , 0x01DCE6 }, - { "Asia/Rangoon" , 0x01DEBC }, - { "Asia/Riyadh" , 0x01DF34 }, - { "Asia/Saigon" , 0x01DF89 }, - { "Asia/Sakhalin" , 0x01E001 }, - { "Asia/Samarkand" , 0x01E1F8 }, - { "Asia/Seoul" , 0x01E32E }, - { "Asia/Shanghai" , 0x01E3D2 }, - { "Asia/Singapore" , 0x01E4B2 }, - { "Asia/Taipei" , 0x01E569 }, - { "Asia/Tashkent" , 0x01E681 }, - { "Asia/Tbilisi" , 0x01E7B2 }, - { "Asia/Tehran" , 0x01E96C }, - { "Asia/Tel_Aviv" , 0x01EBDA }, - { "Asia/Thimbu" , 0x01EF09 }, - { "Asia/Thimphu" , 0x01EF6F }, - { "Asia/Tokyo" , 0x01EFD5 }, - { "Asia/Ujung_Pandang" , 0x01F05E }, - { "Asia/Ulaanbaatar" , 0x01F0DA }, - { "Asia/Ulan_Bator" , 0x01F235 }, - { "Asia/Urumqi" , 0x01F382 }, - { "Asia/Ust-Nera" , 0x01F449 }, - { "Asia/Vientiane" , 0x01F64E }, - { "Asia/Vladivostok" , 0x01F6C6 }, - { "Asia/Yakutsk" , 0x01F8B2 }, - { "Asia/Yekaterinburg" , 0x01FA97 }, - { "Asia/Yerevan" , 0x01FCA2 }, - { "Atlantic/Azores" , 0x01FEA2 }, - { "Atlantic/Bermuda" , 0x0203A5 }, - { "Atlantic/Canary" , 0x020686 }, - { "Atlantic/Cape_Verde" , 0x02095C }, - { "Atlantic/Faeroe" , 0x0209D5 }, - { "Atlantic/Faroe" , 0x020C79 }, - { "Atlantic/Jan_Mayen" , 0x020F1D }, - { "Atlantic/Madeira" , 0x02124F }, - { "Atlantic/Reykjavik" , 0x021758 }, - { "Atlantic/South_Georgia" , 0x021911 }, - { "Atlantic/St_Helena" , 0x021B23 }, - { "Atlantic/Stanley" , 0x021955 }, - { "Australia/ACT" , 0x021B78 }, - { "Australia/Adelaide" , 0x021E95 }, - { "Australia/Brisbane" , 0x0221C1 }, - { "Australia/Broken_Hill" , 0x022288 }, - { "Australia/Canberra" , 0x0225C6 }, - { "Australia/Currie" , 0x0228E3 }, - { "Australia/Darwin" , 0x022C16 }, - { "Australia/Eucla" , 0x022C9C }, - { "Australia/Hobart" , 0x022D71 }, - { "Australia/LHI" , 0x0230CF }, - { "Australia/Lindeman" , 0x02336A }, - { "Australia/Lord_Howe" , 0x02344B }, - { "Australia/Melbourne" , 0x0236F6 }, - { "Australia/North" , 0x023A1B }, - { "Australia/NSW" , 0x023A8F }, - { "Australia/Perth" , 0x023DAC }, - { "Australia/Queensland" , 0x023E84 }, - { "Australia/South" , 0x023F30 }, - { "Australia/Sydney" , 0x02424D }, - { "Australia/Tasmania" , 0x02458A }, - { "Australia/Victoria" , 0x0248CF }, - { "Australia/West" , 0x024BEC }, - { "Australia/Yancowinna" , 0x024CA2 }, - { "Brazil/Acre" , 0x024FC4 }, - { "Brazil/DeNoronha" , 0x0250C3 }, - { "Brazil/East" , 0x0251E3 }, - { "Brazil/West" , 0x0254C0 }, - { "Canada/Atlantic" , 0x0255B8 }, - { "Canada/Central" , 0x025AA0 }, - { "Canada/East-Saskatchewan" , 0x0263AA }, - { "Canada/Eastern" , 0x025EBA }, - { "Canada/Mountain" , 0x026533 }, - { "Canada/Newfoundland" , 0x0268A9 }, - { "Canada/Pacific" , 0x026DD4 }, - { "Canada/Saskatchewan" , 0x0271ED }, - { "Canada/Yukon" , 0x027376 }, - { "CET" , 0x027679 }, - { "Chile/Continental" , 0x027982 }, - { "Chile/EasterIsland" , 0x027D1D }, - { "CST6CDT" , 0x02805F }, - { "Cuba" , 0x0283B0 }, - { "EET" , 0x028723 }, - { "Egypt" , 0x0289D6 }, - { "Eire" , 0x028C99 }, - { "EST" , 0x0291AA }, - { "EST5EDT" , 0x0291EE }, - { "Etc/GMT" , 0x02953F }, - { "Etc/GMT+0" , 0x02960B }, - { "Etc/GMT+1" , 0x029695 }, - { "Etc/GMT+10" , 0x029722 }, - { "Etc/GMT+11" , 0x0297B0 }, - { "Etc/GMT+12" , 0x02983E }, - { "Etc/GMT+2" , 0x029959 }, - { "Etc/GMT+3" , 0x0299E5 }, - { "Etc/GMT+4" , 0x029A71 }, - { "Etc/GMT+5" , 0x029AFD }, - { "Etc/GMT+6" , 0x029B89 }, - { "Etc/GMT+7" , 0x029C15 }, - { "Etc/GMT+8" , 0x029CA1 }, - { "Etc/GMT+9" , 0x029D2D }, - { "Etc/GMT-0" , 0x0295C7 }, - { "Etc/GMT-1" , 0x02964F }, - { "Etc/GMT-10" , 0x0296DB }, - { "Etc/GMT-11" , 0x029769 }, - { "Etc/GMT-12" , 0x0297F7 }, - { "Etc/GMT-13" , 0x029885 }, - { "Etc/GMT-14" , 0x0298CC }, - { "Etc/GMT-2" , 0x029913 }, - { "Etc/GMT-3" , 0x02999F }, - { "Etc/GMT-4" , 0x029A2B }, - { "Etc/GMT-5" , 0x029AB7 }, - { "Etc/GMT-6" , 0x029B43 }, - { "Etc/GMT-7" , 0x029BCF }, - { "Etc/GMT-8" , 0x029C5B }, - { "Etc/GMT-9" , 0x029CE7 }, - { "Etc/GMT0" , 0x029583 }, - { "Etc/Greenwich" , 0x029D73 }, - { "Etc/UCT" , 0x029DB7 }, - { "Etc/Universal" , 0x029DFB }, - { "Etc/UTC" , 0x029E3F }, - { "Etc/Zulu" , 0x029E83 }, - { "Europe/Amsterdam" , 0x029EC7 }, - { "Europe/Andorra" , 0x02A305 }, - { "Europe/Athens" , 0x02A581 }, - { "Europe/Belfast" , 0x02A8C4 }, - { "Europe/Belgrade" , 0x02ADFB }, - { "Europe/Berlin" , 0x02B0C4 }, - { "Europe/Bratislava" , 0x02B428 }, - { "Europe/Brussels" , 0x02B75A }, - { "Europe/Bucharest" , 0x02BB91 }, - { "Europe/Budapest" , 0x02BEBB }, - { "Europe/Busingen" , 0x02C22E }, - { "Europe/Chisinau" , 0x02C4E5 }, - { "Europe/Copenhagen" , 0x02C873 }, - { "Europe/Dublin" , 0x02CB7D }, - { "Europe/Gibraltar" , 0x02D08E }, - { "Europe/Guernsey" , 0x02D4E5 }, - { "Europe/Helsinki" , 0x02DA1C }, - { "Europe/Isle_of_Man" , 0x02DCD2 }, - { "Europe/Istanbul" , 0x02E209 }, - { "Europe/Jersey" , 0x02E5F6 }, - { "Europe/Kaliningrad" , 0x02EB2D }, - { "Europe/Kiev" , 0x02ED93 }, - { "Europe/Lisbon" , 0x02F0AA }, - { "Europe/Ljubljana" , 0x02F5AE }, - { "Europe/London" , 0x02F877 }, - { "Europe/Luxembourg" , 0x02FDAE }, - { "Europe/Madrid" , 0x030204 }, - { "Europe/Malta" , 0x0305CA }, - { "Europe/Mariehamn" , 0x030983 }, - { "Europe/Minsk" , 0x030C39 }, - { "Europe/Monaco" , 0x030E47 }, - { "Europe/Moscow" , 0x031282 }, - { "Europe/Nicosia" , 0x0314D3 }, - { "Europe/Oslo" , 0x0317BB }, - { "Europe/Paris" , 0x031AED }, - { "Europe/Podgorica" , 0x031F33 }, - { "Europe/Prague" , 0x0321FC }, - { "Europe/Riga" , 0x03252E }, - { "Europe/Rome" , 0x032873 }, - { "Europe/Samara" , 0x032C36 }, - { "Europe/San_Marino" , 0x032E69 }, - { "Europe/Sarajevo" , 0x03322C }, - { "Europe/Simferopol" , 0x0334F5 }, - { "Europe/Skopje" , 0x033820 }, - { "Europe/Sofia" , 0x033AE9 }, - { "Europe/Stockholm" , 0x033DF1 }, - { "Europe/Tallinn" , 0x0340A0 }, - { "Europe/Tirane" , 0x0343DA }, - { "Europe/Tiraspol" , 0x0346E0 }, - { "Europe/Uzhgorod" , 0x034A6E }, - { "Europe/Vaduz" , 0x034D85 }, - { "Europe/Vatican" , 0x035018 }, - { "Europe/Vienna" , 0x0353DB }, - { "Europe/Vilnius" , 0x035708 }, - { "Europe/Volgograd" , 0x035A47 }, - { "Europe/Warsaw" , 0x035C47 }, - { "Europe/Zagreb" , 0x036028 }, - { "Europe/Zaporozhye" , 0x0362F1 }, - { "Europe/Zurich" , 0x036632 }, - { "Factory" , 0x0368E1 }, - { "GB" , 0x036952 }, - { "GB-Eire" , 0x036E89 }, - { "GMT" , 0x0373C0 }, - { "GMT+0" , 0x03748C }, - { "GMT-0" , 0x037448 }, - { "GMT0" , 0x037404 }, - { "Greenwich" , 0x0374D0 }, - { "Hongkong" , 0x037514 }, - { "HST" , 0x0376D6 }, - { "Iceland" , 0x03771A }, - { "Indian/Antananarivo" , 0x0378D3 }, - { "Indian/Chagos" , 0x037947 }, - { "Indian/Christmas" , 0x0379A9 }, - { "Indian/Cocos" , 0x0379ED }, - { "Indian/Comoro" , 0x037A31 }, - { "Indian/Kerguelen" , 0x037A86 }, - { "Indian/Mahe" , 0x037ADB }, - { "Indian/Maldives" , 0x037B30 }, - { "Indian/Mauritius" , 0x037B85 }, - { "Indian/Mayotte" , 0x037BFB }, - { "Indian/Reunion" , 0x037C50 }, - { "Iran" , 0x037CA5 }, - { "Israel" , 0x037F13 }, - { "Jamaica" , 0x038242 }, - { "Japan" , 0x038307 }, - { "Kwajalein" , 0x038390 }, - { "Libya" , 0x0383F3 }, - { "MET" , 0x0385EC }, - { "Mexico/BajaNorte" , 0x0388F5 }, - { "Mexico/BajaSur" , 0x038C5E }, - { "Mexico/General" , 0x038EA3 }, - { "MST" , 0x039101 }, - { "MST7MDT" , 0x039145 }, - { "Navajo" , 0x039496 }, - { "NZ" , 0x03980F }, - { "NZ-CHAT" , 0x039B8D }, - { "Pacific/Apia" , 0x039E75 }, - { "Pacific/Auckland" , 0x03A011 }, - { "Pacific/Chatham" , 0x03A39D }, - { "Pacific/Chuuk" , 0x03A694 }, - { "Pacific/Easter" , 0x03A6ED }, - { "Pacific/Efate" , 0x03AA4B }, - { "Pacific/Enderbury" , 0x03AB11 }, - { "Pacific/Fakaofo" , 0x03AB7F }, - { "Pacific/Fiji" , 0x03ABD0 }, - { "Pacific/Funafuti" , 0x03AD63 }, - { "Pacific/Galapagos" , 0x03ADA7 }, - { "Pacific/Gambier" , 0x03AE1F }, - { "Pacific/Guadalcanal" , 0x03AE84 }, - { "Pacific/Guam" , 0x03AED9 }, - { "Pacific/Honolulu" , 0x03AF2F }, - { "Pacific/Johnston" , 0x03AFA6 }, - { "Pacific/Kiritimati" , 0x03AFF8 }, - { "Pacific/Kosrae" , 0x03B063 }, - { "Pacific/Kwajalein" , 0x03B0C0 }, - { "Pacific/Majuro" , 0x03B12C }, - { "Pacific/Marquesas" , 0x03B18B }, - { "Pacific/Midway" , 0x03B1F2 }, - { "Pacific/Nauru" , 0x03B27C }, - { "Pacific/Niue" , 0x03B2F4 }, - { "Pacific/Norfolk" , 0x03B352 }, - { "Pacific/Noumea" , 0x03B3A7 }, - { "Pacific/Pago_Pago" , 0x03B437 }, - { "Pacific/Palau" , 0x03B4C0 }, - { "Pacific/Pitcairn" , 0x03B504 }, - { "Pacific/Pohnpei" , 0x03B559 }, - { "Pacific/Ponape" , 0x03B5AE }, - { "Pacific/Port_Moresby" , 0x03B5F3 }, - { "Pacific/Rarotonga" , 0x03B637 }, - { "Pacific/Saipan" , 0x03B713 }, - { "Pacific/Samoa" , 0x03B776 }, - { "Pacific/Tahiti" , 0x03B7FF }, - { "Pacific/Tarawa" , 0x03B864 }, - { "Pacific/Tongatapu" , 0x03B8B8 }, - { "Pacific/Truk" , 0x03B944 }, - { "Pacific/Wake" , 0x03B989 }, - { "Pacific/Wallis" , 0x03B9D9 }, - { "Pacific/Yap" , 0x03BA1D }, - { "Poland" , 0x03BA62 }, - { "Portugal" , 0x03BE43 }, - { "PRC" , 0x03C33F }, - { "PST8PDT" , 0x03C3F0 }, - { "ROC" , 0x03C741 }, - { "ROK" , 0x03C859 }, - { "Singapore" , 0x03C8FD }, - { "Turkey" , 0x03C9B4 }, - { "UCT" , 0x03CDA1 }, - { "Universal" , 0x03CDE5 }, - { "US/Alaska" , 0x03CE29 }, - { "US/Aleutian" , 0x03D192 }, - { "US/Arizona" , 0x03D4F8 }, - { "US/Central" , 0x03D586 }, - { "US/East-Indiana" , 0x03DF90 }, - { "US/Eastern" , 0x03DA91 }, - { "US/Hawaii" , 0x03E1FA }, - { "US/Indiana-Starke" , 0x03E26B }, - { "US/Michigan" , 0x03E5DC }, - { "US/Mountain" , 0x03E913 }, - { "US/Pacific" , 0x03EC8C }, - { "US/Pacific-New" , 0x03F091 }, - { "US/Samoa" , 0x03F496 }, - { "UTC" , 0x03F51F }, - { "W-SU" , 0x03F816 }, - { "WET" , 0x03F563 }, - { "Zulu" , 0x03FA50 }, + { "Africa/Ceuta" , 0x000ABC }, + { "Africa/Conakry" , 0x000DC3 }, + { "Africa/Dakar" , 0x000E2E }, + { "Africa/Dar_es_Salaam" , 0x000E94 }, + { "Africa/Djibouti" , 0x000F01 }, + { "Africa/Douala" , 0x000F56 }, + { "Africa/El_Aaiun" , 0x000FAB }, + { "Africa/Freetown" , 0x001011 }, + { "Africa/Gaborone" , 0x001120 }, + { "Africa/Harare" , 0x00118D }, + { "Africa/Johannesburg" , 0x0011E2 }, + { "Africa/Juba" , 0x001250 }, + { "Africa/Kampala" , 0x001363 }, + { "Africa/Khartoum" , 0x0013E2 }, + { "Africa/Kigali" , 0x0014F5 }, + { "Africa/Kinshasa" , 0x00154A }, + { "Africa/Lagos" , 0x0015A5 }, + { "Africa/Libreville" , 0x0015FA }, + { "Africa/Lome" , 0x00164F }, + { "Africa/Luanda" , 0x001693 }, + { "Africa/Lubumbashi" , 0x0016E8 }, + { "Africa/Lusaka" , 0x001743 }, + { "Africa/Malabo" , 0x001798 }, + { "Africa/Maputo" , 0x0017FE }, + { "Africa/Maseru" , 0x001853 }, + { "Africa/Mbabane" , 0x0018BB }, + { "Africa/Mogadishu" , 0x001911 }, + { "Africa/Monrovia" , 0x00196C }, + { "Africa/Nairobi" , 0x0019D2 }, + { "Africa/Ndjamena" , 0x001A51 }, + { "Africa/Niamey" , 0x001ABD }, + { "Africa/Nouakchott" , 0x001B30 }, + { "Africa/Ouagadougou" , 0x001B9B }, + { "Africa/Porto-Novo" , 0x001BF0 }, + { "Africa/Sao_Tome" , 0x001C56 }, + { "Africa/Timbuktu" , 0x001CAB }, + { "Africa/Tripoli" , 0x001D16 }, + { "Africa/Tunis" , 0x001F0F }, + { "Africa/Windhoek" , 0x002021 }, + { "America/Adak" , 0x002268 }, + { "America/Anchorage" , 0x0025DE }, + { "America/Anguilla" , 0x002952 }, + { "America/Antigua" , 0x0029A7 }, + { "America/Araguaina" , 0x002A0D }, + { "America/Argentina/Buenos_Aires" , 0x002C67 }, + { "America/Argentina/Catamarca" , 0x002E15 }, + { "America/Argentina/ComodRivadavia" , 0x002FD6 }, + { "America/Argentina/Cordoba" , 0x00317C }, + { "America/Argentina/Jujuy" , 0x003351 }, + { "America/Argentina/La_Rioja" , 0x003505 }, + { "America/Argentina/Mendoza" , 0x0036BD }, + { "America/Argentina/Rio_Gallegos" , 0x00387D }, + { "America/Argentina/Salta" , 0x003A32 }, + { "America/Argentina/San_Juan" , 0x003BDE }, + { "America/Argentina/San_Luis" , 0x003D96 }, + { "America/Argentina/Tucuman" , 0x003F5C }, + { "America/Argentina/Ushuaia" , 0x004118 }, + { "America/Aruba" , 0x0042D3 }, + { "America/Asuncion" , 0x004339 }, + { "America/Atikokan" , 0x00461E }, + { "America/Atka" , 0x0046F4 }, + { "America/Bahia" , 0x004A5A }, + { "America/Bahia_Banderas" , 0x004BED }, + { "America/Barbados" , 0x004E66 }, + { "America/Belem" , 0x004F00 }, + { "America/Belize" , 0x004FFB }, + { "America/Blanc-Sablon" , 0x005177 }, + { "America/Boa_Vista" , 0x00522B }, + { "America/Bogota" , 0x005334 }, + { "America/Boise" , 0x0053A0 }, + { "America/Buenos_Aires" , 0x005737 }, + { "America/Cambridge_Bay" , 0x0058D0 }, + { "America/Campo_Grande" , 0x005BF8 }, + { "America/Cancun" , 0x005EE7 }, + { "America/Caracas" , 0x006129 }, + { "America/Catamarca" , 0x006190 }, + { "America/Cayenne" , 0x006336 }, + { "America/Cayman" , 0x006398 }, + { "America/Chicago" , 0x0063ED }, + { "America/Chihuahua" , 0x006904 }, + { "America/Coral_Harbour" , 0x006B6F }, + { "America/Cordoba" , 0x006C01 }, + { "America/Costa_Rica" , 0x006DA7 }, + { "America/Creston" , 0x006E31 }, + { "America/Cuiaba" , 0x006EBD }, + { "America/Curacao" , 0x00719B }, + { "America/Danmarkshavn" , 0x007201 }, + { "America/Dawson" , 0x007345 }, + { "America/Dawson_Creek" , 0x007662 }, + { "America/Denver" , 0x00783C }, + { "America/Detroit" , 0x007BC2 }, + { "America/Dominica" , 0x007F21 }, + { "America/Edmonton" , 0x007F76 }, + { "America/Eirunepe" , 0x00832E }, + { "America/El_Salvador" , 0x008441 }, + { "America/Ensenada" , 0x0084B6 }, + { "America/Fort_Wayne" , 0x00895D }, + { "America/Fortaleza" , 0x00881F }, + { "America/Glace_Bay" , 0x008BC7 }, + { "America/Godthab" , 0x008F3E }, + { "America/Goose_Bay" , 0x009202 }, + { "America/Grand_Turk" , 0x0096BF }, + { "America/Grenada" , 0x00996E }, + { "America/Guadeloupe" , 0x0099C3 }, + { "America/Guatemala" , 0x009A18 }, + { "America/Guayaquil" , 0x009AA1 }, + { "America/Guyana" , 0x009AFE }, + { "America/Halifax" , 0x009B7F }, + { "America/Havana" , 0x00A095 }, + { "America/Hermosillo" , 0x00A408 }, + { "America/Indiana/Indianapolis" , 0x00A4E6 }, + { "America/Indiana/Knox" , 0x00A777 }, + { "America/Indiana/Marengo" , 0x00AB0E }, + { "America/Indiana/Petersburg" , 0x00ADB4 }, + { "America/Indiana/Tell_City" , 0x00B301 }, + { "America/Indiana/Vevay" , 0x00B59A }, + { "America/Indiana/Vincennes" , 0x00B7D5 }, + { "America/Indiana/Winamac" , 0x00BA89 }, + { "America/Indianapolis" , 0x00B097 }, + { "America/Inuvik" , 0x00BD42 }, + { "America/Iqaluit" , 0x00C039 }, + { "America/Jamaica" , 0x00C35B }, + { "America/Jujuy" , 0x00C420 }, + { "America/Juneau" , 0x00C5CA }, + { "America/Kentucky/Louisville" , 0x00C948 }, + { "America/Kentucky/Monticello" , 0x00CD66 }, + { "America/Knox_IN" , 0x00D0EB }, + { "America/Kralendijk" , 0x00D45C }, + { "America/La_Paz" , 0x00D4C2 }, + { "America/Lima" , 0x00D529 }, + { "America/Los_Angeles" , 0x00D5D1 }, + { "America/Louisville" , 0x00D9E2 }, + { "America/Lower_Princes" , 0x00DDD7 }, + { "America/Maceio" , 0x00DE3D }, + { "America/Managua" , 0x00DF77 }, + { "America/Manaus" , 0x00E02A }, + { "America/Marigot" , 0x00E12C }, + { "America/Martinique" , 0x00E181 }, + { "America/Matamoros" , 0x00E1ED }, + { "America/Mazatlan" , 0x00E446 }, + { "America/Mendoza" , 0x00E6B3 }, + { "America/Menominee" , 0x00E867 }, + { "America/Merida" , 0x00EBE8 }, + { "America/Metlakatla" , 0x00EE23 }, + { "America/Mexico_City" , 0x00EF5D }, + { "America/Miquelon" , 0x00F1D8 }, + { "America/Moncton" , 0x00F44A }, + { "America/Monterrey" , 0x00F8E1 }, + { "America/Montevideo" , 0x00FB44 }, + { "America/Montreal" , 0x00FE56 }, + { "America/Montserrat" , 0x01036C }, + { "America/Nassau" , 0x0103C1 }, + { "America/New_York" , 0x010706 }, + { "America/Nipigon" , 0x010C11 }, + { "America/Nome" , 0x010F62 }, + { "America/Noronha" , 0x0112E0 }, + { "America/North_Dakota/Beulah" , 0x011410 }, + { "America/North_Dakota/Center" , 0x0117A4 }, + { "America/North_Dakota/New_Salem" , 0x011B38 }, + { "America/Ojinaga" , 0x011EE1 }, + { "America/Panama" , 0x012142 }, + { "America/Pangnirtung" , 0x012197 }, + { "America/Paramaribo" , 0x0124CD }, + { "America/Phoenix" , 0x01255F }, + { "America/Port-au-Prince" , 0x01260D }, + { "America/Port_of_Spain" , 0x01292C }, + { "America/Porto_Acre" , 0x01282D }, + { "America/Porto_Velho" , 0x012981 }, + { "America/Puerto_Rico" , 0x012A77 }, + { "America/Rainy_River" , 0x012AE2 }, + { "America/Rankin_Inlet" , 0x012E1A }, + { "America/Recife" , 0x013100 }, + { "America/Regina" , 0x01322A }, + { "America/Resolute" , 0x0133E8 }, + { "America/Rio_Branco" , 0x0136D9 }, + { "America/Rosario" , 0x0137DC }, + { "America/Santa_Isabel" , 0x013982 }, + { "America/Santarem" , 0x013D25 }, + { "America/Santiago" , 0x013E2A }, + { "America/Santo_Domingo" , 0x0141D3 }, + { "America/Sao_Paulo" , 0x014299 }, + { "America/Scoresbysund" , 0x0145A8 }, + { "America/Shiprock" , 0x014896 }, + { "America/Sitka" , 0x014C25 }, + { "America/St_Barthelemy" , 0x014FAD }, + { "America/St_Johns" , 0x015002 }, + { "America/St_Kitts" , 0x015555 }, + { "America/St_Lucia" , 0x0155AA }, + { "America/St_Thomas" , 0x0155FF }, + { "America/St_Vincent" , 0x015654 }, + { "America/Swift_Current" , 0x0156A9 }, + { "America/Tegucigalpa" , 0x0157CA }, + { "America/Thule" , 0x015849 }, + { "America/Thunder_Bay" , 0x015A90 }, + { "America/Tijuana" , 0x015DD9 }, + { "America/Toronto" , 0x016172 }, + { "America/Tortola" , 0x016689 }, + { "America/Vancouver" , 0x0166DE }, + { "America/Virgin" , 0x016B1B }, + { "America/Whitehorse" , 0x016B70 }, + { "America/Winnipeg" , 0x016E8D }, + { "America/Yakutat" , 0x0172CD }, + { "America/Yellowknife" , 0x017638 }, + { "Antarctica/Casey" , 0x017948 }, + { "Antarctica/Davis" , 0x0179E5 }, + { "Antarctica/DumontDUrville" , 0x017A86 }, + { "Antarctica/Macquarie" , 0x017B18 }, + { "Antarctica/Mawson" , 0x017D92 }, + { "Antarctica/McMurdo" , 0x017E0E }, + { "Antarctica/Palmer" , 0x018110 }, + { "Antarctica/Rothera" , 0x01842C }, + { "Antarctica/South_Pole" , 0x0184A2 }, + { "Antarctica/Syowa" , 0x0187AA }, + { "Antarctica/Vostok" , 0x018818 }, + { "Arctic/Longyearbyen" , 0x018889 }, + { "Asia/Aden" , 0x018BBB }, + { "Asia/Almaty" , 0x018C10 }, + { "Asia/Amman" , 0x018D8F }, + { "Asia/Anadyr" , 0x019045 }, + { "Asia/Aqtau" , 0x01922A }, + { "Asia/Aqtobe" , 0x019429 }, + { "Asia/Ashgabat" , 0x0195E1 }, + { "Asia/Ashkhabad" , 0x0196FE }, + { "Asia/Baghdad" , 0x01981B }, + { "Asia/Bahrain" , 0x019990 }, + { "Asia/Baku" , 0x0199F6 }, + { "Asia/Bangkok" , 0x019CDE }, + { "Asia/Beirut" , 0x019D33 }, + { "Asia/Bishkek" , 0x01A040 }, + { "Asia/Brunei" , 0x01A1EC }, + { "Asia/Calcutta" , 0x01A24E }, + { "Asia/Choibalsan" , 0x01A2C7 }, + { "Asia/Chongqing" , 0x01A440 }, + { "Asia/Chungking" , 0x01A52F }, + { "Asia/Colombo" , 0x01A5DE }, + { "Asia/Dacca" , 0x01A67A }, + { "Asia/Damascus" , 0x01A720 }, + { "Asia/Dhaka" , 0x01AA70 }, + { "Asia/Dili" , 0x01AB16 }, + { "Asia/Dubai" , 0x01AB9F }, + { "Asia/Dushanbe" , 0x01ABF4 }, + { "Asia/Gaza" , 0x01ACF7 }, + { "Asia/Harbin" , 0x01AF50 }, + { "Asia/Hebron" , 0x01B037 }, + { "Asia/Ho_Chi_Minh" , 0x01B299 }, + { "Asia/Hong_Kong" , 0x01B311 }, + { "Asia/Hovd" , 0x01B4D3 }, + { "Asia/Irkutsk" , 0x01B64B }, + { "Asia/Istanbul" , 0x01B831 }, + { "Asia/Jakarta" , 0x01BC1E }, + { "Asia/Jayapura" , 0x01BCC8 }, + { "Asia/Jerusalem" , 0x01BD64 }, + { "Asia/Kabul" , 0x01C093 }, + { "Asia/Kamchatka" , 0x01C0E4 }, + { "Asia/Karachi" , 0x01C2C0 }, + { "Asia/Kashgar" , 0x01C375 }, + { "Asia/Kathmandu" , 0x01C446 }, + { "Asia/Katmandu" , 0x01C4AC }, + { "Asia/Khandyga" , 0x01C512 }, + { "Asia/Kolkata" , 0x01C737 }, + { "Asia/Krasnoyarsk" , 0x01C7B0 }, + { "Asia/Kuala_Lumpur" , 0x01C998 }, + { "Asia/Kuching" , 0x01CA55 }, + { "Asia/Kuwait" , 0x01CB43 }, + { "Asia/Macao" , 0x01CB98 }, + { "Asia/Macau" , 0x01CCD3 }, + { "Asia/Magadan" , 0x01CE0E }, + { "Asia/Makassar" , 0x01CFF0 }, + { "Asia/Manila" , 0x01D0B4 }, + { "Asia/Muscat" , 0x01D139 }, + { "Asia/Nicosia" , 0x01D18E }, + { "Asia/Novokuznetsk" , 0x01D476 }, + { "Asia/Novosibirsk" , 0x01D678 }, + { "Asia/Omsk" , 0x01D863 }, + { "Asia/Oral" , 0x01DA4A }, + { "Asia/Phnom_Penh" , 0x01DC1A }, + { "Asia/Pontianak" , 0x01DC92 }, + { "Asia/Pyongyang" , 0x01DD53 }, + { "Asia/Qatar" , 0x01DDC0 }, + { "Asia/Qyzylorda" , 0x01DE26 }, + { "Asia/Rangoon" , 0x01DFFC }, + { "Asia/Riyadh" , 0x01E074 }, + { "Asia/Saigon" , 0x01E0C9 }, + { "Asia/Sakhalin" , 0x01E141 }, + { "Asia/Samarkand" , 0x01E338 }, + { "Asia/Seoul" , 0x01E46E }, + { "Asia/Shanghai" , 0x01E512 }, + { "Asia/Singapore" , 0x01E5F2 }, + { "Asia/Taipei" , 0x01E6A9 }, + { "Asia/Tashkent" , 0x01E7C1 }, + { "Asia/Tbilisi" , 0x01E8F2 }, + { "Asia/Tehran" , 0x01EAAC }, + { "Asia/Tel_Aviv" , 0x01ED1A }, + { "Asia/Thimbu" , 0x01F049 }, + { "Asia/Thimphu" , 0x01F0AF }, + { "Asia/Tokyo" , 0x01F115 }, + { "Asia/Ujung_Pandang" , 0x01F19E }, + { "Asia/Ulaanbaatar" , 0x01F21A }, + { "Asia/Ulan_Bator" , 0x01F375 }, + { "Asia/Urumqi" , 0x01F4C2 }, + { "Asia/Ust-Nera" , 0x01F589 }, + { "Asia/Vientiane" , 0x01F78E }, + { "Asia/Vladivostok" , 0x01F806 }, + { "Asia/Yakutsk" , 0x01F9F2 }, + { "Asia/Yekaterinburg" , 0x01FBD7 }, + { "Asia/Yerevan" , 0x01FDE2 }, + { "Atlantic/Azores" , 0x01FFE2 }, + { "Atlantic/Bermuda" , 0x0204E5 }, + { "Atlantic/Canary" , 0x0207C6 }, + { "Atlantic/Cape_Verde" , 0x020A9C }, + { "Atlantic/Faeroe" , 0x020B15 }, + { "Atlantic/Faroe" , 0x020DB9 }, + { "Atlantic/Jan_Mayen" , 0x02105D }, + { "Atlantic/Madeira" , 0x02138F }, + { "Atlantic/Reykjavik" , 0x021898 }, + { "Atlantic/South_Georgia" , 0x021A51 }, + { "Atlantic/St_Helena" , 0x021C63 }, + { "Atlantic/Stanley" , 0x021A95 }, + { "Australia/ACT" , 0x021CB8 }, + { "Australia/Adelaide" , 0x021FD5 }, + { "Australia/Brisbane" , 0x022301 }, + { "Australia/Broken_Hill" , 0x0223C8 }, + { "Australia/Canberra" , 0x022706 }, + { "Australia/Currie" , 0x022A23 }, + { "Australia/Darwin" , 0x022D56 }, + { "Australia/Eucla" , 0x022DDC }, + { "Australia/Hobart" , 0x022EB1 }, + { "Australia/LHI" , 0x02320F }, + { "Australia/Lindeman" , 0x0234AA }, + { "Australia/Lord_Howe" , 0x02358B }, + { "Australia/Melbourne" , 0x023836 }, + { "Australia/North" , 0x023B5B }, + { "Australia/NSW" , 0x023BCF }, + { "Australia/Perth" , 0x023EEC }, + { "Australia/Queensland" , 0x023FC4 }, + { "Australia/South" , 0x024070 }, + { "Australia/Sydney" , 0x02438D }, + { "Australia/Tasmania" , 0x0246CA }, + { "Australia/Victoria" , 0x024A0F }, + { "Australia/West" , 0x024D2C }, + { "Australia/Yancowinna" , 0x024DE2 }, + { "Brazil/Acre" , 0x025104 }, + { "Brazil/DeNoronha" , 0x025203 }, + { "Brazil/East" , 0x025323 }, + { "Brazil/West" , 0x025600 }, + { "Canada/Atlantic" , 0x0256F8 }, + { "Canada/Central" , 0x025BE0 }, + { "Canada/East-Saskatchewan" , 0x0264EA }, + { "Canada/Eastern" , 0x025FFA }, + { "Canada/Mountain" , 0x026673 }, + { "Canada/Newfoundland" , 0x0269E9 }, + { "Canada/Pacific" , 0x026F14 }, + { "Canada/Saskatchewan" , 0x02732D }, + { "Canada/Yukon" , 0x0274B6 }, + { "CET" , 0x0277B9 }, + { "Chile/Continental" , 0x027AC2 }, + { "Chile/EasterIsland" , 0x027E5D }, + { "CST6CDT" , 0x02819F }, + { "Cuba" , 0x0284F0 }, + { "EET" , 0x028863 }, + { "Egypt" , 0x028B16 }, + { "Eire" , 0x028DD9 }, + { "EST" , 0x0292EA }, + { "EST5EDT" , 0x02932E }, + { "Etc/GMT" , 0x02967F }, + { "Etc/GMT+0" , 0x02974B }, + { "Etc/GMT+1" , 0x0297D5 }, + { "Etc/GMT+10" , 0x029862 }, + { "Etc/GMT+11" , 0x0298F0 }, + { "Etc/GMT+12" , 0x02997E }, + { "Etc/GMT+2" , 0x029A99 }, + { "Etc/GMT+3" , 0x029B25 }, + { "Etc/GMT+4" , 0x029BB1 }, + { "Etc/GMT+5" , 0x029C3D }, + { "Etc/GMT+6" , 0x029CC9 }, + { "Etc/GMT+7" , 0x029D55 }, + { "Etc/GMT+8" , 0x029DE1 }, + { "Etc/GMT+9" , 0x029E6D }, + { "Etc/GMT-0" , 0x029707 }, + { "Etc/GMT-1" , 0x02978F }, + { "Etc/GMT-10" , 0x02981B }, + { "Etc/GMT-11" , 0x0298A9 }, + { "Etc/GMT-12" , 0x029937 }, + { "Etc/GMT-13" , 0x0299C5 }, + { "Etc/GMT-14" , 0x029A0C }, + { "Etc/GMT-2" , 0x029A53 }, + { "Etc/GMT-3" , 0x029ADF }, + { "Etc/GMT-4" , 0x029B6B }, + { "Etc/GMT-5" , 0x029BF7 }, + { "Etc/GMT-6" , 0x029C83 }, + { "Etc/GMT-7" , 0x029D0F }, + { "Etc/GMT-8" , 0x029D9B }, + { "Etc/GMT-9" , 0x029E27 }, + { "Etc/GMT0" , 0x0296C3 }, + { "Etc/Greenwich" , 0x029EB3 }, + { "Etc/UCT" , 0x029EF7 }, + { "Etc/Universal" , 0x029F3B }, + { "Etc/UTC" , 0x029F7F }, + { "Etc/Zulu" , 0x029FC3 }, + { "Europe/Amsterdam" , 0x02A007 }, + { "Europe/Andorra" , 0x02A445 }, + { "Europe/Athens" , 0x02A6C1 }, + { "Europe/Belfast" , 0x02AA04 }, + { "Europe/Belgrade" , 0x02AF3B }, + { "Europe/Berlin" , 0x02B204 }, + { "Europe/Bratislava" , 0x02B568 }, + { "Europe/Brussels" , 0x02B89A }, + { "Europe/Bucharest" , 0x02BCD1 }, + { "Europe/Budapest" , 0x02BFFB }, + { "Europe/Busingen" , 0x02C36E }, + { "Europe/Chisinau" , 0x02C625 }, + { "Europe/Copenhagen" , 0x02C9B3 }, + { "Europe/Dublin" , 0x02CCBD }, + { "Europe/Gibraltar" , 0x02D1CE }, + { "Europe/Guernsey" , 0x02D625 }, + { "Europe/Helsinki" , 0x02DB5C }, + { "Europe/Isle_of_Man" , 0x02DE12 }, + { "Europe/Istanbul" , 0x02E349 }, + { "Europe/Jersey" , 0x02E736 }, + { "Europe/Kaliningrad" , 0x02EC6D }, + { "Europe/Kiev" , 0x02EED3 }, + { "Europe/Lisbon" , 0x02F1EA }, + { "Europe/Ljubljana" , 0x02F6EE }, + { "Europe/London" , 0x02F9B7 }, + { "Europe/Luxembourg" , 0x02FEEE }, + { "Europe/Madrid" , 0x030344 }, + { "Europe/Malta" , 0x03070A }, + { "Europe/Mariehamn" , 0x030AC3 }, + { "Europe/Minsk" , 0x030D79 }, + { "Europe/Monaco" , 0x030F87 }, + { "Europe/Moscow" , 0x0313C2 }, + { "Europe/Nicosia" , 0x031613 }, + { "Europe/Oslo" , 0x0318FB }, + { "Europe/Paris" , 0x031C2D }, + { "Europe/Podgorica" , 0x032073 }, + { "Europe/Prague" , 0x03233C }, + { "Europe/Riga" , 0x03266E }, + { "Europe/Rome" , 0x0329B3 }, + { "Europe/Samara" , 0x032D76 }, + { "Europe/San_Marino" , 0x032FA9 }, + { "Europe/Sarajevo" , 0x03336C }, + { "Europe/Simferopol" , 0x033635 }, + { "Europe/Skopje" , 0x033960 }, + { "Europe/Sofia" , 0x033C29 }, + { "Europe/Stockholm" , 0x033F31 }, + { "Europe/Tallinn" , 0x0341E0 }, + { "Europe/Tirane" , 0x03451A }, + { "Europe/Tiraspol" , 0x034820 }, + { "Europe/Uzhgorod" , 0x034BAE }, + { "Europe/Vaduz" , 0x034EC5 }, + { "Europe/Vatican" , 0x035158 }, + { "Europe/Vienna" , 0x03551B }, + { "Europe/Vilnius" , 0x035848 }, + { "Europe/Volgograd" , 0x035B87 }, + { "Europe/Warsaw" , 0x035D87 }, + { "Europe/Zagreb" , 0x036168 }, + { "Europe/Zaporozhye" , 0x036431 }, + { "Europe/Zurich" , 0x036772 }, + { "Factory" , 0x036A21 }, + { "GB" , 0x036A92 }, + { "GB-Eire" , 0x036FC9 }, + { "GMT" , 0x037500 }, + { "GMT+0" , 0x0375CC }, + { "GMT-0" , 0x037588 }, + { "GMT0" , 0x037544 }, + { "Greenwich" , 0x037610 }, + { "Hongkong" , 0x037654 }, + { "HST" , 0x037816 }, + { "Iceland" , 0x03785A }, + { "Indian/Antananarivo" , 0x037A13 }, + { "Indian/Chagos" , 0x037A87 }, + { "Indian/Christmas" , 0x037AE9 }, + { "Indian/Cocos" , 0x037B2D }, + { "Indian/Comoro" , 0x037B71 }, + { "Indian/Kerguelen" , 0x037BC6 }, + { "Indian/Mahe" , 0x037C1B }, + { "Indian/Maldives" , 0x037C70 }, + { "Indian/Mauritius" , 0x037CC5 }, + { "Indian/Mayotte" , 0x037D3B }, + { "Indian/Reunion" , 0x037D90 }, + { "Iran" , 0x037DE5 }, + { "Israel" , 0x038053 }, + { "Jamaica" , 0x038382 }, + { "Japan" , 0x038447 }, + { "Kwajalein" , 0x0384D0 }, + { "Libya" , 0x038533 }, + { "MET" , 0x03872C }, + { "Mexico/BajaNorte" , 0x038A35 }, + { "Mexico/BajaSur" , 0x038D9E }, + { "Mexico/General" , 0x038FE3 }, + { "MST" , 0x039241 }, + { "MST7MDT" , 0x039285 }, + { "Navajo" , 0x0395D6 }, + { "NZ" , 0x03994F }, + { "NZ-CHAT" , 0x039CCD }, + { "Pacific/Apia" , 0x039FB5 }, + { "Pacific/Auckland" , 0x03A151 }, + { "Pacific/Chatham" , 0x03A4DD }, + { "Pacific/Chuuk" , 0x03A7D4 }, + { "Pacific/Easter" , 0x03A82D }, + { "Pacific/Efate" , 0x03AB8B }, + { "Pacific/Enderbury" , 0x03AC51 }, + { "Pacific/Fakaofo" , 0x03ACBF }, + { "Pacific/Fiji" , 0x03AD10 }, + { "Pacific/Funafuti" , 0x03AEA3 }, + { "Pacific/Galapagos" , 0x03AEE7 }, + { "Pacific/Gambier" , 0x03AF5F }, + { "Pacific/Guadalcanal" , 0x03AFC4 }, + { "Pacific/Guam" , 0x03B019 }, + { "Pacific/Honolulu" , 0x03B06F }, + { "Pacific/Johnston" , 0x03B0E6 }, + { "Pacific/Kiritimati" , 0x03B138 }, + { "Pacific/Kosrae" , 0x03B1A3 }, + { "Pacific/Kwajalein" , 0x03B200 }, + { "Pacific/Majuro" , 0x03B26C }, + { "Pacific/Marquesas" , 0x03B2CB }, + { "Pacific/Midway" , 0x03B332 }, + { "Pacific/Nauru" , 0x03B3BC }, + { "Pacific/Niue" , 0x03B434 }, + { "Pacific/Norfolk" , 0x03B492 }, + { "Pacific/Noumea" , 0x03B4E7 }, + { "Pacific/Pago_Pago" , 0x03B577 }, + { "Pacific/Palau" , 0x03B600 }, + { "Pacific/Pitcairn" , 0x03B644 }, + { "Pacific/Pohnpei" , 0x03B699 }, + { "Pacific/Ponape" , 0x03B6EE }, + { "Pacific/Port_Moresby" , 0x03B733 }, + { "Pacific/Rarotonga" , 0x03B777 }, + { "Pacific/Saipan" , 0x03B853 }, + { "Pacific/Samoa" , 0x03B8B6 }, + { "Pacific/Tahiti" , 0x03B93F }, + { "Pacific/Tarawa" , 0x03B9A4 }, + { "Pacific/Tongatapu" , 0x03B9F8 }, + { "Pacific/Truk" , 0x03BA84 }, + { "Pacific/Wake" , 0x03BAC9 }, + { "Pacific/Wallis" , 0x03BB19 }, + { "Pacific/Yap" , 0x03BB5D }, + { "Poland" , 0x03BBA2 }, + { "Portugal" , 0x03BF83 }, + { "PRC" , 0x03C47F }, + { "PST8PDT" , 0x03C530 }, + { "ROC" , 0x03C881 }, + { "ROK" , 0x03C999 }, + { "Singapore" , 0x03CA3D }, + { "Turkey" , 0x03CAF4 }, + { "UCT" , 0x03CEE1 }, + { "Universal" , 0x03CF25 }, + { "US/Alaska" , 0x03CF69 }, + { "US/Aleutian" , 0x03D2D2 }, + { "US/Arizona" , 0x03D638 }, + { "US/Central" , 0x03D6C6 }, + { "US/East-Indiana" , 0x03E0D0 }, + { "US/Eastern" , 0x03DBD1 }, + { "US/Hawaii" , 0x03E33A }, + { "US/Indiana-Starke" , 0x03E3AB }, + { "US/Michigan" , 0x03E71C }, + { "US/Mountain" , 0x03EA53 }, + { "US/Pacific" , 0x03EDCC }, + { "US/Pacific-New" , 0x03F1D1 }, + { "US/Samoa" , 0x03F5D6 }, + { "UTC" , 0x03F65F }, + { "W-SU" , 0x03F956 }, + { "WET" , 0x03F6A3 }, + { "Zulu" , 0x03FB90 }, }; /* This is a generated file, do not modify */ -const unsigned char timelib_timezone_db_data_builtin[260756] = { +const unsigned char timelib_timezone_db_data_builtin[261076] = { /* Africa/Abidjan */ @@ -758,7 +758,7 @@ const unsigned char timelib_timezone_db_data_builtin[260756] = { /* Africa/Casablanca */ 0x50, 0x48, 0x50, 0x31, 0x01, 0x4D, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x96, 0x51, 0xF9, 0x9C, +0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x96, 0x51, 0xF9, 0x9C, 0xC6, 0xFF, 0x14, 0x80, 0xC7, 0x58, 0xAC, 0x70, 0xC7, 0xD9, 0xED, 0x80, 0xD2, 0xA1, 0x32, 0xF0, 0xDB, 0x35, 0xA4, 0x00, 0xDB, 0xEE, 0x27, 0xF0, 0xFB, 0x25, 0x72, 0x40, 0xFB, 0xC2, 0xEF, 0x70, 0x08, 0x6B, 0x84, 0x80, 0x08, 0xC6, 0x6D, 0xF0, 0x0B, 0xE8, 0x0C, 0x00, 0x0C, 0x61, 0x47, 0xF0, @@ -766,28 +766,33 @@ const unsigned char timelib_timezone_db_data_builtin[260756] = { 0x1A, 0xB7, 0xA6, 0x00, 0x1E, 0x18, 0x6F, 0xF0, 0x48, 0x41, 0xE6, 0x80, 0x48, 0xBB, 0x22, 0x70, 0x4A, 0x23, 0x1A, 0x00, 0x4A, 0x8D, 0xD5, 0x70, 0x4B, 0xDC, 0xC0, 0x80, 0x4C, 0x5D, 0xE5, 0x70, 0x4D, 0x97, 0xB8, 0x80, 0x4E, 0x34, 0x8C, 0xF0, 0x4F, 0x9C, 0xA0, 0xA0, 0x50, 0x08, 0xBB, 0xA0, -0x50, 0x31, 0x9A, 0x20, 0x50, 0x67, 0xA7, 0xA0, 0x51, 0x7C, 0x82, 0xA0, 0x52, 0x47, 0x89, 0xA0, -0x53, 0x5C, 0x64, 0xA0, 0x54, 0x27, 0x6B, 0xA0, 0x55, 0x3C, 0x46, 0xA0, 0x56, 0x07, 0x4D, 0xA0, -0x57, 0x1C, 0x28, 0xA0, 0x57, 0xE7, 0x2F, 0xA0, 0x59, 0x05, 0x45, 0x20, 0x59, 0xC7, 0x11, 0xA0, -0x5A, 0xE5, 0x27, 0x20, 0x5B, 0xB0, 0x2E, 0x20, 0x5C, 0xC5, 0x09, 0x20, 0x5D, 0x90, 0x10, 0x20, -0x5E, 0xA4, 0xEB, 0x20, 0x5F, 0x6F, 0xF2, 0x20, 0x60, 0x84, 0xCD, 0x20, 0x61, 0x4F, 0xD4, 0x20, -0x62, 0x64, 0xAF, 0x20, 0x63, 0x2F, 0xB6, 0x20, 0x64, 0x4D, 0xCB, 0xA0, 0x65, 0x0F, 0x98, 0x20, -0x66, 0x2D, 0xAD, 0xA0, 0x66, 0xF8, 0xB4, 0xA0, 0x68, 0x0D, 0x8F, 0xA0, 0x68, 0xD8, 0x96, 0xA0, -0x69, 0xED, 0x71, 0xA0, 0x6A, 0xB8, 0x78, 0xA0, 0x6B, 0xCD, 0x53, 0xA0, 0x6C, 0x98, 0x5A, 0xA0, -0x6D, 0xB6, 0x70, 0x20, 0x6E, 0x78, 0x3C, 0xA0, 0x6F, 0x96, 0x52, 0x20, 0x70, 0x61, 0x59, 0x20, -0x71, 0x76, 0x34, 0x20, 0x72, 0x41, 0x3B, 0x20, 0x73, 0x56, 0x16, 0x20, 0x74, 0x21, 0x1D, 0x20, -0x75, 0x35, 0xF8, 0x20, 0x76, 0x00, 0xFF, 0x20, 0x77, 0x15, 0xDA, 0x20, 0x77, 0xE0, 0xE1, 0x20, -0x78, 0xFE, 0xF6, 0xA0, 0x79, 0xC0, 0xC3, 0x20, 0x7A, 0xDE, 0xD8, 0xA0, 0x7B, 0xA9, 0xDF, 0xA0, -0x7C, 0xBE, 0xBA, 0xA0, 0x7D, 0x89, 0xC1, 0xA0, 0x7E, 0x9E, 0x9C, 0xA0, 0x7F, 0x69, 0xA3, 0xA0, -0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, -0x02, 0x03, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, +0x50, 0x31, 0x9A, 0x20, 0x50, 0x67, 0xA7, 0xA0, 0x51, 0x7C, 0x82, 0xA0, 0x51, 0xDB, 0x6E, 0xA0, +0x52, 0x02, 0xFB, 0xA0, 0x52, 0x47, 0x89, 0xA0, 0x53, 0x5C, 0x64, 0xA0, 0x53, 0xAF, 0x73, 0x20, +0x53, 0xD7, 0x00, 0x20, 0x54, 0x27, 0x6B, 0xA0, 0x55, 0x3C, 0x46, 0xA0, 0x55, 0x82, 0x26, 0x20, +0x55, 0xA9, 0xB3, 0x20, 0x56, 0x07, 0x4D, 0xA0, 0x57, 0x1C, 0x28, 0xA0, 0x57, 0x56, 0x2A, 0xA0, +0x57, 0x7D, 0xB7, 0xA0, 0x57, 0xE7, 0x2F, 0xA0, 0x59, 0x05, 0x45, 0x20, 0x59, 0x28, 0xDD, 0xA0, +0x59, 0x50, 0x6A, 0xA0, 0x59, 0xC7, 0x11, 0xA0, 0x5A, 0xE5, 0x27, 0x20, 0x5A, 0xFB, 0x90, 0xA0, +0x5B, 0x23, 0x1D, 0xA0, 0x5B, 0xB0, 0x2E, 0x20, 0x5C, 0xC5, 0x09, 0x20, 0x5C, 0xCF, 0x95, 0x20, +0x5C, 0xF7, 0x22, 0x20, 0x5D, 0x90, 0x10, 0x20, 0x5E, 0xC9, 0xD5, 0x20, 0x5F, 0x6F, 0xF2, 0x20, +0x60, 0x9C, 0x88, 0x20, 0x61, 0x4F, 0xD4, 0x20, 0x62, 0x70, 0x8C, 0xA0, 0x63, 0x2F, 0xB6, 0x20, +0x64, 0x4D, 0xCB, 0xA0, 0x65, 0x0F, 0x98, 0x20, 0x66, 0x2D, 0xAD, 0xA0, 0x66, 0xF8, 0xB4, 0xA0, +0x68, 0x0D, 0x8F, 0xA0, 0x68, 0xD8, 0x96, 0xA0, 0x69, 0xED, 0x71, 0xA0, 0x6A, 0xB8, 0x78, 0xA0, +0x6B, 0xCD, 0x53, 0xA0, 0x6C, 0x98, 0x5A, 0xA0, 0x6D, 0xB6, 0x70, 0x20, 0x6E, 0x78, 0x3C, 0xA0, +0x6F, 0x96, 0x52, 0x20, 0x70, 0x61, 0x59, 0x20, 0x71, 0x76, 0x34, 0x20, 0x72, 0x41, 0x3B, 0x20, +0x73, 0x56, 0x16, 0x20, 0x74, 0x21, 0x1D, 0x20, 0x75, 0x35, 0xF8, 0x20, 0x76, 0x00, 0xFF, 0x20, +0x77, 0x15, 0xDA, 0x20, 0x77, 0xE0, 0xE1, 0x20, 0x78, 0xFE, 0xF6, 0xA0, 0x79, 0xC0, 0xC3, 0x20, +0x7A, 0xDE, 0xD8, 0xA0, 0x7B, 0xA9, 0xDF, 0xA0, 0x7C, 0xBE, 0xBA, 0xA0, 0x7D, 0x89, 0xC1, 0xA0, +0x7E, 0x9E, 0x9C, 0xA0, 0x7F, 0x69, 0xA3, 0xA0, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, +0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, -0x02, 0xFF, 0xFF, 0xF8, 0xE4, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x10, 0x01, 0x04, 0x00, 0x00, 0x00, -0x00, 0x00, 0x09, 0x00, 0x00, 0x0E, 0x10, 0x00, 0x0D, 0x4C, 0x4D, 0x54, 0x00, 0x57, 0x45, 0x53, -0x54, 0x00, 0x57, 0x45, 0x54, 0x00, 0x43, 0x45, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xBC, 0xAC, 0xC8, 0x01, 0x07, 0x16, 0x42, 0x00, 0x00, 0x00, 0x00, +0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, +0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0xFF, 0xFF, 0xF8, 0xE4, 0x00, 0x00, 0x00, 0x00, 0x0E, +0x10, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0E, 0x10, 0x00, 0x0D, 0x4C, +0x4D, 0x54, 0x00, 0x57, 0x45, 0x53, 0x54, 0x00, 0x57, 0x45, 0x54, 0x00, 0x43, 0x45, 0x54, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0xAC, 0xC8, 0x01, 0x07, 0x16, 0x42, +0x00, 0x00, 0x00, 0x00, /* Africa/Ceuta */ 0x50, 0x48, 0x50, 0x31, 0x01, 0x45, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -1863,7 +1868,7 @@ const unsigned char timelib_timezone_db_data_builtin[260756] = { 0x45, 0x31, 0xB2, 0x40, 0x45, 0xF3, 0x70, 0xB0, 0x47, 0x1A, 0xCE, 0xC0, 0x47, 0xD3, 0x52, 0xB0, 0x48, 0xFA, 0xB0, 0xC0, 0x49, 0xB3, 0x34, 0xB0, 0x4A, 0xDA, 0x92, 0xC0, 0x4B, 0xC1, 0x3B, 0x30, 0x4C, 0xA7, 0xFF, 0xC0, 0x4D, 0xA1, 0x1D, 0x30, 0x4E, 0x87, 0xE1, 0xC0, 0x4F, 0x80, 0xFF, 0x30, -0x50, 0x70, 0xFE, 0x40, 0x51, 0x6A, 0x1B, 0xB0, 0x52, 0x50, 0xE0, 0x40, 0x53, 0x49, 0xFD, 0xB0, +0x50, 0x70, 0xFE, 0x40, 0x51, 0x4E, 0x6C, 0x30, 0x52, 0x50, 0xE0, 0x40, 0x53, 0x49, 0xFD, 0xB0, 0x54, 0x30, 0xC2, 0x40, 0x55, 0x29, 0xDF, 0xB0, 0x56, 0x10, 0xA4, 0x40, 0x57, 0x09, 0xC1, 0xB0, 0x57, 0xF0, 0x86, 0x40, 0x58, 0xE9, 0xA3, 0xB0, 0x59, 0xD0, 0x68, 0x40, 0x5A, 0xC9, 0x85, 0xB0, 0x5B, 0xB9, 0x84, 0xC0, 0x5C, 0xB2, 0xA2, 0x30, 0x5D, 0x99, 0x66, 0xC0, 0x5E, 0x92, 0x84, 0x30, @@ -5743,7 +5748,7 @@ const unsigned char timelib_timezone_db_data_builtin[260756] = { /* America/Port-au-Prince */ 0x50, 0x48, 0x50, 0x31, 0x01, 0x48, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0D, 0x9C, 0x6E, 0x71, 0xFC, +0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0D, 0x9C, 0x6E, 0x71, 0xFC, 0x19, 0x1B, 0x46, 0xD0, 0x1A, 0x01, 0xEF, 0x40, 0x1A, 0xF1, 0xEE, 0x50, 0x1B, 0xE1, 0xD1, 0x40, 0x1C, 0xD1, 0xD0, 0x50, 0x1D, 0xC1, 0xB3, 0x40, 0x1E, 0xB1, 0xB2, 0x50, 0x1F, 0xA1, 0x95, 0x40, 0x20, 0x91, 0x94, 0x50, 0x21, 0x81, 0x77, 0x40, 0x22, 0x55, 0xD4, 0xE0, 0x23, 0x6A, 0xAF, 0xE0, @@ -5753,13 +5758,29 @@ const unsigned char timelib_timezone_db_data_builtin[260756] = { 0x2F, 0x7E, 0x3D, 0x60, 0x30, 0x93, 0x18, 0x60, 0x31, 0x67, 0x59, 0xE0, 0x32, 0x72, 0xFA, 0x60, 0x33, 0x47, 0x3B, 0xE0, 0x34, 0x52, 0xDC, 0x60, 0x42, 0x4F, 0x78, 0x50, 0x43, 0x64, 0x45, 0x40, 0x44, 0x2F, 0x5A, 0x50, 0x45, 0x44, 0x27, 0x40, 0x4F, 0x5C, 0x4D, 0x70, 0x50, 0x96, 0x04, 0x60, -0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, 0x03, 0x04, 0x03, -0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x01, -0x02, 0x01, 0x02, 0x01, 0x02, 0xFF, 0xFF, 0xBC, 0x44, 0x00, 0x00, 0xFF, 0xFF, 0xC7, 0xC0, 0x01, -0x05, 0xFF, 0xFF, 0xB9, 0xB0, 0x00, 0x09, 0xFF, 0xFF, 0xC7, 0xC0, 0x01, 0x05, 0xFF, 0xFF, 0xB9, -0xB0, 0x00, 0x09, 0x50, 0x50, 0x4D, 0x54, 0x00, 0x45, 0x44, 0x54, 0x00, 0x45, 0x53, 0x54, 0x00, -0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0x9B, 0xD5, 0x00, 0xA4, -0x49, 0x4A, 0x00, 0x00, 0x00, 0x00, +0x51, 0x3C, 0x2F, 0x70, 0x52, 0x75, 0xE6, 0x60, 0x53, 0x1C, 0x11, 0x70, 0x54, 0x55, 0xC8, 0x60, +0x54, 0xFB, 0xF3, 0x70, 0x56, 0x35, 0xAA, 0x60, 0x56, 0xE5, 0x0F, 0xF0, 0x58, 0x1E, 0xC6, 0xE0, +0x58, 0xC4, 0xF1, 0xF0, 0x59, 0xFE, 0xA8, 0xE0, 0x5A, 0xA4, 0xD3, 0xF0, 0x5B, 0xDE, 0x8A, 0xE0, +0x5C, 0x84, 0xB5, 0xF0, 0x5D, 0xBE, 0x6C, 0xE0, 0x5E, 0x64, 0x97, 0xF0, 0x5F, 0x9E, 0x4E, 0xE0, +0x60, 0x4D, 0xB4, 0x70, 0x61, 0x87, 0x6B, 0x60, 0x62, 0x2D, 0x96, 0x70, 0x63, 0x67, 0x4D, 0x60, +0x64, 0x0D, 0x78, 0x70, 0x65, 0x47, 0x2F, 0x60, 0x65, 0xED, 0x5A, 0x70, 0x67, 0x27, 0x11, 0x60, +0x67, 0xCD, 0x3C, 0x70, 0x69, 0x06, 0xF3, 0x60, 0x69, 0xAD, 0x1E, 0x70, 0x6A, 0xE6, 0xD5, 0x60, +0x6B, 0x96, 0x3A, 0xF0, 0x6C, 0xCF, 0xF1, 0xE0, 0x6D, 0x76, 0x1C, 0xF0, 0x6E, 0xAF, 0xD3, 0xE0, +0x6F, 0x55, 0xFE, 0xF0, 0x70, 0x8F, 0xB5, 0xE0, 0x71, 0x35, 0xE0, 0xF0, 0x72, 0x6F, 0x97, 0xE0, +0x73, 0x15, 0xC2, 0xF0, 0x74, 0x4F, 0x79, 0xE0, 0x74, 0xFE, 0xDF, 0x70, 0x76, 0x38, 0x96, 0x60, +0x76, 0xDE, 0xC1, 0x70, 0x78, 0x18, 0x78, 0x60, 0x78, 0xBE, 0xA3, 0x70, 0x79, 0xF8, 0x5A, 0x60, +0x7A, 0x9E, 0x85, 0x70, 0x7B, 0xD8, 0x3C, 0x60, 0x7C, 0x7E, 0x67, 0x70, 0x7D, 0xB8, 0x1E, 0x60, +0x7E, 0x5E, 0x49, 0x70, 0x7F, 0x98, 0x00, 0x60, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, +0x02, 0x01, 0x02, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, +0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, +0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, +0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, +0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0xFF, +0xFF, 0xBC, 0x44, 0x00, 0x00, 0xFF, 0xFF, 0xC7, 0xC0, 0x01, 0x05, 0xFF, 0xFF, 0xB9, 0xB0, 0x00, +0x09, 0xFF, 0xFF, 0xC7, 0xC0, 0x01, 0x05, 0xFF, 0xFF, 0xB9, 0xB0, 0x00, 0x09, 0x50, 0x50, 0x4D, +0x54, 0x00, 0x45, 0x44, 0x54, 0x00, 0x45, 0x53, 0x54, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0x9B, 0xD5, 0x00, 0xA4, 0x49, 0x4A, 0x00, 0x00, 0x00, 0x00, + /* America/Porto_Acre */ 0x50, 0x48, 0x50, 0x31, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -18361,4 +18382,4 @@ const unsigned char timelib_timezone_db_data_builtin[260756] = { 0x00, 0x00, 0x55, 0x54, 0x43, 0x00, 0x00, 0x00, 0x00, 0x89, 0x54, 0x40, 0x01, 0x12, 0xA8, 0x80, 0x00, 0x00, 0x00, 0x00, }; -const timelib_tzdb timezonedb_builtin = { "2013.1", 579, timezonedb_idx_builtin, timelib_timezone_db_data_builtin }; +const timelib_tzdb timezonedb_builtin = { "2013.2", 579, timezonedb_idx_builtin, timelib_timezone_db_data_builtin }; From bdaafe3c7b7f388e34078a0a9d7215c8d58acadb Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 12 Mar 2013 08:33:36 +0100 Subject: [PATCH 123/276] fixed headers order --- ext/enchant/enchant.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/enchant/enchant.c b/ext/enchant/enchant.c index 8aa8093a3e0..c36987fc33e 100644 --- a/ext/enchant/enchant.c +++ b/ext/enchant/enchant.c @@ -23,10 +23,10 @@ #include "config.h" #endif -#include #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" +#include #include "php_enchant.h" typedef EnchantBroker * EnchantBrokerPtr; From fcc6611de9054327441786e52444b5f8eecdd525 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 16 Feb 2013 19:13:36 +0100 Subject: [PATCH 124/276] Add support for non-scalar Iterator keys in foreach RFC: https://wiki.php.net/rfc/foreach-non-scalar-keys --- UPGRADING | 2 + UPGRADING.INTERNALS | 8 + .../generator_with_nonscalar_keys.phpt | 52 ++++++ Zend/zend.h | 1 - Zend/zend_API.c | 34 ++++ Zend/zend_API.h | 2 + Zend/zend_generators.c | 24 +-- Zend/zend_hash.c | 18 ++ Zend/zend_hash.h | 4 +- Zend/zend_interfaces.c | 38 +--- Zend/zend_interfaces.h | 2 +- Zend/zend_iterators.h | 7 +- Zend/zend_types.h | 1 + Zend/zend_vm_def.h | 70 +++---- Zend/zend_vm_execute.h | 70 +++---- ext/com_dotnet/com_iterator.c | 9 +- ext/com_dotnet/com_saproxy.c | 9 +- ext/date/php_date.c | 7 +- ext/dom/dom_iterators.c | 27 +-- .../breakiterator/breakiterator_iterators.cpp | 10 +- ext/intl/common/common_enum.cpp | 14 +- .../resourcebundle/resourcebundle_iterator.c | 13 +- ext/mysqli/mysqli_result_iterator.c | 5 +- ext/pdo/pdo_stmt.c | 9 +- ext/phar/phar_object.c | 50 ++--- ext/simplexml/simplexml.c | 27 +-- ext/soap/php_encoding.c | 19 +- ext/spl/spl_array.c | 21 +-- ext/spl/spl_directory.c | 20 +- ext/spl/spl_dllist.c | 5 +- ext/spl/spl_fixedarray.c | 8 +- ext/spl/spl_heap.c | 5 +- ext/spl/spl_iterators.c | 171 +++++------------- ext/spl/spl_iterators.h | 5 +- .../iterator_to_array_nonscalar_keys.phpt | 31 ++++ ext/spl/tests/multiple_iterator_001.phpt | 20 +- ext/standard/array.c | 62 +------ 37 files changed, 379 insertions(+), 501 deletions(-) create mode 100644 Zend/tests/generators/generator_with_nonscalar_keys.phpt create mode 100644 ext/spl/tests/iterator_to_array_nonscalar_keys.phpt diff --git a/UPGRADING b/UPGRADING index 76d6f4fb839..ca35a99cd89 100755 --- a/UPGRADING +++ b/UPGRADING @@ -81,6 +81,8 @@ PHP 5.5 UPGRADE NOTES a string constant. (https://wiki.php.net/rfc/class_name_scalars) - Support for changing the process's title in CLI/CLI-Server SAPIs. (Keyur) (https://wiki.php.net/rfc/cli_process_title) +- Added support for non-scalar Iterator keys in foreach. + (https://wiki.php.net/rfc/foreach-non-scalar-keys). ======================================== 2. Changes in SAPI modules diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 44cdfaee6c8..56243d1f81e 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -64,6 +64,14 @@ void zend_qsort_r(void *base, size_t nmemb, size_t siz, compare_r_func_t compare The extra argument it has (relatively to zend_qsort()) is passed to the comparison function. + d. get_current_key + +The signature of the get_current_key iteration handler has been changed to: + +void (*get_current_key)(zend_object_iterator *iter, zval *key TSRMLS_DC); + +The key should be written into the zval* using the ZVAL_* macros. + ======================== 2. Build system changes ======================== diff --git a/Zend/tests/generators/generator_with_nonscalar_keys.phpt b/Zend/tests/generators/generator_with_nonscalar_keys.phpt new file mode 100644 index 00000000000..5ae55a1be09 --- /dev/null +++ b/Zend/tests/generators/generator_with_nonscalar_keys.phpt @@ -0,0 +1,52 @@ +--TEST-- +Generators can return non-scalar keys +--FILE-- + [4, 5, 6]; + yield (object) ['a' => 'b'] => (object) ['b' => 'a']; + yield 3.14 => 2.73; + yield false => true; + yield true => false; + yield null => null; +} + +foreach (gen() as $k => $v) { + var_dump($k, $v); +} + +?> +--EXPECT-- +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) +} +object(stdClass)#3 (1) { + ["a"]=> + string(1) "b" +} +object(stdClass)#4 (1) { + ["b"]=> + string(1) "a" +} +float(3.14) +float(2.73) +bool(false) +bool(true) +bool(true) +bool(false) +NULL +NULL diff --git a/Zend/zend.h b/Zend/zend.h index e30c26b524d..36554637ef3 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -299,7 +299,6 @@ void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((nore /* * zval */ -typedef struct _zval_struct zval; typedef struct _zend_class_entry zend_class_entry; typedef struct _zend_guard { diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 95c90ea753c..2653d0849af 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1502,6 +1502,40 @@ ZEND_API int add_get_index_stringl(zval *arg, ulong index, const char *str, uint } /* }}} */ +ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */ +{ + int result; + + switch (Z_TYPE_P(key)) { + case IS_STRING: + result = zend_symtable_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof(zval *), NULL); + break; + case IS_NULL: + result = zend_symtable_update(ht, "", 1, &value, sizeof(zval *), NULL); + break; + case IS_RESOURCE: + zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(key), Z_LVAL_P(key)); + /* break missing intentionally */ + case IS_BOOL: + case IS_LONG: + result = zend_hash_index_update(ht, Z_LVAL_P(key), &value, sizeof(zval *), NULL); + break; + case IS_DOUBLE: + result = zend_hash_index_update(ht, zend_dval_to_lval(Z_LVAL_P(key)), &value, sizeof(zval *), NULL); + break; + default: + zend_error(E_WARNING, "Illegal offset type"); + result = FAILURE; + } + + if (result == SUCCESS) { + Z_ADDREF_P(value); + } + + return result; +} +/* }}} */ + ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long n TSRMLS_DC) /* {{{ */ { zval *tmp; diff --git a/Zend/zend_API.h b/Zend/zend_API.h index fb642c14755..c26141b1833 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -426,6 +426,8 @@ ZEND_API int add_get_index_double(zval *arg, ulong idx, double d, void **dest); ZEND_API int add_get_index_string(zval *arg, ulong idx, const char *str, void **dest, int duplicate); ZEND_API int add_get_index_stringl(zval *arg, ulong idx, const char *str, uint length, void **dest, int duplicate); +ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value); + ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long l TSRMLS_DC); ZEND_API int add_property_null_ex(zval *arg, const char *key, uint key_len TSRMLS_DC); ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, int b TSRMLS_DC); diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index c1dbee124f3..3f43552f1f0 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -755,31 +755,17 @@ static void zend_generator_iterator_get_data(zend_object_iterator *iterator, zva } /* }}} */ -static int zend_generator_iterator_get_key(zend_object_iterator *iterator, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */ +static void zend_generator_iterator_get_key(zend_object_iterator *iterator, zval *key TSRMLS_DC) /* {{{ */ { zend_generator *generator = (zend_generator *) iterator->data; zend_generator_ensure_initialized(generator TSRMLS_CC); - if (!generator->key) { - return HASH_KEY_NON_EXISTANT; + if (generator->key) { + ZVAL_ZVAL(key, generator->key, 1, 0); + } else { + ZVAL_NULL(key); } - - if (Z_TYPE_P(generator->key) == IS_LONG) { - *int_key = Z_LVAL_P(generator->key); - return HASH_KEY_IS_LONG; - } - - if (Z_TYPE_P(generator->key) == IS_STRING) { - *str_key = estrndup(Z_STRVAL_P(generator->key), Z_STRLEN_P(generator->key)); - *str_key_len = Z_STRLEN_P(generator->key) + 1; - return HASH_KEY_IS_STRING; - } - - /* Waiting for Etienne's patch to allow arbitrary zval keys. Until then - * error out on non-int and non-string keys. */ - zend_error_noreturn(E_ERROR, "Currently only int and string keys can be yielded"); - return HASH_KEY_NON_EXISTANT; /* Nerver reached */ } /* }}} */ diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 0609d707f53..bca47b330fd 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -1171,6 +1171,24 @@ ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, char **str_index, return HASH_KEY_NON_EXISTANT; } +ZEND_API void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos) { + Bucket *p; + + IS_CONSISTENT(ht); + + p = pos ? (*pos) : ht->pInternalPointer; + + if (!p) { + Z_TYPE_P(key) = IS_NULL; + } else if (p->nKeyLength) { + Z_TYPE_P(key) = IS_STRING; + Z_STRVAL_P(key) = IS_INTERNED(p->arKey) ? (char *) p->arKey : estrndup(p->arKey, p->nKeyLength - 1); + Z_STRLEN_P(key) = p->nKeyLength - 1; + } else { + Z_TYPE_P(key) = IS_LONG; + Z_LVAL_P(key) = p->h; + } +} ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos) { diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 88c3bfb421e..a0c147f3978 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -170,13 +170,13 @@ ZEND_API int zend_hash_quick_exists(const HashTable *ht, const char *arKey, uint ZEND_API int zend_hash_index_exists(const HashTable *ht, ulong h); ZEND_API ulong zend_hash_next_free_element(const HashTable *ht); - /* traversing */ #define zend_hash_has_more_elements_ex(ht, pos) \ (zend_hash_get_current_key_type_ex(ht, pos) == HASH_KEY_NON_EXISTANT ? FAILURE : SUCCESS) ZEND_API int zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos); ZEND_API int zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos); ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, char **str_index, uint *str_length, ulong *num_index, zend_bool duplicate, HashPosition *pos); +ZEND_API void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos); ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos); ZEND_API int zend_hash_get_current_data_ex(HashTable *ht, void **pData, HashPosition *pos); ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos); @@ -199,6 +199,8 @@ ZEND_API int zend_hash_set_pointer(HashTable *ht, const HashPointer *ptr); zend_hash_move_backwards_ex(ht, NULL) #define zend_hash_get_current_key(ht, str_index, num_index, duplicate) \ zend_hash_get_current_key_ex(ht, str_index, NULL, num_index, duplicate, NULL) +#define zend_hash_get_current_key_zval(ht, key) \ + zend_hash_get_current_key_zval_ex(ht, key, NULL) #define zend_hash_get_current_key_type(ht) \ zend_hash_get_current_key_type_ex(ht, NULL) #define zend_hash_get_current_data(ht, pData) \ diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index e2e81ed326a..16751549b46 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -195,7 +195,7 @@ static int zend_user_it_get_current_key_default(zend_object_iterator *_iter, cha /* }}} */ /* {{{ zend_user_it_get_current_key */ -ZEND_API int zend_user_it_get_current_key(zend_object_iterator *_iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) +ZEND_API void zend_user_it_get_current_key(zend_object_iterator *_iter, zval *key TSRMLS_DC) { zend_user_iterator *iter = (zend_user_iterator*)_iter; zval *object = (zval*)iter->it.data; @@ -203,42 +203,16 @@ ZEND_API int zend_user_it_get_current_key(zend_object_iterator *_iter, char **st zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_key, "key", &retval); - if (!retval) { - *int_key = 0; - if (!EG(exception)) - { + if (retval) { + ZVAL_ZVAL(key, retval, 1, 1); + } else { + if (!EG(exception)) { zend_error(E_WARNING, "Nothing returned from %s::key()", iter->ce->name); } - return HASH_KEY_IS_LONG; - } - switch (Z_TYPE_P(retval)) { - default: - zend_error(E_WARNING, "Illegal type returned from %s::key()", iter->ce->name); - case IS_NULL: - *int_key = 0; - zval_ptr_dtor(&retval); - return HASH_KEY_IS_LONG; - case IS_STRING: - *str_key = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval)); - *str_key_len = Z_STRLEN_P(retval)+1; - zval_ptr_dtor(&retval); - return HASH_KEY_IS_STRING; - - case IS_DOUBLE: - *int_key = (long)Z_DVAL_P(retval); - zval_ptr_dtor(&retval); - return HASH_KEY_IS_LONG; - - case IS_RESOURCE: - case IS_BOOL: - case IS_LONG: - *int_key = (long)Z_LVAL_P(retval); - zval_ptr_dtor(&retval); - return HASH_KEY_IS_LONG; + ZVAL_LONG(key, 0); } } -/* }}} */ /* {{{ zend_user_it_move_forward */ ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter TSRMLS_DC) diff --git a/Zend/zend_interfaces.h b/Zend/zend_interfaces.h index 23547951ed7..ba4bc6ccb6d 100644 --- a/Zend/zend_interfaces.h +++ b/Zend/zend_interfaces.h @@ -51,7 +51,7 @@ ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend ZEND_API void zend_user_it_rewind(zend_object_iterator *_iter TSRMLS_DC); ZEND_API int zend_user_it_valid(zend_object_iterator *_iter TSRMLS_DC); -ZEND_API int zend_user_it_get_current_key(zend_object_iterator *_iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC); +ZEND_API void zend_user_it_get_current_key(zend_object_iterator *_iter, zval *key TSRMLS_DC); ZEND_API void zend_user_it_get_current_data(zend_object_iterator *_iter, zval ***data TSRMLS_DC); ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter TSRMLS_DC); ZEND_API void zend_user_it_invalidate_current(zend_object_iterator *_iter TSRMLS_DC); diff --git a/Zend/zend_iterators.h b/Zend/zend_iterators.h index b484102b20a..f74068a2718 100644 --- a/Zend/zend_iterators.h +++ b/Zend/zend_iterators.h @@ -38,8 +38,11 @@ typedef struct _zend_object_iterator_funcs { /* fetch the item data for the current element */ void (*get_current_data)(zend_object_iterator *iter, zval ***data TSRMLS_DC); - /* fetch the key for the current element (return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG) (optional, may be NULL) */ - int (*get_current_key)(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC); + /* fetch the key for the current element (optional, may be NULL). The key + * should be written into the provided zval* using the ZVAL_* macros. If + * this handler is not provided auto-incrementing integer keys will be + * used. */ + void (*get_current_key)(zend_object_iterator *iter, zval *key TSRMLS_DC); /* step forwards to next element */ void (*move_forward)(zend_object_iterator *iter TSRMLS_DC); diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 3e68add3dc3..9cdf31fb343 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -52,6 +52,7 @@ typedef unsigned long zend_uintptr_t; typedef unsigned int zend_object_handle; typedef struct _zend_object_handlers zend_object_handlers; +typedef struct _zval_struct zval; typedef struct _zend_object_value { zend_object_handle handle; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 578a319fd19..b01574058c3 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4245,13 +4245,13 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) zend_free_op free_op1; zval *array = EX_T(opline->op1.var).fe.ptr; zval **value; - char *str_key; - uint str_key_len; - ulong int_key; HashTable *fe_ht; zend_object_iterator *iter = NULL; - int key_type = 0; - zend_bool use_key = (zend_bool)(opline->extended_value & ZEND_FE_FETCH_WITH_KEY); + + zval *key = NULL; + if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) { + key = &EX_T((opline+1)->result.var).tmp_var; + } SAVE_OPLINE(); @@ -4262,8 +4262,11 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); case ZEND_ITER_PLAIN_OBJECT: { - const char *class_name, *prop_name; zend_object *zobj = zend_objects_get_address(array TSRMLS_CC); + int key_type; + char *str_key; + zend_uint str_key_len; + zend_ulong int_key; fe_ht = Z_OBJPROP_P(array); zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos); @@ -4275,15 +4278,23 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL); zend_hash_move_forward(fe_ht); - } while (key_type == HASH_KEY_NON_EXISTANT || - (key_type != HASH_KEY_IS_LONG && - zend_check_property_access(zobj, str_key, str_key_len-1 TSRMLS_CC) != SUCCESS)); - zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos); - if (use_key && key_type != HASH_KEY_IS_LONG) { - zend_unmangle_property_name_ex(str_key, str_key_len-1, &class_name, &prop_name, &str_key_len); - str_key = estrndup(prop_name, str_key_len); - str_key_len++; + } while (key_type != HASH_KEY_IS_LONG && + zend_check_property_access(zobj, str_key, str_key_len - 1 TSRMLS_CC) != SUCCESS); + + if (key) { + if (key_type == HASH_KEY_IS_LONG) { + ZVAL_LONG(key, int_key); + } else { + const char *class_name, *prop_name; + int prop_name_len; + zend_unmangle_property_name_ex( + str_key, str_key_len - 1, &class_name, &prop_name, &prop_name_len + ); + ZVAL_STRINGL(key, prop_name, prop_name_len, 1); + } } + + zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos); break; } @@ -4294,8 +4305,8 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) /* reached end of iteration */ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); } - if (use_key) { - key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 1, NULL); + if (key) { + zend_hash_get_current_key_zval(fe_ht, key); } zend_hash_move_forward(fe_ht); zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos); @@ -4330,16 +4341,15 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) /* failure in get_current_data */ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); } - if (use_key) { + if (key) { if (iter->funcs->get_current_key) { - key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC); + iter->funcs->get_current_key(iter, key TSRMLS_CC); if (UNEXPECTED(EG(exception) != NULL)) { zval_ptr_dtor(&array); HANDLE_EXCEPTION(); } } else { - key_type = HASH_KEY_IS_LONG; - int_key = iter->index; + ZVAL_LONG(key, iter->index); } } break; @@ -4355,26 +4365,6 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) AI_SET_PTR(&EX_T(opline->result.var), *value); } - if (use_key) { - zval *key = &EX_T((opline+1)->result.var).tmp_var; - - switch (key_type) { - case HASH_KEY_IS_STRING: - Z_STRVAL_P(key) = (char*)str_key; - Z_STRLEN_P(key) = str_key_len-1; - Z_TYPE_P(key) = IS_STRING; - break; - case HASH_KEY_IS_LONG: - Z_LVAL_P(key) = int_key; - Z_TYPE_P(key) = IS_LONG; - break; - default: - case HASH_KEY_NON_EXISTANT: - ZVAL_NULL(key); - break; - } - } - CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 392569678df..426da693c58 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -13588,13 +13588,13 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG zval *array = EX_T(opline->op1.var).fe.ptr; zval **value; - char *str_key; - uint str_key_len; - ulong int_key; HashTable *fe_ht; zend_object_iterator *iter = NULL; - int key_type = 0; - zend_bool use_key = (zend_bool)(opline->extended_value & ZEND_FE_FETCH_WITH_KEY); + + zval *key = NULL; + if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) { + key = &EX_T((opline+1)->result.var).tmp_var; + } SAVE_OPLINE(); @@ -13605,8 +13605,11 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); case ZEND_ITER_PLAIN_OBJECT: { - const char *class_name, *prop_name; zend_object *zobj = zend_objects_get_address(array TSRMLS_CC); + int key_type; + char *str_key; + zend_uint str_key_len; + zend_ulong int_key; fe_ht = Z_OBJPROP_P(array); zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos); @@ -13618,15 +13621,23 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL); zend_hash_move_forward(fe_ht); - } while (key_type == HASH_KEY_NON_EXISTANT || - (key_type != HASH_KEY_IS_LONG && - zend_check_property_access(zobj, str_key, str_key_len-1 TSRMLS_CC) != SUCCESS)); - zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos); - if (use_key && key_type != HASH_KEY_IS_LONG) { - zend_unmangle_property_name_ex(str_key, str_key_len-1, &class_name, &prop_name, &str_key_len); - str_key = estrndup(prop_name, str_key_len); - str_key_len++; + } while (key_type != HASH_KEY_IS_LONG && + zend_check_property_access(zobj, str_key, str_key_len - 1 TSRMLS_CC) != SUCCESS); + + if (key) { + if (key_type == HASH_KEY_IS_LONG) { + ZVAL_LONG(key, int_key); + } else { + const char *class_name, *prop_name; + int prop_name_len; + zend_unmangle_property_name_ex( + str_key, str_key_len - 1, &class_name, &prop_name, &prop_name_len + ); + ZVAL_STRINGL(key, prop_name, prop_name_len, 1); + } } + + zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos); break; } @@ -13637,8 +13648,8 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG /* reached end of iteration */ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); } - if (use_key) { - key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 1, NULL); + if (key) { + zend_hash_get_current_key_zval(fe_ht, key); } zend_hash_move_forward(fe_ht); zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos); @@ -13673,16 +13684,15 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG /* failure in get_current_data */ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); } - if (use_key) { + if (key) { if (iter->funcs->get_current_key) { - key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC); + iter->funcs->get_current_key(iter, key TSRMLS_CC); if (UNEXPECTED(EG(exception) != NULL)) { zval_ptr_dtor(&array); HANDLE_EXCEPTION(); } } else { - key_type = HASH_KEY_IS_LONG; - int_key = iter->index; + ZVAL_LONG(key, iter->index); } } break; @@ -13698,26 +13708,6 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG AI_SET_PTR(&EX_T(opline->result.var), *value); } - if (use_key) { - zval *key = &EX_T((opline+1)->result.var).tmp_var; - - switch (key_type) { - case HASH_KEY_IS_STRING: - Z_STRVAL_P(key) = (char*)str_key; - Z_STRLEN_P(key) = str_key_len-1; - Z_TYPE_P(key) = IS_STRING; - break; - case HASH_KEY_IS_LONG: - Z_LVAL_P(key) = int_key; - Z_TYPE_P(key) = IS_LONG; - break; - default: - case HASH_KEY_NON_EXISTANT: - ZVAL_NULL(key); - break; - } - } - CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); diff --git a/ext/com_dotnet/com_iterator.c b/ext/com_dotnet/com_iterator.c index ce4bdd67c04..ecf395b161f 100644 --- a/ext/com_dotnet/com_iterator.c +++ b/ext/com_dotnet/com_iterator.c @@ -74,16 +74,15 @@ static void com_iter_get_data(zend_object_iterator *iter, zval ***data TSRMLS_DC *data = &I->zdata; } -static int com_iter_get_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, - ulong *int_key TSRMLS_DC) +static void com_iter_get_key(zend_object_iterator *iter, zval *key TSRMLS_DC) { struct php_com_iterator *I = (struct php_com_iterator*)iter->data; if (I->key == (ulong)-1) { - return HASH_KEY_NON_EXISTANT; + ZVAL_NULL(key); + } else { + ZVAL_LONG(key, I->key); } - *int_key = I->key; - return HASH_KEY_IS_LONG; } static int com_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC) diff --git a/ext/com_dotnet/com_saproxy.c b/ext/com_dotnet/com_saproxy.c index ad928497439..5450370cd9f 100644 --- a/ext/com_dotnet/com_saproxy.c +++ b/ext/com_dotnet/com_saproxy.c @@ -519,16 +519,15 @@ static void saproxy_iter_get_data(zend_object_iterator *iter, zval ***data TSRML *data = ptr_ptr; } -static int saproxy_iter_get_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, - ulong *int_key TSRMLS_DC) +static void saproxy_iter_get_key(zend_object_iterator *iter, zval *key TSRMLS_DC) { php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data; if (I->key == -1) { - return HASH_KEY_NON_EXISTANT; + ZVAL_NULL(key); + } else { + ZVAL_LONG(key, I->key); } - *int_key = (ulong)I->key; - return HASH_KEY_IS_LONG; } static int saproxy_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 71958578de9..f36ccc1ade0 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -1867,11 +1867,10 @@ static void date_period_it_current_data(zend_object_iterator *iter, zval ***data /* {{{ date_period_it_current_key */ -static int date_period_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) +static void date_period_it_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) { - date_period_it *iterator = (date_period_it *)iter; - *int_key = iterator->current_index; - return HASH_KEY_IS_LONG; + date_period_it *iterator = (date_period_it *)iter; + ZVAL_LONG(key, iterator->current_index); } /* }}} */ diff --git a/ext/dom/dom_iterators.c b/ext/dom/dom_iterators.c index f4183d2f9a4..6c8cf84e9fe 100644 --- a/ext/dom/dom_iterators.c +++ b/ext/dom/dom_iterators.c @@ -157,35 +157,22 @@ static void php_dom_iterator_current_data(zend_object_iterator *iter, zval ***da } /* }}} */ -static int php_dom_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */ +static void php_dom_iterator_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */ { - zval *curobj; - xmlNodePtr curnode = NULL; - dom_object *intern; - zval *object; - int namelen; - php_dom_iterator *iterator = (php_dom_iterator *)iter; - - object = (zval *)iterator->intern.data; + zval *object = (zval *)iterator->intern.data; if (instanceof_function(Z_OBJCE_P(object), dom_nodelist_class_entry TSRMLS_CC)) { - *int_key = iter->index; - return HASH_KEY_IS_LONG; + ZVAL_LONG(key, iter->index); } else { - curobj = iterator->curobj; + dom_object *intern = (dom_object *)zend_object_store_get_object(iterator->curobj TSRMLS_CC); - intern = (dom_object *)zend_object_store_get_object(curobj TSRMLS_CC); if (intern != NULL && intern->ptr != NULL) { - curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node; + xmlNodePtr curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node; + ZVAL_STRINGL(key, (char *) curnode->name, xmlStrlen(curnode->name), 1); } else { - return HASH_KEY_NON_EXISTANT; + ZVAL_NULL(key); } - - namelen = xmlStrlen(curnode->name); - *str_key = estrndup(curnode->name, namelen); - *str_key_len = namelen + 1; - return HASH_KEY_IS_STRING; } } /* }}} */ diff --git a/ext/intl/breakiterator/breakiterator_iterators.cpp b/ext/intl/breakiterator/breakiterator_iterators.cpp index d88ad8a712d..3748991aedb 100644 --- a/ext/intl/breakiterator/breakiterator_iterators.cpp +++ b/ext/intl/breakiterator/breakiterator_iterators.cpp @@ -139,14 +139,10 @@ static void _breakiterator_parts_destroy_it(zend_object_iterator *iter TSRMLS_DC zval_ptr_dtor(reinterpret_cast(&iter->data)); } -static int _breakiterator_parts_get_current_key(zend_object_iterator *iter, - char **str_key, - uint *str_key_len, - ulong *int_key TSRMLS_DC) +static void _breakiterator_parts_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) { /* the actual work is done in move_forward and rewind */ - *int_key = iter->index; - return HASH_KEY_IS_LONG; + ZVAL_LONG(key, iter->index); } static void _breakiterator_parts_move_forward(zend_object_iterator *iter TSRMLS_DC) @@ -343,4 +339,4 @@ U_CFUNC void breakiterator_register_IntlPartsIterator_class(TSRMLS_D) PARTSITER_DECL_LONG_CONST(KEY_RIGHT); #undef PARTSITER_DECL_LONG_CONST -} \ No newline at end of file +} diff --git a/ext/intl/common/common_enum.cpp b/ext/intl/common/common_enum.cpp index da47a437a67..3ba78558275 100644 --- a/ext/intl/common/common_enum.cpp +++ b/ext/intl/common/common_enum.cpp @@ -251,19 +251,7 @@ static PHP_METHOD(IntlIterator, key) INTLITERATOR_METHOD_FETCH_OBJECT; if (ii->iterator->funcs->get_current_key) { - char *str_key; - uint str_key_len; - ulong int_key; - - switch (ii->iterator->funcs->get_current_key( - ii->iterator, &str_key, &str_key_len, &int_key TSRMLS_CC)) { - case HASH_KEY_IS_LONG: - RETURN_LONG(int_key); - break; - case HASH_KEY_IS_STRING: - RETURN_STRINGL(str_key, str_key_len-1, 0); - break; - } + ii->iterator->funcs->get_current_key(ii->iterator, return_value TSRMLS_CC); } else { RETURN_LONG(ii->iterator->index); } diff --git a/ext/intl/resourcebundle/resourcebundle_iterator.c b/ext/intl/resourcebundle/resourcebundle_iterator.c index 16e1b928791..78236fda5db 100644 --- a/ext/intl/resourcebundle/resourcebundle_iterator.c +++ b/ext/intl/resourcebundle/resourcebundle_iterator.c @@ -101,21 +101,18 @@ static void resourcebundle_iterator_current( zend_object_iterator *iter, zval ** /* }}} */ /* {{{ resourcebundle_iterator_key */ -static int resourcebundle_iterator_key( zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC ) +static void resourcebundle_iterator_key( zend_object_iterator *iter, zval *key TSRMLS_DC ) { ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter; if (!iterator->current) { resourcebundle_iterator_read( iterator TSRMLS_CC); } + if (iterator->is_table) { - *str_key = estrdup( iterator->currentkey ); - *str_key_len = strlen( iterator->currentkey ) + 1; - return HASH_KEY_IS_STRING; - } - else { - *int_key = iterator->i; - return HASH_KEY_IS_LONG; + ZVAL_STRING(key, iterator->currentkey, 1); + } else { + ZVAL_LONG(key, iterator->i); } } /* }}} */ diff --git a/ext/mysqli/mysqli_result_iterator.c b/ext/mysqli/mysqli_result_iterator.c index 0f5ccdd63dd..3ea7bafe490 100644 --- a/ext/mysqli/mysqli_result_iterator.c +++ b/ext/mysqli/mysqli_result_iterator.c @@ -150,12 +150,11 @@ static void php_mysqli_result_iterator_rewind(zend_object_iterator *iter TSRMLS_ /* {{{ php_mysqli_result_iterator_current_key */ -static int php_mysqli_result_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) +static void php_mysqli_result_iterator_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) { php_mysqli_result_iterator *iterator = (php_mysqli_result_iterator*) iter; - *int_key = (ulong) iterator->row_num; - return HASH_KEY_IS_LONG; + ZVAL_LONG(key, iterator->row_num); } /* }}} */ diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 5dc445ff8de..1b0db91c380 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -2499,16 +2499,15 @@ static void pdo_stmt_iter_get_data(zend_object_iterator *iter, zval ***data TSRM *data = &I->fetch_ahead; } -static int pdo_stmt_iter_get_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, - ulong *int_key TSRMLS_DC) +static void pdo_stmt_iter_get_key(zend_object_iterator *iter, zval *key TSRMLS_DC) { struct php_pdo_iterator *I = (struct php_pdo_iterator*)iter->data; if (I->key == (ulong)-1) { - return HASH_KEY_NON_EXISTANT; + ZVAL_NULL(key); + } else { + ZVAL_LONG(key, I->key); } - *int_key = I->key; - return HASH_KEY_IS_LONG; } static void pdo_stmt_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC) diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index a6dd2c81460..94ffd3744be 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -1434,16 +1434,13 @@ struct _phar_t { static int phar_build(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ */ { zval **value; - zend_uchar key_type; zend_bool close_fp = 1; - ulong int_key; struct _phar_t *p_obj = (struct _phar_t*) puser; uint str_key_len, base_len = p_obj->l, fname_len; phar_entry_data *data; php_stream *fp; size_t contents_len; char *fname, *error = NULL, *base = p_obj->b, *opened, *save = NULL, *temp = NULL; - phar_zstr key; char *str_key; zend_class_entry *ce = p_obj->c; phar_archive_object *phar_obj = p_obj->p; @@ -1478,35 +1475,24 @@ static int phar_build(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ } if (iter->funcs->get_current_key) { - key_type = iter->funcs->get_current_key(iter, &key, &str_key_len, &int_key TSRMLS_CC); + zval key; + iter->funcs->get_current_key(iter, &key TSRMLS_CC); if (EG(exception)) { return ZEND_HASH_APPLY_STOP; } - if (key_type == HASH_KEY_IS_LONG) { + if (Z_TYPE(key) != IS_STRING) { + zval_dtor(&key); zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name); return ZEND_HASH_APPLY_STOP; } - if (key_type > 9) { /* IS_UNICODE == 10 */ -#if PHP_VERSION_ID < 60000 -/* this can never happen, but fixes a compile warning */ - spprintf(&str_key, 0, "%s", key); -#else - spprintf(&str_key, 0, "%v", key); - ezfree(key); -#endif - } else { - PHAR_STR(key, str_key); - } + str_key_len = Z_STRLEN(key); + str_key = estrndup(Z_STRVAL(key), str_key_len); save = str_key; - - if (str_key[str_key_len - 1] == '\0') { - str_key_len--; - } - + zval_dtor(&key); } else { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name); return ZEND_HASH_APPLY_STOP; @@ -1641,32 +1627,24 @@ phar_spl_fileinfo: } } else { if (iter->funcs->get_current_key) { - key_type = iter->funcs->get_current_key(iter, &key, &str_key_len, &int_key TSRMLS_CC); + zval key; + iter->funcs->get_current_key(iter, &key TSRMLS_CC); if (EG(exception)) { return ZEND_HASH_APPLY_STOP; } - if (key_type == HASH_KEY_IS_LONG) { + if (Z_TYPE(key) != IS_STRING) { + zval_dtor(&key); zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name); return ZEND_HASH_APPLY_STOP; } - if (key_type > 9) { /* IS_UNICODE == 10 */ -#if PHP_VERSION_ID < 60000 -/* this can never happen, but fixes a compile warning */ - spprintf(&str_key, 0, "%s", key); -#else - spprintf(&str_key, 0, "%v", key); - ezfree(key); -#endif - } else { - PHAR_STR(key, str_key); - } + str_key_len = Z_STRLEN(key); + str_key = estrndup(Z_STRVAL(key), str_key_len); save = str_key; - - if (str_key[str_key_len - 1] == '\0') str_key_len--; + zval_dtor(&key); } else { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name); return ZEND_HASH_APPLY_STOP; diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index baae3842c26..e7c2f298447 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -59,7 +59,7 @@ static zval *sxe_get_value(zval *z TSRMLS_DC); static void php_sxe_iterator_dtor(zend_object_iterator *iter TSRMLS_DC); static int php_sxe_iterator_valid(zend_object_iterator *iter TSRMLS_DC); static void php_sxe_iterator_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC); -static int php_sxe_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC); +static void php_sxe_iterator_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC); static void php_sxe_iterator_move_forward(zend_object_iterator *iter TSRMLS_DC); static void php_sxe_iterator_rewind(zend_object_iterator *iter TSRMLS_DC); @@ -2376,29 +2376,22 @@ static void php_sxe_iterator_current_data(zend_object_iterator *iter, zval ***da } /* }}} */ -static int php_sxe_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */ +static void php_sxe_iterator_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */ { - zval *curobj; - xmlNodePtr curnode = NULL; - php_sxe_object *intern; - int namelen; - php_sxe_iterator *iterator = (php_sxe_iterator *)iter; - curobj = iterator->sxe->iter.data; + zval *curobj = iterator->sxe->iter.data; + php_sxe_object *intern = (php_sxe_object *)zend_object_store_get_object(curobj TSRMLS_CC); - intern = (php_sxe_object *)zend_object_store_get_object(curobj TSRMLS_CC); + xmlNodePtr curnode = NULL; if (intern != NULL && intern->node != NULL) { curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->node)->node; } - if (!curnode) { - return HASH_KEY_NON_EXISTANT; + + if (curnode) { + ZVAL_STRINGL(key, (char *) curnode->name, xmlStrlen(curnode->name), 1); + } else { + ZVAL_NULL(key); } - - namelen = xmlStrlen(curnode->name); - *str_key = estrndup((char *)curnode->name, namelen); - *str_key_len = namelen + 1; - return HASH_KEY_IS_STRING; - } /* }}} */ diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 897956d91b7..5cec3e558eb 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -2313,10 +2313,6 @@ static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNod zend_object_iterator *iter; zend_class_entry *ce = Z_OBJCE_P(data); zval **val; - char *str_key; - uint str_key_len; - ulong int_key; - int key_type; ALLOC_ZVAL(array_copy); INIT_PZVAL(array_copy); @@ -2345,19 +2341,14 @@ static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNod goto iterator_done; } if (iter->funcs->get_current_key) { - key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC); + zval key; + iter->funcs->get_current_key(iter, &key TSRMLS_CC); if (EG(exception)) { goto iterator_done; } - switch(key_type) { - case HASH_KEY_IS_STRING: - add_assoc_zval_ex(array_copy, str_key, str_key_len, *val); - efree(str_key); - break; - case HASH_KEY_IS_LONG: - add_index_zval(array_copy, int_key, *val); - break; - } + array_set_zval_key(Z_ARRVAL_P(array_copy), &key, *val); + zval_ptr_dtor(val); + zval_dtor(&key); } else { add_next_index_zval(array_copy, *val); } diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index e56a8f09e2a..a00d23a7b24 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -1018,20 +1018,20 @@ static void spl_array_it_get_current_data(zend_object_iterator *iter, zval ***da } /* }}} */ -static int spl_array_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */ +static void spl_array_it_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */ { spl_array_it *iterator = (spl_array_it *)iter; spl_array_object *object = iterator->object; HashTable *aht = spl_array_get_hash_table(object, 0 TSRMLS_CC); if (object->ar_flags & SPL_ARRAY_OVERLOADED_KEY) { - return zend_user_it_get_current_key(iter, str_key, str_key_len, int_key TSRMLS_CC); + zend_user_it_get_current_key(iter, key TSRMLS_CC); } else { if (spl_array_object_verify_pos_ex(object, aht, "ArrayIterator::current(): " TSRMLS_CC) == FAILURE) { - return HASH_KEY_NON_EXISTANT; + ZVAL_NULL(key); + } else { + zend_hash_get_current_key_zval_ex(aht, key, &object->pos); } - - return zend_hash_get_current_key_ex(aht, str_key, str_key_len, int_key, 1, &object->pos); } } /* }}} */ @@ -1556,16 +1556,7 @@ void spl_array_iterator_key(zval *object, zval *return_value TSRMLS_DC) /* {{{ * return; } - switch (zend_hash_get_current_key_ex(aht, &string_key, &string_length, &num_key, 1, &intern->pos)) { - case HASH_KEY_IS_STRING: - RETVAL_STRINGL(string_key, string_length - 1, 0); - break; - case HASH_KEY_IS_LONG: - RETVAL_LONG(num_key); - break; - case HASH_KEY_NON_EXISTANT: - return; - } + zend_hash_get_current_key_zval_ex(aht, return_value, &intern->pos); } /* }}} */ diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index f43a3709e13..cf653f6899b 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -1621,7 +1621,7 @@ SPL_METHOD(GlobIterator, count) static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter TSRMLS_DC); static int spl_filesystem_dir_it_valid(zend_object_iterator *iter TSRMLS_DC); static void spl_filesystem_dir_it_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC); -static int spl_filesystem_dir_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC); +static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC); static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter TSRMLS_DC); static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter TSRMLS_DC); @@ -1698,12 +1698,11 @@ static void spl_filesystem_dir_it_current_data(zend_object_iterator *iter, zval /* }}} */ /* {{{ spl_filesystem_dir_it_current_key */ -static int spl_filesystem_dir_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) +static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) { spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter); - - *int_key = object->u.dir.index; - return HASH_KEY_IS_LONG; + + ZVAL_LONG(key, object->u.dir.index); } /* }}} */ @@ -1777,19 +1776,16 @@ static void spl_filesystem_tree_it_current_data(zend_object_iterator *iter, zval /* }}} */ /* {{{ spl_filesystem_tree_it_current_key */ -static int spl_filesystem_tree_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) +static void spl_filesystem_tree_it_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) { spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter); - + if (SPL_FILE_DIR_KEY(object, SPL_FILE_DIR_KEY_AS_FILENAME)) { - *str_key_len = strlen(object->u.dir.entry.d_name) + 1; - *str_key = estrndup(object->u.dir.entry.d_name, *str_key_len - 1); + ZVAL_STRING(key, object->u.dir.entry.d_name, 1); } else { spl_filesystem_object_get_file_name(object TSRMLS_CC); - *str_key_len = object->file_name_len + 1; - *str_key = estrndup(object->file_name, object->file_name_len); + ZVAL_STRINGL(key, object->file_name, object->file_name_len, 1); } - return HASH_KEY_IS_STRING; } /* }}} */ diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index a8417feada3..d8081efb26e 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -1023,12 +1023,11 @@ static void spl_dllist_it_get_current_data(zend_object_iterator *iter, zval ***d } /* }}} */ -static int spl_dllist_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */ +static void spl_dllist_it_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */ { spl_dllist_it *iterator = (spl_dllist_it *)iter; - *int_key = (ulong) iterator->traverse_position; - return HASH_KEY_IS_LONG; + ZVAL_LONG(key, iterator->traverse_position); } /* }}} */ diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index fec7e2c4aca..86a5371ed30 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -948,18 +948,16 @@ static void spl_fixedarray_it_get_current_data(zend_object_iterator *iter, zval } /* }}} */ -static int spl_fixedarray_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */ +static void spl_fixedarray_it_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */ { spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter; spl_fixedarray_object *intern = iterator->object; if (intern->flags & SPL_FIXEDARRAY_OVERLOADED_KEY) { - return zend_user_it_get_current_key(iter, str_key, str_key_len, int_key TSRMLS_CC); + zend_user_it_get_current_key(iter, key TSRMLS_CC); } else { - *int_key = (ulong) iterator->object->current; - return HASH_KEY_IS_LONG; + ZVAL_LONG(key, iterator->object->current); } - } /* }}} */ diff --git a/ext/spl/spl_heap.c b/ext/spl/spl_heap.c index d2de85b2a78..cb1f68dcf11 100644 --- a/ext/spl/spl_heap.c +++ b/ext/spl/spl_heap.c @@ -949,12 +949,11 @@ static void spl_pqueue_it_get_current_data(zend_object_iterator *iter, zval ***d } /* }}} */ -static int spl_heap_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */ +static void spl_heap_it_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */ { spl_heap_it *iterator = (spl_heap_it *)iter; - *int_key = (ulong) iterator->object->heap->count - 1; - return HASH_KEY_IS_LONG; + ZVAL_LONG(key, iterator->object->heap->count - 1); } /* }}} */ diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 87b3763cfd7..fcb4d20a639 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -190,16 +190,15 @@ static void spl_recursive_it_get_current_data(zend_object_iterator *iter, zval * sub_iter->funcs->get_current_data(sub_iter, data TSRMLS_CC); } -static int spl_recursive_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) +static void spl_recursive_it_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) { spl_recursive_it_object *object = (spl_recursive_it_object*)iter->data; zend_object_iterator *sub_iter = object->iterators[object->level].iterator; if (sub_iter->funcs->get_current_key) { - return sub_iter->funcs->get_current_key(sub_iter, str_key, str_key_len, int_key TSRMLS_CC); + sub_iter->funcs->get_current_key(sub_iter, key TSRMLS_CC); } else { - *int_key = iter->index; - return HASH_KEY_IS_LONG; + ZVAL_LONG(key, iter->index); } } @@ -617,20 +616,7 @@ SPL_METHOD(RecursiveIteratorIterator, key) } if (iterator->funcs->get_current_key) { - char *str_key; - uint str_key_len; - ulong int_key; - - switch (iterator->funcs->get_current_key(iterator, &str_key, &str_key_len, &int_key TSRMLS_CC)) { - case HASH_KEY_IS_LONG: - RETURN_LONG(int_key); - break; - case HASH_KEY_IS_STRING: - RETURN_STRINGL(str_key, str_key_len-1, 0); - break; - default: - RETURN_NULL(); - } + iterator->funcs->get_current_key(iterator, return_value TSRMLS_CC); } else { RETURN_NULL(); } @@ -1171,20 +1157,7 @@ SPL_METHOD(RecursiveTreeIterator, key) } if (iterator->funcs->get_current_key) { - char *str_key; - uint str_key_len; - ulong int_key; - - switch (iterator->funcs->get_current_key(iterator, &str_key, &str_key_len, &int_key TSRMLS_CC)) { - case HASH_KEY_IS_LONG: - ZVAL_LONG(&key, int_key); - break; - case HASH_KEY_IS_STRING: - ZVAL_STRINGL(&key, str_key, str_key_len-1, 0); - break; - default: - ZVAL_NULL(&key); - } + iterator->funcs->get_current_key(iterator, &key TSRMLS_CC); } else { ZVAL_NULL(&key); } @@ -1590,9 +1563,9 @@ static inline void spl_dual_it_free(spl_dual_it_object *intern TSRMLS_DC) zval_ptr_dtor(&intern->current.data); intern->current.data = NULL; } - if (intern->current.str_key) { - efree(intern->current.str_key); - intern->current.str_key = NULL; + if (intern->current.key) { + zval_ptr_dtor(&intern->current.key); + intern->current.key = NULL; } if (intern->dit_type == DIT_CachingIterator || intern->dit_type == DIT_RecursiveCachingIterator) { if (intern->u.caching.zstr) { @@ -1635,11 +1608,16 @@ static inline int spl_dual_it_fetch(spl_dual_it_object *intern, int check_more T intern->current.data = *data; Z_ADDREF_P(intern->current.data); } + + MAKE_STD_ZVAL(intern->current.key); if (intern->inner.iterator->funcs->get_current_key) { - intern->current.key_type = intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, &intern->current.str_key, &intern->current.str_key_len, &intern->current.int_key TSRMLS_CC); + intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, intern->current.key TSRMLS_CC); + if (EG(exception)) { + zval_ptr_dtor(&intern->current.key); + intern->current.key = NULL; + } } else { - intern->current.key_type = HASH_KEY_IS_LONG; - intern->current.int_key = intern->current.pos; + ZVAL_LONG(intern->current.key, intern->current.pos); } return EG(exception) ? FAILURE : SUCCESS; } @@ -1711,12 +1689,8 @@ SPL_METHOD(dual_it, key) SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - if (intern->current.data) { - if (intern->current.key_type == HASH_KEY_IS_STRING) { - RETURN_STRINGL(intern->current.str_key, intern->current.str_key_len-1, 1); - } else { - RETURN_LONG(intern->current.int_key); - } + if (intern->current.key) { + RETURN_ZVAL(intern->current.key, 1, 0); } RETURN_NULL(); } /* }}} */ @@ -1927,27 +1901,18 @@ SPL_METHOD(CallbackFilterIterator, accept) zend_fcall_info *fci = &intern->u.cbfilter->fci; zend_fcall_info_cache *fcc = &intern->u.cbfilter->fcc; zval **params[3]; - zval zkey; - zval *zkey_p = &zkey; zval *result; if (zend_parse_parameters_none() == FAILURE) { return; } - if (intern->current.data == NULL) { + if (intern->current.data == NULL || intern->current.key == NULL) { RETURN_FALSE; } - - INIT_PZVAL(&zkey); - if (intern->current.key_type == HASH_KEY_IS_LONG) { - ZVAL_LONG(&zkey, intern->current.int_key); - } else { - ZVAL_STRINGL(&zkey, intern->current.str_key, intern->current.str_key_len-1, 0); - } params[0] = &intern->current.data; - params[1] = &zkey_p; + params[1] = &intern->current.key; params[2] = &intern->inner.zobject; fci->retval_ptr_ptr = &result; @@ -1971,9 +1936,9 @@ SPL_METHOD(CallbackFilterIterator, accept) SPL_METHOD(RegexIterator, accept) { spl_dual_it_object *intern; - char *subject, tmp[32], *result; + char *subject, *result; int subject_len, use_copy, count = 0, result_len; - zval subject_copy, zcount, *replacement, tmp_replacement; + zval *subject_ptr, subject_copy, zcount, *replacement, tmp_replacement; if (zend_parse_parameters_none() == FAILURE) { return; @@ -1986,24 +1951,18 @@ SPL_METHOD(RegexIterator, accept) } if (intern->u.regex.flags & REGIT_USE_KEY) { - if (intern->current.key_type == HASH_KEY_IS_LONG) { - subject_len = slprintf(tmp, sizeof(tmp), "%ld", intern->current.int_key); - subject = &tmp[0]; - use_copy = 0; - } else { - subject_len = intern->current.str_key_len - 1; - subject = estrndup(intern->current.str_key, subject_len); - use_copy = 1; - } + subject_ptr = intern->current.key; } else { - zend_make_printable_zval(intern->current.data, &subject_copy, &use_copy); - if (use_copy) { - subject = Z_STRVAL(subject_copy); - subject_len = Z_STRLEN(subject_copy); - } else { - subject = Z_STRVAL_P(intern->current.data); - subject_len = Z_STRLEN_P(intern->current.data); - } + subject_ptr = intern->current.data; + } + + zend_make_printable_zval(subject_ptr, &subject_copy, &use_copy); + if (use_copy) { + subject = Z_STRVAL(subject_copy); + subject_len = Z_STRLEN(subject_copy); + } else { + subject = Z_STRVAL_P(subject_ptr); + subject_len = Z_STRLEN_P(subject_ptr); } switch (intern->u.regex.mode) @@ -2051,12 +2010,9 @@ SPL_METHOD(RegexIterator, accept) result = php_pcre_replace_impl(intern->u.regex.pce, subject, subject_len, replacement, 0, &result_len, -1, &count TSRMLS_CC); if (intern->u.regex.flags & REGIT_USE_KEY) { - if (intern->current.key_type != HASH_KEY_IS_LONG) { - efree(intern->current.str_key); - } - intern->current.key_type = HASH_KEY_IS_STRING; - intern->current.str_key = result; - intern->current.str_key_len = result_len + 1; + zval_ptr_dtor(&intern->current.key); + MAKE_STD_ZVAL(intern->current.key); + ZVAL_STRINGL(intern->current.key, result, result_len, 0); } else { zval_ptr_dtor(&intern->current.data); MAKE_STD_ZVAL(intern->current.data); @@ -2590,14 +2546,14 @@ static inline void spl_caching_it_next(spl_dual_it_object *intern TSRMLS_DC) /* Full cache ? */ if (intern->u.caching.flags & CIT_FULL_CACHE) { zval *zcacheval; + zval *key = intern->current.key; MAKE_STD_ZVAL(zcacheval); ZVAL_ZVAL(zcacheval, intern->current.data, 1, 0); - if (intern->current.key_type == HASH_KEY_IS_LONG) { - add_index_zval(intern->u.caching.zcache, intern->current.int_key, zcacheval); - } else { - zend_symtable_update(HASH_OF(intern->u.caching.zcache), intern->current.str_key, intern->current.str_key_len, &zcacheval, sizeof(void*), NULL); - } + + array_set_zval_key(HASH_OF(intern->u.caching.zcache), key, zcacheval); + + zval_ptr_dtor(&zcacheval); } /* Recursion ? */ if (intern->dit_type == DIT_RecursiveCachingIterator) { @@ -2755,13 +2711,9 @@ SPL_METHOD(CachingIterator, __toString) return; } if (intern->u.caching.flags & CIT_TOSTRING_USE_KEY) { - if (intern->current.key_type == HASH_KEY_IS_STRING) { - RETURN_STRINGL(intern->current.str_key, intern->current.str_key_len-1, 1); - } else { - RETVAL_LONG(intern->current.int_key); - convert_to_string(return_value); - return; - } + MAKE_COPY_ZVAL(&intern->current.key, return_value); + convert_to_string(return_value); + return; } else if (intern->u.caching.flags & CIT_TOSTRING_USE_CURRENT) { MAKE_COPY_ZVAL(&intern->current.data, return_value); convert_to_string(return_value); @@ -3123,19 +3075,7 @@ SPL_METHOD(NoRewindIterator, key) SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); if (intern->inner.iterator->funcs->get_current_key) { - char *str_key; - uint str_key_len; - ulong int_key; - switch (intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, &str_key, &str_key_len, &int_key TSRMLS_CC)) { - case HASH_KEY_IS_LONG: - RETURN_LONG(int_key); - break; - case HASH_KEY_IS_STRING: - RETURN_STRINGL(str_key, str_key_len-1, 0); - break; - default: - RETURN_NULL(); - } + intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, return_value TSRMLS_CC); } else { RETURN_NULL(); } @@ -3502,11 +3442,7 @@ done: static int spl_iterator_to_array_apply(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ */ { - zval **data, *return_value = (zval*)puser; - char *str_key; - uint str_key_len; - ulong int_key; - int key_type; + zval **data, *return_value = (zval*)puser; iter->funcs->get_current_data(iter, &data TSRMLS_CC); if (EG(exception)) { @@ -3516,20 +3452,13 @@ static int spl_iterator_to_array_apply(zend_object_iterator *iter, void *puser T return ZEND_HASH_APPLY_STOP; } if (iter->funcs->get_current_key) { - key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC); + zval key; + iter->funcs->get_current_key(iter, &key TSRMLS_CC); if (EG(exception)) { return ZEND_HASH_APPLY_STOP; } - Z_ADDREF_PP(data); - switch(key_type) { - case HASH_KEY_IS_STRING: - add_assoc_zval_ex(return_value, str_key, str_key_len, *data); - efree(str_key); - break; - case HASH_KEY_IS_LONG: - add_index_zval(return_value, int_key, *data); - break; - } + array_set_zval_key(Z_ARRVAL_P(return_value), &key, *data); + zval_dtor(&key); } else { Z_ADDREF_PP(data); add_next_index_zval(return_value, *data); diff --git a/ext/spl/spl_iterators.h b/ext/spl/spl_iterators.h index 39cc0d1337d..73d9d2e6147 100644 --- a/ext/spl/spl_iterators.h +++ b/ext/spl/spl_iterators.h @@ -133,10 +133,7 @@ typedef struct _spl_dual_it_object { } inner; struct { zval *data; - char *str_key; - uint str_key_len; - ulong int_key; - int key_type; /* HASH_KEY_IS_STRING or HASH_KEY_IS_LONG */ + zval *key; int pos; } current; dual_it_type dit_type; diff --git a/ext/spl/tests/iterator_to_array_nonscalar_keys.phpt b/ext/spl/tests/iterator_to_array_nonscalar_keys.phpt new file mode 100644 index 00000000000..a4cbcc3298f --- /dev/null +++ b/ext/spl/tests/iterator_to_array_nonscalar_keys.phpt @@ -0,0 +1,31 @@ +--TEST-- +Tests iterator_to_array() with non-scalar keys +--FILE-- + 0; + yield 1 => 1; + yield 2.5 => 2; + yield null => 3; + yield [] => 4; + yield new stdClass => 5; +} + +var_dump(iterator_to_array(gen())); + +?> +--EXPECTF-- +Warning: Illegal offset type in %s on line %d + +Warning: Illegal offset type in %s on line %d +array(4) { + ["foo"]=> + int(0) + [1]=> + int(1) + [0]=> + int(2) + [""]=> + int(3) +} diff --git a/ext/spl/tests/multiple_iterator_001.phpt b/ext/spl/tests/multiple_iterator_001.phpt index edd03f50408..eb77f79371b 100644 --- a/ext/spl/tests/multiple_iterator_001.phpt +++ b/ext/spl/tests/multiple_iterator_001.phpt @@ -23,8 +23,8 @@ echo "-- Default flags, MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_K var_dump($m->getFlags() === (MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_NUMERIC)); -foreach($m as $value) { - var_dump($m->key(), $value); +foreach($m as $key => $value) { + var_dump($key, $value); } try { $m->current(); @@ -42,8 +42,8 @@ echo "-- Flags = MultipleIterator::MIT_NEED_ANY | MultipleIterator::MIT_KEYS_NUM $m->setFlags(MultipleIterator::MIT_NEED_ANY | MultipleIterator::MIT_KEYS_NUMERIC); var_dump($m->getFlags() === (MultipleIterator::MIT_NEED_ANY | MultipleIterator::MIT_KEYS_NUMERIC)); -foreach($m as $value) { - var_dump($m->key(), $value); +foreach($m as $key => $value) { + var_dump($key, $value); } echo "-- Default flags, added element --\n"; @@ -51,8 +51,8 @@ echo "-- Default flags, added element --\n"; $m->setFlags(MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_NUMERIC); $iter2[] = 3; -foreach($m as $value) { - var_dump($m->key(), $value); +foreach($m as $key => $value) { + var_dump($key, $value); } echo "-- Flags |= MultipleIterator::MIT_KEYS_ASSOC, with iterator associated with NULL --\n"; @@ -71,8 +71,8 @@ $m->attachIterator($iter1, "iter1"); $m->attachIterator($iter2, b"iter2"); $m->attachIterator($iter3, 3); -foreach($m as $value) { - var_dump($m->key(), $value); +foreach($m as $key => $value) { + var_dump($key, $value); } echo "-- Associate with invalid value --\n"; @@ -98,8 +98,8 @@ var_dump($m->containsIterator($iter2)); var_dump($m->detachIterator($iter2)); var_dump($m->countIterators()); var_dump($m->containsIterator($iter2)); -foreach($m as $value) { - var_dump($m->key(), $value); +foreach($m as $key => $value) { + var_dump($key, $value); } ?> diff --git a/ext/standard/array.c b/ext/standard/array.c index 40a27c05362..3188953c8e1 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -935,16 +935,7 @@ PHP_FUNCTION(key) return; } - switch (zend_hash_get_current_key_ex(array, &string_key, &string_length, &num_key, 0, NULL)) { - case HASH_KEY_IS_STRING: - RETVAL_STRINGL(string_key, string_length - 1, 1); - break; - case HASH_KEY_IS_LONG: - RETVAL_LONG(num_key); - break; - case HASH_KEY_NON_EXISTANT: - return; - } + zend_hash_get_current_key_zval(array, return_value); } /* }}} */ @@ -1055,9 +1046,6 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive zval **args[3], /* Arguments to userland function */ *retval_ptr, /* Return value - unused */ *key=NULL; /* Entry key */ - char *string_key; - uint string_key_len; - ulong num_key; /* Set up known arguments */ args[1] = &key; @@ -1103,17 +1091,7 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive } else { /* Allocate space for key */ MAKE_STD_ZVAL(key); - - /* Set up the key */ - switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_key_len, &num_key, 0, NULL)) { - case HASH_KEY_IS_LONG: - Z_TYPE_P(key) = IS_LONG; - Z_LVAL_P(key) = num_key; - break; - case HASH_KEY_IS_STRING: - ZVAL_STRINGL(key, string_key, string_key_len - 1, 1); - break; - } + zend_hash_get_current_key_zval(target_hash, key); /* Call the userland function */ if (zend_call_function(&BG(array_walk_fci), &BG(array_walk_fci_cache) TSRMLS_CC) == SUCCESS) { @@ -1225,15 +1203,8 @@ static void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) /* {{{ if (behavior == 0) { RETURN_TRUE; } else { - /* Return current key */ - switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &str_key_len, &num_key, 0, &pos)) { - case HASH_KEY_IS_STRING: - RETURN_STRINGL(string_key, str_key_len - 1, 1); - break; - case HASH_KEY_IS_LONG: - RETURN_LONG(num_key); - break; - } + zend_hash_get_current_key_zval_ex(Z_ARRVAL_P(array), return_value, &pos); + return; } } zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos); @@ -2480,19 +2451,8 @@ PHP_FUNCTION(array_keys) if (add_key) { MAKE_STD_ZVAL(new_val); - - switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &string_key, &string_key_len, &num_key, 1, &pos)) { - case HASH_KEY_IS_STRING: - ZVAL_STRINGL(new_val, string_key, string_key_len - 1, 0); - zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, sizeof(zval *), NULL); - break; - - case HASH_KEY_IS_LONG: - Z_TYPE_P(new_val) = IS_LONG; - Z_LVAL_P(new_val) = num_key; - zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, sizeof(zval *), NULL); - break; - } + zend_hash_get_current_key_zval_ex(Z_ARRVAL_P(input), new_val, &pos); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, sizeof(zval *), NULL); } zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos); @@ -2705,15 +2665,7 @@ PHP_FUNCTION(array_flip) zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos); while (zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&entry, &pos) == SUCCESS) { MAKE_STD_ZVAL(data); - switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &str_key_len, &num_key, 1, &pos)) { - case HASH_KEY_IS_STRING: - ZVAL_STRINGL(data, string_key, str_key_len - 1, 0); - break; - case HASH_KEY_IS_LONG: - Z_TYPE_P(data) = IS_LONG; - Z_LVAL_P(data) = num_key; - break; - } + zend_hash_get_current_key_zval_ex(Z_ARRVAL_P(array), data, &pos); if (Z_TYPE_PP(entry) == IS_LONG) { zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_PP(entry), &data, sizeof(data), NULL); From 28634bf603d312bf066eab0a95700ae187d8d347 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 12 Mar 2013 17:39:20 +0100 Subject: [PATCH 125/276] Forgot to remove some now unused variables --- ext/spl/spl_array.c | 3 --- ext/standard/array.c | 12 ------------ 2 files changed, 15 deletions(-) diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index a00d23a7b24..edeade37556 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -1547,9 +1547,6 @@ SPL_METHOD(Array, key) void spl_array_iterator_key(zval *object, zval *return_value TSRMLS_DC) /* {{{ */ { spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - char *string_key; - uint string_length; - ulong num_key; HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); if (spl_array_object_verify_pos(intern, aht TSRMLS_CC) == FAILURE) { diff --git a/ext/standard/array.c b/ext/standard/array.c index 3188953c8e1..54077cd734b 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -927,9 +927,6 @@ PHP_FUNCTION(current) PHP_FUNCTION(key) { HashTable *array; - char *string_key; - uint string_length; - ulong num_key; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &array) == FAILURE) { return; @@ -1183,9 +1180,6 @@ static void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) /* {{{ res; /* comparison result */ HashPosition pos; /* hash iterator */ zend_bool strict = 0; /* strict comparison or not */ - ulong num_key; - uint str_key_len; - char *string_key; int (*is_equal_func)(zval *, zval *, zval * TSRMLS_DC) = is_equal_function; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za|b", &value, &array, &strict) == FAILURE) { @@ -2418,9 +2412,6 @@ PHP_FUNCTION(array_keys) res, /* Result of comparison */ *new_val; /* New value */ int add_key; /* Flag to indicate whether a key should be added */ - char *string_key; /* String key */ - uint string_key_len; - ulong num_key; /* Numeric key */ zend_bool strict = 0; /* do strict comparison */ HashPosition pos; int (*is_equal_func)(zval *, zval *, zval * TSRMLS_DC) = is_equal_function; @@ -2651,9 +2642,6 @@ PHP_FUNCTION(array_pad) PHP_FUNCTION(array_flip) { zval *array, **entry, *data; - char *string_key; - uint str_key_len; - ulong num_key; HashPosition pos; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { From f1e2edff8befb7863723adbe5680ce3d9714d9ed Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Wed, 13 Mar 2013 13:37:51 +0100 Subject: [PATCH 126/276] fix for bug #63530 mysqlnd_stmt::bind_one_parameter uses wrong alloc for stmt->param_bind --- NEWS | 4 ++++ ext/mysqlnd/mysqlnd_ps.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 82afa3a040e..fb877c01853 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,10 @@ PHP NEWS - PCRE: . Merged PCRE 8.32). (Anatol) +- mysqlnd + . Fixed bug #63530 (mysqlnd_stmt::bind_one_parameter crashes, uses wrong alloc + for stmt->param_bind). (Andrey) + 28 Feb 2013, PHP 5.3.23RC1 diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c index c553aa55a78..00205907a99 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -1485,7 +1485,7 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_parameter)(MYSQLND_STMT * const s, unsigne if (stmt->param_count) { if (!stmt->param_bind) { - stmt->param_bind = mnd_ecalloc(stmt->param_count, sizeof(MYSQLND_PARAM_BIND)); + stmt->param_bind = mnd_pecalloc(stmt->param_count, sizeof(MYSQLND_PARAM_BIND), stmt->persistent); if (!stmt->param_bind) { DBG_RETURN(FAIL); } From d77c865aff794826f6286c078268db6a005fea33 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 13 Mar 2013 17:51:10 +0400 Subject: [PATCH 127/276] Removed redundand code --- Zend/zend_vm_def.h | 26 +++-------- Zend/zend_vm_execute.h | 104 ++++++++++------------------------------- 2 files changed, 30 insertions(+), 100 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 578a319fd19..b7445c96620 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2839,17 +2839,17 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY) if (OP1_TYPE == IS_TMP_VAR) { FREE_OP1(); } - } else if (!IS_OP1_TMP_FREE()) { /* Not a temp var */ - if (*EG(return_value_ptr_ptr)) { - zval_ptr_dtor(EG(return_value_ptr_ptr)); - } + } else { if (OP1_TYPE == IS_CONST || - (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) { + OP1_TYPE == IS_TMP_VAR || + PZVAL_IS_REF(retval_ptr)) { zval *ret; ALLOC_ZVAL(ret); INIT_PZVAL_COPY(ret, retval_ptr); - zval_copy_ctor(ret); + if (OP1_TYPE != IS_TMP_VAR) { + zval_copy_ctor(ret); + } *EG(return_value_ptr_ptr) = ret; } else if ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) && retval_ptr == &EG(uninitialized_zval)) { @@ -2861,16 +2861,6 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY) *EG(return_value_ptr_ptr) = retval_ptr; Z_ADDREF_P(retval_ptr); } - } else { - zval *ret; - - if (*EG(return_value_ptr_ptr)) { - zval_ptr_dtor(EG(return_value_ptr_ptr)); - } - - ALLOC_ZVAL(ret); - INIT_PZVAL_COPY(ret, retval_ptr); - *EG(return_value_ptr_ptr) = ret; } FREE_OP1_IF_VAR(); ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); @@ -2886,10 +2876,6 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY) SAVE_OPLINE(); do { - if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) { - zval_ptr_dtor(EG(return_value_ptr_ptr)); - } - if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 392569678df..ddbc39d68db 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2333,17 +2333,17 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG if (IS_CONST == IS_TMP_VAR) { } - } else if (!0) { /* Not a temp var */ - if (*EG(return_value_ptr_ptr)) { - zval_ptr_dtor(EG(return_value_ptr_ptr)); - } + } else { if (IS_CONST == IS_CONST || - (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) { + IS_CONST == IS_TMP_VAR || + PZVAL_IS_REF(retval_ptr)) { zval *ret; ALLOC_ZVAL(ret); INIT_PZVAL_COPY(ret, retval_ptr); - zval_copy_ctor(ret); + if (IS_CONST != IS_TMP_VAR) { + zval_copy_ctor(ret); + } *EG(return_value_ptr_ptr) = ret; } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && retval_ptr == &EG(uninitialized_zval)) { @@ -2355,16 +2355,6 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG *EG(return_value_ptr_ptr) = retval_ptr; Z_ADDREF_P(retval_ptr); } - } else { - zval *ret; - - if (*EG(return_value_ptr_ptr)) { - zval_ptr_dtor(EG(return_value_ptr_ptr)); - } - - ALLOC_ZVAL(ret); - INIT_PZVAL_COPY(ret, retval_ptr); - *EG(return_value_ptr_ptr) = ret; } return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -2380,10 +2370,6 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); do { - if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) { - zval_ptr_dtor(EG(return_value_ptr_ptr)); - } - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); @@ -7654,17 +7640,17 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (IS_TMP_VAR == IS_TMP_VAR) { zval_dtor(free_op1.var); } - } else if (!1) { /* Not a temp var */ - if (*EG(return_value_ptr_ptr)) { - zval_ptr_dtor(EG(return_value_ptr_ptr)); - } + } else { if (IS_TMP_VAR == IS_CONST || - (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) { + IS_TMP_VAR == IS_TMP_VAR || + PZVAL_IS_REF(retval_ptr)) { zval *ret; ALLOC_ZVAL(ret); INIT_PZVAL_COPY(ret, retval_ptr); - zval_copy_ctor(ret); + if (IS_TMP_VAR != IS_TMP_VAR) { + zval_copy_ctor(ret); + } *EG(return_value_ptr_ptr) = ret; } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && retval_ptr == &EG(uninitialized_zval)) { @@ -7676,16 +7662,6 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) *EG(return_value_ptr_ptr) = retval_ptr; Z_ADDREF_P(retval_ptr); } - } else { - zval *ret; - - if (*EG(return_value_ptr_ptr)) { - zval_ptr_dtor(EG(return_value_ptr_ptr)); - } - - ALLOC_ZVAL(ret); - INIT_PZVAL_COPY(ret, retval_ptr); - *EG(return_value_ptr_ptr) = ret; } return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -7701,10 +7677,6 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); do { - if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) { - zval_ptr_dtor(EG(return_value_ptr_ptr)); - } - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); @@ -12888,17 +12860,17 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (IS_VAR == IS_TMP_VAR) { if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; } - } else if (!0) { /* Not a temp var */ - if (*EG(return_value_ptr_ptr)) { - zval_ptr_dtor(EG(return_value_ptr_ptr)); - } + } else { if (IS_VAR == IS_CONST || - (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) { + IS_VAR == IS_TMP_VAR || + PZVAL_IS_REF(retval_ptr)) { zval *ret; ALLOC_ZVAL(ret); INIT_PZVAL_COPY(ret, retval_ptr); - zval_copy_ctor(ret); + if (IS_VAR != IS_TMP_VAR) { + zval_copy_ctor(ret); + } *EG(return_value_ptr_ptr) = ret; } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && retval_ptr == &EG(uninitialized_zval)) { @@ -12910,16 +12882,6 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) *EG(return_value_ptr_ptr) = retval_ptr; Z_ADDREF_P(retval_ptr); } - } else { - zval *ret; - - if (*EG(return_value_ptr_ptr)) { - zval_ptr_dtor(EG(return_value_ptr_ptr)); - } - - ALLOC_ZVAL(ret); - INIT_PZVAL_COPY(ret, retval_ptr); - *EG(return_value_ptr_ptr) = ret; } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -12935,10 +12897,6 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); do { - if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) { - zval_ptr_dtor(EG(return_value_ptr_ptr)); - } - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); @@ -30534,17 +30492,17 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (IS_CV == IS_TMP_VAR) { } - } else if (!0) { /* Not a temp var */ - if (*EG(return_value_ptr_ptr)) { - zval_ptr_dtor(EG(return_value_ptr_ptr)); - } + } else { if (IS_CV == IS_CONST || - (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) { + IS_CV == IS_TMP_VAR || + PZVAL_IS_REF(retval_ptr)) { zval *ret; ALLOC_ZVAL(ret); INIT_PZVAL_COPY(ret, retval_ptr); - zval_copy_ctor(ret); + if (IS_CV != IS_TMP_VAR) { + zval_copy_ctor(ret); + } *EG(return_value_ptr_ptr) = ret; } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && retval_ptr == &EG(uninitialized_zval)) { @@ -30556,16 +30514,6 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) *EG(return_value_ptr_ptr) = retval_ptr; Z_ADDREF_P(retval_ptr); } - } else { - zval *ret; - - if (*EG(return_value_ptr_ptr)) { - zval_ptr_dtor(EG(return_value_ptr_ptr)); - } - - ALLOC_ZVAL(ret); - INIT_PZVAL_COPY(ret, retval_ptr); - *EG(return_value_ptr_ptr) = ret; } return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -30581,10 +30529,6 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); do { - if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) { - zval_ptr_dtor(EG(return_value_ptr_ptr)); - } - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); From c09652c2899dd4149fe3187b5b50f6b3c54da384 Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Wed, 13 Mar 2013 15:56:44 +0100 Subject: [PATCH 128/276] fix the fix --- ext/mysqlnd/mysqlnd_ps.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c index 2a0c9dd5945..15b293825b4 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -1463,8 +1463,7 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_parameter)(MYSQLND_STMT * const s, unsigne if (stmt->param_count) { if (!stmt->param_bind) { -// stmt->param_bind = mnd_pecalloc(stmt->param_count, sizeof(MYSQLND_PARAM_BIND), stmt->persistent); - stmt->param_bind = mnd_ecalloc(stmt->param_count, sizeof(MYSQLND_PARAM_BIND)); + stmt->param_bind = mnd_pecalloc(stmt->param_count, sizeof(MYSQLND_PARAM_BIND), stmt->persistent); if (!stmt->param_bind) { DBG_RETURN(FAIL); } From e43c5a83957c6a9953a74b5403a5f1d5ae341770 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Thu, 14 Mar 2013 14:38:20 +0100 Subject: [PATCH 129/276] fix zts check --- ext/pcre/php_pcre.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index cab3a4c8ddd..fe72dbc9c9e 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -250,7 +250,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le pcre_cache_entry new_entry; #if HAVE_SETLOCALE -# ifdef PHP_WIN32 && ZTS +# if defined(PHP_WIN32) && defined(ZTS) _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); # endif locale = setlocale(LC_CTYPE, NULL); From 61ac64b372bdd09144a7c276bb7094478ec3132f Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 14 Mar 2013 23:11:10 +0400 Subject: [PATCH 130/276] Allow only shared O+ build --- ZendAccelerator.h | 2 ++ config.m4 | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ZendAccelerator.h b/ZendAccelerator.h index 87736ec839c..be2218cdb8d 100644 --- a/ZendAccelerator.h +++ b/ZendAccelerator.h @@ -67,6 +67,8 @@ #ifndef ZEND_EXT_API # if WIN32|WINNT # define ZEND_EXT_API __declspec(dllexport) +# elif defined(__GNUC__) && __GNUC__ >= 4 +# define ZEND_EXT_API __attribute__ ((visibility("default"))) # else # define ZEND_EXT_API # endif diff --git a/config.m4 b/config.m4 index 19c8e9464c5..a15d651308b 100644 --- a/config.m4 +++ b/config.m4 @@ -341,7 +341,7 @@ int main() { shared_alloc_mmap.c \ shared_alloc_posix.c \ Optimizer/zend_optimizer.c, - $ext_shared,,,,yes) + shared,,,,yes) PHP_ADD_BUILD_DIR([$ext_builddir/Optimizer], 1) fi From 0ab356c8e59018fbedd0fd6ddfd6a82f4558c9a9 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 15 Mar 2013 10:45:49 +0400 Subject: [PATCH 131/276] Autogolobal $GLOBALS has to be pinged even if auto_globals_jit=0 --- ZendAccelerator.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index e6029cf4543..bb571a48056 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -1154,11 +1154,10 @@ static int zend_accel_get_auto_globals(TSRMLS_D) { int i, ag_size = (sizeof(jit_auto_globals_info) / sizeof(jit_auto_globals_info[0])); int n = 1; - zval **res; int mask = 0; for (i = 0; i < ag_size ; i++) { - if (zend_hash_find(&EG(symbol_table), jit_auto_globals_info[i].name, jit_auto_globals_info[i].len, (void *)&res) == SUCCESS) { + if (zend_hash_exists(&EG(symbol_table), jit_auto_globals_info[i].name, jit_auto_globals_info[i].len)) { mask |= n; } n += n; @@ -1166,6 +1165,16 @@ static int zend_accel_get_auto_globals(TSRMLS_D) return mask; } +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO +static int zend_accel_get_auto_globals_no_jit(TSRMLS_D) +{ + if (zend_hash_exists(&EG(symbol_table), jit_auto_globals_info[3].name, jit_auto_globals_info[3].len)) { + return 8; + } + return 0; +} +#endif + static void zend_accel_set_auto_globals(int mask TSRMLS_DC) { int i, ag_size = (sizeof(jit_auto_globals_info) / sizeof(jit_auto_globals_info[0])); @@ -1318,11 +1327,15 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han will have to ping the used auto global variables before execution */ #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO if (PG(auto_globals_jit)) { + new_persistent_script->ping_auto_globals_mask = zend_accel_get_auto_globals(TSRMLS_C); + } else { + new_persistent_script->ping_auto_globals_mask = zend_accel_get_auto_globals_no_jit(TSRMLS_C); + } #else if ((PG(auto_globals_jit) && !PG(register_globals) && !PG(register_long_arrays))) { -#endif new_persistent_script->ping_auto_globals_mask = zend_accel_get_auto_globals(TSRMLS_C); - } + } +#endif if (ZCG(accel_directives).validate_timestamps) { /* Obtain the file timestamps, *before* actually compiling them, From be020633f245f61183f1e2190a6476f790ccd1c2 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 15 Mar 2013 11:49:33 +0400 Subject: [PATCH 132/276] More accurate restart scheduling --- ZendAccelerator.c | 17 ++++++----------- zend_accelerator_module.c | 3 ++- zend_shared_alloc.c | 38 +++++++++++++++++++++----------------- zend_shared_alloc.h | 1 - 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/ZendAccelerator.c b/ZendAccelerator.c index bb571a48056..87b60f1e01a 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -71,8 +71,6 @@ typedef int gid_t; #include #include -#define MIN_FREE_MEMORY 64*1024 - #define SHM_PROTECT() \ do { \ if (ZCG(accel_directives).protect_memory) { \ @@ -853,6 +851,7 @@ static inline int do_validate_timestamps(zend_persistent_script *persistent_scri static void zend_accel_schedule_restart_if_necessary(TSRMLS_D) { if ((((double) ZSMMG(wasted_shared_memory)) / ZCG(accel_directives).memory_consumption) >= ZCG(accel_directives).max_wasted_percentage) { + ZSMMG(memory_exhausted) = 1; zend_accel_schedule_restart(TSRMLS_C); } } @@ -1031,14 +1030,12 @@ static void zend_accel_add_key(char *key, unsigned int key_length, zend_accel_ha if (zend_accel_hash_is_full(&ZCSG(hash))) { zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!"); ZSMMG(memory_exhausted) = 1; + zend_accel_schedule_restart(TSRMLS_C); } else { char *new_key = zend_shared_alloc(key_length + 1); if (new_key) { memcpy(new_key, key, key_length + 1); zend_accel_hash_update(&ZCSG(hash), new_key, key_length + 1, 1, bucket); - } else { - zend_accel_error(ACCEL_LOG_DEBUG, "No more memory!"); - ZSMMG(memory_exhausted) = 1; } } } @@ -1060,7 +1057,7 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr if (zend_accel_hash_is_full(&ZCSG(hash))) { zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!"); ZSMMG(memory_exhausted) = 1; - zend_accel_schedule_restart_if_necessary(TSRMLS_C); + zend_accel_schedule_restart(TSRMLS_C); zend_shared_alloc_unlock(TSRMLS_C); return new_persistent_script; } @@ -1088,11 +1085,6 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr /* Allocate shared memory */ ZCG(mem) = zend_shared_alloc(memory_used); if (!ZCG(mem)) { - zend_accel_error(ACCEL_LOG_DEBUG, "No more memory!"); - zend_accel_schedule_restart_if_necessary(TSRMLS_C); - if (zend_shared_alloc_get_largest_free_block() < MIN_FREE_MEMORY) { - ZSMMG(memory_exhausted) = 1; - } zend_shared_alloc_unlock(TSRMLS_C); return new_persistent_script; } @@ -1126,6 +1118,7 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr if (!zend_accel_hash_update(&ZCSG(hash), key, key_length + 1, 1, bucket)) { zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!"); ZSMMG(memory_exhausted) = 1; + zend_accel_schedule_restart(TSRMLS_C); } } @@ -1469,6 +1462,7 @@ static zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int persistent_script->corrupted = 1; persistent_script->timestamp = 0; ZSMMG(wasted_shared_memory) += persistent_script->dynamic_members.memory_consumption; + zend_accel_schedule_restart_if_necessary(TSRMLS_C); } zend_shared_alloc_unlock(TSRMLS_C); persistent_script = NULL; @@ -1489,6 +1483,7 @@ static zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int persistent_script->corrupted = 1; persistent_script->timestamp = 0; ZSMMG(wasted_shared_memory) += persistent_script->dynamic_members.memory_consumption; + zend_accel_schedule_restart_if_necessary(TSRMLS_C); } zend_shared_alloc_unlock(TSRMLS_C); persistent_script = NULL; diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index 701820f228e..c7c3b6058f2 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -496,7 +496,8 @@ static ZEND_FUNCTION(accelerator_get_status) MAKE_STD_ZVAL(statistics); array_init(statistics); add_assoc_long(statistics, "num_cached_scripts", ZCSG(hash).num_direct_entries); - add_assoc_long(statistics, "max_cached_scripts", ZCSG(hash).max_num_entries); + add_assoc_long(statistics, "num_cached_keys", ZCSG(hash).num_entries); + add_assoc_long(statistics, "max_cached_keys", ZCSG(hash).max_num_entries); add_assoc_long(statistics, "hits", ZCSG(hits)); add_assoc_long(statistics, "last_restart_time", ZCSG(last_restart_time)); add_assoc_long(statistics, "misses", ZSMMG(memory_exhausted)?ZCSG(misses):ZCSG(misses)-ZCSG(blacklist_misses)); diff --git a/zend_shared_alloc.c b/zend_shared_alloc.c index b6040cf0ad8..1a983aeea70 100644 --- a/zend_shared_alloc.c +++ b/zend_shared_alloc.c @@ -256,10 +256,29 @@ void zend_shared_alloc_shutdown(void) #endif } +static size_t zend_shared_alloc_get_largest_free_block(void) +{ + int i; + size_t largest_block_size = 0; + + for (i = 0; i < ZSMMG(shared_segments_count); i++) { + size_t block_size = ZSMMG(shared_segments)[i]->size - ZSMMG(shared_segments)[i]->pos; + + if (block_size>largest_block_size) { + largest_block_size = block_size; + } + } + return largest_block_size; +} + +#define MIN_FREE_MEMORY 64*1024 + #define SHARED_ALLOC_FAILED() do { \ zend_accel_error(ACCEL_LOG_WARNING, "Not enough free shared space to allocate %ld bytes (%ld bytes free)", (long)size, (long)ZSMMG(shared_free)); \ - ZSMMG(memory_exhausted) = 1; \ - zend_accel_schedule_restart(TSRMLS_C); \ + if (zend_shared_alloc_get_largest_free_block() < MIN_FREE_MEMORY) { \ + ZSMMG(memory_exhausted) = 1; \ + zend_accel_schedule_restart(TSRMLS_C); \ + } \ } while (0) void *zend_shared_alloc(size_t size) @@ -425,21 +444,6 @@ size_t zend_shared_alloc_get_free_memory(void) return ZSMMG(shared_free); } -size_t zend_shared_alloc_get_largest_free_block(void) -{ - int i; - size_t largest_block_size = 0; - - for (i = 0; i < ZSMMG(shared_segments_count); i++) { - size_t block_size = ZSMMG(shared_segments)[i]->size - ZSMMG(shared_segments)[i]->pos; - - if (block_size>largest_block_size) { - largest_block_size = block_size; - } - } - return largest_block_size; -} - void zend_shared_alloc_save_state(void) { int i; diff --git a/zend_shared_alloc.h b/zend_shared_alloc.h index 77ef723fbba..c8411b5624c 100644 --- a/zend_shared_alloc.h +++ b/zend_shared_alloc.h @@ -159,7 +159,6 @@ void *zend_shared_alloc_get_xlat_entry(const void *old); size_t zend_shared_alloc_get_free_memory(void); void zend_shared_alloc_save_state(void); void zend_shared_alloc_restore_state(void); -size_t zend_shared_alloc_get_largest_free_block(void); const char *zend_accel_get_shared_model(void); /* memory write protection */ From 9350f45aca48a1ad95da5dbaca0ee8a06e46a8d6 Mon Sep 17 00:00:00 2001 From: Ferenc Kovacs Date: Fri, 15 Mar 2013 09:40:28 +0100 Subject: [PATCH 133/276] explain the step updating the git submodule reference in web/php.git --- README.RELEASE_PROCESS | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.RELEASE_PROCESS b/README.RELEASE_PROCESS index b6209686c74..6cc9c4e9ab8 100644 --- a/README.RELEASE_PROCESS +++ b/README.RELEASE_PROCESS @@ -162,7 +162,15 @@ origin ``". 11. run: ``./makedist php 5.4.1``, this will export the tree, create configure and build two tarballs (one gz and one bz2). -12. Commit those two tarballs to Git (php-distributions.git) +12. Commit those two tarballs to web/php-distributions.git, then update the git + submodule reference in web/php.git: + git submodule init; + git submodule update; + cd distributions; + git pull origin master; + cd ..; + git commit distributions; + git push; 13. Once the release has been tagged, contact the PHP Windows development team (internals-win@lists.php.net) so that Windows binaries can be created. Once From c765c81cf68d278708bdee816d636d41e6098d33 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 15 Mar 2013 16:21:07 +0400 Subject: [PATCH 134/276] "ZendOptimizerPlus" is renamed to "opcache" to de merged into PHP-5.5 under ext/opcache (the product name is still "Zend Optimizer+") --- README | 68 +++++++++--------- ZendAccelerator.c | 2 +- config.m4 | 9 ++- config.w32 | 13 ++-- shared_alloc_win32.c | 2 +- zend_accelerator_module.c | 148 +++++++++++++++++++------------------- 6 files changed, 120 insertions(+), 122 deletions(-) diff --git a/README b/README index c0304a73abf..bbcfbbf0e77 100644 --- a/README +++ b/README @@ -42,19 +42,19 @@ Speed Tuning We recommend the following configuration options for best performance. -zend_optimizerplus.memory_consumption=128 -zend_optimizerplus.interned_strings_buffer=8 -zend_optimizerplus.max_accelerated_files=4000 -zend_optimizerplus.revalidate_freq=60 -zend_optimizerplus.fast_shutdown=1 -zend_optimizerplus.enable_cli=1 +opcache.memory_consumption=128 +opcache.interned_strings_buffer=8 +opcache.max_accelerated_files=4000 +opcache.revalidate_freq=60 +opcache.fast_shutdown=1 +opcache.enable_cli=1 You also may add the following, but it may break some applications and frameworks. Please, read description of these directives and add them on your own risk. -zend_optimizerplus.save_comments=0 -zend_optimizerplus.enable_file_override=1 +opcache.save_comments=0 +opcache.enable_file_override=1 In some cases you may like to prefer enabling/disabling some features to avoid incompatibilities at the cost of some performance degradation. @@ -62,44 +62,44 @@ to avoid incompatibilities at the cost of some performance degradation. Configuration Directives ------------------------ -zend_optimizerplus.enable (default "1") +opcache.enable (default "1") Optimizer+ On/Off switch. When set to Off, code is not optimized. -zend_optimizerplus.memory_consumption (default "64") +opcache.memory_consumption (default "64") The Optimizer+ shared memory storage size. The amount of memory for storing precompiled PHP code in Mbytes. -zend_optimizerplus.interned_strings_buffer (default "4") +opcache.interned_strings_buffer (default "4") The amount of memory for interned strings in Mbytes. -zend_optimizerplus.max_accelerated_files (default "2000") +opcache.max_accelerated_files (default "2000") The maximum number of keys (scripts) in the Optimizer+ hash table. The number is actually the first one in the following set of prime numbers that is bigger than the one supplied: { 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987 }. Only numbers between 200 and 100000 are allowed. -zend_optimizerplus.max_wasted_percentage (default "5") +opcache.max_wasted_percentage (default "5") The maximum percentage of "wasted" memory until a restart is scheduled. -zend_optimizerplus.use_cwd (default "1") +opcache.use_cwd (default "1") When this directive is enabled, the Optimizer+ appends the current working directory to the script key, thus eliminating possible collisions between files with the same name (basename). Disabling the directive improves performance, but may break existing applications. -zend_optimizerplus.validate_timestamps (default "1") +opcache.validate_timestamps (default "1") When disabled, you must reset the Optimizer+ manually or restart the webserver for changes to the filesystem to take effect. The frequency of the check is controlled by the directive - "zend_optimizerplus.revalidate_freq". + "opcache.revalidate_freq". -zend_optimizerplus.revalidate_freq (default "2") +opcache.revalidate_freq (default "2") How often (in seconds) to check file timestamps for changes to the shared memory storage allocation. ("1" means validate once per second, but only once per request. "0" means always validate) -zend_optimizerplus.revalidate_path (default "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 the same include_path, the file is not searched again. Thus, if a file @@ -108,29 +108,29 @@ zend_optimizerplus.revalidate_path (default "0") your applications. The default for this directive is disabled, which means that optimization is active. -zend_optimizerplus.save_comments (default "1") +opcache.save_comments (default "1") If disabled, all PHPDoc comments are dropped from the code to reduce the size of the optimized code. Disabling "Doc Comments" may break some existing applications and frameworks (e.g. Doctrine, ZF2, PHPUnit) -zend_optimizerplus.load_comments (default "1") +opcache.load_comments (default "1") If disabled, PHPDoc comments are not loaded from SHM, so "Doc Comments" may be always stored (save_comments=1), but not loaded by applications that don't need them anyway. -zend_optimizerplus.fast_shutdown (default "0") +opcache.fast_shutdown (default "0") If enabled, a fast shutdown sequence is used for the accelerated code The fast shutdown sequence doesn't free each allocated block, but lets the Zend Engine Memory Manager do the work. -zend_optimizerplus.enable_file_override (default "0") +opcache.enable_file_override (default "0") Allow file existence override (file_exists, etc.) performance feature. -zend_optimizerplus.optimization_level (default "0xffffffff") +opcache.optimization_level (default "0xffffffff") A bitmask, where each bit enables or disables the appropriate Optimizer+ passes -zend_optimizerplus.inherited_hack (default "1") +opcache.inherited_hack (default "1") Enable this hack as a workaround for "can't redeclare class" errors. The Optimizer+ stores the places where DECLARE_CLASS opcodes use inheritance (These are the only opcodes that can be executed by PHP, @@ -143,10 +143,10 @@ zend_optimizerplus.inherited_hack (default "1") that optimization is active. In php-5.3 and above this hack is not needed anymore and this setting has no effect. -zend_optimizerplus.dups_fix (default "0") +opcache.dups_fix (default "0") Enable this hack as a workaround for "Cannot redeclare class" errors. -zend_optimizerplus.blacklist_filename +opcache.blacklist_filename The location of the Optimizer+ blacklist file. The Optimizer+ blacklist file is a text file that holds the names of files that should not be accelerated. The file format is to add each filename @@ -159,17 +159,17 @@ zend_optimizerplus.blacklist_filename compile time evaluation. 3) Code that triggers an Optimizer+ bug. -zend_optimizerplus.max_file_size (default "0") +opcache.max_file_size (default "0") Allows exclusion of large files from being cached. By default all files are cached. -zend_optimizerplus.consistency_checks (default "0") +opcache.consistency_checks (default "0") Check the cache checksum each N requests. The default value of "0" means that the checks are disabled. Because calculating the checksum impairs performance, this directive should be enabled only as part of a debugging process. -zend_optimizerplus.force_restart_timeout (default "180") +opcache.force_restart_timeout (default "180") How long to wait (in seconds) for a scheduled restart to begin if the cache is not being accessed. The Optimizer+ uses this directive to identify a situation where there may @@ -179,23 +179,23 @@ zend_optimizerplus.force_restart_timeout (default "180") If the log level is 3 or above, a "killed locker" error is recorded in the Apache logs when this happens. -zend_optimizerplus.error_log +opcache.error_log Optimizer+ error_log file name. Empty string assumes "stderr". -zend_optimizerplus.log_verbosity_level (default "1") +opcache.log_verbosity_level (default "1") All Optimizer+ errors go to the Web server log. By default, only fatal errors (level 0) or errors (level 1) are logged. You can also enable warnings (level 2), info messages (level 3) or debug messages (level 4). -zend_optimizerplus.preferred_memory_model +opcache.preferred_memory_model Preferred Shared Memory back-end. Leave empty and let the system decide. -zend_optimizerplus.protect_memory (default "0") +opcache.protect_memory (default "0") Protect the shared memory from unexpected writing during script execution. Useful for internal debugging only. -zend_optimizerplus.mmap_base +opcache.mmap_base Mapping base of shared memory segments (for Windows only). All the PHP processes have to map shared memory into the same address space. This directive allows to manually fix the "Unable to reattach to base address" diff --git a/ZendAccelerator.c b/ZendAccelerator.c index 87b60f1e01a..17eac09caf8 100644 --- a/ZendAccelerator.c +++ b/ZendAccelerator.c @@ -913,7 +913,7 @@ char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_lengt if ((cwd = accel_getcwd(&cwd_len TSRMLS_CC)) == NULL) { /* we don't handle this well for now. */ - zend_accel_error(ACCEL_LOG_INFO, "getcwd() failed for '%s' (%d), please try to set zend_optimizerplus.use_cwd to 0 in ini file", file_handle->filename, errno); + zend_accel_error(ACCEL_LOG_INFO, "getcwd() failed for '%s' (%d), please try to set opcache.use_cwd to 0 in ini file", file_handle->filename, errno); if (file_handle->opened_path) { cwd = file_handle->opened_path; cwd_len = strlen(cwd); diff --git a/config.m4 b/config.m4 index a15d651308b..4e41c8bc191 100644 --- a/config.m4 +++ b/config.m4 @@ -2,11 +2,10 @@ dnl dnl $Id$ dnl -PHP_ARG_ENABLE(optimizer-plus, whether to enable Zend OptimizerPlus support, -[ --enable-optimizer-plus Enable Zend OptimizerPlus support]) +PHP_ARG_ENABLE(opcache, whether to enable Zend Optimizer+ support, +[ --enable-opcache Enable Zend Optimizer+ support]) -if test "$PHP_OPTIMIZER_PLUS" != "no"; then - AC_DEFINE(HAVE_OPTIMIZER_PLUS, 1, [ ]) +if test "$PHP_OPCACHE" != "no"; then AC_CHECK_FUNC(mprotect,[ AC_DEFINE(HAVE_MPROTECT, 1, [Define if you have mprotect() function]) @@ -327,7 +326,7 @@ int main() { msg=yes,msg=no,msg=no) AC_MSG_RESULT([$msg]) - PHP_NEW_EXTENSION(ZendOptimizerPlus, + PHP_NEW_EXTENSION(opcache, ZendAccelerator.c \ zend_accelerator_blacklist.c \ zend_accelerator_debug.c \ diff --git a/config.w32 b/config.w32 index feebe41afd3..aeca78a77bb 100644 --- a/config.w32 +++ b/config.w32 @@ -1,11 +1,11 @@ -ARG_ENABLE("optimizer-plus", "whether to enable Zend OptimizerPlus support", "yes"); +ARG_ENABLE("opcache", "whether to enable Zend Optimizer+ support", "yes"); -if (PHP_OPTIMIZER_PLUS != "no") { +if (PHP_OPCACHE != "no") { PHP_PGI = "no"; // workaround PHP_PGO = "no"; // workaround - EXTENSION('ZendOptimizerPlus', "\ + EXTENSION('opcache', "\ ZendAccelerator.c \ zend_accelerator_blacklist.c \ zend_accelerator_debug.c \ @@ -17,12 +17,11 @@ if (PHP_OPTIMIZER_PLUS != "no") { zend_shared_alloc.c \ shared_alloc_win32.c", true); - ADD_SOURCES(configure_module_dirname + "/Optimizer", "zend_optimizer.c", "ZendOptimizerPlus", "OptimizerObj"); + ADD_SOURCES(configure_module_dirname + "/Optimizer", "zend_optimizer.c", "opcache", "OptimizerObj"); - ADD_FLAG('CFLAGS_ZENDOPTIMIZERPLUS', "/I " + configure_module_dirname); - ADD_FLAG('CFLAGS_ZENDOPTIMIZERPLUS', "/D HAVE_OPTIMIZER_PLUS=1"); + ADD_FLAG('CFLAGS_OPCACHE', "/I " + configure_module_dirname); - ADD_FLAG('CFLAGS_ZENDOPTIMIZERPLUS', "/Dregexec=php_regexec /Dregerror=php_regerror /Dregfree=php_regfree /Dregcomp=php_regcomp /Iext/ereg/regex"); + ADD_FLAG('CFLAGS_OPCACHE', "/Dregexec=php_regexec /Dregerror=php_regerror /Dregfree=php_regfree /Dregcomp=php_regcomp /Iext/ereg/regex"); } diff --git a/shared_alloc_win32.c b/shared_alloc_win32.c index dc2bfd7a13b..7eb93af62f2 100644 --- a/shared_alloc_win32.c +++ b/shared_alloc_win32.c @@ -275,7 +275,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ } if (sscanf(s, "%p", &default_mapping_base_set[0]) != 1) { zend_shared_alloc_unlock_win32(); - zend_win_error_message(ACCEL_LOG_FATAL, "Bad mapping address specified in zend_optimizerplus.mmap_base", err); + zend_win_error_message(ACCEL_LOG_FATAL, "Bad mapping address specified in opcache.mmap_base", err); return ALLOC_FAILURE; } } diff --git a/zend_accelerator_module.c b/zend_accelerator_module.c index c7c3b6058f2..e55884aba1e 100644 --- a/zend_accelerator_module.c +++ b/zend_accelerator_module.c @@ -38,18 +38,18 @@ #define TOKENTOSTR(X) #X /* User functions */ -static ZEND_FUNCTION(accelerator_reset); +static ZEND_FUNCTION(opcache_reset); /* Private functions */ -static ZEND_FUNCTION(accelerator_get_status); -static ZEND_FUNCTION(accelerator_get_configuration); +static ZEND_FUNCTION(opcache_get_status); +static ZEND_FUNCTION(opcache_get_configuration); static zend_function_entry accel_functions[] = { /* User functions */ - ZEND_FE(accelerator_reset, NULL) + ZEND_FE(opcache_reset, NULL) /* Private functions */ - ZEND_FE(accelerator_get_configuration, NULL) - ZEND_FE(accelerator_get_status, NULL) + ZEND_FE(opcache_get_configuration, NULL) + ZEND_FE(opcache_get_status, NULL) { NULL, NULL, NULL, 0, 0 } }; @@ -74,12 +74,12 @@ static ZEND_INI_MH(OnUpdateMemoryConsumption) zend_ini_entry *ini_entry; memsize = 8; - zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.memory_consumption is set below the required 8MB.\n"); + zend_accel_error(ACCEL_LOG_WARNING, "opcache.memory_consumption is set below the required 8MB.\n"); zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the minimal 8MB configuration.\n"); if (zend_hash_find(EG(ini_directives), - "zend_optimizerplus.memory_consumption", - sizeof("zend_optimizerplus.memory_consumption"), + "opcache.memory_consumption", + sizeof("opcache.memory_consumption"), (void *) &ini_entry) == FAILURE) { return FAILURE; } @@ -115,18 +115,18 @@ static ZEND_INI_MH(OnUpdateMaxAcceleratedFiles) if (size < MIN_ACCEL_FILES) { size = MIN_ACCEL_FILES; new_new_value = TOKENTOSTR(MIN_ACCEL_FILES); - zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.max_accelerated_files is set below the required minimum (%d).\n", MIN_ACCEL_FILES); + zend_accel_error(ACCEL_LOG_WARNING, "opcache.max_accelerated_files is set below the required minimum (%d).\n", MIN_ACCEL_FILES); zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the minimal configuration.\n"); } if (size > MAX_ACCEL_FILES) { size = MAX_ACCEL_FILES; new_new_value = TOKENTOSTR(MAX_ACCEL_FILES); - zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.max_accelerated_files is set above the limit (%d).\n", MAX_ACCEL_FILES); + zend_accel_error(ACCEL_LOG_WARNING, "opcache.max_accelerated_files is set above the limit (%d).\n", MAX_ACCEL_FILES); zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the maximal configuration.\n"); } if (zend_hash_find(EG(ini_directives), - "zend_optimizerplus.max_accelerated_files", - sizeof("zend_optimizerplus.max_accelerated_files"), + "opcache.max_accelerated_files", + sizeof("opcache.max_accelerated_files"), (void *) &ini_entry) == FAILURE) { return FAILURE; } @@ -158,11 +158,11 @@ static ZEND_INI_MH(OnUpdateMaxWastedPercentage) zend_ini_entry *ini_entry; percentage = 5; - zend_accel_error(ACCEL_LOG_WARNING, "zend_optimizerplus.max_wasted_percentage must be set between 1 and 50.\n"); + zend_accel_error(ACCEL_LOG_WARNING, "opcache.max_wasted_percentage must be set between 1 and 50.\n"); zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use 5%.\n"); if (zend_hash_find(EG(ini_directives), - "zend_optimizerplus.max_wasted_percentage", - sizeof("zend_optimizerplus.max_wasted_percentage"), + "opcache.max_wasted_percentage", + sizeof("opcache.max_wasted_percentage"), (void *) &ini_entry) == FAILURE) { return FAILURE; } @@ -199,39 +199,39 @@ static ZEND_INI_MH(OnUpdateAccelBlacklist) } ZEND_INI_BEGIN() - STD_PHP_INI_BOOLEAN("zend_optimizerplus.enable" , "1", PHP_INI_SYSTEM, OnUpdateBool, enabled , zend_accel_globals, accel_globals) - STD_PHP_INI_BOOLEAN("zend_optimizerplus.use_cwd" , "1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.use_cwd , zend_accel_globals, accel_globals) - STD_PHP_INI_BOOLEAN("zend_optimizerplus.validate_timestamps", "1", PHP_INI_ALL , OnUpdateBool, accel_directives.validate_timestamps, zend_accel_globals, accel_globals) - STD_PHP_INI_BOOLEAN("zend_optimizerplus.inherited_hack" , "1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.inherited_hack , zend_accel_globals, accel_globals) - STD_PHP_INI_BOOLEAN("zend_optimizerplus.dups_fix" , "0", PHP_INI_ALL , OnUpdateBool, accel_directives.ignore_dups , zend_accel_globals, accel_globals) - STD_PHP_INI_BOOLEAN("zend_optimizerplus.revalidate_path" , "0", PHP_INI_ALL , OnUpdateBool, accel_directives.revalidate_path , zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("opcache.enable" , "1", PHP_INI_SYSTEM, OnUpdateBool, enabled , zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("opcache.use_cwd" , "1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.use_cwd , zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("opcache.validate_timestamps", "1", PHP_INI_ALL , OnUpdateBool, accel_directives.validate_timestamps, zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("opcache.inherited_hack" , "1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.inherited_hack , zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("opcache.dups_fix" , "0", PHP_INI_ALL , OnUpdateBool, accel_directives.ignore_dups , zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("opcache.revalidate_path" , "0", PHP_INI_ALL , OnUpdateBool, accel_directives.revalidate_path , zend_accel_globals, accel_globals) - STD_PHP_INI_ENTRY("zend_optimizerplus.log_verbosity_level" , "1" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.log_verbosity_level, zend_accel_globals, accel_globals) - STD_PHP_INI_ENTRY("zend_optimizerplus.memory_consumption" , "64" , PHP_INI_SYSTEM, OnUpdateMemoryConsumption, accel_directives.memory_consumption, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("opcache.log_verbosity_level" , "1" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.log_verbosity_level, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("opcache.memory_consumption" , "64" , PHP_INI_SYSTEM, OnUpdateMemoryConsumption, accel_directives.memory_consumption, zend_accel_globals, accel_globals) #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO - STD_PHP_INI_ENTRY("zend_optimizerplus.interned_strings_buffer", "4" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.interned_strings_buffer, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("opcache.interned_strings_buffer", "4" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.interned_strings_buffer, zend_accel_globals, accel_globals) #endif - STD_PHP_INI_ENTRY("zend_optimizerplus.max_accelerated_files" , "2000", PHP_INI_SYSTEM, OnUpdateMaxAcceleratedFiles, accel_directives.max_accelerated_files, zend_accel_globals, accel_globals) - STD_PHP_INI_ENTRY("zend_optimizerplus.max_wasted_percentage" , "5" , PHP_INI_SYSTEM, OnUpdateMaxWastedPercentage, accel_directives.max_wasted_percentage, zend_accel_globals, accel_globals) - STD_PHP_INI_ENTRY("zend_optimizerplus.consistency_checks" , "0" , PHP_INI_ALL , OnUpdateLong, accel_directives.consistency_checks, zend_accel_globals, accel_globals) - STD_PHP_INI_ENTRY("zend_optimizerplus.force_restart_timeout" , "180" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.force_restart_timeout, zend_accel_globals, accel_globals) - STD_PHP_INI_ENTRY("zend_optimizerplus.revalidate_freq" , "2" , PHP_INI_ALL , OnUpdateLong, accel_directives.revalidate_freq, zend_accel_globals, accel_globals) - STD_PHP_INI_ENTRY("zend_optimizerplus.preferred_memory_model", "" , PHP_INI_SYSTEM, OnUpdateStringUnempty, accel_directives.memory_model, zend_accel_globals, accel_globals) - STD_PHP_INI_ENTRY("zend_optimizerplus.blacklist_filename" , "" , PHP_INI_SYSTEM, OnUpdateAccelBlacklist, accel_directives.user_blacklist_filename, zend_accel_globals, accel_globals) - STD_PHP_INI_ENTRY("zend_optimizerplus.max_file_size" , "0" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.max_file_size, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("opcache.max_accelerated_files" , "2000", PHP_INI_SYSTEM, OnUpdateMaxAcceleratedFiles, accel_directives.max_accelerated_files, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("opcache.max_wasted_percentage" , "5" , PHP_INI_SYSTEM, OnUpdateMaxWastedPercentage, accel_directives.max_wasted_percentage, zend_accel_globals, accel_globals) + 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.blacklist_filename" , "" , PHP_INI_SYSTEM, OnUpdateAccelBlacklist, 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) - STD_PHP_INI_ENTRY("zend_optimizerplus.protect_memory" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.protect_memory, zend_accel_globals, accel_globals) - STD_PHP_INI_ENTRY("zend_optimizerplus.save_comments" , "1" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.save_comments, zend_accel_globals, accel_globals) - STD_PHP_INI_ENTRY("zend_optimizerplus.load_comments" , "1" , PHP_INI_ALL, OnUpdateBool, accel_directives.load_comments, zend_accel_globals, accel_globals) - STD_PHP_INI_ENTRY("zend_optimizerplus.fast_shutdown" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.fast_shutdown, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("opcache.protect_memory" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.protect_memory, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("opcache.save_comments" , "1" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.save_comments, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("opcache.load_comments" , "1" , PHP_INI_ALL, OnUpdateBool, accel_directives.load_comments, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("opcache.fast_shutdown" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.fast_shutdown, zend_accel_globals, accel_globals) - STD_PHP_INI_ENTRY("zend_optimizerplus.optimization_level" , DEFAULT_OPTIMIZATION_LEVEL , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.optimization_level, zend_accel_globals, accel_globals) - STD_PHP_INI_BOOLEAN("zend_optimizerplus.enable_file_override" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.file_override_enabled, zend_accel_globals, accel_globals) - STD_PHP_INI_BOOLEAN("zend_optimizerplus.enable_cli" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.enable_cli, zend_accel_globals, accel_globals) - STD_PHP_INI_ENTRY("zend_optimizerplus.error_log" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.error_log, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("opcache.optimization_level" , DEFAULT_OPTIMIZATION_LEVEL , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.optimization_level, zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("opcache.enable_file_override" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.file_override_enabled, zend_accel_globals, accel_globals) + STD_PHP_INI_BOOLEAN("opcache.enable_cli" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.enable_cli, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("opcache.error_log" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.error_log, zend_accel_globals, accel_globals) #ifdef ZEND_WIN32 - STD_PHP_INI_ENTRY("zend_optimizerplus.mmap_base", NULL, PHP_INI_SYSTEM, OnUpdateString, accel_directives.mmap_base, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("opcache.mmap_base", NULL, PHP_INI_SYSTEM, OnUpdateString, accel_directives.mmap_base, zend_accel_globals, accel_globals) #endif ZEND_INI_END() @@ -459,7 +459,7 @@ static zval* accelerator_get_scripts(TSRMLS_D) /* {{{ proto array accelerator_get_status() Obtain statistics information regarding code acceleration in the Zend Performance Suite */ -static ZEND_FUNCTION(accelerator_get_status) +static ZEND_FUNCTION(opcache_get_status) { long reqs; zval *memory_usage,*statistics,*scripts; @@ -480,7 +480,7 @@ static ZEND_FUNCTION(accelerator_get_status) array_init(return_value); /* Trivia */ - add_assoc_bool(return_value, "accelerator_enabled", 1 /*ZCG(enabled) && accel_startup_ok && ZCSG(accelerator_enabled)*/); + add_assoc_bool(return_value, "opcache_enabled", 1 /*ZCG(enabled) && accel_startup_ok && ZCSG(accelerator_enabled)*/); add_assoc_bool(return_value, "cache_full", ZSMMG(memory_exhausted)); /* Memory usage statistics */ @@ -504,8 +504,8 @@ static ZEND_FUNCTION(accelerator_get_status) add_assoc_long(statistics, "blacklist_misses", ZCSG(blacklist_misses)); reqs = ZCSG(hits)+ZCSG(misses); add_assoc_double(statistics, "blacklist_miss_ratio", reqs?(((double) ZCSG(blacklist_misses))/reqs)*100.0:0); - add_assoc_double(statistics, "accelerator_hit_rate", reqs?(((double) ZCSG(hits))/reqs)*100.0:0); - add_assoc_zval(return_value, "accelerator_statistics", statistics); + add_assoc_double(statistics, "opcache_hit_rate", reqs?(((double) ZCSG(hits))/reqs)*100.0:0); + add_assoc_zval(return_value, "opcache_statistics", statistics); /* accelerated scripts */ scripts = accelerator_get_scripts(TSRMLS_C); @@ -522,7 +522,7 @@ static int add_blacklist_path(zend_blacklist_entry *p, zval *return_value TSRMLS /* {{{ proto array accelerator_get_configuration() Obtain configuration information for the Zend Performance Suite */ -static ZEND_FUNCTION(accelerator_get_configuration) +static ZEND_FUNCTION(opcache_get_configuration) { zval *directives,*version,*blacklist; @@ -540,35 +540,35 @@ static ZEND_FUNCTION(accelerator_get_configuration) /* directives */ MAKE_STD_ZVAL(directives); array_init(directives); - add_assoc_bool(directives, "zend_optimizerplus.enable", ZCG(enabled)); - add_assoc_bool(directives, "zend_optimizerplus.enable_cli", ZCG(accel_directives).enable_cli); - add_assoc_bool(directives, "zend_optimizerplus.use_cwd", ZCG(accel_directives).use_cwd); - add_assoc_bool(directives, "zend_optimizerplus.validate_timestamps", ZCG(accel_directives).validate_timestamps); - add_assoc_bool(directives, "zend_optimizerplus.inherited_hack", ZCG(accel_directives).inherited_hack); - add_assoc_bool(directives, "zend_optimizerplus.dups_fix", ZCG(accel_directives).ignore_dups); - add_assoc_bool(directives, "zend_optimizerplus.revalidate_path", ZCG(accel_directives).revalidate_path); + add_assoc_bool(directives, "opcache.enable", ZCG(enabled)); + add_assoc_bool(directives, "opcache.enable_cli", ZCG(accel_directives).enable_cli); + add_assoc_bool(directives, "opcache.use_cwd", ZCG(accel_directives).use_cwd); + add_assoc_bool(directives, "opcache.validate_timestamps", ZCG(accel_directives).validate_timestamps); + add_assoc_bool(directives, "opcache.inherited_hack", ZCG(accel_directives).inherited_hack); + add_assoc_bool(directives, "opcache.dups_fix", ZCG(accel_directives).ignore_dups); + add_assoc_bool(directives, "opcache.revalidate_path", ZCG(accel_directives).revalidate_path); - add_assoc_long(directives, "zend_optimizerplus.log_verbosity_level", ZCG(accel_directives).log_verbosity_level); - add_assoc_long(directives, "zend_optimizerplus.memory_consumption", ZCG(accel_directives).memory_consumption); + add_assoc_long(directives, "opcache.log_verbosity_level", ZCG(accel_directives).log_verbosity_level); + add_assoc_long(directives, "opcache.memory_consumption", ZCG(accel_directives).memory_consumption); #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO - add_assoc_long(directives, "zend_optimizerplus.interned_strings_buffer",ZCG(accel_directives).interned_strings_buffer); + add_assoc_long(directives, "opcache.interned_strings_buffer",ZCG(accel_directives).interned_strings_buffer); #endif - add_assoc_long(directives, "zend_optimizerplus.max_accelerated_files", ZCG(accel_directives).max_accelerated_files); - add_assoc_double(directives, "zend_optimizerplus.max_wasted_percentage", ZCG(accel_directives).max_wasted_percentage); - add_assoc_long(directives, "zend_optimizerplus.consistency_checks", ZCG(accel_directives).consistency_checks); - add_assoc_long(directives, "zend_optimizerplus.force_restart_timeout", ZCG(accel_directives).force_restart_timeout); - add_assoc_long(directives, "zend_optimizerplus.revalidate_freq", ZCG(accel_directives).revalidate_freq); - add_assoc_string(directives, "zend_optimizerplus.preferred_memory_model", STRING_NOT_NULL(ZCG(accel_directives).memory_model), 1); - add_assoc_string(directives, "zend_optimizerplus.blacklist_filename", STRING_NOT_NULL(ZCG(accel_directives).user_blacklist_filename), 1); - add_assoc_long(directives, "zend_optimizerplus.max_file_size", ZCG(accel_directives).max_file_size); - add_assoc_string(directives, "zend_optimizerplus.error_log", STRING_NOT_NULL(ZCG(accel_directives).error_log), 1); + add_assoc_long(directives, "opcache.max_accelerated_files", ZCG(accel_directives).max_accelerated_files); + add_assoc_double(directives, "opcache.max_wasted_percentage", ZCG(accel_directives).max_wasted_percentage); + add_assoc_long(directives, "opcache.consistency_checks", ZCG(accel_directives).consistency_checks); + add_assoc_long(directives, "opcache.force_restart_timeout", ZCG(accel_directives).force_restart_timeout); + add_assoc_long(directives, "opcache.revalidate_freq", ZCG(accel_directives).revalidate_freq); + add_assoc_string(directives, "opcache.preferred_memory_model", STRING_NOT_NULL(ZCG(accel_directives).memory_model), 1); + add_assoc_string(directives, "opcache.blacklist_filename", STRING_NOT_NULL(ZCG(accel_directives).user_blacklist_filename), 1); + add_assoc_long(directives, "opcache.max_file_size", ZCG(accel_directives).max_file_size); + add_assoc_string(directives, "opcache.error_log", STRING_NOT_NULL(ZCG(accel_directives).error_log), 1); - add_assoc_bool(directives, "zend_optimizerplus.protect_memory", ZCG(accel_directives).protect_memory); - add_assoc_bool(directives, "zend_optimizerplus.save_comments", ZCG(accel_directives).save_comments); - add_assoc_bool(directives, "zend_optimizerplus.load_comments", ZCG(accel_directives).load_comments); - add_assoc_bool(directives, "zend_optimizerplus.fast_shutdown", ZCG(accel_directives).fast_shutdown); - add_assoc_bool(directives, "zend_optimizerplus.enable_file_override", ZCG(accel_directives).file_override_enabled); - add_assoc_long(directives, "zend_optimizerplus.optimization_level", ZCG(accel_directives).optimization_level); + add_assoc_bool(directives, "opcache.protect_memory", ZCG(accel_directives).protect_memory); + add_assoc_bool(directives, "opcache.save_comments", ZCG(accel_directives).save_comments); + add_assoc_bool(directives, "opcache.load_comments", ZCG(accel_directives).load_comments); + add_assoc_bool(directives, "opcache.fast_shutdown", ZCG(accel_directives).fast_shutdown); + add_assoc_bool(directives, "opcache.enable_file_override", ZCG(accel_directives).file_override_enabled); + add_assoc_long(directives, "opcache.optimization_level", ZCG(accel_directives).optimization_level); add_assoc_zval(return_value, "directives", directives); @@ -576,7 +576,7 @@ static ZEND_FUNCTION(accelerator_get_configuration) MAKE_STD_ZVAL(version); array_init(version); add_assoc_string(version, "version", ACCELERATOR_VERSION, 1); - add_assoc_string(version, "accelerator_product_name", ACCELERATOR_PRODUCT_NAME, 1); + add_assoc_string(version, "opcache_product_name", ACCELERATOR_PRODUCT_NAME, 1); add_assoc_zval(return_value, "version", version); /* blacklist */ @@ -588,7 +588,7 @@ static ZEND_FUNCTION(accelerator_get_configuration) /* {{{ proto void accelerator_reset() Request that the contents of the Accelerator module in the ZPS be reset */ -static ZEND_FUNCTION(accelerator_reset) +static ZEND_FUNCTION(opcache_reset) { /* keep the compiler happy */ (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; From b7788c52f1e30e425795870e0a1450a620a41f08 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 15 Mar 2013 13:48:33 +0100 Subject: [PATCH 135/276] Fix wrong macro usage and add missing NEWS entry --- NEWS | 2 ++ Zend/zend_API.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 9d87b9592f2..16932689538 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,8 @@ PHP NEWS details here: https://wiki.php.net/rfc/cli_process_title. (Keyur) . Fixed bug #64370 (microtime(true) less than $_SERVER['REQUEST_TIME_FLOAT']). (Anatol) + . Added support for non-scalar Iterator keys in foreach + (https://wiki.php.net/rfc/foreach-non-scalar-keys). (Nikita Popov) - mysqlnd . Fixed bug #63530 (mysqlnd_stmt::bind_one_parameter crashes, uses wrong alloc diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 2653d0849af..8c3a3579543 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1521,7 +1521,7 @@ ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */ result = zend_hash_index_update(ht, Z_LVAL_P(key), &value, sizeof(zval *), NULL); break; case IS_DOUBLE: - result = zend_hash_index_update(ht, zend_dval_to_lval(Z_LVAL_P(key)), &value, sizeof(zval *), NULL); + result = zend_hash_index_update(ht, zend_dval_to_lval(Z_DVAL_P(key)), &value, sizeof(zval *), NULL); break; default: zend_error(E_WARNING, "Illegal offset type"); From 0ee71557ffd285552659b6aa37ea236e3bad493f Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Fri, 15 Mar 2013 16:59:54 +0100 Subject: [PATCH 136/276] Fixed bug #53437 Crash with unserialized DatePeriod instance --- NEWS | 4 + ext/date/php_date.c | 327 ++++++++++++++++++++++++++++-- ext/date/php_date.h | 2 + ext/date/tests/bug45682.phpt | 20 +- ext/date/tests/bug48678.phpt | 18 +- ext/date/tests/bug49081.phpt | 7 + ext/date/tests/bug49778.phpt | 16 +- ext/date/tests/bug52113.phpt | 165 ++++++++++++++- ext/date/tests/bug52738.phpt | 7 + ext/date/tests/bug52808.phpt | 54 ++++- ext/date/tests/bug53437.phpt | 134 +++++++++++- ext/date/tests/bug53437_var1.phpt | 13 ++ ext/date/tests/bug53437_var2.phpt | 80 ++++++++ ext/date/tests/bug53437_var3.phpt | 45 ++++ ext/date/tests/date_diff1.phpt | 18 +- 15 files changed, 862 insertions(+), 48 deletions(-) create mode 100644 ext/date/tests/bug53437_var1.phpt create mode 100644 ext/date/tests/bug53437_var2.phpt create mode 100644 ext/date/tests/bug53437_var3.phpt diff --git a/NEWS b/NEWS index 16932689538..9dc334d6240 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,10 @@ PHP NEWS . Fixed bug #63530 (mysqlnd_stmt::bind_one_parameter crashes, uses wrong alloc for stmt->param_bind). (Andrey) +- DateTime + . Fixed bug #53437 (Crash when using unserialized DatePeriod instance). + (Gustavo, Derick, Anatol) + 07 Mar 2013, PHP 5.5.0 Alpha 6 - Core: diff --git a/ext/date/php_date.c b/ext/date/php_date.c index f36ccc1ade0..52241234cab 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -39,6 +39,20 @@ static __inline __int64_t php_date_llabs( __int64_t i ) { return i >= 0 ? i : -i static inline long long php_date_llabs( long long i ) { return i >= 0 ? i : -i; } #endif +#ifdef PHP_WIN32 +#define DATE_I64_BUF_LEN 65 +# define DATE_I64A(i, s, len) _i64toa_s(i, s, len, 10) +# define DATE_A64I(i, s) i = _atoi64(s) +#else +#define DATE_I64_BUF_LEN 65 +# define DATE_I64A(i, s, len) \ + do { \ + int st = snprintf(s, len, "%lld", i); \ + s[st] = '\0'; \ + } while (0); +# define DATE_A64I(i, s) i = atoll(s) +#endif + /* {{{ arginfo */ ZEND_BEGIN_ARG_INFO_EX(arginfo_date, 0, 0, 1) ZEND_ARG_INFO(0, format) @@ -488,6 +502,8 @@ const zend_function_entry date_funcs_interval[] = { const zend_function_entry date_funcs_period[] = { PHP_ME(DatePeriod, __construct, arginfo_date_period_construct, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC) + PHP_ME(DatePeriod, __wakeup, NULL, ZEND_ACC_PUBLIC) + PHP_ME(DatePeriod, __set_state, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) PHP_FE_END }; @@ -594,9 +610,13 @@ static HashTable *date_object_get_gc(zval *object, zval ***table, int *n TSRMLS_ static HashTable *date_object_get_properties(zval *object TSRMLS_DC); static HashTable *date_object_get_gc_interval(zval *object, zval ***table, int *n TSRMLS_DC); static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC); +static HashTable *date_object_get_gc_period(zval *object, zval ***table, int *n TSRMLS_DC); +static HashTable *date_object_get_properties_period(zval *object TSRMLS_DC); zval *date_interval_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC); void date_interval_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC); +static zval *date_period_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC); +static void date_period_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC); /* {{{ Module struct */ zend_module_entry date_module_entry = { @@ -2012,6 +2032,11 @@ static void date_register_classes(TSRMLS_D) zend_class_implements(date_ce_period TSRMLS_CC, 1, zend_ce_traversable); memcpy(&date_object_handlers_period, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); date_object_handlers_period.clone_obj = date_object_clone_period; + date_object_handlers_period.get_properties = date_object_get_properties_period; + date_object_handlers_period.get_property_ptr_ptr = NULL; + date_object_handlers_period.get_gc = date_object_get_gc_period; + date_object_handlers_period.read_property = date_period_read_property; + date_object_handlers_period.write_property = date_period_write_property; #define REGISTER_PERIOD_CLASS_CONST_STRING(const_name, value) \ zend_declare_class_constant_long(date_ce_period, const_name, sizeof(const_name)-1, value TSRMLS_CC); @@ -2124,7 +2149,7 @@ static HashTable *date_object_get_properties(zval *object TSRMLS_DC) props = zend_std_get_properties(object TSRMLS_CC); - if (!dateobj->time) { + if (!dateobj->time || GC_G(gc_active)) { return props; } @@ -2272,7 +2297,6 @@ static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC) zval *zv; php_interval_obj *intervalobj; - intervalobj = (php_interval_obj *) zend_object_store_get_object(object TSRMLS_CC); props = zend_std_get_properties(object TSRMLS_CC); @@ -2281,6 +2305,15 @@ static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC) return props; } +#define PHP_DATE_INTERVAL_ADD_PROPERTY_I64(n, f) \ + do { \ + char i64_buf[DATE_I64_BUF_LEN]; \ + MAKE_STD_ZVAL(zv); \ + DATE_I64A(intervalobj->diff->f, i64_buf, DATE_I64_BUF_LEN); \ + ZVAL_STRING(zv, i64_buf, 1); \ + zend_hash_update(props, n, strlen(n) + 1, &zv, sizeof(zval), NULL); \ + } while(0); + #define PHP_DATE_INTERVAL_ADD_PROPERTY(n,f) \ MAKE_STD_ZVAL(zv); \ ZVAL_LONG(zv, intervalobj->diff->f); \ @@ -2292,14 +2325,21 @@ static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC) PHP_DATE_INTERVAL_ADD_PROPERTY("h", h); PHP_DATE_INTERVAL_ADD_PROPERTY("i", i); PHP_DATE_INTERVAL_ADD_PROPERTY("s", s); + PHP_DATE_INTERVAL_ADD_PROPERTY("weekday", weekday); + PHP_DATE_INTERVAL_ADD_PROPERTY("weekday_behavior", weekday_behavior); + PHP_DATE_INTERVAL_ADD_PROPERTY("first_last_day_of", first_last_day_of); PHP_DATE_INTERVAL_ADD_PROPERTY("invert", invert); if (intervalobj->diff->days != -99999) { - PHP_DATE_INTERVAL_ADD_PROPERTY("days", days); + PHP_DATE_INTERVAL_ADD_PROPERTY_I64("days", days); } else { MAKE_STD_ZVAL(zv); ZVAL_FALSE(zv); zend_hash_update(props, "days", 5, &zv, sizeof(zval), NULL); } + PHP_DATE_INTERVAL_ADD_PROPERTY("special_type", special.type); + PHP_DATE_INTERVAL_ADD_PROPERTY_I64("special_amount", special.amount); + PHP_DATE_INTERVAL_ADD_PROPERTY("have_weekday_relative", have_weekday_relative); + PHP_DATE_INTERVAL_ADD_PROPERTY("have_special_relative", have_special_relative); return props; } @@ -2401,6 +2441,7 @@ PHPAPI zval *php_date_instantiate(zend_class_entry *pce, zval *object TSRMLS_DC) object_init_ex(object, pce); Z_SET_REFCOUNT_P(object, 1); Z_UNSET_ISREF_P(object); + return object; } @@ -3951,30 +3992,48 @@ PHP_METHOD(DateInterval, __construct) } /* }}} */ -static long php_date_long_from_hash_element(HashTable *myht, char *element, size_t size) -{ - zval **z_arg = NULL; - - if (zend_hash_find(myht, element, size + 1, (void**) &z_arg) == SUCCESS) { - convert_to_long(*z_arg); - return Z_LVAL_PP(z_arg); - } else { - return -1; - } -} static int php_date_interval_initialize_from_hash(zval **return_value, php_interval_obj **intobj, HashTable *myht TSRMLS_DC) { (*intobj)->diff = timelib_rel_time_ctor(); - (*intobj)->diff->y = php_date_long_from_hash_element(myht, "y", 1); - (*intobj)->diff->m = php_date_long_from_hash_element(myht, "m", 1); - (*intobj)->diff->d = php_date_long_from_hash_element(myht, "d", 1); - (*intobj)->diff->h = php_date_long_from_hash_element(myht, "h", 1); - (*intobj)->diff->i = php_date_long_from_hash_element(myht, "i", 1); - (*intobj)->diff->s = php_date_long_from_hash_element(myht, "s", 1); - (*intobj)->diff->invert = php_date_long_from_hash_element(myht, "invert", 6); - (*intobj)->diff->days = php_date_long_from_hash_element(myht, "days", 4); +#define PHP_DATE_INTERVAL_READ_PROPERTY(element, member, itype) \ + do { \ + zval **z_arg = NULL; \ + if (zend_hash_find(myht, element, strlen(element) + 1, (void**) &z_arg) == SUCCESS) { \ + convert_to_long(*z_arg); \ + (*intobj)->diff->member = (itype)Z_LVAL_PP(z_arg); \ + } else { \ + (*intobj)->diff->member = (itype)-1; \ + } \ + } while (0); + +#define PHP_DATE_INTERVAL_READ_PROPERTY_I64(element, member) \ + do { \ + zval **z_arg = NULL; \ + if (zend_hash_find(myht, element, strlen(element) + 1, (void**) &z_arg) == SUCCESS) { \ + convert_to_string(*z_arg); \ + DATE_A64I((*intobj)->diff->member, Z_STRVAL_PP(z_arg)); \ + } else { \ + (*intobj)->diff->member = -1LL; \ + } \ + } while (0); + + PHP_DATE_INTERVAL_READ_PROPERTY("y", y, timelib_sll) + PHP_DATE_INTERVAL_READ_PROPERTY("m", m, timelib_sll) + PHP_DATE_INTERVAL_READ_PROPERTY("d", d, timelib_sll) + PHP_DATE_INTERVAL_READ_PROPERTY("h", h, timelib_sll) + PHP_DATE_INTERVAL_READ_PROPERTY("i", i, timelib_sll) + PHP_DATE_INTERVAL_READ_PROPERTY("s", s, timelib_sll) + PHP_DATE_INTERVAL_READ_PROPERTY("weekday", weekday, int) + PHP_DATE_INTERVAL_READ_PROPERTY("weekday_behavior", weekday_behavior, int) + PHP_DATE_INTERVAL_READ_PROPERTY("first_last_day_of", first_last_day_of, int) + PHP_DATE_INTERVAL_READ_PROPERTY("invert", invert, int); + PHP_DATE_INTERVAL_READ_PROPERTY_I64("days", days); + PHP_DATE_INTERVAL_READ_PROPERTY("special_type", special.type, unsigned int); + PHP_DATE_INTERVAL_READ_PROPERTY_I64("special_amount", special.amount); + PHP_DATE_INTERVAL_READ_PROPERTY("have_weekday_relative", have_weekday_relative, unsigned int); + PHP_DATE_INTERVAL_READ_PROPERTY("have_special_relative", have_special_relative, unsigned int); (*intobj)->initialized = 1; return 0; @@ -4580,6 +4639,230 @@ PHP_FUNCTION(date_sun_info) timelib_time_dtor(t2); } /* }}} */ + +static HashTable *date_object_get_gc_period(zval *object, zval ***table, int *n TSRMLS_DC) +{ + *table = NULL; + *n = 0; + return zend_std_get_properties(object TSRMLS_CC); +} + +static HashTable *date_object_get_properties_period(zval *object TSRMLS_DC) +{ + HashTable *props; + zval *zv; + php_period_obj *period_obj; + + period_obj = zend_object_store_get_object(object TSRMLS_CC); + + props = zend_std_get_properties(object TSRMLS_CC); + + if (!period_obj->start || GC_G(gc_active)) { + return props; + } + + MAKE_STD_ZVAL(zv); + if (period_obj->start) { + php_date_obj *date_obj; + object_init_ex(zv, date_ce_date); + date_obj = zend_object_store_get_object(zv TSRMLS_CC); + date_obj->time = timelib_time_clone(period_obj->start); + } else { + ZVAL_NULL(zv); + } + zend_hash_update(props, "start", sizeof("start"), &zv, sizeof(zv), NULL); + + MAKE_STD_ZVAL(zv); + if (period_obj->current) { + php_date_obj *date_obj; + object_init_ex(zv, date_ce_date); + date_obj = zend_object_store_get_object(zv TSRMLS_CC); + date_obj->time = timelib_time_clone(period_obj->current); + } else { + ZVAL_NULL(zv); + } + zend_hash_update(props, "current", sizeof("current"), &zv, sizeof(zv), NULL); + + MAKE_STD_ZVAL(zv); + if (period_obj->end) { + php_date_obj *date_obj; + object_init_ex(zv, date_ce_date); + date_obj = zend_object_store_get_object(zv TSRMLS_CC); + date_obj->time = timelib_time_clone(period_obj->end); + } else { + ZVAL_NULL(zv); + } + zend_hash_update(props, "end", sizeof("end"), &zv, sizeof(zv), NULL); + + MAKE_STD_ZVAL(zv); + if (period_obj->interval) { + php_interval_obj *interval_obj; + object_init_ex(zv, date_ce_interval); + interval_obj = zend_object_store_get_object(zv TSRMLS_CC); + interval_obj->diff = timelib_rel_time_clone(period_obj->interval); + interval_obj->initialized = 1; + } else { + ZVAL_NULL(zv); + } + zend_hash_update(props, "interval", sizeof("interval"), &zv, sizeof(zv), NULL); + + /* converted to larger type (int->long); must check when unserializing */ + MAKE_STD_ZVAL(zv); + ZVAL_LONG(zv, (long) period_obj->recurrences); + zend_hash_update(props, "recurrences", sizeof("recurrences"), &zv, sizeof(zv), NULL); + + MAKE_STD_ZVAL(zv); + ZVAL_BOOL(zv, period_obj->include_start_date); + zend_hash_update(props, "include_start_date", sizeof("include_start_date"), &zv, sizeof(zv), NULL); + + return props; +} + +static int php_date_period_initialize_from_hash(php_period_obj *period_obj, HashTable *myht TSRMLS_DC) +{ + zval **ht_entry; + + /* this function does no rollback on error */ + + if (zend_hash_find(myht, "start", sizeof("start"), (void**) &ht_entry) == SUCCESS) { + if (Z_TYPE_PP(ht_entry) == IS_OBJECT && Z_OBJCE_PP(ht_entry) == date_ce_date) { + php_date_obj *date_obj; + date_obj = zend_object_store_get_object(*ht_entry TSRMLS_CC); + period_obj->start = timelib_time_clone(date_obj->time); + period_obj->start_ce = Z_OBJCE_PP(ht_entry); + } else if (Z_TYPE_PP(ht_entry) != IS_NULL) { + return 0; + } + } else { + return 0; + } + + if (zend_hash_find(myht, "end", sizeof("end"), (void**) &ht_entry) == SUCCESS) { + if (Z_TYPE_PP(ht_entry) == IS_OBJECT && Z_OBJCE_PP(ht_entry) == date_ce_date) { + php_date_obj *date_obj; + date_obj = zend_object_store_get_object(*ht_entry TSRMLS_CC); + period_obj->end = timelib_time_clone(date_obj->time); + } else if (Z_TYPE_PP(ht_entry) != IS_NULL) { + return 0; + } + } else { + return 0; + } + + if (zend_hash_find(myht, "current", sizeof("current"), (void**) &ht_entry) == SUCCESS) { + if (Z_TYPE_PP(ht_entry) == IS_OBJECT && Z_OBJCE_PP(ht_entry) == date_ce_date) { + php_date_obj *date_obj; + date_obj = zend_object_store_get_object(*ht_entry TSRMLS_CC); + period_obj->current = timelib_time_clone(date_obj->time); + } else if (Z_TYPE_PP(ht_entry) != IS_NULL) { + return 0; + } + } else { + return 0; + } + + if (zend_hash_find(myht, "interval", sizeof("interval"), (void**) &ht_entry) == SUCCESS) { + if (Z_TYPE_PP(ht_entry) == IS_OBJECT && Z_OBJCE_PP(ht_entry) == date_ce_interval) { + php_interval_obj *interval_obj; + interval_obj = zend_object_store_get_object(*ht_entry TSRMLS_CC); + period_obj->interval = timelib_rel_time_clone(interval_obj->diff); + } else { /* interval is required */ + return 0; + } + } else { + return 0; + } + + if (zend_hash_find(myht, "recurrences", sizeof("recurrences"), (void**) &ht_entry) == SUCCESS && + Z_TYPE_PP(ht_entry) == IS_LONG && Z_LVAL_PP(ht_entry) >= 0 && Z_LVAL_PP(ht_entry) <= INT_MAX) { + period_obj->recurrences = Z_LVAL_PP(ht_entry); + } else { + return 0; + } + + if (zend_hash_find(myht, "include_start_date", sizeof("include_start_date"), (void**) &ht_entry) == SUCCESS && + Z_TYPE_PP(ht_entry) == IS_BOOL) { + period_obj->include_start_date = Z_BVAL_PP(ht_entry); + } else { + return 0; + } + + period_obj->initialized = 1; + + return 1; +} + +/* {{{ proto DatePeriod::__set_state() +*/ +PHP_METHOD(DatePeriod, __set_state) +{ + php_period_obj *period_obj; + zval *array; + HashTable *myht; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { + RETURN_FALSE; + } + + myht = Z_ARRVAL_P(array); + + object_init_ex(return_value, date_ce_period); + period_obj = zend_object_store_get_object(return_value TSRMLS_CC); + if (!php_date_period_initialize_from_hash(period_obj, myht TSRMLS_CC)) { + php_error(E_ERROR, "Invalid serialization data for DatePeriod object"); + } +} +/* }}} */ + +/* {{{ proto DatePeriod::__wakeup() +*/ +PHP_METHOD(DatePeriod, __wakeup) +{ + zval *object = getThis(); + php_period_obj *period_obj; + HashTable *myht; + + period_obj = zend_object_store_get_object(object TSRMLS_CC); + + myht = Z_OBJPROP_P(object); + + if (!php_date_period_initialize_from_hash(period_obj, myht TSRMLS_CC)) { + php_error(E_ERROR, "Invalid serialization data for DatePeriod object"); + } +} +/* }}} */ + +/* {{{ date_period_read_property */ +static zval *date_period_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) +{ + zval *zv; + if (type != BP_VAR_IS && type != BP_VAR_R) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Retrieval of DatePeriod properties for modification is unsupported"); + } + + Z_OBJPROP_P(object); /* build properties hash table */ + + zv = std_object_handlers.read_property(object, member, type, key TSRMLS_CC); + if (Z_TYPE_P(zv) == IS_OBJECT && Z_OBJ_HANDLER_P(zv, clone_obj)) { + /* defensive copy */ + zend_object_value zov = Z_OBJ_HANDLER_P(zv, clone_obj)(zv TSRMLS_CC); + MAKE_STD_ZVAL(zv); + Z_TYPE_P(zv) = IS_OBJECT; + Z_OBJVAL_P(zv) = zov; + } + + return zv; +} +/* }}} */ + +/* {{{ date_period_write_property */ +static void date_period_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) +{ + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Writing to DatePeriod properties is unsupported"); +} +/* }}} */ + + /* * Local variables: * tab-width: 4 diff --git a/ext/date/php_date.h b/ext/date/php_date.h index 3af3fa42ede..efae0a1db8e 100644 --- a/ext/date/php_date.h +++ b/ext/date/php_date.h @@ -101,6 +101,8 @@ PHP_FUNCTION(date_interval_format); PHP_FUNCTION(date_interval_create_from_date_string); PHP_METHOD(DatePeriod, __construct); +PHP_METHOD(DatePeriod, __wakeup); +PHP_METHOD(DatePeriod, __set_state); /* Options and Configuration */ PHP_FUNCTION(date_default_timezone_set); diff --git a/ext/date/tests/bug45682.phpt b/ext/date/tests/bug45682.phpt index d8bbfc5a042..094c7fdf45b 100644 --- a/ext/date/tests/bug45682.phpt +++ b/ext/date/tests/bug45682.phpt @@ -11,8 +11,8 @@ $other = new DateTime("31-July-2008"); $diff = date_diff($date, $other); var_dump($diff); ---EXPECT-- -object(DateInterval)#3 (8) { +--EXPECTF-- +object(DateInterval)#%d (15) { ["y"]=> int(0) ["m"]=> @@ -25,8 +25,22 @@ object(DateInterval)#3 (8) { int(0) ["s"]=> int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) ["invert"]=> int(0) ["days"]=> - int(3) + string(1) "3" + ["special_type"]=> + int(0) + ["special_amount"]=> + string(1) "0" + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) } diff --git a/ext/date/tests/bug48678.phpt b/ext/date/tests/bug48678.phpt index e2cb724f761..253cb84ce6b 100644 --- a/ext/date/tests/bug48678.phpt +++ b/ext/date/tests/bug48678.phpt @@ -15,8 +15,15 @@ DateInterval Object [h] => 12 [i] => 30 [s] => 5 + [weekday] => 0 + [weekday_behavior] => 0 + [first_last_day_of] => 0 [invert] => 0 - [days] =>%s + [days] => + [special_type] => 0 + [special_amount] => 0 + [have_weekday_relative] => 0 + [have_special_relative] => 0 ) DateInterval Object ( @@ -26,6 +33,13 @@ DateInterval Object [h] => 12 [i] => 30 [s] => 5 + [weekday] => 0 + [weekday_behavior] => 0 + [first_last_day_of] => 0 [invert] => 0 - [days] =>%s + [days] => 0 + [special_type] => 0 + [special_amount] => 0 + [have_weekday_relative] => 0 + [have_special_relative] => 0 ) diff --git a/ext/date/tests/bug49081.phpt b/ext/date/tests/bug49081.phpt index f4f02903d14..31f73514819 100644 --- a/ext/date/tests/bug49081.phpt +++ b/ext/date/tests/bug49081.phpt @@ -17,6 +17,13 @@ DateInterval Object [h] => 4 [i] => 0 [s] => 0 + [weekday] => 0 + [weekday_behavior] => 0 + [first_last_day_of] => 0 [invert] => 0 [days] => 30 + [special_type] => 0 + [special_amount] => 0 + [have_weekday_relative] => 0 + [have_special_relative] => 0 ) diff --git a/ext/date/tests/bug49778.phpt b/ext/date/tests/bug49778.phpt index 67c8e27f91c..cc52a23b254 100644 --- a/ext/date/tests/bug49778.phpt +++ b/ext/date/tests/bug49778.phpt @@ -8,7 +8,7 @@ echo $i->format("%d"), "\n"; echo $i->format("%a"), "\n"; ?> --EXPECT-- -object(DateInterval)#1 (8) { +object(DateInterval)#1 (15) { ["y"]=> int(0) ["m"]=> @@ -21,10 +21,24 @@ object(DateInterval)#1 (8) { int(0) ["s"]=> int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) ["invert"]=> int(0) ["days"]=> bool(false) + ["special_type"]=> + int(0) + ["special_amount"]=> + string(1) "0" + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) } 7 (unknown) diff --git a/ext/date/tests/bug52113.phpt b/ext/date/tests/bug52113.phpt index a7d9339d13d..226dae5f26c 100644 --- a/ext/date/tests/bug52113.phpt +++ b/ext/date/tests/bug52113.phpt @@ -32,7 +32,7 @@ var_dump($unser, $p); ?> --EXPECT-- -object(DateInterval)#3 (8) { +object(DateInterval)#3 (15) { ["y"]=> int(0) ["m"]=> @@ -45,12 +45,26 @@ object(DateInterval)#3 (8) { int(0) ["s"]=> int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) ["invert"]=> int(0) ["days"]=> + string(1) "0" + ["special_type"]=> + int(0) + ["special_amount"]=> + string(1) "0" + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> int(0) } -string(128) "O:12:"DateInterval":8:{s:1:"y";i:0;s:1:"m";i:0;s:1:"d";i:0;s:1:"h";i:4;s:1:"i";i:0;s:1:"s";i:0;s:6:"invert";i:0;s:4:"days";i:0;}" +string(328) "O:12:"DateInterval":15:{s:1:"y";i:0;s:1:"m";i:0;s:1:"d";i:0;s:1:"h";i:4;s:1:"i";i:0;s:1:"s";i:0;s:7:"weekday";i:0;s:16:"weekday_behavior";i:0;s:17:"first_last_day_of";i:0;s:6:"invert";i:0;s:4:"days";s:1:"0";s:12:"special_type";i:0;s:14:"special_amount";s:1:"0";s:21:"have_weekday_relative";i:0;s:21:"have_special_relative";i:0;}" DateInterval::__set_state(array( 'y' => 0, 'm' => 0, @@ -58,9 +72,16 @@ DateInterval::__set_state(array( 'h' => 4, 'i' => 0, 's' => 0, + 'weekday' => 0, + 'weekday_behavior' => 0, + 'first_last_day_of' => 0, 'invert' => 0, - 'days' => 0, -))object(DateInterval)#5 (8) { + 'days' => '0', + 'special_type' => 0, + 'special_amount' => '0', + 'have_weekday_relative' => 0, + 'have_special_relative' => 0, +))object(DateInterval)#5 (15) { ["y"]=> int(0) ["m"]=> @@ -73,14 +94,78 @@ DateInterval::__set_state(array( int(0) ["s"]=> int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) ["invert"]=> int(0) ["days"]=> + string(1) "0" + ["special_type"]=> + int(0) + ["special_amount"]=> + string(1) "0" + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> int(0) } -object(DatePeriod)#6 (0) { +object(DatePeriod)#6 (6) { + ["start"]=> + object(DateTime)#4 (3) { + ["date"]=> + string(19) "2003-01-02 08:00:00" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" + } + ["current"]=> + NULL + ["end"]=> + NULL + ["interval"]=> + object(DateInterval)#7 (15) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(0) + ["h"]=> + int(4) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + string(1) "0" + ["special_type"]=> + int(0) + ["special_amount"]=> + string(1) "0" + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) + } + ["recurrences"]=> + int(3) + ["include_start_date"]=> + bool(true) } -object(DateInterval)#4 (8) { +object(DateInterval)#8 (15) { ["y"]=> int(7) ["m"]=> @@ -93,10 +178,74 @@ object(DateInterval)#4 (8) { int(3) ["s"]=> int(2) + ["weekday"]=> + int(-1) + ["weekday_behavior"]=> + int(-1) + ["first_last_day_of"]=> + int(-1) ["invert"]=> int(1) ["days"]=> - int(2400) + string(4) "2400" + ["special_type"]=> + int(-1) + ["special_amount"]=> + string(2) "-1" + ["have_weekday_relative"]=> + int(-1) + ["have_special_relative"]=> + int(-1) } -object(DatePeriod)#7 (0) { +object(DatePeriod)#9 (6) { + ["start"]=> + object(DateTime)#6 (3) { + ["date"]=> + string(19) "2003-01-02 08:00:00" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" + } + ["current"]=> + NULL + ["end"]=> + NULL + ["interval"]=> + object(DateInterval)#7 (15) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(0) + ["h"]=> + int(4) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + string(1) "0" + ["special_type"]=> + int(0) + ["special_amount"]=> + string(1) "0" + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) + } + ["recurrences"]=> + int(3) + ["include_start_date"]=> + bool(true) } diff --git a/ext/date/tests/bug52738.phpt b/ext/date/tests/bug52738.phpt index fc1b6029e98..ea219f7c7c6 100644 --- a/ext/date/tests/bug52738.phpt +++ b/ext/date/tests/bug52738.phpt @@ -27,6 +27,13 @@ di Object [h] => 0 [i] => 0 [s] => 0 + [weekday] => 0 + [weekday_behavior] => 0 + [first_last_day_of] => 0 [invert] => 0 [days] => + [special_type] => 0 + [special_amount] => 0 + [have_weekday_relative] => 0 + [have_special_relative] => 0 ) diff --git a/ext/date/tests/bug52808.phpt b/ext/date/tests/bug52808.phpt index e031ac6ee35..e3b38bb5ffd 100644 --- a/ext/date/tests/bug52808.phpt +++ b/ext/date/tests/bug52808.phpt @@ -25,7 +25,7 @@ foreach($intervals as $iv) { echo "==DONE==\n"; ?> --EXPECTF-- -object(DateInterval)#%d (8) { +object(DateInterval)#%d (15) { ["y"]=> int(1) ["m"]=> @@ -38,12 +38,26 @@ object(DateInterval)#%d (8) { int(30) ["s"]=> int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) ["invert"]=> int(1) ["days"]=> - int(437) + string(3) "437" + ["special_type"]=> + int(0) + ["special_amount"]=> + string(1) "0" + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) } -object(DateInterval)#%d (8) { +object(DateInterval)#%d (15) { ["y"]=> int(0) ["m"]=> @@ -56,12 +70,26 @@ object(DateInterval)#%d (8) { int(30) ["s"]=> int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) ["invert"]=> int(0) ["days"]=> - int(294) + string(3) "294" + ["special_type"]=> + int(0) + ["special_amount"]=> + string(1) "0" + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) } -object(DateInterval)#%d (8) { +object(DateInterval)#%d (15) { ["y"]=> int(0) ["m"]=> @@ -74,10 +102,24 @@ object(DateInterval)#%d (8) { int(30) ["s"]=> int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) ["invert"]=> int(0) ["days"]=> - int(294) + string(3) "294" + ["special_type"]=> + int(0) + ["special_amount"]=> + string(1) "0" + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) } DateInterval::__construct(): Failed to parse interval (2007-05-11T15:30:00Z/) DateInterval::__construct(): Failed to parse interval (2007-05-11T15:30:00Z) diff --git a/ext/date/tests/bug53437.phpt b/ext/date/tests/bug53437.phpt index f0898665385..7a282ab6c2e 100644 --- a/ext/date/tests/bug53437.phpt +++ b/ext/date/tests/bug53437.phpt @@ -1,7 +1,5 @@ --TEST-- -Bug #53437 (Crash when using unserialized DatePeriod instance) ---XFAIL-- -Bug #53437 Not fixed yet +Bug #53437 (Crash when using unserialized DatePeriod instance), variation 1 --FILE-- format('Y-m-d H:i:s')."\r\n"; } ?> +==DONE== --EXPECT-- +Original: +2010-01-01 00:00:00 +2010-01-02 00:00:00 +2010-01-03 00:00:00 + +object(DatePeriod)#1 (6) { + ["start"]=> + object(DateTime)#2 (3) { + ["date"]=> + string(19) "2010-01-01 00:00:00" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" + } + ["current"]=> + object(DateTime)#4 (3) { + ["date"]=> + string(19) "2010-01-04 00:00:00" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" + } + ["end"]=> + NULL + ["interval"]=> + object(DateInterval)#5 (15) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(1) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["special_type"]=> + int(0) + ["special_amount"]=> + string(1) "0" + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) + } + ["recurrences"]=> + int(3) + ["include_start_date"]=> + bool(true) +} +object(DatePeriod)#5 (6) { + ["start"]=> + object(DateTime)#10 (3) { + ["date"]=> + string(19) "2010-01-01 00:00:00" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" + } + ["current"]=> + object(DateTime)#7 (3) { + ["date"]=> + string(19) "2010-01-04 00:00:00" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" + } + ["end"]=> + NULL + ["interval"]=> + object(DateInterval)#8 (15) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(1) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + string(1) "0" + ["special_type"]=> + int(0) + ["special_amount"]=> + string(1) "0" + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) + } + ["recurrences"]=> + int(3) + ["include_start_date"]=> + bool(true) +} +Unserialized: +2010-01-01 00:00:00 +2010-01-02 00:00:00 +2010-01-03 00:00:00 +==DONE== diff --git a/ext/date/tests/bug53437_var1.phpt b/ext/date/tests/bug53437_var1.phpt new file mode 100644 index 00000000000..f1f9843d5ee --- /dev/null +++ b/ext/date/tests/bug53437_var1.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #53437 (Crash when using unserialized DatePeriod instance), variation 2 +--FILE-- + +==DONE== +--EXPECTF-- +Fatal error: Invalid serialization data for DatePeriod object in %sbug53437_var1.php on line %d diff --git a/ext/date/tests/bug53437_var2.phpt b/ext/date/tests/bug53437_var2.phpt new file mode 100644 index 00000000000..70565960efb --- /dev/null +++ b/ext/date/tests/bug53437_var2.phpt @@ -0,0 +1,80 @@ +--TEST-- +Bug #53437 DateInterval basic serialization +--FILE-- + +==DONE== +--EXPECT-- +object(DateInterval)#1 (15) { + ["y"]=> + int(2) + ["m"]=> + int(0) + ["d"]=> + int(4) + ["h"]=> + int(6) + ["i"]=> + int(8) + ["s"]=> + int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["special_type"]=> + int(0) + ["special_amount"]=> + string(1) "0" + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) +} +object(DateInterval)#2 (15) { + ["y"]=> + int(2) + ["m"]=> + int(0) + ["d"]=> + int(4) + ["h"]=> + int(6) + ["i"]=> + int(8) + ["s"]=> + int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + string(1) "0" + ["special_type"]=> + int(0) + ["special_amount"]=> + string(1) "0" + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) +} +==DONE== diff --git a/ext/date/tests/bug53437_var3.phpt b/ext/date/tests/bug53437_var3.phpt new file mode 100644 index 00000000000..06f68df61ff --- /dev/null +++ b/ext/date/tests/bug53437_var3.phpt @@ -0,0 +1,45 @@ +--TEST-- +Bug #53437 DateInterval unserialize bad data +--FILE-- + +==DONE== +--EXPECT-- +object(DateInterval)#1 (15) { + ["y"]=> + int(2) + ["m"]=> + int(0) + ["d"]=> + int(0) + ["h"]=> + int(6) + ["i"]=> + int(8) + ["s"]=> + int(0) + ["weekday"]=> + int(10) + ["weekday_behavior"]=> + int(10) + ["first_last_day_of"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + string(1) "0" + ["special_type"]=> + int(0) + ["special_amount"]=> + string(19) "9223372036854775807" + ["have_weekday_relative"]=> + int(9) + ["have_special_relative"]=> + int(0) +} +==DONE== diff --git a/ext/date/tests/date_diff1.phpt b/ext/date/tests/date_diff1.phpt index cf32fcbf3ba..3f3d1da7a80 100644 --- a/ext/date/tests/date_diff1.phpt +++ b/ext/date/tests/date_diff1.phpt @@ -28,7 +28,7 @@ object(DateTime)#2 (3) { ["timezone"]=> string(3) "EDT" } -object(DateInterval)#3 (8) { +object(DateInterval)#3 (15) { ["y"]=> int(0) ["m"]=> @@ -41,8 +41,22 @@ object(DateInterval)#3 (8) { int(19) ["s"]=> int(40) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) ["invert"]=> int(0) ["days"]=> - int(33) + string(2) "33" + ["special_type"]=> + int(0) + ["special_amount"]=> + string(1) "0" + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) } From 8d35170c5fe9b9c0c864b7a6c4dc6b0149809569 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 15 Mar 2013 21:03:05 +0400 Subject: [PATCH 137/276] Renamed ZendOptimizerPlus.so into opcache.so --- README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README b/README index bbcfbbf0e77..e7df8769b67 100644 --- a/README +++ b/README @@ -25,11 +25,11 @@ Quick Install - Install - make install # this will copy ZendOptimizerPlus.so into PHP extension directory + make install # this will copy opcache.so into PHP extension directory - Edit php.ini - zend_extension=/...full path.../ZendOptimizerPlus.so + zend_extension=/...full path.../opcache.so NOTE: In case you are going to use Zend Optimizer+ together with Xdebug, be sure that Xdebug is loaded after Optimizer+. "php -v" must show Xdebug From b903d2d6cdf9a9efac181a21e95ea93dc8a864dd Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Fri, 15 Mar 2013 19:04:40 +0100 Subject: [PATCH 138/276] Backported patch for #64370 --- NEWS | 5 + ext/standard/tests/bug64370_var1.phpt | 26 ++++++ ext/standard/tests/bug64370_var2.phpt | 23 +++++ win32/globals.c | 2 - win32/php_win32_globals.h | 4 - win32/time.c | 129 ++++++++------------------ 6 files changed, 94 insertions(+), 95 deletions(-) create mode 100644 ext/standard/tests/bug64370_var1.phpt create mode 100644 ext/standard/tests/bug64370_var2.phpt diff --git a/NEWS b/NEWS index fb877c01853..41f5eab4e77 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,11 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2013, PHP 5.3.24 + +- Core + . Fixed bug #64370 (microtime(true) less than $_SERVER['REQUEST_TIME_FLOAT']). + (Anatol) + - PCRE: . Merged PCRE 8.32). (Anatol) diff --git a/ext/standard/tests/bug64370_var1.phpt b/ext/standard/tests/bug64370_var1.phpt new file mode 100644 index 00000000000..ff64d616167 --- /dev/null +++ b/ext/standard/tests/bug64370_var1.phpt @@ -0,0 +1,26 @@ +--TEST-- +Test bug #64370 microtime(true) less than $_SERVER['REQUEST_TIME_FLOAT'] +--SKIPIF-- += 0)) . "\n"; +?> +===DONE=== +--EXPECTF-- +$_SERVER['REQUEST_TIME']: %d +$_SERVER['REQUEST_TIME_FLOAT']: %f +time(): %d +microtime(true): %f +created in %f ms +1 +===DONE=== diff --git a/ext/standard/tests/bug64370_var2.phpt b/ext/standard/tests/bug64370_var2.phpt new file mode 100644 index 00000000000..d0d3590ea7b --- /dev/null +++ b/ext/standard/tests/bug64370_var2.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test bug #64370 sequential microtime(true) calls +--FILE-- + $i++) { + $m0 = microtime(true); + $m1 = microtime(true); + $d = $m1 - $m0; + + /*echo "$d\n";*/ + + if ($d < 0) { + die("failed in {$i}th iteration"); + } +} +echo "ok\n"; +?> +===DONE=== +--EXPECT-- +ok +===DONE=== diff --git a/win32/globals.c b/win32/globals.c index 1bbb3b4481d..b381cc12371 100644 --- a/win32/globals.c +++ b/win32/globals.c @@ -65,8 +65,6 @@ PHP_RSHUTDOWN_FUNCTION(win32_core_globals) ; closelog(); - wg->starttime.tv_sec = 0; - wg->lasttime = 0; return SUCCESS; } diff --git a/win32/php_win32_globals.h b/win32/php_win32_globals.h index 1686e5df63e..b2b07f68e18 100644 --- a/win32/php_win32_globals.h +++ b/win32/php_win32_globals.h @@ -38,10 +38,6 @@ struct _php_win32_core_globals { char *log_header; HANDLE log_source; - /* time */ - struct timeval starttime; - __int64 lasttime, freq; - HKEY registry_key; HANDLE registry_event; HashTable *registry_directories; diff --git a/win32/time.c b/win32/time.c index 391a8a81e99..77e4504cd12 100644 --- a/win32/time.c +++ b/win32/time.c @@ -12,13 +12,6 @@ /* $Id$ */ - /** - * - * 04-Feb-2001 - * - Added patch by "Vanhanen, Reijo" - * Improves accuracy of msec - */ - /* Include stuff ************************************************************ */ #include @@ -32,98 +25,56 @@ #include #include "php_win32_globals.h" -int getfilesystemtime(struct timeval *time_Info) +typedef VOID (WINAPI *MyGetSystemTimeAsFileTime)(LPFILETIME lpSystemTimeAsFileTime); + +static MyGetSystemTimeAsFileTime get_time_func(void) { - FILETIME ft; - __int64 ff; - ULARGE_INTEGER convFromft; + MyGetSystemTimeAsFileTime timefunc = NULL; + HMODULE hMod = LoadLibrary("kernel32.dll"); - GetSystemTimeAsFileTime(&ft); /* 100 ns blocks since 01-Jan-1641 */ - /* resolution seems to be 0.01 sec */ - /* - * Do not cast a pointer to a FILETIME structure to either a - * ULARGE_INTEGER* or __int64* value because it can cause alignment faults on 64-bit Windows. - * via http://technet.microsoft.com/en-us/library/ms724284(v=vs.85).aspx - */ - convFromft.HighPart = ft.dwHighDateTime; - convFromft.LowPart = ft.dwLowDateTime; - ff = convFromft.QuadPart; + if (hMod) { + /* Max possible resolution <1us, win8/server2012 */ + timefunc = (MyGetSystemTimeAsFileTime)GetProcAddress(hMod, "GetSystemTimePreciseAsFileTime"); - time_Info->tv_sec = (int)(ff/(__int64)10000000-(__int64)11644473600); - time_Info->tv_usec = (int)(ff % 10000000)/10; - return 0; + if(!timefunc) { + /* 100ns blocks since 01-Jan-1641 */ + timefunc = (MyGetSystemTimeAsFileTime)GetProcAddress(hMod, "GetSystemTimeAsFileTime"); + } + } + + return timefunc; } - +int getfilesystemtime(struct timeval *tv) +{ + FILETIME ft; + unsigned __int64 ff = 0; + MyGetSystemTimeAsFileTime timefunc; + + timefunc = get_time_func(); + if (timefunc) { + timefunc(&ft); + } else { + GetSystemTimeAsFileTime(&ft); + } + + ff |= ft.dwHighDateTime; + ff <<= 32; + ff |= ft.dwLowDateTime; + ff /= 10; /* convert to microseconds */ + ff -= 11644473600000000Ui64; /* convert to unix epoch */ + + tv->tv_sec = (long)(ff / 1000000UL); + tv->tv_usec = (long)(ff % 1000000UL); + + return 0; +} PHPAPI int gettimeofday(struct timeval *time_Info, struct timezone *timezone_Info) { - __int64 timer; - LARGE_INTEGER li; - BOOL b; - double dt; - TSRMLS_FETCH(); - /* Get the time, if they want it */ if (time_Info != NULL) { - if (PW32G(starttime).tv_sec == 0) { - b = QueryPerformanceFrequency(&li); - if (!b) { - PW32G(starttime).tv_sec = -1; - } - else { - PW32G(freq) = li.QuadPart; - b = QueryPerformanceCounter(&li); - if (!b) { - PW32G(starttime).tv_sec = -1; - } - else { - getfilesystemtime(&PW32G(starttime)); - timer = li.QuadPart; - dt = (double)timer/PW32G(freq); - PW32G(starttime).tv_usec -= (int)((dt-(int)dt)*1000000); - if (PW32G(starttime).tv_usec < 0) { - PW32G(starttime).tv_usec += 1000000; - --PW32G(starttime).tv_sec; - } - PW32G(starttime).tv_sec -= (int)dt; - } - } - } - if (PW32G(starttime).tv_sec > 0) { - b = QueryPerformanceCounter(&li); - if (!b) { - PW32G(starttime).tv_sec = -1; - } - else { - timer = li.QuadPart; - if (timer < PW32G(lasttime)) { - getfilesystemtime(time_Info); - dt = (double)timer/PW32G(freq); - PW32G(starttime) = *time_Info; - PW32G(starttime).tv_usec -= (int)((dt-(int)dt)*1000000); - if (PW32G(starttime).tv_usec < 0) { - PW32G(starttime).tv_usec += 1000000; - --PW32G(starttime).tv_sec; - } - PW32G(starttime).tv_sec -= (int)dt; - } - else { - PW32G(lasttime) = timer; - dt = (double)timer/PW32G(freq); - time_Info->tv_sec = PW32G(starttime).tv_sec + (int)dt; - time_Info->tv_usec = PW32G(starttime).tv_usec + (int)((dt-(int)dt)*1000000); - if (time_Info->tv_usec >= 1000000) { - time_Info->tv_usec -= 1000000; - ++time_Info->tv_sec; - } - } - } - } - if (PW32G(starttime).tv_sec < 0) { - getfilesystemtime(time_Info); - } - + getfilesystemtime(time_Info); } /* Get the timezone, if they want it */ if (timezone_Info != NULL) { From 73c38eca5a7f3c68e1122aee001409dbd615c5a8 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Fri, 15 Mar 2013 19:11:53 +0100 Subject: [PATCH 139/276] updated NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index ac0c94346ba..0176a93de21 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2013, PHP 5.4.14 +- Core + . Fixed bug #64370 (microtime(true) less than $_SERVER['REQUEST_TIME_FLOAT']). + (Anatol) + - PCRE: . Merged PCRE 8.32. (Anatol) From f8b91d9acff10ede7bd3f2bc631794a3abef8ff7 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Fri, 15 Mar 2013 21:22:35 +0100 Subject: [PATCH 140/276] Fixed bug #62852 Unserialize Invalid Date crash Error handling is the same as in bug #53437, E_ERROR if we expect an invalid object. --- NEWS | 1 + ext/date/php_date.c | 25 +++++++++++++++++-------- ext/date/tests/bug62852.phpt | 26 ++------------------------ ext/date/tests/bug62852_var2.phpt | 25 +++++++++++++++++++++++++ ext/date/tests/bug62852_var3.phpt | 25 +++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 32 deletions(-) create mode 100644 ext/date/tests/bug62852_var2.phpt create mode 100644 ext/date/tests/bug62852_var3.phpt diff --git a/NEWS b/NEWS index 9dc334d6240..46e69d6228d 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,7 @@ PHP NEWS - DateTime . Fixed bug #53437 (Crash when using unserialized DatePeriod instance). (Gustavo, Derick, Anatol) + . Fixed bug #62852 (Unserialize Invalid Date causes crash). (Anatol) 07 Mar 2013, PHP 5.5.0 Alpha 6 diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 52241234cab..b454dd0f06d 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -2674,13 +2674,15 @@ static int php_date_initialize_from_hash(zval **return_value, php_date_obj **dat case TIMELIB_ZONETYPE_OFFSET: case TIMELIB_ZONETYPE_ABBR: { char *tmp = emalloc(Z_STRLEN_PP(z_date) + Z_STRLEN_PP(z_timezone) + 2); + int ret; snprintf(tmp, Z_STRLEN_PP(z_date) + Z_STRLEN_PP(z_timezone) + 2, "%s %s", Z_STRVAL_PP(z_date), Z_STRVAL_PP(z_timezone)); - php_date_initialize(*dateobj, tmp, Z_STRLEN_PP(z_date) + Z_STRLEN_PP(z_timezone) + 1, NULL, NULL, 0 TSRMLS_CC); + ret = php_date_initialize(*dateobj, tmp, Z_STRLEN_PP(z_date) + Z_STRLEN_PP(z_timezone) + 1, NULL, NULL, 0 TSRMLS_CC); efree(tmp); - return 1; + return 1 == ret; } - case TIMELIB_ZONETYPE_ID: + case TIMELIB_ZONETYPE_ID: { + int ret; convert_to_string(*z_timezone); tzi = php_date_parse_tzfile(Z_STRVAL_PP(z_timezone), DATE_TIMEZONEDB TSRMLS_CC); @@ -2691,9 +2693,10 @@ static int php_date_initialize_from_hash(zval **return_value, php_date_obj **dat tzobj->tzi.tz = tzi; tzobj->initialized = 1; - php_date_initialize(*dateobj, Z_STRVAL_PP(z_date), Z_STRLEN_PP(z_date), NULL, tmp_obj, 0 TSRMLS_CC); + ret = php_date_initialize(*dateobj, Z_STRVAL_PP(z_date), Z_STRLEN_PP(z_date), NULL, tmp_obj, 0 TSRMLS_CC); zval_ptr_dtor(&tmp_obj); - return 1; + return 1 == ret; + } } } } @@ -2717,7 +2720,9 @@ PHP_METHOD(DateTime, __set_state) php_date_instantiate(date_ce_date, return_value TSRMLS_CC); dateobj = (php_date_obj *) zend_object_store_get_object(return_value TSRMLS_CC); - php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC); + if (!php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC)) { + php_error(E_ERROR, "Invalid serialization data for DateTime object"); + } } /* }}} */ @@ -2737,7 +2742,9 @@ PHP_METHOD(DateTimeImmutable, __set_state) php_date_instantiate(date_ce_immutable, return_value TSRMLS_CC); dateobj = (php_date_obj *) zend_object_store_get_object(return_value TSRMLS_CC); - php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC); + if (!php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC)) { + php_error(E_ERROR, "Invalid serialization data for DateTimeImmutable object"); + } } /* }}} */ @@ -2753,7 +2760,9 @@ PHP_METHOD(DateTime, __wakeup) myht = Z_OBJPROP_P(object); - php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC); + if (!php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC)) { + php_error(E_ERROR, "Invalid serialization data for DateTime object"); + } } /* }}} */ diff --git a/ext/date/tests/bug62852.phpt b/ext/date/tests/bug62852.phpt index 26de5102151..7013a3f97c5 100644 --- a/ext/date/tests/bug62852.phpt +++ b/ext/date/tests/bug62852.phpt @@ -1,36 +1,14 @@ --TEST-- -Bug #62852 (Unserialize invalid DateTime causes crash) +Bug #62852 (Unserialize invalid DateTime causes crash), variation 1 --INI-- date.timezone=GMT ---XFAIL-- -bug is not fixed yet --FILE-- --EXPECTF-- -okey +Fatal error: Invalid serialization data for DateTime object in %sbug62852.php on line %d diff --git a/ext/date/tests/bug62852_var2.phpt b/ext/date/tests/bug62852_var2.phpt new file mode 100644 index 00000000000..f93ba28ab1f --- /dev/null +++ b/ext/date/tests/bug62852_var2.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #62852 (Unserialize invalid DateTime causes crash), variation 2 +--INI-- +date.timezone=GMT +--FILE-- + Date: Sat, 16 Mar 2013 12:07:09 +0400 Subject: [PATCH 141/276] Fixed O+ testes --- ext/opcache/tests/001_cli.phpt | 14 +++++++------- ext/opcache/tests/bug64353.phpt | 4 ++-- ext/opcache/tests/issue0057.phpt | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ext/opcache/tests/001_cli.phpt b/ext/opcache/tests/001_cli.phpt index 6c42049038c..c51db23f56f 100644 --- a/ext/opcache/tests/001_cli.phpt +++ b/ext/opcache/tests/001_cli.phpt @@ -1,17 +1,17 @@ --TEST-- 001: O+ works in CLI --INI-- -zend_optimizerplus.enable=1 -zend_optimizerplus.enable_cli=1 +opcache.enable=1 +opcache.enable_cli=1 --SKIPIF-- --FILE-- --EXPECT-- bool(true) diff --git a/ext/opcache/tests/bug64353.phpt b/ext/opcache/tests/bug64353.phpt index a4e1dabc250..463b6ee2281 100644 --- a/ext/opcache/tests/bug64353.phpt +++ b/ext/opcache/tests/bug64353.phpt @@ -2,8 +2,8 @@ Bug #64353 (Built-in classes can be unavailable with dynamic includes and Optimizer+) --INI-- allow_url_include=1 -zend_optimizerplus.enable=1 -zend_optimizerplus.enable_cli=1 +opcache.enable=1 +opcache.enable_cli=1 --SKIPIF-- --FILE-- diff --git a/ext/opcache/tests/issue0057.phpt b/ext/opcache/tests/issue0057.phpt index 1ef3cbb8e26..49e9156f155 100644 --- a/ext/opcache/tests/issue0057.phpt +++ b/ext/opcache/tests/issue0057.phpt @@ -1,9 +1,9 @@ --TEST-- ISSUE #57 (segfaults in drupal7) --INI-- -zend_optimizerplus.enable=1 -zend_optimizerplus.enable_cli=1 -zend_optimizerplus.optimization_level=-1 +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 --SKIPIF-- --FILE-- From 92430bcf5dd76bf9b12363693efcc471b3527618 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Sat, 16 Mar 2013 16:08:11 +0400 Subject: [PATCH 142/276] Fixed compatibility with ext/phar --- ext/opcache/ZendAccelerator.c | 4 +- ext/opcache/zend_accelerator_module.c | 57 ++++++++++++++------------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 17eac09caf8..daf80cea29f 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -1221,7 +1221,9 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han } #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO - if (file_handle->type == ZEND_HANDLE_STREAM) { + if (file_handle->type == ZEND_HANDLE_STREAM && + (!strstr(file_handle->filename, ".phar") || + strstr(file_handle->filename, "://"))) { char *buf; size_t size; diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index e55884aba1e..11dd7d3220c 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -37,6 +37,10 @@ #define MAX_ACCEL_FILES 100000 #define TOKENTOSTR(X) #X +static void (*orig_file_exists)(INTERNAL_FUNCTION_PARAMETERS) = NULL; +static void (*orig_is_file)(INTERNAL_FUNCTION_PARAMETERS) = NULL; +static void (*orig_is_readable)(INTERNAL_FUNCTION_PARAMETERS) = NULL; + /* User functions */ static ZEND_FUNCTION(opcache_reset); @@ -280,50 +284,44 @@ static int filename_is_in_cache(char *filename, int filename_len TSRMLS_DC) return 0; } -static void accel_file_in_cache(int type, INTERNAL_FUNCTION_PARAMETERS) +static int accel_file_in_cache(INTERNAL_FUNCTION_PARAMETERS) { - char *filename; - int filename_len; -#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO zval **zfilename; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &zfilename) == FAILURE) { - WRONG_PARAM_COUNT; + if (ZEND_NUM_ARGS() != 1 || + zend_get_parameters_array_ex(1, &zfilename) == FAILURE || + Z_TYPE_PP(zfilename) != IS_STRING || + Z_STRLEN_PP(zfilename) == 0) { + return 0; } - convert_to_string_ex(zfilename); - filename = Z_STRVAL_PP(zfilename); - filename_len = Z_STRLEN_PP(zfilename); -#elif ZEND_EXTENSION_API_NO == PHP_5_3_X_API_NO - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { - return; - } -#else - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) { - return; - } -#endif - if (filename_len > 0) { - if (filename_is_in_cache(filename, filename_len TSRMLS_CC)) { - RETURN_TRUE; - } - } - - php_stat(filename, filename_len, type, return_value TSRMLS_CC); + return filename_is_in_cache(Z_STRVAL_PP(zfilename), Z_STRLEN_PP(zfilename) TSRMLS_CC); } static void accel_file_exists(INTERNAL_FUNCTION_PARAMETERS) { - accel_file_in_cache(FS_EXISTS, INTERNAL_FUNCTION_PARAM_PASSTHRU); + if (accel_file_in_cache(INTERNAL_FUNCTION_PARAM_PASSTHRU)) { + RETURN_TRUE; + } else { + orig_file_exists(INTERNAL_FUNCTION_PARAM_PASSTHRU); + } } static void accel_is_file(INTERNAL_FUNCTION_PARAMETERS) { - accel_file_in_cache(FS_IS_FILE, INTERNAL_FUNCTION_PARAM_PASSTHRU); + if (accel_file_in_cache(INTERNAL_FUNCTION_PARAM_PASSTHRU)) { + RETURN_TRUE; + } else { + orig_is_file(INTERNAL_FUNCTION_PARAM_PASSTHRU); + } } static void accel_is_readable(INTERNAL_FUNCTION_PARAMETERS) { - accel_file_in_cache(FS_IS_R, INTERNAL_FUNCTION_PARAM_PASSTHRU); + if (accel_file_in_cache(INTERNAL_FUNCTION_PARAM_PASSTHRU)) { + RETURN_TRUE; + } else { + orig_is_readable(INTERNAL_FUNCTION_PARAM_PASSTHRU); + } } static ZEND_MINIT_FUNCTION(zend_accelerator) @@ -346,12 +344,15 @@ void zend_accel_override_file_functions(TSRMLS_D) if (ZCG(enabled) && accel_startup_ok && ZCG(accel_directives).file_override_enabled) { /* override file_exists */ if (zend_hash_find(CG(function_table), "file_exists", sizeof("file_exists"), (void **)&old_function) == SUCCESS) { + orig_file_exists = old_function->internal_function.handler; old_function->internal_function.handler = accel_file_exists; } if (zend_hash_find(CG(function_table), "is_file", sizeof("is_file"), (void **)&old_function) == SUCCESS) { + orig_is_file = old_function->internal_function.handler; old_function->internal_function.handler = accel_is_file; } if (zend_hash_find(CG(function_table), "is_readable", sizeof("is_readable"), (void **)&old_function) == SUCCESS) { + orig_is_readable = old_function->internal_function.handler; old_function->internal_function.handler = accel_is_readable; } } From e9641141aaad136757af06fddd6d870147ac2000 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Sat, 16 Mar 2013 16:11:00 +0400 Subject: [PATCH 143/276] Made test compatible with O+ --- Zend/tests/bug55156.phpt | 3 +++ Zend/tests/ns_026.phpt | 2 ++ ext/phar/tests/create_new_and_modify.phpt | 8 ++++++++ ext/phar/tests/delete_in_phar.phpt | 9 +++++++++ ext/phar/tests/delete_in_phar_confirm.phpt | 9 +++++++++ ext/phar/tests/tar/create_new_and_modify.phpt | 8 ++++++++ ext/phar/tests/tar/delete_in_phar.phpt | 8 ++++++++ ext/phar/tests/tar/delete_in_phar_confirm.phpt | 8 ++++++++ ext/phar/tests/zip/create_new_and_modify.phpt | 8 ++++++++ ext/phar/tests/zip/delete_in_phar.phpt | 8 ++++++++ ext/phar/tests/zip/delete_in_phar_confirm.phpt | 8 ++++++++ ext/reflection/tests/005.phpt | 3 +++ ext/reflection/tests/009.phpt | 3 +++ ext/reflection/tests/025.phpt | 3 +++ .../tests/ReflectionClass_getDocComment_001.phpt | 3 +++ .../tests/ReflectionFunction_getDocComment.001.phpt | 3 +++ .../tests/ReflectionMethod_getDocComment_basic.phpt | 3 +++ ext/reflection/tests/ReflectionProperty_basic2.phpt | 3 +++ .../tests/ReflectionProperty_getDocComment_basic.phpt | 3 +++ ext/reflection/tests/bug36308.phpt | 3 +++ run-tests.php | 1 + tests/output/ob_017.phpt | 2 ++ tests/output/ob_start_basic_004.phpt | 2 ++ 23 files changed, 111 insertions(+) diff --git a/Zend/tests/bug55156.phpt b/Zend/tests/bug55156.phpt index 6c0ff768d1c..7d75ce3e944 100644 --- a/Zend/tests/bug55156.phpt +++ b/Zend/tests/bug55156.phpt @@ -1,5 +1,8 @@ --TEST-- Bug #55156 (ReflectionClass::getDocComment() returns comment even though the class has none) +--INI-- +opcache.save_comments=1 +opcache.load_comments=1 --FILE-- getSignature(); include $pname . '/a.php'; +if (function_exists("opcache_get_status")) { + $status = opcache_get_status(); + if ($status["opcache_enabled"]) { + ini_set("opcache.revalidate_freq", "0"); + sleep(2); + } +} + file_put_contents($pname .'/a.php', "modified!\n"); file_put_contents($pname .'/b.php', "another!\n"); diff --git a/ext/phar/tests/delete_in_phar.phpt b/ext/phar/tests/delete_in_phar.phpt index 4842d279133..d28f136f77b 100644 --- a/ext/phar/tests/delete_in_phar.phpt +++ b/ext/phar/tests/delete_in_phar.phpt @@ -15,6 +15,15 @@ $files = array(); $files['a.php'] = ''; $files['b.php'] = ''; $files['b/c.php'] = ''; + +if (function_exists("opcache_get_status")) { + $status = opcache_get_status(); + if ($status["opcache_enabled"]) { + ini_set("opcache.revalidate_freq", "0"); + sleep(2); + } +} + include 'files/phar_test.inc'; include $pname . '/a.php'; diff --git a/ext/phar/tests/delete_in_phar_confirm.phpt b/ext/phar/tests/delete_in_phar_confirm.phpt index 13a8d0db298..0d4eb1e2aa2 100644 --- a/ext/phar/tests/delete_in_phar_confirm.phpt +++ b/ext/phar/tests/delete_in_phar_confirm.phpt @@ -15,6 +15,15 @@ $files = array(); $files['a.php'] = ''; $files['b.php'] = ''; $files['b/c.php'] = ''; + +if (function_exists("opcache_get_status")) { + $status = opcache_get_status(); + if ($status["opcache_enabled"]) { + ini_set("opcache.revalidate_freq", "0"); + sleep(2); + } +} + include 'files/phar_test.inc'; include $pname . '/a.php'; diff --git a/ext/phar/tests/tar/create_new_and_modify.phpt b/ext/phar/tests/tar/create_new_and_modify.phpt index 8062fda769b..905bfabc828 100644 --- a/ext/phar/tests/tar/create_new_and_modify.phpt +++ b/ext/phar/tests/tar/create_new_and_modify.phpt @@ -15,6 +15,14 @@ $pname = 'phar://' . $fname; file_put_contents($pname . '/a.php', "brand new!\n"); +if (function_exists("opcache_get_status")) { + $status = opcache_get_status(); + if ($status["opcache_enabled"]) { + ini_set("opcache.revalidate_freq", "0"); + sleep(2); + } +} + $phar = new Phar($fname); var_dump($phar->isFileFormat(Phar::TAR)); $sig1 = md5_file($fname); diff --git a/ext/phar/tests/tar/delete_in_phar.phpt b/ext/phar/tests/tar/delete_in_phar.phpt index 91ef4a20462..1982b6bda9c 100644 --- a/ext/phar/tests/tar/delete_in_phar.phpt +++ b/ext/phar/tests/tar/delete_in_phar.phpt @@ -18,6 +18,14 @@ $phar['b/c.php'] = ''; $phar->setStub(''); $phar->stopBuffering(); +if (function_exists("opcache_get_status")) { + $status = opcache_get_status(); + if ($status["opcache_enabled"]) { + ini_set("opcache.revalidate_freq", "0"); + sleep(2); + } +} + include $alias . '/a.php'; include $alias . '/b.php'; include $alias . '/b/c.php'; diff --git a/ext/phar/tests/tar/delete_in_phar_confirm.phpt b/ext/phar/tests/tar/delete_in_phar_confirm.phpt index 707bcbd0eda..7593ebc1fb0 100644 --- a/ext/phar/tests/tar/delete_in_phar_confirm.phpt +++ b/ext/phar/tests/tar/delete_in_phar_confirm.phpt @@ -18,6 +18,14 @@ $phar['b/c.php'] = ''; $phar->setStub(''); $phar->stopBuffering(); +if (function_exists("opcache_get_status")) { + $status = opcache_get_status(); + if ($status["opcache_enabled"]) { + ini_set("opcache.revalidate_freq", "0"); + sleep(2); + } +} + include $alias . '/a.php'; include $alias . '/b.php'; include $alias . '/b/c.php'; diff --git a/ext/phar/tests/zip/create_new_and_modify.phpt b/ext/phar/tests/zip/create_new_and_modify.phpt index 5a3ec3317b3..55d69cca0e2 100644 --- a/ext/phar/tests/zip/create_new_and_modify.phpt +++ b/ext/phar/tests/zip/create_new_and_modify.phpt @@ -15,6 +15,14 @@ $pname = 'phar://' . $fname; file_put_contents($pname . '/a.php', "brand new!\n"); +if (function_exists("opcache_get_status")) { + $status = opcache_get_status(); + if ($status["opcache_enabled"]) { + ini_set("opcache.revalidate_freq", "0"); + sleep(2); + } +} + $phar = new Phar($fname); var_dump($phar->isFileFormat(Phar::ZIP)); $sig1 = md5_file($fname); diff --git a/ext/phar/tests/zip/delete_in_phar.phpt b/ext/phar/tests/zip/delete_in_phar.phpt index b7bda7ca4b6..f01280013f0 100644 --- a/ext/phar/tests/zip/delete_in_phar.phpt +++ b/ext/phar/tests/zip/delete_in_phar.phpt @@ -18,6 +18,14 @@ $phar['b/c.php'] = ''; $phar->setStub(''); $phar->stopBuffering(); +if (function_exists("opcache_get_status")) { + $status = opcache_get_status(); + if ($status["opcache_enabled"]) { + ini_set("opcache.revalidate_freq", "0"); + sleep(2); + } +} + include $alias . '/a.php'; include $alias . '/b.php'; include $alias . '/b/c.php'; diff --git a/ext/phar/tests/zip/delete_in_phar_confirm.phpt b/ext/phar/tests/zip/delete_in_phar_confirm.phpt index fdd0b42b5cb..00804991770 100644 --- a/ext/phar/tests/zip/delete_in_phar_confirm.phpt +++ b/ext/phar/tests/zip/delete_in_phar_confirm.phpt @@ -18,6 +18,14 @@ $phar['b/c.php'] = ''; $phar->setStub(''); $phar->stopBuffering(); +if (function_exists("opcache_get_status")) { + $status = opcache_get_status(); + if ($status["opcache_enabled"]) { + ini_set("opcache.revalidate_freq", "0"); + sleep(2); + } +} + include $alias . '/a.php'; include $alias . '/b.php'; include $alias . '/b/c.php'; diff --git a/ext/reflection/tests/005.phpt b/ext/reflection/tests/005.phpt index f337e44ae68..e257699b6f8 100644 --- a/ext/reflection/tests/005.phpt +++ b/ext/reflection/tests/005.phpt @@ -1,5 +1,8 @@ --TEST-- ReflectionMethod::getDocComment() uses wrong comment block +--INI-- +opcache.save_comments=1 +opcache.load_comments=1 --FILE-- +--INI-- +opcache.save_comments=1 +opcache.load_comments=1 --FILE-- Steve Seear +--INI-- +opcache.save_comments=1 +opcache.load_comments=1 --FILE-- Steve Seear +--INI-- +opcache.save_comments=1 +opcache.load_comments=1 --FILE-- Date: Sat, 16 Mar 2013 17:24:54 +0400 Subject: [PATCH 144/276] Fixed memory leaks --- ext/opcache/Optimizer/block_pass.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index 3d4bb0c1d27..d4299c8add6 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -1304,9 +1304,11 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra /* JMP L, L: JMP L1 -> JMP L1 */ /* JMP L, L: JMPZNZ L1,L2 -> JMPZNZ L1,L2 */ *last_op = *target; +#if ZEND_EXTENSION_API_NO < PHP_5_4_X_API_NO if (ZEND_OP1_TYPE(last_op) == IS_CONST) { zval_copy_ctor(&ZEND_OP1_LITERAL(last_op)); } +#endif del_source(block, block->op1_to); if (block->op1_to->op2_to) { block->op2_to = block->op1_to->op2_to; @@ -1332,9 +1334,11 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra target->opcode == ZEND_EXIT) { /* JMP L, L: RETURN to immediate RETURN */ *last_op = *target; +#if ZEND_EXTENSION_API_NO < PHP_5_4_X_API_NO if (ZEND_OP1_TYPE(last_op) == IS_CONST) { zval_copy_ctor(&ZEND_OP1_LITERAL(last_op)); } +#endif del_source(block, block->op1_to); block->op1_to = NULL; #if 0 From acd160530a3ef41403853fd983bef3082726b690 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 16 Mar 2013 23:14:06 +0800 Subject: [PATCH 145/276] Fix test after f8b91d9acff10ede7bd3f2bc631794a3abef8ff7 --- ext/date/tests/bug55397.phpt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/date/tests/bug55397.phpt b/ext/date/tests/bug55397.phpt index efc09b50479..13778a00b2c 100644 --- a/ext/date/tests/bug55397.phpt +++ b/ext/date/tests/bug55397.phpt @@ -7,5 +7,4 @@ date_default_timezone_set('Europe/Prague'); var_dump(unserialize('O:8:"DateTime":0:{}') == new DateTime); ?> --EXPECTF-- -Warning: %s: Trying to compare an incomplete DateTime object in %s on line %d -bool(false) +Fatal error: Invalid serialization data for DateTime object in %sbug55397.php on line %d From c1cf7538f07d8f905afbff5e82f4c727f6cb9fee Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 16 Mar 2013 22:58:47 +0800 Subject: [PATCH 146/276] Fixed test after nick previous fix --- ext/spl/tests/iterator_to_array_nonscalar_keys.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/spl/tests/iterator_to_array_nonscalar_keys.phpt b/ext/spl/tests/iterator_to_array_nonscalar_keys.phpt index a4cbcc3298f..4ca9485faf5 100644 --- a/ext/spl/tests/iterator_to_array_nonscalar_keys.phpt +++ b/ext/spl/tests/iterator_to_array_nonscalar_keys.phpt @@ -24,7 +24,7 @@ array(4) { int(0) [1]=> int(1) - [0]=> + [2]=> int(2) [""]=> int(3) From 62364e6e01092911fa11e6d28f9acc3ed9af07e8 Mon Sep 17 00:00:00 2001 From: Etienne Kneuss Date: Sat, 16 Mar 2013 18:19:14 +0100 Subject: [PATCH 147/276] Remove spurious int cast in between two longs --- ext/spl/spl_dllist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index 964ad994da0..38e6aaccd93 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -875,7 +875,7 @@ SPL_METHOD(SplDoublyLinkedList, offsetUnset) } intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - index = (int)spl_offset_convert_to_long(zindex TSRMLS_CC); + index = spl_offset_convert_to_long(zindex TSRMLS_CC); llist = intern->llist; if (index < 0 || index >= intern->llist->count) { From fa3fc711d3fb54bf1746138ffcf7f46426921204 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Sat, 16 Mar 2013 18:07:21 +0100 Subject: [PATCH 148/276] setting plausible default value for struct members especially for unsigned members so they don't casted to max unsigned --- ext/date/php_date.c | 30 +++++++++++++++--------------- ext/date/tests/bug52113.phpt | 6 +++--- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index b454dd0f06d..a073aa691ea 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -4006,14 +4006,14 @@ static int php_date_interval_initialize_from_hash(zval **return_value, php_inter { (*intobj)->diff = timelib_rel_time_ctor(); -#define PHP_DATE_INTERVAL_READ_PROPERTY(element, member, itype) \ +#define PHP_DATE_INTERVAL_READ_PROPERTY(element, member, itype, def) \ do { \ zval **z_arg = NULL; \ if (zend_hash_find(myht, element, strlen(element) + 1, (void**) &z_arg) == SUCCESS) { \ convert_to_long(*z_arg); \ (*intobj)->diff->member = (itype)Z_LVAL_PP(z_arg); \ } else { \ - (*intobj)->diff->member = (itype)-1; \ + (*intobj)->diff->member = (itype)def; \ } \ } while (0); @@ -4028,21 +4028,21 @@ static int php_date_interval_initialize_from_hash(zval **return_value, php_inter } \ } while (0); - PHP_DATE_INTERVAL_READ_PROPERTY("y", y, timelib_sll) - PHP_DATE_INTERVAL_READ_PROPERTY("m", m, timelib_sll) - PHP_DATE_INTERVAL_READ_PROPERTY("d", d, timelib_sll) - PHP_DATE_INTERVAL_READ_PROPERTY("h", h, timelib_sll) - PHP_DATE_INTERVAL_READ_PROPERTY("i", i, timelib_sll) - PHP_DATE_INTERVAL_READ_PROPERTY("s", s, timelib_sll) - PHP_DATE_INTERVAL_READ_PROPERTY("weekday", weekday, int) - PHP_DATE_INTERVAL_READ_PROPERTY("weekday_behavior", weekday_behavior, int) - PHP_DATE_INTERVAL_READ_PROPERTY("first_last_day_of", first_last_day_of, int) - PHP_DATE_INTERVAL_READ_PROPERTY("invert", invert, int); + PHP_DATE_INTERVAL_READ_PROPERTY("y", y, timelib_sll, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("m", m, timelib_sll, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("d", d, timelib_sll, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("h", h, timelib_sll, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("i", i, timelib_sll, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("s", s, timelib_sll, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("weekday", weekday, int, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("weekday_behavior", weekday_behavior, int, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("first_last_day_of", first_last_day_of, int, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("invert", invert, int, 0); PHP_DATE_INTERVAL_READ_PROPERTY_I64("days", days); - PHP_DATE_INTERVAL_READ_PROPERTY("special_type", special.type, unsigned int); + PHP_DATE_INTERVAL_READ_PROPERTY("special_type", special.type, unsigned int, 0); PHP_DATE_INTERVAL_READ_PROPERTY_I64("special_amount", special.amount); - PHP_DATE_INTERVAL_READ_PROPERTY("have_weekday_relative", have_weekday_relative, unsigned int); - PHP_DATE_INTERVAL_READ_PROPERTY("have_special_relative", have_special_relative, unsigned int); + PHP_DATE_INTERVAL_READ_PROPERTY("have_weekday_relative", have_weekday_relative, unsigned int, 0); + PHP_DATE_INTERVAL_READ_PROPERTY("have_special_relative", have_special_relative, unsigned int, 0); (*intobj)->initialized = 1; return 0; diff --git a/ext/date/tests/bug52113.phpt b/ext/date/tests/bug52113.phpt index 226dae5f26c..862e92e9615 100644 --- a/ext/date/tests/bug52113.phpt +++ b/ext/date/tests/bug52113.phpt @@ -189,13 +189,13 @@ object(DateInterval)#8 (15) { ["days"]=> string(4) "2400" ["special_type"]=> - int(-1) + int(0) ["special_amount"]=> string(2) "-1" ["have_weekday_relative"]=> - int(-1) + int(0) ["have_special_relative"]=> - int(-1) + int(0) } object(DatePeriod)#9 (6) { ["start"]=> From 07b1eaa6097903084be2abf0273dd1ed8e91b0d4 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Sun, 17 Mar 2013 10:40:59 +0400 Subject: [PATCH 149/276] Removed files that are neccessary only for standalone pecl branch --- ext/opcache/.gitignore | 87 -------------------------- ext/opcache/.travis.yml | 14 ----- ext/opcache/LICENSE | 68 -------------------- ext/opcache/package.xml | 134 ---------------------------------------- 4 files changed, 303 deletions(-) delete mode 100644 ext/opcache/.gitignore delete mode 100644 ext/opcache/.travis.yml delete mode 100644 ext/opcache/LICENSE delete mode 100644 ext/opcache/package.xml diff --git a/ext/opcache/.gitignore b/ext/opcache/.gitignore deleted file mode 100644 index 8f2bec9d3ab..00000000000 --- a/ext/opcache/.gitignore +++ /dev/null @@ -1,87 +0,0 @@ -# General Ignores -*~ -.#* -*. -*.slo -*.mk -*.mem -*.gcda -*.gcno -*.la -*.lo -*.o -*.a -*.ncb -*.opt -*.plg -*swp -*.patch -*.tgz -*.tar.gz -*.tar.bz2 -.FBCIndex -.FBCLockFolder -.deps -.libs -phpt.* -core -dynlib.m4 -Debug -Debug_TS -Makefile -Makefile.fragments -Makefile.objects -Makefile.global -Release -Release_TS -Release_TSDbg -Release_TS_inline -Release_inline -ZendEngine1 -_libs -acconfig.h -aclocal.m4 -acinclude.m4 -autom4te.cache -bsd_converted -buildconf.stamp -buildmk.stamp -confdefs.h -config.h -config.guess -config.cache -config.h.in -config.log -config.nice -config.nice.bat -config.status -config.sub -config_vars.mk -configuration-parser.c -configuration-parser.h -configuration-parser.output -configuration-scanner.c -configure -configure.in -configure.bat -configure.js -conftest -conftest.c -debug.log -diff -generated_lists -include -install-sh -internal_functions.c -lcov_data -lcov_html -libs -libtool -ltmain.sh -meta_cc -meta_ccld -missing -mkinstalldirs -modules -build -run-tests.php diff --git a/ext/opcache/.travis.yml b/ext/opcache/.travis.yml deleted file mode 100644 index b876f57d30f..00000000000 --- a/ext/opcache/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: php -php: - - 5.2 - - 5.3 - - 5.4 - - 5.5 - -before_script: - - phpize - - ./configure --enable-optimizer-plus - - make - -script: - - php -d zend_extension=`pwd`/modules/ZendOptimizerPlus.so -m | grep "Zend Optimizer+" \ No newline at end of file diff --git a/ext/opcache/LICENSE b/ext/opcache/LICENSE deleted file mode 100644 index 42536af3206..00000000000 --- a/ext/opcache/LICENSE +++ /dev/null @@ -1,68 +0,0 @@ --------------------------------------------------------------------- - The PHP License, version 3.01 -Copyright (c) 1999 - 2012 The PHP Group. All rights reserved. --------------------------------------------------------------------- - -Redistribution and use in source and binary forms, with or without -modification, is permitted provided that the following conditions -are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - 3. The name "PHP" must not be used to endorse or promote products - derived from this software without prior written permission. For - written permission, please contact group@php.net. - - 4. Products derived from this software may not be called "PHP", nor - may "PHP" appear in their name, without prior written permission - from group@php.net. You may indicate that your software works in - conjunction with PHP by saying "Foo for PHP" instead of calling - it "PHP Foo" or "phpfoo" - - 5. The PHP Group may publish revised and/or new versions of the - license from time to time. Each version will be given a - distinguishing version number. - Once covered code has been published under a particular version - of the license, you may always continue to use it under the terms - of that version. You may also choose to use such covered code - under the terms of any subsequent version of the license - published by the PHP Group. No one other than the PHP Group has - the right to modify the terms applicable to covered code created - under this License. - - 6. Redistributions of any form whatsoever must retain the following - acknowledgment: - "This product includes PHP software, freely available from - ". - -THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND -ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP -DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -OF THE POSSIBILITY OF SUCH DAMAGE. - --------------------------------------------------------------------- - -This software consists of voluntary contributions made by many -individuals on behalf of the PHP Group. - -The PHP Group can be contacted via Email at group@php.net. - -For more information on the PHP Group and the PHP project, -please see . - -PHP includes the Zend Engine, freely available at -. diff --git a/ext/opcache/package.xml b/ext/opcache/package.xml deleted file mode 100644 index b890a2dda7e..00000000000 --- a/ext/opcache/package.xml +++ /dev/null @@ -1,134 +0,0 @@ - - - zendoptimizerplus - pecl.php.net - The Zend Optimizer+ provides faster PHP execution through opcode caching and optimization. - - The Zend Optimizer+ provides faster PHP execution through opcode caching and - optimization. It improves PHP performance by storing precompiled script - bytecode in the shared memory. This eliminates the stages of reading code from - the disk and compiling it on future access. In addition, it applies a few - bytecode optimization patterns that make code execution faster. - - - Dmitry Stogov - dmitry - dmitry@zend.com - yes - - - Zeev Suraski - zeev - zeev@zend.com - yes - - - Hannes Magnusson - bjori - bjori@php.net - yes - - - Xinchen Hui - laruence - laruence@php.net - yes - - 2013-03-04 - - - 7.0.0 - 7.0.0 - - - beta - beta - - PHP License - - - Initial release - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5.2.0 - - - 1.4.0b1 - - - - zendoptimizerplus - - - - - 7.0.0 - 7.0.0 - - - beta - beta - - 2013-03-04 - PHP License - - - Initial release. - - - - From 930b272d700a7f854357628e446505fab29906a8 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Sun, 17 Mar 2013 10:58:30 +0400 Subject: [PATCH 150/276] Enabled O+ build by default (it may be disabled before 5.0.0 release) --- ext/opcache/config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4 index 4e41c8bc191..a217234854d 100644 --- a/ext/opcache/config.m4 +++ b/ext/opcache/config.m4 @@ -3,7 +3,7 @@ dnl $Id$ dnl PHP_ARG_ENABLE(opcache, whether to enable Zend Optimizer+ support, -[ --enable-opcache Enable Zend Optimizer+ support]) +[ --enable-opcache Enable Zend Optimizer+ support], yes) if test "$PHP_OPCACHE" != "no"; then From 0b8b6a727ddd31ff14e4af919c77a3f1b5e2b3f0 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Sun, 17 Mar 2013 11:42:25 +0400 Subject: [PATCH 151/276] Added ability to load zend_extensions without absolute path names --- main/php_ini.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/main/php_ini.c b/main/php_ini.c index b15a3846dd3..59e9ae80d31 100644 --- a/main/php_ini.c +++ b/main/php_ini.c @@ -357,7 +357,24 @@ static void php_load_php_extension_cb(void *arg TSRMLS_DC) */ static void php_load_zend_extension_cb(void *arg TSRMLS_DC) { - zend_load_extension(*((char **) arg)); + char *filename = *((char **) arg); + int length = strlen(filename); + + if (IS_ABSOLUTE_PATH(filename, length)) { + zend_load_extension(filename); + } else { + char *libpath; + char *extension_dir = INI_STR("extension_dir"); + int extension_dir_len = strlen(extension_dir); + + if (IS_SLASH(extension_dir[extension_dir_len-1])) { + spprintf(&libpath, 0, "%s%s", extension_dir, filename); + } else { + spprintf(&libpath, 0, "%s%c%s", extension_dir, DEFAULT_SLASH, filename); + } + zend_load_extension(libpath); + efree(libpath); + } } /* }}} */ From e66c8681c7e559c0893ec84ff16a4de3ea6d5f32 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Sun, 17 Mar 2013 11:56:04 +0400 Subject: [PATCH 152/276] Made opcache_get_status() return statistics during O+ restart --- ext/opcache/zend_accelerator_module.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 11dd7d3220c..e6c69392744 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -474,14 +474,14 @@ static ZEND_FUNCTION(opcache_get_status) } #endif - if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled)) { + if (!accel_startup_ok) { RETURN_FALSE; } array_init(return_value); /* Trivia */ - add_assoc_bool(return_value, "opcache_enabled", 1 /*ZCG(enabled) && accel_startup_ok && ZCSG(accelerator_enabled)*/); + add_assoc_bool(return_value, "opcache_enabled", ZCG(enabled) && ZCSG(accelerator_enabled)); add_assoc_bool(return_value, "cache_full", ZSMMG(memory_exhausted)); /* Memory usage statistics */ From dcc927d3f2d199b0799152c9100906e64b94b5ea Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Sun, 17 Mar 2013 12:17:04 +0400 Subject: [PATCH 153/276] Load "black list" only if O+ is enabled --- ext/opcache/ZendAccelerator.c | 9 ++++++++ ext/opcache/zend_accelerator_module.c | 30 +-------------------------- 2 files changed, 10 insertions(+), 29 deletions(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index daf80cea29f..a85b7e40a69 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -2489,6 +2489,15 @@ static int accel_startup(zend_extension *extension) /* Override file_exists(), is_file() and is_readable() */ zend_accel_override_file_functions(TSRMLS_C); + /* Load black list */ + accel_blacklist.entries = NULL; + if (ZCG(enabled) && accel_startup_ok && + ZCG(accel_directives).user_blacklist_filename && + *ZCG(accel_directives.user_blacklist_filename)) { + zend_accel_blacklist_init(&accel_blacklist); + zend_accel_blacklist_load(&accel_blacklist, ZCG(accel_directives.user_blacklist_filename)); + } + #if 0 /* FIXME: We probably don't need it here */ zend_accel_copy_internal_functions(TSRMLS_C); diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index e6c69392744..4223a1f6bcb 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -177,31 +177,6 @@ static ZEND_INI_MH(OnUpdateMaxWastedPercentage) return SUCCESS; } -static ZEND_INI_MH(OnUpdateAccelBlacklist) -{ - char **p; -#ifndef ZTS - char *base = (char *) mh_arg2; -#else - char *base = (char *) ts_resource(*((int *) mh_arg2)); -#endif - - /* keep the compiler happy */ - (void)entry; (void)new_value_length; (void)mh_arg2; (void)mh_arg3; (void)stage; - - if (new_value && !new_value[0]) { - return FAILURE; - } - - p = (char **) (base + (size_t)mh_arg1); - *p = new_value; - - zend_accel_blacklist_init(&accel_blacklist); - zend_accel_blacklist_load(&accel_blacklist, *p); - - return SUCCESS; -} - ZEND_INI_BEGIN() STD_PHP_INI_BOOLEAN("opcache.enable" , "1", PHP_INI_SYSTEM, OnUpdateBool, enabled , zend_accel_globals, accel_globals) STD_PHP_INI_BOOLEAN("opcache.use_cwd" , "1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.use_cwd , zend_accel_globals, accel_globals) @@ -221,7 +196,7 @@ ZEND_INI_BEGIN() 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.blacklist_filename" , "" , PHP_INI_SYSTEM, OnUpdateAccelBlacklist, accel_directives.user_blacklist_filename, 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) STD_PHP_INI_ENTRY("opcache.protect_memory" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.protect_memory, zend_accel_globals, accel_globals) @@ -328,9 +303,6 @@ static ZEND_MINIT_FUNCTION(zend_accelerator) { (void)type; /* keep the compiler happy */ - /* must be 0 before the ini entry OnUpdate function is called */ - accel_blacklist.entries = NULL; - REGISTER_INI_ENTRIES(); #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO zend_set_user_opcode_handler(ZEND_DECLARE_INHERITED_CLASS_DELAYED, ZEND_DECLARE_INHERITED_CLASS_DELAYED_HANDLER); From b32405053f5a32d8c4d83f7566f5b414afd3aedb Mon Sep 17 00:00:00 2001 From: Boris Lytochkin Date: Sun, 17 Mar 2013 20:00:37 +0400 Subject: [PATCH 154/276] Fix bug #61981 --- ext/snmp/snmp.c | 4 ++-- ext/snmp/tests/snmp-object.phpt | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c index a3bd44c27b6..0ae140f7d10 100644 --- a/ext/snmp/snmp.c +++ b/ext/snmp/snmp.c @@ -832,9 +832,9 @@ retry: } } else if (st & SNMP_USE_SUFFIX_AS_KEYS && st & SNMP_CMD_WALK) { snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length); - if (objid_query->vars[0].name_length <= vars->name_length && snmp_oid_compare(objid_query->vars[0].name, objid_query->vars[0].name_length, vars->name, objid_query->vars[0].name_length) == 0) { + if (rootlen <= vars->name_length && snmp_oid_compare(root, rootlen, vars->name, rootlen) == 0) { buf2[0] = '\0'; - count = objid_query->vars[0].name_length; + count = rootlen; while(count < vars->name_length){ sprintf(buf, "%lu.", vars->name[count]); strcat(buf2, buf); diff --git a/ext/snmp/tests/snmp-object.phpt b/ext/snmp/tests/snmp-object.phpt index 06b6492bd7f..522d417aff0 100644 --- a/ext/snmp/tests/snmp-object.phpt +++ b/ext/snmp/tests/snmp-object.phpt @@ -83,6 +83,19 @@ var_dump(gettype($z)); var_dump(count($z)); var_dump(key($z)); var_dump(array_shift($z)); +var_dump(key($z)); +array_shift($z); +var_dump(key($z)); +array_shift($z); +var_dump(key($z)); +array_shift($z); +var_dump(key($z)); +array_shift($z); +var_dump(key($z)); +array_shift($z); +var_dump(key($z)); +array_shift($z); +var_dump(key($z)); var_dump($session->close()); echo "SNMPv3 (default security settings)\n"; @@ -194,6 +207,13 @@ string(5) "array" int(%d) string(3) "1.0" string(%d) "%s" +string(3) "2.0" +string(3) "3.0" +string(3) "4.0" +string(3) "5.0" +string(3) "6.0" +string(3) "7.0" +string(3) "8.0" bool(true) SNMPv3 (default security settings) string(%d) "%S" From 44197774c02506be626c85ec60889b58c6c0575e Mon Sep 17 00:00:00 2001 From: Boris Lytochkin Date: Sun, 17 Mar 2013 20:29:14 +0400 Subject: [PATCH 155/276] Fixed bug #61981 --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 0176a93de21..d697c5f162c 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,10 @@ PHP NEWS - PCRE: . Merged PCRE 8.32. (Anatol) +- SNMP: + . Fixed bug #61981 (OO API, walk: $suffix_as_key is not working correctly). + (Boris Lytochkin) + ?? ??? 2013, PHP 5.4.13 - Core: From 85d9d85ce27cf46d26b2717a5cfc3b8f917116ef Mon Sep 17 00:00:00 2001 From: Boris Lytochkin Date: Sun, 17 Mar 2013 20:40:15 +0400 Subject: [PATCH 156/276] more test coverage: missing square bracket error message --- ext/snmp/tests/ipv6.phpt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/snmp/tests/ipv6.phpt b/ext/snmp/tests/ipv6.phpt index 12879416c62..f5239e11789 100644 --- a/ext/snmp/tests/ipv6.phpt +++ b/ext/snmp/tests/ipv6.phpt @@ -20,6 +20,10 @@ snmp_set_quick_print(false); snmp_set_valueretrieval(SNMP_VALUE_PLAIN); var_dump(snmpget($hostname6_port, $community, '.1.3.6.1.2.1.1.1.0')); +var_dump(snmpget('[dead:beef::', $community, '.1.3.6.1.2.1.1.1.0')); ?> --EXPECTF-- %unicode|string%(%d) "%s" + +Warning: snmpget(): malformed IPv6 address, closing square bracket missing in %s on line %d +bool(false) \ No newline at end of file From fe384b34447b5c7f7f472b5a073b11f5d3a33401 Mon Sep 17 00:00:00 2001 From: Boris Lytochkin Date: Sun, 17 Mar 2013 20:52:55 +0400 Subject: [PATCH 157/276] merge with 5.4 --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 46e69d6228d..2ea5117f8d5 100644 --- a/NEWS +++ b/NEWS @@ -39,6 +39,10 @@ PHP NEWS - DateTime: . Fixed bug #64359 (strftime crash with VS2012). (Anatol) +- SNMP: + . Fixed bug #61981 (OO API, walk: $suffix_as_key is not working correctly). + (Boris Lytochkin) + 21 Feb 2013, PHP 5.5.0 Alpha 5 - Core: From ccf7d7cc93d91e621a5dfac341fd6e4dafdf4aaa Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 18 Mar 2013 11:23:26 +0400 Subject: [PATCH 158/276] Add optional flag to opcache_get_status() --- ext/opcache/zend_accelerator_module.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 4223a1f6bcb..50596aaf081 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -430,21 +430,20 @@ static zval* accelerator_get_scripts(TSRMLS_D) return return_value; } -/* {{{ proto array accelerator_get_status() - Obtain statistics information regarding code acceleration in the Zend Performance Suite */ +/* {{{ proto array accelerator_get_status([bool fetch_scripts]) + Obtain statistics information regarding code acceleration */ static ZEND_FUNCTION(opcache_get_status) { long reqs; zval *memory_usage,*statistics,*scripts; + zend_bool fetch_scripts = 1; /* keep the compiler happy */ (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used; -#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO - if (zend_parse_parameters_none() == FAILURE) { - RETURN_FALSE; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &fetch_scripts) == FAILURE) { + return; } -#endif if (!accel_startup_ok) { RETURN_FALSE; @@ -480,10 +479,12 @@ static ZEND_FUNCTION(opcache_get_status) add_assoc_double(statistics, "opcache_hit_rate", reqs?(((double) ZCSG(hits))/reqs)*100.0:0); add_assoc_zval(return_value, "opcache_statistics", statistics); - /* accelerated scripts */ - scripts = accelerator_get_scripts(TSRMLS_C); - if (scripts) { - add_assoc_zval(return_value, "scripts", scripts); + if (fetch_scripts) { + /* accelerated scripts */ + scripts = accelerator_get_scripts(TSRMLS_C); + if (scripts) { + add_assoc_zval(return_value, "scripts", scripts); + } } } @@ -494,7 +495,7 @@ static int add_blacklist_path(zend_blacklist_entry *p, zval *return_value TSRMLS } /* {{{ proto array accelerator_get_configuration() - Obtain configuration information for the Zend Performance Suite */ + Obtain configuration information */ static ZEND_FUNCTION(opcache_get_configuration) { zval *directives,*version,*blacklist; From db4d473d53b7b89ac01b3337a94ece4a07a6444f Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Mon, 18 Mar 2013 00:51:16 -0700 Subject: [PATCH 159/276] fix NEWS --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index d697c5f162c..fd05e22e012 100644 --- a/NEWS +++ b/NEWS @@ -12,7 +12,7 @@ PHP NEWS . Fixed bug #61981 (OO API, walk: $suffix_as_key is not working correctly). (Boris Lytochkin) -?? ??? 2013, PHP 5.4.13 +14 Mar 2013, PHP 5.4.13 - Core: . Fixed bug #64354 (Unserialize array of objects whose class can't From 87c8ea15f29cd89e8a58d2f6dce4348453c6ac59 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Mon, 18 Mar 2013 00:52:15 -0700 Subject: [PATCH 160/276] fix NEWS --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 41f5eab4e77..adf868f0f47 100644 --- a/NEWS +++ b/NEWS @@ -14,7 +14,7 @@ PHP NEWS for stmt->param_bind). (Andrey) -28 Feb 2013, PHP 5.3.23RC1 +14 Mar 2013, PHP 5.3.23 - Phar: . Fixed timestamp update on Phar contents modification. (Dmitry) From 1fe43d07989316d308e4dfd6989038fa09a51ff1 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 18 Mar 2013 13:13:35 +0400 Subject: [PATCH 161/276] Add oom, wasted, hash and manual restart counters to help identify potential configuration problems --- ext/opcache/ZendAccelerator.c | 34 +++++++++++++++++++++------ ext/opcache/ZendAccelerator.h | 14 ++++++++++- ext/opcache/zend_accelerator_module.c | 14 +++++++---- ext/opcache/zend_shared_alloc.c | 4 ++-- 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index a85b7e40a69..7c5e1247297 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -852,7 +852,7 @@ static void zend_accel_schedule_restart_if_necessary(TSRMLS_D) { if ((((double) ZSMMG(wasted_shared_memory)) / ZCG(accel_directives).memory_consumption) >= ZCG(accel_directives).max_wasted_percentage) { ZSMMG(memory_exhausted) = 1; - zend_accel_schedule_restart(TSRMLS_C); + zend_accel_schedule_restart(ACCEL_RESTART_WASTED TSRMLS_CC); } } @@ -1030,7 +1030,7 @@ static void zend_accel_add_key(char *key, unsigned int key_length, zend_accel_ha if (zend_accel_hash_is_full(&ZCSG(hash))) { zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!"); ZSMMG(memory_exhausted) = 1; - zend_accel_schedule_restart(TSRMLS_C); + zend_accel_schedule_restart(ACCEL_RESTART_HASH TSRMLS_CC); } else { char *new_key = zend_shared_alloc(key_length + 1); if (new_key) { @@ -1057,7 +1057,7 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr if (zend_accel_hash_is_full(&ZCSG(hash))) { zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!"); ZSMMG(memory_exhausted) = 1; - zend_accel_schedule_restart(TSRMLS_C); + zend_accel_schedule_restart(ACCEL_RESTART_HASH TSRMLS_CC); zend_shared_alloc_unlock(TSRMLS_C); return new_persistent_script; } @@ -1118,7 +1118,7 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr if (!zend_accel_hash_update(&ZCSG(hash), key, key_length + 1, 1, bucket)) { zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!"); ZSMMG(memory_exhausted) = 1; - zend_accel_schedule_restart(TSRMLS_C); + zend_accel_schedule_restart(ACCEL_RESTART_HASH TSRMLS_CC); } } @@ -1500,7 +1500,7 @@ static zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int ZCSG(misses)++; /* No memory left. Behave like without the Accelerator */ - if (ZSMMG(memory_exhausted)) { + if (ZSMMG(memory_exhausted) || ZCSG(restart_pending)) { SHM_PROTECT(); return accelerator_orig_compile_file(file_handle, type TSRMLS_CC); } @@ -1964,6 +1964,20 @@ static void accel_activate(void) if (accel_is_inactive(TSRMLS_C) == SUCCESS) { zend_accel_error(ACCEL_LOG_DEBUG, "Restarting!"); ZCSG(restart_pending) = 0; + switch ZCSG(restart_reason) { + case ACCEL_RESTART_OOM: + ZCSG(oom_restarts)++; + break; + case ACCEL_RESTART_WASTED: + ZCSG(wasted_restarts)++; + break; + case ACCEL_RESTART_HASH: + ZCSG(hash_restarts)++; + break; + case ACCEL_RESTART_USER: + ZCSG(manual_restarts)++; + break; + } accel_restart_enter(TSRMLS_C); zend_reset_cache_vars(TSRMLS_C); @@ -2322,8 +2336,13 @@ static void zend_accel_init_shm(TSRMLS_D) zend_reset_cache_vars(TSRMLS_C); + ZCSG(oom_restarts) = 0; + ZCSG(wasted_restarts) = 0; + ZCSG(hash_restarts) = 0; + ZCSG(manual_restarts) = 0; + ZCSG(accelerator_enabled) = 1; - ZCSG(last_restart_time) = 0; + ZCSG(last_restart_time) = zend_accel_get_time(); ZCSG(restart_in_progress) = 0; zend_shared_alloc_unlock(TSRMLS_C); @@ -2547,7 +2566,7 @@ static void accel_shutdown(zend_extension *extension) } -void zend_accel_schedule_restart(TSRMLS_D) +void zend_accel_schedule_restart(zend_accel_restart_reason reason TSRMLS_DC) { if (ZCSG(restart_pending)) { /* don't schedule twice */ @@ -2556,6 +2575,7 @@ void zend_accel_schedule_restart(TSRMLS_D) zend_accel_error(ACCEL_LOG_DEBUG, "Restart Scheduled!"); ZCSG(restart_pending) = 1; + ZCSG(restart_reason) = reason; ZCSG(cache_status_before_restart) = ZCSG(accelerator_enabled); ZCSG(accelerator_enabled) = 0; diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h index be2218cdb8d..45eae71dd74 100644 --- a/ext/opcache/ZendAccelerator.h +++ b/ext/opcache/ZendAccelerator.h @@ -164,6 +164,13 @@ typedef unsigned __int64 accel_time_t; typedef time_t accel_time_t; #endif +typedef enum _zend_accel_restart_reason { + ACCEL_RESTART_OOM, /* restart because of out of memory */ + ACCEL_RESTART_WASTED, /* restart because of wasted memory */ + ACCEL_RESTART_HASH, /* restart because of hash overflow */ + ACCEL_RESTART_USER /* restart sheduled by opcache_reset() */ +} zend_accel_restart_reason; + typedef struct _zend_persistent_script { ulong hash_value; char *full_path; /* full real path with resolved symlinks */ @@ -259,6 +266,10 @@ typedef struct _zend_accel_shared_globals { unsigned long hits; unsigned long misses; unsigned long blacklist_misses; + unsigned long oom_restarts; /* number of restarts because of out of memory */ + unsigned long wasted_restarts; /* number of restarts because of wasted memory */ + unsigned long hash_restarts; /* number of restarts because of hash overflow */ + unsigned long manual_restarts; /* number of restarts sheduled by opcache_reset() */ zend_accel_hash hash; /* hash table for cached scripts */ zend_accel_hash include_paths; /* used "include_path" values */ @@ -267,6 +278,7 @@ typedef struct _zend_accel_shared_globals { time_t force_restart_time; zend_bool accelerator_enabled; zend_bool restart_pending; + zend_accel_restart_reason restart_reason; zend_bool cache_status_before_restart; #ifdef ZEND_WIN32 unsigned long mem_usage; @@ -304,7 +316,7 @@ extern zend_accel_globals accel_globals; extern char *zps_api_failure_reason; -void zend_accel_schedule_restart(TSRMLS_D); +void zend_accel_schedule_restart(zend_accel_restart_reason reason TSRMLS_DC); int accelerator_shm_read_lock(TSRMLS_D); void accelerator_shm_read_unlock(TSRMLS_D); diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 50596aaf081..019ce6697e4 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -342,7 +342,7 @@ void zend_accel_info(ZEND_MODULE_INFO_FUNC_ARGS) { php_info_print_table_start(); - if (ZCG(enabled) && accel_startup_ok && ZCSG(accelerator_enabled)) { + if (ZCG(enabled) && accel_startup_ok && (ZCG(counted) || ZCSG(accelerator_enabled))) { php_info_print_table_row(2, "Opcode Caching", "Up and Running"); } else { php_info_print_table_row(2, "Opcode Caching", "Disabled"); @@ -452,8 +452,10 @@ static ZEND_FUNCTION(opcache_get_status) array_init(return_value); /* Trivia */ - add_assoc_bool(return_value, "opcache_enabled", ZCG(enabled) && ZCSG(accelerator_enabled)); + add_assoc_bool(return_value, "opcache_enabled", ZCG(enabled) && (ZCG(counted) || ZCSG(accelerator_enabled))); add_assoc_bool(return_value, "cache_full", ZSMMG(memory_exhausted)); + add_assoc_bool(return_value, "restart_pending", ZCSG(restart_pending)); + add_assoc_bool(return_value, "restart_in_progress", ZCSG(restart_in_progress)); /* Memory usage statistics */ MAKE_STD_ZVAL(memory_usage); @@ -472,6 +474,10 @@ static ZEND_FUNCTION(opcache_get_status) add_assoc_long(statistics, "max_cached_keys", ZCSG(hash).max_num_entries); add_assoc_long(statistics, "hits", ZCSG(hits)); add_assoc_long(statistics, "last_restart_time", ZCSG(last_restart_time)); + add_assoc_long(statistics, "oom_restarts", ZCSG(oom_restarts)); + add_assoc_long(statistics, "wasted_restarts", ZCSG(wasted_restarts)); + add_assoc_long(statistics, "hash_restarts", ZCSG(hash_restarts)); + add_assoc_long(statistics, "manual_restarts", ZCSG(manual_restarts)); add_assoc_long(statistics, "misses", ZSMMG(memory_exhausted)?ZCSG(misses):ZCSG(misses)-ZCSG(blacklist_misses)); add_assoc_long(statistics, "blacklist_misses", ZCSG(blacklist_misses)); reqs = ZCSG(hits)+ZCSG(misses); @@ -561,7 +567,7 @@ static ZEND_FUNCTION(opcache_get_configuration) } /* {{{ proto void accelerator_reset() - Request that the contents of the Accelerator module in the ZPS be reset */ + Request that the contents of the opcode cache to be reset */ static ZEND_FUNCTION(opcache_reset) { /* keep the compiler happy */ @@ -577,6 +583,6 @@ static ZEND_FUNCTION(opcache_reset) RETURN_FALSE; } - zend_accel_schedule_restart(TSRMLS_C); + zend_accel_schedule_restart(ACCEL_RESTART_USER TSRMLS_CC); RETURN_TRUE; } diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c index 1a983aeea70..5e37e385863 100644 --- a/ext/opcache/zend_shared_alloc.c +++ b/ext/opcache/zend_shared_alloc.c @@ -276,8 +276,8 @@ static size_t zend_shared_alloc_get_largest_free_block(void) #define SHARED_ALLOC_FAILED() do { \ zend_accel_error(ACCEL_LOG_WARNING, "Not enough free shared space to allocate %ld bytes (%ld bytes free)", (long)size, (long)ZSMMG(shared_free)); \ if (zend_shared_alloc_get_largest_free_block() < MIN_FREE_MEMORY) { \ - ZSMMG(memory_exhausted) = 1; \ - zend_accel_schedule_restart(TSRMLS_C); \ + ZSMMG(memory_exhausted) = 1; \ + zend_accel_schedule_restart(ACCEL_RESTART_OOM TSRMLS_CC); \ } \ } while (0) From 5b0879e7c969e0bd87b0ad6fad03e278a0a46642 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 18 Mar 2013 13:36:31 +0400 Subject: [PATCH 162/276] Avoid trailing line break --- ext/opcache/zend_accelerator_module.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 019ce6697e4..dd8eb5987ff 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -403,6 +403,8 @@ static zval* accelerator_get_scripts(TSRMLS_D) for (i = 0; inext) { zend_persistent_script *script; + char *str; + int len; if (cache_entry->indirect) continue; @@ -414,7 +416,10 @@ static zval* accelerator_get_scripts(TSRMLS_D) add_assoc_long(persistent_script_report, "hits", script->dynamic_members.hits); add_assoc_long(persistent_script_report, "memory_consumption", script->dynamic_members.memory_consumption); ta = localtime(&script->dynamic_members.last_used); - add_assoc_string(persistent_script_report, "last_used", asctime(ta), 1); + str = asctime(ta); + len = strlen(str); + if (len > 0 && str[len - 1] == '\n') len--; + add_assoc_stringl(persistent_script_report, "last_used", str, len, 1); add_assoc_long(persistent_script_report, "last_used_timestamp", script->dynamic_members.last_used); if (ZCG(accel_directives).validate_timestamps) { add_assoc_long(persistent_script_report, "timestamp", (long)script->timestamp); From 840c0d6091ccf25780b97178acd51e2627cefc9a Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 19 Mar 2013 10:17:44 +0400 Subject: [PATCH 163/276] Add stats to phpinfo --- ext/opcache/zend_accelerator_module.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index dd8eb5987ff..6f72dd9ebc0 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -356,8 +356,33 @@ void zend_accel_info(ZEND_MODULE_INFO_FUNC_ARGS) if (!accel_startup_ok || zps_api_failure_reason) { php_info_print_table_row(2, "Startup Failed", zps_api_failure_reason); } else { + char buf[32]; php_info_print_table_row(2, "Startup", "OK"); php_info_print_table_row(2, "Shared memory model", zend_accel_get_shared_model()); + snprintf(buf, sizeof(buf), "%ld", ZCSG(hits)); + php_info_print_table_row(2, "Cache hits", buf); + snprintf(buf, sizeof(buf), "%ld", ZSMMG(memory_exhausted)?ZCSG(misses):ZCSG(misses)-ZCSG(blacklist_misses)); + php_info_print_table_row(2, "Cache misses", buf); + snprintf(buf, sizeof(buf), "%ld", ZCG(accel_directives).memory_consumption-zend_shared_alloc_get_free_memory()-ZSMMG(wasted_shared_memory)); + php_info_print_table_row(2, "Used memory", buf); + snprintf(buf, sizeof(buf), "%ld", zend_shared_alloc_get_free_memory()); + php_info_print_table_row(2, "Free memory", buf); + snprintf(buf, sizeof(buf), "%ld", ZSMMG(wasted_shared_memory)); + php_info_print_table_row(2, "Wasted memory", buf); + snprintf(buf, sizeof(buf), "%ld", ZCSG(hash).num_direct_entries); + php_info_print_table_row(2, "Cached scripts", buf); + snprintf(buf, sizeof(buf), "%ld", ZCSG(hash).num_entries); + php_info_print_table_row(2, "Cached keys", buf); + snprintf(buf, sizeof(buf), "%ld", ZCSG(hash).max_num_entries); + php_info_print_table_row(2, "Max keys", buf); + snprintf(buf, sizeof(buf), "%ld", ZCSG(oom_restarts)); + php_info_print_table_row(2, "OOM restarts", buf); + snprintf(buf, sizeof(buf), "%ld", ZCSG(wasted_restarts)); + php_info_print_table_row(2, "Wasted memory restarts", buf); + snprintf(buf, sizeof(buf), "%ld", ZCSG(hash_restarts)); + php_info_print_table_row(2, "Hash keys restarts", buf); + snprintf(buf, sizeof(buf), "%ld", ZCSG(manual_restarts)); + php_info_print_table_row(2, "Manual restarts", buf); } } From a62ffb72f403d255c744b27f617ee6b6ac62c216 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 19 Mar 2013 10:32:24 +0400 Subject: [PATCH 164/276] Renamed Zend Optimizer+ into Zend OPcache --- ext/opcache/Optimizer/zend_optimizer.c | 2 +- ext/opcache/Optimizer/zend_optimizer.h | 2 +- .../Optimizer/zend_optimizer_internal.h | 2 +- ext/opcache/README | 44 +++++++++---------- ext/opcache/ZendAccelerator.c | 2 +- ext/opcache/ZendAccelerator.h | 6 +-- ext/opcache/config.m4 | 4 +- ext/opcache/config.w32 | 2 +- ext/opcache/shared_alloc_mmap.c | 2 +- ext/opcache/shared_alloc_posix.c | 2 +- ext/opcache/shared_alloc_shm.c | 2 +- ext/opcache/shared_alloc_win32.c | 10 ++--- ext/opcache/tests/bug64353.phpt | 2 +- ext/opcache/tests/skipif.inc | 2 +- ext/opcache/zend_accelerator_blacklist.c | 2 +- ext/opcache/zend_accelerator_blacklist.h | 2 +- ext/opcache/zend_accelerator_debug.c | 2 +- ext/opcache/zend_accelerator_debug.h | 2 +- ext/opcache/zend_accelerator_hash.c | 2 +- ext/opcache/zend_accelerator_hash.h | 2 +- ext/opcache/zend_accelerator_module.c | 2 +- ext/opcache/zend_accelerator_module.h | 2 +- ext/opcache/zend_accelerator_util_funcs.c | 2 +- ext/opcache/zend_accelerator_util_funcs.h | 2 +- ext/opcache/zend_persist.c | 2 +- ext/opcache/zend_persist.h | 2 +- ext/opcache/zend_persist_calc.c | 2 +- ext/opcache/zend_shared_alloc.c | 2 +- ext/opcache/zend_shared_alloc.h | 2 +- 29 files changed, 57 insertions(+), 57 deletions(-) diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index e46e5a2ecec..b574ecc81f2 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/Optimizer/zend_optimizer.h b/ext/opcache/Optimizer/zend_optimizer.h index ff848535d30..98275a20aae 100644 --- a/ext/opcache/Optimizer/zend_optimizer.h +++ b/ext/opcache/Optimizer/zend_optimizer.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/Optimizer/zend_optimizer_internal.h b/ext/opcache/Optimizer/zend_optimizer_internal.h index 6f853641fac..0097496df9a 100644 --- a/ext/opcache/Optimizer/zend_optimizer_internal.h +++ b/ext/opcache/Optimizer/zend_optimizer_internal.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/README b/ext/opcache/README index e7df8769b67..f87e1ccbfc6 100644 --- a/ext/opcache/README +++ b/ext/opcache/README @@ -1,7 +1,7 @@ -The Zend Optimizer+ -=================== +The Zend OPcache +================ -The Zend Optimizer+ provides faster PHP execution through opcode caching and +The Zend OPcache provides faster PHP execution through opcode caching and optimization. It improves PHP performance by storing precompiled script bytecode in the shared memory. This eliminates the stages of reading code from the disk and compiling it on future access. In addition, it applies a few @@ -10,7 +10,7 @@ bytecode optimization patterns that make code execution faster. Compatibility ------------- -This version of Zend Optimizer+ is compatible with PHP 5.2.*, 5.3.*, 5.4.* +This version of Zend OPcache is compatible with PHP 5.2.*, 5.3.*, 5.4.* and PHP-5.5 development branch. PHP 5.2 support may be removed in the future. Quick Install @@ -31,9 +31,9 @@ Quick Install zend_extension=/...full path.../opcache.so -NOTE: In case you are going to use Zend Optimizer+ together with Xdebug, -be sure that Xdebug is loaded after Optimizer+. "php -v" must show Xdebug -after Optimizer+. +NOTE: In case you are going to use Zend OPcache together with Xdebug, +be sure that Xdebug is loaded after OPcache. "php -v" must show Xdebug +after OPcache. - Restart PHP @@ -63,17 +63,17 @@ Configuration Directives ------------------------ opcache.enable (default "1") - Optimizer+ On/Off switch. When set to Off, code is not optimized. + OPcache On/Off switch. When set to Off, code is not optimized. opcache.memory_consumption (default "64") - The Optimizer+ shared memory storage size. The amount of memory for storing + The OPcache shared memory storage size. The amount of memory for storing precompiled PHP code in Mbytes. opcache.interned_strings_buffer (default "4") The amount of memory for interned strings in Mbytes. opcache.max_accelerated_files (default "2000") - The maximum number of keys (scripts) in the Optimizer+ hash table. + The maximum number of keys (scripts) in the OPcache hash table. The number is actually the first one in the following set of prime numbers that is bigger than the one supplied: { 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987 }. Only numbers between 200 and 100000 @@ -83,13 +83,13 @@ opcache.max_wasted_percentage (default "5") The maximum percentage of "wasted" memory until a restart is scheduled. opcache.use_cwd (default "1") - When this directive is enabled, the Optimizer+ appends the current working + When this directive is enabled, the OPcache appends the current working directory to the script key, thus eliminating possible collisions between files with the same name (basename). Disabling the directive improves performance, but may break existing applications. opcache.validate_timestamps (default "1") - When disabled, you must reset the Optimizer+ manually or restart the + When disabled, you must reset the OPcache manually or restart the webserver for changes to the filesystem to take effect. The frequency of the check is controlled by the directive "opcache.revalidate_freq". @@ -127,15 +127,15 @@ opcache.enable_file_override (default "0") Allow file existence override (file_exists, etc.) performance feature. opcache.optimization_level (default "0xffffffff") - A bitmask, where each bit enables or disables the appropriate Optimizer+ + A bitmask, where each bit enables or disables the appropriate OPcache passes opcache.inherited_hack (default "1") Enable this hack as a workaround for "can't redeclare class" errors. - The Optimizer+ stores the places where DECLARE_CLASS opcodes use + The OPcache stores the places where DECLARE_CLASS opcodes use inheritance (These are the only opcodes that can be executed by PHP, but which may not be executed because the parent class is missing due to - optimization). When the file is loaded, Optimizer+ tries to bind the + optimization). When the file is loaded, OPcache tries to bind the inherited classes by using the current environment. The problem with this scenario is that, while the DECLARE_CLASS opcode may not be needed for the current script, if the script requires that the opcode at least be defined, @@ -147,8 +147,8 @@ opcache.dups_fix (default "0") Enable this hack as a workaround for "Cannot redeclare class" errors. opcache.blacklist_filename - The location of the Optimizer+ blacklist file. - The Optimizer+ blacklist file is a text file that holds the names of files + The location of the OPcache blacklist file. + The OPcache blacklist file is a text file that holds the names of files that should not be accelerated. The file format is to add each filename to a new line. The filename may be a full path or just a file prefix (i.e., /var/www/x blacklists all the files and directories in /var/www @@ -157,7 +157,7 @@ opcache.blacklist_filename 1) Directories that contain auto generated code, like Smarty or ZFW cache. 2) Code that does not work well when accelerated, due to some delayed compile time evaluation. - 3) Code that triggers an Optimizer+ bug. + 3) Code that triggers an OPcache bug. opcache.max_file_size (default "0") Allows exclusion of large files from being cached. By default all files @@ -172,18 +172,18 @@ opcache.consistency_checks (default "0") opcache.force_restart_timeout (default "180") How long to wait (in seconds) for a scheduled restart to begin if the cache is not being accessed. - The Optimizer+ uses this directive to identify a situation where there may + The OPcache uses this directive to identify a situation where there may be a problem with a process. After this time period has passed, the - Optimizer+ assumes that something has happened and starts killing the + OPcache assumes that something has happened and starts killing the processes that still hold the locks that are preventing a restart. If the log level is 3 or above, a "killed locker" error is recorded in the Apache logs when this happens. opcache.error_log - Optimizer+ error_log file name. Empty string assumes "stderr". + OPcache error_log file name. Empty string assumes "stderr". opcache.log_verbosity_level (default "1") - All Optimizer+ errors go to the Web server log. + All OPcache errors go to the Web server log. By default, only fatal errors (level 0) or errors (level 1) are logged. You can also enable warnings (level 2), info messages (level 3) or debug messages (level 4). diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 7c5e1247297..64c5aa8f14b 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h index 45eae71dd74..3f10630ac83 100644 --- a/ext/opcache/ZendAccelerator.h +++ b/ext/opcache/ZendAccelerator.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ @@ -26,7 +26,7 @@ # include #endif -#define ACCELERATOR_PRODUCT_NAME "Zend Optimizer+" +#define ACCELERATOR_PRODUCT_NAME "Zend OPcache" #define ACCELERATOR_VERSION "7.0.1-dev" /* 2 - added Profiler support, on 20010712 */ /* 3 - added support for Optimizer's encoded-only-files mode */ @@ -34,7 +34,7 @@ /* 5 - API 4 didn't really work with the license-enabled file format. v5 does. */ /* 6 - Monitor was removed from ZendPlatform.so, to a module of its own */ /* 7 - Optimizer was embedded into Accelerator */ -/* 8 - Standalone Open Source OptimizerPlus */ +/* 8 - Standalone Open Source Zend OPcache */ #define ACCELERATOR_API_NO 8 #if ZEND_WIN32 diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4 index a217234854d..cbf7d5a19c0 100644 --- a/ext/opcache/config.m4 +++ b/ext/opcache/config.m4 @@ -2,8 +2,8 @@ dnl dnl $Id$ dnl -PHP_ARG_ENABLE(opcache, whether to enable Zend Optimizer+ support, -[ --enable-opcache Enable Zend Optimizer+ support], yes) +PHP_ARG_ENABLE(opcache, whether to enable Zend OPcache support, +[ --enable-opcache Enable Zend OPcache support], yes) if test "$PHP_OPCACHE" != "no"; then diff --git a/ext/opcache/config.w32 b/ext/opcache/config.w32 index aeca78a77bb..280ce228c64 100644 --- a/ext/opcache/config.w32 +++ b/ext/opcache/config.w32 @@ -1,4 +1,4 @@ -ARG_ENABLE("opcache", "whether to enable Zend Optimizer+ support", "yes"); +ARG_ENABLE("opcache", "whether to enable Zend OPcache support", "yes"); if (PHP_OPCACHE != "no") { diff --git a/ext/opcache/shared_alloc_mmap.c b/ext/opcache/shared_alloc_mmap.c index 961f4fea9af..12f00554a14 100644 --- a/ext/opcache/shared_alloc_mmap.c +++ b/ext/opcache/shared_alloc_mmap.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/shared_alloc_posix.c b/ext/opcache/shared_alloc_posix.c index 46f0257bb3a..f3377dec607 100644 --- a/ext/opcache/shared_alloc_posix.c +++ b/ext/opcache/shared_alloc_posix.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/shared_alloc_shm.c b/ext/opcache/shared_alloc_shm.c index a8b244aac15..d2b842304b5 100644 --- a/ext/opcache/shared_alloc_shm.c +++ b/ext/opcache/shared_alloc_shm.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/shared_alloc_win32.c b/ext/opcache/shared_alloc_win32.c index 7eb93af62f2..e323952845d 100644 --- a/ext/opcache/shared_alloc_win32.c +++ b/ext/opcache/shared_alloc_win32.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ @@ -26,11 +26,11 @@ #include #include -#define ACCEL_FILEMAP_NAME "ZendOptimizer+.SharedMemoryArea" -#define ACCEL_MUTEX_NAME "ZendOptimizer+.SharedMemoryMutex" +#define ACCEL_FILEMAP_NAME "ZendOPcache.SharedMemoryArea" +#define ACCEL_MUTEX_NAME "ZendOPcache.SharedMemoryMutex" #define ACCEL_FILEMAP_BASE_DEFAULT 0x01000000 -#define ACCEL_FILEMAP_BASE "ZendOptimizer+.MemoryBase" -#define ACCEL_EVENT_SOURCE "Zend Optimizer+" +#define ACCEL_FILEMAP_BASE "ZendOPcache.MemoryBase" +#define ACCEL_EVENT_SOURCE "Zend OPcache" static HANDLE memfile = NULL, memory_mutex = NULL; static void *mapping_base; diff --git a/ext/opcache/tests/bug64353.phpt b/ext/opcache/tests/bug64353.phpt index 463b6ee2281..b1f0c6e7135 100644 --- a/ext/opcache/tests/bug64353.phpt +++ b/ext/opcache/tests/bug64353.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #64353 (Built-in classes can be unavailable with dynamic includes and Optimizer+) +Bug #64353 (Built-in classes can be unavailable with dynamic includes and OPcache) --INI-- allow_url_include=1 opcache.enable=1 diff --git a/ext/opcache/tests/skipif.inc b/ext/opcache/tests/skipif.inc index 8652a94de74..c5a81810391 100644 --- a/ext/opcache/tests/skipif.inc +++ b/ext/opcache/tests/skipif.inc @@ -1,3 +1,3 @@ diff --git a/ext/opcache/zend_accelerator_blacklist.c b/ext/opcache/zend_accelerator_blacklist.c index 87dc4744574..0ccd62e3441 100644 --- a/ext/opcache/zend_accelerator_blacklist.c +++ b/ext/opcache/zend_accelerator_blacklist.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/zend_accelerator_blacklist.h b/ext/opcache/zend_accelerator_blacklist.h index 5d7730f4701..626b8d2c476 100644 --- a/ext/opcache/zend_accelerator_blacklist.h +++ b/ext/opcache/zend_accelerator_blacklist.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/zend_accelerator_debug.c b/ext/opcache/zend_accelerator_debug.c index 1234c0fc93c..93349e3d172 100644 --- a/ext/opcache/zend_accelerator_debug.c +++ b/ext/opcache/zend_accelerator_debug.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/zend_accelerator_debug.h b/ext/opcache/zend_accelerator_debug.h index 8d0d7320bf5..2ff88e21d3f 100644 --- a/ext/opcache/zend_accelerator_debug.h +++ b/ext/opcache/zend_accelerator_debug.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/zend_accelerator_hash.c b/ext/opcache/zend_accelerator_hash.c index dbdc2ef1405..afd227c5d54 100644 --- a/ext/opcache/zend_accelerator_hash.c +++ b/ext/opcache/zend_accelerator_hash.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/zend_accelerator_hash.h b/ext/opcache/zend_accelerator_hash.h index a1a836c03c3..fdfddb40644 100644 --- a/ext/opcache/zend_accelerator_hash.h +++ b/ext/opcache/zend_accelerator_hash.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 6f72dd9ebc0..290813c06bd 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/zend_accelerator_module.h b/ext/opcache/zend_accelerator_module.h index 5ac5716ca7c..539b4e85af9 100644 --- a/ext/opcache/zend_accelerator_module.h +++ b/ext/opcache/zend_accelerator_module.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index 06299d8a0bf..7d5028c4c14 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/zend_accelerator_util_funcs.h b/ext/opcache/zend_accelerator_util_funcs.h index 804e0f786b3..a926145c986 100644 --- a/ext/opcache/zend_accelerator_util_funcs.h +++ b/ext/opcache/zend_accelerator_util_funcs.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 6f9678e2850..0bffae4d0e2 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/zend_persist.h b/ext/opcache/zend_persist.h index ffb990ae751..cf3fb73cddd 100644 --- a/ext/opcache/zend_persist.h +++ b/ext/opcache/zend_persist.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index 00c8784a84b..18af756f6e8 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c index 5e37e385863..f4465ce78f2 100644 --- a/ext/opcache/zend_shared_alloc.c +++ b/ext/opcache/zend_shared_alloc.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/opcache/zend_shared_alloc.h b/ext/opcache/zend_shared_alloc.h index c8411b5624c..23af630f80d 100644 --- a/ext/opcache/zend_shared_alloc.h +++ b/ext/opcache/zend_shared_alloc.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | Zend Optimizer+ | + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) 1998-2013 The PHP Group | +----------------------------------------------------------------------+ From f621f0b8e7f1a2d061d37e16f71bcb2000c2a786 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 19 Mar 2013 10:45:38 +0400 Subject: [PATCH 165/276] strlen() returns size_t --- ext/opcache/zend_accelerator_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 290813c06bd..778fee54b38 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -429,7 +429,7 @@ static zval* accelerator_get_scripts(TSRMLS_D) for (cache_entry = ZCSG(hash).hash_table[i]; cache_entry; cache_entry = cache_entry->next) { zend_persistent_script *script; char *str; - int len; + size_t len; if (cache_entry->indirect) continue; From e62bb0325763d9847847dd198e05c9b3147caf05 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 19 Mar 2013 12:48:23 +0400 Subject: [PATCH 166/276] Fixed bug #64417 (ArrayAccess::&offsetGet() in a trait causes fatal error) --- NEWS | 2 ++ Zend/tests/bug64417.phpt | 39 +++++++++++++++++++++++++++++++++++++++ Zend/zend_compile.c | 2 +- 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/bug64417.phpt diff --git a/NEWS b/NEWS index fd05e22e012..75b588bfaed 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,8 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2013, PHP 5.4.14 - Core + . Fixed bug #64417 (ArrayAccess::&offsetGet() in a trait causes fatal error). + (Dmitry) . Fixed bug #64370 (microtime(true) less than $_SERVER['REQUEST_TIME_FLOAT']). (Anatol) diff --git a/Zend/tests/bug64417.phpt b/Zend/tests/bug64417.phpt new file mode 100644 index 00000000000..f3ef740b43e --- /dev/null +++ b/Zend/tests/bug64417.phpt @@ -0,0 +1,39 @@ +--TEST-- +Bug #64417 (BC break: ArrayAccess::&offsetGet() in a trait causes fatal error) +--FILE-- +container[] = $value; + } else { + $this->container[$offset] = $value; + } + } + public function offsetExists($offset) { + return isset($this->container[$offset]); + } + public function offsetUnset($offset) { + unset($this->container[$offset]); + } + public function &offsetGet($offset) { + $result = null; + if (isset($this->container[$offset])) { + $result = &$this->container[$offset]; + } + return $result; + } +} + +class obj implements ArrayAccess { + use aa; +} + +$o = new obj; +$o['x'] = 1; +++$o['x']; +echo $o['x'], "\n"; +--EXPECT-- +2 + diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 0a1749dbd87..766a2de01a3 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3634,7 +3634,7 @@ static zend_bool zend_traits_method_compatibility_check(zend_function *fn, zend_ zend_uint other_flags = other_fn->common.scope->ce_flags; return zend_do_perform_implementation_check(fn, other_fn TSRMLS_CC) - && zend_do_perform_implementation_check(other_fn, fn TSRMLS_CC) + && ((other_fn->common.scope->ce_flags & ZEND_ACC_INTERFACE) || zend_do_perform_implementation_check(other_fn, fn TSRMLS_CC)) && ((fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_STATIC)) == (other_flags & (ZEND_ACC_FINAL|ZEND_ACC_STATIC))); /* equal final and static qualifier */ } From 4a6291508d69fab951562b996ed7223c052a0168 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 19 Mar 2013 14:56:53 +0400 Subject: [PATCH 167/276] Fixed bug #62343 (Show class_alias In get_declared_classes()) --- NEWS | 1 + Zend/tests/bug62343.phpt | 13 +++++++++++++ Zend/zend_builtin_functions.c | 15 ++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/bug62343.phpt diff --git a/NEWS b/NEWS index adf868f0f47..c8c6f754a0e 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ PHP NEWS - Core . Fixed bug #64370 (microtime(true) less than $_SERVER['REQUEST_TIME_FLOAT']). (Anatol) + . Fixed bug #62343 (Show class_alias In get_declared_classes()) (Dmitry) - PCRE: . Merged PCRE 8.32). (Anatol) diff --git a/Zend/tests/bug62343.phpt b/Zend/tests/bug62343.phpt new file mode 100644 index 00000000000..b0208c4ac38 --- /dev/null +++ b/Zend/tests/bug62343.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #62343 (Show class_alias In get_declared_classes()) +--FILE-- + +--EXPECT-- +string(1) "b" +string(1) "a" diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 06f14624be4..c60cff522c2 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1541,6 +1541,13 @@ ZEND_FUNCTION(restore_exception_handler) } /* }}} */ +static int same_name(const char *key, const char *name, zend_uint name_len) +{ + char *lcname = zend_str_tolower_dup(name, name_len); + int ret = memcmp(lcname, key, name_len) == 0; + efree(lcname); + return ret; +} static int copy_class_or_interface_name(zend_class_entry **pce TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) { @@ -1552,7 +1559,13 @@ static int copy_class_or_interface_name(zend_class_entry **pce TSRMLS_DC, int nu if ((hash_key->nKeyLength==0 || hash_key->arKey[0]!=0) && (comply_mask == (ce->ce_flags & mask))) { - add_next_index_stringl(array, ce->name, ce->name_length, 1); + if (ce->refcount > 1 && + (ce->name_length != hash_key->nKeyLength - 1 || + !same_name(hash_key->arKey, ce->name, ce->name_length))) { + add_next_index_stringl(array, hash_key->arKey, hash_key->nKeyLength - 1, 1); + } else { + add_next_index_stringl(array, ce->name, ce->name_length, 1); + } } return ZEND_HASH_APPLY_KEEP; } From 984561cfa81adfd893833bce506544349b04c803 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 19 Mar 2013 15:45:48 +0400 Subject: [PATCH 168/276] Partial fix for bug #64239 --- Zend/tests/bug64239_1.phpt | 22 +++++++++++++++++++++ Zend/zend_builtin_functions.c | 37 +++++++++++++++++++++++------------ 2 files changed, 46 insertions(+), 13 deletions(-) create mode 100644 Zend/tests/bug64239_1.phpt diff --git a/Zend/tests/bug64239_1.phpt b/Zend/tests/bug64239_1.phpt new file mode 100644 index 00000000000..fe58cbd7679 --- /dev/null +++ b/Zend/tests/bug64239_1.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #64239 (get_class_methods() changed behavior) +--FILE-- +backtrace(); } +} +class B { + use T2 { t2method as Bmethod; } +} +trait T2 { + public function t2method() { + } +} +var_dump(get_class_methods("B")); +--EXPECT-- +array(2) { + [0]=> + string(7) "bmethod" + [1]=> + string(8) "t2method" +} diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 1e85785c400..dcb18182e1d 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1025,6 +1025,13 @@ ZEND_FUNCTION(get_object_vars) } /* }}} */ +static int same_name(const char *key, const char *name, zend_uint name_len) +{ + char *lcname = zend_str_tolower_dup(name, name_len); + int ret = memcmp(lcname, key, name_len) == 0; + efree(lcname); + return ret; +} /* {{{ proto array get_class_methods(mixed class) Returns an array of method names for class or class instance. */ @@ -1072,14 +1079,26 @@ ZEND_FUNCTION(get_class_methods) uint len = strlen(mptr->common.function_name); /* Do not display old-style inherited constructors */ - if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0 || - mptr->common.scope == ce || - zend_hash_get_current_key_ex(&ce->function_table, &key, &key_len, &num_index, 0, &pos) != HASH_KEY_IS_STRING || - zend_binary_strcasecmp(key, key_len-1, mptr->common.function_name, len) == 0) { - + if (zend_hash_get_current_key_ex(&ce->function_table, &key, &key_len, &num_index, 0, &pos) != HASH_KEY_IS_STRING) { MAKE_STD_ZVAL(method_name); ZVAL_STRINGL(method_name, mptr->common.function_name, len, 1); zend_hash_next_index_insert(return_value->value.ht, &method_name, sizeof(zval *), NULL); + } else if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0 || + mptr->common.scope == ce || + zend_binary_strcasecmp(key, key_len-1, mptr->common.function_name, len) == 0) { + + if (mptr->type == ZEND_USER_FUNCTION && + *mptr->op_array.refcount > 1 && + (len != key_len - 1 || + !same_name(key, mptr->common.function_name, len))) { + MAKE_STD_ZVAL(method_name); + ZVAL_STRINGL(method_name, key, key_len - 1, 1); + zend_hash_next_index_insert(return_value->value.ht, &method_name, sizeof(zval *), NULL); + } else { + MAKE_STD_ZVAL(method_name); + ZVAL_STRINGL(method_name, mptr->common.function_name, len, 1); + zend_hash_next_index_insert(return_value->value.ht, &method_name, sizeof(zval *), NULL); + } } } zend_hash_move_forward_ex(&ce->function_table, &pos); @@ -1640,14 +1659,6 @@ ZEND_FUNCTION(restore_exception_handler) } /* }}} */ -static int same_name(const char *key, const char *name, zend_uint name_len) -{ - char *lcname = zend_str_tolower_dup(name, name_len); - int ret = memcmp(lcname, key, name_len) == 0; - efree(lcname); - return ret; -} - static int copy_class_or_interface_name(zend_class_entry **pce TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) { zval *array = va_arg(args, zval *); From 7b0993bfb4b19bb160a72310b907c4fc12a5bef9 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 19 Mar 2013 16:59:01 +0400 Subject: [PATCH 169/276] Fixed bug #63976 (Parent class incorrectly using child constant in class property) --- NEWS | 2 ++ Zend/tests/bug63976.phpt | 20 ++++++++++++++++++++ Zend/zend_API.c | 38 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/bug63976.phpt diff --git a/NEWS b/NEWS index 3c6579d028f..ca51fc39303 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,8 @@ PHP NEWS (Dmitry) . Fixed bug #64370 (microtime(true) less than $_SERVER['REQUEST_TIME_FLOAT']). (Anatol) + . Fixed bug #63976 (Parent class incorrectly using child constant in class + property). (Dmitry) . Fixed bug #62343 (Show class_alias In get_declared_classes()) (Dmitry) - PCRE: diff --git a/Zend/tests/bug63976.phpt b/Zend/tests/bug63976.phpt new file mode 100644 index 00000000000..0ac09d9b3d1 --- /dev/null +++ b/Zend/tests/bug63976.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #63976 (Parent class incorrectly using child constant in class property) +--FILE-- +table); +?> +--EXPECT-- +string(3) "foo" diff --git a/Zend/zend_API.c b/Zend/zend_API.c index eec4ab0bb15..b9e97cb342b 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1022,6 +1022,40 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destro } /* }}} */ +static int zval_update_class_constant(zval **pp, int is_static, int offset TSRMLS_DC) /* {{{ */ +{ + if ((Z_TYPE_PP(pp) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || + (Z_TYPE_PP(pp) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT_ARRAY) { + zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry); + + if ((*scope)->parent) { + zend_class_entry *ce = *scope; + HashPosition pos; + zend_property_info *prop_info; + + do { + for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos); + zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS; + zend_hash_move_forward_ex(&ce->properties_info, &pos)) { + if (is_static == ((prop_info->flags & ZEND_ACC_STATIC) != 0) && + offset == prop_info->offset) { + zend_class_entry *old_scope = *scope; + *scope = prop_info->ce; + int ret = zval_update_constant(pp, (void*)1 TSRMLS_CC); + *scope = old_scope; + return ret; + } + } + ce = ce->parent; + } while (ce); + + } + return zval_update_constant(pp, (void*)1 TSRMLS_CC); + } + return 0; +} +/* }}} */ + ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ { if ((class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) == 0 || (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count)) { @@ -1034,7 +1068,7 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC for (i = 0; i < class_type->default_properties_count; i++) { if (class_type->default_properties_table[i]) { - zval_update_constant(&class_type->default_properties_table[i], (void**)1 TSRMLS_CC); + zval_update_class_constant(&class_type->default_properties_table[i], 0, i TSRMLS_CC); } } @@ -1075,7 +1109,7 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC } for (i = 0; i < class_type->default_static_members_count; i++) { - zval_update_constant(&CE_STATIC_MEMBERS(class_type)[i], (void**)1 TSRMLS_CC); + zval_update_class_constant(&CE_STATIC_MEMBERS(class_type)[i], 1, i TSRMLS_CC); } *scope = old_scope; From 7687b8b81c599b0374cb902e9dd812d2cfc12efd Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 19 Mar 2013 14:42:18 +0100 Subject: [PATCH 170/276] fix C90 compat --- Zend/zend_API.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index b9e97cb342b..668ddff39f8 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1039,9 +1039,10 @@ static int zval_update_class_constant(zval **pp, int is_static, int offset TSRML zend_hash_move_forward_ex(&ce->properties_info, &pos)) { if (is_static == ((prop_info->flags & ZEND_ACC_STATIC) != 0) && offset == prop_info->offset) { + int ret; zend_class_entry *old_scope = *scope; *scope = prop_info->ce; - int ret = zval_update_constant(pp, (void*)1 TSRMLS_CC); + ret = zval_update_constant(pp, (void*)1 TSRMLS_CC); *scope = old_scope; return ret; } From 42574690795937290a4ad6d319f917c077542953 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Mon, 18 Mar 2013 22:01:42 +0100 Subject: [PATCH 171/276] Fix #48358 add() method for SplDoublyLinkedLis --- NEWS | 4 ++ ext/spl/spl_dllist.c | 66 +++++++++++++++++-- ...plDoublyLinkedList_add_invalid_offset.phpt | 13 ++++ ...ublyLinkedList_add_missing_parameter1.phpt | 11 ++++ ...ublyLinkedList_add_missing_parameter2.phpt | 11 ++++ .../SplDoublyLinkedList_add_null_offset.phpt | 13 ++++ ext/spl/tests/dllist_013.phpt | 45 +++++++++++++ 7 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 ext/spl/tests/SplDoublyLinkedList_add_invalid_offset.phpt create mode 100644 ext/spl/tests/SplDoublyLinkedList_add_missing_parameter1.phpt create mode 100644 ext/spl/tests/SplDoublyLinkedList_add_missing_parameter2.phpt create mode 100644 ext/spl/tests/SplDoublyLinkedList_add_null_offset.phpt create mode 100644 ext/spl/tests/dllist_013.phpt diff --git a/NEWS b/NEWS index 2ea5117f8d5..805a40d3294 100644 --- a/NEWS +++ b/NEWS @@ -22,6 +22,10 @@ PHP NEWS (Gustavo, Derick, Anatol) . Fixed bug #62852 (Unserialize Invalid Date causes crash). (Anatol) +- SPL: + . Implement FR #48358 (Add SplDoublyLinkedList::add() to insert an element + at a given offset). (Mark Baker, David Soria Parra) + 07 Mar 2013, PHP 5.5.0 Alpha 6 - Core: diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index a7f15d00e8c..3ac22010fce 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -794,7 +794,7 @@ SPL_METHOD(SplDoublyLinkedList, offsetGet) intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); index = spl_offset_convert_to_long(zindex TSRMLS_CC); - if (index < 0 || index >= intern->llist->count) { + if (index < 0 || index >= intern->llist->count) { zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC); return; } @@ -881,9 +881,9 @@ SPL_METHOD(SplDoublyLinkedList, offsetUnset) intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); index = spl_offset_convert_to_long(zindex TSRMLS_CC); - llist = intern->llist; + llist = intern->llist; - if (index < 0 || index >= intern->llist->count) { + if (index < 0 || index >= intern->llist->count) { zend_throw_exception(spl_ce_OutOfRangeException, "Offset out of range", 0 TSRMLS_CC); return; } @@ -1138,7 +1138,7 @@ SPL_METHOD(SplDoublyLinkedList, serialize) spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); smart_str buf = {0}; spl_ptr_llist_element *current = intern->llist->head, *next; - zval *flags; + zval *flags; php_serialize_data_t var_hash; if (zend_parse_parameters_none() == FAILURE) { @@ -1234,6 +1234,61 @@ error: } /* }}} */ +/* {{{ proto void SplDoublyLinkedList::add(mixed $index, mixed $newval) U + Inserts a new entry before the specified $index consisting of $newval. */ +SPL_METHOD(SplDoublyLinkedList, add) +{ + zval *zindex, *value; + spl_dllist_object *intern; + spl_ptr_llist_element *element; + long index; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zindex, &value) == FAILURE) { + return; + } + SEPARATE_ARG_IF_REF(value); + + intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + index = spl_offset_convert_to_long(zindex TSRMLS_CC); + + if (index < 0 || index > intern->llist->count) { + zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC); + return; + } + + if (index == intern->llist->count) { + /* If index is the last entry+1 then we do a push because we're not inserting before any entry */ + spl_ptr_llist_push(intern->llist, value TSRMLS_CC); + } else { + /* Get the element we want to insert before */ + element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO); + + /* Create the new element we want to insert */ + spl_ptr_llist_element *elem = emalloc(sizeof(spl_ptr_llist_element)); + + elem->data = value; + elem->rc = 1; + /* connect to the neighbours */ + elem->next = element; + elem->prev = element->prev; + + /* connect the neighbours to this new element */ + if (elem->prev == NULL) { + intern->llist->head = elem; + } else { + element->prev->next = elem; + } + element->prev = elem; + + intern->llist->count++; + + if (intern->llist->ctor) { + intern->llist->ctor(elem TSRMLS_CC); + } + } +} /* }}} */ + + /* iterator handler table */ zend_object_iterator_funcs spl_dllist_it_funcs = { spl_dllist_it_dtor, @@ -1321,6 +1376,9 @@ static const zend_function_entry spl_funcs_SplDoublyLinkedList[] = { SPL_ME(SplDoublyLinkedList, offsetGet, arginfo_dllist_offsetGet, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, offsetSet, arginfo_dllist_offsetSet, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, offsetUnset, arginfo_dllist_offsetGet, ZEND_ACC_PUBLIC) + + SPL_ME(SplDoublyLinkedList, add, arginfo_dllist_offsetSet, ZEND_ACC_PUBLIC) + /* Iterator */ SPL_ME(SplDoublyLinkedList, rewind, arginfo_dllist_void, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, current, arginfo_dllist_void, ZEND_ACC_PUBLIC) diff --git a/ext/spl/tests/SplDoublyLinkedList_add_invalid_offset.phpt b/ext/spl/tests/SplDoublyLinkedList_add_invalid_offset.phpt new file mode 100644 index 00000000000..b94b067f4d8 --- /dev/null +++ b/ext/spl/tests/SplDoublyLinkedList_add_invalid_offset.phpt @@ -0,0 +1,13 @@ +--TEST-- +Check that SplDoublyLinkedList::add throws an exception with an invalid offset argument +--FILE-- +add(12,'Offset 12 should not exist')); +} catch (OutOfRangeException $e) { + echo "Exception: ".$e->getMessage()."\n"; +} +?> +--EXPECTF-- +Exception: Offset invalid or out of range diff --git a/ext/spl/tests/SplDoublyLinkedList_add_missing_parameter1.phpt b/ext/spl/tests/SplDoublyLinkedList_add_missing_parameter1.phpt new file mode 100644 index 00000000000..12cfe40008b --- /dev/null +++ b/ext/spl/tests/SplDoublyLinkedList_add_missing_parameter1.phpt @@ -0,0 +1,11 @@ +--TEST-- +Check that SplDoublyLinkedList::add generate a warning and returns a NULL with missing arguments +--FILE-- +add()); +?> +--EXPECTF-- +Warning: SplDoublyLinkedList::add() expects exactly 2 parameters, 0 given in %s on line %d +NULL + diff --git a/ext/spl/tests/SplDoublyLinkedList_add_missing_parameter2.phpt b/ext/spl/tests/SplDoublyLinkedList_add_missing_parameter2.phpt new file mode 100644 index 00000000000..c9c319316fd --- /dev/null +++ b/ext/spl/tests/SplDoublyLinkedList_add_missing_parameter2.phpt @@ -0,0 +1,11 @@ +--TEST-- +Check that SplDoublyLinkedList::add generate a warning and returns a NULL with a missing value argument +--FILE-- +add(2)); +?> +--EXPECTF-- +Warning: SplDoublyLinkedList::add() expects exactly 2 parameters, 1 given in %s on line %d +NULL + diff --git a/ext/spl/tests/SplDoublyLinkedList_add_null_offset.phpt b/ext/spl/tests/SplDoublyLinkedList_add_null_offset.phpt new file mode 100644 index 00000000000..396f89b491e --- /dev/null +++ b/ext/spl/tests/SplDoublyLinkedList_add_null_offset.phpt @@ -0,0 +1,13 @@ +--TEST-- +Check that SplDoublyLinkedList::add throws an exception with an invalid offset argument +--FILE-- +add(NULL,2)); +} catch (OutOfRangeException $e) { + echo "Exception: ".$e->getMessage()."\n"; +} +?> +--EXPECTF-- +Exception: Offset invalid or out of range diff --git a/ext/spl/tests/dllist_013.phpt b/ext/spl/tests/dllist_013.phpt new file mode 100644 index 00000000000..b60f0639249 --- /dev/null +++ b/ext/spl/tests/dllist_013.phpt @@ -0,0 +1,45 @@ +--TEST-- +SPL: DoublyLinkedList: insert operations +--FILE-- +add(2,5); +} catch (OutOfRangeException $e) { + echo "Exception: ".$e->getMessage()."\n"; +} + +$dll->add(0,6); // 6 +$dll->add(0,3); // 3 6 +// Insert in the middle of the DLL +$dll->add(1,4); // 3 4 6 +$dll->add(2,5); // 3 4 5 6 +$dll->unshift(2); // 2 3 5 4 6 +// Insert at the beginning and end of the DLL +$dll->add(0,1); // 1 2 3 4 5 6 +$dll->add(6,7); // 1 2 3 4 5 6 7 + +echo count($dll)."\n"; + +echo $dll->pop()."\n"; +echo $dll->pop()."\n"; +echo $dll->pop()."\n"; +echo $dll->pop()."\n"; +echo $dll->pop()."\n"; +echo $dll->pop()."\n"; +echo $dll->pop()."\n"; +?> +===DONE=== + +--EXPECTF-- +Exception: Offset invalid or out of range +7 +7 +6 +5 +4 +3 +2 +1 +===DONE=== From c6f6bf88d8c660f7dcb412b0d5049d376e3a5d36 Mon Sep 17 00:00:00 2001 From: Carson McDonald Date: Tue, 12 Mar 2013 04:15:50 -0400 Subject: [PATCH 172/276] Fix typos --- main/php_ini.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/php_ini.c b/main/php_ini.c index b15a3846dd3..bceb6e59f84 100644 --- a/main/php_ini.c +++ b/main/php_ini.c @@ -290,7 +290,7 @@ static void php_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_t is_special_section = 1; has_per_dir_config = 1; - /* make the path lowercase on Windows, for case insensitivty. Does nothign for other platforms */ + /* make the path lowercase on Windows, for case insensitivity. Does nothing for other platforms */ TRANSLATE_SLASHES_LOWER(key); /* HOST sections */ From b3d82845dbdd00d7d9293247331cd08862ec30a2 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 19 Mar 2013 15:13:27 +0100 Subject: [PATCH 173/276] fix C89 compat --- ext/spl/spl_dllist.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index 3ac22010fce..83610863e42 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -1260,12 +1260,12 @@ SPL_METHOD(SplDoublyLinkedList, add) /* If index is the last entry+1 then we do a push because we're not inserting before any entry */ spl_ptr_llist_push(intern->llist, value TSRMLS_CC); } else { - /* Get the element we want to insert before */ - element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO); - /* Create the new element we want to insert */ spl_ptr_llist_element *elem = emalloc(sizeof(spl_ptr_llist_element)); + /* Get the element we want to insert before */ + element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO); + elem->data = value; elem->rc = 1; /* connect to the neighbours */ From 60b36a681986c754a925daa7142e28b450f85c38 Mon Sep 17 00:00:00 2001 From: David Soria Parra Date: Tue, 19 Mar 2013 15:26:40 +0100 Subject: [PATCH 174/276] ZO+ NEWS --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 805a40d3294..c8b70ef1e17 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ PHP NEWS ?? ??? 20??, PHP 5.5.0 Beta 1 - Core: + . Added Zend Optimizer+ extension and enable it by default. More details here: + https://wiki.php.net/rfc/optimizerplus. (Dmitry) . Fixed bug #64354 (Unserialize array of objects whose class can't be autoloaded fail). (Laruence) . Added support for changing the process's title in CLI/CLI-Server SAPIs. From 5e55c6d9fd5cd69fa67296cd6371d81812b98f2a Mon Sep 17 00:00:00 2001 From: David Soria Parra Date: Tue, 19 Mar 2013 16:15:54 +0100 Subject: [PATCH 175/276] Refer to Zend Optimizer as Zend Opcache from now on --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index c8b70ef1e17..ef2fc8f97ab 100644 --- a/NEWS +++ b/NEWS @@ -3,7 +3,7 @@ PHP NEWS ?? ??? 20??, PHP 5.5.0 Beta 1 - Core: - . Added Zend Optimizer+ extension and enable it by default. More details here: + . Added Zend Opcache extension and enable it by default. More details here: https://wiki.php.net/rfc/optimizerplus. (Dmitry) . Fixed bug #64354 (Unserialize array of objects whose class can't be autoloaded fail). (Laruence) From 8d199c7c4f93ebe5b9293096143d7007a6ad13a4 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 19 Mar 2013 21:19:55 +0100 Subject: [PATCH 176/276] Backported fix for bug #62852 --- NEWS | 3 +++ ext/date/php_date.c | 21 ++++++++++++++------- ext/date/tests/bug62852.phpt | 26 ++------------------------ ext/date/tests/bug62852_var2.phpt | 25 +++++++++++++++++++++++++ ext/date/tests/bug62852_var3.phpt | 25 +++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 31 deletions(-) create mode 100644 ext/date/tests/bug62852_var2.phpt create mode 100644 ext/date/tests/bug62852_var3.phpt diff --git a/NEWS b/NEWS index c8c6f754a0e..facb9ad1549 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,9 @@ PHP NEWS . Fixed bug #63530 (mysqlnd_stmt::bind_one_parameter crashes, uses wrong alloc for stmt->param_bind). (Andrey) +- DateTime + . Fixed bug #62852 (Unserialize Invalid Date causes crash). (Anatol) + 14 Mar 2013, PHP 5.3.23 diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 2e616b17045..e27be7d81eb 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -2554,13 +2554,15 @@ static int php_date_initialize_from_hash(zval **return_value, php_date_obj **dat case TIMELIB_ZONETYPE_OFFSET: case TIMELIB_ZONETYPE_ABBR: { char *tmp = emalloc(Z_STRLEN_PP(z_date) + Z_STRLEN_PP(z_timezone) + 2); + int ret; snprintf(tmp, Z_STRLEN_PP(z_date) + Z_STRLEN_PP(z_timezone) + 2, "%s %s", Z_STRVAL_PP(z_date), Z_STRVAL_PP(z_timezone)); - php_date_initialize(*dateobj, tmp, Z_STRLEN_PP(z_date) + Z_STRLEN_PP(z_timezone) + 1, NULL, NULL, 0 TSRMLS_CC); + ret = php_date_initialize(*dateobj, tmp, Z_STRLEN_PP(z_date) + Z_STRLEN_PP(z_timezone) + 1, NULL, NULL, 0 TSRMLS_CC); efree(tmp); - return 1; + return 1 == ret; } - case TIMELIB_ZONETYPE_ID: + case TIMELIB_ZONETYPE_ID: { + int ret; convert_to_string(*z_timezone); tzi = php_date_parse_tzfile(Z_STRVAL_PP(z_timezone), DATE_TIMEZONEDB TSRMLS_CC); @@ -2571,9 +2573,10 @@ static int php_date_initialize_from_hash(zval **return_value, php_date_obj **dat tzobj->tzi.tz = tzi; tzobj->initialized = 1; - php_date_initialize(*dateobj, Z_STRVAL_PP(z_date), Z_STRLEN_PP(z_date), NULL, tmp_obj, 0 TSRMLS_CC); + ret = php_date_initialize(*dateobj, Z_STRVAL_PP(z_date), Z_STRLEN_PP(z_date), NULL, tmp_obj, 0 TSRMLS_CC); zval_ptr_dtor(&tmp_obj); - return 1; + return 1 == ret; + } } } } @@ -2597,7 +2600,9 @@ PHP_METHOD(DateTime, __set_state) php_date_instantiate(date_ce_date, return_value TSRMLS_CC); dateobj = (php_date_obj *) zend_object_store_get_object(return_value TSRMLS_CC); - php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC); + if (!php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC)) { + php_error(E_ERROR, "Invalid serialization data for DateTime object"); + } } /* }}} */ @@ -2613,7 +2618,9 @@ PHP_METHOD(DateTime, __wakeup) myht = Z_OBJPROP_P(object); - php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC); + if (!php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC)) { + php_error(E_ERROR, "Invalid serialization data for DateTime object"); + } } /* }}} */ diff --git a/ext/date/tests/bug62852.phpt b/ext/date/tests/bug62852.phpt index 26de5102151..7013a3f97c5 100644 --- a/ext/date/tests/bug62852.phpt +++ b/ext/date/tests/bug62852.phpt @@ -1,36 +1,14 @@ --TEST-- -Bug #62852 (Unserialize invalid DateTime causes crash) +Bug #62852 (Unserialize invalid DateTime causes crash), variation 1 --INI-- date.timezone=GMT ---XFAIL-- -bug is not fixed yet --FILE-- --EXPECTF-- -okey +Fatal error: Invalid serialization data for DateTime object in %sbug62852.php on line %d diff --git a/ext/date/tests/bug62852_var2.phpt b/ext/date/tests/bug62852_var2.phpt new file mode 100644 index 00000000000..f93ba28ab1f --- /dev/null +++ b/ext/date/tests/bug62852_var2.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #62852 (Unserialize invalid DateTime causes crash), variation 2 +--INI-- +date.timezone=GMT +--FILE-- + Date: Tue, 19 Mar 2013 20:44:19 -0500 Subject: [PATCH 177/276] array_column: Fix compile-time warnings --- ext/standard/array.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index fa197375228..69837648626 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2571,9 +2571,9 @@ PHP_FUNCTION(array_column) zval *zarray, *zcolumn, *zkey = NULL, **data, **zcolval, **zkeyval; HashTable *arr_hash; HashPosition pointer; - ulong column_idx = 0, key_idx = 0, keyval_idx = 0; + ulong column_idx = 0, key_idx = 0; char *column = NULL, *key = NULL, *keyval = NULL; - int column_len = 0, key_len = 0; + int column_len = 0, key_len = 0, keyval_idx = -1; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az|z", &zarray, &zcolumn, &zkey) == FAILURE) { return; @@ -2640,13 +2640,13 @@ PHP_FUNCTION(array_column) Z_ADDREF_PP(zcolval); keyval = NULL; - keyval_idx = NULL; + keyval_idx = -1; if (zkey) { if (key && zend_hash_find(Z_ARRVAL_PP(data), key, key_len + 1, (void**)&zkeyval) == FAILURE) { - keyval_idx = NULL; + keyval_idx = -1; } else if (!key && zend_hash_index_find(Z_ARRVAL_PP(data), key_idx, (void**)&zkeyval) == FAILURE) { - keyval_idx = NULL; + keyval_idx = -1; } else { switch (Z_TYPE_PP(zkeyval)) { case IS_LONG: @@ -2660,14 +2660,14 @@ PHP_FUNCTION(array_column) keyval = Z_STRVAL_PP(zkeyval); break; default: - keyval_idx = NULL; + keyval_idx = -1; } } } if (keyval) { add_assoc_zval(return_value, keyval, *zcolval); - } else if (keyval_idx != NULL) { + } else if (keyval_idx != -1) { add_index_zval(return_value, keyval_idx, *zcolval); } else { add_next_index_zval(return_value, *zcolval); From 5aaff8d634ec919a5fa24c05485b5ad250588982 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Tue, 19 Mar 2013 22:32:50 -0700 Subject: [PATCH 178/276] clarify NEWS --- NEWS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index ef2fc8f97ab..597010b5345 100644 --- a/NEWS +++ b/NEWS @@ -3,8 +3,8 @@ PHP NEWS ?? ??? 20??, PHP 5.5.0 Beta 1 - Core: - . Added Zend Opcache extension and enable it by default. More details here: - https://wiki.php.net/rfc/optimizerplus. (Dmitry) + . Added Zend Opcache extension and enable building it by default. + More details here: https://wiki.php.net/rfc/optimizerplus. (Dmitry) . Fixed bug #64354 (Unserialize array of objects whose class can't be autoloaded fail). (Laruence) . Added support for changing the process's title in CLI/CLI-Server SAPIs. From 22159fb7b7324c3d4bb9fe00d3d2ce575a15743d Mon Sep 17 00:00:00 2001 From: Pierre Joye Date: Wed, 20 Mar 2013 07:46:59 +0100 Subject: [PATCH 179/276] - add new interpolation method . imagescale . imageaffine . replace imagerotate with new generic and optimized new implementations . imagesetinterpolationmethod, to set the default interpolation to be used with the new functions . add imagepalettetotruecolor --- Zend/zend_language_scanner.c | 15780 ++++++++++++++-------------- Zend/zend_language_scanner_defs.h | 30 +- ext/gd/config.w32 | 4 +- ext/gd/gd.c | 254 +- ext/gd/libgd/gd.c | 73 +- ext/gd/libgd/gd.h | 130 +- ext/gd/php_gd.h | 4 + 7 files changed, 8361 insertions(+), 7914 deletions(-) diff --git a/Zend/zend_language_scanner.c b/Zend/zend_language_scanner.c index f2ba6bf9d4d..afaa89071f5 100644 --- a/Zend/zend_language_scanner.c +++ b/Zend/zend_language_scanner.c @@ -1,7890 +1,7890 @@ -/* Generated by re2c 0.13.5 */ -#line 1 "Zend/zend_language_scanner.l" -/* - +----------------------------------------------------------------------+ - | Zend Engine | - +----------------------------------------------------------------------+ - | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) | - +----------------------------------------------------------------------+ - | This source file is subject to version 2.00 of the Zend license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.zend.com/license/2_00.txt. | - | If you did not receive a copy of the Zend license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@zend.com so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Marcus Boerger | - | Nuno Lopes | - | Scott MacVicar | - | Flex version authors: | - | Andi Gutmans | - | Zeev Suraski | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#if 0 -# define YYDEBUG(s, c) printf("state: %d char: %c\n", s, c) -#else -# define YYDEBUG(s, c) -#endif - -#include "zend_language_scanner_defs.h" - -#include -#include "zend.h" -#ifdef PHP_WIN32 -# include -#endif -#include "zend_alloc.h" -#include -#include "zend_compile.h" -#include "zend_language_scanner.h" -#include "zend_highlight.h" -#include "zend_constants.h" -#include "zend_variables.h" -#include "zend_operators.h" -#include "zend_API.h" -#include "zend_strtod.h" -#include "zend_exceptions.h" -#include "tsrm_virtual_cwd.h" -#include "tsrm_config_common.h" - -#define YYCTYPE unsigned char -#define YYFILL(n) { if ((YYCURSOR + n) >= (YYLIMIT + ZEND_MMAP_AHEAD)) { return 0; } } -#define YYCURSOR SCNG(yy_cursor) -#define YYLIMIT SCNG(yy_limit) -#define YYMARKER SCNG(yy_marker) - -#define YYGETCONDITION() SCNG(yy_state) -#define YYSETCONDITION(s) SCNG(yy_state) = s - -#define STATE(name) yyc##name - -/* emulate flex constructs */ -#define BEGIN(state) YYSETCONDITION(STATE(state)) -#define YYSTATE YYGETCONDITION() -#define yytext ((char*)SCNG(yy_text)) -#define yyleng SCNG(yy_leng) -#define yyless(x) do { YYCURSOR = (unsigned char*)yytext + x; \ - yyleng = (unsigned int)x; } while(0) -#define yymore() goto yymore_restart - -/* perform sanity check. If this message is triggered you should - increase the ZEND_MMAP_AHEAD value in the zend_streams.h file */ -#define YYMAXFILL 16 -#if ZEND_MMAP_AHEAD < YYMAXFILL -# error ZEND_MMAP_AHEAD should be greater than or equal to YYMAXFILL -#endif - -#ifdef HAVE_STDARG_H -# include -#endif - -#ifdef HAVE_UNISTD_H -# include -#endif - -/* Globals Macros */ -#define SCNG LANG_SCNG -#ifdef ZTS -ZEND_API ts_rsrc_id language_scanner_globals_id; -#else -ZEND_API zend_php_scanner_globals language_scanner_globals; -#endif - -#define HANDLE_NEWLINES(s, l) \ -do { \ - char *p = (s), *boundary = p+(l); \ - \ - while (p= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z') || (c) == '_' || (c) >= 0x7F) - -#define ZEND_IS_OCT(c) ((c)>='0' && (c)<='7') -#define ZEND_IS_HEX(c) (((c)>='0' && (c)<='9') || ((c)>='a' && (c)<='f') || ((c)>='A' && (c)<='F')) - -BEGIN_EXTERN_C() - -static size_t encoding_filter_script_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC) -{ - const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C); - assert(internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding)); - return zend_multibyte_encoding_converter(to, to_length, from, from_length, internal_encoding, LANG_SCNG(script_encoding) TSRMLS_CC); -} - -static size_t encoding_filter_script_to_intermediate(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC) -{ - return zend_multibyte_encoding_converter(to, to_length, from, from_length, zend_multibyte_encoding_utf8, LANG_SCNG(script_encoding) TSRMLS_CC); -} - -static size_t encoding_filter_intermediate_to_script(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC) -{ - return zend_multibyte_encoding_converter(to, to_length, from, from_length, -LANG_SCNG(script_encoding), zend_multibyte_encoding_utf8 TSRMLS_CC); -} - -static size_t encoding_filter_intermediate_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC) -{ - const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C); - assert(internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding)); - return zend_multibyte_encoding_converter(to, to_length, from, from_length, -internal_encoding, zend_multibyte_encoding_utf8 TSRMLS_CC); -} - - -static void _yy_push_state(int new_state TSRMLS_DC) -{ - zend_stack_push(&SCNG(state_stack), (void *) &YYGETCONDITION(), sizeof(int)); - YYSETCONDITION(new_state); -} - -#define yy_push_state(state_and_tsrm) _yy_push_state(yyc##state_and_tsrm) - -static void yy_pop_state(TSRMLS_D) -{ - int *stack_state; - zend_stack_top(&SCNG(state_stack), (void **) &stack_state); - YYSETCONDITION(*stack_state); - zend_stack_del_top(&SCNG(state_stack)); -} - -static void yy_scan_buffer(char *str, unsigned int len TSRMLS_DC) -{ - YYCURSOR = (YYCTYPE*)str; - YYLIMIT = YYCURSOR + len; - if (!SCNG(yy_start)) { - SCNG(yy_start) = YYCURSOR; - } -} - -void startup_scanner(TSRMLS_D) -{ - CG(parse_error) = 0; - CG(doc_comment) = NULL; - CG(doc_comment_len) = 0; - zend_stack_init(&SCNG(state_stack)); - zend_ptr_stack_init(&SCNG(heredoc_label_stack)); -} - -static void heredoc_label_dtor(zend_heredoc_label *heredoc_label) { - efree(heredoc_label->label); -} - -void shutdown_scanner(TSRMLS_D) -{ - CG(parse_error) = 0; - RESET_DOC_COMMENT(); - zend_stack_destroy(&SCNG(state_stack)); - zend_ptr_stack_clean(&SCNG(heredoc_label_stack), (void (*)(void *)) &heredoc_label_dtor, 1); - zend_ptr_stack_destroy(&SCNG(heredoc_label_stack)); -} - -ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state TSRMLS_DC) -{ - lex_state->yy_leng = SCNG(yy_leng); - lex_state->yy_start = SCNG(yy_start); - lex_state->yy_text = SCNG(yy_text); - lex_state->yy_cursor = SCNG(yy_cursor); - lex_state->yy_marker = SCNG(yy_marker); - lex_state->yy_limit = SCNG(yy_limit); - - lex_state->state_stack = SCNG(state_stack); - zend_stack_init(&SCNG(state_stack)); - - lex_state->heredoc_label_stack = SCNG(heredoc_label_stack); - zend_ptr_stack_init(&SCNG(heredoc_label_stack)); - - lex_state->in = SCNG(yy_in); - lex_state->yy_state = YYSTATE; - lex_state->filename = zend_get_compiled_filename(TSRMLS_C); - lex_state->lineno = CG(zend_lineno); - - lex_state->script_org = SCNG(script_org); - lex_state->script_org_size = SCNG(script_org_size); - lex_state->script_filtered = SCNG(script_filtered); - lex_state->script_filtered_size = SCNG(script_filtered_size); - lex_state->input_filter = SCNG(input_filter); - lex_state->output_filter = SCNG(output_filter); - lex_state->script_encoding = SCNG(script_encoding); -} - -ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC) -{ - SCNG(yy_leng) = lex_state->yy_leng; - SCNG(yy_start) = lex_state->yy_start; - SCNG(yy_text) = lex_state->yy_text; - SCNG(yy_cursor) = lex_state->yy_cursor; - SCNG(yy_marker) = lex_state->yy_marker; - SCNG(yy_limit) = lex_state->yy_limit; - - zend_stack_destroy(&SCNG(state_stack)); - SCNG(state_stack) = lex_state->state_stack; - - zend_ptr_stack_clean(&SCNG(heredoc_label_stack), (void (*)(void *)) &heredoc_label_dtor, 1); - zend_ptr_stack_destroy(&SCNG(heredoc_label_stack)); - SCNG(heredoc_label_stack) = lex_state->heredoc_label_stack; - - SCNG(yy_in) = lex_state->in; - YYSETCONDITION(lex_state->yy_state); - CG(zend_lineno) = lex_state->lineno; - zend_restore_compiled_filename(lex_state->filename TSRMLS_CC); - - if (SCNG(script_filtered)) { - efree(SCNG(script_filtered)); - SCNG(script_filtered) = NULL; - } - SCNG(script_org) = lex_state->script_org; - SCNG(script_org_size) = lex_state->script_org_size; - SCNG(script_filtered) = lex_state->script_filtered; - SCNG(script_filtered_size) = lex_state->script_filtered_size; - SCNG(input_filter) = lex_state->input_filter; - SCNG(output_filter) = lex_state->output_filter; - SCNG(script_encoding) = lex_state->script_encoding; -} - -ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle TSRMLS_DC) -{ - zend_llist_del_element(&CG(open_files), file_handle, (int (*)(void *, void *)) zend_compare_file_handles); - /* zend_file_handle_dtor() operates on the copy, so we have to NULLify the original here */ - file_handle->opened_path = NULL; - if (file_handle->free_filename) { - file_handle->filename = NULL; - } -} - -#define BOM_UTF32_BE "\x00\x00\xfe\xff" -#define BOM_UTF32_LE "\xff\xfe\x00\x00" -#define BOM_UTF16_BE "\xfe\xff" -#define BOM_UTF16_LE "\xff\xfe" -#define BOM_UTF8 "\xef\xbb\xbf" - -static const zend_encoding *zend_multibyte_detect_utf_encoding(const unsigned char *script, size_t script_size TSRMLS_DC) -{ - const unsigned char *p; - int wchar_size = 2; - int le = 0; - - /* utf-16 or utf-32? */ - p = script; - while ((p-script) < script_size) { - p = memchr(p, 0, script_size-(p-script)-2); - if (!p) { - break; - } - if (*(p+1) == '\0' && *(p+2) == '\0') { - wchar_size = 4; - break; - } - - /* searching for UTF-32 specific byte orders, so this will do */ - p += 4; - } - - /* BE or LE? */ - p = script; - while ((p-script) < script_size) { - if (*p == '\0' && *(p+wchar_size-1) != '\0') { - /* BE */ - le = 0; - break; - } else if (*p != '\0' && *(p+wchar_size-1) == '\0') { - /* LE* */ - le = 1; - break; - } - p += wchar_size; - } - - if (wchar_size == 2) { - return le ? zend_multibyte_encoding_utf16le : zend_multibyte_encoding_utf16be; - } else { - return le ? zend_multibyte_encoding_utf32le : zend_multibyte_encoding_utf32be; - } - - return NULL; -} - -static const zend_encoding* zend_multibyte_detect_unicode(TSRMLS_D) -{ - const zend_encoding *script_encoding = NULL; - int bom_size; - unsigned char *pos1, *pos2; - - if (LANG_SCNG(script_org_size) < sizeof(BOM_UTF32_LE)-1) { - return NULL; - } - - /* check out BOM */ - if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_BE, sizeof(BOM_UTF32_BE)-1)) { - script_encoding = zend_multibyte_encoding_utf32be; - bom_size = sizeof(BOM_UTF32_BE)-1; - } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_LE, sizeof(BOM_UTF32_LE)-1)) { - script_encoding = zend_multibyte_encoding_utf32le; - bom_size = sizeof(BOM_UTF32_LE)-1; - } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_BE, sizeof(BOM_UTF16_BE)-1)) { - script_encoding = zend_multibyte_encoding_utf16be; - bom_size = sizeof(BOM_UTF16_BE)-1; - } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_LE, sizeof(BOM_UTF16_LE)-1)) { - script_encoding = zend_multibyte_encoding_utf16le; - bom_size = sizeof(BOM_UTF16_LE)-1; - } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF8, sizeof(BOM_UTF8)-1)) { - script_encoding = zend_multibyte_encoding_utf8; - bom_size = sizeof(BOM_UTF8)-1; - } - - if (script_encoding) { - /* remove BOM */ - LANG_SCNG(script_org) += bom_size; - LANG_SCNG(script_org_size) -= bom_size; - - return script_encoding; - } - - /* script contains NULL bytes -> auto-detection */ - if ((pos1 = memchr(LANG_SCNG(script_org), 0, LANG_SCNG(script_org_size)))) { - /* check if the NULL byte is after the __HALT_COMPILER(); */ - pos2 = LANG_SCNG(script_org); - - while (pos1 - pos2 >= sizeof("__HALT_COMPILER();")-1) { - pos2 = memchr(pos2, '_', pos1 - pos2); - if (!pos2) break; - pos2++; - if (strncasecmp((char*)pos2, "_HALT_COMPILER", sizeof("_HALT_COMPILER")-1) == 0) { - pos2 += sizeof("_HALT_COMPILER")-1; - while (*pos2 == ' ' || - *pos2 == '\t' || - *pos2 == '\r' || - *pos2 == '\n') { - pos2++; - } - if (*pos2 == '(') { - pos2++; - while (*pos2 == ' ' || - *pos2 == '\t' || - *pos2 == '\r' || - *pos2 == '\n') { - pos2++; - } - if (*pos2 == ')') { - pos2++; - while (*pos2 == ' ' || - *pos2 == '\t' || - *pos2 == '\r' || - *pos2 == '\n') { - pos2++; - } - if (*pos2 == ';') { - return NULL; - } - } - } - } - } - /* make best effort if BOM is missing */ - return zend_multibyte_detect_utf_encoding(LANG_SCNG(script_org), LANG_SCNG(script_org_size) TSRMLS_CC); - } - - return NULL; -} - -static const zend_encoding* zend_multibyte_find_script_encoding(TSRMLS_D) -{ - const zend_encoding *script_encoding; - - if (CG(detect_unicode)) { - /* check out bom(byte order mark) and see if containing wchars */ - script_encoding = zend_multibyte_detect_unicode(TSRMLS_C); - if (script_encoding != NULL) { - /* bom or wchar detection is prior to 'script_encoding' option */ - return script_encoding; - } - } - - /* if no script_encoding specified, just leave alone */ - if (!CG(script_encoding_list) || !CG(script_encoding_list_size)) { - return NULL; - } - - /* if multiple encodings specified, detect automagically */ - if (CG(script_encoding_list_size) > 1) { - return zend_multibyte_encoding_detector(LANG_SCNG(script_org), LANG_SCNG(script_org_size), CG(script_encoding_list), CG(script_encoding_list_size) TSRMLS_CC); - } - - return CG(script_encoding_list)[0]; -} - -ZEND_API int zend_multibyte_set_filter(const zend_encoding *onetime_encoding TSRMLS_DC) -{ - const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C); - const zend_encoding *script_encoding = onetime_encoding ? onetime_encoding: zend_multibyte_find_script_encoding(TSRMLS_C); - - if (!script_encoding) { - return FAILURE; - } - - /* judge input/output filter */ - LANG_SCNG(script_encoding) = script_encoding; - LANG_SCNG(input_filter) = NULL; - LANG_SCNG(output_filter) = NULL; - - if (!internal_encoding || LANG_SCNG(script_encoding) == internal_encoding) { - if (!zend_multibyte_check_lexer_compatibility(LANG_SCNG(script_encoding))) { - /* and if not, work around w/ script_encoding -> utf-8 -> script_encoding conversion */ - LANG_SCNG(input_filter) = encoding_filter_script_to_intermediate; - LANG_SCNG(output_filter) = encoding_filter_intermediate_to_script; - } else { - LANG_SCNG(input_filter) = NULL; - LANG_SCNG(output_filter) = NULL; - } - return SUCCESS; - } - - if (zend_multibyte_check_lexer_compatibility(internal_encoding)) { - LANG_SCNG(input_filter) = encoding_filter_script_to_internal; - LANG_SCNG(output_filter) = NULL; - } else if (zend_multibyte_check_lexer_compatibility(LANG_SCNG(script_encoding))) { - LANG_SCNG(input_filter) = NULL; - LANG_SCNG(output_filter) = encoding_filter_script_to_internal; - } else { - /* both script and internal encodings are incompatible w/ flex */ - LANG_SCNG(input_filter) = encoding_filter_script_to_intermediate; - LANG_SCNG(output_filter) = encoding_filter_intermediate_to_internal; - } - - return 0; -} - -ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC) -{ - const char *file_path = NULL; - char *buf; - size_t size, offset = 0; - - /* The shebang line was read, get the current position to obtain the buffer start */ - if (CG(start_lineno) == 2 && file_handle->type == ZEND_HANDLE_FP && file_handle->handle.fp) { - if ((offset = ftell(file_handle->handle.fp)) == -1) { - offset = 0; - } - } - - if (zend_stream_fixup(file_handle, &buf, &size TSRMLS_CC) == FAILURE) { - return FAILURE; - } - - zend_llist_add_element(&CG(open_files), file_handle); - if (file_handle->handle.stream.handle >= (void*)file_handle && file_handle->handle.stream.handle <= (void*)(file_handle+1)) { - zend_file_handle *fh = (zend_file_handle*)zend_llist_get_last(&CG(open_files)); - size_t diff = (char*)file_handle->handle.stream.handle - (char*)file_handle; - fh->handle.stream.handle = (void*)(((char*)fh) + diff); - file_handle->handle.stream.handle = fh->handle.stream.handle; - } - - /* Reset the scanner for scanning the new file */ - SCNG(yy_in) = file_handle; - SCNG(yy_start) = NULL; - - if (size != -1) { - if (CG(multibyte)) { - SCNG(script_org) = (unsigned char*)buf; - SCNG(script_org_size) = size; - SCNG(script_filtered) = NULL; - - zend_multibyte_set_filter(NULL TSRMLS_CC); - - if (SCNG(input_filter)) { - if ((size_t)-1 == SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) { - zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected " - "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding))); - } - buf = (char*)SCNG(script_filtered); - size = SCNG(script_filtered_size); - } - } - SCNG(yy_start) = (unsigned char *)buf - offset; - yy_scan_buffer(buf, size TSRMLS_CC); - } else { - zend_error_noreturn(E_COMPILE_ERROR, "zend_stream_mmap() failed"); - } - - BEGIN(INITIAL); - - if (file_handle->opened_path) { - file_path = file_handle->opened_path; - } else { - file_path = file_handle->filename; - } - - zend_set_compiled_filename(file_path TSRMLS_CC); - - if (CG(start_lineno)) { - CG(zend_lineno) = CG(start_lineno); - CG(start_lineno) = 0; - } else { - CG(zend_lineno) = 1; - } - - CG(increment_lineno) = 0; - return SUCCESS; -} -END_EXTERN_C() - - -ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) -{ - zend_lex_state original_lex_state; - zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array)); - zend_op_array *original_active_op_array = CG(active_op_array); - zend_op_array *retval=NULL; - int compiler_result; - zend_bool compilation_successful=0; - znode retval_znode; - zend_bool original_in_compilation = CG(in_compilation); - - retval_znode.op_type = IS_CONST; - retval_znode.u.constant.type = IS_LONG; - retval_znode.u.constant.value.lval = 1; - Z_UNSET_ISREF(retval_znode.u.constant); - Z_SET_REFCOUNT(retval_znode.u.constant, 1); - - zend_save_lexical_state(&original_lex_state TSRMLS_CC); - - retval = op_array; /* success oriented */ - - if (open_file_for_scanning(file_handle TSRMLS_CC)==FAILURE) { - if (type==ZEND_REQUIRE) { - zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC); - zend_bailout(); - } else { - zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC); - } - compilation_successful=0; - } else { - init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC); - CG(in_compilation) = 1; - CG(active_op_array) = op_array; - zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context))); - zend_init_compiler_context(TSRMLS_C); - compiler_result = zendparse(TSRMLS_C); - zend_do_return(&retval_znode, 0 TSRMLS_CC); - CG(in_compilation) = original_in_compilation; - if (compiler_result==1) { /* parser error */ - zend_bailout(); - } - compilation_successful=1; - } - - if (retval) { - CG(active_op_array) = original_active_op_array; - if (compilation_successful) { - pass_two(op_array TSRMLS_CC); - zend_release_labels(TSRMLS_C); - } else { - efree(op_array); - retval = NULL; - } - } - zend_restore_lexical_state(&original_lex_state TSRMLS_CC); - return retval; -} - - -zend_op_array *compile_filename(int type, zval *filename TSRMLS_DC) -{ - zend_file_handle file_handle; - zval tmp; - zend_op_array *retval; - char *opened_path = NULL; - - if (filename->type != IS_STRING) { - tmp = *filename; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - filename = &tmp; - } - file_handle.filename = filename->value.str.val; - file_handle.free_filename = 0; - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.opened_path = NULL; - file_handle.handle.fp = NULL; - - retval = zend_compile_file(&file_handle, type TSRMLS_CC); - if (retval && file_handle.handle.stream.handle) { - int dummy = 1; - - if (!file_handle.opened_path) { - file_handle.opened_path = opened_path = estrndup(filename->value.str.val, filename->value.str.len); - } - - zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL); - - if (opened_path) { - efree(opened_path); - } - } - zend_destroy_file_handle(&file_handle TSRMLS_CC); - - if (filename==&tmp) { - zval_dtor(&tmp); - } - return retval; -} - -ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_DC) -{ - char *buf; - size_t size; - - /* enforce two trailing NULLs for flex... */ - if (IS_INTERNED(str->value.str.val)) { - char *tmp = safe_emalloc(1, str->value.str.len, ZEND_MMAP_AHEAD); - memcpy(tmp, str->value.str.val, str->value.str.len + ZEND_MMAP_AHEAD); - str->value.str.val = tmp; - } else { - str->value.str.val = safe_erealloc(str->value.str.val, 1, str->value.str.len, ZEND_MMAP_AHEAD); - } - - memset(str->value.str.val + str->value.str.len, 0, ZEND_MMAP_AHEAD); - - SCNG(yy_in) = NULL; - SCNG(yy_start) = NULL; - - buf = str->value.str.val; - size = str->value.str.len; - - if (CG(multibyte)) { - SCNG(script_org) = (unsigned char*)buf; - SCNG(script_org_size) = size; - SCNG(script_filtered) = NULL; - - zend_multibyte_set_filter(zend_multibyte_get_internal_encoding(TSRMLS_C) TSRMLS_CC); - - if (SCNG(input_filter)) { - if ((size_t)-1 == SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) { - zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected " - "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding))); - } - buf = (char*)SCNG(script_filtered); - size = SCNG(script_filtered_size); - } - } - - yy_scan_buffer(buf, size TSRMLS_CC); - - zend_set_compiled_filename(filename TSRMLS_CC); - CG(zend_lineno) = 1; - CG(increment_lineno) = 0; - return SUCCESS; -} - - -ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D) -{ - size_t offset = SCNG(yy_cursor) - SCNG(yy_start); - if (SCNG(input_filter)) { - size_t original_offset = offset, length = 0; - do { - unsigned char *p = NULL; - if ((size_t)-1 == SCNG(input_filter)(&p, &length, SCNG(script_org), offset TSRMLS_CC)) { - return (size_t)-1; - } - efree(p); - if (length > original_offset) { - offset--; - } else if (length < original_offset) { - offset++; - } - } while (original_offset != length); - } - return offset; -} - - -zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC) -{ - zend_lex_state original_lex_state; - zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array)); - zend_op_array *original_active_op_array = CG(active_op_array); - zend_op_array *retval; - zval tmp; - int compiler_result; - zend_bool original_in_compilation = CG(in_compilation); - - if (source_string->value.str.len==0) { - efree(op_array); - return NULL; - } - - CG(in_compilation) = 1; - - tmp = *source_string; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - source_string = &tmp; - - zend_save_lexical_state(&original_lex_state TSRMLS_CC); - if (zend_prepare_string_for_scanning(source_string, filename TSRMLS_CC)==FAILURE) { - efree(op_array); - retval = NULL; - } else { - zend_bool orig_interactive = CG(interactive); - - CG(interactive) = 0; - init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE TSRMLS_CC); - CG(interactive) = orig_interactive; - CG(active_op_array) = op_array; - zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context))); - zend_init_compiler_context(TSRMLS_C); - BEGIN(ST_IN_SCRIPTING); - compiler_result = zendparse(TSRMLS_C); - - if (SCNG(script_filtered)) { - efree(SCNG(script_filtered)); - SCNG(script_filtered) = NULL; - } - - if (compiler_result==1) { - CG(active_op_array) = original_active_op_array; - CG(unclean_shutdown)=1; - destroy_op_array(op_array TSRMLS_CC); - efree(op_array); - retval = NULL; - } else { - zend_do_return(NULL, 0 TSRMLS_CC); - CG(active_op_array) = original_active_op_array; - pass_two(op_array TSRMLS_CC); - zend_release_labels(TSRMLS_C); - retval = op_array; - } - } - zend_restore_lexical_state(&original_lex_state TSRMLS_CC); - zval_dtor(&tmp); - CG(in_compilation) = original_in_compilation; - return retval; -} - - -BEGIN_EXTERN_C() -int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini TSRMLS_DC) -{ - zend_lex_state original_lex_state; - zend_file_handle file_handle; - - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.filename = filename; - file_handle.free_filename = 0; - file_handle.opened_path = NULL; - zend_save_lexical_state(&original_lex_state TSRMLS_CC); - if (open_file_for_scanning(&file_handle TSRMLS_CC)==FAILURE) { - zend_message_dispatcher(ZMSG_FAILED_HIGHLIGHT_FOPEN, filename TSRMLS_CC); - zend_restore_lexical_state(&original_lex_state TSRMLS_CC); - return FAILURE; - } - zend_highlight(syntax_highlighter_ini TSRMLS_CC); - if (SCNG(script_filtered)) { - efree(SCNG(script_filtered)); - SCNG(script_filtered) = NULL; - } - zend_destroy_file_handle(&file_handle TSRMLS_CC); - zend_restore_lexical_state(&original_lex_state TSRMLS_CC); - return SUCCESS; -} - -int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, char *str_name TSRMLS_DC) -{ - zend_lex_state original_lex_state; - zval tmp = *str; - - str = &tmp; - zval_copy_ctor(str); - zend_save_lexical_state(&original_lex_state TSRMLS_CC); - if (zend_prepare_string_for_scanning(str, str_name TSRMLS_CC)==FAILURE) { - zend_restore_lexical_state(&original_lex_state TSRMLS_CC); - return FAILURE; - } - BEGIN(INITIAL); - zend_highlight(syntax_highlighter_ini TSRMLS_CC); - if (SCNG(script_filtered)) { - efree(SCNG(script_filtered)); - SCNG(script_filtered) = NULL; - } - zend_restore_lexical_state(&original_lex_state TSRMLS_CC); - zval_dtor(str); - return SUCCESS; -} - -ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, const zend_encoding *old_encoding TSRMLS_DC) -{ - size_t length; - unsigned char *new_yy_start; - - /* convert and set */ - if (!SCNG(input_filter)) { - if (SCNG(script_filtered)) { - efree(SCNG(script_filtered)); - SCNG(script_filtered) = NULL; - } - SCNG(script_filtered_size) = 0; - length = SCNG(script_org_size); - new_yy_start = SCNG(script_org); - } else { - if ((size_t)-1 == SCNG(input_filter)(&new_yy_start, &length, SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) { - zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected " - "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding))); - } - SCNG(script_filtered) = new_yy_start; - SCNG(script_filtered_size) = length; - } - - SCNG(yy_cursor) = new_yy_start + (SCNG(yy_cursor) - SCNG(yy_start)); - SCNG(yy_marker) = new_yy_start + (SCNG(yy_marker) - SCNG(yy_start)); - SCNG(yy_text) = new_yy_start + (SCNG(yy_text) - SCNG(yy_start)); - SCNG(yy_limit) = new_yy_start + (SCNG(yy_limit) - SCNG(yy_start)); - - SCNG(yy_start) = new_yy_start; -} - - -# define zend_copy_value(zendlval, yytext, yyleng) \ - if (SCNG(output_filter)) { \ - size_t sz = 0; \ - SCNG(output_filter)((unsigned char **)&(zendlval->value.str.val), &sz, (unsigned char *)yytext, (size_t)yyleng TSRMLS_CC); \ - zendlval->value.str.len = sz; \ - } else { \ - zendlval->value.str.val = (char *) estrndup(yytext, yyleng); \ - zendlval->value.str.len = yyleng; \ - } - -static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quote_type TSRMLS_DC) -{ - register char *s, *t; - char *end; - - ZVAL_STRINGL(zendlval, str, len, 1); - - /* convert escape sequences */ - s = t = zendlval->value.str.val; - end = s+zendlval->value.str.len; - while (s= end) { - *t++ = '\\'; - break; - } - - switch(*s) { - case 'n': - *t++ = '\n'; - zendlval->value.str.len--; - break; - case 'r': - *t++ = '\r'; - zendlval->value.str.len--; - break; - case 't': - *t++ = '\t'; - zendlval->value.str.len--; - break; - case 'f': - *t++ = '\f'; - zendlval->value.str.len--; - break; - case 'v': - *t++ = '\v'; - zendlval->value.str.len--; - break; - case 'e': -#ifdef PHP_WIN32 - *t++ = VK_ESCAPE; -#else - *t++ = '\e'; -#endif - zendlval->value.str.len--; - break; - case '"': - case '`': - if (*s != quote_type) { - *t++ = '\\'; - *t++ = *s; - break; - } - case '\\': - case '$': - *t++ = *s; - zendlval->value.str.len--; - break; - case 'x': - case 'X': - if (ZEND_IS_HEX(*(s+1))) { - char hex_buf[3] = { 0, 0, 0 }; - - zendlval->value.str.len--; /* for the 'x' */ - - hex_buf[0] = *(++s); - zendlval->value.str.len--; - if (ZEND_IS_HEX(*(s+1))) { - hex_buf[1] = *(++s); - zendlval->value.str.len--; - } - *t++ = (char) strtol(hex_buf, NULL, 16); - } else { - *t++ = '\\'; - *t++ = *s; - } - break; - default: - /* check for an octal */ - if (ZEND_IS_OCT(*s)) { - char octal_buf[4] = { 0, 0, 0, 0 }; - - octal_buf[0] = *s; - zendlval->value.str.len--; - if (ZEND_IS_OCT(*(s+1))) { - octal_buf[1] = *(++s); - zendlval->value.str.len--; - if (ZEND_IS_OCT(*(s+1))) { - octal_buf[2] = *(++s); - zendlval->value.str.len--; - } - } - *t++ = (char) strtol(octal_buf, NULL, 8); - } else { - *t++ = '\\'; - *t++ = *s; - } - break; - } - } else { - *t++ = *s; - } - - if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) { - CG(zend_lineno)++; - } - s++; - } - *t = 0; - if (SCNG(output_filter)) { - size_t sz = 0; - s = zendlval->value.str.val; - SCNG(output_filter)((unsigned char **)&(zendlval->value.str.val), &sz, (unsigned char *)s, (size_t)zendlval->value.str.len TSRMLS_CC); - zendlval->value.str.len = sz; - efree(s); - } -} - - -int lex_scan(zval *zendlval TSRMLS_DC) -{ -restart: - SCNG(yy_text) = YYCURSOR; - -yymore_restart: - - -#line 1006 "Zend/zend_language_scanner.c" -{ - YYCTYPE yych; - unsigned int yyaccept = 0; - if (YYGETCONDITION() < 5) { - if (YYGETCONDITION() < 2) { - if (YYGETCONDITION() < 1) { - goto yyc_ST_IN_SCRIPTING; - } else { - goto yyc_ST_LOOKING_FOR_PROPERTY; - } - } else { - if (YYGETCONDITION() < 3) { - goto yyc_ST_BACKQUOTE; - } else { - if (YYGETCONDITION() < 4) { - goto yyc_ST_DOUBLE_QUOTES; - } else { - goto yyc_ST_HEREDOC; - } - } - } - } else { - if (YYGETCONDITION() < 7) { - if (YYGETCONDITION() < 6) { - goto yyc_ST_LOOKING_FOR_VARNAME; - } else { - goto yyc_ST_VAR_OFFSET; - } - } else { - if (YYGETCONDITION() < 8) { - goto yyc_INITIAL; - } else { - if (YYGETCONDITION() < 9) { - goto yyc_ST_END_HEREDOC; - } else { - goto yyc_ST_NOWDOC; - } - } - } - } -/* *********************************** */ -yyc_INITIAL: - { - static const unsigned char yybm[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 128, 128, 0, 0, 128, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 128, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }; - - YYDEBUG(0, *YYCURSOR); - YYFILL(8); - yych = *YYCURSOR; - if (yych != '<') goto yy4; - YYDEBUG(2, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych <= '?') { - if (yych == '%') goto yy7; - if (yych >= '?') goto yy5; - } else { - if (yych <= 'S') { - if (yych >= 'S') goto yy9; - } else { - if (yych == 's') goto yy9; - } - } -yy3: - YYDEBUG(3, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1803 "Zend/zend_language_scanner.l" - { - if (YYCURSOR > YYLIMIT) { - return 0; - } - -inline_char_handler: - - while (1) { - YYCTYPE *ptr = memchr(YYCURSOR, '<', YYLIMIT - YYCURSOR); - - YYCURSOR = ptr ? ptr + 1 : YYLIMIT; - - if (YYCURSOR < YYLIMIT) { - switch (*YYCURSOR) { - case '?': - if (CG(short_tags) || !strncasecmp((char*)YYCURSOR + 1, "php", 3) || (*(YYCURSOR + 1) == '=')) { /* Assume [ \t\n\r] follows "php" */ - break; - } - continue; - case '%': - if (CG(asp_tags)) { - break; - } - continue; - case 's': - case 'S': - /* Probably NOT an opening PHP