Commit dba370a8 by David Daney Committed by David Daney

lang.opt (-freduced-reflection): New option.

	* 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
parent 492edb3a
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> 2006-03-15 Tom Tromey <tromey@redhat.com>
PR java/26638: PR java/26638:
......
/* Functions related to the Boehm garbage collector. /* 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. This file is part of GCC.
...@@ -184,7 +184,7 @@ get_boehm_type_descriptor (tree type) ...@@ -184,7 +184,7 @@ get_boehm_type_descriptor (tree type)
/* If the object is all pointers, or if the part with pointers fits /* 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 in our bitmap, then we are ok. Otherwise we have to allocate it
a different way. */ 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 /* In this case the initial part of the object is all reference
fields, and the end of the object is all non-reference fields, and the end of the object is all non-reference
...@@ -193,7 +193,12 @@ get_boehm_type_descriptor (tree type) ...@@ -193,7 +193,12 @@ get_boehm_type_descriptor (tree type)
this: this:
value = DS_LENGTH | WORDS_TO_BYTES (last_set_index + 1); value = DS_LENGTH | WORDS_TO_BYTES (last_set_index + 1);
DS_LENGTH is 0. 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; count = 0;
low = 0; low = 0;
high = 0; high = 0;
......
...@@ -1548,6 +1548,16 @@ supers_all_compiled (tree type) ...@@ -1548,6 +1548,16 @@ supers_all_compiled (tree type)
return 1; 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 void
make_class_data (tree type) make_class_data (tree type)
{ {
...@@ -1570,7 +1580,10 @@ make_class_data (tree type) ...@@ -1570,7 +1580,10 @@ make_class_data (tree type)
tree constant_pool_constructor; tree constant_pool_constructor;
tree interfaces = null_pointer_node; tree interfaces = null_pointer_node;
int interface_len = 0; int interface_len = 0;
int uses_jv_markobj = 0;
tree type_decl = TYPE_NAME (type); 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 /** Offset from start of virtual function table declaration
to where objects actually point at, following new g++ ABI. */ to where objects actually point at, following new g++ ABI. */
tree dtable_start_offset = build_int_cst (NULL_TREE, tree dtable_start_offset = build_int_cst (NULL_TREE,
...@@ -1579,6 +1592,22 @@ make_class_data (tree type) ...@@ -1579,6 +1592,22 @@ make_class_data (tree type)
this_class_addr = build_class_ref (type); this_class_addr = build_class_ref (type);
decl = TREE_OPERAND (this_class_addr, 0); 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. */ /* Build Field array. */
field = TYPE_FIELDS (type); field = TYPE_FIELDS (type);
while (field && DECL_ARTIFICIAL (field)) while (field && DECL_ARTIFICIAL (field))
...@@ -1589,9 +1618,11 @@ make_class_data (tree type) ...@@ -1589,9 +1618,11 @@ make_class_data (tree type)
{ {
if (! DECL_ARTIFICIAL (field)) if (! DECL_ARTIFICIAL (field))
{ {
tree init = make_field_value (field);
if (FIELD_STATIC (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); tree initial = DECL_INITIAL (field);
static_field_count++; static_field_count++;
static_fields = tree_cons (NULL_TREE, init, static_fields); static_fields = tree_cons (NULL_TREE, init, static_fields);
...@@ -1603,8 +1634,9 @@ make_class_data (tree type) ...@@ -1603,8 +1634,9 @@ make_class_data (tree type)
rest_of_decl_compilation (field, 1, 1); rest_of_decl_compilation (field, 1, 1);
DECL_INITIAL (field) = initial; DECL_INITIAL (field) = initial;
} }
else else if (uses_jv_markobj || !flag_reduced_reflection)
{ {
tree init = make_field_value (field);
instance_field_count++; instance_field_count++;
instance_fields = tree_cons (NULL_TREE, init, instance_fields); instance_fields = tree_cons (NULL_TREE, init, instance_fields);
} }
...@@ -1643,9 +1675,35 @@ make_class_data (tree type) ...@@ -1643,9 +1675,35 @@ make_class_data (tree type)
which we don't have a .class file. */ which we don't have a .class file. */
if (METHOD_DUMMY (method)) if (METHOD_DUMMY (method))
continue; continue;
init = make_method_value (method);
method_count++; /* Generate method reflection data if:
methods = tree_cons (NULL_TREE, init, methods);
- !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); method_array_type = build_prim_array_type (method_type_node, method_count);
methods_decl = build_decl (VAR_DECL, mangled_classname ("_MT_", type), methods_decl = build_decl (VAR_DECL, mangled_classname ("_MT_", type),
...@@ -1657,21 +1715,6 @@ make_class_data (tree type) ...@@ -1657,21 +1715,6 @@ make_class_data (tree type)
DECL_IGNORED_P (methods_decl) = 1; DECL_IGNORED_P (methods_decl) = 1;
rest_of_decl_compilation (methods_decl, 1, 0); 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) if (class_dtable_decl == NULL_TREE)
{ {
class_dtable_decl = build_dtable_decl (class_type_node); class_dtable_decl = build_dtable_decl (class_type_node);
...@@ -1781,7 +1824,8 @@ make_class_data (tree type) ...@@ -1781,7 +1824,8 @@ make_class_data (tree type)
CLASS_INTERFACE (type_decl) ? null_pointer_node : super); CLASS_INTERFACE (type_decl) ? null_pointer_node : super);
PUSH_FIELD_VALUE (cons, "constants", constant_pool_constructor); PUSH_FIELD_VALUE (cons, "constants", constant_pool_constructor);
PUSH_FIELD_VALUE (cons, "methods", 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", PUSH_FIELD_VALUE (cons, "method_count",
build_int_cst (NULL_TREE, method_count)); build_int_cst (NULL_TREE, method_count));
......
...@@ -546,6 +546,28 @@ This is convenient, as it means that things like ...@@ -546,6 +546,28 @@ This is convenient, as it means that things like
@code{Class.forName()} will search @samp{CLASSPATH} to find the @code{Class.forName()} will search @samp{CLASSPATH} to find the
desired class. 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 @end table
......
...@@ -215,6 +215,9 @@ extern int flag_indirect_dispatch; ...@@ -215,6 +215,9 @@ extern int flag_indirect_dispatch;
/* When zero, don't generate runtime array store checks. */ /* When zero, don't generate runtime array store checks. */
extern int flag_store_check; 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. */ /* Encoding used for source files. */
extern const char *current_encoding; extern const char *current_encoding;
......
...@@ -608,6 +608,15 @@ java_post_options (const char **pfilename) ...@@ -608,6 +608,15 @@ java_post_options (const char **pfilename)
if (! flag_indirect_dispatch) if (! flag_indirect_dispatch)
flag_verify_invocations = true; 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. */ /* Open input file. */
if (filename == 0 || !strcmp (filename, "-")) if (filename == 0 || !strcmp (filename, "-"))
......
...@@ -164,6 +164,10 @@ Enable optimization of static class initialization code ...@@ -164,6 +164,10 @@ Enable optimization of static class initialization code
foutput-class-dir= foutput-class-dir=
Java Joined RejectNegative Java Joined RejectNegative
freduced-reflection
Java Var(flag_reduced_reflection)
Reduce the amount of reflection meta-data generated
fstore-check fstore-check
Java Var(flag_store_check) Init(1) Java Var(flag_store_check) Init(1)
Enable assignability checks for stores into object arrays Enable assignability checks for stores into object arrays
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment