[multiple changes]

2000-01-04  Tom Tromey  <tromey@cygnus.com>

	* java/lang/reflect/natConstructor.cc (newInstance): Pass
	declaring class as return_type argument to
	_Jv_CallNonvirtualMethodA.
	* java/lang/reflect/natMethod.cc (_Jv_CallNonvirtualMethodA): In
	constructor case, create object and use it as `this' argument.
	* java/lang/Class.h (_getConstructors): Declare.
	(_getFields): Declare.
	* java/lang/Class.java (getConstructors): Wrote.
	(_getConstructors): New native method.
	(getDeclaredConstructors): Wrote.
	(_getFields): Declare new native method.
	* java/lang/natClass.cc (_Jv_LookupInterfaceMethod): Removed
	incorrect comment.
	(getMethod): Work correctly when class is primitive.
	(getDeclaredMethods): Likewise.  Compute offset using `method',
	not `mptr'.
	(getDeclaredMethod): Likewise.
	(getConstructor): Wrote.
	(ConstructorClass): New define.
	(getDeclaredConstructor): Wrote.
	(_getConstructors): New method.
	(_getFields): New method.
	(getFields): Wrote.

	* Makefile.in: Rebuilt.
	* Makefile.am (AM_CXXFLAGS): Added -D_GNU_SOURCE.

	* prims.cc: Remove `#pragma implementation'.
	* gcj/array.h: Remove `#pragma interface'.

	* prims.cc (_Jv_equaln): New function.
	* java/lang/Class.java (getSignature): Declare.
	* resolve.cc (_Jv_LookupDeclaredMethod): Moved to natClass.cc.
	* java/lang/natClass.cc (_Jv_LookupDeclaredMethod): Moved from
	resolve.cc.
	(getSignature): New method.
	(getDeclaredMethod): Wrote.
	(getMethod): Wrote.
	Include StringBuffer.h.
	* java/lang/Class.h (Class): Added _Jv_FromReflectedConstructor
	as a friend.  Unconditionally declare _Jv_LookupDeclaredMethod as
	a friend.
	(getSignature): Declare.
	* include/jvm.h (_Jv_GetTypesFromSignature): Declare.
	(_Jv_equaln): Declare.
	(_Jv_CallNonvirtualMethodA): Declare.
	* Makefile.in: Rebuilt.
	* Makefile.am (nat_source_files): Added natConstructor.cc.
	(java/lang/reflect/Constructor.h): New target.
	* java/lang/reflect/natConstructor.cc: New file.
	* java/lang/reflect/Constructor.java (newInstance): Now native.
	(declaringClass): Renamed from decl_class.
	(offset): Renamed from index.
	(getType): New native method.
	(getModifiers): Now native.
	(getParameterTypes): Call getType if required.
	(hashCode): Include hash code from declaring class.
	(modifiers): Removed.
	(toString): Call getType if required.
	* gcj/method.h (_Jv_FromReflectedConstructor): New function.
	* java/lang/reflect/natMethod.cc (hack_call): New method.
	Removed `#if 0' around FFI code.
	Include <gnu/gcj/RawData.h>.
	(invoke): Use _Jv_CallNonvirtualMethodA.  Throw
	IllegalArgumentException when argument object and class disagree.
	(_Jv_GetTypesFromSignature): New function.
	(getType): Use it.
	(ObjectClass): New define.
	(_Jv_CallNonvirtualMethodA): New function.
	* java/lang/reflect/Method.java (hack_trampoline): New method.
	(hack_call): New native method.

1999-12-21  Per Bothner  <per@bothner.com>

	* java/lang/natClass.cc (getDeclaredMethods): Correctly compute
	offset in new Method.

From-SVN: r31199
This commit is contained in:
Tom Tromey 2000-01-04 08:46:52 +00:00
parent 00da7781ff
commit 0f918fea8b
18 changed files with 739 additions and 232 deletions

View file

