This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
PR java/12760 [BC ABI] Re-enable fast interface dispatch
- From: Andrew Haley <aph at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org, java-patches at gcc dot gnu dot org
- Date: Wed, 8 Sep 2004 19:07:44 +0100
- Subject: PR java/12760 [BC ABI] Re-enable fast interface dispatch
This allows BC-compiled programs to use fast interface dispatch, with
full binary compatibility. It uses two atable slots for each call,
one for the interface and one for the index. Runtime patch to follow.
It's a little space inefficient in that it wastes a dummy symbol table
entry for each interface referenced. The problem here is that our
current symbol table design doesn't seem to have any way to indicate
whether we're looking for an interface or a class.
Andrew.
2004-09-08 Andrew Haley <aph@redhat.com>
* java-tree.h (get_symbol_table_index): Add new argument,
"exists".
* expr.c (build_field_ref): New argument for
get_symbol_table_index.
(build_known_method_ref): Likewise
(get_symbol_table_index): Add new argument, "exists".
(build_invokevirtual): New argument for
get_symbol_table_index.
(build_invokeinterface): Use fast method for interface dispatch.
* class.c (build_static_field_ref): New argument for
get_symbol_table_index.
(build_symbol_entry): Generate dummy entry for interface calls of
decl is NULL.
Index: class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.180.2.11
diff -p -2 -c -w -r1.180.2.11 class.c
*** class.c 3 Sep 2004 14:36:48 -0000 1.180.2.11
--- class.c 8 Sep 2004 18:05:48 -0000
*************** build_static_field_ref (tree fdecl)
*** 1095,1099 ****
tree table_index
= build_int_2 (get_symbol_table_index
! (fdecl, &TYPE_ATABLE_METHODS (output_class)), 0);
tree field_address
= build (ARRAY_REF, TREE_TYPE (TREE_TYPE (TYPE_ATABLE_DECL (output_class))),
--- 1095,1099 ----
tree table_index
= build_int_2 (get_symbol_table_index
! (fdecl, &TYPE_ATABLE_METHODS (output_class), NULL), 0);
tree field_address
= build (ARRAY_REF, TREE_TYPE (TREE_TYPE (TYPE_ATABLE_DECL (output_class))),
*************** build_symbol_entry (tree decl)
*** 2395,2398 ****
--- 2395,2400 ----
{
tree clname, name, signature, sym;
+ if (decl)
+ {
clname = build_utf8_ref (DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))));
/* ??? Constructors are given the name foo.foo all the way through
*************** build_symbol_entry (tree decl)
*** 2408,2411 ****
--- 2410,2420 ----
(IDENTIFIER_POINTER (signature),
IDENTIFIER_LENGTH (signature)));
+ }
+ else
+ {
+ clname = convert (ptr_type_node, integer_minus_one_node);
+ name = null_pointer_node;
+ signature = null_pointer_node;
+ }
START_RECORD_CONSTRUCTOR (sym, symbol_type);
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/expr.c,v
retrieving revision 1.185.2.12
diff -p -2 -c -w -r1.185.2.12 expr.c
*** expr.c 6 Sep 2004 14:05:04 -0000 1.185.2.12
--- expr.c 8 Sep 2004 18:05:49 -0000
*************** build_field_ref (tree self_value, tree s
*** 1724,1728 ****
tree otable_index =
build_int_2 (get_symbol_table_index
! (field_decl, &TYPE_OTABLE_METHODS (output_class)), 0);
tree field_offset =
build (ARRAY_REF, integer_type_node, TYPE_OTABLE_DECL (output_class),
--- 1724,1728 ----
tree otable_index =
build_int_2 (get_symbol_table_index
! (field_decl, &TYPE_OTABLE_METHODS (output_class), NULL), 0);
tree field_offset =
build (ARRAY_REF, integer_type_node, TYPE_OTABLE_DECL (output_class),
*************** build_known_method_ref (tree method, tre
*** 1999,2003 ****
tree table_index =
build_int_2 (get_symbol_table_index
! (method, &TYPE_ATABLE_METHODS (output_class)), 0);
func =
build (ARRAY_REF,
--- 1999,2003 ----
tree table_index =
build_int_2 (get_symbol_table_index
! (method, &TYPE_ATABLE_METHODS (output_class), NULL), 0);
func =
build (ARRAY_REF,
*************** invoke_build_dtable (int is_invoke_inter
*** 2078,2090 ****
/* Determine the index in SYMBOL_TABLE for a reference to the decl
T. If this decl has not been seen before, it will be added to the
! otable_methods. If it has, the existing table slot will be
! reused. */
int
! get_symbol_table_index (tree t, tree *symbol_table)
{
int i = 1;
tree method_list;
if (*symbol_table == NULL_TREE)
{
--- 2078,2095 ----
/* Determine the index in SYMBOL_TABLE for a reference to the decl
T. If this decl has not been seen before, it will be added to the
! [oa]table_methods. If it has, the existing table slot will be
! reused. If t is NULL_TREE, we're asking for an new empty slot to
! be created. *EXISTS is set to true if the slot for the symbol
! already existed before this function was called. */
int
! get_symbol_table_index (tree t, tree *symbol_table, bool *exists)
{
int i = 1;
tree method_list;
+ if (exists)
+ *exists = false;
+
if (*symbol_table == NULL_TREE)
{
*************** get_symbol_table_index (tree t, tree *sy
*** 2098,2103 ****
{
tree value = TREE_VALUE (method_list);
! if (value == t)
return i;
i++;
if (TREE_CHAIN (method_list) == NULL_TREE)
--- 2103,2112 ----
{
tree value = TREE_VALUE (method_list);
! if (t != NULL_TREE && value == t)
! {
! if (exists)
! *exists = true;
return i;
+ }
i++;
if (TREE_CHAIN (method_list) == NULL_TREE)
*************** build_invokevirtual (tree dtable, tree m
*** 2127,2131 ****
otable_index
= build_int_2 (get_symbol_table_index
! (method, &TYPE_OTABLE_METHODS (output_class)), 0);
method_index = build (ARRAY_REF, integer_type_node,
TYPE_OTABLE_DECL (output_class),
--- 2136,2140 ----
otable_index
= build_int_2 (get_symbol_table_index
! (method, &TYPE_OTABLE_METHODS (output_class), NULL), 0);
method_index = build (ARRAY_REF, integer_type_node,
TYPE_OTABLE_DECL (output_class),
*************** build_invokeinterface (tree dtable, tree
*** 2164,2171 ****
tree interface;
tree idx;
!
! /* We expand invokeinterface here. _Jv_LookupInterfaceMethod() will
! ensure that the selected method exists, is public and not
! abstract nor static. */
if (class_ident == NULL_TREE)
--- 2173,2183 ----
tree interface;
tree idx;
! #if 0
! const char *s ="org.objectweb.util.monolog.wrapper.javaLog.LevelImpl";
! if (strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (output_class))),
! s) == 0)
! fprintf (stderr, "Hello!\n");
! #endif
! /* We expand invokeinterface here. */
if (class_ident == NULL_TREE)
*************** build_invokeinterface (tree dtable, tree
*** 2184,2221 ****
if (flag_indirect_dispatch)
{
! // FIXME: We look up the interface by name every time we make an
! // interface call. There is an interface cache in the runtime
! // library, but even so this sucks.
!
! // PR 12760 says: "... the best solution would be to make the
! // "otable" for interfaces have a pair of values - interface
! // where the target method is found in addition to offset. Both
! // of these would be passed to _Jv_LookupInterfaceMethodIdx."
! // However, other Java implementations seem to resolve
! // interfaces lazily, so there is some compatibility advantage
! // in doing things this way.
!
! tree method_signature = TYPE_SIGNATURE (TREE_TYPE (method));
! tree method_name = DECL_NAME (method);
!
! lookup_arg = build_tree_list (NULL_TREE,
! (build_utf8_ref
! (unmangle_classname
! (IDENTIFIER_POINTER(method_signature),
! IDENTIFIER_LENGTH(method_signature)))));
! lookup_arg = tree_cons (NULL_TREE, dtable,
! tree_cons (NULL_TREE, build_utf8_ref (method_name),
! lookup_arg));
! return build (CALL_EXPR, ptr_type_node,
! build_address_of (soft_lookupinterfacemethodbyname_node),
! lookup_arg, NULL_TREE);
}
else
{
idx = build_int_2 (get_interface_method_index (method, interface), 0);
}
lookup_arg = tree_cons (NULL_TREE, dtable,
! tree_cons (NULL_TREE, build_class_ref (interface),
build_tree_list (NULL_TREE, idx)));
--- 2196,2226 ----
if (flag_indirect_dispatch)
{
! bool already_exists;
! int atable_index = get_symbol_table_index (method,
! &TYPE_ATABLE_METHODS (output_class),
! &already_exists);
!
! interface
! = build (ARRAY_REF,
! TREE_TYPE (TREE_TYPE (TYPE_ATABLE_DECL (output_class))),
! TYPE_ATABLE_DECL (output_class), build_int_2 (atable_index, 0));
! idx
! = build (ARRAY_REF,
! TREE_TYPE (TREE_TYPE (TYPE_ATABLE_DECL (output_class))),
! TYPE_ATABLE_DECL (output_class), build_int_2 (atable_index+1, 0));
! interface = convert (class_ptr_type, interface);
! idx = convert (integer_type_node, idx);
!
! if (! already_exists)
! get_symbol_table_index (NULL_TREE, &TYPE_ATABLE_METHODS (output_class), NULL);
}
else
{
idx = build_int_2 (get_interface_method_index (method, interface), 0);
+ interface = build_class_ref (interface);
}
lookup_arg = tree_cons (NULL_TREE, dtable,
! tree_cons (NULL_TREE, interface,
build_tree_list (NULL_TREE, idx)));
*************** build_invokeinterface (tree dtable, tree
*** 2226,2230 ****
/* Expand one of the invoke_* opcodes.
! OCPODE is the specific opcode.
METHOD_REF_INDEX is an index into the constant pool.
NARGS is the number of arguments, or -1 if not specified. */
--- 2231,2235 ----
/* Expand one of the invoke_* opcodes.
! OPCODE is the specific opcode.
METHOD_REF_INDEX is an index into the constant pool.
NARGS is the number of arguments, or -1 if not specified. */
Index: java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.197.2.7
diff -p -2 -c -w -r1.197.2.7 java-tree.h
*** java-tree.h 1 Sep 2004 13:10:48 -0000 1.197.2.7
--- java-tree.h 8 Sep 2004 18:05:49 -0000
*************** extern void finish_method (tree);
*** 1386,1390 ****
extern void java_expand_body (tree);
! extern int get_symbol_table_index (tree, tree *);
extern tree make_catch_class_record (tree, tree);
--- 1386,1390 ----
extern void java_expand_body (tree);
! extern int get_symbol_table_index (tree, tree *, bool *);
extern tree make_catch_class_record (tree, tree);