Flutter Engine
The Flutter Engine
Classes | Public Types | Public Member Functions | Static Public Member Functions | Friends | List of all members
flutter::DartIsolate Class Reference

Represents an instance of a live isolate. An isolate is a separate Dart execution context. Different Dart isolates don't share memory and can be scheduled concurrently by the Dart VM on one of the Dart VM managed worker pool threads. More...

#include <dart_isolate.h>

Inheritance diagram for flutter::DartIsolate:
flutter::UIDartState tonic::DartState

Classes

class  Flags
 

Public Types

enum class  Phase {
  Unknown , Uninitialized , Initialized , LibrariesSetup ,
  Ready , Running , Shutdown
}
 The engine represents all dart isolates as being in one of the known phases. By invoking various methods on the Dart isolate, the engine transition the Dart isolate from one phase to the next. The Dart isolate will only move from one phase to the next in the order specified in the DartIsolate::Phase enum. That is, once the isolate has moved out of a particular phase, it can never transition back to that phase in the future. There is no error recovery mechanism and callers that find their isolates in an undesirable phase must discard the isolate and start over. More...
 

Public Member Functions

 ~DartIsolate () override
 
Phase GetPhase () const
 The current phase of the isolate. The engine represents all dart isolates as being in one of the known phases. By invoking various methods on the Dart isolate, the engine transitions the Dart isolate from one phase to the next. The Dart isolate will only move from one phase to the next in the order specified in the DartIsolate::Phase enum. That is, the once the isolate has moved out of a particular phase, it can never transition back to that phase in the future. There is no error recovery mechanism and callers that find their isolates in an undesirable phase must discard the isolate and start over. More...
 
std::string GetServiceId ()
 Returns the ID for an isolate which is used to query the service protocol. More...
 
bool PrepareForRunningFromPrecompiledCode ()
 Prepare the isolate for running for a precompiled code bundle. The Dart VM must be configured for running precompiled code. More...
 
bool PrepareForRunningFromKernel (const std::shared_ptr< const fml::Mapping > &kernel, bool child_isolate, bool last_piece)
 Prepare the isolate for running for a a list of kernel files. More...
 
bool PrepareForRunningFromKernels (std::vector< std::shared_ptr< const fml::Mapping > > kernels)
 Prepare the isolate for running for a a list of kernel files. More...
 
bool PrepareForRunningFromKernels (std::vector< std::unique_ptr< const fml::Mapping > > kernels)
 Prepare the isolate for running for a a list of kernel files. More...
 
bool RunFromLibrary (std::optional< std::string > library_name, std::optional< std::string > entrypoint, const std::vector< std::string > &args)
 Transition the root isolate to the Phase::Running phase and invoke the main entrypoint (the "main" method) in the specified library. The isolate must already be in the Phase::Ready phase. More...
 
bool Shutdown ()
 Transition the isolate to the Phase::Shutdown phase. The only thing left to do is to collect the isolate. More...
 
void AddIsolateShutdownCallback (const fml::closure &closure)
 Registers a callback that will be invoked in isolate scope just before the isolate transitions to the Phase::Shutdown phase. More...
 
std::weak_ptr< DartIsolateGetWeakIsolatePtr ()
 A weak pointer to the Dart isolate instance. This instance may only be used on the task runner that created the root isolate. More...
 
fml::RefPtr< fml::TaskRunnerGetMessageHandlingTaskRunner () const
 The task runner on which the Dart code for the root isolate is running. For the root isolate, this is the UI task runner for the shell that owns the root isolate. More...
 
Dart_Isolate CreatePlatformIsolate (Dart_Handle entry_point, char **error) override
 Creates a new isolate in the same group as this isolate, which runs on the platform thread. This method can only be invoked on the root isolate. More...
 
bool LoadLoadingUnit (intptr_t loading_unit_id, std::unique_ptr< const fml::Mapping > snapshot_data, std::unique_ptr< const fml::Mapping > snapshot_instructions)
 
void LoadLoadingUnitError (intptr_t loading_unit_id, const std::string &error_message, bool transient)
 
DartIsolateGroupDataGetIsolateGroupData ()
 
const DartIsolateGroupDataGetIsolateGroupData () const
 
- Public Member Functions inherited from flutter::UIDartState
Dart_Port main_port () const
 
bool IsRootIsolate () const
 
void SetDebugName (const std::string &name)
 
const std::string & debug_name () const
 
const std::string & logger_prefix () const
 
PlatformConfigurationplatform_configuration () const
 
void SetPlatformMessageHandler (std::weak_ptr< PlatformMessageHandler > handler)
 
Dart_Handle HandlePlatformMessage (std::unique_ptr< PlatformMessage > message)
 
const TaskRunnersGetTaskRunners () const
 
void ScheduleMicrotask (Dart_Handle handle)
 
void FlushMicrotasksNow ()
 
fml::WeakPtr< IOManagerGetIOManager () const
 
fml::RefPtr< flutter::SkiaUnrefQueueGetSkiaUnrefQueue () const
 
std::shared_ptr< VolatilePathTrackerGetVolatilePathTracker () const
 
std::shared_ptr< fml::ConcurrentTaskRunnerGetConcurrentTaskRunner () const
 
fml::TaskRunnerAffineWeakPtr< SnapshotDelegateGetSnapshotDelegate () const
 
fml::WeakPtr< ImageDecoderGetImageDecoder () const
 
fml::WeakPtr< ImageGeneratorRegistryGetImageGeneratorRegistry () const
 
std::shared_ptr< IsolateNameServerGetIsolateNameServer () const
 
tonic::DartErrorHandleType GetLastError ()
 
void LogMessage (const std::string &tag, const std::string &message) const
 
UnhandledExceptionCallback unhandled_exception_callback () const
 
int64_t GetRootIsolateToken () const
 
bool IsImpellerEnabled () const
 Whether Impeller is enabled for this application. More...
 
