4a8fb1a1de
This patch is the main part of a consolodation of the hash_table patches to the cxx-conversion branch for files not under gcc/config. Update various hash tables from htab_t to hash_table. Modify types and calls to match. * tree-parloops.c'reduction * tree-parloops.c'name_to_copy Fold reduction_info_hash and reduction_info_eq into new struct reduction_hasher. Fold name_to_copy_elt_eq and name_to_copy_elt_hash into new struct name_to_copy_hasher. * trans-mem.c'tm_log Fold tm_log_hash, tm_log_eq, tm_log_free into new struct log_entry_hasher. * trans-mem.c'tm_memopt_value_numbers Fold tm_memop_hash, tm_memop_eq into new struct tm_memop_hasher. * tree-ssa-strlen.c'decl_to_stridxlist_htab Fold decl_to_stridxlist_hash into new struct stridxlist_hasher. * tree-ssa-loop-ivopts.c'ivopts_data::inv_expr_tab Fold htab_inv_expr_hash and htab_inv_expr_eq into new struct iv_inv_expr_hasher. * tree-ssa-uncprop.c'equiv Equiv renamed to val_ssa_equiv because of name ambiguity with local variables. Fold equiv_hash, equiv_eq and equiv_free into new struct val_ssa_equiv_hasher. Renamed variables equiv_hash_elt to an_equiv_elt because of name ambiguity with struct type. Changed equiv_hash_elt_p to an_equiv_elt_p to match. * tree-ssa-phiopt.c'seen_ssa_names Fold name_to_bb_hash and name_to_bb_eq into new struct ssa_names_hasher. * tree-ssa-structalias.c'pointer_equiv_class_table * tree-ssa-structalias.c'location_equiv_class_table Fold equiv_class_label_hash and equiv_class_label_eq into new struct equiv_class_hasher. * tree-ssa-structalias.c'shared_bitmap_table Fold shared_bitmap_hash and shared_bitmap_eq into new struct shared_bitmap_hasher. * tree-ssa-live.c'var_map_base_init::tree_to_index New struct tree_int_map_hasher. * tree-sra.c'candidates Fold uid_decl_map_hash and uid_decl_map_eq into new struct uid_decl_hasher. This change moves the definitions from tree-ssa.c into tree-sra.c and removes the declarations from tree-flow.h tree-browser.c Remove stale declaration of removed TB_parent_eq. Fix template parameter for base class to match value_type. gimple.h Use gimplify_hasher::hash rather than gimple_tree_hash in the assertion check. Change return values to match return type. (I.e. no conversions.) * graphite-clast-to-gimple.c'ivs_params::newivs_index * graphite-clast-to-gimple.c'ivs_params::params_index * graphite-clast-to-gimple.c'print_generated_program::params_index * graphite-clast-to-gimple.c'gloog::newivs_index * graphite-clast-to-gimple.c'gloog::params_index * graphite.c graphite_transform_loops::bb_pbb_mapping * sese.c copy_bb_and_scalar_dependences::rename_map Move hash table declarations to a new graphite-htab.h, because they are used in few places. Remove unused: htab_t scop::original_pddrs SCOP_ORIGINAL_PDDRS Remove unused: insert_loop_close_phis insert_guard_phis debug_ivtype_map ivtype_map_elt_info new_ivtype_map_elt * gimplify.c'gimplify_ctx::temp_htab Move struct gimple_temp_hash_elt and struct gimplify_ctx to a new gimplify-ctx.h, because they are used few places. * cselib.c'cselib_hash_table * gcse.c'pre_ldst_table * gimple-ssa-strength-reduction.c'base_cand_map * haifa-sched.c'delay_htab * haifa-sched.c'delay_htab_i2 * ira-color.c'allocno_hard_regs_htab * ira-costs.c'cost_classes_htab * loop-invariant.c'merge_identical_invariants::eq * loop-iv.c'bivs * loop-unroll.c'opt_info::insns_to_split * loop-unroll.c'opt_info::insns_with_var_to_expand * passes.c'name_to_pass_map * plugin.c'event_tab * postreload-gcse.c'expr_table * store-motion.c'store_motion_mems_table * tree-cfg.c'discriminator_per_locus * tree-scalar-evolution.c'resolve_mixers::cache * tree-ssa-dom.c'avail_exprs Remove unused: dse.c bitmap clear_alias_sets dse.c bitmap disqualified_clear_alias_sets dse.c alloc_pool clear_alias_mode_pool dse.c dse_step2_spill dse.c dse_step5_spill graphds.h htab_t graph::indices * attribs.c'scoped_attributes::attribute_hash * bitmap.c'bitmap_desc_hash * dwarf2cfi.c'trace_index * dwarf2out.c'break_out_includes::cu_hash_table * dwarf2out.c'copy_decls_for_unworthy_types::decl_table * dwarf2out.c'optimize_external_refs::map * dwarf2out.c'output_comp_unit::extern_map * dwarf2out.c'output_comdat_type_unit::extern_map * dwarf2out.c'output_macinfo::macinfo_htab * dwarf2out.c'optimize_location_lists::htab * dwarf2out.c'dwarf2out_finish::comdat_type_table * except.c'ehspec_hash_type * except.c'assign_filter_values::ttypes * except.c'assign_filter_values::ehspec * except.c'sjlj_assign_call_site_values::ar_hash * except.c'convert_to_eh_region_ranges::ar_hash * trans-mem.c'tm_new_mem_hash * tree-browser.c'TB_up_ht * tree-eh.c'finally_tree Move the declaration of hash_table <alloc_pool_hasher> alloc_pool_hash in alloc-pool.c to after the method definitions for its parameter class. * ggc-common.c'loc_hash * ggc-common.c'ptr_hash Add a new hash_table method elements_with_deleted to meet the needs of gcc-common.c. Correct many methods with parameter types compare_type to the correct value_type. (Correct code was unlikely to notice the change, but incorrect code will.) * tree-complex.c'complex_variable_components * tree-parloops.c'eliminate_local_variables_stmt::decl_address * tree-parloops.c'separate_decls_in_region::decl_copies Move hash table declarations to a new tree-hasher.h, to resolve compilation dependences and because they are used in few places. * lto-streamer.h'output_block::string_hash_table * lto-streamer-in.c'file_name_hash_table * lto-streamer.c'tree_htab The struct string_slot moves from data-streamer.h to lto-streamer.h to resolve compilation dependences. Tested on x86_64. Index: gcc/ChangeLog 2013-04-25 Lawrence Crowl <crowl@google.com> * Makefile.in: Update as needed below. * alloc-pool.c (static hash_table <alloc_pool_hasher> alloc_pool_hash): Move declaration to after the type's method definitons. * attribs.c (htab_t scoped_attributes::attribute_hash): Change type to hash_table. Update dependent calls and types. * bitmap.c (htab_t bitmap_desc_hash): Change type to hash_table. Update dependent calls and types. * cselib.c (htab_t cselib_hash_table): Change type to hash_table. Update dependent calls and types. * data-streamer.h (struct string_slot): Move to lto-streamer.h. (hash_string_slot_node): Move implementation into lto-streamer.h struct string_slot_hasher. (eq_string_slot_node): Likewise. * data-streamer-out.c: Update output_block::string_hash_table dependent calls and types. * dwarf2cfi.c (htab_t trace_index): Change type to hash_table. Update dependent calls and types. * dwarf2out.c (htab_t break_out_includes::cu_hash_table): Change type to hash_table. Update dependent calls and types. (htab_t copy_decls_for_unworthy_types::decl_table): Likewise. (htab_t optimize_external_refs::map): Likewise. (htab_t output_comp_unit::extern_map): Likewise. (htab_t output_comdat_type_unit::extern_map): Likewise. (htab_t output_macinfo::macinfo_htab): Likewise. (htab_t optimize_location_lists::htab): Likewise. (htab_t dwarf2out_finish::comdat_type_table): Likewise. * except.c (htab_t ehspec_hash_type): Change type to hash_table. Update dependent calls and types. (assign_filter_values::ttypes): Likewise. (assign_filter_values::ehspec): Likewise. (sjlj_assign_call_site_values::ar_hash): Likewise. (convert_to_eh_region_ranges::ar_hash): Likewise. * gcse.c (htab_t pre_ldst_table): Change type to hash_table. Update dependent calls and types. * ggc-common.c (htab_t saving_htab): Change type to hash_table. Update dependent calls and types. (htab_t loc_hash): Likewise. (htab_t ptr_hash): Likewise. (call_count): Rename ggc_call_count. (call_alloc): Rename ggc_call_alloc. (loc_descriptor): Rename make_loc_descriptor. (add_statistics): Rename ggc_add_statistics. * ggc-common.c (saving_htab): Change type to hash_table. Update dependent calls and types. * gimple.h (struct gimplify_ctx): Move to gimplify-ctx.h. (push_gimplify_context): Likewise. (pop_gimplify_context): Likewise. (struct gimple_temp_hash_elt): Added. (struct gimplify_hasher): Likewise. (struct gimplify_ctx.temp_htab): Change type to hash_table. Update dependent calls and types. * gimple-fold.c: Include gimplify-ctx.h. * gimple-ssa-strength-reduction.c (htab_t base_cand_map): Change type to hash_table. Update dependent calls and types. (base_cand_dump_callback): Rename to ssa_base_cand_dump_callback to avoid potential global name collision. * gimplify.c: Include gimplify-ctx.h. (struct gimple_temp_hash_elt): Move to gimplify-ctx.h. (htab_t gimplify_ctx::temp_htab): Update dependent calls and types for new type hash_table. (gimple_tree_hash): Move into gimplify_hasher in gimplify-ctx.h. (gimple_tree_eq): Move into gimplify_hasher in gimplify-ctx.h. * gimplify-ctx.h: New. (struct gimple_temp_hash_elt): Move from gimplify.c. (class gimplify_hasher): New. (struct gimplify_ctx): Move from gimple.h. (htab_t gimplify_ctx::temp_htab): Change type to hash_table. Update dependent calls and types. * graphite-clast-to-gimple.c: Include graphite-htab.h. (htab_t ivs_params::newivs_index): Change type to hash_table. Update dependent calls and types. (htab_t ivs_params::params_index): Likewise. (htab_t print_generated_program::params_index): Likewise. (htab_t gloog::newivs_index): Likewise. (htab_t gloog::params_index): Likewise. * graphite.c: Include graphite-htab.h. 4htab_t graphite_transform_loops::bb_pbb_mapping): Change type to hash_table. Update dependent calls and types. * graphite-clast-to-gimple.h: (extern gloog) Move to graphite-htab.h. (bb_pbb_map_hash): Fold into bb_pbb_htab_type in graphite-htab.h. (eq_bb_pbb_map): Fold into bb_pbb_htab_type in graphite-htab.h. * graphite-dependences.c: Include graphite-htab.h. (loop_is_parallel_p): Change hash table type of parameter. * graphite-htab.h: New. (typedef hash_table <bb_pbb_hasher> bb_pbb_htab_type): New. (extern find_pbb_via_hash): Move from graphite-poly.h. (extern loop_is_parallel_p): Move from graphite-poly.h. (extern get_loop_body_pbbs): Move from graphite-poly.h. * graphite-poly.h (extern find_pbb_via_hash): Move to graphite-htab.h. (extern loop_is_parallel_p): Move to graphite-htab.h. (extern get_loop_body_pbbs): Move to graphite-htab.h. * haifa-sched.c (htab_t delay_htab): Change type to hash_table. Update dependent calls and types. (htab_t delay_htab_i2): Likewise. * ira-color.c (htab_t allocno_hard_regs_htab): Change type to hash_table. Update dependent calls and types. * ira-costs.c (htab_t cost_classes_htab): Change type to hash_table. Update dependent calls and types. * loop-invariant.c (htab_t merge_identical_invariants::eq): Change type to hash_table. Update dependent calls and types. * loop-iv.c (htab_t bivs): Change type to hash_table. Update dependent calls and types. * loop-unroll.c (htab_t opt_info::insns_to_split): Change type to hash_table. Update dependent calls and types. (htab_t opt_info::insns_with_var_to_expand): Likewise. * lto-streamer.h (struct string_slot): Move from data-streamer.h (struct string_slot_hasher): New. (htab_t output_block::string_hash_table): Change type to hash_table. Update dependent calls and types. * lto-streamer-in.c (freeing_string_slot_hasher): New. (htab_t file_name_hash_table): Change type to hash_table. Update dependent calls and types. * lto-streamer-out.c: Update output_block::string_hash_table dependent calls and types. * lto-streamer.c (htab_t tree_htab): Change type to hash_table. Update dependent calls and types. * omp-low.c: Include gimplify-ctx.h. * passes.c (htab_t name_to_pass_map): Change type to hash_table. Update dependent calls and types. (pass_traverse): Rename to passes_pass_traverse. * plugin.c (htab_t event_tab): Change type to hash_table. Update dependent calls and types. * postreload-gcse.c (htab_t expr_table): Change type to hash_table. Update dependent calls and types. (dump_hash_table_entry): Rename dump_expr_hash_table_entry. * sese.c (debug_rename_map_1): Make extern. (htab_t copy_bb_and_scalar_dependences::rename_map): Change type to hash_table. Update dependent calls and types. * sese.h (extern debug_rename_map): Move to .c file. * store-motion.c (htab_t store_motion_mems_table): Change type to hash_table. Update dependent calls and types. * trans-mem.c (htab_t tm_new_mem_hash): Change type to hash_table. Update dependent calls and types. * tree-browser.c (htab_t TB_up_ht): Change type to hash_table. Update dependent calls and types. * tree-cfg.c (htab_t discriminator_per_locus): Change type to hash_table. Update dependent calls and types. * tree-complex.c: Include tree-hasher.h (htab_t complex_variable_components): Change type to hash_table. Update dependent calls and types. * tree-eh.c (htab_t finally_tree): Change type to hash_table. Update dependent calls and types. * tree-flow.h (extern int_tree_map_hash): Moved into tree-hasher struct int_tree_hasher. (extern int_tree_map_eq): Likewise. (uid_decl_map_hash): Removed. (extern decl_tree_map_eq): Likewise. * tree-hasher.h: New. (struct int_tree_hasher): New. (typedef int_tree_htab_type): New. * tree-inline.c: Include gimplify-ctx.h. * tree-mudflap.c: Include gimplify-ctx.h. * tree-parloops.c: Include tree-hasher.h. (htab_t eliminate_local_variables_stmt::decl_address): Change type to hash_table. Update dependent calls and types. (htab_t separate_decls_in_region::decl_copies): Likewise. * tree-scalar-evolution.c (htab_t resolve_mixers::cache): Change type to hash_table. Update dependent calls and types. * tree-sra.c (candidates): Change type to hash_table. Update dependent calls and types. * tree-ssa.c (int_tree_map_eq): Moved into struct int_tree_hasher in tree-flow.h. (int_tree_map_hash): Likewise. * tree-ssa-dom.c (htab_t avail_exprs): Change type to hash_table. Update dependent calls and types. * tree-ssa-live.c (var_map_base_init::tree_to_index): Change type to hash_table. Update dependent calls and types. * tree-ssa-loop-ivopts.c (struct ivopts_data.inv_expr_tab): Change type to hash_table. Update dependent calls and types. * tree-ssa-phiopt.c (seen_ssa_names): Change type to hash_table. Update dependent calls and types. * tree-ssa-strlen.c (decl_to_stridxlist_htab): Change type to hash_table. Update dependent calls and types. * tree-ssa-uncprop.c (equiv): Change type to hash_table. Update dependent calls and types. From-SVN: r198329
421 lines
12 KiB
C
421 lines
12 KiB
C
/* Functions to support a pool of allocatable objects.
|
|
Copyright (C) 1987-2013 Free Software Foundation, Inc.
|
|
Contributed by Daniel Berlin <dan@cgsoftware.com>
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free
|
|
Software Foundation; either version 3, or (at your option) any later
|
|
version.
|
|
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GCC; see the file COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#include "config.h"
|
|
#include "system.h"
|
|
#include "alloc-pool.h"
|
|
#include "hash-table.h"
|
|
|
|
#define align_eight(x) (((x+7) >> 3) << 3)
|
|
|
|
/* The internal allocation object. */
|
|
typedef struct allocation_object_def
|
|
{
|
|
#ifdef ENABLE_CHECKING
|
|
/* The ID of alloc pool which the object was allocated from. */
|
|
ALLOC_POOL_ID_TYPE id;
|
|
#endif
|
|
|
|
union
|
|
{
|
|
/* The data of the object. */
|
|
char data[1];
|
|
|
|
/* Because we want any type of data to be well aligned after the ID,
|
|
the following elements are here. They are never accessed so
|
|
the allocated object may be even smaller than this structure.
|
|
We do not care about alignment for floating-point types. */
|
|
char *align_p;
|
|
HOST_WIDEST_INT align_i;
|
|
} u;
|
|
} allocation_object;
|
|
|
|
/* Convert a pointer to allocation_object from a pointer to user data. */
|
|
#define ALLOCATION_OBJECT_PTR_FROM_USER_PTR(X) \
|
|
((allocation_object *) (((char *) (X)) \
|
|
- offsetof (allocation_object, u.data)))
|
|
|
|
/* Convert a pointer to user data from a pointer to allocation_object. */
|
|
#define USER_PTR_FROM_ALLOCATION_OBJECT_PTR(X) \
|
|
((void *) (((allocation_object *) (X))->u.data))
|
|
|
|
#ifdef ENABLE_CHECKING
|
|
/* Last used ID. */
|
|
static ALLOC_POOL_ID_TYPE last_id;
|
|
#endif
|
|
|
|
/* Store information about each particular alloc_pool. Note that this
|
|
will underestimate the amount the amount of storage used by a small amount:
|
|
1) The overhead in a pool is not accounted for.
|
|
2) The unallocated elements in a block are not accounted for. Note
|
|
that this can at worst case be one element smaller that the block
|
|
size for that pool. */
|
|
struct alloc_pool_descriptor
|
|
{
|
|
const char *name;
|
|
/* Number of pools allocated. */
|
|
unsigned long created;
|
|
/* Gross allocated storage. */
|
|
unsigned long allocated;
|
|
/* Amount of currently active storage. */
|
|
unsigned long current;
|
|
/* Peak amount of storage used. */
|
|
unsigned long peak;
|
|
/* Size of element in the pool. */
|
|
int elt_size;
|
|
};
|
|
|
|
/* Hashtable helpers. */
|
|
struct alloc_pool_hasher : typed_noop_remove <alloc_pool_descriptor>
|
|
{
|
|
typedef alloc_pool_descriptor value_type;
|
|
typedef char compare_type;
|
|
static inline hashval_t hash (const alloc_pool_descriptor *);
|
|
static inline bool equal (const value_type *, const compare_type *);
|
|
};
|
|
|
|
inline hashval_t
|
|
alloc_pool_hasher::hash (const value_type *d)
|
|
{
|
|
return htab_hash_pointer (d->name);
|
|
}
|
|
|
|
inline bool
|
|
alloc_pool_hasher::equal (const value_type *d,
|
|
const compare_type *p2)
|
|
{
|
|
return d->name == p2;
|
|
}
|
|
|
|
/* Hashtable mapping alloc_pool names to descriptors. */
|
|
static hash_table <alloc_pool_hasher> alloc_pool_hash;
|
|
|
|
/* For given name, return descriptor, create new if needed. */
|
|
static struct alloc_pool_descriptor *
|
|
allocate_pool_descriptor (const char *name)
|
|
{
|
|
struct alloc_pool_descriptor **slot;
|
|
|
|
if (!alloc_pool_hash.is_created ())
|
|
alloc_pool_hash.create (10);
|
|
|
|
slot = alloc_pool_hash.find_slot_with_hash (name,
|
|
htab_hash_pointer (name), INSERT);
|
|
if (*slot)
|
|
return *slot;
|
|
*slot = XCNEW (struct alloc_pool_descriptor);
|
|
(*slot)->name = name;
|
|
return *slot;
|
|
}
|
|
|
|
/* Create a pool of things of size SIZE, with NUM in each block we
|
|
allocate. */
|
|
|
|
alloc_pool
|
|
create_alloc_pool (const char *name, size_t size, size_t num)
|
|
{
|
|
alloc_pool pool;
|
|
size_t header_size;
|
|
|
|
gcc_checking_assert (name);
|
|
|
|
/* Make size large enough to store the list header. */
|
|
if (size < sizeof (alloc_pool_list))
|
|
size = sizeof (alloc_pool_list);
|
|
|
|
/* Now align the size to a multiple of 4. */
|
|
size = align_eight (size);
|
|
|
|
#ifdef ENABLE_CHECKING
|
|
/* Add the aligned size of ID. */
|
|
size += offsetof (allocation_object, u.data);
|
|
#endif
|
|
|
|
/* Um, we can't really allocate 0 elements per block. */
|
|
gcc_checking_assert (num);
|
|
|
|
/* Allocate memory for the pool structure. */
|
|
pool = XNEW (struct alloc_pool_def);
|
|
|
|
/* Now init the various pieces of our pool structure. */
|
|
pool->name = /*xstrdup (name)*/name;
|
|
pool->elt_size = size;
|
|
pool->elts_per_block = num;
|
|
|
|
if (GATHER_STATISTICS)
|
|
{
|
|
struct alloc_pool_descriptor *desc = allocate_pool_descriptor (name);
|
|
desc->elt_size = size;
|
|
desc->created++;
|
|
}
|
|
|
|
/* List header size should be a multiple of 8. */
|
|
header_size = align_eight (sizeof (struct alloc_pool_list_def));
|
|
|
|
pool->block_size = (size * num) + header_size;
|
|
pool->returned_free_list = NULL;
|
|
pool->virgin_free_list = NULL;
|
|
pool->virgin_elts_remaining = 0;
|
|
pool->elts_allocated = 0;
|
|
pool->elts_free = 0;
|
|
pool->blocks_allocated = 0;
|
|
pool->block_list = NULL;
|
|
|
|
#ifdef ENABLE_CHECKING
|
|
/* Increase the last used ID and use it for this pool.
|
|
ID == 0 is used for free elements of pool so skip it. */
|
|
last_id++;
|
|
if (last_id == 0)
|
|
last_id++;
|
|
|
|
pool->id = last_id;
|
|
#endif
|
|
|
|
return (pool);
|
|
}
|
|
|
|
/* Free all memory allocated for the given memory pool. */
|
|
void
|
|
empty_alloc_pool (alloc_pool pool)
|
|
{
|
|
alloc_pool_list block, next_block;
|
|
|
|
gcc_checking_assert (pool);
|
|
|
|
/* Free each block allocated to the pool. */
|
|
for (block = pool->block_list; block != NULL; block = next_block)
|
|
{
|
|
next_block = block->next;
|
|
free (block);
|
|
}
|
|
|
|
if (GATHER_STATISTICS)
|
|
{
|
|
struct alloc_pool_descriptor *desc = allocate_pool_descriptor (pool->name);
|
|
desc->current -= (pool->elts_allocated - pool->elts_free) * pool->elt_size;
|
|
}
|
|
|
|
pool->returned_free_list = NULL;
|
|
pool->virgin_free_list = NULL;
|
|
pool->virgin_elts_remaining = 0;
|
|
pool->elts_allocated = 0;
|
|
pool->elts_free = 0;
|
|
pool->blocks_allocated = 0;
|
|
pool->block_list = NULL;
|
|
}
|
|
|
|
/* Free all memory allocated for the given memory pool and the pool itself. */
|
|
void
|
|
free_alloc_pool (alloc_pool pool)
|
|
{
|
|
/* First empty the pool. */
|
|
empty_alloc_pool (pool);
|
|
#ifdef ENABLE_CHECKING
|
|
memset (pool, 0xaf, sizeof (*pool));
|
|
#endif
|
|
/* Lastly, free the pool. */
|
|
free (pool);
|
|
}
|
|
|
|
/* Frees the alloc_pool, if it is empty and zero *POOL in this case. */
|
|
void
|
|
free_alloc_pool_if_empty (alloc_pool *pool)
|
|
{
|
|
if ((*pool)->elts_free == (*pool)->elts_allocated)
|
|
{
|
|
free_alloc_pool (*pool);
|
|
*pool = NULL;
|
|
}
|
|
}
|
|
|
|
/* Allocates one element from the pool specified. */
|
|
void *
|
|
pool_alloc (alloc_pool pool)
|
|
{
|
|
alloc_pool_list header;
|
|
#ifdef ENABLE_VALGRIND_CHECKING
|
|
int size;
|
|
#endif
|
|
|
|
if (GATHER_STATISTICS)
|
|
{
|
|
struct alloc_pool_descriptor *desc = allocate_pool_descriptor (pool->name);
|
|
|
|
desc->allocated += pool->elt_size;
|
|
desc->current += pool->elt_size;
|
|
if (desc->peak < desc->current)
|
|
desc->peak = desc->current;
|
|
}
|
|
|
|
gcc_checking_assert (pool);
|
|
#ifdef ENABLE_VALGRIND_CHECKING
|
|
size = pool->elt_size - offsetof (allocation_object, u.data);
|
|
#endif
|
|
|
|
/* If there are no more free elements, make some more!. */
|
|
if (!pool->returned_free_list)
|
|
{
|
|
char *block;
|
|
if (!pool->virgin_elts_remaining)
|
|
{
|
|
alloc_pool_list block_header;
|
|
|
|
/* Make the block. */
|
|
block = XNEWVEC (char, pool->block_size);
|
|
block_header = (alloc_pool_list) block;
|
|
block += align_eight (sizeof (struct alloc_pool_list_def));
|
|
|
|
/* Throw it on the block list. */
|
|
block_header->next = pool->block_list;
|
|
pool->block_list = block_header;
|
|
|
|
/* Make the block available for allocation. */
|
|
pool->virgin_free_list = block;
|
|
pool->virgin_elts_remaining = pool->elts_per_block;
|
|
|
|
/* Also update the number of elements we have free/allocated, and
|
|
increment the allocated block count. */
|
|
pool->elts_allocated += pool->elts_per_block;
|
|
pool->elts_free += pool->elts_per_block;
|
|
pool->blocks_allocated += 1;
|
|
}
|
|
|
|
|
|
/* We now know that we can take the first elt off the virgin list and
|
|
put it on the returned list. */
|
|
block = pool->virgin_free_list;
|
|
header = (alloc_pool_list) USER_PTR_FROM_ALLOCATION_OBJECT_PTR (block);
|
|
header->next = NULL;
|
|
#ifdef ENABLE_CHECKING
|
|
/* Mark the element to be free. */
|
|
((allocation_object *) block)->id = 0;
|
|
#endif
|
|
VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS (header,size));
|
|
pool->returned_free_list = header;
|
|
pool->virgin_free_list += pool->elt_size;
|
|
pool->virgin_elts_remaining--;
|
|
|
|
}
|
|
|
|
/* Pull the first free element from the free list, and return it. */
|
|
header = pool->returned_free_list;
|
|
VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (header, sizeof(*header)));
|
|
pool->returned_free_list = header->next;
|
|
pool->elts_free--;
|
|
|
|
#ifdef ENABLE_CHECKING
|
|
/* Set the ID for element. */
|
|
ALLOCATION_OBJECT_PTR_FROM_USER_PTR (header)->id = pool->id;
|
|
#endif
|
|
VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (header, size));
|
|
|
|
return ((void *) header);
|
|
}
|
|
|
|
/* Puts PTR back on POOL's free list. */
|
|
void
|
|
pool_free (alloc_pool pool, void *ptr)
|
|
{
|
|
alloc_pool_list header;
|
|
#if defined(ENABLE_VALGRIND_CHECKING) || defined(ENABLE_CHECKING)
|
|
int size;
|
|
size = pool->elt_size - offsetof (allocation_object, u.data);
|
|
#endif
|
|
|
|
#ifdef ENABLE_CHECKING
|
|
gcc_assert (ptr
|
|
/* Check if we free more than we allocated, which is Bad (TM). */
|
|
&& pool->elts_free < pool->elts_allocated
|
|
/* Check whether the PTR was allocated from POOL. */
|
|
&& pool->id == ALLOCATION_OBJECT_PTR_FROM_USER_PTR (ptr)->id);
|
|
|
|
memset (ptr, 0xaf, size);
|
|
|
|
/* Mark the element to be free. */
|
|
ALLOCATION_OBJECT_PTR_FROM_USER_PTR (ptr)->id = 0;
|
|
#endif
|
|
|
|
header = (alloc_pool_list) ptr;
|
|
header->next = pool->returned_free_list;
|
|
pool->returned_free_list = header;
|
|
VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS (ptr, size));
|
|
pool->elts_free++;
|
|
|
|
if (GATHER_STATISTICS)
|
|
{
|
|
struct alloc_pool_descriptor *desc = allocate_pool_descriptor (pool->name);
|
|
desc->current -= pool->elt_size;
|
|
}
|
|
}
|
|
|
|
/* Output per-alloc_pool statistics. */
|
|
|
|
/* Used to accumulate statistics about alloc_pool sizes. */
|
|
struct output_info
|
|
{
|
|
unsigned long total_created;
|
|
unsigned long total_allocated;
|
|
};
|
|
|
|
/* Called via hash_table.traverse. Output alloc_pool descriptor pointed out by
|
|
SLOT and update statistics. */
|
|
int
|
|
print_alloc_pool_statistics (alloc_pool_descriptor **slot,
|
|
struct output_info *i)
|
|
{
|
|
struct alloc_pool_descriptor *d = *slot;
|
|
|
|
if (d->allocated)
|
|
{
|
|
fprintf (stderr,
|
|
"%-22s %6d %10lu %10lu(%10lu) %10lu(%10lu) %10lu(%10lu)\n",
|
|
d->name, d->elt_size, d->created, d->allocated,
|
|
d->allocated / d->elt_size, d->peak, d->peak / d->elt_size,
|
|
d->current, d->current / d->elt_size);
|
|
i->total_allocated += d->allocated;
|
|
i->total_created += d->created;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* Output per-alloc_pool memory usage statistics. */
|
|
void
|
|
dump_alloc_pool_statistics (void)
|
|
{
|
|
struct output_info info;
|
|
|
|
if (! GATHER_STATISTICS)
|
|
return;
|
|
|
|
if (!alloc_pool_hash.is_created ())
|
|
return;
|
|
|
|
fprintf (stderr, "\nAlloc-pool Kind Elt size Pools Allocated (elts) Peak (elts) Leak (elts)\n");
|
|
fprintf (stderr, "--------------------------------------------------------------------------------------------------------------\n");
|
|
info.total_created = 0;
|
|
info.total_allocated = 0;
|
|
alloc_pool_hash.traverse <struct output_info *,
|
|
print_alloc_pool_statistics> (&info);
|
|
fprintf (stderr, "--------------------------------------------------------------------------------------------------------------\n");
|
|
fprintf (stderr, "%-22s %7lu %10lu\n",
|
|
"Total", info.total_created, info.total_allocated);
|
|
fprintf (stderr, "--------------------------------------------------------------------------------------------------------------\n");
|
|
}
|