[ VM / Service ] Add isolateGroupId to IsolateRef and Isolate

This will reduce the number of RPCs we need to do in package:coverage.

Benchmarked on a bunch of flutter test suites, and it halved the time
spent gathering coverage, bringing package:coverage's performance in
line with flutter's custom coverage collector. This unblocks migrating
flutter test to package:coverage.

Bug: https://github.com/flutter/flutter/issues/108313
Change-Id: I27651c7ce356d8b20c9c88444ad25d7677795a6d
TEST=Updated existing tests
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/255720
Commit-Queue: Liam Appelbe <liama@google.com>
Reviewed-by: Ben Konyi <bkonyi@google.com>
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index 8145e3e..a50a013 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Changelog
 
+## 9.4.0
+- Update to version `3.61` of the spec.
+- Add `isolateGroupId` property to `@Isolate` and `Isolate`.
+
 ## 9.3.0
 - Update to version `3.60` of the spec.
 - Add `gcType` property to `Event`.
diff --git a/pkg/vm_service/java/version.properties b/pkg/vm_service/java/version.properties
index f0edd09..034bc0f 100644
--- a/pkg/vm_service/java/version.properties
+++ b/pkg/vm_service/java/version.properties
@@ -1 +1 @@
-version=3.60
+version=3.61
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index c82374a..94ce600 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -1,5 +1,5 @@
 name: vm_service
-version: 9.3.0
+version: 9.4.0
 description: >-
   A library to communicate with a service implementing the Dart VM
   service protocol.
diff --git a/runtime/observatory/tests/service/get_isolate_rpc_test.dart b/runtime/observatory/tests/service/get_isolate_rpc_test.dart
index e1a60ba..0706166 100644
--- a/runtime/observatory/tests/service/get_isolate_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_isolate_rpc_test.dart
@@ -19,6 +19,7 @@
     expect(result['isolateFlags'], isA<List>());
     expect(result['isolateFlags'].length, isPositive);
     expect(result['isSystemIsolate'], isFalse);
+    expect(result['isolateGroupId'], startsWith('isolateGroups/'));
     expect(result['_originNumber'], equals(result['number']));
     expect(result['startTime'], isPositive);
     expect(result['livePorts'], isPositive);
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index 7572f29..41fe377 100644
--- a/runtime/observatory/tests/service/get_version_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
     final result = await vm.invokeRpcNoUpgrade('getVersion', {});
     expect(result['type'], 'Version');
     expect(result['major'], 3);
-    expect(result['minor'], 60);
+    expect(result['minor'], 61);
     expect(result['_privateMajor'], 0);
     expect(result['_privateMinor'], 0);
   },
diff --git a/runtime/observatory/tests/service/get_vm_rpc_test.dart b/runtime/observatory/tests/service/get_vm_rpc_test.dart
index 0291ff3..c11141c 100644
--- a/runtime/observatory/tests/service/get_vm_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_vm_rpc_test.dart
@@ -24,8 +24,12 @@
     expect(result['startTime'], isPositive);
     expect(result['isolates'].length, isPositive);
     expect(result['isolates'][0]['type'], equals('@Isolate'));
+    expect(result['isolates'][0]['id'], startsWith('isolates/'));
+    expect(
+        result['isolates'][0]['isolateGroupId'], startsWith('isolateGroups/'));
     expect(result['isolateGroups'].length, isPositive);
     expect(result['isolateGroups'][0]['type'], equals('@IsolateGroup'));
+    expect(result['isolateGroups'][0]['id'], startsWith('isolateGroups/'));
   },
 ];
 
diff --git a/runtime/observatory_2/tests/service_2/get_isolate_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_isolate_rpc_test.dart
index 40cb013..e8dd023 100644
--- a/runtime/observatory_2/tests/service_2/get_isolate_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_isolate_rpc_test.dart
@@ -16,7 +16,10 @@
     expect(result['type'], equals('Isolate'));
     expect(result['id'], startsWith('isolates/'));
     expect(result['number'], isA<String>());
