[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:
parent
00da7781ff
commit
0f918fea8b
18 changed files with 739 additions and 232 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue