Flutter Engine
 
Loading...
Searching...
No Matches
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.
 
std::string GetServiceId ()
 Returns the ID for an isolate which is used to query the service protocol.
 
bool PrepareForRunningFromPrecompiledCode ()
 Prepare the isolate for running for a precompiled code bundle. The Dart VM must be configured for running precompiled code.
 
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.
 
bool PrepareForRunningFromKernels (std::vector< std::shared_ptr< const fml::Mapping > > kernels)
 Prepare the isolate for running for a a list of kernel files.
 
bool PrepareForRunningFromKernels (std::vector< std::unique_ptr< const fml::Mapping > > kernels)
 Prepare the isolate for running for a a list of kernel files.
 
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.
 
bool Shutdown ()
 Transition the isolate to the Phase::Shutdown phase. The only thing left to do is to collect the isolate.
 
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.
 
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.
 
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.
 
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.
 
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
 
void SetOwnerToCurrentThread ()
 
- 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 ()
 
bool HasPendingMicrotasks ()
 
fml::WeakPtr< IOManagerGetIOManager () const
 
fml::RefPtr< flutter::SkiaUnrefQueueGetSkiaUnrefQueue () const
 
std::shared_ptr< fml::ConcurrentTaskRunnerGetConcurrentTaskRunner () const
 
fml::TaskRunnerAffineWeakPtr< SnapshotDelegateGetSnapshotDelegate () const
 
fml::TaskRunnerAffineWeakPtr< ImageDecoderGetImageDecoder () const
 
fml::TaskRunnerAffineWeakPtr< 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 IsDeterministicRenderingEnabled () const
 Whether deterministic rendering practices are enabled for this application.
 
bool IsImpellerEnabled () const
 Whether Impeller is enabled for this application.
 
bool IsFlutterGPUEnabled () const
 Whether Flutter GPU is enabled for this application.
 
impeller::RuntimeStageBackend GetRuntimeStageBackend () const
 The runtime stage to use for fragment shaders.
 
- 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 ()
 

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, std::shared_ptr< NativeAssetsManager > native_assets_manager=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.
 
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:

  • 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.

Definition at line 57 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 88 of file dart_isolate.h.

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

Constructor & Destructor Documentation

◆ ~DartIsolate()

flutter::DartIsolate::~DartIsolate ( )
override

Definition at line 480 of file dart_isolate.cc.

480 {
482 FML_DCHECK(GetMessageHandlingTaskRunner()->RunsTasksOnCurrentThread());
483 }
484}
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:122

References FML_DCHECK, GetMessageHandlingTaskRunner(), and flutter::UIDartState::IsRootIsolate().

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 1388 of file dart_isolate.cc.

1388 {
1389 shutdown_callbacks_.emplace_back(std::make_unique<AutoFireClosure>(closure));
1390}

◆ 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 294 of file dart_isolate.cc.

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

References flutter::UIDartState::Context::advisory_script_entrypoint, flutter::UIDartState::Context::advisory_script_uri, callback, tonic::CheckAndHandleError(), flutter::PlatformConfiguration::client(), tonic::DartInvokeVoid(), error, FML_CHECK, FML_DCHECK, FML_LOG, flutter::PlatformConfigurationClient::GetPlatformIsolateManager(), flutter::TaskRunners::GetPlatformTaskRunner(), flutter::UIDartState::GetTaskRunners(), tonic::DartState::isolate(), key, flutter::UIDartState::platform_configuration(), flutter::Settings::task_observer_add, tonic::ToDart(), and flutter::Settings::unhandled_exception_callback.

◆ 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,
std::shared_ptr< NativeAssetsManager native_assets_manager = 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 87 of file dart_isolate.cc.

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

References FML_LOG, tonic::DartState::isolate(), flutter::Settings::kMergeAfterLaunch, LibrariesSetup, flutter::Settings::merged_platform_ui_thread, flutter::UIDartState::platform_configuration(), Ready, flutter::Settings::root_isolate_create_callback, flutter::Settings::root_isolate_shutdown_callback, flutter::DartIsolate::Flags::SetIsDontNeedSafe(), and flutter::DartIsolate::Flags::SetNullSafetyEnabled().

