mirror of
https://github.com/php/php-src.git
synced 2024-09-21 09:57:23 +00:00
Merge branch 'master' into scalar_type_hints_v5
This commit is contained in:
commit
dc35868a77
1
NEWS
1
NEWS
@ -34,6 +34,7 @@
|
||||
. Implemented FR #55467 (phpinfo: PHP Variables with $ and single quotes). (Kalle)
|
||||
. Fixed bug #55415 (php_info produces invalid anchor names). (Kalle, Johannes)
|
||||
. Added ?? operator. (Andrea)
|
||||
. Added <=> operator. (Andrea)
|
||||
. Added \u{xxxxx} Unicode Codepoint Escape Syntax. (Andrea)
|
||||
. Fixed oversight where define() did not support arrays yet const syntax did. (Andrea, Dmitry)
|
||||
. Use "integer" and "float" instead of "long" and "double" in ZPP, type hint and conversion error messages. (Andrea)
|
||||
|
@ -398,6 +398,8 @@ Other
|
||||
. Added \u{xxxxxx} Unicode Codepoint Escape Syntax for double-quoted strings
|
||||
and heredocs.
|
||||
. define() now supports arrays as constant values, fixing an oversight where define() did not support arrays yet const syntax did.
|
||||
. Added the comparison operator (<=>), aka the spaceship operator.
|
||||
(RFC: https://wiki.php.net/rfc/combined-comparison-operator)
|
||||
|
||||
========================================
|
||||
3. Changes in SAPI modules
|
||||
|
18
Zend/tests/bug69092.2.phpt
Normal file
18
Zend/tests/bug69092.2.phpt
Normal file
@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
Bug #69092-2 (Declare Encoding Compile Check Wrong) - multibyte off
|
||||
--INI--
|
||||
zend.multibyte=0
|
||||
--FILE--
|
||||
<?php
|
||||
echo "Hi";
|
||||
|
||||
function foo() {
|
||||
declare(encoding="UTF-8");
|
||||
}
|
||||
|
||||
echo "Bye"
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: declare(encoding=...) ignored because Zend multibyte feature is turned off by settings in %s on line %d
|
||||
|
||||
Fatal error: Encoding declaration pragma must be the very first statement in the script in %s on line %d
|
22
Zend/tests/bug69092.phpt
Normal file
22
Zend/tests/bug69092.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Bug #69092 (Declare Encoding Compile Check Wrong)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded("mbstring")) {
|
||||
die("skip Requires mbstring extension");
|
||||
}
|
||||
?>
|
||||
--INI--
|
||||
zend.multibyte=On
|
||||
--FILE--
|
||||
<?php
|
||||
echo "Hi";
|
||||
|
||||
function foo() {
|
||||
declare(encoding="utf-8");
|
||||
}
|
||||
|
||||
echo "Bye"
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Encoding declaration pragma must be the very first statement in the script in %s on line %d
|
@ -3938,7 +3938,7 @@ ZEND_API zend_string *zend_resolve_method_name(zend_class_entry *ce, zend_functi
|
||||
zend_string *name;
|
||||
|
||||
if (f->common.type != ZEND_USER_FUNCTION ||
|
||||
*(f->op_array.refcount) < 2 ||
|
||||
(f->op_array.refcount && *(f->op_array.refcount) < 2) ||
|
||||
!f->common.scope ||
|
||||
!f->common.scope->trait_aliases) {
|
||||
return f->common.function_name;
|
||||
|
1142
Zend/zend_ast.c
1142
Zend/zend_ast.c
File diff suppressed because it is too large
Load Diff
@ -203,6 +203,7 @@ ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind ki
|
||||
ZEND_API zend_ast *zend_ast_list_add(zend_ast *list, zend_ast *op);
|
||||
|
||||
ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope);
|
||||
ZEND_API zend_string *zend_ast_export(const char *prefix, zend_ast *ast, const char *suffix);
|
||||
|
||||
ZEND_API zend_ast *zend_ast_copy(zend_ast *ast);
|
||||
ZEND_API void zend_ast_destroy(zend_ast *ast);
|
||||
|
@ -1227,7 +1227,7 @@ ZEND_FUNCTION(get_class_methods)
|
||||
zend_binary_strcasecmp(key->val, key->len, mptr->common.function_name->val, len) == 0) {
|
||||
|
||||
if (mptr->type == ZEND_USER_FUNCTION &&
|
||||
*mptr->op_array.refcount > 1 &&
|
||||
(!mptr->op_array.refcount || *mptr->op_array.refcount > 1) &&
|
||||
!same_name(key, mptr->common.function_name)) {
|
||||
ZVAL_STR_COPY(&method_name, zend_find_alias_name(mptr->common.scope, key));
|
||||
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
|
||||
@ -1936,7 +1936,9 @@ ZEND_FUNCTION(create_function)
|
||||
zend_error(E_ERROR, "Unexpected inconsistency in create_function()");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
(*func->refcount)++;
|
||||
if (func->refcount) {
|
||||
(*func->refcount)++;
|
||||
}
|
||||
static_variables = func->static_variables;
|
||||
func->static_variables = NULL;
|
||||
zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1);
|
||||
|
@ -499,7 +499,9 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent
|
||||
zend_hash_apply_with_arguments(static_variables, zval_copy_static_var, 1, closure->func.op_array.static_variables);
|
||||
}
|
||||
closure->func.op_array.run_time_cache = NULL;
|
||||
(*closure->func.op_array.refcount)++;
|
||||
if (closure->func.op_array.refcount) {
|
||||
(*closure->func.op_array.refcount)++;
|
||||
}
|
||||
} else {
|
||||
/* verify that we aren't binding internal function to a wrong scope */
|
||||
if(func->common.scope != NULL) {
|
||||
|
@ -927,9 +927,13 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */
|
||||
if (function->type == ZEND_USER_FUNCTION) {
|
||||
zend_op_array *op_array = &function->op_array;
|
||||
|
||||
(*op_array->refcount)++;
|
||||
if (op_array->refcount) {
|
||||
(*op_array->refcount)++;
|
||||
}
|
||||
if (op_array->static_variables) {
|
||||
op_array->static_variables = zend_array_dup(op_array->static_variables);
|
||||
if (!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
|
||||
GC_REFCOUNT(op_array->static_variables)++;
|
||||
}
|
||||
}
|
||||
op_array->run_time_cache = NULL;
|
||||
} else if (function->type == ZEND_INTERNAL_FUNCTION) {
|
||||
@ -972,7 +976,9 @@ ZEND_API int do_bind_function(const zend_op_array *op_array, const zend_op *opli
|
||||
}
|
||||
return FAILURE;
|
||||
} else {
|
||||
(*function->op_array.refcount)++;
|
||||
if (function->op_array.refcount) {
|
||||
(*function->op_array.refcount)++;
|
||||
}
|
||||
function->op_array.static_variables = NULL; /* NULL out the unbound function */
|
||||
return SUCCESS;
|
||||
}
|
||||
@ -3160,6 +3166,12 @@ static void zend_compile_static_var_common(zend_ast *var_ast, zval *value, zend_
|
||||
zend_hash_init(CG(active_op_array)->static_variables, 8, NULL, ZVAL_PTR_DTOR, 0);
|
||||
}
|
||||
|
||||
if (GC_REFCOUNT(CG(active_op_array)->static_variables) > 1) {
|
||||
if (!(GC_FLAGS(CG(active_op_array)->static_variables) & IS_ARRAY_IMMUTABLE)) {
|
||||
GC_REFCOUNT(CG(active_op_array)->static_variables)--;
|
||||
}
|
||||
CG(active_op_array)->static_variables = zend_array_dup(CG(active_op_array)->static_variables);
|
||||
}
|
||||
zend_hash_update(CG(active_op_array)->static_variables, Z_STR(var_node.u.constant), value);
|
||||
|
||||
opline = zend_emit_op(&result, by_ref ? ZEND_FETCH_W : ZEND_FETCH_R, &var_node, NULL);
|
||||
@ -3872,16 +3884,26 @@ void zend_compile_declare(zend_ast *ast) /* {{{ */
|
||||
ZVAL_COPY_VALUE(&CG(declarables).ticks, &value_zv);
|
||||
zval_dtor(&value_zv);
|
||||
} else if (zend_string_equals_literal_ci(name, "encoding")) {
|
||||
uint32_t i = 0;
|
||||
zend_bool valid = 0;
|
||||
/* Encoding declaration was already handled during parsing. Here we
|
||||
* only check that it is the first statement in the file. */
|
||||
uint32_t num = CG(active_op_array)->last;
|
||||
while (num > 0 &&
|
||||
(CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
|
||||
CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
|
||||
--num;
|
||||
}
|
||||
zend_ast_list *file_ast = zend_ast_get_list(CG(ast));
|
||||
|
||||
if (num > 0) {
|
||||
/* Check to see if this declare is preceeded only by declare statements */
|
||||
while (valid == 0 && i < file_ast->children) {
|
||||
if (file_ast->child[i] == ast) {
|
||||
valid = 1;
|
||||
} else if (file_ast->child[i] == NULL) {
|
||||
/* Empty statements are not allowed prior to a declare */
|
||||
break;
|
||||
} else if (file_ast->child[i]->kind != ZEND_AST_DECLARE) {
|
||||
/* declares can only be preceeded by other declares */
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (valid != 1) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Encoding declaration pragma must be "
|
||||
"the very first statement in the script");
|
||||
}
|
||||
|
@ -1230,6 +1230,12 @@ static zend_always_inline HashTable *zend_get_target_symbol_table(zend_execute_d
|
||||
} else if (EXPECTED(fetch_type == ZEND_FETCH_STATIC)) {
|
||||
ZEND_ASSERT(EX(func)->op_array.static_variables != NULL);
|
||||
ht = EX(func)->op_array.static_variables;
|
||||
if (GC_REFCOUNT(ht) > 1) {
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
|
||||
GC_REFCOUNT(ht)--;
|
||||
}
|
||||
EX(func)->op_array.static_variables = ht = zend_array_dup(ht);
|
||||
}
|
||||
} else {
|
||||
ZEND_ASSERT(fetch_type == ZEND_FETCH_LOCAL);
|
||||
if (!EX(symbol_table)) {
|
||||
|
@ -595,8 +595,9 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas
|
||||
if (Z_REFCOUNTED_P(p)) Z_SET_REFCOUNT_P(p, refcount);
|
||||
} else if (Z_TYPE_P(p) == IS_CONSTANT_AST) {
|
||||
zval tmp;
|
||||
SEPARATE_ZVAL_NOREF(p);
|
||||
|
||||
if (inline_change) {
|
||||
SEPARATE_ZVAL_NOREF(p);
|
||||
}
|
||||
zend_ast_evaluate(&tmp, Z_ASTVAL_P(p), scope);
|
||||
if (inline_change) {
|
||||
zend_ast_destroy_and_free(Z_ASTVAL_P(p));
|
||||
|
@ -236,7 +236,9 @@ ZEND_API void zend_generator_create_zval(zend_execute_data *call, zend_op_array
|
||||
zend_op_array *op_array_copy = (zend_op_array*)emalloc(sizeof(zend_op_array));
|
||||
*op_array_copy = *op_array;
|
||||
|
||||
(*op_array->refcount)++;
|
||||
if (op_array->refcount) {
|
||||
(*op_array->refcount)++;
|
||||
}
|
||||
op_array->run_time_cache = NULL;
|
||||
if (op_array->static_variables) {
|
||||
ALLOC_HASHTABLE(op_array_copy->static_variables);
|
||||
|
@ -130,7 +130,8 @@ ZEND_API void zend_function_dtor(zval *zv)
|
||||
|
||||
ZEND_API void zend_cleanup_op_array_data(zend_op_array *op_array)
|
||||
{
|
||||
if (op_array->static_variables) {
|
||||
if (op_array->static_variables &&
|
||||
!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
|
||||
zend_hash_clean(op_array->static_variables);
|
||||
}
|
||||
}
|
||||
@ -317,16 +318,19 @@ ZEND_API void destroy_op_array(zend_op_array *op_array)
|
||||
zval *end;
|
||||
uint32_t i;
|
||||
|
||||
if (op_array->static_variables) {
|
||||
zend_hash_destroy(op_array->static_variables);
|
||||
FREE_HASHTABLE(op_array->static_variables);
|
||||
if (op_array->static_variables &&
|
||||
!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
|
||||
if (--GC_REFCOUNT(op_array->static_variables) == 0) {
|
||||
zend_array_destroy(op_array->static_variables);
|
||||
FREE_HASHTABLE(op_array->static_variables);
|
||||
}
|
||||
}
|
||||
|
||||
if (op_array->run_time_cache && !op_array->function_name) {
|
||||
efree(op_array->run_time_cache);
|
||||
}
|
||||
|
||||
if (--(*op_array->refcount)>0) {
|
||||
if (!op_array->refcount || --(*op_array->refcount)>0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -350,6 +350,9 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
|
||||
#define IS_STR_CONSTANT (1<<3) /* constant index */
|
||||
#define IS_STR_CONSTANT_UNQUALIFIED (1<<4) /* the same as IS_CONSTANT_UNQUALIFIED */
|
||||
|
||||
/* array flags */
|
||||
#define IS_ARRAY_IMMUTABLE (1<<1) /* the same as IS_TYPE_IMMUTABLE */
|
||||
|
||||
/* object flags (zval.value->gc.u.flags) */
|
||||
#define IS_OBJ_APPLY_COUNT 0x07
|
||||
#define IS_OBJ_DESTRUCTOR_CALLED (1<<3)
|
||||
|
@ -9,4 +9,4 @@ declare(encoding="ISO-8859-1");
|
||||
echo "ok\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
ok
|
||||
ok
|
@ -10,4 +10,4 @@ declare(encoding="ISO-8859-15") {
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
ok
|
||||
Fatal error: Encoding declaration pragma must be the very first statement in the script in %s on line %d
|
16
ext/mbstring/tests/zend_multibyte-15.phpt
Normal file
16
ext/mbstring/tests/zend_multibyte-15.phpt
Normal file
@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
zend multibyte (15)
|
||||
--INI--
|
||||
zend.multibyte=1
|
||||
--FILE--
|
||||
<?php
|
||||
declare(encoding="ISO-8859-15") {
|
||||
echo "ok\n";
|
||||
}
|
||||
declare(encoding="UTF-8") {
|
||||
echo "ok\n";
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
ok
|
||||
ok
|
14
ext/mbstring/tests/zend_multibyte-16.phpt
Normal file
14
ext/mbstring/tests/zend_multibyte-16.phpt
Normal file
@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
zend multibyte (16)
|
||||
--INI--
|
||||
zend.multibyte=1
|
||||
--FILE--
|
||||
<?php
|
||||
declare(encoding="ISO-8859-15") {
|
||||
echo "ok\n";
|
||||
}
|
||||
echo "ok\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
ok
|
||||
ok
|
@ -1163,7 +1163,13 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr
|
||||
memory_used = zend_accel_script_persist_calc(new_persistent_script, key, key_length);
|
||||
|
||||
/* Allocate shared memory */
|
||||
#ifdef __SSE2__
|
||||
/* Align to 64-byte boundary */
|
||||
ZCG(mem) = zend_shared_alloc(memory_used + 64);
|
||||
ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L);
|
||||
#else
|
||||
ZCG(mem) = zend_shared_alloc(memory_used);
|
||||
#endif
|
||||
if (!ZCG(mem)) {
|
||||
zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
|
||||
zend_shared_alloc_unlock();
|
||||
@ -1973,7 +1979,11 @@ static int accel_clean_non_persistent_function(zval *zv)
|
||||
return ZEND_HASH_APPLY_STOP;
|
||||
} else {
|
||||
if (function->op_array.static_variables) {
|
||||
accel_fast_hash_destroy(function->op_array.static_variables);
|
||||
if (!(GC_FLAGS(function->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
|
||||
if (--GC_REFCOUNT(function->op_array.static_variables) == 0) {
|
||||
accel_fast_hash_destroy(function->op_array.static_variables);
|
||||
}
|
||||
}
|
||||
function->op_array.static_variables = NULL;
|
||||
}
|
||||
return ZEND_HASH_APPLY_REMOVE;
|
||||
@ -2025,7 +2035,11 @@ static void zend_accel_fast_shutdown(void)
|
||||
break;
|
||||
} else {
|
||||
if (func->op_array.static_variables) {
|
||||
accel_fast_hash_destroy(func->op_array.static_variables);
|
||||
if (!(GC_FLAGS(func->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
|
||||
if (--GC_REFCOUNT(func->op_array.static_variables) == 0) {
|
||||
accel_fast_hash_destroy(func->op_array.static_variables);
|
||||
}
|
||||
}
|
||||
}
|
||||
zend_accel_fast_del_bucket(EG(function_table), _idx-1, _p);
|
||||
}
|
||||
@ -2043,7 +2057,11 @@ static void zend_accel_fast_shutdown(void)
|
||||
ZEND_HASH_FOREACH_PTR(&ce->function_table, func) {
|
||||
if (func->type == ZEND_USER_FUNCTION) {
|
||||
if (func->op_array.static_variables) {
|
||||
accel_fast_hash_destroy(func->op_array.static_variables);
|
||||
if (!(GC_FLAGS(func->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
|
||||
if (--GC_REFCOUNT(func->op_array.static_variables) == 0) {
|
||||
accel_fast_hash_destroy(func->op_array.static_variables);
|
||||
}
|
||||
}
|
||||
func->op_array.static_variables = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -25,10 +25,6 @@
|
||||
#include "zend_persist.h"
|
||||
#include "zend_shared_alloc.h"
|
||||
|
||||
#define ZEND_PROTECTED_REFCOUNT (1<<30)
|
||||
|
||||
static uint32_t zend_accel_refcount = ZEND_PROTECTED_REFCOUNT;
|
||||
|
||||
#if SIZEOF_SIZE_T <= SIZEOF_ZEND_LONG
|
||||
/* If sizeof(void*) == sizeof(ulong) we can use zend_hash index functions */
|
||||
# define accel_xlat_set(old, new) zend_hash_index_update_ptr(&ZCG(bind_hash), (zend_ulong)(zend_uintptr_t)(old), (new))
|
||||
@ -55,8 +51,11 @@ static void zend_accel_destroy_zend_function(zval *zv)
|
||||
|
||||
if (function->type == ZEND_USER_FUNCTION) {
|
||||
if (function->op_array.static_variables) {
|
||||
|
||||
FREE_HASHTABLE(function->op_array.static_variables);
|
||||
if (!(GC_FLAGS(function->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
|
||||
if (--GC_REFCOUNT(function->op_array.static_variables) == 0) {
|
||||
FREE_HASHTABLE(function->op_array.static_variables);
|
||||
}
|
||||
}
|
||||
function->op_array.static_variables = NULL;
|
||||
}
|
||||
}
|
||||
@ -366,24 +365,6 @@ static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind)
|
||||
}
|
||||
}
|
||||
|
||||
/* protects reference count, creates copy of statics */
|
||||
static zend_always_inline void zend_prepare_function_for_execution(zend_op_array *op_array)
|
||||
{
|
||||
/* protect reference count */
|
||||
op_array->refcount = &zend_accel_refcount;
|
||||
(*op_array->refcount) = ZEND_PROTECTED_REFCOUNT;
|
||||
|
||||
/* copy statics */
|
||||
if (UNEXPECTED(op_array->static_variables)) {
|
||||
HashTable *shared_statics = op_array->static_variables;
|
||||
|
||||
ALLOC_HASHTABLE(op_array->static_variables);
|
||||
GC_REFCOUNT(op_array->static_variables) = 1;
|
||||
GC_TYPE(op_array->static_variables) = IS_ARRAY;
|
||||
zend_hash_clone_zval(op_array->static_variables, shared_statics, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce)
|
||||
{
|
||||
uint idx;
|
||||
@ -432,31 +413,11 @@ static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class
|
||||
ZVAL_PTR(&q->val, ARENA_REALLOC(Z_PTR(p->val)));
|
||||
new_entry = (zend_op_array*)Z_PTR(q->val);
|
||||
|
||||
/* Copy constructor */
|
||||
/* we use refcount to show that op_array is referenced from several places */
|
||||
if (new_entry->refcount != NULL) {
|
||||
accel_xlat_set(Z_PTR(p->val), new_entry);
|
||||
}
|
||||
|
||||
zend_prepare_function_for_execution(new_entry);
|
||||
|
||||
if (old_ce == new_entry->scope) {
|
||||
new_entry->scope = ce;
|
||||
} else {
|
||||
if ((new_ce = accel_xlat_get(new_entry->scope)) != NULL) {
|
||||
new_entry->scope = new_ce;
|
||||
} else {
|
||||
zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s", ce->name->val, new_entry->function_name->val);
|
||||
}
|
||||
}
|
||||
new_entry->scope = ARENA_REALLOC(new_entry->scope);
|
||||
|
||||
/* update prototype */
|
||||
if (new_entry->prototype) {
|
||||
if ((new_prototype = accel_xlat_get(new_entry->prototype)) != NULL) {
|
||||
new_entry->prototype = new_prototype;
|
||||
} else {
|
||||
zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s", ce->name->val, new_entry->function_name->val);
|
||||
}
|
||||
new_entry->prototype = ARENA_REALLOC(new_entry->prototype);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -517,24 +478,14 @@ static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_cla
|
||||
prop_info->doc_comment = NULL;
|
||||
}
|
||||
}
|
||||
if (prop_info->ce == old_ce) {
|
||||
prop_info->ce = ce;
|
||||
} else if ((new_ce = accel_xlat_get(prop_info->ce)) != NULL) {
|
||||
prop_info->ce = new_ce;
|
||||
} else {
|
||||
zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s, property %s", ce->name->val, prop_info->name->val);
|
||||
}
|
||||
prop_info->ce = ARENA_REALLOC(prop_info->ce);
|
||||
}
|
||||
}
|
||||
|
||||
#define zend_update_inherited_handler(handler) \
|
||||
{ \
|
||||
if (ce->handler != NULL) { \
|
||||
if ((new_func = accel_xlat_get(ce->handler)) != NULL) { \
|
||||
ce->handler = new_func; \
|
||||
} else { \
|
||||
zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s", ce->name->val); \
|
||||
} \
|
||||
ce->handler = ARENA_REALLOC(ce->handler); \
|
||||
} \
|
||||
}
|
||||
|
||||
@ -549,11 +500,6 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
|
||||
*pce = ce = ARENA_REALLOC(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 (old_ce->default_properties_table) {
|
||||
int i;
|
||||
|
||||
@ -603,11 +549,7 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
|
||||
}
|
||||
|
||||
if (ce->parent) {
|
||||
if ((new_ce = accel_xlat_get(ce->parent)) != NULL) {
|
||||
ce->parent = new_ce;
|
||||
} else {
|
||||
zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s", ce->name->val);
|
||||
}
|
||||
ce->parent = ARENA_REALLOC(ce->parent);
|
||||
}
|
||||
|
||||
zend_update_inherited_handler(constructor);
|
||||
@ -718,21 +660,14 @@ static void zend_accel_function_hash_copy(HashTable *target, HashTable *source)
|
||||
for (idx = 0; idx < source->nNumUsed; idx++) {
|
||||
p = source->arData + idx;
|
||||
if (Z_TYPE(p->val) == IS_UNDEF) continue;
|
||||
if (p->key) {
|
||||
t = zend_hash_add(target, p->key, &p->val);
|
||||
if (UNEXPECTED(t == NULL)) {
|
||||
if (p->key->len > 0 && p->key->val[0] == 0) {
|
||||
/* Mangled key */
|
||||
t = zend_hash_update(target, p->key, &p->val);
|
||||
} else {
|
||||
t = zend_hash_find(target, p->key);
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
t = zend_hash_index_add(target, p->h, &p->val);
|
||||
if (UNEXPECTED(t == NULL)) {
|
||||
t = zend_hash_index_find(target, p->h);
|
||||
ZEND_ASSERT(p->key);
|
||||
t = zend_hash_add(target, p->key, &p->val);
|
||||
if (UNEXPECTED(t == NULL)) {
|
||||
if (p->key->len > 0 && p->key->val[0] == 0) {
|
||||
/* Mangled key */
|
||||
t = zend_hash_update(target, p->key, &p->val);
|
||||
} else {
|
||||
t = zend_hash_find(target, p->key);
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
@ -767,26 +702,18 @@ static void zend_accel_function_hash_copy_from_shm(HashTable *target, HashTable
|
||||
for (idx = 0; idx < source->nNumUsed; idx++) {
|
||||
p = source->arData + idx;
|
||||
if (Z_TYPE(p->val) == IS_UNDEF) continue;
|
||||
if (p->key) {
|
||||
t = zend_hash_add(target, p->key, &p->val);
|
||||
if (UNEXPECTED(t == NULL)) {
|
||||
if (p->key->len > 0 && p->key->val[0] == 0) {
|
||||
/* Mangled key */
|
||||
t = zend_hash_update(target, p->key, &p->val);
|
||||
} else {
|
||||
t = zend_hash_find(target, p->key);
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
t = zend_hash_index_add(target, p->h, &p->val);
|
||||
if (UNEXPECTED(t == NULL)) {
|
||||
t = zend_hash_index_find(target, p->h);
|
||||
ZEND_ASSERT(p->key);
|
||||
t = zend_hash_add(target, p->key, &p->val);
|
||||
if (UNEXPECTED(t == NULL)) {
|
||||
if (p->key->len > 0 && p->key->val[0] == 0) {
|
||||
/* Mangled key */
|
||||
t = zend_hash_update(target, p->key, &p->val);
|
||||
} else {
|
||||
t = zend_hash_find(target, p->key);
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
Z_PTR_P(t) = ARENA_REALLOC(Z_PTR(p->val));
|
||||
zend_prepare_function_for_execution((zend_op_array*)Z_PTR_P(t));
|
||||
}
|
||||
target->nInternalPointer = target->nNumOfElements ? 0 : INVALID_IDX;
|
||||
return;
|
||||
@ -818,24 +745,15 @@ static void zend_accel_class_hash_copy(HashTable *target, HashTable *source, uni
|
||||
for (idx = 0; idx < source->nNumUsed; idx++) {
|
||||
p = source->arData + idx;
|
||||
if (Z_TYPE(p->val) == IS_UNDEF) continue;
|
||||
if (p->key) {
|
||||
t = zend_hash_add(target, p->key, &p->val);
|
||||
if (UNEXPECTED(t == NULL)) {
|
||||
if (p->key->len > 0 && p->key->val[0] == 0) {
|
||||
/* Mangled key - ignore and wait for runtime */
|
||||
continue;
|
||||
} else if (!ZCG(accel_directives).ignore_dups) {
|
||||
t = zend_hash_find(target, p->key);
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
t = zend_hash_index_add(target, p->h, &p->val);
|
||||
if (UNEXPECTED(t == NULL)) {
|
||||
if (!ZCG(accel_directives).ignore_dups) {
|
||||
t = zend_hash_index_find(target,p->h);
|
||||
goto failure;
|
||||
}
|
||||
ZEND_ASSERT(p->key);
|
||||
t = zend_hash_add(target, p->key, &p->val);
|
||||
if (UNEXPECTED(t == NULL)) {
|
||||
if (p->key->len > 0 && p->key->val[0] == 0) {
|
||||
/* Mangled key - ignore and wait for runtime */
|
||||
continue;
|
||||
} else if (!ZCG(accel_directives).ignore_dups) {
|
||||
t = zend_hash_find(target, p->key);
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
if (pCopyConstructor) {
|
||||
@ -853,6 +771,34 @@ failure:
|
||||
zend_error(E_ERROR, "Cannot redeclare class %s", ce1->name->val);
|
||||
}
|
||||
|
||||
#ifdef __SSE2__
|
||||
#include <mmintrin.h>
|
||||
#include <emmintrin.h>
|
||||
|
||||
static zend_always_inline void fast_memcpy(void *dest, const void *src, size_t size)
|
||||
{
|
||||
__m128i *dqdest = (__m128i*)dest;
|
||||
const __m128i *dqsrc = (const __m128i*)src;
|
||||
const __m128i *end = (const __m128i*)((const char*)src + size);
|
||||
|
||||
do {
|
||||
_mm_prefetch(dqsrc + 4, _MM_HINT_NTA);
|
||||
_mm_prefetch(dqsrc + 6, _MM_HINT_NTA);
|
||||
|
||||
__m128i xmm0 = _mm_load_si128(dqsrc + 0);
|
||||
__m128i xmm1 = _mm_load_si128(dqsrc + 1);
|
||||
__m128i xmm2 = _mm_load_si128(dqsrc + 2);
|
||||
__m128i xmm3 = _mm_load_si128(dqsrc + 3);
|
||||
dqsrc += 4;
|
||||
_mm_stream_si128(dqdest + 0, xmm0);
|
||||
_mm_stream_si128(dqdest + 1, xmm1);
|
||||
_mm_stream_si128(dqdest + 2, xmm2);
|
||||
_mm_stream_si128(dqdest + 3, xmm3);
|
||||
dqdest += 4;
|
||||
} while (dqsrc != end);
|
||||
}
|
||||
#endif
|
||||
|
||||
zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory)
|
||||
{
|
||||
zend_op_array *op_array;
|
||||
@ -866,8 +812,15 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script,
|
||||
ZCG(current_persistent_script) = persistent_script;
|
||||
ZCG(arena_mem) = NULL;
|
||||
if (EXPECTED(persistent_script->arena_size)) {
|
||||
#ifdef __SSE2__
|
||||
/* Target address must be aligned to 64-byte boundary */
|
||||
ZCG(arena_mem) = zend_arena_alloc(&CG(arena), persistent_script->arena_size + 64);
|
||||
ZCG(arena_mem) = (void*)(((zend_uintptr_t)ZCG(arena_mem) + 63L) & ~63L);
|
||||
fast_memcpy(ZCG(arena_mem), persistent_script->arena_mem, persistent_script->arena_size);
|
||||
#else
|
||||
ZCG(arena_mem) = zend_arena_alloc(&CG(arena), persistent_script->arena_size);
|
||||
memcpy(ZCG(arena_mem), persistent_script->arena_mem, persistent_script->arena_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Copy all the necessary stuff from shared memory to regular memory, and protect the shared script */
|
||||
@ -880,8 +833,6 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script,
|
||||
zend_accel_function_hash_copy_from_shm(CG(function_table), &persistent_script->function_table);
|
||||
}
|
||||
|
||||
zend_prepare_function_for_execution(op_array);
|
||||
|
||||
/* Register __COMPILER_HALT_OFFSET__ constant */
|
||||
if (persistent_script->compiler_halt_offset != 0 &&
|
||||
persistent_script->full_path) {
|
||||
|
@ -204,6 +204,7 @@ static void zend_persist_zval(zval *z)
|
||||
/* make immutable array */
|
||||
Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
|
||||
GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
|
||||
GC_FLAGS(Z_COUNTED_P(z)) |= IS_ARRAY_IMMUTABLE;
|
||||
Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
|
||||
}
|
||||
}
|
||||
@ -229,6 +230,63 @@ static void zend_persist_zval(zval *z)
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_persist_zval_static(zval *z)
|
||||
{
|
||||
zend_uchar flags;
|
||||
void *new_ptr;
|
||||
|
||||
switch (Z_TYPE_P(z)) {
|
||||
case IS_STRING:
|
||||
case IS_CONSTANT:
|
||||
flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
|
||||
zend_accel_store_interned_string(Z_STR_P(z));
|
||||
Z_GC_FLAGS_P(z) |= flags;
|
||||
Z_TYPE_FLAGS_P(z) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
|
||||
break;
|
||||
case IS_ARRAY:
|
||||
new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z));
|
||||
if (new_ptr) {
|
||||
Z_ARR_P(z) = new_ptr;
|
||||
Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
|
||||
} else {
|
||||
if (Z_IMMUTABLE_P(z)) {
|
||||
Z_ARR_P(z) = zend_accel_memdup(Z_ARR_P(z), sizeof(zend_array));
|
||||
zend_hash_persist_immutable(Z_ARRVAL_P(z));
|
||||
} else {
|
||||
GC_REMOVE_FROM_BUFFER(Z_ARR_P(z));
|
||||
zend_accel_store(Z_ARR_P(z), sizeof(zend_array));
|
||||
zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval);
|
||||
/* make immutable array */
|
||||
Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
|
||||
GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
|
||||
GC_FLAGS(Z_COUNTED_P(z)) |= IS_ARRAY_IMMUTABLE;
|
||||
Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IS_REFERENCE:
|
||||
new_ptr = zend_shared_alloc_get_xlat_entry(Z_REF_P(z));
|
||||
if (new_ptr) {
|
||||
Z_REF_P(z) = new_ptr;
|
||||
} else {
|
||||
zend_accel_store(Z_REF_P(z), sizeof(zend_reference));
|
||||
zend_persist_zval(Z_REFVAL_P(z));
|
||||
}
|
||||
break;
|
||||
case IS_CONSTANT_AST:
|
||||
new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z));
|
||||
if (new_ptr) {
|
||||
Z_AST_P(z) = new_ptr;
|
||||
} else {
|
||||
zend_accel_store(Z_AST_P(z), sizeof(zend_ast_ref));
|
||||
Z_ASTVAL_P(z) = zend_persist_ast(Z_ASTVAL_P(z));
|
||||
Z_TYPE_FLAGS_P(z) = IS_TYPE_CONSTANT | IS_TYPE_IMMUTABLE;
|
||||
GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_persist_zval_const(zval *z)
|
||||
{
|
||||
zend_uchar flags;
|
||||
@ -258,6 +316,7 @@ static void zend_persist_zval_const(zval *z)
|
||||
/* make immutable array */
|
||||
Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
|
||||
GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
|
||||
GC_FLAGS(Z_COUNTED_P(z)) |= IS_ARRAY_IMMUTABLE;
|
||||
Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
|
||||
}
|
||||
}
|
||||
@ -293,7 +352,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
|
||||
return;
|
||||
}
|
||||
|
||||
if (--(*op_array->refcount) == 0) {
|
||||
if (op_array->refcount && --(*op_array->refcount) == 0) {
|
||||
efree(op_array->refcount);
|
||||
}
|
||||
op_array->refcount = NULL;
|
||||
@ -313,8 +372,18 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
|
||||
}
|
||||
|
||||
if (op_array->static_variables) {
|
||||
zend_hash_persist(op_array->static_variables, zend_persist_zval);
|
||||
zend_accel_store(op_array->static_variables, sizeof(HashTable));
|
||||
HashTable *stored = zend_shared_alloc_get_xlat_entry(op_array->static_variables);
|
||||
|
||||
if (stored) {
|
||||
op_array->static_variables = stored;
|
||||
} else {
|
||||
zend_hash_persist(op_array->static_variables, zend_persist_zval_static);
|
||||
zend_accel_store(op_array->static_variables, sizeof(HashTable));
|
||||
/* make immutable array */
|
||||
GC_REFCOUNT(op_array->static_variables) = 2;
|
||||
GC_TYPE_INFO(op_array->static_variables) = IS_ARRAY | (IS_ARRAY_IMMUTABLE << 8);
|
||||
op_array->static_variables->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
|
||||
}
|
||||
}
|
||||
|
||||
if (zend_shared_alloc_get_xlat_entry(op_array->opcodes)) {
|
||||
@ -494,8 +563,6 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
|
||||
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;
|
||||
@ -660,63 +727,47 @@ static int zend_update_parent_ce(zval *zv)
|
||||
|
||||
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 (ce->__callstatic) {
|
||||
ce->__callstatic = zend_shared_alloc_get_xlat_entry(ce->__callstatic);
|
||||
ce->__callstatic->op_array.refcount++;
|
||||
}
|
||||
if (ce->__debugInfo) {
|
||||
ce->__debugInfo = zend_shared_alloc_get_xlat_entry(ce->__debugInfo);
|
||||
ce->__debugInfo->op_array.refcount++;
|
||||
}
|
||||
zend_hash_apply(&ce->properties_info, (apply_func_t) zend_update_property_info_ce);
|
||||
return 0;
|
||||
@ -738,6 +789,11 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script
|
||||
*key = zend_accel_memdup(*key, key_length + 1);
|
||||
zend_accel_store_string(script->full_path);
|
||||
|
||||
#ifdef __SSE2__
|
||||
/* Align to 64-byte boundary */
|
||||
ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L);
|
||||
#endif
|
||||
|
||||
script->arena_mem = ZCG(arena_mem) = ZCG(mem);
|
||||
ZCG(mem) = (void*)((char*)ZCG(mem) + script->arena_size);
|
||||
|
||||
|
@ -150,8 +150,13 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array)
|
||||
}
|
||||
|
||||
if (op_array->static_variables) {
|
||||
ADD_DUP_SIZE(op_array->static_variables, sizeof(HashTable));
|
||||
zend_hash_persist_calc(op_array->static_variables, zend_persist_zval_calc);
|
||||
if (!zend_shared_alloc_get_xlat_entry(op_array->static_variables)) {
|
||||
HashTable *old = op_array->static_variables;
|
||||
|
||||
ADD_DUP_SIZE(op_array->static_variables, sizeof(HashTable));
|
||||
zend_hash_persist_calc(op_array->static_variables, zend_persist_zval_calc);
|
||||
zend_shared_alloc_register_xlat_entry(old, op_array->static_variables);
|
||||
}
|
||||
}
|
||||
|
||||
if (zend_shared_alloc_get_xlat_entry(op_array->opcodes)) {
|
||||
@ -356,10 +361,20 @@ uint zend_accel_script_persist_calc(zend_persistent_script *new_persistent_scrip
|
||||
ADD_DUP_SIZE(key, key_length + 1);
|
||||
ADD_STRING(new_persistent_script->full_path);
|
||||
|
||||
#ifdef __SSE2__
|
||||
/* Align size to 64-byte boundary */
|
||||
new_persistent_script->size = (new_persistent_script->size + 63) & ~63;
|
||||
#endif
|
||||
|
||||
zend_accel_persist_class_table_calc(&new_persistent_script->class_table);
|
||||
zend_hash_persist_calc(&new_persistent_script->function_table, zend_persist_op_array_calc);
|
||||
zend_persist_op_array_calc_ex(&new_persistent_script->main_op_array);
|
||||
|
||||
#ifdef __SSE2__
|
||||
/* Align size to 64-byte boundary */
|
||||
new_persistent_script->arena_size = (new_persistent_script->arena_size + 63) & ~63;
|
||||
#endif
|
||||
|
||||
new_persistent_script->size += new_persistent_script->arena_size;
|
||||
|
||||
ZCG(current_persistent_script) = NULL;
|
||||
|
@ -91,7 +91,7 @@ typedef struct _handler_entry {
|
||||
|
||||
typedef struct _zend_shared_memory_state {
|
||||
int *positions; /* current positions for each segment */
|
||||
int shared_free; /* amount of free shared memory */
|
||||
size_t shared_free; /* amount of free shared memory */
|
||||
} zend_shared_memory_state;
|
||||
|
||||
typedef struct _zend_smm_shared_globals {
|
||||
|
@ -1852,6 +1852,12 @@ ZEND_METHOD(reflection_function, getStaticVariables)
|
||||
/* Return an empty array in case no static variables exist */
|
||||
array_init(return_value);
|
||||
if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.static_variables != NULL) {
|
||||
if (GC_REFCOUNT(fptr->op_array.static_variables) > 1) {
|
||||
if (!(GC_FLAGS(fptr->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
|
||||
GC_REFCOUNT(fptr->op_array.static_variables)--;
|
||||
}
|
||||
fptr->op_array.static_variables = zend_array_dup(fptr->op_array.static_variables);
|
||||
}
|
||||
zend_hash_apply_with_argument(fptr->op_array.static_variables, (apply_func_arg_t) zval_update_constant_inline_change, fptr->common.scope);
|
||||
zend_hash_copy(Z_ARRVAL_P(return_value), fptr->op_array.static_variables, zval_add_ref);
|
||||
}
|
||||
|
@ -192,18 +192,21 @@ static inline void spl_filesystem_object_get_file_name(spl_filesystem_object *in
|
||||
{
|
||||
char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH;
|
||||
|
||||
if (!intern->file_name) {
|
||||
switch (intern->type) {
|
||||
switch (intern->type) {
|
||||
case SPL_FS_INFO:
|
||||
case SPL_FS_FILE:
|
||||
php_error_docref(NULL, E_ERROR, "Object not initialized");
|
||||
if (!intern->file_name) {
|
||||
php_error_docref(NULL, E_ERROR, "Object not initialized");
|
||||
}
|
||||
break;
|
||||
case SPL_FS_DIR:
|
||||
if (intern->file_name) {
|
||||
efree(intern->file_name);
|
||||
}
|
||||
intern->file_name_len = (int)spprintf(&intern->file_name, 0, "%s%c%s",
|
||||
spl_filesystem_object_get_path(intern, NULL),
|
||||
slash, intern->u.dir.entry.d_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
|
44
ext/spl/tests/bug68557-win32.phpt
Normal file
44
ext/spl/tests/bug68557-win32.phpt
Normal file
@ -0,0 +1,44 @@
|
||||
--TEST--
|
||||
Bug #68557 (SplFileInfo::getPathname() may be broken)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (substr(PHP_OS, 0, 3) != 'WIN') {
|
||||
die('skip.. only for Windows');
|
||||
}
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
mkdir(__DIR__ . DIRECTORY_SEPARATOR . 'tmp');
|
||||
touch(__DIR__ . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'a');
|
||||
touch(__DIR__ . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'b');
|
||||
|
||||
$d = new DirectoryIterator(__DIR__ . DIRECTORY_SEPARATOR . 'tmp');
|
||||
|
||||
$d->seek(0);
|
||||
var_dump($d->current()->getPathname());
|
||||
|
||||
$d->seek(1);
|
||||
var_dump($d->current()->getPathname());
|
||||
|
||||
$d->seek(0);
|
||||
var_dump($d->current()->getPathname());
|
||||
|
||||
$d->seek(1);
|
||||
var_dump($d->current()->getPathname());
|
||||
|
||||
$d->seek(2);
|
||||
var_dump($d->current()->getPathname());
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
unlink(__DIR__ . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'a');
|
||||
unlink(__DIR__ . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'b');
|
||||
rmdir(__DIR__ . DIRECTORY_SEPARATOR . 'tmp');
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(%d) "%s\tmp\."
|
||||
string(%d) "%s\tmp\.."
|
||||
string(%d) "%s\tmp\."
|
||||
string(%d) "%s\tmp\.."
|
||||
string(%d) "%s\tmp\a"
|
||||
|
44
ext/spl/tests/bug68557.phpt
Normal file
44
ext/spl/tests/bug68557.phpt
Normal file
@ -0,0 +1,44 @@
|
||||
--TEST--
|
||||
Bug #68557 (SplFileInfo::getPathname() may be broken)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (substr(PHP_OS, 0, 3) == 'WIN') {
|
||||
die('skip.. Not for Windows');
|
||||
}
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
mkdir(__DIR__ . DIRECTORY_SEPARATOR . 'tmp');
|
||||
touch(__DIR__ . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'a');
|
||||
touch(__DIR__ . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'b');
|
||||
|
||||
$d = new DirectoryIterator(__DIR__ . DIRECTORY_SEPARATOR . 'tmp');
|
||||
|
||||
$d->seek(0);
|
||||
var_dump($d->current()->getPathname());
|
||||
|
||||
$d->seek(1);
|
||||
var_dump($d->current()->getPathname());
|
||||
|
||||
$d->seek(0);
|
||||
var_dump($d->current()->getPathname());
|
||||
|
||||
$d->seek(1);
|
||||
var_dump($d->current()->getPathname());
|
||||
|
||||
$d->seek(2);
|
||||
var_dump($d->current()->getPathname());
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
unlink(__DIR__ . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'a');
|
||||
unlink(__DIR__ . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'b');
|
||||
rmdir(__DIR__ . DIRECTORY_SEPARATOR . 'tmp');
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(%d) "%s/tmp/b"
|
||||
string(%d) "%s/tmp/a"
|
||||
string(%d) "%s/tmp/b"
|
||||
string(%d) "%s/tmp/a"
|
||||
string(%d) "%s/tmp/.."
|
||||
|
@ -3391,6 +3391,9 @@ static void php_putenv_destructor(zval *zv) /* {{{ */
|
||||
unsetenv(pe->key);
|
||||
# elif defined(PHP_WIN32)
|
||||
SetEnvironmentVariable(pe->key, NULL);
|
||||
# ifndef ZTS
|
||||
_putenv_s(pe->key, "");
|
||||
# endif
|
||||
# else
|
||||
char **env;
|
||||
|
||||
|
@ -180,6 +180,7 @@ PHPAPI void php_output_deactivate(void)
|
||||
php_output_handler **handler = NULL;
|
||||
|
||||
if ((OG(flags) & PHP_OUTPUT_ACTIVATED)) {
|
||||
php_output_header();
|
||||
|
||||
OG(flags) ^= PHP_OUTPUT_ACTIVATED;
|
||||
OG(active) = NULL;
|
||||
|
@ -1,5 +0,0 @@
|
||||
@if exist ..\ZendEngine2\OBJECTS2_HOWTO (
|
||||
move ..\Zend ..\ZendEngine1
|
||||
move ..\ZendEngine2 ..\Zend
|
||||
echo "PLEASE RESTART VISUAL C++ TO RELOAD THE ZEND PROJECT."
|
||||
exit 1 )
|
Loading…
Reference in New Issue
Block a user