Announcing Dart 2.2: Faster native code, support for set literals

By Michael Thomsen

Today, we’re announcing the stable release of the Dart 2.2 SDK, an incremental update to Dart 2 that offers improved performance of ahead-of-time (AOT) compiled native code and a new set literal language feature.

We continue our work to make AOT-compiled code, such as Flutter apps, even faster. In Dart 2.1, we reduced overhead of type checks, greatly reducing the cost of the type checks for both AOT-compiled code and for code run in the VM with JIT (just-in-time) compilation.

In Dart 2.2, we have focused specifically on performance of AOT-compiled code, improving AOT performance by 11–16% on microbenchmarks (at the cost of a ~1% increase in code size). This improvement is the result of several quarters’ work to reduce the overhead of static calls. Our optimized AOT code is now able to call the destination directly using a PC-relative call (that is, using the program counter); before we had to make several lookups to an object pool to determine the destination address. These optimizations are especially useful when code contains lots of constructor and static method calls, such as Flutter user interface code that creates lots of widgets.

Dart’s core library (dart:core) contains a number of collection classes for modelling Maps, Lists, and Sets of objects. Maps are collections of key-value pairs. Lists are ordered sequences of values, where each value may be accessed by an index, and may occur more than once. Sets are unordered collections of values, where each value can occur only once, and where you can efficiently check whether a value is in the set.

Dart collections are commonly initialized with compile-time constants, so Dart has a convenient literal syntax for expressing this initialization. In Dart, a List can be initialized with:

Previously, Dart supported the literal syntax only for Lists and Maps, so initialization of Sets was cumbersome as we had to initialize via a list:

This code is not just inconvenient and inefficient; the lack of literal support prevents making currencies a compile-time constant. With Dart 2.2’s extension of literals to support sets, we can initialize a set and make it const using a convenient new syntax:

For real-world examples of how the Flutter team is starting to apply set literals, see PR #27811. For more general details on how to use set literals, see the updated Dart 2.2 language tour.

The Dart language implementations — the Dart VM used by Flutter, the dart2js compiler, and the Dart dev compiler (dartdevc) — share a common front end. The Dart Common Front End, or CFE, parses Dart code, performs type inference, and translates Dart into a lower-level intermediate language that back-end implementations accept as input.

The set literals feature is an example of a language construct that we were able to develop rapidly because of the CFE. The code for parsing set literals and performing type inference was implemented once in the CFE for all Dart back ends. In addition, we built a front-end-only transitional implementation that could be used by the back ends initially. In the transitional implementation, the non-const version of the currencies set literal above was translated during compilation into the equivalent of:

The transitional implementation of const set literals is different because const sets cannot be built up incrementally in pieces. Instead, we implemented this in terms of a private unmodifiable set class that wraps a const map, where the set elements are the keys of the map:

The unmodifiable set class implements the methods in the Set interface in terms of the wrapped map.

Overall, we were able to implement set literals initially as a CFE-only feature. The back ends could use the CFE implementation initially, and later develop their own native support independently of the initial launch of the feature. This allowed backends to postpone their native support until the performance aspects of this feature were better understood.

Dart 2 was such a substantial upgrade to Dart that it’s taken us a while to get the formal Dart language specification updated to match all the changes we made. We have finally completed that work, and the spec is up-to-date as of Dart 2.2. We’ve also moved the language specification source to the new language repository, and added continuous integration to ensure a rolling draft specification is generated in PDF format as we evolve the specification for future versions of the Dart language. Both the 2.2 and rolling Dart 2.x specifications are available from the Dart specification page.

Dart SDK 2.2 is available from the Dart homepage today. If you’re a Flutter developer, Dart 2.2 is already included. (Note: the current Flutter master and dev channels will report Dart 2.2. Today’s Flutter 1.2 stable release will report Dart 2.1.2; this has the same features as Dart 2.2).

That’s it for now. We hope you enjoy Dart 2.2!