Referenced by flutter::testing::CreateAndRunRootIsolate(), flutter::RuntimeController::LaunchRootIsolate(), flutter::testing::RunDartCodeInIsolateOnUITaskRunner(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::PlatformIsolateManagerTest::TestWithRootIsolate().

◆ GetIsolateGroupData() [1/2]

DartIsolateGroupData & flutter::DartIsolate::GetIsolateGroupData ( )

Definition at line 1052 of file dart_isolate.cc.

1052 {
1053 std::shared_ptr<DartIsolateGroupData>* isolate_group_data =
1054 static_cast<std::shared_ptr<DartIsolateGroupData>*>(
1055 Dart_IsolateGroupData(isolate()));
1056 return **isolate_group_data;
1057}

References tonic::DartState::isolate().

Referenced by GetIsolateGroupData(), PrepareForRunningFromKernel(), and PrepareForRunningFromPrecompiledCode().

◆ GetIsolateGroupData() [2/2]

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

Definition at line 1059 of file dart_isolate.cc.

1059 {
1060 DartIsolate* non_const_this = const_cast<DartIsolate*>(this);
1061 return non_const_this->GetIsolateGroupData();
1062}

References GetIsolateGroupData().

◆ 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 548 of file dart_isolate.cc.

548 {
549 return message_handling_task_runner_;
550}

Referenced by ~DartIsolate().

◆ 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 486 of file dart_isolate.cc.

486 {
487 return phase_;
488}

Referenced by flutter::IsolateConfiguration::PrepareIsolate().

◆ 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 490 of file dart_isolate.cc.

490 {
491 const char* service_id_buf = Dart_IsolateServiceId(isolate());
492 std::string service_id(service_id_buf);
493 free(const_cast<char*>(service_id_buf));
494 return service_id;
495}

References tonic::DartState::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 1379 of file dart_isolate.cc.

1379 {
1380 return std::static_pointer_cast<DartIsolate>(shared_from_this());
1381}

◆ 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 1434 of file dart_isolate.cc.

1435 {
1437 return Dart_Null();
1438 }
1439
1440 auto* isolate_group_data =
1441 static_cast<std::shared_ptr<DartIsolateGroupData>*>(
1442 Dart_CurrentIsolateGroupData());
1443 // Mapping must be retained until isolate shutdown.
1444 (*isolate_group_data)->AddKernelBuffer(mapping);
1445
1446 auto lib =
1447 Dart_LoadLibraryFromKernel(mapping->GetMapping(), mapping->GetSize());
1448 if (tonic::CheckAndHandleError(lib)) {
1449 return Dart_Null();
1450 }
1451 auto result = Dart_FinalizeLoading(false);
1452 if (Dart_IsError(result)) {
1453 return result;
1454 }
1455 return Dart_GetField(lib, Dart_NewStringFromCString("main"));
1456}
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:176

References tonic::CheckAndHandleError(), and flutter::DartVM::IsRunningPrecompiledCode().

Referenced by flutter::LoadLibraryFromKernel().

◆ 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 552 of file dart_isolate.cc.

555 {
556 tonic::DartState::Scope scope(this);
557
558 fml::RefPtr<DartSnapshot> dart_snapshot =
560 std::move(snapshot_data), std::move(snapshot_instructions));
561
562 Dart_Handle result = Dart_DeferredLoadComplete(
563 loading_unit_id, dart_snapshot->GetDataMapping(),
564 dart_snapshot->GetInstructionsMapping());
565 if (tonic::CheckAndHandleError(result)) {
566 LoadLoadingUnitError(loading_unit_id, Dart_GetError(result),
567 /*transient*/ true);
568 return false;
569 }
570 loading_unit_snapshots_.insert(dart_snapshot);
571 return true;
572}
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.

References tonic::CheckAndHandleError(), flutter::DartSnapshot::IsolateSnapshotFromMappings(), and LoadLoadingUnitError().

◆ LoadLoadingUnitError()

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

Definition at line 574 of file dart_isolate.cc.

576 {
577 tonic::DartState::Scope scope(this);
578 Dart_Handle result = Dart_DeferredLoadCompleteError(
579 loading_unit_id, error_message.c_str(), transient);
581}

References tonic::CheckAndHandleError().

Referenced by LoadLoadingUnit().

◆ 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 755 of file dart_isolate.cc.

758 {
759 TRACE_EVENT0("flutter", "DartIsolate::PrepareForRunningFromKernel");
760 if (phase_ != Phase::LibrariesSetup) {
761 return false;
762 }
763
765 return false;
766 }
767
768 tonic::DartState::Scope scope(this);
769
770 if (!child_isolate && !is_spawning_in_group_) {
771 if (!mapping || mapping->GetSize() == 0) {
772 return false;
773 }
774
775 // Use root library provided by kernel in favor of one provided by snapshot.
776 Dart_SetRootLibrary(Dart_Null());
777
778 if (!LoadKernel(mapping, last_piece)) {
779 return false;
780 }
781 }
782
783 if (!last_piece) {
784 // More to come.
785 return true;
786 }
787
788 if (Dart_IsNull(Dart_RootLibrary())) {
789 return false;
790 }
791
792 if (!MarkIsolateRunnable()) {
793 return false;
794 }
795
796 // Child isolate shares root isolate embedder_isolate (lines 691 and 693
797 // below). Re-initializing child_isolate_preparer_ lambda while it is being
798 // executed leads to crashes.
799 if (GetIsolateGroupData().GetChildIsolatePreparer() == nullptr) {
801 [buffers =
802 GetIsolateGroupData().GetKernelBuffers()](DartIsolate* isolate) {
803 for (uint64_t i = 0; i < buffers.size(); i++) {
804 bool last_piece = i + 1 == buffers.size();
805 const std::shared_ptr<const fml::Mapping>& buffer = buffers.at(i);
806 if (!isolate->PrepareForRunningFromKernel(buffer,
807 /*child_isolate=*/true,
808 last_piece)) {
809 return false;
810 }
811 }
812 return true;
813 });
814 }
815
816 const fml::closure& isolate_create_callback =
818 if (isolate_create_callback) {
819 isolate_create_callback();
820 }
821
822 phase_ = Phase::Ready;
823
824 return true;
825}
void SetChildIsolatePreparer(const ChildIsolatePreparer &value)
const fml::closure & GetIsolateCreateCallback() const
DartIsolateGroupData & GetIsolateGroupData()
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 disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
Definition switch_defs.h:98
#define TRACE_EVENT0(category_group, name)

References flutter::buffer, flutter::DartIsolateGroupData::GetIsolateCreateCallback(), GetIsolateGroupData(), i, tonic::DartState::isolate(), flutter::DartVM::IsRunningPrecompiledCode(), LibrariesSetup, Ready, flutter::DartIsolateGroupData::SetChildIsolatePreparer(), and TRACE_EVENT0.

Referenced by flutter::KernelIsolateConfiguration::DoPrepareIsolate(), flutter::KernelListIsolateConfiguration::DoPrepareIsolate(), and PrepareForRunningFromKernels().

◆ 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 827 of file dart_isolate.cc.

828 {
829 const auto count = kernels.size();
830 if (count == 0) {
831 return false;
832 }
833
834 for (size_t i = 0; i < count; ++i) {
835 bool last = (i == (count - 1));
836 if (!PrepareForRunningFromKernel(kernels[i], /*child_isolate=*/false,
837 last)) {
838 return false;
839 }
840 }
841
842 return true;
843}
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.

References i, and PrepareForRunningFromKernel().

Referenced by PrepareForRunningFromKernels().

◆ 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 845 of file dart_isolate.cc.

846 {
847 std::vector<std::shared_ptr<const fml::Mapping>> shared_kernels;
848 shared_kernels.reserve(kernels.size());
849 for (auto& kernel : kernels) {
850 shared_kernels.emplace_back(std::move(kernel));
851 }
852 return PrepareForRunningFromKernels(shared_kernels);
853}
bool PrepareForRunningFromKernels(std::vector< std::shared_ptr< const fml::Mapping > > kernels)
Prepare the isolate for running for a a list of kernel files.

References PrepareForRunningFromKernels().

◆ 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 696 of file dart_isolate.cc.

