aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/java/ChangeLog14
-rw-r--r--gcc/java/boehm.c11
-rw-r--r--gcc/java/class.c86
-rw-r--r--gcc/java/gcj.texi22
-rw-r--r--gcc/java/java-tree.h3
-rw-r--r--gcc/java/lang.c9
-rw-r--r--gcc/java/lang.opt4
7 files changed, 125 insertions, 24 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 93d439a..6a0afa2 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -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:
diff --git a/gcc/java/boehm.c b/gcc/java/boehm.c
index 1bfe9e5..6ea5944 100644
--- a/gcc/java/boehm.c
+++ b/gcc/java/boehm.c
@@ -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;
diff --git a/gcc/java/class.c b/gcc/java/class.c
index 6d666e3..bce1677 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -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));
diff --git a/gcc/java/gcj.texi b/gcc/java/gcj.texi
index 84659a54..ae7bcb7 100644
--- a/gcc/java/gcj.texi
+++ b/gcc/java/gcj.texi
@@ -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
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index d421b51..285945c 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -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;
diff --git a/gcc/java/lang.c b/gcc/java/lang.c
index 5f9a370..e1f822e 100644
--- a/gcc/java/lang.c
+++ b/gcc/java/lang.c
@@ -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, "-"))
diff --git a/gcc/java/lang.opt b/gcc/java/lang.opt
index 001a4a7..6ffb0aa 100644
--- a/gcc/java/lang.opt
+++ b/gcc/java/lang.opt
@@ -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