summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2014-08-05 15:38:43 +0400
committerDmitry Stogov <dmitry@zend.com>2014-08-05 15:38:43 +0400
commitce1af1e47bebb5ebbc2aa8f7a0b4dfb91ef8d327 (patch)
treed3045a9f5295f8dedd652f7daa7432c4dd1fe83c
parent3700364ca53b54fc26b9fa17bb98ad839541b51a (diff)
downloadphp-git-ce1af1e47bebb5ebbc2aa8f7a0b4dfb91ef8d327.tar.gz
Fixed bug #67725 (now we create immutable arrays only in SHM)
-rw-r--r--Zend/tests/gc_029.phpt4
-rw-r--r--Zend/zend_compile.c68
-rw-r--r--Zend/zend_compile.h1
-rw-r--r--Zend/zend_constants.c4
-rw-r--r--Zend/zend_vm_def.h4
-rw-r--r--Zend/zend_vm_execute.h14
-rw-r--r--ext/intl/collator/collator_sort.c2
-rw-r--r--ext/opcache/Optimizer/zend_optimizer.c3
-rw-r--r--ext/opcache/zend_persist.c10
9 files changed, 42 insertions, 68 deletions
diff --git a/Zend/tests/gc_029.phpt b/Zend/tests/gc_029.phpt
index 18fef3c7d7..3873d8becd 100644
--- a/Zend/tests/gc_029.phpt
+++ b/Zend/tests/gc_029.phpt
@@ -33,5 +33,5 @@ unset($foo);
unset($bar);
var_dump(gc_collect_cycles());
?>
---EXPECT--
-int(3)
+--EXPECTREGEX--
+int\([23]\)
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index f099802a62..ae26733a7b 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -6378,23 +6378,27 @@ str_index:
if (constant_array) {
/* remove run-time array construction and use constant array instead */
opline = &CG(active_op_array)->opcodes[next_op_num-1];
- while (opline != init_opline) {
+ while (1) {
if (opline->op2_type == IS_CONST) {
zend_del_literal(CG(active_op_array), opline->op2.constant);
}
- zend_del_literal(CG(active_op_array), opline->op1.constant);
+ if (opline->op1_type == IS_CONST) {
+ if (Z_TYPE(CONSTANT(opline->op1.constant)) == IS_ARRAY &&
+ Z_REFCOUNTED(CONSTANT(opline->op1.constant)) &&
+ Z_REFCOUNT(CONSTANT(opline->op1.constant)) == 2) {
+ /* don't delete nested arrays */
+ Z_DELREF(CONSTANT(opline->op1.constant));
+ ZVAL_UNDEF(&CONSTANT(opline->op1.constant));
+ }
+ zend_del_literal(CG(active_op_array), opline->op1.constant);
+ }
+ if (opline == init_opline) {
+ break;
+ }
opline--;
}
- if (opline->op2_type == IS_CONST) {
- zend_del_literal(CG(active_op_array), opline->op2.constant);
- }
- if (opline->op1_type == IS_CONST) {
- zend_del_literal(CG(active_op_array), opline->op1.constant);
- }
CG(active_op_array)->last = array_node->u.op.opline_num;
- zend_make_immutable_array(&array TSRMLS_CC);
-
result->op_type = IS_CONST;
ZVAL_COPY_VALUE(&result->u.constant, &array);
} else {
@@ -7846,58 +7850,14 @@ void zend_do_end_compilation(TSRMLS_D) /* {{{ */
}
/* }}} */
-ZEND_API void zend_make_immutable_array(zval *zv TSRMLS_DC) /* {{{ */
-{
- zend_constant *c;
-
- if (Z_IMMUTABLE_P(zv)) {
- return;
- }
-
- Z_TYPE_FLAGS_P(zv) = IS_TYPE_IMMUTABLE;
- GC_REFCOUNT(Z_COUNTED_P(zv)) = 2;
- Z_ARRVAL_P(zv)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
-
- /* store as an anonymous constant */
- c = emalloc(sizeof(zend_constant));
- ZVAL_COPY_VALUE(&c->value, zv);
- c->flags = 0;
- c->name = NULL;
- c->module_number = PHP_USER_CONSTANT;
- zend_hash_next_index_insert_ptr(EG(zend_constants), c);
-}
-/* }}} */
-
-void zend_make_immutable_array_r(zval *zv TSRMLS_DC) /* {{{ */
-{
- zval *el;
-
- if (Z_IMMUTABLE_P(zv)) {
- return;
- }
- zend_make_immutable_array(zv TSRMLS_CC);
- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zv), el) {
- if (Z_TYPE_P(el) == IS_ARRAY) {
- zend_make_immutable_array_r(el TSRMLS_CC);
- }
- } ZEND_HASH_FOREACH_END();
-}
-/* }}} */
-
void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
{
if (ast->kind == ZEND_CONST) {
ZVAL_COPY_VALUE(&result->u.constant, &ast->u.val);
efree(ast);
- if (Z_TYPE(result->u.constant) == IS_ARRAY) {
- zend_make_immutable_array_r(&result->u.constant TSRMLS_CC);
- }
} else if (zend_ast_is_ct_constant(ast)) {
zend_ast_evaluate(&result->u.constant, ast, NULL TSRMLS_CC);
zend_ast_destroy(ast);
- if (Z_TYPE(result->u.constant) == IS_ARRAY) {
- zend_make_immutable_array_r(&result->u.constant TSRMLS_CC);
- }
} else {
ZVAL_NEW_AST(&result->u.constant, ast);
}
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 4c28be91f3..3a085f6db7 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -461,7 +461,6 @@ typedef int (*unary_op_type)(zval *, zval * TSRMLS_DC);
typedef int (*binary_op_type)(zval *, zval *, zval * TSRMLS_DC);
ZEND_API unary_op_type get_unary_op(int opcode);
ZEND_API binary_op_type get_binary_op(int opcode);
-ZEND_API void zend_make_immutable_array(zval *zv TSRMLS_DC);
void zend_do_while_cond(znode *expr, znode *close_bracket_token TSRMLS_DC);
void zend_do_while_end(const znode *while_token, const znode *close_bracket_token TSRMLS_DC);
diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c
index b134ed4cfe..64ea7060fa 100644
--- a/Zend/zend_constants.c
+++ b/Zend/zend_constants.c
@@ -32,9 +32,7 @@ void free_zend_constant(zval *zv)
zend_constant *c = Z_PTR_P(zv);
if (!(c->flags & CONST_PERSISTENT)) {
- if (Z_REFCOUNTED(c->value) || Z_IMMUTABLE(c->value)) {
- _zval_dtor_func(Z_COUNTED(c->value) ZEND_FILE_LINE_CC);
- }
+ zval_dtor(&c->value);
} else {
zval_internal_dtor(&c->value);
}
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index e4ba9597a6..9c5c17fd8f 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -3835,7 +3835,7 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
retval = EX_VAR(opline->result.var);
ZVAL_COPY_VALUE(retval, &c->value);
if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
- if (Z_OPT_COPYABLE_P(retval) && (c->flags & CONST_PERSISTENT)) {
+ if (Z_OPT_COPYABLE_P(retval)) {
zval_copy_ctor_func(retval);
} else {
Z_ADDREF_P(retval);
@@ -4478,6 +4478,8 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
}
} else if (Z_IMMUTABLE_P(array_ptr)) {
zval_copy_ctor(array_ptr);
+ } else {
+ SEPARATE_ZVAL_NOREF(array_ptr);
}
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 761f4c630c..93ad949162 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -3095,6 +3095,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
}
} else if (Z_IMMUTABLE_P(array_ptr)) {
zval_copy_ctor(array_ptr);
+ } else {
+ SEPARATE_ZVAL_NOREF(array_ptr);
}
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
@@ -4137,7 +4139,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
retval = EX_VAR(opline->result.var);
ZVAL_COPY_VALUE(retval, &c->value);
if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
- if (Z_OPT_COPYABLE_P(retval) && (c->flags & CONST_PERSISTENT)) {
+ if (Z_OPT_COPYABLE_P(retval)) {
zval_copy_ctor_func(retval);
} else {
Z_ADDREF_P(retval);
@@ -8601,6 +8603,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
}
} else if (Z_IMMUTABLE_P(array_ptr)) {
zval_copy_ctor(array_ptr);
+ } else {
+ SEPARATE_ZVAL_NOREF(array_ptr);
}
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
@@ -14030,6 +14034,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
}
} else if (Z_IMMUTABLE_P(array_ptr)) {
zval_copy_ctor(array_ptr);
+ } else {
+ SEPARATE_ZVAL_NOREF(array_ptr);
}
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
@@ -16173,7 +16179,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
retval = EX_VAR(opline->result.var);
ZVAL_COPY_VALUE(retval, &c->value);
if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
- if (Z_OPT_COPYABLE_P(retval) && (c->flags & CONST_PERSISTENT)) {
+ if (Z_OPT_COPYABLE_P(retval)) {
zval_copy_ctor_func(retval);
} else {
Z_ADDREF_P(retval);
@@ -25440,7 +25446,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
retval = EX_VAR(opline->result.var);
ZVAL_COPY_VALUE(retval, &c->value);
if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
- if (Z_OPT_COPYABLE_P(retval) && (c->flags & CONST_PERSISTENT)) {
+ if (Z_OPT_COPYABLE_P(retval)) {
zval_copy_ctor_func(retval);
} else {
Z_ADDREF_P(retval);
@@ -31369,6 +31375,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
}
} else if (Z_IMMUTABLE_P(array_ptr)) {
zval_copy_ctor(array_ptr);
+ } else {
+ SEPARATE_ZVAL_NOREF(array_ptr);
}
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
diff --git a/ext/intl/collator/collator_sort.c b/ext/intl/collator/collator_sort.c
index 8bf5449e14..43140b2f41 100644
--- a/ext/intl/collator/collator_sort.c
+++ b/ext/intl/collator/collator_sort.c
@@ -498,7 +498,7 @@ PHP_FUNCTION( collator_sort_with_sort_keys )
/* sort it */
zend_qsort( sortKeyIndxBuf, sortKeyCount, sortKeyIndxSize, collator_cmp_sort_keys TSRMLS_CC );
- zval_dtor( array );
+ zval_ptr_dtor( array );
/* for resulting hash we'll assign new hash keys rather then reordering */
array_init(array);
diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c
index e4e1f74acc..fd711cb9ee 100644
--- a/ext/opcache/Optimizer/zend_optimizer.c
+++ b/ext/opcache/Optimizer/zend_optimizer.c
@@ -110,9 +110,6 @@ int zend_optimizer_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC)
int i = op_array->last_literal;
op_array->last_literal++;
op_array->literals = (zval*)erealloc(op_array->literals, op_array->last_literal * sizeof(zval));
- if (Z_TYPE_P(zv) == IS_ARRAY) {
- zend_make_immutable_array(zv TSRMLS_CC);
- }
ZVAL_COPY_VALUE(&op_array->literals[i], zv);
Z_CACHE_SLOT(op_array->literals[i]) = -1;
//??? Z_SET_REFCOUNT(op_array->literals[i].constant, 2);
diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c
index 69eecfd641..070d77670b 100644
--- a/ext/opcache/zend_persist.c
+++ b/ext/opcache/zend_persist.c
@@ -195,6 +195,7 @@ static void zend_persist_zval(zval *z TSRMLS_DC)
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));
@@ -202,6 +203,10 @@ static void zend_persist_zval(zval *z TSRMLS_DC)
} else {
zend_accel_store(Z_ARR_P(z), sizeof(zend_array));
zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval TSRMLS_CC);
+ /* make immutable array */
+ Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
+ GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
+ Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
}
}
break;
@@ -252,6 +257,7 @@ static void zend_persist_zval_const(zval *z TSRMLS_DC)
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));
@@ -259,6 +265,10 @@ static void zend_persist_zval_const(zval *z TSRMLS_DC)
} else {
zend_accel_store(Z_ARR_P(z), sizeof(zend_array));
zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval TSRMLS_CC);
+ /* make immutable array */
+ Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
+ GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
+ Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
}
}
break;