mirror of
https://github.com/php/php-src.git
synced 2026-03-28 10:12:18 +01:00
Fixed bug #67725 (now we create immutable arrays only in SHM)
This commit is contained in:
@@ -33,5 +33,5 @@ unset($foo);
|
||||
unset($bar);
|
||||
var_dump(gc_collect_cycles());
|
||||
?>
|
||||
--EXPECT--
|
||||
int(3)
|
||||
--EXPECTREGEX--
|
||||
int\([23]\)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user