Commit 2c80f015 by Andrew Haley Committed by Andrew Haley

re PR java/19285 (Interfaces not initialized by static field access)

2005-04-28  Andrew Haley  <aph@redhat.com>

        PR java/19285
        * java-tree.h (soft_resolvepoolentry_node): New.
        (alloc_constant_fieldref): Declare.
        * expr.c (expand_java_field_op): Don't call class_init for
        accesses to static fields with indirect dispatch.
        * builtins.c (initialize_builtins): Add "__builtin_expect".
        * decl.c (soft_resolvepoolentry_node): New variable.
        (java_init_decl_processing): Create a decl for
        "_Jv_ResolvePoolEntry".
        * class.c (build_fieldref_cache_entry): New function.
        (build_static_field_ref): Rewrite for indirect dispatch.
        * constants.c (find_name_and_type_constant_tree): New function.
        (alloc_constant_fieldref): Likewise.
        (build_constants_constructor): Handle CONSTANT_Fieldref and
        CONSTANT_NameAndType.

        PR java/21115
        * expr.c (force_evaluation_order): Convert outgoing args smaller
        than integer.

From-SVN: r99010
parent a68b179c
2005-04-28 Andrew Haley <aph@redhat.com>
PR java/19285
* java-tree.h (soft_resolvepoolentry_node): New.
(alloc_constant_fieldref): Declare.
* expr.c (expand_java_field_op): Don't call class_init for
accesses to static fields with indirect dispatch.
* builtins.c (initialize_builtins): Add "__builtin_expect".
* decl.c (soft_resolvepoolentry_node): New variable.
(java_init_decl_processing): Create a decl for
"_Jv_ResolvePoolEntry".
* class.c (build_fieldref_cache_entry): New function.
(build_static_field_ref): Rewrite for indirect dispatch.
* constants.c (find_name_and_type_constant_tree): New function.
(alloc_constant_fieldref): Likewise.
(build_constants_constructor): Handle CONSTANT_Fieldref and
CONSTANT_NameAndType.
PR java/21115
* expr.c (force_evaluation_order): Convert outgoing args smaller
than integer.
2005-04-27 Bryce McKinlay <mckinlay@redhat.com> 2005-04-27 Bryce McKinlay <mckinlay@redhat.com>
* gcj.texi (libgcj Runtime Properties): Remove obsolete * gcj.texi (libgcj Runtime Properties): Remove obsolete
......
...@@ -161,6 +161,7 @@ initialize_builtins (void) ...@@ -161,6 +161,7 @@ initialize_builtins (void)
{ {
tree double_ftype_double, double_ftype_double_double; tree double_ftype_double, double_ftype_double_double;
tree float_ftype_float, float_ftype_float_float; tree float_ftype_float, float_ftype_float_float;
tree boolean_ftype_boolean_boolean;
tree t; tree t;
int i; int i;
...@@ -216,7 +217,14 @@ initialize_builtins (void) ...@@ -216,7 +217,14 @@ initialize_builtins (void)
double_ftype_double, "_ZN4java4lang4Math4sqrtEd"); double_ftype_double, "_ZN4java4lang4Math4sqrtEd");
define_builtin (BUILT_IN_TAN, "__builtin_tan", define_builtin (BUILT_IN_TAN, "__builtin_tan",
double_ftype_double, "_ZN4java4lang4Math3tanEd"); double_ftype_double, "_ZN4java4lang4Math3tanEd");
t = tree_cons (NULL_TREE, boolean_type_node, end_params_node);
t = tree_cons (NULL_TREE, boolean_type_node, t);
boolean_ftype_boolean_boolean = build_function_type (boolean_type_node, t);
define_builtin (BUILT_IN_EXPECT, "__builtin_expect",
boolean_ftype_boolean_boolean,
"__builtin_expect");
build_common_builtin_nodes (); build_common_builtin_nodes ();
} }
......
...@@ -1037,6 +1037,31 @@ build_class_ref (tree type) ...@@ -1037,6 +1037,31 @@ build_class_ref (tree type)
return build_indirect_class_ref (type); return build_indirect_class_ref (type);
} }
/* Create a local statically allocated variable that will hold a
pointer to a static field. */
static tree
build_fieldref_cache_entry (int index, tree fdecl ATTRIBUTE_UNUSED)
{
tree decl, decl_name;
const char *name = IDENTIFIER_POINTER (mangled_classname ("_cpool_", output_class));
char *buf = alloca (strlen (name) + 20);
sprintf (buf, "%s_%d_ref", name, index);
decl_name = get_identifier (buf);
decl = IDENTIFIER_GLOBAL_VALUE (decl_name);
if (decl == NULL_TREE)
{
decl = build_decl (VAR_DECL, decl_name, ptr_type_node);
TREE_STATIC (decl) = 1;
TREE_PUBLIC (decl) = 0;
DECL_EXTERNAL (decl) = 0;
DECL_ARTIFICIAL (decl) = 1;
make_decl_rtl (decl);
pushdecl_top_level (decl);
}
return decl;
}
tree tree
build_static_field_ref (tree fdecl) build_static_field_ref (tree fdecl)
{ {
...@@ -1062,59 +1087,47 @@ build_static_field_ref (tree fdecl) ...@@ -1062,59 +1087,47 @@ build_static_field_ref (tree fdecl)
DECL_EXTERNAL (fdecl) = 1; DECL_EXTERNAL (fdecl) = 1;
make_decl_rtl (fdecl); make_decl_rtl (fdecl);
} }
return fdecl;
} }
else
if (flag_indirect_dispatch)
{ {
tree table_index /* Generate a CONSTANT_FieldRef for FDECL in the constant pool
= build_int_cst (NULL_TREE, get_symbol_table_index and a class local static variable CACHE_ENTRY, then
(fdecl, &TYPE_ATABLE_METHODS (output_class)));
tree field_address *(fdecl **)((__builtin_expect (cache_entry == null, false))
= build4 (ARRAY_REF, ? cache_entry = _Jv_ResolvePoolEntry (output_class, cpool_index)
TREE_TYPE (TREE_TYPE (TYPE_ATABLE_DECL (output_class))), : cache_entry)
TYPE_ATABLE_DECL (output_class), table_index,
NULL_TREE, NULL_TREE); This can mostly be optimized away, so that the usual path is a
field_address = convert (build_pointer_type (TREE_TYPE (fdecl)), load followed by a test and branch. _Jv_ResolvePoolEntry is
field_address); only called once for each constant pool entry.
return fold (build1 (INDIRECT_REF, TREE_TYPE (fdecl),
field_address)); There is an optimization that we don't do: at the start of a
} method, create a local copy of CACHE_ENTRY and use that instead.
else
{ */
/* Compile as:
*(FTYPE*)build_class_ref(FCLASS)->fields[INDEX].info.addr */ int cpool_index = alloc_constant_fieldref (output_class, fdecl);
tree ref = build_class_ref (fclass); tree cache_entry = build_fieldref_cache_entry (cpool_index, fdecl);
tree fld; tree test
int field_index = 0; = build3 (CALL_EXPR, boolean_type_node,
ref = build1 (INDIRECT_REF, class_type_node, ref); build_address_of (built_in_decls[BUILT_IN_EXPECT]),
ref = build3 (COMPONENT_REF, field_ptr_type_node, ref, tree_cons (NULL_TREE, build2 (EQ_EXPR, boolean_type_node,
lookup_field (&class_type_node, fields_ident), cache_entry, null_pointer_node),
NULL_TREE); build_tree_list (NULL_TREE, boolean_false_node)),
NULL_TREE);
for (fld = TYPE_FIELDS (fclass); ; fld = TREE_CHAIN (fld)) tree cpool_index_cst = build_int_cst (NULL_TREE, cpool_index);
{ tree init
if (fld == fdecl) = build3 (CALL_EXPR, ptr_type_node,
break; build_address_of (soft_resolvepoolentry_node),
if (fld == NULL_TREE) tree_cons (NULL_TREE, build_class_ref (output_class),
fatal_error ("field '%s' not found in class", build_tree_list (NULL_TREE, cpool_index_cst)),
IDENTIFIER_POINTER (DECL_NAME (fdecl))); NULL_TREE);
if (FIELD_STATIC (fld)) init = build2 (MODIFY_EXPR, ptr_type_node, cache_entry, init);
field_index++; init = build3 (COND_EXPR, ptr_type_node, test, init, cache_entry);
} init = fold_convert (build_pointer_type (TREE_TYPE (fdecl)), init);
field_index *= int_size_in_bytes (field_type_node); fdecl = build1 (INDIRECT_REF, TREE_TYPE (fdecl), init);
ref = fold (build2 (PLUS_EXPR, field_ptr_type_node, }
ref, build_int_cst (NULL_TREE, field_index))); return fdecl;
ref = build1 (INDIRECT_REF, field_type_node, ref);
ref = build3 (COMPONENT_REF, field_info_union_node,
ref, lookup_field (&field_type_node, info_ident),
NULL_TREE);
ref = build3 (COMPONENT_REF, ptr_type_node,
ref, TREE_CHAIN (TYPE_FIELDS (field_info_union_node)),
NULL_TREE);
ref = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (fdecl)), ref);
return fold (build1 (INDIRECT_REF, TREE_TYPE(fdecl), ref));
}
} }
int int
......
...@@ -356,6 +356,41 @@ alloc_name_constant (int tag, tree name) ...@@ -356,6 +356,41 @@ alloc_name_constant (int tag, tree name)
return find_tree_constant (outgoing_cpool, tag, name); return find_tree_constant (outgoing_cpool, tag, name);
} }
/* Create a constant pool entry for a name_and_type. This one has '.'
rather than '/' because it isn't going into a class file, it's
going into a compiled object. We don't use the '/' separator in
compiled objects. */
static int
find_name_and_type_constant_tree (CPool *cpool, tree name, tree type)
{
int name_index = find_utf8_constant (cpool, name);
int type_index
= find_utf8_constant (cpool,
identifier_subst (build_java_signature (type),
"", '/', '.', ""));
return find_constant1 (cpool, CONSTANT_NameAndType,
(name_index << 16) | type_index);
}
/* Look for a field ref that matches DECL in the constant pool of
CLASS.
Return the index of the entry. */
int
alloc_constant_fieldref (tree class, tree decl)
{
CPool *outgoing_cpool = cpool_for_class (class);
int class_index
= find_tree_constant (outgoing_cpool, CONSTANT_Class,
DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))));
int name_type_index
= find_name_and_type_constant_tree (outgoing_cpool, DECL_NAME (decl),
TREE_TYPE (decl));
return find_constant1 (outgoing_cpool, CONSTANT_Fieldref,
(class_index << 16) | name_type_index);
}
/* Build an identifier for the internal name of reference type TYPE. */ /* Build an identifier for the internal name of reference type TYPE. */
tree tree
...@@ -442,14 +477,33 @@ build_constants_constructor (void) ...@@ -442,14 +477,33 @@ build_constants_constructor (void)
tree data_list = NULL_TREE; tree data_list = NULL_TREE;
int i; int i;
for (i = outgoing_cpool->count; --i > 0; ) for (i = outgoing_cpool->count; --i > 0; )
{ switch (outgoing_cpool->tags[i])
tags_list {
= tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]), case CONSTANT_Fieldref:
tags_list); case CONSTANT_NameAndType:
data_list {
= tree_cons (NULL_TREE, build_utf8_ref (outgoing_cpool->data[i].t), jword temp = outgoing_cpool->data[i].w;
data_list);
} tags_list
= tree_cons (NULL_TREE,
build_int_cst (NULL_TREE, outgoing_cpool->tags[i]),
tags_list);
data_list
= tree_cons (NULL_TREE,
fold_convert (ptr_type_node,
(build_int_cst (NULL_TREE, temp))),
data_list);
}
break;
default:
tags_list
= tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]),
tags_list);
data_list
= tree_cons (NULL_TREE, build_utf8_ref (outgoing_cpool->data[i].t),
data_list);
break;
}
if (outgoing_cpool->count > 0) if (outgoing_cpool->count > 0)
{ {
tree data_decl, tags_decl, tags_type; tree data_decl, tags_decl, tags_type;
...@@ -461,7 +515,7 @@ build_constants_constructor (void) ...@@ -461,7 +515,7 @@ build_constants_constructor (void)
data_list = tree_cons (NULL_TREE, null_pointer_node, data_list); data_list = tree_cons (NULL_TREE, null_pointer_node, data_list);
data_decl = build_constant_data_ref (); data_decl = build_constant_data_ref ();
TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type), TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type);
DECL_INITIAL (data_decl) = build_constructor (TREE_TYPE (data_decl), DECL_INITIAL (data_decl) = build_constructor (TREE_TYPE (data_decl),
data_list); data_list);
DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl)); DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl));
......
...@@ -104,6 +104,9 @@ static int uniq; ...@@ -104,6 +104,9 @@ static int uniq;
static GTY(()) tree pending_local_decls; static GTY(()) tree pending_local_decls;
/* The decl for "_Jv_ResolvePoolEntry". */
tree soft_resolvepoolentry_node;
#if defined(DEBUG_JAVA_BINDING_LEVELS) #if defined(DEBUG_JAVA_BINDING_LEVELS)
int binding_depth = 0; int binding_depth = 0;
int is_class_level = 0; int is_class_level = 0;
...@@ -1015,7 +1018,13 @@ java_init_decl_processing (void) ...@@ -1015,7 +1018,13 @@ java_init_decl_processing (void)
build_function_type (void_type_node, build_function_type (void_type_node,
t), t),
0, NOT_BUILT_IN, NULL, NULL_TREE); 0, NOT_BUILT_IN, NULL, NULL_TREE);
t = tree_cons (NULL_TREE, class_ptr_type,
tree_cons (NULL_TREE, int_type_node, endlink));
soft_resolvepoolentry_node
= builtin_function ("_Jv_ResolvePoolEntry",
build_function_type (ptr_type_node, t),
0,NOT_BUILT_IN, NULL, NULL_TREE);
DECL_IS_PURE (soft_resolvepoolentry_node) = 1;
throw_node = builtin_function ("_Jv_Throw", throw_node = builtin_function ("_Jv_Throw",
build_function_type (void_type_node, t), build_function_type (void_type_node, t),
0, NOT_BUILT_IN, NULL, NULL_TREE); 0, NOT_BUILT_IN, NULL, NULL_TREE);
......
...@@ -2715,7 +2715,8 @@ expand_java_field_op (int is_static, int is_putting, int field_ref_index) ...@@ -2715,7 +2715,8 @@ expand_java_field_op (int is_static, int is_putting, int field_ref_index)
} }
field_ref = build_field_ref (field_ref, self_type, field_name); field_ref = build_field_ref (field_ref, self_type, field_name);
if (is_static) if (is_static
&& ! flag_indirect_dispatch)
field_ref = build_class_init (self_type, field_ref); field_ref = build_class_init (self_type, field_ref);
if (is_putting) if (is_putting)
{ {
...@@ -3484,7 +3485,8 @@ maybe_adjust_start_pc (struct JCF *jcf, int code_offset, ...@@ -3484,7 +3485,8 @@ maybe_adjust_start_pc (struct JCF *jcf, int code_offset,
For method invocation, we modify the arguments so that a For method invocation, we modify the arguments so that a
left-to-right order evaluation is performed. Saved expressions left-to-right order evaluation is performed. Saved expressions
will, in CALL_EXPR order, be reused when the call will be expanded. will, in CALL_EXPR order, be reused when the call will be expanded.
*/
We also promote outgoing args if needed. */
tree tree
force_evaluation_order (tree node) force_evaluation_order (tree node)
...@@ -3518,6 +3520,15 @@ force_evaluation_order (tree node) ...@@ -3518,6 +3520,15 @@ force_evaluation_order (tree node)
/* This reverses the evaluation order. This is a desired effect. */ /* This reverses the evaluation order. This is a desired effect. */
for (cmp = NULL_TREE; arg; arg = TREE_CHAIN (arg)) for (cmp = NULL_TREE; arg; arg = TREE_CHAIN (arg))
{ {
/* Promote types smaller than integer. This is required by
some ABIs. */
tree type = TREE_TYPE (TREE_VALUE (arg));
if (targetm.calls.promote_prototypes (type)
&& INTEGRAL_TYPE_P (type)
&& INT_CST_LT_UNSIGNED (TYPE_SIZE (type),
TYPE_SIZE (integer_type_node)))
TREE_VALUE (arg) = fold_convert (integer_type_node, TREE_VALUE (arg));
tree saved = save_expr (force_evaluation_order (TREE_VALUE (arg))); tree saved = save_expr (force_evaluation_order (TREE_VALUE (arg)));
cmp = (cmp == NULL_TREE ? saved : cmp = (cmp == NULL_TREE ? saved :
build2 (COMPOUND_EXPR, void_type_node, cmp, saved)); build2 (COMPOUND_EXPR, void_type_node, cmp, saved));
......
...@@ -686,6 +686,9 @@ extern GTY(()) tree java_global_trees[JTI_MAX]; ...@@ -686,6 +686,9 @@ extern GTY(()) tree java_global_trees[JTI_MAX];
#define wfl_operator \ #define wfl_operator \
java_global_trees[JTI_WFL_OPERATOR] java_global_trees[JTI_WFL_OPERATOR]
/* The decl for "_Jv_ResolvePoolEntry". */
extern GTY(()) tree soft_resolvepoolentry_node;
extern const char *cyclic_inheritance_report; extern const char *cyclic_inheritance_report;
struct lang_identifier GTY(()) struct lang_identifier GTY(())
...@@ -1285,6 +1288,7 @@ extern tree get_method_index (tree decl); ...@@ -1285,6 +1288,7 @@ extern tree get_method_index (tree decl);
extern void make_class_data (tree); extern void make_class_data (tree);
extern void register_class (void); extern void register_class (void);
extern int alloc_name_constant (int, tree); extern int alloc_name_constant (int, tree);
extern int alloc_constant_fieldref (tree, tree);
extern void emit_register_classes (tree *); extern void emit_register_classes (tree *);
extern tree emit_symbol_table (tree, tree, tree, tree, tree, int); extern tree emit_symbol_table (tree, tree, tree, tree, tree, int);
extern void lang_init_source (int); extern void lang_init_source (int);
......
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