@@ -451,40 +451,92 @@ ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *sc
451451 return ret ;
452452}
453453
454- ZEND_API zend_ast * zend_ast_copy (zend_ast * ast )
454+ static size_t zend_ast_tree_size (zend_ast * ast )
455455{
456- if (ast == NULL ) {
457- return NULL ;
458- } else if (ast -> kind == ZEND_AST_ZVAL ) {
459- zend_ast_zval * new = emalloc (sizeof (zend_ast_zval ));
456+ size_t size ;
457+
458+ if (ast -> kind == ZEND_AST_ZVAL ) {
459+ size = sizeof (zend_ast_zval );
460+ } else if (zend_ast_is_list (ast )) {
461+ uint32_t i ;
462+ zend_ast_list * list = zend_ast_get_list (ast );
463+
464+ size = zend_ast_list_size (list -> children );
465+ for (i = 0 ; i < list -> children ; i ++ ) {
466+ if (list -> child [i ]) {
467+ size += zend_ast_tree_size (list -> child [i ]);
468+ }
469+ }
470+ } else {
471+ uint32_t i , children = zend_ast_get_num_children (ast );
472+
473+ size = zend_ast_size (children );
474+ for (i = 0 ; i < children ; i ++ ) {
475+ if (ast -> child [i ]) {
476+ size += zend_ast_tree_size (ast -> child [i ]);
477+ }
478+ }
479+ }
480+ return size ;
481+ }
482+
483+ static void * zend_ast_tree_copy (zend_ast * ast , void * buf )
484+ {
485+ if (ast -> kind == ZEND_AST_ZVAL ) {
486+ zend_ast_zval * new = (zend_ast_zval * )buf ;
460487 new -> kind = ZEND_AST_ZVAL ;
461488 new -> attr = ast -> attr ;
462489 ZVAL_COPY (& new -> val , zend_ast_get_zval (ast ));
463- return ( zend_ast * ) new ;
490+ buf = ( void * )(( char * ) buf + sizeof ( zend_ast_zval )) ;
464491 } else if (zend_ast_is_list (ast )) {
465492 zend_ast_list * list = zend_ast_get_list (ast );
466- zend_ast_list * new = emalloc ( zend_ast_list_size ( list -> children )) ;
493+ zend_ast_list * new = ( zend_ast_list * ) buf ;
467494 uint32_t i ;
468495 new -> kind = list -> kind ;
469496 new -> attr = list -> attr ;
470497 new -> children = list -> children ;
498+ buf = (void * )((char * )buf + zend_ast_list_size (list -> children ));
471499 for (i = 0 ; i < list -> children ; i ++ ) {
472- new -> child [i ] = zend_ast_copy (list -> child [i ]);
500+ if (list -> child [i ]) {
501+ new -> child [i ] = (zend_ast * )buf ;
502+ buf = zend_ast_tree_copy (list -> child [i ], buf );
503+ } else {
504+ new -> child [i ] = NULL ;
505+ }
473506 }
474- return (zend_ast * ) new ;
475507 } else {
476508 uint32_t i , children = zend_ast_get_num_children (ast );
477- zend_ast * new = emalloc ( zend_ast_size ( children )) ;
509+ zend_ast * new = ( zend_ast * ) buf ;
478510 new -> kind = ast -> kind ;
479511 new -> attr = ast -> attr ;
512+ buf = (void * )((char * )buf + zend_ast_size (children ));
480513 for (i = 0 ; i < children ; i ++ ) {
481- new -> child [i ] = zend_ast_copy (ast -> child [i ]);
514+ if (ast -> child [i ]) {
515+ new -> child [i ] = (zend_ast * )buf ;
516+ buf = zend_ast_tree_copy (ast -> child [i ], buf );
517+ } else {
518+ new -> child [i ] = NULL ;
519+ }
482520 }
483- return new ;
484521 }
522+ return buf ;
485523}
486524
487- static void zend_ast_destroy_ex (zend_ast * ast , zend_bool free ) {
525+ ZEND_API zend_ast_ref * zend_ast_copy (zend_ast * ast )
526+ {
527+ size_t tree_size ;
528+ zend_ast_ref * ref ;
529+
530+ ZEND_ASSERT (ast != NULL );
531+ tree_size = zend_ast_tree_size (ast ) + sizeof (zend_ast_ref );
532+ ref = emalloc (tree_size );
533+ zend_ast_tree_copy (ast , GC_AST (ref ));
534+ GC_REFCOUNT (ref ) = 1 ;
535+ GC_TYPE_INFO (ref ) = IS_CONSTANT_AST ;
536+ return ref ;
537+ }
538+
539+ ZEND_API void zend_ast_destroy (zend_ast * ast ) {
488540 if (!ast ) {
489541 return ;
490542 }
@@ -508,37 +560,26 @@ static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) {
508560 if (decl -> doc_comment ) {
509561 zend_string_release (decl -> doc_comment );
510562 }
511- zend_ast_destroy_ex (decl -> child [0 ], free );
512- zend_ast_destroy_ex (decl -> child [1 ], free );
513- zend_ast_destroy_ex (decl -> child [2 ], free );
514- zend_ast_destroy_ex (decl -> child [3 ], free );
563+ zend_ast_destroy (decl -> child [0 ]);
564+ zend_ast_destroy (decl -> child [1 ]);
565+ zend_ast_destroy (decl -> child [2 ]);
566+ zend_ast_destroy (decl -> child [3 ]);
515567 break ;
516568 }
517569 default :
518570 if (zend_ast_is_list (ast )) {
519571 zend_ast_list * list = zend_ast_get_list (ast );
520572 uint32_t i ;
521573 for (i = 0 ; i < list -> children ; i ++ ) {
522- zend_ast_destroy_ex (list -> child [i ], free );
574+ zend_ast_destroy (list -> child [i ]);
523575 }
524576 } else {
525577 uint32_t i , children = zend_ast_get_num_children (ast );
526578 for (i = 0 ; i < children ; i ++ ) {
527- zend_ast_destroy_ex (ast -> child [i ], free );
579+ zend_ast_destroy (ast -> child [i ]);
528580 }
529581 }
530582 }
531-
532- if (free ) {
533- efree (ast );
534- }
535- }
536-
537- ZEND_API void zend_ast_destroy (zend_ast * ast ) {
538- zend_ast_destroy_ex (ast , 0 );
539- }
540- ZEND_API void zend_ast_destroy_and_free (zend_ast * ast ) {
541- zend_ast_destroy_ex (ast , 1 );
542583}
543584
544585ZEND_API void zend_ast_apply (zend_ast * ast , zend_ast_apply_func fn ) {
0 commit comments