Redundant bridge methods in nested classes
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Fri Jul 31 12:12:26 UTC 2015
On 31/07/15 11:18, Maurizio Cimadamore wrote:
> As you noticed, this order doesn't sit well with a tree visitor, as
> there's no way i.e. to visit B without also doing B.Nested - which
> will mess up the order completely (as is the case now). What this
> means is that TransTypes should probably NOT translate class
> recursively. I think that such an approach would have more chances to
> succeed than the existing one.
Thinking more about this, while it's probably not a big deal to turn
TransType into something that handles one class at a time (like Attr for
instance), doing so for Lower will probably be a major undertaking; a
lot of the state variables in Lower assume that you visit the enclosing
classes before you reach inner classes - stuff like 'outerThisStack';
additionally, some of the desugared code in lower always ends up in the
toplevel class, no matter the nesting (see the constructor tag class,
which is always a static inner class of the toplevel). Pulling out these
pieces so that Lower is well-behaved will be generally very very hard.
If this can't be done, of course we need a dependency from inner to
outer (as now), and that means that we start getting cycles in our graph:
transtypes:
A -> I
A.Nested -> B
B -> I
B.Nested -> A
lower:
A -> A.Nested
B -> B.Nested
Meaning the order now is:
I, { A, A.Nested, B, B.Nested }
In other words, there's a cycle now - meaning you can disentangle the
mess using some heuristics (as we do now), but there will be cases where
compilation order will show up.
I see few solutions out of this:
(1) make Lower and TransTypes smarter, so that they do not rely on any
dependencies; then we can process classes in any order
(2) make only one of them smarter and sort dependencies accordingly;
i.e. if TransTypes is rewritten so that it doesn't rely on actual
members, we can just get rid of all transtypes-like dependencies
(3) split desugar into two steps - one does erasure, and sorts envs
using transtypes dependencies; another does lowering and sorts envs
using lower dependencies
Of these, (1) looks the most disruptive, while (3) seems the most
straightforward, albeit I don't think (3) can be made to work alongside
different compilation policies; i.e. (3) would work fine using a policy
like SIMPLE (where all classes to be compiled are advanced to the next
stage before any other action is taken); for policies such as BY_FILE or
BY_TODO (the default), things are harder, as things are pushed down the
pipeline eagerly - i.e. you can have one class in the code generation
step, while another class has not even been attributed. Note that such
policies are fare better when it comes to memory footprint, as ASTs are
typically discarded after code generation; so, when compiling a large
number of files at once, the sooner you hit code generation, the better
(memory-wise). (2) seems like a fair balance, but it's still a lot of
work (see my previous email).
Maurizio
More information about the compiler-dev
mailing list