This is the mail archive of the java@gcc.gnu.org mailing list for the Java 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]

patch to bring java vtables closer to g++ abi conformance


The g++ v3 abi (http://www.codesourcery.com/cxx-abi/abi.html) specifies
that each vtable contains an offset-to-top and a type_info pointer.
These words are *before* the word pointed to by each object's vtable
pointer.  Thus if we add the extra header words it does not actually
break binary compatibility, unless you look at these new fields - or the
object's file symbols.   I.e the vtable pointer to class foo is now
_ZTVN3fooE+8 (assuming a 32-bit target) instead of ZTVN3fooE.

This patch does not actually implement the type_info pointer, but leaves
a slot for a pointer which we can fill in later.  If we do that then
C++ code that uses rtti might actually work instead of crashing.  If we
do this, perhaps we can embed the type_info object *inside* a Class
object, as if Class inherits from *both* Object and type_info.  But
I left this for another day.

So this change doesn't at this point have much effect, except adding two
words for each Java class.  However, it brings us closer to abi
compliance, making it less likely to confuse various tools such as
debuggers.  I looked at this issue in the context of gdb crashing.  Now
I'm not totally sure this patch is needed for gdb, since I also fixed
some things in gdb itself.  In any case it seems like a good idea.

Comments?  Anyone think I shouldn't check it in?
-- 
	--Per Bothner
per@bothner.com   http://www.bothner.com/per/
2002-01-23  Per Bothner  <per@bothner.com>

	*  class.c:  Change vtable to more compatible with g++ v3 abi.
	(get_dispatch_table):  Prepend offset-to-top (laways 0) and
	type_info pointer (currently unimplemented hence NULL) to vtable.
	Specifically, prepend offset-to-top and typeinfo ptr (currently null).
	(make_class_data):  Variable dtable_start_offset is sizeof 2 pointers.
	Adjust vtable pointers by dtable_start_offse - i.e. skip new words.
	(build_dtable_decl):  Add declarations for new fields.

Index: class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.124
diff -u -p -r1.124 class.c
--- class.c	2002/01/03 07:50:49	1.124
+++ class.c	2002/01/23 17:25:02
@@ -1445,11 +1445,17 @@ get_dispatch_table (type, this_class_add
   list = tree_cons (NULL_TREE, gc_descr, list);
   for (j = 1; j < TARGET_VTABLE_USES_DESCRIPTORS-1; ++j)
     list = tree_cons (NULL_TREE, gc_descr, list);
-  list = tree_cons (integer_zero_node, this_class_addr, list);
+  list = tree_cons (NULL_TREE, this_class_addr, list);
 
+  /** Pointer to type_info object (to be implemented), according to g++ ABI. */
+  list = tree_cons (NULL_TREE, integer_zero_node, list);
+  /** Ofset to start of whole object.  Always 0 for Java. */
+  list = tree_cons (integer_zero_node, integer_zero_node, list);
+
   arraysize = (TARGET_VTABLE_USES_DESCRIPTORS? nvirtuals + 1 : nvirtuals + 2);
   if (TARGET_VTABLE_USES_DESCRIPTORS)
     arraysize *= TARGET_VTABLE_USES_DESCRIPTORS;
+  arraysize += 2;
   return build (CONSTRUCTOR,
 		build_prim_array_type (nativecode_ptr_type_node, arraysize),
 		NULL_TREE, list);
@@ -1479,6 +1485,9 @@ make_class_data (type)
   tree interfaces = null_pointer_node;
   int interface_len = 0;
   tree type_decl = TYPE_NAME (type);
+  /** Offset from start of virtual function table declaration
+      to where objects actually point at, following new g++ ABI. */
+  tree dtable_start_offset = build_int_2 (2 * POINTER_SIZE / BITS_PER_UNIT, 0);
 
   this_class_addr = build_class_ref (type);
   decl = TREE_OPERAND (this_class_addr, 0);
@@ -1632,7 +1641,9 @@ make_class_data (type)
 
   START_RECORD_CONSTRUCTOR (temp, object_type_node);
   PUSH_FIELD_VALUE (temp, "vtable",
-		    build1 (ADDR_EXPR, dtable_ptr_type, class_dtable_decl));
+		    build (PLUS_EXPR, dtable_ptr_type,
+			   build1 (ADDR_EXPR, dtable_ptr_type, class_dtable_decl),
+			   dtable_start_offset));
   if (! flag_hash_synchronization)
     PUSH_FIELD_VALUE (temp, "sync_info", null_pointer_node);
   FINISH_RECORD_CONSTRUCTOR (temp);
@@ -1668,7 +1679,9 @@ make_class_data (type)
   else
     PUSH_FIELD_VALUE (cons, "vtable",
 		      dtable_decl == NULL_TREE ? null_pointer_node
-		      : build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl));
+		      : build (PLUS_EXPR, dtable_ptr_type,
+			       build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl),
+			       dtable_start_offset));
   
   if (otable_methods == NULL_TREE)
     {
@@ -1801,7 +1814,7 @@ build_dtable_decl (type)
   /* We need to build a new dtable type so that its size is uniquely
      computed when we're dealing with the class for real and not just
      faking it (like java.lang.Class during the initialization of the
-     compiler.) We now we're not faking a class when CURRENT_CLASS is
+     compiler.) We know we're not faking a class when CURRENT_CLASS is
      TYPE. */
   if (current_class == type)
     {
@@ -1809,6 +1822,9 @@ build_dtable_decl (type)
       int n;
 
       dtype = make_node (RECORD_TYPE);
+
+      PUSH_FIELD (dtype, dummy, "top_offset", ptr_type_node);
+      PUSH_FIELD (dtype, dummy, "type_info", ptr_type_node);
 
       PUSH_FIELD (dtype, dummy, "class", class_ptr_type);
       for (n = 1; n < TARGET_VTABLE_USES_DESCRIPTORS; ++n)

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