Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups"

This reverts commit 3d14b75f97.

An Isolate Group (IG) is a collection of isolates which were spawned from the
same source. This allows the VM to:

  * have a guarantee that all isolates within one IG can safely exchange
    structured objects (currently we rely on embedder for this
    guarantee)

  * hot-reload all isolates together (currently we only reload one
    isolate, leaving same-source isolates in inconsistent state)

  * make a shared heap for all isolates from the same IG, which paves
    the way for faster communication and sharing of immutable objects.

All isolates within one IG will share the same IsolateGroupSource.

**Embedder changes**

This change makes breaking embedder API changes to support this new
concept of Isolate Groups: The existing isolate lifecycle callbacks
given to Dart_Initialize will become Isolate Group lifecycle callbacks.
A new callback `initialize_isolate` callback will be added which can
initialize a new isolate within an existing IG.

Existing embedders can be updated by performing the following renames

  Dart_CreateIsolate -> Dart_CreateIsolateGroup
  Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback
  Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback
  Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel
  Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData
  Dart_IsolateData -> Dart_IsolateGroupData
  Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData
  Dart_InitializeParams.create -> Dart_InitializeParams.create_group
  Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group
  Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate

By default `Isolate.spawn` will cause the creation of a new IG.

Though an embedder can opt-into supporting multiple isolates within one IG by
providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`.
The responsibility of this new callback is to initialize an existing
isolate (which was setup by re-using source code from the spawning
isolate - i.e. the one which used `Isolate.spawn`) by setting native
resolvers, initializing global state, etc.

Issue https://github.com/dart-lang/sdk/issues/36648
Issue https://github.com/dart-lang/sdk/issues/36097

Original review: https://dart-review.googlesource.com/c/sdk/+/105241

Difference to original review:

  * Give each isolate it's own [Loader] (for now)
  * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate)
  * Fix IsolateData memory leak if isolate startup fails

Difference to first reland(Patchset 2):

  * Fix typo where memory was freed twice.

Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367
Commit-Queue: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Alexander Aprelev 2019-07-08 23:49:05 +00:00 committed by commit-bot@chromium.org
parent 5470159054
commit 0425997b31
27 changed files with 1282 additions and 467 deletions

View file

@ -45,9 +45,9 @@ Dart_Isolate CreateKernelServiceIsolate(const IsolateCreationData& data,
const uint8_t* buffer,
intptr_t buffer_size,
char** error) {
Dart_Isolate kernel_isolate = Dart_CreateIsolateFromKernel(
Dart_Isolate kernel_isolate = Dart_CreateIsolateGroupFromKernel(
data.script_uri, data.main, buffer, buffer_size, data.flags,
data.callback_data, error);
data.isolate_group_data, data.isolate_data, error);
if (kernel_isolate == nullptr) {
return nullptr;
}
@ -78,9 +78,9 @@ Dart_Isolate CreateVmServiceIsolate(const IsolateCreationData& data,
}
data.flags->load_vmservice_library = true;
Dart_Isolate service_isolate = Dart_CreateIsolateFromKernel(
Dart_Isolate service_isolate = Dart_CreateIsolateGroupFromKernel(
data.script_uri, data.main, kernel_buffer, kernel_buffer_size, data.flags,
data.callback_data, error);
data.isolate_group_data, data.isolate_data, error);
if (service_isolate == nullptr) {
return nullptr;
}

View file

@ -745,23 +745,25 @@ static int CreateIsolateAndSnapshot(const CommandLineOptions& inputs) {
isolate_flags.entry_points = no_entry_points;
}
IsolateData* isolate_data = new IsolateData(NULL, NULL, NULL, NULL);
auto isolate_group_data =
new IsolateGroupData(nullptr, nullptr, nullptr, nullptr, false);
Dart_Isolate isolate;
char* error = NULL;
if (isolate_snapshot_data == NULL) {
// We need to capture the vmservice library in the core snapshot, so load it
// in the main isolate as well.
isolate_flags.load_vmservice_library = true;
isolate = Dart_CreateIsolateFromKernel(NULL, NULL, kernel_buffer,
kernel_buffer_size, &isolate_flags,
isolate_data, &error);
isolate = Dart_CreateIsolateGroupFromKernel(
NULL, NULL, kernel_buffer, kernel_buffer_size, &isolate_flags,
isolate_group_data, /*isolate_data=*/nullptr, &error);
} else {
isolate = Dart_CreateIsolate(NULL, NULL, isolate_snapshot_data,
isolate_snapshot_instructions, NULL, NULL,
&isolate_flags, isolate_data, &error);
isolate = Dart_CreateIsolateGroup(NULL, NULL, isolate_snapshot_data,
isolate_snapshot_instructions, NULL, NULL,
&isolate_flags, isolate_group_data,
/*isolate_data=*/nullptr, &error);
}
if (isolate == NULL) {
delete isolate_data;
delete isolate_group_data;
Syslog::PrintErr("%s\n", error);
free(error);
return kErrorExitCode;
@ -783,9 +785,9 @@ static int CreateIsolateAndSnapshot(const CommandLineOptions& inputs) {
// If the input dill file does not have a root library, then
// Dart_LoadScript will error.
//
// TODO(kernel): Dart_CreateIsolateFromKernel should respect the root library
// in the kernel file, though this requires auditing the other loading paths
// in the embedders that had to work around this.
// TODO(kernel): Dart_CreateIsolateGroupFromKernel should respect the root
// library in the kernel file, though this requires auditing the other
// loading paths in the embedders that had to work around this.
result = Dart_SetRootLibrary(
Dart_LoadLibraryFromKernel(kernel_buffer, kernel_buffer_size));
CHECK_RESULT(result);

View file

@ -9,45 +9,54 @@
namespace dart {
namespace bin {
IsolateData::IsolateData(const char* url,
const char* package_root,
const char* packages_file,
AppSnapshot* app_snapshot)
IsolateGroupData::IsolateGroupData(const char* url,
const char* package_root,
const char* packages_file,
AppSnapshot* app_snapshot,
bool isolate_run_app_snapshot)
: script_url((url != NULL) ? strdup(url) : NULL),
package_root(NULL),
packages_file(NULL),
loader_(NULL),
app_snapshot_(app_snapshot),
dependencies_(NULL),
resolved_packages_config_(NULL),
kernel_buffer_(NULL),
kernel_buffer_size_(0) {
kernel_buffer_size_(0),
isolate_run_app_snapshot_(isolate_run_app_snapshot) {
if (package_root != NULL) {
ASSERT(packages_file == NULL);
this->package_root = strdup(package_root);
package_root = strdup(package_root);
} else if (packages_file != NULL) {
this->packages_file = strdup(packages_file);
packages_file_ = strdup(packages_file);
}
}
void IsolateData::OnIsolateShutdown() {
}
IsolateData::~IsolateData() {
IsolateGroupData::~IsolateGroupData() {
free(script_url);
script_url = NULL;
free(package_root);
package_root = NULL;
free(packages_file);
packages_file = NULL;
free(packages_file_);
packages_file_ = NULL;
free(resolved_packages_config_);
resolved_packages_config_ = NULL;
kernel_buffer_ = NULL;
kernel_buffer_size_ = 0;
delete app_snapshot_;
app_snapshot_ = NULL;
delete dependencies_;
}
IsolateData::IsolateData(IsolateGroupData* isolate_group_data)
: isolate_group_data_(isolate_group_data),
loader_(nullptr),
packages_file_(nullptr) {
if (isolate_group_data->packages_file_ != nullptr) {
packages_file_ = strdup(isolate_group_data->packages_file_);
}
}
IsolateData::~IsolateData() {
free(packages_file_);
packages_file_ = nullptr;
}
} // namespace bin
} // namespace dart

View file

@ -28,20 +28,20 @@ class AppSnapshot;
class EventHandler;
class Loader;
// Data associated with every isolate in the standalone VM
// Data associated with every isolate group in the standalone VM
// embedding. This is used to free external resources for each isolate
// when the isolate shuts down.
class IsolateData {
// group when the isolate group shuts down.
class IsolateGroupData {
public:
IsolateData(const char* url,
const char* package_root,
const char* packages_file,
AppSnapshot* app_snapshot);
~IsolateData();
IsolateGroupData(const char* url,
const char* package_root,
const char* packages_file,
AppSnapshot* app_snapshot,
bool isolate_run_app_snapshot);
~IsolateGroupData();
char* script_url;
char* package_root;
char* packages_file;
const std::shared_ptr<uint8_t>& kernel_buffer() const {
return kernel_buffer_;
@ -49,16 +49,16 @@ class IsolateData {
intptr_t kernel_buffer_size() const { return kernel_buffer_size_; }
// Associate the given kernel buffer with this IsolateData without giving it
// ownership of the buffer.
// Associate the given kernel buffer with this IsolateGroupData without
// giving it ownership of the buffer.
void SetKernelBufferUnowned(uint8_t* buffer, intptr_t size) {
ASSERT(kernel_buffer_.get() == NULL);
kernel_buffer_ = std::shared_ptr<uint8_t>(buffer, FreeUnownedKernelBuffer);
kernel_buffer_size_ = size;
}
// Associate the given kernel buffer with this IsolateData and give it
// ownership of the buffer. This IsolateData is the first one to own the
// Associate the given kernel buffer with this IsolateGroupData and give it
// ownership of the buffer. This IsolateGroupData is the first one to own the
// buffer.
void SetKernelBufferNewlyOwned(uint8_t* buffer, intptr_t size) {
ASSERT(kernel_buffer_.get() == NULL);
@ -66,9 +66,9 @@ class IsolateData {
kernel_buffer_size_ = size;
}
// Associate the given kernel buffer with this IsolateData and give it
// Associate the given kernel buffer with this IsolateGroupData and give it
// ownership of the buffer. The buffer is already owned by another
// IsolateData.
// IsolateGroupData.
void SetKernelBufferAlreadyOwned(std::shared_ptr<uint8_t> buffer,
intptr_t size) {
ASSERT(kernel_buffer_.get() == NULL);
@ -76,14 +76,6 @@ class IsolateData {
kernel_buffer_size_ = size;
}
void UpdatePackagesFile(const char* packages_file_) {
if (packages_file != NULL) {
free(packages_file);
packages_file = NULL;
}
packages_file = strdup(packages_file_);
}
const char* resolved_packages_config() const {
return resolved_packages_config_;
}
@ -96,6 +88,54 @@ class IsolateData {
resolved_packages_config_ = strdup(packages_config);
}
MallocGrowableArray<char*>* dependencies() const { return dependencies_; }
void set_dependencies(MallocGrowableArray<char*>* deps) {
dependencies_ = deps;
}
bool RunFromAppSnapshot() const {
// If the main isolate is using an app snapshot the [app_snapshot_] pointer
// will be still nullptr (see main.cc:CreateIsolateGroupAndSetupHelper)
//
// Because of thus we have an additional boolean signaling whether the
// isolate was started from an app snapshot.
return app_snapshot_ != nullptr || isolate_run_app_snapshot_;
}
private:
friend class IsolateData; // For packages_file_
std::unique_ptr<AppSnapshot> app_snapshot_;
MallocGrowableArray<char*>* dependencies_;
char* resolved_packages_config_;
std::shared_ptr<uint8_t> kernel_buffer_;
intptr_t kernel_buffer_size_;
char* packages_file_ = nullptr;
bool isolate_run_app_snapshot_;
static void FreeUnownedKernelBuffer(uint8_t*) {}
DISALLOW_COPY_AND_ASSIGN(IsolateGroupData);
};
// Data associated with every isolate in the standalone VM
// embedding. This is used to free external resources for each isolate
// when the isolate shuts down.
class IsolateData {
public:
explicit IsolateData(IsolateGroupData* isolate_group_data);
~IsolateData();
IsolateGroupData* isolate_group_data() const { return isolate_group_data_; }
void UpdatePackagesFile(const char* packages_file) {
if (packages_file != nullptr) {
free(packages_file_);
packages_file_ = nullptr;
}
packages_file_ = strdup(packages_file);
}
// While loading a loader is associated with the isolate.
bool HasLoader() const { return loader_ != NULL; }
Loader* loader() const {
@ -106,22 +146,13 @@ class IsolateData {
ASSERT((loader_ == NULL) || (loader == NULL));
loader_ = loader;
}
MallocGrowableArray<char*>* dependencies() const { return dependencies_; }
void set_dependencies(MallocGrowableArray<char*>* deps) {
dependencies_ = deps;
}
void OnIsolateShutdown();
const char* packages_file() const { return packages_file_; }
private:
IsolateGroupData* isolate_group_data_;
Loader* loader_;
AppSnapshot* app_snapshot_;
MallocGrowableArray<char*>* dependencies_;
char* resolved_packages_config_;
std::shared_ptr<uint8_t> kernel_buffer_;
intptr_t kernel_buffer_size_;
static void FreeUnownedKernelBuffer(uint8_t*) {}
char* packages_file_;
DISALLOW_COPY_AND_ASSIGN(IsolateData);
};

View file

@ -263,7 +263,7 @@ static bool PathContainsSeparator(const char* path) {
void Loader::AddDependencyLocked(Loader* loader, const char* resolved_uri) {
MallocGrowableArray<char*>* dependencies =
loader->isolate_data_->dependencies();
loader->isolate_group_data()->dependencies();
if (dependencies == NULL) {
return;
}
@ -271,10 +271,10 @@ void Loader::AddDependencyLocked(Loader* loader, const char* resolved_uri) {
}
void Loader::ResolveDependenciesAsFilePaths() {
IsolateData* isolate_data =
reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
ASSERT(isolate_data != NULL);
MallocGrowableArray<char*>* dependencies = isolate_data->dependencies();
IsolateGroupData* isolate_group_data =
reinterpret_cast<IsolateGroupData*>(Dart_CurrentIsolateGroupData());
ASSERT(isolate_group_data != NULL);
MallocGrowableArray<char*>* dependencies = isolate_group_data->dependencies();
if (dependencies == NULL) {
return;
}
@ -454,15 +454,15 @@ bool Loader::ProcessQueueLocked(ProcessResult process_result) {
return !hit_error;
}
void Loader::InitForSnapshot(const char* snapshot_uri) {
IsolateData* isolate_data =
reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
void Loader::InitForSnapshot(const char* snapshot_uri,
IsolateData* isolate_data) {
ASSERT(isolate_data != NULL);
ASSERT(!isolate_data->HasLoader());
// Setup a loader. The constructor does a bunch of leg work.
Loader* loader = new Loader(isolate_data);
// Send the init message.
loader->Init(isolate_data->package_root, isolate_data->packages_file,
loader->Init(isolate_data->isolate_group_data()->package_root,
isolate_data->packages_file(),
DartUtils::original_working_directory, snapshot_uri);
// Destroy the loader. The destructor does a bunch of leg work.
delete loader;
@ -516,15 +516,15 @@ Dart_Handle Loader::SendAndProcessReply(intptr_t tag,
Dart_Handle url,
uint8_t** payload,
intptr_t* payload_length) {
IsolateData* isolate_data =
reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
auto isolate_data = reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
ASSERT(isolate_data != NULL);
ASSERT(!isolate_data->HasLoader());
Loader* loader = NULL;
// Setup the loader. The constructor does a bunch of leg work.
loader = new Loader(isolate_data);
loader->Init(isolate_data->package_root, isolate_data->packages_file,
loader->Init(isolate_data->isolate_group_data()->package_root,
isolate_data->packages_file(),
DartUtils::original_working_directory, NULL);
ASSERT(loader != NULL);
ASSERT(isolate_data->HasLoader());
@ -565,6 +565,10 @@ Dart_Handle Loader::ResolveAsFilePath(Dart_Handle url,
payload_length);
}
IsolateGroupData* Loader::isolate_group_data() {
return isolate_data_->isolate_group_data();
}
#if defined(DART_PRECOMPILED_RUNTIME)
Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
Dart_Handle library,
@ -679,8 +683,7 @@ Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
}
}
IsolateData* isolate_data =
reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
auto isolate_data = reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
ASSERT(isolate_data != NULL);
if ((tag == Dart_kScriptTag) && Dart_IsString(library)) {
// Update packages file for isolate.
@ -707,7 +710,8 @@ Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
// Setup the loader. The constructor does a bunch of leg work.
loader = new Loader(isolate_data);
loader->Init(isolate_data->package_root, isolate_data->packages_file,
loader->Init(isolate_data->isolate_group_data()->package_root,
isolate_data->packages_file(),
DartUtils::original_working_directory,
(tag == Dart_kScriptTag) ? url_string : NULL);
} else {

View file

@ -20,7 +20,8 @@ class Loader {
explicit Loader(IsolateData* isolate_data);
~Loader();
static void InitForSnapshot(const char* snapshot_uri);
static void InitForSnapshot(const char* snapshot_uri,
IsolateData* isolate_data);
static Dart_Handle ReloadNativeExtensions();
@ -36,6 +37,8 @@ class Loader {
Dart_Handle library,
Dart_Handle url);
IsolateGroupData* isolate_group_data();
Dart_Handle error() const { return error_; }
static void InitOnce();

View file

@ -132,10 +132,10 @@ static void WriteDepsFile(Dart_Isolate isolate) {
return;
}
Loader::ResolveDependenciesAsFilePaths();
IsolateData* isolate_data =
reinterpret_cast<IsolateData*>(Dart_IsolateData(isolate));
ASSERT(isolate_data != NULL);
MallocGrowableArray<char*>* dependencies = isolate_data->dependencies();
auto isolate_group_data =
reinterpret_cast<IsolateGroupData*>(Dart_IsolateGroupData(isolate));
ASSERT(isolate_group_data != NULL);
MallocGrowableArray<char*>* dependencies = isolate_group_data->dependencies();
ASSERT(dependencies != NULL);
File* file =
File::Open(NULL, Options::depfile(), File::kWriteTruncate);
@ -190,57 +190,157 @@ static void OnExitHook(int64_t exit_code) {
}
}
static Dart_Handle SetupCoreLibraries(Dart_Isolate isolate,
IsolateData* isolate_data,
bool is_isolate_group_start,
const char** resolved_packages_config) {
auto isolate_group_data = isolate_data->isolate_group_data();
const auto packages_file = isolate_data->packages_file();
const auto script_uri = isolate_group_data->script_url;
Dart_Handle result;
// Set up the library tag handler for this isolate.
result = Dart_SetLibraryTagHandler(Loader::LibraryTagHandler);
if (Dart_IsError(result)) return result;
// Prepare builtin and other core libraries for use to resolve URIs.
// Set up various closures, e.g: printing, timers etc.
// Set up 'package root' for URI resolution.
result = DartUtils::PrepareForScriptLoading(false, Options::trace_loading());
if (Dart_IsError(result)) return result;
if (Dart_IsVMFlagSet("support_service") || !Dart_IsPrecompiledRuntime()) {
// Set up the load port provided by the service isolate so that we can
// load scripts.
result = DartUtils::SetupServiceLoadPort();
if (Dart_IsError(result)) return result;
}
// Setup package root if specified.
result = DartUtils::SetupPackageRoot(nullptr, packages_file);
if (Dart_IsError(result)) return result;
if (!Dart_IsNull(result) && resolved_packages_config != nullptr) {
result = Dart_StringToCString(result, resolved_packages_config);
if (Dart_IsError(result)) return result;
ASSERT(*resolved_packages_config != nullptr);
#if !defined(DART_PRECOMPILED_RUNTIME)
if (is_isolate_group_start) {
isolate_group_data->set_resolved_packages_config(
*resolved_packages_config);
} else {
ASSERT(strcmp(isolate_group_data->resolved_packages_config(),
*resolved_packages_config) == 0);
}
#endif
}
result = Dart_SetEnvironmentCallback(DartUtils::EnvironmentCallback);
if (Dart_IsError(result)) return result;
// Setup the native resolver as the snapshot does not carry it.
Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
Builtin::SetNativeResolver(Builtin::kIOLibrary);
Builtin::SetNativeResolver(Builtin::kCLILibrary);
VmService::SetNativeResolver();
const char* namespc =
Dart_IsKernelIsolate(isolate) ? NULL : Options::namespc();
result =
DartUtils::SetupIOLibrary(namespc, script_uri, Options::exit_disabled());
if (Dart_IsError(result)) return result;
return Dart_Null();
}
static bool OnIsolateInitialize(void** child_callback_data, char** error) {
Dart_Isolate isolate = Dart_CurrentIsolate();
ASSERT(isolate != nullptr);
auto isolate_group_data =
reinterpret_cast<IsolateGroupData*>(Dart_CurrentIsolateGroupData());
auto isolate_data = new IsolateData(isolate_group_data);
*child_callback_data = isolate_data;
Dart_EnterScope();
const auto script_uri = isolate_group_data->script_url;
const bool isolate_run_app_snapshot =
isolate_group_data->RunFromAppSnapshot();
Dart_Handle result = SetupCoreLibraries(isolate, isolate_data,
/*group_start=*/false,
/*resolved_packages_config=*/nullptr);
if (Dart_IsError(result)) goto failed;
if (isolate_run_app_snapshot) {
if (Dart_IsVMFlagSet("support_service") || !Dart_IsPrecompiledRuntime()) {
Loader::InitForSnapshot(script_uri, isolate_data);
}
} else {
result = DartUtils::ResolveScript(Dart_NewStringFromCString(script_uri));
if (Dart_IsError(result)) return result;
if (isolate_group_data->kernel_buffer().get() != nullptr) {
// Various core-library parts will send requests to the Loader to resolve
// relative URIs and perform other related tasks. We need Loader to be
// initialized for this to work because loading from Kernel binary
// bypasses normal source code loading paths that initialize it.
const char* resolved_script_uri = NULL;
result = Dart_StringToCString(result, &resolved_script_uri);
if (Dart_IsError(result)) return result;
Loader::InitForSnapshot(resolved_script_uri, isolate_data);
}
}
if (isolate_run_app_snapshot) {
result = Loader::ReloadNativeExtensions();
if (Dart_IsError(result)) goto failed;
}
if (Options::gen_snapshot_kind() == kAppJIT) {
// If we sort, we must do it for all isolates, not just the main isolate,
// otherwise isolates related by spawnFunction will disagree on CIDs and
// cannot correctly send each other messages.
result = Dart_SortClasses();
if (Dart_IsError(result)) goto failed;
}
// Make the isolate runnable so that it is ready to handle messages.
Dart_ExitScope();
Dart_ExitIsolate();
*error = Dart_IsolateMakeRunnable(isolate);
Dart_EnterIsolate(isolate);
return *error == nullptr;
failed:
*error = strdup(Dart_GetError(result));
Dart_ExitScope();
return false;
}
static Dart_Isolate IsolateSetupHelper(Dart_Isolate isolate,
bool is_main_isolate,
const char* script_uri,
const char* package_root,
const char* packages_config,
bool isolate_run_app_snapshot,
Dart_IsolateFlags* flags,
char** error,
int* exit_code) {
Dart_EnterScope();
#if !defined(DART_PRECOMPILED_RUNTIME)
IsolateData* isolate_data =
reinterpret_cast<IsolateData*>(Dart_IsolateData(isolate));
const uint8_t* kernel_buffer = isolate_data->kernel_buffer().get();
intptr_t kernel_buffer_size = isolate_data->kernel_buffer_size();
#endif
// Set up the library tag handler for this isolate.
Dart_Handle result = Dart_SetLibraryTagHandler(Loader::LibraryTagHandler);
CHECK_RESULT(result);
auto isolate_data = reinterpret_cast<IsolateData*>(Dart_IsolateData(isolate));
// Prepare builtin and other core libraries for use to resolve URIs.
// Set up various closures, e.g: printing, timers etc.
// Set up 'package root' for URI resolution.
result = DartUtils::PrepareForScriptLoading(false, Options::trace_loading());
CHECK_RESULT(result);
if (Dart_IsVMFlagSet("support_service") || !Dart_IsPrecompiledRuntime()) {
// Set up the load port provided by the service isolate so that we can
// load scripts.
result = DartUtils::SetupServiceLoadPort();
CHECK_RESULT(result);
}
// Setup package root if specified.
result = DartUtils::SetupPackageRoot(NULL, packages_config);
CHECK_RESULT(result);
const char* resolved_packages_config = NULL;
if (!Dart_IsNull(result)) {
result = Dart_StringToCString(result, &resolved_packages_config);
CHECK_RESULT(result);
ASSERT(resolved_packages_config != NULL);
#if !defined(DART_PRECOMPILED_RUNTIME)
isolate_data->set_resolved_packages_config(resolved_packages_config);
#endif
}
result = Dart_SetEnvironmentCallback(DartUtils::EnvironmentCallback);
const char* resolved_packages_config = nullptr;
Dart_Handle result = SetupCoreLibraries(isolate, isolate_data,
/*is_isolate_group_start=*/true,
&resolved_packages_config);
CHECK_RESULT(result);
#if !defined(DART_PRECOMPILED_RUNTIME)
auto isolate_group_data = isolate_data->isolate_group_data();
const uint8_t* kernel_buffer = isolate_group_data->kernel_buffer().get();
intptr_t kernel_buffer_size = isolate_group_data->kernel_buffer_size();
if (!isolate_run_app_snapshot && kernel_buffer == NULL &&
!Dart_IsKernelIsolate(isolate)) {
if (!dfe.CanUseDartFrontend()) {
@ -264,8 +364,8 @@ static Dart_Isolate IsolateSetupHelper(Dart_Isolate isolate,
Dart_ShutdownIsolate();
return NULL;
}
isolate_data->SetKernelBufferNewlyOwned(application_kernel_buffer,
application_kernel_buffer_size);
isolate_group_data->SetKernelBufferNewlyOwned(
application_kernel_buffer, application_kernel_buffer_size);
kernel_buffer = application_kernel_buffer;
kernel_buffer_size = application_kernel_buffer_size;
}
@ -279,25 +379,14 @@ static Dart_Isolate IsolateSetupHelper(Dart_Isolate isolate,
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
// Setup the native resolver as the snapshot does not carry it.
Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
Builtin::SetNativeResolver(Builtin::kIOLibrary);
Builtin::SetNativeResolver(Builtin::kCLILibrary);
VmService::SetNativeResolver();
if (isolate_run_app_snapshot) {
Dart_Handle result = Loader::ReloadNativeExtensions();
CHECK_RESULT(result);
}
const char* namespc =
Dart_IsKernelIsolate(isolate) ? NULL : Options::namespc();
if (isolate_run_app_snapshot) {
result = DartUtils::SetupIOLibrary(namespc, script_uri,
Options::exit_disabled());
CHECK_RESULT(result);
if (Dart_IsVMFlagSet("support_service") || !Dart_IsPrecompiledRuntime()) {
Loader::InitForSnapshot(script_uri);
Loader::InitForSnapshot(script_uri, isolate_data);
}
#if !defined(DART_PRECOMPILED_RUNTIME)
if (is_main_isolate) {
@ -329,16 +418,12 @@ static Dart_Isolate IsolateSetupHelper(Dart_Isolate isolate,
const char* resolved_script_uri = NULL;
result = Dart_StringToCString(uri, &resolved_script_uri);
CHECK_RESULT(result);
Loader::InitForSnapshot(resolved_script_uri);
Loader::InitForSnapshot(resolved_script_uri, isolate_data);
}
Dart_TimelineEvent("LoadScript", Dart_TimelineGetMicros(),
Dart_GetMainPortId(), Dart_Timeline_Event_Async_End, 0,
NULL, NULL);
result = DartUtils::SetupIOLibrary(namespc, script_uri,
Options::exit_disabled());
CHECK_RESULT(result);
#else
UNREACHABLE();
#endif // !defined(DART_PRECOMPILED_RUNTIME)
@ -396,7 +481,8 @@ static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri,
}
Dart_Isolate isolate = NULL;
IsolateData* isolate_data = NULL;
IsolateGroupData* isolate_group_data = nullptr;
IsolateData* isolate_data = nullptr;
bool isolate_run_app_snapshot = false;
AppSnapshot* app_snapshot = NULL;
// Kernel isolate uses an app snapshot or uses the dill file.
@ -411,42 +497,48 @@ static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri,
app_snapshot->SetBuffers(
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
&isolate_snapshot_data, &isolate_snapshot_instructions);
isolate_data =
new IsolateData(uri, package_root, packages_config, app_snapshot);
isolate = Dart_CreateIsolate(
isolate_group_data =
new IsolateGroupData(uri, package_root, packages_config, app_snapshot,
isolate_run_app_snapshot);
isolate_data = new IsolateData(isolate_group_data);
isolate = Dart_CreateIsolateGroup(
DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME,
isolate_snapshot_data, isolate_snapshot_instructions,
app_isolate_shared_data, app_isolate_shared_instructions, flags,
isolate_data, error);
isolate_group_data, isolate_data, error);
}
if (isolate == NULL) {
// Clear error from app snapshot and re-trying from kernel file.
free(*error);
*error = NULL;
delete isolate_data;
delete isolate_group_data;
const uint8_t* kernel_service_buffer = NULL;
intptr_t kernel_service_buffer_size = 0;
dfe.LoadKernelService(&kernel_service_buffer, &kernel_service_buffer_size);
ASSERT(kernel_service_buffer != NULL);
isolate_data = new IsolateData(uri, package_root, packages_config, NULL);
isolate_data->SetKernelBufferUnowned(
isolate_group_data = new IsolateGroupData(
uri, package_root, packages_config, nullptr, isolate_run_app_snapshot);
isolate_group_data->SetKernelBufferUnowned(
const_cast<uint8_t*>(kernel_service_buffer),
kernel_service_buffer_size);
isolate = Dart_CreateIsolateFromKernel(
isolate_data = new IsolateData(isolate_group_data);
isolate = Dart_CreateIsolateGroupFromKernel(
DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME,
kernel_service_buffer, kernel_service_buffer_size, flags, isolate_data,
error);
kernel_service_buffer, kernel_service_buffer_size, flags,
isolate_group_data, isolate_data, error);
}
if (isolate == NULL) {
Syslog::PrintErr("%s\n", *error);
delete isolate_data;
delete isolate_group_data;
return NULL;
}
kernel_isolate_is_running = true;
return IsolateSetupHelper(isolate, false, uri, package_root, packages_config,
return IsolateSetupHelper(isolate, false, uri, packages_config,
isolate_run_app_snapshot, flags, error, exit_code);
}
#endif // !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
@ -462,18 +554,19 @@ static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
int* exit_code) {
ASSERT(script_uri != NULL);
Dart_Isolate isolate = NULL;
IsolateData* isolate_data =
new IsolateData(script_uri, package_root, packages_config, NULL);
auto isolate_group_data = new IsolateGroupData(
script_uri, package_root, packages_config, nullptr, false);
#if defined(DART_PRECOMPILED_RUNTIME)
// AOT: All isolates start from the app snapshot.
const uint8_t* isolate_snapshot_data = app_isolate_snapshot_data;
const uint8_t* isolate_snapshot_instructions =
app_isolate_snapshot_instructions;
isolate = Dart_CreateIsolate(
isolate = Dart_CreateIsolateGroup(
script_uri, DART_VM_SERVICE_ISOLATE_NAME, isolate_snapshot_data,
isolate_snapshot_instructions, app_isolate_shared_data,
app_isolate_shared_instructions, flags, isolate_data, error);
app_isolate_shared_instructions, flags, isolate_group_data,
/*isolate_data=*/nullptr, error);
#else
// JIT: Service isolate uses the core libraries snapshot.
@ -483,13 +576,14 @@ static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
const uint8_t* isolate_snapshot_data = core_isolate_snapshot_data;
const uint8_t* isolate_snapshot_instructions =
core_isolate_snapshot_instructions;
isolate = Dart_CreateIsolate(
isolate = Dart_CreateIsolateGroup(
script_uri, DART_VM_SERVICE_ISOLATE_NAME, isolate_snapshot_data,
isolate_snapshot_instructions, app_isolate_shared_data,
app_isolate_shared_instructions, flags, isolate_data, error);
app_isolate_shared_instructions, flags, isolate_group_data,
/*isolate_data=*/nullptr, error);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
if (isolate == NULL) {
delete isolate_data;
delete isolate_group_data;
return NULL;
}
@ -518,15 +612,16 @@ static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
}
// Returns newly created Isolate on success, NULL on failure.
static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
const char* script_uri,
const char* name,
const char* package_root,
const char* packages_config,
Dart_IsolateFlags* flags,
void* callback_data,
char** error,
int* exit_code) {
static Dart_Isolate CreateIsolateGroupAndSetupHelper(
bool is_main_isolate,
const char* script_uri,
const char* name,
const char* package_root,
const char* packages_config,
Dart_IsolateFlags* flags,
void* callback_data,
char** error,
int* exit_code) {
int64_t start = Dart_TimelineGetMicros();
ASSERT(script_uri != NULL);
uint8_t* kernel_buffer = NULL;
@ -566,8 +661,8 @@ static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
}
if (flags->copy_parent_code && callback_data) {
IsolateData* parent_isolate_data =
reinterpret_cast<IsolateData*>(callback_data);
IsolateGroupData* parent_isolate_data =
reinterpret_cast<IsolateGroupData*>(callback_data);
parent_kernel_buffer = parent_isolate_data->kernel_buffer();
kernel_buffer = parent_kernel_buffer.get();
kernel_buffer_size = parent_isolate_data->kernel_buffer_size();
@ -578,19 +673,20 @@ static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
IsolateData* isolate_data =
new IsolateData(script_uri, package_root, packages_config, app_snapshot);
auto isolate_group_data =
new IsolateGroupData(script_uri, package_root, packages_config,
app_snapshot, isolate_run_app_snapshot);
if (kernel_buffer != NULL) {
if (parent_kernel_buffer) {
isolate_data->SetKernelBufferAlreadyOwned(std::move(parent_kernel_buffer),
kernel_buffer_size);
isolate_group_data->SetKernelBufferAlreadyOwned(
std::move(parent_kernel_buffer), kernel_buffer_size);
} else {
isolate_data->SetKernelBufferNewlyOwned(kernel_buffer,
kernel_buffer_size);
isolate_group_data->SetKernelBufferNewlyOwned(kernel_buffer,
kernel_buffer_size);
}
}
if (is_main_isolate && (Options::depfile() != NULL)) {
isolate_data->set_dependencies(new MallocGrowableArray<char*>());
isolate_group_data->set_dependencies(new MallocGrowableArray<char*>());
}
Dart_Isolate isolate = NULL;
@ -616,45 +712,48 @@ static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
// TODO(sivachandra): When the platform program is unavailable, check if
// application kernel binary is self contained or an incremental binary.
// Isolate should be created only if it is a self contained kernel binary.
isolate = Dart_CreateIsolateFromKernel(
auto isolate_data = new IsolateData(isolate_group_data);
isolate = Dart_CreateIsolateGroupFromKernel(
script_uri, name, platform_kernel_buffer, platform_kernel_buffer_size,
flags, isolate_data, error);
flags, isolate_group_data, isolate_data, error);
} else {
isolate = Dart_CreateIsolate(
auto isolate_data = new IsolateData(isolate_group_data);
isolate = Dart_CreateIsolateGroup(
script_uri, name, isolate_snapshot_data, isolate_snapshot_instructions,
app_isolate_shared_data, app_isolate_shared_instructions, flags,
isolate_data, error);
isolate_group_data, isolate_data, error);
}
#else
isolate = Dart_CreateIsolate(
auto isolate_data = new IsolateData(isolate_group_data);
isolate = Dart_CreateIsolateGroup(
script_uri, name, isolate_snapshot_data, isolate_snapshot_instructions,
app_isolate_shared_data, app_isolate_shared_instructions, flags,
isolate_data, error);
isolate_group_data, isolate_data, error);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
Dart_Isolate created_isolate = NULL;
if (isolate == NULL) {
delete isolate_data;
delete isolate_group_data;
} else {
created_isolate = IsolateSetupHelper(
isolate, is_main_isolate, script_uri, package_root, packages_config,
isolate, is_main_isolate, script_uri, packages_config,
isolate_run_app_snapshot, flags, error, exit_code);
}
int64_t end = Dart_TimelineGetMicros();
Dart_TimelineEvent("CreateIsolateAndSetupHelper", start, end,
Dart_TimelineEvent("CreateIsolateGroupAndSetupHelper", start, end,
Dart_Timeline_Event_Duration, 0, NULL, NULL);
return created_isolate;
}
#undef CHECK_RESULT
static Dart_Isolate CreateIsolateAndSetup(const char* script_uri,
const char* main,
const char* package_root,
const char* package_config,
Dart_IsolateFlags* flags,
void* callback_data,
char** error) {
static Dart_Isolate CreateIsolateGroupAndSetup(const char* script_uri,
const char* main,
const char* package_root,
const char* package_config,
Dart_IsolateFlags* flags,
void* callback_data,
char** error) {
// The VM should never call the isolate helper with a NULL flags.
ASSERT(flags != NULL);
ASSERT(flags->version == DART_FLAGS_CURRENT_VERSION);
@ -677,30 +776,30 @@ static Dart_Isolate CreateIsolateAndSetup(const char* script_uri,
script_uri, package_root, package_config, flags, error, &exit_code);
}
bool is_main_isolate = false;
return CreateIsolateAndSetupHelper(is_main_isolate, script_uri, main,
package_root, package_config, flags,
callback_data, error, &exit_code);
return CreateIsolateGroupAndSetupHelper(is_main_isolate, script_uri, main,
package_root, package_config, flags,
callback_data, error, &exit_code);
}
static void OnIsolateShutdown(void* callback_data) {
static void OnIsolateShutdown(void* isolate_group_data, void* isolate_data) {
Dart_EnterScope();
Dart_Handle sticky_error = Dart_GetStickyError();
if (!Dart_IsNull(sticky_error) && !Dart_IsFatalError(sticky_error)) {
Syslog::PrintErr("%s\n", Dart_GetError(sticky_error));
}
IsolateData* isolate_data = reinterpret_cast<IsolateData*>(callback_data);
isolate_data->OnIsolateShutdown();
Dart_ExitScope();
}
static void DeleteIsolateData(void* callback_data) {
IsolateData* isolate_data = reinterpret_cast<IsolateData*>(callback_data);
static void DeleteIsolateData(void* isolate_group_data, void* callback_data) {
auto isolate_data = reinterpret_cast<IsolateData*>(callback_data);
delete isolate_data;
}
static void DeleteIsolateGroupData(void* callback_data) {
auto isolate_group_data = reinterpret_cast<IsolateGroupData*>(callback_data);
delete isolate_group_data;
}
static const char* kStdoutStreamId = "Stdout";
static const char* kStderrStreamId = "Stderr";
@ -787,7 +886,7 @@ static void LoadBytecode() {
}
bool RunMainIsolate(const char* script_name, CommandLineOptions* dart_options) {
// Call CreateIsolateAndSetup which creates an isolate and loads up
// Call CreateIsolateGroupAndSetup which creates an isolate and loads up
// the specified application script.
char* error = NULL;
bool is_main_isolate = true;
@ -795,7 +894,7 @@ bool RunMainIsolate(const char* script_name, CommandLineOptions* dart_options) {
Dart_IsolateFlags flags;
Dart_IsolateFlagsInitialize(&flags);
Dart_Isolate isolate = CreateIsolateAndSetupHelper(
Dart_Isolate isolate = CreateIsolateGroupAndSetupHelper(
is_main_isolate, script_name, "main", Options::package_root(),
Options::packages_file(), &flags, NULL /* callback_data */, &error,
&exit_code);
@ -823,8 +922,8 @@ bool RunMainIsolate(const char* script_name, CommandLineOptions* dart_options) {
Dart_EnterScope();
IsolateData* isolate_data =
reinterpret_cast<IsolateData*>(Dart_IsolateData(isolate));
auto isolate_group_data =
reinterpret_cast<IsolateGroupData*>(Dart_IsolateGroupData(isolate));
if (Options::gen_snapshot_kind() == kKernel) {
if (vm_run_app_snapshot) {
Syslog::PrintErr(
@ -834,7 +933,7 @@ bool RunMainIsolate(const char* script_name, CommandLineOptions* dart_options) {
Platform::Exit(kErrorExitCode);
}
Snapshot::GenerateKernel(Options::snapshot_filename(), script_name,
isolate_data->resolved_packages_config());
isolate_group_data->resolved_packages_config());
} else {
// Lookup the library of the root script.
Dart_Handle root_lib = Dart_RootLibrary();
@ -1107,9 +1206,11 @@ void main(int argc, char** argv) {
init_params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
init_params.vm_snapshot_data = vm_snapshot_data;
init_params.vm_snapshot_instructions = vm_snapshot_instructions;
init_params.create = CreateIsolateAndSetup;
init_params.shutdown = OnIsolateShutdown;
init_params.cleanup = DeleteIsolateData;
init_params.create_group = CreateIsolateGroupAndSetup;
init_params.initialize_isolate = OnIsolateInitialize;
init_params.shutdown_isolate = OnIsolateShutdown;
init_params.cleanup_isolate = DeleteIsolateData;
init_params.cleanup_group = DeleteIsolateGroupData;
init_params.file_open = DartUtils::OpenFile;
init_params.file_read = DartUtils::ReadFile;
init_params.file_write = DartUtils::WriteFile;

View file

@ -127,7 +127,7 @@ static Dart_Isolate CreateIsolateAndSetup(const char* script_uri,
return NULL;
}
Dart_Isolate isolate = NULL;
bin::IsolateData* isolate_data = NULL;
bin::IsolateGroupData* isolate_group_data = NULL;
const uint8_t* kernel_service_buffer = NULL;
intptr_t kernel_service_buffer_size = 0;
@ -146,12 +146,13 @@ static Dart_Isolate CreateIsolateAndSetup(const char* script_uri,
app_snapshot->SetBuffers(
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
&isolate_snapshot_data, &isolate_snapshot_instructions);
isolate_data = new bin::IsolateData(script_uri, package_root,
packages_config, app_snapshot);
isolate =
Dart_CreateIsolate(DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME,
isolate_snapshot_data, isolate_snapshot_instructions,
NULL, NULL, flags, isolate_data, error);
isolate_group_data =
new bin::IsolateGroupData(script_uri, package_root, packages_config,
app_snapshot, app_snapshot != nullptr);
isolate = Dart_CreateIsolateGroup(
DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME,
isolate_snapshot_data, isolate_snapshot_instructions, NULL, NULL, flags,
isolate_group_data, /*isolate_data=*/nullptr, error);
if (*error != NULL) {
free(*error);
*error = NULL;
@ -161,29 +162,29 @@ static Dart_Isolate CreateIsolateAndSetup(const char* script_uri,
// This can cause the isolate to be killed early which will return `nullptr`
// here.
if (isolate == nullptr) {
delete isolate_data;
delete isolate_group_data;
return NULL;
}
}
if (isolate == NULL) {
delete isolate_data;
isolate_data = NULL;
delete isolate_group_data;
isolate_group_data = NULL;
bin::dfe.Init();
bin::dfe.LoadKernelService(&kernel_service_buffer,
&kernel_service_buffer_size);
ASSERT(kernel_service_buffer != NULL);
isolate_data =
new bin::IsolateData(script_uri, package_root, packages_config, NULL);
isolate_data->SetKernelBufferUnowned(
isolate_group_data = new bin::IsolateGroupData(
script_uri, package_root, packages_config, nullptr, false);
isolate_group_data->SetKernelBufferUnowned(
const_cast<uint8_t*>(kernel_service_buffer),
kernel_service_buffer_size);
isolate = Dart_CreateIsolateFromKernel(
isolate = Dart_CreateIsolateGroupFromKernel(
script_uri, main, kernel_service_buffer, kernel_service_buffer_size,
flags, isolate_data, error);
flags, isolate_group_data, /*isolate_data=*/nullptr, error);
}
if (isolate == NULL) {
delete isolate_data;
delete isolate_group_data;
return NULL;
}
@ -213,9 +214,9 @@ static Dart_Isolate CreateIsolateAndSetup(const char* script_uri,
return isolate;
}
static void CleanupIsolate(void* callback_data) {
bin::IsolateData* isolate_data =
reinterpret_cast<bin::IsolateData*>(callback_data);
static void CleanupIsolateGroup(void* callback_data) {
bin::IsolateGroupData* isolate_data =
reinterpret_cast<bin::IsolateGroupData*>(callback_data);
delete isolate_data;
}
@ -311,18 +312,22 @@ static int Main(int argc, const char** argv) {
TesterState::vm_snapshot_data = dart::bin::vm_snapshot_data;
TesterState::create_callback = CreateIsolateAndSetup;
TesterState::cleanup_callback = CleanupIsolate;
TesterState::group_cleanup_callback = CleanupIsolateGroup;
TesterState::argv = dart_argv;
TesterState::argc = dart_argc;
error = Dart::Init(
dart::bin::vm_snapshot_data, dart::bin::vm_snapshot_instructions,
CreateIsolateAndSetup /* create */, nullptr /* shutdown */,
CleanupIsolate /* cleanup */, nullptr /* thread_exit */,
dart::bin::DartUtils::OpenFile, dart::bin::DartUtils::ReadFile,
dart::bin::DartUtils::WriteFile, dart::bin::DartUtils::CloseFile,
nullptr /* entropy_source */, nullptr /* get_service_assets */,
start_kernel_isolate, nullptr /* observer */);
/*create_group=*/CreateIsolateAndSetup,
/*initialize_isolate=*/nullptr,
/*shutdown_isolate=*/nullptr,
/*cleanup_isolate=*/nullptr,
/*cleanup_group=*/CleanupIsolateGroup,
/*thread_exit=*/nullptr, dart::bin::DartUtils::OpenFile,
dart::bin::DartUtils::ReadFile, dart::bin::DartUtils::WriteFile,
dart::bin::DartUtils::CloseFile, nullptr /* entropy_source */,
nullptr /* get_service_assets */, start_kernel_isolate,
/*code_observer=*/nullptr);
if (error != nullptr) {
Syslog::PrintErr("Failed to initialize VM: %s\n", error);
free(error);

View file

@ -76,7 +76,7 @@
* current isolate may be NULL, in which case no isolate is ready to
* execute. Most of the Dart apis require there to be a current
* isolate in order to function without error. The current isolate is
* set by any call to Dart_CreateIsolate or Dart_EnterIsolate.
* set by any call to Dart_CreateIsolateGroup or Dart_EnterIsolate.
*/
typedef struct _Dart_Isolate* Dart_Isolate;
@ -541,7 +541,7 @@ DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags* flags);
*
* This callback, provided by the embedder, is called when the VM
* needs to create an isolate. The callback should create an isolate
* by calling Dart_CreateIsolate and load any scripts required for
* by calling Dart_CreateIsolateGroup and load any scripts required for
* execution.
*
* This callback may be called on a different thread than the one
@ -550,7 +550,7 @@ DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags* flags);
* When the function returns NULL, it is the responsibility of this
* function to ensure that Dart_ShutdownIsolate has been called if
* required (for example, if the isolate was created successfully by
* Dart_CreateIsolate() but the root library fails to load
* Dart_CreateIsolateGroup() but the root library fails to load
* successfully, then the function should call Dart_ShutdownIsolate
* before returning).
*
@ -560,7 +560,7 @@ DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags* flags);
* freed.
*
* \param script_uri The uri of the main source file or snapshot to load.
* Either the URI of the parent isolate set in Dart_CreateIsolate for
* Either the URI of the parent isolate set in Dart_CreateIsolateGroup for
* Isolate.spawn, or the argument to Isolate.spawnUri canonicalized by the
* library tag handler of the parent isolate.
* The callback is responsible for loading the program by a call to
@ -582,20 +582,54 @@ DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags* flags);
* from the spawning isolate or passed as parameters when spawning the
* isolate from Dart code.
* \param callback_data The callback data which was passed to the
* parent isolate when it was created by calling Dart_CreateIsolate().
* parent isolate when it was created by calling Dart_CreateIsolateGroup().
* \param error A structure into which the embedder can place a
* C string containing an error message in the case of failures.
*
* \return The embedder returns NULL if the creation and
* initialization was not successful and the isolate if successful.
*/
typedef Dart_Isolate (*Dart_IsolateCreateCallback)(const char* script_uri,
const char* main,
const char* package_root,
const char* package_config,
Dart_IsolateFlags* flags,
void* callback_data,
char** error);
typedef Dart_Isolate (*Dart_IsolateGroupCreateCallback)(
const char* script_uri,
const char* main,
const char* package_root,
const char* package_config,
Dart_IsolateFlags* flags,
void* callback_data,
char** error);
/**
* An isolate initialization callback function.
*
* This callback, provided by the embedder, is called when the VM has created an
* isolate within an existing isolate group (i.e. from the same source as an
* existing isolate).
*
* The callback should setup native resolvers and might want to set a custom
* message handler via [Dart_SetMessageNotifyCallback] and mark the isolate as
* runnable.
*
* This callback may be called on a different thread than the one
* running the parent isolate.
*
* When the function returns `false`, it is the responsibility of this
* function to ensure that `Dart_ShutdownIsolate` has been called.
*
* When the function returns `false`, the function should set *error to
* a malloc-allocated buffer containing a useful error message. The
* caller of this function (the VM) will make sure that the buffer is
* freed.
*
* \param child_isolate_data The callback data to associate with the new
* child isolate.
* \param error A structure into which the embedder can place a
* C string containing an error message in the case the initialization fails.
*
* \return The embedder returns true if the initialization was successful and
* false otherwise (in which case the VM will terminate the isolate).
*/
typedef bool (*Dart_InitializeIsolateCallback)(void** child_isolate_data,
char** error);
/**
* An isolate unhandled exception callback function.
@ -614,11 +648,13 @@ typedef void (*Dart_IsolateUnhandledExceptionCallback)(Dart_Handle error);
* This function should be used to dispose of native resources that
* are allocated to an isolate in order to avoid leaks.
*
* \param callback_data The same callback data which was passed to the
* isolate when it was created.
*
* \param isolate_group_data The same callback data which was passed to the
* isolate group when it was created.
* \param isolate_data The same callback data which was passed to the isolate
* when it was created.
*/
typedef void (*Dart_IsolateShutdownCallback)(void* callback_data);
typedef void (*Dart_IsolateShutdownCallback)(void* isolate_group_data,
void* isolate_data);
/**
* An isolate cleanup callback function.
@ -630,11 +666,28 @@ typedef void (*Dart_IsolateShutdownCallback)(void* callback_data);
* This function should be used to dispose of native resources that
* are allocated to an isolate in order to avoid leaks.
*
* \param callback_data The same callback data which was passed to the
* isolate when it was created.
* \param isolate_group_data The same callback data which was passed to the
* isolate group when it was created.
* \param isolate_data The same callback data which was passed to the isolate
* when it was created.
*/
typedef void (*Dart_IsolateCleanupCallback)(void* isolate_group_data,
void* isolate_data);
/**
* An isolate group cleanup callback function.
*
* This callback, provided by the embedder, is called after the vm
* shuts down an isolate group.
*
* This function should be used to dispose of native resources that
* are allocated to an isolate in order to avoid leaks.
*
* \param isolate_group_data The same callback data which was passed to the
* isolate group when it was created.
*
*/
typedef void (*Dart_IsolateCleanupCallback)(void* callback_data);
typedef void (*Dart_IsolateGroupCleanupCallback)(void* isolate_group_data);
/**
* A thread death callback function.
@ -739,12 +792,17 @@ typedef struct Dart_CodeObserver {
* \param instructions_snapshot A buffer containing a snapshot of precompiled
* instructions, or NULL if no snapshot is provided. If provided, the buffer
* must remain valid until Dart_Cleanup returns.
* \param create A function to be called during isolate creation.
* See Dart_IsolateCreateCallback.
* \param shutdown A function to be called when an isolate is shutdown.
* \param initialize_isolate A function to be called during isolate
* initialization inside an existing isolate group.
* See Dart_InitializeIsolateCallback.
* \param create_group A function to be called during isolate group creation.
* See Dart_IsolateGroupCreateCallback.
* \param shutdown A function to be called right before an isolate is shutdown.
* See Dart_IsolateShutdownCallback.
* \param cleanup A function to be called after an isolate is shutdown.
* \param cleanup A function to be called after an isolate was shutdown.
* See Dart_IsolateCleanupCallback.
* \param cleanup_group A function to be called after an isolate group is shutdown.
* See Dart_IsolateGroupCleanupCallback.
* \param get_service_assets A function to be called by the service isolate when
* it requires the vmservice assets archive.
* See Dart_GetVMServiceAssetsArchive.
@ -755,9 +813,11 @@ typedef struct {
int32_t version;
const uint8_t* vm_snapshot_data;
const uint8_t* vm_snapshot_instructions;
Dart_IsolateCreateCallback create;
Dart_IsolateShutdownCallback shutdown;
Dart_IsolateCleanupCallback cleanup;
Dart_IsolateGroupCreateCallback create_group;
Dart_InitializeIsolateCallback initialize_isolate;
Dart_IsolateShutdownCallback shutdown_isolate;
Dart_IsolateCleanupCallback cleanup_isolate;
Dart_IsolateGroupCleanupCallback cleanup_group;
Dart_ThreadExitCallback thread_exit;
Dart_FileOpenCallback file_open;
Dart_FileReadCallback file_read;
@ -824,7 +884,7 @@ DART_EXPORT bool Dart_IsVMFlagSet(const char* flag_name);
* Requires there to be no current isolate.
*
* \param script_uri The main source file or snapshot this isolate will load.
* The VM will provide this URI to the Dart_IsolateCreateCallback when a child
* The VM will provide this URI to the Dart_IsolateGroupCreateCallback when a child
* isolate is created by Isolate.spawn. The embedder should use a URI that
* allows it to load the same program into such a child isolate.
* \param name A short name for the isolate to improve debugging messages.
@ -835,7 +895,7 @@ DART_EXPORT bool Dart_IsVMFlagSet(const char* flag_name);
* remain valid until the isolate shuts down.
* \param flags Pointer to VM specific flags or NULL for default flags.
* \param callback_data Embedder data. This data will be passed to
* the Dart_IsolateCreateCallback when new isolates are spawned from
* the Dart_IsolateGroupCreateCallback when new isolates are spawned from
* this parent isolate.
* \param error Returns NULL if creation is successful, an error message
* otherwise. The caller is responsible for calling free() on the error
@ -844,15 +904,16 @@ DART_EXPORT bool Dart_IsVMFlagSet(const char* flag_name);
* \return The new isolate on success, or NULL if isolate creation failed.
*/
DART_EXPORT Dart_Isolate
Dart_CreateIsolate(const char* script_uri,
const char* name,
const uint8_t* isolate_snapshot_data,
const uint8_t* isolate_snapshot_instructions,
const uint8_t* shared_data,
const uint8_t* shared_instructions,
Dart_IsolateFlags* flags,
void* callback_data,
char** error);
Dart_CreateIsolateGroup(const char* script_uri,
const char* name,
const uint8_t* isolate_snapshot_data,
const uint8_t* isolate_snapshot_instructions,
const uint8_t* shared_data,
const uint8_t* shared_instructions,
Dart_IsolateFlags* flags,
void* isolate_group_data,
void* isolate_data,
char** error);
/* TODO(turnidge): Document behavior when there is already a current
* isolate. */
@ -863,7 +924,7 @@ Dart_CreateIsolate(const char* script_uri,
* Requires there to be no current isolate.
*
* \param script_uri The main source file or snapshot this isolate will load.
* The VM will provide this URI to the Dart_IsolateCreateCallback when a child
* The VM will provide this URI to the Dart_IsolateGroupCreateCallback when a child
* isolate is created by Isolate.spawn. The embedder should use a URI that
* allows it to load the same program into such a child isolate.
* \param name A short name for the isolate to improve debugging messages.
@ -873,7 +934,7 @@ Dart_CreateIsolate(const char* script_uri,
* remain valid until isolate shutdown.
* \param flags Pointer to VM specific flags or NULL for default flags.
* \param callback_data Embedder data. This data will be passed to
* the Dart_IsolateCreateCallback when new isolates are spawned from
* the Dart_IsolateGroupCreateCallback when new isolates are spawned from
* this parent isolate.
* \param error Returns NULL if creation is successful, an error message
* otherwise. The caller is responsible for calling free() on the error
@ -882,13 +943,14 @@ Dart_CreateIsolate(const char* script_uri,
* \return The new isolate on success, or NULL if isolate creation failed.
*/
DART_EXPORT Dart_Isolate
Dart_CreateIsolateFromKernel(const char* script_uri,
const char* name,
const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size,
Dart_IsolateFlags* flags,
void* callback_data,
char** error);
Dart_CreateIsolateGroupFromKernel(const char* script_uri,
const char* name,
const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size,
Dart_IsolateFlags* flags,
void* isolate_group_data,
void* isolate_data,
char** error);
/**
* Shuts down the current isolate. After this call, the current isolate is NULL.
* Any current scopes created by Dart_EnterScope will be exited. Invokes the
@ -906,19 +968,31 @@ DART_EXPORT void Dart_ShutdownIsolate();
DART_EXPORT Dart_Isolate Dart_CurrentIsolate();
/**
* Returns the callback data associated with the current Isolate. This data was
* passed to the isolate when it was created.
* Returns the callback data associated with the current isolate. This
* data was set when the isolate got created or initialized.
*/
DART_EXPORT void* Dart_CurrentIsolateData();
/**
* Returns the callback data associated with the specified Isolate. This data
* was passed to the isolate when it was created.
* The embedder is responsible for ensuring the consistency of this data
* with respect to the lifecycle of an Isolate.
* Returns the callback data associated with the given isolate. This
* data was set when the isolate got created or initialized.
*/
DART_EXPORT void* Dart_IsolateData(Dart_Isolate isolate);
/**
* Returns the callback data associated with the current isolate group. This
* data was passed to the isolate group when it was created.
*/
DART_EXPORT void* Dart_CurrentIsolateGroupData();
/**
* Returns the callback data associated with the specified isolate group. This
* data was passed to the isolate when it was created.
* The embedder is responsible for ensuring the consistency of this data
* with respect to the lifecycle of an isolate group.
*/
DART_EXPORT void* Dart_IsolateGroupData(Dart_Isolate isolate);
/**
* Returns the debugging name for the current isolate.
*
@ -2514,9 +2588,9 @@ DART_EXPORT Dart_Handle Dart_SetNativeInstanceField(Dart_Handle obj,
typedef struct _Dart_NativeArguments* Dart_NativeArguments;
/**
* Extracts current isolate data from the native arguments structure.
* Extracts current isolate group data from the native arguments structure.
*/
DART_EXPORT void* Dart_GetNativeIsolateData(Dart_NativeArguments args);
DART_EXPORT void* Dart_GetNativeIsolateGroupData(Dart_NativeArguments args);
typedef enum {
Dart_NativeArgument_kBool = 0,
@ -2918,7 +2992,7 @@ DART_EXPORT Dart_Handle Dart_DefaultCanonicalizeUrl(Dart_Handle base_url,
* Requires there to be no current root library.
*
* \param buffer A buffer which contains a kernel binary (see
* pkg/kernel/binary.md). Must remain valid until isolate shutdown.
* pkg/kernel/binary.md). Must remain valid until isolate group shutdown.
* \param buffer_size Length of the passed in buffer.
*
* \return A handle to the root library, or an error.
@ -3288,7 +3362,7 @@ typedef void (*Dart_StreamingWriteCallback)(void* callback_data,
* Running this snapshot requires a VM compiled with DART_PRECOMPILED_SNAPSHOT.
* The kDartVmSnapshotData and kDartVmSnapshotInstructions should be passed to
* Dart_Initialize. The kDartIsolateSnapshotData and
* kDartIsolateSnapshotInstructions should be passed to Dart_CreateIsolate.
* kDartIsolateSnapshotInstructions should be passed to Dart_CreateIsolateGroup.
*
* The callback will be invoked one or more times to provide the assembly code.
*
@ -3364,7 +3438,7 @@ DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_SortClasses();
* startup and quicker warmup in a subsequent process.
*
* Outputs a snapshot in two pieces. The pieces should be passed to
* Dart_CreateIsolate in a VM using the same VM snapshot pieces used in the
* Dart_CreateIsolateGroup in a VM using the same VM snapshot pieces used in the
* current VM. The instructions piece must be loaded with read and execute
* permissions; the data piece may be loaded as read-only.
*

View file

@ -5,8 +5,8 @@
#ifndef RUNTIME_INCLUDE_DART_EMBEDDER_API_H_
#define RUNTIME_INCLUDE_DART_EMBEDDER_API_H_
#include "dart_api.h"
#include "dart_tools_api.h"
#include "include/dart_api.h"
#include "include/dart_tools_api.h"
namespace dart {
namespace embedder {
@ -29,8 +29,11 @@ struct IsolateCreationData {
// Isolate creation flags. Might be absent.
Dart_IsolateFlags* flags;
// Isolate group callback data.
void* isolate_group_data;
// Isolate callback data.
void* callback_data;
void* isolate_data;
};
// Create and initialize kernel-service isolate. This method should be used

View file

@ -129,28 +129,66 @@ class SpawnIsolateTask : public ThreadPool::Task {
}
void Run() override {
// Create a new isolate.
char* error = NULL;
Dart_IsolateCreateCallback callback = Isolate::CreateCallback();
if (callback == NULL) {
ReportError(
"Isolate spawn is not supported by this Dart implementation\n");
IsolateGroupSource* source = state_->source();
// The create isolate group call back is mandatory. If not provided we
// cannot spawn isolates.
Dart_IsolateGroupCreateCallback create_group_callback =
Isolate::CreateGroupCallback();
if (create_group_callback == nullptr) {
FailedSpawn("Isolate spawn is not supported by this Dart embedder\n");
return;
}
// Make a copy of the state's isolate flags and hand it to the callback.
Dart_IsolateFlags api_flags = *(state_->isolate_flags());
// The initialize callback is optional atm, we fall back to creating isolate
// groups if it was not provided.
Dart_InitializeIsolateCallback initialize_callback =
Isolate::InitializeCallback();
const char* name = (state_->debug_name() == NULL) ? state_->function_name()
: state_->debug_name();
ASSERT(name != NULL);
Isolate* isolate = reinterpret_cast<Isolate*>((callback)(
state_->script_url(), name, nullptr, state_->package_config(),
&api_flags, parent_isolate_->init_callback_data(), &error));
parent_isolate_->DecrementSpawnCount();
parent_isolate_ = nullptr;
if (isolate == NULL) {
ReportError(error);
// Create a new isolate.
char* error = nullptr;
Isolate* isolate = nullptr;
if (source == nullptr || initialize_callback == nullptr) {
// Make a copy of the state's isolate flags and hand it to the callback.
Dart_IsolateFlags api_flags = *(state_->isolate_flags());
isolate = reinterpret_cast<Isolate*>((create_group_callback)(
state_->script_url(), name, nullptr, state_->package_config(),
&api_flags, parent_isolate_->init_callback_data(), &error));
parent_isolate_->DecrementSpawnCount();
parent_isolate_ = nullptr;
} else {
if (initialize_callback == nullptr) {
FailedSpawn("Isolate spawn is not supported by this embedder.");
return;
}
isolate = CreateIsolateFromExistingSource(source, name, &error);
parent_isolate_->DecrementSpawnCount();
parent_isolate_ = nullptr;
if (isolate == nullptr) {
FailedSpawn(error);
free(error);
return;
}
void* child_isolate_data = nullptr;
bool success = initialize_callback(&child_isolate_data, &error);
isolate->set_init_callback_data(child_isolate_data);
if (!success) {
Dart_ShutdownIsolate();
FailedSpawn(error);
free(error);
return;
}
Dart_ExitIsolate();
}
if (isolate == nullptr) {
FailedSpawn(error);
free(error);
return;
}
@ -169,6 +207,13 @@ class SpawnIsolateTask : public ThreadPool::Task {
}
private:
void FailedSpawn(const char* error) {
ReportError(error != nullptr
? error
: "Unknown error occured during Isolate spawning.");
state_ = nullptr;
}
void ReportError(const char* error) {
Dart_CObject error_cobj;
error_cobj.type = Dart_CObject_kString;
@ -240,7 +285,7 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 0, 11) {
std::unique_ptr<IsolateSpawnState> state(new IsolateSpawnState(
port.Id(), isolate->origin_id(), String2UTF8(script_uri), func,
&message_buffer, utf8_package_config, paused.value(), fatal_errors,
on_exit_port, on_error_port, utf8_debug_name));
on_exit_port, on_error_port, utf8_debug_name, isolate->source()));
// Since this is a call to Isolate.spawn, copy the parent isolate's code.
state->isolate_flags()->copy_parent_code = true;
@ -351,10 +396,12 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnUri, 0, 13) {
const char* utf8_debug_name =
debugName.IsNull() ? NULL : String2UTF8(debugName);
IsolateGroupSource* null_source = nullptr;
std::unique_ptr<IsolateSpawnState> state(new IsolateSpawnState(
port.Id(), canonical_uri, utf8_package_config, &arguments_buffer,
&message_buffer, paused.value(), fatal_errors, on_exit_port,
on_error_port, utf8_debug_name));
on_error_port, utf8_debug_name, null_source));
// If we were passed a value then override the default flags state for
// checked mode.

View file

@ -91,7 +91,7 @@ var tests = <IsolateTest>[
final numRanges = coverage['ranges'].length;
expect(coverage['type'], equals('SourceReport'));
expect((numRanges == 12), isTrue);
expect(numRanges, equals(12));
expect(coverage['ranges'][0], equals(expectedRange));
expect(coverage['scripts'].length, 1);
expect(

View file

@ -89,7 +89,7 @@ void allEventsHaveIsolateNumber(List events) {
}
if (event['cat'] == 'Embedder' &&
(event['name'] == 'DFE::ReadScript' ||
event['name'] == 'CreateIsolateAndSetupHelper')) {
event['name'] == 'CreateIsolateGroupAndSetupHelper')) {
continue;
}
Map arguments = event['args'];

View file

@ -130,9 +130,11 @@ static void CheckOffsets() {
char* Dart::Init(const uint8_t* vm_isolate_snapshot,
const uint8_t* instructions_snapshot,
Dart_IsolateCreateCallback create,
Dart_IsolateGroupCreateCallback create_group,
Dart_InitializeIsolateCallback initialize_isolate,
Dart_IsolateShutdownCallback shutdown,
Dart_IsolateCleanupCallback cleanup,
Dart_IsolateShutdownCallback cleanup,
Dart_IsolateGroupCleanupCallback cleanup_group,
Dart_ThreadExitCallback thread_exit,
Dart_FileOpenCallback file_open,
Dart_FileReadCallback file_read,
@ -355,9 +357,11 @@ char* Dart::Init(const uint8_t* vm_isolate_snapshot,
Api::InitHandles();
Thread::ExitIsolate(); // Unregister the VM isolate from this thread.
Isolate::SetCreateCallback(create);
Isolate::SetCreateGroupCallback(create_group);
Isolate::SetInitializeCallback_(initialize_isolate);
Isolate::SetShutdownCallback(shutdown);
Isolate::SetCleanupCallback(cleanup);
Isolate::SetGroupCleanupCallback(cleanup_group);
if (FLAG_support_service) {
Service::SetGetServiceAssetsCallback(get_service_assets);
@ -620,7 +624,7 @@ RawError* Dart::InitializeIsolate(const uint8_t* snapshot_data,
const uint8_t* shared_instructions,
const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size,
void* data) {
void* isolate_data) {
// Initialize the new isolate.
Thread* T = Thread::Current();
Isolate* I = T->isolate();
@ -724,7 +728,7 @@ RawError* Dart::InitializeIsolate(const uint8_t* snapshot_data,
}
I->heap()->InitGrowthControl();
I->set_init_callback_data(data);
I->set_init_callback_data(isolate_data);
Api::SetupAcquiredError(I);
if (FLAG_print_class_table) {
I->class_table()->Print();
@ -850,11 +854,12 @@ void Dart::RunShutdownCallback() {
Thread* thread = Thread::Current();
ASSERT(thread->execution_state() == Thread::kThreadInVM);
Isolate* isolate = thread->isolate();
void* callback_data = isolate->init_callback_data();
void* isolate_group_data = isolate->source()->callback_data;
void* isolate_data = isolate->init_callback_data();
Dart_IsolateShutdownCallback callback = Isolate::ShutdownCallback();
if (callback != NULL) {
TransitionVMToNative transition(thread);
(callback)(callback_data);
(callback)(isolate_group_data, isolate_data);
}
}

View file

@ -28,9 +28,11 @@ class Dart : public AllStatic {
// (caller owns error message and has to free it).
static char* Init(const uint8_t* vm_snapshot_data,
const uint8_t* vm_snapshot_instructions,
Dart_IsolateCreateCallback create,
Dart_IsolateGroupCreateCallback create_group,
Dart_InitializeIsolateCallback initialize_isolate,
Dart_IsolateShutdownCallback shutdown,
Dart_IsolateCleanupCallback cleanup,
Dart_IsolateGroupCleanupCallback cleanup_group,
Dart_ThreadExitCallback thread_exit,
Dart_FileOpenCallback file_open,
Dart_FileReadCallback file_read,

View file

@ -1007,11 +1007,13 @@ DART_EXPORT char* Dart_Initialize(Dart_InitializeParams* params) {
}
return Dart::Init(params->vm_snapshot_data, params->vm_snapshot_instructions,
params->create, params->shutdown, params->cleanup,
params->thread_exit, params->file_open, params->file_read,
params->file_write, params->file_close,
params->entropy_source, params->get_service_assets,
params->start_kernel_isolate, params->code_observer);
params->create_group, params->initialize_isolate,
params->shutdown_isolate, params->cleanup_isolate,
params->cleanup_group, params->thread_exit,
params->file_open, params->file_read, params->file_write,
params->file_close, params->entropy_source,
params->get_service_assets, params->start_kernel_isolate,
params->code_observer);
}
DART_EXPORT char* Dart_Cleanup() {
@ -1060,26 +1062,13 @@ ISOLATE_METRIC_LIST(ISOLATE_METRIC_API);
// --- Isolates ---
static Dart_Isolate CreateIsolate(const char* script_uri,
static Dart_Isolate CreateIsolate(IsolateGroupSource* source,
const char* name,
const uint8_t* snapshot_data,
const uint8_t* snapshot_instructions,
const uint8_t* shared_data,
const uint8_t* shared_instructions,
const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size,
Dart_IsolateFlags* flags,
void* callback_data,
void* isolate_data,
char** error) {
CHECK_NO_ISOLATE(Isolate::Current());
// Setup default flags in case none were passed.
Dart_IsolateFlags api_flags;
if (flags == NULL) {
Isolate::FlagsInitialize(&api_flags);
flags = &api_flags;
}
Isolate* I = Dart::CreateIsolate((name == NULL) ? "isolate" : name, *flags);
Isolate* I = Dart::CreateIsolate(name, source->flags);
if (I == NULL) {
if (error != NULL) {
*error = strdup("Isolate creation failed");
@ -1096,14 +1085,15 @@ static Dart_Isolate CreateIsolate(const char* script_uri,
// bootstrap library files which call out to a tag handler that may create
// Api Handles when an error is encountered.
T->EnterApiScope();
const Error& error_obj = Error::Handle(
Z,
Dart::InitializeIsolate(snapshot_data, snapshot_instructions,
shared_data, shared_instructions, kernel_buffer,
kernel_buffer_size, callback_data));
const Error& error_obj =
Error::Handle(Z, Dart::InitializeIsolate(
source->snapshot_data,
source->snapshot_instructions, source->shared_data,
source->shared_instructions, source->kernel_buffer,
source->kernel_buffer_size, isolate_data));
if (error_obj.IsNull()) {
#if defined(DART_NO_SNAPSHOT) && !defined(PRODUCT)
if (FLAG_check_function_fingerprints && kernel_buffer == NULL) {
if (FLAG_check_function_fingerprints && source->kernel_buffer == NULL) {
Library::CheckFunctionFingerprints();
}
#endif // defined(DART_NO_SNAPSHOT) && !defined(PRODUCT).
@ -1115,6 +1105,8 @@ static Dart_Isolate CreateIsolate(const char* script_uri,
T->ExitApiScope();
}
I->set_source(source);
if (success) {
// A Thread structure has been associated to the thread, we do the
// safepoint transition explicitly here instead of using the
@ -1132,37 +1124,127 @@ static Dart_Isolate CreateIsolate(const char* script_uri,
return reinterpret_cast<Dart_Isolate>(NULL);
}
Isolate* CreateIsolateFromExistingSource(IsolateGroupSource* source,
const char* name,
char** error) {
API_TIMELINE_DURATION(Thread::Current());
CHECK_NO_ISOLATE(Isolate::Current());
Isolate* isolate = reinterpret_cast<Isolate*>(
CreateIsolate(source, name, /*isolate_data=*/nullptr, error));
if (isolate == nullptr) return nullptr;
RELEASE_ASSERT(isolate->source() == source);
if (source->script_kernel_buffer != nullptr) {
#if defined(DART_PRECOMPILED_RUNTIME)
UNREACHABLE();
#else
Dart_EnterScope();
{
Thread* T = Thread::Current();
TransitionNativeToVM transition(T);
HANDLESCOPE(T);
StackZone zone(T);
// The kernel loader is about to allocate a bunch of new libraries,
// classes and functions into old space. Force growth, and use of the
// bump allocator instead of freelists.
BumpAllocateScope bump_allocate_scope(T);
// NOTE: We do not attach a finalizer for this object, because the
// embedder will free it once the isolate group has shutdown.
const auto& td = ExternalTypedData::Handle(ExternalTypedData::New(
kExternalTypedDataUint8ArrayCid,
const_cast<uint8_t*>(source->script_kernel_buffer),
source->script_kernel_size, Heap::kOld));
std::unique_ptr<kernel::Program> program =
kernel::Program::ReadFromTypedData(td,
const_cast<const char**>(error));
if (program == nullptr) {
UNIMPLEMENTED();
}
const Object& tmp =
kernel::KernelLoader::LoadEntireProgram(program.get());
// If the existing isolate could spawn with a root library we should be
// able to do the same
RELEASE_ASSERT(!tmp.IsNull() && tmp.IsLibrary());
isolate->object_store()->set_root_library(Library::Cast(tmp));
}
Dart_ExitScope();
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
return isolate;
}
DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags* flags) {
Isolate::FlagsInitialize(flags);
}
DART_EXPORT Dart_Isolate
Dart_CreateIsolate(const char* script_uri,
const char* name,
const uint8_t* snapshot_data,
const uint8_t* snapshot_instructions,
const uint8_t* shared_data,
const uint8_t* shared_instructions,
Dart_IsolateFlags* flags,
void* callback_data,
char** error) {
Dart_CreateIsolateGroup(const char* script_uri,
const char* name,
const uint8_t* snapshot_data,
const uint8_t* snapshot_instructions,
const uint8_t* shared_data,
const uint8_t* shared_instructions,
Dart_IsolateFlags* flags,
void* isolate_group_data,
void* isolate_data,
char** error) {
API_TIMELINE_DURATION(Thread::Current());
return CreateIsolate(script_uri, name, snapshot_data, snapshot_instructions,
shared_data, shared_instructions, NULL, 0, flags,
callback_data, error);
Dart_IsolateFlags api_flags;
if (flags == nullptr) {
Isolate::FlagsInitialize(&api_flags);
flags = &api_flags;
}
const char* non_null_name = name == nullptr ? "isolate" : name;
auto source = new IsolateGroupSource(script_uri, non_null_name, snapshot_data,
snapshot_instructions, shared_data,
shared_instructions, nullptr, -1, *flags,
isolate_group_data);
source->IncrementIsolateUsageCount();
Dart_Isolate isolate =
CreateIsolate(source, non_null_name, isolate_data, error);
if (source->DecrementIsolateUsageCount()) {
delete source;
}
return isolate;
}
DART_EXPORT Dart_Isolate
Dart_CreateIsolateFromKernel(const char* script_uri,
const char* name,
const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size,
Dart_IsolateFlags* flags,
void* callback_data,
char** error) {
Dart_CreateIsolateGroupFromKernel(const char* script_uri,
const char* name,
const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size,
Dart_IsolateFlags* flags,
void* isolate_group_data,
void* isolate_data,
char** error) {
API_TIMELINE_DURATION(Thread::Current());
return CreateIsolate(script_uri, name, NULL, NULL, NULL, NULL, kernel_buffer,
kernel_buffer_size, flags, callback_data, error);
Dart_IsolateFlags api_flags;
if (flags == nullptr) {
Isolate::FlagsInitialize(&api_flags);
flags = &api_flags;
}
const char* non_null_name = name == nullptr ? "isolate" : name;
auto source = new IsolateGroupSource(
script_uri, non_null_name, nullptr, nullptr, nullptr, nullptr,
kernel_buffer, kernel_buffer_size, *flags, isolate_group_data);
source->IncrementIsolateUsageCount();
Dart_Isolate isolate =
CreateIsolate(source, non_null_name, isolate_data, error);
if (source->DecrementIsolateUsageCount()) {
delete source;
}
return isolate;
}
DART_EXPORT void Dart_ShutdownIsolate() {
@ -1173,7 +1255,7 @@ DART_EXPORT void Dart_ShutdownIsolate() {
// The Thread structure is disassociated from the isolate, we do the
// safepoint transition explicitly here instead of using the TransitionXXX
// scope objects as the original transition happened outside this scope in
// Dart_EnterIsolate/Dart_CreateIsolate.
// Dart_EnterIsolate/Dart_CreateIsolateGroup.
ASSERT(T->execution_state() == Thread::kThreadInNative);
T->ExitSafepoint();
T->set_execution_state(Thread::kThreadInVM);
@ -1212,9 +1294,23 @@ DART_EXPORT void* Dart_IsolateData(Dart_Isolate isolate) {
if (isolate == NULL) {
FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
}
// TODO(16615): Validate isolate parameter.
Isolate* iso = reinterpret_cast<Isolate*>(isolate);
return iso->init_callback_data();
// TODO(http://dartbug.com/16615): Validate isolate parameter.
return reinterpret_cast<Isolate*>(isolate)->init_callback_data();
}
DART_EXPORT void* Dart_CurrentIsolateGroupData() {
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
return isolate->source()->callback_data;
}
DART_EXPORT void* Dart_IsolateGroupData(Dart_Isolate isolate) {
if (isolate == NULL) {
FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
}
// TODO(http://dartbug.com/16615): Validate isolate parameter.
return reinterpret_cast<Isolate*>(isolate)->source()->callback_data;
}
DART_EXPORT Dart_Handle Dart_DebugName() {
@ -1229,6 +1325,7 @@ DART_EXPORT const char* Dart_IsolateServiceId(Dart_Isolate isolate) {
if (isolate == NULL) {
FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
}
// TODO(http://dartbug.com/16615): Validate isolate parameter.
Isolate* I = reinterpret_cast<Isolate*>(isolate);
int64_t main_port = static_cast<int64_t>(I->main_port());
return OS::SCreate(NULL, "isolates/%" Pd64, main_port);
@ -1236,7 +1333,7 @@ DART_EXPORT const char* Dart_IsolateServiceId(Dart_Isolate isolate) {
DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate) {
CHECK_NO_ISOLATE(Isolate::Current());
// TODO(16615): Validate isolate parameter.
// TODO(http://dartbug.com/16615): Validate isolate parameter.
Isolate* iso = reinterpret_cast<Isolate*>(isolate);
if (!Thread::EnterIsolate(iso)) {
FATAL(
@ -1496,7 +1593,7 @@ DART_EXPORT void Dart_ExitIsolate() {
// The Thread structure is disassociated from the isolate, we do the
// safepoint transition explicitly here instead of using the TransitionXXX
// scope objects as the original transition happened outside this scope in
// Dart_EnterIsolate/Dart_CreateIsolate.
// Dart_EnterIsolate/Dart_CreateIsolateGroup.
ASSERT(T->execution_state() == Thread::kThreadInNative);
T->ExitSafepoint();
T->set_execution_state(Thread::kThreadInVM);
@ -4561,7 +4658,7 @@ DART_EXPORT Dart_Handle Dart_SetNativeInstanceField(Dart_Handle obj,
return Api::Success();
}
DART_EXPORT void* Dart_GetNativeIsolateData(Dart_NativeArguments args) {
DART_EXPORT void* Dart_GetNativeIsolateGroupData(Dart_NativeArguments args) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
Isolate* isolate = arguments->thread()->isolate();
ASSERT(isolate == Isolate::Current());
@ -5043,9 +5140,15 @@ DART_EXPORT Dart_Handle Dart_LoadScriptFromKernel(const uint8_t* buffer,
// instead of freelists.
BumpAllocateScope bump_allocate_scope(T);
// NOTE: We do not attach a finalizer for this object, because the embedder
// will free it once the isolate group has shutdown.
const auto& td = ExternalTypedData::Handle(ExternalTypedData::New(
kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(buffer),
buffer_size, Heap::kOld));
const char* error = nullptr;
std::unique_ptr<kernel::Program> program =
kernel::Program::ReadFromBuffer(buffer, buffer_size, &error);
kernel::Program::ReadFromTypedData(td, &error);
if (program == nullptr) {
return Api::NewError("Can't load Kernel binary: %s.", error);
}
@ -5055,6 +5158,10 @@ DART_EXPORT Dart_Handle Dart_LoadScriptFromKernel(const uint8_t* buffer,
if (tmp.IsError()) {
return Api::NewHandle(T, tmp.raw());
}
I->source()->script_kernel_size = buffer_size;
I->source()->script_kernel_buffer = buffer;
// TODO(32618): Setting root library based on whether it has 'main' or not
// is not correct because main can be in the exported namespace of a library
// or it could be a getter.
@ -5291,9 +5398,16 @@ DART_EXPORT Dart_Handle Dart_LoadLibraryFromKernel(const uint8_t* buffer,
// instead of freelists.
BumpAllocateScope bump_allocate_scope(T);
// NOTE: We do not attach a finalizer for this object, because the embedder
// will/should free it once the isolate group has shutdown.
// See also http://dartbug.com/37030.
const auto& td = ExternalTypedData::Handle(ExternalTypedData::New(
kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(buffer),
buffer_size, Heap::kOld));
const char* error = nullptr;
std::unique_ptr<kernel::Program> program =
kernel::Program::ReadFromBuffer(buffer, buffer_size, &error);
kernel::Program::ReadFromTypedData(td, &error);
if (program == nullptr) {
return Api::NewError("Can't load Kernel binary: %s.", error);
}

View file

@ -5,6 +5,8 @@
#ifndef RUNTIME_VM_DART_API_IMPL_H_
#define RUNTIME_VM_DART_API_IMPL_H_
#include <memory>
#include "vm/allocation.h"
#include "vm/heap/safepoint.h"
#include "vm/native_arguments.h"
@ -32,7 +34,7 @@ const char* CanonicalFunction(const char* func);
if ((isolate) == NULL) { \
FATAL1( \
"%s expects there to be a current isolate. Did you " \
"forget to call Dart_CreateIsolate or Dart_EnterIsolate?", \
"forget to call Dart_CreateIsolateGroup or Dart_EnterIsolate?", \
CURRENT_FUNC); \
} \
} while (0)
@ -359,6 +361,14 @@ class Api : AllStatic {
#define ASSERT_CALLBACK_STATE(thread) \
ASSERT(thread->no_callback_scope_depth() == 0)
class IsolateGroupSource;
// Creates a new isolate from [source] (which should come from an existing
// isolate).
Isolate* CreateIsolateFromExistingSource(IsolateGroupSource* source,
const char* name,
char** error);
} // namespace dart.
#endif // RUNTIME_VM_DART_API_IMPL_H_

View file

@ -33,9 +33,9 @@ UNIT_TEST_CASE(DartAPI_DartInitializeAfterCleanup) {
memset(&params, 0, sizeof(Dart_InitializeParams));
params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
params.vm_snapshot_data = TesterState::vm_snapshot_data;
params.create = TesterState::create_callback;
params.shutdown = TesterState::shutdown_callback;
params.cleanup = TesterState::cleanup_callback;
params.create_group = TesterState::create_callback;
params.shutdown_isolate = TesterState::shutdown_callback;
params.cleanup_group = TesterState::group_cleanup_callback;
params.start_kernel_isolate = true;
// Reinitialize and ensure we can execute Dart code.
@ -63,9 +63,9 @@ UNIT_TEST_CASE(DartAPI_DartInitializeCallsCodeObserver) {
memset(&params, 0, sizeof(Dart_InitializeParams));
params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
params.vm_snapshot_data = TesterState::vm_snapshot_data;
params.create = TesterState::create_callback;
params.shutdown = TesterState::shutdown_callback;
params.cleanup = TesterState::cleanup_callback;
params.create_group = TesterState::create_callback;
params.shutdown_isolate = TesterState::shutdown_callback;
params.cleanup_group = TesterState::group_cleanup_callback;
params.start_kernel_isolate = true;
bool was_called = false;
@ -3670,20 +3670,21 @@ VM_UNIT_TEST_CASE(DartAPI_Isolates) {
VM_UNIT_TEST_CASE(DartAPI_CurrentIsolateData) {
Dart_IsolateShutdownCallback saved_shutdown = Isolate::ShutdownCallback();
Dart_IsolateCleanupCallback saved_cleanup = Isolate::CleanupCallback();
Dart_IsolateGroupCleanupCallback saved_cleanup =
Isolate::GroupCleanupCallback();
Isolate::SetShutdownCallback(NULL);
Isolate::SetCleanupCallback(NULL);
Isolate::SetGroupCleanupCallback(NULL);
intptr_t mydata = 12345;
Dart_Isolate isolate =
TestCase::CreateTestIsolate(NULL, reinterpret_cast<void*>(mydata));
EXPECT(isolate != NULL);
EXPECT_EQ(mydata, reinterpret_cast<intptr_t>(Dart_CurrentIsolateData()));
EXPECT_EQ(mydata, reinterpret_cast<intptr_t>(Dart_IsolateData(isolate)));
EXPECT_EQ(mydata, reinterpret_cast<intptr_t>(Dart_CurrentIsolateGroupData()));
EXPECT_EQ(mydata, reinterpret_cast<intptr_t>(Dart_IsolateGroupData(isolate)));
Dart_ShutdownIsolate();
Isolate::SetShutdownCallback(saved_shutdown);
Isolate::SetCleanupCallback(saved_cleanup);
Isolate::SetGroupCleanupCallback(saved_cleanup);
}
static Dart_Handle LoadScript(const char* url_str, const char* source) {
@ -6618,8 +6619,8 @@ static Dart_Isolate RunLoopTestCallback(const char* script_name,
// Common code for RunLoop_Success/RunLoop_Failure.
static void RunLoopTest(bool throw_exception) {
Dart_IsolateCreateCallback saved = Isolate::CreateCallback();
Isolate::SetCreateCallback(RunLoopTestCallback);
Dart_IsolateGroupCreateCallback saved = Isolate::CreateGroupCallback();
Isolate::SetCreateGroupCallback(RunLoopTestCallback);
Dart_Isolate isolate =
RunLoopTestCallback(NULL, NULL, NULL, NULL, NULL, NULL, NULL);
@ -6643,7 +6644,7 @@ static void RunLoopTest(bool throw_exception) {
Dart_ExitScope();
Dart_ShutdownIsolate();
Isolate::SetCreateCallback(saved);
Isolate::SetCreateGroupCallback(saved);
}
VM_UNIT_TEST_CASE(DartAPI_RunLoop_Success) {
@ -6654,45 +6655,93 @@ VM_UNIT_TEST_CASE(DartAPI_RunLoop_Exception) {
RunLoopTest(true);
}
static void* shutdown_callback_data;
static void IsolateShutdownTestCallback(void* callback_data) {
shutdown_callback_data = callback_data;
static void* shutdown_isolate_group_data;
static void* shutdown_isolate_data;
static void* cleanup_isolate_group_data;
static void* cleanup_isolate_data;
// Called on isolate shutdown time (which is still allowed to run Dart code)
static void IsolateShutdownTestCallback(void* group_data, void* isolate_data) {
// Shutdown runs before cleanup.
EXPECT(cleanup_isolate_group_data == nullptr);
EXPECT(cleanup_isolate_data == nullptr);
// Shutdown must have a current isolate (since it is allowed to execute Dart
// code)
EXPECT(Dart_CurrentIsolate() != nullptr);
EXPECT(Dart_CurrentIsolateGroupData() == group_data);
EXPECT(Dart_CurrentIsolateData() == isolate_data);
shutdown_isolate_group_data = group_data;
shutdown_isolate_data = isolate_data;
}
static void* cleanup_callback_data;
static void IsolateCleanupTestCallback(void* callback_data) {
cleanup_callback_data = callback_data;
// Called on isolate cleanup time (which is after the isolate has been
// destroyed)
static void IsolateCleanupTestCallback(void* group_data, void* isolate_data) {
// Cleanup runs after shutdown.
EXPECT(shutdown_isolate_group_data != nullptr);
EXPECT(shutdown_isolate_data != nullptr);
// The isolate was destroyed and there should not be a current isolate.
EXPECT(Dart_CurrentIsolate() == nullptr);
cleanup_isolate_group_data = group_data;
cleanup_isolate_data = isolate_data;
}
// Called on isolate group cleanup time (once all isolates have been destroyed)
static void* cleanup_group_callback_data;
static void IsolateGroupCleanupTestCallback(void* callback_data) {
cleanup_group_callback_data = callback_data;
}
VM_UNIT_TEST_CASE(DartAPI_IsolateShutdownAndCleanup) {
Dart_IsolateShutdownCallback saved_shutdown = Isolate::ShutdownCallback();
Dart_IsolateCleanupCallback saved_cleanup = Isolate::CleanupCallback();
Dart_IsolateGroupCleanupCallback saved_cleanup =
Isolate::GroupCleanupCallback();
Isolate::SetShutdownCallback(IsolateShutdownTestCallback);
Isolate::SetCleanupCallback(IsolateCleanupTestCallback);
Isolate::SetGroupCleanupCallback(IsolateGroupCleanupTestCallback);
shutdown_isolate_group_data = nullptr;
shutdown_isolate_data = nullptr;
cleanup_group_callback_data = nullptr;
void* my_group_data = reinterpret_cast<void*>(123);
void* my_data = reinterpret_cast<void*>(456);
shutdown_callback_data = NULL;
cleanup_callback_data = NULL;
void* my_data = reinterpret_cast<void*>(12345);
// Create an isolate.
Dart_Isolate isolate = TestCase::CreateTestIsolate(NULL, my_data);
Dart_Isolate isolate =
TestCase::CreateTestIsolate(nullptr, my_group_data, my_data);
EXPECT(isolate != NULL);
// The shutdown callback has not been called.
EXPECT_EQ(0, reinterpret_cast<intptr_t>(shutdown_callback_data));
EXPECT_EQ(0, reinterpret_cast<intptr_t>(cleanup_callback_data));
EXPECT(nullptr == shutdown_isolate_data);
EXPECT(nullptr == shutdown_isolate_group_data);
EXPECT(nullptr == cleanup_group_callback_data);
// The isolate is the active isolate which allows us to access the isolate
// specific and isolate-group specific data.
EXPECT(Dart_CurrentIsolateData() == my_data);
EXPECT(Dart_CurrentIsolateGroupData() == my_group_data);
// Shutdown the isolate.
Dart_ShutdownIsolate();
// The shutdown callback has been called.
EXPECT_EQ(12345, reinterpret_cast<intptr_t>(shutdown_callback_data));
EXPECT_EQ(12345, reinterpret_cast<intptr_t>(cleanup_callback_data));
// The shutdown & cleanup callbacks have been called.
EXPECT(my_data == shutdown_isolate_data);
EXPECT(my_group_data == shutdown_isolate_group_data);
EXPECT(my_data == cleanup_isolate_data);
EXPECT(my_group_data == cleanup_isolate_group_data);
EXPECT(my_group_data == cleanup_group_callback_data);
Isolate::SetShutdownCallback(saved_shutdown);
Isolate::SetCleanupCallback(saved_cleanup);
Isolate::SetGroupCleanupCallback(saved_cleanup);
}
static int64_t add_result = 0;
static void IsolateShutdownRunDartCodeTestCallback(void* callback_data) {
static void IsolateShutdownRunDartCodeTestCallback(void* isolate_group_data,
void* isolate_data) {
Dart_Isolate isolate = Dart_CurrentIsolate();
if (Dart_IsKernelIsolate(isolate) || Dart_IsServiceIsolate(isolate)) {
return;

View file

@ -1001,7 +1001,11 @@ Isolate::~Isolate() {
}
void Isolate::InitVM() {
create_callback_ = nullptr;
create_group_callback_ = nullptr;
initialize_callback_ = nullptr;
shutdown_callback_ = nullptr;
cleanup_callback_ = nullptr;
cleanup_group_callback_ = nullptr;
if (isolates_list_monitor_ == nullptr) {
isolates_list_monitor_ = new Monitor();
}
@ -1900,15 +1904,34 @@ void Isolate::Shutdown() {
// as we are shutting down the isolate.
Thread::ExitIsolate();
Dart_IsolateCleanupCallback cleanup = Isolate::CleanupCallback();
if (cleanup != nullptr) {
cleanup(init_callback_data());
// The source is null iff the isolate is the "vm-isolate".
ASSERT((source_ == nullptr) == (Dart::vm_isolate() == this));
if (source_ != nullptr) {
// Run isolate specific cleanup function.
Dart_IsolateCleanupCallback cleanup = Isolate::CleanupCallback();
if (cleanup != nullptr) {
cleanup(source_->callback_data, init_callback_data());
}
// Run isolate group specific cleanup function if the last isolate in an
// isolate group died.
if (source_->DecrementIsolateUsageCount()) {
auto group_cleanup_callback = Isolate::GroupCleanupCallback();
if (group_cleanup_callback != nullptr) {
group_cleanup_callback(source_->callback_data);
}
delete source_;
source_ = nullptr;
}
}
}
Dart_IsolateCreateCallback Isolate::create_callback_ = nullptr;
Dart_InitializeIsolateCallback Isolate::initialize_callback_ = nullptr;
Dart_IsolateGroupCreateCallback Isolate::create_group_callback_ = nullptr;
Dart_IsolateShutdownCallback Isolate::shutdown_callback_ = nullptr;
Dart_IsolateCleanupCallback Isolate::cleanup_callback_ = nullptr;
Dart_IsolateGroupCleanupCallback Isolate::cleanup_group_callback_ = nullptr;
Monitor* Isolate::isolates_list_monitor_ = nullptr;
Isolate* Isolate::isolates_list_head_ = nullptr;
@ -2930,7 +2953,8 @@ IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port,
bool errors_are_fatal,
Dart_Port on_exit_port,
Dart_Port on_error_port,
const char* debug_name)
const char* debug_name,
IsolateGroupSource* source)
: isolate_(nullptr),
parent_port_(parent_port),
origin_id_(origin_id),
@ -2942,6 +2966,7 @@ IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port,
class_name_(nullptr),
function_name_(nullptr),
debug_name_(debug_name),
source_(source),
serialized_args_(nullptr),
serialized_message_(message_buffer->StealMessage()),
paused_(paused),
@ -2973,7 +2998,8 @@ IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port,
bool errors_are_fatal,
Dart_Port on_exit_port,
Dart_Port on_error_port,
const char* debug_name)
const char* debug_name,
IsolateGroupSource* source)
: isolate_(nullptr),
parent_port_(parent_port),
origin_id_(ILLEGAL_PORT),
@ -2985,6 +3011,7 @@ IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port,
class_name_(nullptr),
function_name_(nullptr),
debug_name_(debug_name),
source_(source),
serialized_args_(args_buffer->StealMessage()),
serialized_message_(message_buffer->StealMessage()),
isolate_flags_(),

View file

@ -155,6 +155,78 @@ typedef FixedCache<intptr_t, CatchEntryMovesRefPtr, 16> CatchEntryMovesCache;
unsafe_trust_strong_mode_types, \
FLAG_experimental_unsafe_mode_use_at_your_own_risk)
// Represents the information used for spawning the first isolate within an
// isolate group.
//
// Any subsequent isolates created via `Isolate.spawn()` will be created using
// the same [IsolateGroupSource] (the object itself is shared among all isolates
// within the same group).
//
// Issue(http://dartbug.com/36097): It is still possible to run into issues if
// an isolate has spawned another one and then loads more code into the first
// one, which the latter will not get. Though it makes the status quo better
// than what we had before (where the embedder needed to maintain the
// same-source guarantee).
//
// => This is only the first step towards having multiple isolates share the
// same heap (and therefore the same program structure).
//
class IsolateGroupSource {
public:
IsolateGroupSource(const char* script_uri,
const char* name,
const uint8_t* snapshot_data,
const uint8_t* snapshot_instructions,
const uint8_t* shared_data,
const uint8_t* shared_instructions,
const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size,
Dart_IsolateFlags flags,
void* callback_data)
: script_uri(script_uri),
name(strdup(name)),
snapshot_data(snapshot_data),
snapshot_instructions(snapshot_instructions),
shared_data(shared_data),
shared_instructions(shared_instructions),
kernel_buffer(kernel_buffer),
kernel_buffer_size(kernel_buffer_size),
flags(flags),
callback_data(callback_data),
script_kernel_buffer(nullptr),
script_kernel_size(-1) {}
~IsolateGroupSource() { free(name); }
// The arguments used for spawning in
// `Dart_CreateIsolateGroupFromKernel` / `Dart_CreateIsolate`.
const char* script_uri;
char* name;
const uint8_t* snapshot_data;
const uint8_t* snapshot_instructions;
const uint8_t* shared_data;
const uint8_t* shared_instructions;
const uint8_t* kernel_buffer;
const intptr_t kernel_buffer_size;
Dart_IsolateFlags flags;
void* callback_data;
// The kernel buffer used in `Dart_LoadScriptFromKernel`.
const uint8_t* script_kernel_buffer;
intptr_t script_kernel_size;
void IncrementIsolateUsageCount() {
AtomicOperations::IncrementBy(&isolate_count_, 1);
}
// Returns true if this was the last reference.
bool DecrementIsolateUsageCount() {
return AtomicOperations::FetchAndDecrement(&isolate_count_) == 1;
}
private:
intptr_t isolate_count_ = 0;
};
class Isolate : public BaseIsolate {
public:
// Keep both these enums in sync with isolate_patch.dart.
@ -239,6 +311,13 @@ class Isolate : public BaseIsolate {
message_notify_callback_ = value;
}
IsolateGroupSource* source() const { return source_; }
void set_source(IsolateGroupSource* source) {
source->IncrementIsolateUsageCount();
source_ = source;
}
bool HasPendingMessages();
Thread* mutator_thread() const;
@ -437,11 +516,18 @@ class Isolate : public BaseIsolate {
void DecrementSpawnCount();
void WaitForOutstandingSpawns();
static void SetCreateCallback(Dart_IsolateCreateCallback cb) {
create_callback_ = cb;
static void SetCreateGroupCallback(Dart_IsolateGroupCreateCallback cb) {
create_group_callback_ = cb;
}
static Dart_IsolateCreateCallback CreateCallback() {
return create_callback_;
static Dart_IsolateGroupCreateCallback CreateGroupCallback() {
return create_group_callback_;
}
static void SetInitializeCallback_(Dart_InitializeIsolateCallback cb) {
initialize_callback_ = cb;
}
static Dart_InitializeIsolateCallback InitializeCallback() {
return initialize_callback_;
}
static void SetShutdownCallback(Dart_IsolateShutdownCallback cb) {
@ -458,6 +544,13 @@ class Isolate : public BaseIsolate {
return cleanup_callback_;
}
static void SetGroupCleanupCallback(Dart_IsolateGroupCleanupCallback cb) {
cleanup_group_callback_ = cb;
}
static Dart_IsolateGroupCleanupCallback GroupCleanupCallback() {
return cleanup_group_callback_;
}
#if !defined(PRODUCT)
void set_object_id_ring(ObjectIdRing* ring) { object_id_ring_ = ring; }
ObjectIdRing* object_id_ring() { return object_id_ring_; }
@ -1056,9 +1149,11 @@ class Isolate : public BaseIsolate {
ReversePcLookupCache* reverse_pc_lookup_cache_ = nullptr;
static Dart_IsolateCreateCallback create_callback_;
static Dart_IsolateGroupCreateCallback create_group_callback_;
static Dart_InitializeIsolateCallback initialize_callback_;
static Dart_IsolateShutdownCallback shutdown_callback_;
static Dart_IsolateCleanupCallback cleanup_callback_;
static Dart_IsolateGroupCleanupCallback cleanup_group_callback_;
#if !defined(PRODUCT)
static void WakePauseEventHandler(Dart_Isolate isolate);
@ -1072,6 +1167,7 @@ class Isolate : public BaseIsolate {
static Monitor* isolates_list_monitor_;
static Isolate* isolates_list_head_;
static bool creation_enabled_;
IsolateGroupSource* source_ = nullptr;
#define REUSABLE_FRIEND_DECLARATION(name) \
friend class Reusable##name##HandleScope;
@ -1145,7 +1241,8 @@ class IsolateSpawnState {
bool errorsAreFatal,
Dart_Port onExit,
Dart_Port onError,
const char* debug_name);
const char* debug_name,
IsolateGroupSource* source);
IsolateSpawnState(Dart_Port parent_port,
const char* script_url,
const char* package_config,
@ -1155,7 +1252,8 @@ class IsolateSpawnState {
bool errorsAreFatal,
Dart_Port onExit,
Dart_Port onError,
const char* debug_name);
const char* debug_name,
IsolateGroupSource* source);
~IsolateSpawnState();
Isolate* isolate() const { return isolate_; }
@ -1180,6 +1278,8 @@ class IsolateSpawnState {
RawInstance* BuildArgs(Thread* thread);
RawInstance* BuildMessage(Thread* thread);
IsolateGroupSource* source() const { return source_; }
private:
Isolate* isolate_;
Dart_Port parent_port_;
@ -1192,6 +1292,7 @@ class IsolateSpawnState {
const char* class_name_;
const char* function_name_;
const char* debug_name_;
IsolateGroupSource* source_;
std::unique_ptr<Message> serialized_args_;
std::unique_ptr<Message> serialized_message_;

View file

@ -60,7 +60,7 @@ const int KernelIsolate::kListDependenciesTag = 5;
const int KernelIsolate::kNotifyIsolateShutdown = 6;
const char* KernelIsolate::kName = DART_KERNEL_ISOLATE_NAME;
Dart_IsolateCreateCallback KernelIsolate::create_callback_ = NULL;
Dart_IsolateGroupCreateCallback KernelIsolate::create_group_callback_ = NULL;
Monitor* KernelIsolate::monitor_ = new Monitor();
KernelIsolate::State KernelIsolate::state_ = KernelIsolate::kStopped;
Isolate* KernelIsolate::isolate_ = NULL;
@ -76,9 +76,9 @@ class RunKernelTask : public ThreadPool::Task {
char* error = NULL;
Isolate* isolate = NULL;
Dart_IsolateCreateCallback create_callback =
KernelIsolate::create_callback();
ASSERT(create_callback != NULL);
Dart_IsolateGroupCreateCallback create_group_callback =
KernelIsolate::create_group_callback();
ASSERT(create_group_callback != NULL);
// Note: these flags must match those passed to the VM during
// the app-jit training run (see //utils/kernel-service/BUILD.gn).
@ -94,8 +94,8 @@ class RunKernelTask : public ThreadPool::Task {
#endif
isolate = reinterpret_cast<Isolate*>(
create_callback(KernelIsolate::kName, KernelIsolate::kName, NULL, NULL,
&api_flags, NULL, &error));
create_group_callback(KernelIsolate::kName, KernelIsolate::kName, NULL,
NULL, &api_flags, NULL, &error));
if (isolate == NULL) {
if (FLAG_trace_kernel) {
OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Isolate creation error: %s\n",
@ -227,8 +227,8 @@ void KernelIsolate::Run() {
}
// Grab the isolate create callback here to avoid race conditions with tests
// that change this after Dart_Initialize returns.
create_callback_ = Isolate::CreateCallback();
if (create_callback_ == NULL) {
create_group_callback_ = Isolate::CreateGroupCallback();
if (create_group_callback_ == NULL) {
KernelIsolate::InitializingFailed();
return;
}

View file

@ -76,11 +76,11 @@ class KernelIsolate : public AllStatic {
static void FinishedExiting();
static void FinishedInitializing();
static void InitializingFailed();
static Dart_IsolateCreateCallback create_callback() {
return create_callback_;
static Dart_IsolateGroupCreateCallback create_group_callback() {
return create_group_callback_;
}
static Dart_IsolateCreateCallback create_callback_;
static Dart_IsolateGroupCreateCallback create_group_callback_;
static Monitor* monitor_;
enum State {
kStopped,

View file

@ -73,7 +73,7 @@ static RawArray* MakeServerControlMessage(const SendPort& sp,
}
const char* ServiceIsolate::kName = DART_VM_SERVICE_ISOLATE_NAME;
Dart_IsolateCreateCallback ServiceIsolate::create_callback_ = NULL;
Dart_IsolateGroupCreateCallback ServiceIsolate::create_group_callback_ = NULL;
Monitor* ServiceIsolate::monitor_ = new Monitor();
ServiceIsolate::State ServiceIsolate::state_ = ServiceIsolate::kStopped;
Isolate* ServiceIsolate::isolate_ = NULL;
@ -330,16 +330,15 @@ class RunServiceTask : public ThreadPool::Task {
char* error = NULL;
Isolate* isolate = NULL;
Dart_IsolateCreateCallback create_callback =
ServiceIsolate::create_callback();
ASSERT(create_callback != NULL);
const auto create_group_callback = ServiceIsolate::create_group_callback();
ASSERT(create_group_callback != NULL);
Dart_IsolateFlags api_flags;
Isolate::FlagsInitialize(&api_flags);
isolate = reinterpret_cast<Isolate*>(
create_callback(ServiceIsolate::kName, ServiceIsolate::kName, NULL,
NULL, &api_flags, NULL, &error));
create_group_callback(ServiceIsolate::kName, ServiceIsolate::kName,
NULL, NULL, &api_flags, NULL, &error));
if (isolate == NULL) {
if (FLAG_trace_service) {
OS::PrintErr(DART_VM_SERVICE_ISOLATE_NAME
@ -478,8 +477,8 @@ void ServiceIsolate::Run() {
}
// Grab the isolate create callback here to avoid race conditions with tests
// that change this after Dart_Initialize returns.
create_callback_ = Isolate::CreateCallback();
if (create_callback_ == NULL) {
create_group_callback_ = Isolate::CreateGroupCallback();
if (create_group_callback_ == NULL) {
ServiceIsolate::InitializingFailed();
return;
}

View file

@ -65,11 +65,11 @@ class ServiceIsolate : public AllStatic {
static void FinishedInitializing();
static void InitializingFailed();
static void MaybeMakeServiceIsolate(Isolate* isolate);
static Dart_IsolateCreateCallback create_callback() {
return create_callback_;
static Dart_IsolateGroupCreateCallback create_group_callback() {
return create_group_callback_;
}
static Dart_IsolateCreateCallback create_callback_;
static Dart_IsolateGroupCreateCallback create_group_callback_;
static Monitor* monitor_;
enum State {
kStopped,

View file

@ -37,9 +37,9 @@ const uint8_t* platform_strong_dill = kPlatformStrongDill;
const intptr_t platform_strong_dill_size = kPlatformStrongDillSize;
const uint8_t* TesterState::vm_snapshot_data = NULL;
Dart_IsolateCreateCallback TesterState::create_callback = NULL;
Dart_IsolateGroupCreateCallback TesterState::create_callback = NULL;
Dart_IsolateShutdownCallback TesterState::shutdown_callback = NULL;
Dart_IsolateCleanupCallback TesterState::cleanup_callback = NULL;
Dart_IsolateGroupCleanupCallback TesterState::group_cleanup_callback = nullptr;
const char** TesterState::argv = NULL;
int TesterState::argc = 0;
@ -107,17 +107,20 @@ Dart_Isolate TestCase::CreateIsolate(const uint8_t* data_buffer,
intptr_t len,
const uint8_t* instr_buffer,
const char* name,
void* data) {
void* group_data,
void* isolate_data) {
char* err;
Dart_IsolateFlags api_flags;
Isolate::FlagsInitialize(&api_flags);
Dart_Isolate isolate = NULL;
if (len == 0) {
isolate = Dart_CreateIsolate(name, NULL, data_buffer, instr_buffer, NULL,
NULL, &api_flags, data, &err);
isolate = Dart_CreateIsolateGroup(name, NULL, data_buffer, instr_buffer,
NULL, NULL, &api_flags, group_data,
isolate_data, &err);
} else {
isolate = Dart_CreateIsolateFromKernel(name, NULL, data_buffer, len,
&api_flags, data, &err);
isolate = Dart_CreateIsolateGroupFromKernel(name, NULL, data_buffer, len,
&api_flags, group_data,
isolate_data, &err);
}
if (isolate == NULL) {
OS::PrintErr("Creation of isolate failed '%s'\n", err);
@ -127,10 +130,13 @@ Dart_Isolate TestCase::CreateIsolate(const uint8_t* data_buffer,
return isolate;
}
Dart_Isolate TestCase::CreateTestIsolate(const char* name, void* data) {
Dart_Isolate TestCase::CreateTestIsolate(const char* name,
void* group_data,
void* isolate_data) {
return CreateIsolate(bin::core_isolate_snapshot_data,
0 /* Snapshots have length encoded within them. */,
bin::core_isolate_snapshot_instructions, name, data);
bin::core_isolate_snapshot_instructions, name,
group_data, isolate_data);
}
static const char* kPackageScheme = "package:";

View file

@ -232,9 +232,9 @@ extern const intptr_t platform_strong_dill_size;
class TesterState : public AllStatic {
public:
static const uint8_t* vm_snapshot_data;
static Dart_IsolateCreateCallback create_callback;
static Dart_IsolateGroupCreateCallback create_callback;
static Dart_IsolateShutdownCallback shutdown_callback;
static Dart_IsolateCleanupCallback cleanup_callback;
static Dart_IsolateGroupCleanupCallback group_cleanup_callback;
static const char** argv;
static int argc;
};
@ -358,8 +358,9 @@ class TestCase : TestCaseBase {
const char* name = NULL) {
return CreateIsolate(buffer, 0, NULL, name);
}
static Dart_Isolate CreateTestIsolate(const char* name = NULL,
void* data = NULL);
static Dart_Isolate CreateTestIsolate(const char* name = nullptr,
void* isolate_group_data = nullptr,
void* isolate_data = nullptr);
static Dart_Handle library_handler(Dart_LibraryTag tag,
Dart_Handle library,
Dart_Handle url);
@ -393,7 +394,8 @@ class TestCase : TestCaseBase {
intptr_t len,
const uint8_t* instr_buffer,
const char* name,
void* data = NULL);
void* group_data = nullptr,
void* isolate_data = nullptr);
static char* ValidateCompilationResult(Zone* zone,
Dart_KernelCompilationResult result,

View file

@ -0,0 +1,221 @@
diff --git a/runtime/dart_isolate.cc b/runtime/dart_isolate.cc
index 96ac6facd..b649ca834 100644
--- a/runtime/dart_isolate.cc
+++ b/runtime/dart_isolate.cc
@@ -163,7 +163,7 @@ bool DartIsolate::Initialize(Dart_Isolate dart_isolate, bool is_root_isolate) {
}
auto* isolate_data = static_cast<std::shared_ptr<DartIsolate>*>(
- Dart_IsolateData(dart_isolate));
+ Dart_IsolateGroupData(dart_isolate));
if (isolate_data->get() != this) {
return false;
}
@@ -174,7 +174,7 @@ bool DartIsolate::Initialize(Dart_Isolate dart_isolate, bool is_root_isolate) {
// We are entering a new scope (for the first time since initialization) and
// we want to restore the current scope to null when we exit out of this
// method. This balances the implicit Dart_EnterIsolate call made by
- // Dart_CreateIsolate (which calls the Initialize).
+ // Dart_CreateIsolateGroup (which calls the Initialize).
Dart_ExitIsolate();
tonic::DartIsolateScope scope(isolate());
@@ -636,8 +636,8 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate(
return service_isolate->isolate();
}
-// |Dart_IsolateCreateCallback|
-Dart_Isolate DartIsolate::DartIsolateCreateCallback(
+// |Dart_IsolateGroupCreateCallback|
+Dart_Isolate DartIsolate::DartIsolateGroupCreateCallback(
const char* advisory_script_uri,
const char* advisory_script_entrypoint,
const char* package_root,
@@ -720,14 +720,16 @@ DartIsolate::CreateDartVMAndEmbedderObjectPair(
}
// Create the Dart VM isolate and give it the embedder object as the baton.
- Dart_Isolate isolate = Dart_CreateIsolate(
+ Dart_Isolate isolate = Dart_CreateIsolateGroup(
advisory_script_uri, //
advisory_script_entrypoint, //
(*embedder_isolate)->GetIsolateSnapshot()->GetDataMapping(),
(*embedder_isolate)->GetIsolateSnapshot()->GetInstructionsMapping(),
(*embedder_isolate)->GetSharedSnapshot()->GetDataMapping(),
(*embedder_isolate)->GetSharedSnapshot()->GetInstructionsMapping(), flags,
- embedder_isolate.get(), error);
+ embedder_isolate.get(), // isolate_group_data
+ embedder_isolate.get(), // isolate_data
+ error);
if (isolate == nullptr) {
FML_DLOG(ERROR) << *error;
@@ -775,10 +777,10 @@ void DartIsolate::DartIsolateShutdownCallback(
isolate_group_data->get()->OnShutdownCallback();
}
-// |Dart_IsolateCleanupCallback|
-void DartIsolate::DartIsolateCleanupCallback(
- std::shared_ptr<DartIsolate>* isolate_data) {
- delete isolate_data;
+// |Dart_IsolateGroupCleanupCallback|
+void DartIsolate::DartIsolateGroupCleanupCallback(
+ std::shared_ptr<DartIsolate>* isolate_group_data) {
+ delete isolate_group_data;
}
fml::RefPtr<const DartSnapshot> DartIsolate::GetIsolateSnapshot() const {
diff --git a/runtime/dart_isolate.h b/runtime/dart_isolate.h
index 60412972a..453810b1b 100644
--- a/runtime/dart_isolate.h
+++ b/runtime/dart_isolate.h
@@ -156,8 +156,8 @@ class DartIsolate : public UIDartState {
void OnShutdownCallback();
- // |Dart_IsolateCreateCallback|
- static Dart_Isolate DartIsolateCreateCallback(
+ // |Dart_IsolateGroupCreateCallback|
+ static Dart_Isolate DartIsolateGroupCreateCallback(
const char* advisory_script_uri,
const char* advisory_script_entrypoint,
const char* package_root,
@@ -189,9 +189,9 @@ class DartIsolate : public UIDartState {
std::shared_ptr<DartIsolate>* isolate_group_data,
std::shared_ptr<DartIsolate>* isolate_data);
- // |Dart_IsolateCleanupCallback|
- static void DartIsolateCleanupCallback(
- std::shared_ptr<DartIsolate>* embedder_isolate);
+ // |Dart_IsolateGroupCleanupCallback|
+ static void DartIsolateGroupCleanupCallback(
+ std::shared_ptr<DartIsolate>* isolate_group_data);
FML_DISALLOW_COPY_AND_ASSIGN(DartIsolate);
};
diff --git a/runtime/dart_vm.cc b/runtime/dart_vm.cc
index 903e74b15..555d0c9ee 100644
--- a/runtime/dart_vm.cc
+++ b/runtime/dart_vm.cc
@@ -366,12 +366,13 @@ DartVM::DartVM(std::shared_ptr<const DartVMData> vm_data,
params.vm_snapshot_data = vm_data_->GetVMSnapshot().GetDataMapping();
params.vm_snapshot_instructions =
vm_data_->GetVMSnapshot().GetInstructionsMapping();
- params.create = reinterpret_cast<decltype(params.create)>(
- DartIsolate::DartIsolateCreateCallback);
- params.shutdown = reinterpret_cast<decltype(params.shutdown)>(
- DartIsolate::DartIsolateShutdownCallback);
- params.cleanup = reinterpret_cast<decltype(params.cleanup)>(
- DartIsolate::DartIsolateCleanupCallback);
+ params.create_group = reinterpret_cast<decltype(params.create_group)>(
+ DartIsolate::DartIsolateGroupCreateCallback);
+ params.shutdown_isolate =
+ reinterpret_cast<decltype(params.shutdown_isolate)>(
+ DartIsolate::DartIsolateShutdownCallback);
+ params.cleanup_group = reinterpret_cast<decltype(params.cleanup_group)>(
+ DartIsolate::DartIsolateGroupCleanupCallback);
params.thread_exit = ThreadExitCallback;
params.get_service_assets = GetVMServiceAssetsArchiveCallback;
params.entropy_source = dart::bin::GetEntropy;
diff --git a/shell/platform/fuchsia/dart/dart_component_controller.cc b/shell/platform/fuchsia/dart/dart_component_controller.cc
index 1c4f71050..c8e7cc5ab 100644
--- a/shell/platform/fuchsia/dart/dart_component_controller.cc
+++ b/shell/platform/fuchsia/dart/dart_component_controller.cc
@@ -324,12 +324,13 @@ bool DartComponentController::CreateIsolate(
auto state = new std::shared_ptr<tonic::DartState>(new tonic::DartState(
namespace_fd, [this](Dart_Handle result) { MessageEpilogue(result); }));
- isolate_ = Dart_CreateIsolate(
+ isolate_ = Dart_CreateIsolateGroup(
url_.c_str(), label_.c_str(), isolate_snapshot_data,
isolate_snapshot_instructions, shared_snapshot_data,
- shared_snapshot_instructions, nullptr /* flags */, state, &error);
+ shared_snapshot_instructions, nullptr /* flags */,
+ state /* isolate_group_data */, state /* isolate_data */, &error);
if (!isolate_) {
- FX_LOGF(ERROR, LOG_TAG, "Dart_CreateIsolate failed: %s", error);
+ FX_LOGF(ERROR, LOG_TAG, "Dart_CreateIsolateGroup failed: %s", error);
return false;
}
diff --git a/shell/platform/fuchsia/dart/dart_runner.cc b/shell/platform/fuchsia/dart/dart_runner.cc
index 200500d2c..b9ded3ac4 100644
--- a/shell/platform/fuchsia/dart/dart_runner.cc
+++ b/shell/platform/fuchsia/dart/dart_runner.cc
@@ -61,13 +61,13 @@ const char* kDartVMArgs[] = {
// clang-format on
};
-Dart_Isolate IsolateCreateCallback(const char* uri,
- const char* name,
- const char* package_root,
- const char* package_config,
- Dart_IsolateFlags* flags,
- void* callback_data,
- char** error) {
+Dart_Isolate IsolateGroupCreateCallback(const char* uri,
+ const char* name,
+ const char* package_root,
+ const char* package_config,
+ Dart_IsolateFlags* flags,
+ void* callback_data,
+ char** error) {
if (std::string(uri) == DART_VM_SERVICE_ISOLATE_NAME) {
#if defined(DART_PRODUCT)
*error = strdup("The service isolate is not implemented in product mode");
@@ -81,7 +81,7 @@ Dart_Isolate IsolateCreateCallback(const char* uri,
return NULL;
}
-void IsolateShutdownCallback(void* callback_data) {
+void IsolateShutdownCallback(void* isolate_group_data, void* isolate_data) {
// The service isolate (and maybe later the kernel isolate) doesn't have an
// async loop.
auto dispatcher = async_get_default_dispatcher();
@@ -92,8 +92,8 @@ void IsolateShutdownCallback(void* callback_data) {
}
}
-void IsolateCleanupCallback(void* callback_data) {
- delete static_cast<std::shared_ptr<tonic::DartState>*>(callback_data);
+void IsolateGroupCleanupCallback(void* isolate_group_data) {
+ delete static_cast<std::shared_ptr<tonic::DartState>*>(isolate_group_data);
}
void RunApplication(
@@ -167,9 +167,9 @@ DartRunner::DartRunner() : context_(sys::ComponentContext::Create()) {
params.vm_snapshot_data = vm_snapshot_data_.address();
params.vm_snapshot_instructions = vm_snapshot_instructions_.address();
#endif
- params.create = IsolateCreateCallback;
- params.shutdown = IsolateShutdownCallback;
- params.cleanup = IsolateCleanupCallback;
+ params.create_group = IsolateGroupCreateCallback;
+ params.shutdown_isolate = IsolateShutdownCallback;
+ params.cleanup_group = IsolateGroupCleanupCallback;
params.entropy_source = EntropySource;
#if !defined(DART_PRODUCT)
params.get_service_assets = GetVMServiceAssetsArchiveCallback;
diff --git a/shell/platform/fuchsia/dart/service_isolate.cc b/shell/platform/fuchsia/dart/service_isolate.cc
index 2e6eda265..5287d638f 100644
--- a/shell/platform/fuchsia/dart/service_isolate.cc
+++ b/shell/platform/fuchsia/dart/service_isolate.cc
@@ -123,14 +123,14 @@ Dart_Isolate CreateServiceIsolate(const char* uri,
#endif
auto state = new std::shared_ptr<tonic::DartState>(new tonic::DartState());
- Dart_Isolate isolate = Dart_CreateIsolate(
+ Dart_Isolate isolate = Dart_CreateIsolateGroup(
uri, DART_VM_SERVICE_ISOLATE_NAME, mapped_isolate_snapshot_data.address(),
mapped_isolate_snapshot_instructions.address(),
mapped_shared_snapshot_data.address(),
- mapped_shared_snapshot_instructions.address(), nullptr /* flags */, state,
- error);
+ mapped_shared_snapshot_instructions.address(), nullptr /* flags */,
+ state /* isolate_group_data */, state /* isolate_data */, error);
if (!isolate) {
- FX_LOGF(ERROR, LOG_TAG, "Dart_CreateIsolate failed: %s", *error);
+ FX_LOGF(ERROR, LOG_TAG, "Dart_CreateIsolateGroup failed: %s", *error);
return nullptr;
}