The introduced "constants" transformation can evaluate constant expressions. The
original use-sites of constant expressions are replaced by a new [ConstantExpression]
node, which points to a subclass of a new [Constant] class hierarchy. Constant
[Field]s and [VariableDeclarations]s will be removed, since all use-sites are
re-written.
The [Constant] class hierarchy is, similarly to the [DartType] class hierarchy, not
part of the AST tree (also has no parent pointer). The constants form a
DAG (directed acyclic graph).
There is no canonicalization requirement of the [Constant] objects referenced by the
AST (via [ConstantExpression]). Although it is beneficial to canonicalize them during
construction, since it reduces time spent in operator==/hashCode.
This CL furthermore adds support for a constant table in the binary format. Similarly
to [String]s, we canonicalize the constants before writing the table to the binary.
The constant table entries in the binary are written in a post-order way, to ensure
easy construction on the backend side.
The text format will be augmented with a "constants { ... }" section at the end,
which lists the constants in the same order as in the binary format.
The transformation can be used by those backends who choose to do so. It is not
enabled by default atm. It should therefore not affect analyzer, fasta or other
components.
Change-Id: I57cd9624fedcf537ab6870db76246149647bed21
Reviewed-on: https://dart-review.googlesource.com/14382
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Kevin Millikin <kmillikin@google.com>
It was previously an array of Smi values. By converting to TypedData
array of int32_t values, we shave off 70+KB from the kernel based core
snapshots. While 70KB might not seem too high, it is 5% of the excess
size we have wrt to the token stream based core snapshots.
Change-Id: I5b58a1d1ac27391eca1efff179301bb04162e97b
Reviewed-on: https://dart-review.googlesource.com/19800
Commit-Queue: Siva Chandra <sivachandra@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
This fixes a number of issues caused by constant evalation reporting
an error, but not correctly propergating that error in AOT mode.
Fixes#31298
Bug:
Change-Id: I43d378e96f033a9bd5bc0d90e1c2cf130d2cce2e
Reviewed-on: https://dart-review.googlesource.com/19183
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
* When building method invocation that requires checking receiver for null
and has type arguments make sure that we duplicate type arguments above the
receiver temporary. Before this fix the stack ended up looking like
`[type_arguments_temp][receiver_temp][receiver]...` and after the fix it
looks like `[type_arguments_temp][receiver_temp][type_arguments][receiver]...`.
* Fix how we generate StaticCall with type arguments: we were adjusting
arguments count by one manually if type arguments were present at each call site
to FlowGraphBuilder::StaticCall. This is very brittle and were leading to
incorrect number of arguments used if caller forgot to adjust. Instead handle
this inside FlowGraphBuilder::StaticCall just like other similar methods do it
(e.g. FlowGraphBuilder::InstanceCall).
Fixes https://github.com/dart-lang/sdk/issues/31297
Bug:
Change-Id: I3713fdde838d159985c68b456f911eab7746824c
Reviewed-on: https://dart-review.googlesource.com/19563
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
On the otherwise path it was producing a block that ended with a call. Such IR
is invalid because blocks can only end with control flow instructions, like
Branch, Goto, Return or Throw.
Bug:
Change-Id: I67971fba00c01f1e063ac584abfa6aec2ea376d9
Reviewed-on: https://dart-review.googlesource.com/19004
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
CloneContext is implemented as a runtime call so it is considerably slower
than AllocateContext which leads to performance issues in loops that capture
iteration variables in for loops.
Lowering CloneContext into AllocateUninitializedContext and a sequence of
explicit load&store instructions both improves the performance by avoiding
the runtime call and also makes CloneContext semantics exposed to store-load
forwarding and allocation sinking.
PutIfAbsent benchmark from issue #31113 is improved by 5x, while
ForInGeneratedLoop benchmark is improved by 8x.
Bug: https://github.com/dart-lang/sdk/issues/31113
Change-Id: I03fdede75f1a85fda92487aa8f9307ce06f23903
Reviewed-on: https://dart-review.googlesource.com/16280
Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Currently, the Kernel FE doesn't set up parent pointers correctly for
signature function types. This prevents type parameters on generic
function types from being finalized correctly. In addition, finalization
of generic interface types within a generic function type can crash if they
reference not-yet-finalized type parameters of the enclosing function type.
This review solves both issues. Several failing tests pass again, although
more thorough testing is blocked on Github issue #31213 (nested generic function
types crashing in Fasta).
Bug:
Change-Id: Ib5ee6b2566492e3fd6688fe5a6b6976692562ea1
Reviewed-on: https://dart-review.googlesource.com/16360
Reviewed-by: Régis Crelier <regis@google.com>
Currently, we have some tests that run with reified generic functions ON and
some with it OFF. However, this causes inconsistencies when running the Kernel
FE from snapshot in the VM, since the VM requires that the flag be consistent
with the snapshot. Our solution is to turn the reified generic functions flag
into a per-isolate flag, which is always disabled in the Kernel FE's isolate.
Bug:
Change-Id: Ia91e9f0ff5fc059edf4bdbd79ef14abb288b4a49
Reviewed-on: https://dart-review.googlesource.com/16020
Commit-Queue: Samir Jindel <sjindel@google.com>
Reviewed-by: Régis Crelier <regis@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
This flag indicates when a procedure's return type makes contravariant
use of a class type parameter. The front end will have to insert "as"
checks at any call sites that refer to such a procedure as their
interface target. Placing the flag on the procedure will allow the
front end to determine whether the check is needed once, at the same
time as it's determining the need for covariant parameter checks,
rather than when compiling individual call sites.
Once this lands I will follow up with CLs that cause the front end to
set the flag appropriately, and to generate the necessary "as" checks.
Change-Id: I989fc702bc233384eb5ea8cd630c8efd384ab248
Reviewed-on: https://dart-review.googlesource.com/14365
Reviewed-by: Samir Jindel <sjindel@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Devirtualization optimization now adds metadata to kernel AST instead
of transforming nodes to Direct* ones. The direct call metadata
provides information about checking receiver for null, while
Direct* kernel nodes do not support null checking.
VM's kernel binary loader is extended to extract arbitrary metadata
from kernel binaries and keep it for flow graph builder.
Kernel flow graph builder is extended to take direct call metadata
into account and generate CheckNull/StaticCall instructions
for devirtualized PropertyGet, PropertySet and MethodInvocation nodes.
Issue: https://github.com/dart-lang/sdk/issues/30480
Change-Id: I57f56fbf4a8981d33b1571c0d93105cf8ca71d76
Reviewed-on: https://dart-review.googlesource.com/12260
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
Before this change, each function and field had its own kernel data blob
in the VM heap. With this change, the entire kernel data of a library is
stored as one single blob in the VM heap. Functions and fields store an
offset which points to the kernel data, specific to them, in that single
blob.
The pointer to the kernel data for a library is saved in two places:
1. With the library objects themselves.
2. With all the patch classes of the library.
3. With the patch classes created during hot reload.
Change-Id: Ie03e738c4d20f16056a5ef04341b75506fda9c60
Bug:
Reviewed-on: https://dart-review.googlesource.com/6601
Commit-Queue: Siva Chandra <sivachandra@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
When precompiling we might trigger optimizing compilation eagerly
so constant evaluation did not have a chance to run.
It is totally fine though because precompiler does not use
background thread.
Bug:
Change-Id: I6e889284d9ef9be8b09c6f4fe7695c82a78bcee4
Reviewed-on: https://dart-review.googlesource.com/12280
Reviewed-by: Alexander Markov <alexmarkov@google.com>
- We no longer erase type parameters of generic non-closures in the body of closures.
- We implement support for captured type parameters in the VM.
Bug:
Change-Id: I4f2f19301df1b44108ab2073332934d5d083e219
Reviewed-on: https://dart-review.googlesource.com/10942
Reviewed-by: Régis Crelier <regis@google.com>
Reviewed-by: Kevin Millikin <kmillikin@google.com>
Previously we could hit an assert when for instance "42 ~/ 0"
was being optimized by the background compiler. The reason was
that we assert that we're on the "mutator thread" when allocating
memory (which is done as we're evaluating the code - and we're
trying to evaluate it again because evaluating it gives an error,
and errors aren't cached).
However, to create a test for this it would be better if we could
make it always crash, i.e. use something like
```
--optimization_counter_threshold=5 --no-background-compilation
```
to force an optimization, but still make it crash dispite the
optimization happening in mutator thread (because of
--no-background-compilation).
This CL propagates if we're optimizing to the kernel builder,
and in the constant builder further more asserts that we're not.
Additionally it introduces a test that shows the crash and fixes it.
Change-Id: Ic5412ec8b8a1dbc2ba323f0a02a51103a32fab5c
Reviewed-on: https://dart-review.googlesource.com/11380
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
In kernel the loop level wasn't set correctly for for loops, resulting
in the loop variable not always being fresh.
Examples:
```
// Capture the loop variable, ensure we capture the right value.
for (int i = 0; i < 10; i++) { if (i == 7) f = () => "i = $i"; }
print(f());
// There is only one instance of k. The captured variable continues to change.
int k;
for (k = 0; k < 10; k++) { if (k == 7) f = () => "k = $k"; }
print(f());
```
resulted in
i = 10
k = 10
(i.e. it's wrong)
whereas
```
// Capture the loop variable, ensure we capture the right value.
for (int i = 0; i < 10; i++) { if (i == 7) { f = () => "i = $i"; } }
print(f());
{
// There is only one instance of k. The captured variable continues to change.
int k;
for (k = 0; k < 10; k++) { if (k == 7) { f = () => "k = $k"; } }
print(f());
}
```
resultet in
i = 7
k = 10
(i.e. it's correct).
Now both examples produce the correct result.
Change-Id: I1fb4c888c6a0eaa690f62226e093508992b33ed4
Reviewed-on: https://dart-review.googlesource.com/9961
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
This reverts commit ade37f931e.
This re-lands RebindRule change with fixes for the "-mdebug--hot-reload" test failures.
Original commit is reverted in patch set 1.
Fixes are in following patch sets.
Bug:
Change-Id: I49375af9b891323fe05c670d77cbf880964aae54
Reviewed-on: https://dart-review.googlesource.com/9361
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
Change-Id: I6219462fed278dbb90361c2084eed886c9245097
Revert "Revert "Introduce inline cache reload rule attribute to static call AST node and ICData.""
This reverts commit 162283c2f3.
This re-lands the change with original revert in Patch set 1, actual bug fix in next patch set.
Bug:
Change-Id: I6219462fed278dbb90361c2084eed886c9245097
Reviewed-on: https://dart-review.googlesource.com/8760
Commit-Queue: Alexander Aprelev <aam@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Before this CL we skipped procedure bodies in kernel_loader.cc by
parsing the body (but not storing anything).
With this CL we now skip them directly (i.e. don't read them at all)
in kernel_loader.cc by using the newly available extra indexes in kernel.
Change-Id: I48cf0599b2a85102c9008ff7c455785151ef3c9c
Reviewed-on: https://dart-review.googlesource.com/5764
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Samir Jindel <sjindel@google.com>
This adds more indexes to the kernel format so we know where classes
and procedures starts and stops. This allows for more random access.
E.g. one could now read the program index and jump directly to
library $i_1$, then read the library index and jump directly to class $i_2$,
read the class index and jump directly to procedure $i_3$.
The utilization (in this CL) is to not (always) read the procedure body
up front when loading kernel code on the dart side (ast_from_binary).
The observation is that - when running through the VM - almost none
of the bodies from the platform file are actually used.
This lowers the start-up cost which is noticeable for small programs
(e.g. hello world, or tests).
In this CL this is only done on the dart side and not on the C++ side,
that's for another CL.
Startup time:
dart2js: -1.84253% +/- 1.22157%
hello world: -11.1188% +/- 5.57892%
Running "time python tools/test.py -m release -cdartk language -j6":
real: -11.72% +/- 0.35%
user: -14.59% +/- 0.24%
sys: -12.71% +/- 0.61%
File size change (compiling with fasta to dill file incl. platform):
hello world: 0.88% (35,934 bytes).
dart2js: 0.97% (200,967 bytes).
Change-Id: I1f0ec121bc75bb17f11d3fade03da9815037d0bb
Reviewed-on: https://dart-review.googlesource.com/5262
Reviewed-by: Kevin Millikin <kmillikin@google.com>
This reverts commit 68a727fa5c.
Revert "Fix ICData::New() invocation. Follow-up to 68a727fa5cf5."
This reverts commit ac06b1c8ea.
Revert "Fix last ICData::New() invocation. Follow-up to 68a727fa5cf5."
This reverts commit da26ffc4de.
Bug:
Change-Id: Ia2d4e6a3c3a3a329982c90aded11e72bf25a9a34
Reviewed-on: https://dart-review.googlesource.com/8402
Reviewed-by: Alexander Aprelev <aam@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
Reload rule describes how inline cache has to be processed during hot reload, whether it should
be updated, reset or preserved.
Bug: dartbug.com/30639
Change-Id: I40b63ade786456ec48d4fa205a076654c2996bce
Reviewed-on: https://dart-review.googlesource.com/7586
Commit-Queue: Alexander Aprelev <aam@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
This should take care of some or all flaky tests like:
TypePropagationTest_Kernel | test_forEach_async_inheritedStream
What was happening is that every tests adds /test.dart to AnalysisDriver,
which means that this file is scheduled for analysis at some point,
and then it also calls getResult() to get the resolved unit. When we
resolve the file for the first time, the ByteStore is empty, so we
build the corresponding Kernel file from scratch, and it has the offset.
But the second time we read the Kernel file from ByteStore. So, if we
manage to process the file as added first, and then as getResult(),
we fail because we cannot resolve the import directive. But if we
were not able to process the file as added, and just do getResult()
first (which also marks the file as added as ready), we succeed.
So, it was flaky.
R=ahe@google.com, kmillikin@google.com, paulberry@google.com, sigmund@google.com
Bug: https://github.com/dart-lang/sdk/issues/30863
Change-Id: I96151e3ebefcd212f2a7a1b2b22abb7d87ed4781
Reviewed-on: https://dart-review.googlesource.com/7782
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This CL adds support for DirectMethodInvocation and DirectPropertyGet
operations into StreamingConstantEvaluator (which is a part of kernel
binary reader in VM).
The DirectMethodInvocation and DirectPropertyGet operations appear as
the result of devirualization of method and getter invocations in
precompiler+strong mode.
Issue: https://github.com/dart-lang/sdk/issues/30480
Change-Id: Ia0a5ef0ae09156add6677be7c9e32aa5a2e18ed7
Reviewed-on: https://dart-review.googlesource.com/6343
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
This reverts commit 9a8621b60a.
Revert "Rework getElement() in resynthesizer."
This reverts commit e4fa080f69.
Revert "Create (empty) initializers for parameters resynthesized from Kernel."
This reverts commit 8df6c79b9d.
Revert "Run NonErrorResolverTest in strong mode. Extract not strong tests."
This reverts commit 9bdda4b1d3.
Revert "Move TypeProvider creation into KernelResynthesizer and create loadLibrary functions."
This reverts commit c59eaf1788.
Revert "Return SimpleIdentifier or PrefixedIdentifier from _buildIdentifier()."
This reverts commit 6d0515f9ca.
Change-Id: I1099ca715ce6287ab56808b7cc3abe0589e939c1
Reviewed-on: https://dart-review.googlesource.com/7550
Reviewed-by: Peter von der Ahé <ahe@google.com>
Kernel file reader in Dart VM, when reading DirectPropertyGet
referencing a method (not getter nor field), was ignoring
receiver expression and was capturing 'this' to create tear-off.
The implicit assumption receiver == 'this' for tear-offs in
DirectPropertyGet is no longer true: devirtualization optimization
can convert PropertyGet to DirectPropertyGet nodes for arbitrary
receivers.
This CL fixes handling of tear-off when reading DirectPropertyGet
from kernel binary by checking receiver tag, and generating inline
code for implicit closure allocation only when receiver is actually
'this'. Otheriwse, corresponding method extractor is obtained and
called (directly).
Issue: https://github.com/dart-lang/sdk/issues/30480
Change-Id: Ic8974e8cdcfb072ead8a27d6d5377dda4e4d0bd8
Reviewed-on: https://dart-review.googlesource.com/5560
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>