impeller::RuntimeStageBackend GetRuntimeStageBackend () const
 The expected type for runtime stage shaders. More...
 
virtual Dart_Isolate CreatePlatformIsolate (Dart_Handle entry_point, char **error)
 
- Public Member Functions inherited from tonic::DartState
 DartState (int dirfd=-1, std::function< void(Dart_Handle)> message_epilogue=nullptr)
 
virtual ~DartState ()
 
std::weak_ptr< DartStateGetWeakPtr ()
 
Dart_Isolate isolate ()
 
void SetIsolate (Dart_Isolate isolate)
 
Dart_PersistentHandle private_constructor_name ()
 
DartClassLibraryclass_library ()
 
DartMessageHandlermessage_handler ()
 
FileLoaderfile_loader ()
 
void MessageEpilogue (Dart_Handle message_result)
 
void SetReturnCode (uint32_t return_code)
 
void SetReturnCodeCallback (std::function< void(uint32_t)> callback)
 
bool has_set_return_code () const
 
void SetIsShuttingDown ()
 
bool IsShuttingDown ()
 
virtual void DidSetIsolate ()
 

Static Public Member Functions

static std::weak_ptr< DartIsolateCreateRunningRootIsolate (const Settings &settings, const fml::RefPtr< const DartSnapshot > &isolate_snapshot, std::unique_ptr< PlatformConfiguration > platform_configuration, Flags flags, const fml::closure &root_isolate_create_callback, const fml::closure &isolate_create_callback, const fml::closure &isolate_shutdown_callback, std::optional< std::string > dart_entrypoint, std::optional< std::string > dart_entrypoint_library, const std::vector< std::string > &dart_entrypoint_args, std::unique_ptr< IsolateConfiguration > isolate_configuration, const UIDartState::Context &context, const DartIsolate *spawning_isolate=nullptr)
 Creates an instance of a root isolate and returns a weak pointer to the same. The isolate instance may only be used safely on the engine thread on which it was created. In the shell, this is the UI thread and task runner. Using the isolate on any other thread is user error. More...
 
static Dart_Handle LoadLibraryFromKernel (const std::shared_ptr< const fml::Mapping > &mapping)
 
- Static Public Member Functions inherited from flutter::UIDartState
static UIDartStateCurrent ()
 
static void ThrowIfUIOperationsProhibited ()
 
- Static Public Member Functions inherited from tonic::DartState
static DartStateFrom (Dart_Isolate isolate)
 
static DartStateCurrent ()
 
static Dart_Handle HandleLibraryTag (Dart_LibraryTag tag, Dart_Handle library, Dart_Handle url)
 

Friends

class IsolateConfiguration
 
class DartVM
 

Additional Inherited Members

- Protected Member Functions inherited from flutter::UIDartState
 UIDartState (TaskObserverAdd add_callback, TaskObserverRemove remove_callback, std::string logger_prefix, UnhandledExceptionCallback unhandled_exception_callback, LogMessageCallback log_message_callback, std::shared_ptr< IsolateNameServer > isolate_name_server, bool is_root_isolate_, const UIDartState::Context &context)
 
 ~UIDartState () override
 
void SetPlatformConfiguration (std::unique_ptr< PlatformConfiguration > platform_configuration)
 
const std::string & GetAdvisoryScriptURI () const
 
- Protected Member Functions inherited from tonic::DartState
Dart_Isolate isolate () const
 
 TONIC_DISALLOW_COPY_AND_ASSIGN (DartState)
 

Detailed Description

Represents an instance of a live isolate. An isolate is a separate Dart execution context. Different Dart isolates don't share memory and can be scheduled concurrently by the Dart VM on one of the Dart VM managed worker pool threads.

The entire lifecycle of a Dart isolate is controlled by the Dart VM. Because of this, the engine never holds a strong pointer to the Dart VM for extended periods of time. This allows the VM (or the isolates themselves) to terminate Dart execution without consulting the engine.

The isolate that the engine creates to act as the host for the Flutter application code with UI bindings is called the root isolate.

The root isolate is special in the following ways:

Definition at line 63 of file dart_isolate.h.

Member Enumeration Documentation

◆ Phase

enum class flutter::DartIsolate::Phase
strong

The engine represents all dart isolates as being in one of the known phases. By invoking various methods on the Dart isolate, the engine transition the Dart isolate from one phase to the next. The Dart isolate will only move from one phase to the next in the order specified in the DartIsolate::Phase enum. That is, once the isolate has moved out of a particular phase, it can never transition back to that phase in the future. There is no error recovery mechanism and callers that find their isolates in an undesirable phase must discard the isolate and start over.

Enumerator
Unknown 

The initial phase of all Dart isolates. This is an internal phase and callers can never get a reference to a Dart isolate in this phase.

Uninitialized 

The Dart isolate has been created but none of the library tag or message handers have been set yet. The is an internal phase and callers can never get a reference to a Dart isolate in this phase.

Initialized 

The Dart isolate has been fully initialized but none of the libraries referenced by that isolate have been loaded yet. This is an internal phase and callers can never get a reference to a Dart isolate in this phase.

LibrariesSetup 

The isolate has been fully initialized and is waiting for the caller to associate isolate snapshots with the same. The isolate will only be ready to execute Dart code once one of the Prepare calls are successfully made.

Ready 

The isolate is fully ready to start running Dart code. Callers can transition the isolate to the next state by calling the Run or RunFromLibrary methods.

Running 

The isolate is currently running Dart code.

Shutdown 

The isolate is no longer running Dart code and is in the middle of being collected. This is in internal phase and callers can never get a reference to a Dart isolate in this phase.

Definition at line 94 of file dart_isolate.h.