+    expect(result['isolateFlags'], isA<List>());
+    expect(result['isolateFlags'].length, isPositive);
     expect(result['isSystemIsolate'], isFalse);
+    expect(result['isolateGroupId'], startsWith('isolateGroups/'));
     expect(result['_originNumber'], equals(result['number']));
     expect(result['startTime'], isPositive);
     expect(result['livePorts'], isPositive);
diff --git a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
index d99783f..7704093 100644
--- a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
     final result = await vm.invokeRpcNoUpgrade('getVersion', {});
     expect(result['type'], equals('Version'));
     expect(result['major'], equals(3));
-    expect(result['minor'], equals(60));
+    expect(result['minor'], equals(61));
     expect(result['_privateMajor'], equals(0));
     expect(result['_privateMinor'], equals(0));
   },
diff --git a/runtime/observatory_2/tests/service_2/get_vm_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_vm_rpc_test.dart
index 6fff547..c77f768 100644
--- a/runtime/observatory_2/tests/service_2/get_vm_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_vm_rpc_test.dart
@@ -24,8 +24,12 @@
     expect(result['startTime'], isPositive);
     expect(result['isolates'].length, isPositive);
     expect(result['isolates'][0]['type'], equals('@Isolate'));
+    expect(result['isolates'][0]['id'], startsWith('isolates/'));
+    expect(
+        result['isolates'][0]['isolateGroupId'], startsWith('isolateGroups/'));
     expect(result['isolateGroups'].length, isPositive);
     expect(result['isolateGroups'][0]['type'], equals('@IsolateGroup'));
+    expect(result['isolateGroups'][0]['id'], startsWith('isolateGroups/'));
   },
 ];
 
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index f4143de..f3dcdf4 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -3115,6 +3115,8 @@
   jsobj.AddProperty("name", name());
   jsobj.AddPropertyF("number", "%" Pd64 "", static_cast<int64_t>(main_port()));
   jsobj.AddProperty("isSystemIsolate", is_system_isolate());
+  jsobj.AddPropertyF("isolateGroupId", ISOLATE_GROUP_SERVICE_ID_FORMAT_STRING,
+                     group()->id());
   if (ref) {
     return;
   }
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index cd32fd0..0ffb69e 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -17,7 +17,7 @@
 namespace dart {
 
 #define SERVICE_PROTOCOL_MAJOR_VERSION 3
-#define SERVICE_PROTOCOL_MINOR_VERSION 60
+#define SERVICE_PROTOCOL_MINOR_VERSION 61
 
 class Array;
 class EmbedderServiceHandler;
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index d7d7e52..7825af0 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.60
+# Dart VM Service Protocol 3.61
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes of _version 3.60_ of the Dart VM Service Protocol. This
+This document describes of _version 3.61_ of the Dart VM Service Protocol. This
 protocol is used to communicate with a running Dart Virtual Machine.
 
 To use the Service Protocol, start the VM with the *--observe* flag.
@@ -3174,6 +3174,9 @@
   // Specifies whether the isolate was spawned by the VM or embedder for
   // internal use. If `false`, this isolate is likely running user code.
   bool isSystemIsolate;
+
+  // The id of the isolate group that this isolate belongs to.
+  string isolateGroupId;
 }
 ```
 
@@ -3195,6 +3198,9 @@
   // internal use. If `false`, this isolate is likely running user code.
   bool isSystemIsolate;
 
+  // The id of the isolate group that this isolate belongs to.
+  string isolateGroupId;
+
   // The list of isolate flags provided to this isolate. See Dart_IsolateFlags
   // in dart_api.h for the list of accepted isolate flags.
   IsolateFlag[] isolateFlags;
@@ -4386,5 +4392,6 @@
 3.58 | Added optional `local` parameter to `lookupResolvedPackageUris` RPC.
 3.59 | Added `abstract` property to `@Function` and `Function`.
 3.60 | Added `gcType` property to `Event`.
+3.61 | Added `isolateGroupId` property to `@Isolate` and `Isolate`.
 
 [discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss