In gcc/java:

* 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
This commit is contained in:
Bryce McKinlay 2001-01-08 23:28:56 +00:00 committed by Bryce McKinlay
parent 5bab9296f5
commit 5bb11b2e20
11 changed files with 174 additions and 94 deletions

View 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);
// Create new array class.
jclass array_class = _Jv_NewClass (array_name, &ObjectClass,
element->loader);
if (! array_class)
// 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);
// as per vmspec 5.3.3.2
array_class->accflags = element->accflags;
// FIXME: initialize other Class instance variables,
// e.g. `fields'.
// say this class is initialized and ready to go!
array_class->state = JV_STATE_DONE;
// vmspec, section 5.3.3 describes this
if (element->loader != loader)
_Jv_RegisterInitiatingLoader (array_class, loader);
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;
}
// For primitive types, point back at this array.
if (element->isPrimitive())
element->methods = (_Jv_Method *) array_class;
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;
}
return array_class;
// An array class has no visible instance fields. "length" is invisible to
// reflection.
// say this class is initialized and ready to go!
array_class->state = JV_STATE_DONE;
// vmspec, section 5.3.3 describes this
if (element->loader != loader)
_Jv_RegisterInitiatingLoader (array_class, loader);
element->arrayclass = array_class;
}