Assignments are propagated into their first use, e.g:
var x = foo(),
y = bar();
baz(x, y, y)
Becomes:
var y;
baz(foo(), y = bar(), y);
By itself, this usually degrades readability and is only a modest
improvement in code size (but it never degrades code size).
The main advantage is when it unlocks other optimizations such as
inlining of `x` in the above example.
The ability to rewrite ugly while(true) loops is one of the main wins
for this, but there are currently other things also blocking that, which
I will take in another CL.
Setters are also propagated to their use site, mostly to assist
introduction of compound operators in the future.
I'm considering if some of this should be enabled only when minifying
due to the unreadable output, but for now it's always on.
OVERVIEW OF CHANGES:
- Assign and SetField are now Expressions.
- VariableDeclaration is a new Dart-specific statement for declaring
captured variables inside loops
(previously handled by the `Assign.isDeclaration` field).
- StatementRewriter now propagates assignments into variable uses,
regardless of use count.
The assignment is then converted to a variable use if there are no
more uses of the variable. E.g:
{ x = foo(); bar(x); } ==> bar(x = foo()) ==> bar(foo())
- Combining statements and expressions now works a bit differently
so we can inline combined assignments into an inlined combined break
without risking reprocessing.
- New phase PullIntoInitializers moves assignment expressions back
into statements so they can be part of the variable initializer.
The StatementRewriter cannot be predict ahead of time whether
an assignment propagation is beneficial, so this phase cleans up
some bad propagations.
R=kmillikin@google.com
Review URL: https://codereview.chromium.org//1088493002
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@45132 260f80e4-7a28-3924-810f-c04153c831b5
When the receiver parameter is inserted at the front of the parameter list, some parameters may have already been inserted and others will be inserted later.
If none have already been inserted, then the subsequent parameters were being inserted in front of the receiver parameter. This is fixed by marking the receiver as the lastAddedParameter if it is the only one. This did not seem to affect 'this', presumably because the position of 'this' is immaterial since it is always removed from the JS function parameters.
R=sigmund@google.com
Review URL: https://codereview.chromium.org//1066303002
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@45048 260f80e4-7a28-3924-810f-c04153c831b5
Changes in both IRs:
- ExecutableDefinition -> RootNode
- PassMixin has been removed and the Pass interface has been
reduced to a single rewrite(RootNode) method.
- ConstructorDefinition no longer subclasses FunctionDefinition.
Changes in the cps IR:
- RunnableBody -> Body
Changes in tree IR:
- RootNodes have "forEachBody" and "replaceEachBody" helper methods that
take care of the boilerplate for traversing roots and initializers.
- We now have visitors for initializers and root nodes. The RecursiveVisitor still
just visits statements and expressions since forEachBody takes care of the root
nodes and initializers.
- Initializers are no longer expressions. Why were they expressions?
- We now have a RecursiveTransformer class which behaves like RecursiveVisitor,
except visitors are expected to return a transformed node.
This removes a lot of boilerplate traversal from transformations.
R=kmillikin@google.com
Committed: https://code.google.com/p/dart/source/detail?r=45000
Reverted: https://code.google.com/p/dart/source/detail?r=45004
Review URL: https://codereview.chromium.org//1068243002
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@45006 260f80e4-7a28-3924-810f-c04153c831b5
Changes in both IRs:
- ExecutableDefinition -> RootNode
- PassMixin has been removed and the Pass interface has been
reduced to a single rewrite(RootNode) method.
- ConstructorDefinition no longer subclasses FunctionDefinition.
Changes in the cps IR:
- RunnableBody -> Body
Changes in tree IR:
- RootNodes have "forEachBody" and "replaceEachBody" helper methods that
take care of the boilerplate for traversing roots and initializers.
- We now have visitors for initializers and root nodes. The RecursiveVisitor still
just visits statements and expressions since forEachBody takes care of the root
nodes and initializers.
- Initializers are no longer expressions. Why were they expressions?
- We now have a RecursiveTransformer class which behaves like RecursiveVisitor,
except visitors are expected to return a transformed node.
This removes a lot of boilerplate traversal from transformations.
R=kmillikin@google.com
Committed: https://code.google.com/p/dart/source/detail?r=45000
Review URL: https://codereview.chromium.org//1068243002
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@45004 260f80e4-7a28-3924-810f-c04153c831b5
Changes in both IRs:
- ExecutableDefinition -> RootNode
- PassMixin has been removed and the Pass interface has been
reduced to a single rewrite(RootNode) method.
- ConstructorDefinition no longer subclasses FunctionDefinition.
Changes in the cps IR:
- RunnableBody -> Body
Changes in tree IR:
- RootNodes have "forEachBody" and "replaceEachBody" helper methods that
take care of the boilerplate for traversing roots and initializers.
- We now have visitors for initializers and root nodes. The RecursiveVisitor still
just visits statements and expressions since forEachBody takes care of the root
nodes and initializers.
- Initializers are no longer expressions. Why were they expressions?
- We now have a RecursiveTransformer class which behaves like RecursiveVisitor,
except visitors are expected to return a transformed node.
This removes a lot of boilerplate traversal from transformations.
R=kmillikin@google.com
Review URL: https://codereview.chromium.org//1068243002
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@45000 260f80e4-7a28-3924-810f-c04153c831b5
RegisterAllocator and CopyPropagator have been removed.
Variables are merged after StatementRewriter.
This simplifies CPS->Tree translation is a little bit since the mapping
to variables is one-to-one.
The StatementRewriter has a more SSA-like input, but has to be more
aggressive when looking for a redex. It now looks through a chain of
phi-assignments to check if two statements can be combined, whereas
before it would only combine two identical jumps.
I haven't been able to measure a significant slowdown, though I'm sure
it is at least a little bit slower.
R=kmillikin@google.com
Review URL: https://codereview.chromium.org//1007103003
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@44962 260f80e4-7a28-3924-810f-c04153c831b5