This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: libffi vs. SPARC (again)



I've got an updated patch to natMethod.cc that should solve the problems
reported returning boolean values on big-endian targets using reflection.

Earlier this had been reported as a possible libffi bug; after some
more investigation I noticed the following in libffi/README:

        RVALUE is a pointer to a chunk of memory that is to hold the
                result of the function call. Currently, it must be
                at least one word in size (except for the n32 version
                under Irix 6.x, which must be a pointer to an 8 byte
                aligned value (a long long). It must also be at least
                word aligned (depending on the return type, and the
                system's alignment requirements). If RTYPE is
                &ffi_type_void, this is ignored. If RVALUE is NULL,
                the return value is discarded.

It stands to reason that if the return value must be one full word, the
return type must also reflect its size.  (IMHO ffi_prep_cif should
complain if it sees e.g. rtype == FFI_TYPE_SINT8, but we ignore
ffi_prep_cif errors anyway so that wouldn't be much help.)

I'm a little concerned with the extent of data copying taking place.  A
typical call to Method.invoke() will copy its arguments twice:  once in
_Jv_CallAnyMethodA, and again in ffi_prep_args.  My application is very
demanding on reflection; this needs to be fast.  I don't see how it can
improve much given the current libffi API.  I may investigate using the
raw API here; though it is skewed for stack architectures (x86) it might
be of some value.

Tested on alphaev56-unknown-linux-gnu, sparc-unknown-linux-gnu.

2001-11-14  Jeff Sturm  <jsturm@one-point.com>

	* java/lang/reflect/natMethod.cc (get_ffi_return_type):
	New function.
	(_Jv_CallAnyMethodA): Use it.  Cast return value to narrower
	type as needed.

Index: java/lang/reflect/natMethod.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/reflect/natMethod.cc,v
retrieving revision 1.24
diff -u -p -r1.24 natMethod.cc
--- natMethod.cc	2001/10/02 13:44:32	1.24
+++ natMethod.cc	2001/11/14 07:30:09
@@ -149,6 +149,39 @@ get_ffi_type (jclass klass)
 
   return r;
 }
+
+static inline ffi_type *
+get_ffi_return_type (jclass klass)
+{
+  // A special case.
+  if (klass == NULL)
+    return &ffi_type_pointer;
+
+  ffi_type *r;
+  if (klass == JvPrimClass (byte))
+    r = &ffi_type_sint32;
+  else if (klass == JvPrimClass (short))
+    r = &ffi_type_sint32;
+  else if (klass == JvPrimClass (int))
+    r = &ffi_type_sint32;
+  else if (klass == JvPrimClass (long))
+    r = &ffi_type_sint64;
+  else if (klass == JvPrimClass (float))
+    r = &ffi_type_float;
+  else if (klass == JvPrimClass (double))
+    r = &ffi_type_double;
+  else if (klass == JvPrimClass (boolean))
+    r = &ffi_type_sint32;
+  else if (klass == JvPrimClass (char))
+    r = &ffi_type_uint32;
+  else
+    {
+      JvAssert (! klass->isPrimitive());
+      r = &ffi_type_pointer;
+    }
+
+  return r;
+}
 #endif // USE_LIBFFI
 
 jobject
@@ -347,7 +380,9 @@ _Jv_CallAnyMethodA (jobject obj,
   if (is_constructor || return_type == JvPrimClass (void))
     rtype = &ffi_type_void;
   else
-    rtype = get_ffi_type (return_type);
+    // Return type must be at least one word, so get_ffi_return_type
+    // guarantees this.
+    rtype = get_ffi_return_type (return_type);
   ffi_type **argtypes = (ffi_type **) alloca (param_count
 					      * sizeof (ffi_type *));
 
@@ -420,6 +455,8 @@ _Jv_CallAnyMethodA (jobject obj,
       p += tsize;
     }
 
+  jvalue result_word;
+
   // FIXME: initialize class here.
 
   using namespace java::lang;
@@ -429,7 +466,7 @@ _Jv_CallAnyMethodA (jobject obj,
 
   try
     {
-      ffi_call (&cif, (void (*)()) meth->ncode, result, values);
+      ffi_call (&cif, (void (*)()) meth->ncode, &result_word, values);
     }
   catch (Throwable *ex2)
     {
@@ -440,8 +477,20 @@ _Jv_CallAnyMethodA (jobject obj,
       ex = new InvocationTargetException (ex2);
     }
 
+  // Handle return type.  Constructor return values are faked, and
+  // subword return types must be narrowed to the proper jvalue element.
   if (is_constructor)
     result->l = obj;
+  else if (return_type == JvPrimClass (byte))
+    result->b = (jbyte)result_word.i;
+  else if (return_type == JvPrimClass (short))
+    result->s = (jshort)result_word.i;
+  else if (return_type == JvPrimClass (boolean))
+    result->z = (jboolean)result_word.i;
+  else if (return_type == JvPrimClass (char))
+    result->c = (jchar)result_word.i;
+  else
+    memcpy (result, &result_word, sizeof (jvalue));
 
   return ex;
 #else


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]