In gcc/java:
authorBryce McKinlay <bryce@albatross.co.nz>
Mon, 8 Jan 2001 23:28:56 +0000 (23:28 +0000)
committerBryce McKinlay <bryce@gcc.gnu.org>
Mon, 8 Jan 2001 23:28:56 +0000 (23:28 +0000)
* class.c (make_class_data): Push initial value for "arrayclass".
* decl.c (init_decl_processing): Add new class field "arrayclass".

In libjava:
* java/lang/Class.h (_Jv_InitClass): Use __builtin_expect.
(_Jv_NewArrayClass): Renamed from _Jv_FindArrayClass.
(_Jv_GetArrayClass): New inline function.
(arrayclass): New field.
* prims.cc (_Jv_NewObjectArray): Use _Jv_GetArrayClass. Don't use
_Jv_GetArrayElementFromElementType.
(_Jv_NewPrimArray): Ditto.
(_Jv_PrimClass constructor): Initialize "depth", "ancestors", and
"idt" for completeness. Initialze "arrayclass" using _Jv_NewArrayClass.
Set Modifier::ABSTRACT.
* java/lang/natClassLoader.cc (_Jv_NewClass): Initialize "arrayclass".
(_Jv_NewArrayClass): Renamed from _Jv_FindArrayClass. Now void.
Now synchronized. Array classes are now referenced from
elementClass->arrayclass. Don't use _Jv_FindClassInCache.
Set array classes' accessibility flags correctly. Optimize so that
all array classes share the same IDT.
* java/lang/reflect/natArray.cc (newInstance): Use _Jv_GetArrayClass.
* java/lang/reflect/natMethod.cc (_Jv_GetTypesFromSignature): Ditto.
* java/lang/natClass.cc (_getFields): Increment offset. Prevent fields
in superclasses from overwriting classes own fields.
(_Jv_IsAssignableFrom): Check for NULL source idt instead of calling
Modifier::isAbstract().
(null_idt): New static field.
(_Jv_PrepareConstantTimeTables): Optimize case where class implements
no interfaces.
(_Jv_IndexOf): Made inline.
* boehm.cc (_Jv_MarkObj): Mark "arrayclass" field.

From-SVN: r38808

gcc/java/ChangeLog
gcc/java/class.c
gcc/java/decl.c
libjava/ChangeLog
libjava/boehm.cc
libjava/java/lang/Class.h
libjava/java/lang/natClass.cc
libjava/java/lang/natClassLoader.cc
libjava/java/lang/reflect/natArray.cc
libjava/java/lang/reflect/natMethod.cc
libjava/prims.cc

index e3e7e46aa3e028454a2050addd60645c0655d832..ebf96fac18fd68434d962d603a4961e3ded631a1 100644 (file)
@@ -1,3 +1,8 @@
+2001-01-05  Bryce McKinlay  <bryce@albatross.co.nz>
+
+       * class.c (make_class_data): Push initial value for "arrayclass".
+       * decl.c (init_decl_processing): Add new class field "arrayclass".
+
 2001-01-05  Bryce McKinlay  <bryce@albatross.co.nz>
 
        From patha@softlab.ericsson.se:
index 92dd0b971cd9f10df971da495d0723d1ac914c25..ae715f14efcac4fdf3ff67cad944aa9f3d68a299 100644 (file)
@@ -1441,6 +1441,7 @@ make_class_data (type)
   PUSH_FIELD_VALUE (cons, "depth", integer_zero_node);
   PUSH_FIELD_VALUE (cons, "ancestors", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "idt", null_pointer_node);
+  PUSH_FIELD_VALUE (cons, "arrayclass", null_pointer_node);
 
   FINISH_RECORD_CONSTRUCTOR (cons);
 
index df6b236e45ed6b9286caac84386f69300e17cdae..8d7887809e9511de76341eeb0d3bf5eabcd0769c 100644 (file)
@@ -672,6 +672,7 @@ init_decl_processing ()
   PUSH_FIELD (class_type_node, field, "depth", short_type_node);
   PUSH_FIELD (class_type_node, field, "ancestors", ptr_type_node);
   PUSH_FIELD (class_type_node, field, "idt", ptr_type_node);  
+  PUSH_FIELD (class_type_node, field, "arrayclass", ptr_type_node);  
   for (t = TYPE_FIELDS (class_type_node);  t != NULL_TREE;  t = TREE_CHAIN (t))
     FIELD_PRIVATE (t) = 1;
   push_super_field (class_type_node, object_type_node);
index e76f2f44ba8629f0a20adad8d30762a26b7c4d28..42421be56dab0992c7143ddcaba0c027640f2907 100644 (file)
@@ -1,3 +1,33 @@
+2001-01-08  Bryce McKinlay  <bryce@albatross.co.nz>
+
+       * java/lang/Class.h (_Jv_InitClass): Use __builtin_expect.
+       (_Jv_NewArrayClass): Renamed from _Jv_FindArrayClass.
+       (_Jv_GetArrayClass): New inline function.
+       (arrayclass): New field.
+       * prims.cc (_Jv_NewObjectArray): Use _Jv_GetArrayClass. Don't use
+       _Jv_GetArrayElementFromElementType. 
+       (_Jv_NewPrimArray): Ditto.
+       (_Jv_PrimClass constructor): Initialize "depth", "ancestors", and
+       "idt" for completeness. Initialze "arrayclass" using _Jv_NewArrayClass.
+       Set Modifier::ABSTRACT.
+       * java/lang/natClassLoader.cc (_Jv_NewClass): Initialize "arrayclass".
+       (_Jv_NewArrayClass): Renamed from _Jv_FindArrayClass. Now void. 
+       Now synchronized. Array classes are now referenced from
+       elementClass->arrayclass. Don't use _Jv_FindClassInCache.
+       Set array classes' accessibility flags correctly. Optimize so that
+       all array classes share the same IDT.
+       * java/lang/reflect/natArray.cc (newInstance): Use _Jv_GetArrayClass.
+       * java/lang/reflect/natMethod.cc (_Jv_GetTypesFromSignature): Ditto.
+       * java/lang/natClass.cc (_getFields): Increment offset. Prevent fields
+       in superclasses from overwriting classes own fields.
+       (_Jv_IsAssignableFrom): Check for NULL source idt instead of calling
+       Modifier::isAbstract().
+       (null_idt): New static field.
+       (_Jv_PrepareConstantTimeTables): Optimize case where class implements
+       no interfaces.
+       (_Jv_IndexOf): Made inline.
+       * boehm.cc (_Jv_MarkObj): Mark "arrayclass" field.
+
 2001-01-08  Tom Tromey  <tromey@redhat.com>
 
        Fix for PR java/1586:
index 877d97c9d9c8eed1c255d739193e54f81cb05626..49b4eab27fde9e7ea4de877384e511f667eaa942 100644 (file)
@@ -225,6 +225,8 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * /* env */)
        }
       p = (ptr_t) c->loader;
       MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cBlabel);
+      p = (ptr_t) c->arrayclass;
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cDlabel);
 
 #ifdef INTERPRETER
       if (_Jv_IsInterpretedClass (c))
index edaebb3245a5d95217f9c2fbed19459f099eaae3..12e3ed5838fb32d083b5cde636df8ca1d8ac6c45 100644 (file)
@@ -210,7 +210,7 @@ private:
   inline friend void 
   _Jv_InitClass (jclass klass)
   {
-    if (klass->state == JV_STATE_DONE)
+    if (__builtin_expect (klass->state == JV_STATE_DONE, true))
       return;
     klass->initializeClass ();  
   }
@@ -254,9 +254,9 @@ private:
                               java::lang::ClassLoader *loader);
   friend jclass _Jv_FindClassInCache (_Jv_Utf8Const *name,
                                      java::lang::ClassLoader *loader);
-  friend jclass _Jv_FindArrayClass (jclass element,
-                                   java::lang::ClassLoader *loader,
-                                   _Jv_VTable *array_vtable = 0);
+  friend void _Jv_NewArrayClass (jclass element,
+                                java::lang::ClassLoader *loader,
+                                _Jv_VTable *array_vtable = 0);
   friend jclass _Jv_NewClass (_Jv_Utf8Const *name, jclass superclass,
                              java::lang::ClassLoader *loader);
 
