mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-22 21:41:28 +08:00
Revert my last two changes, r201865 and r201864
2013-08-20 David Malcolm <dmalcolm@redhat.com> Revert my last two changes, r201865 and r201864: Revert r201865: 2013-08-20 David Malcolm <dmalcolm@redhat.com> Make opt_pass and gcc::pass_manager be GC-managed, so that pass instances can own GC refs. * Makefile.in (GTFILES): Add pass_manager.h and tree-pass.h. * context.c (gcc::context::gt_ggc_mx): Traverse passes_. (gcc::context::gt_pch_nx): Likewise. (gcc::context::gt_pch_nx): Likewise. * ggc.h (gt_ggc_mx <T>): New. (gt_pch_nx_with_op <T>): New. (gt_pch_nx <T>): New. * passes.c (opt_pass::gt_ggc_mx): New. (opt_pass::gt_pch_nx): New. (opt_pass::gt_pch_nx_with_op): New. (pass_manager::gt_ggc_mx): New. (pass_manager::gt_pch_nx): New. (pass_manager::gt_pch_nx_with_op): New. (pass_manager::operator new): Use ggc_internal_cleared_alloc_stat rather than xcalloc. * pass_manager.h (class pass_manager): Add GTY((user)) marking. (pass_manager::gt_ggc_mx): New. (pass_manager::gt_pch_nx): New. (pass_manager::gt_pch_nx_with_op): New. * tree-pass.h (class opt_pass): Add GTY((user)) marking. (opt_pass::operator new): New. (opt_pass::gt_ggc_mx): New. (opt_pass::gt_pch_nx): New. (opt_pass::gt_pch_nx_with_op): New. Revert r201864: 2013-08-20 David Malcolm <dmalcolm@redhat.com> * Makefile.in (GTFILES): Add context.h. * context.c (gcc::context::operator new): New. (gcc::context::gt_ggc_mx): New. (gcc::context::gt_pch_nx): New. (gcc::context::gt_pch_nx): New. * context.h (gcc::context): Add GTY((user)) marking. (gcc::context::operator new): New. (gcc::context::gt_ggc_mx): New. (gcc::context::gt_pch_nx): New. (gcc::context::gt_pch_nx): New. (g): Add GTY marking. (gt_ggc_mx (gcc::context *)): New. (gt_pch_nx (gcc::context *)): New. (gt_pch_nx (gcc::context *ctxt, gt_pointer_operator op, void *cookie)): New. * gengtype.c (open_base_files) <ifiles>: Add context.h. From-SVN: r201887
This commit is contained in:
parent
a046136a50
commit
6cd4d135d7
@ -1,3 +1,58 @@
|
||||
2013-08-20 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
Revert my last two changes, r201865 and r201864:
|
||||
|
||||
Revert r201865:
|
||||
2013-08-20 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
Make opt_pass and gcc::pass_manager be GC-managed, so that pass
|
||||
instances can own GC refs.
|
||||
|
||||
* Makefile.in (GTFILES): Add pass_manager.h and tree-pass.h.
|
||||
* context.c (gcc::context::gt_ggc_mx): Traverse passes_.
|
||||
(gcc::context::gt_pch_nx): Likewise.
|
||||
(gcc::context::gt_pch_nx): Likewise.
|
||||
* ggc.h (gt_ggc_mx <T>): New.
|
||||
(gt_pch_nx_with_op <T>): New.
|
||||
(gt_pch_nx <T>): New.
|
||||
* passes.c (opt_pass::gt_ggc_mx): New.
|
||||
(opt_pass::gt_pch_nx): New.
|
||||
(opt_pass::gt_pch_nx_with_op): New.
|
||||
(pass_manager::gt_ggc_mx): New.
|
||||
(pass_manager::gt_pch_nx): New.
|
||||
(pass_manager::gt_pch_nx_with_op): New.
|
||||
(pass_manager::operator new): Use
|
||||
ggc_internal_cleared_alloc_stat rather than xcalloc.
|
||||
* pass_manager.h (class pass_manager): Add GTY((user)) marking.
|
||||
(pass_manager::gt_ggc_mx): New.
|
||||
(pass_manager::gt_pch_nx): New.
|
||||
(pass_manager::gt_pch_nx_with_op): New.
|
||||
* tree-pass.h (class opt_pass): Add GTY((user)) marking.
|
||||
(opt_pass::operator new): New.
|
||||
(opt_pass::gt_ggc_mx): New.
|
||||
(opt_pass::gt_pch_nx): New.
|
||||
(opt_pass::gt_pch_nx_with_op): New.
|
||||
|
||||
Revert r201864:
|
||||
2013-08-20 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* Makefile.in (GTFILES): Add context.h.
|
||||
* context.c (gcc::context::operator new): New.
|
||||
(gcc::context::gt_ggc_mx): New.
|
||||
(gcc::context::gt_pch_nx): New.
|
||||
(gcc::context::gt_pch_nx): New.
|
||||
* context.h (gcc::context): Add GTY((user)) marking.
|
||||
(gcc::context::operator new): New.
|
||||
(gcc::context::gt_ggc_mx): New.
|
||||
(gcc::context::gt_pch_nx): New.
|
||||
(gcc::context::gt_pch_nx): New.
|
||||
(g): Add GTY marking.
|
||||
(gt_ggc_mx (gcc::context *)): New.
|
||||
(gt_pch_nx (gcc::context *)): New.
|
||||
(gt_pch_nx (gcc::context *ctxt, gt_pointer_operator op,
|
||||
void *cookie)): New.
|
||||
* gengtype.c (open_base_files) <ifiles>: Add context.h.
|
||||
|
||||
2013-08-20 Alexey Makhalov <makhaloff@gmail.com>
|
||||
|
||||
* dce.c (fini_dce): Call df_analyze again just in case
|
||||
|
@ -3831,9 +3831,6 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
|
||||
$(srcdir)/vtable-verify.c \
|
||||
$(srcdir)/asan.c \
|
||||
$(srcdir)/tsan.c $(srcdir)/ipa-devirt.c \
|
||||
$(srcdir)/context.h \
|
||||
$(srcdir)/pass_manager.h \
|
||||
$(srcdir)/tree-pass.h \
|
||||
@all_gtfiles@
|
||||
|
||||
# Compute the list of GT header files from the corresponding C sources,
|
||||
|
@ -27,33 +27,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
/* The singleton holder of global state: */
|
||||
gcc::context *g;
|
||||
|
||||
void *
|
||||
gcc::context::operator new (std::size_t size)
|
||||
{
|
||||
return ggc_internal_cleared_alloc_stat (size MEM_STAT_INFO);
|
||||
}
|
||||
|
||||
gcc::context::context()
|
||||
{
|
||||
passes_ = new gcc::pass_manager (this);
|
||||
}
|
||||
|
||||
/* Functions relating to the garbage collector. */
|
||||
void
|
||||
gcc::context::gt_ggc_mx ()
|
||||
{
|
||||
::gt_ggc_mx (passes_);
|
||||
}
|
||||
|
||||
void
|
||||
gcc::context::gt_pch_nx ()
|
||||
{
|
||||
::gt_pch_nx (passes_);
|
||||
}
|
||||
|
||||
void
|
||||
gcc::context::gt_pch_nx (gt_pointer_operator op ATTRIBUTE_UNUSED,
|
||||
void *cookie ATTRIBUTE_UNUSED)
|
||||
{
|
||||
op (&passes_, cookie);
|
||||
}
|
||||
|
@ -27,30 +27,11 @@ class pass_manager;
|
||||
/* GCC's internal state can be divided into zero or more
|
||||
"parallel universe" of state; an instance of this class is one such
|
||||
context of state. */
|
||||
class GTY((user)) context
|
||||
class context
|
||||
{
|
||||
public:
|
||||
/* Ensure that instances are allocated within the GC-heap. */
|
||||
void *operator new (std::size_t size);
|
||||
|
||||
context();
|
||||
|
||||
/* Garbage-collector integration.
|
||||
|
||||
Each context assumes it has full control of the GC-heap that it
|
||||
is associated with. It acts as a root for that GC-heap, owning
|
||||
references to within it.
|
||||
|
||||
Note that context instances are allocated within their own GC
|
||||
heap.
|
||||
|
||||
The methods are called the *first time* that the context is reached
|
||||
during a ggc/pch traversal, rather than every time. */
|
||||
|
||||
void gt_ggc_mx ();
|
||||
void gt_pch_nx ();
|
||||
void gt_pch_nx (gt_pointer_operator op, void *cookie);
|
||||
|
||||
/* Pass-management. */
|
||||
|
||||
pass_manager *get_passes () { gcc_assert (passes_); return passes_; }
|
||||
@ -65,42 +46,6 @@ private:
|
||||
|
||||
/* The global singleton context aka "g".
|
||||
(the name is chosen to be easy to type in a debugger). */
|
||||
extern GTY(()) gcc::context *g;
|
||||
|
||||
/* Global hooks for ggc/pch.
|
||||
|
||||
The gcc::context class is marked with GTY((user)), which leads to
|
||||
gengtype creating autogenerated functions for handling context within
|
||||
gtype-desc.c:
|
||||
|
||||
void gt_ggc_mx_context (void *x_p);
|
||||
void gt_pch_nx_context (void *x_p)
|
||||
void gt_pch_p_7context (void *this_obj,
|
||||
void *x_p,
|
||||
gt_pointer_operator op,
|
||||
void *cookie);
|
||||
|
||||
Those functions call the following global functions the first time
|
||||
that the context is reached during a traversal, and the following
|
||||
global functions in turn simply call the corresponding methods of the
|
||||
context (so that they can access private fields of the context). */
|
||||
|
||||
inline void
|
||||
gt_ggc_mx (gcc::context *ctxt)
|
||||
{
|
||||
ctxt->gt_ggc_mx ();
|
||||
}
|
||||
|
||||
inline void
|
||||
gt_pch_nx (gcc::context *ctxt)
|
||||
{
|
||||
ctxt->gt_pch_nx ();
|
||||
}
|
||||
|
||||
inline void
|
||||
gt_pch_nx (gcc::context *ctxt, gt_pointer_operator op, void *cookie)
|
||||
{
|
||||
ctxt->gt_pch_nx (op, cookie);
|
||||
}
|
||||
extern gcc::context *g;
|
||||
|
||||
#endif /* ! GCC_CONTEXT_H */
|
||||
|
@ -1739,7 +1739,7 @@ open_base_files (void)
|
||||
"tree-flow.h", "reload.h", "cpp-id-data.h", "tree-chrec.h",
|
||||
"except.h", "output.h", "gimple.h", "cfgloop.h",
|
||||
"target.h", "ipa-prop.h", "lto-streamer.h", "target-globals.h",
|
||||
"ipa-inline.h", "dwarf2out.h", "context.h", NULL
|
||||
"ipa-inline.h", "dwarf2out.h", NULL
|
||||
};
|
||||
const char *const *ifp;
|
||||
outf_p gtype_desc_c;
|
||||
|
46
gcc/ggc.h
46
gcc/ggc.h
@ -276,50 +276,4 @@ ggc_alloc_cleared_gimple_statement_d_stat (size_t s MEM_STAT_DECL)
|
||||
ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
|
||||
}
|
||||
|
||||
/* gengtype will autogenerate traversal functions (in gtype-desc.c) for
|
||||
all GTY-marked types that it sees are referenced by a GTY marker.
|
||||
|
||||
Unfortunately, it will not generate traveral functions for types that
|
||||
are only referenced by GTY((user)) types.
|
||||
|
||||
The following templates are a substitute, providing equivalent
|
||||
traversal functions for such types. They are instantiated for
|
||||
types whose objects that are traversed during GC/PCH, and are
|
||||
called *every time* that an instance of type T is traversed during
|
||||
GC/PCH.
|
||||
|
||||
They require the presence of the following member functions
|
||||
|
||||
void gt_ggc_mx ();
|
||||
void gt_pch_nx ();
|
||||
void gt_pch_nx_with_op (gt_pointer_operator op, void *cookie);
|
||||
|
||||
within class T, which are called *once* per object - the first
|
||||
time the object is visited during the traversal. */
|
||||
|
||||
template<class T>
|
||||
inline void gt_ggc_mx (T *p)
|
||||
{
|
||||
if (ggc_test_and_set_mark (p))
|
||||
p->gt_ggc_mx ();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void gt_pch_nx_with_op (void *this_obj, void *p,
|
||||
gt_pointer_operator op, void *cookie)
|
||||
{
|
||||
if (p == this_obj)
|
||||
{
|
||||
T *t = static_cast<T *>(p);
|
||||
t->gt_pch_nx_with_op (op, cookie);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void gt_pch_nx (T *p)
|
||||
{
|
||||
if (gt_pch_note_object (p, p, gt_pch_nx_with_op<T>))
|
||||
p->gt_pch_nx ();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -44,19 +44,13 @@ namespace gcc {
|
||||
|
||||
class context;
|
||||
|
||||
class GTY((user)) pass_manager
|
||||
class pass_manager
|
||||
{
|
||||
public:
|
||||
/* Ensure that instances are allocated in the GC-managed heap. */
|
||||
void *operator new (size_t sz);
|
||||
|
||||
pass_manager(context *ctxt);
|
||||
|
||||
/* GTY((user)) methods. */
|
||||
void gt_ggc_mx ();
|
||||
void gt_pch_nx ();
|
||||
void gt_pch_nx_with_op (gt_pointer_operator op, void *cookie);
|
||||
|
||||
void register_pass (struct register_pass_info *pass_info);
|
||||
void register_one_dump_file (struct opt_pass *pass);
|
||||
|
||||
@ -140,3 +134,4 @@ private:
|
||||
} // namespace gcc
|
||||
|
||||
#endif /* ! GCC_PASS_MANAGER_H */
|
||||
|
||||
|
140
gcc/passes.c
140
gcc/passes.c
@ -82,58 +82,6 @@ struct opt_pass *current_pass;
|
||||
|
||||
static void register_pass_name (struct opt_pass *, const char *);
|
||||
|
||||
void*
|
||||
opt_pass::operator new (size_t sz)
|
||||
{
|
||||
return ggc_internal_cleared_alloc_stat (sz MEM_STAT_INFO);
|
||||
}
|
||||
|
||||
void opt_pass::gt_ggc_mx ()
|
||||
{
|
||||
::gt_ggc_mx (ctxt_);
|
||||
::gt_ggc_mx (sub);
|
||||
|
||||
/* Avoid deep stack usage by iteratively walking the chain of "next"
|
||||
passes, rather than recursing (analogous to the chain_next/chain_prev
|
||||
GTY options). */
|
||||
|
||||
/* "this" has already been marked.
|
||||
Mark a chain of as-yet-unmarked passes. */
|
||||
opt_pass *limit = this->next;
|
||||
while (ggc_test_and_set_mark (limit))
|
||||
limit = limit->next;
|
||||
|
||||
/* "limit" is the first in the chain that wasn't just marked, either
|
||||
because it is NULL, or because it was already marked.
|
||||
Hence all of the passes in the half-open interval:
|
||||
[this->next...limit)
|
||||
have just been marked: visit them. */
|
||||
for (opt_pass *iter = this->next; iter != limit; iter = iter->next)
|
||||
iter->gt_ggc_mx ();
|
||||
}
|
||||
|
||||
void opt_pass::gt_pch_nx ()
|
||||
{
|
||||
::gt_pch_nx (ctxt_);
|
||||
::gt_pch_nx (sub);
|
||||
|
||||
/* Analogous to opt_pass::gt_ggc_mx. */
|
||||
opt_pass *limit = this->next;
|
||||
while (gt_pch_note_object (limit, limit, ::gt_pch_nx_with_op<opt_pass>))
|
||||
limit = limit->next;
|
||||
|
||||
for (opt_pass *iter = this->next; iter != limit; iter = iter->next)
|
||||
iter->gt_pch_nx ();
|
||||
|
||||
}
|
||||
|
||||
void opt_pass::gt_pch_nx_with_op (gt_pointer_operator op, void *cookie)
|
||||
{
|
||||
op (&(ctxt_), cookie);
|
||||
op (&(sub), cookie);
|
||||
op (&(next), cookie);
|
||||
}
|
||||
|
||||
/* Most passes are single-instance (within their context) and thus don't
|
||||
need to implement cloning, but passes that support multiple instances
|
||||
*must* provide their own implementation of the clone method.
|
||||
@ -168,92 +116,6 @@ opt_pass::opt_pass(const pass_data &data, context *ctxt)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
pass_manager::gt_ggc_mx ()
|
||||
{
|
||||
/* We want to efficiently visit all pass objects without incurring deep
|
||||
call chains that could blow the stack.
|
||||
|
||||
Although there are multiple fields referencing passes within the
|
||||
pass_manager, *almost* all of the underlying pass instances are
|
||||
referenced by the passes_by_id array.
|
||||
|
||||
Specifically, passes are in the passes_by_id array if they have
|
||||
register_one_dump_file called on them, which requires them to have
|
||||
a name, and for that name to *not* begin with "*". Currently
|
||||
there are 25 passes with a "*" prefix and thus not in the array.
|
||||
|
||||
Each pass holds references to its sub and next, so visiting a pass
|
||||
will potentially trigger a recursive traversal through these
|
||||
neighbours - if these passes haven't been visited yet.
|
||||
|
||||
By walking the passes_by_id array *backwards*, in the common case
|
||||
this leads to us walking the pass tree from the leaf passes first,
|
||||
eventually reaching the trunk passes, and hence none of the calls
|
||||
should recurse, given that at each point in the iteration pass->sub
|
||||
and pass->next will already have been marked.
|
||||
|
||||
Having walked the array, we then walk the higher-level fields,
|
||||
again in bottom-up order, which will ensure that we visit all
|
||||
remaining passes. Most of the passes will have already been
|
||||
visited, which should minimize further recursion. */
|
||||
for (int i = passes_by_id_size ; i > 0; )
|
||||
::gt_ggc_mx (passes_by_id[--i]);
|
||||
|
||||
::gt_ggc_mx (all_late_ipa_passes);
|
||||
::gt_ggc_mx (all_lto_gen_passes);
|
||||
::gt_ggc_mx (all_regular_ipa_passes);
|
||||
::gt_ggc_mx (all_lowering_passes);
|
||||
::gt_ggc_mx (all_small_ipa_passes);
|
||||
::gt_ggc_mx (all_passes);
|
||||
}
|
||||
|
||||
void
|
||||
pass_manager::gt_pch_nx ()
|
||||
{
|
||||
/* Analogous to pass_manager::gt_ggc_mx */
|
||||
for (int i = passes_by_id_size ; i > 0; )
|
||||
::gt_pch_nx (passes_by_id[--i]);
|
||||
|
||||
::gt_pch_nx (all_late_ipa_passes);
|
||||
::gt_pch_nx (all_lto_gen_passes);
|
||||
::gt_pch_nx (all_regular_ipa_passes);
|
||||
::gt_pch_nx (all_lowering_passes);
|
||||
::gt_pch_nx (all_small_ipa_passes);
|
||||
::gt_pch_nx (all_passes);
|
||||
}
|
||||
|
||||
void
|
||||
pass_manager::gt_pch_nx_with_op (gt_pointer_operator op, void *cookie)
|
||||
{
|
||||
/* Unlike the _mx and _nx hooks, we must visit *every* field, since
|
||||
they must each be reconstructed when reading the data back from
|
||||
disk. */
|
||||
op (&(all_passes), cookie);
|
||||
op (&(all_small_ipa_passes), cookie);
|
||||
op (&(all_lowering_passes), cookie);
|
||||
op (&(all_regular_ipa_passes), cookie);
|
||||
op (&(all_lto_gen_passes), cookie);
|
||||
op (&(all_late_ipa_passes), cookie);
|
||||
|
||||
for (int i = 0; i < passes_by_id_size; i++)
|
||||
op (&(passes_by_id[i]), cookie);
|
||||
|
||||
#define INSERT_PASSES_AFTER(PASS)
|
||||
#define PUSH_INSERT_PASSES_WITHIN(PASS)
|
||||
#define POP_INSERT_PASSES()
|
||||
#define NEXT_PASS(PASS, NUM) op (&(PASS ## _ ## NUM), cookie);
|
||||
#define TERMINATE_PASS_LIST()
|
||||
|
||||
#include "pass-instances.def"
|
||||
|
||||
#undef INSERT_PASSES_AFTER
|
||||
#undef PUSH_INSERT_PASSES_WITHIN
|
||||
#undef POP_INSERT_PASSES
|
||||
#undef NEXT_PASS
|
||||
#undef TERMINATE_PASS_LIST
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
pass_manager::execute_early_local_passes ()
|
||||
@ -1602,7 +1464,7 @@ void *
|
||||
pass_manager::operator new (size_t sz)
|
||||
{
|
||||
/* Ensure that all fields of the pass manager are zero-initialized. */
|
||||
return ggc_internal_cleared_alloc_stat (sz MEM_STAT_INFO);
|
||||
return xcalloc (1, sz);
|
||||
}
|
||||
|
||||
pass_manager::pass_manager (context *ctxt)
|
||||
|
@ -76,22 +76,11 @@ namespace gcc
|
||||
|
||||
/* An instance of a pass. This is also "pass_data" to minimize the
|
||||
changes in existing code. */
|
||||
class GTY((user)) opt_pass : public pass_data
|
||||
class opt_pass : public pass_data
|
||||
{
|
||||
public:
|
||||
/* Ensure that instances are allocated in the GC-managed heap. */
|
||||
void *operator new (size_t sz);
|
||||
|
||||
virtual ~opt_pass () { }
|
||||
|
||||
/* GTY((user)) methods, to be called once per traversal.
|
||||
opt_pass subclasses with additional GC-managed data should override
|
||||
these, chain up to the base class implementation, then walk their
|
||||
extra fields. */
|
||||
virtual void gt_ggc_mx ();
|
||||
virtual void gt_pch_nx ();
|
||||
virtual void gt_pch_nx_with_op (gt_pointer_operator op, void *cookie);
|
||||
|
||||
/* Create a copy of this pass.
|
||||
|
||||
Passes that can have multiple instances must provide their own
|
||||
|
Loading…
x
Reference in New Issue
Block a user