]> granicus.if.org Git - php/commitdiff
Changed zend_ast_ref structure to use only one allocation, removing dichotomy between...
authorDmitry Stogov <dmitry@zend.com>
Mon, 9 Oct 2017 13:57:51 +0000 (16:57 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 9 Oct 2017 13:57:51 +0000 (16:57 +0300)
UPGRADING.INTERNALS
Zend/zend_ast.c
Zend/zend_ast.h
Zend/zend_compile.c
Zend/zend_types.h
Zend/zend_variables.c
ext/opcache/zend_file_cache.c
ext/opcache/zend_persist.c

index d314f8316a15879d6035fea76e9dda46a1f2b0ad..6fe98f0a4558f00feccb12ba8860f61a1b21cf05 100644 (file)
@@ -13,6 +13,7 @@ PHP 7.2 INTERNALS UPGRADE NOTES
   j. Run-time constant operand addressing
   k. Array/Object recursion protection
   l. HASH_FLAG_PERSISTENT
+  m. zend_ast_ref
 
 2. Build system changes
   a. Unix build system changes
@@ -88,6 +89,11 @@ PHP 7.2 INTERNALS UPGRADE NOTES
   l. HASH_FLAG_PERSISTENT renamed into IS_ARRAY_PERSISTENT and moved into
      GC_FLAGS (to be consistent with IS_STR_PERSISTENT).
 
+  m. zend_ast_ref structure is changed to use only one allocation.
+     zend_ast_copy() now returns zend_ast_ref (instead of zend_asr).
+     zend_ast_destroy_and_free() is removed. ZVAL_NEW_AST() is replaced
+     by ZVAL_AST().
+
 ========================
 2. Build system changes
 ========================
index 772ba04e63aac24e26ecf40aca5ee0b6ba7a2a34..defa5353191ef25e67b73a88fd5050e860f72028 100644 (file)
@@ -451,40 +451,92 @@ ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *sc
        return ret;
 }
 
-ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)
+static size_t zend_ast_tree_size(zend_ast *ast)
 {
-       if (ast == NULL) {
-               return NULL;
-       } else if (ast->kind == ZEND_AST_ZVAL) {
-               zend_ast_zval *new = emalloc(sizeof(zend_ast_zval));
+       size_t size;
+
+       if (ast->kind == ZEND_AST_ZVAL) {
+               size = sizeof(zend_ast_zval);
+       } else if (zend_ast_is_list(ast)) {
+               uint32_t i;
+               zend_ast_list *list = zend_ast_get_list(ast);
+
+               size = zend_ast_list_size(list->children);
+               for (i = 0; i < list->children; i++) {
+                       if (list->child[i]) {
+                               size += zend_ast_tree_size(list->child[i]);
+                       }
+               }
+       } else {
+               uint32_t i, children = zend_ast_get_num_children(ast);
+
+               size = zend_ast_size(children);
+               for (i = 0; i < children; i++) {
+                       if (ast->child[i]) {
+                               size += zend_ast_tree_size(ast->child[i]);
+                       }
+               }
+       }
+       return size;
+}
+
+static void* zend_ast_tree_copy(zend_ast *ast, void *buf)
+{
+       if (ast->kind == ZEND_AST_ZVAL) {
+               zend_ast_zval *new = (zend_ast_zval*)buf;
                new->kind = ZEND_AST_ZVAL;
                new->attr = ast->attr;
                ZVAL_COPY(&new->val, zend_ast_get_zval(ast));
-               return (zend_ast *) new;
+               buf = (void*)((char*)buf + sizeof(zend_ast_zval));
        } else if (zend_ast_is_list(ast)) {
                zend_ast_list *list = zend_ast_get_list(ast);
-               zend_ast_list *new = emalloc(zend_ast_list_size(list->children));
+               zend_ast_list *new = (zend_ast_list*)buf;
                uint32_t i;
                new->kind = list->kind;
                new->attr = list->attr;
                new->children = list->children;
+               buf = (void*)((char*)buf + zend_ast_list_size(list->children));
                for (i = 0; i < list->children; i++) {
-                       new->child[i] = zend_ast_copy(list->child[i]);
+                       if (list->child[i]) {
+                               new->child[i] = (zend_ast*)buf;
+                               buf = zend_ast_tree_copy(list->child[i], buf);
+                       } else {
+                               new->child[i] = NULL;
+                       }
                }
-               return (zend_ast *) new;
        } else {
                uint32_t i, children = zend_ast_get_num_children(ast);
-               zend_ast *new = emalloc(zend_ast_size(children));
+               zend_ast *new = (zend_ast*)buf;
                new->kind = ast->kind;
                new->attr = ast->attr;
+               buf = (void*)((char*)buf + zend_ast_size(children));
                for (i = 0; i < children; i++) {
-                       new->child[i] = zend_ast_copy(ast->child[i]);
+                       if (ast->child[i]) {
+                               new->child[i] = (zend_ast*)buf;
+                               buf = zend_ast_tree_copy(ast->child[i], buf);
+                       } else {
+                               new->child[i] = NULL;
+                       }
                }
-               return new;
        }
+       return buf;
 }
 
-static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) {
+ZEND_API zend_ast_ref *zend_ast_copy(zend_ast *ast)
+{
+       size_t tree_size;
+       zend_ast_ref *ref;
+
+       ZEND_ASSERT(ast != NULL);
+       tree_size = zend_ast_tree_size(ast) + sizeof(zend_ast_ref);
+       ref = emalloc(tree_size);
+       zend_ast_tree_copy(ast, GC_AST(ref));
+       GC_REFCOUNT(ref) = 1;
+       GC_TYPE_INFO(ref) = IS_CONSTANT_AST;
+       return ref;
+}
+
+ZEND_API void zend_ast_destroy(zend_ast *ast) {
        if (!ast) {
                return;
        }
@@ -508,10 +560,10 @@ static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) {
                        if (decl->doc_comment) {
                                zend_string_release(decl->doc_comment);
                        }
-                       zend_ast_destroy_ex(decl->child[0], free);
-                       zend_ast_destroy_ex(decl->child[1], free);
-                       zend_ast_destroy_ex(decl->child[2], free);
-                       zend_ast_destroy_ex(decl->child[3], free);
+                       zend_ast_destroy(decl->child[0]);
+                       zend_ast_destroy(decl->child[1]);
+                       zend_ast_destroy(decl->child[2]);
+                       zend_ast_destroy(decl->child[3]);
                        break;
                }
                default:
@@ -519,26 +571,15 @@ static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) {
                                zend_ast_list *list = zend_ast_get_list(ast);
                                uint32_t i;
                                for (i = 0; i < list->children; i++) {
-                                       zend_ast_destroy_ex(list->child[i], free);
+                                       zend_ast_destroy(list->child[i]);
                                }
                        } else {
                                uint32_t i, children = zend_ast_get_num_children(ast);
                                for (i = 0; i < children; i++) {
-                                       zend_ast_destroy_ex(ast->child[i], free);
+                                       zend_ast_destroy(ast->child[i]);
                                }
                        }
        }
