This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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: FYI: gcj/libgcj JNI and Windows


I'm checking this in to 3.3 and 3.4.

This is the most recent version of Ranjit's gcj and libgcj JNI patch.
This lets JNI work correctly on Windows.  It changes JNI method lookup
to use names as mangled on Windows (including @ + the argument size),
and it also changes gcj to know that JNI methods are stdcall.

Tom

Index: gcc/java/ChangeLog
from  Ranjit Mathew  <rmathew@hotmail.com>

	* decl.c (java_init_decl_processing): Change 
	soft_lookupjnimethod_node to reflect the change in
	signature of _Jv_LookupJNIMethod in libjava/jni.cc
	* expr.c (build_jni_stub): Calculate and pass the size
	on the stack of the arguments to a JNI function. Use
	new target macro MODIFY_JNI_METHOD_CALL to allow a 
	target to modify the call to a JNI method.

Index: gcc/java/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/decl.c,v
retrieving revision 1.139.2.1
diff -u -r1.139.2.1 decl.c
--- gcc/java/decl.c 14 Jan 2003 20:30:27 -0000 1.139.2.1
+++ gcc/java/decl.c 12 Feb 2003 23:33:08 -0000
@@ -883,7 +883,9 @@
 
   t = tree_cons (NULL_TREE, object_ptr_type_node,
 		 tree_cons (NULL_TREE, ptr_type_node,
-			    tree_cons (NULL_TREE, ptr_type_node, endlink)));
+			    tree_cons (NULL_TREE, ptr_type_node, 
+			               tree_cons (NULL_TREE, int_type_node, 
+				                  endlink))));
   soft_lookupjnimethod_node
     = builtin_function ("_Jv_LookupJNIMethod",
 			build_function_type (ptr_type_node, t),
Index: gcc/java/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/expr.c,v
retrieving revision 1.153.2.1
diff -u -r1.153.2.1 expr.c
--- gcc/java/expr.c 3 Jan 2003 23:10:05 -0000 1.153.2.1
+++ gcc/java/expr.c 12 Feb 2003 23:33:10 -0000
@@ -2171,6 +2171,8 @@
   tree method_args, res_type;
   tree meth_var;
 
+  int args_size = 0;
+
   tree klass = DECL_CONTEXT (method);
   int from_class = ! CLASS_FROM_SOURCE_P (klass);
   klass = build_class_ref (klass);
@@ -2232,7 +2234,16 @@
      special way, we would do that here.  */
   args = NULL_TREE;
   for (tem = method_args; tem != NULL_TREE; tem = TREE_CHAIN (tem))
-    args = tree_cons (NULL_TREE, tem, args);
+    {
+      int arg_bits = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (tem)));
+#ifdef PARM_BOUNDARY
+      arg_bits = (((arg_bits + PARM_BOUNDARY - 1) / PARM_BOUNDARY)
+                  * PARM_BOUNDARY);
+#endif
+      args_size += (arg_bits / BITS_PER_UNIT);
+
+      args = tree_cons (NULL_TREE, tem, args);
+    }
   args = nreverse (args);
   arg_types = TYPE_ARG_TYPES (TREE_TYPE (method));
 
@@ -2241,31 +2252,38 @@
      available in the argument list.  */
   if (METHOD_STATIC (method))
     {
+      args_size += int_size_in_bytes (TREE_TYPE (klass));
       args = tree_cons (NULL_TREE, klass, args);
       arg_types = tree_cons (NULL_TREE, object_ptr_type_node, arg_types);
     }
 
   /* The JNIEnv structure is the first argument to the JNI function.  */
+  args_size += int_size_in_bytes (TREE_TYPE (env_var));
   args = tree_cons (NULL_TREE, env_var, args);
   arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
 
   /* We call _Jv_LookupJNIMethod to find the actual underlying
      function pointer.  _Jv_LookupJNIMethod will throw the appropriate
      exception if this function is not found at runtime.  */
+  tem = build_tree_list (NULL_TREE, build_int_2 (args_size, 0));
   method_sig = build_java_signature (TREE_TYPE (method));
-  lookup_arg =
-    build_tree_list (NULL_TREE,
-		     build_utf8_ref (unmangle_classname
-				     (IDENTIFIER_POINTER (method_sig),
-				      IDENTIFIER_LENGTH (method_sig))));
+  lookup_arg = tree_cons (NULL_TREE,
+                          build_utf8_ref (unmangle_classname
+                                          (IDENTIFIER_POINTER (method_sig),
+                                           IDENTIFIER_LENGTH (method_sig))), 
+                          tem);
   tem = DECL_NAME (method);
   lookup_arg
     = tree_cons (NULL_TREE, klass,
 		 tree_cons (NULL_TREE, build_utf8_ref (tem), lookup_arg));
+  
+  tem = build_function_type (TREE_TYPE (TREE_TYPE (method)), arg_types);
+
+#ifdef MODIFY_JNI_METHOD_CALL
+  tem = MODIFY_JNI_METHOD_CALL (tem);
+#endif
 
