Type propagation:
Added better type_propagation rules for various operators to detect more uint31/uint32/non-negative cases.
Moved the rules to per-operator code so the rules can be shared by invokes (e.g. '<') and the builtin operations they are lowered to (NumLt).
In the case of NumLt, this removes lower bounds checks from injected bounds checks (i.e. NumLt(index, 0)) for constant indexes by simple constant folding.
Bit operations:
The '>>> 0' coercion is often not needed.
If we can tell the result is in the uint31 range then the result
generated by JavaScript's bit operations will not have become
negative.
Added a tree analysis to codegen to tell if the result fits in uint31.
This works quite well and removes about as many coercions as SSA.
It misses some coercions due to lack of type information in tree_ir.
Added missing operators:
NumShr aka '>>>', valid on limited inputs.
NumDiv (Seems like a simple omission, boost some math code)
NumTruncatingDivideToSigned32
R=asgerf@google.com
Review URL: https://codereview.chromium.org/1393763004 .
All passes must now preserve valid parent pointers. Several passes
already did this (or tried to do it).
The IR integrity checker can now check that parent pointers are valid.
This has caught a number of missing parent pointers assignments in
passes that otherwise tried to preserve them.
All node constructors now set parent pointers. This is very convenient
for simple transformations, but also a bit of a trap since updating a
field on an existing node does not update the parent pointer.
This is a pretty heavy-handed change. The main rationale for it are:
- The helpers methods require parent pointers, so they are more useful
when parent pointers are always set.
- The integrity checker can catch bogus parent pointers after passes
that have to maintain them anyway.
- The integrity checker is super slow, but this can finally be fixed
if it can assume parent pointers are valid (not part of this CL).
The IR visitors have been changed a bit to support a generic parent
visitor that does not have to implement every visit method.
The 'parent index' fields have been removed.
BUG=
R=kmillikin@google.com
Review URL: https://codereview.chromium.org//1375213003 .
Use the $isXXX properties for type tests on raw (non-parameterized) types.
Use special builtin operations for the weird JSArray type hierarchy.
Still TODO:
If the only use of an interceptor is a single 'getInterceptor(value).$isXXX', and XXX is not a supertype of a native type, replace with 'value instanceof XXX'.
R=kmillikin@google.com
Review URL: https://codereview.chromium.org/1385423002 .
Classes only emitted for rti are empty shells and, even if they are
marked as reflectable, are not otherwise referenced from the program. So
we should not try to emit type metatdata because it is neither needed
for is it always complete (as most of the class, including its type
variables, is missing).
Fixes#24493.
BUG= http://dartbug.com/24493R=sigmund@google.com
Review URL: https://codereview.chromium.org/1394483002 .
- initial visitor to collecting data about sends (incomplete)
- logic to emit data in a json summary file.
- logic to print summary information on the command-line
- logic to display some of the data in a web UI.
BUG=
R=johnniwinther@google.com
Review URL: https://codereview.chromium.org//1220043005 .
This adds four helpers:
- InteriorExpression: remove, insertAbove, and insertBelow.
- Primitive: destroy.
As discussed elsewhere, using such helpers is a double-edged sword.
They make the code easier to read and write, but it's easy to end up
with helpers that look like they work for a particular purpose, but
actually don't because of slight variations in different use-cases.
These methods have a couple of pitfalls, like forgetting to unlink
references after a call to `remove`, or accidentally using the body
of an orphaned node. But these are generally caught quickly in
checked-mode so, it seems like it will be worth it.
BUG=
R=kmillikin@google.com
Review URL: https://codereview.chromium.org//1375513002 .
Neither of these optimizations can "obviously" be placed before any of
the others without missing out on an optimization:
Constifying an interceptor makes it LICM'able because its dependency on
the input disappears. This suggests we should constify before LICM.
Interceptors in disjoint scopes might become sharable after LICM.
This suggests we LICM before sharing.
Constifying an interceptor can prevent sharing, because we "forget"
which input it came from. This suggests we share before constifying.
The last point could also be resolved by performing a stronger analysis
to determine which interceptors in scope are a valid substitute for a
given interceptor. But having everything in one pass isn't too bad.
BUG=
R=sra@google.com
Review URL: https://codereview.chromium.org//1364703004 .
Because of this bug, the tree IR had a tendency to put throw
statements at the bottom of a method, even if it meant inserting
an explicit negation in a branch.
BUG=
R=sra@google.com
Review URL: https://codereview.chromium.org//1368963002 .
Passing the -v flag to dart2js now prints the time spent in individual
optimization passes.
It should also be easier to throw in ad-hoc timing of specific
procedures for some quick-and-dirty timing measurements.
BUG=
R=johnniwinther@google.com
Review URL: https://codereview.chromium.org//1362953002 .