[PATCH][v2] vtv: Fix Memory Leak and Other Improvements
Léo Hardt <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
vtv: Fix Memory Leak and Other Improvements Since there is only one listed maintainer for libvtv, who doesn't seem active in recent years, is it possible for global reviewers to take a look at this patch? Currently, vtable_find_or_create_map_decl, given a class decl, calls get_mangled_vtable_map_var_name (from mangle.cc) to: (1) create a VTV map entry for the given class; and (2) return the expected DECL_ASSEMBLER_NAME of its VTV tracker. Here are some issues and improvements for that logic: a. (2) was only needed once for each class, and in that case, we call get_identifier (var_name). Now we only generate the identifier iff it is needed. b. Since get_identifier copies data, (and when it wasn't called, we didn't free (var_name)), var_name was always leaked. var_name is now computed without heap allocation. c. get_identifier was called twice for the same symbol, which costs an extra hash table lookup. Now we store it in a variable. d. "vtable-class-hierarchy" and "mangle" depended on each other. This is just because (1) is done inside mangle.cc. By moving that statement to vtable-class-hierarchy, we untangle one circular dependency. The effect of vtable_find_or_create_map_decl has not changed. Successfully bootstrapped with "--enable-vtable-verify". gcc/cp/ChangeLog: * cp-tree.h (get_mangled_vtable_map_var_name): Only get the name, without side effects. (get_mangled_type_name_if_anon): Split off from function above. * mangle.cc (get_mangled_vtable_map_var_name): Only get the name, without side effects. (get_mangled_type_name_if_anon): Split off from function above. * vtable-class-hierarchy.cc (vtable_find_or_create_map_decl): Fix memory leak. Signed-off-by: Léo Hardt <[email protected]> --- gcc/cp/cp-tree.h | 3 +- gcc/cp/mangle.cc | 53 ++++++++++++++++---------------- gcc/cp/vtable-class-hierarchy.cc | 23 ++++++++------ 3 files changed, 43 insertions(+), 36 deletions(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 87245184461..2d2db9db113 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -9226,7 +9226,8 @@ extern tree mangle_tls_wrapper_fn (tree); extern bool decl_tls_wrapper_p (tree); extern tree mangle_ref_init_variable (tree); extern tree mangle_template_parm_object (tree); -extern char *get_mangled_vtable_map_var_name (tree); +extern tree get_mangled_type_name_if_anon (tree); +extern tree get_mangled_vtable_map_var_name (tree); extern bool mangle_return_type_p (tree); extern tree mangle_decomp (tree, vec<tree> &); extern void mangle_module_substitution (int); diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc index 4ec57a54c34..5d4126f3bb4 100644 --- a/gcc/cp/mangle.cc +++ b/gcc/cp/mangle.cc @@ -48,7 +48,6 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "target.h" -#include "vtable-verify.h" #include "cp-tree.h" #include "stringpool.h" #include "cgraph.h" @@ -5378,41 +5377,43 @@ mangle_template_parm_object (tree expr) return finish_mangling_get_identifier (); } -/* Given a CLASS_TYPE, such as a record for std::bad_exception this - function generates a mangled name for the vtable map variable of - the class type. For example, if the class type is - "std::bad_exception", the mangled name for the class is - "St13bad_exception". This function would generate the name - "_ZN4_VTVISt13bad_exceptionE12__vtable_mapE", which unmangles as: - "_VTV<std::bad_exception>::__vtable_map". */ +/* Given a CLASS_TYPE, such as a record for std::bad_exception this + function returns NULL_TREE if TYPE_NAME (CLASS_TYPE) is not from + an anonymous namespace. Otherwise, returns the mangled type name. + */ -char * -get_mangled_vtable_map_var_name (tree class_type) +tree +get_mangled_type_name_if_anon(tree class_type) { - char *var_name = NULL; - const char *prefix = "_ZN4_VTVI"; - const char *postfix = "E12__vtable_mapE"; - gcc_assert (TREE_CODE (class_type) == RECORD_TYPE); - tree class_id = DECL_ASSEMBLER_NAME (TYPE_NAME (class_type)); + bool is_anon = strstr (IDENTIFIER_POINTER (class_id), "<anon>") != NULL; + return is_anon ? get_mangled_id (TYPE_NAME (class_type)) : NULL_TREE; +} - if (strstr (IDENTIFIER_POINTER (class_id), "<anon>") != NULL) - { - class_id = get_mangled_id (TYPE_NAME (class_type)); - vtbl_register_mangled_name (TYPE_NAME (class_type), class_id); - } +/* Given a CLASS_TYPE_ASSEMBLER_NAME, such as of the TYPE_NAME of a + record for std::bad_exception, this function generates a mangled + identifier for the vtable map variable of the class type. + For example, if the class type is "std::bad_exception", the mangled + name for the class is "St13bad_exception". This function would + generate the name "_ZN4_VTVISt13bad_exceptionE12__vtable_mapE", + which unmangles as "_VTV<std::bad_exception>::__vtable_map". */ + +tree +get_mangled_vtable_map_var_name (tree class_type_assembler_name) +{ + const char *prefix = "_ZN4_VTVI"; + const char *postfix = "E12__vtable_mapE"; - unsigned int len = strlen (IDENTIFIER_POINTER (class_id)) + - strlen (prefix) + - strlen (postfix) + 1; + const char * class_name = + IDENTIFIER_POINTER (class_type_assembler_name); - var_name = (char *) xmalloc (len); + gcc_assert (strstr (class_name, "<anon>") == NULL); - sprintf (var_name, "%s%s%s", prefix, IDENTIFIER_POINTER (class_id), postfix); + char *var_name = ACONCAT ((prefix, class_name, postfix, NULL)); - return var_name; + return get_identifier(var_name); } #include "gt-cp-mangle.h" diff --git a/gcc/cp/vtable-class-hierarchy.cc b/gcc/cp/vtable-class-hierarchy.cc index 2e52ea3c4a0..7b80d82035b 100644 --- a/gcc/cp/vtable-class-hierarchy.cc +++ b/gcc/cp/vtable-class-hierarchy.cc @@ -1204,15 +1204,22 @@ vtv_generate_init_routine (void) struct vtbl_map_node * vtable_find_or_create_map_decl (tree base_type) { - char *var_name = NULL; struct vtbl_map_node *vtable_map_node = NULL; + tree base_type_name = DECL_ASSEMBLER_NAME (TYPE_NAME (base_type)); /* Verify the type has an associated vtable. */ if (!TYPE_BINFO (base_type) || !BINFO_VTABLE (TYPE_BINFO (base_type))) return NULL; /* Create map lookup symbol for base class */ - var_name = get_mangled_vtable_map_var_name (base_type); + tree mangled_base_type_name = get_mangled_type_name_if_anon (base_type); + + if (mangled_base_type_name != NULL_TREE) + { + vtbl_register_mangled_name + (TYPE_NAME (base_type), mangled_base_type_name); + base_type_name = mangled_base_type_name; + } /* We've already created the variable; just look it. */ vtable_map_node = vtbl_map_get_node (TYPE_MAIN_VARIANT (base_type)); @@ -1223,17 +1230,15 @@ vtable_find_or_create_map_decl (tree base_type) variable for this class, do so now, and add it to the varpool, to make sure it gets saved and written out. */ - tree var_decl = NULL; + tree var_name = get_mangled_vtable_map_var_name (base_type_name); tree var_type = build_pointer_type (void_type_node); - tree initial_value = integer_zero_node; - - var_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, - get_identifier (var_name), var_type); + tree var_decl = + build_decl (UNKNOWN_LOCATION, VAR_DECL, var_name, var_type); DECL_EXTERNAL (var_decl) = 0; TREE_STATIC (var_decl) = 1; DECL_VISIBILITY (var_decl) = VISIBILITY_HIDDEN; - SET_DECL_ASSEMBLER_NAME (var_decl, get_identifier (var_name)); + SET_DECL_ASSEMBLER_NAME (var_decl, var_name); DECL_ARTIFICIAL (var_decl) = 1; /* We cannot mark this variable as read-only because we want to be able to write to it at runtime. */ @@ -1246,7 +1251,7 @@ vtable_find_or_create_map_decl (tree base_type) set_decl_section_name (var_decl, ".vtable_map_vars"); symtab_node::get (var_decl)->implicit_section = true; - DECL_INITIAL (var_decl) = initial_value; + DECL_INITIAL (var_decl) = integer_zero_node; comdat_linkage (var_decl); -- 2.39.5