From 3141ed0fe01e5e5cd726dc6410f49a0323361d94 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 29 Nov 2005 18:34:58 +0000 Subject: [PATCH] re PR java/18278 (JNI functions cannot return a weak reference) gcc/java: PR java/18278: * expr.c (build_jni_stub): Unwrap the return value. * java-tree.h (soft_unwrapjni_node): New define. (enum java_tree_index): Added JTI_SOFT_UNWRAPJNI_NODE. * decl.c (java_init_decl_processing): Initialize soft_unwrapjni_node. libjava: PR java/18278: * testsuite/libjava.jni/pr18278.out: New file. * testsuite/libjava.jni/pr18278.c: New file. * testsuite/libjava.jni/pr18278.java: New file. * include/jvm.h (_Jv_UnwrapJNIweakReference): Declare. * jni.cc (_Jv_UnwrapJNIweakReference): New function. (call): Unwrap return value if needed. From-SVN: r107676 --- gcc/java/ChangeLog | 9 +++++++++ gcc/java/decl.c | 6 ++++++ gcc/java/expr.c | 13 +++++++++++-- gcc/java/java-tree.h | 3 +++ libjava/ChangeLog | 10 ++++++++++ libjava/include/jvm.h | 2 ++ libjava/jni.cc | 13 +++++++++++++ libjava/testsuite/libjava.jni/pr18278.c | 10 ++++++++++ libjava/testsuite/libjava.jni/pr18278.java | 13 +++++++++++++ libjava/testsuite/libjava.jni/pr18278.out | 2 ++ 10 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 libjava/testsuite/libjava.jni/pr18278.c create mode 100644 libjava/testsuite/libjava.jni/pr18278.java create mode 100644 libjava/testsuite/libjava.jni/pr18278.out diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 60a0aef353d..a8309728abc 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,12 @@ +2005-11-28 Tom Tromey + + PR java/18278: + * expr.c (build_jni_stub): Unwrap the return value. + * java-tree.h (soft_unwrapjni_node): New define. + (enum java_tree_index): Added JTI_SOFT_UNWRAPJNI_NODE. + * decl.c (java_init_decl_processing): Initialize + soft_unwrapjni_node. + 2005-11-24 Bryce McKinlay * gcj.texi (gij options): Add -Xss documentation. diff --git a/gcc/java/decl.c b/gcc/java/decl.c index de8f9ada3e9..21488ff5354 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -1169,6 +1169,12 @@ java_init_decl_processing (void) build_function_type (void_type_node, t), 0, NOT_BUILT_IN, NULL, NULL_TREE); + t = tree_cons (NULL_TREE, object_ptr_type_node, endlink); + soft_unwrapjni_node + = builtin_function ("_Jv_UnwrapJNIweakReference", + build_function_type (object_ptr_type_node, t), + 0, NOT_BUILT_IN, NULL, NULL_TREE); + t = tree_cons (NULL_TREE, int_type_node, tree_cons (NULL_TREE, int_type_node, endlink)); soft_idiv_node diff --git a/gcc/java/expr.c b/gcc/java/expr.c index a21e1513d6e..4c2f3f48b89 100644 --- a/gcc/java/expr.c +++ b/gcc/java/expr.c @@ -2558,8 +2558,17 @@ build_jni_stub (tree method) /* If the JNI call returned a result, capture it here. If we had to unwrap JNI object results, we would do that here. */ if (res_var != NULL_TREE) - call = build2 (MODIFY_EXPR, TREE_TYPE (TREE_TYPE (method)), - res_var, call); + { + /* If the call returns an object, it may return a JNI weak + reference, in which case we must unwrap it. */ + if (! JPRIMITIVE_TYPE_P (TREE_TYPE (TREE_TYPE (method)))) + call = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (method)), + build_address_of (soft_unwrapjni_node), + build_tree_list (NULL_TREE, call), + NULL_TREE); + call = build2 (MODIFY_EXPR, TREE_TYPE (TREE_TYPE (method)), + res_var, call); + } TREE_SIDE_EFFECTS (call) = 1; CAN_COMPLETE_NORMALLY (call) = 1; diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index 658da38d39a..d3371318960 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -394,6 +394,7 @@ enum java_tree_index JTI_SOFT_LOOKUPJNIMETHOD_NODE, JTI_SOFT_GETJNIENVNEWFRAME_NODE, JTI_SOFT_JNIPOPSYSTEMFRAME_NODE, + JTI_SOFT_UNWRAPJNI_NODE, JTI_SOFT_FMOD_NODE, JTI_SOFT_IDIV_NODE, JTI_SOFT_IREM_NODE, @@ -663,6 +664,8 @@ extern GTY(()) tree java_global_trees[JTI_MAX]; java_global_trees[JTI_SOFT_GETJNIENVNEWFRAME_NODE] #define soft_jnipopsystemframe_node \ java_global_trees[JTI_SOFT_JNIPOPSYSTEMFRAME_NODE] +#define soft_unwrapjni_node \ + java_global_trees[JTI_SOFT_UNWRAPJNI_NODE] #define soft_fmod_node \ java_global_trees[JTI_SOFT_FMOD_NODE] #define soft_idiv_node \ diff --git a/libjava/ChangeLog b/libjava/ChangeLog index d303755736f..2d88d05c1c2 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,13 @@ +2005-11-28 Tom Tromey + + PR java/18278: + * testsuite/libjava.jni/pr18278.out: New file. + * testsuite/libjava.jni/pr18278.c: New file. + * testsuite/libjava.jni/pr18278.java: New file. + * include/jvm.h (_Jv_UnwrapJNIweakReference): Declare. + * jni.cc (_Jv_UnwrapJNIweakReference): New function. + (call): Unwrap return value if needed. + 2005-11-25 Mark Wielaard * standard.omit.in: Remove javax/rmi, org/omg, gnu/CORBA and diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h index fc104d695f8..8d3405947d2 100644 --- a/libjava/include/jvm.h +++ b/libjava/include/jvm.h @@ -459,6 +459,8 @@ extern "C" void _Jv_RegisterClasses_Counted (const jclass *classes, extern "C" void _Jv_RegisterResource (void *vptr); extern void _Jv_UnregisterClass (_Jv_Utf8Const*, java::lang::ClassLoader*); +extern "C" jobject _Jv_UnwrapJNIweakReference (jobject); + extern jclass _Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader); extern jclass _Jv_FindClassFromSignature (char *, diff --git a/libjava/jni.cc b/libjava/jni.cc index 13bb12cf5dd..fd827065718 100644 --- a/libjava/jni.cc +++ b/libjava/jni.cc @@ -226,6 +226,12 @@ unwrap (T *obj) return reinterpret_cast (wr->get ()); } +jobject +_Jv_UnwrapJNIweakReference (jobject obj) +{ + return unwrap (obj); +} + static jobject JNICALL @@ -2304,6 +2310,13 @@ _Jv_JNIMethod::call (ffi_cif *, void *ret, ffi_raw *args, void *__this) ret, real_args); #endif + // We might need to unwrap a JNI weak reference here. + if (_this->jni_cif.rtype == &ffi_type_pointer) + { + _Jv_value *val = (_Jv_value *) ret; + val->object_value = unwrap (val->object_value); + } + if (sync != NULL) _Jv_MonitorExit (sync); diff --git a/libjava/testsuite/libjava.jni/pr18278.c b/libjava/testsuite/libjava.jni/pr18278.c new file mode 100644 index 00000000000..7ca73a43062 --- /dev/null +++ b/libjava/testsuite/libjava.jni/pr18278.c @@ -0,0 +1,10 @@ +#include +#include + +#include "pr18278.h" + +jobject Java_pr18278_weakRef(JNIEnv *env, jclass cls, jobject data) +{ + jobject r = (* env)->NewWeakGlobalRef(env, data); + return r; +} diff --git a/libjava/testsuite/libjava.jni/pr18278.java b/libjava/testsuite/libjava.jni/pr18278.java new file mode 100644 index 00000000000..8a39ddebf4d --- /dev/null +++ b/libjava/testsuite/libjava.jni/pr18278.java @@ -0,0 +1,13 @@ +public class pr18278 { + public pr18278() {} + + public static void main(String[] args) { + System.loadLibrary("pr18278"); + String bob = "Bob"; + Object o = weakRef("Bob"); + System.out.println(o); + System.out.println(bob == o); + } + + static native Object weakRef(Object o); +} diff --git a/libjava/testsuite/libjava.jni/pr18278.out b/libjava/testsuite/libjava.jni/pr18278.out new file mode 100644 index 00000000000..e01142a4a2f --- /dev/null +++ b/libjava/testsuite/libjava.jni/pr18278.out @@ -0,0 +1,2 @@ +Bob +true