[gcjx] Patch: FYI: fix attribute lengths

Tom Tromey tromey@redhat.com
Sun Jan 16 04:36:00 GMT 2005


I'm checking this in on the gcjx branch.

We were incorrectly computing the size of the Code attribute in some
cases.  To make this simpler in the future, I changed all attributes
to compute their own sizes; this means if we need to add attributes to
the Code attribute in the future, no further changes will need to be
made.

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>
	* bytecode/locals.cc (emit): Updated.
	(update): Update 'valid'.
	* bytecode/locals.hh (locals::valid): New field.
	(locals): Updated.
	(locals::size): New method.
	* bytecode/generate.cc (write): Don't emit the size.
	(write_line_table): Likewise.
	(count_exception_handlers): New method.
	* bytecode/outpool.hh (output_constant_pool::size): Declare.
	* bytecode/outpool.cc (size): New method.
	(write_inner_classes): Don't emit the size.
	* bytecode/attribute.cc (size): New methods.
	(emit): Write the size.  Update all other emit methods.
	* bytecode/generate.hh (line_table_attribute::size): New method.
	(local_variable_table_attribute::size): Likewise.
	(bytecode_generator::count_exception_handlers): Declare.
	(bytecode_generator::bytecode_size): New method.
	* bytecode/attribute.hh (bytecode_attribute_list::size): Declare.
	(bytecode_attribute::size): Likewise.
	(simple_name_attribute::size): New method.
	(utf8_attribute::size): New method.
	(inner_classes_attribute::size): Declare.
	(exceptions_attribute::size): New method.
	(code_attribute::size): Declare.
	(field_value_attribute::size): New method.
	(annotation_attribute::size): Likewise.
	(parameter_attribute::size): Likewise.
	(annotation_default_attribute::size): Likewise.

2005-01-15  Tom Tromey  <tromey@redhat.com>

Index: bytecode/attribute.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/bytecode/Attic/attribute.cc,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 attribute.cc
--- bytecode/attribute.cc 13 Jan 2005 03:18:34 -0000 1.1.2.1
+++ bytecode/attribute.cc 16 Jan 2005 04:34:23 -0000
@@ -1,6 +1,6 @@
 // Attribute for bytecode output.
 
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -43,6 +43,7 @@
 bytecode_attribute::emit (bytecode_stream &writer)
 {
   writer.put2 (pool->add_utf (name));
+  writer.put4 (size ());
 }
 
 
@@ -51,7 +52,6 @@
 simple_name_attribute::emit (bytecode_stream &writer)
 {
   bytecode_attribute::emit (writer);
-  writer.put4 (0);
 }
 
 
@@ -70,7 +70,6 @@
 utf8_attribute::emit (bytecode_stream &writer)
 {
   bytecode_attribute::emit (writer);
-  writer.put4 (2);
   writer.put2 (pool->add_utf (value));
 }
 
@@ -89,6 +88,12 @@
   pool->write_inner_classes ();
 }
 