-  jni_func_type
-    = build_pointer_type (build_function_type (TREE_TYPE (TREE_TYPE (method)),
-					       arg_types));
+  jni_func_type = build_pointer_type (tem);
 
   jnifunc = build (COND_EXPR, ptr_type_node,
 		   meth_var, meth_var,
Index: libjava/ChangeLog
from  Ranjit Mathew  <rmathew@hotmail.com>

	* jni.cc (_Jv_LookupJNIMethod): Modify to accept the
	size of the arguments for a JNI function. For Win32,
	modify to search for all forms of possible exported
	names of an stdcall JNI function.
	(_Jv_JNIMethod::call): Modify to calculate the size
	of the arguments passed to a JNI function and pass
	it to _Jv_LookupJNIMethod.

Index: libjava/jni.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/jni.cc,v
retrieving revision 1.68.2.1
diff -u -r1.68.2.1 jni.cc
--- libjava/jni.cc 31 Jan 2003 22:50:28 -0000 1.68.2.1
+++ libjava/jni.cc 12 Feb 2003 23:33:24 -0000
@@ -10,6 +10,7 @@
 
 #include <config.h>
 
+#include <stdio.h>
 #include <stddef.h>
 #include <string.h>
 
@@ -2028,9 +2029,9 @@
 // This is `extern "C"' because the compiler uses it.
 extern "C" void *
 _Jv_LookupJNIMethod (jclass klass, _Jv_Utf8Const *name,
-		     _Jv_Utf8Const *signature)
+		     _Jv_Utf8Const *signature, int args_size)
 {
-  char buf[10 + 6 * (name->length + signature->length)];
+  char buf[10 + 6 * (name->length + signature->length) + 12];
   int long_start;
   void *function;
 
@@ -2050,18 +2051,72 @@
     return function;
 
   // If there was no override, then look in the symbol table.
-  mangled_name (klass, name, signature, buf, &long_start);
-  char c = buf[long_start];
-  buf[long_start] = '\0';
-  function = _Jv_FindSymbolInExecutable (buf);
+  buf[0] = '_';
+  mangled_name (klass, name, signature, buf + 1, &long_start);
+  char c = buf[long_start + 1];
+  buf[long_start + 1] = '\0';
+
+  function = _Jv_FindSymbolInExecutable (buf + 1);
+#ifdef WIN32
+  // On Win32, we use the "stdcall" calling convention (see JNICALL
+  // in jni.h).
+  // 
+  // For a function named 'fooBar' that takes 'nn' bytes as arguments,
+  // by default, MinGW GCC exports it as 'fooBar@nn', MSVC exports it
+  // as '_fooBar@nn' and Borland C exports it as 'fooBar'. We try to
+  // take care of all these variations here.
+
+  char asz_buf[12];    /* '@' + '2147483647' (32-bit INT_MAX) + '\0' */
+  char long_nm_sv[11]; /* Ditto, except for the '\0'. */
+
   if (function == NULL)
     {
-      buf[long_start] = c;
+      // We have tried searching for the 'fooBar' form (BCC) - now
+      // try the others.
+
+      // First, save the part of the long name that will be damaged
+      // by appending '@nn'.
+      memcpy (long_nm_sv, (buf + long_start + 1 + 1), sizeof (long_nm_sv));
+
+      sprintf (asz_buf, "@%d", args_size);
+      strcat (buf, asz_buf);
+
+      // Search for the '_fooBar@nn' form (MSVC).
       function = _Jv_FindSymbolInExecutable (buf);
+
+      if (function == NULL)
+        {
+          // Search for the 'fooBar@nn' form (MinGW GCC).
+          function = _Jv_FindSymbolInExecutable (buf + 1);
+        }
+    }
+#else /* WIN32 */
+  args_size;  /* Dummy statement to avoid unused parameter warning */
+#endif /* ! WIN32 */
+
+  if (function == NULL)
+    {
+      buf[long_start + 1] = c;
+#ifdef WIN32
+      // Restore the part of the long name that was damaged by 
+      // appending the '@nn'.
+      memcpy ((buf + long_start + 1 + 1), long_nm_sv, sizeof (long_nm_sv));
+#endif /* WIN32 */
+      function = _Jv_FindSymbolInExecutable (buf + 1);
       if (function == NULL)
 	{
-	  jstring str = JvNewStringUTF (name->data);
-	  throw new java::lang::UnsatisfiedLinkError (str);
+#ifdef WIN32
+          strcat (buf, asz_buf);
+          function = _Jv_FindSymbolInExecutable (buf);
+          if (function == NULL)
+            function = _Jv_FindSymbolInExecutable (buf + 1);
+
+          if (function == NULL)
+#endif /* WIN32 */
+            {
+              jstring str = JvNewStringUTF (name->data);
+              throw new java::lang::UnsatisfiedLinkError (str);
+            }
 	}
     }
 
@@ -2092,9 +2147,17 @@
     // time.
     JvSynchronize sync (global_ref_table);
     if (_this->function == NULL)
-      _this->function = _Jv_LookupJNIMethod (_this->defining_class,
-					     _this->self->name,
-					     _this->self->signature);
+      {
+        int args_size = sizeof (JNIEnv *) + _this->args_raw_size;
+
+        if (_this->self->accflags & java::lang::reflect::Modifier::STATIC)
+          args_size += sizeof (_this->defining_class);
+
+        _this->function = _Jv_LookupJNIMethod (_this->defining_class,
+                                               _this->self->name,
+                                               _this->self->signature,
+                                               args_size);
+      }
   }
 
   JvAssert (_this->args_raw_size % sizeof (ffi_raw) == 0);


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