OSDN Git Service

2000-01-04 Tom Tromey <tromey@cygnus.com>
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 4 Jan 2000 08:46:52 +0000 (08:46 +0000)
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 4 Jan 2000 08:46:52 +0000 (08:46 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@31199 138bc75d-0d04-0410-961f-82ee72b054a4

18 files changed:
libjava/ChangeLog
libjava/Makefile.am
libjava/Makefile.in
libjava/gcj/Makefile.in
libjava/gcj/array.h
libjava/gcj/method.h
libjava/include/Makefile.in
libjava/include/jvm.h
libjava/java/lang/Class.h
libjava/java/lang/Class.java
libjava/java/lang/natClass.cc
libjava/java/lang/reflect/Constructor.java
libjava/java/lang/reflect/Method.java
libjava/java/lang/reflect/natConstructor.cc [new file with mode: 0644]
libjava/java/lang/reflect/natMethod.cc
libjava/prims.cc
libjava/resolve.cc
libjava/testsuite/Makefile.in

index cfdd986..5cd39d2 100644 (file)
@@ -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
index ee5a88e..d15784d 100644 (file)
@@ -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 \
index d71f070..feb516d 100644 (file)
@@ -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 *);' \
index 7bbcec4..a149935 100644 (file)
@@ -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@
index f373359..76a75f6 100644 (file)
@@ -11,8 +11,6 @@ details.  */
 #ifndef __GCJ_ARRAY_H__
 #define __GCJ_ARRAY_H__
 
-#pragma interface
-
 #include <java/lang/Object.h>
 
 extern "Java" {
index a97ba4a..e5402a0 100644 (file)
@@ -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__ */
index d68544b..38af4a5 100644 (file)
@@ -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@
index 791cdfa..3b59b8d 100644 (file)
@@ -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__));
index c88c86e..dfdbf72 100644 (file)
@@ -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);
index f9bd59b..a304e6c 100644 (file)
@@ -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;
index 2072031..939fe38 100644 (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;
index 466c120..7815d7c 100644 (file)
@@ -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;
 }
index e0571f8..dd87816 100644 (file)
@@ -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 (file)
index 0000000..1197e68
--- /dev/null
@@ -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);
+}
index 0130ac4..5635b9f 100644 (file)
@@ -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;
-}
index 7f73047..2a413ae 100644 (file)
@@ -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)
index 00a340d..e39cb93 100644 (file)
@@ -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.
index 276c84c..25d7a3d 100644 (file)
@@ -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@