94 {
95 // NOLINTBEGIN(readability-identifier-naming)
96 //--------------------------------------------------------------------------
97 /// The initial phase of all Dart isolates. This is an internal phase and
98 /// callers can never get a reference to a Dart isolate in this phase.
99 ///
100 Unknown,
101 //--------------------------------------------------------------------------
102 /// The Dart isolate has been created but none of the library tag or message
103 /// handers have been set yet. The is an internal phase and callers can
104 /// never get a reference to a Dart isolate in this phase.
105 ///
106 Uninitialized,
107 //--------------------------------------------------------------------------
108 /// The Dart isolate has been fully initialized but none of the
109 /// libraries referenced by that isolate have been loaded yet. This is an
110 /// internal phase and callers can never get a reference to a Dart isolate
111 /// in this phase.
112 ///
113 Initialized,
114 //--------------------------------------------------------------------------
115 /// The isolate has been fully initialized and is waiting for the caller to
116 /// associate isolate snapshots with the same. The isolate will only be
117 /// ready to execute Dart code once one of the `Prepare` calls are
118 /// successfully made.
119 ///
120 LibrariesSetup,
121 //--------------------------------------------------------------------------
122 /// The isolate is fully ready to start running Dart code. Callers can
123 /// transition the isolate to the next state by calling the `Run` or
124 /// `RunFromLibrary` methods.
125 ///
126 Ready,
127 //--------------------------------------------------------------------------
128 /// The isolate is currently running Dart code.
129 ///
130 Running,
131 //--------------------------------------------------------------------------
132 /// The isolate is no longer running Dart code and is in the middle of being
133 /// collected. This is in internal phase and callers can never get a
134 /// reference to a Dart isolate in this phase.
135 ///
136 Shutdown,
137 // NOLINTEND(readability-identifier-naming)
138 };
bool Shutdown()
Transition the isolate to the Phase::Shutdown phase. The only thing left to do is to collect the isol...
Definition: DM.cpp:241

Constructor & Destructor Documentation

◆ ~DartIsolate()

flutter::DartIsolate::~DartIsolate ( )
override

Definition at line 471 of file dart_isolate.cc.

471 {
473 FML_DCHECK(GetMessageHandlingTaskRunner()->RunsTasksOnCurrentThread());
474 }
475}
fml::RefPtr< fml::TaskRunner > GetMessageHandlingTaskRunner() const
The task runner on which the Dart code for the root isolate is running. For the root isolate,...
bool IsRootIsolate() const
#define FML_DCHECK(condition)
Definition: logging.h:103

Member Function Documentation

◆ AddIsolateShutdownCallback()

void flutter::DartIsolate::AddIsolateShutdownCallback ( const fml::closure closure)

Registers a callback that will be invoked in isolate scope just before the isolate transitions to the Phase::Shutdown phase.

Parameters
[in]closureThe callback to invoke on isolate shutdown.

Definition at line 1301 of file dart_isolate.cc.

1301 {
1302 shutdown_callbacks_.emplace_back(std::make_unique<AutoFireClosure>(closure));
1303}
std::function< void()> closure
Definition: closure.h:14

◆ CreatePlatformIsolate()

Dart_Isolate flutter::DartIsolate::CreatePlatformIsolate ( Dart_Handle  entry_point,
char **  error 
)
overridevirtual

Creates a new isolate in the same group as this isolate, which runs on the platform thread. This method can only be invoked on the root isolate.

Parameters
[in]entry_pointThe entrypoint to invoke once the isolate is spawned. Will be run on the platform thread.
[out]errorIf spawning fails inside the Dart VM, this is set to the error string. The error should be reported to the user. Otherwise it is set to null. It's possible for spawning to fail, but this error still be null. In that case the failure should not be reported to the user.
Returns
The newly created isolate, or null if spawning failed.

Reimplemented from flutter::UIDartState.

Definition at line 286 of file dart_isolate.cc.

