0425997b31
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>
104 lines
3.3 KiB
C++
104 lines
3.3 KiB
C++
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#include "include/dart_embedder_api.h"
|
|
|
|
#include "bin/dartutils.h"
|
|
#include "bin/eventhandler.h"
|
|
#include "bin/isolate_data.h"
|
|
#include "bin/thread.h"
|
|
#include "bin/utils.h"
|
|
#include "bin/vmservice_impl.h"
|
|
|
|
namespace dart {
|
|
namespace embedder {
|
|
|
|
static char* MallocFormatedString(const char* format, ...) {
|
|
va_list args;
|
|
va_start(args, format);
|
|
intptr_t len = vsnprintf(NULL, 0, format, args);
|
|
va_end(args);
|
|
|
|
char* buffer = reinterpret_cast<char*>(malloc(len + 1));
|
|
MSAN_UNPOISON(buffer, (len + 1));
|
|
va_list args2;
|
|
va_start(args2, format);
|
|
vsnprintf(buffer, (len + 1), format, args2);
|
|
va_end(args2);
|
|
return buffer;
|
|
}
|
|
|
|
bool InitOnce(char** error) {
|
|
if (!bin::DartUtils::SetOriginalWorkingDirectory()) {
|
|
bin::OSError err;
|
|
*error = MallocFormatedString("Error determining current directory: %s\n",
|
|
err.message());
|
|
return false;
|
|
}
|
|
bin::TimerUtils::InitOnce();
|
|
bin::EventHandler::Start();
|
|
return true;
|
|
}
|
|
|
|
Dart_Isolate CreateKernelServiceIsolate(const IsolateCreationData& data,
|
|
const uint8_t* buffer,
|
|
intptr_t buffer_size,
|
|
char** error) {
|
|
Dart_Isolate kernel_isolate = Dart_CreateIsolateGroupFromKernel(
|
|
data.script_uri, data.main, buffer, buffer_size, data.flags,
|
|
data.isolate_group_data, data.isolate_data, error);
|
|
if (kernel_isolate == nullptr) {
|
|
return nullptr;
|
|
}
|
|
|
|
Dart_EnterScope();
|
|
Dart_Handle result = Dart_LoadScriptFromKernel(buffer, buffer_size);
|
|
if (Dart_IsError(result)) {
|
|
*error = strdup(Dart_GetError(result));
|
|
Dart_ExitScope();
|
|
Dart_ShutdownIsolate();
|
|
return nullptr;
|
|
}
|
|
result = bin::DartUtils::PrepareForScriptLoading(/*is_service_isolate=*/false,
|
|
/*trace_loading=*/false);
|
|
Dart_ExitScope();
|
|
Dart_ExitIsolate();
|
|
return kernel_isolate;
|
|
}
|
|
|
|
Dart_Isolate CreateVmServiceIsolate(const IsolateCreationData& data,
|
|
const VmServiceConfiguration& config,
|
|
const uint8_t* kernel_buffer,
|
|
intptr_t kernel_buffer_size,
|
|
char** error) {
|
|
if (data.flags == nullptr) {
|
|
*error = strdup("Expected non-null flags");
|
|
return nullptr;
|
|
}
|
|
data.flags->load_vmservice_library = true;
|
|
|
|
Dart_Isolate service_isolate = Dart_CreateIsolateGroupFromKernel(
|
|
data.script_uri, data.main, kernel_buffer, kernel_buffer_size, data.flags,
|
|
data.isolate_group_data, data.isolate_data, error);
|
|
if (service_isolate == nullptr) {
|
|
return nullptr;
|
|
}
|
|
|
|
Dart_EnterScope();
|
|
// Load embedder specific bits and return.
|
|
if (!bin::VmService::Setup(config.ip, config.port, config.dev_mode,
|
|
config.disable_auth_codes, /*trace_loading=*/false,
|
|
config.deterministic)) {
|
|
*error = strdup(bin::VmService::GetErrorMessage());
|
|
return nullptr;
|
|
}
|
|
|
|
Dart_ExitScope();
|
|
Dart_ExitIsolate();
|
|
return service_isolate;
|
|
}
|
|
|
|
} // namespace embedder
|
|
} // namespace dart
|