lang.opt (-freduced-reflection): New option.
authorDavid Daney <ddaney@avtrex.com>
Wed, 15 Mar 2006 19:10:23 +0000 (19:10 +0000)
committerDavid Daney <daney@gcc.gnu.org>
Wed, 15 Mar 2006 19:10:23 +0000 (19:10 +0000)
* lang.opt (-freduced-reflection): New option.
* lang.c (java_post_options): Generate an error if
-freduced-reflection used with -fjni or -findirect-dispatch.
* java-tree.h (flag_reduced_reflection): Declare new variable.
* boehm.c (get_boehm_type_descriptor): Indicate all pointers
if bitmap overflows and flag_reduced_reflection set.
* class.c (uses_jv_markobj_p): New function.
(make_class_data): Moved generation of vtable to before
reflection data, generate less reflection data if
flag_reduced_reflection set.
* gcj.texi: Document -freduced-reflection.

From-SVN: r112095

gcc/java/ChangeLog
gcc/java/boehm.c
gcc/java/class.c
gcc/java/gcj.texi
gcc/java/java-tree.h
gcc/java/lang.c
gcc/java/lang.opt

index 93d439ace1f6ed1fcf5a67e2d84d538f304f0b1a..6a0afa2eb718005a4db3f25e7256a9c1d3be918c 100644 (file)
@@ -1,3 +1,17 @@
+2006-03-15  David Daney  <ddaney@avtrex.com>
+
+       * lang.opt (-freduced-reflection): New option.
+       * lang.c (java_post_options): Generate an error if
+       -freduced-reflection used with -fjni or -findirect-dispatch.
+       * java-tree.h (flag_reduced_reflection): Declare new variable.
+       * boehm.c (get_boehm_type_descriptor): Indicate all pointers
+       if bitmap overflows and flag_reduced_reflection set.
+       * class.c (uses_jv_markobj_p): New function.
+       (make_class_data): Moved generation of vtable to before
+       reflection data, generate less reflection data if
+       flag_reduced_reflection set.
+       * gcj.texi: Document -freduced-reflection.
+
 2006-03-15  Tom Tromey  <tromey@redhat.com>
 
        PR java/26638:
index 1bfe9e5f0e404f56b3ce3e10e7047446632f8548..6ea59440471861f82c09691ac14268c3629dcb63 100644 (file)
@@ -1,5 +1,5 @@
 /* Functions related to the Boehm garbage collector.
-   Copyright (C) 2000, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2003, 2004, 2006 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -184,7 +184,7 @@ get_boehm_type_descriptor (tree type)
   /* If the object is all pointers, or if the part with pointers fits
      in our bitmap, then we are ok.  Otherwise we have to allocate it
      a different way.  */
-  if (all_bits_set != -1)
+  if (all_bits_set != -1 || (pointer_after_end && flag_reduced_reflection))
     {
       /* In this case the initial part of the object is all reference
         fields, and the end of the object is all non-reference
@@ -193,7 +193,12 @@ get_boehm_type_descriptor (tree type)
         this:
         value = DS_LENGTH | WORDS_TO_BYTES (last_set_index + 1);
         DS_LENGTH is 0.
-        WORDS_TO_BYTES shifts by log2(bytes-per-pointer).  */
+        WORDS_TO_BYTES shifts by log2(bytes-per-pointer).
+
+         In the case of flag_reduced_reflection and the bitmap would
+         overflow, we tell the gc that the object is all pointers so
+         that we don't have to emit reflection data for run time
+         marking. */
       count = 0;
       low = 0;
       high = 0;
index 6d666e362e60d84359c615a5593f55e870218801..bce16779b757610c5e417574cd6b528c677ca91c 100644 (file)
@@ -1548,6 +1548,16 @@ supers_all_compiled (tree type)
   return 1;
 }
 
