[vm/concurrency] Make an IsolateGroup object which will contain group-specific resources

The isolate group object will keep a doubly-linked list of all isolates
within it's group. This will allow us to later on iterate all isolates
within a group for e.g. GC purposes.

The isolate group object will eventually hold the shared heap, thread registry
and other resources. This CL is only the start.

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

Change-Id: I32103bbb4830cd4f16665c4032d47dabdf3594dd
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108407
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Martin Kustermann 2019-07-11 12:13:43 +00:00 committed by commit-bot@chromium.org
parent 24725a8559
commit 4c5028d139
9 changed files with 206 additions and 147 deletions

View file

@ -20,9 +20,13 @@ def CheckMemcpy(filename):
content = fh.read()
match = re.search('\\bmemcpy\\b', content)
if match:
line_number = content[0:match.start()].count('\n') + 1
print("%s:%d: use of memcpy is forbidden" % (filename, line_number))
return 1
offset = match.start()
end_of_line = content.index('\n', offset)
# We allow explicit use of memcpy with an opt-in via NOLINT
if 'NOLINT' not in content[offset:end_of_line]:
line_number = content[0:match.start()].count('\n') + 1
print("%s:%d: use of memcpy is forbidden" % (filename, line_number))
return 1
return 0

View file

@ -129,7 +129,7 @@ class SpawnIsolateTask : public ThreadPool::Task {
}
void Run() override {
IsolateGroupSource* source = state_->source();
auto group = state_->isolate_group();
// The create isolate group call back is mandatory. If not provided we
// cannot spawn isolates.
@ -152,7 +152,7 @@ class SpawnIsolateTask : public ThreadPool::Task {
// Create a new isolate.
char* error = nullptr;
Isolate* isolate = nullptr;
if (source == nullptr || initialize_callback == nullptr) {
if (group == 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)(
@ -166,7 +166,7 @@ class SpawnIsolateTask : public ThreadPool::Task {
return;
}
isolate = CreateIsolateFromExistingSource(source, name, &error);
isolate = CreateWithinExistingIsolateGroup(group, name, &error);
parent_isolate_->DecrementSpawnCount();
parent_isolate_ = nullptr;
if (isolate == nullptr) {
@ -285,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, isolate->source()));
on_exit_port, on_error_port, utf8_debug_name, isolate->group()));
// Since this is a call to Isolate.spawn, copy the parent isolate's code.
state->isolate_flags()->copy_parent_code = true;
@ -396,12 +396,10 @@ 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, null_source));
on_error_port, utf8_debug_name, /*group=*/nullptr));
// If we were passed a value then override the default flags state for
// checked mode.
@ -470,7 +468,7 @@ static void ExternalTypedDataFinalizer(void* isolate_callback_data,
free(peer);
}
static intptr_t GetUint8SizeOrThrow(const Instance& instance) {
static intptr_t GetTypedDataSizeOrThrow(const Instance& instance) {
// From the Dart side we are guaranteed that the type of [instance] is a
// subtype of TypedData.
if (instance.IsTypedDataBase()) {
@ -503,19 +501,18 @@ DEFINE_NATIVE_ENTRY(TransferableTypedData_factory, 0, 2) {
UNREACHABLE();
}
Instance& instance = Instance::Handle();
unsigned long long total_bytes = 0;
const unsigned long kMaxBytes =
TypedData::MaxElements(kTypedDataUint8ArrayCid);
uint64_t total_bytes = 0;
const uint64_t kMaxBytes = TypedData::MaxElements(kTypedDataUint8ArrayCid);
for (intptr_t i = 0; i < array_length; i++) {
instance ^= array.At(i);
total_bytes += GetUint8SizeOrThrow(instance);
total_bytes += static_cast<uintptr_t>(GetTypedDataSizeOrThrow(instance));
if (total_bytes > kMaxBytes) {
const Array& error_args = Array::Handle(Array::New(3));
error_args.SetAt(0, array);
error_args.SetAt(1, String::Handle(String::New("data")));
error_args.SetAt(2,
String::Handle(String::NewFormatted(
"Aggregated list exceeds max size %ld", kMaxBytes)));
error_args.SetAt(
2, String::Handle(String::NewFormatted(
"Aggregated list exceeds max size %" Pu64 "", kMaxBytes)));
Exceptions::ThrowByType(Exceptions::kArgumentValue, error_args);
UNREACHABLE();
}
@ -539,11 +536,11 @@ DEFINE_NATIVE_ENTRY(TransferableTypedData_factory, 0, 2) {
void* source = typed_data.DataAddr(0);
// The memory does not overlap.
memcpy(data + offset, source, length_in_bytes);
memcpy(data + offset, source, length_in_bytes); // NOLINT
offset += length_in_bytes;
}
}
ASSERT(static_cast<unsigned long>(offset) == total_bytes);
ASSERT(static_cast<uintptr_t>(offset) == total_bytes);
return TransferableTypedData::New(data, total_bytes);
}

View file

@ -138,13 +138,13 @@ static constexpr dart::compiler::target::word ICData_owner_offset = 20;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 28;
static constexpr dart::compiler::target::word
ICData_receivers_static_type_offset = 16;
static constexpr dart::compiler::target::word Isolate_class_table_offset = 24;
static constexpr dart::compiler::target::word Isolate_current_tag_offset = 8;
static constexpr dart::compiler::target::word Isolate_default_tag_offset = 12;
static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 16;
static constexpr dart::compiler::target::word Isolate_object_store_offset = 20;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 44;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 4;
static constexpr dart::compiler::target::word Isolate_class_table_offset = 32;
static constexpr dart::compiler::target::word Isolate_current_tag_offset = 16;
static constexpr dart::compiler::target::word Isolate_default_tag_offset = 20;
static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 24;
static constexpr dart::compiler::target::word Isolate_object_store_offset = 28;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 52;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 12;
static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 16;
static constexpr dart::compiler::target::word
LinkedHashMap_deleted_keys_offset = 24;
@ -491,13 +491,13 @@ static constexpr dart::compiler::target::word ICData_owner_offset = 40;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 52;
static constexpr dart::compiler::target::word
ICData_receivers_static_type_offset = 32;
static constexpr dart::compiler::target::word Isolate_class_table_offset = 48;
static constexpr dart::compiler::target::word Isolate_current_tag_offset = 16;
static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24;
static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 32;
static constexpr dart::compiler::target::word Isolate_object_store_offset = 40;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 88;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 8;
static constexpr dart::compiler::target::word Isolate_class_table_offset = 64;
static constexpr dart::compiler::target::word Isolate_current_tag_offset = 32;
static constexpr dart::compiler::target::word Isolate_default_tag_offset = 40;
static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 48;
static constexpr dart::compiler::target::word Isolate_object_store_offset = 56;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 104;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 24;
static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32;
static constexpr dart::compiler::target::word
LinkedHashMap_deleted_keys_offset = 48;
@ -845,13 +845,13 @@ static constexpr dart::compiler::target::word ICData_owner_offset = 20;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 28;
static constexpr dart::compiler::target::word
ICData_receivers_static_type_offset = 16;
static constexpr dart::compiler::target::word Isolate_class_table_offset = 24;
static constexpr dart::compiler::target::word Isolate_current_tag_offset = 8;
static constexpr dart::compiler::target::word Isolate_default_tag_offset = 12;
static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 16;
static constexpr dart::compiler::target::word Isolate_object_store_offset = 20;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 44;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 4;
static constexpr dart::compiler::target::word Isolate_class_table_offset = 32;
static constexpr dart::compiler::target::word Isolate_current_tag_offset = 16;
static constexpr dart::compiler::target::word Isolate_default_tag_offset = 20;
static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 24;
static constexpr dart::compiler::target::word Isolate_object_store_offset = 28;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 52;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 12;
static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 16;
static constexpr dart::compiler::target::word
LinkedHashMap_deleted_keys_offset = 24;
@ -1194,13 +1194,13 @@ static constexpr dart::compiler::target::word ICData_owner_offset = 40;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 52;
static constexpr dart::compiler::target::word
ICData_receivers_static_type_offset = 32;
static constexpr dart::compiler::target::word Isolate_class_table_offset = 48;
static constexpr dart::compiler::target::word Isolate_current_tag_offset = 16;
static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24;
static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 32;
static constexpr dart::compiler::target::word Isolate_object_store_offset = 40;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 88;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 8;
static constexpr dart::compiler::target::word Isolate_class_table_offset = 64;
static constexpr dart::compiler::target::word Isolate_current_tag_offset = 32;
static constexpr dart::compiler::target::word Isolate_default_tag_offset = 40;
static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 48;
static constexpr dart::compiler::target::word Isolate_object_store_offset = 56;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 104;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 24;
static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32;
static constexpr dart::compiler::target::word
LinkedHashMap_deleted_keys_offset = 48;
@ -1551,13 +1551,13 @@ static constexpr dart::compiler::target::word ICData_owner_offset = 40;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 52;
static constexpr dart::compiler::target::word
ICData_receivers_static_type_offset = 32;
static constexpr dart::compiler::target::word Isolate_class_table_offset = 48;
static constexpr dart::compiler::target::word Isolate_current_tag_offset = 16;
static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24;
static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 32;
static constexpr dart::compiler::target::word Isolate_object_store_offset = 40;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 88;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 8;
static constexpr dart::compiler::target::word Isolate_class_table_offset = 64;
static constexpr dart::compiler::target::word Isolate_current_tag_offset = 32;
static constexpr dart::compiler::target::word Isolate_default_tag_offset = 40;
static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 48;
static constexpr dart::compiler::target::word Isolate_object_store_offset = 56;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 104;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 24;
static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32;
static constexpr dart::compiler::target::word
LinkedHashMap_deleted_keys_offset = 48;
@ -1835,13 +1835,13 @@ static constexpr dart::compiler::target::word ICData_owner_offset = 20;
static constexpr dart::compiler::target::word ICData_state_bits_offset = 28;
static constexpr dart::compiler::target::word
ICData_receivers_static_type_offset = 16;
static constexpr dart::compiler::target::word Isolate_class_table_offset = 24;
static constexpr dart::compiler::target::word Isolate_current_tag_offset = 8;
static constexpr dart::compiler::target::word Isolate_default_tag_offset = 12;
static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 16;
static constexpr dart::compiler::target::word Isolate_object_store_offset = 20;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 44;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 4;
static constexpr dart::compiler::target::word Isolate_class_table_offset = 32;
static constexpr dart::compiler::target::word Isolate_current_tag_offset = 16;
static constexpr dart::compiler::target::word Isolate_default_tag_offset = 20;
static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 24;
static constexpr dart::compiler::target::word Isolate_object_store_offset = 28;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 52;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 12;
static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 16;
static constexpr dart::compiler::target::word
LinkedHashMap_deleted_keys_offset = 24;

View file

@ -2,6 +2,9 @@
// 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 <memory>
#include <utility>
#include "vm/dart.h"
#include "vm/clustered_snapshot.h"
@ -234,7 +237,18 @@ char* Dart::Init(const uint8_t* vm_isolate_snapshot,
// Setup default flags for the VM isolate.
Dart_IsolateFlags api_flags;
Isolate::FlagsInitialize(&api_flags);
vm_isolate_ = Isolate::InitIsolate("vm-isolate", api_flags, is_vm_isolate);
// We make a fake [IsolateGroupSource] here, since the "vm-isolate" is not
// really an isolate itself - it acts more as a container for VM-global
// objects.
std::unique_ptr<IsolateGroupSource> source(
new IsolateGroupSource(nullptr, "vm-isolate", nullptr, nullptr, nullptr,
nullptr, nullptr, -1, api_flags));
auto group = new IsolateGroup(std::move(source), /*embedder_data=*/nullptr);
vm_isolate_ =
Isolate::InitIsolate("vm-isolate", group, api_flags, is_vm_isolate);
group->set_initial_spawn_successful();
// Verify assumptions about executing in the VM isolate.
ASSERT(vm_isolate_ == Isolate::Current());
ASSERT(vm_isolate_ == Thread::Current()->isolate());
@ -604,9 +618,11 @@ char* Dart::Cleanup() {
}
Isolate* Dart::CreateIsolate(const char* name_prefix,
const Dart_IsolateFlags& api_flags) {
const Dart_IsolateFlags& api_flags,
IsolateGroup* isolate_group) {
// Create a new isolate.
Isolate* isolate = Isolate::InitIsolate(name_prefix, api_flags);
Isolate* isolate =
Isolate::InitIsolate(name_prefix, isolate_group, api_flags);
return isolate;
}
@ -854,7 +870,7 @@ void Dart::RunShutdownCallback() {
Thread* thread = Thread::Current();
ASSERT(thread->execution_state() == Thread::kThreadInVM);
Isolate* isolate = thread->isolate();
void* isolate_group_data = isolate->source()->callback_data;
void* isolate_group_data = isolate->group()->embedder_data();
void* isolate_data = isolate->init_callback_data();
Dart_IsolateShutdownCallback callback = Isolate::ShutdownCallback();
if (callback != NULL) {

View file

@ -48,7 +48,8 @@ class Dart : public AllStatic {
static char* Cleanup();
static Isolate* CreateIsolate(const char* name_prefix,
const Dart_IsolateFlags& api_flags);
const Dart_IsolateFlags& api_flags,
IsolateGroup* isolate_group);
// Initialize an isolate, either from a snapshot, from a Kernel binary, or
// from SDK library sources. If the snapshot_buffer is non-NULL,

View file

@ -6,6 +6,7 @@
#include "include/dart_native_api.h"
#include <memory>
#include <utility>
#include "lib/stacktrace.h"
#include "platform/assert.h"
@ -1068,13 +1069,14 @@ ISOLATE_METRIC_LIST(ISOLATE_METRIC_API);
// --- Isolates ---
static Dart_Isolate CreateIsolate(IsolateGroupSource* source,
static Dart_Isolate CreateIsolate(IsolateGroup* group,
const char* name,
void* isolate_data,
char** error) {
CHECK_NO_ISOLATE(Isolate::Current());
Isolate* I = Dart::CreateIsolate(name, source->flags);
auto source = group->source();
Isolate* I = Dart::CreateIsolate(name, source->flags, group);
if (I == NULL) {
if (error != NULL) {
*error = strdup("Isolate creation failed");
@ -1111,8 +1113,6 @@ static Dart_Isolate CreateIsolate(IsolateGroupSource* source,
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
@ -1130,17 +1130,18 @@ static Dart_Isolate CreateIsolate(IsolateGroupSource* source,
return reinterpret_cast<Dart_Isolate>(NULL);
}
Isolate* CreateIsolateFromExistingSource(IsolateGroupSource* source,
const char* name,
char** error) {
Isolate* CreateWithinExistingIsolateGroup(IsolateGroup* group,
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));
CreateIsolate(group, name, /*isolate_data=*/nullptr, error));
if (isolate == nullptr) return nullptr;
RELEASE_ASSERT(isolate->source() == source);
auto source = group->source();
ASSERT(isolate->source() == source);
if (source->script_kernel_buffer != nullptr) {
#if defined(DART_PRECOMPILED_RUNTIME)
@ -1210,15 +1211,14 @@ Dart_CreateIsolateGroup(const char* script_uri,
}
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();
std::unique_ptr<IsolateGroupSource> source(new IsolateGroupSource(
script_uri, non_null_name, snapshot_data, snapshot_instructions,
shared_data, shared_instructions, nullptr, -1, *flags));
auto group = new IsolateGroup(std::move(source), isolate_group_data);
Dart_Isolate isolate =
CreateIsolate(source, non_null_name, isolate_data, error);
if (source->DecrementIsolateUsageCount()) {
delete source;
CreateIsolate(group, non_null_name, isolate_data, error);
if (isolate != nullptr) {
group->set_initial_spawn_successful();
}
return isolate;
}
@ -1241,14 +1241,14 @@ Dart_CreateIsolateGroupFromKernel(const char* script_uri,
}
const char* non_null_name = name == nullptr ? "isolate" : name;
auto source = new IsolateGroupSource(
std::unique_ptr<IsolateGroupSource> source(new IsolateGroupSource(
script_uri, non_null_name, nullptr, nullptr, nullptr, nullptr,
kernel_buffer, kernel_buffer_size, *flags, isolate_group_data);
source->IncrementIsolateUsageCount();
kernel_buffer, kernel_buffer_size, *flags));
auto group = new IsolateGroup(std::move(source), isolate_group_data);
Dart_Isolate isolate =
CreateIsolate(source, non_null_name, isolate_data, error);
if (source->DecrementIsolateUsageCount()) {
delete source;
CreateIsolate(group, non_null_name, isolate_data, error);
if (isolate != nullptr) {
group->set_initial_spawn_successful();
}
return isolate;
}
@ -1308,7 +1308,7 @@ DART_EXPORT void* Dart_CurrentIsolateGroupData() {
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
return isolate->source()->callback_data;
return isolate->group()->embedder_data();
}
DART_EXPORT void* Dart_IsolateGroupData(Dart_Isolate isolate) {
@ -1316,7 +1316,7 @@ DART_EXPORT void* Dart_IsolateGroupData(Dart_Isolate isolate) {
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;
return reinterpret_cast<Isolate*>(isolate)->group()->embedder_data();
}
DART_EXPORT Dart_Handle Dart_DebugName() {

View file

@ -365,9 +365,9 @@ class IsolateGroupSource;
// Creates a new isolate from [source] (which should come from an existing
// isolate).
Isolate* CreateIsolateFromExistingSource(IsolateGroupSource* source,
const char* name,
char** error);
Isolate* CreateWithinExistingIsolateGroup(IsolateGroup* group,
const char* name,
char** error);
} // namespace dart.

View file

@ -130,6 +130,43 @@ static RawInstance* DeserializeMessage(Thread* thread, Message* message) {
}
}
IsolateGroup::IsolateGroup(std::unique_ptr<IsolateGroupSource> source,
void* embedder_data)
: source_(std::move(source)),
embedder_data_(embedder_data),
isolates_monitor_(new Monitor()),
isolates_() {}
IsolateGroup::~IsolateGroup() {}
void IsolateGroup::RegisterIsolate(Isolate* isolate) {
MonitorLocker ml(isolates_monitor_.get());
isolates_.Append(isolate);
isolate_count_++;
}
void IsolateGroup::UnregisterIsolate(Isolate* isolate) {
bool is_last_isolate = false;
{
MonitorLocker ml(isolates_monitor_.get());
isolates_.Remove(isolate);
isolate_count_--;
is_last_isolate = isolate_count_ == 0;
}
if (is_last_isolate) {
// If the creation of the isolate group (or the first isolate within the
// isolate group) failed, we do not invoke the cleanup callback (the
// embedder is responsible for handling the creation error).
if (initial_spawn_successful_) {
auto group_shutdown_callback = Isolate::GroupCleanupCallback();
if (group_shutdown_callback != nullptr) {
group_shutdown_callback(embedder_data());
}
}
delete this;
}
}
bool IsolateVisitor::IsVMInternalIsolate(Isolate* isolate) const {
return Isolate::IsVMInternalIsolate(isolate);
}
@ -863,7 +900,8 @@ void BaseIsolate::AssertCurrentThreadIsMutator() const {
// TODO(srdjan): Some Isolate monitors can be shared. Replace their usage with
// that shared monitor.
Isolate::Isolate(const Dart_IsolateFlags& api_flags)
Isolate::Isolate(IsolateGroup* isolate_group,
const Dart_IsolateFlags& api_flags)
: BaseIsolate(),
current_tag_(UserTag::null()),
default_tag_(UserTag::null()),
@ -929,6 +967,9 @@ Isolate::Isolate(const Dart_IsolateFlags& api_flags)
}
NOT_IN_PRECOMPILED(optimizing_background_compiler_ =
new BackgroundCompiler(this));
isolate_group->RegisterIsolate(this);
isolate_group_ = isolate_group;
}
#undef REUSABLE_HANDLE_SCOPE_INIT
@ -998,6 +1039,11 @@ Isolate::~Isolate() {
}
delete[] embedder_entry_points_;
}
// Run isolate group specific cleanup function if the last isolate in an
// isolate group died.
isolate_group_->UnregisterIsolate(this);
isolate_group_ = nullptr;
}
void Isolate::InitVM() {
@ -1014,9 +1060,10 @@ void Isolate::InitVM() {
}
Isolate* Isolate::InitIsolate(const char* name_prefix,
IsolateGroup* isolate_group,
const Dart_IsolateFlags& api_flags,
bool is_vm_isolate) {
Isolate* result = new Isolate(api_flags);
Isolate* result = new Isolate(isolate_group, api_flags);
ASSERT(result != nullptr);
#if !defined(PRODUCT)
@ -1112,6 +1159,7 @@ Isolate* Isolate::InitIsolate(const char* name_prefix,
if (ServiceIsolate::IsServiceIsolate(result)) {
ServiceIsolate::SetServiceIsolate(nullptr);
}
delete result;
return nullptr;
}
@ -1904,25 +1952,11 @@ void Isolate::Shutdown() {
// as we are shutting down the isolate.
Thread::ExitIsolate();
// 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.
// Run isolate specific cleanup function for all non "vm-isolate's.
if (Dart::vm_isolate() != this) {
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;
cleanup(isolate_group_->embedder_data(), init_callback_data());
}
}
}
@ -2891,6 +2925,7 @@ void Isolate::UnscheduleThread(Thread* thread,
// so we create a MonitorLocker object which does not do any
// no_safepoint_scope_depth increments/decrements.
MonitorLocker ml(threads_lock(), false);
if (is_mutator) {
if (thread->sticky_error() != Error::null()) {
ASSERT(sticky_error_ == Error::null());
@ -2954,7 +2989,7 @@ IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port,
Dart_Port on_exit_port,
Dart_Port on_error_port,
const char* debug_name,
IsolateGroupSource* source)
IsolateGroup* isolate_group)
: isolate_(nullptr),
parent_port_(parent_port),
origin_id_(origin_id),
@ -2966,7 +3001,7 @@ IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port,
class_name_(nullptr),
function_name_(nullptr),
debug_name_(debug_name),
source_(source),
isolate_group_(isolate_group),
serialized_args_(nullptr),
serialized_message_(message_buffer->StealMessage()),
paused_(paused),
@ -2999,7 +3034,7 @@ IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port,
Dart_Port on_exit_port,
Dart_Port on_error_port,
const char* debug_name,
IsolateGroupSource* source)
IsolateGroup* group)
: isolate_(nullptr),
parent_port_(parent_port),
origin_id_(ILLEGAL_PORT),
@ -3011,7 +3046,7 @@ IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port,
class_name_(nullptr),
function_name_(nullptr),
debug_name_(debug_name),
source_(source),
isolate_group_(group),
serialized_args_(args_buffer->StealMessage()),
serialized_message_(message_buffer->StealMessage()),
isolate_flags_(),

View file

@ -23,6 +23,7 @@
#include "vm/growable_array.h"
#include "vm/handles.h"
#include "vm/heap/verifier.h"
#include "vm/intrusive_dlist.h"
#include "vm/megamorphic_cache_table.h"
#include "vm/metrics.h"
#include "vm/os_thread.h"
@ -181,8 +182,7 @@ class IsolateGroupSource {
const uint8_t* shared_instructions,
const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size,
Dart_IsolateFlags flags,
void* callback_data)
Dart_IsolateFlags flags)
: script_uri(script_uri),
name(strdup(name)),
snapshot_data(snapshot_data),
@ -192,7 +192,6 @@ class IsolateGroupSource {
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); }
@ -208,26 +207,36 @@ class IsolateGroupSource {
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 {
// Represents an isolate group and is shared among all isolates within a group.
class IsolateGroup {
public:
IsolateGroup(std::unique_ptr<IsolateGroupSource> source, void* embedder_data);
~IsolateGroup();
IsolateGroupSource* source() const { return source_.get(); }
void* embedder_data() const { return embedder_data_; }
void set_initial_spawn_successful() { initial_spawn_successful_ = true; }
void RegisterIsolate(Isolate* isolate);
void UnregisterIsolate(Isolate* isolate);
private:
std::unique_ptr<IsolateGroupSource> source_;
void* embedder_data_ = nullptr;
std::unique_ptr<Monitor> isolates_monitor_;
IntrusiveDList<Isolate> isolates_;
intptr_t isolate_count_ = 0;
bool initial_spawn_successful_ = false;
};
class Isolate : public BaseIsolate, public IntrusiveDListEntry<Isolate> {
public:
// Keep both these enums in sync with isolate_patch.dart.
// The different Isolate API message types.
@ -311,12 +320,8 @@ class Isolate : public BaseIsolate {
message_notify_callback_ = value;
}
IsolateGroupSource* source() const { return source_; }
void set_source(IsolateGroupSource* source) {
source->IncrementIsolateUsageCount();
source_ = source;
}
IsolateGroupSource* source() const { return isolate_group_->source(); }
IsolateGroup* group() const { return isolate_group_; }
bool HasPendingMessages();
@ -913,10 +918,11 @@ class Isolate : public BaseIsolate {
friend class Dart; // Init, InitOnce, Shutdown.
friend class IsolateKillerVisitor; // Kill().
explicit Isolate(const Dart_IsolateFlags& api_flags);
Isolate(IsolateGroup* group, const Dart_IsolateFlags& api_flags);
static void InitVM();
static Isolate* InitIsolate(const char* name_prefix,
IsolateGroup* isolate_group,
const Dart_IsolateFlags& api_flags,
bool is_vm_isolate = false);
@ -984,6 +990,7 @@ class Isolate : public BaseIsolate {
MarkingStack* marking_stack_ = nullptr;
MarkingStack* deferred_marking_stack_ = nullptr;
Heap* heap_ = nullptr;
IsolateGroup* isolate_group_ = nullptr;
#define ISOLATE_FLAG_BITS(V) \
V(ErrorsFatal) \
@ -1167,7 +1174,6 @@ 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;
@ -1242,7 +1248,7 @@ class IsolateSpawnState {
Dart_Port onExit,
Dart_Port onError,
const char* debug_name,
IsolateGroupSource* source);
IsolateGroup* group);
IsolateSpawnState(Dart_Port parent_port,
const char* script_url,
const char* package_config,
@ -1253,7 +1259,7 @@ class IsolateSpawnState {
Dart_Port onExit,
Dart_Port onError,
const char* debug_name,
IsolateGroupSource* source);
IsolateGroup* group);
~IsolateSpawnState();
Isolate* isolate() const { return isolate_; }
@ -1278,7 +1284,7 @@ class IsolateSpawnState {
RawInstance* BuildArgs(Thread* thread);
RawInstance* BuildMessage(Thread* thread);
IsolateGroupSource* source() const { return source_; }
IsolateGroup* isolate_group() const { return isolate_group_; }
private:
Isolate* isolate_;
@ -1292,7 +1298,7 @@ class IsolateSpawnState {
const char* class_name_;
const char* function_name_;
const char* debug_name_;
IsolateGroupSource* source_;
IsolateGroup* isolate_group_;
std::unique_ptr<Message> serialized_args_;
std::unique_ptr<Message> serialized_message_;