From 9dfc2ec225a5a8f0a5d2a9b5853d0a19d728e129 Mon Sep 17 00:00:00 2001
From: Andrew Haley <aph@redhat.com>
Date: Wed, 1 Oct 2003 16:22:13 +0000
Subject: jcf-parse.c (java_parse_file): Write otable and atable.

2003-10-01  Andrew Haley  <aph@redhat.com>

        * jcf-parse.c (java_parse_file): Write otable and atable.
        * java-tree.h (atable_methods): New.
        (atable_decl): New.
        (atable_syms_decl): New.
        (enum java_tree_index): Add JTI_ATABLE_METHODS, JTI_ATABLE_DECL,
        JTI_ATABLE_SYMS_DECL.  Rename JTI_METHOD_SYMBOL* to JTI_SYMBOL*.
        (symbol_*type): Rename method_symbol* to symbol*type.
        (emit_offset_symbol_table): Delete.
        (emit_symbol_table): New.
        (get_symbol_table_index): New.
        (atable_type): New.
        * expr.c (build_field_ref): Handle flag_indirect_dispatch.
        (build_known_method_ref): Likewise.
        (get_symbol_table_index): Rename from get_offset_table_index.
        Parameterize to allow re-use by differing types of symbol table.
        (build_invokevirtual): Pass table to get_offset_table_index.
        * decl.c (java_init_decl_processing): Push types and decls for
        atable and atable_syyms.
        * class.c (build_static_field_ref): Handle flag_indirect_dispatch.
        (make_class_data): Add new fields atable and atable_syms.
        (emit_symbol_table): Rename from emit_offset_symbol_table.
        Parameterize to allow re-use by different types of symbol table.
        (build_symbol_entry): Renamed from build_method_symbols_entry.

2003-10-01  Andrew Haley  <aph@redhat.com>

        * java/lang/natClass.cc (initializeClass): Check for otable and
        atable.
        (_Jv_LinkOffsetTable): Check for existence of atable.  Rewrite
        loops using for().  Search superinterfaces.  Check for fields as
        well as methods.  Initialize atable as well as otable: check for
        static methods as well as virtual methods.
        * java/lang/Class.h (struct _Jv_AddressTable): New.
        (atable): New.
        (atable_syms): New.
        * include/jvm.h (_Jv_equalUtf8Consts): constify.
        * prims.cc (_Jv_equalUtf8Consts): constify.

From-SVN: r71979
---
 libjava/ChangeLog                 |  14 ++
 libjava/include/jvm.h             |   2 +-
 libjava/java/lang/Class.h         |  10 +-
 libjava/java/lang/natClass.cc     | 260 +++++++++++++++++++++++++++++++-------
 libjava/java/util/LinkedList.java |   2 +-
 libjava/prims.cc                  |   8 +-
 6 files changed, 241 insertions(+), 55 deletions(-)

(limited to 'libjava')

diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index d12987a..a86041a 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,17 @@
+2003-10-01  Andrew Haley  <aph@redhat.com>
+
+	* java/lang/natClass.cc (initializeClass): Check for otable and
+	atable.
+	(_Jv_LinkOffsetTable): Check for existence of atable.  Rewrite
+	loops using for().  Search superinterfaces.  Check for fields as
+	well as methods.  Initialize atable as well as otable: check for
+	static methods as well as virtual methods.
+	* java/lang/Class.h (struct _Jv_AddressTable): New.
+	(atable): New.
+	(atable_syms): New.
+	* include/jvm.h (_Jv_equalUtf8Consts): constify.
+	* prims.cc (_Jv_equalUtf8Consts): constify.
+
 2003-09-29  Tom Tromey  <tromey@redhat.com>
 
 	PR libgcj/10596:
diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h
index ed6c61e..b28f61a 100644
--- a/libjava/include/jvm.h
+++ b/libjava/include/jvm.h
@@ -145,7 +145,7 @@ extern int _Jv_strLengthUtf8(char* str, int len);
 typedef struct _Jv_Utf8Const Utf8Const;
 _Jv_Utf8Const *_Jv_makeUtf8Const (char *s, int len);
 _Jv_Utf8Const *_Jv_makeUtf8Const (jstring string);
-extern jboolean _Jv_equalUtf8Consts (_Jv_Utf8Const *, _Jv_Utf8Const *);
+extern jboolean _Jv_equalUtf8Consts (const _Jv_Utf8Const *, const _Jv_Utf8Const *);
 extern jboolean _Jv_equal (_Jv_Utf8Const *, jstring, jint);
 extern jboolean _Jv_equaln (_Jv_Utf8Const *, jstring, jint);
 
diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h
index 7fe96d0..7572c6c 100644
--- a/libjava/java/lang/Class.h
+++ b/libjava/java/lang/Class.h
@@ -125,6 +125,12 @@ struct _Jv_OffsetTable
   jint offsets[];
 };
 
+struct _Jv_AddressTable
+{
+  jint state;
+  void *addresses[];
+};
+
 #define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1)
 
 #define JV_CLASS(Obj) ((jclass) (*(_Jv_VTable **) Obj)->clas)
@@ -324,7 +330,7 @@ private:
   friend jstring _Jv_GetMethodString(jclass, _Jv_Utf8Const *);
   friend jshort _Jv_AppendPartialITable (jclass, jclass, void **, jshort);
   friend jshort _Jv_FindIIndex (jclass *, jshort *, jshort);
-  friend void _Jv_LinkOffsetTable (jclass);
+  friend void _Jv_LinkSymbolTable (jclass);
   friend void _Jv_LayoutVTableMethods (jclass klass);
   friend void _Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *);
   friend void _Jv_MakeVTable (jclass);
@@ -404,6 +410,8 @@ private:
   _Jv_OffsetTable *otable;
   // Offset table symbols.
   _Jv_MethodSymbol *otable_syms;
+  _Jv_AddressTable *atable;
+  _Jv_MethodSymbol *atable_syms;
   // Interfaces implemented by this class.
   jclass *interfaces;
   // The class loader for this class.
diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc
index 551a531..aa5867f 100644
--- a/libjava/java/lang/natClass.cc
+++ b/libjava/java/lang/natClass.cc
@@ -36,6 +36,7 @@ details.  */
 #include <java/lang/IllegalAccessError.h>
 #include <java/lang/IllegalArgumentException.h>
 #include <java/lang/IncompatibleClassChangeError.h>
+#include <java/lang/NoSuchFieldError.h>
 #include <java/lang/ArrayIndexOutOfBoundsException.h>
 #include <java/lang/InstantiationException.h>
 #include <java/lang/NoClassDefFoundError.h>
@@ -790,7 +791,7 @@ java::lang::Class::initializeClass (void)
          so ensure internal tables are built.  */
       _Jv_PrepareConstantTimeTables (this);
       _Jv_MakeVTable(this);
-      _Jv_LinkOffsetTable(this);
+      _Jv_LinkSymbolTable(this);
 
       return;
     }
@@ -830,8 +831,8 @@ java::lang::Class::initializeClass (void)
   if (vtable == NULL)
     _Jv_MakeVTable(this);
 
-  if (otable != NULL && otable->state == 0)
-    _Jv_LinkOffsetTable(this);
+  if (otable || atable)
+    _Jv_LinkSymbolTable(this);
 
   // Steps 8, 9, 10, 11.
   try
@@ -1533,75 +1534,238 @@ java::lang::Class::getProtectionDomain0 ()
   return protectionDomain;
 }
 
-// Functions for indirect dispatch (symbolic virtual method binding) support.
+// Functions for indirect dispatch (symbolic virtual binding) support.
+
+// There are two tables, atable and otable.  atable is an array of
+// addresses, and otable is an array of offsets, and these are used
+// for static and virtual members respectively.
+
+// {a,o}table_syms is an array of _Jv_MethodSymbols.  Each such symbol
+// is a tuple of {classname, member name, signature}.
+// _Jv_LinkSymbolTable() scans these two arrays and fills in the
+// corresponding atable and otable with the addresses of static
+// members and the offsets of virtual members.
+
+// The offset (in bytes) for each resolved method or field is placed
+// at the corresponding position in the virtual method offset table
+// (klass->otable). 
+
+// The same otable and atable may be shared by many classes.
 
-// Resolve entries in the virtual method offset symbol table 
-// (klass->otable_syms). The vtable offset (in bytes) for each resolved method 
-// is placed at the corresponding position in the virtual method offset table 
-// (klass->otable). A single otable and otable_syms pair may be shared by many 
-// classes.
 void