287 {
288 *error = nullptr;
289 PlatformConfiguration* platform_config = platform_configuration();
290 FML_DCHECK(platform_config != nullptr);
291 std::shared_ptr<PlatformIsolateManager> platform_isolate_manager =
292 platform_config->client()->GetPlatformIsolateManager();
293 std::weak_ptr<PlatformIsolateManager> weak_platform_isolate_manager =
294 platform_isolate_manager;
295 if (platform_isolate_manager->HasShutdownMaybeFalseNegative()) {
296 // Don't set the error string. We want to silently ignore this error,
297 // because the engine is shutting down.
298 FML_LOG(INFO) << "CreatePlatformIsolate called after shutdown";
299 return nullptr;
300 }
301
302 Dart_Isolate parent_isolate = isolate();
303 Dart_ExitIsolate(); // Exit parent_isolate.
304
305 const TaskRunners& task_runners = GetTaskRunners();
306 fml::RefPtr<fml::TaskRunner> platform_task_runner =
307 task_runners.GetPlatformTaskRunner();
308 FML_DCHECK(platform_task_runner);
309
310 auto isolate_group_data = std::shared_ptr<DartIsolateGroupData>(
311 *static_cast<std::shared_ptr<DartIsolateGroupData>*>(
312 Dart_IsolateGroupData(parent_isolate)));
313
314 Settings settings(isolate_group_data->GetSettings());
315
316 // PlatformIsolate.spawn should behave like Isolate.spawn when unhandled
317 // exceptions happen (log the exception, but don't terminate the app). But the
318 // default unhandled_exception_callback may terminate the app, because it is
319 // only called for the root isolate (child isolates are managed by the VM and
320 // have a different error code path). So override it to simply log the error.
321 settings.unhandled_exception_callback = [](const std::string& error,
322 const std::string& stack_trace) {
323 FML_LOG(ERROR) << "Unhandled exception:\n" << error << "\n" << stack_trace;
324 return true;
325 };
326
327 // The platform isolate task observer must be added on the platform thread. So
328 // schedule the add function on the platform task runner.
329 TaskObserverAdd old_task_observer_add = settings.task_observer_add;
330 settings.task_observer_add = [old_task_observer_add, platform_task_runner,
331 weak_platform_isolate_manager](
332 intptr_t key, const fml::closure& callback) {
333 platform_task_runner->PostTask([old_task_observer_add,
334 weak_platform_isolate_manager, key,
335 callback]() {
336 std::shared_ptr<PlatformIsolateManager> platform_isolate_manager =
337 weak_platform_isolate_manager.lock();
338 if (platform_isolate_manager == nullptr ||
339 platform_isolate_manager->HasShutdown()) {
340 // Shutdown happened in between this task being posted, and it running.
341 // platform_isolate has already been shut down. Do nothing.
342 FML_LOG(INFO) << "Shutdown before platform isolate task observer added";
343 return;
344 }
345 old_task_observer_add(key, callback);
346 });
347 };
348
349 UIDartState::Context context(task_runners);
350 context.advisory_script_uri = isolate_group_data->GetAdvisoryScriptURI();
351 context.advisory_script_entrypoint =
352 isolate_group_data->GetAdvisoryScriptEntrypoint();
353 auto isolate_data = std::make_unique<std::shared_ptr<DartIsolate>>(
354 std::shared_ptr<DartIsolate>(
355 new DartIsolate(settings, context, platform_isolate_manager)));
356
357 IsolateMaker isolate_maker =
358 [parent_isolate](
359 std::shared_ptr<DartIsolateGroupData>* unused_isolate_group_data,
360 std::shared_ptr<DartIsolate>* isolate_data, Dart_IsolateFlags* flags,
361 char** error) {
363 /*group_member=*/parent_isolate,
364 /*name=*/"PlatformIsolate",
365 /*shutdown_callback=*/
366 reinterpret_cast<Dart_IsolateShutdownCallback>(
367 DartIsolate::SpawnIsolateShutdownCallback),
368 /*cleanup_callback=*/
369 reinterpret_cast<Dart_IsolateCleanupCallback>(
370 DartIsolateCleanupCallback),
371 /*child_isolate_data=*/isolate_data,
372 /*error=*/error);
373 };
374 Dart_Isolate platform_isolate = CreateDartIsolateGroup(
375 nullptr, std::move(isolate_data), nullptr, error, isolate_maker);
376
377 Dart_EnterIsolate(parent_isolate);
378
379 if (*error) {
380 return nullptr;
381 }
382
383 if (!platform_isolate_manager->RegisterPlatformIsolate(platform_isolate)) {
384 // The PlatformIsolateManager was shutdown while we were creating the
385 // isolate. This means that we're shutting down the engine. We need to
386 // shutdown the platform isolate.
387 FML_LOG(INFO) << "Shutdown during platform isolate creation";
388 tonic::DartIsolateScope isolate_scope(platform_isolate);
390 return nullptr;
391 }
392
393 tonic::DartApiScope api_scope;
394 Dart_PersistentHandle entry_point_handle =
395 Dart_NewPersistentHandle(entry_point);
396
397 platform_task_runner->PostTask([entry_point_handle, platform_isolate,
398 weak_platform_isolate_manager]() {
399 std::shared_ptr<PlatformIsolateManager> platform_isolate_manager =
400 weak_platform_isolate_manager.lock();
401 if (platform_isolate_manager == nullptr ||
402 platform_isolate_manager->HasShutdown()) {
403 // Shutdown happened in between this task being posted, and it running.
404 // platform_isolate has already been shut down. Do nothing.
405 FML_LOG(INFO) << "Shutdown before platform isolate entry point";
406 return;
407 }
408
409 tonic::DartIsolateScope isolate_scope(platform_isolate);
410 tonic::DartApiScope api_scope;
411 Dart_Handle entry_point = Dart_HandleFromPersistent(entry_point_handle);
412 Dart_DeletePersistentHandle(entry_point_handle);
413
414 // Disable Isolate.exit().
415 Dart_Handle isolate_lib = Dart_LookupLibrary(tonic::ToDart("dart:isolate"));
418 isolate_lib, tonic::ToDart("Isolate"), 0, nullptr);
421 Dart_SetField(isolate_type, tonic::ToDart("_mayExit"), Dart_False());
423
424 tonic::DartInvokeVoid(entry_point);
425 });
426
427 return platform_isolate;
428}
PlatformConfiguration * platform_configuration() const
const TaskRunners & GetTaskRunners() const
Dart_Isolate isolate()
Definition: dart_state.h:51
DART_EXPORT Dart_Handle Dart_HandleFromPersistent(Dart_PersistentHandle object)
DART_EXPORT Dart_Handle Dart_GetNonNullableType(Dart_Handle library, Dart_Handle class_name, intptr_t number_of_type_arguments, Dart_Handle *type_arguments)
void(* Dart_IsolateCleanupCallback)(void *isolate_group_data, void *isolate_data)
Definition: dart_api.h:729
DART_EXPORT void Dart_ShutdownIsolate(void)
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
DART_EXPORT Dart_PersistentHandle Dart_NewPersistentHandle(Dart_Handle object)
DART_EXPORT Dart_Isolate Dart_CreateIsolateInGroup(Dart_Isolate group_member, const char *name, Dart_IsolateShutdownCallback shutdown_callback, Dart_IsolateCleanupCallback cleanup_callback, void *child_isolate_data, char **error)
struct _Dart_Isolate * Dart_Isolate
Definition: dart_api.h:88
DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url)
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_SetField(Dart_Handle container, Dart_Handle name, Dart_Handle value)
Dart_Handle Dart_PersistentHandle
Definition: dart_api.h:259
DART_EXPORT Dart_Handle Dart_False(void)
void(* Dart_IsolateShutdownCallback)(void *isolate_group_data, void *isolate_data)
Definition: dart_api.h:711
DART_EXPORT void * Dart_IsolateGroupData(Dart_Isolate isolate)
DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate)
DART_EXPORT void Dart_ExitIsolate(void)
DART_EXPORT void Dart_DeletePersistentHandle(Dart_PersistentHandle object)
FlutterSemanticsFlag flags
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
#define FML_LOG(severity)
Definition: logging.h:82
#define FML_CHECK(condition)
Definition: logging.h:85
std::function< void(intptr_t, fml::closure)> TaskObserverAdd
Definition: settings.h:82
Dart_Handle ToDart(const T &object)
Dart_Handle DartInvokeVoid(Dart_Handle closure)
Definition: dart_invoke.cc:29
bool CheckAndHandleError(Dart_Handle handle)
Definition: dart_error.cc:33
#define ERROR(message)
Definition: elf_loader.cc:260

