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]

Re: Patch: PR 16923


Hi,

Here's an updated patch that exposes the initialization argument
structures to CNI and moves argument parsing into separate functions.
It also makes the -verbose parsing more precise.

make check succeeds, with one new pass and no new failures.

OK to commit?
Tom

2005-02-22  Thomas Fitzsimmons  <fitzsim@redhat.com>

	PR libgcj/16923
	* gij.cc (main): Remove last_D_option.  Dynamically allocate
	_Jv_Compiler_Properties.
	* jni.cc (JNI_CreateJavaVM): Check JNI version.  Pass args to
	_Jv_CreateJavaVM and check return value.  Move argument parsing
	code to prims.cc.
	* prims.cc (no_properties): Remove.
	(_Jv_Compiler_Properties): Initialize to NULL.
	(_Jv_Properties_Count): Initialize to 0.
	(parse_verbose_args): New function.
	(parse_init_args): New function.
	(_Jv_CreateJavaVM): Call parse_init_args.
	(_Jv_RunMain): Check return value of _Jv_CreateJavaVM.
	* gcj/cni.h (JvVMOption): New struct.
	(JvVMInitArgs): Likewise.
	* include/java-props.h (_Jv_Properties_Count): Declare.
	* java/lang/natRuntime.cc (insertSystemProperties): Use
	_Jv_Properties_Count in for loop exit condition.
	* testsuite/libjava.jni/jni.exp
	(gcj_invocation_compile_c_to_binary): New procedure.
	(gcj_invocation_test_one): Likewise.
	(gcj_jni_run): Run JNI invocation API tests.
	* testsuite/libjava.jni/invocation/PR16923.c,
	testsuite/libjava.jni/invocation/PR16923.java,
	testsuite/libjava.jni/invocation/PR16923.out: New test.

Index: gij.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gij.cc,v
retrieving revision 1.25
diff -u -r1.25 gij.cc
--- gij.cc	18 Feb 2005 20:52:14 -0000	1.25
+++ gij.cc	22 Feb 2005 05:51:45 -0000
@@ -57,7 +57,6 @@
 {
   /* We rearrange ARGV so that all the -D options appear near the
      beginning.  */
-  int last_D_option = 0;
   bool jar_mode = false;
 
   int i;
@@ -77,7 +76,12 @@
 
       if (! strncmp (arg, "-D", 2))
 	{
-	  argv[last_D_option++] = arg + 2;
+	  _Jv_Compiler_Properties = (const char**) realloc
+	    (_Jv_Compiler_Properties,
+	     (_Jv_Properties_Count + 1) * sizeof (char*));
+
+	  _Jv_Compiler_Properties[_Jv_Properties_Count++] = strdup (arg + 2);
+
 	  continue;
 	}
 
@@ -153,9 +157,6 @@
 	}
     }
 