@ -1,6 +1,6 @@
// natClass.cc - Implementation of java.lang.Class native methods.
/* Copyright (C) 1998, 1999 Cygnus Solutions
/* Copyright (C) 1998, 1999, 2000 Cygnus Solutions
This file is part of libgcj.
@ -38,6 +38,7 @@ details. */
#include <java/lang/NullPointerException.h>
#include <java/lang/System.h>
#include <java/lang/SecurityManager.h>
#include <java/lang/StringBuffer.h>
#include <java-cpool.h>
@ -55,6 +56,8 @@ extern java::lang::Class ClassClass;
extern java::lang::Class MethodClass;
#define FieldClass _CL_Q44java4lang7reflect5Field
extern java::lang::Class FieldClass;
#define ConstructorClass _CL_Q44java4lang7reflect11Constructor
extern java::lang::Class ConstructorClass;
// Some constants we use to look up the class initializer.
static _Jv_Utf8Const *void_signature = _Jv_makeUtf8Const ("()V", 3);
@ -96,27 +99,95 @@ java::lang::Class::forName (jstring className)
}
java::lang::reflect::Constructor *
java::lang::Class::getConstructor (JArray<jclass> *)
java::lang::Class::getConstructor (JArray<jclass> *param_types)
{
JvFail ("java::lang::Class::getConstructor not implemented");
jstring partial_sig = getSignature (param_types);
jint hash = partial_sig->hashCode ();
int i = isPrimitive () ? 0 : method_count;
while (--i >= 0)
{
// FIXME: access checks.
if (_Jv_equalUtf8Consts (methods[i].name, init_name)
&& _Jv_equal (methods[i].signature, partial_sig, hash))
{
// Found it. For getConstructor, the constructor must be
// public.
using namespace java::lang::reflect;
if (Modifier::isPublic(methods[i].accflags))
break;
Constructor *cons = new Constructor ();
cons->offset = (char *) (&methods[i]) - (char *) methods;
cons->declaringClass = this;
return cons;
}
}
JvThrow (new java::lang::NoSuchMethodException);
}
JArray<java::lang::reflect::Constructor *> *
java::lang::Class::getConstructors (void)
java::lang::Class::_getConstructors (jboolean declared)
{
JvFail ("java::lang::Class::getConstructors not implemented");
// FIXME: this method needs access checks.
int numConstructors = 0;
int max = isPrimitive () ? 0 : method_count;
int i;
for (i = max; --i >= 0; )
{
_Jv_Method *method = &methods[i];
if (method->name == NULL
&& ! _Jv_equalUtf8Consts (method->name, init_name))
continue;
if (declared
&& ! java::lang::reflect::Modifier::isPublic(method->accflags))
continue;
numConstructors++;
}
JArray<java::lang::reflect::Constructor *> *result
= (JArray<java::lang::reflect::Constructor *> *)
JvNewObjectArray (numConstructors, &ConstructorClass, NULL);
java::lang::reflect::Constructor** cptr = elements (result);
for (i = 0; i < max; i++)
{
_Jv_Method *method = &methods[i];
if (method->name == NULL
&& ! _Jv_equalUtf8Consts (method->name, init_name))
continue;
if (declared
&& ! java::lang::reflect::Modifier::isPublic(method->accflags))
continue;
java::lang::reflect::Constructor *cons
= new java::lang::reflect::Constructor ();
cons->offset = (char *) method - (char *) methods;
cons->declaringClass = this;
*cptr++ = cons;
}
return result;
}
java::lang::reflect::Constructor *
java::lang::Class::getDeclaredConstructor (JArray<jclass> *)
java::lang::Class::getDeclaredConstructor (JArray<jclass> *param_types)
{
JvFail ("java::lang::Class::getDeclaredConstructor not implemented");
}
jstring partial_sig = getSignature (param_types);
jint hash = partial_sig->hashCode ();
JArray<java::lang::reflect::Constructor *> *
java::lang::Class::getDeclaredConstructors (void)
{
JvFail ("java::lang::Class::getDeclaredConstructors not implemented");
int i = isPrimitive () ? 0 : method_count;
while (--i >= 0)
{
// FIXME: access checks.
if (_Jv_equalUtf8Consts (methods[i].name, init_name)
&& _Jv_equal (methods[i].signature, partial_sig, hash))
{
// Found it.
using namespace java::lang::reflect;
Constructor *cons = new Constructor ();
cons->offset = (char *) (&methods[i]) - (char *) methods;
cons->declaringClass = this;
return cons;
}
}
JvThrow (new java::lang::NoSuchMethodException);
}
java::lang::reflect::Field *
@ -187,18 +258,67 @@ java::lang::Class::getDeclaredFields (void)
return result;
}
java::lang::reflect::Method *
java::lang::Class::getDeclaredMethod (jstring, JArray<jclass> *)
void
java::lang::Class::getSignature (java::lang::StringBuffer *buffer)
{
JvFail ("java::lang::Class::getDeclaredMethod not implemented");
if (isPrimitive())
buffer->append((jchar) method_count);
else
{
jstring name = getName();
if (name->charAt(0) != '[')
buffer->append((jchar) 'L');
buffer->append(name);
if (name->charAt(0) != '[')
buffer->append((jchar) ';');
}
}
// This doesn't have to be native. It is an implementation detail
// only called from the C++ code, though, so maybe this is clearer.
jstring
java::lang::Class::getSignature (JArray<jclass> *param_types)
{
java::lang::StringBuffer *buf = new java::lang::StringBuffer ();
buf->append((jchar) '(');
jclass *v = elements (param_types);
for (int i = 0; i < param_types->length; ++i)
v[i]->getSignature(buf);
buf->append((jchar) ')');
return buf->toString();
}
java::lang::reflect::Method *
java::lang::Class::getDeclaredMethod (jstring name,
JArray<jclass> *param_types)
{
jstring partial_sig = getSignature (param_types);
jint p_len = partial_sig->length();
_Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
int i = isPrimitive () ? 0 : method_count;
while (--i >= 0)
{
// FIXME: access checks.
if (_Jv_equalUtf8Consts (methods[i].name, utf_name)
&& _Jv_equaln (methods[i].signature, partial_sig, p_len))
{
// Found it.
using namespace java::lang::reflect;
Method *rmethod = new Method ();
rmethod->offset = (char*) (&methods[i]) - (char*) methods;
rmethod->declaringClass = this;
}
}
JvThrow (new java::lang::NoSuchMethodException);
}
JArray<java::lang::reflect::Method *> *
java::lang::Class::getDeclaredMethods (void)
{
int numMethods = 0;
int max = isPrimitive () ? 0 : method_count;
int i;
for (i = method_count; --i >= 0; )
for (i = max; --i >= 0; )
{
_Jv_Method *method = &methods[i];
if (method->name == NULL
@ -211,15 +331,16 @@ java::lang::Class::getDeclaredMethods (void)
= (JArray<java::lang::reflect::Method *> *)
JvNewObjectArray (numMethods, &MethodClass, NULL);
java::lang::reflect::Method** mptr = elements (result);
for (i = 0; i < method_count; i++)
for (i = 0; i < max; i++)
{
_Jv_Method *method = &methods[i];
if (method->name == NULL
|| _Jv_equalUtf8Consts (method->name, clinit_name)
|| _Jv_equalUtf8Consts (method->name, init_name))
continue;
java::lang::reflect::Method* rmethod = new java::lang::reflect::Method ();
rmethod->offset = (char*) mptr - (char*) elements (result);
java::lang::reflect::Method* rmethod
= new java::lang::reflect::Method ();
rmethod->offset = (char*) method - (char*) methods;
rmethod->declaringClass = this;
*mptr++ = rmethod;
}
@ -258,10 +379,58 @@ java::lang::Class::getDeclaringClass (void)
return NULL; // Placate compiler.
}
jint
java::lang::Class::_getFields (JArray<java::lang::reflect::Field *> *result,
jint offset)
{
int count = 0;
for (int i = 0; i < field_count; i++)
{
_Jv_Field *field = &fields[i];
if (! (field->getModifiers() & java::lang::reflect::Modifier::PUBLIC))
continue;
++count;
if (result != NULL)
{
java::lang::reflect::Field *rfield
= new java::lang::reflect::Field ();
rfield->offset = (char *) field - (char *) fields;
rfield->declaringClass = this;
rfield->name = _Jv_NewStringUtf8Const (field->name);
(elements (result))[offset + i] = rfield;
}
}
jclass superclass = getSuperclass();
if (superclass != NULL)
{
int s_count = superclass->_getFields (result, offset);
count += s_count;
offset += s_count;
}
for (int i = 0; i < interface_count; ++i)
{
int f_count = interfaces[i]->_getFields (result, offset);
count += f_count;
offset += f_count;
}
return count;
}
JArray<java::lang::reflect::Field *> *
java::lang::Class::getFields (void)
{
JvFail ("java::lang::Class::getFields not implemented");
using namespace java::lang::reflect;
int count = _getFields (NULL, 0);
JArray<java::lang::reflect::Field *> *result
= ((JArray<java::lang::reflect::Field *> *)
JvNewObjectArray (count, &FieldClass, NULL));
_getFields (result, 0);
return result;
}
JArray<jclass> *
@ -275,9 +444,30 @@ java::lang::Class::getInterfaces (void)
}
java::lang::reflect::Method *
java::lang::Class::getMethod (jstring, JArray<jclass> *)
java::lang::Class::getMethod (jstring name, JArray<jclass> *param_types)
{
JvFail ("java::lang::Class::getMethod not implemented");
jstring partial_sig = getSignature (param_types);
jint p_len = partial_sig->length();
_Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
for (Class *klass = this; klass; klass = klass->getSuperclass())
{
int i = klass->isPrimitive () ? 0 : klass->method_count;
while (--i >= 0)
{
// FIXME: access checks.
if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
&& _Jv_equaln (klass->methods[i].signature, partial_sig, p_len))
{
// Found it.
using namespace java::lang::reflect;
Method *rmethod = new Method ();
rmethod->offset = (char*) (&klass->methods[i]) - (char*) methods;
rmethod->declaringClass = klass;
return rmethod;
}
}
}
JvThrow (new java::lang::NoSuchMethodException);
}
JArray<java::lang::reflect::Method *> *
@ -494,6 +684,8 @@ java::lang::Class::initializeClass (void)
// Some class-related convenience functions.
//
// Find a method declared in the class. If it is not declared locally
// (or if it is inherited), return NULL.
_Jv_Method *
_Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
_Jv_Utf8Const *signature)
@ -507,6 +699,21 @@ _Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
return NULL;
}
_Jv_Method *
_Jv_LookupDeclaredMethod (jclass klass, _Jv_Utf8Const *name,
_Jv_Utf8Const *signature)
{
for (; klass; klass = klass->getSuperclass())
{
_Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
if (meth)
return meth;
}
return NULL;
}
// NOTE: MCACHE_SIZE should be a power of 2 minus one.
#define MCACHE_SIZE 1023
@ -553,16 +760,6 @@ void *
_Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name,
_Jv_Utf8Const *signature)
{
// FIXME: can't do this until we have a working class loader.
// This probably isn't the right thing to do anyway, since we can't
// call a method of a class until the class is linked. But this
// captures the general idea.
// klass->getClassLoader()->resolveClass(klass);
//
// KKT: This is unnessecary, exactly for the reason you present:
// _Jv_LookupInterfaceMethod is only called on object instances, and
// such have already been initialized (which includes resolving).
void *ncode = _Jv_FindMethodInCache (klass, name, signature);
if (ncode != 0)
return ncode;