-
-       if (free) {
-               efree(ast);
-       }
-}
-
-ZEND_API void zend_ast_destroy(zend_ast *ast) {
-       zend_ast_destroy_ex(ast, 0);
-}
-ZEND_API void zend_ast_destroy_and_free(zend_ast *ast) {
-       zend_ast_destroy_ex(ast, 1);
 }
 
 ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn) {
index a0aff31d709fb3e56f7d6ef12cf9e4e5d593b423..9e0aeeb54598acfa62ec117f2baafc646945c805 100644 (file)
@@ -206,9 +206,8 @@ ZEND_API zend_ast *zend_ast_list_add(zend_ast *list, zend_ast *op);
 ZEND_API int 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 zend_ast_ref *zend_ast_copy(zend_ast *ast);
 ZEND_API void zend_ast_destroy(zend_ast *ast);
-ZEND_API void zend_ast_destroy_and_free(zend_ast *ast);
 
 typedef void (*zend_ast_apply_func)(zend_ast **ast_ptr);
 ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn);
index ee93b83eba0db1a352d7580e88d9e5337e069b44..2f73afcf9e49489dd624efc5a6388d1a83bce83e 100644 (file)
@@ -8040,7 +8040,7 @@ void zend_const_expr_to_zval(zval *result, zend_ast *ast) /* {{{ */
        if (ast->kind == ZEND_AST_ZVAL) {
                ZVAL_COPY_VALUE(result, zend_ast_get_zval(ast));
        } else {
-               ZVAL_NEW_AST(result, zend_ast_copy(ast));
+               ZVAL_AST(result, zend_ast_copy(ast));
                /* destroy the ast here, it might have been replaced */
                zend_ast_destroy(ast);
        }
index fc2510ae0ff318cad11f4dcf70af1e71860606d9..9ade3983be02ad84550132f3014f67c08998bc42 100644 (file)
@@ -355,7 +355,7 @@ struct _zend_reference {
 
 struct _zend_ast_ref {
        zend_refcounted_h gc;
-       zend_ast         *ast;
+       /*zend_ast        ast; zend_ast follows the zend_ast_ref structure */
 };
 
 /* regular data types */
@@ -635,7 +635,9 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
 #define Z_AST(zval)                                    (zval).value.ast
 #define Z_AST_P(zval_p)                                Z_AST(*(zval_p))
 
-#define Z_ASTVAL(zval)                         (zval).value.ast->ast
+#define GC_AST(p)                                      ((zend_ast*)(((char*)p) + sizeof(zend_ast_ref)))
+
+#define Z_ASTVAL(zval)                         GC_AST(Z_AST(zval))
 #define Z_ASTVAL_P(zval_p)                     Z_ASTVAL(*(zval_p))
 
 #define Z_INDIRECT(zval)                       (zval).value.zv
@@ -818,14 +820,9 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
                Z_TYPE_INFO_P(z) = IS_REFERENCE_EX;                                             \
        } while (0)
 