+int
+inner_classes_attribute::size ()
+{
+  return pool->size ();
+}
+
 
 
 exceptions_attribute::exceptions_attribute (output_constant_pool *p,
@@ -107,7 +112,6 @@
 exceptions_attribute::emit (bytecode_stream &writer)
 {
   bytecode_attribute::emit (writer);
-  writer.put4 (2 + 2 * excs.size ());
   writer.put2 (excs.size ());
   for (std::set<model_type *>::const_iterator i = excs.begin ();
        i != excs.end ();
@@ -130,6 +134,12 @@
   gen->write (&writer);
 }
 
+int
+code_attribute::size ()
+{
+  return gen->bytecode_size ();
+}
+
 
 
 field_value_attribute::field_value_attribute (output_constant_pool *p,
@@ -165,7 +175,6 @@
 field_value_attribute::emit (bytecode_stream &writer)
 {
   bytecode_attribute::emit (writer);
-  writer.put4 (2);
   writer.put2 (index);
 }
 
@@ -322,7 +331,6 @@
 annotation_attribute::emit (bytecode_stream &writer)
 {
   bytecode_attribute::emit (writer);
-  writer.put4 (len);
   writer.put2 (annos.size ());
   for (std::list<model_annotation *>::const_iterator i = annos.begin ();
        i != annos.end ();
@@ -356,7 +364,6 @@
 parameter_attribute::emit (bytecode_stream &writer)
 {
   bytecode_attribute::emit (writer);
-  writer.put4 (len);
   writer.put2 (annos.size ());
   for (std::list< std::list<model_annotation *> >::const_iterator j
 	 = annos.begin ();
@@ -385,7 +392,6 @@
 annotation_default_attribute::emit (bytecode_stream &writer)
 {
   bytecode_attribute::emit (writer);
-  writer.put4 (len);
   emit_annotation_value (&writer, pool, expr);
 }
 
@@ -412,3 +418,17 @@
        ++i)
     (*i)->emit (writer);
 }
+
+int
+bytecode_attribute_list::size ()
+{
+  int result = 2;
+  for (std::list<bytecode_attribute *>::const_iterator i = attrs.begin ();
+       i != attrs.end ();
+       ++i)
+    {
+      // '6' is 2 byte for the name and 4 for the length.
+      result += 6 + (*i)->size ();
+    }
+  return result;
+}
Index: bytecode/attribute.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/bytecode/Attic/attribute.hh,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 attribute.hh
--- bytecode/attribute.hh 13 Jan 2005 03:18:34 -0000 1.1.2.1
+++ bytecode/attribute.hh 16 Jan 2005 04:34:23 -0000
@@ -1,6 +1,6 @@
 // Attribute for bytecode output.
 
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -47,6 +47,9 @@
   /// attribute; subclasses must emit the size of the attribute and
   /// its contents.
   virtual void emit (bytecode_stream &);
+
+  /// Compute the size of this attribute.
+  virtual int size () = 0;
 };
 
 /// An attribute which is just a tag.
@@ -60,6 +63,11 @@
   }
 
   void emit (bytecode_stream &);
+
+  int size ()
+  {
+    return 0;
+  }
 };
 
 /// An attribute that consists of a name and a utf8 value.
@@ -74,6 +82,11 @@
 		  const std::string &);
 
   void emit (bytecode_stream &);
+
+  int size ()
+  {
+    return 2;
+  }
 };
 
 /// An attribute that handles InnerClasses for the constant pool.  It
@@ -85,6 +98,8 @@
   inner_classes_attribute (output_constant_pool *);
 
   void emit (bytecode_stream &);
+
+  int size ();
 };
 
 /// An attribute that handles exceptions for a method.
@@ -99,6 +114,11 @@
 			const std::set<model_type *> &);
 
   void emit (bytecode_stream &);
+
+  int size ()
+  {
+    return 2 + 2 * excs.size ();
+  }
 };
 
 /// An attribute that handles the code for a method.
@@ -112,6 +132,8 @@
   code_attribute (output_constant_pool *, bytecode_generator *);
 
   void emit (bytecode_stream &);
+
+  int size ();
 };
 
 /// An attribute that handles the constant value of a field.
@@ -125,6 +147,11 @@
   field_value_attribute (output_constant_pool *, model_field *);
 
   void emit (bytecode_stream &);
+
+  int size ()
+  {
+    return 2;
+  }
 };
 
 /// This represents annotations that are attached to a class, field,
@@ -144,6 +171,11 @@
 			const std::list<model_annotation *> &);
 
   void emit (bytecode_stream &);
+
+  int size ()
+  {
+    return len;
+  }
 };
 
 /// This represents annotations attached to method parameters.
@@ -162,6 +194,11 @@
 		       const std::list< std::list<model_annotation *> > &);
 
   void emit (bytecode_stream &);
