This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH]: Use vector for access check stack


Mark,
this patch reduces the memory the access checking stack uses.  In addition
to using a vector, we use a simple counter when access checking is off.  Your
implementation of pop_to_parent was being overly conservative wrt the garbage
collector -- that cannot run in the middle of a function without also
seeing local variables.

built & tested on i686-pc-linux-gnu, ok?

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2004-06-28  Nathan Sidwell  <nathan@codesourcery.com>

	* cp-tree.h (struct deferred_access): Move to ...
	* semantics.c (struct deferred_access): ... here. Adjust.
	(deferred_access_stack): Make a VEC(deferred_access),
	(deferred_access_free_list): Remove.
	(deferred_access_no_check): New.
	(push_deferring_access_checks, resume_deferring_access_checks,
	stop_deferring_access_checks, pop_deferring_access_checks,
	get_deferred_access_checks, pop_to_parent_deferring_access_checks,
	perform_deferred_access_checks, perform_or_defer_access_check): Adjust.

Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.992
diff -c -3 -p -r1.992 cp-tree.h
*** cp/cp-tree.h	28 Jun 2004 11:07:19 -0000	1.992
--- cp/cp-tree.h	28 Jun 2004 11:36:36 -0000
*************** extern GTY(()) tree integer_three_node;
*** 3102,3133 ****
     function, two inside the body of a function in a local class, etc.)  */
  extern int function_depth;
  
- typedef struct deferred_access GTY(())
- {
-   /* A TREE_LIST representing name-lookups for which we have deferred
-      checking access controls.  We cannot check the accessibility of
-      names used in a decl-specifier-seq until we know what is being
-      declared because code like:
- 
-        class A { 
-          class B {};
-          B* f();
-        }
- 
-        A::B* A::f() { return 0; }
- 
-      is valid, even though `A::B' is not generally accessible.  
- 
-      The TREE_PURPOSE of each node is the scope used to qualify the
-      name being looked up; the TREE_VALUE is the DECL to which the
-      name was resolved.  */
-   tree deferred_access_checks;
-   /* The current mode of access checks.  */
-   enum deferring_kind deferring_access_checks_kind;
-   /* The next deferred access data in stack or linked-list.  */
-   struct deferred_access *next;
- } deferred_access;
- 
  /* in pt.c  */
  
  /* These values are used for the `STRICT' parameter to type_unification and
--- 3102,3107 ----
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.412
diff -c -3 -p -r1.412 semantics.c
*** cp/semantics.c	28 Jun 2004 10:41:19 -0000	1.412
--- cp/semantics.c	28 Jun 2004 11:37:42 -0000
***************
*** 44,49 ****
--- 44,50 ----
  #include "diagnostic.h"
  #include "cgraph.h"
  #include "tree-iterator.h"
+ #include "vec.h"
  
  /* There routines provide a modular interface to perform many parsing
     operations.  They may therefore be used during actual parsing, or
*************** static tree finalize_nrv_r (tree *, int 
*** 111,119 ****
        In case of parsing error, we simply call `pop_deferring_access_checks'
        without `perform_deferred_access_checks'.  */
  
  /* Data for deferred access checking.  */
! static GTY(()) deferred_access *deferred_access_stack;
! static GTY(()) deferred_access *deferred_access_free_list;
  
  /* Save the current deferred access states and start deferred
     access checking iff DEFER_P is true.  */
--- 112,147 ----
        In case of parsing error, we simply call `pop_deferring_access_checks'
        without `perform_deferred_access_checks'.  */
  
+ typedef struct deferred_access GTY(())
+ {
+   /* A TREE_LIST representing name-lookups for which we have deferred
+      checking access controls.  We cannot check the accessibility of
+      names used in a decl-specifier-seq until we know what is being
+      declared because code like:
+ 
+        class A { 
+          class B {};
+          B* f();
+        }
+ 
+        A::B* A::f() { return 0; }
+ 
+      is valid, even though `A::B' is not generally accessible.  
+ 
+      The TREE_PURPOSE of each node is the scope used to qualify the
+      name being looked up; the TREE_VALUE is the DECL to which the
+      name was resolved.  */
+   tree deferred_access_checks;
+   
+   /* The current mode of access checks.  */
+   enum deferring_kind deferring_access_checks_kind;
+   
+ } deferred_access;
+ DEF_VEC_O (deferred_access);
+ 
  /* Data for deferred access checking.  */
! static GTY(()) VEC (deferred_access) *deferred_access_stack;
! static GTY(()) unsigned deferred_access_no_check;
  
  /* Save the current deferred access states and start deferred
     access checking iff DEFER_P is true.  */
*************** static GTY(()) deferred_access *deferred
*** 121,147 ****
  void
  push_deferring_access_checks (deferring_kind deferring)
  {
-   deferred_access *d;
- 
    /* For context like template instantiation, access checking
       disabling applies to all nested context.  */
!   if (deferred_access_stack
!       && deferred_access_stack->deferring_access_checks_kind == dk_no_check)
!     deferring = dk_no_check;
! 
!   /* Recycle previously used free store if available.  */
!   if (deferred_access_free_list)
!     {
!       d = deferred_access_free_list;
!       deferred_access_free_list = d->next;
!     }
    else
!     d = ggc_alloc (sizeof (deferred_access));
  
!   d->next = deferred_access_stack;
!   d->deferred_access_checks = NULL_TREE;
!   d->deferring_access_checks_kind = deferring;
!   deferred_access_stack = d;
  }
  
  /* Resume deferring access checks again after we stopped doing
--- 149,166 ----
  void
  push_deferring_access_checks (deferring_kind deferring)
  {
    /* For context like template instantiation, access checking
       disabling applies to all nested context.  */
!   if (deferred_access_no_check || deferring == dk_no_check)
!     deferred_access_no_check++;
    else
!     {
!       deferred_access *ptr;
  
!       ptr = VEC_safe_push (deferred_access, deferred_access_stack, NULL);
!       ptr->deferred_access_checks = NULL_TREE;
!       ptr->deferring_access_checks_kind = deferring;
!     }
  }
  
  /* Resume deferring access checks again after we stopped doing
*************** push_deferring_access_checks (deferring_
*** 150,157 ****
  void
  resume_deferring_access_checks (void)
  {
!   if (deferred_access_stack->deferring_access_checks_kind == dk_no_deferred)
!     deferred_access_stack->deferring_access_checks_kind = dk_deferred;
  }
  
  /* Stop deferring access checks.  */
--- 169,177 ----
  void
  resume_deferring_access_checks (void)
  {
!   if (!deferred_access_no_check)
!     VEC_last (deferred_access, deferred_access_stack)
!       ->deferring_access_checks_kind = dk_deferred;
  }
  
  /* Stop deferring access checks.  */
*************** resume_deferring_access_checks (void)
*** 159,166 ****
  void
  stop_deferring_access_checks (void)
  {
!   if (deferred_access_stack->deferring_access_checks_kind == dk_deferred)
!     deferred_access_stack->deferring_access_checks_kind = dk_no_deferred;
  }
  
  /* Discard the current deferred access checks and restore the
--- 179,187 ----
  void
  stop_deferring_access_checks (void)
  {
!   if (!deferred_access_no_check)
!     VEC_last (deferred_access, deferred_access_stack)
!       ->deferring_access_checks_kind = dk_no_deferred;
  }
  
  /* Discard the current deferred access checks and restore the
*************** stop_deferring_access_checks (void)
*** 169,183 ****
  void
  pop_deferring_access_checks (void)
  {
!   deferred_access *d = deferred_access_stack;
!   deferred_access_stack = d->next;
! 
!   /* Remove references to access checks TREE_LIST.  */
!   d->deferred_access_checks = NULL_TREE;
! 
!   /* Store in free list for later use.  */
!   d->next = deferred_access_free_list;
!   deferred_access_free_list = d;
  }
  
  /* Returns a TREE_LIST representing the deferred checks.  
--- 190,199 ----
  void
  pop_deferring_access_checks (void)
  {
!   if (deferred_access_no_check)
!     deferred_access_no_check--;
!   else
!     VEC_pop (deferred_access, deferred_access_stack);
  }
  
  /* Returns a TREE_LIST representing the deferred checks.  
*************** pop_deferring_access_checks (void)
*** 188,194 ****
  tree
  get_deferred_access_checks (void)
  {
!   return deferred_access_stack->deferred_access_checks;
  }
  
  /* Take current deferred checks and combine with the
--- 204,214 ----
  tree
  get_deferred_access_checks (void)
  {
!   if (deferred_access_no_check)
!     return NULL;
!   else
!     return (VEC_last (deferred_access, deferred_access_stack)
! 	    ->deferred_access_checks);
  }
  
  /* Take current deferred checks and combine with the
*************** get_deferred_access_checks (void)
*** 198,224 ****
  void
  pop_to_parent_deferring_access_checks (void)
  {
!   tree deferred_check = get_deferred_access_checks ();
!   deferred_access *d1 = deferred_access_stack;
!   deferred_access *d2 = deferred_access_stack->next;
!   deferred_access *d3 = deferred_access_stack->next->next;
! 
!   /* Temporary swap the order of the top two states, just to make
!      sure the garbage collector will not reclaim the memory during 
!      processing below.  */
!   deferred_access_stack = d2;
!   d2->next = d1;
!   d1->next = d3;
! 
!   for ( ; deferred_check; deferred_check = TREE_CHAIN (deferred_check))
!     /* Perform deferred check if required.  */
!     perform_or_defer_access_check (TREE_PURPOSE (deferred_check), 
! 				   TREE_VALUE (deferred_check));
! 
!   deferred_access_stack = d1;
!   d1->next = d2;
!   d2->next = d3;
!   pop_deferring_access_checks ();
  }
  
  /* Perform the deferred access checks.
--- 218,265 ----
  void
  pop_to_parent_deferring_access_checks (void)
  {
!   if (deferred_access_no_check)
!     deferred_access_no_check--;
!   else
!     {
!       tree checks;
!       deferred_access *ptr;
! 
!       checks = (VEC_last (deferred_access, deferred_access_stack)
! 		->deferred_access_checks);
! 
!       VEC_pop (deferred_access, deferred_access_stack);
!       ptr = VEC_last (deferred_access, deferred_access_stack);
!       if (ptr->deferring_access_checks_kind == dk_no_deferred)
! 	{
! 	  /* Check access.  */
! 	  for (; checks; checks = TREE_CHAIN (checks)) 
! 	    enforce_access (TREE_PURPOSE (checks), 
! 			    TREE_VALUE (checks));
! 	}
!       else
! 	{
! 	  /* Merge with parent.  */
! 	  tree next;
! 	  tree original = ptr->deferred_access_checks;
! 	  
! 	  for (; checks; checks = next)
! 	    {
! 	      tree probe;
! 	      
! 	      next = TREE_CHAIN (checks);
! 
! 	      for (probe = original; probe; probe = TREE_CHAIN (probe))
! 		if (TREE_VALUE (probe) == TREE_VALUE (checks)
! 		    && TREE_PURPOSE (probe) == TREE_PURPOSE (checks))
! 		  goto found;
! 	      /* Insert into parent's checks.  */
! 	      TREE_CHAIN (checks) = ptr->deferred_access_checks;
! 	      ptr->deferred_access_checks = checks;
! 	    found:;
! 	    }
! 	}
!     }
  }
  
  /* Perform the deferred access checks.
*************** void
*** 241,247 ****
  perform_deferred_access_checks (void)
  {
    tree deferred_check;
!   for (deferred_check = deferred_access_stack->deferred_access_checks;
         deferred_check;
         deferred_check = TREE_CHAIN (deferred_check))
      /* Check access.  */
--- 282,290 ----
  perform_deferred_access_checks (void)
  {
    tree deferred_check;
! 
!   for (deferred_check = (VEC_last (deferred_access, deferred_access_stack)
! 			 ->deferred_access_checks);
         deferred_check;
         deferred_check = TREE_CHAIN (deferred_check))
      /* Check access.  */
*************** void
*** 256,285 ****
  perform_or_defer_access_check (tree binfo, tree decl)
  {
    tree check;
  
!   /* Exit if we are in a context that no access checking is performed.  */
!   if (deferred_access_stack->deferring_access_checks_kind == dk_no_check)
      return;
    
    my_friendly_assert (TREE_CODE (binfo) == TREE_VEC, 20030623);
  
    /* If we are not supposed to defer access checks, just check now.  */
!   if (deferred_access_stack->deferring_access_checks_kind == dk_no_deferred)
      {
        enforce_access (binfo, decl);
        return;
      }
    
    /* See if we are already going to perform this check.  */
!   for (check = deferred_access_stack->deferred_access_checks;
         check;
         check = TREE_CHAIN (check))
      if (TREE_VALUE (check) == decl && TREE_PURPOSE (check) == binfo)
        return;
    /* If not, record the check.  */
!   deferred_access_stack->deferred_access_checks
!     = tree_cons (binfo, decl,
! 		 deferred_access_stack->deferred_access_checks);
  }
  
  /* Returns nonzero if the current statement is a full expression,
--- 299,331 ----
  perform_or_defer_access_check (tree binfo, tree decl)
  {
    tree check;
+   deferred_access *ptr;
  
!   /* Exit if we are in a context that no access checking is performed.
!      */
!   if (deferred_access_no_check)
      return;
    
    my_friendly_assert (TREE_CODE (binfo) == TREE_VEC, 20030623);
  
+   ptr = VEC_last (deferred_access, deferred_access_stack);
+   
    /* If we are not supposed to defer access checks, just check now.  */
!   if (ptr->deferring_access_checks_kind == dk_no_deferred)
      {
        enforce_access (binfo, decl);
        return;
      }
    
    /* See if we are already going to perform this check.  */
!   for (check = ptr->deferred_access_checks;
         check;
         check = TREE_CHAIN (check))
      if (TREE_VALUE (check) == decl && TREE_PURPOSE (check) == binfo)
        return;
    /* If not, record the check.  */
!   ptr->deferred_access_checks
!     = tree_cons (binfo, decl, ptr->deferred_access_checks);
  }
  
  /* Returns nonzero if the current statement is a full expression,

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]