[ Service ] Add support for isolate-based RPCs to dart_runtime_service_vm
This change adds initial support for working with isolates in the Dart Runtime Service and its backends. The new `IsolateManager` base class tracks the set of active isolates and their lifecycle events. The `VmIsolateManager` extends this class, adding support specific to interacting with isolates within the Dart VM. TEST=vm/cc/DartAPI_InvokeVMServiceMethod*_Exp Change-Id: I3dfa298722c40dbdfdd58105cc78f31d058dd7a2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/486560 Reviewed-by: Ryan Macnak <rmacnak@google.com> Commit-Queue: Ben Konyi <bkonyi@google.com> Reviewed-by: Jessy Yameogo <yjessy@google.com>
This commit is contained in:
+50
-15
@@ -110,8 +110,14 @@ static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
|
||||
// vm/cc tests to randomly time out due to inability to shut service-isolate
|
||||
// down.
|
||||
// Issue(https://dartbug.com/37741):
|
||||
if ((strcmp(run_filter, "DartAPI_InvokeVMServiceMethod") != 0) &&
|
||||
(strcmp(run_filter, "DartAPI_InvokeVMServiceMethod_Loop") != 0)) {
|
||||
const bool is_service_test =
|
||||
(strcmp(run_filter, "DartAPI_InvokeVMServiceMethod") == 0) ||
|
||||
(strcmp(run_filter, "DartAPI_InvokeVMServiceMethod_Loop") == 0);
|
||||
const bool is_exp_service_test =
|
||||
(strcmp(run_filter, "DartAPI_InvokeVMServiceMethod_Exp") == 0) ||
|
||||
(strcmp(run_filter, "DartAPI_InvokeVMServiceMethod_Loop_Exp") == 0);
|
||||
|
||||
if (!is_service_test && !is_exp_service_test) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -122,21 +128,50 @@ static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
|
||||
packages_config, /*app_snapshot=*/nullptr,
|
||||
/*isolate_run_app_snapshot=*/false);
|
||||
|
||||
const uint8_t* kernel_buffer = nullptr;
|
||||
intptr_t kernel_buffer_size = 0;
|
||||
|
||||
bin::dfe.Init();
|
||||
bin::dfe.LoadPlatform(&kernel_buffer, &kernel_buffer_size);
|
||||
RELEASE_ASSERT(kernel_buffer != nullptr);
|
||||
|
||||
flags->load_vmservice_library = true;
|
||||
flags->is_service_isolate = true;
|
||||
isolate_group_data->SetKernelBufferUnowned(
|
||||
const_cast<uint8_t*>(kernel_buffer), kernel_buffer_size);
|
||||
isolate = Dart_CreateIsolateGroupFromKernel(
|
||||
script_uri, DART_VM_SERVICE_ISOLATE_NAME, kernel_buffer,
|
||||
kernel_buffer_size, flags, isolate_group_data, /*isolate_data=*/nullptr,
|
||||
error);
|
||||
|
||||
#if defined(EXPERIMENTAL_VM_SERVICE)
|
||||
if (is_exp_service_test) {
|
||||
ASSERT(!is_service_test);
|
||||
const uint8_t* isolate_snapshot_data = nullptr;
|
||||
const uint8_t* isolate_snapshot_instructions = nullptr;
|
||||
|
||||
bin::VmService::enable_experimental_vm_service = true;
|
||||
auto [app_snapshot, script_name] = bin::Snapshot::TryReadSDKSnapshot(
|
||||
"dart_runtime_service_vm.dart.snapshot");
|
||||
if (app_snapshot == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
const uint8_t* ignore_vm_snapshot_data;
|
||||
const uint8_t* ignore_vm_snapshot_instructions;
|
||||
app_snapshot->SetBuffers(
|
||||
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
|
||||
&isolate_snapshot_data, &isolate_snapshot_instructions);
|
||||
isolate = Dart_CreateIsolateGroup(
|
||||
script_uri, DART_VM_SERVICE_ISOLATE_NAME, isolate_snapshot_data,
|
||||
isolate_snapshot_instructions, flags, isolate_group_data,
|
||||
/*isolate_data=*/nullptr, error);
|
||||
}
|
||||
#endif // defined(EXPERIMENTAL_VM_SERVICE)
|
||||
|
||||
if (is_service_test) {
|
||||
ASSERT(!is_exp_service_test);
|
||||
const uint8_t* kernel_buffer = nullptr;
|
||||
intptr_t kernel_buffer_size = 0;
|
||||
|
||||
bin::dfe.Init();
|
||||
bin::dfe.LoadPlatform(&kernel_buffer, &kernel_buffer_size);
|
||||
RELEASE_ASSERT(kernel_buffer != nullptr);
|
||||
|
||||
isolate_group_data->SetKernelBufferUnowned(
|
||||
const_cast<uint8_t*>(kernel_buffer), kernel_buffer_size);
|
||||
isolate = Dart_CreateIsolateGroupFromKernel(
|
||||
script_uri, DART_VM_SERVICE_ISOLATE_NAME, kernel_buffer,
|
||||
kernel_buffer_size, flags, isolate_group_data, /*isolate_data=*/nullptr,
|
||||
error);
|
||||
}
|
||||
|
||||
if (isolate == nullptr) {
|
||||
delete isolate_group_data;
|
||||
return nullptr;
|
||||
|
||||
@@ -10559,11 +10559,11 @@ TEST_CASE(DartAPI_InvokeImportedFunction) {
|
||||
"NoSuchMethodError: No top-level method 'getCurrentTag' declared.");
|
||||
}
|
||||
|
||||
TEST_CASE(DartAPI_InvokeVMServiceMethod) {
|
||||
static void InvokeVMServiceMethodCommon() {
|
||||
char buffer[1024];
|
||||
Utils::SNPrint(buffer, sizeof(buffer),
|
||||
R"({
|
||||
"jsonrpc": 2.0,
|
||||
"jsonrpc": "2.0",
|
||||
"id": "foo",
|
||||
"method": "getVM",
|
||||
"params": { }
|
||||
@@ -10618,6 +10618,16 @@ TEST_CASE(DartAPI_InvokeVMServiceMethod) {
|
||||
EXPECT(result == Dart_True());
|
||||
}
|
||||
|
||||
TEST_CASE(DartAPI_InvokeVMServiceMethod) {
|
||||
InvokeVMServiceMethodCommon();
|
||||
}
|
||||
|
||||
#if defined(EXPERIMENTAL_VM_SERVICE)
|
||||
TEST_CASE(DartAPI_InvokeVMServiceMethod_Exp) {
|
||||
InvokeVMServiceMethodCommon();
|
||||
}
|
||||
#endif // defined(EXPERIMENTAL_VM_SERVICE)
|
||||
|
||||
static Monitor* loop_test_lock = new Monitor();
|
||||
static bool loop_test_exit = false;
|
||||
static bool loop_reset_count = false;
|
||||
@@ -10630,7 +10640,7 @@ static void InvokeServiceMessages(uword param) {
|
||||
char buffer[1024];
|
||||
Utils::SNPrint(buffer, sizeof(buffer),
|
||||
R"({
|
||||
"jsonrpc": 2.0,
|
||||
"jsonrpc": "2.0",
|
||||
"id": "foo",
|
||||
"method": "getVM",
|
||||
"params": { }
|
||||
@@ -10661,7 +10671,7 @@ static void InvokeServiceMessages(uword param) {
|
||||
} while (count < 100);
|
||||
}
|
||||
|
||||
TEST_CASE(DartAPI_InvokeVMServiceMethod_Loop) {
|
||||
static void InvokeVMServiceMethodLoopCommon() {
|
||||
{
|
||||
MonitorLocker ml(loop_test_lock);
|
||||
loop_test_exit = false;
|
||||
@@ -10673,6 +10683,16 @@ TEST_CASE(DartAPI_InvokeVMServiceMethod_Loop) {
|
||||
}
|
||||
OSThread::Join(loop_test_join_id);
|
||||
}
|
||||
|
||||
TEST_CASE(DartAPI_InvokeVMServiceMethod_Loop) {
|
||||
InvokeVMServiceMethodLoopCommon();
|
||||
}
|
||||
|
||||
#if defined(EXPERIMENTAL_VM_SERVICE)
|
||||
TEST_CASE(DartAPI_InvokeVMServiceMethod_Loop_Exp) {
|
||||
InvokeVMServiceMethodLoopCommon();
|
||||
}
|
||||
#endif // defined(EXPERIMENTAL_VM_SERVICE)
|
||||
#endif // !defined(PRODUCT)
|
||||
|
||||
static void HandleResponse(Dart_Port dest_port_id, Dart_CObject* message) {
|
||||
|
||||
@@ -578,12 +578,18 @@ void ServiceIsolate::Shutdown() {
|
||||
|
||||
void ServiceIsolate::BootVmServiceLibrary() {
|
||||
Thread* thread = Thread::Current();
|
||||
const Library& vmservice_library =
|
||||
Library::Handle(Library::LookupLibrary(thread, Symbols::DartVMService()));
|
||||
ASSERT(!vmservice_library.IsNull());
|
||||
Library& lib =
|
||||
Library::Handle(thread->isolate_group()->object_store()->root_library());
|
||||
const String& boot_function_name = String::Handle(String::New("boot"));
|
||||
const Function& boot_function = Function::Handle(
|
||||
vmservice_library.LookupFunctionAllowPrivate(boot_function_name));
|
||||
Function& boot_function =
|
||||
Function::Handle(lib.LookupFunctionAllowPrivate(boot_function_name));
|
||||
|
||||
if (boot_function.IsNull()) {
|
||||
lib ^= Library::LookupLibrary(thread, Symbols::DartVMService());
|
||||
ASSERT(!lib.IsNull());
|
||||
boot_function ^= lib.LookupFunctionAllowPrivate(boot_function_name);
|
||||
}
|
||||
|
||||
ASSERT(!boot_function.IsNull());
|
||||
const Object& result = Object::Handle(
|
||||
DartEntry::InvokeFunction(boot_function, Object::empty_array()));
|
||||
@@ -608,16 +614,18 @@ void ServiceIsolate::RegisterRunningIsolates(
|
||||
ASSERT(thread->isolate()->is_service_isolate());
|
||||
|
||||
// Obtain "_registerIsolate" function to call.
|
||||
const String& library_url = Symbols::DartVMService();
|
||||
ASSERT(!library_url.IsNull());
|
||||
const Library& library =
|
||||
Library::Handle(zone, Library::LookupLibrary(thread, library_url));
|
||||
ASSERT(!library.IsNull());
|
||||
const String& function_name =
|
||||
String::Handle(zone, String::New("_registerIsolate"));
|
||||
ASSERT(!function_name.IsNull());
|
||||
const Function& register_function_ =
|
||||
Function::Handle(zone, library.LookupFunctionAllowPrivate(function_name));
|
||||
Library& lib =
|
||||
Library::Handle(thread->isolate_group()->object_store()->root_library());
|
||||
const String& function_name = String::Handle(String::New("_registerIsolate"));
|
||||
Function& register_function_ =
|
||||
Function::Handle(lib.LookupFunctionAllowPrivate(function_name));
|
||||
|
||||
if (register_function_.IsNull()) {
|
||||
lib ^= Library::LookupLibrary(thread, Symbols::DartVMService());
|
||||
ASSERT(!lib.IsNull());
|
||||
register_function_ ^= lib.LookupFunctionAllowPrivate(function_name);
|
||||
}
|
||||
|
||||
ASSERT(!register_function_.IsNull());
|
||||
|
||||
Integer& port_int = Integer::Handle(zone);
|
||||
|
||||
Reference in New Issue
Block a user