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