+/* The forth (index of 3) element in the vtable is the GC descriptor.
+   A value of 2 indicates that the class uses _Jv_MarkObj. */
+static int
+uses_jv_markobj_p(tree dtable)
+{
+  tree v;
+  v = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (dtable), 3)->value;
+  return (2 == TREE_INT_CST_LOW (v));
+}
+
 void
 make_class_data (tree type)
 {
@@ -1570,7 +1580,10 @@ make_class_data (tree type)
   tree constant_pool_constructor;
   tree interfaces = null_pointer_node;
   int interface_len = 0;
+  int uses_jv_markobj = 0;
   tree type_decl = TYPE_NAME (type);
+  tree id_main = get_identifier("main");
+  tree id_class = get_identifier("java.lang.Class");
   /** Offset from start of virtual function table declaration
       to where objects actually point at, following new g++ ABI. */
   tree dtable_start_offset = build_int_cst (NULL_TREE,
@@ -1579,6 +1592,22 @@ make_class_data (tree type)
   this_class_addr = build_class_ref (type);
   decl = TREE_OPERAND (this_class_addr, 0);
 
+  if (supers_all_compiled (type) && ! CLASS_INTERFACE (type_decl)
+      && !flag_indirect_dispatch)
+    {
+      tree dtable = get_dispatch_table (type, this_class_addr);
+      uses_jv_markobj = uses_jv_markobj_p(dtable);
+      dtable_decl = build_dtable_decl (type);
+      DECL_INITIAL (dtable_decl) = dtable;
+      TREE_STATIC (dtable_decl) = 1;
+      DECL_ARTIFICIAL (dtable_decl) = 1;
+      DECL_IGNORED_P (dtable_decl) = 1;
+      TREE_PUBLIC (dtable_decl) = 1;
+      rest_of_decl_compilation (dtable_decl, 1, 0);
+      if (type == class_type_node)
+       class_dtable_decl = dtable_decl;
+    }
+
   /* Build Field array. */
   field = TYPE_FIELDS (type);
   while (field && DECL_ARTIFICIAL (field))
@@ -1589,9 +1618,11 @@ make_class_data (tree type)
     {
       if (! DECL_ARTIFICIAL (field))
        {
-         tree init = make_field_value (field);
          if (FIELD_STATIC (field))
            {
+              /* We must always create reflection data for static fields
+                 as it is used in the creation of the field itself. */
+              tree init = make_field_value (field);
              tree initial = DECL_INITIAL (field);
              static_field_count++;
              static_fields = tree_cons (NULL_TREE, init, static_fields);
@@ -1603,8 +1634,9 @@ make_class_data (tree type)
              rest_of_decl_compilation (field, 1, 1);
              DECL_INITIAL (field) = initial;
            }
-         else
+         else if (uses_jv_markobj || !flag_reduced_reflection)
            {
+              tree init = make_field_value (field);
              instance_field_count++;
              instance_fields = tree_cons (NULL_TREE, init, instance_fields);
            }
@@ -1643,9 +1675,35 @@ make_class_data (tree type)
         which we don't have a .class file.  */
       if (METHOD_DUMMY (method))
        continue;
-      init = make_method_value (method);
-      method_count++;
-      methods = tree_cons (NULL_TREE, init, methods);
+
+      /* Generate method reflection data if:
+
+          - !flag_reduced_reflection.
+
+          - <clinit> -- The runtime uses reflection to initialize the
+            class.
+
+          - Any method in class java.lang.Class -- Class.forName() and
+            perhaps other things require it.
+
+          - class$ -- It does not work if reflection data missing.
+
+          - main -- Reflection is used to find main(String[]) methods.
+
+          - public not static -- It is potentially part of an
+            interface.  The runtime uses reflection data to build
+            interface dispatch tables.  */
+      if (!flag_reduced_reflection
+          || DECL_CLINIT_P (method)
+          || DECL_NAME (type_decl) == id_class
+          || DECL_NAME (method) == id_main
+          || (METHOD_PUBLIC (method) && !METHOD_STATIC (method))
+          || TYPE_DOT_CLASS (type) == method)
+        {
+          init = make_method_value (method);
+          method_count++;
+          methods = tree_cons (NULL_TREE, init, methods);
+        }
     }
   method_array_type = build_prim_array_type (method_type_node, method_count);
   methods_decl = build_decl (VAR_DECL, mangled_classname ("_MT_", type),
@@ -1657,21 +1715,6 @@ make_class_data (tree type)
   DECL_IGNORED_P (methods_decl) = 1;
   rest_of_decl_compilation (methods_decl, 1, 0);
 
-  if (supers_all_compiled (type) && ! CLASS_INTERFACE (type_decl)
-      && !flag_indirect_dispatch)
-    {
-      tree dtable = get_dispatch_table (type, this_class_addr);
-      dtable_decl = build_dtable_decl (type);
-      DECL_INITIAL (dtable_decl) = dtable;
-      TREE_STATIC (dtable_decl) = 1;
-      DECL_ARTIFICIAL (dtable_decl) = 1;
-      DECL_IGNORED_P (dtable_decl) = 1;
-      TREE_PUBLIC (dtable_decl) = 1;
-      rest_of_decl_compilation (dtable_decl, 1, 0);
-      if (type == class_type_node)
-       class_dtable_decl = dtable_decl;
-    }
-
   if (class_dtable_decl == NULL_TREE)
     {
       class_dtable_decl = build_dtable_decl (class_type_node);
@@ -1781,7 +1824,8 @@ make_class_data (tree type)
                    CLASS_INTERFACE (type_decl) ? null_pointer_node : super);
   PUSH_FIELD_VALUE (cons, "constants", constant_pool_constructor);
   PUSH_FIELD_VALUE (cons, "methods",
-                   build1 (ADDR_EXPR, method_ptr_type_node, methods_decl));
+                    methods_decl == NULL_TREE ? null_pointer_node
+                   : build1 (ADDR_EXPR, method_ptr_type_node, methods_decl));
   PUSH_FIELD_VALUE (cons, "method_count",
                    build_int_cst (NULL_TREE, method_count));
 
index 84659a54bdcd5332252791df78ffcfb09bf67651..ae7bcb7532b306c8ba4515aca160c61a7549601d 100644 (file)
@@ -546,6 +546,28 @@ This is convenient, as it means that things like
 @code{Class.forName()} will search @samp{CLASSPATH} to find the
 desired class.
 
+@item -freduced-reflection
+This option causes the code generated by @command{gcj} to contain a
+reduced amount of the class meta-data used to support runtime
+reflection. The cost of this savings is the loss of
+the ability to use certain reflection capabilities of the standard
+Java runtime environment. When set all meta-data except for that
+which is needed to obtain correct runtime semantics is eliminated.
+
+For code that does not use reflection (i.e. the methods in the
+@code{java.lang.reflect} package), @code{-freduced-reflection}
+will result in proper operation with a savings in executable code size.
+
+JNI (@code{-fjni}) and the binary compatibility ABI
+(@code{-findirect-dispatch}) do not work properly without full
+reflection meta-data.  Because of this, it is an error to use these options
+with @code{-freduced-reflection}.
+
+@strong{Caution:} If there is no reflection meta-data, code that uses
+a @code{SecurityManager} may not work properly.  Also calling
+@code{Class.forName()} may fail if the calling method has no
+reflection meta-data.
+
 @end table
 
 
index d421b514a464dc760bdc6c4971a675f5dd4d4514..285945c9935ed431acc59176639a76667d0ac935 100644 (file)
@@ -215,6 +215,9 @@ extern int flag_indirect_dispatch;
 /* When zero, don't generate runtime array store checks. */
 extern int flag_store_check;
 
+/* When nonzero, generate only a limited set of class meta-data. */
+extern int flag_reduced_reflection;
+
 /* Encoding used for source files.  */
 extern const char *current_encoding;
 
index 5f9a3701fdc4c4842375346744992b2a632f0063..e1f822ea3a3115f62fb29cf681b78273a6a50877 100644 (file)
@@ -608,6 +608,15 @@ java_post_options (const char **pfilename)
   if (! flag_indirect_dispatch)
     flag_verify_invocations = true;
 
+  if (flag_reduced_reflection)
+    {
+      if (flag_indirect_dispatch)
+        error ("-findirect-dispatch is incompatible "
+               "with -freduced-reflection");
+      if (flag_jni)
+        error ("-fjni is incompatible with -freduced-reflection");
+    }
+
   /* Open input file.  */
 
   if (filename == 0 || !strcmp (filename, "-"))
index 001a4a75f9dbcabffc20d2b30bff93cb021e377e..6ffb0aadbd1e213270d87cdbebc45d868b3e2fd7 100644 (file)
@@ -164,6 +164,10 @@ Enable optimization of static class initialization code
 foutput-class-dir=
 Java Joined RejectNegative
 
+freduced-reflection
+Java Var(flag_reduced_reflection)
+Reduce the amount of reflection meta-data generated
+
 fstore-check
 Java Var(flag_store_check) Init(1)
 Enable assignability checks for stores into object arrays