From: Alan Lawrence <alan.lawrence@arm.com>
To: Trevor Saunders <tsaunders@mozilla.com>
Cc: "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH] support ggc hash_map and hash_set
Date: Fri, 17 Oct 2014 13:36:00 -0000 [thread overview]
Message-ID: <54411A11.8060001@arm.com> (raw)
In-Reply-To: <20140910021254.GA31208@tsaunders-iceball.corp.tor1.mozilla.com>
Sorry, somehow I missed this email. Yes, that appears to have fixed it!
Thank you very much,
Alan
Trevor Saunders wrote:
> On Tue, Sep 09, 2014 at 03:37:26PM +0100, Alan Lawrence wrote:
>> Following this, we're seeing ICEs in tests in gcc.dg/pch.exp and g++.dg/pch.exp,
>> with cross-builds (hosted on x86_64) targetting bare metal AArch64 and ARM
>> (aarch64-none-elf, aarch64_be-none-elf and arm-none-eabi; I haven't tested
>> armeb-none-eabi; builds targeting linux are OK), for *release builds only*.
>
> Could you test the below patch? it seems to work for me, but I'm not
> familiar with testing cross compilers.
>
> diff --git a/gcc/hash-table.h b/gcc/hash-table.h
> index c2a68fd..028b7de 100644
> --- a/gcc/hash-table.h
> +++ b/gcc/hash-table.h
> @@ -1598,8 +1598,9 @@ template<typename D>
> static void
> gt_pch_nx (hash_table<D> *h)
> {
> - gcc_checking_assert (gt_pch_note_object (h->m_entries, h,
> - hashtab_entry_note_pointers<D>));
> + bool success ATTRIBUTE_UNUSED
> + = gt_pch_note_object (h->m_entries, h, hashtab_entry_note_pointers<D>);
> + gcc_checking_assert (success);
> for (size_t i = 0; i < h->m_size; i++)
> {
> if (hash_table<D>::is_empty (h->m_entries[i])
>
> Trev
>
>> Affected tests:
>>
>> gcc.dg/pch.exp: all variants of
>> ./except-1.h
>> ./inline-3.h
>> gcc.dg/pch/except-1.c
>> gcc.dg/pch/inline-3.c
>>
>> g++.dg: all variants of
>> ./array-1.H
>> ./empty.H
>> ./externc-1.H
>> ./local-1.H
>> ./pch.H
>> ./static-1.H
>> ./system-1.H
>> ./system-2.H
>> ./template-1.H
>> ./uninst.H
>> ./wchar-1.H
>>
>> (These then lead to failures of g++.dg/pch/{array-1,...}.C and corresponding
>> assembly comparisons).
>>
>> Sample log:
>>
>> Executing on host: build/obj/gcc2/gcc/testsuite/g++/../../xg++
>> -Bbuild/obj/gcc2/gcc/testsuite/g++/../../ ./template-1.H
>> -fno-diagnostics-show-caret -fdiagnostics-color=never -nostdinc++
>> -Ibuild/obj/gcc2/aarch64-none-elf/ilp32/libstdc++-v3/include/aarch64-none-elf
>> -Ibuild/obj/gcc2/aarch64-none-elf/ilp32/libstdc++-v3/include
>> -Isrc/gcc/libstdc++-v3/libsupc++ -Isrc/gcc/libstdc++-v3/include/backward
>> -Isrc/gcc/libstdc++-v3/testsuite/util -fmessage-length=0 -O2 -g
>> -specs=aem-ve.specs -mabi=ilp32 -mcmodel=small -o template-1.H.gch
>> (timeout = 300)
>> spawn build/obj/gcc2/gcc/testsuite/g++/../../xg++
>> -Bbuild/obj/gcc2/gcc/testsuite/g++/../../ ./template-1.H
>> -fno-diagnostics-show-caret -fdiagnostics-color=never -nostdinc++
>> -Ibuild/obj/gcc2/aarch64-none-elf/ilp32/libstdc++-v3/include/aarch64-none-elf
>> -Ibuild/obj/gcc2/aarch64-none-elf/ilp32/libstdc++-v3/include
>> -Isrc/gcc/libstdc++-v3/libsupc++ -Isrc/gcc/libstdc++-v3/include/backward
>> -Isrc/gcc/libstdc++-v3/testsuite/util -fmessage-length=0 -O2 -g
>> -specs=aem-ve.specs -mabi=ilp32 -mcmodel=small -o template-1.H.gch
>>
>> ./template-1.H:5:2: internal compiler error: in relocate_ptrs, at ggc-common.c:435
>> Please submit a full bug report,
>> with preprocessed source if appropriate.
>> See <http://gcc.gnu.org/bugs.html> for instructions.
>> compiler exited with status 1
>> output is:
>> ./array-1.H:4:2: internal compiler error: in relocate_ptrs, at ggc-common.c:435
>> Please submit a full bug report,
>> with preprocessed source if appropriate.
>> See <http://gcc.gnu.org/bugs.html> for instructions.
>>
>> FAIL: ./array-1.H -g (internal compiler error)
>> FAIL: ./array-1.H -g (test for excess errors)
>> Excess errors:
>> ./array-1.H:4:2: internal compiler error: in relocate_ptrs, at ggc-common.c:435
>>
>> --Alan
>>
>> tsaunders@mozilla.com wrote:
>>> From: Trevor Saunders <tsaunders@mozilla.com>
>>>
>>> Hi,
>>>
>>> There are still some issues to make this work really nicely, but this part is
>>> probably good enough its worth reviewing.
>>>
>>> For one thing you can't use ggc hash_map or set in front ends with some types
>>> or gengtype will decide to put the overloads of the marking routines it
>>> provides in a front end file instead of the one it choose before breaking other
>>> front ends. However that seems to be an unrelated issue you can trigger it
>>> without using hash_map/set, so we might as well solve it separetly.
>>>
>>> I had to have the entry marking functions for set deligate to the traits class
>>> because gcc < 4.9.1 issues clearly bogus errors if you inline the code from the
>>> traits implementation. We may well want to make map work the same way at some
>>> point to enable some of the special GTY attributes like if_marked, but it
>>> doesn't seem to be necessary right now.
>>>
>>> bootstrapped + regtested without regressions on x86_64-unknown-linux-gnu, ok?
>>>
>>> Trev
>>>
>>> gcc/ChangeLog:
>>>
>>> 2014-09-01 Trevor Saunders <tsaunders@mozilla.com>
>>>
>>> * alloc-pool.c: Include coretypes.h.
>>> * cgraph.h, dbxout.c, dwarf2out.c, except.c, except.h, function.c,
>>> function.h, symtab.c, tree-cfg.c, tree-eh.c: Use hash_map and
>>> hash_set instead of htab.
>>> * ggc-page.c (in_gc): New variable.
>>> (ggc_free): Do nothing if a collection is taking place.
>>> (ggc_collect): Set in_gc appropriately.
>>> * ggc.h (gt_ggc_mx(const char *)): New function.
>>> (gt_pch_nx(const char *)): Likewise.
>>> (gt_ggc_mx(int)): Likewise.
>>> (gt_pch_nx(int)): Likewise.
>>> * hash-map.h (hash_map::hash_entry::ggc_mx): Likewise.
>>> (hash_map::hash_entry::pch_nx): Likewise.
>>> (hash_map::hash_entry::pch_nx_helper): Likewise.
>>> (hash_map::hash_map): Adjust.
>>> (hash_map::create_ggc): New function.
>>> (gt_ggc_mx): Likewise.
>>> (gt_pch_nx): Likewise.
>>> * hash-set.h (default_hashset_traits::ggc_mx): Likewise.
>>> (default_hashset_traits::pch_nx): Likewise.
>>> (hash_set::hash_entry::ggc_mx): Likewise.
>>> (hash_set::hash_entry::pch_nx): Likewise.
>>> (hash_set::hash_entry::pch_nx_helper): Likewise.
>>> (hash_set::hash_set): Adjust.
>>> (hash_set::create_ggc): New function.
>>> (hash_set::elements): Likewise.
>>> (gt_ggc_mx): Likewise.
>>> (gt_pch_nx): Likewise.
>>> * hash-table.h (hash_table::hash_table): Adjust.
>>> (hash_table::m_ggc): New member.
>>> (hash_table::~hash_table): Adjust.
>>> (hash_table::expand): Likewise.
>>> (hash_table::empty): Likewise.
>>> (gt_ggc_mx): New function.
>>> (hashtab_entry_note_pointers): Likewise.
>>> (gt_pch_nx): Likewise.
>>>
>>>
>>> diff --git a/gcc/alloc-pool.c b/gcc/alloc-pool.c
>>> index 0d31835..bfaa0e4 100644
>>> --- a/gcc/alloc-pool.c
>>> +++ b/gcc/alloc-pool.c
>>> @@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see
>>>
>>> #include "config.h"
>>> #include "system.h"
>>> +#include "coretypes.h"
>>> #include "alloc-pool.h"
>>> #include "hash-table.h"
>>> #include "hash-map.h"
>>> diff --git a/gcc/cgraph.h b/gcc/cgraph.h
>>> index 879899c..030a1c7 100644
>>> --- a/gcc/cgraph.h
>>> +++ b/gcc/cgraph.h
>>> @@ -1604,7 +1604,6 @@ struct cgraph_2node_hook_list;
>>>
>>> /* Map from a symbol to initialization/finalization priorities. */
>>> struct GTY(()) symbol_priority_map {
>>> - symtab_node *symbol;
>>> priority_type init;
>>> priority_type fini;
>>> };
>>> @@ -1872,7 +1871,7 @@ public:
>>> htab_t GTY((param_is (symtab_node))) assembler_name_hash;
>>>
>>> /* Hash table used to hold init priorities. */
>>> - htab_t GTY ((param_is (symbol_priority_map))) init_priority_hash;
>>> + hash_map<symtab_node *, symbol_priority_map> *init_priority_hash;
>>>
>>> FILE* GTY ((skip)) dump_file;
>>>
>>> diff --git a/gcc/dbxout.c b/gcc/dbxout.c
>>> index 946f1d1..d856bdd 100644
>>> --- a/gcc/dbxout.c
>>> +++ b/gcc/dbxout.c
>>> @@ -2484,12 +2484,9 @@ dbxout_expand_expr (tree expr)
>>> /* Helper function for output_used_types. Queue one entry from the
>>> used types hash to be output. */
>>>
>>> -static int
>>> -output_used_types_helper (void **slot, void *data)
>>> +bool
>>> +output_used_types_helper (tree const &type, vec<tree> *types_p)
>>> {
>>> - tree type = (tree) *slot;
>>> - vec<tree> *types_p = (vec<tree> *) data;
>>> -
>>> if ((TREE_CODE (type) == RECORD_TYPE
>>> || TREE_CODE (type) == UNION_TYPE
>>> || TREE_CODE (type) == QUAL_UNION_TYPE
>>> @@ -2502,7 +2499,7 @@ output_used_types_helper (void **slot, void *data)
>>> && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
>>> types_p->quick_push (TYPE_NAME (type));
>>>
>>> - return 1;
>>> + return true;
>>> }
>>>
>>> /* This is a qsort callback which sorts types and declarations into a
>>> @@ -2544,8 +2541,9 @@ output_used_types (void)
>>> int i;
>>> tree type;
>>>
>>> - types.create (htab_elements (cfun->used_types_hash));
>>> - htab_traverse (cfun->used_types_hash, output_used_types_helper, &types);
>>> + types.create (cfun->used_types_hash->elements ());
>>> + cfun->used_types_hash->traverse<vec<tree> *, output_used_types_helper>
>>> + (&types);
>>>
>>> /* Sort by UID to prevent dependence on hash table ordering. */
>>> types.qsort (output_types_sort);
>>> diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
>>> index 7c0be86..21afc3f 100644
>>> --- a/gcc/dwarf2out.c
>>> +++ b/gcc/dwarf2out.c
>>> @@ -18013,17 +18013,15 @@ dwarf2out_abstract_function (tree decl)
>>> Marks the DIE of a given type in *SLOT as perennial, so it never gets
>>> marked as unused by prune_unused_types. */
>>>
>>> -static int
>>> -premark_used_types_helper (void **slot, void *data ATTRIBUTE_UNUSED)
>>> +bool
>>> +premark_used_types_helper (tree const &type, void *)
>>> {
>>> - tree type;
>>> dw_die_ref die;
>>>
>>> - type = (tree) *slot;
>>> die = lookup_type_die (type);
>>> if (die != NULL)
>>> die->die_perennial_p = 1;
>>> - return 1;
>>> + return true;
>>> }
>>>
>>> /* Helper function of premark_types_used_by_global_vars which gets called
>>> @@ -18066,7 +18064,7 @@ static void
>>> premark_used_types (struct function *fun)
>>> {
>>> if (fun && fun->used_types_hash)
>>> - htab_traverse (fun->used_types_hash, premark_used_types_helper, NULL);
>>> + fun->used_types_hash->traverse<void *, premark_used_types_helper> (NULL);
>>> }
>>>
>>> /* Mark all members of types_used_by_vars_entry as perennial. */
>>> diff --git a/gcc/except.c b/gcc/except.c
>>> index 1f57c3f..fecc060 100644
>>> --- a/gcc/except.c
>>> +++ b/gcc/except.c
>>> @@ -149,8 +149,13 @@ along with GCC; see the file COPYING3. If not see
>>> #endif
>>>
>>> static GTY(()) int call_site_base;
>>> -static GTY ((param_is (union tree_node)))
>>> - htab_t type_to_runtime_map;
>>> +
>>> +struct tree_hash_traits : default_hashmap_traits
>>> +{
>>> + static hashval_t hash (tree t) { return TREE_HASH (t); }
>>> +};
>>> +
>>> +static GTY (()) hash_map<tree, tree, tree_hash_traits> *type_to_runtime_map;
>>>
>>> /* Describe the SjLj_Function_Context structure. */
>>> static GTY(()) tree sjlj_fc_type_node;
>>> @@ -213,9 +218,6 @@ typedef hash_table<action_record_hasher> action_hash_type;
>>> static bool get_eh_region_and_lp_from_rtx (const_rtx, eh_region *,
>>> eh_landing_pad *);
>>>
>>> -static int t2r_eq (const void *, const void *);
>>> -static hashval_t t2r_hash (const void *);
>>> -
>>> static void dw2_build_landing_pads (void);
>>>
>>> static int collect_one_action_chain (action_hash_type *, eh_region);
>>> @@ -237,7 +239,8 @@ init_eh (void)
>>> if (! flag_exceptions)
>>> return;
>>>
>>> - type_to_runtime_map = htab_create_ggc (31, t2r_hash, t2r_eq, NULL);
>>> + type_to_runtime_map
>>> + = hash_map<tree, tree, tree_hash_traits>::create_ggc (31);
>>>
>>> /* Create the SjLj_Function_Context structure. This should match
>>> the definition in unwind-sjlj.c. */
>>> @@ -671,54 +674,28 @@ eh_region_outermost (struct function *ifun, eh_region region_a,
>>> return region_a;
>>> }
>>>
>>> -static int
>>> -t2r_eq (const void *pentry, const void *pdata)
>>> -{
>>> - const_tree const entry = (const_tree) pentry;
>>> - const_tree const data = (const_tree) pdata;
>>> -
>>> - return TREE_PURPOSE (entry) == data;
>>> -}
>>> -
>>> -static hashval_t
>>> -t2r_hash (const void *pentry)
>>> -{
>>> - const_tree const entry = (const_tree) pentry;
>>> - return TREE_HASH (TREE_PURPOSE (entry));
>>> -}
>>> -
>>> void
>>> add_type_for_runtime (tree type)
>>> {
>>> - tree *slot;
>>> -
>>> /* If TYPE is NOP_EXPR, it means that it already is a runtime type. */
>>> if (TREE_CODE (type) == NOP_EXPR)
>>> return;
>>>
>>> - slot = (tree *) htab_find_slot_with_hash (type_to_runtime_map, type,
>>> - TREE_HASH (type), INSERT);
>>> - if (*slot == NULL)
>>> - {
>>> - tree runtime = lang_hooks.eh_runtime_type (type);
>>> - *slot = tree_cons (type, runtime, NULL_TREE);
>>> - }
>>> + bool existed = false;
>>> + tree *slot = &type_to_runtime_map->get_or_insert (type, &existed);
>>> + if (!existed)
>>> + *slot = lang_hooks.eh_runtime_type (type);
>>> }
>>>
>>> tree
>>> lookup_type_for_runtime (tree type)
>>> {
>>> - tree *slot;
>>> -
>>> /* If TYPE is NOP_EXPR, it means that it already is a runtime type. */
>>> if (TREE_CODE (type) == NOP_EXPR)
>>> return type;
>>>
>>> - slot = (tree *) htab_find_slot_with_hash (type_to_runtime_map, type,
>>> - TREE_HASH (type), NO_INSERT);
>>> -
>>> /* We should have always inserted the data earlier. */
>>> - return TREE_VALUE (*slot);
>>> + return *type_to_runtime_map->get (type);
>>> }
>>>
>>>
>>> @@ -3150,12 +3127,12 @@ output_function_exception_table (const char *fnname)
>>> }
>>>
>>> void
>>> -set_eh_throw_stmt_table (struct function *fun, struct htab *table)
>>> +set_eh_throw_stmt_table (function *fun, hash_map<gimple, int> *table)
>>> {
>>> fun->eh->throw_stmt_table = table;
>>> }
>>>
>>> -htab_t
>>> +hash_map<gimple, int> *
>>> get_eh_throw_stmt_table (struct function *fun)
>>> {
>>> return fun->eh->throw_stmt_table;
>>> diff --git a/gcc/except.h b/gcc/except.h
>>> index 71a8dce..3259151 100644
>>> --- a/gcc/except.h
>>> +++ b/gcc/except.h
>>> @@ -204,7 +204,7 @@ struct GTY(()) eh_status
>>>
>>> /* At the gimple level, a mapping from gimple statement to landing pad
>>> or must-not-throw region. See record_stmt_eh_region. */
>>> - htab_t GTY((param_is (struct throw_stmt_node))) throw_stmt_table;
>>> + hash_map<gimple, int> *GTY(()) throw_stmt_table;
>>>
>>> /* All of the runtime type data used by the function. These objects
>>> are emitted to the lang-specific-data-area for the function. */
>>> @@ -291,8 +291,8 @@ struct GTY(()) throw_stmt_node {
>>> int lp_nr;
>>> };
>>>
>>> -extern struct htab *get_eh_throw_stmt_table (struct function *);
>>> -extern void set_eh_throw_stmt_table (struct function *, struct htab *);
>>> +extern hash_map<gimple, int> *get_eh_throw_stmt_table (struct function *);
>>> +extern void set_eh_throw_stmt_table (function *, hash_map<gimple, int> *);
>>>
>>> enum eh_personality_kind {
>>> eh_personality_none,
>>> diff --git a/gcc/function.c b/gcc/function.c
>>> index 464c6cd..2e46799 100644
>>> --- a/gcc/function.c
>>> +++ b/gcc/function.c
>>> @@ -6093,14 +6093,10 @@ used_types_insert_helper (tree type, struct function *func)
>>> {
>>> if (type != NULL && func != NULL)
>>> {
>>> - void **slot;
>>> -
>>> if (func->used_types_hash == NULL)
>>> - func->used_types_hash = htab_create_ggc (37, htab_hash_pointer,
>>> - htab_eq_pointer, NULL);
>>> - slot = htab_find_slot (func->used_types_hash, type, INSERT);
>>> - if (*slot == NULL)
>>> - *slot = type;
>>> + func->used_types_hash = hash_set<tree>::create_ggc (37);
>>> +
>>> + func->used_types_hash->add (type);
>>> }
>>> }
>>>
>>> diff --git a/gcc/function.h b/gcc/function.h
>>> index 071f5dd..e71210d 100644
>>> --- a/gcc/function.h
>>> +++ b/gcc/function.h
>>> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
>>> #define GCC_FUNCTION_H
>>>
>>> #include "hashtab.h"
>>> +#include "hash-set.h"
>>> #include "vec.h"
>>> #include "machmode.h"
>>> #include "tm.h" /* For CUMULATIVE_ARGS. */
>>> @@ -564,7 +565,7 @@ struct GTY(()) function {
>>> struct language_function * language;
>>>
>>> /* Used types hash table. */
>>> - htab_t GTY ((param_is (union tree_node))) used_types_hash;
>>> + hash_set<tree> *GTY (()) used_types_hash;
>>>
>>> /* Dwarf2 Frame Description Entry, containing the Call Frame Instructions
>>> used for unwinding. Only set when either dwarf2 unwinding or dwarf2
>>> diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
>>> index 3939540..2a9b2d9 100644
>>> --- a/gcc/ggc-page.c
>>> +++ b/gcc/ggc-page.c
>>> @@ -500,6 +500,10 @@ static struct globals
>>> } stats;
>>> } G;
>>>
>>> +/* True if a gc is currently taking place. */
>>> +
>>> +static bool in_gc = false;
>>> +
>>> /* The size in bytes required to maintain a bitmap for the objects
>>> on a page-entry. */
>>> #define BITMAP_SIZE(Num_objects) \
>>> @@ -1574,6 +1578,9 @@ ggc_get_size (const void *p)
>>> void
>>> ggc_free (void *p)
>>> {
>>> + if (in_gc)
>>> + return;
>>> +
>>> page_entry *pe = lookup_page_table_entry (p);
>>> size_t order = pe->order;
>>> size_t size = OBJECT_SIZE (order);
>>> @@ -2139,7 +2146,6 @@ ggc_collect (void)
>>> MAX (G.allocated_last_gc, (size_t)PARAM_VALUE (GGC_MIN_HEAPSIZE) * 1024);
>>>
>>> float min_expand = allocated_last_gc * PARAM_VALUE (GGC_MIN_EXPAND) / 100;
>>> -
>>> if (G.allocated < allocated_last_gc + min_expand && !ggc_force_collect)
>>> return;
>>>
>>> @@ -2162,6 +2168,7 @@ ggc_collect (void)
>>>
>>> invoke_plugin_callbacks (PLUGIN_GGC_START, NULL);
>>>
>>> + in_gc = true;
>>> clear_marks ();
>>> ggc_mark_roots ();
>>> ggc_handle_finalizers ();
>>> @@ -2173,6 +2180,7 @@ ggc_collect (void)
>>> validate_free_objects ();
>>> sweep_pages ();
>>>
>>> + in_gc = false;
>>> G.allocated_last_gc = G.allocated;
>>>
>>> invoke_plugin_callbacks (PLUGIN_GGC_END, NULL);
>>> diff --git a/gcc/ggc.h b/gcc/ggc.h
>>> index 1c0fd3d..6280c43 100644
>>> --- a/gcc/ggc.h
>>> +++ b/gcc/ggc.h
>>> @@ -337,4 +337,25 @@ ggc_alloc_cleared_gimple_statement_stat (size_t s CXX_MEM_STAT_INFO)
>>> ggc_internal_cleared_alloc (s PASS_MEM_STAT);
>>> }
>>>
>>> +static inline void
>>> +gt_ggc_mx (const char *s)
>>> +{
>>> + ggc_test_and_set_mark (const_cast<char *> (s));
>>> +}
>>> +
>>> +static inline void
>>> +gt_pch_nx (const char *)
>>> +{
>>> +}
>>> +
>>> +static inline void
>>> +gt_ggc_mx (int)
>>> +{
>>> +}
>>> +
>>> +static inline void
>>> +gt_pch_nx (int)
>>> +{
>>> +}
>>> +
>>> #endif
>>> diff --git a/gcc/hash-map.h b/gcc/hash-map.h
>>> index d2eed33..c65e1e5 100644
>>> --- a/gcc/hash-map.h
>>> +++ b/gcc/hash-map.h
>>> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
>>> #ifndef hash_map_h
>>> #define hash_map_h
>>>
>>> +#include <new>
>>> #include "hash-table.h"
>>>
>>> /* implement default behavior for traits when types allow it. */
>>> @@ -103,7 +104,7 @@ private:
>>>
>>> template<typename Key, typename Value,
>>> typename Traits = default_hashmap_traits>
>>> -class hash_map
>>> +class GTY((user)) hash_map
>>> {
>>> struct hash_entry
>>> {
>>> @@ -135,10 +136,56 @@ class hash_map
>>>
>>> static void mark_empty (hash_entry &e) { Traits::mark_empty (e); }
>>> static bool is_empty (const hash_entry &e) { return Traits::is_empty (e); }
>>> +
>>> + static void ggc_mx (hash_entry &e)
>>> + {
>>> + gt_ggc_mx (e.m_key);
>>> + gt_ggc_mx (e.m_value);
>>> + }
>>> +
>>> + static void pch_nx (hash_entry &e)
>>> + {
>>> + gt_pch_nx (e.m_key);
>>> + gt_pch_nx (e.m_value);
>>> + }
>>> +
>>> + static void pch_nx (hash_entry &e, gt_pointer_operator op, void *c)
>>> + {
>>> + pch_nx_helper (e.m_key, op, c);
>>> + pch_nx_helper (e.m_value, op, c);
>>> + }
>>> +
>>> + private:
>>> + template<typename T>
>>> + static void
>>> + pch_nx_helper (T &x, gt_pointer_operator op, void *cookie)
>>> + {
>>> + gt_pch_nx (&x, op, cookie);
>>> + }
>>> +
>>> + static void
>>> + pch_nx_helper (int, gt_pointer_operator, void *)
>>> + {
>>> + }
>>> +
>>> + template<typename T>
>>> + static void
>>> + pch_nx_helper (T *&x, gt_pointer_operator op, void *cookie)
>>> + {
>>> + op (&x, cookie);
>>> + }
>>> };
>>>
>>> public:
>>> - explicit hash_map (size_t n = 13) : m_table (n) {}
>>> + explicit hash_map (size_t n = 13, bool ggc = false) : m_table (n, ggc) {}
>>> +
>>> + /* Create a hash_map in ggc memory. */
>>> + static hash_map *create_ggc (size_t size)
>>> + {
>>> + hash_map *map = ggc_alloc<hash_map> ();
>>> + new (map) hash_map (size, true);
>>> + return map;
>>> + }
>>>
>>> /* If key k isn't already in the map add key k with value v to the map, and
>>> return false. Otherwise set the value of the entry for key k to be v and
>>> @@ -208,7 +255,35 @@ public:
>>> }
>>>
>>> private:
>>> +
>>> + template<typename T, typename U, typename V> friend void gt_ggc_mx (hash_map<T, U, V> *);
>>> + template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *);
>>> + template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *, gt_pointer_operator, void *);
>>> +
>>> hash_table<hash_entry> m_table;
>>> };
>>>
>>> +/* ggc marking routines. */
>>> +
>>> +template<typename K, typename V, typename H>
>>> +static inline void
>>> +gt_ggc_mx (hash_map<K, V, H> *h)
>>> +{
>>> + gt_ggc_mx (&h->m_table);
>>> +}
>>> +
>>> +template<typename K, typename V, typename H>
>>> +static inline void
>>> +gt_pch_nx (hash_map<K, V, H> *h)
>>> +{
>>> + gt_pch_nx (&h->m_table);
>>> +}
>>> +
>>> +template<typename K, typename V, typename H>
>>> +static inline void
>>> +gt_pch_nx (hash_map<K, V, H> *h, gt_pointer_operator op, void *cookie)
>>> +{
>>> + op (&h->m_table.m_entries, cookie);
>>> +}
>>> +
>>> #endif
>>> diff --git a/gcc/hash-set.h b/gcc/hash-set.h
>>> index 47bae9e..0a500cb 100644
>>> --- a/gcc/hash-set.h
>>> +++ b/gcc/hash-set.h
>>> @@ -81,6 +81,26 @@ struct default_hashset_traits
>>> /* Return true if the passed in entry is marked as empty. */
>>>
>>> template<typename T> static bool is_empty (T *e) { return e == NULL; }
>>> +
>>> + /* ggc walking routine, mark all objects refered to by this one. */
>>> +
>>> + template<typename T>
>>> + static void
>>> + ggc_mx (T &x)
>>> + {
>>> + extern void gt_ggc_mx (T &);
>>> + gt_ggc_mx (x);
>>> + }
>>> +
>>> + /* pch walking routine, note all objects refered to by this element. */
>>> +
>>> + template<typename T>
>>> + static void
>>> + pch_nx (T &x)
>>> + {
>>> + extern void gt_pch_nx (T &);
>>> + gt_pch_nx (x);
>>> + }
>>> };
>>>
>>> template<typename Key, typename Traits = default_hashset_traits>
>>> @@ -128,10 +148,50 @@ class hash_set
>>> {
>>> return Traits::is_empty (e.m_key);
>>> }
>>> +
>>> + static void ggc_mx (hash_entry &e)
>>> + {
>>> + Traits::ggc_mx (e.m_key);
>>> + }
>>> +
>>> + static void pch_nx (hash_entry &e)
>>> + {
>>> + Traits::pch_nx (e.m_key);
>>> + }
>>> +
>>> + static void pch_nx (hash_entry &e, gt_pointer_operator op, void *c)
>>> + {
>>> + pch_nx_helper (e.m_key, op, c);
>>> + }
>>> +
>>> + private:
>>> + template<typename T>
>>> + static void
>>> + pch_nx_helper (T &x, gt_pointer_operator op, void *cookie)
>>> + {
>>> + gt_pch_nx (&x, op, cookie);
>>> + }
>>> +
>>> + template<typename T>
>>> + static void
>>> + pch_nx_helper (T *&x, gt_pointer_operator op, void *cookie)
>>> + {
>>> + op (&x, cookie);
>>> + }
>>> };
>>>
>>> public:
>>> - explicit hash_set (size_t n = 13) : m_table (n) {}
>>> + explicit hash_set (size_t n = 13, bool ggc = false) : m_table (n, ggc) {}
>>> +
>>> + /* Create a hash_set in gc memory with space for at least n elements. */
>>> +
>>> + static hash_set *
>>> + create_ggc (size_t n)
>>> + {
>>> + hash_set *set = ggc_alloc<hash_set> ();
>>> + new (set) hash_set (n, true);
>>> + return set;
>>> + }
>>>
>>> /* If key k isn't already in the map add it to the map, and
>>> return false. Otherwise return true. */
>>> @@ -166,8 +226,40 @@ public:
>>> f ((*iter).m_key, a);
>>> }
>>>
>>> + /* Return the number of elements in the set. */
>>> +
>>> + size_t elements () const { return m_table.elements (); }
>>> +
>>> private:
>>> +
>>> + template<typename T, typename U> friend void gt_ggc_mx (hash_set<T, U> *);
>>> + template<typename T, typename U> friend void gt_pch_nx (hash_set<T, U> *);
>>> + template<typename T, typename U> friend void gt_pch_nx (hash_set<T, U> *, gt_pointer_operator, void *);
>>> +
>>> hash_table<hash_entry> m_table;
>>> };
>>>
>>> +/* ggc marking routines. */
>>> +
>>> +template<typename K, typename H>
>>> +static inline void
>>> +gt_ggc_mx (hash_set<K, H> *h)
>>> +{
>>> + gt_ggc_mx (&h->m_table);
>>> +}
>>> +
>>> +template<typename K, typename H>
>>> +static inline void
>>> +gt_pch_nx (hash_set<K, H> *h)
>>> +{
>>> + gt_pch_nx (&h->m_table);
>>> +}
>>> +
>>> +template<typename K, typename H>
>>> +static inline void
>>> +gt_pch_nx (hash_set<K, H> *h, gt_pointer_operator op, void *cookie)
>>> +{
>>> + op (&h->m_table.m_entries, cookie);
>>> +}
>>> +
>>> #endif
>>> diff --git a/gcc/hash-table.h b/gcc/hash-table.h
>>> index 9c6a34a..4c18786 100644
>>> --- a/gcc/hash-table.h
>>> +++ b/gcc/hash-table.h
>>> @@ -196,8 +196,11 @@ along with GCC; see the file COPYING3. If not see
>>> #ifndef TYPED_HASHTAB_H
>>> #define TYPED_HASHTAB_H
>>>
>>> +#include "ggc.h"
>>> #include "hashtab.h"
>>>
>>> +template<typename, typename, typename> class hash_map;
>>> +template<typename, typename> class hash_set;
>>>
>>> /* The ordinary memory allocator. */
>>> /* FIXME (crowl): This allocator may be extracted for wider sharing later. */
>>> @@ -998,7 +1001,7 @@ class hash_table<Descriptor, Allocator, true>
>>> typedef typename Descriptor::compare_type compare_type;
>>>
>>> public:
>>> - hash_table (size_t);
>>> + explicit hash_table (size_t, bool ggc = false);
>>> ~hash_table ();
>>>
>>> /* Current size (in entries) of the hash table. */
>>> @@ -1105,6 +1108,11 @@ public:
>>> }
>>>
>>> private:
>>> + template<typename T> friend void gt_ggc_mx (hash_table<T> *);
>>> + template<typename T> friend void gt_pch_nx (hash_table<T> *);
>>> + template<typename T> friend void hashtab_entry_note_pointers (void *, void *, gt_pointer_operator, void *);
>>> + template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *, gt_pointer_operator, void *);
>>> + template<typename T, typename U> friend void gt_pch_nx (hash_set<T, U> *, gt_pointer_operator, void *);
>>>
>>> value_type *find_empty_slot_for_expand (hashval_t);
>>> void expand ();
>>> @@ -1149,18 +1157,26 @@ private:
>>> /* Current size (in entries) of the hash table, as an index into the
>>> table of primes. */
>>> unsigned int m_size_prime_index;
>>> +
>>> + /* if m_entries is stored in ggc memory. */
>>> + bool m_ggc;
>>> };
>>>
>>> template<typename Descriptor, template<typename Type> class Allocator>
>>> -hash_table<Descriptor, Allocator, true>::hash_table (size_t size) :
>>> - m_n_elements (0), m_n_deleted (0), m_searches (0), m_collisions (0)
>>> +hash_table<Descriptor, Allocator, true>::hash_table (size_t size, bool ggc) :
>>> + m_n_elements (0), m_n_deleted (0), m_searches (0), m_collisions (0),
>>> + m_ggc (ggc)
>>> {
>>> unsigned int size_prime_index;
>>>
>>> size_prime_index = hash_table_higher_prime_index (size);
>>> size = prime_tab[size_prime_index].prime;
>>>
>>> - m_entries = Allocator <value_type> ::data_alloc (size);
>>> + if (!m_ggc)
>>> + m_entries = Allocator <value_type> ::data_alloc (size);
>>> + else
>>> + m_entries = ggc_cleared_vec_alloc<value_type> (size);
>>> +
>>> gcc_assert (m_entries != NULL);
>>> m_size = size;
>>> m_size_prime_index = size_prime_index;
>>> @@ -1173,7 +1189,10 @@ hash_table<Descriptor, Allocator, true>::~hash_table ()
>>> if (!is_empty (m_entries[i]) && !is_deleted (m_entries[i]))
>>> Descriptor::remove (m_entries[i]);
>>>
>>> - Allocator <value_type> ::data_free (m_entries);
>>> + if (!m_ggc)
>>> + Allocator <value_type> ::data_free (m_entries);
>>> + else
>>> + ggc_free (m_entries);
>>> }
>>>
>>> /* Similar to find_slot, but without several unwanted side effects:
>>> @@ -1245,7 +1264,12 @@ hash_table<Descriptor, Allocator, true>::expand ()
>>> nsize = osize;
>>> }
>>>
>>> - value_type *nentries = Allocator <value_type> ::data_alloc (nsize);
>>> + value_type *nentries;
>>> + if (!m_ggc)
>>> + nentries = Allocator <value_type> ::data_alloc (nsize);
>>> + else
>>> + nentries = ggc_cleared_vec_alloc<value_type> (nsize);
>>> +
>>> gcc_assert (nentries != NULL);
>>> m_entries = nentries;
>>> m_size = nsize;
>>> @@ -1269,7 +1293,10 @@ hash_table<Descriptor, Allocator, true>::expand ()
>>> }
>>> while (p < olimit);
>>>
>>> - Allocator <value_type> ::data_free (oentries);
>>> + if (!m_ggc)
>>> + Allocator <value_type> ::data_free (oentries);
>>> + else
>>> + ggc_free (oentries);
>>> }
>>>
>>> template<typename Descriptor, template<typename Type> class Allocator>
>>> @@ -1290,8 +1317,17 @@ hash_table<Descriptor, Allocator, true>::empty ()
>>> int nindex = hash_table_higher_prime_index (1024 / sizeof (PTR));
>>> int nsize = prime_tab[nindex].prime;
>>>
>>> - Allocator <value_type> ::data_free (m_entries);
>>> - m_entries = Allocator <value_type> ::data_alloc (nsize);
>>> + if (!m_ggc)
>>> + {
>>> + Allocator <value_type> ::data_free (m_entries);
>>> + m_entries = Allocator <value_type> ::data_alloc (nsize);
>>> + }
>>> + else
>>> + {
>>> + ggc_free (m_entries);
>>> + m_entries = ggc_cleared_vec_alloc<value_type> (nsize);
>>> + }
>>> +
>>> m_size = nsize;
>>> m_size_prime_index = nindex;
>>> }
>>> @@ -1519,4 +1555,59 @@ hash_table<Descriptor, Allocator, true>::iterator::operator ++ ()
>>> (ITER) != (HTAB).end () ? (RESULT = *(ITER) , true) : false; \
>>> ++(ITER))
>>>
>>> +/* ggc walking routines. */
>>> +
>>> +template<typename E>
>>> +static inline void
>>> +gt_ggc_mx (hash_table<E> *h)
>>> +{
>>> + typedef hash_table<E> table;
>>> +
>>> + if (!ggc_test_and_set_mark (h->m_entries))
>>> + return;
>>> +
>>> + for (size_t i = 0; i < h->m_size; i++)
>>> + {
>>> + if (table::is_empty (h->m_entries[i])
>>> + || table::is_deleted (h->m_entries[i]))
>>> + continue;
>>> +
>>> + E::ggc_mx (h->m_entries[i]);
>>> + }
>>> +}
>>> +
>>> +template<typename D>
>>> +static inline void
>>> +hashtab_entry_note_pointers (void *obj, void *h, gt_pointer_operator op,
>>> + void *cookie)
>>> +{
>>> + hash_table<D> *map = static_cast<hash_table<D> *> (h);
>>> + gcc_assert (map->m_entries == obj);
>>> + for (size_t i = 0; i < map->m_size; i++)
>>> + {
>>> + typedef hash_table<D> table;
>>> + if (table::is_empty (map->m_entries[i])
>>> + || table::is_deleted (map->m_entries[i]))
>>> + continue;
>>> +
>>> + D::pch_nx (map->m_entries[i], op, cookie);
>>> + }
>>> +}
>>> +
>>> +template<typename D>
>>> +static void
>>> +gt_pch_nx (hash_table<D> *h)
>>> +{
>>> + gcc_assert (gt_pch_note_object (h->m_entries, h,
>>> + hashtab_entry_note_pointers<D>));
>>> + for (size_t i = 0; i < h->m_size; i++)
>>> + {
>>> + if (hash_table<D>::is_empty (h->m_entries[i])
>>> + || hash_table<D>::is_deleted (h->m_entries[i]))
>>> + continue;
>>> +
>>> + D::pch_nx (h->m_entries[i]);
>>> + }
>>> +}
>>> +
>>> #endif /* TYPED_HASHTAB_H */
>>> diff --git a/gcc/symtab.c b/gcc/symtab.c
>>> index 739a8e4..792b3b5 100644
>>> --- a/gcc/symtab.c
>>> +++ b/gcc/symtab.c
>>> @@ -407,15 +407,7 @@ symtab_node::unregister (void)
>>> if (!is_a <varpool_node *> (this) || !DECL_HARD_REGISTER (decl))
>>> symtab->unlink_from_assembler_name_hash (this, false);
>>> if (in_init_priority_hash)
>>> - {
>>> - symbol_priority_map in;
>>> - void **slot;
>>> - in.symbol = this;
>>> -
>>> - slot = htab_find_slot (symtab->init_priority_hash, &in, NO_INSERT);
>>> - if (slot)
>>> - htab_clear_slot (symtab->init_priority_hash, slot);
>>> - }
>>> + symtab->init_priority_hash->remove (this);
>>> }
>>>
>>>
>>> @@ -1455,14 +1447,10 @@ symtab_node::set_section (const char *section)
>>> priority_type
>>> symtab_node::get_init_priority ()
>>> {
>>> - symbol_priority_map *h;
>>> - symbol_priority_map in;
>>> -
>>> if (!this->in_init_priority_hash)
>>> return DEFAULT_INIT_PRIORITY;
>>> - in.symbol = this;
>>> - h = (symbol_priority_map *) htab_find (symtab->init_priority_hash,
>>> - &in);
>>> +
>>> + symbol_priority_map *h = symtab->init_priority_hash->get (this);
>>> return h ? h->init : DEFAULT_INIT_PRIORITY;
>>> }
>>>
>>> @@ -1481,35 +1469,12 @@ enum availability symtab_node::get_availability (void)
>>> priority_type
>>> cgraph_node::get_fini_priority ()
>>> {
>>> - symbol_priority_map *h;
>>> - symbol_priority_map in;
>>> -
>>> if (!this->in_init_priority_hash)
>>> return DEFAULT_INIT_PRIORITY;
>>> - in.symbol = this;
>>> - h = (symbol_priority_map *) htab_find (symtab->init_priority_hash,
>>> - &in);
>>> + symbol_priority_map *h = symtab->init_priority_hash->get (this);
>>> return h ? h->fini : DEFAULT_INIT_PRIORITY;
>>> }
>>>
>>> -/* Return true if the from tree in both priority maps are equal. */
>>> -
>>> -int
>>> -symbol_priority_map_eq (const void *va, const void *vb)
>>> -{
>>> - const symbol_priority_map *const a = (const symbol_priority_map *) va,
>>> - *const b = (const symbol_priority_map *) vb;
>>> - return (a->symbol == b->symbol);
>>> -}
>>> -
>>> -/* Hash a from symbol in a symbol_priority_map. */
>>> -
>>> -unsigned int
>>> -symbol_priority_map_hash (const void *item)
>>> -{
>>> - return htab_hash_pointer (((const symbol_priority_map *)item)->symbol);
>>> -}
>>> -
>>> /* Return the initialization and finalization priority information for
>>> DECL. If there is no previous priority information, a freshly
>>> allocated structure is returned. */
>>> @@ -1517,23 +1482,14 @@ symbol_priority_map_hash (const void *item)
>>> symbol_priority_map *
>>> symtab_node::priority_info (void)
>>> {
>>> - symbol_priority_map in;
>>> - symbol_priority_map *h;
>>> - void **loc;
>>> -
>>> - in.symbol = this;
>>> if (!symtab->init_priority_hash)
>>> - symtab->init_priority_hash = htab_create_ggc (512,
>>> - symbol_priority_map_hash,
>>> - symbol_priority_map_eq, 0);
>>> + symtab->init_priority_hash = hash_map<symtab_node *, symbol_priority_map>::create_ggc (13);
>>>
>>> - loc = htab_find_slot (symtab->init_priority_hash, &in, INSERT);
>>> - h = (symbol_priority_map *) *loc;
>>> - if (!h)
>>> + bool existed;
>>> + symbol_priority_map *h
>>> + = &symtab->init_priority_hash->get_or_insert (this, &existed);
>>> + if (!existed)
>>> {
>>> - h = ggc_cleared_alloc<symbol_priority_map> ();
>>> - *loc = h;
>>> - h->symbol = this;
>>> h->init = DEFAULT_INIT_PRIORITY;
>>> h->fini = DEFAULT_INIT_PRIORITY;
>>> in_init_priority_hash = true;
>>> diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
>>> index c75516d..e89d76a 100644
>>> --- a/gcc/tree-cfg.c
>>> +++ b/gcc/tree-cfg.c
>>> @@ -4723,19 +4723,17 @@ verify_node_sharing (tree *tp, int *walk_subtrees, void *data)
>>> }
>>>
>>> static bool eh_error_found;
>>> -static int
>>> -verify_eh_throw_stmt_node (void **slot, void *data)
>>> +bool
>>> +verify_eh_throw_stmt_node (const gimple &stmt, const int &,
>>> + hash_set<gimple> *visited)
>>> {
>>> - struct throw_stmt_node *node = (struct throw_stmt_node *)*slot;
>>> - hash_set<void *> *visited = (hash_set<void *> *) data;
>>> -
>>> - if (!visited->contains (node->stmt))
>>> + if (!visited->contains (stmt))
>>> {
>>> error ("dead STMT in EH table");
>>> - debug_gimple_stmt (node->stmt);
>>> + debug_gimple_stmt (stmt);
>>> eh_error_found = true;
>>> }
>>> - return 1;
>>> + return true;
>>> }
>>>
>>> /* Verify if the location LOCs block is in BLOCKS. */
>>> @@ -4996,10 +4994,10 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>>> }
>>>
>>> eh_error_found = false;
>>> - if (get_eh_throw_stmt_table (cfun))
>>> - htab_traverse (get_eh_throw_stmt_table (cfun),
>>> - verify_eh_throw_stmt_node,
>>> - &visited_stmts);
>>> + hash_map<gimple, int> *eh_table = get_eh_throw_stmt_table (cfun);
>>> + if (eh_table)
>>> + eh_table->traverse<hash_set<gimple> *, verify_eh_throw_stmt_node>
>>> + (&visited_stmts);
>>>
>>> if (err || eh_error_found)
>>> internal_error ("verify_gimple failed");
>>> diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
>>> index 6c6faf3..9da8da2 100644
>>> --- a/gcc/tree-eh.c
>>> +++ b/gcc/tree-eh.c
>>> @@ -77,23 +77,12 @@ typedef union {tree *tp; tree t; gimple g;} treemple;
>>> static void
>>> add_stmt_to_eh_lp_fn (struct function *ifun, gimple t, int num)
>>> {
>>> - struct throw_stmt_node *n;
>>> - void **slot;
>>> -
>>> gcc_assert (num != 0);
>>>
>>> - n = ggc_alloc<throw_stmt_node> ();
>>> - n->stmt = t;
>>> - n->lp_nr = num;
>>> -
>>> if (!get_eh_throw_stmt_table (ifun))
>>> - set_eh_throw_stmt_table (ifun, htab_create_ggc (31, struct_ptr_hash,
>>> - struct_ptr_eq,
>>> - ggc_free));
>>> + set_eh_throw_stmt_table (ifun, hash_map<gimple, int>::create_ggc (31));
>>>
>>> - slot = htab_find_slot (get_eh_throw_stmt_table (ifun), n, INSERT);
>>> - gcc_assert (!*slot);
>>> - *slot = n;
>>> + gcc_assert (!get_eh_throw_stmt_table (ifun)->put (t, num));
>>> }
>>>
>>> /* Add statement T in the current function (cfun) to EH landing pad NUM. */
>>> @@ -130,22 +119,14 @@ record_stmt_eh_region (eh_region region, gimple t)
>>> bool
>>> remove_stmt_from_eh_lp_fn (struct function *ifun, gimple t)
>>> {
>>> - struct throw_stmt_node dummy;
>>> - void **slot;
>>> -
>>> if (!get_eh_throw_stmt_table (ifun))
>>> return false;
>>>
>>> - dummy.stmt = t;
>>> - slot = htab_find_slot (get_eh_throw_stmt_table (ifun), &dummy,
>>> - NO_INSERT);
>>> - if (slot)
>>> - {
>>> - htab_clear_slot (get_eh_throw_stmt_table (ifun), slot);
>>> - return true;
>>> - }
>>> - else
>>> + if (!get_eh_throw_stmt_table (ifun)->get (t))
>>> return false;
>>> +
>>> + get_eh_throw_stmt_table (ifun)->remove (t);
>>> + return true;
>>> }
>>>
>>>
>>> @@ -166,14 +147,11 @@ remove_stmt_from_eh_lp (gimple t)
>>> int
>>> lookup_stmt_eh_lp_fn (struct function *ifun, gimple t)
>>> {
>>> - struct throw_stmt_node *p, n;
>>> -
>>> if (ifun->eh->throw_stmt_table == NULL)
>>> return 0;
>>>
>>> - n.stmt = t;
>>> - p = (struct throw_stmt_node *) htab_find (ifun->eh->throw_stmt_table, &n);
>>> - return p ? p->lp_nr : 0;
>>> + int *lp_nr = ifun->eh->throw_stmt_table->get (t);
>>> + return lp_nr ? *lp_nr : 0;
>>> }
>>>
>>> /* Likewise, but always use the current function. */
>>> --
>>> 2.1.0
>
next prev parent reply other threads:[~2014-10-17 13:31 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-02 1:57 tsaunders
2014-09-02 8:36 ` Richard Biener
2014-09-02 11:57 ` Trevor Saunders
[not found] ` <540F10A6.5010807@arm.com>
2014-09-09 14:40 ` Alan Lawrence
2014-09-10 2:14 ` Trevor Saunders
2014-10-17 13:36 ` Alan Lawrence [this message]
2014-10-14 14:12 ` Richard Biener
2014-10-15 4:23 ` Trevor Saunders
2014-10-15 7:34 ` Richard Biener
2023-07-06 18:53 ` GGC: Remove 'const char *' 'gt_ggc_mx', 'gt_pch_nx' variants (was: [PATCH] support ggc hash_map and hash_set) Thomas Schwinge
2023-07-07 6:20 ` Richard Biener
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=54411A11.8060001@arm.com \
--to=alan.lawrence@arm.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=tsaunders@mozilla.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).