unset($bar);
var_dump(gc_collect_cycles());
?>
---EXPECT--
-int(3)
+--EXPECTREGEX--
+int\([23]\)
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 {
}
/* }}} */
-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);
}
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);
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);
}
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);
}
} 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) {
}
} 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) {
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);
}
} 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) {
}
} 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) {
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);
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);
}
} 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) {
/* 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);
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);
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));
} 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;
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));
} 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;