+
+  int size ()
+  {
+    return len;
+  }
 };
 
 /// This represents an annotation default value.
@@ -178,6 +215,11 @@
   annotation_default_attribute (output_constant_pool *, model_expression *);
 
   void emit (bytecode_stream &);
+
+  int size ()
+  {
+    return len;
+  }
 };
 
 /// This holds a list of attributes.  It owns each attribute object
@@ -199,6 +241,9 @@
   }
 
   void emit (bytecode_stream &);
+
+  // Compute the size needed by all attributes.
+  int size ();
 };
 
 #endif // GCJX_BYTECODE_ATTRIBUTE_HH
Index: bytecode/generate.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/bytecode/Attic/generate.cc,v
retrieving revision 1.1.2.4
diff -u -r1.1.2.4 generate.cc
--- bytecode/generate.cc 15 Jan 2005 21:27:50 -0000 1.1.2.4
+++ bytecode/generate.cc 16 Jan 2005 04:34:24 -0000
@@ -183,8 +183,8 @@
     }
 }
 
-void
-bytecode_generator::write (bytecode_stream *out)
+int
+bytecode_generator::count_exception_handlers ()
 {
   // Count the number of exception handlers we have.
   int count = 0;
@@ -204,6 +204,13 @@
 				 "past 65535 bytes");
 	}
     }
+  return count;
+}
+
+void
+bytecode_generator::write (bytecode_stream *out)
+{
+  int count = count_exception_handlers ();
 
   if (count > 65535)
     throw method->error ("method requires more than 65535 exception regions");
@@ -214,12 +221,6 @@
   if (vars.get_max () > 65535)
     throw method->error ("bytecode uses more than 65535 local variable slots");
 
-  // Compute the total length of the Code section.
-  int length = 8 + bytecode_length + 2 + 8 * count + 2;
-  if (global->get_compiler ()->target_debug () && line_count > 0)
-    length += 6 + 2 + 4 * line_count;
-
-  out->put4 (length);
   out->put2 (max_stack);
   out->put2 (vars.get_max ());
   out->put4 (bytecode_length);
@@ -295,7 +296,6 @@
 void
 bytecode_generator::write_line_table (bytecode_stream *out)
 {
-  out->put4 (2 + 4 * line_count);
   out->put2 (line_count);
   int last_line = -1;
   for (bytecode_block *work = first_block; work; work = work->next ())
Index: bytecode/generate.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/bytecode/Attic/generate.hh,v
retrieving revision 1.1.2.3
diff -u -r1.1.2.3 generate.hh
--- bytecode/generate.hh 15 Jan 2005 21:27:51 -0000 1.1.2.3
+++ bytecode/generate.hh 16 Jan 2005 04:34:24 -0000
@@ -179,6 +179,11 @@
       bytecode_attribute::emit (writer);
       gen->write_line_table (&writer);
     }
+
+    int size ()
+    {
+      return 2 + 4 * gen->line_count;
+    }
   };
 
   /// This class is used to handle the LocalVariableTable attribute.
@@ -201,6 +206,11 @@
       bytecode_attribute::emit (writer);
       vars->emit (pool, &writer);
     }
+
+    int size ()
+    {
+      return vars->size ();
+    }
   };
 
   void write_line_table (bytecode_stream *);
@@ -283,6 +293,8 @@
   bytecode_block *new_bytecode_block ();
   void note_line (model_element *);
 