696 {
697 TRACE_EVENT0("flutter", "DartIsolate::PrepareForRunningFromPrecompiledCode");
698 if (phase_ != Phase::LibrariesSetup) {
699 return false;
700 }
701
702 tonic::DartState::Scope scope(this);
703
704 if (Dart_IsNull(Dart_RootLibrary())) {
705 return false;
706 }
707
708 if (!MarkIsolateRunnable()) {
709 return false;
710 }
711
712 if (GetIsolateGroupData().GetChildIsolatePreparer() == nullptr) {
714 return isolate->PrepareForRunningFromPrecompiledCode();
715 });
716 }
717
718 const fml::closure& isolate_create_callback =
720 if (isolate_create_callback) {
721 isolate_create_callback();
722 }
723
724 phase_ = Phase::Ready;
725 return true;
726}

References flutter::DartIsolateGroupData::GetIsolateCreateCallback(), GetIsolateGroupData(), tonic::DartState::isolate(), LibrariesSetup, Ready, flutter::DartIsolateGroupData::SetChildIsolatePreparer(), and TRACE_EVENT0.

Referenced by flutter::AppSnapshotIsolateConfiguration::DoPrepareIsolate().

◆ 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 909 of file dart_isolate.cc.

911 {
912 TRACE_EVENT0("flutter", "DartIsolate::RunFromLibrary");
913 if (phase_ != Phase::Ready) {
914 return false;
915 }
916
917 tonic::DartState::Scope scope(this);
918
919 auto library_handle =
920 library_name.has_value() && !library_name.value().empty()
921 ? ::Dart_LookupLibrary(tonic::ToDart(library_name.value().c_str()))
922 : ::Dart_RootLibrary();
923 auto entrypoint_handle = entrypoint.has_value() && !entrypoint.value().empty()
924 ? tonic::ToDart(entrypoint.value().c_str())
925 : tonic::ToDart("main");
926
928 // TODO(gaaclarke): Remove once the framework PR lands that uses `--source`
929 // to compile the Dart Plugin Registrant
930 // (https://github.com/flutter/flutter/pull/100572).
932 }
933
934 auto user_entrypoint_function =
935 ::Dart_GetField(library_handle, entrypoint_handle);
936
937 auto entrypoint_args = tonic::ToDart(args);
938
939 if (!InvokeMainEntrypoint(user_entrypoint_function, entrypoint_args)) {
940 return false;
941 }
942
943 phase_ = Phase::Running;
944
945 return true;
946}
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)

References args, flutter::FindAndInvokeDartPluginRegistrant(), flutter::InvokeDartPluginRegistrantIfAvailable(), flutter::InvokeMainEntrypoint(), Ready, Running, tonic::ToDart(), and TRACE_EVENT0.

◆ SetOwnerToCurrentThread()

void flutter::DartIsolate::SetOwnerToCurrentThread ( )

Definition at line 1383 of file dart_isolate.cc.

1383 {
1384 tonic::DartIsolateScope isolate_scope(isolate());
1385 Dart_SetCurrentThreadOwnsIsolate();
1386}

References tonic::DartState::isolate().

◆ 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 948 of file dart_isolate.cc.

948 {
949 TRACE_EVENT0("flutter", "DartIsolate::Shutdown");
950 // This call may be re-entrant since Dart_ShutdownIsolate can invoke the
951 // cleanup callback which deletes the embedder side object of the dart isolate
952 // (a.k.a. this).
953 if (phase_ == Phase::Shutdown) {
954 return false;
955 }
956 phase_ = Phase::Shutdown;
957 Dart_Isolate vm_isolate = isolate();
958 // The isolate can be nullptr if this instance is the stub isolate data used
959 // during root isolate creation.
960 if (vm_isolate != nullptr) {
961 // We need to enter the isolate because Dart_ShutdownIsolate does not take
962 // the isolate to shutdown as a parameter.
963 FML_DCHECK(Dart_CurrentIsolate() == nullptr);
964 Dart_EnterIsolate(vm_isolate);
965 Dart_ShutdownIsolate();
966 FML_DCHECK(Dart_CurrentIsolate() == nullptr);
967 }
968 return true;
969}

References FML_DCHECK, tonic::DartState::isolate(), Shutdown, and TRACE_EVENT0.

Friends And Related Symbol Documentation

◆ DartVM

friend class DartVM
friend

Definition at line 430 of file dart_isolate.h.

◆ IsolateConfiguration

friend class IsolateConfiguration
friend

Definition at line 419 of file dart_isolate.h.


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