This reimplements dynamic call code generation to add support for type
checking, named parameters (optional and required), and fixes a few
related bugs on the way.
Currently we do not try to be as efficient as possible. The goal with
this patch is to implement it correctly.
Summary of the changes:
- For every dynamic access kind and member name, we generate a new
"forwarder" function. Dynamic gets, sets, and invocations are compiled
to calls to the forwarders with the right access kind (invocation,
get, set) and member name.
For example, if the program has dynamic invocation of a member "f", we
create an "invocation forwarder for f". If it has a dynamic get of a
member "x", we generate "getter forwarder for x".
- Forwarder functions take 4 arguments:
- Receiver of the invocation, get, or set.
- A Dart list for type arguments in the invocation. For gets and sets
the list is empty.
- A Dart list for positional arguments in the invocation. For gets the
list is empty. For sets, the list only has one element.
- A Dart list for named arguments. For gets and sets the list is
empty. The list has alternating elements of type `Symbol` and
`Object?`, for the name and value of the named parameters.
- A forwarder function compares receiver class ID with the potential
targets of the call. When it finds a match, it compares the callee
"shape" with the parameters passed in the call site.
As it compares the shapes it adjusts argument lists:
- Creates default values for missing optional positional and named
arguments
- Reorders the named argument list to match order expected by the
callee
If it can't find a matching class ID and a member with the right name
and shape, it calls `noSuchMethod` on the receiver.
If it finds a matching class ID and a member, it calls the "type
checker" for the member, passing the original receiver and adjusted
argument lists.
- A "type checker" implements argument type checking for a member, and
it's a member of the same class as the member it's checking types
for. This is to allow accessing class-bound type parameters when
generating type checking code.
- Type checking is implemented using `_isSubtype` on arguments in the
lists.
- When type checking is successful a type checker calls the original
member, passing the arguments as expected by the member.
If type checking is unsuccessful it throws a type error.
Most of the changes are for generating Wasm functions that compare
shapes, adjusts argument lists, and checks types.
Changes to members:
- `Translator.dynamics` fields is renamed to
`Translator.dynamicForwarders`
- New field `Translator.dynamicForwarderFunctionType` added for the Wasm
function type of forwarder and type checker functions.
- Two new code gen utilities added:
- `Translator.indexList`: generates code that indexes a Dart list
- `Translator.getListLength`: generates code that gets length of a
Dart list
- New `Reference` extensions added to get type checker function
references of members
- New runtime library `named_parameters` implements two helper functions
for dealing with named argument lists
- The library `dynamic_dispatch` is replaced by `dynamic_forwarders`,
which consists of two classes:
- `DynamicForwarders`: maintains mapping from call kind (get, set,
invocation) and member name to forwarder functions.
- `Forwarder`: a single forwarder, implements code generation for
forwarder functions.
- `CodeGenerator` gets 3 new members:
- `_callForwader` generates call to a forwarder
- `_generateFieldSetterTypeCheckerMethod` generates code for a type
checker of a setter function.
- `_generateProcedureTypeCheckerMethod` generates code for a type
checker of a method.
Fixes#50367
Change-Id: I2b9d84237c8517bd217166d8acb67e025f0498fb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/272261
Reviewed-by: Joshua Litt <joshualitt@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
Reviewed-by: Aske Simon Christensen <askesc@google.com>
This CL removes some duplication of Strings:
* Most duplication in `relevanceTagsInFile` (`ElementKind.CLASS`, etc)
when loaded from file.
* Usage of `()` for `parameters`.
* Empty string return type.
* Known type return type.
On the analyzer instance I've measured on (8 folders with analyzer etc
open) this saves:
Before CL: 161851 kb 2158725 _OneByteString dart:core
1: 154622 kb 2001695 _OneByteString dart:core // removes most practical duplication from relevanceTagsInFile
2: 153247 kb 1957751 _OneByteString dart:core // Removes () parameters
3: 152970 kb 1939890 _OneByteString dart:core // Removes empty string return type
3: 151287 kb 1886063 _OneByteString dart:core // removes void, String, bool, int, Future<void> return type
That's a total of 10,564 kb or 272,662 instances.
This is also ~1.7% of total ram usage.
Change-Id: Ide2ae55ae052d9f8bc382805a204dce48bf2b263
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/273742
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Fixes https://github.com/dart-lang/sdk/issues/46967
Creates classes for non-external factories and static members, and
modifies invocations to point to these members instead. Tear-offs of
interop constructors (external or otherwise) are now supported since
they're just non-external static methods.
Change-Id: Id754fb4bc872051a8df4169aefd4bdc078452fb5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/270501
Reviewed-by: Nicholas Shahan <nshahan@google.com>
Commit-Queue: Srujan Gaddam <srujzs@google.com>
In the new runtime type system when running with weak null safety,
perform type tests multiple times to produce optional warnings or
errors when a test passes but would fail in sound null safety.
This is the same technique DDC uses with the current type system.
Issue: https://github.com/dart-lang/sdk/issues/48585
Change-Id: Ic1514987a6f4ffeb127a0d2be5ec15b606016212
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/266543
Reviewed-by: Mark Zhou <markzipan@google.com>
Reviewed-by: Anna Gringauze <annagrin@google.com>
Commit-Queue: Nicholas Shahan <nshahan@google.com>
Variable patterns behave so differently inside a patternAssignment
that we may want to represent them using different AST nodes inside
the analyzer/CFE. This change adds a boolean flag allowing the
implementation to know what kind of variable pattern it's looking at
when parsing occurs.
Bug: https://github.com/dart-lang/sdk/issues/50035
Change-Id: I60adf2865bbe24f85b72a79b1360833bf823bd67
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/273829
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
The field `Var.errorId` was being used for two purposes:
- For checking error messages.
- To distinguish different variables with the same name when merging
variables in `||` and cases.
As a result, a lot of variables to be tagged with error IDs even in
tests that weren't generating any errors, which was confusing.
This change creates a new `Var.identity` field which is used for
merging variables in `||` and cases; it defaults to the variable name
but may be overridden in tests where distinguishing variables of the
same name is important.
Change-Id: Ieb587f434520dc484180aaa72658c899a2eb06d0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/273824
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This change makes the API for the `ifCaseElement` method similar to
that of `ifCase`, which should make it easier to write flow analysis
unit tests for if-case elements.
Bug: https://github.com/dart-lang/sdk/issues/50419
Change-Id: I64c160f3b6df38b0d337f9b8f9c6c9189e9a13ed
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/274161
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
This change makes the API for the `ifCase` method the same as that of
`if_`, which should make it easier to write flow analysis unit tests
for if-case statements.
Bug: https://github.com/dart-lang/sdk/issues/50419
Change-Id: Iea7e0fabba9966eae52c0d28b52d2f8fcea25e46
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/273820
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This shares a cache for mapping Elements to their public LibraryElements across each snippet producer, and also skips snippet producers that produce snippets that won't match any typed prefix.
Change-Id: I6b64b3c55f1030a5eaa7ca1afdcd6c416e4baa08
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/273962
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This prepares dart2js to default to sound null safety in Dart 3.0.
The compiler no longer infers the default mode based on the input
program, instead uses sound null safety unless
'--no-sound-null-safety' is specified.
On a separate change, we expect to remove the option of disabling
null safety.
Note: this change should also be reflected in the CHANGELOG, but
we've currently not included it to redeuce merge conflicts, as we plan
to land multiple 3.0-alpha changes in a short window of time
Change-Id: Id87498cc5976548ec89d1f36c60674b72406950a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/270860
Reviewed-by: Nate Biggs <natebiggs@google.com>
Commit-Queue: Siva Annamalai <asiva@google.com>
Reviewed-by: Mayank Patke <fishythefish@google.com>
- Flip flag to make strong null safety the default
- Remove code that auto detects null safety mode from source files,
it is necessary to specify --no-strong-null-safety to opt out.
- Retains sniffing of AOT/JIT snapshots and kernel files to determine
null safety mode, the opt out has to be done when generating these
file.
TEST=ci
Change-Id: If2c9608eedb7c46d9c3cd85e261ee9640e0d28eb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/261140
Reviewed-by: Alexander Thomas <athom@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Siva Annamalai <asiva@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
- Fix ddc null dereference while generating symbols with mixins
- Fix incremental compiler failure on non-SCC components
- Reworked expression compiler worker tests for effiiciency
- Create module configuration in tests only once
- Add test case of compiling expression in an non-SCC module
- Add test case of compiling expression in an SCC module
This is a reland of commit e6f779bcdd
Original change's description:
> Cache expression compilers in incremental DDC mode
>
> - cache expression compilers in expression compiler worker
> to improve performance of exression compilation.
> - pass module format in expression compiler worker
> (the ddc format tests were not running!)
> - fix an issue where the same library was imported twice
> in module_builder.dart
> - add verbose mode timeline logging to ProgramCompiler.
> - update tests.
>
> Closes: https://github.com/dart-lang/sdk/issues/49944
> Change-Id: Ie7408dcd42e757b1eb5e7f5ccbc1b078b6417011
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/268361
> Reviewed-by: Johnni Winther <johnniwinther@google.com>
> Reviewed-by: Mark Zhou <markzipan@google.com>
> Commit-Queue: Anna Gringauze <annagrin@google.com>
> Reviewed-by: Nicholas Shahan <nshahan@google.com>
Change-Id: I80546773d957f37ec5b2353ea060b50f3fba0aa7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/271801
Reviewed-by: Jens Johansen <jensj@google.com>
Reviewed-by: Nicholas Shahan <nshahan@google.com>
Reviewed-by: Mark Zhou <markzipan@google.com>
Commit-Queue: Anna Gringauze <annagrin@google.com>
This can be used by the front end to detect when to add synthetic
break statements to switches involving patterns.
Bug: https://github.com/dart-lang/sdk/issues/50624
Change-Id: I783b0920b8dc6ccbc7af8062fba7bfdeaa9dd9cc
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/273800
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
In
b2889872c3,
the switch expression syntax was changed so that it no longer uses the
`case` keyword.
Change-Id: I97c10b3462b5849e1baf386df81a656d5ac25c09
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/273623
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
When asking for all references of a member it starts by finding all
supertypes for the class, then for each supertype (including itself)
(that has a member with the same name as the one we're querying for)
it searches for all subtypes.
We recall that when getting all subtypes, it really gets all direct
subtypes, then for each of those, their direct subtypes etc.
Naturally, then, with getting all subtypes for all supertypes we
will often ask for all direct subtypes of the same class several times.
In fact, it's O(n^2):
As an example, if asking for references to `foo` on this
(in a file in analyzer, with 8 workspaces):
```
class X0 { void foo() { print('hello'); } }
class X1 extends X0 { void foo() { print('hello'); } }
class X2 extends X1 { void foo() { print('hello'); } }
[...]
class X149 extends X148 { void foo() { print('hello'); } }
```
we ask for subtypes 90600 (150 classes * 151 / 2 * 8 workspaces) times.
This CL stops that from happening and in the example from above we
"only" asks for subtypes 1200 (150 classes * 8 workspaces) times.
For the `newFile` from `AbstractSingleUnitTest` example, for instance,
we go from 28,264 asks to 17,432 asks (a ~38% reduction).
Non-first runtimes when asking for references:
Before:
0:00:03.074853
0:00:03.021881
0:00:03.034707
0:00:03.115596
0:00:03.032574
After:
0:00:02.223978
0:00:02.149937
0:00:02.150236
0:00:02.104704
0:00:02.175859
Difference at 95.0% confidence
-0.894979 +/- 0.060283
-29.2867% +/- 1.97266%
(Student's t, pooled s = 0.0413338)
Change-Id: Id792a595e74de01c7186ab1263c38728f051f603
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/272623
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Generate type hierarchy rules for all interface types used in a
module. These rules are utilized by the `isSubtype()` to determine
interface subtypes.
Issue: https://github.com/dart-lang/sdk/issues/48585
Change-Id: I63f64075d4947f234eca5e730ad15588e60b9e1e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/266542
Reviewed-by: Anna Gringauze <annagrin@google.com>
Reviewed-by: Mark Zhou <markzipan@google.com>
Commit-Queue: Nicholas Shahan <nshahan@google.com>