+  int count_exception_handlers ();
+
   // Used to push a new expression target.
   class push_expr_target
   {
@@ -351,6 +363,13 @@
   /// Write the bytecode for this method.
   void write (bytecode_stream *);
 
+  /// Compute the overall length used by the Code attribute.
+  int bytecode_size ()
+  {
+    int count = count_exception_handlers ();
+    return 8 + bytecode_length + 2 + 8 * count + attributes.size ();
+  }
+
   /// Used to keep track of lifetimes of local variables.
   bytecode_block *get_current () const
   {
Index: bytecode/locals.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/bytecode/Attic/locals.cc,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 locals.cc
--- bytecode/locals.cc 15 Jan 2005 21:27:51 -0000 1.1.2.2
+++ bytecode/locals.cc 16 Jan 2005 04:34:24 -0000
@@ -139,7 +139,7 @@
 bool
 locals::update ()
 {
-  bool any = false;
+  valid = 0;
   for (std::list<debug_info>::iterator i = var_descriptions.begin ();
        i != var_descriptions.end ();
        ++i)
@@ -153,10 +153,10 @@
 	  assert (info.end->live_p ());
 	  // Don't emit debug info for a zero-length range.
 	  if (info.start != info.end)
-	    any = true;
+	    ++valid;
 	}
     }
-  return any;
+  return valid > 0;
 }
 
 void
@@ -180,10 +180,12 @@
 	}
     }
 
+  assert (count == valid);
+  assert (count > 0);
+
   if (! out)
     return;
 
-  out->put4 (2 + 10 * count);
   out->put2 (count);
   for (std::list<debug_info>::const_iterator i = var_descriptions.begin ();
        i != var_descriptions.end ();
Index: bytecode/locals.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/bytecode/Attic/locals.hh,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 locals.hh
--- bytecode/locals.hh 15 Jan 2005 21:27:51 -0000 1.1.2.2
+++ bytecode/locals.hh 16 Jan 2005 04:34:24 -0000
@@ -66,11 +66,15 @@
   // appear several times here, due to how we emit 'finally' clauses.
   std::list<debug_info> var_descriptions;
 
+  // Number of variables that survived updating.
+  int valid;
+
 public:
 
   locals (bytecode_generator *g)
     : gen (g),
-      max (0)
+      max (0),
+      valid (-1)
   {
     scope.push_back (NULL);
   }
@@ -115,6 +119,12 @@
   /// information.  If the writer is NULL, just enter information into
   /// the constant pool.
   void emit (output_constant_pool *, bytecode_stream *);
+
+  /// Return the size of the local variable table attribute.
+  int size ()
+  {
+    return 2 + 10 * valid;
+  }
 };
 
 /// This is an class for allocating a temporary local variable.  Usage
Index: bytecode/outpool.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/bytecode/Attic/outpool.cc,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 outpool.cc
--- bytecode/outpool.cc 13 Jan 2005 03:18:34 -0000 1.1.2.1
+++ bytecode/outpool.cc 16 Jan 2005 04:34:24 -0000
@@ -1,6 +1,6 @@
 // A constant pool being generated.
 
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -333,7 +333,6 @@
 {
   // Here we freely use 'add', assuming that the entries have all been
   // added already.
-  bytes.put4 (2 + 8 * nested_classes.size ());
   bytes.put2 (nested_classes.size ());
 
   for (std::set<model_class *>::const_iterator i = nested_classes.begin ();
@@ -356,6 +355,12 @@
     }
 }
 
+int
+output_constant_pool::size ()
+{
+  return 2 + 8 * nested_classes.size ();
+}
+
 void
 output_constant_pool::update_descriptor (std::map<std::string, model_class *> &desc_map,
 					 model_type *t)
Index: bytecode/outpool.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/bytecode/Attic/outpool.hh,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 outpool.hh
--- bytecode/outpool.hh 13 Jan 2005 03:18:34 -0000 1.1.2.1
+++ bytecode/outpool.hh 16 Jan 2005 04:34:24 -0000
@@ -1,6 +1,6 @@
 // A constant pool being generated.
 
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -109,6 +109,9 @@
   /// Write the inner classes attribute.
   void write_inner_classes ();
 
+  /// Return the number of bytes used by this attribute.
+  int size ();
+
   /// Create a fake compilation unit object from this outgoing
   /// constant pool.  This can only be called after finish().  This is
   /// used when verifying bytecode after creating it.



More information about the Java-patches mailing list