This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils 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]

Fix hppa .block and memory hog


Hi,

during building cross hppa binutils I noticed that the machine was 
grinding to a halt and started to die a horrible swap death.  
During investigating I produced the below patch.  The memory hog is 
block2.s of the testsuite, which uses ".block -1", i.e. an invalid 
argument to block.  The test is supposed to fail with an error message.  
That doesn't work, and I really can't figure out why it ever would work, 
nobody is actually testing the bounds for this argument, and happily 
converting eventual signed numbers to unsigned types.  Anyway, that's why 
it was trying to create a 8GB frag (see below, why not 4GB), and 
zero-initialize it.

So, after a bit of googling I found 
  http://docs.hp.com/en/92432-90012/ch04s04.html
which mentions that the actually correct bounds are 0 and 0x3fffffff.  I 
implemented this test, and also changed block1.s accordingly, as it was 
testing for 07fffffff.

And the last part is the above mentioned difference for allocating a 8GB
frag if it wants to have room for 4GB.  It's simply the too greedy
allocation strategy which happily doubles the amount of requested storage
as safety measure against future storage needs for that frag.  Obviously
this should be limited a bit to not waste too much memory.  I arbitrarily
chose a cutoff point of 1<<16 bytes, so larger needs just get an addend of
0x10000 and are not multiplied.  I don't think frags of even that size are
that common (even less of them will be resized multiple times), if I've
understood them correctly, so the performance impact should be minimal.

I tested this with the GAS testsuite on the above mentioned hppa cross 
assembler.


Ciao,
Michael.
-- 
	* frags.c (frag_grow): Don't be too greedy in allocating memory.
	* config/tc-hppa.c (pa_block): Check arguments to .block[z].

	* gas/hppa/parse/block1.s: Use official limit (0x3fffffff) for
	.block.

--- ./gas/config/tc-hppa.c.mm	2005-04-29 19:50:28.000000000 +0200
+++ ./gas/config/tc-hppa.c	2005-05-10 01:29:46.000000000 +0200
@@ -5951,6 +5951,12 @@ pa_block (z)
 
   temp_size = get_absolute_expression ();
 
+  if (temp_size > 0x3FFFFFFF)
+    {
+      as_bad (_("Argument to .BLOCK/.BLOCKZ must be between 0 and 0x3fffffff"));
+      temp_size = 0;
+    }
+
   /* Always fill with zeros, that's what the HP assembler does.  */
   temp_fill = 0;
 
--- ./gas/testsuite/gas/hppa/parse/block1.s.mm	1999-08-31 19:12:29.000000000 +0200
+++ ./gas/testsuite/gas/hppa/parse/block1.s	2005-05-10 01:34:18.000000000 +0200
@@ -4,7 +4,7 @@
 foo:
 	.block
 bar:
-	.block 0x7fffffff
+	.block 0x3fffffff
 com:
 
 
--- ./gas/frags.c.mm	2005-04-09 21:03:04.000000000 +0200
+++ ./gas/frags.c	2005-05-10 01:56:04.000000000 +0200
@@ -91,7 +91,14 @@ frag_grow (unsigned int nchars)
       frag_wane (frag_now);
       frag_new (0);
       oldc = frchain_now->frch_obstack.chunk_size;
-      frchain_now->frch_obstack.chunk_size = 2 * nchars + SIZEOF_STRUCT_FRAG;
+      /* Try to allocate a bit more than needed right now.  But don't do
+         this if we would waste too much memory.  Especially necessary
+	 for extremely big (like 2GB initialized) frags.  */
+      if (nchars < 0x10000)
+	frchain_now->frch_obstack.chunk_size = 2 * nchars;
+      else
+        frchain_now->frch_obstack.chunk_size = nchars + 0x10000;
+      frchain_now->frch_obstack.chunk_size += SIZEOF_STRUCT_FRAG;
       if (frchain_now->frch_obstack.chunk_size > 0)
 	while ((n = obstack_room (&frchain_now->frch_obstack)) < nchars
 	       && (unsigned long) frchain_now->frch_obstack.chunk_size > nchars)


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