From eec875422f79e536fcde443bfe8c0a01b260deb2 Mon Sep 17 00:00:00 2001 From: Hans Boehm Date: Fri, 14 Dec 2001 19:01:02 +0000 Subject: [PATCH] class.c (get_dispatch_table): Fix java vtable layout for TARGET_VTABLE_USES_DESCRIPTORS. * class.c (get_dispatch_table): Fix java vtable layout for TARGET_VTABLE_USES_DESCRIPTORS. * decl.c (java_init_decl_processing): Initialize alloc_no_finalizer_node, finalize_identifier_node. * expr.c (class_has_finalize_method): New function. (expand_java_NEW): Generate calls for finalizer-free allocation. (build_invokevirtual): Fix java vtable layout for TARGET_VTABLE_USES_DESCRIPTORS. * java-tree.h (enum java_tree_index): New entries: JTI_ALLOC_NO_FINALIZER_NODE, JTI_FINALIZE_IDENTIFIER_NODE. (alloc_no_finalizer_node, finalize_deintifier_node): New macros. (class_has_finalize_method): declare. (HAS_FINALIZER_P): New macro. * parse.y (patch_invoke): Generate calls for finalizer-free allocation. From-SVN: r48004 --- gcc/java/ChangeLog | 18 ++++++++++++++++++ gcc/java/class.c | 24 +++++++++++++++++------- gcc/java/decl.c | 6 ++++++ gcc/java/expr.c | 27 +++++++++++++++++++++++---- gcc/java/java-tree.h | 12 ++++++++++++ gcc/java/parse.y | 7 ++++++- 6 files changed, 82 insertions(+), 12 deletions(-) diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 96edf3246bd..3654cff875e 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,21 @@ +2001-12-14 Hans Boehm + + * class.c (get_dispatch_table): Fix java vtable layout + for TARGET_VTABLE_USES_DESCRIPTORS. + * decl.c (java_init_decl_processing): Initialize + alloc_no_finalizer_node, finalize_identifier_node. + * expr.c (class_has_finalize_method): New function. + (expand_java_NEW): Generate calls for finalizer-free allocation. + (build_invokevirtual): Fix java vtable layout for + TARGET_VTABLE_USES_DESCRIPTORS. + * java-tree.h (enum java_tree_index): New entries: + JTI_ALLOC_NO_FINALIZER_NODE, JTI_FINALIZE_IDENTIFIER_NODE. + (alloc_no_finalizer_node, finalize_deintifier_node): New macros. + (class_has_finalize_method): declare. + (HAS_FINALIZER_P): New macro. + * parse.y (patch_invoke): Generate calls for finalizer-free + allocation. + 2001-12-12 Matthias Klose * Make-lang.in: JAVA_INSTALL_NAME, JAVA_CROSS_NAME: Remove diff --git a/gcc/java/class.c b/gcc/java/class.c index f328806af6d..5695aba3e40 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -694,6 +694,13 @@ add_method_1 (handle_class, access_flags, name, function_type) TREE_CHAIN (fndecl) = TYPE_METHODS (handle_class); TYPE_METHODS (handle_class) = fndecl; + /* Notice that this is a finalizer and update the class type + accordingly. This is used to optimize instance allocation. */ + if (name == finalize_identifier_node + && TREE_TYPE (function_type) == void_type_node + && TREE_VALUE (TYPE_ARG_TYPES (function_type)) == void_type_node) + HAS_FINALIZER_P (handle_class) = 1; + if (access_flags & ACC_PUBLIC) METHOD_PUBLIC (fndecl) = 1; if (access_flags & ACC_PROTECTED) METHOD_PROTECTED (fndecl) = 1; if (access_flags & ACC_PRIVATE) @@ -1374,6 +1381,7 @@ get_dispatch_table (type, this_class_addr) tree list = NULL_TREE; int nvirtuals = TREE_VEC_LENGTH (vtable); int arraysize; + tree gc_descr; for (i = nvirtuals; --i >= 0; ) { @@ -1415,15 +1423,17 @@ get_dispatch_table (type, this_class_addr) using the Boehm GC we sometimes stash a GC type descriptor there. We set the PURPOSE to NULL_TREE not to interfere (reset) the emitted byte count during the output to the assembly file. */ - for (j = 1; j < TARGET_VTABLE_USES_DESCRIPTORS; ++j) - list = tree_cons (NULL_TREE, null_pointer_node, list); - list = tree_cons (NULL_TREE, get_boehm_type_descriptor (type), list); - - for (j = 1; j < TARGET_VTABLE_USES_DESCRIPTORS; ++j) - list = tree_cons (NULL_TREE, null_pointer_node, list); + /* With TARGET_VTABLE_USES_DESCRIPTORS, we only add one extra + fake "function descriptor". It's first word is the is the class + pointer, and subsequent words (usually one) contain the GC descriptor. + In all other cases, we reserve two extra vtable slots. */ + gc_descr = get_boehm_type_descriptor (type); + list = tree_cons (NULL_TREE, gc_descr, list); + for (j = 1; j < TARGET_VTABLE_USES_DESCRIPTORS-1; ++j) + list = tree_cons (NULL_TREE, gc_descr, list); list = tree_cons (integer_zero_node, this_class_addr, list); - arraysize = nvirtuals + 2; + arraysize = (TARGET_VTABLE_USES_DESCRIPTORS? nvirtuals + 1 : nvirtuals + 2); if (TARGET_VTABLE_USES_DESCRIPTORS) arraysize *= TARGET_VTABLE_USES_DESCRIPTORS; return build (CONSTRUCTOR, diff --git a/gcc/java/decl.c b/gcc/java/decl.c index 0b1e0164116..17b3607a871 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -586,6 +586,7 @@ java_init_decl_processing () instinit_identifier_node = get_identifier ("instinit$"); void_signature_node = get_identifier ("()V"); length_identifier_node = get_identifier ("length"); + finalize_identifier_node = get_identifier ("finalize"); this_identifier_node = get_identifier ("this"); super_identifier_node = get_identifier ("super"); continue_identifier_node = get_identifier ("continue"); @@ -729,6 +730,11 @@ java_init_decl_processing () build_function_type (ptr_type_node, t), 0, NOT_BUILT_IN, NULL); DECL_IS_MALLOC (alloc_object_node) = 1; + alloc_no_finalizer_node = + builtin_function ("_Jv_AllocObjectNoFinalizer", + build_function_type (ptr_type_node, t), + 0, NOT_BUILT_IN, NULL); + DECL_IS_MALLOC (alloc_no_finalizer_node) = 1; t = tree_cons (NULL_TREE, ptr_type_node, endlink); soft_initclass_node = builtin_function ("_Jv_InitClass", diff --git a/gcc/java/expr.c b/gcc/java/expr.c index f865d958008..ef1a13959e1 100644 --- a/gcc/java/expr.c +++ b/gcc/java/expr.c @@ -1131,15 +1131,31 @@ build_address_of (value) return build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (value)), value); } +bool class_has_finalize_method (type) + tree type; +{ + tree super = CLASSTYPE_SUPER (type); + + if (super == NULL_TREE) + return false; /* Every class with a real finalizer inherits */ + /* from java.lang.Object. */ + else + return HAS_FINALIZER_P (type) || class_has_finalize_method (super); +} + static void expand_java_NEW (type) tree type; { + tree alloc_node; + + alloc_node = (class_has_finalize_method (type) ? alloc_object_node + : alloc_no_finalizer_node); if (! CLASS_LOADED_P (type)) load_class (type, 1); safe_layout_class (type); push_value (build (CALL_EXPR, promote_type (type), - build_address_of (alloc_object_node), + build_address_of (alloc_node), tree_cons (NULL_TREE, build_class_ref (type), build_tree_list (NULL_TREE, size_in_bytes (type))), @@ -1849,9 +1865,12 @@ build_invokevirtual (dtable, method) = build_pointer_type (nativecode_ptr_type_node); tree method_index = convert (sizetype, DECL_VINDEX (method)); - /* Add one to skip "class" field of dtable, and one to skip unused - vtable entry (for C++ compatibility). */ - method_index = size_binop (PLUS_EXPR, method_index, size_int (2)); + if (TARGET_VTABLE_USES_DESCRIPTORS) + /* Add one to skip bogus descriptor for class and GC descriptor. */ + method_index = size_binop (PLUS_EXPR, method_index, size_int (1)); + else + /* Add 1 to skip "class" field of dtable, and 1 to skip GC descriptor. */ + method_index = size_binop (PLUS_EXPR, method_index, size_int (2)); method_index = size_binop (MULT_EXPR, method_index, TYPE_SIZE_UNIT (nativecode_ptr_ptr_type_node)); diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index 63c08d7c80d..9d11bf6baf1 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -60,6 +60,7 @@ struct JCF; RESOLVE_PACKAGE_NAME_P (in EXPR_WITH_FILE_LOCATION) SWITCH_HAS_DEFAULT (in SWITCH_EXPR) ZIP_FILE_P (in TREE_LIST in current_file_list) + HAS_FINALIZER (in RECORD_TYPE) 4: IS_A_COMMAND_LINE_FILENAME_P (in IDENTIFIER_NODE) RESOLVE_TYPE_NAME_P (in EXPR_WITH_FILE_LOCATION) CALL_USING_SUPER (in CALL_EXPR) @@ -290,6 +291,7 @@ enum java_tree_index JTI_FINIT_LEG_IDENTIFIER_NODE, JTI_VOID_SIGNATURE_NODE, JTI_LENGTH_IDENTIFIER_NODE, + JTI_FINALIZE_IDENTIFIER_NODE, JTI_THIS_IDENTIFIER_NODE, JTI_SUPER_IDENTIFIER_NODE, JTI_CONTINUE_IDENTIFIER_NODE, @@ -334,6 +336,7 @@ enum java_tree_index JTI_THROW_NODE, JTI_ALLOC_OBJECT_NODE, + JTI_ALLOC_NO_FINALIZER_NODE, JTI_SOFT_INSTANCEOF_NODE, JTI_SOFT_CHECKCAST_NODE, JTI_SOFT_INITCLASS_NODE, @@ -485,6 +488,8 @@ extern tree java_global_trees[JTI_MAX]; java_global_trees[JTI_VOID_SIGNATURE_NODE] /* "()V" */ #define length_identifier_node \ java_global_trees[JTI_LENGTH_IDENTIFIER_NODE] /* "length" */ +#define finalize_identifier_node \ + java_global_trees[JTI_FINALIZE_IDENTIFIER_NODE] /* "finalize" */ #define this_identifier_node \ java_global_trees[JTI_THIS_IDENTIFIER_NODE] /* "this" */ #define super_identifier_node \ @@ -569,6 +574,8 @@ extern tree java_global_trees[JTI_MAX]; java_global_trees[JTI_THROW_NODE] #define alloc_object_node \ java_global_trees[JTI_ALLOC_OBJECT_NODE] +#define alloc_no_finalizer_node \ + java_global_trees[JTI_ALLOC_NO_FINALIZER_NODE] #define soft_instanceof_node \ java_global_trees[JTI_SOFT_INSTANCEOF_NODE] #define soft_checkcast_node \ @@ -1163,6 +1170,7 @@ extern void java_debug_context PARAMS ((void)); extern void safe_layout_class PARAMS ((tree)); extern tree get_boehm_type_descriptor PARAMS ((tree)); +extern bool class_has_finalize_method PARAMS ((tree)); extern unsigned long java_hash_hash_tree_node PARAMS ((hash_table_key)); extern bool java_hash_compare_tree_node PARAMS ((hash_table_key, hash_table_key)); @@ -1421,6 +1429,10 @@ extern tree *type_map; already checked (for redifitions, etc, see java_check_regular_methods.) */ #define CLASS_METHOD_CHECKED_P(EXPR) TREE_LANG_FLAG_2 (EXPR) +/* True if TYPE (a TREE_TYPE denoting a class type) was found to + feature a finalizer method. */ +#define HAS_FINALIZER_P(EXPR) TREE_LANG_FLAG_3 (EXPR) + /* True if EXPR (a WFL in that case) resolves into an expression name */ #define RESOLVE_EXPRESSION_NAME_P(WFL) TREE_LANG_FLAG_0 (WFL) diff --git a/gcc/java/parse.y b/gcc/java/parse.y index 80c60fd570c..4dae766a695 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -10662,6 +10662,8 @@ patch_invoke (patch, method, args) { tree class = DECL_CONTEXT (method); tree c1, saved_new, size, new; + tree alloc_node; + if (flag_emit_class_files || flag_emit_xref) { TREE_TYPE (patch) = build_pointer_type (class); @@ -10670,8 +10672,11 @@ patch_invoke (patch, method, args) if (!TYPE_SIZE (class)) safe_layout_class (class); size = size_in_bytes (class); + alloc_node = + (class_has_finalize_method (class) ? alloc_object_node + : alloc_no_finalizer_node); new = build (CALL_EXPR, promote_type (class), - build_address_of (alloc_object_node), + build_address_of (alloc_node), tree_cons (NULL_TREE, build_class_ref (class), build_tree_list (NULL_TREE, size_in_bytes (class))),