◆ CreateRunningRootIsolate()

std::weak_ptr< DartIsolate > flutter::DartIsolate::CreateRunningRootIsolate ( const Settings settings,
const fml::RefPtr< const DartSnapshot > &  isolate_snapshot,
std::unique_ptr< PlatformConfiguration platform_configuration,
Flags  flags,
const fml::closure root_isolate_create_callback,
const fml::closure isolate_create_callback,
const fml::closure isolate_shutdown_callback,
std::optional< std::string >  dart_entrypoint,
std::optional< std::string >  dart_entrypoint_library,
const std::vector< std::string > &  dart_entrypoint_args,
std::unique_ptr< IsolateConfiguration isolate_configuration,
const UIDartState::Context context,
const DartIsolate spawning_isolate = nullptr 
)
static

Creates an instance of a root isolate and returns a weak pointer to the same. The isolate instance may only be used safely on the engine thread on which it was created. In the shell, this is the UI thread and task runner. Using the isolate on any other thread is user error.

The isolate that the engine creates to act as the host for the Flutter application code with UI bindings is called the root isolate.

The root isolate is special in the following ways:

  • The root isolate forms a new isolate group. Child isolates are added to their parents groups. When the root isolate dies, all isolates in its group are terminated.
  • Only root isolates get UI bindings.
  • Root isolates execute their code on engine managed threads. All other isolates run their Dart code on Dart VM managed thread pool workers that the engine has no control over.
  • Since the engine does not know the thread on which non-root isolates are run, the engine has no opportunity to get a reference to non-root isolates. Such isolates can only be terminated if they terminate themselves or their isolate group is torn down.
Parameters
[in]settingsThe settings used to create the isolate.
[in]platform_configurationThe platform configuration for handling communication with the framework.
[in]flagsThe Dart isolate flags for this isolate instance.
[in]dart_entrypointThe name of the dart entrypoint function to invoke.
[in]dart_entrypoint_libraryThe name of the dart library containing the entrypoint.
[in]dart_entrypoint_argsArguments passed as a List<String> to Dart's entrypoint function.
[in]isolate_configurationThe isolate configuration used to configure the isolate before invoking the entrypoint.
[in]root_isolate_create_callbackA callback called after the root isolate is created, without isolate scope. This gives the caller a chance to finish any setup before running the Dart program, and after any embedder callbacks in the settings object.
[in]isolate_create_callbackThe isolate create callback. This will be called when the before the main Dart entrypoint is invoked in the root isolate. The isolate is already in the running state at this point and an isolate scope is current.
[in]isolate_shutdown_callbackThe isolate shutdown callback. This will be called before the isolate is about to transition into the Shutdown phase. The isolate is still running at this point and an isolate scope is current.
[in]contextEngine-owned state which is accessed by the root dart isolate.
[in]spawning_isolateThe isolate that is spawning the new isolate.
Returns
A weak pointer to the root Dart isolate. The caller must ensure that the isolate is not referenced for long periods of time as it prevents isolate collection when the isolate terminates itself. The caller may also only use the isolate on the thread on which the isolate was created.

Definition at line 90 of file dart_isolate.cc.

103 {
104 if (!isolate_snapshot) {
105 FML_LOG(ERROR) << "Invalid isolate snapshot.";
106 return {};
107 }
108
109 if (!isolate_configuration) {
110 FML_LOG(ERROR) << "Invalid isolate configuration.";
111 return {};
112 }
113
114 isolate_flags.SetNullSafetyEnabled(
115 isolate_configuration->IsNullSafetyEnabled(*isolate_snapshot));
116 isolate_flags.SetIsDontNeedSafe(isolate_snapshot->IsDontNeedSafe());
117
118 auto isolate = CreateRootIsolate(settings, //
119 isolate_snapshot, //
120 std::move(platform_configuration), //
121 isolate_flags, //
122 isolate_create_callback, //
123 isolate_shutdown_callback, //
124 context, //
125 spawning_isolate //
126 )
127 .lock();
128
129 if (!isolate) {
130 FML_LOG(ERROR) << "Could not create root isolate.";
131 return {};
132 }
133
134 fml::ScopedCleanupClosure shutdown_on_error([isolate]() {
135 if (!isolate->Shutdown()) {
136 FML_DLOG(ERROR) << "Could not shutdown transient isolate.";
137 }
138 });
139
140 if (isolate->GetPhase() != DartIsolate::Phase::LibrariesSetup) {
141 FML_LOG(ERROR) << "Root isolate was created in an incorrect phase: "
142 << static_cast<int>(isolate->GetPhase());
143 return {};
144 }
145
146 if (!isolate_configuration->PrepareIsolate(*isolate.get())) {
147 FML_LOG(ERROR) << "Could not prepare isolate.";
148 return {};
149 }
150
151 if (isolate->GetPhase() != DartIsolate::Phase::Ready) {
152 FML_LOG(ERROR) << "Root isolate not in the ready phase for Dart entrypoint "
153 "invocation.";
154 return {};
155 }
156
157 if (settings.root_isolate_create_callback) {
158 // Isolate callbacks always occur in isolate scope and before user code has
159 // had a chance to run.
160 tonic::DartState::Scope scope(isolate.get());
161 settings.root_isolate_create_callback(*isolate.get());
162 }
163
164 if (root_isolate_create_callback) {
165 root_isolate_create_callback();
166 }
167
168 if (!isolate->RunFromLibrary(std::move(dart_entrypoint_library), //
169 std::move(dart_entrypoint), //
170 dart_entrypoint_args)) {
171 FML_LOG(ERROR) << "Could not run the run main Dart entrypoint.";
172 return {};
173 }
174
175 if (settings.root_isolate_shutdown_callback) {
176 isolate->AddIsolateShutdownCallback(
177 settings.root_isolate_shutdown_callback);
178 }
179
180 shutdown_on_error.Release();
181
182 return isolate;
183}
Wraps a closure that is invoked in the destructor unless released by the caller.
Definition: closure.h:32

