diff options
author | Andrew Haley <aph@redhat.com> | 2006-03-07 14:13:09 +0000 |
---|---|---|
committer | Andrew Haley <aph@redhat.com> | 2006-03-07 14:13:09 +0000 |
commit | cb0e335406b63bbe1176a4cf0f7681de795c0a88 (patch) | |
tree | 30bcbf8989f494313f2afdc8db024653be927d14 | |
parent | e9597daa742f2eca1491f36b909accaece64f2b0 (diff) |
2006-03-07 Andrew Haley <aph@redhat.com>
* jvgenmain.c: If flag_indirect_classes, generate access to
_class$_<classname>.
* mangle.c (java_mangle_decl): Mangle record types too.
* jvspec.c: Allow -findirect-classes.
* constants.c (build_ref_from_constant_pool): If
flag_indirect_classes, build a constant ref via the class, not
directly.
* decl.c (constants_field_decl_node,
constants_data_field_decl_node): New variables.
(java_init_decl_processing): Initialize them.
* class.c (build_static_class_ref): New function.
(build_class_ref): Change direct ref to class to indirect ref to
_class$_<classname>.
(build_class_ref): Call build_static_class_ref.
(make_field_value): If flag_indirect_classes, don't create a
pointer to a field.
(make_class_data): Call build_static_class_ref instead of
build_class_ref.
(register_class): If flag_indirect_classes, just push
current_class instead of generating a class ref.
(emit_indirect_register_classes): Nw function.
(emit_register_classes): If flag_indirect_classes, call
emit_indirect_register_classes.
2006-03-07 Andrew Haley <aph@redhat.com>
* include/execution.h (do_allocate_static_fields): Allocate the
static fields.
* java/lang/Class.h (_Jv_NewClassFromInitializer): Declare
* java/lang/natClassLoader.cc (_Jv_NewClassFromInitializer): New
function.
* boehm.cc (_Jv_InitGC): Return if gc is already initialized.
* gnu/gcj/runtime/natSharedLibLoader.cc (_Jv_GC_has_static_roots):
New function.
2006-03-07 Andrew Haley <aph@redhat.com>
* dyn_load.c (GC_has_static_roots): Declare.
(GC_register_dynlib_callback): Call GC_has_static_roots.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/gcj/gcj-abi-experimental-branch@111806 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | boehm-gc/ChangeLog | 5 | ||||
-rw-r--r-- | boehm-gc/dyn_load.c | 7 | ||||
-rw-r--r-- | gcc/java/ChangeLog | 26 | ||||
-rw-r--r-- | gcc/java/Make-lang.in | 6 | ||||
-rw-r--r-- | gcc/java/class.c | 137 | ||||
-rw-r--r-- | gcc/java/config-lang.in | 2 | ||||
-rw-r--r-- | gcc/java/constants.c | 23 | ||||
-rw-r--r-- | gcc/java/decl.c | 6 | ||||
-rw-r--r-- | gcc/java/java-expr.c | 2 | ||||
-rw-r--r-- | gcc/java/java-tree.h | 7 | ||||
-rw-r--r-- | gcc/java/jvgenmain.c | 66 | ||||
-rw-r--r-- | gcc/java/jvspec.c | 2 | ||||
-rw-r--r-- | gcc/java/lang.opt | 4 | ||||
-rw-r--r-- | gcc/java/mangle.c | 3 | ||||
-rw-r--r-- | libjava/ChangeLog | 11 | ||||
-rw-r--r-- | libjava/boehm.cc | 6 | ||||
-rw-r--r-- | libjava/gnu/gcj/runtime/natSharedLibLoader.cc | 28 | ||||
-rw-r--r-- | libjava/include/execution.h | 20 | ||||
-rw-r--r-- | libjava/java/lang/Class.h | 3 | ||||
-rw-r--r-- | libjava/java/lang/natClassLoader.cc | 38 |
20 files changed, 352 insertions, 50 deletions
diff --git a/boehm-gc/ChangeLog b/boehm-gc/ChangeLog index 81bf9f6112f..3ba8ebbe488 100644 --- a/boehm-gc/ChangeLog +++ b/boehm-gc/ChangeLog @@ -1,3 +1,8 @@ +2006-03-07 Andrew Haley <aph@redhat.com> + + * dyn_load.c (GC_has_static_roots): Declare. + (GC_register_dynlib_callback): Call GC_has_static_roots. + 2006-02-09 Tom Tromey <tromey@redhat.com> * pthread_support.c: Conditionally include dlfcn.h. diff --git a/boehm-gc/dyn_load.c b/boehm-gc/dyn_load.c index 749bf824681..ae1dc76a7d9 100644 --- a/boehm-gc/dyn_load.c +++ b/boehm-gc/dyn_load.c @@ -390,6 +390,9 @@ GC_bool GC_register_main_static_data() /* Thus we also treat it as a weak symbol. */ #define HAVE_DL_ITERATE_PHDR +int (*GC_has_static_roots)(struct dl_phdr_info * info, size_t size, void *ptr) + __attribute__((weak)); + static int GC_register_dynlib_callback(info, size, ptr) struct dl_phdr_info * info; size_t size; @@ -411,6 +414,10 @@ static int GC_register_dynlib_callback(info, size, ptr) { if( !(p->p_flags & PF_W) ) break; start = ((char *)(p->p_vaddr)) + info->dlpi_addr; + + if (GC_has_static_roots && !GC_has_static_roots(info, size, start)) + break; + GC_add_roots_inner(start, start + p->p_memsz, TRUE); } break; diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 3a36b6b766b..763389e1132 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,29 @@ +2006-03-07 Andrew Haley <aph@redhat.com> + + * jvgenmain.c: If flag_indirect_classes, generate access to + _class$_<classname>. + * mangle.c (java_mangle_decl): Mangle record types too. + * jvspec.c: Allow -findirect-classes. + * constants.c (build_ref_from_constant_pool): If + flag_indirect_classes, build a constant ref via the class, not + directly. + * decl.c (constants_field_decl_node, + constants_data_field_decl_node): New variables. + (java_init_decl_processing): Initialize them. + * class.c (build_static_class_ref): New function. + (build_class_ref): Change direct ref to class to indirect ref to + _class$_<classname>. + (build_class_ref): Call build_static_class_ref. + (make_field_value): If flag_indirect_classes, don't create a + pointer to a field. + (make_class_data): Call build_static_class_ref instead of + build_class_ref. + (register_class): If flag_indirect_classes, just push + current_class instead of generating a class ref. + (emit_indirect_register_classes): Nw function. + (emit_register_classes): If flag_indirect_classes, call + emit_indirect_register_classes. + 2006-02-20 Andrew Haley <aph@redhat.com> * jcf-parse.c (parse_class_file): Set input_location from diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in index 8cecf4f702a..afbc8a10258 100644 --- a/gcc/java/Make-lang.in +++ b/gcc/java/Make-lang.in @@ -98,7 +98,7 @@ $(srcdir)/java/keyword.h: $(srcdir)/java/keyword.gperf gt-java-parse.h : s-gtype ; @true # Executables built by this Makefile: -JAVA_OBJS = java/parse.o java/class.o java/decl.o java/expr.o \ +JAVA_OBJS = java/parse.o java/class.o java/decl.o java/java-expr.o \ java/constants.o java/lang.o java/typeck.o java/except.o \ java/verify-glue.o java/verify-impl.o \ java/zextract.o java/jcf-io.o java/win32-host.o java/jcf-parse.o java/mangle.o \ @@ -313,10 +313,10 @@ java/decl.o: java/decl.c $(CONFIG_H) $(JAVA_TREE_H) $(RTL_H) java/jcf.h \ java/except.o: java/except.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h real.h \ $(RTL_H) java/javaop.h java/java-opcodes.h except.h java/java-except.h \ toplev.h $(SYSTEM_H) coretypes.h $(TM_H) function.h -java/expr.o: java/expr.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h real.h \ +java/java-expr.o: java/java-expr.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h real.h \ $(RTL_H) $(EXPR_H) java/javaop.h java/java-opcodes.h except.h \ java/java-except.h java/java-except.h java/parse.h toplev.h \ - $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) gt-java-expr.h target.h + $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) gt-java-java-expr.h target.h java/jcf-depend.o: java/jcf-depend.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) java/jcf.h java/jcf-parse.o: java/jcf-parse.c $(CONFIG_H) $(JAVA_TREE_H) flags.h \ diff --git a/gcc/java/class.c b/gcc/java/class.c index e3eed983345..b8814ce6063 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -944,6 +944,38 @@ 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; +} + /* Build a reference to the class TYPE. Also handles primitive types and array types. */ @@ -953,7 +985,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); @@ -962,17 +994,27 @@ build_class_ref (tree type) && TREE_CODE (type) == RECORD_TYPE) return build_indirect_class_ref (type); - if (TREE_CODE (type) == RECORD_TYPE) + if (flag_indirect_classes + && type == output_class) { - if (TYPE_SIZE (type) == error_mark_node) - return null_pointer_node; - decl_name = identifier_subst (DECL_NAME (TYPE_NAME (type)), - "", '/', '/', ".class"); + tree decl_name = mangled_classname ("_class$_", output_class); decl = IDENTIFIER_GLOBAL_VALUE (decl_name); if (decl == NULL_TREE) { - decl = build_decl (VAR_DECL, decl_name, class_type_node); + 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))); +// decl +// = build_decl (VAR_DECL, decl_name, +// build_pointer_type +// (build_type_variant (class_type_node, +// /* const */ 1, 0))); TREE_STATIC (decl) = 1; + TREE_INVARIANT (decl) = 1; TREE_PUBLIC (decl) = 1; DECL_IGNORED_P (decl) = 1; DECL_ARTIFICIAL (decl) = 1; @@ -981,15 +1023,18 @@ build_class_ref (tree type) 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; + pushdecl_top_level (decl); } - } + return decl; + } + + if (TREE_CODE (type) == RECORD_TYPE) + return build_static_class_ref (type); else { const char *name; + tree decl_name; char buffer[25]; if (flag_emit_class_files) { @@ -1287,16 +1332,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; @@ -1577,7 +1628,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); /* Build Field array. */ @@ -1601,7 +1652,8 @@ make_class_data (tree type) if (initial != NULL_TREE && TREE_TYPE (initial) == string_ptr_type_node) DECL_INITIAL (field) = NULL_TREE; - rest_of_decl_compilation (field, 1, 1); + if (! flag_indirect_classes) + rest_of_decl_compilation (field, 1, 1); DECL_INITIAL (field) = initial; } else @@ -2406,10 +2458,41 @@ 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; + + t = build_function_type_list (class_ptr_type, class_ptr_type, NULL); + t = build_decl (FUNCTION_DECL, + get_identifier ("_Jv_NewClassFromInitializer"), t); + TREE_PUBLIC (t) = 1; + DECL_EXTERNAL (t) = 1; + register_class_fn = t; + + for (i = 0; VEC_iterate (tree, registered_class, i, klass); ++i) + { + output_class = current_class = klass; + t = build_static_class_ref (klass); + t = tree_cons (NULL, t, NULL); + t = build_function_call_expr (register_class_fn, t); + t = build2 (MODIFY_EXPR, class_ptr_type, build_class_ref (klass), + 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 @@ -2426,6 +2509,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/config-lang.in b/gcc/java/config-lang.in index d046c66fcaf..cd7414a2903 100644 --- a/gcc/java/config-lang.in +++ b/gcc/java/config-lang.in @@ -36,7 +36,7 @@ compilers="jc1\$(exeext) jvgenmain\$(exeext)" stagestuff="jc1\$(exeext) gcj\$(exeext) jvgenmain\$(exeext) gcjh\$(exeext) gjnih\$(exeext) jv-scan\$(exeext) jcf-dump\$(exeext)" -gtfiles="\$(srcdir)/java/java-tree.h \$(srcdir)/java/jcf.h \$(srcdir)/java/lex.h \$(srcdir)/java/parse.h \$(srcdir)/java/builtins.c \$(srcdir)/java/class.c \$(srcdir)/java/constants.c \$(srcdir)/java/decl.c \$(srcdir)/java/expr.c \$(srcdir)/java/jcf-parse.c \$(srcdir)/java/jcf-write.c \$(srcdir)/java/lang.c \$(srcdir)/java/mangle.c \$(srcdir)/java/parse.y \$(srcdir)/java/resource.c" +gtfiles="\$(srcdir)/java/java-tree.h \$(srcdir)/java/jcf.h \$(srcdir)/java/lex.h \$(srcdir)/java/parse.h \$(srcdir)/java/builtins.c \$(srcdir)/java/class.c \$(srcdir)/java/constants.c \$(srcdir)/java/decl.c \$(srcdir)/java/java-expr.c \$(srcdir)/java/jcf-parse.c \$(srcdir)/java/jcf-write.c \$(srcdir)/java/lang.c \$(srcdir)/java/mangle.c \$(srcdir)/java/parse.y \$(srcdir)/java/resource.c" target_libs=${libgcj_saved} lang_dirs="zlib fastjar" diff --git a/gcc/java/constants.c b/gcc/java/constants.c index 5d2f6785356..2f4c0530035 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 06da90bff73..34160186453 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -123,6 +123,10 @@ static GTY(()) tree pending_local_decls; /* The decl for "_Jv_ResolvePoolEntry". */ tree soft_resolvepoolentry_node; +tree constants_field_decl_node; + +tree constants_data_field_decl_node; + #if defined(DEBUG_JAVA_BINDING_LEVELS) int binding_depth = 0; int is_class_level = 0; @@ -883,6 +887,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 +929,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-expr.c b/gcc/java/java-expr.c index 785ccc485bf..107d28a6313 100644 --- a/gcc/java/java-expr.c +++ b/gcc/java/java-expr.c @@ -3635,4 +3635,4 @@ promote_arguments (void) } } -#include "gt-java-expr.h" +#include "gt-java-java-expr.h" diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index d421b514a46..2fe1ce814e3 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; @@ -267,6 +270,10 @@ extern GTY(()) tree java_lang_cloneable_identifier_node; extern GTY(()) tree java_io_serializable_identifier_node; extern GTY(()) tree gcj_abi_version; +extern GTY(()) tree constants_field_decl_node; + +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 f3402798e55..79c97760bc4 100644 --- a/gcc/java/jvgenmain.c +++ b/gcc/java/jvgenmain.c @@ -42,6 +42,8 @@ struct obstack *mangle_obstack = &name_obstack; static void usage (const char *) ATTRIBUTE_NORETURN; +int flag_indirect_classes = 0; + static void usage (const char *name) { @@ -56,7 +58,7 @@ main (int argc, char **argv) char *classname, *p; FILE *stream; const char *mangled_classname; - int i, last_arg; + int i, last_arg, first_arg; /* Unlock the stdio streams. */ unlock_std_streams (); @@ -66,7 +68,15 @@ main (int argc, char **argv) if (argc < 2) usage (argv[0]); - for (i = 1; i < argc; ++i) + if (strcmp (argv[1], "-findirect-classes") == 0) + { + flag_indirect_classes = 1; + first_arg = 2; + } + else + first_arg = 1; + + for (i = first_arg; i < argc; ++i) { if (! strncmp (argv[i], "-D", 2)) { @@ -106,11 +116,11 @@ main (int argc, char **argv) else stream = stdout; - /* At this point every element of ARGV from 1 to LAST_ARG is a `-D' - option. Process them appropriately. */ + /* At this point every element of ARGV from FIRST_ARG to LAST_ARG is + a `-D' option. Process them appropriately. */ fprintf (stream, "extern const char **_Jv_Compiler_Properties;\n"); fprintf (stream, "static const char *props[] =\n{\n"); - for (i = 1; i < last_arg; ++i) + for (i = first_arg; i < last_arg; ++i) { const char *p; fprintf (stream, " \""); @@ -127,11 +137,19 @@ 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); + if (flag_indirect_classes) + { + fprintf (stream, " extern void *%s;\n", mangled_classname); + fprintf (stream, " JvRunMain (%s, argc, argv);\n", mangled_classname); + } + else + { + fprintf (stream, " extern int %s;\n", mangled_classname); + fprintf (stream, " JvRunMain (&%s, argc, argv);\n", mangled_classname); + } fprintf (stream, "}\n"); if (stream != stdout && fclose (stream) != 0) { @@ -149,20 +167,34 @@ do_mangle_classname (const char *string) const char *ptr; int count = 0; - obstack_grow (&name_obstack, "_ZN", 3); - - for (ptr = string; *ptr; ptr++ ) + if (flag_indirect_classes) { - if (ptr[0] == '.') + obstack_grow (&name_obstack, "_class$_", strlen ("_class$_")); + for (ptr = string; *ptr; ptr++ ) { - append_gpp_mangled_name (&ptr [-count], count); - count = 0; + if (*ptr == '.') + obstack_1grow (mangle_obstack, '_'); + else + obstack_1grow (mangle_obstack, *ptr); } - else - count++; } - append_gpp_mangled_name (&ptr [-count], count); - obstack_grow (mangle_obstack, "6class$E", 8); + else + { + obstack_grow (&name_obstack, "_ZN", 3); + + for (ptr = string; *ptr; ptr++ ) + { + if (*ptr == '.') + { + 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_1grow (mangle_obstack, '\0'); return obstack_finish (mangle_obstack); } diff --git a/gcc/java/jvspec.c b/gcc/java/jvspec.c index 63f49ff74b3..a48ff56919b 100644 --- a/gcc/java/jvspec.c +++ b/gcc/java/jvspec.c @@ -58,7 +58,7 @@ int lang_specific_extra_outfiles = 0; int shared_libgcc = 1; static const char jvgenmain_spec[] = - "jvgenmain %{D*} %b %m.i |\n\ + "jvgenmain %{findirect-classes} %{D*} %b %m.i |\n\ cc1 %m.i %1 \ %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\ %{g*} %{O*} \ diff --git a/gcc/java/lang.opt b/gcc/java/lang.opt index 001a4a75f9d..5dcba5695c5 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) +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 a99bfe5b56c..f9b379221d2 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. */ diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 8e092cf7bfd..6d6c7dcaf2f 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,14 @@ +2006-03-07 Andrew Haley <aph@redhat.com> + + * include/execution.h (do_allocate_static_fields): Allocate the + static fields. + * java/lang/Class.h (_Jv_NewClassFromInitializer): Declare + * java/lang/natClassLoader.cc (_Jv_NewClassFromInitializer): New + function. + * boehm.cc (_Jv_InitGC): Return if gc is already initialized. + * gnu/gcj/runtime/natSharedLibLoader.cc (_Jv_GC_has_static_roots): + New function. + 2006-02-15 Matthias Klose <doko@debian.org> * gnu/java/nio/charset, gnu/java/net/protocol/file, diff --git a/libjava/boehm.cc b/libjava/boehm.cc index 7066e286b49..716362aef49 100644 --- a/libjava/boehm.cc +++ b/libjava/boehm.cc @@ -468,6 +468,12 @@ void _Jv_InitGC (void) { int proc; + static bool gc_initialized; + + if (gc_initialized) + return; + + gc_initialized = 1; // Ignore pointers that do not point to the start of an object. GC_all_interior_pointers = 0; diff --git a/libjava/gnu/gcj/runtime/natSharedLibLoader.cc b/libjava/gnu/gcj/runtime/natSharedLibLoader.cc index 90ed1d72d68..4970240019e 100644 --- a/libjava/gnu/gcj/runtime/natSharedLibLoader.cc +++ b/libjava/gnu/gcj/runtime/natSharedLibLoader.cc @@ -21,6 +21,7 @@ details. */ #ifdef HAVE_DLOPEN #include <dlfcn.h> +#include <link.h> /* Only used during dlopen, while having a lock on Class.class. */ static java::lang::ClassLoader *curLoader; @@ -29,6 +30,33 @@ static gnu::gcj::runtime::SharedLibHelper *curHelper; typedef void (*ClassHookFunc) (jclass); typedef void (*CoreHookFunc) (_Jv_core_chain *); +static int +_Jv_GC_has_static_roots (struct dl_phdr_info * info, size_t size, void *ptr) +{ + static const char suffix[] = "libgcj.so.7"; + const char *name = info->dlpi_name; + + fprintf (stderr, "%p: lib %s ", ptr, name); + + if (strlen (name) <= strlen (suffix)) + goto defaul; + + // If a DSO name ends with SUFFIX, it has GC roots. + if (strcmp (name + strlen (name) - strlen (suffix), + suffix) == 0) + { + fprintf (stderr, "registered\n"); + return 1; + } + + defaul: + fprintf (stderr, "not registered\n"); + return 0; +} + +int (*GC_has_static_roots)(struct dl_phdr_info * info, size_t size, void *ptr) + = _Jv_GC_has_static_roots; + void _Jv_sharedlib_register_hook (jclass cls) { diff --git a/libjava/include/execution.h b/libjava/include/execution.h index 88189f6449e..fe141e91ec9 100644 --- a/libjava/include/execution.h +++ b/libjava/include/execution.h @@ -55,9 +55,25 @@ struct _Jv_CompiledEngine : public _Jv_ExecutionEngine return NULL; } - static void do_allocate_static_fields (jclass, int, int) + static void do_allocate_static_fields (jclass klass, + int pointer_size, + int other_size) { - // Compiled classes don't need this. + // Splitting the allocations here lets us scan reference fields + // and avoid scanning non-reference fields. + char *reference_fields = (char *) _Jv_AllocRawObj (pointer_size); + char *non_reference_fields = (char *) _Jv_AllocBytes (other_size); + + for (int i = 0; i < klass->field_count; i++) + { + _Jv_Field *field = &klass->fields[i]; + + if ((field->flags & java::lang::reflect::Modifier::STATIC) == 0) + continue; + + char *base = field->isRef() ? reference_fields : non_reference_fields; + field->u.addr = base + field->u.boffset; + } } static void do_create_ncode (jclass) diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h index 787e2638b2b..b697f14123c 100644 --- a/libjava/java/lang/Class.h +++ b/libjava/java/lang/Class.h @@ -39,6 +39,8 @@ extern "Java" // We declare these here to avoid including gcj/cni.h. extern "C" void _Jv_InitClass (jclass klass); +extern "C" jclass _Jv_NewClassFromInitializer + (const jclass class_initializer); extern "C" void _Jv_RegisterClasses (const jclass *classes); extern "C" void _Jv_RegisterClasses_Counted (const jclass *classes, size_t count); @@ -427,6 +429,7 @@ private: int method_idx); friend void ::_Jv_InitClass (jclass klass); + friend java::lang::Class* ::_Jv_NewClassFromInitializer (const jclass class_initializer); friend _Jv_Method* ::_Jv_LookupDeclaredMethod (jclass, _Jv_Utf8Const *, _Jv_Utf8Const*, jclass *); diff --git a/libjava/java/lang/natClassLoader.cc b/libjava/java/lang/natClassLoader.cc index fa6f201db46..b82096cd979 100644 --- a/libjava/java/lang/natClassLoader.cc +++ b/libjava/java/lang/natClassLoader.cc @@ -184,6 +184,44 @@ _Jv_RegisterClasses_Counted (const jclass * classes, size_t count) } } +jclass +_Jv_NewClassFromInitializer (const jclass class_initializer) +{ + _Jv_InitGC (); + jclass new_class = (jclass)_Jv_AllocObj (sizeof *new_class, + &java::lang::Class::class$); + memcpy ((void*)new_class, (void*)class_initializer, sizeof *new_class); + + if (_Jv_CheckABIVersion ((unsigned long) new_class->next_or_version)) + { + jsize count = new_class->field_count; + if (count) + { + new_class->fields + = (_Jv_Field*) _Jv_AllocRawObj (count * sizeof (_Jv_Field)); + memcpy ((void*)new_class->fields, + (void*)class_initializer->fields, + count * sizeof (_Jv_Field)); + } + + count = new_class->constants.size; + if (count) + { + new_class->constants.data + = (_Jv_word*) _Jv_AllocRawObj (count * sizeof (_Jv_word)); + memcpy ((void*)new_class->constants.data, + (void*)class_initializer->constants.data, + count * sizeof (_Jv_word)); + } + + (*_Jv_RegisterClassHook) (new_class); + } + + return new_class; +} + + + void _Jv_RegisterClassHookDefault (jclass klass) { |