]> granicus.if.org Git - php/commitdiff
Fixed bug #67725 (now we create immutable arrays only in SHM)
authorDmitry Stogov <dmitry@zend.com>
Tue, 5 Aug 2014 11:38:43 +0000 (15:38 +0400)
committerDmitry Stogov <dmitry@zend.com>
Tue, 5 Aug 2014 11:38:43 +0000 (15:38 +0400)
Zend/tests/gc_029.phpt
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_constants.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/intl/collator/collator_sort.c
ext/opcache/Optimizer/zend_optimizer.c
ext/opcache/zend_persist.c

index 18fef3c7d775434fa228d36ce74493abfec79f2a..3873d8becd02de910573f72bda4c0a625fdc31fe 100644 (file)
@@ -33,5 +33,5 @@ unset($foo);
 unset($bar);
 var_dump(gc_collect_cycles());
 ?>
---EXPECT--
-int(3)
+--EXPECTREGEX--
+int\([23]\)
index f099802a627f3d3fca87c87f0b6403b09c27fdc9..ae26733a7b1be2b27f70ae364af0c11aebbe55e3 100644 (file)
@@ -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);
        }
index 4c28be91f3de9e25e281da5805e24ae364c7e979..3a085f6db74a85c88392d1fa364542db80f5e2f5 100644 (file)
@@ -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);
index b134ed4cfe8ee1fa09752184aeb8697c375cb0f5..64ea7060fa8984132d2e9c223f60cc2c9cf42b3d 100644 (file)
@@ -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);
        }
index e4ba9597a689fd334ca0a9138b716909213c8acf..9c5c17fd8f6fff117206797b92571b4357dd557f 100644 (file)
@@ -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) {
index 761f4c630c11c5cd71e7710a5db88de9c0555f0f..93ad949162fc53ae379a1cbc0d054ec4bde472e0 100644 (file)
@@ -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) {
index 8bf5449e1430e3bde599894b90c2a2ed02ed1eba..43140b2f419adaf784cf925993f4e18d15f79eb1 100644 (file)
@@ -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);
 
index e4e1f74acc468440a453473433588802cc8ffdd0..fd711cb9ee4dd51b1b1c7291059867eaa6a62077 100644 (file)
@@ -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);
index 69eecfd641381de78cd22cc74b709b55623e36a3..070d77670b434ef6e053cebf7c17da2fe81417b6 100644 (file)
@@ -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;