-_Jv_LinkOffsetTable(jclass klass)
+_Jv_LinkSymbolTable(jclass klass)
 {
-  //// FIXME: Need to lock the otable ////
+  //// FIXME: Need to lock the tables ////
   
+  int index = 0;
+  _Jv_MethodSymbol sym;
   if (klass->otable == NULL
       || klass->otable->state != 0)
-    return;
-  
+    goto atable;
+   
   klass->otable->state = 1;
 
-  int index = 0;
-  _Jv_MethodSymbol sym = klass->otable_syms[0];
-
-  while (sym.name != NULL)
+  for (index = 0; sym = klass->otable_syms[index], sym.name != NULL; index++)
     {
       jclass target_class = _Jv_FindClass (sym.class_name, NULL);
       _Jv_Method *meth = NULL;            
+
+      const _Jv_Utf8Const *signature = sym.signature;
+
+      // FIXME: This should be special index for ThrowNoSuchMethod().
+      klass->otable->offsets[index] = -1;
       
-      if (target_class != NULL)
-	if (target_class->isInterface())
+      if (target_class == NULL)
+	continue;
+
+      if (target_class->isInterface())
+	{
+	  // FIXME: This does not yet fully conform to binary compatibility
+	  // rules. It will break if a declaration is moved into a 
+	  // superinterface.
+	  for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
+	    {
+	      for (int i=0; i < cls->method_count; i++)
+		{
+		  meth = &cls->methods[i];
+		  if (_Jv_equalUtf8Consts (sym.name, meth->name)
+		      && _Jv_equalUtf8Consts (signature, meth->signature))
+		    {
+		      klass->otable->offsets[index] = i + 1;
+		      goto found;
+		    }
+		}
+	    
+	    }
+	found:
+	  continue;
+	}
+
+      // We're looking for a field or a method, and we can tell
+      // which is needed by looking at the signature.
+      if (signature->length >= 2
+	  && signature->data[0] == '(')
+	{
+ 	  // If the target class does not have a vtable_method_count yet, 
+	  // then we can't tell the offsets for its methods, so we must lay 
+	  // it out now.
+	  if (target_class->vtable_method_count == -1)
+	    {
+	      JvSynchronize sync (target_class);
+	      _Jv_LayoutVTableMethods (target_class);
+	    }
+		
+	  meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
+					  sym.signature);
+		
+	  if (meth != NULL)
+	    {
+	      klass->otable->offsets[index] = 
+		_Jv_VTable::idx_to_offset (meth->index);	      
+	    }
+
+	  continue;
+	}
+
+      // try fields
+      {
+	_Jv_Field *the_field = NULL;
+
+	for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
 	  {
-	    // FIXME: This does not yet fully conform to binary compatibility
-	    // rules. It will break if a declaration is moved into a 
-	    // superinterface.
-	    for (int i=0; i < target_class->method_count; i++)
+	    for (int i = 0; i < cls->field_count; i++)
 	      {
-		meth = &target_class->methods[i];
-		if (_Jv_equalUtf8Consts (sym.name, meth->name)
-		    && _Jv_equalUtf8Consts (sym.signature, meth->signature))
-		  {
-		    klass->otable->offsets[index] = i + 1;
-		    break;
-		  }
+		_Jv_Field *field = &cls->fields[i];
+		if (! _Jv_equalUtf8Consts (field->name, sym.name))
+		  continue;
+
+		// FIXME: What access checks should we perform here?
+// 		if (_Jv_CheckAccess (klass, cls, field->flags))
+// 		  {
+
+		if (!field->isResolved ())
+		  _Jv_ResolveField (field, cls->loader);
+
+// 		if (field_type != 0 && field->type != field_type)
+// 		  throw new java::lang::LinkageError
+// 		    (JvNewStringLatin1 
+// 		     ("field type mismatch with different loaders"));
+
+		the_field = field;
+		goto end_of_field_search;
 	      }
 	  }
-	else
+      end_of_field_search:
+	if (the_field != NULL)
 	  {
-	    // If the target class does not have a vtable_method_count yet, 
-	    // then we can't tell the offsets for its methods, so we must lay 
-	    // it out now.
-	    if (target_class->vtable_method_count == -1)
+	    if (the_field->flags & 0x0008 /* Modifier::STATIC */)
+	      {	      
+		throw new java::lang::IncompatibleClassChangeError;
+	      }
+	    else
 	      {
-		JvSynchronize sync (target_class);
-		_Jv_LayoutVTableMethods (target_class);
+		klass->otable->offsets[index] = the_field->u.boffset;
 	      }
+	  }
+	else
+	  {
+	    throw new java::lang::NoSuchFieldError
+	      (_Jv_NewStringUtf8Const (sym.name));
+	  }
+      }
+    }
+
+ atable:
+  if (klass->atable == NULL
+      || klass->atable->state != 0)
+    return;
+
+  klass->atable->state = 1;
+
+  for (index = 0; sym = klass->atable_syms[index], sym.name != NULL; index++)
+    {
+      jclass target_class = _Jv_FindClass (sym.class_name, NULL);
+      _Jv_Method *meth = NULL;            
+      const _Jv_Utf8Const *signature = sym.signature;
+
+      // ??? Setting this pointer to null will at least get us a
+      // NullPointerException
+      klass->atable->addresses[index] = NULL;
+      
+      if (target_class == NULL)
+	continue;
+      
+      // We're looking for a static field or a static method, and we
+      // can tell which is needed by looking at the signature.
+      if (signature->length >= 2
+	  && signature->data[0] == '(')
+	{
+ 	  // If the target class does not have a vtable_method_count yet, 
+	  // then we can't tell the offsets for its methods, so we must lay 
+	  // it out now.
+	  if (target_class->vtable_method_count == -1)
+	    {
+	      JvSynchronize sync (target_class);
+	      _Jv_LayoutVTableMethods (target_class);
+	    }
+	  
+	  meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
+					  sym.signature);
+	  
+	  if (meth != NULL)
+	    klass->atable->addresses[index] = meth->ncode;
+	  else
+	    klass->atable->addresses[index] = (void *)_Jv_ThrowNoSuchMethodError;
 
-            meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
-					    sym.signature);
+	  continue;
+	}
+
+      // try fields
+      {
+	_Jv_Field *the_field = NULL;
 
-	    if (meth != NULL)
+	for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
+	  {
+	    for (int i = 0; i < cls->field_count; i++)
 	      {
-		klass->otable->offsets[index] = 
-		  _Jv_VTable::idx_to_offset (meth->index);
+		_Jv_Field *field = &cls->fields[i];
+		if (! _Jv_equalUtf8Consts (field->name, sym.name))
+		  continue;
+
+		// FIXME: What access checks should we perform here?
+// 		if (_Jv_CheckAccess (klass, cls, field->flags))
+// 		  {
+
+		if (!field->isResolved ())
+		  _Jv_ResolveField (field, cls->loader);
+		
+// 		if (field_type != 0 && field->type != field_type)
+// 		  throw new java::lang::LinkageError
+// 		    (JvNewStringLatin1 
+// 		     ("field type mismatch with different loaders"));
+
+		the_field = field;
+		goto end_of_static_field_search;
 	      }
 	  }
-
-      if (meth == NULL)
-	// FIXME: This should be special index for ThrowNoSuchMethod().
-	klass->otable->offsets[index] = -1;
-
-      sym = klass->otable_syms[++index];
+      end_of_static_field_search:
+	if (the_field != NULL)
+	  {
+	    if (the_field->flags & 0x0008 /* Modifier::STATIC */)
+	      {	      
+		klass->atable->addresses[index] = the_field->u.addr;
+	      }
+	    else
+	      {
+		throw new java::lang::IncompatibleClassChangeError;
+	      }
+	  }
+	else
+	  {
+	    throw new java::lang::NoSuchFieldError
+	      (_Jv_NewStringUtf8Const (sym.name));
+	  }
+      }
     }
 }
 