-#define ZVAL_NEW_AST(z, a) do {                                                                        \
+#define ZVAL_AST(z, ast) do {                                                                  \
                zval *__z = (z);                                                                                \
-               zend_ast_ref *_ast =                                                                    \
-               (zend_ast_ref *) emalloc(sizeof(zend_ast_ref));                 \
-               GC_REFCOUNT(_ast) = 1;                                                                  \
-               GC_TYPE_INFO(_ast) = IS_CONSTANT_AST;                                   \
-               _ast->ast = (a);                                                                                \
-               Z_AST_P(__z) = _ast;                                                                    \
+               Z_AST_P(__z) = ast;                                                                             \
                Z_TYPE_INFO_P(__z) = IS_CONSTANT_AST_EX;                                \
        } while (0)
 
index 6c1e235eb604f50f91cfd5874038506593541272..09338013b878f6048897fccadc95f967b7b923e9 100644 (file)
@@ -46,8 +46,8 @@ ZEND_API void ZEND_FASTCALL _zval_dtor_func(zend_refcounted *p ZEND_FILE_LINE_DC
                case IS_CONSTANT_AST: {
                                zend_ast_ref *ast = (zend_ast_ref*)p;
 
-                               zend_ast_destroy_and_free(ast->ast);
-                               efree_size(ast, sizeof(zend_ast_ref));
+                               zend_ast_destroy(GC_AST(ast));
+                               efree(ast);
                                break;
                        }
                case IS_OBJECT: {
@@ -174,8 +174,7 @@ ZEND_API void ZEND_FASTCALL _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
                CHECK_ZVAL_STRING_REL(Z_STR_P(zvalue));
                Z_STR_P(zvalue) = zend_string_dup(Z_STR_P(zvalue), 0);
        } else if (EXPECTED(Z_TYPE_P(zvalue) == IS_CONSTANT_AST)) {
-               zend_ast *copy = zend_ast_copy(Z_ASTVAL_P(zvalue));
-               ZVAL_NEW_AST(zvalue, copy);
+               ZVAL_AST(zvalue, zend_ast_copy(Z_ASTVAL_P(zvalue)));
        }
 }
 
index 972700d4fe0a3775ef5961e2491cf19711dc3262..a7758058ded190bfb1d2c38b604716f6dc5eee3a 100644 (file)
@@ -337,9 +337,7 @@ static void zend_file_cache_serialize_zval(zval                     *zv,
                                SERIALIZE_PTR(Z_AST_P(zv));
                                ast = Z_AST_P(zv);
                                UNSERIALIZE_PTR(ast);
-                               if (!IS_SERIALIZED(ast->ast)) {
-                                       ast->ast = zend_file_cache_serialize_ast(ast->ast, script, info, buf);
-                               }
+                               zend_file_cache_serialize_ast(Z_ASTVAL_P(zv), script, info, buf);
                        }
                        break;
        }
@@ -950,10 +948,7 @@ static void zend_file_cache_unserialize_zval(zval                    *zv,
                                zend_ast_ref *ast;
 
                                UNSERIALIZE_PTR(Z_AST_P(zv));
-                               ast = Z_AST_P(zv);
-                               if (!IS_UNSERIALIZED(ast->ast)) {
-                                       ast->ast = zend_file_cache_unserialize_ast(ast->ast, script, buf);
-                               }
+                               zend_file_cache_unserialize_ast(Z_ASTVAL_P(zv), script, buf);
                        }
                        break;
        }
index cd4077279fef6bce5f7de2755e7791d41a7e6a81..c21842b66f3e4a1c7d5499f0f0f742ebde4ab9a2 100644 (file)
@@ -273,7 +273,6 @@ static zend_ast *zend_persist_ast(zend_ast *ast)
                }
        }
 
-       efree(ast);
        return node;
 }
 
@@ -323,10 +322,12 @@ static void zend_persist_zval(zval *z)
                                Z_AST_P(z) = new_ptr;
                                Z_TYPE_FLAGS_P(z) = IS_TYPE_CONSTANT | IS_TYPE_COPYABLE;
                        } else {
-                               zend_accel_store(Z_AST_P(z), sizeof(zend_ast_ref));
-                               Z_ASTVAL_P(z) = zend_persist_ast(Z_ASTVAL_P(z));
+                               zend_ast_ref *old_ref = Z_AST_P(z);
+                               Z_ARR_P(z) = zend_accel_memdup(Z_AST_P(z), sizeof(zend_ast_ref));
+                               zend_persist_ast(GC_AST(old_ref));
                                Z_TYPE_FLAGS_P(z) = IS_TYPE_CONSTANT | IS_TYPE_COPYABLE;
                                GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
+                               efree(old_ref);
                        }
                        break;
        }