◆ GetIsolateGroupData() [1/2]

DartIsolateGroupData & flutter::DartIsolate::GetIsolateGroupData ( )

Definition at line 1028 of file dart_isolate.cc.

1028 {
1029 std::shared_ptr<DartIsolateGroupData>* isolate_group_data =
1030 static_cast<std::shared_ptr<DartIsolateGroupData>*>(
1032 return **isolate_group_data;
1033}

◆ GetIsolateGroupData() [2/2]

const DartIsolateGroupData & flutter::DartIsolate::GetIsolateGroupData ( ) const

Definition at line 1035 of file dart_isolate.cc.

1035 {
1036 DartIsolate* non_const_this = const_cast<DartIsolate*>(this);
1037 return non_const_this->GetIsolateGroupData();
1038}

◆ GetMessageHandlingTaskRunner()

fml::RefPtr< fml::TaskRunner > flutter::DartIsolate::GetMessageHandlingTaskRunner ( ) const

The task runner on which the Dart code for the root isolate is running. For the root isolate, this is the UI task runner for the shell that owns the root isolate.

Returns
The message handling task runner.

Definition at line 533 of file dart_isolate.cc.

533 {
534 return message_handling_task_runner_;
535}

◆ GetPhase()

DartIsolate::Phase flutter::DartIsolate::GetPhase ( ) const

The current phase of the isolate. The engine represents all dart isolates as being in one of the known phases. By invoking various methods on the Dart isolate, the engine transitions the Dart isolate from one phase to the next. The Dart isolate will only move from one phase to the next in the order specified in the DartIsolate::Phase enum. That is, the once the isolate has moved out of a particular phase, it can never transition back to that phase in the future. There is no error recovery mechanism and callers that find their isolates in an undesirable phase must discard the isolate and start over.

Returns
The current isolate phase.

Definition at line 477 of file dart_isolate.cc.

477 {
478 return phase_;
479}

◆ GetServiceId()

std::string flutter::DartIsolate::GetServiceId ( )

Returns the ID for an isolate which is used to query the service protocol.

Returns
The service identifier for this isolate.

Definition at line 481 of file dart_isolate.cc.

481 {
482 const char* service_id_buf = Dart_IsolateServiceId(isolate());
483 std::string service_id(service_id_buf);
484 free(const_cast<char*>(service_id_buf));
485 return service_id;
486}
DART_EXPORT const char * Dart_IsolateServiceId(Dart_Isolate isolate)

◆ GetWeakIsolatePtr()

std::weak_ptr< DartIsolate > flutter::DartIsolate::GetWeakIsolatePtr ( )

A weak pointer to the Dart isolate instance. This instance may only be used on the task runner that created the root isolate.

Returns
The weak isolate pointer.

Definition at line 1297 of file dart_isolate.cc.

1297 {
1298 return std::static_pointer_cast<DartIsolate>(shared_from_this());
1299}

◆ LoadLibraryFromKernel()

Dart_Handle flutter::DartIsolate::LoadLibraryFromKernel ( const std::shared_ptr< const fml::Mapping > &  mapping)
static

Returns the "main" entrypoint of the library contained in the kernel data in mapping.

Definition at line 1347 of file dart_isolate.cc.

1348 {
1350 return Dart_Null();
1351 }
1352
1353 auto* isolate_group_data =
1354 static_cast<std::shared_ptr<DartIsolateGroupData>*>(
1356 // Mapping must be retained until isolate shutdown.
1357 (*isolate_group_data)->AddKernelBuffer(mapping);
1358
1359 auto lib =
1360 Dart_LoadLibraryFromKernel(mapping->GetMapping(), mapping->GetSize());
1361 if (tonic::CheckAndHandleError(lib)) {
1362 return Dart_Null();
1363 }
1364 auto result = Dart_FinalizeLoading(false);
1365 if (Dart_IsError(result)) {
1366 return result;
1367 }
1368 return Dart_GetField(lib, Dart_NewStringFromCString("main"));
1369}
static bool IsRunningPrecompiledCode()
Checks if VM instances in the process can run precompiled code. This call can be made at any time and...
Definition: dart_vm.cc:205
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_LoadLibraryFromKernel(const uint8_t *kernel_buffer, intptr_t kernel_buffer_size)
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_FinalizeLoading(bool complete_futures)
DART_EXPORT Dart_Handle Dart_Null(void)
DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char *str)
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_GetField(Dart_Handle container, Dart_Handle name)
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
DART_EXPORT void * Dart_CurrentIsolateGroupData(void)

◆ LoadLoadingUnit()

bool flutter::DartIsolate::LoadLoadingUnit ( intptr_t  loading_unit_id,
std::unique_ptr< const fml::Mapping snapshot_data,
std::unique_ptr< const fml::Mapping snapshot_instructions 
)

Definition at line 537 of file dart_isolate.cc.