@@ -268,6 +268,16 @@ private:
   friend jshort _Jv_AppendPartialITable (jclass, jclass, void **, jshort);
   friend jshort _Jv_FindIIndex (jclass *, jshort *, jshort);
 
+  // Return array class corresponding to element type KLASS, creating it if
+  // neccessary.
+  inline friend jclass
+  _Jv_GetArrayClass (jclass klass, java::lang::ClassLoader *loader)
+  {
+    if (__builtin_expect (!klass->arrayclass, false))
+      _Jv_NewArrayClass (klass, loader);
+    return klass->arrayclass;
+  }
+
 #ifdef INTERPRETER
   friend jboolean _Jv_IsInterpretedClass (jclass);
   friend void _Jv_InitField (jobject, jclass, _Jv_Field*);
@@ -302,8 +312,7 @@ private:
   // Class constants.
   _Jv_Constants constants;
   // Methods.  If this is an array class, then this field holds a
-  // pointer to the element type.  If this is a primitive class, this
-  // is used to cache a pointer to the appropriate array type.
+  // pointer to the element type.
   _Jv_Method *methods;
   // Number of methods.  If this class is primitive, this holds the
   // character used to represent this type in a signature.
@@ -337,6 +346,8 @@ private:
   jclass *ancestors;
   // Interface Dispatch Table.
   _Jv_IDispatchTable *idt;
+  // Pointer to the class that represents an array of this class.
+  jclass arrayclass;
 };
 
 #endif /* __JAVA_LANG_CLASS_H__ */
index 4d45d07e39cb9cfc6e65a3c60a0f72584fb3a313..3a02b46a8af9b9c5ad93748c2fd3600019a8c41b 100644 (file)
@@ -421,7 +421,7 @@ java::lang::Class::_getFields (JArray<java::lang::reflect::Field *> *result,
          rfield->offset = (char *) field - (char *) fields;
          rfield->declaringClass = this;
          rfield->name = _Jv_NewStringUtf8Const (field->name);
-         (elements (result))[offset + i] = rfield;
+         (elements (result))[offset++] = rfield;
        }
     }
   jclass superclass = getSuperclass();
@@ -929,8 +929,7 @@ _Jv_IsAssignableFrom (jclass target, jclass source)
       // Abstract classes have no IDT, and IDTs provide no way to check
       // two interfaces for assignability.
       if (__builtin_expect 
-         (java::lang::reflect::Modifier::isAbstract (source->accflags)
-          || source->isInterface(), false))
+          (source->idt == NULL || source->isInterface(), false))
         return _Jv_InterfaceAssignableFrom (target, source);
        
       _Jv_IDispatchTable *cl_idt = source->idt;
@@ -1007,6 +1006,8 @@ _Jv_CheckArrayStore (jobject arr, jobject obj)
 #define INITIAL_IOFFSETS_LEN 4
 #define INITIAL_IFACES_LEN 4
 
+static _Jv_IDispatchTable null_idt = { {SHRT_MAX, 0, NULL} };
+
 // Generate tables for constant-time assignment testing and interface
 // method lookup. This implements the technique described by Per Bothner
 // <per@bothner.com> on the java-discuss mailing list on 1999-09-02:
@@ -1028,8 +1029,10 @@ _Jv_PrepareConstantTimeTables (jclass klass)
   // interfaces or primitive types.
    
   jclass klass0 = klass;
+  jboolean has_interfaces = 0;
   while (klass0 != &ObjectClass)
     {
+      has_interfaces += klass0->interface_count;
       klass0 = klass0->superclass;
       klass->depth++;
     }
@@ -1051,6 +1054,14 @@ _Jv_PrepareConstantTimeTables (jclass klass)
     
   if (java::lang::reflect::Modifier::isAbstract (klass->accflags))
     return;
+  
+  // Optimization: If class implements no interfaces, use a common
+  // predefined interface table.
+  if (!has_interfaces)
+    {
+      klass->idt = &null_idt;
+      return;
+    }
 
   klass->idt = 
     (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable));
@@ -1095,7 +1106,7 @@ _Jv_PrepareConstantTimeTables (jclass klass)
 }
 
 // Return index of item in list, or -1 if item is not present.
