`int` variables can attain NaN values because web int arithmetic
implemented by JavaScript numbers (doubles) is not closed under many
operations. It is possible get NaN using only addition:
int a = 1, b = -1;
while (a + a != a) { a += a; b += b; }
int nan = a + b;
On the VM, a, b and nan are all zero.
On the web, a, b and nan are Infinity, -Infinity and NaN, respectively.
Since NaN can leak into int arithmetic, is it helpful if bounds checks
catch NaN indexes. NaN compares false in any comparison, so a test
of the form
if (index < 0 || index >= a.length) throw ioore(a, index);
fails to detect a NaN value of `index`.
This is fixed by negating the comparisons, and applying De Morgan's law:
if (!(index >= 0 && index < a.length)) throw ioore(a, index);
These changes have been applied to JSArray.[], JSArray.[]= and String.[]
For dart2js the change is a little more involved. Primitive indexing is
lowered to code with a HBoundsCheck check instruction. The code generated
for the instruction now uses, e.g. `!(i>=0)` instead of `i<0`.
This leads to a small code size regression.
There is no regression at -O4 since bounds checks are omitted at -O4.
At -O3 (where the regression is largest) the regression is
0.01% for cm
0.06% for flutter gallery -- array-heavy diff and layout
0.21% for Meteor -- array-heavy code
0.30% for Box2DOctane -- array-heavy code
I believe the regression can be largely alleviated by determining if
NaN is impossible at the index check, and if so, reverting to the smaller
code pattern. The analysis could be global, incorporating NaN into the
global abstract value domain, or a much simpler a local dataflow
analysis. Many indexes are loop driven and cannot reach infinity because
they are incremented by a small bump and eventually (even without a loop
guard) the index would stop growing when the increment falls below the
rounding error in O(2^53) iterations.
Change-Id: I23ab1eb779f1d0c9c6655e13d69f65d453db9284
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/210321
Commit-Queue: Stephen Adams <sra@google.com>
Reviewed-by: Mayank Patke <fishythefish@google.com>
The old way was for the JavaScript string literals to be pre-escaped.
This was cumbersome since each place that creates a JavaScript string
literal needs to make a decision about whether escaping is needed and
the kind of escaping (UTF8 or ASCII).
This change moves the responsibility for escaping into the js_ast printer.
The escaped text exists only while printing, which reduces the heap in a
large modular compile link scenario by 220MB, since the unescaped string
is in memory anyway.
There were three kinds of escaping - ASCII, UTF8, and 'legacy', if not
specified. This has been reduced to ASCII (default) and UTF8, chosen by
a printer option.
Change-Id: Ic57d8fb70a213d3518244f1a152cd33e54103259
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/200400
Commit-Queue: Stephen Adams <sra@google.com>
Reviewed-by: Mayank Patke <fishythefish@google.com>
Reviewed-by: Joshua Litt <joshualitt@google.com>
In each library where an import is removed, the library uses some elements
provided by the import, BUT there is another import which provides all of the
same elements, and at least one more which the library uses.
In this change, we remove the imports which can be simply removed in favor of
the other already present imports.
See https://github.com/dart-lang/sdk/issues/44569 for more information.
Change-Id: I38a6422e5fc59767fe54eae78a5e24357f1cc030
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/199461
Reviewed-by: Mayank Patke <fishythefish@google.com>
Commit-Queue: Samuel Rawlins <srawlins@google.com>
- js_ast.Name is no longer Comparable
- _NameReference is used on demand rather than for every occurrence.
This saves 50MB in the big link scenario.
- remove unused asVariableUse() method
Change-Id: I37f55044d394b7e047ca88c527641471bc94c641
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/198981
Commit-Queue: Stephen Adams <sra@google.com>
Reviewed-by: Joshua Litt <joshualitt@google.com>
Since the flag is now enabled by default, there should be no mention of it.
There are still some uses in front_end/testcases that are not just removable
(it also uses `no-non-nullable`). There migth be more uses that are not
as easily found as grepping for `--enable-experiment
Removes two VM tests where fixing them meant they were just duplicating
the corresponding non *_2/ tests.
Fixes#44941
TEST= Large number of tests chaged.=(no-)?non-nullable`.
Change-Id: Ief755981ccde9a5482fcdf408c2929c74433a710
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/183688
Commit-Queue: Lasse R.H. Nielsen <lrn@google.com>
Reviewed-by: Nate Bosch <nbosch@google.com>
JSDouble represents doubles that are not integers. It is usually wrong
to use JSDouble, so use JSNumber instead where we mean 'all double
values'.
This fixes#44818 by not mistakenly pretending that division cannot
have an integral result.
Will follow up with a CL to rename JSDouble.
Fixed: 44818
Change-Id: Ic324df2ee1f2c7434bc0b064c0dbd7b6800ad93b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/183360
Commit-Queue: Stephen Adams <sra@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
This should cause no change in behavior, but the layer of indirection
keeps us from assuming that typemasks are the underlying implementation
of the abstract value domain.
Change-Id: I2b51b0da489407de86d5638b2eda9541fdd0276e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/171780
Reviewed-by: Stephen Adams <sra@google.com>
Commit-Queue: Mayank Patke <fishythefish@google.com>
Pass the CommonMasks abstract value domain instead of the JClosedWorld to TypeMask methods that need access to *their* abstract value domain. It is wrong to get the abstract value domain from the JClosedWorld because when we try to wrap abstract values, the abstract value domain in the JClosedWorld is the wrapper domain, not the domain being wrapped.
Change-Id: I5bbd0f4c56abe45714dd0a2657f73ef240efae0e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/155640
Commit-Queue: Christian Altamirano <coam@google.com>
Reviewed-by: Stephen Adams <sra@google.com>
On a per output-unit basis, repeated large strings are shared via a
`string$` pool.
TODOs:
- don't do it with strings passed to JS() code (they might need
to be property accesses).
- tweak thresholds, using different thresholds for slow/run-once code.
Change-Id: Ib14245d9d428e52fb2ca23f34fa533de97fa2208
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136304
Reviewed-by: Joshua Litt <joshualitt@google.com>
Commit-Queue: Stephen Adams <sra@google.com>