This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
Re: class initialization check overhead
- From: Jeff Sturm <jsturm at one-point dot com>
- To: Adam Megacz <gcj at lists dot megacz dot com>
- Cc: java at gcc dot gnu dot org
- Date: Fri, 25 Oct 2002 08:47:40 -0400 (EDT)
- Subject: Re: class initialization check overhead
On 24 Oct 2002, Adam Megacz wrote:
> I assume this means inlining across .java files when they are all
> compiled in a single invocation of jc1?
Yes. That, together with -fprofile-arcs/-fbranch-probabilities yields a
very favorable improvement on my code. I also tuned down the inliner
params a little.
> Care to share the patch? =)
I have many patches lumped together at the moment. Soon I'll have to see
which are suitable for submission.
(The inlining patch is not, it has serious bugs, like omitting
`synchronized' and the class init test.)
Try this:
Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/builtins.c,v
retrieving revision 1.10
diff -u -p -r1.10 builtins.c
--- builtins.c 11 Jul 2002 01:20:22 -0000 1.10
+++ builtins.c 25 Oct 2002 12:39:39 -0000
@@ -65,6 +65,7 @@ static tree abs_builtin PARAMS ((tree, t
static tree cos_builtin PARAMS ((tree, tree));
static tree sin_builtin PARAMS ((tree, tree));
static tree sqrt_builtin PARAMS ((tree, tree));
+static tree init_builtin PARAMS ((tree, tree));
static tree build_function_call_expr PARAMS ((tree, tree));
static void define_builtin PARAMS ((enum built_in_function,
@@ -105,6 +106,7 @@ static GTY(()) struct builtin_record jav
{ { "java.lang.Math" }, { "cos" }, cos_builtin },
{ { "java.lang.Math" }, { "sin" }, sin_builtin },
{ { "java.lang.Math" }, { "sqrt" }, sqrt_builtin },
+ { { "java.lang.Object" }, { "<init>" }, init_builtin },
{ { NULL }, { NULL }, NULL }
};
@@ -185,6 +187,13 @@ sqrt_builtin (method_return_type, method
if (fn == NULL_TREE)
return NULL_TREE;
return build_function_call_expr (fn, method_arguments);
+}
+
+static tree
+init_builtin (method_return_type, method_arguments)
+ tree method_return_type ATTRIBUTE_UNUSED, method_arguments;
+{
+ return empty_stmt_node;
}
Index: class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.135
diff -u -p -r1.135 class.c
--- class.c 21 Sep 2002 02:19:44 -0000 1.135
+++ class.c 25 Oct 2002 12:39:44 -0000
@@ -353,7 +353,7 @@ lookup_class (name)
{
tree decl = IDENTIFIER_CLASS_VALUE (name);
if (decl == NULL_TREE)
- decl = push_class (make_class (), name);
+ decl = push_class (make_class (), name);
return TREE_TYPE (decl);
}
@@ -639,6 +639,10 @@ add_method_1 (this_class, access_flags,
&& TREE_VALUE (TYPE_ARG_TYPES (function_type)) == void_type_node)
HAS_FINALIZER_P (this_class) = 1;
+ /* Constructors are inlining candidates. */
+ if (ID_INIT_P (name))
+ DECL_INLINE (fndecl) = 1;
+
if (access_flags & ACC_PUBLIC) METHOD_PUBLIC (fndecl) = 1;
if (access_flags & ACC_PROTECTED) METHOD_PROTECTED (fndecl) = 1;
if (access_flags & ACC_PRIVATE)
@@ -1823,6 +1827,23 @@ build_dtable_decl (type)
return build_decl (VAR_DECL,
java_mangle_vtable (&temporary_obstack, type), dtype);
+}
+
+tree
+build_dtable_ref (type)
+ tree type;
+{
+ tree dtable_decl;
+ tree dtable_start_offset = build_int_2 (2 * POINTER_SIZE / BITS_PER_UNIT, 0);
+
+ dtable_decl = build_dtable_decl (type);
+ TREE_STATIC (dtable_decl) = 1;
+ TREE_PUBLIC (dtable_decl) = 1;
+ DECL_EXTERNAL (dtable_decl) = 1;
+
+ return build (PLUS_EXPR, dtable_ptr_type,
+ build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl),
+ dtable_start_offset);
}
/* Pre-pend the TYPE_FIELDS of THIS_CLASS with a dummy FIELD_DECL for the
Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/decl.c,v
retrieving revision 1.132
diff -u -p -r1.132 decl.c
--- decl.c 21 Sep 2002 02:19:44 -0000 1.132
+++ decl.c 25 Oct 2002 12:39:48 -0000
@@ -428,7 +428,7 @@ java_init_decl_processing ()
pushdecl (build_decl (TYPE_DECL, get_identifier ("short"), short_type_node));
int_type_node = make_signed_type (32);
pushdecl (build_decl (TYPE_DECL, get_identifier ("int"), int_type_node));
- long_type_node = make_signed_type (64);
+ long_integer_type_node = long_type_node = make_signed_type (64);
pushdecl (build_decl (TYPE_DECL, get_identifier ("long"), long_type_node));
unsigned_byte_type_node = make_unsigned_type (8);
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/expr.c,v
retrieving revision 1.152
diff -u -p -r1.152 expr.c
--- expr.c 27 Sep 2002 18:27:44 -0000 1.152
+++ expr.c 25 Oct 2002 12:39:54 -0000
@@ -1201,6 +1201,21 @@ expand_java_NEW (type)
NULL_TREE));
}
+/* This returns an expression which will extract the dtable of an
+ object. */
+
+tree
+build_get_dtable (value)
+ tree value;
+{
+ tree vtable_field = lookup_field (&object_type_node,
+ get_identifier ("vtable"));
+ return build (COMPONENT_REF, dtable_ptr_type,
+ build_java_indirect_ref (object_type_node, value,
+ flag_check_references),
+ vtable_field);
+}
+
/* This returns an expression which will extract the class of an
object. */
@@ -1279,12 +1288,25 @@ build_instanceof (value, type)
}
else
{
+ tree save = save_expr (value);
expr = build (CALL_EXPR, itype,
build_address_of (soft_instanceof_node),
- tree_cons (NULL_TREE, value,
+ tree_cons (NULL_TREE, save,
build_tree_list (NULL_TREE,
build_class_ref (type))),
NULL_TREE);
+ if (optimize > 2 && ! CLASS_INTERFACE (klass))
+ {
+ expr = build (TRUTH_ORIF_EXPR, itype,
+ build (EQ_EXPR, itype,
+ build_get_class (save),
+ build_class_ref (type)),
+ expr);
+ expr = build (COND_EXPR, itype,
+ save,
+ expr,
+ boolean_false_node);
+ }
}
TREE_SIDE_EFFECTS (expr) = TREE_SIDE_EFFECTS (value);
return expr;
Index: lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/lang.c,v
retrieving revision 1.111
diff -u -p -r1.111 lang.c
--- lang.c 2 Oct 2002 18:46:45 -0000 1.111
+++ lang.c 25 Oct 2002 12:39:56 -0000
@@ -670,7 +670,7 @@ put_decl_node (node)
if (TREE_CODE (TREE_TYPE (node)) == METHOD_TYPE)
args = TREE_CHAIN (args);
put_decl_string ("(", 1);
- for ( ; args != end_params_node; args = TREE_CHAIN (args), i++)
+ for ( ; args && args != end_params_node; args = TREE_CHAIN (args), i++)
{
if (i > 0)
put_decl_string (",", 1);
Index: parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.396
diff -u -p -r1.396 parse.y
--- parse.y 21 Sep 2002 02:19:44 -0000 1.396
+++ parse.y 25 Oct 2002 12:40:29 -0000
@@ -4820,6 +4820,12 @@ finish_method_declaration (method_body)
method_body = build1 (RETURN_EXPR, void_type_node, NULL);
BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (current_function_decl)) = method_body;
+
+ /* Save the function for inlining. */
+ if (DECL_FUNCTION_BODY (current_function_decl) && flag_inline_trees)
+ DECL_SAVED_TREE (current_function_decl) =
+ BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (current_function_decl));
+
maybe_absorb_scoping_blocks ();
/* Exit function's body */
exit_block ();
@@ -5488,7 +5494,7 @@ craft_constructor (class_decl, args)
fix_method_argument_names (parm, decl);
/* Now, mark the artificial parameters. */
DECL_FUNCTION_NAP (decl) = artificial;
- DECL_FUNCTION_SYNTHETIC_CTOR (decl) = DECL_CONSTRUCTOR_P (decl) = 1;
+ DECL_INLINE (decl) = DECL_FUNCTION_SYNTHETIC_CTOR (decl) = DECL_CONSTRUCTOR_P (decl) = 1;
return decl;
}
@@ -7430,6 +7436,12 @@ end_artificial_method_body (mdecl)
we have an undefined behavior if no temporary variable is used.) */
tree b = exit_block ();
BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl)) = b;
+
+ /* Save the function for inlining. */
+ if (DECL_FUNCTION_BODY (mdecl) && flag_inline_trees)
+ DECL_SAVED_TREE (mdecl) =
+ BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl));
+
exit_block ();
}