This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
PATCH: libffi vs. SPARC (again)
- To: java-patches at gcc dot gnu dot org
- Subject: PATCH: libffi vs. SPARC (again)
- From: Jeff Sturm <jsturm at one-point dot com>
- Date: Wed, 14 Nov 2001 04:12:36 -0500 (EST)
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