summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libjava/ChangeLog79
-rw-r--r--libjava/Makefile.am11
-rw-r--r--libjava/Makefile.in13
-rw-r--r--libjava/gcj/Makefile.in4
-rw-r--r--libjava/gcj/array.h2
-rw-r--r--libjava/gcj/method.h7
-rw-r--r--libjava/include/Makefile.in4
-rw-r--r--libjava/include/jvm.h8
-rw-r--r--libjava/java/lang/Class.h11
-rw-r--r--libjava/java/lang/Class.java28
-rw-r--r--libjava/java/lang/natClass.cc261
-rw-r--r--libjava/java/lang/reflect/Constructor.java47
-rw-r--r--libjava/java/lang/reflect/Method.java28
-rw-r--r--libjava/java/lang/reflect/natConstructor.cc53
-rw-r--r--libjava/java/lang/reflect/natMethod.cc364
-rw-r--r--libjava/prims.cc22
-rw-r--r--libjava/resolve.cc15
-rw-r--r--libjava/testsuite/Makefile.in4
18 files changed, 734 insertions, 227 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index cfdd9860e89..5cd39d24449 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,82 @@
+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.
+
1999-12-22 Bryce McKinlay <bryce@albatross.co.nz>
* java/lang/natObject.cc (notify): Throw message with
diff --git a/libjava/Makefile.am b/libjava/Makefile.am
index ee5a88e0012..d15784dfb42 100644
--- a/libjava/Makefile.am
+++ b/libjava/Makefile.am
@@ -74,8 +74,10 @@ JAVAC = $(GCJ) -C
EH_COMMON_INCLUDE = @EH_COMMON_INCLUDE@
WARNINGS = -W -Wall
+## We need _GNU_SOURCE defined for some Linux builds. It doesn't hurt
+## to always define it.
AM_CXXFLAGS = -fno-rtti -fvtable-thunks @LIBGCJ_CXXFLAGS@ @EXCEPTIONSPEC@ \
- $(WARNINGS)
+ $(WARNINGS) -D_GNU_SOURCE
if USING_GCC
AM_CFLAGS = @LIBGCJ_CFLAGS@ $(WARNINGS)
else
@@ -229,6 +231,12 @@ java/lang/String.h: java/lang/String.class libgcj.zip
-friend 'jstring _Jv_AllocString (jsize);' \
$(basename $<)
+java/lang/reflect/Constructor.h: java/lang/reflect/Constructor.class libgcj.zip
+ $(GCJH) -classpath $(top_builddir) \
+ -friend 'jmethodID _Jv_FromReflectedConstructor (java::lang::reflect::Constructor *);' \
+ -friend 'java::lang::Class;' \
+ $(basename $<)
+
java/lang/reflect/Field.h: java/lang/reflect/Field.class libgcj.zip
$(GCJH) -classpath $(top_builddir) \
-friend 'jfieldID _Jv_FromReflectedField (java::lang::reflect::Field *);' \
@@ -797,6 +805,7 @@ java/lang/natString.cc \
java/lang/natSystem.cc \
java/lang/natThread.cc \
java/lang/reflect/natArray.cc \
+java/lang/reflect/natConstructor.cc \
java/lang/reflect/natField.cc \
java/lang/reflect/natMethod.cc \
java/net/natInetAddress.cc \
diff --git a/libjava/Makefile.in b/libjava/Makefile.in
index d71f07061de..feb516de38d 100644
--- a/libjava/Makefile.in
+++ b/libjava/Makefile.in
@@ -158,7 +158,7 @@ EH_COMMON_INCLUDE = @EH_COMMON_INCLUDE@
WARNINGS = -W -Wall
AM_CXXFLAGS = -fno-rtti -fvtable-thunks @LIBGCJ_CXXFLAGS@ @EXCEPTIONSPEC@ \
- $(WARNINGS)
+ $(WARNINGS) -D_GNU_SOURCE
@USING_GCC_TRUE@AM_CFLAGS = \
@USING_GCC_TRUE@@LIBGCJ_CFLAGS@ $(WARNINGS)
@@ -619,6 +619,7 @@ java/lang/natString.cc \
java/lang/natSystem.cc \
java/lang/natThread.cc \
java/lang/reflect/natArray.cc \
+java/lang/reflect/natConstructor.cc \
java/lang/reflect/natField.cc \
java/lang/reflect/natMethod.cc \
java/net/natInetAddress.cc \
@@ -726,7 +727,7 @@ THANKS acinclude.m4 aclocal.m4 configure configure.in libgcj.spec.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-TAR = gtar
+TAR = tar
GZIP_ENV = --best
DIST_SUBDIRS = testsuite gcj include gcj include
DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
@@ -1267,7 +1268,7 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
- cp -pr $$d/$$file $(distdir)/$$file; \
+ cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
@@ -1513,6 +1514,12 @@ java/lang/String.h: java/lang/String.class libgcj.zip
-friend 'jstring _Jv_AllocString (jsize);' \
$(basename $<)
+java/lang/reflect/Constructor.h: java/lang/reflect/Constructor.class libgcj.zip
+ $(GCJH) -classpath $(top_builddir) \
+ -friend 'jmethodID _Jv_FromReflectedConstructor (java::lang::reflect::Constructor *);' \
+ -friend 'java::lang::Class;' \
+ $(basename $<)
+
java/lang/reflect/Field.h: java/lang/reflect/Field.class libgcj.zip
$(GCJH) -classpath $(top_builddir) \
-friend 'jfieldID _Jv_FromReflectedField (java::lang::reflect::Field *);' \
diff --git a/libjava/gcj/Makefile.in b/libjava/gcj/Makefile.in
index 7bbcec49f68..a149935cf1e 100644
--- a/libjava/gcj/Makefile.in
+++ b/libjava/gcj/Makefile.in
@@ -76,12 +76,14 @@ DLLTOOL = @DLLTOOL@
EH_COMMON_INCLUDE = @EH_COMMON_INCLUDE@
EXCEPTIONSPEC = @EXCEPTIONSPEC@
EXEEXT = @EXEEXT@
+FORCELIBGCCSPEC = @FORCELIBGCCSPEC@
GCDEPS = @GCDEPS@
GCINCS = @GCINCS@
GCLIBS = @GCLIBS@
GCOBJS = @GCOBJS@
GCSPEC = @GCSPEC@
LD = @LD@
+LIBDATASTARTSPEC = @LIBDATASTARTSPEC@
LIBGCJ_CFLAGS = @LIBGCJ_CFLAGS@
LIBGCJ_CXXFLAGS = @LIBGCJ_CXXFLAGS@
LIBGCJ_JAVAFLAGS = @LIBGCJ_JAVAFLAGS@
@@ -90,7 +92,6 @@ LN_S = @LN_S@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
NM = @NM@
-OBJDUMP = @OBJDUMP@
PACKAGE = @PACKAGE@
PERL = @PERL@
RANLIB = @RANLIB@
@@ -100,6 +101,7 @@ THREADINCS = @THREADINCS@
THREADLIBS = @THREADLIBS@
THREADOBJS = @THREADOBJS@
THREADSPEC = @THREADSPEC@
+USE_SYMBOL_UNDERSCORE = @USE_SYMBOL_UNDERSCORE@
VERSION = @VERSION@
ZDEPS = @ZDEPS@
ZINCS = @ZINCS@
diff --git a/libjava/gcj/array.h b/libjava/gcj/array.h
index f3733595e76..76a75f61e0d 100644
--- a/libjava/gcj/array.h
+++ b/libjava/gcj/array.h
@@ -11,8 +11,6 @@ details. */
#ifndef __GCJ_ARRAY_H__
#define __GCJ_ARRAY_H__
-#pragma interface
-
#include <java/lang/Object.h>
extern "Java" {
diff --git a/libjava/gcj/method.h b/libjava/gcj/method.h
index a97ba4a682f..e5402a0ed8a 100644
--- a/libjava/gcj/method.h
+++ b/libjava/gcj/method.h
@@ -18,4 +18,11 @@ _Jv_FromReflectedMethod(java::lang::reflect::Method *method)
((char *) method->declaringClass->methods + method->offset);
}
+extern inline jmethodID
+_Jv_FromReflectedConstructor (java::lang::reflect::Constructor *constructor)
+{
+ return (jmethodID)
+ ((char *) constructor->declaringClass->methods + constructor->offset);
+}
+
#endif /* __GCJ_METHOD_H__ */
diff --git a/libjava/include/Makefile.in b/libjava/include/Makefile.in
index d68544b9e72..38af4a5872b 100644
--- a/libjava/include/Makefile.in
+++ b/libjava/include/Makefile.in
@@ -76,12 +76,14 @@ DLLTOOL = @DLLTOOL@
EH_COMMON_INCLUDE = @EH_COMMON_INCLUDE@
EXCEPTIONSPEC = @EXCEPTIONSPEC@
EXEEXT = @EXEEXT@
+FORCELIBGCCSPEC = @FORCELIBGCCSPEC@
GCDEPS = @GCDEPS@
GCINCS = @GCINCS@
GCLIBS = @GCLIBS@
GCOBJS = @GCOBJS@
GCSPEC = @GCSPEC@
LD = @LD@
+LIBDATASTARTSPEC = @LIBDATASTARTSPEC@
LIBGCJ_CFLAGS = @LIBGCJ_CFLAGS@
LIBGCJ_CXXFLAGS = @LIBGCJ_CXXFLAGS@
LIBGCJ_JAVAFLAGS = @LIBGCJ_JAVAFLAGS@
@@ -90,7 +92,6 @@ LN_S = @LN_S@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
NM = @NM@
-OBJDUMP = @OBJDUMP@
PACKAGE = @PACKAGE@
PERL = @PERL@
RANLIB = @RANLIB@
@@ -100,6 +101,7 @@ THREADINCS = @THREADINCS@
THREADLIBS = @THREADLIBS@
THREADOBJS = @THREADOBJS@
THREADSPEC = @THREADSPEC@
+USE_SYMBOL_UNDERSCORE = @USE_SYMBOL_UNDERSCORE@
VERSION = @VERSION@
ZDEPS = @ZDEPS@
ZINCS = @ZINCS@
diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h
index 791cdfadec9..3b59b8dfe7c 100644
--- a/libjava/include/jvm.h
+++ b/libjava/include/jvm.h
@@ -53,6 +53,7 @@ _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_equal (_Jv_Utf8Const *, jstring, jint);
+extern jboolean _Jv_equaln (_Jv_Utf8Const *, jstring, jint);
#define StringClass _CL_Q34java4lang6String
extern java::lang::Class StringClass;
@@ -161,6 +162,13 @@ extern jclass _Jv_FindClass (_Jv_Utf8Const *name,
java::lang::ClassLoader *loader);
extern jclass _Jv_FindClassFromSignature (char *,
java::lang::ClassLoader *loader);
+extern void _Jv_GetTypesFromSignature (jmethodID method,
+ jclass declaringClass,
+ JArray<jclass> **arg_types_out,
+ jclass *return_type_out);
+extern jobject _Jv_CallNonvirtualMethodA (jobject, jclass,
+ jmethodID, jboolean,
+ JArray<jclass> *, jobjectArray);
extern jobject _Jv_NewMultiArray (jclass, jint ndims, jint* dims)
__attribute__((__malloc__));
diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h
index c88c86e2e84..dfdbf72c831 100644
--- a/libjava/java/lang/Class.h
+++ b/libjava/java/lang/Class.h
@@ -1,6 +1,6 @@
// Class.h - Header file for java.lang.Class. -*- c++ -*-
-/* Copyright (C) 1998, 1999 Cygnus Solutions
+/* Copyright (C) 1998, 1999, 2000 Cygnus Solutions
This file is part of libgcj.
@@ -94,12 +94,16 @@ public:
java::lang::reflect::Field *getField (jstring);
private:
+ jint _getFields (JArray<java::lang::reflect::Field *> *result, jint offset);
+ JArray<java::lang::reflect::Constructor *> *_getConstructors (jboolean);
java::lang::reflect::Field *getField (jstring, jint);
public:
JArray<java::lang::reflect::Field *> *getFields (void);
JArray<jclass> *getInterfaces (void);
+ void getSignature (java::lang::StringBuffer *buffer);
+ static jstring getSignature (JArray<jclass> *);
java::lang::reflect::Method *getMethod (jstring, JArray<jclass> *);
JArray<java::lang::reflect::Method *> *getMethods (void);
@@ -156,6 +160,8 @@ private:
// Friend functions implemented in natClass.cc.
friend _Jv_Method *_Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
_Jv_Utf8Const *signature);
+ friend _Jv_Method* _Jv_LookupDeclaredMethod (jclass, _Jv_Utf8Const *,
+ _Jv_Utf8Const*);
friend void _Jv_InitClass (jclass klass);
friend jfieldID JvGetFirstInstanceField (jclass);
@@ -166,6 +172,7 @@ private:
friend jobject _Jv_JNI_ToReflectedField (_Jv_JNIEnv *, jclass, jfieldID);
friend jfieldID _Jv_FromReflectedField (java::lang::reflect::Field *);
friend jmethodID _Jv_FromReflectedMethod (java::lang::reflect::Method *);
+ friend jmethodID _Jv_FromReflectedConstructor (java::lang::reflect::Constructor *);
friend class _Jv_PrimClass;
@@ -190,8 +197,6 @@ private:
#ifdef INTERPRETER
friend jboolean _Jv_IsInterpretedClass (jclass);
friend void _Jv_InitField (jobject, jclass, _Jv_Field*);
- friend _Jv_Method* _Jv_LookupDeclaredMethod (jclass, _Jv_Utf8Const *,
- _Jv_Utf8Const*);
friend int _Jv_DetermineVTableIndex (jclass, _Jv_Utf8Const *,
_Jv_Utf8Const*);
friend void _Jv_InitField (jobject, jclass, int);
diff --git a/libjava/java/lang/Class.java b/libjava/java/lang/Class.java
index f9bd59b2598..a304e6c0113 100644
--- a/libjava/java/lang/Class.java
+++ b/libjava/java/lang/Class.java
@@ -1,6 +1,6 @@
// Class.java - Representation of a Java class.
-/* Copyright (C) 1998, 1999 Cygnus Solutions
+/* Copyright (C) 1998, 1999, 2000 Cygnus Solutions
This file is part of libgcj.
@@ -36,14 +36,27 @@ public final class Class implements Serializable
public native Constructor getConstructor (Class[] parameterTypes)
throws NoSuchMethodException, SecurityException;
- public native Constructor[] getConstructors () throws SecurityException;
- public native Class[] getDeclaredClasses () throws SecurityException;
+ // This is used to implement getConstructors and
+ // getDeclaredConstructors.
+ private native Constructor[] _getConstructors (boolean declared)
+ throws SecurityException;
+
+ public Constructor[] getConstructors () throws SecurityException
+ {
+ return _getConstructors (false);
+ }
public native Constructor getDeclaredConstructor (Class[] parameterTypes)
throws NoSuchMethodException, SecurityException;
- public native Constructor[] getDeclaredConstructors ()
- throws SecurityException;
+
+ public native Class[] getDeclaredClasses () throws SecurityException;
+
+ public Constructor[] getDeclaredConstructors () throws SecurityException
+ {
+ return _getConstructors (true);
+ }
+
public native Field getDeclaredField (String fieldName)
throws NoSuchFieldException, SecurityException;
public native Field[] getDeclaredFields () throws SecurityException;
@@ -69,10 +82,15 @@ public final class Class implements Serializable
throw new NoSuchFieldException(fieldName);
return fld;
}
+
+ private native Field[] _getFields (Field[] result, int offset);
public native Field[] getFields () throws SecurityException;
public native Class[] getInterfaces ();
+ private final native void getSignature (StringBuffer buffer);
+ private static final native String getSignature (Class[] parameterTypes);
+
public native Method getMethod (String methodName, Class[] parameterTypes)
throws NoSuchMethodException, SecurityException;
public native Method[] getMethods () throws SecurityException;
diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc
index 20720312f58..939fe387e7a 100644
--- a/libjava/java/lang/natClass.cc
+++ b/libjava/java/lang/natClass.cc
@@ -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;
diff --git a/libjava/java/lang/reflect/Constructor.java b/libjava/java/lang/reflect/Constructor.java
index 466c1204bae..7815d7cedc6 100644
--- a/libjava/java/lang/reflect/Constructor.java
+++ b/libjava/java/lang/reflect/Constructor.java
@@ -28,12 +28,12 @@ public final class Constructor extends AccessibleObject implements Member
if (! (obj instanceof Constructor))
return false;
Constructor c = (Constructor) obj;
- return decl_class == c.decl_class && index == c.index;
+ return declaringClass == c.declaringClass && offset == c.offset;
}
public Class getDeclaringClass ()
{
- return decl_class;
+ return declaringClass;
}
public Class[] getExceptionTypes ()
@@ -41,40 +41,39 @@ public final class Constructor extends AccessibleObject implements Member
return (Class[]) exception_types.clone();
}
- public int getModifiers ()
- {
- return modifiers;
- }
+ public native int getModifiers ();
public String getName ()
- {
- return decl_class.getName();
- }
+ {
+ return declaringClass.getName();
+ }
public Class[] getParameterTypes ()
{
+ if (parameter_types == null)
+ getType ();
return (Class[]) parameter_types.clone();
}
public int hashCode ()
{
// FIXME.
- return getName().hashCode();
+ return getName().hashCode() + declaringClass.getName().hashCode();
}
- // FIXME: this must be native. Should share implementation with
- // Method.invoke.
- public Object newInstance (Object[] args)
+ // Update cached values from method descriptor in class.
+ private native void getType ();
+
+ public native Object newInstance (Object[] args)
throws InstantiationException, IllegalAccessException,
- IllegalArgumentException, InvocationTargetException
- {
- return null;
- }
+ IllegalArgumentException, InvocationTargetException;
public String toString ()
{
+ if (parameter_types == null)
+ getType ();
StringBuffer b = new StringBuffer ();
- b.append(Modifier.toString(modifiers));
+ b.append(Modifier.toString(getModifiers()));
b.append(" ");
b.append(getName());
b.append("(");
@@ -88,19 +87,19 @@ public final class Constructor extends AccessibleObject implements Member
return b.toString();
}
- // Can't create these. FIXME.
+ // Can't create these.
private Constructor ()
{
}
// Declaring class.
- private Class decl_class;
+ private Class declaringClass;
+
// Exception types.
private Class[] exception_types;
- // Modifiers.
- private int modifiers;
// Parameter types.
private Class[] parameter_types;
- // Index of this method in declaring class' method table.
- private int index;
+
+ // Offset in bytes from the start of declaringClass's methods array.
+ private int offset;
}
diff --git a/libjava/java/lang/reflect/Method.java b/libjava/java/lang/reflect/Method.java
index e0571f8a186..dd87816a40d 100644
--- a/libjava/java/lang/reflect/Method.java
+++ b/libjava/java/lang/reflect/Method.java
@@ -10,6 +10,8 @@ details. */
package java.lang.reflect;
+import gnu.gcj.RawData;
+
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date December 12, 1998
@@ -17,7 +19,7 @@ package java.lang.reflect;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
- * Status: Incomplete: invoke() needs to be finished.
+ * Status: Complete, but not correct: access checks aren't done.
*/
public final class Method extends AccessibleObject implements Member
@@ -66,6 +68,30 @@ public final class Method extends AccessibleObject implements Member
return name.hashCode() + declaringClass.getName().hashCode();
}
+ // This is used to perform an actual method call via ffi.
+ private static final native void hack_call (RawData cif,
+ RawData method,
+ RawData ret_value,
+ RawData values);
+
+ // Perform an ffi call while capturing exceptions. We have to do
+ // this because we can't catch Java exceptions from C++.
+ static final Throwable hack_trampoline (RawData cif,
+ RawData method,
+ RawData ret_value,
+ RawData values)
+ {
+ try
+ {
+ hack_call (cif, method, ret_value, values);
+ }
+ catch (Throwable x)
+ {
+ return x;
+ }
+ return null;
+ }
+
public native Object invoke (Object obj, Object[] args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException;
diff --git a/libjava/java/lang/reflect/natConstructor.cc b/libjava/java/lang/reflect/natConstructor.cc
new file mode 100644
index 00000000000..1197e68c90a
--- /dev/null
+++ b/libjava/java/lang/reflect/natConstructor.cc
@@ -0,0 +1,53 @@
+// natConstructor.cc - Native code for Constructor class.
+
+/* Copyright (C) 1999, 2000 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+#include <config.h>
+
+#include <gcj/cni.h>
+#include <jvm.h>
+
+#include <java/lang/reflect/Constructor.h>
+#include <java/lang/reflect/Method.h>
+#include <java/lang/reflect/InvocationTargetException.h>
+#include <java/lang/reflect/Modifier.h>
+#include <java/lang/InstantiationException.h>
+#include <gcj/method.h>
+
+jint
+java::lang::reflect::Constructor::getModifiers ()
+{
+ return _Jv_FromReflectedConstructor (this)->accflags;
+}
+
+void
+java::lang::reflect::Constructor::getType ()
+{
+ _Jv_GetTypesFromSignature (_Jv_FromReflectedConstructor (this),
+ declaringClass,
+ &parameter_types,
+ NULL);
+}
+
+jobject
+java::lang::reflect::Constructor::newInstance (jobjectArray args)
+{
+ if (parameter_types == NULL)
+ getType ();
+
+ using namespace java::lang::reflect;
+ if (Modifier::isAbstract (declaringClass->getModifiers()))
+ JvThrow (new InstantiationException);
+
+ jmethodID meth = _Jv_FromReflectedConstructor (this);
+ // In the constructor case the return type is the type of the
+ // constructor.
+ return _Jv_CallNonvirtualMethodA (NULL, declaringClass, meth, true,
+ parameter_types, args);
+}
diff --git a/libjava/java/lang/reflect/natMethod.cc b/libjava/java/lang/reflect/natMethod.cc
index 0130ac4243f..5635b9fe33d 100644
--- a/libjava/java/lang/reflect/natMethod.cc
+++ b/libjava/java/lang/reflect/natMethod.cc
@@ -1,6 +1,6 @@
// natMethod.cc - Native code for Method class.
-/* Copyright (C) 1998, 1999 Cygnus Solutions
+/* Copyright (C) 1998, 1999, 2000 Cygnus Solutions
This file is part of libgcj.
@@ -8,14 +8,13 @@ This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
-// This is about 90% done. Search for FIXME to see what remains.
-
#include <config.h>
#include <gcj/cni.h>
#include <jvm.h>
#include <java/lang/reflect/Method.h>
+#include <java/lang/reflect/Constructor.h>
#include <java/lang/reflect/InvocationTargetException.h>
#include <java/lang/reflect/Modifier.h>
@@ -32,14 +31,15 @@ details. */
#include <java/lang/NullPointerException.h>
#include <java/lang/Class.h>
#include <gcj/method.h>
+#include <gnu/gcj/RawData.h>
+#define ObjectClass _CL_Q34java4lang6Object
+extern java::lang::Class ObjectClass;
#define ClassClass _CL_Q34java4lang5Class
extern java::lang::Class ClassClass;
#include <stdlib.h>
-#if 0
-
#include <ffi.h>
#define VoidClass _CL_Q34java4lang4Void
@@ -145,37 +145,225 @@ get_ffi_type (jclass klass)
return r;
}
-// FIXME: the body of this method should be a separate function so
-// that Constructor can use it too.
+// Actually perform an FFI call.
+void
+java::lang::reflect::Method::hack_call (gnu::gcj::RawData *rcif,
+ gnu::gcj::RawData *rmethod,
+ gnu::gcj::RawData *rret_value,
+ gnu::gcj::RawData *rvalues)
+{
+ ffi_cif *cif = (ffi_cif *) rcif;
+ void (*method) (...) = (void (*) (...)) rmethod;
+ void *ret_value = (void *) rret_value;
+ void **values = (void **) rvalues;
+
+ ffi_call (cif, method, ret_value, values);
+}
+
jobject
-java::lang::reflect::Method::invoke (jobject obj,
- jobjectArray args)
+java::lang::reflect::Method::invoke (jobject obj, jobjectArray args)
{
- // FIXME: we need to be a friend of Class here.
- _Jv_Method *meth = decl_class->methods[index];
- if (! java::lang::reflect::Modifier::isStatic(modifiers))
+ if (parameter_types == NULL)
+ getType ();
+
+ jmethodID meth = _Jv_FromReflectedMethod (this);
+ if (! java::lang::reflect::Modifier::isStatic(meth->accflags))
{
jclass k = obj ? obj->getClass() : NULL;
- if (! obj || ! decl_class->isAssignableFrom(k))
+ if (! obj)
JvThrow (new java::lang::NullPointerException);
+ if (! declaringClass->isAssignableFrom(k))
+ JvThrow (new java::lang::IllegalArgumentException);
// FIXME: access checks.
- meth = _Jv_LookupMethod (k, meth->name, meth->signature);
+
+ // Find the possibly overloaded method based on the runtime type
+ // of the object.
+ meth = _Jv_LookupDeclaredMethod (k, meth->name, meth->signature);
}
+ return _Jv_CallNonvirtualMethodA (obj, return_type, meth, false,
+ parameter_types, args);
+}
+
+jint
+java::lang::reflect::Method::getModifiers ()
+{
+ return _Jv_FromReflectedMethod (this)->accflags;
+}
+
+jstring
+java::lang::reflect::Method::getName ()
+{
+ if (name == NULL)
+ name = _Jv_NewStringUtf8Const (_Jv_FromReflectedMethod (this)->name);
+ return name;
+}
+
+/* Internal method to set return_type and parameter_types fields. */
+
+void
+java::lang::reflect::Method::getType ()
+{
+ _Jv_GetTypesFromSignature (_Jv_FromReflectedMethod (this),
+ declaringClass,
+ &parameter_types,
+ &return_type);
+}
+
+void
+_Jv_GetTypesFromSignature (jmethodID method,
+ jclass declaringClass,
+ JArray<jclass> **arg_types_out,
+ jclass *return_type_out)
+{
+
+ _Jv_Utf8Const* sig = method->signature;
+ java::lang::ClassLoader *loader = declaringClass->getClassLoader();
+ char *ptr = sig->data;
+ int numArgs = 0;
+ /* First just count the number of parameters. */
+ for (; ; ptr++)
+ {
+ switch (*ptr)
+ {
+ case 0:
+ case ')':
+ case 'V':
+ break;
+ case '[':
+ case '(':
+ continue;
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'S':
+ case 'I':
+ case 'J':
+ case 'Z':
+ numArgs++;
+ continue;
+ case 'L':
+ numArgs++;
+ do
+ ptr++;
+ while (*ptr != ';' && ptr[1] != '\0');
+ continue;
+ }
+ break;
+ }
+
+ JArray<jclass> *args = (JArray<jclass> *)
+ JvNewObjectArray (numArgs, &ClassClass, NULL);
+ jclass* argPtr = elements (args);
+ for (ptr = sig->data; *ptr != '\0'; ptr++)
+ {
+ int num_arrays = 0;
+ jclass type;
+ for (; *ptr == '['; ptr++)
+ num_arrays++;
+ switch (*ptr)
+ {
+ default:
+ return;
+ case ')':
+ argPtr = return_type_out;
+ continue;
+ case '(':
+ continue;
+ case 'V':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'S':
+ case 'I':
+ case 'J':
+ case 'Z':
+ type = _Jv_FindClassFromSignature(ptr, loader);
+ break;
+ case 'L':
+ type = _Jv_FindClassFromSignature(ptr, loader);
+ do
+ ptr++;
+ while (*ptr != ';' && ptr[1] != '\0');
+ break;
+ }
+
+ // FIXME: 2'nd argument should be "current loader"
+ while (--num_arrays >= 0)
+ type = _Jv_FindArrayClass (type, 0);
+ // ARGPTR can be NULL if we are processing the return value of a
+ // call from Constructor.
+ if (argPtr)
+ *argPtr++ = type;
+ }
+ *arg_types_out = args;
+}
+
+// This is a very rough analog of the JNI CallNonvirtual<type>MethodA
+// functions. It handles both Methods and Constructors, and it can
+// handle any return type. In the Constructor case, the `obj'
+// argument is unused and should be NULL; also, the `return_type' is
+// the class that the constructor will construct.
+jobject
+_Jv_CallNonvirtualMethodA (jobject obj,
+ jclass return_type,
+ jmethodID meth,
+ jboolean is_constructor,
+ JArray<jclass> *parameter_types,
+ jobjectArray args)
+{
+ JvAssert (! is_constructor || ! obj);
+ JvAssert (! is_constructor || ! return_type);
+
// FIXME: access checks.
if (parameter_types->length != args->length)
JvThrow (new java::lang::IllegalArgumentException);
+ // See whether call needs an object as the first argument. A
+ // constructor does need a `this' argument, but it is one we create.
+ jboolean needs_this = false;
+ if (is_constructor
+ || ! java::lang::reflect::Modifier::isStatic(meth->accflags))
+ needs_this = true;
+
+ int param_count = parameter_types->length;
+ if (needs_this)
+ ++param_count;
+
ffi_type *rtype = get_ffi_type (return_type);
- ffi_type **argtypes = (ffi_type **) alloca (parameter_types->length
+ ffi_type **argtypes = (ffi_type **) alloca (param_count
* sizeof (ffi_type *));
- jobject *paramelts = elements (parameter_types);
+ jclass *paramelts = elements (parameter_types);
jobject *argelts = elements (args);
+ // FIXME: at some point the compiler is going to add extra arguments
+ // to some functions. In particular we are going to do this for
+ // handling access checks in reflection. We must add these hidden
+ // arguments here.
+
+ // Special case for the `this' argument of a constructor. Note that
+ // the JDK 1.2 docs specify that the new object must be allocated
+ // before argument conversions are done.
+ if (is_constructor)
+ {
+ // FIXME: must special-case String, arrays, maybe others here.
+ obj = JvAllocObject (return_type);
+ }
+
+ int i = 0;
int size = 0;
- for (int i = 0; i < parameter_types->length; ++i)
+ if (needs_this)
+ {
+ // The `NULL' type is `Object'.
+ argtypes[i++] = get_ffi_type (NULL);
+ size += sizeof (jobject);
+ }
+
+ for (; i < param_count; ++i)
{
jclass k = argelts[i] ? argelts[i]->getClass() : NULL;
argtypes[i] = get_ffi_type (k);
@@ -196,7 +384,7 @@ java::lang::reflect::Method::invoke (jobject obj,
}
ffi_cif cif;
- if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, parameter_types->length,
+ if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, param_count,
rtype, argtypes) != FFI_OK)
{
// FIXME: throw some kind of VirtualMachineError here.
@@ -212,7 +400,14 @@ java::lang::reflect::Method::invoke (jobject obj,
Where += sizeof (Type); \
} while (0)
- for (int i = 0; i < parameter_types->length; ++i)
+ i = 0;
+ if (needs_this)
+ {
+ COPY (p, obj, jobject);
+ ++i;
+ }
+
+ for (; i < param_count; ++i)
{
java::lang::Number *num = (java::lang::Number *) paramelts[i];
if (paramelts[i] == JvPrimClass (byte))
@@ -228,7 +423,8 @@ java::lang::reflect::Method::invoke (jobject obj,
else if (paramelts[i] == JvPrimClass (double))
COPY (p, num->doubleValue(), jdouble);
else if (paramelts[i] == JvPrimClass (boolean))
- COPY (p, ((java::lang::Boolean *) argelts[i])->booleanValue(), jboolean);
+ COPY (p, ((java::lang::Boolean *) argelts[i])->booleanValue(),
+ jboolean);
else if (paramelts[i] == JvPrimClass (char))
COPY (p, ((java::lang::Character *) argelts[i])->charValue(), jchar);
else
@@ -238,11 +434,17 @@ java::lang::reflect::Method::invoke (jobject obj,
}
}
- // FIXME: exception handling.
+ // FIXME: initialize class here.
+
+ // Largest possible value. Hopefully it is aligned!
+ jdouble ret_value;
java::lang::Throwable *ex;
- jdouble ret_value; // Largest possible value. Hopefully
- // it is aligned!
- ex = TRAMP_CALL (ffi_call (&cif, meth->ncode, &ret_value, (void *) values));
+ using namespace java::lang;
+ using namespace java::lang::reflect;
+ ex = Method::hack_trampoline ((gnu::gcj::RawData *) &cif,
+ (gnu::gcj::RawData *) meth->ncode,
+ (gnu::gcj::RawData *) &ret_value,
+ (gnu::gcj::RawData *) values);
if (ex)
JvThrow (new InvocationTargetException (ex));
@@ -269,119 +471,9 @@ java::lang::reflect::Method::invoke (jobject obj,
r = NULL;
else
{
- JvAssert (! return_type->isPrimitive());
- r = VAL (java::lang::Object, jobject);
+ JvAssert (return_type == NULL || ! return_type->isPrimitive());
+ r = * (Object **) &ret_value;
}
return r;
}
-
-#else /* 0 */
-
-jobject
-java::lang::reflect::Method::invoke (jobject, jobjectArray)
-{
- JvFail ("not enabled yet");
-}
-
-#endif /* 0 */
-
-jint
-java::lang::reflect::Method::getModifiers ()
-{
- return _Jv_FromReflectedMethod (this)->accflags;
-}
-
-jstring
-java::lang::reflect::Method::getName ()
-{
- if (name == NULL)
- name = _Jv_NewStringUtf8Const (_Jv_FromReflectedMethod (this)->name);
- return name;
-}
-
-/* Internal method to set return_type and parameter_types fields. */
-
-void
-java::lang::reflect::Method::getType ()
-{
- _Jv_Utf8Const* sig = _Jv_FromReflectedMethod (this)->signature;
- java::lang::ClassLoader *loader = declaringClass->getClassLoader();
- char *ptr = sig->data;
- int numArgs = 0;
- /* First just count the number of parameters. */
- for (; ; ptr++)
- {
- switch (*ptr)
- {
- case 0:
- case ')':
- case 'V':
- break;
- case '[':
- case '(':
- continue;
- case 'B':
- case 'C':
- case 'D':
- case 'F':
- case 'S':
- case 'I':
- case 'J':
- case 'Z':
- numArgs++;
- continue;
- case 'L':
- numArgs++;
- do
- ptr++;
- while (*ptr != ';' && ptr[1] != '\0');
- continue;
- }
- break;
- }
-
- JArray<jclass> *args = (JArray<jclass> *)
- JvNewObjectArray (numArgs, &ClassClass, NULL);
- jclass* argPtr = elements (args);
- for (ptr = sig->data; *ptr != '\0'; ptr++)
- {
- int num_arrays = 0;
- jclass type;
- for (; *ptr == '['; ptr++)
- num_arrays++;
- switch (*ptr)
- {
- default:
- return;
- case ')':
- argPtr = &return_type;
- continue;
- case '(':
- continue;
- case 'V':
- case 'B':
- case 'C':
- case 'D':
- case 'F':
- case 'S':
- case 'I':
- case 'J':
- case 'Z':
- type = _Jv_FindClassFromSignature(ptr, loader);
- break;
- case 'L':
- type = _Jv_FindClassFromSignature(ptr, loader);
- do
- ptr++;
- while (*ptr != ';' && ptr[1] != '\0');
- break;
- }
-
- // FIXME: 2'nd argument should be "current loader"
- while (--num_arrays >= 0)
- type = _Jv_FindArrayClass (type, 0);
- *argPtr++ = type;
- }
- parameter_types = args;
-}
diff --git a/libjava/prims.cc b/libjava/prims.cc
index 7f73047aa9d..2a413ae3403 100644
--- a/libjava/prims.cc
+++ b/libjava/prims.cc
@@ -16,8 +16,6 @@ details. */
#include <string.h>
#include <signal.h>
-#pragma implementation "gcj/array.h"
-
#include <gcj/cni.h>
#include <jvm.h>
#include <java-signal.h>
@@ -143,6 +141,26 @@ _Jv_equal (Utf8Const* a, jstring str, jint hash)
return true;
}
+/* Like _Jv_equal, but stop after N characters. */
+jboolean
+_Jv_equaln (Utf8Const *a, jstring str, jint n)
+{
+ jint len = str->length();
+ jint i = 0;
+ jchar *sptr = _Jv_GetStringChars (str);
+ register unsigned char* ptr = (unsigned char*) a->data;
+ register unsigned char* limit = ptr + a->length;
+ for (; n-- > 0; i++, sptr++)
+ {
+ int ch = UTF8_GET (ptr, limit);
+ if (i == len)
+ return ch < 0;
+ if (ch != *sptr)
+ return false;
+ }
+ return true;
+}
+
/* Count the number of Unicode chars encoded in a given Ut8 string. */
int
_Jv_strLengthUtf8(char* str, int len)
diff --git a/libjava/resolve.cc b/libjava/resolve.cc
index 00a340d7454..e39cb9346a0 100644
--- a/libjava/resolve.cc
+++ b/libjava/resolve.cc
@@ -321,21 +321,6 @@ _Jv_ResolveField (_Jv_Field *field, java::lang::ClassLoader *loader)
}
}
-_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;
-}
-
/** FIXME: this is a terribly inefficient algorithm! It would improve
things if compiled classes to know vtable offset, and _Jv_Method had
a field for this.
diff --git a/libjava/testsuite/Makefile.in b/libjava/testsuite/Makefile.in
index 276c84cf588..25d7a3de50e 100644
--- a/libjava/testsuite/Makefile.in
+++ b/libjava/testsuite/Makefile.in
@@ -76,12 +76,14 @@ DLLTOOL = @DLLTOOL@
EH_COMMON_INCLUDE = @EH_COMMON_INCLUDE@
EXCEPTIONSPEC = @EXCEPTIONSPEC@
EXEEXT = @EXEEXT@
+FORCELIBGCCSPEC = @FORCELIBGCCSPEC@
GCDEPS = @GCDEPS@
GCINCS = @GCINCS@
GCLIBS = @GCLIBS@
GCOBJS = @GCOBJS@
GCSPEC = @GCSPEC@
LD = @LD@
+LIBDATASTARTSPEC = @LIBDATASTARTSPEC@
LIBGCJ_CFLAGS = @LIBGCJ_CFLAGS@
LIBGCJ_CXXFLAGS = @LIBGCJ_CXXFLAGS@
LIBGCJ_JAVAFLAGS = @LIBGCJ_JAVAFLAGS@
@@ -90,7 +92,6 @@ LN_S = @LN_S@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
NM = @NM@
-OBJDUMP = @OBJDUMP@
PACKAGE = @PACKAGE@
PERL = @PERL@
RANLIB = @RANLIB@
@@ -100,6 +101,7 @@ THREADINCS = @THREADINCS@
THREADLIBS = @THREADLIBS@
THREADOBJS = @THREADOBJS@
THREADSPEC = @THREADSPEC@
+USE_SYMBOL_UNDERSCORE = @USE_SYMBOL_UNDERSCORE@
VERSION = @VERSION@
ZDEPS = @ZDEPS@
ZINCS = @ZINCS@