diff options
author | Andrew Haley <aph@redhat.com> | 2006-04-24 15:33:16 +0000 |
---|---|---|
committer | Andrew Haley <aph@gcc.gnu.org> | 2006-04-24 15:33:16 +0000 |
commit | 621ae65dcd01b01cbf1b4723d55653c8c1c7855b (patch) | |
tree | 843ad6f8c55847b78d8168eb919c303e362e94d6 /gcc/java | |
parent | 5204d06d82d16eb89d871797cf4ff082f4fa9526 (diff) | |
download | gcc-621ae65dcd01b01cbf1b4723d55653c8c1c7855b.zip gcc-621ae65dcd01b01cbf1b4723d55653c8c1c7855b.tar.gz gcc-621ae65dcd01b01cbf1b4723d55653c8c1c7855b.tar.bz2 |
lang.c (java_init): Handle flag_indirect_classes.
2006-04-21 Andrew Haley <aph@redhat.com>
* lang.c (java_init): Handle flag_indirect_classes.
* jvgenmain.c: Use "class$$" instead of "class$".
* mangle.c (java_mangle_decl): Accept RECORD_TYPEs sw well as
DECLs.
(mangle_class_field): Special case "class$$" as well as "class$".
* constants.c (build_ref_from_constant_pool): If
flag_indirect_classes, generate a ref into the heap.
* decl.c (constants_field_decl_node,
constants_data_field_decl_node): New.
* class.c (build_static_class_ref): New.
(build_classdollar_field): Factor out from build_class_ref().
(make_field_value): Handle static fields in heap.
(make_class_data): Make sure we get a static ref to class.
Make class initializer const if flag_indirect_classes.
(register_class): Build a class_ref for initialization if
flag_indirect_classes.
(emit_indirect_register_classes): New.
2006-04-21 Andrew Haley <aph@redhat.com>
* include/execution.h (struct _Jv_CompiledEngine): Define for
compiled classes.
* java/lang/natClassLoader.cc (_Jv_RegisterClasses): Call
_Jv_RegisterLibForGc.
(_Jv_RegisterClasses_Counted): Likewise.
(_Jv_NewClassFromInitializer): New.
(_Jv_RegisterNewClasses): New.
* sources.am: Regenerate.
* boehm.cc (_Jv_GC_has_static_roots): new.
(_Jv_InitGC): Call GC_register_has_static_roots_callback.
(filename_node, find_file, _Jv_print_gc_store, new_node,
_Jv_GC_has_static_roots, _Jv_RegisterLibForGc): New.
* scripts/makemake.tcl: Add -fno-indirect-classes.
* Makefile.in: Regenerate.
* link.cc (resolve_pool_entry): Allocate constant pool.
Allocate fields.
From-SVN: r113224
Diffstat (limited to 'gcc/java')
-rw-r--r-- | gcc/java/ChangeLog | 20 | ||||
-rw-r--r-- | gcc/java/class.c | 203 | ||||
-rw-r--r-- | gcc/java/constants.c | 23 | ||||
-rw-r--r-- | gcc/java/decl.c | 8 | ||||
-rw-r--r-- | gcc/java/java-tree.h | 9 | ||||
-rw-r--r-- | gcc/java/jvgenmain.c | 10 | ||||
-rw-r--r-- | gcc/java/lang.c | 3 | ||||
-rw-r--r-- | gcc/java/lang.opt | 4 | ||||
-rw-r--r-- | gcc/java/mangle.c | 15 |
9 files changed, 247 insertions, 48 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index fe19f2c..2ce57c0 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,23 @@ +2006-04-21 Andrew Haley <aph@redhat.com> + + * lang.c (java_init): Handle flag_indirect_classes. + * jvgenmain.c: Use "class$$" instead of "class$". + * mangle.c (java_mangle_decl): Accept RECORD_TYPEs sw well as + DECLs. + (mangle_class_field): Special case "class$$" as well as "class$". + * constants.c (build_ref_from_constant_pool): If + flag_indirect_classes, generate a ref into the heap. + * decl.c (constants_field_decl_node, + constants_data_field_decl_node): New. + * class.c (build_static_class_ref): New. + (build_classdollar_field): Factor out from build_class_ref(). + (make_field_value): Handle static fields in heap. + (make_class_data): Make sure we get a static ref to class. + Make class initializer const if flag_indirect_classes. + (register_class): Build a class_ref for initialization if + flag_indirect_classes. + (emit_indirect_register_classes): New. + 2006-04-08 Kazu Hirata <kazu@codesourcery.com> * expr.c, gjavah.c: Fix comment typos. diff --git a/gcc/java/class.c b/gcc/java/class.c index a607451..fe52e67 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -953,6 +953,71 @@ build_indirect_class_ref (tree type) return convert (promote_type (class_ptr_type), cl); } +static tree +build_static_class_ref (tree type) +{ + tree decl_name, decl, ref; + + if (TYPE_SIZE (type) == error_mark_node) + return null_pointer_node; + decl_name = identifier_subst (DECL_NAME (TYPE_NAME (type)), + "", '/', '/', ".class$$"); + decl = IDENTIFIER_GLOBAL_VALUE (decl_name); + if (decl == NULL_TREE) + { + decl = build_decl (VAR_DECL, decl_name, class_type_node); + TREE_STATIC (decl) = 1; + if (! flag_indirect_classes) + TREE_PUBLIC (decl) = 1; + DECL_IGNORED_P (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + if (is_compiled_class (type) == 1) + DECL_EXTERNAL (decl) = 1; + MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); + DECL_CLASS_FIELD_P (decl) = 1; + DECL_CONTEXT (decl) = type; + + /* ??? We want to preserve the DECL_CONTEXT we set just above, + that that means not calling pushdecl_top_level. */ + IDENTIFIER_GLOBAL_VALUE (decl_name) = decl; + } + + ref = build1 (ADDR_EXPR, class_ptr_type, decl); + return ref; +} + +static tree +build_classdollar_field (tree type) +{ + tree decl_name = identifier_subst (DECL_NAME (TYPE_NAME (type)), + "", '/', '/', ".class$"); + tree decl = IDENTIFIER_GLOBAL_VALUE (decl_name); + + if (decl == NULL_TREE) + { + decl + = build_decl (VAR_DECL, decl_name, + (build_type_variant + (build_pointer_type + (build_type_variant (class_type_node, + /* const */ 1, 0)), + /* const */ 1, 0))); + TREE_STATIC (decl) = 1; + TREE_INVARIANT (decl) = 1; + TREE_CONSTANT (decl) = 1; + TREE_READONLY (decl) = 1; + TREE_PUBLIC (decl) = 1; + DECL_IGNORED_P (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); + IDENTIFIER_GLOBAL_VALUE (decl_name) = decl; + DECL_CLASS_FIELD_P (decl) = 1; + DECL_CONTEXT (decl) = type; + } + + return decl; +} + /* Build a reference to the class TYPE. Also handles primitive types and array types. */ @@ -962,7 +1027,7 @@ build_class_ref (tree type) int is_compiled = is_compiled_class (type); if (is_compiled) { - tree ref, decl_name, decl; + tree ref, decl; if (TREE_CODE (type) == POINTER_TYPE) type = TREE_TYPE (type); @@ -971,34 +1036,15 @@ build_class_ref (tree type) && TREE_CODE (type) == RECORD_TYPE) return build_indirect_class_ref (type); + if (type == output_class && flag_indirect_classes) + return build_classdollar_field (type); + if (TREE_CODE (type) == RECORD_TYPE) - { - if (TYPE_SIZE (type) == error_mark_node) - return null_pointer_node; - decl_name = identifier_subst (DECL_NAME (TYPE_NAME (type)), - "", '/', '/', ".class"); - decl = IDENTIFIER_GLOBAL_VALUE (decl_name); - if (decl == NULL_TREE) - { - decl = build_decl (VAR_DECL, decl_name, class_type_node); - TREE_STATIC (decl) = 1; - TREE_PUBLIC (decl) = 1; - DECL_IGNORED_P (decl) = 1; - DECL_ARTIFICIAL (decl) = 1; - if (is_compiled == 1) - DECL_EXTERNAL (decl) = 1; - MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); - DECL_CLASS_FIELD_P (decl) = 1; - DECL_CONTEXT (decl) = type; - - /* ??? We want to preserve the DECL_CONTEXT we set just above, - that that means not calling pushdecl_top_level. */ - IDENTIFIER_GLOBAL_VALUE (decl_name) = decl; - } - } + return build_static_class_ref (type); else { const char *name; + tree decl_name; char buffer[25]; if (flag_emit_class_files) { @@ -1296,16 +1342,22 @@ make_field_value (tree fdecl) PUSH_FIELD_VALUE (finit, "accflags", build_int_cst (NULL_TREE, flags)); PUSH_FIELD_VALUE (finit, "bsize", TYPE_SIZE_UNIT (TREE_TYPE (fdecl))); - PUSH_FIELD_VALUE - (finit, "info", - build_constructor_from_list (field_info_union_node, - build_tree_list - ((FIELD_STATIC (fdecl) - ? TREE_CHAIN (TYPE_FIELDS (field_info_union_node)) - : TYPE_FIELDS (field_info_union_node)), - (FIELD_STATIC (fdecl) - ? build_address_of (fdecl) - : byte_position (fdecl))))); + { + tree field_address = integer_zero_node; + if (! flag_indirect_classes && FIELD_STATIC (fdecl)) + field_address = build_address_of (fdecl); + + PUSH_FIELD_VALUE + (finit, "info", + build_constructor_from_list (field_info_union_node, + build_tree_list + ((FIELD_STATIC (fdecl) + ? TREE_CHAIN (TYPE_FIELDS (field_info_union_node)) + : TYPE_FIELDS (field_info_union_node)), + (FIELD_STATIC (fdecl) + ? field_address + : byte_position (fdecl))))); + } FINISH_RECORD_CONSTRUCTOR (finit); return finit; @@ -1599,7 +1651,7 @@ make_class_data (tree type) tree dtable_start_offset = build_int_cst (NULL_TREE, 2 * POINTER_SIZE / BITS_PER_UNIT); - this_class_addr = build_class_ref (type); + this_class_addr = build_static_class_ref (type); decl = TREE_OPERAND (this_class_addr, 0); if (supers_all_compiled (type) && ! CLASS_INTERFACE (type_decl) @@ -1613,7 +1665,8 @@ make_class_data (tree type) 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 (! flag_indirect_classes) + rest_of_decl_compilation (dtable_decl, 1, 0); if (type == class_type_node) class_dtable_decl = dtable_decl; } @@ -1958,8 +2011,21 @@ make_class_data (tree type) if (flag_hash_synchronization && POINTER_SIZE < 64) DECL_ALIGN (decl) = 64; + if (flag_indirect_classes) + { + TREE_READONLY (decl) = 1; + TREE_CONSTANT (DECL_INITIAL (decl)) = 1; + } + rest_of_decl_compilation (decl, 1, 0); + { + tree classdollar_field = build_classdollar_field (type); + if (!flag_indirect_classes) + DECL_INITIAL (classdollar_field) = build_static_class_ref (type); + rest_of_decl_compilation (classdollar_field, 1, 0); + } + TYPE_OTABLE_DECL (type) = NULL_TREE; TYPE_ATABLE_DECL (type) = NULL_TREE; TYPE_CTABLE_DECL (type) = NULL_TREE; @@ -2465,10 +2531,65 @@ register_class (void) if (!registered_class) registered_class = VEC_alloc (tree, gc, 8); - node = TREE_OPERAND (build_class_ref (current_class), 0); + if (flag_indirect_classes) + node = current_class; + else + node = TREE_OPERAND (build_class_ref (current_class), 0); VEC_safe_push (tree, gc, registered_class, node); } +/* Emit a function that calls _Jv_NewClassFromInitializer for every + class. */ + +static void +emit_indirect_register_classes (tree *list_p) +{ + tree klass, t, register_class_fn; + int i; + + tree init = NULL_TREE; + int size = VEC_length (tree, registered_class) * 2 + 1; + tree class_array_type + = build_prim_array_type (ptr_type_node, size); + tree cdecl = build_decl (VAR_DECL, get_identifier ("_Jv_CLS"), + class_array_type); + tree reg_class_list; + for (i = 0; VEC_iterate (tree, registered_class, i, klass); ++i) + { + init = tree_cons (NULL_TREE, + fold_convert (ptr_type_node, + build_static_class_ref (klass)), init); + init = tree_cons + (NULL_TREE, + fold_convert (ptr_type_node, + build_address_of (build_classdollar_field (klass))), + init); + } + init = tree_cons (NULL_TREE, integer_zero_node, init); + DECL_INITIAL (cdecl) = build_constructor_from_list (class_array_type, + nreverse (init)); + TREE_CONSTANT (DECL_INITIAL (cdecl)) = 1; + TREE_STATIC (cdecl) = 1; + DECL_ARTIFICIAL (cdecl) = 1; + DECL_IGNORED_P (cdecl) = 1; + TREE_READONLY (cdecl) = 1; + TREE_CONSTANT (cdecl) = 1; + rest_of_decl_compilation (cdecl, 1, 0); + reg_class_list = fold_convert (ptr_type_node, build_address_of (cdecl)); + + t = build_function_type_list (void_type_node, + build_pointer_type (ptr_type_node), NULL); + t = build_decl (FUNCTION_DECL, + get_identifier ("_Jv_RegisterNewClasses"), t); + TREE_PUBLIC (t) = 1; + DECL_EXTERNAL (t) = 1; + register_class_fn = t; + t = tree_cons (NULL, reg_class_list, NULL); + t = build_function_call_expr (register_class_fn, t); + append_to_statement_list (t, list_p); +} + + /* Emit something to register classes at start-up time. The preferred mechanism is through the .jcr section, which contain @@ -2485,6 +2606,12 @@ emit_register_classes (tree *list_p) if (registered_class == NULL) return; + if (flag_indirect_classes) + { + emit_indirect_register_classes (list_p); + return; + } + /* TARGET_USE_JCR_SECTION defaults to 1 if SUPPORTS_WEAK and TARGET_ASM_NAMED_SECTION, else 0. Some targets meet those conditions but lack suitable crtbegin/end objects or linker support. These diff --git a/gcc/java/constants.c b/gcc/java/constants.c index 5d2f678..2f4c053 100644 --- a/gcc/java/constants.c +++ b/gcc/java/constants.c @@ -458,8 +458,29 @@ build_ref_from_constant_pool (int index) { tree d = build_constant_data_ref (); tree i = build_int_cst (NULL_TREE, index); - return build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i, + if (flag_indirect_classes) + { + tree decl = build_class_ref (output_class); + tree klass = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (decl)), + decl); + tree constants = build3 (COMPONENT_REF, + TREE_TYPE (constants_field_decl_node), klass, + constants_field_decl_node, + NULL_TREE); + tree data = build3 (COMPONENT_REF, + TREE_TYPE (constants_data_field_decl_node), + constants, + constants_data_field_decl_node, + NULL_TREE); + data = fold_convert (build_pointer_type (TREE_TYPE (d)), data); + d = build1 (INDIRECT_REF, TREE_TYPE (d), data); + /* FIXME: These should be cached. */ + TREE_INVARIANT (d) = 1; + } + d = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i, NULL_TREE, NULL_TREE); + TREE_INVARIANT (d) = 1; + return d; } /* Build an initializer for the constants field of the current constant pool. diff --git a/gcc/java/decl.c b/gcc/java/decl.c index 06da90b..a16c49b 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -123,6 +123,12 @@ static GTY(()) tree pending_local_decls; /* The decl for "_Jv_ResolvePoolEntry". */ tree soft_resolvepoolentry_node; +/* The decl for the .constants field of an instance of Class. */ +tree constants_field_decl_node; + +/* The decl for the .data field of an instance of Class. */ +tree constants_data_field_decl_node; + #if defined(DEBUG_JAVA_BINDING_LEVELS) int binding_depth = 0; int is_class_level = 0; @@ -883,6 +889,7 @@ java_init_decl_processing (void) PUSH_FIELD (constants_type_node, field, "size", unsigned_int_type_node); PUSH_FIELD (constants_type_node, field, "tags", ptr_type_node); PUSH_FIELD (constants_type_node, field, "data", ptr_type_node); + constants_data_field_decl_node = field; FINISH_RECORD (constants_type_node); build_decl (TYPE_DECL, get_identifier ("constants"), constants_type_node); @@ -924,6 +931,7 @@ java_init_decl_processing (void) PUSH_FIELD (class_type_node, field, "accflags", access_flags_type_node); PUSH_FIELD (class_type_node, field, "superclass", class_ptr_type); PUSH_FIELD (class_type_node, field, "constants", constants_type_node); + constants_field_decl_node = field; PUSH_FIELD (class_type_node, field, "methods", method_ptr_type_node); PUSH_FIELD (class_type_node, field, "method_count", short_type_node); PUSH_FIELD (class_type_node, field, "vtable_method_count", short_type_node); diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index 18e1ce6..03a7ea2 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -208,6 +208,9 @@ extern int flag_check_references; initialization optimization should be performed. */ extern int flag_optimize_sci; +/* Generate instances of Class at runtime. */ +extern int flag_indirect_classes; + /* When nonzero, use offset tables for virtual method calls in order to improve binary compatibility. */ extern int flag_indirect_dispatch; @@ -270,6 +273,12 @@ extern GTY(()) tree java_lang_cloneable_identifier_node; extern GTY(()) tree java_io_serializable_identifier_node; extern GTY(()) tree gcj_abi_version; +/* The decl for the .constants field of an instance of Class. */ +extern GTY(()) tree constants_field_decl_node; + +/* The decl for the .data field of an instance of Class. */ +extern GTY(()) tree constants_data_field_decl_node; + enum java_tree_index { JTI_PROMOTED_BYTE_TYPE_NODE, diff --git a/gcc/java/jvgenmain.c b/gcc/java/jvgenmain.c index f340279..e0cddc0 100644 --- a/gcc/java/jvgenmain.c +++ b/gcc/java/jvgenmain.c @@ -127,11 +127,11 @@ main (int argc, char **argv) } fprintf (stream, " 0\n};\n\n"); - fprintf (stream, "extern int %s;\n", mangled_classname); fprintf (stream, "int main (int argc, const char **argv)\n"); fprintf (stream, "{\n"); fprintf (stream, " _Jv_Compiler_Properties = props;\n"); - fprintf (stream, " JvRunMain (&%s, argc, argv);\n", mangled_classname); + fprintf (stream, " extern void *%s;\n", mangled_classname); + fprintf (stream, " JvRunMain (%s, argc, argv);\n", mangled_classname); fprintf (stream, "}\n"); if (stream != stdout && fclose (stream) != 0) { @@ -153,16 +153,16 @@ do_mangle_classname (const char *string) for (ptr = string; *ptr; ptr++ ) { - if (ptr[0] == '.') + if (*ptr == '.') { - append_gpp_mangled_name (&ptr [-count], count); + append_gpp_mangled_name (ptr - count, count); count = 0; } else count++; } append_gpp_mangled_name (&ptr [-count], count); - obstack_grow (mangle_obstack, "6class$E", 8); + obstack_grow (mangle_obstack, "7class$$E", strlen ("7class$$E")); obstack_1grow (mangle_obstack, '\0'); return obstack_finish (mangle_obstack); } diff --git a/gcc/java/lang.c b/gcc/java/lang.c index 58f23e9..6344c3c 100644 --- a/gcc/java/lang.c +++ b/gcc/java/lang.c @@ -368,6 +368,9 @@ java_init (void) if (flag_indirect_dispatch) always_initialize_class_p = true; + if (!flag_indirect_dispatch) + flag_indirect_classes = false; + /* Force minimum function alignment if g++ uses the least significant bit of function pointers to store the virtual bit. This is required to keep vtables compatible. */ diff --git a/gcc/java/lang.opt b/gcc/java/lang.opt index 6ffb0aa..80b9202 100644 --- a/gcc/java/lang.opt +++ b/gcc/java/lang.opt @@ -146,6 +146,10 @@ fhash-synchronization Java Var(flag_hash_synchronization) Assume the runtime uses a hash table to map an object to its synchronization structure +findirect-classes +Java Var(flag_indirect_classes) Init(1) +Generate instances of Class at runtime + findirect-dispatch Java Var(flag_indirect_dispatch) Use offset tables for virtual method calls diff --git a/gcc/java/mangle.c b/gcc/java/mangle.c index a99bfe5..0fe5220 100644 --- a/gcc/java/mangle.c +++ b/gcc/java/mangle.c @@ -79,6 +79,9 @@ static GTY(()) tree atms; void java_mangle_decl (tree decl) { + if (TREE_CODE (decl) == RECORD_TYPE) + mangle_type (decl); + /* A copy of the check from the beginning of lhd_set_decl_assembler_name. Only FUNCTION_DECLs and VAR_DECLs for variables with static storage duration need a real DECL_ASSEMBLER_NAME. */ @@ -99,7 +102,7 @@ java_mangle_decl (tree decl) { if (DECL_CLASS_FIELD_P (decl)) { - mangle_class_field (DECL_CONTEXT (decl)); + mangle_class_field (decl); break; } else if (DECL_VTABLE_P (decl)) @@ -130,10 +133,14 @@ java_mangle_decl (tree decl) /* Beginning of the helper functions */ static void -mangle_class_field (tree type) +mangle_class_field (tree decl) { + tree type = DECL_CONTEXT (decl); mangle_record_type (type, /* for_pointer = */ 0); - MANGLE_RAW_STRING ("6class$"); + if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE) + MANGLE_RAW_STRING ("6class$"); + else + MANGLE_RAW_STRING ("7class$$"); obstack_1grow (mangle_obstack, 'E'); } @@ -229,7 +236,7 @@ mangle_member_name (tree name) append_gpp_mangled_name (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)); - /* If NAME happens to be a C++ keyword, add `$'. */ + /* If NAME happens to be a C++ keyword, add `$'. */ if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name))) obstack_1grow (mangle_obstack, '$'); } |