540 {
541 tonic::DartState::Scope scope(this);
542
543 fml::RefPtr<DartSnapshot> dart_snapshot =
545 std::move(snapshot_data), std::move(snapshot_instructions));
546
548 loading_unit_id, dart_snapshot->GetDataMapping(),
549 dart_snapshot->GetInstructionsMapping());
551 LoadLoadingUnitError(loading_unit_id, Dart_GetError(result),
552 /*transient*/ true);
553 return false;
554 }
555 loading_unit_snapshots_.insert(dart_snapshot);
556 return true;
557}
void LoadLoadingUnitError(intptr_t loading_unit_id, const std::string &error_message, bool transient)
static fml::RefPtr< DartSnapshot > IsolateSnapshotFromMappings(const std::shared_ptr< const fml::Mapping > &snapshot_data, const std::shared_ptr< const fml::Mapping > &snapshot_instructions)
Create an isolate snapshot from existing fml::Mappings.
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_DeferredLoadComplete(intptr_t loading_unit_id, const uint8_t *snapshot_data, const uint8_t *snapshot_instructions)
DART_EXPORT const char * Dart_GetError(Dart_Handle handle)

◆ LoadLoadingUnitError()

void flutter::DartIsolate::LoadLoadingUnitError ( intptr_t  loading_unit_id,
const std::string &  error_message,
bool  transient 
)

Definition at line 559 of file dart_isolate.cc.

561 {
562 tonic::DartState::Scope scope(this);
564 loading_unit_id, error_message.c_str(), transient);
566}
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_DeferredLoadCompleteError(intptr_t loading_unit_id, const char *error_message, bool transient)

◆ PrepareForRunningFromKernel()

bool flutter::DartIsolate::PrepareForRunningFromKernel ( const std::shared_ptr< const fml::Mapping > &  kernel,
bool  child_isolate,
bool  last_piece 
)

Prepare the isolate for running for a a list of kernel files.

        The Dart VM must be configured for running from kernel
        snapshots.

        The isolate must already be in the `Phase::LibrariesSetup`
        phase. This call can be made multiple times. After a series of
        successful calls to this method, the caller can specify the
        last kernel file mapping by specifying `last_piece` to `true`.
        On success, the isolate will transition to the `Phase::Ready`
        phase.
Parameters
[in]kernelThe kernel mapping.
[in]last_pieceIndicates if this is the last kernel mapping expected. After this point, the isolate will attempt a transition to the Phase::Ready phase.
Returns
If the kernel mapping supplied was successfully used to prepare the isolate.

Definition at line 731 of file dart_isolate.cc.

734 {
735 TRACE_EVENT0("flutter", "DartIsolate::PrepareForRunningFromKernel");
736 if (phase_ != Phase::LibrariesSetup) {
737 return false;
738 }
739
741 return false;
742 }
743
744 tonic::DartState::Scope scope(this);
745
746 if (!child_isolate && !is_spawning_in_group_) {
747 if (!mapping || mapping->GetSize() == 0) {
748 return false;
749 }
750
751 // Use root library provided by kernel in favor of one provided by snapshot.
753
754 if (!LoadKernel(mapping, last_piece)) {
755 return false;
756 }
757 }
758
759 if (!last_piece) {
760 // More to come.
761 return true;
762 }
763
765 return false;
766 }
767
768 if (!MarkIsolateRunnable()) {
769 return false;
770 }
771
772 // Child isolate shares root isolate embedder_isolate (lines 691 and 693
773 // below). Re-initializing child_isolate_preparer_ lambda while it is being
774 // executed leads to crashes.
775 if (GetIsolateGroupData().GetChildIsolatePreparer() == nullptr) {
777 [buffers =
778 GetIsolateGroupData().GetKernelBuffers()](DartIsolate* isolate) {
779 for (uint64_t i = 0; i < buffers.size(); i++) {
780 bool last_piece = i + 1 == buffers.size();
781 const std::shared_ptr<const fml::Mapping>& buffer = buffers.at(i);
782 if (!isolate->PrepareForRunningFromKernel(buffer,
783 /*child_isolate=*/true,
784 last_piece)) {
785 return false;
786 }
787 }
788 return true;
789 });
790 }
791
792 const fml::closure& isolate_create_callback =
794 if (isolate_create_callback) {
795 isolate_create_callback();
796 }
797
798 phase_ = Phase::Ready;
799
800 return true;
801}
void SetChildIsolatePreparer(const ChildIsolatePreparer &value)
const fml::closure & GetIsolateCreateCallback() const
DartIsolateGroupData & GetIsolateGroupData()
DART_EXPORT bool Dart_IsNull(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_RootLibrary(void)
DART_EXPORT Dart_Handle Dart_SetRootLibrary(Dart_Handle library)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131

◆ PrepareForRunningFromKernels() [1/2]

bool flutter::DartIsolate::PrepareForRunningFromKernels ( std::vector< std::shared_ptr< const fml::Mapping > >  kernels)

Prepare the isolate for running for a a list of kernel files.

        The Dart VM must be configured for running from kernel
        snapshots.

        The isolate must already be in the `Phase::LibrariesSetup`
        phase. After a successful call to this method, the isolate
        will transition to the `Phase::Ready` phase.
Parameters
[in]kernelsThe kernels
Returns
If the kernel mappings supplied were successfully used to prepare the isolate.

Definition at line 803 of file dart_isolate.cc.

804 {
805 const auto count = kernels.size();
806 if (count == 0) {
807 return false;
808 }
809
810 for (size_t i = 0; i < count; ++i) {
811 bool last = (i == (count - 1));
812 if (!PrepareForRunningFromKernel(kernels[i], /*child_isolate=*/false,
813 last)) {
814 return false;
815 }
816 }
817
818 return true;
819}
int count
Definition: FontMgrTest.cpp:50
bool PrepareForRunningFromKernel(const std::shared_ptr< const fml::Mapping > &kernel, bool child_isolate, bool last_piece)
Prepare the isolate for running for a a list of kernel files.

◆ PrepareForRunningFromKernels() [2/2]

bool flutter::DartIsolate::PrepareForRunningFromKernels ( std::vector< std::unique_ptr< const fml::Mapping > >  kernels)

Prepare the isolate for running for a a list of kernel files.

        The Dart VM must be configured for running from kernel
        snapshots.

        The isolate must already be in the `Phase::LibrariesSetup`
        phase. After a successful call to this method, the isolate
        will transition to the `Phase::Ready` phase.
Parameters
[in]kernelsThe kernels
Returns
If the kernel mappings supplied were successfully used to prepare the isolate.

Definition at line 821 of file dart_isolate.cc.

822 {
823 std::vector<std::shared_ptr<const fml::Mapping>> shared_kernels;
824 shared_kernels.reserve(kernels.size());
825 for (auto& kernel : kernels) {
826 shared_kernels.emplace_back(std::move(kernel));
827 }
828 return PrepareForRunningFromKernels(shared_kernels);
829}
bool PrepareForRunningFromKernels(std::vector< std::shared_ptr< const fml::Mapping > > kernels)
Prepare the isolate for running for a a list of kernel files.

◆ PrepareForRunningFromPrecompiledCode()

bool flutter::DartIsolate::PrepareForRunningFromPrecompiledCode ( )

Prepare the isolate for running for a precompiled code bundle. The Dart VM must be configured for running precompiled code.

The isolate must already be in the Phase::LibrariesSetup phase. After a successful call to this method, the isolate will transition to the Phase::Ready phase.

Returns
Whether the isolate was prepared and the described phase transition made.

Definition at line 672 of file dart_isolate.cc.

672 {
673 TRACE_EVENT0("flutter", "DartIsolate::PrepareForRunningFromPrecompiledCode");
674 if (phase_ != Phase::LibrariesSetup) {
675 return false;
676 }
677
678 tonic::DartState::Scope scope(this);
679
681 return false;
682 }
683
684 if (!MarkIsolateRunnable()) {
685 return false;
686 }
687
688 if (GetIsolateGroupData().GetChildIsolatePreparer() == nullptr) {
690 return isolate->PrepareForRunningFromPrecompiledCode();
691 });
692 }
693
694 const fml::closure& isolate_create_callback =
696 if (isolate_create_callback) {
697 isolate_create_callback();
698 }
699
700 phase_ = Phase::Ready;
701 return true;
702}

◆ RunFromLibrary()

bool flutter::DartIsolate::RunFromLibrary ( std::optional< std::string >  library_name,
std::optional< std::string >  entrypoint,
const std::vector< std::string > &  args 
)

Transition the root isolate to the Phase::Running phase and invoke the main entrypoint (the "main" method) in the specified library. The isolate must already be in the Phase::Ready phase.

Parameters
[in]library_nameThe name of the library in which to invoke the supplied entrypoint.
[in]entrypointThe entrypoint in library_name
[in]argsA list of string arguments to the entrypoint.
Returns
If the isolate successfully transitioned to the running phase and the main entrypoint was invoked.

Definition at line 885 of file dart_isolate.cc.

887 {
888 TRACE_EVENT0("flutter", "DartIsolate::RunFromLibrary");
889 if (phase_ != Phase::Ready) {
890 return false;
891 }
892
893 tonic::DartState::Scope scope(this);
894
895 auto library_handle =
896 library_name.has_value() && !library_name.value().empty()
897 ? ::Dart_LookupLibrary(tonic::ToDart(library_name.value().c_str()))
898 : ::Dart_RootLibrary();
899 auto entrypoint_handle = entrypoint.has_value() && !entrypoint.value().empty()
900 ? tonic::ToDart(entrypoint.value().c_str())
901 : tonic::ToDart("main");
902
904 // TODO(gaaclarke): Remove once the framework PR lands that uses `--source`
905 // to compile the Dart Plugin Registrant
906 // (https://github.com/flutter/flutter/pull/100572).
908 }
909
910 auto user_entrypoint_function =
911 ::Dart_GetField(library_handle, entrypoint_handle);
912
913 auto entrypoint_args = tonic::ToDart(args);
914
915 if (!InvokeMainEntrypoint(user_entrypoint_function, entrypoint_args)) {
916 return false;
917 }
918
919 phase_ = Phase::Running;
920
921 return true;
922}
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
bool InvokeDartPluginRegistrantIfAvailable(Dart_Handle library_handle)
bool FindAndInvokeDartPluginRegistrant()
static bool InvokeMainEntrypoint(Dart_Handle user_entrypoint_function, Dart_Handle args)

◆ Shutdown()

bool flutter::DartIsolate::Shutdown ( )

Transition the isolate to the Phase::Shutdown phase. The only thing left to do is to collect the isolate.

Returns
If the isolate successfully transitioned to the shutdown phase.

Definition at line 924 of file dart_isolate.cc.

924 {
925 TRACE_EVENT0("flutter", "DartIsolate::Shutdown");
926 // This call may be re-entrant since Dart_ShutdownIsolate can invoke the
927 // cleanup callback which deletes the embedder side object of the dart isolate
928 // (a.k.a. this).
929 if (phase_ == Phase::Shutdown) {
930 return false;
931 }
932 phase_ = Phase::Shutdown;
933 Dart_Isolate vm_isolate = isolate();
934 // The isolate can be nullptr if this instance is the stub isolate data used
935 // during root isolate creation.
936 if (vm_isolate != nullptr) {
937 // We need to enter the isolate because Dart_ShutdownIsolate does not take
938 // the isolate to shutdown as a parameter.
939 FML_DCHECK(Dart_CurrentIsolate() == nullptr);
940 Dart_EnterIsolate(vm_isolate);
942 FML_DCHECK(Dart_CurrentIsolate() == nullptr);
943 }
944 return true;
945}
DART_EXPORT Dart_Isolate Dart_CurrentIsolate(void)

Friends And Related Function Documentation

◆ DartVM

friend class DartVM
friend

Definition at line 431 of file dart_isolate.h.

◆ IsolateConfiguration

friend class IsolateConfiguration
friend

Definition at line 420 of file dart_isolate.h.


The documentation for this class was generated from the following files: