This is the mail archive of the gcc@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]

Re: High memory consumption compiling syntax.c


> Date: Mon, 1 Oct 2001 09:00:51 -0700
> From: Zack Weinberg <zack@codesourcery.com>
> 
> You can try -fmem-report (in 3.x).  This will dump statistics on the
> data remaining allocated in the garbage collection arena at the end of
> compilation.  However, from what you report below, it rather sounds
> like the runaway memory allocation is not through the garbage
> collector, so this may not help.

I'm attaching the output of -fmem-report below anyway, in the hope
that it will give some clue.

> Based on previous similar reports, I'm inclined to suspect the basic
> block tree.  Is the control flow in scan_sexps_forward unusually
> complex?  Does it make use of computed GOTO?

I attach the entire function scan_sexps_forward below.  As far as I
could see, it's a large case inside a loop.  (If it helps, I can post
the preprocessed source of that function.)

Thanks for your help.


gcc -c  -Demacs -DHAVE_CONFIG_H   -I. -I.       -O2 -gcoff -fmem-report syntax.c

Tree                 Number            Bytes    % Total
error_mark                1              16       0.003
identifier_node        2914             182k     29.629
tree_list              1706              33k      5.421
block                     8             256       0.041
void_type                 3             312       0.050
integer_type             85            8840       1.404
real_type                 3             312       0.050
complex_type              4             416       0.066
vector_type               5             520       0.083
enumeral_type            15            1560       0.248
boolean_type              1             104       0.017
pointer_type            173              17k      2.858
reference_type            1             104       0.017
array_type               84            8736       1.388
record_type              87            9048       1.437
union_type                5             520       0.083
function_type           349              35k      5.766
integer_cst             927              28k      4.713
string_cst               25             800       0.127
function_decl          1462             148k     24.156
const_decl              126              12k      2.082
type_decl               149              15k      2.462
var_decl                359              36k      5.932
parm_decl                 3             312       0.050
result_decl              38            3952       0.628
field_decl              656              66k     10.839
component_ref             6             192       0.031
indirect_ref              6             120       0.019
constructor              22             704       0.112
compound_expr             1              32       0.005
cond_expr                 1              32       0.005
plus_expr                 4             128       0.020
minus_expr                2              64       0.010
ge_expr                   1              32       0.005
eq_expr                   1              32       0.005
convert_expr              1              20       0.003
nop_expr                 25             500       0.079
non_lvalue_expr           2              40       0.006
save_expr                 1              32       0.005
addr_expr                45             900       0.143
postdecrement_expr         1              32       0.005
Total                  9308             614k

RTX                  Number            Bytes    % Total
const_int               363            2904      17.494
const_double             21             672       4.048
pc                        1               4       0.024
reg                      58             928       5.590
mem                     438            7008      42.217
symbol_ref              605            4840      29.157
cc0                       1               4       0.024
plus                     14             224       1.349
eq                        1              16       0.096
Total                  1502              16k

Log    Allocated        Used    Overhead
2           4096           8         160 
3            180k       8048        4320 
4            312k       8192        4992 
5            212k         31k       2544 
6            252k        182k       2520 
32           832k        366k       7488 
33           552k         34k       7728 
Total       5376k        631k         29k

String pool
entries		3328
identifiers	2914 (87.56%)
slots		16384
bytes		43k (4367  overhead)
table size	192k
coll/search	0.1183
ins/search	0.0827
avg. entry	13.37 bytes (+/- 7.98)
longest entry	57



static void
scan_sexps_forward (stateptr, from, from_byte, end, targetdepth,
		    stopbefore, oldstate, commentstop)
     struct lisp_parse_state *stateptr;
     register int from;
     int end, targetdepth, stopbefore;
     Lisp_Object oldstate;
     int commentstop;
{
  struct lisp_parse_state state;

  register enum syntaxcode code;
  int c1;
  int comnested;
  struct level { int last, prev; };
  struct level levelstart[100];
  register struct level *curlevel = levelstart;
  struct level *endlevel = levelstart + 100;
  register int depth;	/* Paren depth of current scanning location.
			   level - levelstart equals this except
			   when the depth becomes negative.  */
  int mindepth;		/* Lowest DEPTH value seen.  */
  int start_quoted = 0;		/* Nonzero means starting after a char quote */
  Lisp_Object tem;
  int prev_from;		/* Keep one character before FROM.  */
  int prev_from_byte;
  int prev_from_syntax;
  int boundary_stop = commentstop == -1;
  int nofence;
  int found;
  int out_bytepos, out_charpos;
  int temp;

  prev_from = from;
  prev_from_byte = from_byte;
  if (from != BEGV)
    DEC_BOTH (prev_from, prev_from_byte);

  /* Use this macro instead of `from++'.  */
#define INC_FROM				\
do { prev_from = from;				\
     prev_from_byte = from_byte; 		\
     prev_from_syntax				\
       = SYNTAX_WITH_FLAGS (FETCH_CHAR (prev_from_byte)); \
     INC_BOTH (from, from_byte);		\
     UPDATE_SYNTAX_TABLE_FORWARD (from);	\
  } while (0)

  immediate_quit = 1;
  QUIT;

  if (NILP (oldstate))
    {
      depth = 0;
      state.instring = -1;
      state.incomment = 0;
      state.comstyle = 0;	/* comment style a by default.  */
      state.comstr_start = -1;	/* no comment/string seen.  */
    }
  else
    {
      tem = Fcar (oldstate);
      if (!NILP (tem))
	depth = XINT (tem);
      else
	depth = 0;

      oldstate = Fcdr (oldstate);
      oldstate = Fcdr (oldstate);
      oldstate = Fcdr (oldstate);
      tem = Fcar (oldstate);
      /* Check whether we are inside string_fence-style string: */
      state.instring = (!NILP (tem) 
			? (INTEGERP (tem) ? XINT (tem) : ST_STRING_STYLE) 
			: -1);

      oldstate = Fcdr (oldstate);
      tem = Fcar (oldstate);
      state.incomment = (!NILP (tem)
			 ? (INTEGERP (tem) ? XINT (tem) : -1)
			 : 0);

      oldstate = Fcdr (oldstate);
      tem = Fcar (oldstate);
      start_quoted = !NILP (tem);

      /* if the eighth element of the list is nil, we are in comment
	 style a.  If it is non-nil, we are in comment style b */
      oldstate = Fcdr (oldstate);
      oldstate = Fcdr (oldstate);
      tem = Fcar (oldstate);
      state.comstyle = NILP (tem) ? 0 : (EQ (tem, Qsyntax_table) 
					 ? ST_COMMENT_STYLE : 1);

      oldstate = Fcdr (oldstate);
      tem = Fcar (oldstate);
      state.comstr_start = NILP (tem) ? -1 : XINT (tem) ;
      oldstate = Fcdr (oldstate);
      tem = Fcar (oldstate);
      while (!NILP (tem))		/* >= second enclosing sexps.  */
	{
	  /* curlevel++->last ran into compiler bug on Apollo */
	  curlevel->last = XINT (Fcar (tem));
	  if (++curlevel == endlevel)
	    curlevel--; /* error ("Nesting too deep for parser"); */
	  curlevel->prev = -1;
	  curlevel->last = -1;
	  tem = Fcdr (tem);
	}
    }
  state.quoted = 0;
  mindepth = depth;

  curlevel->prev = -1;
  curlevel->last = -1;

  SETUP_SYNTAX_TABLE (prev_from, 1);
  prev_from_syntax = SYNTAX_WITH_FLAGS (FETCH_CHAR (prev_from_byte));
  UPDATE_SYNTAX_TABLE_FORWARD (from);

  /* Enter the loop at a place appropriate for initial state.  */

  if (state.incomment)
    goto startincomment;
  if (state.instring >= 0)
    {
      nofence = state.instring != ST_STRING_STYLE;
      if (start_quoted)
	goto startquotedinstring;
      goto startinstring;
    }
  else if (start_quoted)
    goto startquoted;

#if 0 /* This seems to be redundant with the identical code above.  */
  SETUP_SYNTAX_TABLE (prev_from, 1);
  prev_from_syntax = SYNTAX_WITH_FLAGS (FETCH_CHAR (prev_from_byte));
  UPDATE_SYNTAX_TABLE_FORWARD (from);
#endif

  while (from < end)
    {
      INC_FROM;
      code = prev_from_syntax & 0xff;

      if (code == Scomment)
	{
	  state.comstyle = SYNTAX_FLAGS_COMMENT_STYLE (prev_from_syntax);
	  state.incomment = (SYNTAX_FLAGS_COMMENT_NESTED (prev_from_syntax) ?
			     1 : -1);
	  state.comstr_start = prev_from;
	}
      else if (code == Scomment_fence)
	{
	  /* Record the comment style we have entered so that only
	     the comment-end sequence of the same style actually
	     terminates the comment section.  */
	  state.comstyle = ST_COMMENT_STYLE;
	  state.incomment = -1;
	  state.comstr_start = prev_from;
	  code = Scomment;
	}
     else if (from < end)
	if (SYNTAX_FLAGS_COMSTART_FIRST (prev_from_syntax))
	  if (c1 = FETCH_CHAR (from_byte),
	      SYNTAX_COMSTART_SECOND (c1))
	    /* Duplicate code to avoid a complex if-expression
	       which causes trouble for the SGI compiler.  */
	    {
	      /* Record the comment style we have entered so that only
		 the comment-end sequence of the same style actually
		 terminates the comment section.  */
	      state.comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from_byte));
	      comnested = SYNTAX_FLAGS_COMMENT_NESTED (prev_from_syntax);
	      comnested = comnested || SYNTAX_COMMENT_NESTED (c1);
	      state.incomment = comnested ? 1 : -1;
	      state.comstr_start = prev_from;
	      INC_FROM;
	      code = Scomment;
	    }

      if (SYNTAX_FLAGS_PREFIX (prev_from_syntax))
	continue;
      switch (SWITCH_ENUM_CAST (code))
	{
	case Sescape:
	case Scharquote:
	  if (stopbefore) goto stop;  /* this arg means stop at sexp start */
	  curlevel->last = prev_from;
	startquoted:
	  if (from == end) goto endquoted;
	  INC_FROM;
	  goto symstarted;
	  /* treat following character as a word constituent */
	case Sword:
	case Ssymbol:
	  if (stopbefore) goto stop;  /* this arg means stop at sexp start */
	  curlevel->last = prev_from;
	symstarted:
	  while (from < end)
	    {
	      /* Some compilers can't handle this inside the switch.  */
	      temp = SYNTAX (FETCH_CHAR (from_byte));
	      switch (temp)
		{
		case Scharquote:
		case Sescape:
		  INC_FROM;
		  if (from == end) goto endquoted;
		  break;
		case Sword:
		case Ssymbol:
		case Squote:
		  break;
		default:
		  goto symdone;
		}
	      INC_FROM;
	    }
	symdone:
	  curlevel->prev = curlevel->last;
	  break;

	case Scomment:
	  if (commentstop || boundary_stop) goto done;
	startincomment:
	  /* The (from == BEGV) test was to enter the loop in the middle so
	     that we find a 2-char comment ender even if we start in the
	     middle of it.  We don't want to do that if we're just at the
	     beginning of the comment (think of (*) ... (*)).  */
	  found = forw_comment (from, from_byte, end,
				state.incomment, state.comstyle,
				(from == BEGV || from < state.comstr_start + 3)
				? 0 : prev_from_syntax,
				&out_charpos, &out_bytepos, &state.incomment);
	  from = out_charpos; from_byte = out_bytepos;
	  /* Beware!  prev_from and friends are invalid now.
	     Luckily, the `done' doesn't use them and the INC_FROM
	     sets them to a sane value without looking at them. */
	  if (!found) goto done;
	  INC_FROM;
	  state.incomment = 0;
	  state.comstyle = 0;	/* reset the comment style */
	  if (boundary_stop) goto done;
	  break;

	case Sopen:
	  if (stopbefore) goto stop;  /* this arg means stop at sexp start */
	  depth++;
	  /* curlevel++->last ran into compiler bug on Apollo */
	  curlevel->last = prev_from;
	  if (++curlevel == endlevel)
	    curlevel--; /* error ("Nesting too deep for parser"); */
	  curlevel->prev = -1;
	  curlevel->last = -1;
	  if (targetdepth == depth) goto done;
	  break;

	case Sclose:
	  depth--;
	  if (depth < mindepth)
	    mindepth = depth;
	  if (curlevel != levelstart)
	    curlevel--;
	  curlevel->prev = curlevel->last;
	  if (targetdepth == depth) goto done;
	  break;

	case Sstring:
	case Sstring_fence:
	  state.comstr_start = from - 1;
	  if (stopbefore) goto stop;  /* this arg means stop at sexp start */
	  curlevel->last = prev_from;
	  state.instring = (code == Sstring 
			    ? (FETCH_CHAR (prev_from_byte))
			    : ST_STRING_STYLE);
	  if (boundary_stop) goto done;
	startinstring:
	  {
	    nofence = state.instring != ST_STRING_STYLE;
	    
	    while (1)
	      {
		int c;

		if (from >= end) goto done;
		c = FETCH_CHAR (from_byte);
		/* Some compilers can't handle this inside the switch.  */
		temp = SYNTAX (c);

		/* Check TEMP here so that if the char has
		   a syntax-table property which says it is NOT
		   a string character, it does not end the string.  */
		if (nofence && c == state.instring && temp == Sstring)
		  break;

		switch (temp)
		  {
		  case Sstring_fence:
		    if (!nofence) goto string_end;
		    break;
		  case Scharquote:
		  case Sescape:
		    INC_FROM;
		  startquotedinstring:
		    if (from >= end) goto endquoted;
		  }
		INC_FROM;
	      }
	  }
	string_end:
	  state.instring = -1;
	  curlevel->prev = curlevel->last;
	  INC_FROM;
	  if (boundary_stop) goto done;
	  break;

	case Smath:
	  break;
	}
    }
  goto done;

 stop:   /* Here if stopping before start of sexp. */
  from = prev_from;    /* We have just fetched the char that starts it; */
  goto done; /* but return the position before it. */

 endquoted:
  state.quoted = 1;
 done:
  state.depth = depth;
  state.mindepth = mindepth;
  state.thislevelstart = curlevel->prev;
  state.prevlevelstart
    = (curlevel == levelstart) ? -1 : (curlevel - 1)->last;
  state.location = from;
  state.levelstarts = Qnil;
  while (--curlevel >= levelstart)
      state.levelstarts = Fcons (make_number (curlevel->last),
				 state.levelstarts);
  immediate_quit = 0;

  *stateptr = state;
}


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