diff --git a/libjava/java/util/LinkedList.java b/libjava/java/util/LinkedList.java
index c891f82..2f21fb4 100644
--- a/libjava/java/util/LinkedList.java
+++ b/libjava/java/util/LinkedList.java
@@ -1,4 +1,4 @@
-/* LinkedList.java -- Linked list implementation of the List interface
+ /* LinkedList.java -- Linked list implementation of the List interface
    Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
diff --git a/libjava/prims.cc b/libjava/prims.cc
index 8208995..f15c24b 100644
--- a/libjava/prims.cc
+++ b/libjava/prims.cc
@@ -165,10 +165,10 @@ SIGNAL_HANDLER (catch_fpe)
 
 
 jboolean
-_Jv_equalUtf8Consts (Utf8Const* a, Utf8Const *b)
+_Jv_equalUtf8Consts (const Utf8Const* a, const Utf8Const *b)
 {
   int len;
-  _Jv_ushort *aptr, *bptr;
+  const _Jv_ushort *aptr, *bptr;
   if (a == b)
     return true;
   if (a->hash != b->hash)
@@ -176,8 +176,8 @@ _Jv_equalUtf8Consts (Utf8Const* a, Utf8Const *b)
   len = a->length;
   if (b->length != len)
     return false;
-  aptr = (_Jv_ushort *)a->data;
-  bptr = (_Jv_ushort *)b->data;
+  aptr = (const _Jv_ushort *)a->data;
+  bptr = (const _Jv_ushort *)b->data;
   len = (len + 1) >> 1;
   while (--len >= 0)
     if (*aptr++ != *bptr++)
-- 
cgit v1.1