Main changes are in the added files, compiler/compiler.dart, src/compiler.dart and src/apiimpl.dart.
Start by looking at compiler/compiler_new.dart and compiler/compiler.dart.
BUG=
R=floitsch@google.com
Review URL: https://codereview.chromium.org//1235563003.
There is a new pass that optimizes for continuations that branch on a
parameter, where every invocation passes a constant as that parameter.
This avoids unnecessary boolean flags that can arise from specializing a
call to a method that returns a boolean.
A current short-coming is that this lives in its own pass.
I believe shrinking reductions and redundant joins elimination can
trigger redexes of each other, so in theory we may still get redundant
joins in the output. The two passes might need to be reorganized at
some point.
R=karlklose@google.com
Review URL: https://codereview.chromium.org//1229893002.
For example, the code (assuming 'list' is a native list):
for (var x in list) {
print(x);
}
Becomes:
var i = 0, x = null, $length = list.length, v0;
while (true) {
if (i < list.length) {
x = list[i];
i = i + 1;
v0 = true;
} else {
x = null;
v0 = false;
}
if (!v0)
return null;
P.print(x);
if ($length !== list.length)
H.throwConcurrentModificationError(list);
}
This is clearly in need of redundant join elimination, which is an
optimization that I plan to land separately.
After redundant join elimination it becomes:
var i = 0, x = null, $length = list.length;
while (i < list.length) {
x = list[i];
i = i + 1;
P.print(x);
if ($length !== list.length)
H.throwConcurrentModificationError(list);
}
x = null;
There is still room for improvement regarding redundant assignemnts
to 'x'. They occur because x is a MutableVariable. Rewriting these
into "SSA variables" (continuation parameters) is another optimization
we may want to implement.
BUG=
R=floitsch@google.com
Review URL: https://codereview.chromium.org//1229563005.
Assignment propagation traverses the tree backwards, and should therefore
visit the branch condition of an 'if' after its two branches.
It happened to work (in the sense of not breaking the code) but
only for very subtle reasons.
This fixes an optimization bug that prevented assignments from
propagating to their first use when the first use was in a branch
condition.
BUG=
R=karlklose@google.com
Review URL: https://codereview.chromium.org//1226353003.
Without reflection, redirecting factory constructor invocations are shortcut at the instantiation site. With reflection, code like
reflectClass(Foo).newInstance(const Symbol(''), [])
can hit a redirecting factory constructor and we need to emit a function that does the redirection and type substitution.
R=asgerf@google.com
Review URL: https://codereview.chromium.org//1227873004 .
We now split a LetCont before moving it, so we do not move other
continuation bindings.
The bug surfaced when working on redundant join elimination.
I don't think it can be reproduced with the current set of
optimizations, so the fix is not visible in the tests.
BUG=
R=karlklose@google.com
Review URL: https://codereview.chromium.org//1222913009.
length, forEach, [], and []= are rewritten to direct array access nodes.
There are more methods to specialize, which will be added in separate
CLs.
This CL also contains a class CpsFragment to help build CPS code.
BUG=
R=karlklose@google.com
Review URL: https://codereview.chromium.org//1223813006.
The world will refuse to emit getters and setters for field it thinks
will be accessed directly.
Rewriting getter/setter calls to field accesses must happen at
build-time so we do not rely on an optimization for correctness.
BUG=
R=karlklose@google.com
Review URL: https://codereview.chromium.org//1227543008.
Specializing a node may depend on how its operands are defined, but
they may no longer depend on how its result is used.
Patterns that depended on its result being converted to a boolean
violated this rule, but fortunately they could be refactored to
satisfy the rule, by matching the node doing doing the boolean
conversion.
By processing definitions before their uses, we avoid creating new
redexes for a node that has already been processed.
BUG=
R=floitsch@google.com
Review URL: https://codereview.chromium.org//1220123004.
For example:
getInterceptor(foo).get$toString(foo).call$0()
Should be rewritten to:
getInterceptor(foo).toString$0(foo)
But would erroneously be rewritten to:
getInterceptor(foo).toString$0()
BUG=
R=floitsch@google.com
Review URL: https://codereview.chromium.org//1222763003.