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>
164 lines
4.8 KiB
C++
164 lines
4.8 KiB
C++
// Copyright (c) 2012, 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.
|
|
|
|
#ifndef RUNTIME_BIN_ISOLATE_DATA_H_
|
|
#define RUNTIME_BIN_ISOLATE_DATA_H_
|
|
|
|
#include <memory>
|
|
#include <utility>
|
|
|
|
#include "include/dart_api.h"
|
|
#include "platform/assert.h"
|
|
#include "platform/globals.h"
|
|
|
|
namespace dart {
|
|
|
|
// Forward declaration.
|
|
template <typename T>
|
|
class MallocGrowableArray;
|
|
|
|
} // namespace dart
|
|
|
|
namespace dart {
|
|
namespace bin {
|
|
|
|
// Forward declaration.
|
|
class AppSnapshot;
|
|
class EventHandler;
|
|
class Loader;
|
|
|
|
// Data associated with every isolate group in the standalone VM
|
|
// embedding. This is used to free external resources for each isolate
|
|
// group when the isolate group shuts down.
|
|
class IsolateGroupData {
|
|
public:
|
|
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;
|
|
|
|
const std::shared_ptr<uint8_t>& kernel_buffer() const {
|
|
return kernel_buffer_;
|
|
}
|
|
|
|
intptr_t kernel_buffer_size() const { return kernel_buffer_size_; }
|
|
|
|
// 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 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);
|
|
kernel_buffer_ = std::shared_ptr<uint8_t>(buffer, free);
|
|
kernel_buffer_size_ = size;
|
|
}
|
|
|
|
// Associate the given kernel buffer with this IsolateGroupData and give it
|
|
// ownership of the buffer. The buffer is already owned by another
|
|
// IsolateGroupData.
|
|
void SetKernelBufferAlreadyOwned(std::shared_ptr<uint8_t> buffer,
|
|
intptr_t size) {
|
|
ASSERT(kernel_buffer_.get() == NULL);
|
|
kernel_buffer_ = std::move(buffer);
|
|
kernel_buffer_size_ = size;
|
|
}
|
|
|
|
const char* resolved_packages_config() const {
|
|
return resolved_packages_config_;
|
|
}
|
|
|
|
void set_resolved_packages_config(const char* packages_config) {
|
|
if (resolved_packages_config_ != NULL) {
|
|
free(resolved_packages_config_);
|
|
resolved_packages_config_ = NULL;
|
|
}
|
|
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 {
|
|
ASSERT(loader_ != NULL);
|
|
return loader_;
|
|
}
|
|
void set_loader(Loader* loader) {
|
|
ASSERT((loader_ == NULL) || (loader == NULL));
|
|
loader_ = loader;
|
|
}
|
|
|
|
const char* packages_file() const { return packages_file_; }
|
|
|
|
private:
|
|
IsolateGroupData* isolate_group_data_;
|
|
Loader* loader_;
|
|
char* packages_file_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(IsolateData);
|
|
};
|
|
|
|
} // namespace bin
|
|
} // namespace dart
|
|
|
|
#endif // RUNTIME_BIN_ISOLATE_DATA_H_
|