[vm] Experimental ability to spawn isolate from kernel blob in memory

TEST=runtime/tests/vm/dart/spawn_uri_from_kernel_blob_test.dart

Change-Id: Ieb327f0350d5d8ea1d344c64aa3dd217125da5fe
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/232682
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Alexander Markov
2022-02-23 16:55:52 +00:00
committed by Commit Bot
parent 774cafe41d
commit 211da364be
15 changed files with 401 additions and 25 deletions
+94 -6
View File
@@ -9,6 +9,7 @@
#include "bin/error_exit.h"
#include "bin/exe_utils.h"
#include "bin/file.h"
#include "bin/lockers.h"
#include "bin/platform.h"
#include "bin/utils.h"
#include "include/dart_tools_api.h"
@@ -65,8 +66,9 @@ DFE::DFE()
use_incremental_compiler_(false),
frontend_filename_(nullptr),
application_kernel_buffer_(nullptr),
application_kernel_buffer_size_(0) {
}
application_kernel_buffer_size_(0),
kernel_blobs_(&SimpleHashMap::SameStringValue, 4),
kernel_blobs_lock_() {}
DFE::~DFE() {
if (frontend_filename_ != nullptr) {
@@ -77,6 +79,9 @@ DFE::~DFE() {
free(application_kernel_buffer_);
application_kernel_buffer_ = nullptr;
application_kernel_buffer_size_ = 0;
kernel_blobs_.Clear(
[](void* value) { delete reinterpret_cast<KernelBlob*>(value); });
}
void DFE::Init() {
@@ -247,14 +252,19 @@ void DFE::CompileAndReadScript(const char* script_uri,
void DFE::ReadScript(const char* script_uri,
uint8_t** kernel_buffer,
intptr_t* kernel_buffer_size,
bool decode_uri) const {
bool decode_uri,
std::shared_ptr<uint8_t>* kernel_blob_ptr) {
int64_t start = Dart_TimelineGetMicros();
if (!TryReadKernelFile(script_uri, kernel_buffer, kernel_buffer_size,
decode_uri)) {
decode_uri, kernel_blob_ptr)) {
return;
}
if (!Dart_IsKernel(*kernel_buffer, *kernel_buffer_size)) {
free(*kernel_buffer);
if (kernel_blob_ptr != nullptr && *kernel_blob_ptr) {
*kernel_blob_ptr = nullptr;
} else {
free(*kernel_buffer);
}
*kernel_buffer = nullptr;
*kernel_buffer_size = -1;
}
@@ -438,10 +448,21 @@ static bool TryReadKernelListBuffer(const char* script_uri,
bool DFE::TryReadKernelFile(const char* script_uri,
uint8_t** kernel_ir,
intptr_t* kernel_ir_size,
bool decode_uri) {
bool decode_uri,
std::shared_ptr<uint8_t>* kernel_blob_ptr) {
*kernel_ir = nullptr;
*kernel_ir_size = -1;
if (decode_uri && kernel_blob_ptr != nullptr) {
*kernel_blob_ptr = TryFindKernelBlob(script_uri, kernel_ir_size);
if (*kernel_blob_ptr) {
*kernel_ir = kernel_blob_ptr->get();
ASSERT(DartUtils::SniffForMagicNumber(*kernel_ir, *kernel_ir_size) ==
DartUtils::kKernelMagicNumber);
return true;
}
}
uint8_t* buffer;
if (!TryReadFile(script_uri, &buffer, kernel_ir_size, decode_uri)) {
return false;
@@ -456,5 +477,72 @@ bool DFE::TryReadKernelFile(const char* script_uri,
return TryReadSimpleKernelBuffer(buffer, kernel_ir, kernel_ir_size);
}
const char* DFE::RegisterKernelBlob(const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size) {
ASSERT(DartUtils::SniffForMagicNumber(kernel_buffer, kernel_buffer_size) ==
DartUtils::kKernelMagicNumber);
uint8_t* buffer_copy = reinterpret_cast<uint8_t*>(malloc(kernel_buffer_size));
if (buffer_copy == nullptr) {
return nullptr;
}
memmove(buffer_copy, kernel_buffer, kernel_buffer_size);
MutexLocker ml(&kernel_blobs_lock_);
++kernel_blob_counter_;
char* uri =
Utils::SCreate("dart-kernel-blob://blob%" Pd, kernel_blob_counter_);
KernelBlob* blob = new KernelBlob(uri, buffer_copy, kernel_buffer_size);
const uint32_t hash = SimpleHashMap::StringHash(uri);
SimpleHashMap::Entry* entry =
kernel_blobs_.Lookup(uri, hash, /*insert=*/true);
ASSERT(entry != nullptr);
ASSERT(entry->value == nullptr);
entry->value = blob;
return uri;
}
std::shared_ptr<uint8_t> DFE::TryFindKernelBlob(const char* uri,
intptr_t* kernel_length) {
*kernel_length = -1;
MutexLocker ml(&kernel_blobs_lock_);
if (kernel_blob_counter_ == 0) {
return nullptr;
}
// This const_cast is safe as this 'key' is only used to find entry, not add.
void* key = const_cast<char*>(uri);
const uint32_t hash = SimpleHashMap::StringHash(uri);
SimpleHashMap::Entry* entry =
kernel_blobs_.Lookup(key, hash, /*insert=*/false);
if (entry == nullptr) {
return nullptr;
}
KernelBlob* blob = reinterpret_cast<KernelBlob*>(entry->value);
*kernel_length = blob->size();
return blob->buffer();
}
void DFE::UnregisterKernelBlob(const char* uri) {
MutexLocker ml(&kernel_blobs_lock_);
// This const_cast is safe as this 'key' is only used to find entry, not add.
void* key = const_cast<char*>(uri);
const uint32_t hash = SimpleHashMap::StringHash(uri);
SimpleHashMap::Entry* entry =
kernel_blobs_.Lookup(key, hash, /*insert=*/false);
if (entry == nullptr) {
return;
}
KernelBlob* blob = reinterpret_cast<KernelBlob*>(entry->value);
entry->value = nullptr;
kernel_blobs_.Remove(key, hash);
delete blob;
}
} // namespace bin
} // namespace dart
+61 -10
View File
@@ -7,10 +7,12 @@
#include <memory>
#include "bin/thread.h"
#include "include/dart_api.h"
#include "include/dart_native_api.h"
#include "platform/assert.h"
#include "platform/globals.h"
#include "platform/hashmap.h"
#include "platform/utils.h"
namespace dart {
@@ -102,23 +104,34 @@ class DFE {
// Reads the script kernel file if specified 'script_uri' is a kernel file.
// Returns an in memory kernel representation of the specified script is a
// valid kernel file, false otherwise.
// valid kernel file, sets 'kernel_buffer' to nullptr otherwise.
//
// If 'kernel_blob_ptr' is not nullptr, then this function can also
// read kernel blobs. In such case it sets 'kernel_blob_ptr'
// to a shared pointer which owns the kernel buffer.
// Othwerise, the caller is responsible for free()ing 'kernel_buffer'.
void ReadScript(const char* script_uri,
uint8_t** kernel_buffer,
intptr_t* kernel_buffer_size,
bool decode_uri = true) const;
bool decode_uri = true,
std::shared_ptr<uint8_t>* kernel_blob_ptr = nullptr);
bool KernelServiceDillAvailable() const;
// Tries to read [script_uri] as a Kernel IR file.
// Returns `true` if successful and sets [kernel_file] and [kernel_length]
// Tries to read 'script_uri' as a Kernel IR file.
// Returns `true` if successful and sets 'kernel_buffer' and 'kernel_length'
// to be the kernel IR contents.
// The caller is responsible for free()ing [kernel_file] if `true`
// was returned.
static bool TryReadKernelFile(const char* script_uri,
uint8_t** kernel_buffer,
intptr_t* kernel_buffer_size,
bool decode_uri = true);
//
// If 'kernel_blob_ptr' is not nullptr, then this function can also
// read kernel blobs. In such case it sets 'kernel_blob_ptr'
// to a shared pointer which owns the kernel buffer.
// Othwerise, the caller is responsible for free()ing 'kernel_buffer'
// if `true` was returned.
bool TryReadKernelFile(const char* script_uri,
uint8_t** kernel_buffer,
intptr_t* kernel_buffer_size,
bool decode_uri = true,
std::shared_ptr<uint8_t>* kernel_blob_ptr = nullptr);
// We distinguish between "intent to use Dart frontend" vs "can actually
// use Dart frontend". The method UseDartFrontend tells us about the
@@ -131,6 +144,22 @@ class DFE {
void LoadKernelService(const uint8_t** kernel_service_buffer,
intptr_t* kernel_service_buffer_size);
// Registers given kernel blob and returns blob URI which
// can be used in TryReadKernelFile later to load the given kernel.
// Data from [kernel_buffer] is copied, it doesn't need to stay alive.
// Returns NULL if failed to allocate memory.
const char* RegisterKernelBlob(const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size);
// Looks for kernel blob using the given [uri].
// Returns non-null pointer to the kernel blob if successful and
// sets [kernel_length].
std::shared_ptr<uint8_t> TryFindKernelBlob(const char* uri,
intptr_t* kernel_length);
// Unregisters kernel blob with given URI.
void UnregisterKernelBlob(const char* uri);
private:
bool use_dfe_;
bool use_incremental_compiler_;
@@ -142,11 +171,33 @@ class DFE {
uint8_t* application_kernel_buffer_;
intptr_t application_kernel_buffer_size_;
// Registry of kernel blobs. Maps URI (char *) to KernelBlob.
SimpleHashMap kernel_blobs_;
intptr_t kernel_blob_counter_ = 0;
Mutex kernel_blobs_lock_;
void InitKernelServiceAndPlatformDills();
DISALLOW_COPY_AND_ASSIGN(DFE);
};
class KernelBlob {
public:
// Takes ownership over [uri] and [buffer].
KernelBlob(char* uri, uint8_t* buffer, intptr_t size)
: uri_(uri, std::free), buffer_(buffer, std::free), size_(size) {}
std::shared_ptr<uint8_t> buffer() { return buffer_; }
intptr_t size() const { return size_; }
private:
Utils::CStringUniquePtr uri_;
std::shared_ptr<uint8_t> buffer_;
const intptr_t size_;
DISALLOW_COPY_AND_ASSIGN(KernelBlob);
};
class PathSanitizer {
public:
explicit PathSanitizer(const char* path);
+2 -2
View File
@@ -83,8 +83,8 @@ Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
if (tag == Dart_kKernelTag) {
uint8_t* kernel_buffer = NULL;
intptr_t kernel_buffer_size = 0;
if (!DFE::TryReadKernelFile(url_string, &kernel_buffer,
&kernel_buffer_size)) {
if (!dfe.TryReadKernelFile(url_string, &kernel_buffer,
&kernel_buffer_size)) {
return DartUtils::NewError("'%s' is not a kernel file", url_string);
}
result = Dart_NewExternalTypedData(Dart_TypedData_kUint8, kernel_buffer,
+21 -6
View File
@@ -689,7 +689,7 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
int64_t start = Dart_TimelineGetMicros();
ASSERT(script_uri != NULL);
uint8_t* kernel_buffer = NULL;
std::shared_ptr<uint8_t> parent_kernel_buffer;
std::shared_ptr<uint8_t> kernel_buffer_ptr;
intptr_t kernel_buffer_size = 0;
AppSnapshot* app_snapshot = NULL;
@@ -750,13 +750,14 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
if (flags->copy_parent_code && callback_data != nullptr) {
auto parent_isolate_group_data =
reinterpret_cast<IsolateData*>(callback_data)->isolate_group_data();
parent_kernel_buffer = parent_isolate_group_data->kernel_buffer();
kernel_buffer = parent_kernel_buffer.get();
kernel_buffer_ptr = parent_isolate_group_data->kernel_buffer();
kernel_buffer = kernel_buffer_ptr.get();
kernel_buffer_size = parent_isolate_group_data->kernel_buffer_size();
}
if (kernel_buffer == NULL && !isolate_run_app_snapshot) {
dfe.ReadScript(script_uri, &kernel_buffer, &kernel_buffer_size);
dfe.ReadScript(script_uri, &kernel_buffer, &kernel_buffer_size,
/*decode_uri=*/true, &kernel_buffer_ptr);
}
PathSanitizer script_uri_sanitizer(script_uri);
PathSanitizer packages_config_sanitizer(packages_config);
@@ -770,9 +771,9 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
auto isolate_group_data = new IsolateGroupData(
script_uri, packages_config, app_snapshot, isolate_run_app_snapshot);
if (kernel_buffer != NULL) {
if (parent_kernel_buffer) {
if (kernel_buffer_ptr) {
isolate_group_data->SetKernelBufferAlreadyOwned(
std::move(parent_kernel_buffer), kernel_buffer_size);
std::move(kernel_buffer_ptr), kernel_buffer_size);
} else {
isolate_group_data->SetKernelBufferNewlyOwned(kernel_buffer,
kernel_buffer_size);
@@ -888,6 +889,16 @@ static Dart_Isolate CreateIsolateGroupAndSetup(const char* script_uri,
error, &exit_code);
}
#if !defined(DART_PRECOMPILED_RUNTIME)
static const char* RegisterKernelBlob(const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size) {
return dfe.RegisterKernelBlob(kernel_buffer, kernel_buffer_size);
}
static void UnregisterKernelBlob(const char* kernel_blob_uri) {
dfe.UnregisterKernelBlob(kernel_blob_uri);
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
static void OnIsolateShutdown(void* isolate_group_data, void* isolate_data) {
Dart_EnterScope();
Dart_Handle sticky_error = Dart_GetStickyError();
@@ -1332,6 +1343,10 @@ void main(int argc, char** argv) {
#if !defined(DART_PRECOMPILED_RUNTIME)
init_params.start_kernel_isolate =
dfe.UseDartFrontend() && dfe.CanUseDartFrontend();
if (init_params.start_kernel_isolate) {
init_params.register_kernel_blob = RegisterKernelBlob;
init_params.unregister_kernel_blob = UnregisterKernelBlob;
}
#else
init_params.start_kernel_isolate = false;
#endif
+40
View File
@@ -919,6 +919,36 @@ typedef void (*Dart_PostTaskCallback)(void* post_task_data,
*/
DART_EXPORT void Dart_RunTask(Dart_Task task);
/**
* Optional callback provided by the embedder that is used by the VM to
* implement registration of kernel blobs for the subsequent Isolate.spawnUri
* If no callback is provided, the registration of kernel blobs will throw
* an error.
*
* \param kernel_buffer A buffer which contains a kernel program. Callback
* should copy the contents of `kernel_buffer` as
* it may be freed immediately after registration.
* \param kernel_buffer_size The size of `kernel_buffer`.
*
* \return A C string representing URI which can be later used
* to spawn a new isolate. This C String should be scope allocated
* or owned by the embedder.
* Returns NULL if embedder runs out of memory.
*/
typedef const char* (*Dart_RegisterKernelBlobCallback)(
const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size);
/**
* Optional callback provided by the embedder that is used by the VM to
* unregister kernel blobs.
* If no callback is provided, the unregistration of kernel blobs will throw
* an error.
*
* \param kernel_blob_uri URI of the kernel blob to unregister.
*/
typedef void (*Dart_UnregisterKernelBlobCallback)(const char* kernel_blob_uri);
/**
* Describes how to initialize the VM. Used with Dart_Initialize.
*/
@@ -1003,6 +1033,16 @@ typedef struct {
Dart_PostTaskCallback post_task;
void* post_task_data;
/**
* Kernel blob registration callback function. See Dart_RegisterKernelBlobCallback.
*/
Dart_RegisterKernelBlobCallback register_kernel_blob;
/**
* Kernel blob unregistration callback function. See Dart_UnregisterKernelBlobCallback.
*/
Dart_UnregisterKernelBlobCallback unregister_kernel_blob;
} Dart_InitializeParams;
/**
+56
View File
@@ -1071,6 +1071,62 @@ DEFINE_NATIVE_ENTRY(Isolate_getCurrentRootUriStr, 0, 0) {
return root_lib.url();
}
DEFINE_NATIVE_ENTRY(Isolate_registerKernelBlob, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(TypedData, kernel_blob,
arguments->NativeArgAt(0));
auto register_kernel_blob_callback = Isolate::RegisterKernelBlobCallback();
if (register_kernel_blob_callback == nullptr) {
const auto& error =
String::Handle(zone, String::New("Registration of kernel blobs is not "
"supported by this Dart embedder.\n"));
Exceptions::ThrowArgumentError(error);
UNREACHABLE();
}
bool is_kernel = false;
{
NoSafepointScope no_safepoint;
is_kernel =
Dart_IsKernel(reinterpret_cast<uint8_t*>(kernel_blob.DataAddr(0)),
kernel_blob.LengthInBytes());
}
if (!is_kernel) {
const auto& error = String::Handle(
zone, String::New("kernelBlob doesn\'t contain a valid kernel.\n"));
Exceptions::ThrowArgumentError(error);
UNREACHABLE();
}
const char* uri = nullptr;
{
NoSafepointScope no_safepoint;
uri = register_kernel_blob_callback(
reinterpret_cast<uint8_t*>(kernel_blob.DataAddr(0)),
kernel_blob.LengthInBytes());
}
if (uri == nullptr) {
const Instance& exception = Instance::Handle(
thread->isolate_group()->object_store()->out_of_memory());
Exceptions::Throw(thread, exception);
UNREACHABLE();
}
return String::New(uri);
}
DEFINE_NATIVE_ENTRY(Isolate_unregisterKernelBlob, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(String, kernel_blob_uri,
arguments->NativeArgAt(0));
auto unregister_kernel_blob_callback =
Isolate::UnregisterKernelBlobCallback();
if (unregister_kernel_blob_callback == nullptr) {
const auto& error =
String::Handle(zone, String::New("Registration of kernel blobs is not "
"supported by this Dart embedder.\n"));
Exceptions::ThrowArgumentError(error);
UNREACHABLE();
}
unregister_kernel_blob_callback(kernel_blob_uri.ToCString());
return Object::null();
}
DEFINE_NATIVE_ENTRY(Isolate_sendOOB, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(SendPort, port, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Array, msg, arguments->NativeArgAt(1));
+1 -1
View File
@@ -23,7 +23,7 @@ class SimpleHashMap {
static bool SamePointerValue(void* key1, void* key2) { return key1 == key2; }
static uint32_t StringHash(char* key) {
static uint32_t StringHash(const char* key) {
uint32_t hash_ = 0;
if (key == NULL) return hash_;
int len = strlen(key);
@@ -0,0 +1,11 @@
// Copyright (c) 2022, 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.
import "dart:convert";
import "dart:isolate";
main(List<String> args, SendPort replyPort) {
final String encoded = base64.encode(args[0].codeUnits);
replyPort.send(String.fromCharCodes(base64.decode(encoded)));
}
@@ -0,0 +1,63 @@
// Copyright (c) 2020, 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.
// OtherResources=spawn_uri_from_kernel_blob_script.dart
// Test for Isolate.createUriForKernelBlob and subsequent Isolate.spawnUri.
import 'dart:io' show Platform;
import 'dart:isolate' show Isolate, ReceivePort;
import 'dart:typed_data' show Uint8List;
import "package:expect/expect.dart";
import 'package:front_end/src/api_unstable/vm.dart'
show CompilerOptions, DiagnosticMessage, kernelForProgram, NnbdMode;
import 'package:kernel/kernel.dart';
import 'package:kernel/target/targets.dart';
import 'package:vm/target/vm.dart' show VmTarget;
import 'snapshot_test_helper.dart';
main() async {
final sourceUri =
Platform.script.resolve('spawn_uri_from_kernel_blob_script.dart');
final options = new CompilerOptions()
..target = VmTarget(TargetFlags())
..additionalDills = <Uri>[Uri.file(platformDill)]
..environmentDefines = {}
..nnbdMode = hasSoundNullSafety ? NnbdMode.Strong : NnbdMode.Weak
..onDiagnostic = (DiagnosticMessage message) {
Expect.fail(
"Compilation error: ${message.plainTextFormatted.join('\n')}");
};
final Component component =
(await kernelForProgram(sourceUri, options))!.component!;
final kernelBlob = writeComponentToBytes(component) as Uint8List;
final kernelBlobUri =
(Isolate.current as dynamic).createUriForKernelBlob(kernelBlob);
print('URI: $kernelBlobUri');
for (int i = 0; i < 2; ++i) {
final receivePort = ReceivePort();
receivePort.listen((message) {
Expect.equals(message, 'Hello');
print('ok');
receivePort.close();
});
await Isolate.spawnUri(kernelBlobUri, ['Hello'], receivePort.sendPort);
}
(Isolate.current as dynamic).unregisterKernelBlobUri(kernelBlobUri);
try {
await Isolate.spawnUri(kernelBlobUri, ['Hello'], null);
Expect.fail(
"Isolate.spawnUri didn't complete with error after unregisterKernelBlobUri");
} catch (e) {
print('Got exception: $e');
}
}
+1
View File
@@ -98,6 +98,7 @@ cc/Mixin_PrivateSuperResolution: Skip
cc/Mixin_PrivateSuperResolutionCrossLibraryShouldFail: Skip
dart/b162922506_test: SkipByDesign # Only run in JIT
dart/entrypoints/jit/*: SkipByDesign # These tests should only run on JIT.
dart/spawn_uri_from_kernel_blob_test: SkipByDesign # Only run in JIT.
dart_2/b162922506_test: SkipByDesign # Only run in JIT
dart_2/entrypoints/jit/*: SkipByDesign # These tests should only run on JIT.
dart_2/isolates/reload_*: SkipByDesign # These tests only run on normal JIT.
+2
View File
@@ -304,6 +304,8 @@ namespace dart {
V(Isolate_getCurrentRootUriStr, 0) \
V(Isolate_getDebugName, 1) \
V(Isolate_getPortAndCapabilitiesOfCurrentIsolate, 0) \
V(Isolate_registerKernelBlob, 1) \
V(Isolate_unregisterKernelBlob, 1) \
V(Isolate_sendOOB, 2) \
V(Isolate_spawnFunction, 10) \
V(Isolate_spawnUri, 12) \
+2
View File
@@ -484,6 +484,8 @@ char* Dart::DartInit(const Dart_InitializeParams* params) {
Isolate::SetShutdownCallback(params->shutdown_isolate);
Isolate::SetCleanupCallback(params->cleanup_isolate);
Isolate::SetGroupCleanupCallback(params->cleanup_group);
Isolate::SetRegisterKernelBlobCallback(params->register_kernel_blob);
Isolate::SetUnregisterKernelBlobCallback(params->unregister_kernel_blob);
#ifndef PRODUCT
const bool support_service = true;
+6
View File
@@ -1785,6 +1785,8 @@ void Isolate::InitVM() {
shutdown_callback_ = nullptr;
cleanup_callback_ = nullptr;
cleanup_group_callback_ = nullptr;
register_kernel_blob_callback_ = nullptr;
unregister_kernel_blob_callback_ = nullptr;
if (isolate_creation_monitor_ == nullptr) {
isolate_creation_monitor_ = new Monitor();
}
@@ -2707,6 +2709,10 @@ 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;
Dart_RegisterKernelBlobCallback Isolate::register_kernel_blob_callback_ =
nullptr;
Dart_UnregisterKernelBlobCallback Isolate::unregister_kernel_blob_callback_ =
nullptr;
Random* IsolateGroup::isolate_group_random_ = nullptr;
Monitor* Isolate::isolate_creation_monitor_ = nullptr;
+16
View File
@@ -1230,6 +1230,20 @@ class Isolate : public BaseIsolate, public IntrusiveDListEntry<Isolate> {
static Dart_IsolateGroupCleanupCallback GroupCleanupCallback() {
return cleanup_group_callback_;
}
static void SetRegisterKernelBlobCallback(
Dart_RegisterKernelBlobCallback cb) {
register_kernel_blob_callback_ = cb;
}
static Dart_RegisterKernelBlobCallback RegisterKernelBlobCallback() {
return register_kernel_blob_callback_;
}
static void SetUnregisterKernelBlobCallback(
Dart_UnregisterKernelBlobCallback cb) {
unregister_kernel_blob_callback_ = cb;
}
static Dart_UnregisterKernelBlobCallback UnregisterKernelBlobCallback() {
return unregister_kernel_blob_callback_;
}
#if !defined(PRODUCT)
ObjectIdRing* object_id_ring() const { return object_id_ring_; }
@@ -1680,6 +1694,8 @@ class Isolate : public BaseIsolate, public IntrusiveDListEntry<Isolate> {
static Dart_IsolateShutdownCallback shutdown_callback_;
static Dart_IsolateCleanupCallback cleanup_callback_;
static Dart_IsolateGroupCleanupCallback cleanup_group_callback_;
static Dart_RegisterKernelBlobCallback register_kernel_blob_callback_;
static Dart_UnregisterKernelBlobCallback unregister_kernel_blob_callback_;
#if !defined(PRODUCT)
static void WakePauseEventHandler(Dart_Isolate isolate);
@@ -652,6 +652,31 @@ class Isolate {
static Never exit([SendPort? finalMessagePort, Object? message]) {
_exit(finalMessagePort, message);
}
/**
* Creates an Uri representing the script which was compiled into kernel
* binary in [kernelBlob].
* The resulting Uri can be used for the subsequent spawnUri calls.
* Such spawnUri will start an isolate which would run the given
* compiled script in [kernelBlob].
*/
/*static*/ Uri createUriForKernelBlob(Uint8List kernelBlob) {
return Uri.parse(_registerKernelBlob(kernelBlob));
}
/**
* Unregisters kernel blob previously registered with
* [createUriForKernelBlob] and frees underlying resources.
*/
/*static*/ void unregisterKernelBlobUri(Uri kernelBlobUri) {
_unregisterKernelBlob(kernelBlobUri.toString());
}
@pragma("vm:external-name", "Isolate_registerKernelBlob")
external static String _registerKernelBlob(Uint8List kernelBlob);
@pragma("vm:external-name", "Isolate_unregisterKernelBlob")
external static void _unregisterKernelBlob(String kernelBlobUri);
}
@patch