-jshort
+inline jshort
 _Jv_IndexOf (void *item, void **list, jshort list_len)
 {
   for (int i=0; i < list_len; i++)
index f1704edd9aa0091dce630bc37a84b5cf0639df0f..979de3fc2d684e9affd854f89112da1599b6330f 100644 (file)
@@ -530,26 +530,35 @@ _Jv_NewClass (_Jv_Utf8Const *name, jclass superclass,
   ret->depth = 0;
   ret->ancestors = NULL;
   ret->idt = NULL;
+  ret->arrayclass = NULL;
 
   _Jv_RegisterClass (ret);
 
   return ret;
 }
 
-jclass
-_Jv_FindArrayClass (jclass element, java::lang::ClassLoader *loader,
-                   _Jv_VTable *array_vtable)
+static _Jv_IDispatchTable *array_idt = NULL;
+static jshort array_depth = 0;
+static jclass *array_ancestors = NULL;
+
+// Create a class representing an array of ELEMENT and store a pointer to it
+// in element->arrayclass. LOADER is the ClassLoader which _initiated_ the 
+// instantiation of this array. ARRAY_VTABLE is the vtable to use for the new 
+// array class. This parameter is optional.
+void
+_Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader,
+                  _Jv_VTable *array_vtable)
 {
+  JvSynchronize sync (element);
+
   _Jv_Utf8Const *array_name;
   int len;
+
+  if (element->arrayclass)
+    return;
+
   if (element->isPrimitive())
-    {
-      // For primitive types the array is cached in the class.
-      jclass ret = (jclass) element->methods;
-      if (ret)
-       return ret;
-      len = 3;
-    }
+    len = 3;
   else
     len = element->name->length + 5;
 
@@ -557,7 +566,7 @@ _Jv_FindArrayClass (jclass element, java::lang::ClassLoader *loader,
     char signature[len];
     int index = 0;
     signature[index++] = '[';
-    // Compute name of array class to see if we've already cached it.
+    // Compute name of array class.
     if (element->isPrimitive())
       {
        signature[index++] = (char) element->method_count;
@@ -576,65 +585,76 @@ _Jv_FindArrayClass (jclass element, java::lang::ClassLoader *loader,
     array_name = _Jv_makeUtf8Const (signature, index);
   }
 
-  jclass array_class = _Jv_FindClassInCache (array_name, element->loader);
-
-  if (! array_class)
+  // Create new array class.
+  jclass array_class = _Jv_NewClass (array_name, &ObjectClass,
+                                    element->loader);
+
+  // Note that `vtable_method_count' doesn't include the initial
+  // gc_descr slot.
+  JvAssert (ObjectClass.vtable_method_count == NUM_OBJECT_METHODS);
+  int dm_count = ObjectClass.vtable_method_count;
+
+  // Create a new vtable by copying Object's vtable (except the
+  // class pointer, of course).  Note that we allocate this as
+  // unscanned memory -- the vtables are handled specially by the
+  // GC.
+  int size = (sizeof (_Jv_VTable) + ((dm_count - 1) * sizeof (void *)));
+  _Jv_VTable *vtable;
+  if (array_vtable)
+    vtable = array_vtable;
+  else
+    vtable = (_Jv_VTable *) _Jv_AllocBytes (size);
+  vtable->clas = array_class;
+  memcpy (vtable->method, ObjectClass.vtable->method,
+         dm_count * sizeof (void *));
+  vtable->gc_descr = ObjectClass.vtable->gc_descr;
+  array_class->vtable = vtable;
+  array_class->vtable_method_count = ObjectClass.vtable_method_count;
+
+  // Stash the pointer to the element type.
+  array_class->methods = (_Jv_Method *) element;
+
+  // Register our interfaces.
+  static jclass interfaces[] = { &CloneableClass, &SerializableClass };
+  array_class->interfaces = interfaces;
+  array_class->interface_count = sizeof interfaces / sizeof interfaces[0];
+
+  // Since all array classes have the same interface dispatch table, we can 
+  // cache one and reuse it. It is not neccessary to synchronize this.
+  if (!array_idt)
     {
-      // Create new array class.
-      array_class = _Jv_NewClass (array_name, &ObjectClass, element->loader);
-
-      // Note that `vtable_method_count' doesn't include the initial
-      // gc_descr slot.
-      JvAssert (ObjectClass.vtable_method_count == NUM_OBJECT_METHODS);
-      int dm_count = ObjectClass.vtable_method_count;
-
-      // Create a new vtable by copying Object's vtable (except the
-      // class pointer, of course).  Note that we allocate this as
-      // unscanned memory -- the vtables are handled specially by the
-      // GC.
-      int size = (sizeof (_Jv_VTable) + ((dm_count - 1) * sizeof (void *)));
-      _Jv_VTable *vtable;
-      if (array_vtable)
-       vtable = array_vtable;
-      else
-       vtable = (_Jv_VTable *) _Jv_AllocBytes (size);
-      vtable->clas = array_class;
-      memcpy (vtable->method, ObjectClass.vtable->method,
-             dm_count * sizeof (void *));
-      vtable->gc_descr = ObjectClass.vtable->gc_descr;
-      array_class->vtable = vtable;
-      array_class->vtable_method_count = ObjectClass.vtable_method_count;
-
-      // Stash the pointer to the element type.
-      array_class->methods = (_Jv_Method *) element;
-
-      // Register our interfaces.
-      static jclass interfaces[] = { &CloneableClass, &SerializableClass };
-      array_class->interfaces = interfaces;
-      array_class->interface_count = sizeof interfaces / sizeof interfaces[0];
-
-      // FIXME: Shouldn't this be synchronized? _Jv_PrepareConstantTimeTables
-      // needs to be called with the mutex for array_class held.
-      // Generate the interface dispatch table.
       _Jv_PrepareConstantTimeTables (array_class);
+      array_idt = array_class->idt;
+      array_depth = array_class->depth;
+      array_ancestors = array_class->ancestors;
+    }
+  else
+    {
+      array_class->idt = array_idt;
+      array_class->depth = array_depth;
+      array_class->ancestors = array_ancestors;
+    }
 
-      // as per vmspec 5.3.3.2
-      array_class->accflags = element->accflags;
-
-      // FIXME: initialize other Class instance variables,
-      // e.g. `fields'.
+  using namespace java::lang::reflect;
+  {
+    // Array classes are "abstract final"...
+    _Jv_ushort accflags = Modifier::FINAL | Modifier::ABSTRACT;
+    // ... and inherit accessibility from element type, per vmspec 5.3.3.2
+    accflags |= (element->accflags & Modifier::PUBLIC);
+    accflags |= (element->accflags & Modifier::PROTECTED);
+    accflags |= (element->accflags & Modifier::PRIVATE);      
+    array_class->accflags = accflags;
+  }
 
-      // say this class is initialized and ready to go!
-      array_class->state = JV_STATE_DONE;
+  // An array class has no visible instance fields. "length" is invisible to 
+  // reflection.
 
-      // vmspec, section 5.3.3 describes this
-      if (element->loader != loader)
-       _Jv_RegisterInitiatingLoader (array_class, loader);
-    }
+  // say this class is initialized and ready to go!
+  array_class->state = JV_STATE_DONE;
 
-  // For primitive types, point back at this array.
-  if (element->isPrimitive())
-    element->methods = (_Jv_Method *) array_class;
+  // vmspec, section 5.3.3 describes this
+  if (element->loader != loader)
+    _Jv_RegisterInitiatingLoader (array_class, loader);
 
-  return array_class;
+  element->arrayclass = array_class;
 }
index b5a2124fb6d387d231818dfdf0de4ad96e0cc9a9..1680456d0b33f5463297d83b3f1d11afecdd1bfb 100644 (file)
@@ -54,7 +54,7 @@ java::lang::reflect::Array::newInstance (jclass componentType, jintArray dimensi
   jclass arrayType = componentType;
   for (int i = 0;  i < ndims;  i++)  // FIXME 2nd arg should 
                                      // be "current" loader
-    arrayType = _Jv_FindArrayClass (arrayType, 0);
+    arrayType = _Jv_GetArrayClass (arrayType, 0);
 
   return _Jv_NewMultiArray (arrayType, ndims, dims);
 }
index 26886e9bd85258108aec2fdb4c0fd93965f2b0e4..4e9d3ceea4ab820f872b0fabf3d32dae2e89c59a 100644 (file)
@@ -286,7 +286,7 @@ _Jv_GetTypesFromSignature (jmethodID method,
 
       // FIXME: 2'nd argument should be "current loader"
       while (--num_arrays >= 0)
-       type = _Jv_FindArrayClass (type, 0);
+       type = _Jv_GetArrayClass (type, 0);
       // ARGPTR can be NULL if we are processing the return value of a
       // call from Constructor.
       if (argPtr)
index 06585749c5f4dd7f6ebd63e41b71b66a22f56a2a..c4c7316dfcea2d3ce6030ff21ef4cfd48d370a54 100644 (file)
@@ -394,19 +394,13 @@ _Jv_NewObjectArray (jsize count, jclass elementClass, jobject init)
 
   JvAssert (! elementClass->isPrimitive ());
 
+  // Ensure that elements pointer is properly aligned.
   jobjectArray obj = NULL;
-  size_t size = (size_t) _Jv_GetArrayElementFromElementType (obj,
-                                                            elementClass);
-
-  // Check for overflow.
-  if (__builtin_expect ((size_t) count > 
-                       (SIZE_T_MAX - size) / sizeof (jobject), false))
-    JvThrow (no_memory);
-
+  size_t size = (size_t) elements (obj);
   size += count * sizeof (jobject);
 
-  // FIXME: second argument should be "current loader" //
-  jclass klass = _Jv_FindArrayClass (elementClass, 0);
+  // FIXME: second argument should be "current loader"
+  jclass klass = _Jv_GetArrayClass (elementClass, 0);
 
   obj = (jobjectArray) _Jv_AllocArray (size, klass);
   if (__builtin_expect (! obj, false))
@@ -414,11 +408,11 @@ _Jv_NewObjectArray (jsize count, jclass elementClass, jobject init)
   // Cast away const.
   jsize *lp = const_cast<jsize *> (&obj->length);
   *lp = count;
-  jobject *ptr = elements(obj);
   // We know the allocator returns zeroed memory.  So don't bother
   // zeroing it again.
   if (init)
     {
+      jobject *ptr = elements(obj);
       while (--count >= 0)
        *ptr++ = init;
     }
@@ -443,7 +437,7 @@ _Jv_NewPrimArray (jclass eltype, jint count)
                        (SIZE_T_MAX - size) / elsize, false))
     JvThrow (no_memory);
 