-  argv[last_D_option] = NULL;
-  _Jv_Compiler_Properties = argv;
-
   if (argc - i < 1)
     {
       fprintf (stderr, "Usage: gij [OPTION] ... CLASS [ARGS] ...\n");
Index: jni.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/jni.cc,v
retrieving revision 1.94
diff -u -r1.94 jni.cc
--- jni.cc	14 Feb 2005 13:51:29 -0000	1.94
+++ jni.cc	22 Feb 2005 05:51:46 -0000
@@ -2498,7 +2498,14 @@
 {
   JvAssert (! the_vm);
 
-  _Jv_CreateJavaVM (NULL);
+  jint version = * (jint *) args;
+  // We only support 1.2 and 1.4.
+  if (version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4)
+    return JNI_EVERSION;
+
+  jint result = _Jv_CreateJavaVM (args);
+  if (result)
+    return result;
 
   // FIXME: synchronize
   JavaVM *nvm = (JavaVM *) _Jv_MallocUnchecked (sizeof (JavaVM));
@@ -2506,48 +2513,6 @@
     return JNI_ERR;
   nvm->functions = &_Jv_JNI_InvokeFunctions;
 
-  // Parse the arguments.
-  if (args != NULL)
-    {
-      jint version = * (jint *) args;
-      // We only support 1.2 and 1.4.
-      if (version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4)
-	return JNI_EVERSION;
-      JavaVMInitArgs *ia = reinterpret_cast<JavaVMInitArgs *> (args);
-      for (int i = 0; i < ia->nOptions; ++i)
-	{
-	  if (! strcmp (ia->options[i].optionString, "vfprintf")
-	      || ! strcmp (ia->options[i].optionString, "exit")
-	      || ! strcmp (ia->options[i].optionString, "abort"))
-	    {
-	      // We are required to recognize these, but for now we
-	      // don't handle them in any way.  FIXME.
-	      continue;
-	    }
-	  else if (! strncmp (ia->options[i].optionString,
-			      "-verbose", sizeof ("-verbose") - 1))
-	    {
-	      // We don't do anything with this option either.  We
-	      // might want to make sure the argument is valid, but we
-	      // don't really care all that much for now.
-	      continue;
-	    }
-	  else if (! strncmp (ia->options[i].optionString, "-D", 2))
-	    {
-	      // FIXME.
-	      continue;
-	    }
-	  else if (ia->ignoreUnrecognized)
-	    {
-	      if (ia->options[i].optionString[0] == '_'
-		  || ! strncmp (ia->options[i].optionString, "-X", 2))
-		continue;
-	    }
-
-	  return JNI_ERR;
-	}
-    }
-
   jint r =_Jv_JNI_AttachCurrentThread (nvm, penv, NULL);
   if (r < 0)
     return r;
Index: prims.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/prims.cc,v
retrieving revision 1.103
diff -u -r1.103 prims.cc
--- prims.cc	16 Feb 2005 04:16:06 -0000	1.103
+++ prims.cc	22 Feb 2005 05:51:46 -0000
@@ -80,10 +80,9 @@
 // functions are changed to take a size_t argument instead of jint.
 #define MAX_OBJECT_SIZE ((1<<31) - 1)
 
-static const char *no_properties[] = { NULL };
-
 // Properties set at compile time.
-const char **_Jv_Compiler_Properties = no_properties;
+const char **_Jv_Compiler_Properties = NULL;
+int _Jv_Properties_Count = 0;
 
 // The JAR file to add to the beginning of java.class.path.
 const char *_Jv_Jar_Class_Path;
@@ -909,16 +908,167 @@
   bool runtimeInitialized = false;
 }
 
+static jint
+parse_verbose_args (char* option_string,
+		    bool ignore_unrecognized)
+{
+  size_t len = sizeof ("-verbose");
+
+  if (strlen (option_string) < len)
+    return -1;
+
+  if (option_string[len] == ':'
+      && option_string[len + 1] != '\0')
+    {
+      char* verbose_args = option_string + len + 1;
+      size_t last = 0;
+
+      do
+	{
+	  if (! strncmp (verbose_args,
+			 "gc", (last = sizeof ("gc")) - 1)
+	      && (verbose_args[last] == '\0'
+		  || verbose_args[last] == ','))
+	    {
+	      // FIXME: we should add functions to boehm-gc that
+	      // toggle GC_print_stats, GC_PRINT_ADDRESS_MAP and
+	      // GC_print_back_height.
+
+	    }
+	  else if (! strncmp (verbose_args,
+			      "class",
+			      (last = sizeof ("class")) - 1)
+		   && (verbose_args[last] == '\0'
+		       || verbose_args[last] == ','))
+	    {
+	      gcj::verbose_class_flag = true;
+	    }
+	  else if (! strncmp (verbose_args, "jni",
+			      (last = sizeof ("jni")) - 1)
+		   && (verbose_args[last] == '\0'
+		       || verbose_args[last] == ','))
+	    {
+	      // FIXME: enable JNI messages.
+	    }
+	  else if (ignore_unrecognized
+		   && verbose_args[0] == 'X')
+	    {
+	      // ignore unrecognized non-standard verbose option
+	      last = 0;
+	      while (verbose_args[last] != '\0'
+		     && verbose_args[last++] != ',');
+	    }
+
+	  if (strlen (verbose_args) >= last)
+	    {
+	      if (verbose_args[last] == ',')
+		{
+		  if (verbose_args[last + 1] == '\0')
+		    // trailing comma
+		    return -1;
+		  else
+		    {
+		      verbose_args = verbose_args + last + 1;
+		      last = 0;
+		    }
+		}
+	      // here verbose_args[last] is either '\0' or
+	      // the first character in the next verbose
+	      // argument.
+	    }
+	  else
+	    // partial option
+	    return -1;
+
+	  // verbose_args[last] will be '\0' here if we're
+	  // done.
+	}
+      while (verbose_args[last] != '\0');
+    }
+  else if (option_string[len] == 'g'
+	   && option_string[len + 1] == 'c'
+	   && option_string[len + 2] == '\0')
+    {
+      // FIXME: we should add functions to boehm-gc that
+      // toggle GC_print_stats, GC_PRINT_ADDRESS_MAP and
+      // GC_print_back_height.
+      return 0;
+    }
+  else if (option_string[len] == '\0')
+    {
+      gcj::verbose_class_flag = true;
+      return 0;
+    }
+  else
+    {
+      // unrecognized option beginning with -verbose
+      return -1;
+    }
+  return 0;
+}
+
+static jint
+parse_init_args (void* vm_args)
+{
+  if (vm_args == NULL)
+    return 0;
+
+  JvVMInitArgs* ia = reinterpret_cast<JvVMInitArgs *> (vm_args);
+
+  for (int i = 0; i < ia->nOptions; ++i)
+    {
+      char* option_string = ia->options[i].optionString;
+      if (! strcmp (option_string, "vfprintf")
+	  || ! strcmp (option_string, "exit")
+	  || ! strcmp (option_string, "abort"))
+	{
+	  // FIXME: we are required to recognize these, but for
+	  // now we don't handle them in any way.
+	  continue;
+	}
+      else if (! strncmp (option_string,
+			  "-verbose", sizeof ("-verbose") - 1))
+	{
+	  jint result = parse_verbose_args (option_string,
+					    ia->ignoreUnrecognized);
+	  if (result < 0)
+	    return result;
+	}
+      else if (! strncmp (option_string, "-D", 2))
+	{
+	  _Jv_Compiler_Properties = (const char**) realloc
+	    (_Jv_Compiler_Properties,
+	     (_Jv_Properties_Count + 1) * sizeof (char*));
+
+	  _Jv_Compiler_Properties[_Jv_Properties_Count++] =
+	    strdup (option_string + 2);
+
+	  continue;
+	}
+      else if (ia->ignoreUnrecognized)
+	{
+	  if (option_string[0] == '_'
+	      || ! strncmp (option_string, "-X", 2))
+	    continue;
+	}
+    }
+  return 0;
+}
+
 jint
-_Jv_CreateJavaVM (void* /*vm_args*/)
+_Jv_CreateJavaVM (void* vm_args)
 {
   using namespace gcj;
-  
+
   if (runtimeInitialized)
     return -1;
 
   runtimeInitialized = true;
 
+  jint result = parse_init_args (vm_args);
+  if (result < 0)
+    return -1;
+
   PROCESS_GCJ_PROPERTIES;
 
   /* Threads must be initialized before the GC, so that it inherits the
@@ -1016,7 +1166,12 @@
       // is initialized.
       if (is_jar)
 	_Jv_Jar_Class_Path = strdup (name);
-      _Jv_CreateJavaVM (NULL);
+
+      if (_Jv_CreateJavaVM (NULL) < 0)
+	{
+	  fprintf (stderr, "libgcj: couldn't create virtual machine\n");
+	  exit (1);
+	}
 
       // Get the Runtime here.  We want to initialize it before searching
       // for `main'; that way it will be set up if `main' is a JNI method.
Index: gcj/cni.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gcj/cni.h,v
retrieving revision 1.14
diff -u -r1.14 cni.h
--- gcj/cni.h	12 Aug 2004 06:53:38 -0000	1.14
+++ gcj/cni.h	22 Feb 2005 05:51:46 -0000
@@ -136,4 +136,25 @@
 {
   return _Jv_DetachCurrentThread ();
 }
+
+typedef struct JvVMOption
+{
+  char* optionString;
+  void* extraInfo;
+} JvVMOption;
+
+typedef struct JvVMInitArgs
+{
+  /* For compatibility with JavaVMInitArgs */
+  jint version;
+
+  /* Number of options.  */
+  jint nOptions;
+
+  /* Options to the VM.  */
+  JvVMOption* options;
+
+  /* Whether we should ignore unrecognized options.  */
+  jboolean ignoreUnrecognized;
+} JvVMInitArgs;
 #endif /* __GCJ_CNI_H__ */
Index: include/java-props.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/java-props.h,v
retrieving revision 1.7
diff -u -r1.7 java-props.h
--- include/java-props.h	21 Aug 2000 06:05:19 -0000	1.7
+++ include/java-props.h	22 Feb 2005 05:51:46 -0000
@@ -21,6 +21,7 @@
 
 // Set to NULL-terminated list of properties set at compile time.
 extern const char **_Jv_Compiler_Properties;
+extern int _Jv_Properties_Count;
 
 // The JAR file to add to the beginning of java.class.path.
 extern const char *_Jv_Jar_Class_Path;
Index: java/lang/natRuntime.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natRuntime.cc,v
retrieving revision 1.46
diff -u -r1.46 natRuntime.cc
--- java/lang/natRuntime.cc	18 Feb 2005 23:29:44 -0000	1.46
+++ java/lang/natRuntime.cc	22 Feb 2005 05:51:46 -0000
@@ -557,7 +557,7 @@
   // `-D'.  Important: after this point, the only properties that
   // should be set are those which either the user cannot meaningfully
   // override, or which augment whatever value the user has provided.
-  for (int i = 0; _Jv_Compiler_Properties[i]; ++i)
+  for (int i = 0; i < _Jv_Properties_Count; ++i)
     {
       const char *s, *p;
       // Find the `='.
Index: testsuite/libjava.jni/jni.exp
===================================================================
RCS file: /cvs/gcc/gcc/libjava/testsuite/libjava.jni/jni.exp,v
retrieving revision 1.17
diff -u -r1.17 jni.exp
--- testsuite/libjava.jni/jni.exp	21 Dec 2004 01:01:07 -0000	1.17
+++ testsuite/libjava.jni/jni.exp	22 Feb 2005 05:51:46 -0000
@@ -181,6 +181,85 @@
   return 1
 }
 
+# Compile a single C file and produce a binary.  OPTIONS is a list of
+# options to pass to the compiler.  Returns 0 on failure, 1 on
+# success.
+proc gcj_jni_invocation_compile_c_to_binary {file {options {}}} {
+  global srcdir
+  global host_triplet
+  verbose "options: $options"
+  set options_cxx $options
+  set options ""
+
+  set filename [file tail $file]
+  set name [file rootname $filename]
+
+  # Find jni.h.
+  lappend options "additional_flags=-I$srcdir/../include"
+
+  # Append C++ options
+  lappend options "additional_flags=$options_cxx"
+
+  set x [libjava_prune_warnings \
+	   [target_compile $file $name executable $options]]
+  if {$x != ""} {
+    verbose "target_compile failed: $x" 2
+    fail "$filename compilation"
+    return 0
+  }
+
+  pass "$filename compilation"
+  return 1
+}
+
+# Do all the work for a single invocation API test.  Return 0 on
+# failure.
+proc gcj_jni_invocation_test_one {file} {
+  global runtests
+  global host_triplet
+  global INTERPRETER
+
+  # The base name.  We use it for several purposes.
+  set main [file rootname [file tail $file]]
+  if {! [runtest_file_p $runtests $main]} {
+    # Simply skip it.
+    return 1
+  }
+
+  if {! [bytecompile_file $file [pwd]]} {
+    fail "bytecompile $file"
+    # FIXME - should use `untested' on all remaining tests.
+    # But that is hard.
+    return 0
+  }
+  pass "bytecompile $file"
+
+  set cfile [file rootname $file].c
+  set cxxflags "-lgcj"
+
+  if {! [gcj_jni_invocation_compile_c_to_binary $cfile $cxxflags]} {
+    # FIXME
+    return 0
+  }
+
+  set resultfile [file rootname $file].out
+
+  if {! [gcj_invoke $main $resultfile ""]} {
+    # FIXME
+    return 0
+  }
+
+  # We purposely ignore errors here; we still want to run the other
+  # appropriate tests.
+  set errname [file rootname [file tail $file]]
+
+  # When we succeed we remove all our clutter.
+  eval gcj_cleanup [glob -nocomplain -- ${main}.*] \
+    [list $main]
+
+  return 1
+}
+
 # Run the JNI tests.
 proc gcj_jni_run {} {
   global srcdir subdir
@@ -193,6 +272,13 @@
     foreach x $srcfiles {
       gcj_jni_test_one $x
     }
+
+    # Run JNI invocation API tests
+    catch { lsort [glob -nocomplain ${srcdir}/${subdir}/invocation/*.java] } srcfiles
+
+    foreach x $srcfiles {
+      gcj_jni_invocation_test_one $x
+    }
   } else {
     verbose "JNI tests not run in cross-compilation environment"
   }
Index: testsuite/libjava.jni/invocation/PR16923.c
===================================================================
RCS file: testsuite/libjava.jni/invocation/PR16923.c
diff -N testsuite/libjava.jni/invocation/PR16923.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/libjava.jni/invocation/PR16923.c	22 Feb 2005 05:51:46 -0000
@@ -0,0 +1,43 @@
+#include <assert.h>
+#include <jni.h>
+
+union env_union
+{
+  void *void_env;
+  JNIEnv *jni_env;
+};
+
+int
+main (int argc, const char** argv)
+{
+  union env_union tmp;
+  JNIEnv* env;
+  JavaVM* jvm;
+  JavaVMInitArgs vm_args;
+  JavaVMOption options[1];
+  jclass class_id;
+  jmethodID method_id;
+  jint result;
+
+  options[0].optionString = "-DPR16923=optionReceived";
+
+  vm_args.version = JNI_VERSION_1_2;
+  vm_args.ignoreUnrecognized = JNI_TRUE;
+  vm_args.options = options;
+  vm_args.nOptions = 1;
+
+  result = JNI_CreateJavaVM (&jvm, &tmp.void_env, &vm_args);
+  assert (result >= 0);
+
+  env = tmp.jni_env;
+
+  class_id = (*env)->FindClass (env, "PR16923");
+  assert (class_id);
+
+  method_id = (*env)->GetStaticMethodID (env, class_id, "printIt", "()V");
+  assert (method_id);
+
+  (*env)->CallStaticVoidMethod (env, class_id, method_id, NULL);
+
+  return 0;
+}
Index: testsuite/libjava.jni/invocation/PR16923.java
===================================================================
RCS file: testsuite/libjava.jni/invocation/PR16923.java
diff -N testsuite/libjava.jni/invocation/PR16923.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/libjava.jni/invocation/PR16923.java	22 Feb 2005 05:51:46 -0000
@@ -0,0 +1,7 @@
+public class PR16923
+{
+  public static void printIt ()
+  {
+    System.out.println (System.getProperty ("PR16923"));
+  }
+}
Index: testsuite/libjava.jni/invocation/PR16923.out
===================================================================
RCS file: testsuite/libjava.jni/invocation/PR16923.out
diff -N testsuite/libjava.jni/invocation/PR16923.out
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/libjava.jni/invocation/PR16923.out	22 Feb 2005 05:51:46 -0000
@@ -0,0 +1 @@
+optionReceived

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