Execute Dart code natively with Dart VM
This VM explainer may still be a work in progress, but Dart VM is already good to go. Dart VM provides multiple ways to compile and execute your Dart code natively. Whether it’s from a JIT and AOT compilation pipeline or a snapshot, Dart VM gives developers their code execution method of choice.
Dart’s had a lot of exciting news recently. There was the 2.1 version release late last year, along with a revitalization of Flutter and the creation of Kiwi, a dependency injection library. Now, there’s an exciting new look at an integral part of this programming language: the Dart VM.
Dart VM is a collection of components for executing Dart code natively. While this introduction is something of a work in progress, Dart VM already comes with a whole host of features like a runtime system, garbage collection, snapshots, and core libraries.
Developers can enjoy a modest developing experience, including debugging, profiling, and hot-reload, all available through the service protocol. There are also Just-in-Time (JIT) and Ahead-of-Time (AOT) compilation pipelines, giving developers more options when executing their code. Of course, Dart VM also comes with interpreters and ARM simulators.
Don’t be too fooled by the name; it’s something of a historical artifact. Dart VM is a virtual machine in the sense that it provides an execution environment for a high-level programming language like Dart. However, that doesn’t mean that your Dart code is always interpreted or JIT-compiled when executed on the Dart VM.
In fact, Dart VM offers multiple ways to interpret your code. Developers are spoiled for choice, since Dart VM can execute the code from the source or Kernal binary using JIT, from snapshots, from AOT snapshots, or from the AppJIT snapshot.
The biggest difference between these options is basically when and how the VM converts Dart source code to executable code. No matter which option you go with, the runtime environment that facilitates the execution remains the same.
How does Dart VM work?
Essentially, any of your Dart code in the VM runs within an isolate. An isolate is like an isolated Dart environment with its own memory heap and thread of control. While there can be a bunch of isolates executing code at the same time, they can’t share a state directly and they can only communicate by passing messages through ports.
The OS thread can only enter a single isolate at the time. If it wants to enter another isolate, it must leave the one it is currently in. Additionally, there is only one mutator thread associated with an isolate at a time. The mutator thread executes Dart code and uses the VM’s public C API.
Beyond the mutator thread, an isolate can also be associated with multiple helper threads, including a background JIT compiler thread, GC sweeper threads, and even concurrent GC marker threads.
More information about how all this works is available here.