-  jclass klass = _Jv_FindArrayClass (eltype, 0);
+  jclass klass = _Jv_GetArrayClass (eltype, 0);
 
   __JArray *arr = (__JArray*) _Jv_AllocObj (size + elsize * count, klass);
   if (__builtin_expect (! arr, false))
@@ -529,7 +523,7 @@ public:
       // the same order they are declared in Class.h.
       next = NULL;
       name = _Jv_makeUtf8Const ((char *) cname, -1);
-      accflags = Modifier::PUBLIC | Modifier::FINAL;
+      accflags = Modifier::PUBLIC | Modifier::FINAL | Modifier::ABSTRACT;
       superclass = NULL;
       constants.size = 0;
       constants.tags = NULL;
@@ -547,10 +541,15 @@ public:
       interface_count = 0;
       state = JV_STATE_DONE;
       thread = NULL;
+      depth = -1;
+      ancestors = NULL;
+      idt = NULL;
 
       // Note that we have to set `methods' to NULL.
       if (sig != 'V')
-       _Jv_FindArrayClass (this, NULL, (_Jv_VTable *) array_vtable);
+       _Jv_NewArrayClass (this, NULL, (_Jv_VTable *) array_vtable);
+      else
+        arrayclass = NULL;
     }
 };
 
@@ -606,8 +605,8 @@ _Jv_FindClassFromSignature (char *sig, java::lang::ClassLoader *loader)
 
       }
     case '[':
-      return _Jv_FindArrayClass (_Jv_FindClassFromSignature (&sig[1], loader),
-                                loader);
+      return _Jv_GetArrayClass (_Jv_FindClassFromSignature (&sig[1], loader),
+                               loader);
     }
   JvFail ("couldn't understand class signature");
   return NULL;                 // Placate compiler.