aboutsummaryrefslogtreecommitdiff
path: root/gcc/java/class.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/java/class.c')
-rw-r--r--gcc/java/class.c124
1 files changed, 119 insertions, 5 deletions
diff --git a/gcc/java/class.c b/gcc/java/class.c
index 5695aba..6b05435 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -58,6 +58,8 @@ static int assume_compiled PARAMS ((const char *));
static struct hash_entry *init_test_hash_newfunc PARAMS ((struct hash_entry *,
struct hash_table *,
hash_table_key));
+static tree build_method_symbols_entry PARAMS ((tree));
+
static rtx registerClass_libfunc;
static rtx registerResource_libfunc;
@@ -1276,9 +1278,16 @@ make_method_value (mdecl)
{
static int method_name_count = 0;
tree minit;
+ tree index;
tree code;
#define ACC_TRANSLATED 0x4000
int accflags = get_access_flags_from_decl (mdecl) | ACC_TRANSLATED;
+
+ if (!flag_indirect_dispatch && DECL_VINDEX (mdecl) != NULL_TREE)
+ index = DECL_VINDEX (mdecl);
+ else
+ index = integer_minus_one_node;
+
code = null_pointer_node;
if (DECL_RTL_SET_P (mdecl))
code = build1 (ADDR_EXPR, nativecode_ptr_type_node, mdecl);
@@ -1296,6 +1305,7 @@ make_method_value (mdecl)
IDENTIFIER_LENGTH(signature)))));
}
PUSH_FIELD_VALUE (minit, "accflags", build_int_2 (accflags, 0));
+ PUSH_FIELD_VALUE (minit, "index", index);
PUSH_FIELD_VALUE (minit, "ncode", code);
{
@@ -1541,7 +1551,7 @@ make_class_data (type)
rest_of_decl_compilation (methods_decl, (char*) 0, 1, 0);
if (assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl)))
- && ! CLASS_INTERFACE (type_decl))
+ && ! CLASS_INTERFACE (type_decl) && !flag_indirect_dispatch)
{
tree dtable = get_dispatch_table (type, this_class_addr);
dtable_decl = build_dtable_decl (type);
@@ -1635,7 +1645,12 @@ make_class_data (type)
PUSH_FIELD_VALUE (cons, "methods",
build1 (ADDR_EXPR, method_ptr_type_node, methods_decl));
PUSH_FIELD_VALUE (cons, "method_count", build_int_2 (method_count, 0));
- PUSH_FIELD_VALUE (cons, "vtable_method_count", TYPE_NVIRTUALS (type));
+
+ if (flag_indirect_dispatch)
+ PUSH_FIELD_VALUE (cons, "vtable_method_count", integer_minus_one_node)
+ else
+ PUSH_FIELD_VALUE (cons, "vtable_method_count", TYPE_NVIRTUALS (type));
+
PUSH_FIELD_VALUE (cons, "fields",
fields_decl == NULL_TREE ? null_pointer_node
: build1 (ADDR_EXPR, field_ptr_type_node, fields_decl));
@@ -1643,9 +1658,27 @@ make_class_data (type)
PUSH_FIELD_VALUE (cons, "field_count", build_int_2 (field_count, 0));
PUSH_FIELD_VALUE (cons, "static_field_count",
build_int_2 (static_field_count, 0));
- PUSH_FIELD_VALUE (cons, "vtable",
- dtable_decl == NULL_TREE ? null_pointer_node
- : build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl));
+
+ if (flag_indirect_dispatch)
+ PUSH_FIELD_VALUE (cons, "vtable", null_pointer_node)
+ else
+ PUSH_FIELD_VALUE (cons, "vtable",
+ dtable_decl == NULL_TREE ? null_pointer_node
+ : build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl));
+
+ if (otable_methods == NULL_TREE)
+ {
+ PUSH_FIELD_VALUE (cons, "otable", null_pointer_node);
+ PUSH_FIELD_VALUE (cons, "otable_syms", null_pointer_node);
+ }
+ else
+ {
+ PUSH_FIELD_VALUE (cons, "otable",
+ build1 (ADDR_EXPR, otable_ptr_type, otable_decl));
+ PUSH_FIELD_VALUE (cons, "otable_syms",
+ build1 (ADDR_EXPR, method_symbols_array_ptr_type,
+ otable_syms_decl));
+ }
PUSH_FIELD_VALUE (cons, "interfaces", interfaces);
PUSH_FIELD_VALUE (cons, "loader", null_pointer_node);
PUSH_FIELD_VALUE (cons, "interface_count", build_int_2 (interface_len, 0));
@@ -2160,6 +2193,87 @@ emit_register_classes ()
}
}
+/* Make a method_symbol_type (_Jv_MethodSymbol) node for METHOD. */
+
+tree
+build_method_symbols_entry (tree method)
+{
+ tree clname, name, signature, method_symbol;
+
+ clname = build_utf8_ref (DECL_NAME (TYPE_NAME (DECL_CONTEXT (method))));
+ name = build_utf8_ref (DECL_NAME (method));
+ signature = build_java_signature (TREE_TYPE (method));
+ signature = build_utf8_ref (unmangle_classname
+ (IDENTIFIER_POINTER (signature),
+ IDENTIFIER_LENGTH (signature)));
+
+ START_RECORD_CONSTRUCTOR (method_symbol, method_symbol_type);
+ PUSH_FIELD_VALUE (method_symbol, "clname", clname);
+ PUSH_FIELD_VALUE (method_symbol, "name", name);
+ PUSH_FIELD_VALUE (method_symbol, "signature", signature);
+ FINISH_RECORD_CONSTRUCTOR (method_symbol);
+ TREE_CONSTANT (method_symbol) = 1;
+
+ return method_symbol;
+}
+
+/* Emit the offset symbols table for indirect virtual dispatch. */
+
+void
+emit_offset_symbol_table ()
+{
+ tree method_list, method, table, list, null_symbol;
+ tree otable_bound, otable_array_type;
+ int index;
+
+ /* Only emit an offset table if this translation unit actually made virtual
+ calls. */
+ if (otable_methods == NULL_TREE)
+ return;
+
+ /* Build a list of _Jv_MethodSymbols for each entry in otable_methods. */
+ index = 0;
+ method_list = otable_methods;
+ list = NULL_TREE;
+ while (method_list != NULL_TREE)
+ {
+ method = TREE_VALUE (method_list);
+ list = tree_cons (NULL_TREE, build_method_symbols_entry (method), list);
+ method_list = TREE_CHAIN (method_list);
+ index++;
+ }
+
+ /* Terminate the list with a "null" entry. */
+ START_RECORD_CONSTRUCTOR (null_symbol, method_symbol_type);
+ PUSH_FIELD_VALUE (null_symbol, "clname", null_pointer_node);
+ PUSH_FIELD_VALUE (null_symbol, "name", null_pointer_node);
+ PUSH_FIELD_VALUE (null_symbol, "signature", null_pointer_node);
+ FINISH_RECORD_CONSTRUCTOR (null_symbol);
+ TREE_CONSTANT (null_symbol) = 1;
+ list = tree_cons (NULL_TREE, null_symbol, list);
+
+ /* Put the list in the right order and make it a constructor. */
+ list = nreverse (list);
+ table = build (CONSTRUCTOR, method_symbols_array_type, NULL_TREE, list);
+
+ /* Make it the initial value for otable_syms and emit the decl. */
+ DECL_INITIAL (otable_syms_decl) = table;
+ DECL_ARTIFICIAL (otable_syms_decl) = 1;
+ DECL_IGNORED_P (otable_syms_decl) = 1;
+ rest_of_decl_compilation (otable_syms_decl, NULL, 1, 0);
+
+ /* Now that its size is known, redefine otable as an uninitialized static
+ array of INDEX + 1 integers. The extra entry is used by the runtime
+ to track whether the otable has been initialized. */
+ otable_bound = build_index_type (build_int_2 (index, 0));
+ otable_array_type = build_array_type (integer_type_node, otable_bound);
+ otable_decl = build_decl (VAR_DECL, get_identifier ("otable"),
+ otable_array_type);
+ TREE_STATIC (otable_decl) = 1;
+ TREE_READONLY (otable_decl) = 1;
+ rest_of_decl_compilation (otable_decl, NULL, 1, 0);
+}
+
void
init_class_processing ()
{